MyApplication Shell (2.0).c

/*
    File:       MyApplication Shell (2.0).c
    
    Contains:   My Application Shell.
 
    Written by: John Wang
 
    Copyright:  © 1994 by Apple Computer, Inc., all rights reserved.
 
    Change History (most recent first):
 
        <1>     03/14/94    JW      Re-Created for Universal Headers.
 
    To Do:
    
*/
 
#ifdef THINK_C
#define     applec
#endif
 
#include    <Types.h>
#include    <Memory.h>
#include    <QuickDraw.h>
#include    <Palettes.h>
#include    <QDOffscreen.h>
#include    <Errors.h>
#include    <Fonts.h>
#include    <Dialogs.h>
#include    <Windows.h>
#include    <Menus.h>
#include    <Events.h>
#include    <Desk.h>
#include    <DiskInit.h>
#include    <OSUtils.h>
#include    <Resources.h>
#include    <ToolUtils.h>
#include    <AppleEvents.h>
#include    <EPPC.h>
#include    <GestaltEqu.h>
#include    <Processes.h>
#include    <Balloons.h>
#include    <Aliases.h>
#include    <MixedMode.h>
#include    <Scrap.h>
#include    <LowMem.h>
 
#include    "MyApplication Shell (2.0).h"
#include    "MyApplication.h"
 
#ifdef powerc
QDGlobals       qd;
#endif
 
Boolean         gDoneFlag;          //  Set to true if you want to Application to kindly quit.
Boolean         gHasAppleEvents;    //  true if Gestalt returns saying AppleEvents is available.
short           gScrapCount;        //  Keep track of scrap count.
OSType          gScrapType;         //  Needed to know what type scrap it is.
Handle          gScrap;             //  Must keep a handle to the scrap for update events that
                                    //  happen in the background.  The reason is that when the app
                                    //  is in the background, it does not have access to GetScrap().
 
/* ------------------------------------------------------------------------- */
 
void main()
{
    EventRecord     myEvent;
    long            yieldTime;
    WindowPtr       foundWindow;
    short           windowPart;
    Boolean         isEvent;
    GrafPtr         savePort;
    GDHandle        saveGD;
    PScrapStuff     myScrapStuff;
 
    //  Initialize here.  Set the yield time too.
    Initialize();
    yieldTime = MyYieldTime(suspendResumeMessage);
 
    //  Event loop.
    for ( ; ; ) {
 
        //  Get the event.
        isEvent = WaitNextEvent(everyEvent, &myEvent, yieldTime, nil);
 
        //  Allow application specific event handling.  We have three cases:
        //      MYEVENTDEF == 2: MyEvent gets called for each window.
        //      MYEVENTDEF == 1: MyEvent gets once with window parameter = nil.
        //      MYEVENTDEF == 0: MyEvent never gets called.
        //  MyEvent returns true to indicate that the event is handled and can be ignored.
        //  As the safe thing to do, we always set the port if we know what window is being used.
        #if kMYEVENTDEF == 2
            if ( isEvent ) {
                foundWindow = (WindowPtr) LMGetWindowList();
                while ( foundWindow != nil ) {
                    if ( IsMyWindow(foundWindow) ) {
                        GetPort(&savePort);
                        saveGD = GetGDevice();
                        SetPort(foundWindow);
                        SetGDevice(GetMainDevice());
                        if ( MyEvent(foundWindow, &myEvent) )
                            isEvent = false;
                        SetPort(savePort);
                        SetGDevice(saveGD);
                    }
                    foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
                }
            }
        #elif kMYEVENTDEF == 1
            if ( isEvent ) {
                if ( MyEvent(nil, &myEvent) ) {
                    isEvent = false;
                }
            }
        #elif kMYEVENTDEF == 0
        #endif
        
        //  If the event is unhandled by app specific event handling, then we proceed.
        if ( isEvent ) {
            switch ( myEvent.what ) {
 
                case mouseDown:
                    //  Get current port and device.
                    GetPort(&savePort);
                    saveGD = GetGDevice();
                    
                    //  Set the port and gdevice to the window if we own the window.
                    //  We can then assume anytime the event occured in one of our windows,
                    //     that the port and gdevice are set correctly.
                    windowPart = FindWindow(myEvent.where, &foundWindow);
                    if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
                        SetPort(foundWindow);
                        SetGDevice(GetMainDevice());
                    }
                    
                    //  Handle the different mouse down events.
                    switch ( windowPart ) {
                        case inSysWindow:
                            SystemClick(&myEvent, foundWindow);
                            break;
                        case inMenuBar:
                            AdjustMenus();
                            DoCommand(MenuSelect(myEvent.where));
                            break;
                        case inContent:
                            //  If in the content area of application's window, then select
                            //  the window and call app specific routine.
                            if ( IsMyWindow(foundWindow) ) {
                                SelectWindow(foundWindow);
                                MyInContent(foundWindow, myEvent.where);
                            } else if ( IsMyClipWindow(foundWindow) ) {
                                SelectWindow(foundWindow);
                            }
                            break;
                        case inDrag:
                            //  If dragging one of the application's windows, then handle it.
                            //  However, if we are dragging a zoomed window, we
                            //  must remember to save the new window location into the
                            //  zoomed rect in the data handle.  Otherwise, the event
                            //  manager will think that we are no longer zoomed.
                            if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
                                WStateData  *zoomData;
                                Rect        windowRect;
                                
                                //  Get window location before drag.
                                GetGlobalWindow(foundWindow, &windowRect);
                                
                                //  Drag window.
                                DragWindow (foundWindow, myEvent.where, &qd.screenBits.bounds);
 
                                //  If the windowRect in global coordinates matches the zoom rect,
                                //  then assume that we are dragging the zoomed window.  update
                                //  zoom rect.
                                zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
                                if ( EqualRect(&(zoomData->stdState), &windowRect) ) {
                                    GetGlobalWindow(foundWindow, &windowRect);
                                    zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
                                    zoomData->stdState = windowRect;
                                }
                            }
                            break;
                        case inGrow:
                            //  If growing one of the application's windows, then handle it.
                            //  This also includes the clip window.
                            //  See inDrag for details.
                            if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
                                WStateData  *zoomData;
                                Rect        windowRect;
                                Rect        tempRect;
                                long        tempLong;
                                Str255      tempStr;
                                
                                //  Get window location before drag.
                                GetGlobalWindow(foundWindow, &windowRect);
                                
                                //  Grow the window.
                                tempRect = qd.screenBits.bounds;
                                tempRect.left = tempRect.top = 50;
                                GetWTitle(foundWindow, tempStr);
                                tempRect.left = StringWidth(tempStr) + 50;
                                tempLong = GrowWindow(foundWindow, myEvent.where, &tempRect);
                                if ( tempLong ) {
                                    tempRect = foundWindow->portRect;
                                    InvalRect(&tempRect);
                                    EraseRect(&tempRect);
                                    InvalRect(&tempRect);
                                    SizeWindow(foundWindow, tempLong, tempLong >> 16, true);
                                }
 
                                //  If the windowRect in global coordinates matches the zoom rect,
                                //  then assume that we are dragging the zoomed window.  update
                                //  zoom rect.
                                zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
                                if ( EqualRect(&(zoomData->stdState), &windowRect) ) {
                                    GetGlobalWindow(foundWindow, &windowRect);
                                    zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
                                    zoomData->stdState = windowRect;
                                }
                            }
                            break;
                        case inGoAway:
                            //  Handle clicking on the go away.  If it is the clip window,
                            //  then hide it.
                            if ( TrackGoAway (foundWindow, myEvent.where) ) {
                                if ( IsMyWindow(foundWindow) ) {
                                    BringToFront(foundWindow);
                                    MyClose();
                                } else if ( IsMyClipWindow(foundWindow) ) {
                                    SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
                                    HideClip(foundWindow);
                                }
                            }
                            break;
                        case inZoomIn:
                        case inZoomOut:
                            //  Zoom application window and the clip window.
                            if ( TrackBox(foundWindow, myEvent.where, windowPart) ) {
                                if ( IsMyWindow(foundWindow) )
                                    MyZoomWindow(foundWindow, windowPart);
                                else if ( IsMyClipWindow(foundWindow) )
                                    ZoomClip(foundWindow, windowPart);
                            }
                            break;
                            break;
                        default:
                            break;
                    }
                    
                    //  Restore port and device.
                    SetPort(savePort);
                    SetGDevice(saveGD);
                    
                    break;
                case keyDown:
                case autoKey:
                    if ( myEvent.modifiers & cmdKey ) {
                        if ( myEvent.what == keyDown ) {
                            AdjustMenus();
                            DoCommand(MenuKey(myEvent.message & charCodeMask));
                        }
                    } else
                        MyDoKeyDown(&myEvent);
                    break;
                case updateEvt:
                    //  Handle update events for window and clip window.
                    foundWindow = (WindowPtr) myEvent.message;
                    GetPort(&savePort);
                    saveGD = GetGDevice();
                    SetPort(foundWindow);
                    SetGDevice(GetMainDevice());
                    BeginUpdate(foundWindow);
                    if ( IsMyWindow(foundWindow) )
                        MyDraw(foundWindow);
                    else if ( IsMyClipWindow(foundWindow) )
                        DrawClip(foundWindow);
                    EndUpdate(foundWindow);
                    SetPort(savePort);
                    SetGDevice(saveGD);
                    break;
                case diskEvt:
                    //  This handles a bad disk.  Otherwise the disk will not eject.
                    if ( myEvent.message >> 16 ) {
                        Point   tempPoint;
                        tempPoint.v = 50; tempPoint.h = 50;
                        DIBadMount(tempPoint, myEvent.message);
                    }
                    break;
                case activateEvt:
                    break;
                case app4Evt:
                    switch ( myEvent.message >> 24 ) {
                        case suspendResumeMessage:
                            yieldTime = MyYieldTime(myEvent.message & 0x01);
                            break;
                        default:
                            DebugStr("\pUnexpected suspend/resume message.");
                    }
                    break;
                case kHighLevelEvent:
                    if ( gHasAppleEvents )
                        AEProcessAppleEvent(&myEvent);
                default:
                    break;
            }
        }
    
        //  If DoneFlag set, then quit.
        if ( gDoneFlag )
            Finishup();
 
        //  Do Idle routine.
        //      MYIDLEDEF == 2: MyEvent gets called for each window.
        //      MYIDLEDEF == 1: MyEvent gets once with window parameter = nil.
        //      MYIDLEDEF == 0: MyEvent never gets called.
        //  As the safe thing to do, we always set the port if we know what window is being used.
        #if kMYIDLEDEF == 2
            foundWindow = (WindowPtr) LMGetWindowList();
            while ( foundWindow != nil ) {
                if ( IsMyWindow(foundWindow) ) {
                    GetPort(&savePort);
                    saveGD = GetGDevice();
                    SetPort(foundWindow);
                    SetGDevice(GetMainDevice());
                    MyIdle(foundWindow);
                    SetPort(savePort);
                    SetGDevice(saveGD);
                }
                foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
            }
        #elif kMYIDLEDEF == 1
            MyIdle(nil);
        #elif kMYIDLEDEF == 0
        #endif
 
        //  See if scrap changed.  If so, redraw if the clip window is found.
        myScrapStuff = InfoScrap();
        if ( gScrapCount != myScrapStuff->scrapCount ) {
            foundWindow = (WindowPtr) LMGetWindowList();
            while ( foundWindow != nil ) {
                if ( IsMyClipWindow(foundWindow) ) {
                    GetPort(&savePort);
                    saveGD = GetGDevice();
                    SetPort(foundWindow);
                    SetGDevice(GetMainDevice());
                    DrawClip(foundWindow);
                    SetPort(savePort);
                    SetGDevice(saveGD);
                }
                foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
            }
        }
    }
}
 
/* ------------------------------------------------------------------------- */
 
//  MyApplication Shell support routines (Initialize, DoCommand, and Finishup):
 
void Initialize()
{
    OSErr               err;
    long                vers;
    Handle              myMenu;
    
    //  Initialize Managaer.
    MaxApplZone();
    MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
    MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
    MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
    MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
    InitGraf(&qd.thePort);
    FlushEvents(everyEvent, 0);
    InitWindows();
    InitDialogs(nil);
    InitCursor();
 
    //  Set up menus.
    myMenu = GetNewMBar(kMENUBAR);
    SetMenuBar(myMenu);
    DisposHandle(myMenu);
    AddResMenu(GetMHandle(kMENU_APPLEID), 'DRVR');
    DrawMenuBar();
    
    //  Require at least System 7.0 and Color QuickDraw.  We don't really need to be strict
    //  about this.  So, this can be removed if necessary.  But, test thoroughly with
    //  System 6 and non-color if you do.
    Gestalt(gestaltSystemVersion, &vers);
    vers = (vers >> 8) & 0x0f;
    if ( vers < 7 ) {
        ReportError("\pThis Application does not run under System 6!", -1);
        ExitToShell();
    }
    Gestalt(gestaltQuickdrawVersion, &vers);
    if ( vers < 0x100 ) {
        ReportError("\pThis Application requires Color QuickDraw!", -1);
        ExitToShell();
    }
    
    //  Initialize AppleEvents if available.
    gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &vers) == noErr);
    if ( gHasAppleEvents ) {
        err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(AEOpenHandler), 0, false);
        if ( err ) {
            ReportError("\pError installing AppleEvent handlers.", err);
            ExitToShell();
        }
        err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(AEOpenDocHandler), 0, false);
        if ( err ) {
            ReportError("\pError installing AppleEvent handlers.", err);
            ExitToShell();
        }
        err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(AEQuitHandler), 0, false);
        if ( err ) {
            ReportError("\pError installing AppleEvent handlers.", err);
            ExitToShell();
        }
        err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(AEPrintHandler), 0, false);
        if ( err ) {
            ReportError("\pError installing AppleEvent handlers.", err);
            ExitToShell();
        }
    }
    
    //  Setup other globals.
    gDoneFlag = false;
 
    //  Call app specific Intialization.
    if ( ReportError("\pError returned from MyInitialize:", MyInitialize()) )
        ExitToShell();
}
 
void DoCommand(long mResult)
{
    short           theMenu, theItem;
    Str255          myStr;
    GrafPtr         savePort;
    GDHandle        saveGD;
    WindowPtr       foundWindow;
    
    theItem = LoWord(mResult);
    theMenu = HiWord(mResult);
    
    if ( theItem != 0 || theMenu != 0 ) {
        switch ( theMenu ) {
            case kMENU_APPLEID:
                if ( theItem == 1 ) {
                    ParamText(gMyAboutTitle, gMyAboutDesc, nil, nil);
                    Alert(kALERT_ABOUT, nil);
                } else {
                    GetItem(GetMHandle(kMENU_APPLEID), theItem, myStr);
                    GetPort(&savePort);
                    saveGD = GetGDevice();
                    (void) OpenDeskAcc(myStr);
                    SetPort(savePort);
                    SetGDevice(saveGD);
                }
                break;
    
            case kMENU_FILEID:
                switch ( theItem ) {
                    case kMENU_FILENEW:
                        MyNew();
                        break;
                    case kMENU_FILEOPEN:
                        MyOpen(nil);
                        break;
                    case kMENU_FILECLOSE:
                        if ( IsMyClipWindow(FrontWindow()) ) {
                            SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
                            HideClip(FrontWindow());
                        } else if ( IsMyWindow(FrontWindow()) )
                            MyClose();
                        else
                            SysBeep(50);
                        break;
                    case kMENU_FILESAVE:
                        if ( IsMyWindow(FrontWindow()) )
                            MySave();
                        else
                            SysBeep(50);
                        break;
                    case kMENU_FILESAVEAS:
                        if ( IsMyWindow(FrontWindow()) )
                            MySaveAs();
                        else
                            SysBeep(50);
                        break;
                    case kMENU_FILEPAGESETUP:
                        if ( IsMyWindow(FrontWindow()) )
                            MyPageSetup();
                        else
                            SysBeep(50);
                        break;
                    case kMENU_FILEPRINT:
                        if ( IsMyWindow(FrontWindow()) )
                            MyPrint();
                        else
                            SysBeep(50);
                        break;
                    case kMENU_FILEQUIT:
                        gDoneFlag = true;
                        break;
                    default:
                        if ( ReportError("\pError in handling file menu:", theItem) )
                            ExitToShell();
                }
                break;
    
            case kMENU_EDITID:
                switch ( theItem ) {
                    case kMENU_EDITUNDO:
                        MyUndo();
                        break;
                    case kMENU_EDITCUT:
                        MyCut();
                        break;
                    case kMENU_EDITCOPY:
                        MyCopy();
                        break;
                    case kMENU_EDITPASTE:
                        MyPaste();
                        break;
                    case kMENU_EDITCLEAR:
                        MyClear();
                        break;
                    case kMENU_EDITSELECTALL:
                        MySelectAll();
                        break;
                    case kMENU_EDITSHOWCLIP:
                        GetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, myStr);
                        if ( myStr[1] == 'S' ) {        //  Obviously not very internationalizeable.
                            ShowClip();
                            SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pHide Clipboard");
                        } else {
                            foundWindow = (WindowPtr) LMGetWindowList();
                            while ( foundWindow != nil ) {
                                if ( IsMyClipWindow(foundWindow) ) {
                                    SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
                                    HideClip(foundWindow);
                                }
                                foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
                            }
                        }
                        break;
                    default:
                        if ( ReportError("\pError in handling edit menu:", theItem) )
                            ExitToShell();
                }
                break;
 
            default:
                //  If not handled above, then allow app specific handling to occur.
                if ( ReportError("\pError returned from MyDoCommand:", MyDoCommand(theMenu, theItem)) )
                    ExitToShell();
        }
    }
    HiliteMenu(0);
    return;
}
 
void AdjustMenus()
{
    MenuHandle      mHandle;
    
    if ( IsMyClipWindow(FrontWindow()) ) {
        mHandle = GetMHandle(kMENU_FILEID);
        DisableItem(mHandle, kMENU_FILESAVE);
        DisableItem(mHandle, kMENU_FILESAVEAS);
        DisableItem(mHandle, kMENU_FILEPAGESETUP);
        DisableItem(mHandle, kMENU_FILEPRINT);
        mHandle = GetMHandle(kMENU_EDITID);
        DisableItem(mHandle, kMENU_EDITUNDO);
        DisableItem(mHandle, kMENU_EDITCUT);
        DisableItem(mHandle, kMENU_EDITCOPY);
        DisableItem(mHandle, kMENU_EDITPASTE);
        DisableItem(mHandle, kMENU_EDITCLEAR);
        DisableItem(mHandle, kMENU_EDITSELECTALL);
    } else {
        mHandle = GetMHandle(kMENU_FILEID);
        if (IsMyWindow(FrontWindow())) {
            EnableItem(mHandle, kMENU_FILESAVE);
            EnableItem(mHandle, kMENU_FILESAVEAS);
            EnableItem(mHandle, kMENU_FILEPAGESETUP);
            EnableItem(mHandle, kMENU_FILEPRINT);
        } else {
            DisableItem(mHandle, kMENU_FILESAVE);
            DisableItem(mHandle, kMENU_FILESAVEAS);
            DisableItem(mHandle, kMENU_FILEPAGESETUP);
            DisableItem(mHandle, kMENU_FILEPRINT);
        }
        mHandle = GetMHandle(kMENU_EDITID);
        EnableItem(mHandle, kMENU_EDITUNDO);
        EnableItem(mHandle, kMENU_EDITCUT);
        EnableItem(mHandle, kMENU_EDITCOPY);
        EnableItem(mHandle, kMENU_EDITPASTE);
        EnableItem(mHandle, kMENU_EDITCLEAR);
        EnableItem(mHandle, kMENU_EDITSELECTALL);
    }
    
    MyAdjustMenus();
}
 
void Finishup()
{
    WindowPtr       frontWindow, nxtWindow;
    
    frontWindow = FrontWindow();
    while ( frontWindow != nil ) {
        nxtWindow = (WindowPtr) ((WindowPeek)frontWindow)->nextWindow;
        if ( IsMyClipWindow(frontWindow) ) {
            HideClip(frontWindow);
        }
        frontWindow = nxtWindow;
    }
    
    //  Cleanup app specific stuff since all of the shell handles will be disposed of
    //  when the heap disappears...
    MyFinishup();
 
    //  Finally, quit app.
    ExitToShell();
}
 
/* ------------------------------------------------------------------------- */
 
//  Clip Window support (ShowClip, DrawClip, HideClip, and ZoomClip):
 
void ShowClip()
{
    WindowPtr   myWindow;
    Rect        clipBounds;
    
    myWindow = (WindowPtr) LMGetWindowList();
    while ( myWindow != nil ) {
        if ( IsMyClipWindow(myWindow) ) {
            return;
        }
        myWindow = (WindowPtr) ((CWindowPeek) myWindow)->nextWindow;
    }
    
    SetRect(&clipBounds, 10, 400, 510, 480);    
    myWindow = NewCWindow(0L, &clipBounds, "\pClipboard", true, zoomDocProc, (WindowPtr) -1, true, 0L);
    SetMyClipWindow(myWindow);
    SetPort(myWindow);
 
    gScrapCount = 0;
    gScrapType = 'NONE';    
    if ( (gScrap = NewHandle(0)) == nil ) {
        ReportError("\pCould not create handle for scrap storage:", -1);
        ExitToShell();
    }
}
 
void DrawClip(WindowPtr clipWindow)
{
    PScrapStuff myScrapStuff;
    long        scrapOffset, scrapLength;
    Rect        myFrame;
    Str255      myStr;
    short       moveSize;
    
    //  See if scrap changed.
    myScrapStuff = InfoScrap();
    if ( gScrapCount != myScrapStuff->scrapCount ) {
        gScrapCount = myScrapStuff->scrapCount;
        if ( (scrapLength = GetScrap(gScrap, 'PICT', &scrapOffset)) > 0 ) {
            gScrapType = 'PICT';    
        } else if ( (scrapLength = GetScrap(gScrap, 'TEXT', &scrapOffset)) > 0 ) {
            gScrapType = 'TEXT';    
        } else
            gScrapType = 'NONE';    
    }
 
    //  Erase the window.
    EraseRect(&(clipWindow->portRect));
 
    //  Draw something
    if ( gScrapType == 'PICT' ) {
        myFrame = (**(PicHandle) gScrap).picFrame;
        SetWTitle(clipWindow, "\pClipboard contents: picture");
        DrawPicture((PicHandle) gScrap, &myFrame);
 
    } else if ( gScrapType == 'TEXT' ) {
        SetWTitle(clipWindow, "\pClipboard contents: text");
        moveSize = GetHandleSize(gScrap);
        if ( moveSize > 255 )
            moveSize = 255;
        BlockMove(*gScrap, myStr+1, moveSize);
        myStr[0] = moveSize;
        MoveTo(10, 40);
        DrawString(myStr);
    } else
        SetWTitle(clipWindow, "\pNo PICT or TEXT to display.");
}
 
void HideClip(WindowPtr clipWindow)
{
    DisposeWindow(clipWindow);
    gScrapCount = 0;
    gScrapType = 'NONE';
    DisposeHandle(gScrap);
}
 
void ZoomClip(WindowPtr clipWindow, short windowPart)
{
    WStateData  *zoomData;
    
    //  IMPORTANT: Must not change stdState if not zooming out.  Otherwise, it will fool
    //  the WDEF into thinking that it is not zoomed out when it really is.
    
    //  Don't call anything else since zoomData handle is not locked.
    zoomData = (WStateData *) *(((CWindowPeek) clipWindow)->dataHandle);
    
    if ( gScrapType == 'PICT' ) {
        if ( windowPart == 8 ) {
            (zoomData->stdState).right = (zoomData->stdState).left +
                                            ((**(PicHandle) gScrap).picFrame).right;
            (zoomData->stdState).bottom = (zoomData->stdState).top +
                                            ((**(PicHandle) gScrap).picFrame).bottom;
        }
    } else if ( gScrapType == 'TEXT' ) {
        if ( windowPart == 8 ) {
            (zoomData->stdState).right = (zoomData->stdState).left + 620;
        }   
    }
    ZoomWindow(clipWindow, windowPart, true);
}
 
/* ------------------------------------------------------------------------- */
 
//  Shell utilities (ReportError, and GetGlobalWindow):
 
//  Show Alert.  Then, return true is err != noErr.
Boolean ReportError(Str255 procStr, OSErr err)
{
    long    longerr = err;
    Str255  myStr;
    
    if ( longerr ) {
        NumToString(longerr, myStr);
        ParamText("\pFATAL ERROR", procStr, myStr, nil);
        Alert(kALERT_ERROR, nil);
        return ( true );
    } else
        return ( false );
}
 
void GetGlobalWindow(WindowPtr theWindow, Rect *windowRect)
{
    //  Get the windowRect in global coordinates.
    *windowRect = theWindow->portRect;
    LocalToGlobal(&topLeft(*windowRect));
    LocalToGlobal(&botRight(*windowRect));
}
 
/* ------------------------------------------------------------------------- */
 
//  AppleEvents handling (AEOpenHandler, AEOpenDocHandler, AEPrintHandler,
//     and AECloseHandler) :
 
pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
    //  We don't do anything more than simply call MyNew().
    //  Thus, when app is opened from finder, MyNew will be called because the Finder
    //  will send an open app AppleEvent message.
    if ( kNEWDOCATSTARTUP )
        MyNew();
    
    return ( noErr );
}
 
pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
    OSErr           err;
    AEDescList      docList;
    long            numItems;
    FSSpec          myFSS;
    Size            actualSize;
    long            i;
    DescType        typeCode;
    AEKeyword       theKeyword;
    
    err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList);
    if ( err )
        return ( err );
    
    err = AECountItems(&docList, &numItems);
    if ( err )
        return ( err );
        
    for ( i=1; i<=numItems; i++ ) {
        err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
                            sizeof(FSSpec), &actualSize);
        if ( err )
            return ( err );
        
        MyOpen(&myFSS);
    }
    
    return ( noErr );
}
 
pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
    OSErr           err;
    AEDescList      docList;
    long            numItems;
    FSSpec          myFSS;
    Size            actualSize;
    long            i;
    DescType        typeCode;
    AEKeyword       theKeyword;
    
    err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList);
    if ( err )
        return ( err );
    
    err = AECountItems(&docList, &numItems);
    if ( err )
        return ( err );
    
    for ( i=1; i<=numItems; i++ ) {
        err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
                            sizeof(FSSpec), &actualSize);
        if ( err )
            return ( err );
        
        //  Open each file.  Print it.  Then close it.  MyOpen must make window frontmost.
        MyOpen(&myFSS);
        MyPrint();
        MyClose();
    }
    
    return ( noErr );
}
 
pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
    gDoneFlag = true;
    
    return ( noErr );
}
 
/* ------------------------------------------------------------------------- */
 
//  Called to determine if the window is owned by app.
Boolean IsMyWindow(WindowPtr theWindow)
{
    if ( theWindow )
        return ( ((CWindowPeek) theWindow)->windowKind == kWINDOWDOC );
    else
        return ( false );
}
 
//  Called to set the window's creator.
void SetMyWindow(WindowPtr theWindow)
{
    if ( theWindow )
        ((CWindowPeek) theWindow)->windowKind = kWINDOWDOC;
}
 
//  Called to determine if window is a show clipboard window.
Boolean IsMyClipWindow(WindowPtr theWindow)
{
    if ( theWindow )
        return ( ((CWindowPeek) theWindow)->windowKind == kWINDOWCLIP );
    else
        return ( false );
}
 
//  Called to set the creator as the window clip.
void SetMyClipWindow(WindowPtr theWindow)
{
    if ( theWindow )
        ((CWindowPeek) theWindow)->windowKind = kWINDOWCLIP;
}