Sources/MSAEMove.c

// MSAEMove.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.
 
/*
    14-Nov-95 : GS : Disposed of all interim descriptors in DoMove() and MoveTextToken().
*/
 
#include "MSAEMove.h"
 
#include "MSAEUtils.h"
#include "MSWindow.h"       // for DPtrFromWindowPtr()
#include "MSAETextUtils.h"
 
#include "MSAEDelete.h"
#include "MSAECreate.h"
#include "MSAEGetData.h"
 
 
#pragma segment AppleEvent
 
 
pascal OSErr    DoMove(const AppleEvent *theAppleEvent, AppleEvent *reply, long  handlerRefCon)
{
#ifdef __MWERKS__
    #pragma unused(handlerRefCon)
#endif
 
    AEDesc      directObj = {typeNull, NULL},
                insertHereDesc = {typeNull, NULL},
                resultDesc = {typeNull, NULL};
    OSErr       err;
 
    err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &directObj);
    if (noErr != err) goto done;
 
    err = AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeWildCard, &insertHereDesc);
    if (noErr != err) goto done;
 
        // missing any parameters?
    err = GotRequiredParams(theAppleEvent);
    if (noErr != err) goto done;
    
    err = MoveDesc(&directObj, &insertHereDesc, &resultDesc);
    if (noErr != err) goto done;
    
    err = AddResultToReply(&resultDesc, reply, err);
 
done:
    (void)AEDisposeDesc(&directObj);
    (void)AEDisposeDesc(&insertHereDesc);
    (void)AEDisposeDesc(&resultDesc);
        
    return(err);
}
 
OSErr   MoveTextToken(TextToken* token, AEDesc* insertHereDesc, AEDesc* result)
{
    TextToken       insertAtToken;
    AEDesc          dataDesc = {typeNull, NULL},
                    insertDesc = {typeNull, NULL},
                    propertyDesc = {typeNull, NULL};    // Use to pass no properties
    DescType        insertType;
    short           numPartial;
    OSErr           err;
 
                        // Get the data descriptor to insert
    err = GetTextTextProperty(token, &dataDesc);
    if (noErr != err) goto done;
 
                        // Get the place to insert it
    err = GetInsertDescFromInsertHere(insertHereDesc, &insertDesc, &insertType);
    if (noErr != err) goto done;
    
    if (typeNull == insertType)     // Default to setting the selection in the front window
        err = errAETypeError;       // GetWindowSelection(FrontWindow(), &insertAtToken, &oldLength);
    else                            // Otherwise get a selection from the insertDesc
        err = GetInsertToken(&insertDesc, insertType, &insertAtToken);
        
    if (noErr != err) goto done;
    
                        // Sort out any moving onto self scenarios
                        // and offsets changing due to deletion of where it was
    switch (TokenWithinToken(token, &insertAtToken, &numPartial))
    {
        case kTokenBefore:
                    // Do Nothing
            break;
 
        case kTokenAfter:
                    // Balance up for delete
            insertAtToken.tokenOffset -= token->tokenLength;
            break;
            
        case kTokenWithin:
                    //  tell document 1 of application "MenuScripter"
                    //      move first word to last character of first word
                    //  end tell
            insertAtToken.tokenOffset = token->tokenOffset;
            insertAtToken.tokenLength = 0;
            break;
 
        case kTokenPartialBefore:
            insertAtToken.tokenLength -= numPartial;
            break;
            
        case kTokenPartialAfter:
            insertAtToken.tokenOffset = token->tokenOffset;
            insertAtToken.tokenLength -= numPartial;
            break;
    }
    
                // Delete the text to be moved
    err = DeleteTextToken(token);
    if (noErr != err) goto done;
    
                // Secondly create the text wherever
    err = CreateAtTextToken(cText, &dataDesc, &insertAtToken, &propertyDesc, result);
    if (noErr != err) goto done;
 
done:
    (void)AEDisposeDesc(&dataDesc);
    (void)AEDisposeDesc(&insertDesc);
 
    return(err);
}
 
OSErr   MoveTextDesc(AEDesc* textDesc, AEDesc* insertHereDesc, AEDesc* result)
{
    TextToken       aTextToken;
    Size            actualSize;
    OSErr           err;
 
    if (typeMyText != textDesc->descriptorType)
        return(errAETypeError);
        
    GetRawDataFromDescriptor(textDesc, (Ptr)&aTextToken, sizeof(aTextToken), &actualSize);
    
    err = MoveTextToken(&aTextToken, insertHereDesc, result);
    
    return(err);
}
 
OSErr   MoveDesc(AEDesc* aDesc, AEDesc* insertHereDesc, AEDesc* result)
{
    AEDesc      moveDesc = {typeNull, NULL},
                textDesc = {typeNull, NULL};
    OSErr       err;
    
    if (typeObjectSpecifier == aDesc->descriptorType)
        err = AEResolve(aDesc, kAEIDoMinimum, &moveDesc);
    else if (typeNull != aDesc->descriptorType)
        err = AEDuplicateDesc(aDesc, &moveDesc);
        
    if (noErr != err) goto done;
    
    switch (moveDesc.descriptorType)
    {
        case typeAEList:
            err = errAETypeError;
            // We can't handle moving more than one item because as
            // soon as one item is moved all the rest of the tokens
            // are likely to have their offsets messed up.
            // No doubt it can be done thoughÉ
            break;
            
        default:
            err = AECoerceDesc(&moveDesc, typeMyText, &textDesc);
            if (noErr != err) goto done;
            err = MoveTextDesc(&textDesc, insertHereDesc, result);
    }
    
done:
    (void)AEDisposeDesc(&moveDesc);
    (void)AEDisposeDesc(&textDesc);
    
    return(err);
}