Main.c

/*****************************************************************
 
    Program:    < ATP Demo >
    File:       < Main.c >
    
    Written by  Scott Kuechle
    of <Apple Macintosh Developer Technical Support>
    
    10/92 SRK created
    8/94 SRK Modified to use a queue of parameter
             blocks.
 
    Copyright © 1992, 1994 Apple Computer, Inc.
    All rights reserved.
    
*****************************************************************/
 
 
/*****************************************************************/
/*  I N C L U D E S
/*****************************************************************/
 
#include    "ATP Demo.h"
#include    "ATP Demo.protos"
 
/********************************************************************
/*  G L O B A L   V A R I A B L E   D E C L A R A T I O N S
/********************************************************************/
 
DialogPtr myDialog;
Boolean gHasWaitNextEvent,gInBackground,gGrowRect,gStopped,gStopRect,gGoRect,gHasSystem7;
Boolean gATPEntityFilter;
Boolean gReqClockTime,gSingleRequest,gStopRequests;
MenuHandle ZoneMenu,ObjectMenu,TypeMenu;
short LastZoneMenuChoice,LastTypeMenuChoice,LastObjectMenuChoice;
SysEnvRec gMac;
MenuHandle DataSizeMenu;
Handle gTestDataHdl;
long gTestDataSize;
 
/*****************************************************************/
/*
/* E X T E R N A L S
/*
/*****************************************************************/
 
 
extern  Boolean SendReqToTarget();
extern  void initializeATP();
extern  void removeMyName();
extern  void ATPLoop();
extern  OSErr InitAppleTalk();
extern  Boolean ATPZoneRequest (MenuHandle zoneMenu);
extern  void LookupNames (MenuHandle lookupMenu,
                    Boolean doObjects);
extern  void GetZones();
extern  void GetOurZone();
extern  Str255 gZoneString,gTypeStr,gObjStr,gDataSizeStr;
extern  short gMenuItem;
extern  void removeATP();
extern  void doGetRequest(ATPPBPtr atpPBPtr,
                    char socket,
                    short reqLength,
                    Ptr reqPointer);
extern  void DisplayStatusString(short whichString,Ptr displayStr);
extern  QHdr gAvailQueue;
extern  char gOurATPSocket;
 
 
 
#pragma segment Main
// *****************************************************************
// *    CopyPstr
// *
// *    copies a pascal string
// *****************************************************************
void CopyPstr(Ptr pSource, Ptr pDest)
{
    BlockMove(pSource, pDest, pSource[0]+1);
}
 
// *****************************************************************
// *    PStrCat
// *
// *    appends pascal string sourceStr, to pascal string destinationStr.
// *    Overflow is checked, and the copy halts if the destination
// *    string is filled.
// *****************************************************************
void PStrCat(Ptr sourceStr, Ptr destinationStr)
{
    unsigned int    srcIndex, dstIndex;
    unsigned int    bytesToCopy;
    
    srcIndex = 1;
    dstIndex = destinationStr[0] + 1;
    bytesToCopy = sourceStr[0];
    
    while(bytesToCopy > 0 && dstIndex < 255)
    {
        destinationStr[dstIndex] = sourceStr[srcIndex];
        dstIndex++;
        srcIndex++;
        bytesToCopy--;
    }
    destinationStr[0] = dstIndex - 1;
}
// *****************************************************************
// *    DoActivate
// *
// * This is called when a window is activated or deactivated.
// * In Sample, the Window Manager's handling of activate and
// * deactivate events is sufficient. Other applications may have
// * TextEdit records, controls, lists, etc., to activate/deactivate.
// *****************************************************************
void DoActivate (WindowPtr window, Boolean becomingActive)
{
#pragma unused (window,becomingActive)
 
} /*DoActivate*/
 
 
// *****************************************************************
// *    ShowError
// *
// * Our routine for displaying an error message in a dialog box.
// *****************************************************************
void ShowError(short index)
{
short itemHit;
 
    switch (index)
    {
        case atalkErr:
            ParamText("\perror loading AppleTalk drivers!","\p","\p","\p");
            break;
        case memErr:
            ParamText("\pmemory error.","\p","\p","\p");
            break;
        case menuErr:
            ParamText("\perror initializing menus.","\p","\p","\p");
            break;
        case nbpErr:
            ParamText("\pCouldn't register our name on the network (duplicate already exists).","\p","\p","\p");
            break;
        case noTargetErr:
            ParamText("\ptarget not found.","\p","\p","\p");
            break;
        case badROMsErr:
            ParamText("\pYour machine does not have at least 128K ROMs.","\p","\p","\p");
            break;
        case heapErr:
            ParamText("\pNot enough heap space.","\p","\p","\p");
            break;
        case noMemErr:
            ParamText("\pNot enough memory.","\p","\p","\p");
            break;
        case DrvrErr:
            ParamText("\pFatal Device Manager error.","\p","\p","\p");
            break;
        case SktErr:
            ParamText("\pError opening a socket.","\p","\p","\p");
            break;
        case RsrcErr:
            ParamText("\pError getting program resources.","\p","\p","\p");
            break;
        case dataNotValidErr:
            ParamText("\pTest data received was not valid.","\p","\p","\p");
            break;
        case dataIsValid:
            ParamText("\pTest data received is correct!","\p","\p","\p");
            break;
 
    }
    
    itemHit = Alert(rErrorDialog, nil);
 
}
 
// *****************************************************************
// *    FatalError
// *
// * This is called when we detect that we cannot operate in the
// * current environment.
// *****************************************************************
void FatalError(error)
    short error;
{
 
    ShowError(error);
    ExitToShell();
}
 
// *****************************************************************
// *    IsAppWindow
// *
// *    Tells us whether or not a window is an application window
// *
// *****************************************************************
Boolean IsAppWindow(window)
    WindowPtr   window;
{
    short       windowKind;
 
    if ( window == nil )
        return false;
    else {  /* application windows have windowKinds >= userKind (8) or dialogKind (2) */
        windowKind = ((WindowPeek) window)->windowKind;
        return (windowKind >= userKind) || (windowKind == dialogKind);
    }
} /* IsAppWindow */
 
 
 
 
// *****************************************************************
// *    IsDAWindow
// *
// *    Check if a window belongs to a desk accessory.
// *****************************************************************
Boolean IsDAWindow(WindowPtr window)
{
 
    if (window == nil)
        return false;
    else    /* DA windows have negative windowKinds */
        return((((WindowPeek)window)->windowKind < 0) ? true : false);
} /*IsDAWindow*/
 
// *****************************************************************
// *    DoCloseWindow
// *
// * Close a window. This handles only desk accessory windows because we do not
// * allow our window to be closed. TESample provides an example of how to handle
// * the closing of application windows.
// *****************************************************************
void DoCloseWindow (WindowPtr window)
{
    if (IsDAWindow(window))
        CloseDeskAcc(((WindowPeek)window)->windowKind);
} /*DoCloseWindow*/
 
 
 
 
// *****************************************************************
// *    outlinePopUpMenus
// *
// *    this is a group routine for drawing the popup menu outlines
// *    compleat with drop shadow. the menu title is draw to the left
// *    of the popUp item itself by this routine.
// *****************************************************************
void outlinePopUpMenus (WindowPtr whichWindow, Rect r, Str255 itemString)
{
    FrameRect(&r);
    MoveTo(r.left + 2, r.bottom);
    LineTo(r.right, r.bottom);
    MoveTo(r.right, r.bottom);
    LineTo(r.right, r.top + 2);
    InsetRect(&r, 1, 1);
    EraseRect(&r);
    InsetRect(&r, -1, -1);
    MoveTo(r.left + 5, r.top + 11);
    TextFont(geneva);
    TextSize(9);
    DrawString(itemString);
    drawPopUpTri(whichWindow, r);
}
 
 
 
// *****************************************************************
// *    UpdateUserItems
// *
// *    update procedure for the user items in our dialog.
// *****************************************************************
pascal void UpdateUserItems (WindowPtr whichWindow, short theItem)
{
    GrafPtr savedPort;
    Rect r;
    short kind;
    Handle h;
 
 
        GetPort(&savedPort);
        SetPort(whichWindow);
        GetDItem(whichWindow, theItem, &kind, &h, &r);
        switch(theItem)
        {
            case kzoneItemID: 
                outlinePopUpMenus(whichWindow, r, gZoneString);
                break;
                
            case ktypeItemID: 
                outlinePopUpMenus(whichWindow, r, gTypeStr);
                break;
 
            case kobjectItemID: 
                outlinePopUpMenus(whichWindow, r, gObjStr);
                break;
 
            case kPopupBorderID: 
                UpdateItemBorder(theItem, r);
                break;
 
            case kClockTimeBorder: 
                UpdateItemBorder(theItem, r);
                break;
 
            case kStatusText: 
                break;
 
        }
        SetPort(savedPort);
}
 
// *****************************************************************
// *    DoModeless
// *
// * this handles mouse clicks inside our main dialog
// *****************************************************************
void DoModeless (DialogPtr whichDialog, short whichItem)
{
        Rect r;
        short kind;
        Handle h;
        MenuHandle allPurposeMenu;
        long chosen;
        Point pt;
        Str255 title;
        Boolean reqSent;
 
 
        if (whichDialog == myDialog)
            {
                GetDItem(whichDialog, whichItem, &kind, &h, &r);
                switch(whichItem)
                {
                    case kzoneItemID:
                            pt.v = r.top;
                            pt.h = r.left + 1;
                            LocalToGlobal(&pt);
                            SetCursor(*(GetCursor(watchCursor)));
                            allPurposeMenu = NewMenu(ZoneMenuID, "");
                            InsertMenu(allPurposeMenu, -1);
                            GetZones(allPurposeMenu);
 
                            InitCursor();
                            chosen = PopUpMenuSelect(allPurposeMenu, pt.v, pt.h, 1);
                            if (chosen != 0)
                            {
                                GetItem(allPurposeMenu, LoWord(chosen), gZoneString);
                                gMenuItem = LoWord(chosen);
                                CopyPstr("\p", gObjStr);
                                InvalRect(&r);                                      
                            }
                            InitCursor();
                            DeleteMenu(ZoneMenuID);
                            DisposeMenu(allPurposeMenu);
                            
                        break;
                    case ktypeItemID:
                            if (gATPEntityFilter == false)
                            {
                                pt.v = r.top - 2;
                                pt.h = r.left + 1;
                                LocalToGlobal(&pt);
                                allPurposeMenu = NewMenu(TypeMenuID, "");
                                InsertMenu(allPurposeMenu, -1);
                                SetCursor(*(GetCursor(watchCursor)));
                                LookupNames(allPurposeMenu, false);
                                InitCursor();
                                chosen = PopUpMenuSelect(allPurposeMenu, pt.v, pt.h, 1);
                                if (chosen != 0)
                                {
                                    GetItem(allPurposeMenu, LoWord(chosen), gTypeStr);
                                    gMenuItem = LoWord(chosen);
                                    InvalRect(&r);
                                }
                                
                                DeleteMenu(TypeMenuID);
                                DisposeMenu(allPurposeMenu);
                            }
                            else
                                SysBeep(1);
                        break;
                    case kobjectItemID:
                            pt.v = r.top - 2;
                            pt.h = r.left + 1;
                            LocalToGlobal(&pt);
                            allPurposeMenu = NewMenu(ObjectMenuID, "");
                            InsertMenu(allPurposeMenu, -1);
                            SetCursor(*(GetCursor(watchCursor)));
                            LookupNames(allPurposeMenu, true);
                            InitCursor();
                            chosen = PopUpMenuSelect(allPurposeMenu, pt.v, pt.h, 1);
                            if (chosen != 0)
                            {
                                GetItem(allPurposeMenu, LoWord(chosen), gObjStr);
                                gMenuItem = LoWord(chosen);
                                InvalRect(&r);
                            }
 
 
                            DeleteMenu(ObjectMenuID);
                            DisposeMenu(allPurposeMenu);
                            
                        break;
 
                    case kMoofFilterCheckBox: 
                            if (gATPEntityFilter == false)
                            {
                                SetCtlValue((ControlHandle)h,1);
                                gATPEntityFilter = true;
                                CopyPstr(atpEntityFilter, gTypeStr);
                            }
                            else
                            {
                                SetCtlValue((ControlHandle)h,0);
                                gATPEntityFilter = false;
                                CopyPstr("\p", gTypeStr);
                            }
                            
                            gObjStr[0] = 0;
                                /* update type popup menu */
                            GetDItem(whichDialog, ktypeItemID, &kind, &h, &r);
                            InvalRect(&myDialog->portRect);
 
                            
                        break;  /* iMoofFilter */
 
                    case kReqDataButton:
                            
                                /* clear status string first */
                            ShowStatusString(kBlankText);
                            
                            GetControlTitle((ControlHandle)h,&title);
                                /* Is button titled "Send Requests" ? */
                            if (IUCompPString(title,&kSendReqBtnText,nil) == 0)
                            {
                                    /* go ahead and send a request to the target */
                                reqSent = SendReqToTarget();
                                if (reqSent == true)
                                {
                                        /* haven't stopped continuous requests */
                                    gStopRequests = false;
    
                                        /* is the continuous requests option set? */
                                    if (gSingleRequest == false)
                                    {       /* reset button title to "Stop Requests" */
                                        SetCTitle((ControlHandle)h, &kStopReqBtnText);
                                    }
                                }
                                
                            }
                            else    /* reset button title to "Send Requests" */
                            {
                                gStopRequests = true;
                                SetCTitle((ControlHandle)h, &kSendReqBtnText);
                            }
                            
                        break;
                        
                } /* of case */
            }
    }
 
// *****************************************************************
// *    setEachUserItem
// *
// *    sets the update routine for our dialogs user items
// *****************************************************************
void setEachUserItem (short item)
{
    Rect r;
    short kind;
    Handle h;
    
        GetDItem(myDialog, item, &kind, &h, &r);
        SetDItem(myDialog, item, userItem, (Handle)UpdateUserItems, &r);
 
}
 
// *****************************************************************
// *    HiliteSendReqButton
// *
// *    set the state of the send request button
// *****************************************************************
void HiliteSendReqButton (short mode)
{
    Rect r;
    short kind;
    Handle h;
 
        GetDItem(myDialog, kReqDataButton, &kind, &h, &r);
        HiliteControl((ControlHandle)h, mode);
}
 
// *****************************************************************
// *    DoMenuCommand
// *
// * This is called when an item is chosen from the menu bar (after calling
// * MenuSelect or MenuKey). It performs the right operation for each command.
// * It is good to have both the result of MenuSelect and MenuKey go to
// * one routine like this to keep everything organized.
// *****************************************************************
void DoMenuCommand (long menuResult)
{
 
    short menuID;       /*the resource ID of the selected menu*/
    short menuItem;     /*the item number of the selected menu*/
    short itemHit;
    Str255 daName;
    short daRefNum;
    Boolean handledByDA;
    MenuHandle menu;
 
 
        menuID = HiWord(menuResult);    /* use built-ins (for efficiency)...*/
        menuItem = LoWord(menuResult);  /*to get menu item number and menu number*/
        switch (menuID)
        {
        case mApple: 
                switch(menuItem)
                {
                    case iAbout:                /*bring up alert for About*/
                        itemHit = Alert(rAboutDialog, nil);
                        break;
                    default:
                            /*all non-About items in this menu are DAs*/
                        GetItem(GetMHandle(mApple), menuItem, daName);
                        daRefNum = OpenDeskAcc(daName);
                    break;
                }
            break;
        case mFile: 
                switch(menuItem)
                {
                    case iClose: 
                        DoCloseWindow(FrontWindow());
                        break;
                    case iQuit: 
                        Terminate();
                        break;
                }
            break;
        case mEdit:     /*call SystemEdit for DA editing & MultiFinder*/
                {
                    if (IsDAWindow(FrontWindow()))
                        handledByDA = SystemEdit(menuItem - 1);
                }
            break;
        case mRequestOptions:
                {
                    menu = GetMenuHandle(mRequestOptions);
                    switch(menuItem)
                    {
                        case iReqClockTime:
                                gReqClockTime = true;
                                SetItemMark(menu, iReqClockTime, checkMark);
                                SetItemMark(menu, iReqData, noMark);
                            break;
                        case iReqData: 
                                gReqClockTime = false;
                                SetItemMark(menu, iReqClockTime, noMark);
                                SetItemMark(menu, iReqData, checkMark);
                            break;
                        case iSingleRequest:
                                gSingleRequest = true;
                                SetItemMark(menu, iSingleRequest, checkMark);
                                SetItemMark(menu, iMultipleRequests, noMark);
                            break;
                        case iMultipleRequests:
                                gSingleRequest = false;
                                SetItemMark(menu, iSingleRequest, noMark);
                                SetItemMark(menu, iMultipleRequests, checkMark);
                            break;
                    }
                }
            break;
 
        }
        
        HiliteMenu(0);      /*unhighlight what MenuSelect (or MenuKey) hilited*/
        
} /*DoMenuCommand*/
 
 
// *****************************************************************
// *    AdjustMenus
// *
// * Enable and disable menus based on the current state.
// * The user can only select enabled menu items. We set up all the menu items
// * before calling MenuSelect or MenuKey, since these are the only times that
// * a menu item can be selected. Note that MenuSelect is also the only time
// * the user will see menu items. This approach to deciding what enable
// * disable state a menu item has the advantage of concentrating all the decision-
// * making in one routine, as opposed to being spread throughout the application.
// * Other application designs may take a different approach that is just as valid.
// *****************************************************************
void AdjustMenus()
{
    WindowPtr window;
    MenuHandle menu;
 
 
        window = FrontWindow();
 
        menu = GetMHandle(mFile);
        if (IsDAWindow(window))             /*we can allow desk accessories to be closed from the menu*/
            EnableItem(menu, iClose);
        else
            DisableItem(menu, iClose);          /*but not our window*/
 
        menu = GetMHandle(mEdit);
        if (IsDAWindow(window))
        {                           /*a desk accessory might need the undo item */
            EnableItem(menu, iUndo);
            EnableItem(menu, iCut);
            EnableItem(menu, iCopy);
            EnableItem(menu, iPaste);
            EnableItem(menu, iClear);
        }
        else
        {                           /* but we do not support undo!!! */
            DisableItem(menu, iUndo);
            DisableItem(menu, iCut);
            DisableItem(menu, iCopy);
            DisableItem(menu, iPaste);
            DisableItem(menu, iClear);
        }
 
} /*AdjustMenus*/
 
 
 
 
 
 
// *****************************************************************
// *    Terminate
// *
// *    if we need to quit the program, we remove the connection
// *    end (if any), deallocate any memory we used, remove our
// *    nbp name from the network and exit.
// *****************************************************************
void Terminate()
{
    removeATP();
    ExitToShell();
}
 
// *****************************************************************
// *    Exit
// *
// *    this routine is called for fatal control call errors. We exit
// *    the program in this situation.
// *****************************************************************
void Exit(short message)
{
    ShowError(message);
    Terminate();
}
 
// *****************************************************************
// *    DoIdleProc
// *
// *    this routine is called each time through our event loop. We
// *    process any atpp errors that were returned and check for connections
// *    coming and going.
// *****************************************************************
void DoIdleProc()
{
    ATPLoop();
}
 
 
// *****************************************************************
// *    AdjustCursor
// *
// *Change the cursor's shape, depending on its position. This also calculates the region
// * where the current cursor resides (for WaitNextEvent). If the mouse is ever outside of
// * that region, an event would be generated, causing this routine to be called,
// * allowing us to change the region to the region the mouse is currently in. If
// * there is more to the event than just Òthe mouse movedÓ, we get called before the
// * event is processed to make sure the cursor is the right one. In any (ahem) event,
// * this is called again before we fall back into WNE.
// *****************************************************************
void AdjustCursor (Point mouse, RgnHandle region)
{
    WindowPtr window;
    RgnHandle arrowRgn;
    RgnHandle ourRgn;
    Rect globalPortRect;
 
        window = FrontWindow(); /*we only adjust the cursor when we are in front*/
        if ((!gInBackground) && (!IsDAWindow(window)))
        {
                /*calculate regions for different cursor shapes*/
            arrowRgn = NewRgn();
            ourRgn = NewRgn();
 
                /*start with a big, big rectangular region*/
            SetRectRgn(arrowRgn, extremeNeg, extremeNeg, extremePos, extremePos);
 
                /*calculate ourRgn*/
            if (IsAppWindow(window))
            {
                SetPort(window);            /*make a global version of the portRect*/
                SetOrigin(-window->portBits.bounds.left, -window->portBits.bounds.top);
                globalPortRect = window->portRect;
                RectRgn(ourRgn, &globalPortRect);
                SectRgn(ourRgn, window->visRgn, ourRgn);
                SetOrigin(0, 0);
            }
 
                /*subtract other regions from arrowRgn*/
            DiffRgn(arrowRgn, ourRgn, arrowRgn);
 
                /*change the cursor and the region parameter*/
            if (PtInRgn(mouse, ourRgn))
            {
                SetCursor(&qd.arrow);
                CopyRgn(arrowRgn, region);
 
            }
 
                /*get rid of our local regions*/
            DisposeRgn(arrowRgn);
            DisposeRgn(ourRgn);
        }
} /*AdjustCursor*/
 
// *****************************************************************
// *    UpdateItemBorder
// *
// *    re-draws the borders around our items
// *****************************************************************
void UpdateItemBorder (short item, Rect r)
{
    FontInfo fInfo;
    Rect tRect;
    Str255 theBorderString;
 
        switch(item)
        {
            case kPopupBorderID:
                    strcpy(&theBorderString,"Select A Target Machine");
                break;
 
            case kClockTimeBorder:
                    strcpy(&theBorderString,"Clock Time From Target Machine");
                break;
 
            default:
                break;
        }
 
        c2pstr(theBorderString);
 
        GetFontInfo(&fInfo);
        FrameRect(&r);
        MoveTo(r.left + 5, r.top + fInfo.ascent / 2 - 1);
        tRect.left = r.left + 4;
        tRect.right = tRect.left + StringWidth(theBorderString) + 1;
        tRect.top = r.top;
        tRect.bottom = r.top + 1;
        EraseRect(&tRect);
        DrawString(&theBorderString);
 
}
 
// *****************************************************************
// *    PlotSICN
// *
// * this is the PlotSICN code stolen from Tech Note #
// *****************************************************************
void PlotSICN (Rect theRect,SICNHand theSICN, short theIndex)
{
    SignedByte state;   /* we want a chance to restore original state */
    BitMap srcBits;     /* built up around 'SICN' data so we can _CopyBits */
 
       /* check the index for a valid value */
        if ((GetHandleSize((Handle)theSICN) / sizeof(SICN)) > theIndex)
            {
 
    /* store the resource's current locked/unlocked condition */
                state = HGetState((Handle)theSICN);
 
    /* lock the resource so it won't move during the _CopyBits call */
                HLock((Handle)theSICN);
 
    /* set up the small icon's bitmap */
           /*$PUSH*/
           /*$R-*/
    /* turn off range checking */
                srcBits.baseAddr = (Ptr)(&(**theSICN[theIndex]));
           /*$POP*/
                srcBits.rowBytes = 2;
                SetRect(&srcBits.bounds, 0, 0, 16, 16);
 
    /* draw the small icon in the current grafport */
                CopyBits(&srcBits, &qd.thePort->portBits, &srcBits.bounds, &theRect, srcCopy, nil);
 
    /* restore the resource's locked/unlocked condition */
                HSetState((Handle)theSICN, state);
            }
 
}
 
// *****************************************************************
// *    drawPopUpTri
// *
// * this procedure draws the new "standard" SICN triangle now used
// * in popup menus I guess the drop shadow was not enough of an
// * indiciation to the users of the presence of the pop-up.
// * standard in 7.0 and up systems 
// *****************************************************************
void drawPopUpTri (WindowPtr whichWindow, Rect r)
{
 
#pragma unused (whichWindow)
 
    Handle popUpTri;
    Rect popUpTriRect;
 
        popUpTri = GetResource('SICN', kStandardTriSICN);
        if (popUpTri)
        {
            popUpTriRect = r;
            popUpTriRect.right = popUpTriRect.right - 1;
            popUpTriRect.left = popUpTriRect.right - 16;
            popUpTriRect.top = popUpTriRect.top + 1;
            popUpTriRect.bottom = popUpTriRect.top + 16;
            PlotSICN(popUpTriRect, (SICNHand)popUpTri, 0);
            ReleaseResource(popUpTri);
        }
 
 
}
 
// *****************************************************************
// *    DoEvent
// *
// * Do the right thing for an event. Determine what kind of event it is, and call
// * the appropriate routines.
// *****************************************************************
void DoEvent (EventRecord event)
{
 
    short part;
    char key;
    WindowPtr whichWindow;
 
 
    whichWindow = FrontWindow();
 
        switch(event.what)
        {
            case nullEvent: 
                break;
            case mouseDown: 
                    part = FindWindow(event.where, &whichWindow);
                    if (part != 0)
                    {
                        switch(part)
                        {
                            case inMenuBar: 
                                /*process the menu command*/
                                    AdjustMenus();
                                    DoMenuCommand(MenuSelect(event.where));
                                break;
                            case inSysWindow:               /*let the system handle the mouseDown*/
                                SystemClick(&event, whichWindow);
                                break;
 
                            case inContent: 
                                if (whichWindow != FrontWindow())
                                    SelectWindow(whichWindow);
                                break;
 
                            case inDrag:                        /*pass screenBits.bounds to get all gDevices*/
                                DragWindow(whichWindow, event.where, &qd.screenBits.bounds);
                                break;
                            
                            case inGrow: 
                                break;
                            case inZoomIn:
                            case inZoomOut:
                                break;
                        }
                    }
                break;
            case keyDown:
            case autoKey:
                                /*check for menukey equivalents*/
                    key = (char)(event.message & charCodeMask);
                    if ((event.modifiers & cmdKey) != 0)    /*Command key down*/
                    {
                        if ((event.what == keyDown) || (event.what == autoKey))
                        {
                            AdjustMenus();          /*enable/disable/check menu items properly*/
                            DoMenuCommand(MenuKey(key));
                        }
                    }
                break;                                /*call DoActivate with the window and...*/
            case activateEvt:                        /*true for activate, false for deactivate*/
                DoActivate((WindowPtr)event.message, (event.modifiers & activeFlag) != 0);
                break;
            case updateEvt: 
                break;
            case osEvent: 
                switch(event.message >> 24) /*high byte of message*/
                {
                    case suspendResumeMessage:
                            gInBackground = (event.message & resumeMask) == 0;
                            DoActivate(FrontWindow(), !gInBackground);
                    break;
                }
 
        }
    } /*DoEvent*/
 
 
// *****************************************************************
// *    EventLoop
// *
// * Get events forever, and handle them by calling DoEvent.
// * Get the events by calling WaitNextEvent, if it's available, otherwise
// * by calling GetNextEvent. Also call AdjustCursor each time through the loop.
// *****************************************************************
void EventLoop()
{
 
    RgnHandle cursorRgn;
    Boolean gotEvent;
    EventRecord event;
    long sleepTime;
    WindowPtr whichDialog;
    short whichItem;
    
    
        cursorRgn = NewRgn();           /*weÕll pass WNE an empty region the 1st time thru*/
        sleepTime = 15;
        do
        {
            if (gHasWaitNextEvent)  /*put us 'asleep' forever under MultiFinder*/
            {
                gotEvent = WaitNextEvent(everyEvent, &event, sleepTime, cursorRgn);
            }
            else
            {
                SystemTask();               /*must be called if using GetNextEvent*/
                gotEvent = GetNextEvent(everyEvent, &event);
            }
            DoIdleProc();
            AdjustCursor(event.where, cursorRgn); /*make sure we have the right cursor*/
            whichDialog = FrontWindow();
                /* don't pass command keys or <enter> keys to our dialog */
            if(!((event.what==keyDown)&&(event.modifiers & cmdKey)) && (IsDialogEvent(&event)))     
            {
                if (DialogSelect(&event, &whichDialog, &whichItem))
                    DoModeless(whichDialog, whichItem);
            }
            else        
                DoEvent(event);
        }
        while (true);                   /*loop forever; we quit through an ExitToShell*/
}
 
// *****************************************************************
// *    Main
// *
// *****************************************************************
main()
{
    MaxApplZone();          /*expand the heap so code segments load at the top*/
    CheckEnvirons();        /*check for some basic requirements; exits if not met*/
 
    InitGraf(&qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(nil);
    InitCursor();
    
    if (InitAppleTalk() != noErr)
    {
        ShowError(atalkErr);
        ExitToShell();
    }
    else
    {
        Initialize();           /*initialize the program*/
        UnloadSeg(&Initialize); /*note that Initialize must not be in Main!*/
        EventLoop();            /*call the main event loop*/
    }
}
 
 
#pragma segment Initialize
 
// *****************************************************************
// *    TrapAvailable
// *
// * Check to see if a given trap is implemented. This is only used by the
// * Initialize routine in this program, so we put it in the Initialize segment.
// * The recommended approach to see if a trap is implemented is to see if
// * the address of the trap routine is the same as the address of the
// * Unimplemented trap.
// *****************************************************************
Boolean TrapAvailable(tNumber,tType)
    short       tNumber;
    TrapType    tType;
{
    if ( ( tType == ToolTrap ) &&
        ( gMac.machineType > envMachUnknown ) &&
        ( gMac.machineType < envMacII ) )
    {       /* it's a 512KE, Plus, or SE */
        tNumber = tNumber & 0x03FF;
        if ( tNumber > 0x01FF )                 /* which means the tool traps */
            tNumber = _Unimplemented;           /* only go to 0x01FF */
    }
    return NGetTrapAddress(tNumber, tType) != GetTrapAddress(_Unimplemented);
} /*TrapAvailable*/
 
// *****************************************************************
// *    SetupUserItems
// *
// *****************************************************************
void SetupUserItems()
{
    setEachUserItem(kzoneItemID);
    setEachUserItem(ktypeItemID);
    setEachUserItem(kobjectItemID);
    setEachUserItem(kPopupBorderID);
    setEachUserItem(kClockTimeBorder);
 
}
 
 
 
// *****************************************************************
// *    Initialize
// *
// *    program initialization
// *****************************************************************
void Initialize()
{
 
    Rect r;
    short kind;
    Handle h;
    Handle menuBar;
    DialogPeek dp;
    ATPPBPtr atpPBPtr;
    myATPParamBlockPtr myATPPBPtr;
    MenuHandle menu;
 
        gInBackground = false;
            
        gZoneString[0] = 0;gTypeStr[0] = 0;gObjStr[0] = 0;
 
        GetOurZone();
 
            /*  we will allocate our own window storage instead of letting the Window */
            /*  Manager do it because GetNewWindow may load in temp. resources before */
            /*  making the NewPtr call, and this can lead to heap fragmentation. */
        myDialog = (DialogPtr)(NewPtr(sizeof(DialogRecord)));
        if (myDialog == nil)
            Exit(memErr);
 
 
        myDialog = GetNewDialog(rDialog, (Ptr)myDialog, (DialogPtr)-1);
 
        SetPort(myDialog);
 
        dp = (DialogPeek)myDialog;
 
        TextFont(geneva);
        TextSize(9);
 
        SetWTitle(myDialog, "\pATP");
 
        ShowWindow(myDialog);
 
        LastZoneMenuChoice = 0;
        LastTypeMenuChoice = 0;
        LastObjectMenuChoice = 0;       
        
        SetupUserItems();
 
            /* turn on type entity filter (check box) initially */
        GetDItem(myDialog, kMoofFilterCheckBox, &kind, &h, &r);
        SetCtlValue((ControlHandle)h,1);
        gATPEntityFilter = true;
        CopyPstr(atpEntityFilter, gTypeStr);
        gObjStr[0] = 0;
        
        menuBar = GetNewMBar(rMenuBar);     /*read menus into menu bar*/
        if (menuBar == nil)
            Exit(menuErr);
        SetMenuBar(menuBar);                    /*install menus*/
        DisposHandle(menuBar);
        AddResMenu(GetMHandle(mApple), 'DRVR'); /*add DA names to Apple menu*/
        DrawMenuBar();
 
            /* initialize our "Request Options" menu */
        menu = GetMenuHandle(mRequestOptions);
 
        gReqClockTime = true;
        SetItemMark(menu, iReqClockTime, checkMark);
        gSingleRequest = false;
        SetItemMark(menu, iMultipleRequests, checkMark);
 
        gStopRequests = false;
        initializeATP();
 
        gTestDataHdl = GetResource(kTestDataType,kTestDataRsrcID);
        if (gTestDataHdl == NULL)
            Exit(RsrcErr);
 
        gTestDataSize = MaxSizeRsrc(gTestDataHdl);
 
        atpPBPtr = GetQElement(&gAvailQueue);
        if (atpPBPtr != NULL)
        {
            myATPPBPtr = GetOurPBPtr(atpPBPtr);
                /* issue a get request so that we may receive requests from
                    other machines */
            doGetRequest(atpPBPtr,
                        gOurATPSocket,
                        sizeof(struct ourReqData),
                        myATPPBPtr->reqData);
        }
        else
/* ???????????????????????? */;
 
} /*Initialize*/
 
// *****************************************************************
// *    CheckEnvirons
// *
// *    check the current operating environment
// *****************************************************************
void CheckEnvirons()
{
    long  total, contig, response;
    OSErr ignoreError;
 
    
        /* ignore the error returned from SysEnvirons; even if an error occurred,*/
        /* the SysEnvirons glue will fill in the SysEnvRec*/
            ignoreError = SysEnvirons(sysEnvironsVersion, &gMac);
 
        /* Make sure that the machine has at least 128K ROMs. If it doesn't, exit. */
        if (gMac.machineType < 0) FatalError(9);
        if ((long) GetApplLimit() - (long) ApplicZone() < kMinHeap) FatalError(10);
        PurgeSpace(&total, &contig);
        if (total < kMinSpace)
            if (UnloadScrap() != noErr)
                FatalError(11);
            else
            {
                PurgeSpace(&total, &contig);
                if (total < kMinSpace)
                    FatalError(11);
            }
            
        /* verify if WaitNextEvent, Gestalt and PPCToolbox are available */
        gHasWaitNextEvent = TrapAvailable(_WaitNextEvent, ToolTrap);
        if (TrapAvailable(_Gestalt, ToolTrap)) 
        {       /* verify if system 7.0 */
            Gestalt(gestaltSystemVersion,&response );
            if (response >= 0x0700)
                gHasSystem7 = true;
            else gHasSystem7 = false;
        }
        else
        {
            SysBeep(20);
            gHasSystem7 = false;
        }
 
}