home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1998
/
MacHack 1998.toast
/
Papers
/
C++ Exceptions
/
µShell
/
Core Utilities
/
AEExtras.cp
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1998-04-02
|
29.2 KB
|
1,397 lines
|
[
TEXT/CWIE
]
#ifndef __AEEXTRAS__
#include "AEExtras.h"
#endif
#ifndef __AETYPECOERCIONS__
#include "AETypeCoercions.h"
#endif
#ifndef __EXCEPTIONS__
#include "Exceptions.h"
#endif
#include <OSA.h>
#include <stdarg.h>
#include <AEObjects.h>
#include <AERegistry.h>
#include <ASRegistry.h>
#include <Patches.h>
#include <Traps.h>
#include "AEBuild.h"
#include "DebugWrite.h"
const ProcessSerialNumber kAESelfPSN = { 0, kCurrentProcess };
AEAddressDesc gSelfAddrDesc = {typeNull, nil };
static AEIdleUPP gDefaultAEIdleUPP = nil;
static AEFilterUPP gDefaultAEFilterUPP = nil;
#define ZeroDesc(d) { (d).descriptorType = typeNull; (d).dataHandle = nil; }
//------------------------------------------------------------------------------
static OSStatus vCoerceDescProc(va_list arg)
{
VA_ARG(const AEDesc*, fromDesc, arg);
VA_ARG(DescType, toType, arg);
VA_ARG(AECoerceDescProcPtr, proc, arg);
VA_ARG(AEDesc*, toDesc, arg);
return (*proc)(fromDesc, toType, 0, toDesc);
}
static pascal OSErr XCoerceDescProc(
const AEDesc* fromDesc,
DescType toType,
long handlerRefcon,
AEDesc* toDesc)
{
return Exception::CatchOSErrors(vCoerceDescProc, fromDesc, toType, handlerRefcon, toDesc);
}
pascal void XAEInstallCoerceDescProc(
DescType fromType,
DescType toType,
AECoerceDescProcPtr handler)
{
#if GENERATINGCFM
static RoutineDescriptor UPP =
BUILD_ROUTINE_DESCRIPTOR(uppAECoerceDescProcInfo, XCoerceDescProc);
FailOSErr(AEInstallCoercionHandler(fromType, toType, &UPP, (long) handler, true, false));
#else
FailOSErr(AEInstallCoercionHandler(fromType, toType,
(AECoercionHandlerUPP) &XCoerceDescProc, (long) handler, true, false));
#endif
}
//------------------------------------------------------------------------------
static OSStatus vCoercePtrProc(va_list arg)
{
VA_ARG(DescType, typeCode, arg);
VA_ARG(const void*, dataPtr, arg);
VA_ARG(Size, dataSize, arg);
VA_ARG(DescType, toType, arg);
VA_ARG(AECoercePtrProcPtr, proc, arg);
VA_ARG(AEDesc*, toDesc, arg);
return (*proc)(typeCode, dataPtr, dataSize, toType, 0, toDesc);
}
static pascal OSErr XCoercePtrProc(
DescType typeCode,
const void* dataPtr,
Size dataSize,
DescType toType,
long handlerRefcon,
AEDesc* result)
{
return Exception::CatchOSErrors(vCoercePtrProc, typeCode, dataPtr, dataSize, toType, handlerRefcon, result);
}
pascal void XAEInstallCoercePtrProc(
DescType fromType,
DescType toType,
AECoercePtrProcPtr handler)
{
#if GENERATINGCFM
static RoutineDescriptor UPP =
BUILD_ROUTINE_DESCRIPTOR(uppAECoercePtrProcInfo, XCoerceDescProc);
FailOSErr(AEInstallCoercionHandler(fromType, toType, &UPP, (long) handler, false, false));
#else
FailOSErr(AEInstallCoercionHandler(fromType, toType,
(AECoercionHandlerUPP) &XCoerceDescProc, (long) handler, false, false));
#endif
}
//------------------------------------------------------------------------------
static pascal OSErr CoerceToInsertion(
const AEDesc* fromDesc,
DescType /*toType*/,
long /*handlerRefcon*/,
AEDesc* toDesc)
{
AEDesc tempDesc;
OSErr err = AECreateList(nil, 0, true, &tempDesc);
if (err == noErr)
{
err = AEPutParamDesc(&tempDesc, keyAEObject, fromDesc);
if (err == noErr)
{
DescType in = formIn;
err = AEPutParamPtr(&tempDesc, keyAEPosition, typeEnumeration, &in, sizeof(in));
if (err == noErr)
{
err = AECoerceDesc(&tempDesc, typeInsertionLoc, toDesc);
}
}
AEDisposeDesc(&tempDesc);
}
return err;
}
//------------------------------------------------------------------------------
pascal OSErr InitAEExtras(AEIdleUPP idle, AEFilterUPP filter)
{
OSErr err = noErr;
gDefaultAEIdleUPP = idle;
gDefaultAEFilterUPP = filter;
if (gSelfAddrDesc.dataHandle == nil)
{
err = AECreateDesc(typeProcessSerialNumber, &kAESelfPSN, sizeof(kAESelfPSN), &gSelfAddrDesc);
}
if (err == noErr)
{
err = AEInstallTypeCoercions();
}
if (err == noErr)
{
#if GENERATINGCFM
static RoutineDescriptor sCoerceTypeUPP =
BUILD_ROUTINE_DESCRIPTOR(uppAECoerceDescProcInfo, CoerceToInsertion);
err = AEInstallCoercionHandler(typeObjectSpecifier, typeInsertionLoc, &sCoerceTypeUPP, 0, true, false);
#else
err = AEInstallCoercionHandler(typeObjectSpecifier, typeInsertionLoc,
(AECoercionHandlerUPP)NewAECoerceDescProc(CoerceToInsertion), 0, true, false);
#endif
}
return err;
}
//------------------------------------------------------------------------------
pascal OSErr TempAECreateDesc(DescType typeCode, const void* dataPtr, Size dataSize, AEDesc *result)
{
OSErr err = noErr;
result->descriptorType = typeCode;
result->dataHandle = TempNewHandle(dataSize,&err);
if ((err != noErr) || (result->dataHandle == nil))
{
result->dataHandle = NewHandle(dataSize);
err = MemError();
}
if ( ( err == noErr ) && ( result->dataHandle != nil ) && ( dataPtr != nil ) )
BlockMoveData(dataPtr,*(result->dataHandle),dataSize);
return err;
}
//------------------------------------------------------------------------------
pascal OSErr TempAEDuplicateDesc(const AEDesc *source, AEDesc *dest)
{
OSErr err = noErr;
if (source->dataHandle != nil)
{
char state = HGetState(source->dataHandle);
HLockHi(source->dataHandle);
err = TempAECreateDesc(source->descriptorType,
*source->dataHandle, GetHandleSize(source->dataHandle),
dest);
HSetState(source->dataHandle, state);
}
else
{
*dest = *source;
}
return err;
}
//------------------------------------------------------------------------------
AEIdleUPP AEGetDefaultIdleProc(void)
{
return gDefaultAEIdleUPP;
}
//------------------------------------------------------------------------------
AEIdleUPP AESetDefaultIdleProc(AEIdleUPP newProc)
{
AEIdleUPP old = gDefaultAEIdleUPP;
gDefaultAEIdleUPP = newProc;
return old;
}
//------------------------------------------------------------------------------
AEFilterUPP AEGetDefaultFilterProc(void)
{
return gDefaultAEFilterUPP;
}
//------------------------------------------------------------------------------
AEFilterUPP AESetDefaultFilterProc(AEFilterUPP newProc)
{
AEFilterUPP old = gDefaultAEFilterUPP;
gDefaultAEFilterUPP = newProc;
return old;
}
//------------------------------------------------------------------------------
const AEAddressDesc* AEGetSelfAddress()
{
return &gSelfAddrDesc;
}
//------------------------------------------------------------------------------
enum AEHandlerType // Search order for handlers
{
kAETypeTypeAppHandler,
kAETypeWildAppHandler,
kAEWildTypeAppHandler,
kAEWildWildAppHandler,
kAETypeTypeSysHandler,
kAETypeWildSysHandler,
kAEWildTypeSysHandler,
kAEWildWildSysHandler
};
pascal OSErr XAEGetCoercionHandler(
DescType fromType,
DescType toType,
AECoercionHandlerUPP* handler,
long* handlerRefcon,
Boolean* fromTypeIsDesc,
AECoercionHandlerUPP skipMe)
{
OSErr err = AEGetCoercionHandler(fromType, toType, handler, handlerRefcon, fromTypeIsDesc, false);
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(typeWildCard, toType, handler, handlerRefcon, fromTypeIsDesc, false);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(fromType, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, false);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(typeWildCard, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, false);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(fromType, toType, handler, handlerRefcon, fromTypeIsDesc, true);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(typeWildCard, toType, handler, handlerRefcon, fromTypeIsDesc, true);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(fromType, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, true);
}
if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
{
err = AEGetCoercionHandler(typeWildCard, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, true);
}
if (err == noErr && *handler == skipMe)
{
err = errAEHandlerNotFound;
}
return err;
}
//------------------------------------------------------------------------------
pascal OSErr XAECoercePtr(
DescType typeCode,
const void* dataPtr,
Size dataSize,
DescType toType,
AEDesc* result)
{
AECoercionHandlerUPP handler;
long handlerRefcon;
Boolean fromTypeIsDesc;
OSErr err = XAEGetCoercionHandler(typeCode, toType, &handler, &handlerRefcon, &fromTypeIsDesc);
if (err == noErr)
{
if (fromTypeIsDesc)
{
AEDesc fromDesc;
err = TempAECreateDesc(typeCode, dataPtr,dataSize, &fromDesc);
if (err == noErr)
{
err = CallAECoerceDescProc((AECoerceDescUPP) handler, &fromDesc, toType, handlerRefcon, result);
}
AEDisposeDesc(&fromDesc);
}
else
{
err = CallAECoercePtrProc((AECoercePtrUPP) handler, typeCode, dataPtr, dataSize, toType, handlerRefcon, result);
}
}
return err;
}
//------------------------------------------------------------------------------
pascal OSErr XAECoerceDesc(
const AEDesc* fromDesc,
DescType toType,
AEDesc* result)
{
AECoercionHandlerUPP handler;
long handlerRefcon;
Boolean fromTypeIsDesc;
OSErr err = XAEGetCoercionHandler(fromDesc->descriptorType, toType, &handler, &handlerRefcon, &fromTypeIsDesc);
if (err == noErr)
{
if (fromTypeIsDesc)
{
err = CallAECoerceDescProc((AECoerceDescUPP) handler, fromDesc, toType, handlerRefcon, result);
}
else
{
Handle h = fromDesc->dataHandle;
SignedByte state = HGetState(h);
err = MemError(); // Validate handle
if (err == noErr)
{
HLock(h); // Assume only possible failure here is handle already locked
Size size = GetHandleSize(h);
err = CallAECoercePtrProc((AECoercePtrUPP) handler, fromDesc->descriptorType, *h, size, toType, handlerRefcon, result);
HSetState(h, state);
}
}
}
return err;
}
//------------------------------------------------------------------------------
pascal OSErr AEGetDescPtr(
const AEDesc* theAEDesc,
DescType desiredType,
DescType* typeCode,
void* dataPtr,
Size maximumSize,
Size* actualSize)
{
AEDesc tempDesc;
tempDesc.descriptorType = typeNull;
tempDesc.dataHandle = nil;
const AEDesc *desc = theAEDesc;
OSErr err = noErr;
Size offset = 0;
if (desiredType != typeWildCard
&& desiredType != theAEDesc->descriptorType)
{
DescType oldType = desc->descriptorType;
if (desc->dataHandle == nil) switch (oldType)
{
case typeTrue: // for speed
case typeFalse:
switch (desiredType)
{
case typeBoolean:
*(Boolean*)dataPtr = (oldType == typeTrue);
goto done;
}
break;
}
desc = &tempDesc;
err = AECoerceDesc(theAEDesc, desiredType, &tempDesc);
}
if (err == noErr)
{
Size dataSize = desc->dataHandle ? GetHandleSize(desc->dataHandle) : 0;
*typeCode = desc->descriptorType;
*actualSize = dataSize;
if (dataSize > maximumSize)
dataSize = maximumSize;
BlockMoveData(*desc->dataHandle, dataPtr, dataSize);
}
AEDisposeDesc(&tempDesc);
done:
return err;
}
//------------------------------------------------------------------------------
pascal OSErr AEParseInsertionLocation(
const AEDesc* insertLoc,
AEDesc* container, // the affected container
DescType* position, // the position enumeration
AEDesc* reference,
DescType* refClass) // objects to be replaced
{
AEDesc tempRecord;
AEDesc tempObject;
DescType actualType;
Size actualSize;
DescType localPosition;
OSErr err = noErr;
OSErr err1;
ZeroDesc(tempRecord);
ZeroDesc(tempObject);
if (position != nil)
{
*position = 0;
}
else
{
position = &localPosition;
}
if (container != nil)
{
if (container == insertLoc)
{
tempRecord = *insertLoc;
insertLoc = &tempRecord;
}
ZeroDesc(*container);
}
if (reference != nil)
{
if (reference == insertLoc)
{
tempRecord = *insertLoc;
insertLoc = &tempRecord;
}
ZeroDesc(*reference);
}
if (refClass != nil)
{
*refClass = 0;
}
if (insertLoc == nil)
{
err = paramErr;
}
else switch (insertLoc->descriptorType)
{
case typeObjectSpecifier:
case typeNull:
case typeObjectBeingExamined:
case typeAEList:
// an object specifier used an an insertion location is the container
if (container != nil)
{
if (insertLoc == &tempRecord) // If we own it, just return it
{
*container = *insertLoc;
ZeroDesc(tempRecord);
}
else
{
err = AEDuplicateDesc(insertLoc, container);
}
}
*position = formIn;
break;
case typeInsertionLoc: // Coerce our input into a record (if necessary)
err = AECoerceDesc(insertLoc, typeAERecord, &tempRecord);
insertLoc = &tempRecord;
case typeAERecord: // We're already a record
if (err == noErr)
{
// Get the position parameter
err = AEGetKeyPtr(insertLoc,
keyAEPosition,
typeEnumeration,
&actualType,
position,
sizeof(*position),
&actualSize);
// Get the reference object
err1 = AEGetKeyDesc(insertLoc, keyAEObject, typeWildCard, &tempObject);
if (err == noErr)
{
err = err1;
}
if (err == errAEDescNotFound)
{
err = errAENotAnObjSpec;
}
}
if (err == noErr)
{
switch (*position)
{
case kAEBefore: // tempObject is the reference object
case kAEAfter:
case kAEReplace:
if (reference)
{
*reference = tempObject;
tempObject.descriptorType = typeNull;
tempObject.dataHandle = nil;
}
else
{
reference = &tempObject;
}
err = AEParseObjectSpecifier(reference, refClass, container, nil, nil);
break;
case kAEBeginning: // tempObject is the container
case kAEEnd:
case formIn:
if (container)
{
*container = tempObject;
tempObject.descriptorType = typeNull;
tempObject.dataHandle = nil;
}
break;
default:
err = errAECorruptData;
}
}
break;
default:
err = errAENotAnObjSpec;
}
// Clean up any temporary descriptors
err1 = AEDisposeDesc(&tempObject);
err1 = AEDisposeDesc(&tempRecord);
return err;
}
//------------------------------------------------------------------------------
pascal OSErr AEParseObjectSpecifier(
const AEDesc* object,
DescType* desiredClass,
AEDesc* container,
DescType* keyForm,
AEDesc* keyData)
{
if (object->descriptorType == typeInsertionLoc)
{
// hand off insertion locations...
return AEParseInsertionLocation(object, container, keyForm, keyData, desiredClass);
}
else
{
AEDesc tempRecord;
DescType actualType;
Size actualSize;
OSErr err = noErr;
OSErr err1;
// Clear our temporaries
ZeroDesc(tempRecord);
// Clear our output parameters
if (container != nil)
{
if (container == object)
{
tempRecord = *object;
object = &tempRecord;
}
ZeroDesc(*container);
}
if (desiredClass != nil)
{
*desiredClass = 0;
}
if (keyForm != nil)
{
*keyForm = 0;
}
if (keyData != nil)
{
if (keyData == object)
{
tempRecord = *object;
object = &tempRecord;
}
ZeroDesc(*keyData);
}
if (object == nil)
{
err = paramErr;
}
else switch (object->descriptorType)
{
case typeAEList:
case typeNull:
case typeObjectBeingExamined:
if (keyForm != nil)
{
*keyForm = formSelf;
}
if (keyData != nil)
{
err = TempAEDuplicateDesc(object, keyData);
}
break;
case typeObjectSpecifier:
err = AECoerceDesc(object, typeAERecord, &tempRecord);
object = &tempRecord;
case typeAERecord:
if (err == noErr)
{
if (desiredClass != nil)
{
err = AEGetKeyPtr(object,
keyAEDesiredClass,
typeType,
&actualType,
desiredClass,
sizeof(*desiredClass),
&actualSize);
if (err == errAEDescNotFound)
{
err = errAENotAnObjSpec;
}
}
if (container != nil)
{
err1 = AEGetKeyDesc(object, keyAEContainer, typeWildCard, container);
if (err == noErr)
{
err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
}
}
if (keyForm != nil)
{
err1 = AEGetKeyPtr(object,
keyAEKeyForm,
typeEnumerated,
&actualType,
keyForm,
sizeof(*keyForm),
&actualSize);
if (err == noErr)
{
err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
}
}
if (keyData != nil)
{
err1 = AEGetKeyDesc(object, keyAEKeyData, typeWildCard, keyData);
if (err == noErr)
{
err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
}
}
}
break;
default:
err = errAENotAnObjSpec;
}
err1 = AEDisposeDesc(&tempRecord);
return err;
}
}
//------------------------------------------------------------------------------
DescType IsObjectSpecifier(const AEDesc* desc)
{
DescType type = desc->descriptorType;
switch (type) // these types are considered to be
{ // valid as object specifiers - note
case typeObjectSpecifier: // that we get no help from the
case typeObjectBeingExamined: // toolbox for typeAEList
case typeNull:
return type;
case typeAEList:
return GetUniformItemType(desc, typeObjectSpecifier, true);
default:
return 0;
}
}
//------------------------------------------------------------------------------
DescType IsObjectSpecifierOrInsertion(const AEDesc* desc)
{
if ((desc->descriptorType) == typeInsertionLoc)
{
return typeInsertionLoc;
}
else
{
return IsObjectSpecifier(desc);
}
}
//------------------------------------------------------------------------------
DescType GetUniformItemType(const AEDesc* list, DescType type, bool recursive)
{
DescType actualType;
Size actualSize;
AEKeyword actualKey;
OSErr err = AECountItems(list, &actualSize);
if (err != noErr)
{
type = 0;
}
else
{
long count = actualSize;
switch (type) // indicate initial pass
{
case 0:
case 1:
case typeWildCard:
case typeBest:
type = 1;
}
for (long i = 1; i <= count; i++)
{
err = AESizeOfNthItem(list, i, &actualType, &actualSize);
if (err != noErr)
{
type = 0;
break;
}
else if (actualType == typeAEList && recursive)
{
AEDesc temp;
err = AEGetNthDesc(list, i, typeAEList, &actualKey, &temp);
if (err == noErr)
{
type = GetUniformItemType(&temp, type, recursive);
}
AEDisposeDesc(&temp);
if (err != noErr || type == 0)
{
break;
}
}
else if (actualType != type)
{
if (type == 1)
{
type = actualType;
}
else
{
type = 0;
break;
}
}
}
if (type == 1) // type never got initialized (count == 0)
{
type = typeWildCard;
}
}
return type;
}
//------------------------------------------------------------------------------
/*
DescType GetUniformObjectClass(const AEDesc* list, DescType type, bool recursive)
{
DebugStr("\pGetUniformObjectClass() is not implemented yet.");
return 0;
}
*/
//------------------------------------------------------------------------------
pascal OSErr AEGetEventTarget(
const AppleEvent* event,
AEDesc* container,
/* DescType* containerClass,
*/ DescType* desiredClass,
/* DescType* keyForm,
AEDesc* keyData,
*/
long flags,
AEKeyword* psource)
{
AEKeyword source;
DescType actualType;
Size actualSize;
DescType keyword;
if (desiredClass)
{
*desiredClass = 0;
}
/*
if (keyForm)
{
*keyForm = 0;
}
if (keyData != nil)
{
keyData->descriptorType = typeNull;
keyData->dataHandle = nil;
}
*/
OSErr err = AEGetAttributeDesc(event, source = keyAEEventTargetAttr, typeWildCard, container);
if ((err == noErr && IsObjectSpecifierOrInsertion(container))
|| (err != errAEDescNotFound))
{
goto done;
}
if (flags & kOSAModeDispatchToSubject)
{
err = AEGetAttributeDesc(event, source = keySubjectAttr, typeWildCard, container);
if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
{
goto done;
}
}
if (flags & kOSAModeDispatchToDirectObject)
{
err = AEGetParamDesc(event, source = keyDirectObject, typeWildCard, container);
if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
{
goto done;
}
}
err = AEGetParamDesc(event, source = keyAEInsertHere, typeWildCard, container);
if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
{
goto done;
}
err = AEGetParamDesc(event, source = keyDirectObject, typeWildCard, container);
// there's a system coerction handler for typeFSS -> typeObjectSpecifier!!
// (so we have to do it the hard way)
if (err == noErr ? (IsObjectSpecifierOrInsertion(container)) : err != errAEDescNotFound)
{
goto done;
}
// Try the subject attribute (innermost tell block from AppleScript)
err = AEGetAttributeDesc(event, source = keySubjectAttr, typeWildCard, container);
if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
{
goto done;
}
source = 0;
done:
// now, do some post processing
if (err == noErr || err == errAEDescNotFound)
{
if (source == 0 || source == keySubjectAttr)
{
// AppleScript forgets to put a keyAEInsertHere into create events whose
// target is implied by a tell block, so we need to clean up after it
if (AEGetAttributePtr(event, keyEventClassAttr, typeType, &actualType, &keyword, sizeof(keyword), &actualSize) == noErr
&& keyword == kAECoreSuite
&& AEGetAttributePtr(event, keyEventIDAttr, typeType, &actualType, &keyword, sizeof(keyword), &actualSize) == noErr
&& keyword == kAECreateElement)
{
err = noErr;
source = keyAEInsertHere;
}
}
}
if (err == noErr)
{
// see if we have a keyAEObjectClass paramater
err = AEGetParamPtr(event, keyAEObjectClass, typeType, &actualType, &keyword, sizeof(keyword), &actualSize);
if (err != noErr)
{
keyword = 0;
}
if (source == keyAEInsertHere)
{
// if the event has an insert here param, we're going to dispatch to its container
switch (err)
{
case errAEDescNotFound:
if (desiredClass != nil) // if we've looking for a desired class and there was no keyAEObjectClass
{ // parameter then see if the DO is an object specifier
err = AESizeOfParam(event, keyDirectObject, &actualType, &actualSize);
if (err == noErr) switch (actualType)
{
case typeNull: // ObjSpec for the application
case typeAEList: // Blow off common type for the moment
*desiredClass = actualType;
break;
case typeObjectSpecifier:
{
AEDesc directObject;
err = AEGetParamDesc(event, keyDirectObject, typeAERecord, &directObject);
if (err == noErr)
{
err = AEGetParamPtr(&directObject,
keyAEDesiredClass,
typeType,
&actualType,
&keyword,
sizeof(keyword),
&actualSize);
if (err != noErr)
{
keyword = 0;
}
AEDisposeDesc(&directObject);
}
}
}
}
case noErr:
if (desiredClass != nil)
{
*desiredClass = keyword;
}
// err = AEParseInsertionLocation(container, container, keyForm, keyData, err == noErr ? nil : desiredClass);
err = noErr;
}
}
else
{
err = noErr;
// err = AEParseObjectSpecifier(container, containerClass, nil, nil, nil);
}
if (err == errAENotAnObjSpec)
{
err = errAEDescNotFound;
}
}
if (psource) *psource = err ? 0 : source; // report where we found it
return err;
}
//------------------------------------------------------------------------------
pascal OSErr AECopyParams(const AERecord *src, AERecord *dst, Boolean overwrite)
{
long srccount;
long dstcount;
OSErr err;
AERecord temp;
DescType dsttype = dst->descriptorType;
temp.dataHandle = nil;
// pre-process destination
switch (dsttype)
{
case typeNull: // accept typeNull as an empty list
dstcount = 0;
err = noErr;
break;
default: // try to coerce input to record
err = AECoerceDesc(dst, typeAERecord, &temp);
if (err == noErr)
{
*dst = temp;
temp.dataHandle = nil;
}
else
{
break;
}
case typeAERecord: // known record types
case typeAppleEvent:
err = AECountItems(dst, &dstcount);
break;
}
// pre-process destination
if (err == noErr) switch (src->descriptorType)
{
case typeNull: // accept typeNull as an empty list
srccount = 0;
err = noErr;
break;
default: // try to coerce input to record
err = AECoerceDesc(src, typeAERecord, &temp);
if (err == noErr)
{
src = &temp;
}
else
{
break;
}
case typeAERecord: // known record types
case typeAppleEvent:
err = AECountItems(src, &srccount);
break;
}
if (err == noErr)
{
if (dsttype == typeNull)
{
// Do NOT do this optimization on AppleEvent's
// dst is either a null descriptor or an empty record, so we can
// just return a copy of the input
/*
if (srccount > 0 && dst->descriptorType != typeNull)
{
// dispose of empty list unless we're returning an empty list
err = AEDisposeDesc(dst);
}
*/
if (srccount == 0)
{
// Create an empty record (if we don't have one already)
if (dst->descriptorType == typeNull)
{
err = AECreateList(nil, 0, true, dst);
}
}
else if (src == &temp)
{
// src is a temporary copy, just return it
*dst = temp;
temp.dataHandle = nil;
}
else
{
// return a copy of the input
err = TempAEDuplicateDesc(src, dst);
}
}
else
{
for (long i = 1; err == noErr && i <= srccount; i++)
{
AEKeyword keyword;
AEDesc desc;
err = AEGetNthDesc(src, i, typeWildCard, &keyword, &desc);
if (err == noErr)
{
DescType typeCode;
Size dataSize;
if (!overwrite)
{
err = AESizeOfParam(dst, keyword, &typeCode, &dataSize);
}
if (overwrite || err == errAEDescNotFound)
{
err = AEPutKeyDesc(dst, keyword, &desc);
}
AEDisposeDesc(&desc);
}
}
}
}
if (temp.dataHandle != nil) // clean up if needed
{
AEDisposeDesc(&temp);
}
return err;
}
//------------------------------------------------------------------------------
pascal long RandomInRange(long start, long end)
{
unsigned long rand = (unsigned short) Random()
+ (((unsigned long) (unsigned short) Random()) << 16);
return (((long long) (end - start + 1) * rand) >> 32) + start;
}
//------------------------------------------------------------------------------
#pragma mark -
OSErr AEBuildEventToSelf(
AppleEvent* event,
AEEventClass theAEEventClass,
AEEventID theAEEventID,
char* format, ...)
{
OSErr result;
if (format != nil)
{
static ProcessSerialNumber kCurentProcess = { 0, kCurrentProcess };
va_list ap;
va_start(ap, format);
result = vAEBuildAppleEvent(theAEEventClass, theAEEventID,
typeProcessSerialNumber, &kCurentProcess, sizeof(kCurentProcess),
kAutoGenerateReturnID, kAnyTransactionID, event,
format, ap);
va_end(ap)
}
else
{
result = AECreateAppleEvent(theAEEventClass, theAEEventID, &gSelfAddrDesc, kAutoGenerateReturnID, kAnyTransactionID, event);
}
return result;
}
//------------------------------------------------------------------------------
OSErr AESendEventToSelf(
AEEventClass theAEEventClass,
AEEventID theAEEventID,
long addition_send_flags,
AppleEvent *reply,
char* format, ...)
{
OSErr result;
AppleEvent event;
if (format != nil)
{
va_list ap;
va_start(ap, format);
result = vAEBuildAppleEvent(theAEEventClass, theAEEventID,
typeProcessSerialNumber, &kAESelfPSN, sizeof(kAESelfPSN),
kAutoGenerateReturnID, kAnyTransactionID, &event,
format, ap);
va_end(ap)
}
else
{
result = AECreateAppleEvent(theAEEventClass,
theAEEventID,
&gSelfAddrDesc,
kAutoGenerateReturnID,
kAnyTransactionID,
&event);
}
// DebugWriteAE(&event);
if (result == noErr)
{
AppleEvent loc_reply;
bool dispose_reply = (reply == nil);
AESendMode send_mode = kAECanSwitchLayer | (dispose_reply ? kAENoReply : kAEWaitReply);
if (dispose_reply)
reply = &loc_reply;
// if (record_only)
// send_mode |= kAEDontExecute;
// JimC 980227
send_mode |= addition_send_flags;
result = AESend(&event,
reply,
send_mode,
kAEHighPriority,
kNoTimeOut,
gDefaultAEIdleUPP,
gDefaultAEFilterUPP);
AEDisposeDesc(&event);
if (dispose_reply)
AEDisposeDesc(reply);
}
return result;
}
//------------------------------------------------------------------------------
OSErr AECreateEventToSelf(
AEEventClass theAEEventClass,
AEEventID theAEEventID,
AppleEvent* event,
const AEDesc* target)
{
OSErr err = AECreateAppleEvent(theAEEventClass,
theAEEventID,
&gSelfAddrDesc,
kAutoGenerateReturnID,
kAnyTransactionID,
event);
if ((err == noErr) && (target != nil))
err = AEPutParamDesc(event, keyDirectObject, target);
return err;
}
//------------------------------------------------------------------------------