Sources/MSAERecording.c

// MSAERecording.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 3.1
 
    14-Nov-95 : GS : Disposed of style handle correctly in BuildStyledTextDesc().
    14-Nov-95 : GS : Disposed of text object specifier in IssueSizeCommand(),
                        IssueFontCommand() and IssueStyleCommand().
                        
    Changes for 4.0
    
    29-Feb-96 : GS : MakeWindowObj() makes a document object specifier if the window
                        is a document.
*/
 
#include "MSAERecording.h"
 
#include "MSAEUtils.h"
#include "MSUtils.h"
#include "MSAEWindowUtils.h"
#include "MSAETextUtils.h"
#include "MSAppleEvents.h"
#include "MSAEGetData.h"
 
#include <AEPackObject.h>
 
 
 
static short   gBigBrother;
static char    *gTypingBuffer;
static short   gCharsInBuffer;
static AEDesc  gTypingTargetObject;
 
const short kTextSizeDialog = 1004;
 
 
OSErr   InstallRecordingHandlers(void)
{
    OSErr   err;
    
    gBigBrother = 0;
    gCharsInBuffer = 0;
    gTypingBuffer = (char *)NewPtr(kMaxTELength);
    gTypingTargetObject.dataHandle = 0;
    
    err = AEInstallEventHandler( kCoreEventClass, kAENotifyStartRecording, NewAEEventHandlerProc(HandleStartRecording), noRefCon, false);
    err = AEInstallEventHandler( kCoreEventClass, kAENotifyStopRecording, NewAEEventHandlerProc(HandleStopRecording), noRefCon, false);
 
    return(err);
}
 
pascal OSErr HandleStartRecording(const AppleEvent *theAppleEvent,
                                                          AppleEvent *reply,
                                                          long       handlerRefCon)     
{
#ifdef __MWERKS__
    #pragma unused (reply,handlerRefCon)
#endif
 
    OSErr myErr;
 
    gBigBrother++;
 
    myErr = GotRequiredParams(theAppleEvent);
 
    return(myErr);
    
} // HandleStartRecording
 
pascal OSErr HandleStopRecording(const AppleEvent *theAppleEvent,
                                                         AppleEvent *reply,
                                                             long handlerRefCon)        
{
#ifdef __MWERKS__
    #pragma unused (theAppleEvent,reply,handlerRefCon)
#endif
 
    gBigBrother--;
    return(noErr);
} // HandleStopRecording
 
 
// Make an object specifier for a window given the WindowPtr
 
OSErr   MakeWindowObj(WindowPtr theWindow, AEDesc *result)
{
    AEDesc      nullDesc = {typeNull, NULL},
                aDesc = {typeNull, NULL};
    long        anIndex;
    Str255      aName;
    DescType    keyForm;
    OSErr       err;
    
    if ( ! theWindow )
        return errAENoSuchObject;
        
    if ( IsDocumentWindow( theWindow ) )
        return MakeDocumentObj( theWindow, result );
    
    if ( IsVisible( theWindow ) )
    {
        anIndex = GetWindowIndex(theWindow);
        if ( ! anIndex )
            return errAENoSuchObject;
        
        err = AECreateDesc( typeLongInteger, (Ptr)&anIndex,
                                    sizeof( anIndex ), &aDesc );
        if (noErr != err) goto done;
        
        keyForm = formAbsolutePosition;
    }
    else
    {
        GetWTitle( theWindow, aName );
        
        err = AECreateDesc( typeChar, (Ptr)&aName[1],
                                            aName[0], &aDesc );
        if (noErr != err) goto done;
        
        keyForm = formName;
    }
    
    err = CreateObjSpecifier( cWindow, &nullDesc, keyForm,
                                                &aDesc, false, result );
 
done:
    (void)AEDisposeDesc( &aDesc );
    
    return(err);
} // MakeWindowObj
 
// Make an object specifier for a document given the WindowPtr
 
OSErr   MakeDocumentObj(WindowPtr theWindow, AEDesc *result)
{
    AEDesc      nullDesc = {typeNull, NULL},
                aDesc = {typeNull, NULL};
    long        anIndex;
    Str255      aName;
    DescType    keyForm;
    OSErr       err;
    
    if ( ! theWindow )
        return errAENoSuchObject;
        
    if ( ! IsDocumentWindow( theWindow ) )
        return errAEWrongDataType;
    
    if ( IsVisible( theWindow ) )
    {
        anIndex = GetDocumentIndex(theWindow);
        if ( ! anIndex )
            return errAENoSuchObject;
        
        err = AECreateDesc( typeLongInteger, (Ptr)&anIndex,
                                    sizeof( anIndex ), &aDesc );
        if (noErr != err) goto done;
        
        keyForm = formAbsolutePosition;
    }
    else
    {
        GetWTitle( theWindow, aName );
        
        err = AECreateDesc( typeChar, (Ptr)&aName[1],
                                            aName[0], &aDesc );
        if (noErr != err) goto done;
        
        keyForm = formName;
    }
    
    err = CreateObjSpecifier( cDocument, &nullDesc, keyForm,
                                                &aDesc, false, result );
 
done:
    (void)AEDisposeDesc( &aDesc );
    
    return(err);
} // MakeDocumentObj
 
 
OSErr   MakeTextObjFromToken(TextToken* theToken, AEDesc* result)
{
    OSErr   err;
 
    err = GetTextTokenObjectSpecifier(theToken, result);
    
    return(err);
}
 
 
OSErr   MakeSelectedTextObj(WindowPtr theWindow, TEHandle theTextEditHandle, AEDesc* result)
{
    return( MakeTextObj(theWindow, (**theTextEditHandle).selStart,
                            (**theTextEditHandle).selEnd, result));
} // MakeSelectedTextObj
 
 
OSErr   MakeTextObj(WindowPtr theWindow, short selStart, short selEnd, AEDesc* result)
{
    TextToken   aToken;
    OSErr       err;
    
    aToken.tokenWindow = theWindow;
    aToken.tokenOffset = selStart + 1;
    aToken.tokenLength = selEnd - selStart;
 
    err = MakeTextObjFromToken(&aToken, result);
 
    return(err);
}
 
OSErr   SendSelectionEvent(DPtr docPtr)
{
    AEAddressDesc   ourAddress = {typeNull, NULL};
    AppleEvent      selectEvent = {typeNull, NULL},
                    ignoreReply = {typeNull, NULL};
    AEDesc          textObj = {typeNull, NULL};
    OSErr           err;
 
 
    err = MakeSelfAddress(&ourAddress);
    if (noErr != err) goto done;
    
        // Build an object to represent the current document's selection
        // MakeSelectedTextObj
    err = MakeSelectedTextObj(docPtr->theWindow, docPtr->theText, &textObj);
    if (noErr != err) goto done;
    
    err = AECreateAppleEvent(kAEMiscStandards, kAESelect, &ourAddress, 0, 0, &selectEvent); 
    if (noErr != err) goto done;
    
        // add parameter
    err = AEPutParamDesc(&selectEvent, keyDirectObject, &textObj);
    if (noErr != err) goto done;
                    
        // and now send the message
    err = AESend(&selectEvent, &ignoreReply, kAENoReply, kAEHighPriority, kAEDefaultTimeout, NULL, NULL);
    if (noErr != err) goto done;
 
done:   
    (void)AEDisposeDesc(&ourAddress);
    (void)AEDisposeDesc(&selectEvent);
    (void)AEDisposeDesc(&ignoreReply);
    (void)AEDisposeDesc(&textObj);
 
    return(err);
}
 
void    DoEditCommand(DPtr theDocument, editCommandType whatCommand)
{
    AEAddressDesc   ourAddress = {typeNull, NULL};
    AppleEvent      editCommandEvent = {typeNull, NULL},
                    ignoreReply = {typeNull, NULL};
    AEEventID       theEventID;
    AEEventClass    theEventClass;
    OSErr           err;
    
    err = SendSelectionEvent(theDocument);
    if (noErr != err) goto done;
 
        // Now create and send the appropriate cut, copy, paste or clear AppleEvent
    
    switch (whatCommand)
    {
        case  editCutCommand:
            theEventID = kAECut;
            theEventClass = kAEMiscStandards;
            break;
            
        case  editCopyCommand:
            theEventID = kAECopy;
            theEventClass = kAEMiscStandards;
            break;
 
        case  editPasteCommand:
            theEventID = kAEPaste;
            theEventClass = kAEMiscStandards;
            break;
 
        case  editClearCommand:
            theEventID = kAEDelete;
            theEventClass = kAECoreSuite;
            break;
    }
    
    err = MakeSelfAddress(&ourAddress);
    if (noErr != err) goto done;
            
    err = AECreateAppleEvent(theEventClass, theEventID, &ourAddress, 0, 0, &editCommandEvent);  
    if (noErr != err) goto done;
            
        // and now Send the message
    err = AESend(&editCommandEvent, &ignoreReply, kAENoReply, kAEHighPriority, kAEDefaultTimeout, NULL, NULL);
        
done:
    (void)AEDisposeDesc(&ourAddress);
    (void)AEDisposeDesc(&editCommandEvent);
    (void)AEDisposeDesc(&ignoreReply);
 
} // DoEditCommand
 
void    IssueCutCommand(DPtr theDocument)
{           
    DoEditCommand(theDocument, editCutCommand);
} 
 
void    IssueCopyCommand(DPtr theDocument)
{
    DoEditCommand(theDocument, editCopyCommand);
}
 
void    IssuePasteCommand(DPtr theDocument)
{
    DoEditCommand(theDocument, editPasteCommand);   
}
 
void    IssueClearCommand(DPtr theDocument)
{
    DoEditCommand(theDocument, editClearCommand);   
}
 
// ---------------------------------------------------------------------
//  Name :      SendAESetObjProp
//  Function :  Creates a property object from an object,
//              a property type and its data and sends it to
//              the requested address, and cleans up zapping params too
// ---------------------------------------------------------------------
 
OSErr   SendAESetObjProp(AEDesc *theObj, DescType theProp, AEDesc *theData, AEAddressDesc *toWhom)
{
    AEDesc      propObjSpec;
    AppleEvent  myAppleEvent;
    AppleEvent  defReply;
    OSErr       myErr;
    OSErr       ignoreErr;
    AEDesc      theProperty;
        
    // create an object spec that represents the property of the given object
    
    myErr = AECreateDesc(typeType, (Ptr)&theProp, sizeof(theProp), &theProperty);
    if (myErr==noErr)
        myErr = CreateObjSpecifier(cProperty, theObj, formPropertyID,
                                        &theProperty, true, &propObjSpec);  
        
    // create event
    
    if (myErr==noErr)
        myErr = AECreateAppleEvent(kAECoreSuite, kAESetData, toWhom, 0, 0, &myAppleEvent);
        
    // add prop obj spec to the event
    
    if (myErr==noErr)
        myErr = AEPutParamDesc(&myAppleEvent, keyDirectObject, &propObjSpec);
    
    // add prop data to the event
    
    if (myErr==noErr)
        myErr = AEPutParamDesc(&myAppleEvent,keyAEData, theData);
    
    // send event
    
    if (myErr==noErr)
        myErr = AESend(&myAppleEvent, &defReply, kAENoReply+kAEAlwaysInteract,
                                    kAENormalPriority, kAEDefaultTimeout, nil, nil);
    
    if (myAppleEvent.dataHandle)
        ignoreErr = AEDisposeDesc(&myAppleEvent);
        
    if (&propObjSpec.dataHandle)
      ignoreErr = AEDisposeDesc(&propObjSpec);
    
    if (theData->dataHandle)
        ignoreErr = AEDisposeDesc(theData);
    
    if (toWhom->dataHandle)
        ignoreErr = AEDisposeDesc(toWhom);
    
    return(myErr);
} // SendAESetObjProp
 
 
void    IssueFontCommand(DPtr theDocument, short theItem)
{
    Str255          name;
    AEDesc          strDesc;
    AEAddressDesc   theAddress;
    AEDesc          selTextObj = {typeNull, NULL};
    OSErr           err;
        
    err = MakeSelfAddress(&theAddress);
    
    err = MakeSelectedTextObj(theDocument->theWindow, theDocument->theText, &selTextObj);
    
    GetItem(myMenus[fontM], theItem, name);
    
    if (err==noErr)
        err  = AECreateDesc(typeChar, (Ptr)&name[1], name[0], &strDesc);
    
    if (err==noErr)
        err  = SendAESetObjProp(&selTextObj, pFont, &strDesc, &theAddress);
        
    (void)AEDisposeDesc(&selTextObj);                                           
}
 
// Window property routines
 
void    IssueZoomCommand(WindowPtr whichWindow, short whichPart)
{
    Boolean       zoomBool;
    AEDesc        zoomDesc;
    AEAddressDesc selfAddr;
    AEDesc        frontWinObj;
    OSErr         err;
 
    err = MakeSelfAddress(&selfAddr);
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
    
    zoomBool = (whichPart==inZoomOut);
 
    err = AECreateDesc(typeBoolean, (Ptr)&zoomBool, sizeof(zoomBool), &zoomDesc);
                                            
    err = SendAESetObjProp(&frontWinObj, pIsZoomed, &zoomDesc, &selfAddr);                                                          
} // IssueZoomCommand
 
void    IssueCloseCommand(WindowPtr whichWindow)
{
    AEAddressDesc  selfAddr;
    AEDesc         frontWinObj;
    OSErr          err;
    OSErr          ignoreErr;
    AppleEvent     closeCommandEvent;
    AppleEvent     ignoreReply;
 
    frontWinObj.dataHandle = nil;
    
    err = MakeSelfAddress(&selfAddr);
    
        // If it's a document this will be a document object sprcifier
    err = MakeWindowObj(whichWindow, &frontWinObj);
                                                        
    err = AECreateAppleEvent( kAECoreSuite, kAEClose, &selfAddr,
                kAutoGenerateReturnID, kAnyTransactionID, &closeCommandEvent) ;             
    
    // add parameter - the window to close  
    if (err==noErr) 
        err = AEPutParamDesc(&closeCommandEvent, keyDirectObject, &frontWinObj);
        
    if (err==noErr) 
        err = AESend( &closeCommandEvent, &ignoreReply, kAENoReply + kAEAlwaysInteract,
                                        kAENormalPriority, kAEDefaultTimeout, NULL, NULL );
    
    if (closeCommandEvent.dataHandle) 
        ignoreErr = AEDisposeDesc(&closeCommandEvent);
    
    if (selfAddr.dataHandle) 
        ignoreErr = AEDisposeDesc(&selfAddr);
        
    if (frontWinObj.dataHandle) 
        ignoreErr = AEDisposeDesc(&frontWinObj);
        
} // IssueCloseCommand
 
void    IssueSizeWindow(WindowPtr whichWindow, short newHSize, short newVSize)
{
    Rect          sizeRect;
    Rect          contentRect;
    short         edgeSize;
    AEDesc        sizeDesc;
    AEAddressDesc selfAddr;
    AEDesc        frontWinObj;
    OSErr         err;
 
    sizeRect    = (**(((WindowPeek)whichWindow)->strucRgn)).rgnBBox;
    contentRect = (**(((WindowPeek)whichWindow)->contRgn)).rgnBBox;
    
    edgeSize = sizeRect.right-sizeRect.left-(contentRect.right-contentRect.left);
    sizeRect.right = sizeRect.left+newHSize+edgeSize;
    
    edgeSize = sizeRect.bottom-sizeRect.top-(contentRect.bottom-contentRect.top);
    sizeRect.bottom = sizeRect.top+newVSize+edgeSize;
    
    err = MakeSelfAddress(&selfAddr);
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
    
    if (err==noErr)
        err = AECreateDesc(typeQDRectangle, (Ptr)&sizeRect, sizeof(sizeRect), &sizeDesc);
    
    if (err==noErr)
        err  = SendAESetObjProp(&frontWinObj, pBounds, &sizeDesc, &selfAddr);                                                           
} // IssueSizeWindow
 
void    IssueMoveWindow(WindowPtr whichWindow, Rect* sizeRect)
{
    AEDesc          sizeDesc = { typeNull, NULL },
                    frontWinObj = { typeNull, NULL };
    AEAddressDesc   selfAddr = { typeNull, NULL };
    OSErr           err;
    
    err = MakeSelfAddress(&selfAddr);
    if ( noErr != err ) goto done;
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
    if ( noErr != err ) goto done;
        
    err = AECreateDesc( typeQDRectangle, (Ptr)sizeRect, sizeof( *sizeRect ), &sizeDesc );
    if ( noErr != err ) goto done;
    
    err = SendAESetObjProp(&frontWinObj, pBounds, &sizeDesc, &selfAddr);
        
done:
    (void)AEDisposeDesc( &selfAddr );   // These three are disposed of in SendAESetObjProp()
    (void)AEDisposeDesc( &frontWinObj );//  if it makes it there.
    (void)AEDisposeDesc( &sizeDesc );
} // IssueMoveWindow
 
void    IssuePageSetupWindow(WindowPtr whichWindow, TPrint thePageSetup)
{
    AEDesc        sizeDesc;
    AEAddressDesc selfAddr;
    AEDesc        frontWinObj;
    OSErr         err;
 
    err = MakeSelfAddress(&selfAddr);
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
    
    if (err==noErr)
        err = AECreateDesc(typeTPrint, (Ptr)&thePageSetup, sizeof(thePageSetup), &sizeDesc);
                                             
    if (err==noErr)
        err = SendAESetObjProp(&frontWinObj, pPageSetup, &sizeDesc, &selfAddr);                                                         
                                                 
} //IssuePageSetupWindow
 
 
void IssueGXPageSetupWindow(WindowPtr whichWindow, gxJob thGXJob)
{
    AEDesc        sizeDesc;
    AEAddressDesc selfAddr;
    AEDesc        frontWinObj;
    OSErr         err;
    Handle        thePGXHandle;
 
    // Flatten the gxJob to a handle
 
    thePGXHandle = NewHandle(0);
    GXFlattenJobToHdl(thGXJob, thePGXHandle);
 
    err = MakeSelfAddress(&selfAddr);
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
    
    if (err==noErr)
        err = AECreateDesc(typeTPrint, (Ptr)*thePGXHandle,
                                GetHandleSize (thePGXHandle), &sizeDesc);
                                             
    if (err==noErr)
        err = SendAESetObjProp(&frontWinObj, pGXPageSetup, &sizeDesc, &selfAddr);                                                           
 
    DisposeHandle( thePGXHandle );                                           
} // IssueGXPageSetupWindow
 
 
void IssuePrintWindow(WindowPtr whichWindow, Boolean useDialog)
{
    AEAddressDesc selfAddr = { typeNull, NULL };
    AEDesc        frontWinObj = { typeNull, NULL };
    OSErr         err;
    AppleEvent    printCommandEvent = { typeNull, NULL };
    AppleEvent    ignoreReply;
    AESendMode    sendModeFlags;
 
    err = MakeSelfAddress(&selfAddr);
    
    err = MakeWindowObj(whichWindow, &frontWinObj);
                                                        
    err = AECreateAppleEvent(kCoreEventClass, kAEPrintDocuments, &selfAddr, 0, 0, &printCommandEvent) ;             
 
    //  add parameter - the window to print
 
    if (err==noErr) 
        err = AEPutParamDesc(&printCommandEvent, keyDirectObject, &frontWinObj);
        
    if (err==noErr)
    {
        sendModeFlags = kAENoReply;
        if (useDialog)
            sendModeFlags = sendModeFlags + kAEAlwaysInteract;
        else
            sendModeFlags = sendModeFlags + kAENeverInteract;
        err = AESend(&printCommandEvent,&ignoreReply,sendModeFlags,kAEHighPriority,10000,nil, nil);
    }
    
    (void)AEDisposeDesc(&printCommandEvent);
    (void)AEDisposeDesc(&frontWinObj);
    (void)AEDisposeDesc(&selfAddr);
} // IssuePrintWindow
 
OSErr   IssueAEOpenDoc(FSSpec myFSSpec)
// send OpenDocs AppleEvent to myself, with a one-element list
// containing the given file spec
//
// NOTES : the core AEOpenDocs event is defined as taking a list of
//      aliases (not file specs) as its direct parameter.  However,
//      we can send the file spec instead and depend on AppleEvents'
//      automatic coercion.  In fact, we don't really even have to put 
//      in a list; AppleEvents will coerce a descriptor into a 1-element
//      list if called for.  In this routine, though, we'll make the
//      list for demonstration purposes.
{
    AppleEvent    myAppleEvent = { typeNull, NULL };
    AppleEvent    defReply = { typeNull, NULL };
    AEDescList    docList = { typeNull, NULL };
    AEAddressDesc selfAddr = { typeNull, NULL };
    OSErr         myErr;
        
    //  Create empty list and add one file spec
 
    myErr = AECreateList(nil,0,false, &docList);
    
    if (myErr==noErr) 
        myErr = AEPutPtr(&docList,1,typeFSS,(Ptr)&myFSSpec,sizeof(myFSSpec));
        
    //  Create a self address to send it to
 
    if (myErr==noErr) 
        myErr = MakeSelfAddress(&selfAddr);
        
    if (myErr==noErr) 
        myErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &selfAddr,
                                kAutoGenerateReturnID,  kAnyTransactionID, &myAppleEvent);
 
    //  Put Params into our event and send it
 
    if (myErr == noErr) 
        myErr = AEPutParamDesc(&myAppleEvent, keyDirectObject, &docList);
 
    myErr = AESend(&myAppleEvent, &defReply, kAENoReply+kAEAlwaysInteract, kAENormalPriority,
                                                                    kAEDefaultTimeout, nil, nil);
        
    (void)AEDisposeDesc(&selfAddr);
    (void)AEDisposeDesc(&myAppleEvent);
    (void)AEDisposeDesc(&docList);
        
    return(myErr);
    
} // IssueAEOpenDoc
 
void    IssueAENewWindow(void)
// send the New Element event to myself with a null container
{
    AppleEvent    myAppleEvent = { typeNull, NULL };
    AppleEvent    defReply = { typeNull, NULL };
    AEAddressDesc selfAddr = { typeNull, NULL };
    OSErr         myErr;
    DescType      elemClass;
    
    //  Create the address of us
    
    myErr = MakeSelfAddress(&selfAddr);
    
    //  create event 
    
    myErr = AECreateAppleEvent(kAECoreSuite, kAECreateElement, &selfAddr,
                                    kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent);
    
    //  attach desired class of new element
    
    elemClass = cDocument;
    
    if (myErr == noErr) 
        myErr = AEPutParamPtr(&myAppleEvent, keyAEObjectClass, typeType,
                                        (Ptr)&elemClass, sizeof(elemClass));
        
    //  send the event 
    
    if (myErr == noErr) 
        myErr = AESend(&myAppleEvent, &defReply, kAENoReply+kAENeverInteract,
                            kAENormalPriority, kAEDefaultTimeout, nil, nil);
    //  Clean up - reply never created so don't throw away
 
    (void)AEDisposeDesc(&selfAddr);
    (void)AEDisposeDesc(&myAppleEvent);
                
} // IssueAENewWindow
 
OSErr   IssueSaveCommand( WindowPtr theWindow, FSSpecPtr theSpec )
// send an AppleEvent Save Event to myself
{
    AEDesc        windowObj = { typeNull, NULL };
    AppleEvent    myAppleEvent = { typeNull, NULL };
    AppleEvent    defReply = { typeNull, NULL };
    AEAddressDesc selfAddr = { typeNull, NULL };
    OSErr         anErr;
    
    anErr = MakeWindowObj(theWindow, &windowObj);
    if ( noErr != anErr ) goto done;
    
    anErr = MakeSelfAddress(&selfAddr);
    if ( noErr != anErr ) goto done;
    
        //  Build event
 
    anErr = AECreateAppleEvent(kAECoreSuite, kAESave, &selfAddr,
                            kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent);
    if ( noErr != anErr ) goto done;
  
        //  say which window
 
    anErr = AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObj);
    if ( noErr != anErr ) goto done;
 
        //  add optional file param if we need to
 
    if ( theSpec ) 
    {
        anErr = AEPutParamPtr( &myAppleEvent, keyAEFile, typeFSS,
                                                    (Ptr)theSpec, sizeof( FSSpec ) );
        if ( noErr != anErr ) goto done;
    }
    
        // send the event
 
    anErr = AESend( &myAppleEvent, &defReply, kAENoReply + kAENeverInteract,
                                    kAENormalPriority, kAEDefaultTimeout, NULL, NULL );
 
done:     
    (void)AEDisposeDesc(&selfAddr);
    (void)AEDisposeDesc(&windowObj);
    (void)AEDisposeDesc(&myAppleEvent);
        
    return anErr;
}   // IssueSaveCommand
 
OSErr   IssueRevertCommand(WindowPtr theWindow)
    // send an AppleEvent Revert Event to myself
{
    AEDesc        windowObj = { typeNull, NULL };
    AppleEvent    myAppleEvent = { typeNull, NULL };
    AppleEvent    defReply = { typeNull, NULL };
    OSErr         myErr;
    AEAddressDesc selfAddr = { typeNull, NULL };
    
    myErr = MakeWindowObj(theWindow, &windowObj);
                
    if (myErr==noErr) 
        myErr = MakeSelfAddress(&selfAddr);
        
    // Build event
    
    if (myErr == noErr) 
        myErr  = AECreateAppleEvent(kAEMiscStandards, kAERevert, &selfAddr,
                                    kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent);
    // say which window
    
    if (myErr == noErr) 
        myErr = AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObj);
    //  send the event
 
    if (myErr==noErr) 
        myErr  = AESend(&myAppleEvent, &defReply, kAENoReply+kAENeverInteract,
                                kAENormalPriority, kAEDefaultTimeout, nil, nil);
        
    (void)AEDisposeDesc(&windowObj);
    (void)AEDisposeDesc(&myAppleEvent);
    (void)AEDisposeDesc(&selfAddr);
        
    return(myErr);
} // IssueRevertCommand
 
// ----------------------------------------------------
//  Name :      IssueQuitCommand
//  Purpose :   Sends self a Quit AppleEvent
// ----------------------------------------------------
OSErr   IssueQuitCommand(void)
{
    AppleEvent    myAppleEvent = { typeNull, NULL };
    AppleEvent    defReply = { typeNull, NULL };
    OSErr         myErr;
    AEAddressDesc selfAddr = { typeNull, NULL };
    DescType      mySaveOpt;
                        
    myErr = MakeSelfAddress(&selfAddr);
        
    //  Build event
    
    if (myErr == noErr) 
        myErr  = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &selfAddr,
                                        kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent);
    //  say which save option
    
    mySaveOpt = kAEAsk;
    
    if (myErr == noErr) 
        myErr = AEPutParamPtr(&myAppleEvent, keyAESaveOptions, typeEnumerated,
                                                (Ptr)&mySaveOpt, sizeof(mySaveOpt));
    //  send the event
 
    if (myErr==noErr) 
        myErr  = AESend(&myAppleEvent, &defReply, kAENoReply+kAEAlwaysInteract,
                                    kAENormalPriority, kAEDefaultTimeout, nil, nil);
                    
    (void)AEDisposeDesc(&myAppleEvent);
    (void)AEDisposeDesc(&selfAddr);
        
    return(myErr);
} // IssueQuitCommand
 
#define kOK 1
#define kCancel 2
#define kOtherSize 4
#define kOutlineItem 5
 
Boolean PoseSizeDialog(long *whatSize)
{
    GrafPtr   savedPort;
    DialogPtr aDialog;
    Str255    aString;
    short     itemHit;
 
    GetPort(&savedPort);
    aDialog = GetNewDialog( kTextSizeDialog, NULL, (WindowPtr)-1 );
//  ShowWindow(aDialog);
//  SetPort(aDialog);
    
    AdornDefaultButton( aDialog, kOutlineItem );
     
        //set the edittext button to contain the right size
    NumToString( *whatSize, aString );
    SetText( aDialog, kOtherSize, aString );
 
    do
    {
        ModalDialog( nil, &itemHit );
    } while ( ( itemHit != kOK ) && ( itemHit != kCancel ) );
    
    if ( itemHit == kOK ) 
        RetrieveText( aDialog, kOtherSize, aString );
 
    DisposDialog( aDialog );
    SetPort( savedPort );
    
    if ( itemHit == kOK ) 
    {
        // set the new size of the text
        StringToNum( aString, whatSize );
        if ( ( *whatSize < 1 ) || ( *whatSize > 2000 ) ) 
            *whatSize = 12;
    }
 
    return( itemHit == kOK );
}
 
void    IssueSizeCommand(DPtr theDocument,short theItem)
{
    Str255        name;
    AEDesc        sizeDesc = { typeNull, NULL };
    AEAddressDesc theAddress = { typeNull, NULL };
    OSErr         err;
    AEDesc        selTextObj = { typeNull, NULL };
    
        // Vars to do with menu processing
    short     lastSize;
    short     upItem;
    short     downItem;
    short     otherItem;
    long      theSize;
    TextStyle theStyle;
    short     lineHeight;
    short     fontAscent;
        
    err = MakeSelfAddress(&theAddress);
    
    err = MakeSelectedTextObj(theDocument->theWindow, theDocument->theText, &selTextObj);       
 
        // check if the item is on the Size menu
        // remembering that we can add and delete items from it
    lastSize  = CountMItems(myMenus[sizeM]) - 5;
    upItem    = lastSize + 2;
    downItem  = upItem + 1;
    otherItem = downItem + 2;
  
    TEGetStyle((**(theDocument->theText)).selStart, &theStyle, &lineHeight,
                                            &fontAscent, theDocument->theText);
    
    GetItem(myMenus[sizeM], theItem, name);
 
    if (theItem <= lastSize)
    {
        GetItem(myMenus[sizeM], theItem, name);
        StringToNum(name, &theSize);
    }
    else if (theItem == upItem)  
        theSize = theStyle.tsSize + 1;
    else if (theItem == downItem)
        theSize = theStyle.tsSize - 1;
    else if (theItem == otherItem) 
    {
        theSize = theStyle.tsSize;
        if (!PoseSizeDialog(&theSize))
            return;
    }
 
    if (err==noErr)
        err = CreateOffsetDescriptor(theSize, &sizeDesc);
    
    if (err==noErr)
        err = SendAESetObjProp(&selTextObj, pPointSize, &sizeDesc, &theAddress);
        
    (void)AEDisposeDesc(&selTextObj);                                           
} // IssueSizeCommand
 
void    IssueStyleCommand(DPtr theDocument, short theItem)
{
    Style         theFace;
    OSErr         err;
    AEDesc        result = { typeNull, NULL };
    AEAddressDesc selfAddr = { typeNull, NULL };
    AEDesc        selTextObj = { typeNull, NULL };
    TextStyle     theStyle;
    short         lineHeight;
    short         fontAscent;
        
    TEGetStyle((**(theDocument->theText)).selStart, &theStyle,
                    &lineHeight, &fontAscent, theDocument->theText);
    
    theFace = 0;
 
    switch (theItem)
    {
        case cPlain:
            theFace = 0;
            break;
        case cBold:
            theFace = bold;
            break;
        case cItalic:
            theFace = italic;
            break;
        case cUnderline:
            theFace = underline;
            break;
        case cOutline:
            theFace = outline;
            break;
        case cShadow:
            theFace = shadow;
            break;
        case cCondense:
            theFace = condense;
            break;
        case cExtend:
            theFace = extend;
            break;
    } // of switch
 
    if (theFace==0)
        err = BuildTypeTextStylesDesc(0, bold+italic+underline+outline+shadow+condense+extend, &result);
    else if (theFace & theStyle.tsFace)
        err = BuildTypeTextStylesDesc(0, theFace, &result);
    else
        err = BuildTypeTextStylesDesc(theFace, 0, &result);
    
    err = MakeSelfAddress(&selfAddr);
    
    if (err==noErr)
        err = MakeSelectedTextObj(theDocument->theWindow, theDocument->theText, &selTextObj);
    
    if (err==noErr)
        err = SendAESetObjProp(&selTextObj, pTextStyles, &result, &selfAddr);
        
    (void)AEDisposeDesc(&selTextObj);                                           
} // IssueStyleCommand
 
 
OSErr   IssueSetDataObjToBufferContents(const AEDesc* theObj)
{ 
    OSErr           myErr;
    AEAddressDesc   theAddress = { typeNull, NULL };
    AppleEvent      myAppleEvent = { typeNull, NULL };
    AppleEvent      defReply = { typeNull, NULL };
 
    myErr = MakeSelfAddress(&theAddress);
    
    // create event
    
    if (myErr==noErr)
        myErr = AECreateAppleEvent(kAECoreSuite, kAESetData, &theAddress,
                                                        0, 0, &myAppleEvent);
        
    // add prop obj spec to the event
    
    if (myErr==noErr)
        myErr = AEPutParamDesc(&myAppleEvent, keyDirectObject, theObj);
    
    // add prop data to the event
    
    if (myErr==noErr)
        myErr = AEPutParamPtr(&myAppleEvent, keyAEData, typeChar,
                                    (Ptr)gTypingBuffer, gCharsInBuffer);
                                                    
    // send event
    
    if (myErr==noErr)
     if (gRecordingImplemented)
         myErr = AESend(&myAppleEvent, &defReply, kAENoReply+kAEDontExecute,
                                    kAENormalPriority, kAEDefaultTimeout, nil, nil);
 
    (void)AEDisposeDesc(&theAddress);
    (void)AEDisposeDesc(&myAppleEvent);
        
    return(myErr);
}
 
void    AddKeyToTypingBuffer(DPtr theDocument, char theKey)
{
    OSErr myErr;
    OSErr ignoreErr;
    
    if (theKey==BS || theKey==FS || theKey==GS || theKey==RS || theKey==US)
    {
        FlushAndRecordTypingBuffer();
        if (theKey==BS)
        {
            if ((**theDocument->theText).selStart!=(**theDocument->theText).selEnd)
            {
                myErr = MakeTextObj(theDocument->theWindow,
                                    (**theDocument->theText).selStart,
                                    (**theDocument->theText).selEnd,
                                    &gTypingTargetObject);
            }
            else
            {
                myErr = MakeTextObj(theDocument->theWindow,
                                    (**theDocument->theText).selStart-1,
                                    (**theDocument->theText).selStart,
                                    &gTypingTargetObject);
            }
                
            myErr = IssueSetDataObjToBufferContents(&gTypingTargetObject);
            
            ignoreErr = AEDisposeDesc(&gTypingTargetObject);
            
            gTypingTargetObject.dataHandle = nil;
        }
    }
    else
    {
        if (gCharsInBuffer==0)
            myErr = MakeSelectedTextObj(theDocument->theWindow, theDocument->theText,
                                                                    &gTypingTargetObject);
 
        gTypingBuffer[gCharsInBuffer++] = theKey;
    }
}
 
void    FlushAndRecordTypingBuffer(void)
{ 
    OSErr  myErr;
    OSErr  ignoreErr;
 
    if (gCharsInBuffer != 0)
    {
        myErr = IssueSetDataObjToBufferContents(&gTypingTargetObject);
        
        if (gTypingTargetObject.dataHandle)
            ignoreErr = AEDisposeDesc(&gTypingTargetObject);
    }
        
    gCharsInBuffer = 0;
    gTypingTargetObject.dataHandle = 0;
}
 
    
void    StyleTokConst(short theStyleItem, DescType *thekConst)
{
    switch (theStyleItem)
    {
        case bold:
            *thekConst = kAEBold;
            break;
            
        case italic:
            *thekConst = kAEItalic;
            break;
            
        case underline:
            *thekConst = kAEUnderline;
            break;
            
        case outline:
            *thekConst = kAEOutline;
            break;
            
        case shadow:
            *thekConst = kAEShadow;
            break;
            
        case condense:
            *thekConst = kAECondensed;
            break;
            
        case extend:
            *thekConst = kAEExpanded;
            break;
    }
} // StyleTokConst
 
OSErr   BuildTypeTextStylesDesc(Style onStyles, Style offStyles, AEDesc *resultDesc)
{
 
    OSErr     myErr;
    short     myStyleItem;
    DescType  styleConst;
    AEDesc    onStylesDesc = { typeNull, NULL };
    AEDesc    offStylesDesc = { typeNull, NULL };
    AEDesc    dataDesc = { typeNull, NULL };
 
    myErr = AECreateList(nil, 0, true,  &dataDesc);
    
    myErr = AECreateList(nil, 0, false, &onStylesDesc);
    myErr = AECreateList(nil, 0, false, &offStylesDesc);
    
    for (myStyleItem = bold; myStyleItem<=extend; myStyleItem = myStyleItem <<1)
        if (myErr==noErr)
        {
            StyleTokConst(myStyleItem, &styleConst);
            if (myStyleItem & onStyles)
                myErr = AEPutPtr(&onStylesDesc,
                                    0,              // add to end of list
                                    typeEnumerated, // text for style name
                                    (Ptr)&styleConst,
                                    sizeof(styleConst));
            
            if (myStyleItem & offStyles)
                myErr = AEPutPtr(&offStylesDesc,
                                    0,              // add to end of list
                                    typeEnumerated, // text for style name
                                    (Ptr)&styleConst,
                                    sizeof(styleConst));
        }
    
    if (myErr==noErr)
        myErr = AEPutKeyDesc(&dataDesc, keyAEOnStyles,  &onStylesDesc);
    
    if (myErr==noErr)
        myErr = AEPutKeyDesc(&dataDesc, keyAEOffStyles, &offStylesDesc);
    
    if (myErr==noErr)
        myErr = AECoerceDesc(&dataDesc, typeTextStyles, resultDesc);
        
    (void)AEDisposeDesc(&onStylesDesc);
    (void)AEDisposeDesc(&offStylesDesc);
    (void)AEDisposeDesc(&dataDesc);
 
    return(myErr);
}
 
OSErr   BuildTextStylesDesc(Style theStyle, AEDesc *resultDesc)
{
    short     myStyleItem;
    Style     onStyles;
    Style     offStyles;
            
    onStyles  = 0;
    offStyles = 0;
    
    for (myStyleItem = bold; myStyleItem<=extend; myStyleItem = myStyleItem <<1)
    {
        if (myStyleItem & theStyle)
            onStyles  = onStyles  + myStyleItem;
        else
            offStyles = offStyles + myStyleItem;
    }
 
    return(BuildTypeTextStylesDesc(onStyles, offStyles, resultDesc));
    
} // BuildTextStylesDesc
        
OSErr   BuildStyledTextDesc(TEHandle theHTE, short start, short howLong, AEDesc *resultDesc)
{
    AEDesc       listDesc = { typeNull, NULL };
    short        oldSelStart;
    short        oldSelEnd;
    StScrpHandle myStScrpHandle;
    OSErr        myErr;
    
    oldSelStart = (**theHTE).selStart;
    oldSelEnd   = (**theHTE).selEnd;
    
    TESetSelect(start-1, start+howLong-2, theHTE);
    
    myErr = AECreateList(nil, 0, true,  &listDesc);
    
    HLock((Handle)(**theHTE).hText);
                                                     
    if (myErr == noErr)
        myErr = AEPutKeyPtr(&listDesc, keyAEText, typeChar,
                            (Ptr)&(*(**theHTE).hText)[start-1], howLong);
                                                
    HUnlock((Handle)(**theHTE).hText);
    
    myStScrpHandle = GetStylScrap(theHTE);
    
    if (myStScrpHandle)
    {
        HLock((Handle)myStScrpHandle);
        
        if (myErr==noErr)
            myErr = AEPutKeyPtr(&listDesc, keyAEStyles, typeScrapStyles,
                                    (Ptr)*myStScrpHandle, GetHandleSize((Handle)myStScrpHandle));
            
        HUnlock((Handle)myStScrpHandle);
 
        DisposeHandle((Handle)myStScrpHandle);
    }   
    else
        myErr = AEPutKeyPtr(&listDesc, keyAEStyles, typeScrapStyles, (Ptr)nil, 0);
    
    if (myErr==noErr)
        myErr = AECoerceDesc(&listDesc, typeStyledText, resultDesc); // should be typeIntlText
    
    (void)AEDisposeDesc(&listDesc);
    
    TESetSelect(oldSelStart, oldSelEnd, theHTE);
    
    return(myErr);
}