Sources/MSAECoercions.c

// MSAECoercions.c
//
// Original version by Jon Lansdell and Nigel Humphreys.
// 4.0 and 3.1 updates by Greg Sutton.
// ©Apple Computer Inc 1996, all rights reserved.
 
/*
    Changes for 4.0
    
    29-Feb-96 : GS : Added coercion of document to window.
    29-Feb-96 : GS : Changed coercion of window to text to document to text.
*/
 
#include "MSAECoercions.h"
 
#include "MSAEUtils.h"
#include "MSAETextUtils.h"
 
#include "MSAccessors.h"
#include "MSAESelect.h"
#include "MSToken.h"
 
 
#pragma segment AppleEvent
 
// Install coercion handlers that coerce a descriptor from one type to another.
 
OSErr   InstallCoercions(void)
{
    OSErr   err;
 
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyAppl,      (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyWndw,      (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyDocument,  (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyText,      (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyTextProp,  (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyWindowProp,(AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
    err = AEInstallCoercionHandler(typeObjectSpecifier, typeMyApplProp,  (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceObjToAnything), 0, true, false);
 
    err = AEInstallCoercionHandler(typeMyDocument, typeMyWndw,  (AECoercionHandlerUPP)NewAECoercePtrProc(CoerceDocumentToWindow), 0, false, false);
 
    err = AEInstallCoercionHandler(typeMyDocument, typeMyText,  (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceDocumentToText), 0, true, false);
    err = AEInstallCoercionHandler(typeMyDocumentProp, typeMyText,  (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceDocumentPropertyToText), 0, true, false);
 
    return(err);
}
 
 
// Takes an object specifier that it resolves using AEResolve
// then tries to coerce this result into the type specified by toType.
 
pascal OSErr    CoerceObjToAnything(const AEDesc    *theAEDesc,
                                    DescType        toType,
                                    long            handlerRefCon,
                                    AEDesc          *result)
{
#ifdef __MWERKS__
    #pragma unused (handlerRefCon)
#endif
 
    AEDesc  objDesc = {typeNull, NULL};
    OSErr   err;    
    
    if (theAEDesc->descriptorType != typeObjectSpecifier)
        return(errAEWrongDataType);
    
        // resolve the object specifier
    err = AEResolve(theAEDesc, kAEIDoMinimum, &objDesc);
    if (noErr != err) goto done;
        
        // hopefully it's the right type by now, but we'll give it a nudge
    err = AECoerceDesc(&objDesc, toType, result);
 
done:
    if (objDesc.dataHandle)
        AEDisposeDesc(&objDesc);
            
    return(err);
}   // CoerceObjToAnything
 
 
// A document is effectively a text item that contains all the text in the document
// so allow coercion of documents to text.
 
pascal OSErr    CoerceDocumentToText(AEDesc *theAEDesc,
                                    DescType        toType,
                                    long            handlerRefCon,
                                    AEDesc          *result)
{
#ifdef __MWERKS__
    #pragma unused (toType, handlerRefCon)
#endif
    
    return(TextDescFromDocumentDesc(theAEDesc, result));
}
 
// Some document properties are effectively text so allow a coercion
// e.g. set selection of document 1 to "Something"
 
pascal OSErr    CoerceDocumentPropertyToText(AEDesc     *theAEDesc,
                                            DescType    toType,
                                            long        handlerRefCon,
                                            AEDesc      *result)
{
#ifdef __MWERKS__
    #pragma unused (toType, handlerRefCon)
#endif
    
    WindowPropToken     aWindowPropToken;
    TextToken           aTextToken;
    Size                actualSize;
    short               ignore;
    OSErr               err;
 
    GetRawDataFromDescriptor(theAEDesc, (Ptr)&aWindowPropToken,
                                        sizeof(aWindowPropToken), &actualSize);
    
    switch (aWindowPropToken.tokenProperty)
    {
        case pText:
        case pContents:
            err = TextDescFromDocumentToken(&(aWindowPropToken.tokenWindowToken), result);
            break;
 
        case pSelection:
            err = GetWindowSelection(aWindowPropToken.tokenWindowToken.tokenWindow,
                                                                    &aTextToken, &ignore);
            if (noErr != err) goto done;
            
            err = AECreateDesc(typeMyText, (Ptr)&aTextToken, sizeof(aTextToken), result);
            break;
            
        default:            // Most properties don't make sense to be coerced from
            err = errAECoercionFail;
    }                       // e.g 'select insertion point before bounds of document 1'
    
done:   
    return(err);
}
 
 
// Many actions are the same whether a window or a document e.g. close
//  so allow a document to be coerced back to a window.
 
pascal OSErr    CoerceDocumentToWindow( DescType    typeCode,
                                        Ptr         dataPtr,
                                        Size        dataSize,
                                        DescType    toType,
                                        long        handlerRefcon,
                                        AEDesc*     result )
{
#ifdef __MWERKS__
    #pragma unused ( handlerRefcon )
#endif
 
    OSErr   err;
    
    if ( typeMyDocument == typeCode && typeMyWndw == toType )
        err = AECreateDesc( typeMyWndw, dataPtr, dataSize, result );
    else
        err = errAEWrongDataType;
    
    return err;
}