ProjectBuilder (OS X)/SuspendEvent.c

/*
    File:       SuspendEvent.c
 
    Contains:   A simple example of suspending and resuming an AppleEvent
 
    Written by: C.K. Haun   
 
    Copyright:  © Copyright 2003 Apple Computer, Inc. All rights reserved.
    
    Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
                ("Apple") in consideration of your agreement to the following terms, and your
                use, installation, modification or redistribution of this Apple software
                constitutes acceptance of these terms.  If you do not agree with these terms,
                please do not use, install, modify or redistribute this Apple software.
 
                In consideration of your agreement to abide by the following terms, and subject
                to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
                copyrights in this original Apple software (the "Apple Software"), to use,
                reproduce, modify and redistribute the Apple Software, with or without
                modifications, in source and/or binary forms; provided that if you redistribute
                the Apple Software in its entirety and without modifications, you must retain
                this notice and the following text and disclaimers in all such redistributions of
                the Apple Software.  Neither the name, trademarks, service marks or logos of
                Apple Computer, Inc. may be used to endorse or promote products derived from the
                Apple Software without specific prior written permission from Apple.  Except as
                expressly stated in this notice, no other rights or licenses, express or implied,
                are granted by Apple herein, including but not limited to any patent rights that
                may be infringed by your derivative works or by other works in which the Apple
                Software may be incorporated.
 
                The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
                WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
                WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
                COMBINATION WITH YOUR PRODUCTS.
 
                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
                CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
                (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
                ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                
 
    Change History (most recent first):
    8/2003      MK      Updated for Project Builder
    7/21/1999   KG      Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include "SuspendEvent.h"
 
/* prototypes */
void InitalizeApp(void);                        
void DrawMain(WindowPtr drawIt);
Boolean DoSelected(long val);
void SizeMain(WindowPtr theWindow);
void InitAEStuff(void);
void DoHighLevel(EventRecord *AERecord);
void DoDocumentClick(WindowPtr theWindow);
OSErr modfiedProcessOpenPrint(const AppleEvent *messagein, AppleEvent *theReply, Boolean printIt);
static pascal OSErr AEOpenHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn);
static pascal OSErr AEOpenDocHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn);
static pascal OSErr AEPrintHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn);
static pascal OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn);
void SampleHelpDialog(void);
void CloseMyWindow(WindowPtr twindow);
WindowPtr AddNewWindow(short theID);
void InvalAll(void);
void NilProc(void);
/* one external */
extern void _DataInit();                                    /* this is the C initialization code */
 
/* globals */
Boolean gQuit, gInBackground;
unsigned long gMySleep;
ProcessSerialNumber gOurSN;
short gHelpItem;
 
/* globals for event suspension */
Boolean eventIsPending;
AEDesc theSuspEvent, theSuspReply;
 
#pragma segment Main
int main()
{
    EventRecord myEventRecord;
    WindowPtr twindow;
    short fHit;
    windowCHandle tempWCH;
    BitMap* bitMap;
    
    InitalizeApp();
    do {
        
        WaitNextEvent(everyEvent, &myEventRecord, gMySleep, nil);
        switch (myEventRecord.what) {
            case nullEvent:
                /* no nul processing in this sample */
                break;
            case updateEvt:
                /* always check to see if it's my window */
                /* this may not seem necessary under 7.0, where it's unlikely or impossible for */
                /* a DA to be in your layer, but there are others */
                /* who can stick themselves into your window list, */
                /* BalloonWriter comes quickly to mind */
                if (GetWindowKind( (WindowRef) myEventRecord.message ) == kMyDocumentWindow) {
                    tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
                    if (tempWCH){
                        DrawMain( (WindowPtr)myEventRecord.message );
                    }
                }
                break;
            case mouseDown:
                /* first see where the hit was */
                fHit = FindWindow(myEventRecord.where, &twindow);
                switch (fHit) {
                    Rect limitRect;
                    Str255 tempString;
                    long back;
                    case inDesk:                            /* if they hit in desk, then the process manager */
                        break;                              /* will switch us out, we don't need to do anything */
                    case inMenuBar:
                        DoSelected(MenuSelect(myEventRecord.where));
                        break;
                        
                    case inSysWindow:
                        /* pass to the system */
                        break;
                    case inContent:
                        /* Handle content and control clicks here */
                        if (FrontWindow()) {                /* don't do this unless we have a window open, silly */
                            if (FrontWindow() == twindow && GetWindowKind( twindow ) == kMyDocumentWindow) {
                                windowCHandle clicker;
                                clicker = (windowCHandle)GetWRefCon(twindow);
                                /* jump to the content function stored for this window */
                                HLock((Handle)clicker);     /* lock it down so things don't get stupid */
                                DoDocumentClick( twindow );
                                HUnlock((Handle)clicker);       /* all done */
                            } else {
                                SelectWindow(twindow);      /* select the window */
                                SetPort( GetWindowPort( twindow ) );
                            }
                        }
                        break;
                    case inDrag:
                        bitMap = GetQDGlobalsScreenBits( bitMap );
                        DragWindow(twindow, myEventRecord.where, &bitMap->bounds);
                        break;
                    case inGrow:
                        /* Call GrowWindow here if you have a grow box */
                        SetPort( GetWindowPort( twindow ) );
                        limitRect = bitMap->bounds;
                        limitRect.top = kMinHeight;
                        GetWTitle(twindow, tempString);
                        /* I'm not letting the user shrink the window so */
                        /* small that the title is truncated */
                        limitRect.left = StringWidth(tempString) + 120;
                        back = GrowWindow(twindow, myEventRecord.where, &limitRect);
                        
                        if (back) {
                            Rect sizeRect;
                            GetWindowPortBounds(twindow, &sizeRect);
                            InvalWindowRect(twindow, &sizeRect);
                            sizeRect.top = sizeRect.bottom - 16;
                            sizeRect.left = sizeRect.right - 16;
                            EraseRect(&sizeRect);
                            InvalWindowRect(twindow, &sizeRect);
                            SizeWindow(twindow, back & 0xffff, back >> 16, true);
                            SizeMain( twindow );
                        }
                        InvalWindowRect(twindow, GetWindowPortBounds(twindow, NULL) );
                        
                        break;
                    case inGoAway:
                        /* Click in Close box */
                        if (TrackGoAway(twindow, myEventRecord.where)){
                            CloseMyWindow( twindow );
                        }
                        
                        break;
                    case inZoomIn:
                    case inZoomOut:
                        if (TrackBox(twindow, myEventRecord.where, fHit)) {
                            SetPort( GetWindowPort( twindow ) );
                            ZoomWindow(twindow, fHit, true);
                            InvalWindowRect(twindow, GetWindowPortBounds(twindow, NULL));
                            SizeMain( twindow );
                        }
                }
            case mouseUp:
                /* don't care */
                break;
                /* same action for key or auto key */
            case keyDown:
            case autoKey:
                if (myEventRecord.modifiers & cmdKey)
                    DoSelected(MenuKey(myEventRecord.message & charCodeMask));
                break;
            case keyUp:
                /* don't care */
                break;
            case activateEvt:
                if (myEventRecord.modifiers & activeFlag) {
                    tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
                    DrawMain( (WindowPtr)myEventRecord.message );
                }
                break;
            case networkEvt:
                /* don't care */
                break;
            case driverEvt:
                /* don't care */
                break;
            case app4Evt:
                switch ((myEventRecord.message >> 24) & 0x0FF) {        /* high byte of message */
                    case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
                        gInBackground = (myEventRecord.message & kResumeMask) == 0;
                        if (gInBackground) {
                            /* nothing for going in the background in this sample */
                        } else {
                            /* make sure the cursor is an arrow when we come forward */
                            InitCursor();
                        }
                        break;
                }
                break;
            default:
                break;
                /* This dispatches high level events (AppleEvents, for example) */
                /* to our dispatch routine. This is NEW in the event loop for */
                /* System 7 */
            case kHighLevelEvent:
                DoHighLevel(&myEventRecord);
                break;
                
        }
    }
    while (gQuit != true);
    
    return 0;
    
}
 
/* draws my window. Pretty simple */
void DrawMain(WindowPtr drawIt)
{
    RgnHandle tempRgn;
    short oldSize = GetPortTextSize( GetWindowPort( drawIt ) );
    Rect scratchRect;
    BeginUpdate(drawIt);
    SetPort( GetWindowPort( drawIt ) );
    GetWindowPortBounds(drawIt, &scratchRect);
    EraseRect( &scratchRect );
    /* tell folks if an event has been suspendered */
    if (eventIsPending) {
        Str255 tempString;
        MoveTo(10, 40);
        TextFace(bold);
        TextSize(24);
        
        GetIndString(tempString, kGeneralStrings, kPendingWords1);
        DrawString(tempString);
        GetIndString(tempString, kGeneralStrings, kPendingWords2);
        MoveTo(10, 80);
        DrawString(tempString);
        
        TextSize(oldSize);
        TextFace(normal);
    }
    GetWindowPortBounds(drawIt, &scratchRect);
    scratchRect.top = scratchRect.bottom - 15;
    scratchRect.left = scratchRect.right - 15;
    tempRgn = NewRgn();
    GetClip(tempRgn);
    ClipRect(&scratchRect);
    DrawGrowIcon(drawIt);
    SetClip(tempRgn);
    DisposeRgn(tempRgn);
    
    EndUpdate(drawIt);
}
 
void CloseMyWindow(WindowPtr twindow)
{
    DisposeWindow(twindow);
}
 
/* my menu action taker. It returns a Boolean which I usually ignore, but it */
/* mught be handy someday */
/* Actually, I've been returning that Boolean for 7 years, and */
/* never used it, but Who Knows? */
/* I usually use it in an application to determine if a keystroke was accepted */
/* by a menu or whether it should be passed along to any other key acceptors */
Boolean DoSelected(long val)
{
    short loval, hival;
    Boolean returnVal = false;
    loval = LoWord(val);
    hival = HiWord(val);
    
    switch (hival) {                                        /* switch off the menu number selected */
        case kAppleMenu:                                    /* Apple menu */
            Alert(kAboutBox, nil);                      /* do about box */
            returnVal = true;
            break;
        case kFileMenu:                                     /* File menu */
            switch (loval) {
                case kQuitItem:
                    gQuit = true;                           /* only item */
                    returnVal = true;
                    break;
                default:
                    break;
            }
            break;
        case kEditMenu:
            /* edit menu junk */
            /* don't care */
            switch (loval) {
            default:
                break;
            }
            break;
        case kToolsMenu:
            /* add all your test stuff here */
            switch (loval) {
            default:
                break;
            }
            break;
        case kHMHelpMenuID:                                 /* Defined in Balloons.h */
            /* I only care about this item. If anything else is returned here, I don't know what */
            /* it is, so I leave it alone. Remember, the Help Manager chapter says that */
            /* Apple reserves the right to add and change things in the Help menu */
            
            if (loval == gHelpItem)
                SampleHelpDialog();
            break;
            
    }
    HiliteMenu(0);
    return(returnVal);
}
 
void DoDocumentClick(WindowPtr theWindow)
{
    #pragma unused (theWindow)
    /* look to see if an event is pending, if so resume the event */
    if (eventIsPending) {
        /* restart the event */
        AEResumeTheCurrentEvent(&theSuspEvent, &theSuspReply, (AEEventHandlerUPP)kAEUseStandardDispatch, 0);
        /* kAEUseStandardDispatch means re-enter the handler from the top. */
        /* You're other option to pass here is kAENoDispatch, which tells the */
        /* AppleEvent manager that this event is FINISHED, clean up memory */
        /* and don't re-dspatch. */
        
    }
}
 
 
#pragma segment Initialize
 
/* InitAEStuff installs my appleevent handlers */
void InitAEStuff(void)
{    
    OSErr aevtErr = noErr;
    long aLong = 0;
    Boolean gHasAppleEvents = false;
    /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
    *   then we exit */
    gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
    /* The following series of calls installs all our AppleEvent Handlers.
    *   These handlers are added to the application event handler list that 
    *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
    *   and we call AEProcessEvent, the AppleEvent manager will check our
    *   list of handlers and dispatch to it if there is one.
    */
    if (gHasAppleEvents) {
         aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, 
             NewAEEventHandlerUPP(AEOpenHandler),0, false);
             if (aevtErr)  ExitToShell();
 
         aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
             NewAEEventHandlerUPP(AEOpenDocHandler),0, false);
             if (aevtErr)  ExitToShell();
 
         aevtErr = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
             NewAEEventHandlerUPP(AEQuitHandler), 0, false);
             if (aevtErr)  ExitToShell();
 
         aevtErr = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, 
             NewAEEventHandlerUPP(AEPrintHandler),0, false);
             if (aevtErr)  ExitToShell();
         
       } 
    else ExitToShell();
    
}
/* end InitAEStuff */
 
#pragma segment Main
 
/* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
/* easy for me to say, huh? */
void DoHighLevel(EventRecord *AERecord)
{
    OSErr myErr;
    myErr = AEProcessAppleEvent(AERecord);
    
}
 
/* end DoHighLevel */
 
/* This is the standard Open Application event. */
static pascal OSErr AEOpenHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn)
{
    WindowPtr myWindow;
 
#pragma unused (messagein,reply,refIn)
    /* we of course don't do anything here in this simple app */
    /* except open our window */
    myWindow = AddNewWindow(kDocWindowResID);
    
    return(noErr);
}
 
/* end AEOpenHandler */
 
/* Open Doc, opens our documents. Remember, this can happen at application start AND */
/* anytime else. If your app is up and running and the user goes to the desktop, hilites one */
/* of your files, and double-clicks or selects Open from the finder File menu this event */
/* handler will get called. Which means you don't do any initialization of globals here, or */
/* anything else except open then doc. */
/* SO-- Do NOT assume that you are at app start time in this */
/* routine, or bad things will surely happen to you. */
 
static pascal OSErr AEOpenDocHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn)
{
#pragma unused (refIn)
    return(modfiedProcessOpenPrint(messagein, reply, false));
}
 
static pascal OSErr AEPrintHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn)
{                                                           /* no printing handler in yet, so we'll ignore this */
    /* the operation is functionally identical to the ODOC event, with the additon */
    /* of calling your print routine. */
#pragma unused (refIn)
    return(modfiedProcessOpenPrint(messagein, reply, true));
}
 
/* Standard Quit event handler, to handle a Quit event from the Finder, for example. */
/* ¥¥¥¥¥ DO NOT CALL EXITTOSHELL HERE ¥¥¥¥¥ or you will never have a happy life. */
/* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
/* come through DTS that calls ExitToShell from quit handlers. Let me explain... */
/* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
/* 100% in your application world. A5 is right, you can call any toolbox function, */
/* you can call your own routines, everything _seems_ like you are in complete */
/* control. Well, almost but not quite. The routine has been dispatch to from the */
/* AppleEvent Manager's space, so you _must_ return to that at some point! */
/* Which is why you can't call ETS from here. When you call ExitToShell from an */
/* AE Handler, the most likely thing that happens is the FInder quits, and your */
/* application keeps running. Which ain't what you want, y'know? */
/* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
/* Any of 'em, not just a quit handler. Just don't do it. */
/* This comment keeps getting longer because people keep doing it STOP IT! */
static pascal OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, SInt32 refIn)
{
#pragma unused (messagein,refIn,reply)
    gQuit = true;
    return(noErr);
}
 
/* This is my sample help dialog. Does not do anything, expand as you need */
void SampleHelpDialog(void)
{
    DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
    short itemhit = 0;
    while (itemhit != 1) {
        ModalDialog(nil, &itemhit);
    }
    DisposeDialog(tdial);
}
 
 
#pragma segment Initialize
void InitalizeApp(void)
{
    MenuHandle helpHandle;
    StringHandle helpString;
    short count;
    InitCursor();
    InitAEStuff();
    /* set up my menu junk */
    SetMenuBar(GetNewMBar(kMBarID));
    AppendResMenu(GetMenuHandle(kAppleMenu), 'DRVR');
    
    
    
    
    /* now install my Help menu item in the Help Manager's menu */
    HMGetHelpMenu(&helpHandle, NULL);                      /* Get the Hlpe menu handle */
    count = CountMenuItems(helpHandle);                        /* How many items are there? */
    helpString = GetString(kHelpString);                    /* get my help string */
    DetachResource((Handle)helpString);                             /* detach it */
    HNoPurge((Handle)helpString);
    MoveHHi((Handle)helpString);
    HLock((Handle)helpString);
    InsertMenuItem(helpHandle,*helpString, count + 1);       /* insert my item in the Help menu */
    gHelpItem = CountMenuItems(helpHandle);                    /* The number of the item */
    
    DrawMenuBar();
    GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
    
}
 
 
#pragma segment Main
WindowPtr AddNewWindow(short theID)
{
    windowCHandle setControls;
    WindowPtr tempWP;
    tempWP = GetNewWindow(theID, 0, (WindowPtr)-1);         /* get a new window */
    SetWindowKind(tempWP, kMyDocumentWindow);       /* mark it as my document window */
    setControls = (windowCHandle)NewHandleClear(sizeof(windowControl));     /* add our control structure to it */
    SetWRefCon(tempWP, (long)setControls);                  /* stop stuffing refCon directly <ckh 1.0.3> */
    HLock((Handle)setControls);                             /* lock it down while we fill it*/
    
    /* add pointers to our procedures for drawing, saving, and closing */
    /* This way, all I need is one dispatch point for drawing, closing */
    /* or whatever, I don't have to case off the window kind to go to the */
    /* correct routine. Kinda like object-oriented programming, but I won't */
    /* admit that. */
    (*setControls)->drawMe = (ProcPtr)DrawMain;
    (*setControls)->clickMe = (ProcPtr)DoDocumentClick;
    (*setControls)->sizeMe = (ProcPtr)SizeMain;
    (*setControls)->closeMe = (ProcPtr)CloseMyWindow;
    (*setControls)->generalData = NewHandle(0);
    return(tempWP);
}
 
void SizeMain(WindowPtr theWindow)
{
    WindowPtr tempWP;
    Rect* bounds;
    GetWindowPortBounds(tempWP, bounds);
    InvalWindowRect(theWindow, bounds);
    SetPort( GetWindowPort( tempWP ) );
}
 
void NilProc(void)
{
    
}
 
/* modfiedProcessOpenPrint handles ODOC and PDOC events. Both events open a document, one prints it */
/* This one is modified to suspend any event that opens or prints an kAlDocType document */
/* do NOT use this as is in your app! */
OSErr modfiedProcessOpenPrint(const AppleEvent *messagein, AppleEvent *theReply, Boolean printIt)
{
    #pragma unused(printIt)
    OSErr err = noErr;
    AEDesc theDesc;
    FSSpec theFSS;
    short loopy;
    long numFilesToOpen;
    AEKeyword ignoredKeyWord;
    DescType ignoredType;
    Size ignoredSize;
    FInfo fileInfo;
    Boolean DoSuspend = false;
    err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &theDesc);
    err |= AECountItems(&theDesc, &numFilesToOpen);
    if (!err) {
        for (loopy = 1; ((loopy <= numFilesToOpen) && (!err)); ++loopy) {
            
            err = AEGetNthPtr(&theDesc, loopy, typeFSS, &ignoredKeyWord, &ignoredType, (Ptr)&theFSS, sizeof(theFSS),
                              &ignoredSize);
            if (err == noErr) {
                FSpGetFInfo(&theFSS, &fileInfo);
                /* make sure it's a data file */
                /* and if this was called for an eventPend, don't reopen the kFredDocType docs */
                if (fileInfo.fdCreator == kSuspCreator && fileInfo.fdType == kFredDocType && !eventIsPending) {
                    WindowPtr newW = AddNewWindow(kDocWindowResID);
                    if (newW) {
                        SetWTitle(newW, theFSS.name);
                    }
                } else {
                    /* here we see if it's an kAlDocType file. If it is, we either ignore it */
                    /* if its not from the resume, or we process it */
                    if (fileInfo.fdCreator == kSuspCreator && fileInfo.fdType == kAlDocType) {
                        if (eventIsPending) {
                            WindowPtr newW = AddNewWindow(kDocWindowResID);
                            if (newW) {
                                SetWTitle(newW, theFSS.name);
                            }
                        } else {
                            /* if there is not an event pending, then this is is an Al file */
                            /* from launch, tell ourselves that there is a reason to suspend */
                            DoSuspend = true;
                        }
                    }
                }
            }
        }                                                   /* for loopy = ... */
    }
    AEDisposeDesc(&theDesc);
    /* determine if this is the first pass, then we should suspend. If not, */
    /* we press on */
    if (eventIsPending) {
        /* clear it and life is back to normal */
        eventIsPending = false;
    } else {
        /* first pass, no kAlDocType files have been opened, suspend the event and set the */
        /* flag. */
        /* Only if an kAlDocType file was passed at all, which is the DoSuspend flag. */
        if (DoSuspend) {
            eventIsPending = true;
            AESuspendTheCurrentEvent(messagein);
            theSuspEvent = *messagein;
            theSuspReply = *theReply;
        }
    }
    InvalAll();
    return(err);
}
 
void InvalAll(void)
{
 
    WindowRef nowFront; 
    WindowRef oldPort;
    Rect bounds;
    
    nowFront = GetFrontWindowOfClass(kDocumentWindowClass, true);
    oldPort = nowFront;
    while (nowFront) {
        if (IsWindowVisible( nowFront )) {
            SetPort( GetWindowPort( nowFront ) );
            GetWindowPortBounds(nowFront, &bounds);
            InvalWindowRect(nowFront, &bounds);
        }
        nowFront = GetNextWindowOfClass(nowFront, kDocumentWindowClass, true);
    }
    SetPort( GetWindowPort( oldPort ) );
    
}