Source/SVEditMain.c

/*
    File:       SVEditMain.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/19/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                11/1/95     DS                      Made Changes for GX Printing.
                10/12/95    CW                      Added call to InitDragHandlers in DoSVEdit
                10/12/95    CW                      Changed MaintainCursor to make cursor arrow if over selected text
    
*/
 
#include <Memory.h>
#include <Quickdraw.h>
#include <Types.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 <Sound.h>
 
#include "SVEditMain.h"
 
#include "SVEditGlobals.h"
#include "SVEditUtils.h"
#include "SVAERecording.h"
#include "SVAppleEvents.h"
#include "SVEditWindow.h"
#include "SVEditFile.h"
#include "SVDrag.h"
 
 
/*-----------------------------------------------------------------------*/
/**----------                        Standard Main routines                  --------------**/
/*-----------------------------------------------------------------------*/
 
#pragma segment Main
 
    pascal 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
 
pascal void MaintainMenus(void)
    {
        DPtr       theDoc;
        WindowPtr  firstWindow;
 
        firstWindow = FrontWindow();
        if (!Ours(firstWindow))
            {
                EnableItem(myMenus[fileM], fmNew);
                EnableItem(myMenus[fileM], fmOpen);
                DisableItem(myMenus[fileM], fmClose);
                DisableItem(myMenus[fileM], fmSave);
                DisableItem(myMenus[fileM], fmSaveAs);
                DisableItem(myMenus[fileM], fmRevert);
                DisableItem(myMenus[fileM], fmPageSetUp);
 
                DisableItem(myMenus[fileM], fmNoGXPrint);
                                
                if (firstWindow)
                    {
                        EnableItem(myMenus[editM], undoCommand);
                        EnableItem(myMenus[editM], cutCommand);
                        EnableItem(myMenus[editM], copyCommand);
                        EnableItem(myMenus[editM], pasteCommand);
                        EnableItem(myMenus[editM], clearCommand);
                    }
            }
        else
            {
                theDoc = DPtrFromWindowPtr(firstWindow);
                EnableItem(myMenus[editM], pasteCommand);
                EnableItem(myMenus[fileM], fmClose);
                EnableItem(myMenus[fileM], fmSaveAs);
                EnableItem(myMenus[fileM], fmPageSetUp);
 
                EnableItem(myMenus[fileM], fmNoGXPrint);                
 
                if (theDoc->dirty)
                    EnableItem(myMenus[fileM], fmRevert);
                else
                    DisableItem(myMenus[fileM], fmRevert);
                    
                if ((theDoc->dirty) && (theDoc->everSaved))
                    EnableItem(myMenus[fileM], fmSave);
                else
                    DisableItem(myMenus[fileM], fmSave);
 
                DisableItem(myMenus[editM], undoCommand);
                
                if (((**(theDoc->theText)).selEnd - (**(theDoc->theText)).selStart) < 0)
                    {
                        DisableItem(myMenus[editM], cutCommand);
                        DisableItem(myMenus[editM], copyCommand);
                        DisableItem(myMenus[editM], clearCommand);
                    }
                else
                    {
                        EnableItem(myMenus[editM], cutCommand);
                        EnableItem(myMenus[editM], copyCommand);
                        EnableItem(myMenus[editM], clearCommand);
                    }
    }
    
}
 
#pragma segment Main
 
pascal void SetUpCursors(void)
 
    {
        CursHandle  hCurs;
 
        hCurs = GetCursor(1);
        editCursor = **hCurs;
        hCurs = GetCursor(watchCursor);
        waitCursor = **hCurs;
    }
 
#pragma segment Main
 
pascal void SetUpMenus(void)
    {
        short i;
        
        myMenus[appleM] = GetMenu(appleID);
        AppendResMenu(myMenus[appleM], 'DRVR');
        myMenus[fileM] = GetMenu(fileID);
        myMenus[editM] = GetMenu(editID);
        myMenus[fontM] = GetMenu(mfontID);
        AppendResMenu(myMenus[fontM], 'FONT');
        myMenus[sizeM]  = GetMenu(sizeID);
        myMenus[styleM] = GetMenu(styleID);
 
        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() */
    }
 
pascal void DoFile(short theItem)
    {       
        short   alertResult;
        DPtr    theDoc = nil;
        FSSpec  theFSSpec;
        OSErr   fileErr;
        TPrint  thePSetup;
        
        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 (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;
        }                /*of switch*/
    }
 
#pragma segment Main
 
pascal void DoCommand(long mResult)
    {
        short   theItem;
        short   err;
        long    result;
        Str255  name;
        DPtr    theDocument;
 
        theDocument = DPtrFromWindowPtr(FrontWindow());
        
        theItem = LoWord(mResult);
 
        switch (HiWord(mResult)){
 
            case appleID:
                if (theItem == aboutItem)
                    {
                        SetCursor(&qd.arrow);
                        result = Alert(258, nil);
                    }
                else
                    {
                        GetMenuItemText(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;
                        }    /*of switch*/
                        ShowSelect(theDocument);
                    }
          break;
 
            case mfontID: IssueFontCommand(theDocument, theItem);
                            break;
 
            case sizeID: IssueSizeCommand(theDocument, theItem);
                            break;
 
            case styleID: IssueStyleCommand(theDocument, theItem);
                             break;
 
        }                /*of switch*/
 
        HiliteMenu(0);
 
    }
 
#pragma segment Main
 
 
    pascal void DoMouseDown(const EventRecord *myEvent)
        {
            WindowPtr whichWindow;
            Point     p;
            Rect      dragRect;
            DPtr      theDoc;
 
            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);
                                                }
                    
                                            DoCommand(MenuSelect(p));
                                            HiliteMenu(0);
                                            break;
 
                case inSysWindow: SystemClick(myEvent, whichWindow);
                                  break;
 
                case inDrag:
                    
                        dragRect = qd.screenBits.bounds;
                        
                        if (Ours(whichWindow))
                            {
                                DragWindow(whichWindow, p, &dragRect);
                                /*
                                    As rgnBBox may be passed by address
                                */
                                dragRect = (**((WindowPeek)whichWindow)->strucRgn).rgnBBox;
                                /*
                                    The windows already there, but still tell
                                    the our AppleEvents core about the move in case
                                    they want to do anything
                                */
                                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;
            }                /*of switch*/
        }
 
#pragma segment Main
 
pascal long GetSleep(void)
    {
        long      sleep;
        WindowPtr theWindow;
        DPtr      theDoc;
 
        sleep = 0x7fffffff;
        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)
                                {
                                    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 kOSEvent:
                
                switch (myEvent->message & osEvtMessageMask) { /*high byte of message*/
                    case 0x01000000:
                        {
                            gInBackground = ((myEvent->message & resumeFlag) == 0);
                            DoActivate(FrontWindow(), !gInBackground);
                        }
                }
            } /*of switch*/
    }
    
#pragma segment Main
 
pascal void MainEvent(void)
    {
        EventRecord myEvent;
 
        MaintainCursor(); /* TEIdle in here for now */
        MaintainMenus();
 
        if (WaitNextEvent(everyEvent, &myEvent, GetSleep(), nil))
            HandleOneEvent( &myEvent );
        }
 
#pragma segment Main
 
pascal void DoSVEdit(void)
    {
        OSErr  err;
        short  result;
 
        InitGraf(&qd.thePort);
        InitFonts();
        FlushEvents(everyEvent, 0);
        InitWindows();
        InitMenus();
        TEInit();
        InitDialogs(nil);
        InitCursor();
 
        MaxApplZone();
        SetUpCursors();
 
        SetUpMenus();
 
        gWCount    = 0;
        gNewDocCount = 0;
        gQuitting  = false;
        gFontMItem = 0;
 
        gGestaltAvailable          = false;
        gAppleEventsImplemented    = false;
        gAliasManagerImplemented   = false;
        gEditionManagerImplemented = false;
        gOutlineFontsImplemented   = 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(302, nil);
                return;
            }
 
        err = InitEditionPack();
 
        if (err)
            {
                ShowError((unsigned char *)"\pInitEditionPack", err);
                gQuitting = true;
            }
 
        err = AEObjectInit();
        if (err)
            {
                ShowError((unsigned char *)"\pAEObjectInit", err);
                gQuitting = true;
            }
 
        InitAppleEvents();
 
        err = PPCInit();
        if (err)
            {
                ShowError((unsigned char *)"\pPPCInit", err);
                gQuitting = true;
            }
            
            
        err = InitDragHandlers ( );
        if (err)
            {
                ShowError((unsigned char *)"\pInitDragHandlers", err);
                gQuitting = true;
            }
        
            
        /* 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);
 
 
        while (!gQuitting)
            MainEvent();
    }
    
void main ()
    {
        /*the main routine starts here*/
        DoSVEdit();
    }