Source/SVAESetData.c

/*
    File:       SVAESetData.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 "SVAESetData.h"
 
#include "SVEditWindow.h"
#include "SVEditGlobals.h"
#include "SVEditAEUtils.h"
#include "SVAETextUtils.h"
#include "SVAppleEvents.h"
 
#include "SVAESelect.h"
#include "SVAECreate.h"
 
#include <string.h>
#include <TextUtils.h>
#include <DriverServices.h>
 
 
// --------------------------------------------------------------------------
//  Name:           DoSetData
//  Purpose:        Handles the SetData Apple Event, extracting the direct
//                  object (which says what to set) and the data (what to set
//                  it to).
// --------------------------------------------------------------------------
     
pascal OSErr    DoSetData(const AppleEvent  *theAppleEvent,
                                AppleEvent  *reply,
                                long        handlerRefCon)
{
#pragma unused (reply, handlerRefCon)
    
    AEDesc  directObj = {typeNull, NULL},
            dataDesc = {typeNull, NULL};
    OSErr   err;
            
        // pick up the direct object, which is the object whose data is to be set
    err = AEGetParamDesc(theAppleEvent,  keyDirectObject,
                                    typeWildCard, &directObj);
    if (noErr != err) goto done;
        
        // now the data to set it to - typeWildCard means get as is
        // e.g. this is the name of the font for text
    err = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &dataDesc);
    if (noErr != err) goto done;
    
        // missing any parameters?
    err = GotRequiredParams(theAppleEvent);
    if (noErr != err) goto done;
    
        // set the data
    err = HandleSetData(&directObj, &dataDesc);
 
done:           
    if (directObj.dataHandle)
        AEDisposeDesc(&directObj);
    if (dataDesc.dataHandle)
        AEDisposeDesc(&dataDesc);
 
    return(err);
}   // DoSetData
 
 
// ---------------------------------------------------------------------------
//      Name:           HandleSetData
//      Purpose:        Resolves the object into a token (could be one of 
//                      many) andthe sets the data of that object to dataDesc.
// ---------------------------------------------------------------------------
     
OSErr HandleSetData(const AEDesc *theObj, AEDesc *dataDesc)
{
    TextToken       theTextToken;
    Size            tokenSize;
    AEDesc          objTokenDesc = {typeNull, NULL},
                    itemDesc = {typeNull, NULL},
                    ignoreResult = {typeNull, NULL};
    long            index;
    DescType        returnedType;
    OSErr           err;
 
        //  Coerce theObj into a token which we can use - 
        //       set the property or data for that token
    if (typeObjectSpecifier == theObj->descriptorType)
        err = AEResolve(theObj, kAEIDoMinimum, &objTokenDesc);
    else    // Otherwise, just copy it
        err = AEDuplicateDesc(theObj, &objTokenDesc);
 
    if (noErr != err) goto done;
            
    switch (objTokenDesc.descriptorType)
    {
        case typeMyWindowProp:
            err = DoSetWindowProperty(&objTokenDesc, dataDesc);
            break;
        
        case typeMyTextProp:
            err = SetTextProperty(&objTokenDesc, dataDesc);
            break;
            
        case typeMyText:
            GetRawDataFromDescriptor(&objTokenDesc,  (Ptr)&theTextToken,
                                            sizeof(theTextToken), &tokenSize);
            
                        // itemDesc is a null descriptor here
            err = CreateAtTextToken(cText, dataDesc, &theTextToken,
                                                    &itemDesc, &ignoreResult);
            break;
 
        case typeAEList:                // If it's a list then do each item
            err = AECountItems(&objTokenDesc, &index);
            if (noErr != err) goto done;
 
            for (; index > 0; index--)
            {
                err = AEGetNthDesc(&objTokenDesc, index, typeWildCard, &returnedType, &itemDesc);
 
                if (noErr == err)       // Get property by calling this function again
                    err = HandleSetData(&itemDesc, dataDesc);
                
                if (itemDesc.dataHandle)
                    AEDisposeDesc(&itemDesc);
            }
            break;
            
        default:
            err = errAEWrongDataType;
    }
 
done:
    if (objTokenDesc.dataHandle)    
        AEDisposeDesc(&objTokenDesc);
    if (itemDesc.dataHandle)    
        AEDisposeDesc(&itemDesc);
    if (ignoreResult.dataHandle)
        AEDisposeDesc(&ignoreResult);
 
    return(err);
} // HandleSetData
 
 
OSErr   SetWindowSelectionProperty(WindowPtr theWindow, const AEDesc *dataDesc)
{
    AEDesc      textDesc = {typeNull, NULL},
                ignoreResult = {typeNull, NULL};
    TextToken   aTextToken;
    Size        actualSize;
    short       ignore;
    OSErr       err;
        
    // first check to see if we are dealing with a TEXT descriptor or
    // an object specifier. Since AECoerceDesc will end up calling
    // AEResolve, we don't want to call this if the user entered something
    // like 'Set selection of window 1 to "some text '
 
    switch (dataDesc->descriptorType)
    {
        case typeChar:
        case typeIntlText:
        case typeStyledText:
            err = GetWindowSelection(theWindow, &aTextToken, &ignore);
            if (noErr != err) goto done;
 
                        // textDesc is a null descriptor here
            err = CreateAtTextToken(cText, dataDesc, &aTextToken,
                                                    &textDesc, &ignoreResult);
            break;
            
        default:     // we are dealing with an object specifier
            err = AECoerceDesc(dataDesc, typeMyText, &textDesc);
            if (noErr != err) goto done;
            
            GetRawDataFromDescriptor(&textDesc, (Ptr)&aTextToken, sizeof(aTextToken),
                                            &actualSize);
                                            
            SelectTextToken(&aTextToken);
    }
 
done:
    if (textDesc.dataHandle)
        AEDisposeDesc(&textDesc);
 
    return(err);
}
 
 
// ------------------------------------------------------------------------
//  Name:       SetWindowProperty
//  Purpose:    Sets the window property specified in theWindowPropToken to
//              be that supplied in dataDesc.
// ------------------------------------------------------------------------
     
OSErr   DoSetWindowProperty(const AEDesc *theWPTokenDesc, const AEDesc *dataDesc)
{
    Str255          theNewName;
    DPtr            theDocument;
    Rect            thePosnRect;
    Boolean         theBoolean;
    GrafPtr         oldPort;
    Point           thePosn;
    THPrint         theTHPrint;
    WindowPropToken theWindowPropToken;
    TextToken       aTextToken;
    AEDesc          aDesc = {typeNull, NULL},
                    nullDesc = {typeNull, NULL},
                    ignoreResult = {typeNull, NULL};
    Size            tokenSize;
    short           hOffset;
    short           vOffset;
    OSErr           err;
 
    GetPort(&oldPort);
 
    err = AECoerceDesc(theWPTokenDesc, typeMyWindowProp, &aDesc);
    if (noErr != err) goto done;
 
    GetRawDataFromDescriptor(&aDesc, (Ptr)&theWindowPropToken,
                                    sizeof(theWindowPropToken), &tokenSize);
 
    SetPort(theWindowPropToken.tokenWindowToken.tokenWindow);
    
    theDocument = DPtrFromWindowPtr(theWindowPropToken.tokenWindowToken.tokenWindow);
    
    switch (theWindowPropToken.tokenProperty)
    {
        case pName:
            err = GetPStringFromDescriptor(dataDesc, theNewName);
            if (noErr != err) goto done;
 
            if (theNewName[0] == 0) 
                err = errAEWrongDataType;
            else
            {
                SetWTitle(theWindowPropToken.tokenWindowToken.tokenWindow, theNewName);
                PStrCopy(theDocument->theFileName, theNewName); // Should we do this???
                theDocument->dirty = true;
            }
            break;
            
        case pText:
        case pContents:
                            // Get whole window as place to insert data
            err = TextTokenFromWindowToken(&(theWindowPropToken.tokenWindowToken), &aTextToken);
            if (noErr != err) goto done;
 
            err = CreateAtTextToken(cText, dataDesc, &aTextToken,
                                                    &nullDesc, &ignoreResult);
            break;
            
        case pBounds:
            err = GetRectFromDescriptor(dataDesc, &thePosnRect);
            // the rectangle is for the structure region, and is in global coordinates
            // MoveWindow and SizeWindow apply to the content region, so we have to massage a little
 
            thePosnRect.top    += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.top -
                                  (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.top;
                                                        
            thePosnRect.left   += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.left -
                                  (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.left;
                                                        
            thePosnRect.bottom += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.bottom -
                                  (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.bottom;
                                                        
            thePosnRect.right  += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.right -
                                  (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.right;
            
            if (EmptyRect(&thePosnRect)) 
                err = errAECorruptData;
            else
            {
                MoveWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
                                     thePosnRect.left,
                                     thePosnRect.top,
                                     false);
                SizeWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
                                     thePosnRect.right- thePosnRect.left,
                                     thePosnRect.bottom-thePosnRect.top,
                                     true);
                DoResizeWindow(theDocument);
            }
            break;
            
        case pPosition:
            err = GetPointFromDescriptor(dataDesc, &thePosn);
            // the point is for the structure region, and is in global coordinates
            // MoveWindow applies to the content region, so we have to massage a little
    
            hOffset = (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.left -
                      (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.left;
                                
            vOffset = (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.top -
                      (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.top;
                                
                                
            thePosn.v  += vOffset;
            thePosn.h  += hOffset;
            
            MoveWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
                                 thePosn.h,
                                 thePosn.v,
                                 false);
                                 
            DoResizeWindow(theDocument);
            break;
            
        case pIsZoomed:
            err = GetBooleanFromDescriptor(dataDesc, &theBoolean);
            if (theBoolean)
                ZoomWindow(qd.thePort, inZoomOut, false);
            else
                ZoomWindow(qd.thePort, inZoomIn, false);
                                                    
            DoResizeWindow(theDocument);
            break;
            
        case pVisible:
            err = GetBooleanFromDescriptor(dataDesc, &theBoolean);
            if (theBoolean)
                ShowWindow(theWindowPropToken.tokenWindowToken.tokenWindow);
            else
                HideWindow(theWindowPropToken.tokenWindowToken.tokenWindow);
            break;
            
        case pPageSetup:
                err = GetTHPrintFromDescriptor(dataDesc, &theTHPrint);
                    
                if (theTHPrint) 
                {
                    if (theDocument->thePrintSetup) 
                        DisposeHandle((Handle)theDocument->thePrintSetup);
                        
                    theDocument->thePrintSetup = theTHPrint;
                    
                    ResizePageSetupForDocument(theDocument);
                }
            
        case pSelection:
            err = SetWindowSelectionProperty(theWindowPropToken.tokenWindowToken.tokenWindow, dataDesc);
            break;
    
        default:    
            err = errAEEventNotHandled;
    }
    
done:
    if (aDesc.dataHandle)   
        AEDisposeDesc(&aDesc);
    if (nullDesc.dataHandle)        // You'd hope not
        AEDisposeDesc(&nullDesc);
    if (ignoreResult.dataHandle)    
        AEDisposeDesc(&ignoreResult);
 
    SetPort(oldPort);
    
    return(err);
} // SetWindowProperty
 
 
 
OSErr   GetTHPrintFromDescriptor(const AEDesc *sourceDesc, THPrint *result)
{
    Size    ptSize;
    AEDesc  resultDesc;
    OSErr   err;
    
    *result = NULL;
    
    err = AECoerceDesc(sourceDesc, typeTPrint, &resultDesc);
    if (noErr != err) goto done;
    
    *result = (THPrint)NewHandle(sizeof(TPrint));
    
    PrOpen();
    PrintDefault(*result);
    
    HLock((Handle)*result);
    GetRawDataFromDescriptor(&resultDesc, (Ptr)**result, sizeof(TPrint), &ptSize);
    HUnlock((Handle)*result);
    
    if ((ptSize<sizeof(TPrint)) || (PrValidate(*result)))
    {
        err = errAECoercionFail;
        DisposeHandle((Handle)*result);
        *result = NULL;
    }
    
    PrClose();
 
done:   
    if (resultDesc.dataHandle) 
        AEDisposeDesc(&resultDesc);
        
    return(err);
} // GetTHPrintFromDescriptor
 
 
 
// ----------------------------------------------------------------------
//  Name:       SetTextProperty
//  Purpose:    Sets the text property specfied by theTextPropToken to
//              that in dataDesc.
// ----------------------------------------------------------------------
     
OSErr   SetTextProperty(const AEDesc *tokenDesc, const AEDesc *dataDesc)
{
    DPtr            theDoc;
    Str255          name;
    short           theSize;
    Style           onStyle;
    Style           offStyle;
    TextPropToken   theTextPropToken;
    AEDesc          newDesc = {typeNull, NULL},
                    nullDesc = {typeNull, NULL},
                    ignoreResult = {typeNull, NULL};
    Size            tokenSize;
    OSErr           err;
    
    err = AECoerceDesc(tokenDesc, typeMyTextProp, &newDesc);
    if (noErr != err) goto done;
 
    GetRawDataFromDescriptor(&newDesc, (Ptr)&theTextPropToken,
                                    sizeof(theTextPropToken), &tokenSize);
        
    theDoc = DPtrFromWindowPtr(theTextPropToken.tokenTextToken.tokenWindow);
    theDoc->dirty = true;
    
    switch (theTextPropToken.tokenProperty)
    {
        case pText:
        case pContents:
            err = CreateAtTextToken(cText, dataDesc, &(theTextPropToken.tokenTextToken),
                                                                &nullDesc, &ignoreResult);
            break;
            
        case pFont:
            err = GetPStringFromDescriptor(dataDesc, name);
            if (noErr != err) goto done;
            err = SetFontOfTextToken(&theTextPropToken.tokenTextToken, name);
            break;
            
        case pPointSize:    
            err = GetIntegerFromDescriptor(dataDesc, &theSize);
            if (noErr != err) goto done;
            err = SetSizeOfTextToken(&theTextPropToken.tokenTextToken, theSize);
            break;
            
        case pTextStyles:
            onStyle  = 0;
            offStyle = 0;
            
            err = GetTextStyles(dataDesc, &onStyle, &offStyle);
            if (noErr != err) goto done;
 
            if (onStyle & offStyle != 0)
                err = errAEEventFailed;
            else
                err = SetStyleOfTextToken(&theTextPropToken.tokenTextToken, onStyle, offStyle);
            break;
        
        default:
            err = errAEWrongDataType;
    }
 
done:
    if (newDesc.dataHandle)
        AEDisposeDesc(&newDesc);
            
    return(err);
} // SetTextProperty
 
    
short ItemForNamedFont(Str255 theName)
{
    Str255  itemName;
    short   limit;
 
    limit = CountMItems(myMenus[fontM]);
    while (limit>0)
    {
        GetMenuItemText(myMenus[fontM],limit, itemName);
        if (EqualString(theName, itemName,true,false)==0) 
            return(limit);
        else
            limit--;
    }
    return(0);
} // ItemForNamedFont
 
 
// -----------------------------------------------------------------------
//  Name:       SetFontOfTextToken
//  Purpose:    Sets the font of the text specified by theToken to 
//              the font in name.
// -----------------------------------------------------------------------
     
OSErr   SetFontOfTextToken(TextToken* theToken, Str255 name)
{
    DPtr        docPtr;
    TextToken   oldSelection;
    short       theNumber,
                theItem;
    TextStyle   newStyle;
    Boolean     fCurrentSelection;
    OSErr       err;
 
    docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
    
    if (!docPtr) return(errAENoSuchObject);
        
                // ignore theNumber result
    err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &theNumber);
    if (noErr != err) goto done;
    
    if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
    {
        fCurrentSelection = false;
        err = SelectTextToken(theToken);    // Only set the selection if it's different
        if (noErr != err) goto done;
    }
    else
        fCurrentSelection = true;
            
    GetFNum(name, &theNumber);
    
    theItem = ItemForNamedFont(name); // returns 0 if failed - i.e. SystemFont
    
    if (gFontMItem)
        CheckItem(myMenus[fontM], gFontMItem, false);
    
    gFontMItem = theItem;
    CheckItem(myMenus[fontM], gFontMItem, true);
    
    docPtr->theFont = theNumber;
        
    newStyle.tsFont = theNumber;
    TESetStyle(doFont, &newStyle, true, docPtr->theText); 
    
    AdjustScrollbars(docPtr, false);
    DrawPageExtras(docPtr);
    docPtr->dirty = true;
    
    if (! fCurrentSelection)
        err = SelectTextToken(&oldSelection);
 
done:   
    return(err);
} // SetFontOfTextToken
    
// -----------------------------------------------------------------------
//  Name:           SetSizeOfTextToken
//  Purpose:        Sets the size of the text specified by theToken to 
//                  the size in theSize.
// -----------------------------------------------------------------------
     
OSErr   SetSizeOfTextToken(TextToken* theToken, short theSize)
{
    DPtr        docPtr;
    TextToken   oldSelection;
    TextStyle   newStyle;
    short       ignore;
    Boolean     fCurrentSelection;
    OSErr       err;
 
    docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
    
    if (!docPtr) return(errAENoSuchObject);
        
                // Save the old selection
    err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
    if (noErr != err) goto done;
    
    if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
    {
        fCurrentSelection = false;
        err = SelectTextToken(theToken);
        if (noErr != err) goto done;
    }
    else
        fCurrentSelection = true;
                            
    docPtr->theSize = theSize;
    
    newStyle.tsSize = theSize;
    TESetStyle(doSize, &newStyle, true, docPtr->theText); 
    
    AdjustScrollbars(docPtr, false);
    DrawPageExtras(docPtr);
    docPtr->dirty = true;
    
    if (! fCurrentSelection)    // If we reset the selection we may loose the
        err = SelectTextToken(&oldSelection);   // Size or style just set
 
done:   
    return(err);
} // SetSizeOfTextToken
    
// ------------------------------------------------------------------------
//  Name:           SetStyleOfTextToken
//  Purpose:        Sets the style of the text specified by theToken to 
//                  the style in theStyle.
// ------------------------------------------------------------------------
     
OSErr   SetStyleOfTextToken(TextToken* theToken, Style onStyle, Style offStyle)
{
    DPtr        docPtr;
    TextToken   oldSelection;
    TextStyle   newStyle;
    short       mode;
    Boolean     wasContinuous;
    short       ignore;
    Boolean     fCurrentSelection;
    OSErr       err;
 
    docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
    
    if (!docPtr) return(errAENoSuchObject);
        
                // Save the old selection
    err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
    if (noErr != err) goto done;
    
    if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
    {
        fCurrentSelection = false;
        err = SelectTextToken(theToken);
        if (noErr != err) goto done;
    }
    else
        fCurrentSelection = true;
                            
    docPtr->theStyle = onStyle;
    
        // Check to see if off styles are on for whole selection
    mode = doFace;
    
    wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
    if ((newStyle.tsFace & offStyle) != offStyle) // not off styles are on for all
    {
            // switch on across board so that toggle off will clear all
        newStyle.tsFace  = offStyle - (newStyle.tsFace & offStyle);
        TESetStyle(doFace+doToggle, &newStyle, false, docPtr->theText); 
    }
        
    newStyle.tsFace  = offStyle;
    TESetStyle(doFace+doToggle, &newStyle,(onStyle==0), docPtr->theText); // toggle all to off
    
    mode = doFace;
    if (onStyle)
    {
        wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
        if ((newStyle.tsFace & onStyle) != onStyle) // are they on for only a few chars
        { 
                // Need to make all chars have these characteristics
            newStyle.tsFace = onStyle - (newStyle.tsFace & onStyle); // take out those continuous
            TESetStyle(doFace+doToggle, &newStyle, true, docPtr->theText);
        }
        else
            TESetStyle(0, &newStyle, true, docPtr->theText); // Just Draw it, no changes
    }
        
    AdjustScrollbars(docPtr, false);
    DrawPageExtras(docPtr);
    docPtr->dirty = true;
    
    if (! fCurrentSelection)
        err = SelectTextToken(&oldSelection);
 
done:   
    return(err);
} // SetStyleOfTextToken
 
    
OSErr   GetTextStyles(const AEDesc *dataDesc, Style *onStyles, Style *offStyles)
{
    OSErr      myErr;
    OSErr      ignoreErr;
    AEDescList textSDesc;
    AEDescList onDesc;
    AEDescList offDesc;
    Boolean    hadPlain;
        
  textSDesc.dataHandle = nil;
  onDesc.dataHandle    = nil;
  offDesc.dataHandle   = nil;
    
    *onStyles  = 0;
    *offStyles = 0;
    
  myErr = AECoerceDesc(dataDesc, typeAERecord, &textSDesc);
    
    if (myErr==noErr)
      myErr = AEGetKeyDesc(&textSDesc, keyAEOnStyles, typeAEList, &onDesc);
    
    if (myErr==noErr)
      myErr = AEGetKeyDesc(&textSDesc, keyAEOffStyles, typeAEList, &offDesc);
    
    if (myErr==noErr)
        myErr = MakeStyleFromAEList(&onDesc,  onStyles, &hadPlain);
    
    if (hadPlain)
        *offStyles = bold+italic+underline+outline+shadow+condense+extend;
    else
        {
            if (myErr==noErr)
                myErr = MakeStyleFromAEList(&offDesc, offStyles, &hadPlain);
            
            if (hadPlain)
                myErr = errAEEventFailed;
        }
        
    if (textSDesc.dataHandle)
        ignoreErr = AEDisposeDesc(&textSDesc);
        
    if (onDesc.dataHandle)
        ignoreErr = AEDisposeDesc(&onDesc);
        
    if (offDesc.dataHandle)
        ignoreErr = AEDisposeDesc(&offDesc);
    
    return(myErr);
} // GetTextStyles
 
// -----------------------------------------------------------------------
//  Name:       AddDescStyleItem
//  Purpose:    Adds the kAEXXXX style to theStyle.
// -----------------------------------------------------------------------
     
void    AddDescStyleItem(DescType theDesc, Style *theStyle)
{
    if (theDesc == kAEBold)
        *theStyle = *theStyle+bold;
    else
    if (theDesc == kAEItalic)
        *theStyle = *theStyle+italic;
    else
    if (theDesc == kAEUnderline)
        *theStyle = *theStyle+underline;
    else
    if (theDesc == kAEOutline)
        *theStyle = *theStyle+outline;
    else
    if (theDesc == kAEShadow)
        *theStyle = *theStyle+shadow;
    else
    if (theDesc == kAECondensed)
        *theStyle = *theStyle+condense;
    else
    if (theDesc == kAEExpanded)
        *theStyle = *theStyle+extend;
    else
    if (theDesc == kAEPlain)
        *theStyle = 0;
} // AddDescStyleItem
    
OSErr   MakeStyleFromAEList(const AEDescList *styleList, Style *theStyle, Boolean *hadPlain)
{
    OSErr     myErr;
    DescType  styleDesc;
    long      itemsInList;
    long      actSize;
    AEKeyword keywd;
    DescType  typeCode;
        
    *hadPlain = false;
    *theStyle = 0;
    
  myErr = AECountItems(styleList, &itemsInList);
    while (itemsInList>0)
      if (myErr==noErr)
            {
                myErr  = AEGetNthPtr(styleList,
                                                         itemsInList,
                                                         typeEnumerated,
                                                         &keywd,
                                                         &typeCode,
                                                         (Ptr)&styleDesc,
                                                         sizeof(styleDesc),
                                                         &actSize);
                
                AddDescStyleItem(styleDesc, theStyle);
                
                if (styleDesc == kAEPlain) 
                  {
                        itemsInList = 0;
                        *hadPlain    = true;
                    }
                else
                  itemsInList--;
            }
            
    return(myErr);
} // MakeStyleFromAEList