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.
InstallCoercions.c
/*------------------------------------------------------------------------------ |
* |
* Apple Developer Technical Support |
* |
* AppleEvent Coercion Handler and INIT sample |
* |
* Program: AECoercionINIT |
* File: InstallCoercions.c - C Source |
* |
* by: C.K. Haun <TR> |
* |
* Copyright © 1991 Apple Computer, Inc. |
* All rights reserved. |
* |
*------------------------------------------------------------------------------ |
* This file contains the coercion installing routine. |
* This will get called by our assembly stub at INIT 31 time. |
* Here we get space in the System Heap for our coercions (System level coercions MUST |
* be in the system heap) and move the code to the sys heap, then tell the |
* AppleEvent manager about the coercions. |
* For my BoolToChar, I also grab some resources from my INIT file, since it's |
* open now. |
* Of course, please read the section on coercion routines in Inside Mac VI, AppleEvents |
*------------------------------------------------------------------------------ |
*/ |
/* our includes */ |
#include <Types.h> |
#include <memory.h> |
#include <Resources.h> |
#include <toolutils.h> |
#include <AppleEvents.h> |
#include <GestaltEqu.h> |
#include <Errors.h> |
/* externs defining the coercion routines in Coercions.c */ |
extern pascal OSErr CoerceCharToPString(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result); |
extern pascal OSErr CoercePStringToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result); |
extern pascal OSErr CoerceBooleanToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result); |
extern void Dummy(void); |
/* my special AE data type */ |
#define typeMyPString 'MPST' |
/* resource IDs for my strings */ |
#define kFalseString 128 |
#define kTrueString 129 |
/* For this example, I created a typePString. A typePString would be... */ |
/* descriptorType = 'MPST' |
dataHandle = (handle containing a Pascal-type string) */ |
/* A structure I use for my BoolToChar coercion */ |
struct myBtoCData { |
Handle falseString; |
Handle trueString; |
}; |
typedef struct myBtoCData myBtoCData, *myBtoCDataPtr, **myBtoCDataHdl; |
/* This code installs all our coercion routines */ |
/* Also, I'm checking to see if there is already a converter for this type, if there */ |
/* is (unlikely) I do not replace it. You may want to install a hander even if */ |
/* there is already one there, or rather you may want */ |
/* to chain to it after you've done your work. I would put the old coercion */ |
/* proc pointer in the RefCon when I install my coercer, so It will always be passed */ |
/* to me, since I'm not allocating any global storage in this example */ |
OSErr cInstall(void) |
{ |
OSErr myErr; |
OSErr installErr; |
long aLong; |
Ptr functionStart, functionEnd, newLocation; |
ProcPtr oldHandler; |
long oldRefCon; |
Boolean typeIsDesc; |
myBtoCDataHdl stringData; |
/* First thing we have to do is see if AppleEvents are installed on this machine */ |
/* if they are NOT, then we bail out fast. Or at least at 8 Mhz */ |
/* unless we're on a PowerBook in slowdown mode, then it's slower. But anyway */ |
/* fast enough */ |
myErr = Gestalt(gestaltAppleEventsAttr, &aLong); |
if (!myErr) { |
/* we're OK, the manager is installed */ |
/* install the first one. Remember, you can pass any number in the refCon */ |
/* field during installs, that number will always get passed to your */ |
/* coercion routine. It could be a procptr if your chaining, or it could */ |
/* be a handle if you want some permenent storage */ |
/* First check to see if there is one already, unlikely as all get out */ |
installErr = AEGetCoercionHandler(typeChar, typeMyPString, &oldHandler, &oldRefCon, &typeIsDesc, true); |
/* check the error. If the handler isn't there, we'll install our own */ |
/* if it is there, we don't. You may want to, if you want to add */ |
/* a handler where one already exsists, PLEASE keep the information */ |
/* about the old one, and chain to it when you're through. See the AEM */ |
/* chapter for more details */ |
if ((installErr == errAEHandlerNotFound)) { |
/* Get a pointer for this coercion */ |
functionStart = (Ptr)CoerceCharToPString; |
functionEnd = (Ptr)CoercePStringToChar; |
newLocation = NewPtrSys(functionEnd - functionStart); |
installErr = noErr; |
if (newLocation) { |
BlockMove(functionStart, newLocation, (functionEnd - functionStart)); |
/* Install my handler. Remember, you can pass any longint in the refCon */ |
/* field here (I've left it nil) and that number will be passed to your coercion */ |
/* routine anytime it's called. Maybe you want to allocate a handle */ |
/* and keep data in it, or something like that */ |
/* see the BoolToChar coercion for an example of this */ |
installErr = AEInstallCoercionHandler(typeChar, typeMyPString, (ProcPtr)newLocation, nil, false, true); |
} |
if (installErr) |
DisposPtr(newLocation); |
} |
installErr = AEGetCoercionHandler(typeMyPString, typeChar, &oldHandler, &oldRefCon, &typeIsDesc, true); |
if ((installErr == errAEHandlerNotFound)) { |
functionStart = (Ptr)CoercePStringToChar; |
functionEnd = (Ptr)CoerceBooleanToChar; |
newLocation = NewPtrSys(functionEnd - functionStart); |
installErr = noErr; |
if (newLocation) { |
BlockMove(functionStart, newLocation, (functionEnd - functionStart)); |
installErr = AEInstallCoercionHandler(typeMyPString, typeChar, (ProcPtr)newLocation, nil, false, true); |
} |
if (installErr) |
DisposPtr(newLocation); |
} |
/* This one is a bit more interesting, because I need some additional resources */ |
/* to make it work, two text strings. I will create a handle to hold these, */ |
/* and pass that handle in the refCon so I always get it when I do the coercion */ |
installErr = AEGetCoercionHandler(typeBoolean, typeChar, &oldHandler, &oldRefCon, &typeIsDesc, true); |
if ((installErr == errAEHandlerNotFound)) { |
functionStart = (Ptr)CoerceBooleanToChar; |
functionEnd = (Ptr)Dummy; |
newLocation = NewPtrSys(functionEnd - functionStart); |
installErr = noErr; |
if (newLocation) { |
/* we got the memory for the routine, now can we get the memory for the */ |
/* strings and the strings themselves??? */ |
stringData = (myBtoCDataHdl)NewHandleSys(sizeof(myBtoCData)); |
if (stringData) { |
HLock((Handle)stringData); /* get the resources, if possible */ |
/* ¥¥¥ CAUTION ¥¥¥ CAUTION ¥¥¥ */ |
/* These resources MUST be in the System heap! */ |
/* I have made sure of this by marking them as "sysheap" */ |
/* in their resource attributes, please see the AECoerceINIT.r file. */ |
/* You can do this, or move them to the system heap after you have */ |
/* loaded them. You MUST have them in the system heap! */ |
/* If you don't mark them as "sysheap", or don't */ |
/* move them yourself, then they will be in this */ |
/* installer INIT heap, which will go away */ |
/* when this INIT is finished, and the resources will also */ |
/* go away! */ |
/* If you want resources to stay around from an INIT, */ |
/* make sure they're in the system heap!!!!! */ |
(*stringData)->falseString = GetResource('STR ', kFalseString); |
if (!ResError() && (*stringData)->falseString) { |
/* remove any resource references to this handle, and */ |
/* make sure it won't get purged */ |
DetachResource((*stringData)->falseString); |
HNoPurge((*stringData)->falseString); |
(*stringData)->trueString = GetResource('STR ', kTrueString); |
if (!ResError() && (*stringData)->trueString) { |
/* remove any resource references to this handle, and */ |
/* make sure it won't get purged */ |
DetachResource((*stringData)->trueString); |
HNoPurge((*stringData)->trueString); |
/* Got our strings */ |
HUnlock((Handle)stringData); |
BlockMove(functionStart, newLocation, (functionEnd - functionStart)); |
installErr = AEInstallCoercionHandler(typeBoolean, typeChar, (ProcPtr)newLocation, (long)stringData, |
false, true); |
if (installErr) { |
/* Had an error installing the coercion */ |
/* kill the memory for our resources */ |
DisposHandle((*stringData)->falseString); |
DisposHandle((*stringData)->trueString); |
DisposHandle((Handle)stringData); |
} |
} else { |
/* Couldn't get the 'true' string, stop the process */ |
/* and release the memory we had gotten */ |
DisposHandle((*stringData)->falseString); |
DisposHandle((Handle)stringData); |
installErr = -9; |
} |
} else { |
/* couldn't get the false string, installation failed */ |
DisposHandle((Handle)stringData); |
installErr = -9; |
} |
} |
} else { |
/* string handle error */ |
installErr = memFullErr; |
} |
if (installErr) |
DisposPtr(newLocation); |
} |
} |
return(myErr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22