Sources/MSAEClose.c

// MSAEClose.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
 
    28-Feb-96 : GS : Added differentiation between windows and documents.
*/
 
#include "MSAEClose.h"
 
#include "MSAEUtils.h"
#include "MSWindow.h"       // for DPtrFromWindowPtr()
#include "MSFile.h"         // for DoClose()
 
 
#pragma segment AppleEvent
 
 
pascal OSErr DoCloseWindow(const AppleEvent     *theAppleEvent,
                                AppleEvent      *reply,
                                long            handlerRefCon)
{
#ifdef __MWERKS__
    #pragma unused (reply, handlerRefCon)
#endif
 
    AEDesc          directObj = {typeNull, NULL};
    DescType        saveOpt;
    Size            actualSize;
    DescType        returnedType;
    WindowToken     aWindowToken;
    OSErr           err;
    
        // pick up the direct object, which is the object (window) to close or a list of windows
    err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &directObj);
                
        // pick up optional save param, if any
    saveOpt = kAEAsk;   // the default
    err = AEGetParamPtr(theAppleEvent, keyAESaveOptions, typeEnumerated, 
                            &returnedType, (Ptr)&saveOpt, sizeof(saveOpt), &actualSize);
                                                     
    err = GotRequiredParams(theAppleEvent);
    if (noErr != err) goto done;
    
    if (typeNull != directObj.descriptorType)
        err = CloseDesc(&directObj, saveOpt);
    else if ( FrontWindow() )                   // Default to front window if
    {                                           // no direct object.
        aWindowToken.tokenWindow = FrontWindow();
        err = CloseWindowToken(&aWindowToken, saveOpt);
    }
    else
        err = errAENoSuchObject;
 
done:
    if (directObj.dataHandle) 
        AEDisposeDesc(&directObj);
            
    return(err);
}   // DoCloseWindow
 
 
OSErr   CloseWindowToken(WindowToken* theToken, DescType saveOpt)
{
    WindowPtr       aWindow;
    DPtr            docPtr;
    OSErr           err;
    
    aWindow = theToken->tokenWindow;
    docPtr = DPtrFromWindowPtr( theToken->tokenWindow );
    
    if ( ! aWindow )
        return errAENoSuchObject;
 
        // Should do this in prefs
    err = AESetInteractionAllowed( kAEInteractWithAll );
    if ( noErr != err ) goto done;
    
    if ( docPtr )   // May be other kind of window
    {
            //  We do some of the close checks here to avoid
            //  calling AEInteractWithUser
        if ( docPtr->dirty || ( docPtr->everSaved == false ) ) 
            if ( saveOpt != kAENo ) // Don't flip layers if force no ask
                err = AEInteractWithUser( kAEDefaultTimeout, NULL, NULL );
    }
 
    if ( noErr != err ) goto done;
        
    err = DoClose( aWindow, true, saveOpt );
    
    if ( userCanceledErr == err )   // Don't put up an error if only cancelled
        err = noErr;
 
done:       
    return err;
}
 
 
OSErr   CloseWindowDesc(AEDesc* windowDesc, DescType saveOpt)
{
    WindowToken     aWindowToken;
    Size            actualSize;
    OSErr           err;
 
    if (typeMyWndw != windowDesc->descriptorType)
        return errAETypeError ;
        
    GetRawDataFromDescriptor(windowDesc, (Ptr)&aWindowToken, sizeof(aWindowToken), &actualSize);
 
    err = CloseWindowToken(&aWindowToken, saveOpt);
    
    return(err);
}
 
 
OSErr   CloseDesc(AEDesc* aDesc, DescType saveOpt)
{
    AEDesc      closeDesc = {typeNull, NULL},
                windowDesc = {typeNull, NULL},
                itemDesc = {typeNull, NULL};
    long        itemCount,
                index;
    DescType    theAEKeyword;
    OSErr       err;
    
    if ( typeObjectSpecifier == aDesc->descriptorType )
        err = AEResolve(aDesc, kAEIDoMinimum, &closeDesc);
    else if ( typeNull != aDesc->descriptorType )
        err = AEDuplicateDesc(aDesc, &closeDesc);
        
    if (noErr != err) goto done;
    
    switch (closeDesc.descriptorType)
    {
        case typeAEList:
            err = AECountItems(&closeDesc, &itemCount);
            if (noErr != err) goto done;
            
            for (index = 1; index <= itemCount; index++)    // Do front back order
            {
                err = AEGetNthDesc(&closeDesc, index, typeWildCard, &theAEKeyword, &itemDesc);
                if (noErr != err) goto done;
                
                err = CloseDesc(&itemDesc, saveOpt);        // Call recursively
                if (noErr != err) goto done;
 
                (void)AEDisposeDesc(&itemDesc);
            }
            break;
            
        default:    // Can coerce a document to a window
            err = AECoerceDesc(&closeDesc, typeMyWndw, &windowDesc);
            if (noErr != err) goto done;
            err = CloseWindowDesc(&windowDesc, saveOpt);
    }
    
done:
    (void)AEDisposeDesc(&closeDesc);
    (void)AEDisposeDesc(&windowDesc);
    (void)AEDisposeDesc(&itemDesc);
    
    return(err);
}