Source/SVAECountElements.c

/*
    File:       SVAECountElements.c
 
    Contains:   
 
    Written by: Original version by Jon Lansdell and Nigel Humphreys.
                3.1 updates by Greg Sutton.
 
    Copyright:  Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                7/20/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include "SVAECountElements.h"
 
#include "SVToken.h"
#include "SVEditAEUtils.h"
#include "SVAETextUtils.h"
#include "SVAEWindowUtils.h"
 
 
#pragma segment AppleEvent
 
 
// -----------------------------------------------------------------------
//  Name:       DoCountElements
//  Purpose:    Handles the Number Of Elements AppleEvent.
// -----------------------------------------------------------------------
 
pascal OSErr    DoCountElements(const AppleEvent    *theAppleEvent,
                                      AppleEvent    *reply,
                                      long          handlerRefCon)
{
#pragma unused (handlerRefCon)
 
    AEDesc      container = {typeNull, NULL},
                countDesc = {typeNull, NULL};
    DescType    desiredType;
    DescType    returnedType;
    Size        actualSize;
    OSErr       err;
    
        // pick up direct object, which is the container
        // in which things are to be counted.
    err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &container);
    if (noErr != err) goto done;
        
        // now the class of objects to be counted
    err = AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType,
                                &returnedType, (Ptr)&desiredType, sizeof(desiredType), &actualSize);
    if (noErr != err) goto done;
        
        // missing any parameters?
    err = GotRequiredParams(theAppleEvent);
    if (noErr != err) goto done;
    
        // now get descriptor for count - put through function that
        // can handle lists.
    err = GetDescForNumberOfElements(desiredType, &container, &countDesc);
    
    err = AddResultToReply(&countDesc, reply, err);
 
done:
    if (container.dataHandle)
        AEDisposeDesc(&container);
    
    return(err);
} // DoCountElements
 
 
OSErr   GetDescForNumberOfElements(DescType desiredType, AEDesc* container, AEDesc* result)
{
    long        itemCount,
                index,
                elementCount;
    AEDesc      tempDesc = {typeNull, NULL},
                aDesc = {typeNull, NULL},
                resultDesc = {typeNull, NULL};
    DescType    returnedType;
    OSErr       err;
    
            // If it's an object specifier, resolve into a token
    if (typeObjectSpecifier == container->descriptorType)
        err = AEResolve(container, kAEIDoMinimum, &tempDesc);
    else    // Otherwise, just copy it
        err = AEDuplicateDesc(container, &tempDesc);
 
    if (noErr != err) goto done;
 
    if (typeAEList == tempDesc.descriptorType)
    {
        err = AECreateList(NULL, 0 , false, result);    // Result will also be a list of items
        if (noErr != err) goto done;
        err = AECountItems(&tempDesc, &itemCount);
        if (noErr != err) goto done;
 
        for (index = 1; index <= itemCount; index++)    // Do in forward order
        {
            err = AEGetNthDesc(&tempDesc, index, typeWildCard, &returnedType, &aDesc);
 
            if (noErr == err)       // Call this function recursively if necessary
                err = GetDescForNumberOfElements(desiredType, &aDesc, &resultDesc);
            
            if (noErr == err)       // Add item to the end of our list
                err = AEPutDesc(result, 0, &resultDesc);
            
            if (aDesc.dataHandle)
                AEDisposeDesc(&aDesc);
            if (resultDesc.dataHandle)
                AEDisposeDesc(&resultDesc);
        }
    }
    else
    {
        err = MyCountProc(desiredType, tempDesc.descriptorType, &tempDesc, &elementCount);
        if (noErr != err) goto done;
        err = AECreateDesc(typeLongInteger, (Ptr)&elementCount, sizeof(elementCount), result);
    }
 
done:
    if (aDesc.dataHandle)
        AEDisposeDesc(&aDesc);
    if (resultDesc.dataHandle)
        AEDisposeDesc(&resultDesc);
 
    return(err);
}
 
 
// This count procedure is installed along with MyCaompareProc() to support
// formTest and formWhose.
 
pascal OSErr MyCountProc(DescType desiredType, DescType containerClass,
                                        const AEDesc *container, long* result)
{   
    AEDesc      aDesc = {typeNull, NULL},
                tempDesc = {typeNull, NULL};
    TextToken   aTextToken;
    Size        actualSize;
    short       shortResult;
    OSErr       err;
        
            // If it's an object specifier, resolve into a token
    if (typeObjectSpecifier == container->descriptorType)
        err = AEResolve(container, kAEIDoMinimum, &tempDesc);
    else    // Otherwise, just copy it
        err = AEDuplicateDesc(container, &tempDesc);
        
    if (noErr != err) goto done;
    
    *result = -1;           // easily recognized illegal value
        
    switch (desiredType)
    {
        case cDocument:
        case cWindow:
            if ((containerClass == typeNull) || (containerClass == cApplication))
                *result = CountWindows();
            else
                err = errAEWrongDataType;
            break;
            
        case cChar:
        case cWord:
        case cParagraph:
            err = AECoerceDesc(&tempDesc, typeMyText, &aDesc);
            if (typeNull == aDesc.descriptorType)
                err = errAENoSuchObject;
            if (noErr != err) break;
            GetRawDataFromDescriptor(&aDesc, (Ptr)&aTextToken, sizeof(aTextToken), &actualSize);
 
            err = CountTextElements(TEHandleFromTextToken(&aTextToken),
                                        aTextToken.tokenOffset, aTextToken.tokenLength,
                                                                    desiredType, &shortResult);
            if (noErr != err) break;
            *result = shortResult;
            break;
            
        default:
            err = errAECantHandleClass;
    }
    
done:
    if (tempDesc.dataHandle)
        AEDisposeDesc(&tempDesc);
    if (aDesc.dataHandle)
        AEDisposeDesc(&aDesc);
        
    return(err);
}   // MyCountProc