Sources/MSMain.c

// MSMain.c
//
// Original version by Jon Lansdell and Nigel Humphreys.
// 4.0 and 3.1 updates by Greg Sutton.
// Human Interface changes and GX Printing by Don Swatman
// ©Apple Computer Inc 1996, all rights reserved.
 
/*  
    Changes for 3.1
 
    12-Oct-95 : CW : Added call to InitDragHandlers in DoMenuScripter
    12-Oct-95 : CW : Changed MaintainCursor to make cursor arrow if over selected text
    1-Nov-95  : DS : Made Changes for GX Printing.
 
    Changes for 4.0
 
    26-Feb-96 : DS : Improved Edit Menu Handling
    28-Feb-96 : GS : Checked that window did actually move before sending a
                        move event in IssueMoveWindow()
*/
 
#include <Memory.h>
#include <Quickdraw.h>
#include <Menus.h>
#include <Windows.h>
#include <Dialogs.h>
#include <Traps.h>
#include <Packages.h>
#include <PPCToolBox.h>
#include <Editions.h>
#include <Printing.h>
#include <ToolUtils.h>
#include <Desk.h>
#include <Scrap.h>
#include <OSEvents.h>
#include <AppleEvents.h>
#include <AEObjects.h>
#include <Errors.h>
#include <limits.h>
 
#include "MSMain.h"
 
#include "MSScript.h"
#include "MSASSubroutines.h"
#include "MSGlobals.h"
#include "MSUtils.h"
#include "MSAERecording.h"
#include "MSAppleEvents.h"
#include "MSWindow.h"
#include "MSFile.h"
#include "MSDrag.h"
#include "MSGXPrinting.h"
#include "MSResultWind.h"
#include "MSAEWindowUtils.h"
 
 
    // Prototypes
void    MaintainCursor( void );
void    SetUpCursors( void );
void    SetUpMenus( void );
void    InitApplicationRec( void );
 
void    DoFile( short theItem );
void    DoMouseDown( const EventRecord *myEvent );
long    GetSleep( void );
void    HandleOneEvent( EventRecord *myEvent );
void    MainEvent( void );
 
void    DoMenuScripter( void );
 
    // Constants
const   short   NeedSys7Alert   = 302;
const   short   AboutAlert      = 258;
 
 
#pragma segment Main
 
void    MaintainCursor( void )
{
    Point     pt;
    WindowPtr wPtr;
    GrafPtr   savePort;
    DPtr      theDoc;
 
    wPtr = FrontWindow();
    if (Ours(wPtr))
    {
        theDoc = DPtrFromWindowPtr(wPtr);
        GetPort(&savePort);
        SetPort(wPtr);
        GetMouse(&pt);
        if (theDoc->theText)
            if ( PtInRect ( pt, &(**(theDoc->theText)).viewRect ) &&
                                            ! PointInWindowSelection ( pt, wPtr ) )
                SetCursor(&editCursor);
            else
                SetCursor(&qd.arrow);
        else
            SetCursor(&qd.arrow);
 
        if (theDoc->theText)
            TEIdle(theDoc->theText);
 
        SetPort(savePort);
    }
}
 
#pragma segment Main
 
void MaintainEditItems( TEHandle           theTE,
                        short              numTypes,
                        ConstSFTypeListPtr typeList )
{
    Boolean enableItems;
    short   itemCount;
    long    offset;
    
        // If something is selected then enable cut, copy and clear
    enableItems = false;
    if (theTE)
        if ( (*theTE)->selStart < (*theTE)->selEnd)
            enableItems = true;
        
    SetMenuItemState ( enableItems, myMenus[editM], cutCommand);
    SetMenuItemState ( enableItems, myMenus[editM], copyCommand);
    SetMenuItemState ( enableItems, myMenus[editM], clearCommand );
 
        // if the appropriate type is in scrap, then enable the pasteCommand
    enableItems = false;
    itemCount = 0;
    while ((itemCount < numTypes) && !enableItems)
    {
        enableItems = GetScrap ( nil, typeList[itemCount], &offset);
        ++itemCount;
    }
    
    SetMenuItemState ( enableItems, myMenus[editM], pasteCommand );
}
 
 
void    MaintainMenus( Boolean *pRedrawMenuBar )
{
    DPtr       theDoc;
    WindowPtr  firstWindow;
    SFTypeList myTypes = {'TEXT'};
 
    firstWindow = FrontWindow( );
    if ( ! Ours( firstWindow ) )
    {
        SetMenuItemState( true, myMenus[fileM], fmNew );
        SetMenuItemState( true, myMenus[fileM], fmOpen );
        SetMenuItemState( false, myMenus[fileM], fmClose );
        SetMenuItemState( false, myMenus[fileM], fmSave );
        SetMenuItemState( false, myMenus[fileM], fmSaveAs );
        SetMenuItemState( false, myMenus[fileM], fmRevert );
        SetMenuItemState( false, myMenus[fileM], fmPageSetUp );
        SetMenuItemState( false, myMenus[scriptM], cCompile );
        SetMenuItemState( false, myMenus[scriptM], cExecute );
        
        SetMenuItemState( false, myMenus[scriptM], cResultWindow);
 
        if ( gGXIsPresent )
        {
            SetMenuItemState( false, myMenus[fileM], fmPrint );
            SetMenuItemState( false, myMenus[fileM], fmPrintOne );
        }
        else
            SetMenuItemState( false, myMenus[fileM], fmNoGXPrint );
                        
        if (firstWindow)
        {
            SetMenuItemState( true, myMenus[editM], undoCommand );
            SetMenuItemState( true, myMenus[editM], cutCommand );
            SetMenuItemState( true, myMenus[editM], copyCommand );
            SetMenuItemState( true, myMenus[editM], pasteCommand );
            SetMenuItemState( true, myMenus[editM], clearCommand );
        }
    }
    else
    {
        theDoc = DPtrFromWindowPtr( firstWindow );
 
        if ( theDoc->windowType == kOrdinaryWind )
        {
            *pRedrawMenuBar |= SetMenuItemState( true, myMenus[fontM], kMenuTitle );
            *pRedrawMenuBar |= SetMenuItemState( true, myMenus[sizeM], kMenuTitle );
            *pRedrawMenuBar |= SetMenuItemState( true, myMenus[styleM], kMenuTitle );
 
            SetMenuItemState ( true, myMenus[fileM], fmClose );
            SetMenuItemState ( true, myMenus[fileM], fmSaveAs );
    
            SetMenuItemState( true, myMenus[fileM], fmPageSetUp );
    
            if (gGXIsPresent)
            {
                SetMenuItemState( true, myMenus[fileM], fmPrint );
                SetMenuItemState( true, myMenus[fileM], fmPrintOne );
            }
            else
                SetMenuItemState( true, myMenus[fileM], fmNoGXPrint );              
    
            if (theDoc->dirty)
                SetMenuItemState( true, myMenus[fileM], fmRevert );
            else
                SetMenuItemState( false, myMenus[fileM], fmRevert );
                
            if ((theDoc->dirty) && (theDoc->everSaved))
                SetMenuItemState( true, myMenus[fileM], fmSave );
            else
                SetMenuItemState( false, myMenus[fileM], fmSave );
    
            SetMenuItemState( false, myMenus[editM], undoCommand );
            
            SetMenuItemState( true, myMenus[editM], selectAllCommand );
    
            SetMenuItemState( true, myMenus[scriptM], cCompile );
            SetMenuItemState( true, myMenus[scriptM], cExecute );
            
            EnableAEScriptItems( true );
            
            MaintainEditItems( theDoc->theText, 1, myTypes );
        }
        else
        {
            *pRedrawMenuBar |= SetMenuItemState( false, myMenus[fontM], kMenuTitle );
            *pRedrawMenuBar |= SetMenuItemState( false, myMenus[sizeM], kMenuTitle );
            *pRedrawMenuBar |= SetMenuItemState( false, myMenus[styleM], kMenuTitle );
 
            SetMenuItemState( true, myMenus[fileM], fmClose );
            
            SetMenuItemState( false, myMenus[fileM], fmSaveAs );
            SetMenuItemState( false, myMenus[fileM], fmSave );
    
            SetMenuItemState( true, myMenus[fileM], fmPageSetUp );
    
            if ( gGXIsPresent )
            {
                SetMenuItemState( true, myMenus[fileM], fmPrint );
                SetMenuItemState( true, myMenus[fileM], fmPrintOne );
            }
            else
                SetMenuItemState( true, myMenus[fileM], fmNoGXPrint );              
    
            SetMenuItemState( false, myMenus[fileM], fmRevert );
    
            SetMenuItemState( false, myMenus[editM], pasteCommand );
            SetMenuItemState( false, myMenus[editM], undoCommand );
            SetMenuItemState( false, myMenus[editM], cutCommand );
            SetMenuItemState( false, myMenus[editM], copyCommand );
            SetMenuItemState( false, myMenus[editM], clearCommand );
            SetMenuItemState( false, myMenus[editM], selectAllCommand );
 
            SetMenuItemState( false, myMenus[scriptM], cCompile );
            SetMenuItemState( false, myMenus[scriptM], cExecute );
            
            EnableAEScriptItems( false );
        }
 
        SetMenuItemState( true, myMenus[scriptM], cResultWindow );
        
        if ( IsThereAResultWind( ) )
            SetItemMark( myMenus[scriptM], cResultWindow, checkMark );
        else
            SetItemMark( myMenus[scriptM], cResultWindow, noMark );
    }
 
    if ( *pRedrawMenuBar )
    {
        DrawMenuBar( );
        *pRedrawMenuBar = false;
    }
}
 
 
#pragma segment Main
 
void    SetUpCursors( void )
{
    CursHandle  hCurs;
 
    hCurs = GetCursor( iBeamCursor );
    editCursor = **hCurs;
    hCurs = GetCursor( watchCursor );
    waitCursor = **hCurs;
}
 
#pragma segment Main
 
void    SetUpMenus( void )
{
    short i;
    
    myMenus[appleM] = GetMenu( appleID );
    AddResMenu( myMenus[appleM], 'DRVR' );
    myMenus[fileM] = GetMenu( fileID );
    myMenus[editM] = GetMenu( editID );
    myMenus[fontM] = GetMenu( mfontID );
    AddResMenu( myMenus[fontM], 'FONT' );
    myMenus[sizeM]  = GetMenu( sizeID );
    myMenus[styleM] = GetMenu( styleID );
    myMenus[scriptM] = GetMenu( mscriptID );
    myMenus[subroutineM] = GetMenu( subroutineID );
 
    for (i = appleM; i <= kLastMenu; i++)
        InsertMenu( myMenus[i], 0 );
 
    SetItemStyle( myMenus[styleM], cPlain, 0 );
    SetItemStyle( myMenus[styleM], cBold, bold );
    SetItemStyle( myMenus[styleM], cItalic, italic );
    SetItemStyle( myMenus[styleM], cUnderline, underline );
    SetItemStyle( myMenus[styleM], cOutline, outline );
    SetItemStyle( myMenus[styleM], cShadow, shadow );
    SetItemStyle( myMenus[styleM], cCondense, condense );
    SetItemStyle( myMenus[styleM], cExtend, extend );
 
    SetShortMenus( ); /* Does a DrawMenuBar() */
}
 
void    CheckMenus( void )
{
    static long lastCount = -1; // -1 for first time through
    long        nowCount = CountDocuments( );
 
    if ( lastCount < 0
            || ( ! lastCount && nowCount )
                || ( lastCount && ! nowCount ) )
    {
        if ( CountDocuments( ) > 0 )
            SetLongMenus( );
        else
            SetShortMenus( );
    }
    
    lastCount = nowCount;
}
 
 
//  Use process manager to find the volume and directory of this application.
 
void    InitApplicationRec( void )
{
    ProcessSerialNumber     PSN;
    ProcessInfoRec          info;
    OSErr                   err;
    
    gAppRec.theScriptID = kOSANullScript;
 
    err = GetCurrentProcess( &PSN );
 
    if ( noErr == err )
    {
        info.processName = gAppRec.theName;
        info.processAppSpec = &gAppRec.theSpec;
 
        err = GetProcessInformation( &PSN, &info );
    }
}
 
 
void    DoFile( short theItem )
{       
    short   alertResult;
    DPtr    theDoc = nil;
    FSSpec  theFSSpec;
    OSErr   fileErr;
    TPrint  thePSetup;
    
    theItem = ConvertMenuActualToGXMenu ( theItem );
 
    switch (theItem)
    {
        case fmNew :
            IssueAENewWindow( );
            break;
 
        case fmOpen:
            if ( GetFile( &theFSSpec ) == noErr )
                fileErr = IssueAEOpenDoc( theFSSpec );
            break;
 
        case fmClose:
            IssueCloseCommand( FrontWindow( ) );
            break;
 
        case fmSave:
        case fmSaveAs:
            theDoc = DPtrFromWindowPtr( FrontWindow( ) );
                
            if (theDoc->everSaved == false || theItem == fmSaveAs)
            {
                fileErr = GetFileNameToSaveAs(theDoc);
                if (fileErr == userCanceledErr)
                    break;
                else if (fileErr != noErr)
                    FileError((unsigned char *)"\pError saving ", theDoc->theFileName);
                else
                    fileErr = IssueSaveCommand(theDoc->theWindow, &theDoc->theFSSpec);
            
                if (fileErr == noErr)
                {
                    SetWTitle(theDoc->theWindow, theDoc->theFSSpec.name);
                    theDoc->everSaved = true;
                }
            }
            else
                fileErr = IssueSaveCommand(theDoc->theWindow, nil);
            break;
 
        case fmRevert:
            alertResult = DoFileDialog ( kRevertDialog, FrontWindow ( ) );
            if ( alertResult == kStdOkItemIndex )
            {
                if (IssueRevertCommand(theDoc->theWindow))
                    FileError((unsigned char *)"\pError reverting ", theDoc->theFileName);
            }
            break;
 
        case fmPageSetUp:
            theDoc = DPtrFromWindowPtr(FrontWindow());
            if (gGXIsPresent)
            {
                if (DoGXPageSetup(theDoc))
                    IssueGXPageSetupWindow(theDoc->theWindow, theDoc->documentJob);
            }
            else if (DoPageSetup(theDoc))
            {
                thePSetup = **(theDoc->thePrintSetup);
                IssuePageSetupWindow(theDoc->theWindow, thePSetup);
            }
            break;
 
        case fmPrint:
            IssuePrintWindow(FrontWindow(),kUsePrintDialog);
            break;
            
        case fmPrintOne:
            IssuePrintWindow(FrontWindow(),kNoPrintDialog);
            break;
 
        case fmQuit:
            IssueQuitCommand();
            break;
    } // End of switch
}
 
 
#pragma segment Main
 
void    DoCommand( long mResult )
{
    DoMenuItem( HiWord( mResult ), LoWord( mResult ) );
}
 
void    DoMenuItem( short theMenuID, short theItem )
{
    long        result;
    Str255      name;
    DPtr        theDocument;
    Boolean     exists;
    Boolean     useOldCode;
    Boolean     wasDirty;
    short       err;
 
    theDocument = DPtrFromWindowPtr( GetNthDocument( 1 ) );
 
    err = ScriptForMenuExists( theMenuID, theItem, &exists );
 
    if ( err == noErr && exists == true )
    {
        err = ExecuteScriptForMenu( theMenuID, theItem );
        useOldCode = ( noErr != err && errOSAScriptError != err );
    }
    else
        useOldCode = true;
        
    if ( ! useOldCode )     // Script did whatever without error or no script
        return;
 
    switch ( theMenuID )
    {
        case appleID:
            if (theItem == aboutItem)
            {
                SetCursor(&qd.arrow);
                result = Alert( AboutAlert, NULL );
            }
            else
            {
                GetItem(myMenus[appleM], theItem, name);
                err = OpenDeskAcc(name);
                SetPort(FrontWindow());
            }
            break;
            
        case fileID:
            DoFile(theItem);
            break;
 
        case editID:
            if (SystemEdit(theItem - 1) == false)
            {
                switch (theItem)
                {
                    case cutCommand:
                        IssueCutCommand(theDocument);
                        break;
                                                 
                    case copyCommand:
                        IssueCopyCommand(theDocument);
                        break;
                                                 
                    case pasteCommand:
                        IssuePasteCommand(theDocument);
                        break;
                                                 
                    case clearCommand:
                        IssueClearCommand(theDocument);
                        break;
                                                 
                    case selectAllCommand:
                        if (theDocument)
                            TESetSelect(0, (**(theDocument->theText)).teLength, theDocument->theText);
                       break;
                }
                
                ShowSelect(theDocument);
            }
            break;
 
        case mfontID:
            IssueFontCommand(theDocument, theItem);
            break;
 
        case sizeID:
            IssueSizeCommand(theDocument, theItem);
            break;
 
        case styleID:
            IssueStyleCommand(theDocument, theItem);
            break;
 
        case mscriptID:
            switch (theItem)
            {
                case cCompile:
                    CompileDocument(theDocument);
                    break;
 
                case cExecute:
                    ExecuteDocument(theDocument);
                    break;
 
                case cResultWindow:
                    if ( IsThereAResultWind( ) )
                        IssueCloseCommand( GetResultsWindPtr( ) );
                    else
                        OpenResultWind( );
                    break;
            }
            break;
            
        case subroutineID:
            switch ( theItem )
            {
                case cScript1:
                    ExecuteScript1(theDocument);
                    break;
 
                case cScript2:
                    ExecuteScript2(theDocument);
                    break;
                
                case cScript3:
                    ExecuteScript3(theDocument);
                    break;
                
                case cScript4:
                    wasDirty = theDocument->dirty;
                    theDocument->dirty = true;
                    DoFile(fmSaveAs);
                    
                    if (! theDocument->dirty)
                    ExecuteScript4(theDocument);
 
                    else
                    theDocument->dirty = wasDirty;
                    break;
            }
            break;
    }
 
    HiliteMenu(0);
}
 
#pragma segment Main
 
 
void    DoMouseDown( const EventRecord *myEvent )
{
    WindowPtr   whichWindow;
    Point       p;
    Rect        dragRect,
                oldRect = { 0, 0, 0, 0 };
    DPtr        theDoc;
    long        menuResult;
    Boolean     scriptExists;
    OSErr       err;
 
    p = myEvent->where;
    switch ( FindWindow( p, &whichWindow ) )
    {
        case inDesk:
            SysBeep(10);
            break;
 
        case inGoAway:
            if ( Ours( whichWindow ) )
                if ( TrackGoAway( whichWindow, p ) )
                    IssueCloseCommand(whichWindow);
            break;
 
        case inMenuBar:
            SetCursor( &qd.arrow );
            theDoc = DPtrFromWindowPtr( FrontWindow( ) );
            if ( theDoc )
                SetFontMenu( theDoc );
            
            menuResult = MenuSelect( p );
 
                // Check for script editing -
                // ctrl+option when selecting the menu = Edit Script (if any)
            
            if ( OptionKeyPressed( myEvent )  && CtrlKeyPressed( myEvent ) )
            {
                err = ScriptForMenuExists( HiWord( menuResult ),
                                        LoWord( menuResult ), &scriptExists );
 
                if ( scriptExists && noErr == err )
                    EditMenuScript( HiWord( menuResult ), LoWord( menuResult ) );
                else
                    SysBeep( 10 );
            }
            else
                DoCommand( menuResult );
 
            HiliteMenu( 0 );
            break;
 
        case inSysWindow:
            SystemClick(myEvent, whichWindow);
            break;
 
        case inDrag:
            dragRect = qd.screenBits.bounds;
            
            if ( Ours( whichWindow ) )
            {
                (void)GetWindowBounds( whichWindow, &oldRect );
            
                DragWindow( whichWindow, p, &dragRect );
 
                //  As rgnBBox may be passed by address
 
                (void)GetWindowBounds( whichWindow, &dragRect );
 
                //  The windows already there, but still tell
                //  the our AppleEvents core about the move in case
                //  they want to do anything
                
                if ( ! EqualRect( &oldRect, &dragRect ) )
                 IssueMoveWindow( whichWindow, &dragRect );
            }
            break;
 
        case inGrow:
            SetCursor(&qd.arrow);
            if (Ours(whichWindow))
                MyGrowWindow(whichWindow, p);
            break;
                            
        case inZoomIn:
            DoZoom(whichWindow, inZoomIn, p);
            break;
 
        case inZoomOut:
            DoZoom(whichWindow, inZoomOut, p);
            break;
            
        case inContent:
            if (whichWindow != FrontWindow())
                SelectWindow(whichWindow);
            else if (Ours(whichWindow))
                DoContent(whichWindow, *myEvent);
            break;
    } // End of switch
}
 
#pragma segment Main
 
long    GetSleep( void )
{
    long      sleep;
    WindowPtr theWindow;
    DPtr      theDoc;
 
    sleep = LONG_MAX;
    if ( ! gInBackground )
    {
        theWindow = FrontWindow();
        if (theWindow)
            if (Ours(theWindow))
            {
                theDoc = DPtrFromWindowPtr(theWindow);
                if ((**(theDoc->theText)).selStart == (**(theDoc->theText)).selEnd)
                    sleep = GetCaretTime();
            }
    }
 
    return sleep;
} // GetSleep
 
#pragma segment Main
 
void    HandleOneEvent( EventRecord *myEvent )
{
    DPtr        theDoc;
    char        theChar;
    WindowPtr   theWindow;
    Boolean     activate;
    
    switch (myEvent->what)
    {
        case mouseDown:
            FlushAndRecordTypingBuffer();
            DoMouseDown(myEvent);
            break;
            
        case keyDown:
        case autoKey:
            theDoc = DPtrFromWindowPtr(FrontWindow());
            
            theChar = myEvent->message & charCodeMask;
            
            if ((myEvent->modifiers & cmdKey) == cmdKey)
            {
                DoCommand(MenuKey(theChar));
                HiliteMenu(0);
            }
            else if ( ( theDoc->theText ) && ( theDoc->windowType == kOrdinaryWind ) )
            {
                AddKeyToTypingBuffer(theDoc, theChar);
                
                TEKey(theChar, theDoc->theText);
                AdjustScrollbars(theDoc, false);
        
                ShowSelect(theDoc);
                
                theDoc->dirty = true;
            }
            break;
            
        case activateEvt:
            activate = ((myEvent->modifiers & activeFlag) != 0);
            theWindow = (WindowPtr)myEvent->message;
            DoActivate(theWindow, activate);
            break;
 
        case updateEvt:
            DoUpdate ( (WindowPtr) myEvent->message );
            break;
 
        case kHighLevelEvent:
            FlushAndRecordTypingBuffer();
            DoAppleEvent(*myEvent);
            break;
 
        case osEvt:
            if ( ( myEvent->message >> 24 ) & suspendResumeMessage )    // suspend or resume
            {
                gInBackground = ( ( myEvent->message & resumeFlag ) == 0 );
                DoActivate( FrontWindow( ), ! gInBackground );
            }
            break;
    }
}
    
#pragma segment Main
 
void    MainEvent( void )
{
    EventRecord myEvent;
    Boolean     redrawMenuBar = false;
    
    MaintainCursor(); // TEIdle in here for now
    MaintainMenus( &redrawMenuBar );
    
    if (WaitNextEvent(everyEvent, &myEvent, GetSleep(), nil))
        HandleOneEvent( &myEvent );
}
 
#pragma segment Main
 
OSErr GXPrintingEventOverride(EventRecord *anEvent, Boolean filterEvent)
{
    // Handle events in whatever way is appropriate. MyDoEvent is
    //  our generic event handler. We don't pass it events that it
    //  shouldn't handle while printing dialogs are displayed.
 
    if (!filterEvent)
        switch (anEvent->what) {
            case mouseDown:
            case keyDown:
            case autoKey:
                break;
            default:
                HandleOneEvent( anEvent );
        }
    return noErr;
}
 
#pragma segment Main
 
void    DoMenuScripter( void )
{
    OSErr  err;
    short  result;
 
    InitGraf( &qd.thePort );
    InitFonts( );
    FlushEvents( everyEvent, 0 );
    InitWindows( );
    InitMenus( );
    TEInit( );
    InitDialogs( NULL );
    InitCursor( );
 
    MaxApplZone( );
    SetUpCursors( );
    
    SetCursor( &waitCursor );
 
    err = TEFromScrap();    // Get the Scrap
 
    SetUpMenus( );
 
    gNewDocCount    = 0;
    gFontMItem      = 0;
 
    gQuitting                   = false;
 
    gGestaltAvailable           = false;
    gAppleEventsImplemented     = false;
    gAliasManagerImplemented    = false;
    gEditionManagerImplemented  = false;
    gOutlineFontsImplemented    = false;
    gGXIsPresent                = false;
 
        // Check environment checks to see if we are running 7.0
    if ( ! CheckEnvironment( ) )
    {
        SetCursor( &qd.arrow );
            // Pose the only 7.0 alert
        result = Alert( NeedSys7Alert, NULL );
        return;
    }
    
        // Do before InitEditorScripting() and SetUpScripts()
    InitApplicationRec( );
 
        // Init GX Printing
    InitGXIfPresent( );
 
    err = AEObjectInit( );
    if ( noErr != err )
    {
        ShowError((unsigned char *)"\pAEObjectInit", err);
        goto done;
    }
 
    InitAppleEvents( );
 
    err = PPCInit( );
    if ( noErr != err )
    {
        ShowError((unsigned char *)"\pPPCInit", err);
        goto done;
    }
        
    err = InitDragHandlers( );
    if ( noErr != err )
    {
        ShowError((unsigned char *)"\pInitDragHandlers", err);
        goto done;
    }
    
    err = InitEditorScripting( );
    if ( noErr != err )
    {
        ShowError((unsigned char *)"\pInitEditorScripting", err);
        goto done;
    }
    
    SetUpScripts( );
                              
    SetOSAActiveProcedure( );   // Set after all of our scripts are loaded
        
    // Create the UPPs for the control tracking routines
    //  globals, since we don't want to have to create and dispose of the routine
    //  descriptors each time we call DoContent
    gHScrollActionUPP = NewControlActionProc ( HActionProc );
    gVScrollActionUPP = NewControlActionProc ( VActionProc );
    
    // Create a UPP for drawing a dialog's default button. Again, make it a global
    //  for convenience
    gDefaultButtonUPP = NewUserItemProc( DrawDefaultOutline );
 
    SetCursor( &qd.arrow );
 
    while ( ! gQuitting )
        MainEvent( );
 
    SetCursor( &waitCursor );
 
done:
    (void)CleanUpAEScripts( );
    (void)CloseEditorScripting( );
    CleanUpGXIfPresent( );
}
    
void    main( )
{
    // The main routine starts here
    DoMenuScripter();
}