diff --git a/xpfe/bootstrap/appleevents/PatriciaTree.cpp b/xpfe/bootstrap/appleevents/PatriciaTree.cpp new file mode 100644 index 000000000000..59fb176dd5d1 --- /dev/null +++ b/xpfe/bootstrap/appleevents/PatriciaTree.cpp @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "AEUtils.h" + +#include "PatriciaTree.h" + + +/*---------------------------------------------------------------------------- + CPatriciaTree + +----------------------------------------------------------------------------*/ +CPatriciaTree::CPatriciaTree(long keyBitsLen) +: mTree(nil) +, mKeyBits(keyBitsLen) +{ + + mTree = PatriciaInitTree(mKeyBits); + ThrowErrIfNil(mTree, paramErr); +} + +/*---------------------------------------------------------------------------- + ~CPatriciaTree + +----------------------------------------------------------------------------*/ +CPatriciaTree::~CPatriciaTree() +{ + if (mTree) + { + PatriciaFreeTree(mTree, NodeFreeCallback, (void *)this); + } +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + InsertNode + + Insert a node. Call the class's replace function by default. + + Returns true if replaced +----------------------------------------------------------------------------*/ +Boolean CPatriciaTree::InsertNode(TPatriciaKey key, CPatriciaNode* nodeData) +{ + int result = PatriciaInsert(mTree, NodeReplaceCallback, key, (void *)nodeData, (void *)this); + return (result == 1); +} + +/*---------------------------------------------------------------------------- + SeekNode + + Look for the node with the given key. Returns true if found +----------------------------------------------------------------------------*/ +Boolean CPatriciaTree::SeekNode(TPatriciaKey key, CPatriciaNode**outNodeData) +{ + int result = PatriciaSearch(mTree, key, (void **)outNodeData); + return (result == 1); +} + +/*---------------------------------------------------------------------------- + Traverse + + Traverse over every node in the tree. Returns true if traversed the entire + tree without halting. +----------------------------------------------------------------------------*/ +Boolean CPatriciaTree::Traverse(NodeTraverseFunction traverseFcn, void *arg, void *refCon) +{ + int result = PatriciaTraverse(mTree, traverseFcn, arg, refCon); + return (result == 0); +} + + +/*---------------------------------------------------------------------------- + GetNumNodes + + Get the number of entries in the tree +----------------------------------------------------------------------------*/ +long CPatriciaTree::GetNumNodes() +{ + return (mTree) ? PatriciaGetNumNodes(mTree) : 0; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + ReplaceNode + + Detault replace node implementation. Does nothing. + +----------------------------------------------------------------------------*/ +int CPatriciaTree::ReplaceNode(CPatriciaNode**nodeDataPtr, TPatriciaKey key, CPatriciaNode *replaceData) +{ + return 0; +} + +/*---------------------------------------------------------------------------- + FreeNode + + Detault free node implementation. Does nothing. + +----------------------------------------------------------------------------*/ +int CPatriciaTree::FreeNode(CPatriciaNode *nodeData, TPatriciaKey key) +{ + return 0; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + NodeReplaceCallback + + [static] + +----------------------------------------------------------------------------*/ +int CPatriciaTree::NodeReplaceCallback(void**nodeDataPtr, unsigned char *key, void *replaceData, void *refCon) +{ + CPatriciaTree* theTree = reinterpret_cast(refCon); + Assert(theTree); + return theTree->ReplaceNode((CPatriciaNode**)nodeDataPtr, key, static_cast(replaceData)); +} + +/*---------------------------------------------------------------------------- + NodeTraverseCallback + + [static] + +----------------------------------------------------------------------------*/ +int CPatriciaTree::NodeFreeCallback(void *nodeData, unsigned char *key, void *refCon) +{ + CPatriciaTree* theTree = reinterpret_cast(refCon); + Assert(theTree); + return theTree->FreeNode(static_cast(nodeData), key); +} + diff --git a/xpfe/bootstrap/appleevents/PatriciaTree.h b/xpfe/bootstrap/appleevents/PatriciaTree.h new file mode 100644 index 000000000000..eaf67b24b048 --- /dev/null +++ b/xpfe/bootstrap/appleevents/PatriciaTree.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef PatricaTree_h_ +#define PatricaTree_h_ + +#include "patricia.h" + +// node base class. Subclass for your nodes. + +class CPatriciaNode +{ +public: + CPatriciaNode() {} + virtual ~CPatriciaNode() {} +}; + + +// tree base class. Subclass for your tree. + +class CPatriciaTree +{ +public: + + typedef const unsigned char* TPatriciaKey; + + CPatriciaTree(long keyBitsLen); + virtual ~CPatriciaTree(); + + // override if you want variable replace functionality + // returns true if replaced + virtual Boolean InsertNode(TPatriciaKey key, CPatriciaNode* nodeData); + + // returns true if found + Boolean SeekNode(TPatriciaKey key, CPatriciaNode**outNodeData); + + // returns true if entire tree traversed + Boolean Traverse(NodeTraverseFunction traverseFcn, void *arg, void *refCon); + + long GetNumNodes(); + +protected: + + // your implementation should override these. + virtual int ReplaceNode(CPatriciaNode**nodeDataPtr, TPatriciaKey key, CPatriciaNode *replaceData); + virtual int FreeNode(CPatriciaNode *nodeData, TPatriciaKey key); + +private: + + // static callbacks. + static int NodeReplaceCallback(void**nodeDataPtr, unsigned char *key, void *replaceData, void *refCon); + static int NodeFreeCallback(void *nodeData, unsigned char *key, void *refCon); + +protected: + + PatriciaTreeRef mTree; + long mKeyBits; + +}; + + + + +#endif // PatricaTree_h_ + diff --git a/xpfe/bootstrap/appleevents/nsAEApplicationClass.cpp b/xpfe/bootstrap/appleevents/nsAEApplicationClass.cpp new file mode 100644 index 000000000000..552a9bb2f3d9 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEApplicationClass.cpp @@ -0,0 +1,880 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include +#include + +#include "nsAEUtils.h" +#include "nsAETokens.h" +#include "nsAECoreClass.h" +#include "nsAEDocumentClass.h" +#include "nsAEWindowClass.h" + +#include "nsAEApplicationClass.h" + +#include "nsCommandLineServiceMac.h" + +/*---------------------------------------------------------------------------- + AEApplicationClass + +----------------------------------------------------------------------------*/ +AEApplicationClass::AEApplicationClass() +: AEGenericClass(cApplication, typeNull) +{ +} + +/*---------------------------------------------------------------------------- + ~AEApplicationClass + +----------------------------------------------------------------------------*/ +AEApplicationClass::~AEApplicationClass() +{ +} + +#pragma mark - + + + +/*---------------------------------------------------------------------------- + GetPropertyFromApp + + Override default to customize behaviour. +----------------------------------------------------------------------------*/ +void AEApplicationClass::GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + OSErr err; + CoreTokenRecord token; + DescType requestedProperty = **(DescType**)keyData->dataHandle; + + token.dispatchClass = GetClass(); + token.objectClass = GetClass(); + token.propertyCode = requestedProperty; + + if (CanGetProperty(requestedProperty) || CanSetProperty(requestedProperty)) + { + err = AECreateDesc(cProperty, (Ptr)&token, sizeof(CoreTokenRecord), resultToken); + ThrowIfOSErr(err); + } + else + { + ThrowIfOSErr(errAEEventNotHandled); + } +} + + + +/*---------------------------------------------------------------------------- + GetItemFromContainer + + Not appropriate for the application +----------------------------------------------------------------------------*/ +void AEApplicationClass::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + HandleClose + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + StAEDesc saving; + StAEDesc savingIn; + + // Extract the [saving yes/no/ask] optional parameter, if present + err = AEGetParamDesc(appleEvent, + keyAESaveOptions, + typeWildCard, + &saving); + + if (err != errAEDescNotFound) + ThrowIfOSErr(err); + + // Extract the [saving in ] optional parameter, if present + err = AEGetParamDesc(appleEvent, + keyAEFile, + typeWildCard, + &savingIn); + + if (err != errAEDescNotFound) + ThrowIfOSErr(err); + + // Check for any required parameters we may have missed + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + // Now, do the application-related work + SysBeep(2); + + +} + +/*---------------------------------------------------------------------------- + HandleCount + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + long numberOfObjects = 0L; + + DescType objectClass; + + if (!reply->dataHandle) + return; + + // Get the class of object that we will count + err = GetObjectClassFromAppleEvent(appleEvent, &objectClass); + ThrowIfOSErr(err); + + // Make sure we got & handled all of the required paramters + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + // Send back the results + numberOfObjects = CountApplicationObjects(token, objectClass); + err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long)); + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + HandleDataSize + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + StAEDesc data; + long size = 0L; + + // First, get the data + HandleGetData(token, appleEvent, reply); + + // now, extract it from the reply + err = AEGetKeyDesc(reply, keyDirectObject, typeWildCard, &data); + ThrowIfOSErr(err); + + size = data.GetDataSize(); + + // do we leak all the data here? + err = AEPutParamPtr(reply, + keyAEResult, + typeLongInteger, + (Ptr)&size, + sizeof(long)); + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + HandleDelete + + All attempts to delete an empty list are handled here + Application contains documents and windows, and they can't be deleted + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + if (AEListUtils::TokenContainsTokenList(token)) + { + long numItems; + + AECountItems(token, &numItems); + + if (numItems > 0) + err = errAEEventNotHandled; + } + + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + HandleDuplicate + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleExists + + If exists... + The AEResolve() function in AERCoreSuite.c will already have filtered + out all cases where the object did not exist, so this function should + always return TRUE. + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + Boolean foundIt = true; + + err = AEPutParamPtr(reply, + keyAEResult, + typeBoolean, + (Ptr)&foundIt, + sizeof(Boolean)); + + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + HandleMake + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleMove + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleRun + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleRun(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + // do stuff on startup that we want to do + + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + HandleOpen + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err; + + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + long numItems, i; + Boolean openedGroups = false; + + err = ::AECountItems(token, &numItems); + ThrowIfOSErr(err); + + for (i = 1; i <= numItems; i++) + { + FSSpec fSpec; + FInfo fndrInfo; + AEKeyword keywd; + DescType returnedType; + Size actualSize; + + err = ::AEGetNthPtr(token, i, typeFSS, &keywd, &returnedType, (Ptr)&fSpec, sizeof(fSpec), &actualSize); + ThrowIfOSErr(err); + + err = ::FSpGetFInfo(&fSpec, &fndrInfo); + ThrowIfOSErr(err); + + nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); + cmdLine.HandleOpenOneDoc(fSpec, fndrInfo.fdType); + } +} + + +/*---------------------------------------------------------------------------- + HandlePrint + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err; + + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + long numItems, i; + Boolean openedGroups = false; + + err = ::AECountItems(token, &numItems); + ThrowIfOSErr(err); + + for (i = 1; i <= numItems; i++) + { + FSSpec fSpec; + FInfo fndrInfo; + AEKeyword keywd; + DescType returnedType; + Size actualSize; + + err = ::AEGetNthPtr(token, i, typeFSS, &keywd, &returnedType, (Ptr)&fSpec, sizeof(fSpec), &actualSize); + ThrowIfOSErr(err); + + err = ::FSpGetFInfo(&fSpec, &fndrInfo); + ThrowIfOSErr(err); + + nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); + cmdLine.HandlePrintOneDoc(fSpec, fndrInfo.fdType); + } +} + +/*---------------------------------------------------------------------------- + HandleQuit + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + // get optional saving param + StAEDesc savingParam; + TAskSave askSave = eSaveUnspecified; + + OSErr err = ::AEGetKeyDesc(appleEvent, keyAESaveOptions, typeEnumeration, &savingParam); + if (err != errAEDescNotFound) + { + DescType enumValue = savingParam.GetEnumType(); + + switch (enumValue) + { + case 'yes ': askSave = eSaveYes; break; + case 'no ': askSave = eSaveNo; break; + case 'ask ': askSave = eSaveAsk; break; + } + } + + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); + err = cmdLine.Quit(askSave); + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + HandleSave + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +#if 0 +/*---------------------------------------------------------------------------- + HandleSetData + + +----------------------------------------------------------------------------*/ +void AEApplicationClass::HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + StAEDesc tokenData; + AETokenDesc tokenDesc(token); + DescType propertyCode; + + if (token->descriptorType == cProperty) + { + propertyCode = tokenDesc.GetPropertyCode(); + + if (CanSetProperty(propertyCode)) + { + // only the clipboard property is writeable + // the clipboard data should be in a list, so we extract that list + switch (propertyCode) + { + case pClipboard: + err = AEGetKeyDesc(appleEvent, keyAEData, typeAEList, &tokenData); + ThrowIfOSErr(err); + + SetDataForObject(token, &tokenData); // may throw + + err = AEPutKeyDesc(reply, keyDirectObject, &tokenData); // return the requested data + ThrowIfOSErr(err); + break; + + default: + ThrowIfOSErr(errAENotModifiable); // "Can't set xxx to nnn" + break; + } + } + else + { + ThrowIfOSErr(errAENotModifiable); + } + } + else + { + ThrowIfOSErr(errAEEventNotHandled); + } + +} +#endif + +#pragma mark - + +/*---------------------------------------------------------------------------- + CountObjects + +----------------------------------------------------------------------------*/ +void AEApplicationClass::CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + long numberOfObjects = CountApplicationObjects(container, desiredType); + *result = numberOfObjects; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetDataFromObject + +----------------------------------------------------------------------------*/ +void AEApplicationClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) +{ + OSErr err = noErr; + + Str255 applicationName = "\p"; + Str255 versionString; + + AETokenDesc tokenDesc(token); + + ProcessSerialNumber applicationProcessNumber; + ProcessInfoRec applicationInfo; + FSSpec appFSSpec; + + Boolean isFrontProcess = true; // еее !gInBackground; + + DescType aDescType = cApplication; + + long documentNumber = 0L; + unsigned long elementNumber = 0L; + + Boolean usePropertyCode = tokenDesc.UsePropertyCode(); + DescType propertyCode; + + long free; + long contiguous; + unsigned long ticks; + + err = GetCurrentProcess(&applicationProcessNumber); + + if (err == noErr) + { + applicationInfo.processInfoLength = sizeof(ProcessInfoRec); + applicationInfo.processName = applicationName; + applicationInfo.processAppSpec = &appFSSpec; + err = GetProcessInformation(&applicationProcessNumber, &applicationInfo); + } + + GetShortVersionString(2, versionString); + PurgeSpace(&free, &contiguous); + + ticks = TickCount(); + + propertyCode = tokenDesc.GetPropertyCode(); + + switch (propertyCode) + { + case pProperties: + err = AECreateList(nil, 0, true, data); + ThrowIfOSErr(err); + + err = AEPutKeyPtr(data, pObjectType, typeType, &aDescType, sizeof(DescType)); + err = AEPutKeyPtr(data, pName, typeChar, &applicationName[1], applicationName[0]); + err = AEPutKeyPtr(data, pVersion, typeChar, &versionString[1], versionString[0]); + err = AEPutKeyPtr(data, pIsFrontProcess, typeBoolean, &isFrontProcess, sizeof(Boolean)); + err = AEPutKeyPtr(data, pFreeMemory, typeLongInteger, &free, sizeof(long)); + err = AEPutKeyPtr(data, pLargestFreeBlock, typeLongInteger, &contiguous, sizeof(long)); + err = AEPutKeyPtr(data, pTicks, typeLongInteger, &ticks, sizeof(long)); + break; + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + err = AECreateDesc(typeType, &aDescType, sizeof(DescType), data); + break; + + case pName: + err = AECreateDesc(typeChar, &applicationName[1], applicationName[0], data); + break; + + case pVersion: + err = AECreateDesc(typeChar, &versionString[1], versionString[0], data); + break; + + case pIsFrontProcess: + err = AECreateDesc(typeBoolean, &isFrontProcess, sizeof(Boolean), data); + break; + + case pFreeMemory: + err = AECreateDesc(typeLongInteger, &free, sizeof(long), data); + break; + + case pLargestFreeBlock: + err = AECreateDesc(typeLongInteger, &contiguous, sizeof(long), data); + break; + + case pTicks: + err = AECreateDesc(typeLongInteger, &ticks, sizeof(long), data); + break; + + case pClipboard: + { + // Return all of the items currently on the clipboard. + // The returned information is an AEList, and each data type + // on the scrap gets its own entry in the list + // Since the OS doesn't supply the tools for getting all + // of the types in the scrap, we have to scan the scrap ourselves + + char *scrapPtr; + char *scrapEnd; + PScrapStuff scrapInfo; + OSType itemType; + long itemLength; + long index; + + err = AECreateList(NULL, 0, false, data); + ThrowIfOSErr(err); + + err = LoadScrap(); // Make sure the scrap is in memory, not on disk. + ThrowIfOSErr(err); + + scrapInfo = InfoScrap(); // Get the base address of the scrap in RAM + MoveHHi(scrapInfo->scrapHandle); + HLock (scrapInfo->scrapHandle); // ...and lock it + + scrapPtr = (char *)*scrapInfo->scrapHandle; + scrapEnd = scrapPtr + scrapInfo->scrapSize; + + // scan the scrap in memory and extract each scrap type + + index = 1; + while (scrapPtr < scrapEnd) + { + itemType = *(OSType *)scrapPtr; + scrapPtr += sizeof(itemType); + itemLength = *(long *)scrapPtr; + scrapPtr += sizeof(itemLength); + + // Move this information into the next entry on the list + err = AEPutPtr(data, index, itemType, scrapPtr, itemLength); + ThrowIfOSErr(err); + + index++; + + // Adjust the pointer to the start of the next item + + if (itemLength & 1) + itemLength++; // If it's odd, make it even + + scrapPtr += itemLength; + } + HUnlock (scrapInfo->scrapHandle); + } + break; + + default: + Inherited::GetDataFromObject(token, desiredTypes, data); + break; + } + + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + SetDataForObject + + Assumption: HandleSetData() has already filtered out all attempts + to write to a read-only property. + +----------------------------------------------------------------------------*/ +void AEApplicationClass::SetDataForObject(const AEDesc *token, AEDesc *data) +{ + OSErr err = noErr; + + long numItems; + long index; + AEKeyword theAEKeyword; + + AETokenDesc tokenDesc(token); + Boolean usePropertyCode = tokenDesc.UsePropertyCode(); + DescType propertyCode; + + if (usePropertyCode) + { + propertyCode = tokenDesc.GetPropertyCode(); + + switch (propertyCode) + { + // the clipboard is the only writeable property for the application object + case pClipboard: + // The data should be an AE list containing a series of things to be placed on the + // clipboard. The data type of each item is also the clipboard type for that data + + err = ZeroScrap(); + ThrowIfOSErr(err); + + AECountItems(data, &numItems); + + // Copy each item onto the clipboard + + for (index = 1; index <= numItems; index++) + { + StAEDesc currentItemDesc; + err = AEGetNthDesc(data, index, typeWildCard, &theAEKeyword, ¤tItemDesc); + ThrowIfOSErr(err); + + HLock(currentItemDesc.dataHandle); + err = PutScrap(GetHandleSize(currentItemDesc.dataHandle), + currentItemDesc.descriptorType, + *currentItemDesc.dataHandle); + ThrowIfOSErr(err); + } + break; + + default: + ThrowIfOSErr(errAENotModifiable); + } + } + +} + + +/*---------------------------------------------------------------------------- + GetKeyEventDataAs + +----------------------------------------------------------------------------*/ +DescType AEApplicationClass::GetKeyEventDataAs(DescType propertyCode) +{ + DescType returnType; + + switch (propertyCode) + { + case pClipboard: + returnType = typeAEList; + break; + + default: + returnType = typeWildCard; + + } + return returnType; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CanSetProperty + +----------------------------------------------------------------------------*/ +Boolean AEApplicationClass::CanSetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + // Properties we can set: + + case pClipboard: + result = true; + break; + + // Properties we should be able to set, but they're not implemented yet: + + + // Properties that are read-only + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pProperties: + + case pFreeMemory: + case pLargestFreeBlock: + case pTicks: + + case pIsFrontProcess: + case pName: + case pVersion: + case pInsertionLoc: + case pSelection: + case pUserSelection: + result = false; + break; + + default: + result = Inherited::CanSetProperty(propertyCode); + break; + } + + return result; +} + + +/*---------------------------------------------------------------------------- + CanGetProperty + +----------------------------------------------------------------------------*/ +Boolean AEApplicationClass::CanGetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + // Properties we can get: + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pProperties: + + case pFreeMemory: + case pLargestFreeBlock: + case pTicks: + + case pIsFrontProcess: + case pName: + case pVersion: + case pInsertionLoc: + case pSelection: + case pUserSelection: + result = true; + break; + + // Properties we should be able to get, but they're not implemented yet: + + // Properties we should not be able to get: + + default: + result = Inherited::CanGetProperty(propertyCode); + break; + } + + return result; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CreateSelfSpecifier + +----------------------------------------------------------------------------*/ +void AEApplicationClass::CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier) +{ + OSErr err = ::AECreateDesc(typeNull, nil, 0, outSpecifier); + ThrowIfOSErr(err); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CountApplicationObjects + +----------------------------------------------------------------------------*/ +long AEApplicationClass::CountApplicationObjects(const AEDesc *token, DescType desiredType) +{ + long numberOfObjects = 0; + OSErr err = noErr; + + if (AEListUtils::TokenContainsTokenList(token)) + { + err = AECountItems(token, &numberOfObjects); + } + else + { + AEDispatchHandler* countHandler = AECoreClass::sAECoreHandler->GetDispatchHandler(desiredType); + if (countHandler == nil) + ThrowOSErr(errAEEventNotHandled); + + countHandler->CountObjects(desiredType, typeNull, token, &numberOfObjects); + /* + switch (desiredType) + { + case cDocument: + numberOfObjects = AEDocumentClass::CountDocuments(); + break; + + case cWindow: + numberOfObjects = AEWindowClass::CountWindows(kAnyWindowKind); + break; + + // application specific classes + case cGroupWindow: + numberOfObjects = AEWindowClass::CountWindows(kUserGroupWindowKind); + break; + + + default: + err = errAEEventNotHandled; + break; + } + */ + } + + ThrowIfOSErr(err); + return numberOfObjects; +} + diff --git a/xpfe/bootstrap/appleevents/nsAEApplicationClass.h b/xpfe/bootstrap/appleevents/nsAEApplicationClass.h new file mode 100644 index 000000000000..e6b93be8d0d6 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEApplicationClass.h @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + +#ifndef __AEAPPLICATIONCLASS__ +#define __AEAPPLICATIONCLASS__ + +#include "nsAEGenericClass.h" +#include "nsAEDocumentClass.h" // for document typedef + +class AEApplicationClass : public AEGenericClass +{ + friend class AECoreClass; + friend class AEDocumentClass; + +private: + typedef AEGenericClass Inherited; + +protected: + // only the AECoreClass can instantiate us + AEApplicationClass(); + ~AEApplicationClass(); + +protected: + + // Accessors + virtual void GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + +protected: + + // ---------------------------------------------------------------------------- + // Core Suite Object Event handlers + // ---------------------------------------------------------------------------- + virtual void HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + //virtual void HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleRun(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + + virtual void CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier); + + virtual void GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data); + virtual void SetDataForObject(const AEDesc *token, AEDesc *data); + + virtual Boolean CanSetProperty(DescType propertyCode); + virtual Boolean CanGetProperty(DescType propertyCode); + + virtual DescType GetKeyEventDataAs(DescType propertyCode); + +protected: + long CountApplicationObjects(const AEDesc *token, DescType desiredType); + +}; + + + + +#endif /* __AEAPPLICATIONCLASS__ */ diff --git a/xpfe/bootstrap/appleevents/nsAEClassDispatcher.cpp b/xpfe/bootstrap/appleevents/nsAEClassDispatcher.cpp new file mode 100644 index 000000000000..af52158790fc --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEClassDispatcher.cpp @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEUtils.h" + +#include "nsAEGenericClass.h" +#include "nsAEClassDispatcher.h" + + +/*---------------------------------------------------------------------------- + AEDispatchHandler + + Ownership of the hanlder passes to this object +----------------------------------------------------------------------------*/ + +AEDispatchHandler::AEDispatchHandler(DescType handlerClass, AEGenericClass* handler, Boolean deleteOnRemove /* = true*/ ) +: mDeleteHandler(deleteOnRemove) +, mHandlerClass(handlerClass) +, mHandler(handler) +{ + ASSERT(mHandler, "No handler"); +} + + +/*---------------------------------------------------------------------------- + AEDispatchHandler + +----------------------------------------------------------------------------*/ +AEDispatchHandler::~AEDispatchHandler() +{ + if (mDeleteHandler) + delete mHandler; +} + + +/*---------------------------------------------------------------------------- + DispatchEvent + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::DispatchEvent( AEDesc * token, + const AppleEvent * appleEvent, + AppleEvent * reply) +{ + ASSERT(mHandler, "No handler"); + mHandler->DispatchEvent(token, appleEvent, reply); +} + +/*---------------------------------------------------------------------------- + GetProperty + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + ASSERT(mHandler, "No handler"); + mHandler->GetProperty(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); +} + +/*---------------------------------------------------------------------------- + GetDataFromListOrObject + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::GetDataFromListOrObject( const AEDesc * tokenOrTokenList, + AEDesc * desiredTypes, + AEDesc * data) +{ + ASSERT(mHandler, "No handler"); + mHandler->GetDataFromListOrObject(tokenOrTokenList, desiredTypes, data); +} + + +/*---------------------------------------------------------------------------- + GetItemFromContainer + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + ASSERT(mHandler, "No handler"); + mHandler->GetItemFromContainer(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); +} + + +/*---------------------------------------------------------------------------- + CompareObjects + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::CompareObjects( DescType comparisonOperator, + const AEDesc * object, + const AEDesc * descriptorOrObject, + Boolean * result) +{ + ASSERT(mHandler, "No handler"); + mHandler->CompareObjects(comparisonOperator, object, descriptorOrObject, result); +} + + + +/*---------------------------------------------------------------------------- + CountObjects + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + ASSERT(mHandler, "No handler"); + mHandler->CountObjects(desiredType, containerClass, container, result); +} + + +/*---------------------------------------------------------------------------- + CreateSelfSpecifier + +----------------------------------------------------------------------------*/ +void AEDispatchHandler::CreateSelfSpecifier( const AEDesc * token, + AEDesc * outSpecifier) +{ + ASSERT(mHandler, "No handler"); + mHandler->CreateSelfSpecifier(token, outSpecifier); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + AEDispatchTree + +----------------------------------------------------------------------------*/ +AEDispatchTree::AEDispatchTree() +: mTree(nil) +{ + + mTree = PatriciaInitTree(8 * sizeof(DescType)); + ThrowIfNil(mTree); +} + + +/*---------------------------------------------------------------------------- + ~AEDispatchTree + +----------------------------------------------------------------------------*/ +AEDispatchTree::~AEDispatchTree() +{ + if (mTree) + PatriciaFreeTree(mTree, FreeDispatchTreeNodeData, this); +} + + +/*---------------------------------------------------------------------------- + InsertHandler + +----------------------------------------------------------------------------*/ +void AEDispatchTree::InsertHandler(DescType handlerClass, AEGenericClass *handler, Boolean isDuplicate /* = false */) +{ + AEDispatchHandler *newHandler = new AEDispatchHandler(handlerClass, handler, !isDuplicate); + unsigned char key[5] = {0}; + int result; + + *(DescType *)key = handlerClass; + + result = PatriciaInsert(mTree, nil, key, newHandler, nil); + if (result == kDuplicateKeyError || result == 1) + { + ThrowIfOSErr(kDuplicateKeyError); + } + else if (result != 0) + { + ThrowIfOSErr(result); + } +} + + +/*---------------------------------------------------------------------------- + FindHandler + + +----------------------------------------------------------------------------*/ +AEDispatchHandler* AEDispatchTree::FindHandler(DescType handlerClass) +{ + AEDispatchHandler* foundClass = nil; + unsigned char key[5] = {0}; + + *(DescType *)key = handlerClass; + + (void)PatriciaSearch(mTree, key, &foundClass); + + return foundClass; +} + +/*---------------------------------------------------------------------------- + ReplaceDispatchTreeNode + + static + + if this ever gets called, it means we tried to insert a node for a duplicate class, + which is an error. So return an error. We don't want to throw because the + patricia code may not be exception-safe. +----------------------------------------------------------------------------*/ +int AEDispatchTree::ReplaceDispatchTreeNode(void *nodeData, unsigned char *key, void *replaceData) +{ + return kDuplicateKeyError; +} + +/*---------------------------------------------------------------------------- + FreeDispatchTreeNodeData + + static +----------------------------------------------------------------------------*/ +int AEDispatchTree::FreeDispatchTreeNodeData(void *nodeData, unsigned char *key, void *refCon) +{ + AEDispatchTree* dispatchTree = reinterpret_cast(refCon); + AEDispatchHandler* handler = reinterpret_cast(nodeData); + + delete handler; + return 0; +} + diff --git a/xpfe/bootstrap/appleevents/nsAEClassDispatcher.h b/xpfe/bootstrap/appleevents/nsAEClassDispatcher.h new file mode 100644 index 000000000000..cc362afd4afd --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEClassDispatcher.h @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AECLASSDISPATCHER__ +#define __AECLASSDISPATCHER__ + + +#include "patricia.h" + +// this class is used to dispatch calls to handlers on the basis of their class. It avoids +// us having to switch on the class in the code. + +class AEGenericClass; + +class AEDispatchHandler +{ +public: + AEDispatchHandler(DescType handlerClass, AEGenericClass* handler, Boolean deleteOnRemove = true); + ~AEDispatchHandler(); + + + void DispatchEvent( AEDesc * token, + const AppleEvent * appleEvent, + AppleEvent * reply); + + void GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void GetDataFromListOrObject( const AEDesc * tokenOrTokenList, + AEDesc * desiredTypes, + AEDesc * data); + + void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void CompareObjects( DescType comparisonOperator, + const AEDesc * object, + const AEDesc * descriptorOrObject, + Boolean * result); + + + void CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + + void CreateSelfSpecifier( const AEDesc * token, + AEDesc * outSpecifier); + +protected: + + Boolean mDeleteHandler; + DescType mHandlerClass; + AEGenericClass* mHandler; +}; + + + +class AEDispatchTree +{ +public: + AEDispatchTree(); + ~AEDispatchTree(); + + void InsertHandler(DescType handlerClass, AEGenericClass *handler, Boolean isDuplicate = false); + AEDispatchHandler* FindHandler(DescType handlerClass); + +protected: + + enum { + kDuplicateKeyError = 750 + }; + + static int FreeDispatchTreeNodeData(void *nodeData, unsigned char *key, void *refCon); + static int ReplaceDispatchTreeNode(void *nodeData, unsigned char *key, void *replaceData); + + +protected: + + PatriciaTreeRef mTree; +}; + + + +#endif /* __AECLASSDISPATCHER__ */ + diff --git a/xpfe/bootstrap/appleevents/nsAEClassIterator.cpp b/xpfe/bootstrap/appleevents/nsAEClassIterator.cpp new file mode 100644 index 000000000000..97ee248b68d5 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEClassIterator.cpp @@ -0,0 +1,457 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEUtils.h" +#include "nsAETokens.h" + +#include "nsAEClassIterator.h" + + +const AEClassIterator::ItemRef AEClassIterator::kNoItemRef = -1; +const AEClassIterator::ItemID AEClassIterator::kNoItemID = -1; + +/*---------------------------------------------------------------------------- + GetItemFromContainer + +----------------------------------------------------------------------------*/ +void AEClassIterator::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + OSErr err = noErr; + + CStr255 itemName; + ItemRef itemRef = kNoItemRef; + ItemID itemID = kNoItemID; + DescType keyDataType = keyData->descriptorType; + + Boolean wantsAllItems = false; + + StAEDesc startObject; // These are used to resolve formRange + StAEDesc stopObject; + + CoreTokenRecord token; + + long numItems = GetNumItems(containerToken); + TAEListIndex itemIndex; + + CheckKeyFormSupport(keyForm); // throws on error + + switch (keyForm) + { + case formName: // item by name + if (DescToCString(keyData, itemName, 255) != noErr) + ThrowIfOSErr(errAECoercionFail); + + itemRef = GetNamedItemReference(containerToken, itemName); + if (itemRef == kNoItemRef) + ThrowIfOSErr(errAENoSuchObject); + break; + + case formAbsolutePosition: // item by number + itemIndex = NormalizeAbsoluteIndex(keyData, numItems, &wantsAllItems); + if (wantsAllItems == false) + { + if (itemIndex == 0 || itemIndex > numItems) + ThrowOSErr(errAEIllegalIndex); + } + itemRef = GetIndexedItemReference(containerToken, itemIndex); + if (itemRef == kNoItemRef) + ThrowOSErr(errAENoSuchObject); + break; + + case formRelativePosition: + itemRef = ProcessFormRelativePostition(containerToken, keyData); + break; + + case formRange: + switch (keyDataType) + { + case typeRangeDescriptor: + { + ProcessFormRange((AEDesc *)keyData, &startObject, &stopObject); + + AETokenDesc startToken(&startObject); + AETokenDesc stopToken(&stopObject); + DescType startType = startToken.GetDispatchClass(); + DescType stopType = stopToken.GetDispatchClass(); + + if (startType != mClass || stopType != mClass) + ThrowOSErr(errAEWrongDataType); + } + break; + + default: + ThrowOSErr(errAEWrongDataType); + break; + } + break; + + default: + ThrowIfOSErr(errAEEventNotHandled); + } + + // if user asked for all items, and there aren't any, + // we'll be kind and return an empty list. + + if (wantsAllItems && (err == errAENoSuchObject || err == errAEIllegalIndex)) + { + err = AECreateList(nil, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + return; + } + + ThrowIfOSErr(err); + + // fill in the result token + token.dispatchClass = GetClass(); + token.objectClass = GetClass(); + token.propertyCode = typeNull; + + if (wantsAllItems) + { + err = AECreateList(NULL, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + + for (TAEListIndex index = 1; index <= numItems; index++) + { + ItemID itemID = GetIndexedItemID(containerToken, index); + if (itemID != kNoItemID) + { + SetItemIDInCoreToken(containerToken, &token, itemID); + err = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token)); + ThrowIfOSErr(err); + } + } + } + else if (keyForm == formRange) + { + AETokenDesc startToken(&startObject); + AETokenDesc stopToken(&stopObject); + + ItemID beginItemID = GetItemIDFromToken(&startObject); + ItemID endItemID = GetItemIDFromToken(&stopObject); + + TAEListIndex beginIndex = GetIndexFromItemID(containerToken, beginItemID); + TAEListIndex endIndex = GetIndexFromItemID(containerToken, endItemID); + + err = AECreateList(nil, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + + if (beginIndex > endIndex) // swap elements + { + TAEListIndex temp = beginIndex; + beginIndex = endIndex; + endIndex = temp; + } + + for (TAEListIndex i = beginIndex; i <= endIndex; i ++) + { + ItemID itemID = GetIndexedItemID(containerToken, i); + if (itemID != kNoItemID) + { + SetItemIDInCoreToken(containerToken, &token, itemID); + err = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token)); + ThrowIfOSErr(err); + } + } + } + else + { + SetItemIDInCoreToken(containerToken, &token, GetIDFromReference(containerToken, itemRef)); + err = AECreateDesc(desiredClass, &token, sizeof(token), resultToken); + ThrowIfOSErr(err); + } +} + + +/*---------------------------------------------------------------------------- + ProcessFormRelativePostition + +----------------------------------------------------------------------------*/ + +AEClassIterator::ItemRef AEClassIterator::ProcessFormRelativePostition(const AEDesc* anchorToken, const AEDesc *keyData) +{ + OSErr err = noErr; + ItemID anchorItemID = GetItemIDFromToken(anchorToken); + TAEListIndex anchorListIndex = GetIndexFromItemID(anchorToken, anchorItemID); + TAEListIndex wantedListIndex = 0; + long numItems = GetNumItems(anchorToken); + ItemRef returnRef = kNoItemRef; + + if (anchorListIndex != 0) + { + switch (keyData->descriptorType) + { + case typeEnumerated: + DescType positionEnum; + if (DescToDescType((AEDesc*)keyData, &positionEnum) != noErr) + ThrowIfOSErr(errAECoercionFail); + + switch (positionEnum) + { + case kAENext: // get the window behind the anchor + wantedListIndex = anchorListIndex + 1; + if (wantedListIndex > numItems) + err = errAENoSuchObject; + break; + + case kAEPrevious: // get the document in front of the anchor + wantedListIndex = anchorListIndex - 1; + if (wantedListIndex < 1) + err = errAENoSuchObject; + break; + + default: + err = errAEEventNotHandled; + break; + } + ThrowIfOSErr(err); + break; + + default: + err = errAECoercionFail; + break; + } + } + + ThrowIfOSErr(err); + return GetIndexedItemReference(anchorToken, wantedListIndex); +} + + +/*---------------------------------------------------------------------------- + NormalizeAbsoluteIndex + + Handles formAbsolutePosition resolution + +---------------------------------------------------------------------------*/ +TAEListIndex AEClassIterator::NormalizeAbsoluteIndex(const AEDesc *keyData, TAEListIndex maxIndex, Boolean *isAllItems) +{ + TAEListIndex index; + *isAllItems = false; // set to true if we receive kAEAll constant + + // Extract the formAbsolutePosition data, either a integer or a literal constant + + switch (keyData->descriptorType) + { + case typeLongInteger: // positve or negative index + if (DescToLong(keyData, &index) != noErr) + ThrowOSErr(errAECoercionFail); + + if (index < 0) // convert a negative index from end of list to a positive index from beginning of list + index = maxIndex + index + 1; + break; + + case typeAbsoluteOrdinal: // 'abso' + DescType ordinalDesc; + if (DescToDescType((AEDesc*)keyData, &ordinalDesc) != noErr) + ThrowOSErr(errAECoercionFail); + + switch (ordinalDesc) + { + case kAEFirst: + index = 1; + break; + + case kAEMiddle: + index = (maxIndex >> 1) + (maxIndex % 2); + break; + + case kAELast: + index = maxIndex; + break; + + case kAEAny: + index = (TickCount() % maxIndex) + 1; // poor man's random + break; + + case kAEAll: + index = 1; + *isAllItems = true; + break; + } + break; + + default: + ThrowOSErr(errAEWrongDataType); + } + + // range-check the new index number + if ((index < 1) || (index > maxIndex)) + ThrowOSErr(errAEIllegalIndex); + + return index; +} + + +/*---------------------------------------------------------------------------- + ProcessFormRange + + Handles formRange resolution of boundary objects +----------------------------------------------------------------------------*/ + +void AEClassIterator::ProcessFormRange(AEDesc *keyData, AEDesc *start, AEDesc *stop) +{ + OSErr err = noErr; + StAEDesc rangeRecord; + StAEDesc ospec; + + // coerce the range record data into an AERecord + + err = AECoerceDesc(keyData, typeAERecord, &rangeRecord); + ThrowIfOSErr(err); + + // object specifier for first object in the range + err = AEGetKeyDesc(&rangeRecord, keyAERangeStart, typeWildCard, &ospec); + if (err == noErr && ospec.descriptorType == typeObjectSpecifier) + err = AEResolve(&ospec, kAEIDoMinimum, start); + + ThrowIfOSErr(err); + + ospec.Clear(); + + // object specifier for last object in the range + + err = AEGetKeyDesc(&rangeRecord, keyAERangeStop, typeWildCard, &ospec); + if (err == noErr && ospec.descriptorType == typeObjectSpecifier) + err = AEResolve(&ospec, kAEIDoMinimum, stop); + + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + CheckKeyFormSupport + + throws if unsupported key form +----------------------------------------------------------------------------*/ +void AEClassIterator::CheckKeyFormSupport(DescType keyForm) +{ + UInt16 testMask; + switch (keyForm) + { + case formAbsolutePosition: testMask = eHasFormAbsolutePosition; break; + case formRelativePosition: testMask = eHasFormRelativePosition; break; + case formTest: testMask = eHasFormTest; break; + case formRange: testMask = eHasFormRange; break; + case formPropertyID: testMask = eHasFormPropertyID; break; + case formName: testMask = eHasFormName; break; + default: + ASSERT(false, "Unknown key form"); + } + if ((mKeyFormSupport & testMask) == 0) + ThrowOSErr(errAEBadKeyForm); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetItemFromContainer + +----------------------------------------------------------------------------*/ +void AENamedClassIterator::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + OSErr err = noErr; + + CStr255 itemName; + DescType keyDataType = keyData->descriptorType; + + Boolean wantsAllItems = false; + + StAEDesc startObject; // These are used to resolve formRange + StAEDesc stopObject; + + CoreTokenRecord token; + + long numItems = GetNumItems(containerToken); + + CheckKeyFormSupport(keyForm); // throws on error + + switch (keyForm) + { + case formName: // item by name + if (DescToCString(keyData, itemName, 255) != noErr) + ThrowIfOSErr(errAECoercionFail); + + if (!NamedItemExists(containerToken, itemName)) + ThrowIfOSErr(errAENoSuchObject); + break; + +/* + case formAbsolutePosition: // item by number + DescType ordinalDesc; + if (DescToDescType((AEDesc*)keyData, &ordinalDesc) != noErr) + ThrowOSErr(errAECoercionFail); + + if (ordinalDesc != kAEAll) + ThrowOSErr(errAEWrongDataType); + + wantsAllItems = true; + break; +*/ + default: + ThrowIfOSErr(errAEEventNotHandled); + } + + ThrowIfOSErr(err); + + // fill in the result token + token.dispatchClass = GetClass(); + token.objectClass = GetClass(); + token.propertyCode = typeNull; + + if (wantsAllItems) + { + err = AECreateList(NULL, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + + for (TAEListIndex index = 1; index <= numItems; index++) + { + ItemID itemID = GetIndexedItemID(containerToken, index); + if (itemID != kNoItemID) + { + SetItemIDInCoreToken(containerToken, &token, itemID); + err = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token)); + ThrowIfOSErr(err); + } + } + } + else + { + SetNamedItemIDInCoreToken(containerToken, &token, itemName); + err = AECreateDesc(desiredClass, &token, sizeof(token), resultToken); + ThrowIfOSErr(err); + } +} + diff --git a/xpfe/bootstrap/appleevents/nsAEClassIterator.h b/xpfe/bootstrap/appleevents/nsAEClassIterator.h new file mode 100644 index 000000000000..6739127d0361 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEClassIterator.h @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AECLASSITERATOR__ +#define __AECLASSITERATOR__ + + +#include "nsAETokens.h" + +class AEClassIterator +{ + +protected: + + enum + { + eFormAbsolutePositionBit = 0, + eFormRelativePositionBit, + eFormTestBit, + eFormRangeBit, + eFormPropertyIDBit, + eFormNameBit + }; + + +public: + + enum + { + eHasFormAbsolutePosition = (1 << eFormAbsolutePositionBit), + eHasFormRelativePosition = (1 << eFormRelativePositionBit), + eHasFormTest = (1 << eFormTestBit), + eHasFormRange = (1 << eFormPropertyIDBit), + eHasFormPropertyID = (1 << eFormRangeBit), + eHasFormName = (1 << eFormNameBit), + + eStandardKeyFormSupport = (eHasFormAbsolutePosition | eHasFormRelativePosition | eHasFormRange | eHasFormName) + }; + + + AEClassIterator(DescType classType, UInt16 keyFormSupport = eStandardKeyFormSupport) + : mClass(classType) + , mKeyFormSupport(keyFormSupport) + {} + + virtual ~AEClassIterator() {} + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual UInt32 GetNumItems(const AEDesc* containerToken) = 0; // get the number of items + + typedef UInt32 ItemRef; // runtime, optimized reference to an object + typedef UInt32 ItemID; // persistent reference, used for storage + +protected: + + static const ItemRef kNoItemRef; // value for a nonexistent item reference (usu. -1) + static const ItemID kNoItemID; // value for a nonexistent item ID (usu -1) + + + virtual ItemRef GetNamedItemReference(const AEDesc* containerToken, const char *itemName) = 0; + virtual ItemRef GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex) = 0; + + virtual TAEListIndex GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID) = 0; + + virtual ItemID GetNamedItemID(const AEDesc* containerToken, const char *itemName) = 0; + virtual ItemID GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex) = 0; + + // index to name + virtual void GetIndexedItemName(const AEDesc* containerToken, TAEListIndex itemIndex, char *outName, long maxLen) = 0; + + // conversion routines. + virtual ItemID GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef) = 0; + virtual ItemRef GetReferenceFromID(const AEDesc* containerToken, ItemID itemID) = 0; + + virtual ItemID GetItemIDFromToken(const AEDesc* token) = 0; + virtual void SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID) = 0; + + // Range and index processing routines. + virtual ItemRef ProcessFormRelativePostition(const AEDesc* anchorToken, const AEDesc *keyData); + TAEListIndex NormalizeAbsoluteIndex(const AEDesc *keyData, TAEListIndex maxIndex, Boolean *isAllItems); + void ProcessFormRange(AEDesc *keyData, AEDesc *start, AEDesc *stop); + + void CheckKeyFormSupport(DescType keyForm); // throws if unsupported key form + + DescType GetClass() { return mClass; } + + + DescType mClass; + UInt16 mKeyFormSupport; +}; + + +class AENamedClassIterator : public AEClassIterator +{ +public: + AENamedClassIterator(DescType classType) + : AEClassIterator(classType, eHasFormName) + {} + + ~AENamedClassIterator() {} + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + +protected: + + + // stubs for those pure virtual functions that we can't use with named items + virtual UInt32 GetNumItems(const AEDesc* containerToken) { return 0; } + + virtual ItemRef GetNamedItemReference(const AEDesc* containerToken, const char *itemName) { return kNoItemRef; } + virtual ItemRef GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex) { return kNoItemRef; } + + virtual TAEListIndex GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID) { return 0; } + + virtual Boolean NamedItemExists(const AEDesc* containerToken, const char *itemName) = 0; + + virtual ItemID GetNamedItemID(const AEDesc* containerToken, const char *itemName) { return kNoItemID; } + virtual ItemID GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex) { return kNoItemID; } + + // index to name + virtual void GetIndexedItemName(const AEDesc* containerToken, TAEListIndex itemIndex, char *outName, long maxLen) {} + + // conversion routines. + virtual ItemID GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef) { return kNoItemID; } + virtual ItemRef GetReferenceFromID(const AEDesc* containerToken, ItemID itemID) { return kNoItemRef; } + + virtual ItemID GetItemIDFromToken(const AEDesc* token) { return kNoItemID; } + virtual void SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID) {} + virtual void SetNamedItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* token, const char *itemName) = 0; + +}; + + +// base class for items that cannot be referred to by name +class AEUnnamedClassIterator : public AEClassIterator +{ +public: + + enum + { + eNoNameKeyFormSupport = (eHasFormAbsolutePosition | eHasFormRelativePosition | eHasFormRange) + }; + + + AEUnnamedClassIterator(DescType classType) + : AEClassIterator(classType, eNoNameKeyFormSupport) + {} + + ~AEUnnamedClassIterator() {} + +protected: + + virtual ItemRef GetNamedItemReference(const AEDesc* containerToken, const char *itemName) { ThrowOSErr(errAEEventNotHandled); } + virtual ItemID GetNamedItemID(const AEDesc* containerToken, const char *itemName) { ThrowOSErr(errAEEventNotHandled); } + virtual void GetIndexedItemName(const AEDesc* containerToken, TAEListIndex itemIndex, char *outName, long maxLen) { ThrowOSErr(errAEEventNotHandled); } + +}; + + +#endif /* __AECLASSITERATOR__ */ diff --git a/xpfe/bootstrap/appleevents/nsAEClassTypes.h b/xpfe/bootstrap/appleevents/nsAEClassTypes.h new file mode 100644 index 000000000000..9c342acd0bdc --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEClassTypes.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AECLASSTYPES__ +#define __AECLASSTYPES__ + + +/* Verbs */ +enum { + + kAEUnselect = 'uslt' +}; + + +/* Classes */ +enum { + kPrefsClassID = 'PREF' +}; + +/* Prefs class properties */ +enum { + pPrefsUserName = 'UNAM', + pPrefsEmail = 'EMIL', + + pWindowName = 'NAME' // not sure why this isn't in the headers +}; + + +/* Classes */ +enum { + + cMailServer = 'SMTP', + + cMessageWindow = 'MWIN', + cNewGroupsWindow = 'NWIN', + cFullGroupsWindow = 'FWIN' + +}; + +/* Classes for coercion */ +enum { + cWrappedText = 'cWtx' +}; + + + + +#endif /* __AECLASSTYPES__ */ diff --git a/xpfe/bootstrap/appleevents/nsAECoercionHandlers.cpp b/xpfe/bootstrap/appleevents/nsAECoercionHandlers.cpp new file mode 100644 index 000000000000..9b74cff739f0 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECoercionHandlers.cpp @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#include "nsAEUtils.h" + +#include "nsAECoercionHandlers.h" + + + +AECoercionHandlers* AECoercionHandlers::sAECoercionHandlers = nil; + + +/*---------------------------------------------------------------------------- + AECoercionHandlers + +----------------------------------------------------------------------------*/ + +AECoercionHandlers::AECoercionHandlers() +: mTextDescToPascalString(nil) +, mPascalStringDescToText(nil) +{ + OSErr err; + + mTextDescToPascalString = NewAECoerceDescProc(TextToPascalStringCoercion); + ThrowIfNil(mTextDescToPascalString); + + err = ::AEInstallCoercionHandler(typeChar, typePascalString, + mTextDescToPascalString, + (long)this, + true, /* Pass a pointer not a descriptor */ + false ); /* Application table, not System */ + ThrowIfOSErr(err); + + mPascalStringDescToText = NewAECoerceDescProc(PascalStringToTextCoercion); + ThrowIfNil(mPascalStringDescToText); + + err = ::AEInstallCoercionHandler(typePascalString, typeChar, + mPascalStringDescToText, + (long)this, + true, /* Pass a pointer not a descriptor */ + false ); /* Application table, not System */ + ThrowIfOSErr(err); +} + + + +/*---------------------------------------------------------------------------- + ~AECoercionHandlers + +----------------------------------------------------------------------------*/ + +AECoercionHandlers::~AECoercionHandlers() +{ + if (mTextDescToPascalString) + { + AERemoveCoercionHandler(typeChar, typePascalString, mTextDescToPascalString, false); + DisposeRoutineDescriptor(mTextDescToPascalString); + } + + if (mPascalStringDescToText) + { + AERemoveCoercionHandler(typePascalString, typeChar, mPascalStringDescToText, false); + DisposeRoutineDescriptor(mPascalStringDescToText); + } +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + TextToPascalStringCoercion + +----------------------------------------------------------------------------*/ +OSErr AECoercionHandlers::TextToPascalStringCoercion(const AEDesc *fromDesc, DescType toType, long handlerRefcon, AEDesc *toDesc) +{ + OSErr err = noErr; + + if (toType != typePascalString) + return errAECoercionFail; + + switch (fromDesc->descriptorType) + { + case typeChar: + Str255 pString; + DescToPString(fromDesc, pString, 255); + err = AECreateDesc(typePascalString, pString, pString[0] + 1, toDesc); + break; + + default: + err = errAECoercionFail; + break; + } + + return err; +} + +/*---------------------------------------------------------------------------- + PascalStringToTextCoercion + +----------------------------------------------------------------------------*/ + +OSErr AECoercionHandlers::PascalStringToTextCoercion(const AEDesc *fromDesc, DescType toType, long handlerRefcon, AEDesc *toDesc) +{ + OSErr err = noErr; + + if (toType != typeChar) + return errAECoercionFail; + + switch (fromDesc->descriptorType) + { + case typePascalString: + { + Handle dataHandle = fromDesc->dataHandle; + long stringLen = *(unsigned char *)(*dataHandle); + if (stringLen > 255) + { + err = errAECoercionFail; + break; + } + + StHandleLocker locker(dataHandle); + err = AECreateDesc(typeChar, *dataHandle + 1, stringLen, toDesc); + } + break; + + default: + err = errAECoercionFail; + break; + } + + return err; +} + + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CreateCoercionHandlers + +----------------------------------------------------------------------------*/ + +OSErr CreateCoercionHandlers() +{ + OSErr err = noErr; + + if (AECoercionHandlers::sAECoercionHandlers) + return noErr; + + try + { + AECoercionHandlers::sAECoercionHandlers = new AECoercionHandlers; + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch( ... ) + { + err = paramErr; + } + + return err; + +} + + + +/*---------------------------------------------------------------------------- + ShutdownCoercionHandlers + +----------------------------------------------------------------------------*/ + +OSErr ShutdownCoercionHandlers() +{ + if (!AECoercionHandlers::sAECoercionHandlers) + return noErr; + + try + { + delete AECoercionHandlers::sAECoercionHandlers; + } + catch(...) + { + } + + AECoercionHandlers::sAECoercionHandlers = nil; + return noErr; +} + diff --git a/xpfe/bootstrap/appleevents/nsAECoercionHandlers.h b/xpfe/bootstrap/appleevents/nsAECoercionHandlers.h new file mode 100644 index 000000000000..947feabf2919 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECoercionHandlers.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef AECoercionHandlers_h_ +#define AECoercionHandlers_h_ + +#ifdef __cplusplus + +class AECoercionHandlers +{ +public: + + AECoercionHandlers(); + ~AECoercionHandlers(); + + enum { + typePascalString = 'PStr' /* Descriptor type for a pascal string */ + }; + + +protected: + + static OSErr TextToPascalStringCoercion(const AEDesc *fromDesc, DescType toType, long handlerRefcon, AEDesc *toDesc); + static OSErr PascalStringToTextCoercion(const AEDesc *fromDesc, DescType toType, long handlerRefcon, AEDesc *toDesc); + + +protected: + + AECoerceDescUPP mTextDescToPascalString; + AECoerceDescUPP mPascalStringDescToText; + +public: + + static AECoercionHandlers* GetAECoercionHandlers() { return sAECoercionHandlers; } + static AECoercionHandlers* sAECoercionHandlers; + +}; + +#endif //__cplusplus + +#ifdef __cplusplus +extern "C" { +#endif + +OSErr CreateCoercionHandlers(); +OSErr ShutdownCoercionHandlers(); + +#ifdef __cplusplus +} +#endif + + +#endif // AECoercionHandlers_h_ diff --git a/xpfe/bootstrap/appleevents/nsAECompare.cpp b/xpfe/bootstrap/appleevents/nsAECompare.cpp new file mode 100644 index 000000000000..b5803d55908b --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECompare.cpp @@ -0,0 +1,515 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#include + +#include "nsAEUtils.h" +#include "nsAECompare.h" + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareTexts(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + Boolean result = false; + + short compareResult; + char *lhs; + char *rhs; + long lhsSize; + long rhsSize; + char h1State, h2State; + + lhsSize = GetHandleSize(desc1->dataHandle); + h1State = HGetState(desc1->dataHandle); + HLock(desc1->dataHandle); + lhs = *(desc1->dataHandle); + + rhsSize = GetHandleSize(desc2->dataHandle); + h2State = HGetState(desc2->dataHandle); + HLock(desc2->dataHandle); + rhs = *(desc2->dataHandle); + + compareResult = ::CompareText(lhs, rhs, lhsSize, rhsSize, nil); + + switch (oper) + { + case kAEEquals: + result = (compareResult == 0); + break; + + case kAELessThan: + result = (compareResult < 0); + break; + + case kAELessThanEquals: + result = (compareResult <= 0); + break; + + case kAEGreaterThan: + result = (compareResult > 0); + break; + + case kAEGreaterThanEquals: + result = (compareResult >= 0); + break; + + case kAEBeginsWith: + if (rhsSize > lhsSize) + { + result = false; + } + else + { + // compare only the number of characters in rhs + // begin comparing at the beginning of lhs + compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil); + result = (compareResult == 0); + } + break; + + case kAEEndsWith: + if (rhsSize > lhsSize) + { + result = false; + } + else + { + // compare only the number of characters in rhs + // begin comparing rhsSize characters from the end of lhs + // start + + lhs += (lhsSize - rhsSize); + compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil); + result = (compareResult == 0); + } + break; + + case kAEContains: + // Here I use an inefficient search strategy, but we're dealing with small amounts + // of text and by using CompareText(), we're doing the same style of comparison + // as in the other cases above. + + result = false; + while (lhsSize >= rhsSize) + { + compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil); + if (compareResult == 0) + { + result = true; + break; + } + lhs++; + lhsSize--; + } + break; + + default: + ThrowOSErr(errAEBadTestKey); + } + + HSetState(desc1->dataHandle, h1State); + HSetState(desc2->dataHandle, h2State); + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareEnumeration(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + long lhs; + long rhs; + StAEDesc charDesc; + + // Make each number is a long integer (in case it's a short integer or other integer type) + // before extracting the data */ + + err = AECoerceDesc(desc1, typeChar, &charDesc); + ThrowIfOSErr(err); + + lhs = **(long **)(charDesc.dataHandle); + AEDisposeDesc(&charDesc); + + err = AECoerceDesc(desc2, typeChar, &charDesc); + ThrowIfOSErr(err); + + rhs = **(long **)charDesc.dataHandle; + AEDisposeDesc(&charDesc); + + switch (oper) + { + case kAEEquals: + result = (lhs == rhs); // equality is the only test that makes sense for enumerators + break; + + default: + ThrowOSErr(errAEBadTestKey); + } + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + long lhs; + long rhs; + StAEDesc longDesc; + + // Make each number is a long integer (in case it's a short integer or other integer type) + // before extracting the data */ + + err = AECoerceDesc(desc1, typeLongInteger, &longDesc); + ThrowIfOSErr(err); + + lhs = **(long **)(longDesc.dataHandle); + AEDisposeDesc(&longDesc); + + err = AECoerceDesc(desc2, typeLongInteger, &longDesc); + ThrowIfOSErr(err); + + rhs = **(long **)longDesc.dataHandle; + AEDisposeDesc(&longDesc); + + switch (oper) + { + case kAEEquals: + result = (lhs == rhs); + break; + + case kAELessThan: + result = (lhs < rhs); + break; + + case kAELessThanEquals: + result = (lhs <= rhs); + break; + + case kAEGreaterThan: + result = (lhs > rhs); + break; + + case kAEGreaterThanEquals: + result = (lhs >= rhs); + break; + + default: + ThrowOSErr(errAEBadTestKey); + } + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareFixed(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + Fixed lhs; + Fixed rhs; + + err = DescToFixed(desc1, &lhs); + ThrowIfOSErr(err); + + err = DescToFixed(desc2, &rhs); + ThrowIfOSErr(err); + + switch (oper) + { + case kAEEquals: + result = (lhs == rhs); + break; + + case kAELessThan: + result = (lhs < rhs); + break; + + case kAELessThanEquals: + result = (lhs <= rhs); + break; + + case kAEGreaterThan: + result = (lhs > rhs); + break; + + case kAEGreaterThanEquals: + result = (lhs >= rhs); + break; + + default: + ThrowOSErr(errAEBadTestKey); + } + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareFloat(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + float lhs; + float rhs; + + err = DescToFloat(desc1, &lhs); + ThrowIfOSErr(err); + + err = DescToFloat(desc2, &rhs); + ThrowIfOSErr(err); + + switch (oper) + { + case kAEEquals: + result = (lhs == rhs); + break; + + case kAELessThan: + result = (lhs < rhs); + break; + + case kAELessThanEquals: + result = (lhs <= rhs); + break; + + case kAEGreaterThan: + result = (lhs > rhs); + break; + + case kAEGreaterThanEquals: + result = (lhs >= rhs); + break; + + default: + ThrowOSErr(errAEBadTestKey); + } + + return result; +} + +// ---------------------------------------------------------------------------------------- +// Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE + +Boolean AEComparisons::CompareBoolean(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + + Boolean bool1 = ((**(char **)desc1->dataHandle) != 0); + Boolean bool2 = ((**(char **)desc2->dataHandle) != 0); + + if (oper == kAEEquals) + result = (bool1 == bool2); + else + ThrowOSErr(errAEBadTestKey); // No other tests make sense + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareRGBColor(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + + RGBColor lhs; + RGBColor rhs; + + err = DescToRGBColor(desc1, &lhs); + ThrowIfOSErr(err); + + err = DescToRGBColor(desc2, &rhs); + ThrowIfOSErr(err); + + if (oper == kAEEquals) + result = EqualRGB(lhs, rhs); + else + ThrowOSErr(errAEBadTestKey); // No other tests make sense + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::ComparePoint(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + + Point lhs; + Point rhs; + + err = DescToPoint(desc1, &lhs); + ThrowIfOSErr(err); + + err = DescToPoint(desc2, &rhs); + ThrowIfOSErr(err); + + switch (oper) + { + case kAEEquals: + result = (lhs.h = rhs.h && lhs.v == rhs.v); + break; + + case kAELessThan: + result = (lhs.h < rhs.h && lhs.v < rhs.v); + break; + + case kAELessThanEquals: + result = (lhs.h <= rhs.h && lhs.v <= rhs.v); + break; + + case kAEGreaterThan: + result = (lhs.h > rhs.h && lhs.v > rhs.v); + break; + + case kAEGreaterThanEquals: + result = (lhs.h >= rhs.h && lhs.v >= rhs.v); + break; + + default: + ThrowOSErr(errAEBadTestKey); // No other tests make sense + } + + return result; +} + +// ---------------------------------------------------------------------------------------- + +Boolean AEComparisons::CompareRect(DescType oper, const AEDesc *desc1, const AEDesc *desc2) +{ + OSErr err = noErr; + Boolean result = false; + Rect lhs; + Rect rhs; + + err = DescToRect(desc1, &lhs); + ThrowIfOSErr(err); + + err = DescToRect(desc2, &rhs); + ThrowIfOSErr(err); + + switch (oper) + { + // compare size AND location + case kAEEquals: + result = ((lhs.top == rhs.top) && (lhs.left == rhs.left) && (lhs.bottom == rhs.bottom) && (lhs.right == rhs.right)); + break; + + // compare size only on the rest of the tests + case kAELessThan: + result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left))); + break; + + case kAELessThanEquals: + result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left))); + break; + + case kAEGreaterThan: + result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left))); + break; + + case kAEGreaterThanEquals: + result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left))); + break; + + case kAEContains: + // Note: two identical Rects contain each other, according to this test: + result = ((lhs.top <= rhs.top) && (lhs.left <= rhs.left) && (lhs.bottom >= rhs.bottom) && (lhs.right >= rhs.right)); + break; + + default: + ThrowOSErr(errAEBadTestKey); // No other tests make sense + } + + return result; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + TryPrimitiveComparison + +----------------------------------------------------------------------------*/ + +Boolean AEComparisons::TryPrimitiveComparison(DescType comparisonOperator, const AEDesc *desc1, const AEDesc *desc2) +{ + Boolean result = false; + + // This has to handle all the data types used in the application's + // object model implementation. + switch (desc1->descriptorType) + { + case typeChar: + result = CompareTexts(comparisonOperator, desc1, desc2); + break; + + case typeShortInteger: // also covers typeSMInt 'shor' + case typeLongInteger: // also covers typeInteger 'long' + case typeMagnitude: // 'magn' + result = CompareInteger(comparisonOperator, desc1, desc2); + break; + + case typeEnumerated: + result = CompareEnumeration(comparisonOperator, desc1, desc2); + break; + + case typeFixed: + result = CompareFixed(comparisonOperator, desc1, desc2); + break; + + case typeFloat: + result = CompareFloat(comparisonOperator, desc1, desc2); + break; + + case typeBoolean: + result = CompareBoolean(comparisonOperator, desc1, desc2); + break; + + case typeRGBColor: + result = CompareRGBColor(comparisonOperator, desc1, desc2); + break; + + case typeQDRectangle: + result = CompareRect(comparisonOperator, desc1, desc2); + break; + + case typeQDPoint: + result = ComparePoint(comparisonOperator, desc1, desc2); + break; + + default: + ThrowOSErr(errAEWrongDataType); + } + + return result; +} diff --git a/xpfe/bootstrap/appleevents/nsAECompare.h b/xpfe/bootstrap/appleevents/nsAECompare.h new file mode 100644 index 000000000000..8b8c51bd4b46 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECompare.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +class AEComparisons +{ +public: + + static Boolean CompareTexts(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareEnumeration(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareFixed(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareFloat(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareBoolean(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareRGBColor(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean ComparePoint(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + static Boolean CompareRect(DescType oper, const AEDesc *desc1, const AEDesc *desc2); + + static Boolean TryPrimitiveComparison(DescType comparisonOperator, const AEDesc *desc1, const AEDesc *desc2); + +protected: + static Boolean EqualRGB(RGBColor colorA, RGBColor colorB) + { + return((colorA.red == colorB.red) && (colorA.green == colorB.green) && (colorA.blue == colorB.blue)); + } +}; + diff --git a/xpfe/bootstrap/appleevents/nsAECoreClass.cpp b/xpfe/bootstrap/appleevents/nsAECoreClass.cpp new file mode 100644 index 000000000000..662aac9967ef --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECoreClass.cpp @@ -0,0 +1,1097 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + +#include "nsAEClassTypes.h" +#include "nsAEUtils.h" +#include "nsAETokens.h" +#include "nsAECompare.h" + +#include "nsAEApplicationClass.h" +#include "nsAEDocumentClass.h" +#include "nsAEWindowClass.h" + +#include "nsAEMozillaSuiteHandler.h" +#include "nsAEGetURLSuiteHandler.h" +#include "nsAESpyglassSuiteHandler.h" + +/* +#include "nsAETextClass.h" +#include "nsAEWordClass.h" +#include "nsAECharacterClass.h" +*/ + +#include "nsAECoreClass.h" + +AECoreClass* AECoreClass::sAECoreHandler = nil; + +/*---------------------------------------------------------------------------- + AECoreClass + +----------------------------------------------------------------------------*/ + +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 = NewAEEventHandlerProc(AECoreClass::SuspendEventHandler); + ThrowIfNil(mSuspendEventHandlerUPP); + + mRequiredSuiteHandlerUPP = NewAEEventHandlerProc(AECoreClass::RequiredSuiteHandler); + ThrowIfNil(mRequiredSuiteHandlerUPP); + + mStandardSuiteHandlerUPP = NewAEEventHandlerProc(AECoreClass::CoreSuiteHandler); + ThrowIfNil(mStandardSuiteHandlerUPP); + + mMozillaSuiteHandlerUPP = NewAEEventHandlerProc(AECoreClass::MozillaSuiteHandler); + ThrowIfNil(mMozillaSuiteHandlerUPP); + + mGetURLSuiteHandlerUPP = NewAEEventHandlerProc(AECoreClass::GetURLSuiteHandler); + ThrowIfNil(mGetURLSuiteHandlerUPP); + + mSpyGlassSuiteHandlerUPP = NewAEEventHandlerProc(AECoreClass::SpyglassSuiteHandler); + ThrowIfNil(mSpyGlassSuiteHandlerUPP); + + InstallSuiteHandlers(suspendEvents); + + mCreateElementHandlerUPP = NewAEEventHandlerProc(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 = NewOSLAccessorProc(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 = NewOSLAccessorProc(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 = NewOSLCountProc(AECoreClass::CountObjectsCallback); + ThrowIfNil(mCountItemsCallback); + + mCompareItemsCallback = NewOSLCompareProc(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); +*/ +} + + +/*---------------------------------------------------------------------------- + ~AECoreClass + +----------------------------------------------------------------------------*/ + +AECoreClass::~AECoreClass() +{ + if (mSuspendEventHandlerUPP) + DisposeRoutineDescriptor(mSuspendEventHandlerUPP); + + if (mStandardSuiteHandlerUPP) + DisposeRoutineDescriptor(mStandardSuiteHandlerUPP); + + if (mRequiredSuiteHandlerUPP) + DisposeRoutineDescriptor(mRequiredSuiteHandlerUPP); + + if (mMozillaSuiteHandlerUPP) + DisposeRoutineDescriptor(mMozillaSuiteHandlerUPP); + + if (mGetURLSuiteHandlerUPP) + DisposeRoutineDescriptor(mGetURLSuiteHandlerUPP); + + if (mSpyGlassSuiteHandlerUPP) + DisposeRoutineDescriptor(mSpyGlassSuiteHandlerUPP); + + if (mCreateElementHandlerUPP) + DisposeRoutineDescriptor(mCreateElementHandlerUPP); + + if (mPropertyFromListAccessor) + DisposeRoutineDescriptor(mPropertyFromListAccessor); + + if (mAnythingFromAppAccessor) + DisposeRoutineDescriptor(mAnythingFromAppAccessor); + + if (mCountItemsCallback) + DisposeRoutineDescriptor(mCountItemsCallback); + + if (mCompareItemsCallback) + DisposeRoutineDescriptor(mCompareItemsCallback); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + HandleCoreSuiteEvent + +----------------------------------------------------------------------------*/ +void AECoreClass::HandleCoreSuiteEvent(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) + { + AETokenDesc 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 + { + AETokenDesc 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); +} + + +/*---------------------------------------------------------------------------- + HandleRequiredSuiteEvent + +----------------------------------------------------------------------------*/ +void AECoreClass::HandleRequiredSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + StAEDesc token; + + // ignore error; direct object param might be optional + (void)::AEGetParamDesc(appleEvent, keyDirectObject, typeAEList, &token); + + AEDispatchHandler* handler = GetDispatchHandler(cApplication); + if (!handler) + ThrowIfOSErr(errAEEventNotHandled); + + handler->DispatchEvent(&token, appleEvent, reply); +} + + +/*---------------------------------------------------------------------------- + HandleCreateElementEvent + +----------------------------------------------------------------------------*/ +void AECoreClass::HandleCreateElementEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + StAEDesc token; + OSErr err = noErr; + + // Extract the type of object we want to create. + // We use this to call the event dispatcher for that kind of objects + err = ::AEGetParamDesc(appleEvent, keyAEObjectClass, typeType, &token); + ThrowIfOSErr(err); + + DescType dispatchClass = **(DescType **)(token.dataHandle); + + AEDispatchHandler* handler = GetDispatchHandler(dispatchClass); + if (!handler) + ThrowIfOSErr(errAEEventNotHandled); + + handler->DispatchEvent(&token, appleEvent, reply); +} + + +/*---------------------------------------------------------------------------- + HandleEventSuspend + +----------------------------------------------------------------------------*/ +void AECoreClass::HandleEventSuspend(AppleEvent *appleEvent, AppleEvent *reply) +{ + mSuspendedEvent = *appleEvent; + mReplyToSuspendedEvent = *reply; + OSErr err = ::AESuspendTheCurrentEvent(appleEvent); + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + PropertyTokenFromList + +----------------------------------------------------------------------------*/ +void AECoreClass::PropertyTokenFromList( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + DescType handlerClass; + AETokenDesc containerDesc(containerToken); + + switch (containerClass) + { + case cProperty: + // this is to handle our property from property hack, which enables an article to be a property + // of an article window, and thence to get properties of that article. + handlerClass = containerDesc.GetDispatchClass(); + break; + + default: + handlerClass = containerClass; + break; + + } + AEDispatchHandler* handler = GetDispatchHandler(handlerClass); + if (!handler) + ThrowIfOSErr(errAEEventNotHandled); + + handler->GetProperty( desiredClass, + containerToken, + containerClass, + keyForm, + keyData, + resultToken); +} + + +/*---------------------------------------------------------------------------- + GetAnythingFromApp + +----------------------------------------------------------------------------*/ +void AECoreClass::GetAnythingFromApp( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + AEDispatchHandler* handler = GetDispatchHandler(desiredClass); + if (!handler) + ThrowIfOSErr(errAEEventNotHandled); + + handler->GetItemFromContainer( desiredClass, + containerToken, + containerClass, + keyForm, + keyData, + resultToken); +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + SuspendEventHandler + + This handler receives ALL core suite events EXCEPT Make (CreateElement). + It simply suspends the current event and returns. Someone has to resume + this event later, when we are ready to handle it, by calling ResumeEventHandling(). + +----------------------------------------------------------------------------*/ + +pascal OSErr AECoreClass::SuspendEventHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleEventSuspend(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + RequiredSuiteHandler + + This handler receives ALL core suite events EXCEPT Make (CreateElement) + and passes them on to the correct object dispatcher: + cApplication, cDocument, cFile, cGraphicObject, and cWindow. + Make (CreateElement) is different because it passes its ospec in the + insertionLoc parameter instead of in the direct object parameter. + +----------------------------------------------------------------------------*/ + +pascal OSErr AECoreClass::RequiredSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleRequiredSuiteEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + CoreSuiteHandler + + This handler receives ALL core suite events EXCEPT Make (CreateElement) + and passes them on to the correct object dispatcher: + cApplication, cDocument, cFile, cGraphicObject, and cWindow. + Make (CreateElement) is different because it passes its ospec in the + insertionLoc parameter instead of in the direct object parameter. + +----------------------------------------------------------------------------*/ + +pascal OSErr AECoreClass::CoreSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleCoreSuiteEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + CreateElementHandler + +----------------------------------------------------------------------------*/ + +pascal OSErr AECoreClass::CreateElementHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleCreateElementEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + MozillaSuiteHandler + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::MozillaSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleMozillaSuiteEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + + +/*---------------------------------------------------------------------------- + GetURLSuiteHandler + + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::GetURLSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleGetURLSuiteEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + SpyGlassSuiteHandler + + +----------------------------------------------------------------------------*/ + +pascal OSErr AECoreClass::SpyglassSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + OSErr err = noErr; + + if (coreClass == nil) + return errAECorruptData; + + try + { + coreClass->HandleSpyglassSuiteEvent(appleEvent, reply); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch ( ... ) + { + err = paramErr; + } + + return err; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + HandleMozillaSuiteEvent + + We probably want to handle events for this suite off to another class. +----------------------------------------------------------------------------*/ +void AECoreClass::HandleMozillaSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + AEMozillaSuiteHandler mozEventHandler; + mozEventHandler.HandleMozillaSuiteEvent(appleEvent, reply); +} + + +/*---------------------------------------------------------------------------- + HandleGetURLSuiteEvent + + We probably want to handle events for this suite off to another class. +----------------------------------------------------------------------------*/ +void AECoreClass::HandleGetURLSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + AEGetURLSuiteHandler getURLHandler; + getURLHandler.HandleGetURLSuiteEvent(appleEvent, reply); +} + + +/*---------------------------------------------------------------------------- + HandleSpyGlassSuiteEvent + + We probably want to handle events for this suite off to another class. +----------------------------------------------------------------------------*/ +void AECoreClass::HandleSpyglassSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + AESpyglassSuiteHandler spyglassHandler; + spyglassHandler.HandleSpyglassSuiteEvent(appleEvent, reply); +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + PropertyTokenFromAnything + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::PropertyTokenFromAnything( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + if (!coreClass) return paramErr; + + OSErr err = noErr; + + try + { + coreClass->PropertyTokenFromList(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch (...) + { + err = paramErr; + } + + return err; +} + + + +/*---------------------------------------------------------------------------- + AnythingFromAppAccessor + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::AnythingFromAppAccessor( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon) +{ + AECoreClass* coreClass = reinterpret_cast(refCon); + + if (!coreClass) + return paramErr; + + OSErr err = noErr; + + try + { + coreClass->GetAnythingFromApp(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch (...) + { + err = paramErr; + } + + return err; +} + + +/*---------------------------------------------------------------------------- + CompareObjectsCallback + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::CompareObjectsCallback( DescType comparisonOperator, // operator to use + const AEDesc * object, // left-hand side + const AEDesc * descriptorOrObject, // right-hand side + Boolean * result) +{ + OSErr err = noErr; + try + { + OSErr err = noErr; + StAEDesc desc1; + StAEDesc desc2; + + // This first AEDesc is a token to a specific object, so we resolve it. + AECoreClass::GetAECoreHandler()->ExtractData(object, &desc1); + + // A second AEDesc is either a token to another object or an AEDesc containing literal data. + AECoreClass::GetAECoreHandler()->ExtractData(descriptorOrObject, &desc2); + + // Make sure the data type extracted from the second AEDesc is the same as the + // data specified by the first AEDesc. + + if (desc1.descriptorType != desc2.descriptorType) + { + StAEDesc temp; + + // Create a temporary duplicate of desc2 and coerce it to the + // requested type. This could call a coercion handler you have + // installed. If there are no errors, stuff the coerced value back into desc2 + err = AEDuplicateDesc(&desc2, &temp); + ThrowIfOSErr(err); + + desc2.Clear(); + + err = AECoerceDesc(&temp, desc1.descriptorType, &desc2); + ThrowIfOSErr(err); + } + + AEDispatchHandler* handler = AECoreClass::GetDispatchHandlerForClass(desc1.descriptorType); + if (handler) + handler->CompareObjects(comparisonOperator, &desc1, &desc2, result); + else + *result = AEComparisons::TryPrimitiveComparison(comparisonOperator, &desc1, &desc2); + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch (...) + { + err = paramErr; + } + + return err; +} + + +/*---------------------------------------------------------------------------- + CountObjectsCallback + +----------------------------------------------------------------------------*/ +pascal OSErr AECoreClass::CountObjectsCallback( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + AEDispatchHandler* handler = AECoreClass::GetDispatchHandlerForClass(containerClass); + if (!handler) + return errAEEventNotHandled; + + OSErr err = noErr; + try + { + handler->CountObjects( desiredType, + containerClass, + container, + result); + + } + catch (OSErr catchErr) + { + err = catchErr; + } + catch (...) + { + err = paramErr; + } + + return err; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetEventKeyDataParameter + + Extract the keyData parameter data from an apple event +---------------------------------------------------------------------------*/ +void AECoreClass::GetEventKeyDataParameter(const AppleEvent *appleEvent, DescType requestedType, AEDesc *data) +{ + StAEDesc keyData; + + OSErr err = AEGetKeyDesc(appleEvent, keyAEData, requestedType, &keyData); + ThrowIfOSErr(err); + + ExtractData(&keyData, data); +} + + +/*---------------------------------------------------------------------------- + ExtractData + + ExtractData can receive several types of data: + Source Processing + -------------------- ----------------------------- + an object specifier call AEResolve() to get token, then handle below + a property token call public accessors to get raw data from token + a object token if it's not a property token, the token itself is returned + raw data just return it, it's already data! +---------------------------------------------------------------------------*/ + +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) + { + AETokenDesc 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); + } +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + RegisterClassHandler + + This is where a handler class registers itself +----------------------------------------------------------------------------*/ +void AECoreClass::RegisterClassHandler(DescType handlerClass, AEGenericClass* classHandler, Boolean isDuplicate /* = false */) +{ + mDispatchTree.InsertHandler(handlerClass, classHandler, isDuplicate); +} + +/*---------------------------------------------------------------------------- + GetDispatchHandler + + Get a dispatch handler for the given class +----------------------------------------------------------------------------*/ +AEDispatchHandler* AECoreClass::GetDispatchHandler(DescType dispatchClass) +{ + return mDispatchTree.FindHandler(dispatchClass); +} + + +/*---------------------------------------------------------------------------- + GetDispatchHandler + + Get a dispatch handler for the given class. + + Static +----------------------------------------------------------------------------*/ +AEDispatchHandler* AECoreClass::GetDispatchHandlerForClass(DescType dispatchClass) +{ + if (!sAECoreHandler) + return nil; + + return sAECoreHandler->GetDispatchHandler(dispatchClass); +} + + + +/*---------------------------------------------------------------------------- + InstallSuitesGenericHandler + + Install a handler for each of our suites +----------------------------------------------------------------------------*/ +void AECoreClass::InstallSuiteHandlers(Boolean suspendEvents) +{ + OSErr err; + + err = ::AEInstallEventHandler(kCoreEventClass, typeWildCard, + suspendEvents ? mSuspendEventHandlerUPP : mRequiredSuiteHandlerUPP, + (long)this, + false); + ThrowIfOSErr(err); + + err = ::AEInstallEventHandler(kAECoreSuite, typeWildCard, + suspendEvents ? mSuspendEventHandlerUPP : mStandardSuiteHandlerUPP, + (long)this, + false); + ThrowIfOSErr(err); + + // install the mozilla suite handler + err = ::AEInstallEventHandler(kAEMozillaSuite, typeWildCard, + suspendEvents ? mSuspendEventHandlerUPP : mMozillaSuiteHandlerUPP, + (long)this, + false); + ThrowIfOSErr(err); + + // install the GetURL suite handler + err = ::AEInstallEventHandler(kAEUrlSuite, typeWildCard, + suspendEvents ? mSuspendEventHandlerUPP : mGetURLSuiteHandlerUPP, + (long)this, + false); + ThrowIfOSErr(err); + + // install the SpyGlass suite handler + err = ::AEInstallEventHandler(kAESpyglassSuite, typeWildCard, + suspendEvents ? mSuspendEventHandlerUPP : mSpyGlassSuiteHandlerUPP, + (long)this, + false); + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + HandleCoreSuiteEvent + +----------------------------------------------------------------------------*/ +void AECoreClass::ResumeEventHandling(AppleEvent *appleEvent, AppleEvent *reply, Boolean dispatchEvent) +{ + InstallSuiteHandlers(false); + + OSErr err; + + // now resume the passed in event + err = ::AEResumeTheCurrentEvent(appleEvent, reply, (AEEventHandlerUPP)(dispatchEvent ? kAEUseStandardDispatch : kAENoDispatch), (long)this); + ThrowIfOSErr(err); +} + + + + + diff --git a/xpfe/bootstrap/appleevents/nsAECoreClass.h b/xpfe/bootstrap/appleevents/nsAECoreClass.h new file mode 100644 index 000000000000..b167b6ace5c7 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAECoreClass.h @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#ifndef __AECORECLASS__ +#define __AECORECLASS__ + +#ifdef __cplusplus + + +#include +#include +#include + +#include "nsAEClassDispatcher.h" + +class AEApplicationClass; +class AEDocumentClass; +class AEWindowClass; + +class AECoreClass +{ +public: + + enum { + kAEMozillaSuite = 'MOZZ', + kAEUrlSuite = 'GURL', + kAESpyglassSuite = 'WWW!' + }; + + + AECoreClass(Boolean suspendEvents = false); // throws OSErrs + ~AECoreClass(); + + void HandleCoreSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + void HandleRequiredSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + + void HandleMozillaSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + void HandleGetURLSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + void HandleSpyglassSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + + void HandleCreateElementEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + + void HandleEventSuspend(AppleEvent *appleEvent, AppleEvent *reply); + void ResumeEventHandling(AppleEvent *appleEvent, AppleEvent *reply, Boolean dispatchEvent); + + // AE Handlers + static pascal OSErr SuspendEventHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + static pascal OSErr RequiredSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + static pascal OSErr CoreSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + static pascal OSErr CreateElementHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + + // Handler for Mozilla Suite events + static pascal OSErr MozillaSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + + // Handler for GetURL events + static pascal OSErr GetURLSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + + // Handler for GetURL events + static pascal OSErr SpyglassSuiteHandler(AppleEvent *appleEvent, AppleEvent *reply, long refCon); + + + AEDispatchHandler* GetDispatchHandler(DescType dispatchClass); + + + void GetSuspendedEvent(AppleEvent *appleEvent, AppleEvent *reply) + { + *appleEvent = mSuspendedEvent; + *reply = mReplyToSuspendedEvent; + } + +protected: + + // Property token from list of tokens accessor + void PropertyTokenFromList( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void GetAnythingFromApp( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void RegisterClassHandler( DescType handlerClass, + AEGenericClass* classHandler, + Boolean isDuplicate = false); + + + void InstallSuiteHandlers( Boolean suspendEvents); + +public: + + void GetEventKeyDataParameter( const AppleEvent* appleEvent, + DescType requestedType, + AEDesc* data); + + static pascal OSErr PropertyTokenFromAnything( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon); + + static pascal OSErr AnythingFromAppAccessor( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon); + + static pascal OSErr CompareObjectsCallback( DescType comparisonOperator, // operator to use + const AEDesc * object, // left-hand side + const AEDesc * descriptorOrObject, // right-hand side + Boolean * result); + + + static pascal OSErr CountObjectsCallback( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + + void ExtractData( const AEDesc* source, + AEDesc* data); + + + static AEDispatchHandler* GetDispatchHandlerForClass( DescType dispatchClass); + +protected: + + AEDispatchTree mDispatchTree; // tree of handler dispatchers + + AEEventHandlerUPP mSuspendEventHandlerUPP; + + AEEventHandlerUPP mStandardSuiteHandlerUPP; + AEEventHandlerUPP mRequiredSuiteHandlerUPP; + AEEventHandlerUPP mCreateElementHandlerUPP; + + AEEventHandlerUPP mMozillaSuiteHandlerUPP; + AEEventHandlerUPP mGetURLSuiteHandlerUPP; + AEEventHandlerUPP mSpyGlassSuiteHandlerUPP; + + OSLAccessorUPP mPropertyFromListAccessor; + OSLAccessorUPP mAnythingFromAppAccessor; + + OSLCountUPP mCountItemsCallback; + OSLCompareUPP mCompareItemsCallback; + +private: + + AppleEvent mSuspendedEvent; + AppleEvent mReplyToSuspendedEvent; + +public: + + static AECoreClass* GetAECoreHandler() { return sAECoreHandler; } + static AECoreClass* sAECoreHandler; + +}; + +#endif //__cplusplus + +#endif /* __AECORECLASS__ */ + diff --git a/xpfe/bootstrap/appleevents/nsAEDefs.h b/xpfe/bootstrap/appleevents/nsAEDefs.h new file mode 100644 index 000000000000..9fe39b336db1 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEDefs.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef nsAEDefs_h_ +#define nsAEDefs_h_ + + +#include + + +typedef char CStr255[256]; /* like Str255, except for C-format strings. */ +typedef long TAEListIndex; // a 1-based list index +typedef short TWindowKind; + + +enum { + kAnyWindowKind = 99 +}; + + +typedef enum +{ + eSaveUnspecified, + eSaveYes, + eSaveNo, + eSaveAsk +} TAskSave; + + +#if DEBUG + +#define ASSERT(x,msg) { if (!(x)) { DebugStr("\p"msg); } } + +#else + +#define ASSERT(x) ((void) 0) + +#endif + + + + +#endif // nsAEDefs_h_ diff --git a/xpfe/bootstrap/appleevents/nsAEDocumentClass.cpp b/xpfe/bootstrap/appleevents/nsAEDocumentClass.cpp new file mode 100644 index 000000000000..d90655965e1d --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEDocumentClass.cpp @@ -0,0 +1,694 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + +#include "nsAEUtils.h" +#include "nsAETokens.h" +#include "nsAECoreClass.h" +#include "nsAEApplicationClass.h" + +#include "nsAEDocumentClass.h" + + +/*---------------------------------------------------------------------------- + AEDocumentClass + +----------------------------------------------------------------------------*/ +AEDocumentClass::AEDocumentClass() +: AEGenericClass(cDocument, typeNull) +{ +} + + +/*---------------------------------------------------------------------------- + ~AEDocumentClass + +----------------------------------------------------------------------------*/ +AEDocumentClass::~AEDocumentClass() +{ +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + PropertyFromApplicationAccessor + +----------------------------------------------------------------------------*/ +pascal OSErr AEDocumentClass::PropertyAccessor( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon) +{ + AEDocumentClass* docClass = reinterpret_cast(refCon); + if (!docClass) return paramErr; + + OSErr err = noErr; + + try + { + docClass->GetProperty(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch(...) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + GetItemFromContainer + + Not appropriate for the application +----------------------------------------------------------------------------*/ +void AEDocumentClass::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + GetDocumentFromApp + +----------------------------------------------------------------------------*/ +void AEDocumentClass::GetDocumentFromApp( DescType desiredClass, // cDocument + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) // specified Document is returned in result +{ + OSErr err = noErr; + DescType keyDataType = keyData->descriptorType; + long index; + long numItems; + Boolean wantsAllItems = false; + StAEDesc startObject; // These are used to resolve formRange + StAEDesc stopObject; + DocumentReference document; + Str63 documentName; + CoreTokenRecord token; + + numItems = CountDocuments(); + + switch (keyForm) + { + case formName: // Document by name + { + if (DescToPString(keyData, documentName, 63) != noErr) + { + err = errAECoercionFail; + } + else + { + document = GetDocumentByName(documentName); + if (document == nil) + err = errAENoSuchObject; + } + } + break; + + case formAbsolutePosition: // Document by number + err = NormalizeAbsoluteIndex(keyData, &index, numItems, &wantsAllItems); + if ((err == noErr) && (wantsAllItems == false)) + { + document = GetDocumentByIndex(index); + if (document == nil) + err = errAEIllegalIndex; + } + break; + + case formRelativePosition: + ProcessFormRelativePostition(containerToken, keyData, &document); + break; + + case formRange: + switch (keyDataType) + { + case typeRangeDescriptor: + err = ProcessFormRange((AEDesc *)keyData, &startObject, &stopObject); + if (err == noErr) + { + AETokenDesc startTokenDesc(&startObject); + AETokenDesc stopTokenDesc(&startObject); + + DescType startType = startTokenDesc.GetDispatchClass(); + DescType stopType = stopTokenDesc.GetDispatchClass(); + + if (startType != cDocument || stopType != cDocument) + err = errAEWrongDataType; + } + break; + + default: + err = errAEWrongDataType; + break; + } + break; + + default: + err = errAEEventNotHandled; + break; + } + + // if user asked for all items, and there aren't any, + // we'll be kind and return an empty list. + + if (wantsAllItems && (err == errAENoSuchObject || err == errAEIllegalIndex)) + { + err = AECreateList(NULL, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + return; + } + + ThrowIfOSErr(err); + + // fill in the result token + + token.dispatchClass = GetClass(); + token.objectClass = GetClass(); + token.propertyCode = typeNull; + + if (wantsAllItems) + { + err = AECreateList(NULL, 0, false, (AEDescList*)resultToken); + + if (err == noErr) + { + for (index = 1; index <= numItems; index++) + { + document = GetDocumentByIndex(index); + ThrowIfOSErr(errAEEventNotHandled); + + token.documentID = GetDocumentID(document); + + err = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token)); + ThrowIfOSErr(err); + } + } + } + else if (keyForm == formRange) + { + DocumentReference beginDocument; + DocumentReference endDocument; + long beginIndex; + long endIndex; + + beginDocument = GetDocumentReferenceFromToken(&startObject); + beginIndex = GetDocumentIndex(beginDocument); + + endDocument = GetDocumentReferenceFromToken(&stopObject); + endIndex = GetDocumentIndex(endDocument); + + err = AECreateList(NULL, 0, false, (AEDescList*)resultToken); + ThrowIfOSErr(err); + + if (beginIndex > endIndex) // swap elements + { + DocumentReference temp; + temp = beginDocument; + beginDocument = endDocument; + endDocument = temp; + } + + document = beginDocument; + while (document != nil) + { + token.documentID = GetDocumentID(document); + + err = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token)); + ThrowIfOSErr(err); + + if (document == endDocument) + break; + document = GetNextDocument(document); + } + } + else + { + token.documentID = GetDocumentID(document); + err = AECreateDesc(desiredClass, &token, sizeof(token), resultToken); + } + + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + DocumentAccessor + + Document from null accessor +----------------------------------------------------------------------------*/ +pascal OSErr AEDocumentClass::DocumentAccessor( DescType desiredClass, // cDocument + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, // specified Document is returned in result + long refCon) +{ + AEDocumentClass* docClass = reinterpret_cast(refCon); + if (!docClass) return paramErr; + + OSErr err = noErr; + + try + { + docClass->GetDocumentFromApp(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch(...) + { + err = paramErr; + } + + return err; +} + + + + +#pragma mark - + +/*---------------------------------------------------------------------------- + ProcessFormRelativePostition + +----------------------------------------------------------------------------*/ +void AEDocumentClass::ProcessFormRelativePostition(const AEDesc* anchorToken, const AEDesc *keyData, DocumentReference *document) +{ + AETokenDesc tokenDesc(anchorToken); + OSErr err = noErr; + DescType positionEnum; + DocumentReference anchorDocument; + DocumentReference relativeDocument = nil; + + *document = nil; + + anchorDocument = GetDocumentReferenceFromToken(anchorToken); + + if (err == noErr) + { + + switch (keyData->descriptorType) + { + case typeEnumerated: + if (DescToDescType((AEDesc*)keyData, &positionEnum) != noErr) + { + err = errAECoercionFail; + } + else + { + switch (positionEnum) + { + case kAENext: // get the document behind the anchor + *document = GetPreviousDocument(anchorDocument); + if (*document == nil) + err = errAENoSuchObject; + break; + + case kAEPrevious: // get the document in front of the anchor + *document = GetNextDocument(anchorDocument); + if (*document == nil) + err = errAENoSuchObject; + break; + + default: + err = errAEEventNotHandled; + break; + } + } + break; + + default: + err = errAECoercionFail; + break; + } + } + + ThrowIfOSErr(err); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CanGetProperty + +----------------------------------------------------------------------------*/ +Boolean AEDocumentClass::CanGetProperty(DescType property) +{ + Boolean result = false; + + switch (property) + { + // Properties we can get: + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pName: + case pProperties: + case pIsModified: + result = true; + break; + + // Properties we can't get: + default: + result = Inherited::CanGetProperty(property); + break; + } + + return result; +} + + +/*---------------------------------------------------------------------------- + CanSetProperty + +----------------------------------------------------------------------------*/ +Boolean AEDocumentClass::CanSetProperty(DescType property) +{ + Boolean result = false; + + switch (property) + { + // Properties we can set: + + case pName: + result = true; + break; + + // Properties we can't set: + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pProperties: + case pIsModified: + result = false; + break; + + default: + result = Inherited::CanSetProperty(property); + break; + } + + return result; +} + + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetDataFromObject + +----------------------------------------------------------------------------*/ +void AEDocumentClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) +{ + OSErr err = noErr; + Boolean usePropertyCode = false; + DocumentReference document = nil; + AETokenDesc tokenDesc(token); + DescType aType = cDocument; + Str63 documentName; + Boolean isModified; + + // ugh + document = GetDocumentReferenceFromToken(token); + ThrowIfOSErr(err); + if (document == nil) + ThrowIfOSErr(paramErr); + + GetDocumentName(document, documentName); + isModified = DocumentIsModified(document); + + usePropertyCode = tokenDesc.UsePropertyCode(); + + DescType propertyCode = tokenDesc.GetPropertyCode(); + + switch (propertyCode) + { + case pProperties: + err = AECreateList(NULL, 0L, true, data); + ThrowIfOSErr(err); + + err = AEPutKeyPtr(data, pObjectType, typeType, &aType, sizeof(DescType)); + err = AEPutKeyPtr(data, pName, typeChar, &documentName[1], documentName[0]); + err = AEPutKeyPtr(data, pIsModified, typeBoolean, &isModified, sizeof(Boolean)); + break; + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + err = AECreateDesc(typeType, &aType, sizeof(DescType), data); + break; + + case pName: + err = AECreateDesc(typeChar, &documentName[1], documentName[0], data); + break; + + case pIsModified: + err = AECreateDesc(typeBoolean, &isModified, sizeof(Boolean), data); + break; + + default: + Inherited::GetDataFromObject(token, desiredTypes, data); + break; + } + + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + SetDataForObject + +----------------------------------------------------------------------------*/ +void AEDocumentClass::SetDataForObject(const AEDesc *token, AEDesc *data) +{ + OSErr err = noErr; + Boolean usePropertyCode; + DescType propertyCode; + DocumentReference document = nil; + AETokenDesc tokenDesc(token); + StAEDesc propertyRecord; + + usePropertyCode = tokenDesc.UsePropertyCode(); + document = GetDocumentReferenceFromToken(token); + + if (usePropertyCode == false) + { + err = errAEWriteDenied; + } + else + { + propertyCode = tokenDesc.GetPropertyCode(); + + if (data->descriptorType == typeAERecord) + { + SetDocumentProperties(document, data); + } + else // Build a record with one property + { + err = AECreateList(NULL, 0L, true, &propertyRecord); + ThrowIfOSErr(err); + + err = AEPutKeyDesc(&propertyRecord, propertyCode, data); + ThrowIfOSErr(err); + + SetDocumentProperties(document, &propertyRecord); + } + } + + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + SetDocumentProperties + +----------------------------------------------------------------------------*/ +void AEDocumentClass::SetDocumentProperties(DocumentReference document, AEDesc *propertyRecord) +{ + +} + + +/*---------------------------------------------------------------------------- + CountDocuments + +----------------------------------------------------------------------------*/ +long AEDocumentClass::CountDocuments() +{ + return 0; +} + + +/*---------------------------------------------------------------------------- + GetDocumentByName + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetDocumentByName(ConstStr255Param docName) +{ + return nil; +} + +/*---------------------------------------------------------------------------- + GetDocumentByIndex + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetDocumentByIndex(long index) +{ + return nil; +} + +/*---------------------------------------------------------------------------- + GetDocumentByID + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetDocumentByID(long docID) +{ + return nil; +} + +/*---------------------------------------------------------------------------- + GetNextDocument + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetNextDocument(DocumentReference docRef) +{ + return nil; +} + + +/*---------------------------------------------------------------------------- + GetPreviousDocument + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetPreviousDocument(DocumentReference docRef) +{ + return nil; +} + + +/*---------------------------------------------------------------------------- + GetDocumentReferenceFromToken + +----------------------------------------------------------------------------*/ +DocumentReference AEDocumentClass::GetDocumentReferenceFromToken(const AEDesc *token) +{ + AETokenDesc tokenDesc(token); + long docID = tokenDesc.GetDocumentID(); + + return GetDocumentByID(docID); +} + +/*---------------------------------------------------------------------------- + CloseWindowSaving + +----------------------------------------------------------------------------*/ +void AEDocumentClass::CloseWindowSaving(AEDesc *token, const AEDesc *saving, AEDesc *savingIn) +{ + OSErr err = noErr; + DocumentReference document; + + document = GetDocumentReferenceFromToken(token); + + if (document != nil) + { + // DestroyDocument(document); + } + else + err = errAEEventNotHandled; + + ThrowIfOSErr(err); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CreateSelfSpecifier + +----------------------------------------------------------------------------*/ +void AEDocumentClass::CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier) +{ + ThrowIfOSErr(errAENoSuchObject); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetDocumentID + +----------------------------------------------------------------------------*/ +long GetDocumentID(DocumentReference docRef) +{ + return 0; +} + + +/*---------------------------------------------------------------------------- + GetDocumentIndex + +----------------------------------------------------------------------------*/ +long GetDocumentIndex(DocumentReference docRef) +{ + return 0; +} + +/*---------------------------------------------------------------------------- + GetDocumentIndex + +----------------------------------------------------------------------------*/ +void GetDocumentName(DocumentReference docRef, Str63 docName) +{ + docName[0] = 0; +} + + +/*---------------------------------------------------------------------------- + GetDocumentIndex + +----------------------------------------------------------------------------*/ +Boolean DocumentIsModified(DocumentReference docRef) +{ + return false; +} + diff --git a/xpfe/bootstrap/appleevents/nsAEDocumentClass.h b/xpfe/bootstrap/appleevents/nsAEDocumentClass.h new file mode 100644 index 000000000000..57faaa45dc42 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEDocumentClass.h @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AEDOCUMENTCLASS__ +#define __AEDOCUMENTCLASS__ + +#include "nsAEGenericClass.h" + + +typedef WindowPtr DocumentReference; // for now, we'll refer to document by their window + + +class AEDocumentClass : public AEGenericClass +{ + friend class AECoreClass; + +private: + typedef AEGenericClass Inherited; + +protected: + // only the AECoreClass can instantiate us + AEDocumentClass(); + ~AEDocumentClass(); + + void GetDocumentFromApp( DescType desiredClass, // cDocument + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); // specified Document is returned in result + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + +public: + + static pascal OSErr DocumentAccessor( DescType desiredClass, // cDocument + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, // specified Document is returned in result + long refCon); + + static pascal OSErr PropertyAccessor( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon); + + void ProcessFormRelativePostition( const AEDesc* anchorToken, + const AEDesc* keyData, + DocumentReference* document); + + void CloseWindowSaving( AEDesc* token, + const AEDesc* saving, + AEDesc* savingIn); + +protected: + + // ---------------------------------------------------------------------------- + // Get and Set methods for objects and list. Note that the object methods are pure virtual + // ---------------------------------------------------------------------------- + virtual void GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data); + void GetDataFromList(AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList); + + virtual void SetDataForObject(const AEDesc *token, AEDesc *data); + void SetDataForList(const AEDesc *token, AEDesc *data); + + virtual void CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier); + + virtual Boolean CanSetProperty(DescType propertyCode); + virtual Boolean CanGetProperty(DescType propertyCode); + + + void SetDocumentProperties(DocumentReference document, AEDesc *propertyRecord); + + DocumentReference GetDocumentReferenceFromToken(const AEDesc *token); // these can all throw + DocumentReference GetDocumentByName(ConstStr255Param docName); + DocumentReference GetDocumentByIndex(long index); + DocumentReference GetDocumentByID(long docID); + + DocumentReference GetNextDocument(DocumentReference docRef); + DocumentReference GetPreviousDocument(DocumentReference docRef); + +public: + static long CountDocuments(); + +}; + + +long GetDocumentID(DocumentReference docRef); +long GetDocumentIndex(DocumentReference docRef); +void GetDocumentName(DocumentReference docRef, Str63 docName); +Boolean DocumentIsModified(DocumentReference docRef); + + +#endif /* __AEDOCUMENTCLASS__ */ diff --git a/xpfe/bootstrap/appleevents/nsAEEventHandling.cpp b/xpfe/bootstrap/appleevents/nsAEEventHandling.cpp new file mode 100644 index 000000000000..58ec7fe13280 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEEventHandling.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEEventHandling.h" + +#include "nsAECoreClass.h" + +/*---------------------------------------------------------------------------- + CreateAEHandlerClasses + + This call creates everything. +----------------------------------------------------------------------------*/ + +OSErr CreateAEHandlerClasses(Boolean suspendFirstEvent) +{ + OSErr err = noErr; + + // if we have one, assume we have all + if (AECoreClass::sAECoreHandler) + return noErr; + + try + { + AECoreClass::sAECoreHandler = new AECoreClass(suspendFirstEvent); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + CreateAEHandlerClasses + + This call creates everything. +----------------------------------------------------------------------------*/ + +OSErr ResumeAEHandling(AppleEvent *appleEvent, AppleEvent *reply, Boolean dispatchEvent) +{ + OSErr err = noErr; + + if (!AECoreClass::sAECoreHandler) + return paramErr; + + try + { + AECoreClass::sAECoreHandler->ResumeEventHandling(appleEvent, reply, dispatchEvent); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch( ... ) + { + err = paramErr; + } + + return err; +} + + +/*---------------------------------------------------------------------------- + GetSuspendedEvent + + Return the suspended event, if any +----------------------------------------------------------------------------*/ +OSErr GetSuspendedEvent(AppleEvent *theEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + theEvent->descriptorType = typeNull; + theEvent->dataHandle = nil; + + reply->descriptorType = typeNull; + reply->dataHandle = nil; + + if (!AECoreClass::sAECoreHandler) + return paramErr; + + try + { + AECoreClass::sAECoreHandler->GetSuspendedEvent(theEvent, reply); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch( ... ) + { + err = paramErr; + } + + return err; +} + +/*---------------------------------------------------------------------------- + ShutdownAEHandlerClasses + + and this destroys the whole lot. +----------------------------------------------------------------------------*/ +OSErr ShutdownAEHandlerClasses(void) +{ + if (!AECoreClass::sAECoreHandler) + return noErr; + + try + { + delete AECoreClass::sAECoreHandler; + } + catch(...) + { + } + + AECoreClass::sAECoreHandler = nil; + return noErr; +} + diff --git a/xpfe/bootstrap/appleevents/nsAEEventHandling.h b/xpfe/bootstrap/appleevents/nsAEEventHandling.h new file mode 100644 index 000000000000..ba1c703cefd7 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEEventHandling.h @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEUtils.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSErr CreateAEHandlerClasses(Boolean suspendFirstEvent); +OSErr GetSuspendedEvent(AppleEvent *event, AppleEvent *reply); +OSErr ResumeAEHandling(AppleEvent *event, AppleEvent *reply, Boolean dispatchEvent); +OSErr ShutdownAEHandlerClasses(void); + +#ifdef __cplusplus +} +#endif + diff --git a/xpfe/bootstrap/appleevents/nsAEGenericClass.cpp b/xpfe/bootstrap/appleevents/nsAEGenericClass.cpp new file mode 100644 index 000000000000..7b2badfaeba5 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEGenericClass.cpp @@ -0,0 +1,955 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEUtils.h" +#include "nsAETokens.h" +#include "nsAECoreClass.h" + +#include "nsAEGenericClass.h" + + +/*---------------------------------------------------------------------------- + AEGenericClass + +----------------------------------------------------------------------------*/ +AEGenericClass::AEGenericClass(DescType classType, DescType containerClass) +: mClass(classType) +, mContainerClass(containerClass) +, mItemFromContainerAccessor(nil) +{ + + // Window from null accessor used by the entire window hierarchy + mItemFromContainerAccessor = NewOSLAccessorProc(AEGenericClass::ItemFromContainerAccessor); + ThrowIfNil(mItemFromContainerAccessor); + + OSErr err; + err = AEInstallObjectAccessor(mClass, containerClass, + mItemFromContainerAccessor, + (long)this, + false); + + // although items of a given class can't contain other items of the same class, + // we need this accessor to support formRelativePostion, + // which sends us one item as a "container" and asks us to find + // either the item before or after that item + err = AEInstallObjectAccessor(mClass, mClass, + mItemFromContainerAccessor, + (long)this, + false); + ThrowIfOSErr(err); + +} + +/*---------------------------------------------------------------------------- + ~AEGenericClass + +----------------------------------------------------------------------------*/ +AEGenericClass::~AEGenericClass() +{ + if (mItemFromContainerAccessor) + DisposeRoutineDescriptor(mItemFromContainerAccessor); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + DispatchEvent + + Handles all OSL messages that this object should handle +----------------------------------------------------------------------------*/ +void AEGenericClass::DispatchEvent(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + AEEventID eventID; + OSType typeCode; + Size actualSize = 0L; + + // Get the event ID + err = AEGetAttributePtr(appleEvent, keyEventIDAttr, + typeType, + &typeCode, + (Ptr)&eventID, + sizeof(eventID), + &actualSize); + ThrowIfOSErr(err); + + try + { + switch (eventID) + { + case kAEClone: + HandleDuplicate(token, appleEvent, reply); + break; + + case kAEClose: + HandleClose(token, appleEvent, reply); + break; + + case kAECountElements: + HandleCount(token, appleEvent, reply); + break; + + case kAECreateElement: + HandleMake(token, appleEvent, reply); + break; + + case kAEDelete: + HandleDelete(token, appleEvent, reply); + break; + + case kAEDoObjectsExist: + HandleExists(token, appleEvent, reply); + break; + + case kAEGetData: + HandleGetData(token, appleEvent, reply); + break; + + case kAEGetDataSize: + HandleDataSize(token, appleEvent, reply); + break; + + case kAEMove: + HandleMove(token, appleEvent, reply); + break; + + case kAEOpen: // == kAEOpenDocuments + HandleOpen(token, appleEvent, reply); + break; + + case kAEPrint: + HandlePrint(token, appleEvent, reply); + break; + + case kAEOpenApplication: + HandleRun(token, appleEvent, reply); + break; + + case kAEQuitApplication: + HandleQuit(token, appleEvent, reply); + break; + + case kAESave: + HandleSave(token, appleEvent, reply); + break; + + case kAESetData: + HandleSetData(token, appleEvent, reply); + break; + + // MT-NW suite + case kAEExtract: + HandleExtract(token, appleEvent, reply); + break; + + case kAESendMessage: + HandleSendMessage(token, appleEvent, reply); + break; + + default: + err = errAEEventNotHandled; + break; + } + } + catch (OSErr catchErr) + { + PutReplyErrorNumber(reply, catchErr); + throw; + } + catch ( ... ) + { + PutReplyErrorNumber(reply, paramErr); + throw; + } +} + + +/*---------------------------------------------------------------------------- + GetProperty + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + + // call the base class utility method, which calls back up to the object + GetPropertyFromListOrObject(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + ItemFromContainerAccessor + + Callback for getting an item from its container +----------------------------------------------------------------------------*/ +pascal OSErr AEGenericClass::ItemFromContainerAccessor( DescType desiredClass, // cWindow + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, // specified window is returned in result + long refCon) +{ + AEGenericClass* itemClass = reinterpret_cast(refCon); + if (!itemClass) return paramErr; + + OSErr err = noErr; + + try + { + itemClass->GetItemFromContainer(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + catch(OSErr catchErr) + { + err = catchErr; + } + catch(...) + { + err = paramErr; + } + + return err; +} + + + +#pragma mark - + +/*---------------------------------------------------------------------------- + HandleClose + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleCount + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + AETokenDesc 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); +} + + +/*---------------------------------------------------------------------------- + HandleGetData + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleGetData(AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + StAEDesc data; + StAEDesc desiredTypes; + + (void)AEGetParamDesc(appleEvent, keyAERequestedType, typeAEList, &desiredTypes); + + GetDataFromListOrObject(tokenOrTokenList, &desiredTypes, &data); + + if (reply->descriptorType != typeNull) + { + err = AEPutKeyDesc(reply, keyDirectObject, &data); + ThrowIfOSErr(err); + } +} + +/*---------------------------------------------------------------------------- + HandleSetData + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + SetDataForListOrObject(token, appleEvent, reply); +} + +/*---------------------------------------------------------------------------- + HandleDataSize + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleDelete + + All attempts to delete an empty list are handled here + Application contains documents and windows, and they can't be deleted + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleDuplicate + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleExists + + If exists... + The AEResolve() function in AERCoreSuite.c will already have filtered + out all cases where the object did not exist, so this function should + always return TRUE. + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err; + Boolean foundIt = true; + + err = AEPutParamPtr(reply, + keyAEResult, + typeBoolean, + (Ptr)&foundIt, + sizeof(Boolean)); + + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + HandleMake + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + DescType insertionPos = typeNull; + OSErr err = noErr; + + StAEDesc insertionLoc; + StAEDesc objectSpec; + + // For Create Element, the object specifier is contained in + // a typeInsertionLoc record instead of in a direct parameter. + // We coerce the insertionLoc record into an AERecord so we can extract the fields. + // Notice that this is a REQUIRED parameter, but we give it a default behavior + // by creating a new element at beginning of the first document + + err = ::AEGetParamDesc(appleEvent, // Extract as a AERecord + keyAEInsertHere, + typeAERecord, + &insertionLoc); + if (err == errAEDescNotFound) + { + insertionPos = kAEBeginning; + err = noErr; + } + else if (err == noErr) + { + // Get the enumerated insertion location (at end, in front, before, after, replace.) + + OSType typeCode; + Size actualSize; + err = ::AEGetKeyPtr(&insertionLoc, + keyAEPosition, // insertion location + typeEnumeration, + &typeCode, + (Ptr)&insertionPos, + sizeof(insertionPos), + &actualSize); + + // Extract and resolve the object specifier from the insertion location record. + // In a case like "make new rectangle before rectangle 1 of document 1", + // the ospec will resolve to "rectangle 1 of document 1" + + err = ::AEGetKeyDesc(&insertionLoc, + keyAEObject, + typeWildCard, + &objectSpec); + } + + // if there was a object specifier in the insertion location (eg, "before rectangle 1 of document 1"), + // then we call AEResolve() to get a token for it, + // Otherwise, is was something like "at end" or "at beginning", which is also OK, + // then deal with it correctly later. + if (objectSpec.descriptorType == typeNull) + { + ::AEDisposeDesc(token); // destroy it's old representation, token will now be null descriptor + } + else + { + err = ::AEResolve(&objectSpec, + kAEIDoMinimum, + token); // token will contain info about the object to insert before, after, etc. + ThrowIfOSErr(err); + } + + // Extract the optional parameters from the AppleEvent + + // ----- [with data ....] ----- + + StAEDesc withData; + const AEDesc* withDataPtr = nil; + + err = ::AEGetParamDesc(appleEvent, + keyAEData, + typeWildCard, + &withData); + if (err == errAEDescNotFound) + err = noErr; + else + { + ThrowIfOSErr(err); + withDataPtr = &withData; + } + + // ----- [with properties {property: value, ...}] ----- + StAEDesc withProperties; + const AEDesc* withPropertiesPtr = nil; + err = AEGetParamDesc(appleEvent, + keyAEPropData, + typeWildCard, + &withProperties); + + if (err == errAEDescNotFound) + err = noErr; + else + { + ThrowIfOSErr(err); + withPropertiesPtr = &withProperties; + } + + // Finally, use the token and other parameters to create & initialize the object + MakeNewObject(insertionPos, token, withDataPtr, withPropertiesPtr, reply); +} + +/*---------------------------------------------------------------------------- + HandleMove + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleOpen + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleRun + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleRun(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandlePrint + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleQuit + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleSave + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowOSErr(errAEEventNotHandled); +} + + +/*---------------------------------------------------------------------------- + HandleExtract + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleExtract(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowOSErr(errAEEventNotHandled); +} + + +/*---------------------------------------------------------------------------- + HandleSendMessage + + +----------------------------------------------------------------------------*/ +void AEGenericClass::HandleSendMessage(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowOSErr(errAEEventNotHandled); +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CompareObjects + +----------------------------------------------------------------------------*/ +void AEGenericClass::CompareObjects( DescType comparisonOperator, + const AEDesc * object, + const AEDesc * descriptorOrObject, + Boolean * result) +{ + ThrowOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + CountObjects + +----------------------------------------------------------------------------*/ +void AEGenericClass::CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + ThrowOSErr(errAEEventNotHandled); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetDataFromListOrObject + + +----------------------------------------------------------------------------*/ + +void AEGenericClass::GetDataFromListOrObject(const AEDesc *tokenOrTokenList, AEDesc *desiredTypes, AEDesc *data) +{ + if (AEListUtils::TokenContainsTokenList(tokenOrTokenList) == false) + { + GetDataFromObject(tokenOrTokenList, desiredTypes, data); + } + else + { + ThrowIfOSErr(AECreateList(nil, 0, false, data)); + GetDataFromList(tokenOrTokenList, desiredTypes, data); + } +} + +/*---------------------------------------------------------------------------- + GetDataFromListOrObject + + +----------------------------------------------------------------------------*/ + +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: + { + AETokenDesc 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); + } +} + +/*---------------------------------------------------------------------------- + GetDataFromList + + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetDataFromList(const AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList) +{ + OSErr err; + long itemNum; + long numItems; + DescType keyword; + StAEDesc srcItem; + StAEDesc dstItem; + + err = AECountItems((AEDescList*)srcList, &numItems); + ThrowIfOSErr(err); + + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + err = AEGetNthDesc(srcList, itemNum, typeWildCard, &keyword, &srcItem); + ThrowIfOSErr(err); + + if (AEListUtils::TokenContainsTokenList(&srcItem) == false) + { + GetDataFromObject(&srcItem, desiredTypes, &dstItem); // Get data from single item + } + else + { + ThrowIfOSErr(AECreateList(nil, 0, false, &dstItem)); + GetDataFromList(&srcItem, desiredTypes, &dstItem); + } + err = AEPutDesc(dstList, itemNum, &dstItem); + ThrowIfOSErr(err); + } +} + + +/*---------------------------------------------------------------------------- + GetDataFromObject + + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) +{ + AETokenDesc 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); +} + + +/*---------------------------------------------------------------------------- + SetDataForList + + Given a token that contains a list of cWindow tokens, + walk the list recursively to set the data for each token in the list + +----------------------------------------------------------------------------*/ +void AEGenericClass::SetDataForList(const AEDesc *token, AEDesc *data) +{ + OSErr err; + + if (AEListUtils::TokenContainsTokenList(token) == false) + { + SetDataForObject(token, data); + } + else + { + long numItems; + long itemNum; + err = AECountItems((AEDescList*)token, &numItems); + ThrowIfOSErr(err); + + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + StAEDesc tempToken; + AEKeyword keyword; + + err = AEGetNthDesc((AEDescList*)token, itemNum, typeWildCard, &keyword, &tempToken); + ThrowIfOSErr(err); + + if (AEListUtils::TokenContainsTokenList(&tempToken) == false) + { + SetDataForObject(&tempToken, data); // Set data from single item + } + else + { + SetDataForList(&tempToken, data); // Recurse sublist + } + } + } +} + + +/*---------------------------------------------------------------------------- + CanGetProperty + +----------------------------------------------------------------------------*/ +DescType AEGenericClass::GetKeyEventDataAs(DescType propertyCode) +{ + return typeWildCard; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CanGetProperty + +----------------------------------------------------------------------------*/ +Boolean AEGenericClass::CanGetProperty(DescType propertyCode) +{ + Boolean canGet = false; + + switch (propertyCode) + { + case pContents: + canGet = true; + break; + } + return canGet; +} + +/*---------------------------------------------------------------------------- + CanSetProperty + +----------------------------------------------------------------------------*/ +Boolean AEGenericClass::CanSetProperty(DescType propertyCode) +{ + return false; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CreateSpecifier + + Subclasses should not need to override this. It +----------------------------------------------------------------------------*/ +void AEGenericClass::CreateSpecifier(const AEDesc *token, AEDesc *outSpecifier) +{ + CreateSelfSpecifier(token, outSpecifier); +} + +/*---------------------------------------------------------------------------- + GetContainerSpecifier + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetContainerSpecifier(const AEDesc *token, AEDesc *outContainerSpecifier) +{ + outContainerSpecifier->descriptorType = typeNull; + outContainerSpecifier->dataHandle = nil; + + AEDispatchHandler* handler = AECoreClass::GetDispatchHandlerForClass(mContainerClass); + if (handler) + { + handler->CreateSelfSpecifier(token, outContainerSpecifier); + } +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetPropertyFromListOrObject + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetPropertyFromListOrObject( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + if (AEListUtils::TokenContainsTokenList((AEDescList*)containerToken) == false) + { + GetPropertyFromObject(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } + else + { + OSErr err = AECreateList(nil, 0, false, resultToken); + ThrowIfOSErr(err); + + GetPropertyFromList(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); + } +} + + +/*---------------------------------------------------------------------------- + GetPropertyFromList + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetPropertyFromList( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + OSErr err = noErr; + long itemNum; + long numItems; + DescType keyword; + + err = AECountItems((AEDescList*)containerToken, &numItems); + ThrowIfOSErr(err); + + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + StAEDesc srcItem; + StAEDesc dstItem; + + err = AEGetNthDesc(containerToken, itemNum, typeWildCard, &keyword, &srcItem); + ThrowIfOSErr(err); + + if (AEListUtils::TokenContainsTokenList(&srcItem) == false) + { + GetPropertyFromObject(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem); + } + else + { + err = AECreateList(nil, 0, false, &dstItem); + ThrowIfOSErr(err); + + GetPropertyFromList(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem); + } + + err = AEPutDesc(resultToken, itemNum, &dstItem); + ThrowIfOSErr(err); + } + +} + + +/*---------------------------------------------------------------------------- + GetPropertyFromObject + +----------------------------------------------------------------------------*/ +void AEGenericClass::GetPropertyFromObject( DescType desiredType, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + OSErr err; + DescType requestedProperty; + + err = AEDuplicateDesc(containerToken, resultToken); + ThrowIfOSErr(err); + + requestedProperty = **(DescType**)(keyData->dataHandle); + + if (requestedProperty == kAEAll || requestedProperty == keyAEProperties) + requestedProperty = pProperties; + + if (CanGetProperty(requestedProperty) || CanSetProperty(requestedProperty)) + { + AETokenDesc resultTokenDesc(resultToken); + resultToken->descriptorType = desiredType; + resultTokenDesc.SetPropertyCode(requestedProperty); + } + else + { + ThrowIfOSErr(errAEEventNotHandled); + } +} + + +#pragma mark - + + +/*---------------------------------------------------------------------------- + MakeNewObject + +----------------------------------------------------------------------------*/ +void AEGenericClass::MakeNewObject( const DescType insertionPosition, + const AEDesc* token, + const AEDesc* ptrToWithData, + const AEDesc* ptrToWithProperties, + AppleEvent* reply) +{ + ThrowOSErr(errAEEventNotHandled); +} + diff --git a/xpfe/bootstrap/appleevents/nsAEGenericClass.h b/xpfe/bootstrap/appleevents/nsAEGenericClass.h new file mode 100644 index 000000000000..7c4a4b8e740d --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEGenericClass.h @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AEGENERICCLASS__ +#define __AEGENERICCLASS__ + + +#include "nsAEClassIterator.h" + +// pure virtual base class that provides stubs for much objecct functionality. + +class AEGenericClass +{ + friend class AEDispatchHandler; +public: + + AEGenericClass(DescType classType, DescType containerClass); // throws OSErrs + virtual ~AEGenericClass(); + + + // ---------------------------------------------------------------------------- + // Dispatch routine + // ---------------------------------------------------------------------------- + void DispatchEvent( AEDesc* token, + const AppleEvent* appleEvent, + AppleEvent* reply); // throws OSErrs + + // ---------------------------------------------------------------------------- + // Item from container accessor + // ---------------------------------------------------------------------------- + static pascal OSErr ItemFromContainerAccessor( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, + long refCon); + +protected: + + // MT-NW suite events + enum { + kAEExtract = 'Extr', + kExtractKeyDestFolder = 'Fold', + + kAESendMessage = 'Post' + }; + + + virtual void GetPropertyFromObject( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual void GetProperty( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + // ---------------------------------------------------------------------------- + // GetItemFromContainer + // + // Overridable method to get an item from its container. + // + // ---------------------------------------------------------------------------- + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) = 0; + + // ---------------------------------------------------------------------------- + // OSL Callbacks (compare and count) + // ---------------------------------------------------------------------------- + virtual void CompareObjects( DescType comparisonOperator, + const AEDesc * object, + const AEDesc * descriptorOrObject, + Boolean * result); + + virtual void CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + + // ---------------------------------------------------------------------------- + // Core Suite Object Event handlers + // ---------------------------------------------------------------------------- + virtual void HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleGetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleRun(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + + // ---------------------------------------------------------------------------- + // MT-NW suite event handlers + // ---------------------------------------------------------------------------- + virtual void HandleExtract(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleSendMessage(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + + // ---------------------------------------------------------------------------- + // Get and Set methods for objects and list. Note that the object methods are pure virtual + // ---------------------------------------------------------------------------- + + virtual void GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) = 0; + virtual void SetDataForObject(const AEDesc *token, AEDesc *data) = 0; + + // ---------------------------------------------------------------------------- + // Methods for creating self and container specifiers + // ---------------------------------------------------------------------------- + + void CreateSpecifier(const AEDesc *token, AEDesc *outSpecifier); + virtual void GetContainerSpecifier(const AEDesc *token, AEDesc *outContainerSpecifier); + + virtual void CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier) = 0; + + void GetDataFromListOrObject(const AEDesc *tokenOrTokenList, AEDesc *desiredTypes, AEDesc *data); + void SetDataForListOrObject(const AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply); + + void GetDataFromList(const AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList); + void SetDataForList(const AEDesc *token, AEDesc *data); + + void GetPropertyFromListOrObject( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + void GetPropertyFromList( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual DescType GetKeyEventDataAs(DescType propertyCode); + + virtual Boolean CanSetProperty(DescType propertyCode) = 0; + virtual Boolean CanGetProperty(DescType propertyCode) = 0; + + DescType GetClass() { return mClass; } + + + // ---------------------------------------------------------------------------- + // Methods called from the main handlers + // ---------------------------------------------------------------------------- + + virtual void MakeNewObject( const DescType insertionPosition, + const AEDesc* token, + const AEDesc* ptrToWithData, + const AEDesc* ptrToWithProperties, + AppleEvent* reply); + + +protected: + + DescType mClass; + DescType mContainerClass; + + OSLAccessorUPP mItemFromContainerAccessor; + +}; + + +#endif /* __AEGENERICCLASS__ */ + diff --git a/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.cpp b/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.cpp new file mode 100644 index 000000000000..53ebe7422501 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.cpp @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsIAllocator.h" + +#include "nsAEGetURLSuiteHandler.h" +#include "nsCommandLineServiceMac.h" + + +/*---------------------------------------------------------------------------- + AEGetURLSuiteHandler + +----------------------------------------------------------------------------*/ +AEGetURLSuiteHandler::AEGetURLSuiteHandler() +{ +} + +/*---------------------------------------------------------------------------- + ~AEGetURLSuiteHandler + +----------------------------------------------------------------------------*/ +AEGetURLSuiteHandler::~AEGetURLSuiteHandler() +{ +} + + +/*---------------------------------------------------------------------------- + HandleGetURLSuiteEvent + +----------------------------------------------------------------------------*/ +void AEGetURLSuiteHandler::HandleGetURLSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + AEEventID eventID; + OSType typeCode; + Size actualSize = 0L; + + // Get the event ID + err = AEGetAttributePtr(appleEvent, keyEventIDAttr, + typeType, + &typeCode, + (Ptr)&eventID, + sizeof(eventID), + &actualSize); + ThrowIfOSErr(err); + + try + { + switch (eventID) + { + case kGetURLEvent: + HandleGetURLEvent(appleEvent, reply); + break; + + default: + ThrowOSErr(errAEEventNotHandled); + break; + } + } + catch (OSErr catchErr) + { + PutReplyErrorNumber(reply, catchErr); + throw; + } + catch ( ... ) + { + PutReplyErrorNumber(reply, paramErr); + throw; + } +} + + +/*---------------------------------------------------------------------------- + HandleGetURLEvent + +----------------------------------------------------------------------------*/ +void AEGetURLSuiteHandler::HandleGetURLEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + StAEDesc directParameter; + OSErr err; + + // extract the direct parameter (an object specifier) + err = ::AEGetKeyDesc(appleEvent, keyDirectObject, typeWildCard, &directParameter); + ThrowIfOSErr(err); + + // we need to look for other parameters, to do with destination etc. + + long dataSize = directParameter.GetDataSize(); + char* urlString = (char *)nsAllocator::Alloc(dataSize + 1); + ThrowIfNil(urlString); + + directParameter.GetCString(urlString, dataSize); + + nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); + cmdLine.DispatchURLToNewBrowser(urlString); + + nsAllocator::Free(urlString); +} + diff --git a/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.h b/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.h new file mode 100644 index 000000000000..dd964955562f --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEGetURLSuiteHandler.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#ifndef nsAEGetURLSuiteHandler_h_ +#define nsAEGetURLSuiteHandler_h_ + +#include "nsAEUtils.h" + + +class AEGetURLSuiteHandler +{ +public: + enum { + kGetURLEvent = 'GURL' + }; + + AEGetURLSuiteHandler(); + ~AEGetURLSuiteHandler(); + + void HandleGetURLSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + +protected: + + void HandleGetURLEvent(AppleEvent *appleEvent, AppleEvent *reply); + +}; + + + + +#endif // nsAEGetURLSuiteHandler_h_ diff --git a/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.cpp b/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.cpp new file mode 100644 index 000000000000..d43bd829bd85 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.cpp @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAEMozillaSuiteHandler.h" + + +/*---------------------------------------------------------------------------- + AEMozillaSuiteHandler + +----------------------------------------------------------------------------*/ +AEMozillaSuiteHandler::AEMozillaSuiteHandler() +{ +} + + +/*---------------------------------------------------------------------------- + ~AEMozillaSuiteHandler + +----------------------------------------------------------------------------*/ +AEMozillaSuiteHandler::~AEMozillaSuiteHandler() +{ +} + + +/*---------------------------------------------------------------------------- + HandleMozillaSuiteEvent + +----------------------------------------------------------------------------*/ +void AEMozillaSuiteHandler::HandleMozillaSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + AEEventID eventID; + OSType typeCode; + Size actualSize = 0L; + + // Get the event ID + err = AEGetAttributePtr(appleEvent, keyEventIDAttr, + typeType, + &typeCode, + (Ptr)&eventID, + sizeof(eventID), + &actualSize); + ThrowIfOSErr(err); + + try + { + switch (eventID) + { + case kDoJavaScriptEvent: + // write me! + ThrowOSErr(errAEEventNotHandled); + break; + + default: + ThrowOSErr(errAEEventNotHandled); + break; + } + } + catch (OSErr catchErr) + { + PutReplyErrorNumber(reply, catchErr); + throw; + } + catch ( ... ) + { + PutReplyErrorNumber(reply, paramErr); + throw; + } +} + diff --git a/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.h b/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.h new file mode 100644 index 000000000000..5c4b3c7060f4 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEMozillaSuiteHandler.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#ifndef nsAEMozillaSuiteHandler_h_ +#define nsAEMozillaSuiteHandler_h_ + +#include "nsAEUtils.h" + + +class AEMozillaSuiteHandler +{ +public: + enum { + kDoJavaScriptEvent = 'jscr' + }; + + AEMozillaSuiteHandler(); + ~AEMozillaSuiteHandler(); + + void HandleMozillaSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + +protected: + + +}; + + + +#endif // nsAEMozillaSuiteHandler_h_ diff --git a/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.cpp b/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.cpp new file mode 100644 index 000000000000..5463def3abbd --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.cpp @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsIAllocator.h" + +#include "nsAESpyglassSuiteHandler.h" +#include "nsCommandLineServiceMac.h" + +/*---------------------------------------------------------------------------- + AESpyglassSuiteHandler + +----------------------------------------------------------------------------*/ +AESpyglassSuiteHandler::AESpyglassSuiteHandler() +{ +} + +/*---------------------------------------------------------------------------- + ~AESpyglassSuiteHandler + +----------------------------------------------------------------------------*/ +AESpyglassSuiteHandler::~AESpyglassSuiteHandler() +{ +} + + +/*---------------------------------------------------------------------------- + HandleSpyglassSuiteEvent + +----------------------------------------------------------------------------*/ +void AESpyglassSuiteHandler::HandleSpyglassSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + + AEEventID eventID; + OSType typeCode; + Size actualSize = 0L; + + // Get the event ID + err = AEGetAttributePtr(appleEvent, keyEventIDAttr, + typeType, + &typeCode, + (Ptr)&eventID, + sizeof(eventID), + &actualSize); + ThrowIfOSErr(err); + + try + { + switch (eventID) + { + case kOpenURLEvent: + HandleOpenURLEvent(appleEvent, reply); + break; + + default: + ThrowOSErr(errAEEventNotHandled); + break; + } + } + catch (OSErr catchErr) + { + PutReplyErrorNumber(reply, catchErr); + throw; + } + catch ( ... ) + { + PutReplyErrorNumber(reply, paramErr); + throw; + } +} + + +/*---------------------------------------------------------------------------- + HandleOpenURLEvent + +----------------------------------------------------------------------------*/ +void AESpyglassSuiteHandler::HandleOpenURLEvent(AppleEvent *appleEvent, AppleEvent *reply) +{ + StAEDesc directParameter; + OSErr err; + + // extract the direct parameter (an object specifier) + err = ::AEGetKeyDesc(appleEvent, keyDirectObject, typeWildCard, &directParameter); + ThrowIfOSErr(err); + + // we need to look for other parameters, to do with destination etc. + + + long dataSize = directParameter.GetDataSize(); + char* urlString = (char *)nsAllocator::Alloc(dataSize + 1); + ThrowIfNil(urlString); + + directParameter.GetCString(urlString, dataSize); + + nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); + cmdLine.DispatchURLToNewBrowser(urlString); + + nsAllocator::Free(urlString); +} + + + diff --git a/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.h b/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.h new file mode 100644 index 000000000000..c577fa7c7bf1 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAESpyglassSuiteHandler.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + +#ifndef nsAESpyglassSuiteHandler_h_ +#define nsAESpyglassSuiteHandler_h_ + + +#include "nsAEUtils.h" + + +class AESpyglassSuiteHandler +{ +public: + enum { + kOpenURLEvent = 'OURL' + }; + + AESpyglassSuiteHandler(); + ~AESpyglassSuiteHandler(); + + void HandleSpyglassSuiteEvent(AppleEvent *appleEvent, AppleEvent *reply); // throws OSErrs + +protected: + + void HandleOpenURLEvent(AppleEvent *appleEvent, AppleEvent *reply); +}; + + + + + + +#endif // nsAESpyglassSuiteHandler_h_ diff --git a/xpfe/bootstrap/appleevents/nsAETokens.cpp b/xpfe/bootstrap/appleevents/nsAETokens.cpp new file mode 100644 index 000000000000..596d4471065d --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAETokens.cpp @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#include "nsAETokens.h" + +// --------------------------------------------------------------------------- + +DescType AETokenDesc::GetDispatchClass() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).dispatchClass : typeNull; +} + +// --------------------------------------------------------------------------- + +DescType AETokenDesc::GetObjectClass() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).objectClass : typeNull; +} + +// --------------------------------------------------------------------------- +// The field usePropertyCode has been removed from the token record, +// so we emulate it here by seeing if the propertyCode field is typeNull, +// which is interpreted to mean that this is NOT a property token + +Boolean AETokenDesc::UsePropertyCode() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? ((**tokenData).propertyCode != typeNull) : false; +} + +// --------------------------------------------------------------------------- + +DescType AETokenDesc::GetPropertyCode() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).propertyCode : typeNull; +} + +// --------------------------------------------------------------------------- + +long AETokenDesc::GetDocumentID() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).documentID : 0; +} + +// --------------------------------------------------------------------------- + +WindowPtr AETokenDesc::GetWindowPtr() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).window : nil; +} + + +// --------------------------------------------------------------------------- + +TAEListIndex AETokenDesc::GetElementNumber() const +{ + CoreTokenHandle tokenData = GetTokenHandle(); + return (tokenData) ? (**tokenData).elementNumber : 0; +} + + + +#pragma mark - + +// --------------------------------------------------------------------------- + +void AETokenDesc::SetPropertyCode(DescType propertyCode) +{ + CoreTokenHandle tokenData = GetTokenHandle(); + ThrowIfNil(tokenData); + (**tokenData).propertyCode = propertyCode; +} + +// --------------------------------------------------------------------------- +void AETokenDesc::SetDispatchClass(DescType dispatchClass) +{ + CoreTokenHandle tokenData = GetTokenHandle(); + ThrowIfNil(tokenData); + (**tokenData).dispatchClass = dispatchClass; +} + + +// --------------------------------------------------------------------------- +void AETokenDesc::SetObjectClass(DescType objectClass) +{ + CoreTokenHandle tokenData = GetTokenHandle(); + ThrowIfNil(tokenData); + (**tokenData).objectClass = objectClass; +} + +// --------------------------------------------------------------------------- +void AETokenDesc::SetElementNumber(TAEListIndex number) +{ + CoreTokenHandle tokenData = GetTokenHandle(); + ThrowIfNil(tokenData); + (**tokenData).elementNumber = number; +} + +// --------------------------------------------------------------------------- +void AETokenDesc::SetWindow(WindowPtr wind) +{ + CoreTokenHandle tokenData = GetTokenHandle(); + ThrowIfNil(tokenData); + (**tokenData).window = wind; +} + + diff --git a/xpfe/bootstrap/appleevents/nsAETokens.h b/xpfe/bootstrap/appleevents/nsAETokens.h new file mode 100644 index 000000000000..03ab64243a07 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAETokens.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AETOKENS__ +#define __AETOKENS__ + +#include "nsAEUtils.h" + + +// ---------------------------------------------------------------------------- +// This is the token record used for all tokens in the CORE Suite +// This uses the "kitchen sink" token metaphor: a single token is used to represent +// all objects, and some fields are only appropriate for some objects. + +struct CoreTokenRecord +{ + DescType dispatchClass; // the class that will dispatch this class + DescType objectClass; // the actual class of the tokenized object + DescType propertyCode; // property code, or typeNull if not a property token + long documentID; + TAEListIndex elementNumber; + WindowPtr window; // only used for window objects + + CoreTokenRecord() + : dispatchClass(typeNull) + , objectClass(typeNull) + , propertyCode(typeNull) + , documentID(0) + , elementNumber(0) + , window(nil) + { + } +}; + + +typedef struct CoreTokenRecord CoreTokenRecord, *CoreTokenPtr, **CoreTokenHandle; + + +// AETokenDesc +// A utility class designed to give easy access to the contents of the token + +class AETokenDesc +{ +public: + AETokenDesc(const AEDesc* token) { mToken = token; } + ~AETokenDesc() {} + + DescType GetDispatchClass() const; + DescType GetObjectClass() const; + Boolean UsePropertyCode() const; + DescType GetPropertyCode() const; + + long GetDocumentID() const; + WindowPtr GetWindowPtr() const; + TAEListIndex GetElementNumber() const; + + void SetDispatchClass(DescType dispatchClass); + void SetObjectClass(DescType objectClass); + void SetPropertyCode(DescType propertyCode); + void SetElementNumber(TAEListIndex number); + void SetWindow(WindowPtr wind); + +protected: + + CoreTokenHandle GetTokenHandle() const + { + if (mToken->dataHandle && GetHandleSize(mToken->dataHandle) == sizeof(CoreTokenRecord)) + return (CoreTokenHandle)mToken->dataHandle; + else + return nil; + } + + const AEDesc* mToken; +}; + + +#endif /* __AETOKENS__ */ + diff --git a/xpfe/bootstrap/appleevents/nsAEUtils.cpp b/xpfe/bootstrap/appleevents/nsAEUtils.cpp new file mode 100644 index 000000000000..24dbc9828c30 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEUtils.cpp @@ -0,0 +1,1259 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include + + +#include "nsAETokens.h" +#include "nsAEUtils.h" + + + + +/*---------------------------------------------------------------------------- + CreateAliasAEDesc + + Create an AE descriptor for an alias +----------------------------------------------------------------------------*/ + +OSErr CreateAliasAEDesc(AliasHandle theAlias, AEDesc *ioDesc) +{ + char state = HGetState((Handle)theAlias); + OSErr err; + + HLock((Handle)theAlias); + err = AECreateDesc(typeAlias, *theAlias, GetHandleSize((Handle)theAlias), ioDesc); + HSetState((Handle)theAlias, state); + return err; +} + + +/*---------------------------------------------------------------------------- + GetTextFromAEDesc + + Get a text handle from an AEDesc +----------------------------------------------------------------------------*/ +OSErr GetTextFromAEDesc(const AEDesc *inDesc, Handle *outTextHandle) +{ + Handle textHandle = nil; + Size textLength; + OSErr err; + + textLength = AEGetDescDataSize(inDesc); + + err = MyNewHandle(textLength, &textHandle); + if (err != noErr) return err; + + MyHLock(textHandle); + err = AEGetDescData(inDesc, typeChar, *textHandle, textLength); + MyHUnlock(textHandle); + + if (err != noErr) + goto exit; + + *outTextHandle = textHandle; + return noErr; + +exit: + MyDisposeHandle(textHandle); + return err; +} + + +#if !TARGET_CARBON + +/*---------------------------------------------------------------------------- + AEGetDescData + + Get a copy of the data from the AE desc. The will attempt to coerce to the + requested type, returning an error on failure. +----------------------------------------------------------------------------*/ +OSErr AEGetDescData(const AEDesc *theAEDesc, DescType typeCode, void *dataPtr, Size maximumSize) +{ + Size dataLength; + OSErr err; + + if (theAEDesc->descriptorType != typeCode) + { + AEDesc coercedDesc = { typeNull, nil }; + + err = AECoerceDesc(theAEDesc, typeCode, &coercedDesc); + if (err != noErr) return err; + + dataLength = GetHandleSize(coercedDesc.dataHandle); + BlockMoveData(*coercedDesc.dataHandle, dataPtr, Min(dataLength, maximumSize)); + + AEDisposeDesc(&coercedDesc); + } + else + { + if (theAEDesc->dataHandle) + { + dataLength = GetHandleSize(theAEDesc->dataHandle); + BlockMoveData(*theAEDesc->dataHandle, dataPtr, Min(dataLength, maximumSize)); + } + else + return paramErr; + } + + return noErr; +} + + +/*---------------------------------------------------------------------------- + AEGetDescDataSize + + Get the size of the datahandle. +----------------------------------------------------------------------------*/ +Size AEGetDescDataSize(const AEDesc *theAEDesc) +{ + Size dataSize = 0; + + if (theAEDesc->dataHandle) + dataSize = GetHandleSize(theAEDesc->dataHandle); + + return dataSize; +} + + +#endif //TARGET_CARBON + + +#pragma mark - + + +/*---------------------------------------------------------------------------- + CreateThreadAEInfo + + Allocate a block for the thread info, and fill it. +----------------------------------------------------------------------------*/ +OSErr CreateThreadAEInfo(const AppleEvent *event, AppleEvent *reply, TThreadAEInfoPtr *outThreadAEInfo) +{ + TThreadAEInfo *threadAEInfo = nil; + OSErr err; + + err = MyNewBlockClear(sizeof(TThreadAEInfo), &threadAEInfo); + if (err != noErr) return err; + + threadAEInfo->mAppleEvent = *event; + threadAEInfo->mReply = *reply; + threadAEInfo->mGotEventData = event && reply; + threadAEInfo->mSuspendCount = nil; + + *outThreadAEInfo = threadAEInfo; + return noErr; + +exit: + MyDisposeBlock(threadAEInfo); + return err; +} + + +/*---------------------------------------------------------------------------- + DisposeThreadAEInfo + + Dispose of the thread AE info +----------------------------------------------------------------------------*/ +void DisposeThreadAEInfo(TThreadAEInfo *threadAEInfo) +{ + ASSERT(threadAEInfo && threadAEInfo->mSuspendCount == 0, "Bad suspend count"); + MyDisposeBlock(threadAEInfo); +} + + +/*---------------------------------------------------------------------------- + SuspendThreadAE + + If this if the first suspend, suspend the event. Increment the suspend count. +----------------------------------------------------------------------------*/ +OSErr SuspendThreadAE(TThreadAEInfo *threadAEInfo) +{ + if (threadAEInfo == nil) return noErr; + if (!threadAEInfo->mGotEventData) return noErr; + + if (threadAEInfo->mSuspendCount == 0) + { + OSErr err = AESuspendTheCurrentEvent(&threadAEInfo->mAppleEvent); + if (err != noErr) return err; + } + + ++ threadAEInfo->mSuspendCount; + return noErr; +} + + +/*---------------------------------------------------------------------------- + ResumeThreadAE + + Decrement the suspend count. If this is the last resume, resume the event. +----------------------------------------------------------------------------*/ + +static OSErr AddErrorCodeToReply(TThreadAEInfo *threadAEInfo, OSErr threadError) +{ + long errorValue = threadError; + + if (threadError == noErr) return noErr; + + return AEPutParamPtr(&threadAEInfo->mReply, keyErrorNumber, typeLongInteger, (Ptr)&errorValue, sizeof(long)); +} + + +/*---------------------------------------------------------------------------- + ResumeThreadAE + + Decrement the suspend count. If this is the last resume, resume the event. +----------------------------------------------------------------------------*/ +OSErr ResumeThreadAE(TThreadAEInfo *threadAEInfo, OSErr threadError) +{ + if (threadAEInfo == nil) return noErr; + if (!threadAEInfo->mGotEventData) return noErr; + + -- threadAEInfo->mSuspendCount; + + AddErrorCodeToReply(threadAEInfo, threadError); + + if (threadAEInfo->mSuspendCount == 0) + return AEResumeTheCurrentEvent(&threadAEInfo->mAppleEvent, &threadAEInfo->mReply, (AEEventHandlerUPP)kAENoDispatch, 0); + + return noErr; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + Copy ctor + + this can throw + +----------------------------------------------------------------------------*/ + +StAEDesc::StAEDesc(const StAEDesc& rhs) +{ + ThrowIfOSErr(AEDuplicateDesc(&rhs, this)); +} + +/*---------------------------------------------------------------------------- + operator = + + this can throw + +----------------------------------------------------------------------------*/ + +StAEDesc& StAEDesc::operator= (const StAEDesc& rhs) +{ + ThrowIfOSErr(AEDuplicateDesc(&rhs, this)); + return *this; +} + + +/*---------------------------------------------------------------------------- + Data getters + + These should try to coerce when necessary also. +----------------------------------------------------------------------------*/ + +Boolean StAEDesc::GetBoolean() +{ + if (descriptorType == typeBoolean) + return **(Boolean **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeBoolean, &tempDesc) == noErr) + return **(Boolean **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } + return false; +} + +SInt16 StAEDesc::GetShort() +{ + if (descriptorType == typeShortInteger) + return **(SInt16 **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeShortInteger, &tempDesc) == noErr) + return **(SInt16 **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } + return 0; +} + +SInt32 StAEDesc::GetLong() +{ + if (descriptorType == typeLongInteger) + return **(SInt32 **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeLongInteger, &tempDesc) == noErr) + return **(SInt32 **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } + return 0; +} + +DescType StAEDesc::GetEnumType() +{ + if (descriptorType == typeEnumeration) + return **(DescType **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeEnumeration, &tempDesc) == noErr) + return **(DescType **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } + return 0; +} + + +void StAEDesc::GetRect(Rect& outData) +{ + if (descriptorType == typeQDRectangle) + outData = **(Rect **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeQDRectangle, &tempDesc) == noErr) + outData = **(Rect **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } +} + + +void StAEDesc::GetRGBColor(RGBColor& outData) +{ + if (descriptorType == typeRGBColor) + outData = **(RGBColor **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeRGBColor, &tempDesc) == noErr) + outData = **(RGBColor **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } +} + + +void StAEDesc::GetLongDateTime(LongDateTime& outDateTime) +{ + if (descriptorType == typeLongDateTime) + outDateTime = **(LongDateTime **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeLongDateTime, &tempDesc) == noErr) + outDateTime = **(LongDateTime **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } +} + +void StAEDesc::GetFileSpec(FSSpec &outFileSpec) +{ + if (descriptorType == typeFSS) + outFileSpec = **(FSSpec **)dataHandle; + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeFSS, &tempDesc) == noErr) + outFileSpec = **(FSSpec **)tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } +} + +void StAEDesc::GetCString(char *outString, short maxLen) +{ + if (descriptorType == typeChar) + { + long dataSize = GetDataSize(); + StrCopySafe(outString, *dataHandle, Min(dataSize, maxLen)); + } + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr) + { + long dataSize = tempDesc.GetDataSize(); + StrCopySafe(outString, *tempDesc.dataHandle, Min(dataSize, maxLen)); + } + else + ThrowOSErr(errAECoercionFail); + } +} + +void StAEDesc::GetPString(Str255 outString) +{ + if (descriptorType == typeChar) + { + long stringLen = GetDataSize(); + if (stringLen > 255) + stringLen = 255; + BlockMoveData(*dataHandle, &outString[1], stringLen); + outString[0] = stringLen; + } + else + { + StAEDesc tempDesc; + if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr) + { + long stringLen = tempDesc.GetDataSize(); + if (stringLen > 255) + stringLen = 255; + BlockMoveData(*tempDesc.dataHandle, &outString[1], stringLen); + outString[0] = stringLen; + } + else + ThrowOSErr(errAECoercionFail); + } +} + +Handle StAEDesc::GetTextHandle() +{ + StAEDesc tempDesc; + Handle data = nil; + + if (descriptorType == typeChar) + { + data = dataHandle; + } + else + { + if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr) + data = tempDesc.dataHandle; + else + ThrowOSErr(errAECoercionFail); + } + + if (data) + { + OSErr err = ::HandToHand(&data); + ThrowIfOSErr(err); + return data; + } + + return nil; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + GetFirstNonListToken + + Note: make sure the result descriptor is {typeNull, nil} when it is passed in to this + +----------------------------------------------------------------------------*/ +OSErr AEListUtils::GetFirstNonListToken(const AEDesc *token, AEDesc *result) +{ + OSErr err = noErr; + AEDesc tempToken = { typeNull, nil }; + AEKeyword keyword; + long numItems; + long itemNum; + + if (result->descriptorType == typeNull) + { + if (TokenContainsTokenList(token) == false) + { + err = AEDuplicateDesc(token, result); + } + else + { + err = AECountItems(token, &numItems); + + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + err = AEGetNthDesc((AEDescList *)token, itemNum, typeWildCard, &keyword, &tempToken); + if (err != noErr) + goto CleanUp; + + err = GetFirstNonListToken(&tempToken, result); + if ((err != noErr) || (result->descriptorType != typeNull)) + break; + + AEDisposeDesc(&tempToken); + } + } + } + +CleanUp: + if (err != noErr) + AEDisposeDesc(result); + + AEDisposeDesc(&tempToken); + return err; +} + +/*---------------------------------------------------------------------------- + FlattenAEList + +----------------------------------------------------------------------------*/ +OSErr AEListUtils::FlattenAEList(AEDescList *deepList, AEDescList *flatList) +{ + OSErr err = noErr; + AEDesc item = {typeNull, nil}; + AEKeyword keyword; + long itemNum; + long numItems; + + err = AECountItems(deepList, &numItems); + if (err != noErr) + goto CleanUp; + + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + err = AEGetNthDesc(deepList, itemNum, typeWildCard, &keyword, &item); + if (err != noErr) + goto CleanUp; + + if (item.descriptorType == typeAEList) + err = FlattenAEList(&item, flatList); + else + err = AEPutDesc(flatList, 0L, &item); + + if (err != noErr) + goto CleanUp; + + AEDisposeDesc(&item); + } + +CleanUp: + if (err != noErr) + AEDisposeDesc(flatList); + + AEDisposeDesc(&item); + + return err; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + StEventSuspender + +----------------------------------------------------------------------------*/ +StEventSuspender::StEventSuspender(const AppleEvent *appleEvent, AppleEvent *reply, Boolean deleteData) +: mThreadAEInfo(nil) +, mDeleteData(deleteData) +{ + ThrowIfOSErr(CreateThreadAEInfo(appleEvent, reply, &mThreadAEInfo)); +} + + +/*---------------------------------------------------------------------------- + ~StEventSuspender + +----------------------------------------------------------------------------*/ +StEventSuspender::~StEventSuspender() +{ + if (mDeleteData) + DisposeThreadAEInfo(mThreadAEInfo); +} + +/*---------------------------------------------------------------------------- + SuspendEvent + +----------------------------------------------------------------------------*/ +void StEventSuspender::SuspendEvent() +{ + ThrowIfOSErr(SuspendThreadAE(mThreadAEInfo)); +} + + +/*---------------------------------------------------------------------------- + ResumeEvent + +----------------------------------------------------------------------------*/ +void StEventSuspender::ResumeEvent() +{ + ThrowIfOSErr(ResumeThreadAE(mThreadAEInfo, noErr)); +} + + + +#pragma mark - + + +/*---------------------------------------------------------------------------- + StHandleHolder + +----------------------------------------------------------------------------*/ +StHandleHolder::StHandleHolder(Handle inHandle) +: mHandle(inHandle) +, mLockCount(0) +{ +} + + +/*---------------------------------------------------------------------------- + ~StHandleHolder + +----------------------------------------------------------------------------*/ +StHandleHolder::~StHandleHolder() +{ + if (mHandle) + DisposeHandle(mHandle); +} + + +/*---------------------------------------------------------------------------- + operator= + +----------------------------------------------------------------------------*/ +StHandleHolder& StHandleHolder::operator=(Handle rhs) +{ + ASSERT(mLockCount == 0, "Bad lock count"); + mLockCount = 0; + + if (mHandle) + DisposeHandle(mHandle); + + mHandle = rhs; + return *this; +} + +/*---------------------------------------------------------------------------- + Lock + +----------------------------------------------------------------------------*/ +void StHandleHolder::Lock() +{ + ThrowIfNil(mHandle); + if (++mLockCount > 1) return; + mOldHandleState = HGetState(mHandle); + HLock(mHandle); +} + +/*---------------------------------------------------------------------------- + Unlock + +----------------------------------------------------------------------------*/ +void StHandleHolder::Unlock() +{ + ThrowIfNil(mHandle); + ASSERT(mLockCount > 0, "Bad lock count"); + if (--mLockCount == 0) + HSetState(mHandle, mOldHandleState); +} + + +#pragma mark - + + +/*---------------------------------------------------------------------------- + StAEListIterator + +----------------------------------------------------------------------------*/ +AEListIterator::AEListIterator(AEDesc *token) +: mNumItems(0) +, mCurItem(0) +, mIsListDesc(false) +{ + ThrowIfNil(token); + mListToken = *token; + mIsListDesc = AEListUtils::TokenContainsTokenList(&mListToken); + if (mIsListDesc) + { + ThrowIfOSErr(::AECountItems(token, &mNumItems)); + mCurItem = 1; + } + else + { + mCurItem = 0; + mNumItems = 1; + } +} + + +/*---------------------------------------------------------------------------- + Next + +----------------------------------------------------------------------------*/ +Boolean AEListIterator::Next(AEDesc* outItemData) +{ + if (mIsListDesc) + { + AEKeyword keyword; + + if (mCurItem == 0 || mCurItem > mNumItems) + return false; + + ThrowIfOSErr(::AEGetNthDesc(&mListToken, mCurItem, typeWildCard, &keyword, outItemData)); + + // what about nested lists? + ASSERT(!AEListUtils::TokenContainsTokenList(outItemData), "Nested list found"); + } + else + { + if (mCurItem > 0) + return false; + + ThrowIfOSErr(::AEDuplicateDesc(&mListToken, outItemData)); + } + + mCurItem ++; + return true; +} + + + +#pragma mark - + +/*---------------------------------------------------------------------------- + CheckForUnusedParameters + + Check to see if there exist any additional required parameters in the Apple Event. + If so, return an err to the calling routine, because we didn't extract them all. +----------------------------------------------------------------------------*/ +OSErr CheckForUnusedParameters(const AppleEvent* appleEvent) +{ + OSErr err = noErr; + + DescType actualType = typeNull; + Size actualSize = 0L; + + err = AEGetAttributePtr(appleEvent, + keyMissedKeywordAttr, + typeWildCard, + &actualType, + nil, + 0, + &actualSize); + + if (err == errAEDescNotFound) + err = noErr; + else + err = errAEParamMissed; + + return err; +} + +/*---------------------------------------------------------------------------- + PutReplyErrorNumber + + If a reply is expected, the err number is returned in the reply parameter. +----------------------------------------------------------------------------*/ +OSErr PutReplyErrorNumber(AppleEvent* reply, long errorNumber) +{ + OSErr err = noErr; + + if (reply->dataHandle != nil && errorNumber != noErr) + { + err = AEPutParamPtr(reply, + keyErrorNumber, + typeLongInteger, + (Ptr)&errorNumber, + sizeof(long)); + } + return err; +} + +/*---------------------------------------------------------------------------- + PutReplyErrorMessage + + If a reply is expected, the err message is inserted into the reply parameter. +----------------------------------------------------------------------------*/ +OSErr PutReplyErrorMessage(AppleEvent* reply, char *message) +{ + OSErr err = noErr; + + if (reply->dataHandle != nil && message != NULL) + { + err = AEPutParamPtr(reply, + keyErrorString, + typeChar, + (Ptr)message, + strlen(message)); + } + return err; +} + + +/*---------------------------------------------------------------------------- + GetObjectClassFromAppleEvent + + This is used to extract the type of object that an appleevent is supposed + to work with. In the Core events, this includes: + count each + make new + save in as +---------------------------------------------------------------------------*/ +OSErr GetObjectClassFromAppleEvent(const AppleEvent *appleEvent, DescType *objectClass) +{ + OSErr err = noErr; + OSType typeCode; // should be typeType + long actualSize; + + // Get the class of object that we will count + + err = AEGetParamPtr(appleEvent, + keyAEObjectClass, + typeType, + &typeCode, + (Ptr)objectClass, + sizeof(DescType), + &actualSize); + + if (typeCode != typeType) + err = errAECoercionFail; + + return err; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + DescToPString + + Converts descriptor dataHandle to a pascal string + +---------------------------------------------------------------------------*/ +OSErr DescToPString(const AEDesc* desc, Str255 aPString, short maxLength) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + long charCount; + + if (desc->descriptorType == typeChar) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + charCount = GetHandleSize(dataHandle); + + if (charCount > maxLength) + { + return errAECoercionFail; + } + + BlockMoveData(*dataHandle, &aPString[1], charCount); + aPString[0] = charCount; + return noErr; +} + + + +/*---------------------------------------------------------------------------- + DescToCString + + Converts descriptor dataHandle to a C string + +--------------------------------------------------------------------------- */ +OSErr DescToCString(const AEDesc* desc, CStr255 aCString, short maxLength) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + long charCount; + + if (desc->descriptorType == typeChar) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + charCount = GetHandleSize(dataHandle); + + if (charCount > maxLength) + { + return errAECoercionFail; + } + + BlockMoveData(*dataHandle, aCString, charCount); + aCString[charCount] = '\0'; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a DescType +//---------------------------------------------------------------------------------- + +OSErr DescToDescType(const AEDesc *desc, DescType *descType) +{ + OSErr err = noErr; + + if (GetHandleSize(desc->dataHandle) == 4) + *descType = *(DescType*)*(desc->dataHandle); + else + err = errAECoercionFail; + + return err; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a boolean +//---------------------------------------------------------------------------------- + +OSErr DescToBoolean(const AEDesc* desc, Boolean* aBoolean) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeBoolean) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeBoolean, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aBoolean = **dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a Fixed +//---------------------------------------------------------------------------------- + +OSErr DescToFixed(const AEDesc* desc, Fixed* aFixed) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeFixed) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeFixed, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aFixed = *(Fixed *)*dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a float +//---------------------------------------------------------------------------------- + +OSErr DescToFloat(const AEDesc* desc, float* aFloat) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeFloat) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeFloat, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aFloat = **(float**)dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a long +//---------------------------------------------------------------------------------- + +OSErr DescToLong(const AEDesc* desc, long* aLong) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeLongInteger) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeLongInteger, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aLong = *(long *)*dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a RGBColor +//---------------------------------------------------------------------------------- + +OSErr DescToRGBColor(const AEDesc* desc, RGBColor* aRGBColor) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeRGBColor) // a color value + { + dataHandle = desc->dataHandle; + } + else { + if (AECoerceDesc(desc, typeRGBColor, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aRGBColor = *(RGBColor *)*dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a short. +//---------------------------------------------------------------------------------- + +OSErr DescToShort(const AEDesc* desc, short* aShort) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeShortInteger) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeShortInteger, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aShort = *(short *)*dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Copies descriptor dataHandle to another handle, if its text +//---------------------------------------------------------------------------------- + +OSErr DescToTextHandle(const AEDesc* desc, Handle *text) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + OSErr err; + + if (desc->descriptorType == typeChar) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + err = HandToHand(&dataHandle); + if (err != noErr) return err; + + *text = dataHandle; + return noErr; +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a Rectangle +//---------------------------------------------------------------------------------- + +OSErr DescToRect(const AEDesc* desc, Rect* aRect) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeRectangle) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeQDRectangle, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aRect = *(Rect *)*dataHandle; + return(noErr); +} + +//---------------------------------------------------------------------------------- +// Converts descriptor dataHandle to a Point +//---------------------------------------------------------------------------------- + +OSErr DescToPoint(const AEDesc* desc, Point* aPoint) +{ + StAEDesc tempDesc; + Handle dataHandle = nil; + + if (desc->descriptorType == typeQDPoint) + { + dataHandle = desc->dataHandle; + } + else + { + if (AECoerceDesc(desc, typeQDPoint, &tempDesc) == noErr) + dataHandle = tempDesc.dataHandle; + else + return errAECoercionFail; + } + + *aPoint = *(Point *)*dataHandle; + return(noErr); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + NormalizeAbsoluteIndex + + Handles formAbsolutePosition resolution + +---------------------------------------------------------------------------*/ +OSErr NormalizeAbsoluteIndex(const AEDesc *keyData, long *index, long maxIndex, Boolean *isAllItems) +{ + OSErr err = noErr; + + *isAllItems = false; // set to true if we receive kAEAll constant + + // Extract the formAbsolutePosition data, either a integer or a literal constant + + switch (keyData->descriptorType) + { + case typeLongInteger: // positve or negative index + if (DescToLong(keyData, index) != noErr) + return errAECoercionFail; + + if (*index < 0) // convert a negative index from end of list to a positive index from beginning of list + *index = maxIndex + *index + 1; + break; + + case typeAbsoluteOrdinal: // 'abso' + DescType ordinalDesc; + if (DescToDescType((AEDesc*)keyData, &ordinalDesc) != noErr) + ThrowOSErr(errAECoercionFail); + + switch (ordinalDesc) + { + case kAEFirst: + *index = 1; + break; + + case kAEMiddle: + *index = (maxIndex >> 1) + (maxIndex % 2); + break; + + case kAELast: + *index = maxIndex; + break; + + case kAEAny: + *index = (TickCount() % maxIndex) + 1; // poor man's random + break; + + case kAEAll: + *index = 1; + *isAllItems = true; + break; + } + break; + + default: + return errAEWrongDataType; + break; + } + + // range-check the new index number + if ((*index < 1) || (*index > maxIndex)) + { + err = errAEIllegalIndex; + } + + return err; +} + + +//---------------------------------------------------------------------------------- +// Handles formRange resolution of boundary objects + +OSErr ProcessFormRange(AEDesc *keyData, AEDesc *start, AEDesc *stop) +{ + OSErr err = noErr; + StAEDesc rangeRecord; + StAEDesc ospec; + + // coerce the range record data into an AERecord + + err = AECoerceDesc(keyData, typeAERecord, &rangeRecord); + if (err != noErr) + return err; + + // object specifier for first object in the range + err = AEGetKeyDesc(&rangeRecord, keyAERangeStart, typeWildCard, &ospec); + if (err == noErr && ospec.descriptorType == typeObjectSpecifier) + err = AEResolve(&ospec, kAEIDoMinimum, start); + + if (err != noErr) + return err; + + ospec.Clear(); + + // object specifier for last object in the range + + err = AEGetKeyDesc(&rangeRecord, keyAERangeStop, typeWildCard, &ospec); + if (err == noErr && ospec.descriptorType == typeObjectSpecifier) + err = AEResolve(&ospec, kAEIDoMinimum, stop); + + return err; +} diff --git a/xpfe/bootstrap/appleevents/nsAEUtils.h b/xpfe/bootstrap/appleevents/nsAEUtils.h new file mode 100644 index 000000000000..50991f2762ed --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEUtils.h @@ -0,0 +1,334 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#ifndef __AEUTILS__ +#define __AEUTILS__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include "nsAEDefs.h" +#include "nsMacUtils.h" + + +#define ThrowIfNil(a) { if (a == nil) { throw((OSErr)memFullErr); } } +#define ThrowErrIfNil(a, err) { if (a == nil) { OSErr theErr = (err); throw((OSErr)theErr); } } +#define ThrowIfOSErr(err) { OSErr theErr = (err); if (theErr != noErr) { throw((OSErr)theErr); } } +#define ThrowOSErr(err) { throw((OSErr)err); } +#define ThrowNoErr() { throw((OSErr)noErr); } + + +#define pObjectType 'pObT' + +// Windows +#define pTitle 'pTit' +#define pIsModeless 'pNMo' +#define pIsMovableModal 'pMMo' +#define pIsSuspended 'pSus' +#define pIsPalette 'pPal' +#define pIsDialog 'pDlg' +#define pLocation 'pLcn' // the upper left corner of the object's bounding box + +// Application + +#define pFreeMemory 'pMem' +#define pTicks 'pTic' + + + +// data given to a spawned thread for suspending and resuming Apple Events. +// there should be one of these per event. +typedef struct TThreadAEInfo +{ + AppleEvent mAppleEvent; + AppleEvent mReply; + SInt32 mSuspendCount; // how many suspend calls we have + Boolean mGotEventData; +} TThreadAEInfo, *TThreadAEInfoPtr; + + + + +#ifdef __cplusplus +extern "C" { +#endif + +OSErr CreateAliasAEDesc(AliasHandle theAlias, AEDesc *ioDesc); +OSErr GetTextFromAEDesc(const AEDesc *inDesc, Handle *outTextHandle); + +OSErr CreateThreadAEInfo(const AppleEvent *event, AppleEvent *reply, TThreadAEInfoPtr *outThreadAEInfo); +void DisposeThreadAEInfo(TThreadAEInfo *threadAEInfo); + +OSErr SuspendThreadAE(TThreadAEInfo *threadAEInfo); +OSErr ResumeThreadAE(TThreadAEInfo *threadAEInfo, OSErr threadError); + +#if !TARGET_CARBON + +OSErr AEGetDescData(const AEDesc *theAEDesc, DescType typeCode, void * dataPtr, Size maximumSize); +Size AEGetDescDataSize(const AEDesc *theAEDesc); + +#endif /* TARGET_CARBON */ + +#ifdef __cplusplus +} +#endif + + +// utility port setting class + +class StPortSetter +{ +public: + StPortSetter(WindowPtr destWindowPort) + { + ::GetPort(&mOldPort); +#if TARGET_CARBON + ::SetPortWindowPort(destWindowPort); +#else + ::SetPort(destWindowPort); +#endif + } + + ~StPortSetter() + { + ::SetPort(mOldPort); + } + +protected: + GrafPtr mOldPort; +}; + + +// a stack-based, exception safely class for an AEDesc + +class StAEDesc: public AEDesc +{ +public: + StAEDesc() + { + descriptorType = typeNull; + dataHandle = nil; + } + + StAEDesc(const StAEDesc& rhs); // copy constructor + + ~StAEDesc() + { + ::AEDisposeDesc(this); + } + + void Clear() + { + ::AEDisposeDesc(this); + descriptorType = typeNull; + dataHandle = nil; + } + + void CheckDataType(DescType expectedType) + { + if (descriptorType != expectedType) + ThrowOSErr(errAEWrongDataType); + } + + StAEDesc& operator= (const StAEDesc&rhs); // throws OSErrs + + Size GetDataSize() { return (dataHandle) ? GetHandleSize(dataHandle) : 0; } + + Boolean GetBoolean(); + SInt16 GetShort(); + SInt32 GetLong(); + DescType GetEnumType(); + + void GetRect(Rect& outRect); + void GetRGBColor(RGBColor& outColor); + void GetLongDateTime(LongDateTime& outDateTime); + void GetFileSpec(FSSpec &outFileSpec); + void GetCString(char *outString, short maxLen); + void GetPString(Str255 outString); + + Handle GetTextHandle(); + +}; + + +class StEventSuspender +{ +public: + + // use deleteData = false when calling threads, which take ownership of the TThreadAEInfoPtr + StEventSuspender(const AppleEvent *appleEvent, AppleEvent *reply, Boolean deleteData = true); + ~StEventSuspender(); + + void SetDeleteData(Boolean deleteData) { mDeleteData = deleteData; } + void SuspendEvent(); + void ResumeEvent(); + + TThreadAEInfoPtr GetThreadAEInfo() { return mThreadAEInfo; } + +protected: + + TThreadAEInfoPtr mThreadAEInfo; + Boolean mDeleteData; +}; + +class StHandleHolder +{ +public: + StHandleHolder(Handle inHandle = nil); // takes ownership of the handle + ~StHandleHolder(); + + StHandleHolder& operator=(Handle rhs); + + void Lock(); + void Unlock(); + + Handle GetHandle() { return mHandle; } + Size GetHandleSize() { return (mHandle) ? ::GetHandleSize(mHandle) : 0; } + Ptr GetPtr() { return (mHandle) ? *mHandle : nil; } + + class getter + { + public: + getter(StHandleHolder& handleHolder) + : mHandleHolder(handleHolder) + , mHandle(nil) + { + } + + ~getter() + { + mHandleHolder = mHandle; + } + + operator Handle*() + { + return &mHandle; + } + private: + StHandleHolder& mHandleHolder; + Handle mHandle; + }; + + // it is risky to define operator&, but, hey, we know what we're doing. + getter operator &() + { + return getter(*this); + } + // Does the same as operator&, but more explicitly. + getter AssignHandle() + { + return getter(*this); + } + +protected: + + Handle mHandle; + SInt32 mLockCount; + UInt8 mOldHandleState; +}; + + +class StHandleLocker +{ +public: + StHandleLocker(Handle inHandle) + : mHandle(inHandle) + { + ASSERT(mHandle, "No handle"); + mOldHandleState = HGetState(mHandle); + HLock(mHandle); + } + + ~StHandleLocker() + { + HSetState(mHandle, mOldHandleState); + } +protected: + Handle mHandle; + UInt8 mOldHandleState; +}; + + +class AEListUtils +{ +public: + + static Boolean TokenContainsTokenList(const AEDesc *token) { return (token->descriptorType == typeAEList); } + static OSErr GetFirstNonListToken(const AEDesc *token, AEDesc *result); + static OSErr FlattenAEList(AEDescList *deepList, AEDescList *flatList); +}; + + +// simple iterator for AEDescs which may be lists. Is NOT safe to the list changing under it. +// also, it does not handle nested lists. +class AEListIterator +{ +public: + AEListIterator(AEDesc *token); + ~AEListIterator() {} + + Boolean Next(AEDesc* outItemData); // data should be deleted by the caller. + SInt32 GetNumItems() { return mNumItems; } + +protected: + AEDesc mListToken; // we don't own this. + SInt32 mNumItems; + SInt32 mCurItem; + Boolean mIsListDesc; + +}; + + +OSErr DescToPString(const AEDesc* desc, Str255 aPString, short maxLength); +OSErr DescToCString(const AEDesc* desc, CStr255 aPString, short maxLength); +OSErr DescToDescType(const AEDesc *desc, DescType *descType); +OSErr DescToBoolean(const AEDesc* desc, Boolean* aBoolean); +OSErr DescToFixed(const AEDesc* desc, Fixed* aFixed); +OSErr DescToFloat(const AEDesc* desc, float* aFloat); +OSErr DescToLong(const AEDesc* desc, long* aLong); +OSErr DescToRGBColor(const AEDesc* desc, RGBColor* aRGBColor); +OSErr DescToShort(const AEDesc* desc, short* aShort); +OSErr DescToTextHandle(const AEDesc* desc, Handle *text); +OSErr DescToRect(const AEDesc* desc, Rect* aRect); +OSErr DescToPoint(const AEDesc* desc, Point* aPoint); + +OSErr CheckForUnusedParameters(const AppleEvent* appleEvent); +OSErr PutReplyErrorNumber(AppleEvent* reply, long errorNumber); +OSErr PutReplyErrorMessage(AppleEvent* reply, char *message); +OSErr GetObjectClassFromAppleEvent(const AppleEvent *appleEvent, DescType *objectClass); +OSErr NormalizeAbsoluteIndex(const AEDesc *keyData, long *index, long maxIndex, Boolean *isAllItems); +OSErr ProcessFormRange(AEDesc *keyData, AEDesc *start, AEDesc *stop); + + +#endif /* __AEUTILS__ */ diff --git a/xpfe/bootstrap/appleevents/nsAEWindowClass.cpp b/xpfe/bootstrap/appleevents/nsAEWindowClass.cpp new file mode 100644 index 000000000000..86a1fe1efa4e --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEWindowClass.cpp @@ -0,0 +1,949 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include +#include + +#include "nsWindowUtils.h" + +#include "nsAEUtils.h" +#include "nsAETokens.h" +#include "nsAECoreClass.h" +#include "nsAEApplicationClass.h" + +#include "nsAEWindowClass.h" + + +/*---------------------------------------------------------------------------- + GetNumItems + +----------------------------------------------------------------------------*/ +UInt32 AEWindowIterator::GetNumItems(const AEDesc* containerToken) +{ + return CountWindowsOfKind(mWindowKind); +} + +/*---------------------------------------------------------------------------- + GetNamedItemReference + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemRef AEWindowIterator::GetNamedItemReference(const AEDesc* containerToken, const char *itemName) +{ + WindowPtr wind; + wind = ::GetNamedOrFrontmostWindow(mWindowKind, itemName); + return (wind) ? (ItemRef)wind : kNoItemRef; +} + +/*---------------------------------------------------------------------------- + GetIndexedItemReference + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemRef AEWindowIterator::GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex) +{ + WindowPtr wind = GetIndexedWindowOfKind(mWindowKind, itemIndex); + return (wind) ? (ItemRef)wind : kNoItemRef; +} + +/*---------------------------------------------------------------------------- + GetNamedItemID + + Window refs and IDs are the same for windows +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWindowIterator::GetNamedItemID(const AEDesc* containerToken, const char *itemName) +{ + WindowPtr wind; + wind = ::GetNamedOrFrontmostWindow(mWindowKind, itemName); + return (wind) ? (ItemRef)wind : kNoItemID; +} + +/*---------------------------------------------------------------------------- + GetIndexFromItemID + +----------------------------------------------------------------------------*/ +TAEListIndex AEWindowIterator::GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID) +{ + return GetWindowIndex(mWindowKind, (WindowPtr)itemID); +} + +/*---------------------------------------------------------------------------- + GetIndexedItemID + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWindowIterator::GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex) +{ + WindowPtr wind = GetIndexedWindowOfKind(mWindowKind, itemIndex); + return (wind) ? (ItemRef)wind : kNoItemID; +} + +/*---------------------------------------------------------------------------- + GetIndexedItemName + +----------------------------------------------------------------------------*/ +void AEWindowIterator::GetIndexedItemName(const AEDesc* containerToken, TAEListIndex itemIndex, char *outName, long maxLen) +{ + WindowPtr wind = GetIndexedWindowOfKind(mWindowKind, itemIndex); + GetCleanedWindowName(wind, outName, maxLen); +} + +/*---------------------------------------------------------------------------- + GetIDFromReference + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWindowIterator::GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef) +{ + return (ItemID)itemRef; +} + +/*---------------------------------------------------------------------------- + GetReferenceFromID + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemRef AEWindowIterator::GetReferenceFromID(const AEDesc* containerToken, ItemID itemID) +{ + return (ItemRef)itemID; +} + +/*---------------------------------------------------------------------------- + GetItemIDFromToken + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWindowIterator::GetItemIDFromToken(const AEDesc* token) +{ + AETokenDesc tokenDesc(token); + return (ItemID)tokenDesc.GetWindowPtr(); +} + +/*---------------------------------------------------------------------------- + SetItemIDInCoreToken + +----------------------------------------------------------------------------*/ +void AEWindowIterator::SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID) +{ + tokenRecord->window = (WindowPtr)itemID; +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + AEWindowClass + +----------------------------------------------------------------------------*/ +AEWindowClass::AEWindowClass(DescType classType, TWindowKind windowKind) +: AEGenericClass(classType, typeNull) +, mWindowKind(windowKind) +, mDocumentAccessor(nil) +{ +} + +/*---------------------------------------------------------------------------- + ~AEWindowClass + +----------------------------------------------------------------------------*/ +AEWindowClass::~AEWindowClass() +{ + if (mDocumentAccessor) + DisposeRoutineDescriptor(mDocumentAccessor); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetItemFromContainer + +----------------------------------------------------------------------------*/ +void AEWindowClass::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + AEWindowIterator windowIterator(GetClass(), GetThisWindowKind()); + windowIterator.GetItemFromContainer(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); +} + +/*---------------------------------------------------------------------------- + CompareObjects + +----------------------------------------------------------------------------*/ +void AEWindowClass::CompareObjects( DescType comparisonOperator, + const AEDesc * object1, + const AEDesc * object2, + Boolean * result) +{ + + +} + + +/*---------------------------------------------------------------------------- + CountObjects + +----------------------------------------------------------------------------*/ +void AEWindowClass::CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + *result = CountWindows(mWindowKind); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + HandleClose + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + OSErr err = noErr; + DescType typeCode = 0L; + + StAEDesc saving; + StAEDesc savingIn; + + AEDesc *ptrToSaving = nil; + AEDesc *ptrToSavingIn = nil; + + // Extract the [saving yes/no/ask] optional parameter, if present + err = AEGetParamDesc(appleEvent, keyAESaveOptions, typeWildCard, &saving); + + if (err == noErr) + ptrToSaving = &saving; + else if (err == errAEDescNotFound) + err = noErr; + else + ThrowIfOSErr(err); + + // Extract the [saving in ] optional parameter, if present + err = AEGetParamDesc(appleEvent, keyAEFile, typeFSS, &savingIn); + + if (err == noErr) + ptrToSavingIn = &savingIn; + else if (err == errAEDescNotFound) + err = noErr; + else + ThrowIfOSErr(err); + + // Check for any required parameters we may have missed + err = CheckForUnusedParameters(appleEvent); + ThrowIfOSErr(err); + + // Now, do the application-related work + if (AEListUtils::TokenContainsTokenList(token)) + { + long numItems; + long itemNum; + AEKeyword keyword; + + err = AECountItems(token, &numItems); + ThrowIfOSErr(err); + + if (numItems > 0) + { + for (itemNum = 1; itemNum <= numItems; itemNum++) + { + StAEDesc windowToken; + err = AEGetNthDesc(token, itemNum, typeWildCard, &keyword, &windowToken); + if (err != noErr) break; + + //AECoreClass::sAECoreHandler->GetDocumentClass()->CloseWindowSaving(&windowToken, ptrToSaving, ptrToSavingIn); + } + } + } + else + { + //AECoreClass::sAECoreHandler->GetDocumentClass()->CloseWindowSaving(token, ptrToSaving, ptrToSavingIn); + } +} + +/*---------------------------------------------------------------------------- + HandleDataSize + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleDelete + + All attempts to delete an empty list are handled here + Application contains documents and windows, and they can't be deleted + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleDuplicate + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleExists + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleMake + + We can't make generic windows. + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleMove + + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleOpen + + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandlePrint + + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleQuit + + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +/*---------------------------------------------------------------------------- + HandleSave + + +----------------------------------------------------------------------------*/ +void AEWindowClass::HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) +{ + ThrowIfOSErr(errAEEventNotHandled); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetDataFromObject + + +----------------------------------------------------------------------------*/ +void AEWindowClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) +{ + OSErr err = noErr; + + AETokenDesc tokenDesc(token); + DescType aType = mClass; + Rect aRect; + + Point aPoint; + Boolean aBoolean; + long index; + CStr255 windowTitle; + + DescType propertyCode = tokenDesc.GetPropertyCode(); + Boolean usePropertyCode = tokenDesc.UsePropertyCode(); + WindowPtr window = tokenDesc.GetWindowPtr(); + + switch (propertyCode) + { + case pProperties: + err = AECreateList(NULL, 0L, true, data); + ThrowIfOSErr(err); + + err = AEPutKeyPtr(data, pObjectType, typeType, &aType, sizeof(DescType)); + + GetCleanedWindowName(window, windowTitle, 255); + err = AEPutKeyPtr(data, pTitle, typeChar, windowTitle, strlen(windowTitle)); + + index = GetWindowIndex(GetThisWindowKind(), window); + err = AEPutKeyPtr(data, pIndex, typeLongInteger, &index, sizeof(long)); + + GetWindowGlobalBounds(window, &aRect); + err = AEPutKeyPtr(data, pBounds, typeQDRectangle, &aRect, sizeof(Rect)); + aPoint.h = aRect.left; + aPoint.v = aRect.top; + err = AEPutKeyPtr(data, pLocation, typeQDPoint, &aPoint, sizeof(Point)); + + aBoolean = WindowIsCloseable(window); + err = AEPutKeyPtr(data, pHasCloseBox, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowHasTitleBar(window); + err = AEPutKeyPtr(data, pHasTitleBar, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsModal(window); + err = AEPutKeyPtr(data, pIsModal, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsResizeable(window); + err = AEPutKeyPtr(data, pIsResizable, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsZoomable(window); + err = AEPutKeyPtr(data, pIsZoomable, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsZoomed(window); + err = AEPutKeyPtr(data, pIsZoomed, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = !WindowIsModal(window); + err = AEPutKeyPtr(data, pIsModeless, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsModal(window) && WindowHasTitleBar(window); + err = AEPutKeyPtr(data, pIsMovableModal, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = WindowIsFloating(window); + err = AEPutKeyPtr(data, pIsFloating, typeBoolean, &aBoolean, sizeof(Boolean)); + + aBoolean = IsWindowVisible(window); + err = AEPutKeyPtr(data, pVisible, typeBoolean, &aBoolean, sizeof(Boolean)); + break; + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + err = AECreateDesc(typeType, &aType, sizeof(DescType), data); + break; + + case pBounds: + GetWindowGlobalBounds(window, &aRect); + err = AECreateDesc(typeQDRectangle, &aRect, sizeof(Rect), data); + break; + + case pLocation: + GetWindowGlobalBounds(window, &aRect); + aPoint.h = aRect.left; + aPoint.v = aRect.top; + err = AECreateDesc(typeQDPoint, &aPoint, sizeof(Point), data); + break; + + case pIsModeless: + aBoolean = !WindowIsModal(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIsMovableModal: + aBoolean = WindowIsModal(window) && WindowHasTitleBar(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pHasCloseBox: + aBoolean = WindowIsCloseable(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pHasTitleBar: + aBoolean = WindowHasTitleBar(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIndex: + index = GetWindowIndex(GetThisWindowKind(), window); + err = AECreateDesc(typeLongInteger, &index, sizeof(long), data); + break; + + case pIsModal: + aBoolean = WindowIsModal(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIsResizable: + aBoolean = WindowIsResizeable(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIsZoomable: + aBoolean = WindowIsZoomable(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIsZoomed: + aBoolean = WindowIsZoomed(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pVisible: + aBoolean = IsWindowVisible(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pIsFloating: + aBoolean = WindowIsFloating(window); + err = AECreateDesc(typeBoolean, &aBoolean, sizeof(Boolean), data); + break; + + case pName: // Synonym for pTitle + case pTitle: + GetCleanedWindowName(window, windowTitle, 255); + err = AECreateDesc(typeChar, windowTitle, strlen(windowTitle), data); + break; + + default: + Inherited::GetDataFromObject(token, desiredTypes, data); + break; + } + + ThrowIfOSErr(err); +} + +/*---------------------------------------------------------------------------- + SetDataForObject + + +----------------------------------------------------------------------------*/ +void AEWindowClass::SetDataForObject(const AEDesc *token, AEDesc *data) +{ + OSErr err; + + AETokenDesc tokenDesc(token); + + Boolean usePropertyCode = tokenDesc.UsePropertyCode(); + WindowPtr window = tokenDesc.GetWindowPtr(); + + if (usePropertyCode == false) + { + ThrowIfOSErr(errAEWriteDenied); + } + else + { + DescType propertyCode = tokenDesc.GetPropertyCode(); + + // Convert the single property to a record containing one property + + if (data->descriptorType == typeAERecord) + { + SetWindowProperties(window, data); + } + else // Build a record with one property + { + StAEDesc propertyRecord; + + err = AECreateList(nil, 0, true, &propertyRecord); + ThrowIfOSErr(err); + + err = AEPutKeyDesc(&propertyRecord, propertyCode, data); + ThrowIfOSErr(err); + + SetWindowProperties(window, &propertyRecord); + } + } +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CanSetProperty + + +----------------------------------------------------------------------------*/ +Boolean AEWindowClass::CanSetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + // Properties we can set: + + case pProperties: + result = true; + break; + + // Properties that can be set only for certain types of windows: + + case pTitle: + case pName: // Synonym for pTitle + + case pBounds: + case pLocation: + case pIndex: + case pVisible: + case pIsZoomed: + result = true; + break; + + // Properties we should be able to set, but not implemented yet: + + + // Properties we can't set: + + default: + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pIsModeless: + case pIsMovableModal: + case pIsSuspended: + case pIsPalette: + case pIsDialog: + + case pHasCloseBox: + case pHasTitleBar: + + case pIsFloating: + case pIsModal: + case pIsResizable: + case pIsZoomable: + result = Inherited::CanSetProperty(propertyCode); + break; + } + + return result; +} + + +/*---------------------------------------------------------------------------- + CanGetProperty + + +----------------------------------------------------------------------------*/ +Boolean AEWindowClass::CanGetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + // Properties we can get: + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + + case pContents: + + case pProperties: + case keyAEProperties: + + case pTitle: + case pName: // Synonym for pTitle + + case pIsModeless: + case pIsMovableModal: + case pIsSuspended: + case pIsPalette: + case pIsDialog: + + case pBounds: + case pLocation: + + case pHasCloseBox: + case pHasTitleBar: + case pIndex: + + case pIsFloating: + case pIsModal: + case pIsResizable: + case pIsZoomable: + + case pIsZoomed: + case pVisible: + result = true; + break; + + // Properties we can't get: + default: + result = Inherited::CanGetProperty(propertyCode); + break; + } + + return result; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + SetWindowProperties + + +----------------------------------------------------------------------------*/ +void AEWindowClass::SetWindowProperties(WindowPtr window, const AEDesc *propertyRecord) +{ + OSErr err = noErr; + OSErr ignoreError = noErr; + long numProperties = 0L; + StAEDesc data; + + if (propertyRecord == nil || propertyRecord->descriptorType != typeAERecord) + { + ThrowIfOSErr(errAEWrongDataType); + } + + err = AECountItems(propertyRecord, &numProperties); + ThrowIfOSErr(err); + if (numProperties <= 0) + ThrowIfOSErr(paramErr); + + StPortSetter portSetter(window); + + // pBounds + + ignoreError = AEGetKeyDesc(propertyRecord, pBounds, typeQDRectangle, &data); + if (ignoreError != errAEDescNotFound) + { + Rect r; + err = DescToRect(&data, &r); + + if (err == noErr) + { + short windowWidth = r.right - r.left; + short windowDepth = r.bottom - r.top; + + MoveWindow(window, r.left, r.top, false); + // еее╩DoResize(window, windowWidth, windowDepth); + } + + data.Clear(); + } + + // pLocation + + ignoreError = AEGetKeyDesc(propertyRecord, pLocation, typeQDPoint, &data); + if (ignoreError != errAEDescNotFound) + { + Point p; + err = DescToPoint(&data, &p); + + if (err == noErr) + MoveWindow(window, p.h, p.v, false); // don't let Window Manager bring it to front! + + data.Clear(); + } + + // pIndex + + ignoreError = AEGetKeyDesc(propertyRecord, pIndex, typeLongInteger, &data); + if (ignoreError != errAEDescNotFound) + { + long index; + long numWindows; + WindowPtr behindWindow; + + err = DescToLong(&data, &index); + + if (err == noErr) + { + numWindows = CountWindows(GetThisWindowKind()); + if (index < 0) + index = numWindows + index + 1; + + if (index == 1) + { + SelectWindow(window); + } + else + { + behindWindow = GetWindowByIndex(GetThisWindowKind(), index); + if (behindWindow != NULL) + { + SendBehind(window, behindWindow); + } + else + { + err = errAEEventNotHandled; + } + } + } + + data.Clear(); + } + + // pIsZoomed + + ignoreError = AEGetKeyDesc(propertyRecord, pIsZoomed, typeBoolean, &data); + if (ignoreError != errAEDescNotFound) + { + Boolean zoomIt; + + err = DescToBoolean(&data, &zoomIt); + + if (err == noErr) + { + if (zoomIt) + ZoomWindow(window, inZoomOut, false); + else + ZoomWindow(window, inZoomIn, false); + } + + data.Clear(); + } + + // pVisible + + ignoreError = AEGetKeyDesc(propertyRecord, pVisible, typeBoolean, &data); + if (ignoreError != errAEDescNotFound) + { + Boolean showIt; + err = DescToBoolean(&data, &showIt); + + if (err == noErr) + { + if (showIt) + ShowWindow(window); + else + HideWindow(window); + } + + data.Clear(); + } +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + MakeWindowObjectSpecifier + + +----------------------------------------------------------------------------*/ +void AEWindowClass::MakeWindowObjectSpecifier(WindowPtr wind, AEDesc *outSpecifier) +{ + // fill in the reply with the newly created object + CoreTokenRecord coreToken; + StAEDesc windowToken; + + coreToken.window = wind; + + OSErr err = ::AECreateDesc(typeObjectSpecifier, &coreToken, sizeof(CoreTokenRecord), &windowToken); + ThrowIfOSErr(err); + + CreateSelfSpecifier(&windowToken, outSpecifier); +} + + +/*---------------------------------------------------------------------------- + CreateSelfSpecifier + +----------------------------------------------------------------------------*/ +void AEWindowClass::CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier) +{ + AETokenDesc tokenDesc(token); + WindowPtr window = tokenDesc.GetWindowPtr(); + long position = GetWindowIndex(mWindowKind, window); + AEDesc selfDesc = { typeNull, nil }; + AEDesc containerSpecifier = { typeNull, nil }; + DescType desiredClass = mClass; + DescType keyForm = formAbsolutePosition; + OSErr err = noErr; + + GetContainerSpecifier(token, &containerSpecifier); + + err = ::AECreateDesc(typeLongInteger, &position, sizeof(long), &selfDesc); + ThrowIfOSErr(err); + + err = ::CreateObjSpecifier(desiredClass, &containerSpecifier, keyForm, &selfDesc, true, outSpecifier); + ThrowIfOSErr(err); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + CountWindows + +----------------------------------------------------------------------------*/ +long AEWindowClass::CountWindows(TWindowKind windowKind) +{ + return CountWindowsOfKind(windowKind); +} + + +/*---------------------------------------------------------------------------- + GetWindowByIndex + +----------------------------------------------------------------------------*/ +WindowPtr AEWindowClass::GetWindowByIndex(TWindowKind windowKind, long index) +{ + return ::GetIndexedWindowOfKind(windowKind, index); +} + +/*---------------------------------------------------------------------------- + GetWindowByTitle + +----------------------------------------------------------------------------*/ +WindowPtr AEWindowClass::GetWindowByTitle(TWindowKind windowKind, ConstStr63Param title) +{ + CStr255 windowName; + CopyPascalToCString((const StringPtr)title, windowName, 255); + return ::GetNamedOrFrontmostWindow(windowKind, windowName); +} + +/*---------------------------------------------------------------------------- + GetWindowIndex + +----------------------------------------------------------------------------*/ +long AEWindowClass::GetWindowIndex(TWindowKind windowKind, WindowPtr window) +{ + return ::GetWindowIndex(windowKind, window); +} + + +/*---------------------------------------------------------------------------- + GetPreviousWindow + +----------------------------------------------------------------------------*/ +WindowPtr AEWindowClass::GetPreviousWindow(TWindowKind windowKind, WindowPtr wind) +{ + short windowIndex = GetWindowIndex(windowKind, wind); + return GetIndexedWindowOfKind(windowKind, windowIndex - 1); +} + + diff --git a/xpfe/bootstrap/appleevents/nsAEWindowClass.h b/xpfe/bootstrap/appleevents/nsAEWindowClass.h new file mode 100644 index 000000000000..293b3a719356 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEWindowClass.h @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AEWINDOWCLASS__ +#define __AEWINDOWCLASS__ + + + +#include "nsAEGenericClass.h" + + +class AEWindowIterator : public AEClassIterator +{ +public: + + AEWindowIterator(DescType classType, TWindowKind windowKind) + : AEClassIterator(classType) + , mWindowKind(windowKind) + {} + + virtual UInt32 GetNumItems(const AEDesc* containerToken); + virtual ItemRef GetNamedItemReference(const AEDesc* containerToken, const char *itemName); + virtual ItemRef GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex); + + virtual TAEListIndex GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID); + + virtual ItemID GetNamedItemID(const AEDesc* containerToken, const char *itemName); + virtual ItemID GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex); + + // index to name + virtual void GetIndexedItemName(const AEDesc* containerToken, TAEListIndex itemIndex, char *outName, long maxLen); + + // conversion routines. + virtual ItemID GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef); + virtual ItemRef GetReferenceFromID(const AEDesc* containerToken, ItemID itemID); + + virtual ItemID GetItemIDFromToken(const AEDesc* token); + virtual void SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID); + + TWindowKind GetThisWindowKind() { return mWindowKind; } + +protected: + + TWindowKind mWindowKind; +}; + + + +class AEWindowClass : public AEGenericClass +{ + friend class AECoreClass; + +private: + typedef AEGenericClass Inherited; + +protected: + // only the AECoreClass can instantiate us + AEWindowClass(DescType classType, TWindowKind windowKind); + ~AEWindowClass(); + + + void GetDocumentFromWindow( DescType desiredClass, // cWindow + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); // specified Window is returned in result + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual void CompareObjects( DescType comparisonOperator, + const AEDesc * object, + const AEDesc * descriptorOrObject, + Boolean * result); + + virtual void CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + +public: + // AE Handlers + + static pascal OSErr DocumentAccessor( DescType desiredClass, // cDocument + const AEDesc* containerToken, // null container + DescType containerClass, // cApplication + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken, // specified Document is returned in result + long refCon); + +protected: + + // ---------------------------------------------------------------------------- + // Core Suite Object Event handlers + // ---------------------------------------------------------------------------- + virtual void HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + virtual void HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply); + + // ---------------------------------------------------------------------------- + // Methods for creating self and container specifiers + // ---------------------------------------------------------------------------- + + virtual void CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier); + + // ---------------------------------------------------------------------------- + // Get and Set methods for objects and list + // ---------------------------------------------------------------------------- + + virtual void GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data); + virtual void SetDataForObject(const AEDesc *token, AEDesc *data); + + virtual Boolean CanSetProperty(DescType propertyCode); + virtual Boolean CanGetProperty(DescType propertyCode); + + void SetWindowProperties(WindowPtr wind, const AEDesc *propertyRecord); + void MakeWindowObjectSpecifier(WindowPtr wind, AEDesc *outSpecifier); + + WindowPtr GetWindowByIndex(TWindowKind windowKind, long index); + WindowPtr GetWindowByTitle(TWindowKind windowKind, ConstStr63Param title); + + long GetWindowIndex(TWindowKind windowKind, WindowPtr window); + WindowPtr GetPreviousWindow(TWindowKind windowKind, WindowPtr wind); + + TWindowKind GetThisWindowKind() { return mWindowKind; } + +public: + + static long CountWindows(TWindowKind windowKind); + +protected: + + TWindowKind mWindowKind; + +protected: + + OSLAccessorUPP mDocumentAccessor; + +}; + + +#endif /* __AEWINDOWCLASS__ */ + + diff --git a/xpfe/bootstrap/appleevents/nsAEWordClass.cpp b/xpfe/bootstrap/appleevents/nsAEWordClass.cpp new file mode 100644 index 000000000000..257d3421f792 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEWordClass.cpp @@ -0,0 +1,353 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "def.h" +#include "wasteutil.h" + +#include "AEUtils.h" +#include "AETextClass.h" + +#include "AEWordClass.h" + + +/*---------------------------------------------------------------------------- + GetNumItems + +----------------------------------------------------------------------------*/ +UInt32 AEWordIterator::GetNumItems(const AEDesc* containerToken) +{ + AETokenDesc container(containerToken); + WEReference theWE = container.GetWEReference(); + + return theWE ? GetWENumWords(theWE) : 0; +} + +/*---------------------------------------------------------------------------- + GetIndexedItemReference + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemRef AEWordIterator::GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex) +{ + return (ItemRef)itemIndex; +} + +/*---------------------------------------------------------------------------- + GetIndexFromItemID + +----------------------------------------------------------------------------*/ +TAEListIndex AEWordIterator::GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID) +{ + return (TAEListIndex)itemID; +} + +/*---------------------------------------------------------------------------- + GetIndexedItemID + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWordIterator::GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex) +{ + return (ItemID)GetIndexedItemReference(containerToken, itemIndex); +} + +/*---------------------------------------------------------------------------- + GetIDFromReference + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWordIterator::GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef) +{ + return (ItemID)itemRef; +} + +/*---------------------------------------------------------------------------- + GetReferenceFromID + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemRef AEWordIterator::GetReferenceFromID(const AEDesc* containerToken, ItemID itemID) +{ + return (ItemRef)itemID; +} + +/*---------------------------------------------------------------------------- + GetItemIDFromToken + +----------------------------------------------------------------------------*/ +AEClassIterator::ItemID AEWordIterator::GetItemIDFromToken(const AEDesc* token) +{ + AETokenDesc container(token); + return (ItemID)container.GetElementNumber(); +} + +/*---------------------------------------------------------------------------- + SetItemIDInCoreToken + +----------------------------------------------------------------------------*/ +void AEWordIterator::SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID) +{ + AETokenDesc tokenDesc(containerToken); + WindowPtr wind = tokenDesc.GetWindowPtr(); + WEReference theWE = tokenDesc.GetWEReference(); + + tokenRecord->window = wind; + tokenRecord->theWE = theWE; + + tokenRecord->elementNumber = (TAEListIndex)itemID; +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + AEWordClass + +----------------------------------------------------------------------------*/ + +AEWordClass::AEWordClass() +: AEGenericClass(cWord, AETextClass::cTEText) +{ +} + +/*---------------------------------------------------------------------------- + ~AEWordClass + +----------------------------------------------------------------------------*/ +AEWordClass::~AEWordClass() +{ + +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetItemFromContainer + +----------------------------------------------------------------------------*/ +void AEWordClass::GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken) +{ + AEWordIterator wordIterator; + wordIterator.GetItemFromContainer(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken); +} + + +/*---------------------------------------------------------------------------- + CountObjects + +----------------------------------------------------------------------------*/ +void AEWordClass::CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result) +{ + AEWordIterator wordIterator; + long numItems = wordIterator.GetNumItems(container); + *result = numItems; +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + GetDataFromObject + +----------------------------------------------------------------------------*/ +void AEWordClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) +{ + AETokenDesc tokenDesc(token); + + DescType aDescType = cWord; + DescType propertyCode = tokenDesc.GetPropertyCode(); + WindowPtr window = tokenDesc.GetWindowPtr(); + WEReference theWE = tokenDesc.GetWEReference(); + TAEListIndex wordIndex = tokenDesc.GetElementNumber(); + OSErr err = noErr; + long wordStart, wordEnd; + + ThrowErrIfNil(theWE, errAENoSuchObject); + + switch (propertyCode) + { + case pProperties: + err = AECreateList(nil, 0, true, data); + ThrowIfOSErr(err); + + err = AEPutKeyPtr(data, pObjectType, typeType, &aDescType, sizeof(DescType)); + break; + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + err = AECreateDesc(typeType, &aDescType, sizeof(DescType), data); + ThrowIfOSErr(err); + break; + + case pContents: + case typeNull: + { + err = GetWEIndexedWordOffsets(theWE, wordIndex, &wordStart, &wordEnd); + ThrowIfOSErr(err); + + Handle weHand = WEGetText(theWE); + StHandleLocker lockHand(weHand); + + err = AECreateDesc(typeChar, *weHand + wordStart, wordEnd - wordStart,data); + ThrowIfOSErr(err); + } + break; + + default: + Inherited::GetDataFromObject(token, desiredTypes, data); + break; + } + + ThrowIfOSErr(err); +} + + +/*---------------------------------------------------------------------------- + GetDataFromObject + +----------------------------------------------------------------------------*/ +void AEWordClass::SetDataForObject(const AEDesc *token, AEDesc *data) +{ + AETokenDesc tokenDesc(token); + + DescType aDescType = cWord; + DescType propertyCode = tokenDesc.GetPropertyCode(); + WindowPtr window = tokenDesc.GetWindowPtr(); + WEReference theWE = tokenDesc.GetWEReference(); + TAEListIndex wordIndex = tokenDesc.GetElementNumber(); + OSErr err = noErr; + long wordStart, wordEnd; + + ThrowErrIfNil(theWE, errAENoSuchObject); + + switch (propertyCode) + { + + case pContents: + case typeNull: + { + err = GetWEIndexedWordOffsets(theWE, wordIndex, &wordStart, &wordEnd); + ThrowIfOSErr(err); + + } + break; + } + + ThrowIfOSErr(err); +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + CanSetProperty + +----------------------------------------------------------------------------*/ +Boolean AEWordClass::CanSetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + result = false; + break; + + case typeNull: + result = true; // contents + break; + + case pProperties: + default: + result = Inherited::CanSetProperty(propertyCode); + break; + } + + return result; +} + + +/*---------------------------------------------------------------------------- + CanGetProperty + +----------------------------------------------------------------------------*/ +Boolean AEWordClass::CanGetProperty(DescType propertyCode) +{ + Boolean result = false; + + switch (propertyCode) + { + // Properties we can get: + + case pBestType: + case pClass: + case pDefaultType: + case pObjectType: + case pProperties: + result = true; + break; + + default: + result = Inherited::CanGetProperty(propertyCode); + break; + } + + return result; +} + +#pragma mark - + + +/*---------------------------------------------------------------------------- + CreateSelfSpecifier + +----------------------------------------------------------------------------*/ +void AEWordClass::CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier) +{ + AETokenDesc tokenDesc(token); + + WEReference theWE = tokenDesc.GetWEReference(); + TAEListIndex wordIndex = tokenDesc.GetElementNumber(); + + AEDesc selfDesc = { typeNull, nil }; + AEDesc containerSpecifier = { typeNull, nil }; + OSErr err = noErr; + + GetContainerSpecifier(token, &containerSpecifier); + + err = ::AECreateDesc(typeLongInteger, &wordIndex, sizeof(TAEListIndex), &selfDesc); + ThrowIfOSErr(err); + + err = ::CreateObjSpecifier(mClass, &containerSpecifier, formAbsolutePosition, &selfDesc, true, outSpecifier); + ThrowIfOSErr(err); +} diff --git a/xpfe/bootstrap/appleevents/nsAEWordClass.h b/xpfe/bootstrap/appleevents/nsAEWordClass.h new file mode 100644 index 000000000000..76e436c3c8af --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAEWordClass.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __AEWORDCLASS__ +#define __AEWORDCLASS__ + +#include "AEGenericClass.h" + +class AEWordClass : public AEGenericClass +{ + friend class AECoreClass; + +private: + typedef AEGenericClass Inherited; + +public: + AEWordClass(); + ~AEWordClass(); + + + virtual void GetItemFromContainer( DescType desiredClass, + const AEDesc* containerToken, + DescType containerClass, + DescType keyForm, + const AEDesc* keyData, + AEDesc* resultToken); + + virtual void CountObjects( DescType desiredType, + DescType containerClass, + const AEDesc * container, + long * result); + + // ---------------------------------------------------------------------------- + // Methods for creating self and container specifiers + // ---------------------------------------------------------------------------- + + virtual void CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier); + + virtual void GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data); + virtual void SetDataForObject(const AEDesc *token, AEDesc *data); + + virtual Boolean CanSetProperty(DescType propertyCode); + virtual Boolean CanGetProperty(DescType propertyCode); + +}; + + +class AEWordIterator : public AEUnnamedClassIterator +{ +public: AEWordIterator() + : AEUnnamedClassIterator(cWord) + { + } + + virtual UInt32 GetNumItems(const AEDesc* containerToken); + virtual ItemRef GetIndexedItemReference(const AEDesc* containerToken, TAEListIndex itemIndex); + + virtual TAEListIndex GetIndexFromItemID(const AEDesc* containerToken, ItemID itemID); + + virtual ItemID GetIndexedItemID(const AEDesc* containerToken, TAEListIndex itemIndex); + + // conversion routines. + virtual ItemID GetIDFromReference(const AEDesc* containerToken, ItemRef itemRef); + virtual ItemRef GetReferenceFromID(const AEDesc* containerToken, ItemID itemID); + + virtual ItemID GetItemIDFromToken(const AEDesc* token); + virtual void SetItemIDInCoreToken(const AEDesc* containerToken, CoreTokenRecord* tokenRecord, ItemID itemID); + +}; + + +#endif // __AEWORDCLASS__ + diff --git a/xpfe/bootstrap/appleevents/nsAppleEvents.r b/xpfe/bootstrap/appleevents/nsAppleEvents.r new file mode 100644 index 000000000000..c968fd3ef288 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAppleEvents.r @@ -0,0 +1,157 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + + +/*---------------------------------------------------------------------------- + The Apple Events Template resource 'aedt' (found in Types.r) + is used to associate an Event Class and Event ID with a + unique integer value. These integer values are private to the + application processing the events. + + restriction: PowerPlant uses integer valuse below 4000 + All data for aetds is now centrally located in resae.h +----------------------------------------------------------------------------*/ + + +#include "types.r" +// #include "AEUserTermTypes.r" +#include "nsAppleEvents.h" // Provides AE Types, IDs, and AE_RefNums + // Found in mozilla/xpfe/appshell/public + +/*--------------------------------------------------------------------------*/ +/* ----- World Wide Web - Spyglass Suite ----- */ +/*--------------------------------------------------------------------------*/ + +resource 'aedt' (kSpyGlass_aedtResID, "World-Wide-Web Suite (Spyglass spec)") { + { + AE_spy_receive_suite, AE_spy_openURL, AE_OpenURL, // WWW! OURL +#ifndef MOZILLA_FIVE + AE_spy_receive_suite, AE_spy_registerViewer, AE_RegisterViewer, // WWW! RGVW + AE_spy_receive_suite, AE_spy_unregisterViewer, AE_UnregisterViewer, // WWW! UNRV + AE_spy_receive_suite, AE_spy_showFile, AE_ShowFile, // WWW! SHWF + AE_spy_receive_suite, AE_spy_parse, AE_ParseAnchor, // WWW! PRSA + AE_spy_receive_suite, AE_spy_registerURLecho, AE_RegisterURLEcho, // WWW! RGUE + AE_spy_receive_suite, AE_spy_unregisterURLecho, AE_UnregisterURLEcho, // WWW! UNRU + AE_spy_receive_suite, AE_spy_activate, AE_SpyActivate, // WWW! ACTV + AE_spy_receive_suite, AE_spy_listwindows, AE_SpyListWindows, // WWW! LSTW + AE_spy_receive_suite, AE_spy_getwindowinfo, AE_GetWindowInfo, // WWW! WNFO + AE_spy_receive_suite, AE_spy_registerWinClose, AE_RegisterWinClose, // WWW! RGWC + AE_spy_receive_suite, AE_spy_unregisterWinClose, AE_UnregisterWinClose, // WWW! UNRC + AE_spy_receive_suite, AE_spy_register_protocol, AE_RegisterProtocol, // WWW! RGPR + AE_spy_receive_suite, AE_spy_unregister_protocol, AE_UnregisterProtocol, // WWW! UNRP + AE_spy_receive_suite, AE_spy_CancelProgress, AE_CancelProgress, // WWW! CNCL + AE_spy_receive_suite, AE_spy_findURL, AE_FindURL // WWW! FURL +#endif // MOZILLA_FIVE + } +}; + +/*--------------------------------------------------------------------------*/ +/* ----- Netscape and Macintosh Std URL Suites ----- */ +/*--------------------------------------------------------------------------*/ + +resource 'aedt' (kURLSuite_aedtResID, "Netscape & URL suite") { + { +#ifdef MOZILLA_FIVE + AE_url_suite, AE_url_getURL, AE_GetURL // GURL GURL + , AE_www_suite, AE_www_doJavaScript, AE_DoJavascript // MOSS jscr +#else + AE_www_suite, AE_www_workingURL, AE_GetWD // MOSS wurl + , AE_www_suite, AE_www_openBookmark, AE_OpenBookmark // MOSS book + , AE_www_suite, AE_www_ReadHelpFile, AE_ReadHelpFile // MOSS help + , AE_www_suite, AE_www_go, AE_Go // MOSS gogo + , AE_url_suite, AE_url_getURL, AE_GetURL // GURL GURL + , AE_www_suite, AE_www_ProfileManager, AE_OpenProfileManager // MOSS prfl + , AE_www_suite, AE_www_openAddressBook, AE_OpenAddressBook // MOSS addr + , AE_www_suite, AE_www_openComponent, AE_OpenComponent // MOSS cpnt + , AE_www_suite, AE_www_getActiveProfile, AE_GetActiveProfile // MOSS upro + , AE_www_suite, AE_www_handleCommand, AE_HandleCommand // MOSS hcmd + , AE_www_suite, AE_www_getImportData, AE_GetProfileImportData // MOSS Impt + , AE_www_suite, AE_www_GuestMode, AE_OpenGuestMode // MOSS gues +#endif // MOZILLA_FIVE + } +}; + +/*--------------------------------------------------------------------------*/ +/* Required Suite, we will leave this hard wired for now */ +/*--------------------------------------------------------------------------*/ + +resource 'aedt' (kRequired_aedtResID, "Required Suite") { + { + 'aevt', 'oapp', 1001, + 'aevt', 'odoc', 1002, + 'aevt', 'pdoc', 1003, + 'aevt', 'quit', 1004 + } +}; + +/*--------------------------------------------------------------------------*/ +/* Core Suite, we will leave this hard wired for now */ +/*--------------------------------------------------------------------------*/ + +resource 'aedt' (kCore_aedtResID, "Core Suite") { + { + + 'core', 'clon', 2001, + 'core', 'clos', 2002, + 'core', 'cnte', 2003, + 'core', 'crel', 2004, + 'core', 'delo', 2005, + 'core', 'doex', 2006, + 'core', 'qobj', 2007, + 'core', 'getd', 2008, + 'core', 'dsiz', 2009, + 'core', 'gtei', 2010, + 'core', 'move', 2011, + 'core', 'save', 2012, + 'core', 'setd', 2013 + } +}; + +/*--------------------------------------------------------------------------*/ +/* Misc Standards, we will leave this hard wired for now */ +/*--------------------------------------------------------------------------*/ + +resource 'aedt' (kMisc_aedtResID, "Misc Standards") { + { + 'aevt', 'obit', 3001, + 'misc', 'begi', 3002, + 'misc', 'copy', 3003, + 'misc', 'cpub', 3004, + 'misc', 'cut ', 3005, + 'misc', 'dosc', 3006, + 'misc', 'edit', 3007, + 'misc', 'endt', 3008, + 'misc', 'imgr', 3009, + 'misc', 'isun', 3010, + 'misc', 'mvis', 3011, + 'misc', 'past', 3012, + 'misc', 'redo', 3013, + 'misc', 'rvrt', 3014, + 'misc', 'ttrm', 3015, + 'misc', 'undo', 3016 + } +}; + + + + + diff --git a/xpfe/bootstrap/appleevents/nsAppleEvents.rsrc b/xpfe/bootstrap/appleevents/nsAppleEvents.rsrc new file mode 100644 index 000000000000..60782130b8e0 Binary files /dev/null and b/xpfe/bootstrap/appleevents/nsAppleEvents.rsrc differ diff --git a/xpfe/bootstrap/appleevents/nsAppleEventsService.cpp b/xpfe/bootstrap/appleevents/nsAppleEventsService.cpp new file mode 100644 index 000000000000..391afd4098a8 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAppleEventsService.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsAppleEventsService.h" +#include "nsAECoreClass.h" + +nsAppleEventsService::nsAppleEventsService() +{ + NS_INIT_REFCNT(); +} + +nsAppleEventsService::~nsAppleEventsService() +{ + +} + +NS_IMPL_ISUPPORTS(nsAppleEventsService, NS_GET_IID(nsIAppleEventsService)); + +NS_IMETHODIMP nsAppleEventsService::Init(void) +{ + OSErr err = CreateAEHandlerClasses(false); + return (err == noErr) ? NS_OK : NS_ERROR_FAILURE; +} + + + +NS_IMETHODIMP nsAppleEventsService::Shutdown(void) +{ + ShutdownAEHandlerClasses(); + return NS_OK; +} + diff --git a/xpfe/bootstrap/appleevents/nsAppleEventsService.h b/xpfe/bootstrap/appleevents/nsAppleEventsService.h new file mode 100644 index 000000000000..2cb3a6d954ce --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsAppleEventsService.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef nsAppleEventService_h_ +#define nsAppleEventService_h_ + + +#include "nsIAppleEventsService.h" + +// this is currently unused + +class nsAppleEventsService : public nsIAppleEventsService +{ +public: + + nsAppleEventsService(); + virtual ~nsAppleEventsService(); + + NS_DECL_ISUPPORTS + + NS_DECL_NSIAPPLEEVENTSSERVICE + +protected: + +}; + + + + +#endif // nsAppleEventService_h_ diff --git a/xpfe/bootstrap/appleevents/nsMacUtils.cpp b/xpfe/bootstrap/appleevents/nsMacUtils.cpp new file mode 100644 index 000000000000..2b01c541f72c --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsMacUtils.cpp @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + + +#include + +#include "nsMacUtils.h" + + +OSErr MyNewHandle(long length, Handle *outHandle) +{ + Handle tempHandle = NewHandle(length); + if (!tempHandle) return memFullErr; + *outHandle = tempHandle; + return noErr; +} + + +void MyDisposeHandle(Handle theHandle) +{ + if (theHandle) + DisposeHandle(theHandle); +} + + +void MyHLock(Handle theHandle) +{ + HLock(theHandle); +} + +void MyHUnlock(Handle theHandle) +{ + HUnlock(theHandle); +} + +#pragma mark - + +OSErr MyNewBlockClear(long length, void* *outBlock) +{ + void* newData = calloc(length, 1); + if (!newData) return memFullErr; + *outBlock = newData; + return noErr; +} + +void MyDisposeBlock(void *dataBlock) +{ + if (dataBlock) + free(dataBlock); +} + +#pragma mark - + +/*---------------------------------------------------------------------------- + StrCopySafe + + strcpy which checks destination buffer length + +----------------------------------------------------------------------------*/ +void StrCopySafe(char *dst, const char *src, long destLen) +{ + const unsigned char *p = (unsigned char *) src - 1; + unsigned char *q = (unsigned char *) dst - 1; + unsigned char *end = (unsigned char *)dst + destLen; + + while ( q < end && (*++q = (*++p)) != '\0' ) {;} + if (q == end) + *q = '\0'; +} + +/*---------------------------------------------------------------------------- + CopyPascalString + + Copy a pascal format string. + + Entry: to = pointer to destination string. + from = pointer to source string. +----------------------------------------------------------------------------*/ + +void CopyPascalString (StringPtr to, const StringPtr from) +{ + BlockMoveData(from, to, *from+1); +} + + +/*---------------------------------------------------------------------------- + CopyCToPascalString + + Copy from a C string to a Pascal string, up to maxLen chars. +----------------------------------------------------------------------------*/ + +void CopyCToPascalString(const char *src, StringPtr dest, long maxLen) +{ + char *s = (char *)src; + char *d = (char *)(&dest[1]); + long count = 0; + + while (count < maxLen && *s) { + *d ++ = *s ++; + count ++; + } + + dest[0] = (unsigned char)(count); +} + + +/*---------------------------------------------------------------------------- + CopyPascalToCString + + Copy from a C string to a Pascal string, up to maxLen chars. +----------------------------------------------------------------------------*/ + +void CopyPascalToCString(const StringPtr src, char *dest, long maxLen) +{ + short len = Min(maxLen, src[0]); + + BlockMoveData(&src[1], dest, len); + dest[len] = '\0'; +} + + + +/*---------------------------------------------------------------------------- + GetShortVersionString + + Extracts the version number string from the specified 'vers' resource and + concats it onto the end of the specified string (Pascal-style). The short + version number string is extracted. + + Exit: function result = error code. + *versionNumber = version number. +----------------------------------------------------------------------------*/ + +OSErr GetShortVersionString(short rID, StringPtr version) +{ + VersRecHndl versionH; + OSErr error = resNotFound; + + versionH = (VersRecHndl)Get1Resource('vers', rID); + + if (versionH) + { + CopyPascalString(version, (**versionH).shortVersion); + ReleaseResource((Handle) versionH); + error = noErr; + } + else + CopyPascalString("\p", version); + + return error; +} + + diff --git a/xpfe/bootstrap/appleevents/nsMacUtils.h b/xpfe/bootstrap/appleevents/nsMacUtils.h new file mode 100644 index 000000000000..9c0d39ebeb97 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsMacUtils.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef nsMacUtils_h_ +#define nsMacUtils_h_ + +#include +#include +#include +#include + +#define Min(a, b) ((a) < (b) ? (a) : (b)) + +#ifdef __cplusplus +extern "C" { +#endif + +OSErr MyNewHandle(long length, Handle *outHandle); +void MyDisposeHandle(Handle theHandle); + +void MyHLock(Handle theHandle); +void MyHUnlock(Handle theHandle); + + + +OSErr MyNewBlockClear(long length, void* *outBlock); +void MyDisposeBlock(void *dataBlock); + + +void StrCopySafe(char *dst, const char *src, long destLen); +void CopyPascalString (StringPtr to, const StringPtr from); +void CopyCToPascalString(const char *src, StringPtr dest, long maxLen); +void CopyPascalToCString(const StringPtr src, char *dest, long maxLen); + +OSErr GetShortVersionString(short rID, StringPtr version); + +#ifdef __cplusplus +} +#endif + +#endif /* nsMacUtils_h_ */ diff --git a/xpfe/bootstrap/appleevents/nsWindowUtils.cpp b/xpfe/bootstrap/appleevents/nsWindowUtils.cpp new file mode 100644 index 000000000000..52d6c4fe4112 --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsWindowUtils.cpp @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#include "nsWindowUtils.h" + + + +long CountWindowsOfKind(TWindowKind windowKind) +{ + // еее write me + return 0; +} + + +WindowPtr GetNamedOrFrontmostWindow(TWindowKind windowKind, const char* windowName) +{ + // еее write me + return NULL; +} + + +WindowPtr GetIndexedWindowOfKind(TWindowKind windowKind, TAEListIndex index) +{ + // еее write me + return NULL; +} + + +TAEListIndex GetWindowIndex(TWindowKind windowKind, WindowPtr theWindow) +{ + // еее write me + return 0; +} + + +void GetCleanedWindowName(WindowPtr wind, char* outName, long maxLen) +{ + // еее write me + *outName = '\0'; +} + + +//--------------------------------------------------------- +inline void GetWindowPortRect(WindowPtr wind, Rect *outRect) +{ + *outRect = wind->portRect; +} + +/*---------------------------------------------------------------------------- + LocalToGlobalRect + + Convert a rectangle from local to global coordinates. + + Entry: r = pointer to rectangle. +----------------------------------------------------------------------------*/ + +static void LocalToGlobalRect (Rect *r) +{ + LocalToGlobal((Point*)&r->top); + LocalToGlobal((Point*)&r->bottom); +} + +void GetWindowGlobalBounds(WindowPtr wind, Rect* outBounds) +{ + GrafPtr curPort; + GetWindowPortRect(wind, outBounds); + GetPort(&curPort); + SetPort(wind); + LocalToGlobalRect(outBounds); + SetPort(curPort); +} + + +#pragma mark - + +/*---------------------------------------------------------------------------- + WindowIsResizeable + +----------------------------------------------------------------------------*/ + +Boolean WindowIsResizeable(WindowPtr wind) +{ + OSStatus status; + UInt32 features; + status = GetWindowFeatures(wind, &features); + return ((status == noErr) && ((features & kWindowCanGrow) != 0)); +} + +/*---------------------------------------------------------------------------- + WindowIsZoomable + +----------------------------------------------------------------------------*/ +Boolean WindowIsZoomable(WindowPtr wind) +{ + OSStatus status; + UInt32 features; + status = GetWindowFeatures(wind, &features); + return ((status == noErr) && ((features & kWindowCanZoom) != 0)); +} + +/*---------------------------------------------------------------------------- + WindowIsZoomed + +----------------------------------------------------------------------------*/ +Boolean WindowIsZoomed(WindowPtr wind) +{ + Rect r, userRect; + GetWindowUserState(wind, &userRect); + GetWindowPortRect(wind, &r); + OffsetRect(&userRect, -userRect.left, -userRect.top); + return EqualRect(&userRect, &r); +} + +/*---------------------------------------------------------------------------- + WindowHasTitleBar + + This stuff only works in 8.0 and later (Appearance Mgr) +----------------------------------------------------------------------------*/ +Boolean WindowHasTitleBar(WindowPtr wind) +{ + OSStatus status; + UInt32 features; + status = GetWindowFeatures(wind, &features); + return ((status == noErr) && ((features & kWindowHasTitleBar) != 0)); +} + +/*---------------------------------------------------------------------------- + WindowIsCloseable + + This stuff only works in 8.5 and later (Appearance Mgr) +----------------------------------------------------------------------------*/ +Boolean WindowIsCloseable(WindowPtr wind) +{ + if ((long)GetWindowAttributes != kUnresolvedCFragSymbolAddress) + { + OSStatus status; + UInt32 attributes; + + status = GetWindowAttributes(wind, &attributes); + return ((status == noErr) && ((attributes & kWindowCloseBoxAttribute) != 0)); + } + + return true; +} + +/*---------------------------------------------------------------------------- + WindowIsModal + + This stuff only works in 8.0 and later (Appearance Mgr) +----------------------------------------------------------------------------*/ +Boolean WindowIsModal(WindowPtr wind) +{ + OSStatus status; + UInt32 features; + status = GetWindowFeatures(wind, &features); + return ((status == noErr) && ((features & kWindowIsModal) != 0)); +} + +/*---------------------------------------------------------------------------- + WindowIsFloating + +----------------------------------------------------------------------------*/ +Boolean WindowIsFloating(WindowPtr wind) +{ + WindowClass windClass; + if (GetWindowClass(wind, &windClass) == noErr) + { + return (windClass == kFloatingWindowClass); + } + + return false; +} + +/*---------------------------------------------------------------------------- + WindowIsModified + +----------------------------------------------------------------------------*/ +Boolean WindowIsModified(WindowPtr wind) +{ + // еее write me + return false; +} diff --git a/xpfe/bootstrap/appleevents/nsWindowUtils.h b/xpfe/bootstrap/appleevents/nsWindowUtils.h new file mode 100644 index 000000000000..2867cf1858ca --- /dev/null +++ b/xpfe/bootstrap/appleevents/nsWindowUtils.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef nsWindowUtils_h_ +#define nsWindowUtils_h_ + +#include +#include + +#include "nsAEDefs.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +long CountWindowsOfKind(TWindowKind windowKind); + +WindowPtr GetNamedOrFrontmostWindow(TWindowKind windowKind, const char* windowName); +WindowPtr GetIndexedWindowOfKind(TWindowKind windowKind, TAEListIndex index); +TAEListIndex GetWindowIndex(TWindowKind windowKind, WindowPtr theWindow); + +void GetCleanedWindowName(WindowPtr wind, char* outName, long maxLen); +void GetWindowGlobalBounds(WindowPtr wind, Rect* outRect); + +Boolean WindowIsResizeable(WindowPtr wind); +Boolean WindowIsZoomable(WindowPtr wind); +Boolean WindowIsZoomed(WindowPtr wind); +Boolean WindowHasTitleBar(WindowPtr wind); +Boolean WindowIsModal(WindowPtr wind); +Boolean WindowIsCloseable(WindowPtr wind); +Boolean WindowIsFloating(WindowPtr wind); +Boolean WindowIsModified(WindowPtr wind); + + +#ifdef __cplusplus +} +#endif + + +#endif // nsWindowUtils_h_ diff --git a/xpfe/bootstrap/appleevents/patricia.c b/xpfe/bootstrap/appleevents/patricia.c new file mode 100644 index 000000000000..d036ffba4839 --- /dev/null +++ b/xpfe/bootstrap/appleevents/patricia.c @@ -0,0 +1,520 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +/*--------------------------------------------------------------------- + + Patricia + + D.R. Morrison's "Practical Algorithm To Retrieve Information + Coded in Alphanumeric" + + This implementation geared towards the storage of data that + is indexed through arbitrary-length binary keys (e.g. sequence + data). It also only deals with the case where every key is unique; + duplicate keys are not entered into the tree, although you may + do some processing on duplicates in the ReplaceFunction passed + to PatriciaInsert. + + There is no function to remove nodes from the tree at present. + + The implementation is modular, in the sense that all tree data structures + are declared in this file, and are not intended to be accessed externally. + You should only use the functions prototyped in patricia.h, all of which + start with 'Patricia', and should consider the tree as an opaque data + structure. + + Ref: Donald R. Morrison. PATRICIA -- practical algorithm to retrieve + information coded in alphanumeric. Journal of the ACM, 15(4):514-534, + October 1968 + + See Sedgewick, R. Algorithms, 2nd Ed. (1988) for implemenation details. + +-----------------------------------------------------------------------*/ + +#include +#include + +//#include "utils.h" +#include "patricia.h" + +#include "nsAEDefs.h" // for ASSERT + +/* Uncomment to print verbose logging on tree activity */ +//#define VERBOSE + +/* Data structures */ + +typedef struct TNodeTag { + unsigned char *key; /* The node's key value in an array of chars */ + short bit; /* The bit that is examined at this node */ + long nodeID; /* Unique ID for each node, used for debugging */ + struct TNodeTag *left; /* Pointer to left child node */ + struct TNodeTag *right; /* Pointer to right child node */ + void *data; /* Pointer to user-defined data structure */ +} TNode; + + +typedef struct { + TNode* headNode; /* Pointer to dummy head node */ + long numKeyBits; /* Size of keys, in bits */ + long keySize; /* Size of keys, in chars (assumed to be 8 bits each) */ + long numNodes; /* Number of nodes in tree */ +} TPatriciaTree; + + +/* These macros assume that key is a *[unsigned] char, and that a char is 8 bits big */ + +#define TestKeyBit(key, bit) ( (key[bit >> 3] & (1 << (bit & 7))) != 0 ) +#define CompareKeyBits(key1, key2, bit) ( (key1[bit >> 3] & (1 << (bit & 7))) == (key2[bit >> 3] & (1 << (bit & 7))) ) + +/*--------------------------------------------------------------------- + + MakeNewNode + + Allocates a new node as an object on the heap, and initializes + the key and bit values to those supplied. + + Entry: key binary key data + bit bit value + nodeData user data for this node, if any. + + Exit: return value pointer to the new node, or NULL on error + +-----------------------------------------------------------------------*/ + +static TNode *MakeNewNode(TPatriciaTree *tree, const unsigned char *key, short bit, void *nodeData) +{ + static long nodeID = 0; + TNode *newNode; + + newNode = (TNode *)calloc(1, sizeof(TNode)); + if (newNode == NULL) return NULL; + + newNode->key = (unsigned char *)calloc(tree->keySize + 1, 1); //last bit must be zero + if (newNode->key == NULL) { + free(newNode); + return NULL; + } + memcpy(newNode->key, key, tree->keySize); + newNode->bit = bit; + newNode->data = nodeData; + newNode->nodeID = nodeID; + nodeID ++; + + return newNode; +} + + +/*--------------------------------------------------------------------- + + MakeHeadNode + + Allocates the dummy head node of the tree, which is initialized to + key field = 000000... + bits = numKeyBits + left & right = point to self + data = NULL + + Exit: return value pointer to the new node, or NULL on error + +-----------------------------------------------------------------------*/ + +static TNode *MakeHeadNode(TPatriciaTree *tree) +{ + TNode *newNode; + + newNode = (TNode *)calloc(1, sizeof(TNode)); + if (newNode == NULL) return NULL; + + newNode->key = (unsigned char *)calloc(tree->keySize + 1, 1); //last bit must be zero + if (newNode->key == NULL) { + free(newNode); + return NULL; + } + memset(newNode->key, 0, tree->keySize); + newNode->bit = tree->numKeyBits; + newNode->data = NULL; + newNode->nodeID = -1; + + /* Both self-pointers for the head node */ + newNode->left = newNode; + newNode->right = newNode; + + return newNode; +} + + +/*--------------------------------------------------------------------- + + InternalSearch + + Search the tree for a node with the given key, starting at + startNode. + + Entry: tree pointer to a tree + key binary key data + startNode node to start the search (must NOT be NULL) + + Exit: return value: pointer to found node, or node with upward + link. The caller must verify whether this + is the node wanted by comparing keys. + +-----------------------------------------------------------------------*/ + +static TNode *InternalSearch(TPatriciaTree *tree, TNode *x, const unsigned char *key) +{ + TNode *p; + + ASSERT(x, "No node"); + + do { + p = x; + + if (TestKeyBit(key, x->bit)) + x = x->right; + else + x = x->left; + + } while (p->bit > x->bit); + + return x; +} + + + +/*--------------------------------------------------------------------- + + InternalTraverse + + A traverse routine used internally. + + Entry: tree pointer to a tree + key binary key data + x node to start the search (must NOT be NULL) + traverseFunc function called on each node, like this: + + (*traverseFunc)(x->data, x->key, arg1, arg2); + + Exit: return value: 0 if everything OK + Non-zero value on error + +-----------------------------------------------------------------------*/ + +static int InternalTraverse(TPatriciaTree *tree, TNode *x, NodeTraverseFunction traverseFunc, void *arg1, void *arg2) +{ + TNode *p; + int err = 0; + + ASSERT(x, "No node"); + ASSERT(x->left && x->right, "Left or right child missing"); + +#ifdef VERBOSE + printf("Visiting node %ld with left %ld and right %ld\n", x->nodeID, x->left->nodeID, x->right->nodeID); +#endif + + if (x != tree->headNode) { + err = (*traverseFunc)(x->data, x->key, arg1, arg2); + if (err != 0) return err; + } + + p = x->left; + if (p->bit < x->bit) + err = InternalTraverse(tree, p, traverseFunc, arg1, arg2); + + if (err != 0) return err; + + p = x->right; + if (p->bit < x->bit) + err = InternalTraverse(tree, p, traverseFunc, arg1, arg2); + + return err; +} + + + +/*--------------------------------------------------------------------- + + TraverseAndFree + + A traverse routine used internall. + + Entry: tree pointer to a tree + key binary key data + x node to start the search (must NOT be NULL) + traverseFunc function called on each node, like this: + + (*traverseFunc)(x->data, x->key, arg1, arg2); + + Exit: return value: 0 if everything OK + Non-zero value on error + +-----------------------------------------------------------------------*/ + +static int TraverseAndFree(TPatriciaTree *tree, TNode *x, NodeFreeFunction freeFunc, void *refCon) +{ + TNode *p; + int err = 0; + + ASSERT(x, "No node"); + ASSERT(x->left && x->right, "Left or right child missing"); + + p = x->left; + if (p->bit < x->bit) { + err = TraverseAndFree(tree, p, freeFunc, refCon); + if (err != 0) return err; + } + + p = x->right; + if (p->bit < x->bit) { + err = TraverseAndFree(tree, p, freeFunc, refCon); + if (err != 0) return err; + } + + err = (*freeFunc)(x->data, x->key, refCon); + +#ifdef VERBOSE + printf("Freeing node %ld\n", x->nodeID); +#endif + + free(x->key); + free(x); + + return err; +} + + +#pragma mark - + + +/*--------------------------------------------------------------------- + + InitPatriciaTree + + Allocate and initialize a new, empty PatriciaTree. + + Entry: keySize length of the keys, in bits + + Exit: return value A reference to the created PatriciaTree, + or NULL on error. + +-----------------------------------------------------------------------*/ + +PatriciaTreeRef PatriciaInitTree(long numKeyBits) +{ + TPatriciaTree *tree = NULL; + + tree = (TPatriciaTree *)calloc(1, sizeof(TPatriciaTree)); + if (tree == NULL) return NULL; + + tree->numKeyBits = numKeyBits; + tree->keySize = (numKeyBits >> 3) + ((numKeyBits & 7) != 0); + tree->numNodes = 0; + + tree->headNode = MakeHeadNode(tree); + if (tree->headNode == NULL) { + free(tree); + return NULL; + } + + return (PatriciaTreeRef)tree; +} + + + +/*--------------------------------------------------------------------- + + PatriciaFreeTree + + Free a Patricia tree and all associate data structures. freeFunc is + called on each node's node->data. If no freeFunc is supplied, then + the node->data will NOT be freed. + + Entry: treeRef reference to a previously allocated PatriciaTree + freeFunc a function that is called on each node->data + arg pointer to data that is also passed to the free function. + + The free function is called like this: (*freeFunc)(node->data, node->key, arg) + +-----------------------------------------------------------------------*/ + +void PatriciaFreeTree(PatriciaTreeRef treeRef, NodeFreeFunction freeFunc, void *refCon) +{ + TPatriciaTree *tree = (TPatriciaTree *)treeRef; + + if (tree == NULL) return; + + /* Traverse the tree and free the data */ + TraverseAndFree(tree, tree->headNode, freeFunc, refCon); + + free(tree); +} + + + +/*--------------------------------------------------------------------- + + PatriciaSearch + + Search the tree for the node with the given key. + + Entry: key pointer to binary key data + data pointer to placeholder for returned data + If you pass NULL in this argument, no value + will be returned (i.e. I don't deference 0). + + Exit: return value 1 if key found (data returned in *data) + 0 if key not found (NULL returned in *data) + +-----------------------------------------------------------------------*/ + +int PatriciaSearch(PatriciaTreeRef treeRef, const unsigned char *key, void **data) +{ + TPatriciaTree *tree = (TPatriciaTree *)treeRef; + TNode *foundNode; + + ASSERT(tree, "Where is my tree?"); + + foundNode = InternalSearch(tree, tree->headNode, key); + ASSERT(foundNode, "Should have found node"); + + if (memcmp(foundNode->key, key, tree->keySize) == 0) { + if (data != NULL) + *data = foundNode->data; + return 1; + } else + return 0; +} + + + +/*--------------------------------------------------------------------- + + PatriciaInsert + + Insert a node into the tree with the given key and data. + + Entry: key pointer to binary key data + replaceFunc function executed when a node with the key we + are inserting is found in the tree. + data pointer to node data structure + + Exit: return value 0 if insertion successful + 1 if key already exists + -1 if some other error + +-----------------------------------------------------------------------*/ + +int PatriciaInsert(PatriciaTreeRef treeRef, NodeReplaceFunction replaceFunc, const unsigned char *key, void *data, void *refCon) +{ + TPatriciaTree *tree = (TPatriciaTree *)treeRef; + TNode *x, *t, *p; + short i; + + x = tree->headNode; + t = InternalSearch(tree, x, key); + + ASSERT(t, "Should have found node"); + + if (memcmp(t->key, key, tree->keySize) == 0) { + if (replaceFunc) (*replaceFunc)(&t->data, t->key, data, refCon); + return 1; /* It's already there */ + } + + i = tree->numKeyBits - 1; + + while (CompareKeyBits(key, t->key, i)) + i --; + + do { + p = x; + x = (TestKeyBit(key, x->bit)) ? x->right : x->left; + } while (x->bit > i && p->bit > x->bit); + + t = MakeNewNode(tree, key, i, data); + if (t == NULL) return -1; + + if (TestKeyBit(key, t->bit)) { + t->right = t; + t->left = x; + } else { + t->right = x; + t->left = t; + } + + if (TestKeyBit(key, p->bit)) + p->right = t; + else + p->left = t; + +#ifdef VERBOSE + printf("Inserted node %ld with left %ld and right %ld\n", t->nodeID, t->left->nodeID, t->right->nodeID); +#endif + + tree->numNodes ++; + + return 0; +} + + +/*--------------------------------------------------------------------- + + PatriciaTraverse + + Traverse the tree, executing traverseFunc for each node. It's called like + this: + (*traverseFunc)(node->data, node->key, arg1, arg2); + + traverseFunc should return 0 if it completes successfully, or any other + value if there is an error. In this case, the traverse is abruptly terminated. + + Entry: treeRef reference to a Patricia tree + traverseFunc function to be called on each node + arg1, arg2 arguments passed to traverseFunc + + Exit: return value 0 if traverse competed successfully + -1 if something caused the traverse to + terminate. + +-----------------------------------------------------------------------*/ + +int PatriciaTraverse(PatriciaTreeRef treeRef, NodeTraverseFunction traverseFunc, void *arg, void *refCon) +{ + TPatriciaTree *tree = (TPatriciaTree *)treeRef; + + return InternalTraverse(tree, tree->headNode, traverseFunc, arg, refCon); +} + + +/*--------------------------------------------------------------------- + + PatriciaGetNumNodes + + Return the number of nodes in the tree + +-----------------------------------------------------------------------*/ + +long PatriciaGetNumNodes(PatriciaTreeRef treeRef) +{ + return ((TPatriciaTree *)treeRef)->numNodes; +} diff --git a/xpfe/bootstrap/appleevents/patricia.h b/xpfe/bootstrap/appleevents/patricia.h new file mode 100644 index 000000000000..7bbc9baaeeb8 --- /dev/null +++ b/xpfe/bootstrap/appleevents/patricia.h @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Simon Fraser + */ + + +#ifndef __PATRICIA__ +#define __PATRICIA__ + +/*--------------------------------------------------------------------- + + Patricia + + D.R. Morrison's "Practical Algorithm To Retrieve Information + Coded in Alphanumeric" + + See patricia.c for more information. + + Ref: Donald R. Morrison. PATRICIA -- practical algorithm to retrieve + information coded in alphanumeric. Journal of the ACM, 15(4):514-534, + October 1968 + + See SedgeWick, R. Algorithms, 2nd Ed. (1988) for implemenation details. + +-----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* A type which you should use externally to refer to a Patricia tree. You + application should treat the tree as an opaque data structure, accessed + only through those routines whose prototypes are declared below. + + All externally-visible routines start with 'Patricia'. Internal routines + are declared static in the .c file, and should not be used elsewhere. +*/ +typedef void *PatriciaTreeRef; + + +/* Declarations for user-supplied functions, which are called on replacing + nodes (i.e. when inserting a node with a duplicate key, on traversing + the tree, and on freeing nodes. A non-zero return value indicates failure. +*/ +typedef int (*NodeReplaceFunction) (void* *nodeDataPtr, unsigned char *key, void *replaceData, void *refCon); +typedef int (*NodeTraverseFunction) (void *nodeData, unsigned char *key, void *arg, void *refCon); +typedef int (*NodeFreeFunction) (void *nodeData, unsigned char *key, void *refCon); + +/* The creation and destruction functions for allocating and freeing a tree. + PatriciaInitTree() allocates space for a tree and initializes it. + PatriciaFreeTree() frees the tree nodes and the tree itself. It does *NOT* free + the data associated with each node, unless you pass a NodeFreeFunction that + does this. +*/ +PatriciaTreeRef PatriciaInitTree(long numKeyBits); +void PatriciaFreeTree(PatriciaTreeRef treeRef, NodeFreeFunction freeFunc, void *refCon); + +/* Functions for inserting nodes, searching for a node with a given key, + and traversing the tree. Traversal involves visiting every node in the tree, + but does not guarantee that the nodes are visited in a particular order. +*/ +int PatriciaInsert(PatriciaTreeRef treeRef, NodeReplaceFunction replaceFunc, const unsigned char *key, void *data, void *refCon); +int PatriciaSearch(PatriciaTreeRef treeRef, const unsigned char *key, void **data); +int PatriciaTraverse(PatriciaTreeRef treeRef, NodeTraverseFunction traverseFunc, void *arg, void *refCon); + +/* An accessor function that returns the total number of nodes in the tree +*/ +long PatriciaGetNumNodes(PatriciaTreeRef treeRef); + +#ifdef __cplusplus +} +#endif + +#endif /* __PATRICIA__ */ +