Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Coercions.c
/*------------------------------------------------------------------------------ |
* |
* Apple Developer Technical Support |
* |
* AppleEvent Coercion Handler and INIT sample |
* |
* Program: AECoercionINIT |
* File: Coercions.c - C Source |
* |
* by: C.K. Haun <TR> |
* |
* Copyright © 1991 Apple Computer, Inc. |
* All rights reserved. |
* |
*------------------------------------------------------------------------------ |
* This file contains the actual coercion routines, which will be BlockMoved |
* into the System Heap and installed as System Level coercions |
* at INIT time |
*------------------------------------------------------------------------------ |
*/ |
/* Our includes */ |
#include <Types.h> |
#include <memory.h> |
#include <Errors.h> |
#include <AppleEvents.h> |
#define typeMyPString 'MPST' |
/* A structure I use in my Boolean to Char coercion */ |
struct myBtoCData { |
Handle falseString; |
Handle trueString; |
}; |
typedef struct myBtoCData myBtoCData, *myBtoCDataPtr, **myBtoCDataHdl; |
/* These first two routines coerce a PString to typeChar and back */ |
/* they work on a typeMyPString, which I made up for this example */ |
/* For this example, I created a typePString. A typePString would be... */ |
/* descriptorType = 'MPST' |
dataHandle = (handle containing a Pascal-type string) */ |
pascal OSErr CoerceCharToPString(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result) |
{ |
#pragma unused (refCon) |
OSErr myErr = noErr; |
Str255 theString; |
Size newSize; |
/* This check isn't really necessary, since the AEM won't call you */ |
/* if the data types don't match, but I wanted to used the parameters */ |
/* see the Note at the end of this file for what you Can use these for */ |
if ((origData == typeChar) && (toType == typeMyPString)) { |
/* first make sure the char block isn't over a PString size. If it is, I'll */ |
/* truncate it to a PString and continue */ |
if (theSize > 255) |
newSize = 255; |
else |
newSize = theSize; |
theString[0] = newSize; |
/* Move what we were given into my string */ |
BlockMove(inPtr, (Ptr)&theString[1], newSize); |
/* Make an AppleEvent descriptor out of it */ |
myErr = AECreateDesc(typeMyPString, (Ptr)&theString[0], theString[0] + 1, result); |
} else { |
myErr = errAECoercionFail; |
} |
return(myErr); |
} |
pascal OSErr CoercePStringToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result) |
{ |
#pragma unused (origData,toType,refCon) |
OSErr myErr = noErr; |
/* This check isn't really necessary, since the AEM won't call you */ |
/* if the data types don't match, but I wanted to used the parameters */ |
/* see the Note at the end of this file for what you Can use these for */ |
if ((origData == typeMyPString) && (toType == typeChar)) { |
/* Don't have to worry about the size here, since a typeChar can be much larger */ |
/* than a PString, just make the desriptor */ |
myErr = AECreateDesc(typeChar, (Ptr)(inPtr + 1), theSize - 1, result); |
} else { |
myErr = errAECoercionFail; |
} |
return(myErr); |
} |
/* CoerceBooleanToChar creates a desc that says True or False. */ |
/* nice for human (well, non-programmer) reading */ |
/* NOTE: This coercion uses the refCon field to hold a handle */ |
pascal OSErr CoerceBooleanToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result) |
{ |
OSErr myErr = noErr; |
/* Our string data is in our refCon, (see the Install routine) */ |
/* so coerce it to something we can work with */ |
myBtoCDataHdl myStrings = (myBtoCDataHdl)refCon; |
/* make sure everything is fine first */ |
if (origData != typeBoolean || toType != typeChar) { |
/* something is goofy here */ |
myErr = errAECoercionFail; |
} else { |
/* a boolean should be two bytes. if it isn't, I'm confused */ |
if (theSize == sizeof(short)) { |
Ptr theText; |
short theBool = *((short *)inPtr); |
HLock((Handle)myStrings); |
/* I'm locking both of these even though I'll only use one */ |
/* You can count cycles and see if doing two compares (before and after) */ |
/* and one lock/unlock is faster, but I don't think it matters much */ |
HLock((*myStrings)->falseString); |
HLock((*myStrings)->trueString); |
/* decide which string we're using */ |
if (theBool) |
theText = *((*myStrings)->trueString); |
else |
theText = *((*myStrings)->falseString); |
/* And make a descriptor */ |
myErr = AECreateDesc(typeChar, (theText + 1), *theText, result); |
HUnlock((*myStrings)->falseString); |
HUnlock((*myStrings)->trueString); |
HUnlock((Handle)myStrings); |
} else { |
myErr = errAECoercionFail; |
} |
} |
return(myErr); |
} |
/* Dummy is just a placemarker so I know where the end of is. I could */ |
/* have done that a different way, but this left me some flexibility */ |
void Dummy(void) |
{ |
} |
/* ¥¥¥ Note: The AEM always passes the fromType and toType to your coercion */ |
/* routines. Why? You know you're not going to be called if the types aren't */ |
/* correct, so why bother? */ |
/* THe reason is to allow you to put all your coercions in one big function. */ |
/* You can case off them, and do everything you want in one place, instead of */ |
/* in scattered routines. */ |
/* I am _not_ doing this in this example, because I'm grabbing memory from the */ |
/* System heap to do this stuff, and the smaller I can keep the */ |
/* chuncks the more likely I am to get them low in the heap, and reduce fragmentation. */ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22