Blame | Last modification | View Log | Download | RSS feed
/*WASTE Demo Project:Macintosh Controls with Long ValuesCopyright © 1993-1998 Marco PiovanelliAll Rights ReservedC port by John C. Daub*/#ifndef __AEOBJECTS__#include <AEObjects.h>#endif#ifndef __AEREGISTRY__#include <AERegistry.h>#endif#ifndef __WEDEMOAPP__#include "RIntf.h"#endifenum{kMaxPropLevel = 2} ;typedef DescType PropArray[kMaxPropLevel];void InitDesc ( AEDesc * desc ){desc->descriptorType = typeNull;desc->dataHandle = nil;}OSStatus GetAEDescDataAsHandle ( const AEDesc * inDesc, Handle * outData ){Size dataSize ;Handle dataHandle ;OSStatus err ;* outData = nil ;// do nothing if inDesc is a null descriptorif ( ( inDesc->descriptorType == typeNull ) || ( inDesc->dataHandle == nil ) ){return noErr ;}// get data sizedataSize = AEGetDescDataSize ( inDesc ) ;// allocate a handle this sizedataHandle = NewHandle ( dataSize ) ;if ( ( err = MemError ( ) ) != noErr ){goto cleanup ;}// fill the handleHLock ( dataHandle ) ;err = AEGetDescData ( inDesc, *dataHandle, dataSize ) ;HUnlock ( dataHandle ) ;* outData = dataHandle ;cleanup :if ( err != noErr ){ForgetHandle ( outData ) ;}// return error codereturn err ;}static Boolean PropertyOf ( const AERecord * spec, SInt16 * propLevel, PropArray properties ){AERecord objSpec;AEKeyword key;DescType theType;DescType actualType;Size actualSize;Boolean retVal = false;InitDesc(&objSpec);// if spec is an Apple event (*propLevel = 0), extract its direct parameter// otherwise spec is an object specifier record: extract its container paramkey = (*propLevel == 0) ? keyDirectObject : keyAEContainer;// extract object specifierif (AEGetParamDesc(spec, key, typeAERecord, &objSpec) != noErr)goto cleanup;// does this object specifier specify a property?if (AEGetParamPtr(&objSpec, keyAEDesiredClass, typeType, &actualType,&theType, sizeof(theType), &actualSize) != noErr)goto cleanup;// sanity check: make sure the key form is formPropertyID// this is probably redundant, but checking doesn't hurtif (AEGetParamPtr(&objSpec, keyAEKeyForm, typeEnumerated, &actualType,&theType, sizeof(theType), &actualSize) != noErr)goto cleanup;if (theType != formPropertyID)goto cleanup;// which property does this object specifier specify?if (AEGetParamPtr(&objSpec, keyAEKeyData, typeType, &actualType,&theType, sizeof(theType), &actualSize) != noErr)goto cleanup;// bump property level and save property tag into property arrayproperties[(*propLevel)++] = theType;// property of what?if (AESizeOfParam(&objSpec, keyAEContainer, &actualType, &actualSize) == noErr)if (actualType == typeNull)// property of application (i.e., null container): we are doneretVal = true;else if ((actualType == typeObjectSpecifier) && (*propLevel < kMaxPropLevel))// property of another object, so do a recursive call// unless we have already reached max recursion depthretVal = PropertyOf(&objSpec, propLevel, properties);cleanup:AEDisposeDesc(&objSpec);return retVal;}OSStatus GetContentsOfSelection ( DescType requestedType, AEDesc * desc, WEReference we ){Handle dataHandle = nil ;OSStatus err;// allocate a handle to hold the contents datadataHandle = NewHandle(0);if ((err = MemError()) != noErr){goto cleanup;}// get the text for the specified rangeif ((err = WEStreamRange(kCurrentSelection, kCurrentSelection, requestedType, 0, dataHandle, we )) != noErr){goto cleanup ;}// create the AE descriptorHLock(dataHandle);err = AECreateDesc(requestedType, *dataHandle, GetHandleSize(dataHandle), desc);HUnlock(dataHandle);if (err != noErr){goto cleanup ;}// clear result codeerr = noErr;cleanup:ForgetHandle(&dataHandle);// return result codereturn err;}OSStatus SetContentsOfSelection ( const AEDesc * desc, WEReference we ){Handle textHandle = nil ;Handle stylesHandle = nil ;AEDesc textDesc ;AEDesc stylesDesc ;AEDesc recordDesc ;OSStatus err ;InitDesc(&textDesc);InitDesc(&stylesDesc);InitDesc(&recordDesc);// we expect desc type to be either TEXT or STXTif (desc->descriptorType == typeStyledText){// STYLED TEXT// coerce the styled text descriptor to an Apple event recordif ((err = AECoerceDesc(desc, typeAERecord, &recordDesc)) != noErr)goto cleanup;// extract text + styles from the recordif ((err = AEGetParamDesc(&recordDesc, keyAEText, typeChar, &textDesc)) != noErr)goto cleanup;if ((err = AEGetParamDesc(&recordDesc, keyAEStyles, typeScrapStyles, &stylesDesc)) != noErr)goto cleanup;}else{// UNSTYLED TEXTif ((err = AECoerceDesc(desc, typeChar, &textDesc)) != noErr)goto cleanup;}// get data handles from descsif ((err = GetAEDescDataAsHandle(&textDesc, &textHandle)) != noErr){goto cleanup ;}if ((err = GetAEDescDataAsHandle(&stylesDesc, &stylesHandle)) != noErr){goto cleanup;}// replace the specified range with the given textHLock(textHandle);err = WEInsert(*textHandle, GetHandleSize(textHandle), (StScrpHandle) stylesHandle, nil, we);HUnlock(textHandle);// clear result codeerr = noErr;cleanup:AEDisposeDesc(&recordDesc);AEDisposeDesc(&textDesc);AEDisposeDesc(&stylesDesc);ForgetHandle(&textHandle);ForgetHandle(&stylesHandle);return err;}static pascal OSErr HandleGetData(const AppleEvent *ae, AppleEvent *reply, UInt32 refCon){#pragma unused (refCon)AEDesc textDesc;DocumentHandle hDocument;SInt16 propLevel = 0;PropArray properties;FlavorType requestedType;DescType actualType;Size actualSize;OSStatus err;InitDesc(&textDesc);// the only Apple event object we recognize is "contents of selection"err = errAENoSuchObject;if (!PropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||(properties[0] != pContents) || (properties[1] != pSelection)){goto cleanup;}// extract the optional parameter keyAERequestedType, if present// The Apple Event Registry says this parameter can be a list// of type tags, but in most cases it is just a single tag, as we assume here.if (AEGetParamPtr(ae, keyAERequestedType, typeType, &actualType,&requestedType, sizeof(requestedType), &actualSize) != noErr){requestedType = kTypeText; // return raw TEXT by default}// make sure there is a document window in fronterr = errAENoUserSelection;if ((hDocument = GetWindowDocument(FrontWindow())) == nil){goto cleanup;}// create an Apple event descriptor for the selected textif ((err = GetContentsOfSelection(requestedType, &textDesc, (*hDocument)->we)) != noErr){goto cleanup;}// put the text descriptor into the reply eventif ((err = AEPutParamDesc(reply, keyDirectObject, &textDesc)) != noErr){goto cleanup;}// clear result codeerr = noErr;cleanup:AEDisposeDesc(&textDesc);return err;}static pascal OSErr HandleSetData(const AppleEvent *ae, AppleEvent *reply, UInt32 refCon){#pragma unused (reply, refCon)AEDesc textDesc;DocumentHandle hDocument;SInt16 propLevel = 0;PropArray properties;OSStatus err;InitDesc(&textDesc);// the only Apple event object we recognize is "contents of selection"err = errAENoSuchObject;if (!PropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||(properties[0] != pContents) || (properties[1] != pSelection)){goto cleanup;}// make sure there is a document window in fronterr = errAENoUserSelection;if ((hDocument = GetWindowDocument(FrontWindow())) == nil){goto cleanup;}// extract the required keyAEData parameterif ((err = AEGetParamDesc(ae, keyAEData, typeWildCard, &textDesc)) != noErr)goto cleanup;// set the contents of the selectionif ((err = SetContentsOfSelection(&textDesc, (*hDocument)->we)) != noErr){goto cleanup;}// clear result codeerr = noErr;cleanup:AEDisposeDesc(&textDesc);return err;}OSStatus InstallCoreHandlers(void){OSStatus err;if ((err = AEInstallEventHandler(kAECoreSuite, kAEGetData,NewAEEventHandlerProc(HandleGetData), 0L, false)) != noErr){return err;}if ((err = AEInstallEventHandler(kAECoreSuite, kAESetData,NewAEEventHandlerProc(HandleSetData), 0L, false)) != noErr){return err;}return noErr;}