Source/MainStuff.c

/*--------------------------------------------------------------------------------------
//
//  File:       MainStuff.c
//
//  Contents:   Main event loop.  Only those portions needed for support of the tools 
//              features have been included.
//
//
//  By Georgiann ("George") Delaney
//  ©Ê1989 - 1990, Apple Computer, Inc.
//
//--------------------------------------------------------------------------------------*/
 
 
#include "MacHeaders.h"
 
#include "BitBlitz.h"
#include "MainStuff.h"
 
 
#pragma segment main
 
 
 
/*======================================================================================*/
/*  Shell Global Variables  */
 
Boolean     gFinished       = false;            /* Does the user want to quit the application?      */
 
Boolean     gWNEAvailable;                      /* Specifies if WaitNextEvent is available          */
Boolean     gInBackground   = false;            /* Is the application in the background under MF    */ 
 
Handle      gtheMenuBar;                        /* Handle to the tool menus                         */
MenuHandle  gtheMenus[kMenuCount+kHeirCount];   /* Structure holding the application menus          */  
 
short       gCmdOn          = false;            /* Is the command key being pressed?                */
 
Boolean     gDoubleClick    = false;            /* Determines if the user double-clicked            */
long        gLastTime;
Point       gLastPoint;                         
 
 
 
/*======================================================================================*/
/*  Setup Routines  */
 
 
 
/*--------------------------------------------------------------------------------------*/
void SetUpMenu()
/*
//  This procedure reads in all of the menu resources and builds the application 
//  menu.
*/
{
    short   n;
 
    InitMenus();
    
    gtheMenus[kAppleMenu]   = GetMenu( kAppleMenuID );
    AddResMenu(gtheMenus[kAppleMenu],'DRVR');
    
    gtheMenus[kFileMenu]      = GetMenu(kFileMenuID);
    gtheMenus[kEditMenu]      = GetMenu(kEditMenuID);
    gtheMenus[kOptionsMenu]   = GetMenu(kOptionsMenuID);
 
    gtheMenus[khCopyModeMenu] = GetMenu(khCopyModeMenuID);
    gtheMenus[khClipRgnMenu]  = GetMenu(khClipRgnMenuID);
    gtheMenus[khVisRgnMenu]   = GetMenu(khVisRgnMenuID);
    gtheMenus[khMaskRgnMenu]  = GetMenu(khMaskRgnMenuID);
 
    gtheMenus[khFGColorMenu]  = GetMenu(khFGColorMenuID);
    gtheMenus[khBKColorMenu]  = GetMenu(khBKColorMenuID);
    gtheMenus[khOPColorMenu]  = GetMenu(khOPColorMenuID);
    gtheMenus[khHiliteMenu]   = GetMenu(khHiliteMenuID);
 
    for ( n = 0; n < kMenuCount; n++ ) 
        InsertMenu(gtheMenus[n],0);
 
    for ( n = n; n < (kMenuCount+kHeirCount); n++ ) 
        InsertMenu(gtheMenus[n], hierMenu);
 
    gtheMenuBar = GetMenuBar();  
    DrawMenuBar();
}
 
 
/*--------------------------------------------------------------------------------------*/
void InitAppMenus()
{
 
    if (!gColorAvail)  {
       DisableItem(gtheMenus[kOptionsMenu], kSrcOr );
       DisableItem(gtheMenus[kOptionsMenu], kSrcXor );
       DisableItem(gtheMenus[kOptionsMenu], kSrcBic );
       DisableItem(gtheMenus[kOptionsMenu], kNotSrcCopy );
       DisableItem(gtheMenus[kOptionsMenu], kNotSrcOr );
       DisableItem(gtheMenus[kOptionsMenu], kNotSrcXor );
       DisableItem(gtheMenus[kOptionsMenu], kNotSrcBic );
       DisableItem(gtheMenus[kOptionsMenu], kBlend );
       DisableItem(gtheMenus[kOptionsMenu], kAddPin );
       DisableItem(gtheMenus[kOptionsMenu], kAddOver );
       DisableItem(gtheMenus[kOptionsMenu], kAddMin );
       DisableItem(gtheMenus[kOptionsMenu], kAddMax );
       DisableItem(gtheMenus[kOptionsMenu], kSubPin );
       DisableItem(gtheMenus[kOptionsMenu], kSubOver );
       DisableItem(gtheMenus[kOptionsMenu], kTransparent );
       DisableItem(gtheMenus[kOptionsMenu], kHilite );
       }
    else
        CheckItem  (gtheMenus[khCopyModeMenu],CopyMode2ModeMenuItem(gCopyMode),true);
 
}
 
/*--------------------------------------------------------------------------------------*/
void InitMac()
/*
//  This procedure executes all Macintosh initialization functions. 
*/
{
    EventRecord theEvent;
    
    MaxApplZone();
    MoreMasters();  MoreMasters();  MoreMasters();  MoreMasters();
 
    InitGraf(&qd.thePort);
    InitFonts();
    InitWindows();
    SetUpMenu();
    TEInit();
    InitDialogs(nil);
    InitCursor();
    InitAllPacks();
            
    gWNEAvailable = myTrapAvailable(_WaitNextEvent, ToolTrap);
 
    EventAvail(everyEvent,&theEvent);   /* Force windows to frontÉ (for MF) */
}
 
 
 
 
/*======================================================================================*/
/*  Main Loop and Event Management Routines  */
 
 
/*--------------------------------------------------------------------------------------*/
Boolean IsDAWindow( window )
    WindowPtr   window;
{
    if ( window == nil )
        return false;
    else    
        return ( (WindowPeek) window)->windowKind < 0;
} 
 
 
/*--------------------------------------------------------------------------------------*/
void AdjustMenusForDA()
{
    EnableItem (gtheMenus[kFileMenu], kNew);
    EnableItem (gtheMenus[kFileMenu], kOpen);
    EnableItem (gtheMenus[kFileMenu], kClose);
    EnableItem (gtheMenus[kFileMenu], kSave);
    EnableItem (gtheMenus[kFileMenu], kSaveAs);
    EnableItem (gtheMenus[kFileMenu], kPageSetUp);
    EnableItem (gtheMenus[kFileMenu], kPrint);
    EnableItem (gtheMenus[kFileMenu], kQuit);
 
    EnableItem (gtheMenus[kEditMenu], kUndo);
    EnableItem (gtheMenus[kEditMenu], kCut);
    EnableItem (gtheMenus[kEditMenu], kCopy);
    EnableItem (gtheMenus[kEditMenu], kPaste);
    EnableItem (gtheMenus[kEditMenu], kClear);
 
    DisableItem(gtheMenus[kOptionsMenu], kSrcAttributes );
    DisableItem(gtheMenus[kOptionsMenu], kMskAttributes );
    DisableItem(gtheMenus[kOptionsMenu], kDstAttributes );
    
    DisableItem(gtheMenus[kOptionsMenu], kTrapSelect);
    DisableItem(gtheMenus[kOptionsMenu], kCopyModeSelect);
    DisableItem(gtheMenus[kOptionsMenu], kMaskRgnSelect);
} 
 
 
/*--------------------------------------------------------------------------------------*/
void AdjustMenusForApp()
{
    DisableItem(gtheMenus[kFileMenu], kNew);
    DisableItem(gtheMenus[kFileMenu], kOpen);
    DisableItem(gtheMenus[kFileMenu], kClose);
    DisableItem(gtheMenus[kFileMenu], kSave);
    DisableItem(gtheMenus[kFileMenu], kSaveAs);
    DisableItem(gtheMenus[kFileMenu], kPageSetUp);
    DisableItem(gtheMenus[kFileMenu], kPrint);
    EnableItem (gtheMenus[kFileMenu], kQuit);
 
    DisableItem(gtheMenus[kEditMenu], kUndo);
    DisableItem(gtheMenus[kEditMenu], kCut);
    DisableItem(gtheMenus[kEditMenu], kCopy);
    DisableItem(gtheMenus[kEditMenu], kPaste);
    DisableItem(gtheMenus[kEditMenu], kClear);
 
    EnableItem (gtheMenus[kOptionsMenu], kSrcAttributes );
    EnableItem (gtheMenus[kOptionsMenu], kMskAttributes );
    EnableItem (gtheMenus[kOptionsMenu], kDstAttributes );
    
    EnableItem (gtheMenus[kOptionsMenu], kTrapSelect);
        
    EnableItem (gtheMenus[kOptionsMenu],  kFGColor);
    CheckItem  (gtheMenus[khFGColorMenu], gFGColor.menuIndex,   true);
    
    EnableItem (gtheMenus[kOptionsMenu],  kBKColor);
    CheckItem  (gtheMenus[khBKColorMenu], gBKColor.menuIndex,   true);
 
    EnableItem (gtheMenus[kOptionsMenu],  kClipRgnSelect);
    CheckItem  (gtheMenus[khClipRgnMenu], gRList[kClpRgn].type, true);
 
    EnableItem (gtheMenus[kOptionsMenu],  kVisRgnSelect);
    CheckItem  (gtheMenus[khVisRgnMenu],  gRList[kVisRgn].type, true);
 
    EnableItem (gtheMenus[kOptionsMenu],  kUseScreenBits);
    CheckItem  (gtheMenus[kOptionsMenu],  kUseScreenBits,       gUseScreenBits);
 
    EnableItem (gtheMenus[kOptionsMenu],  kDither);
    CheckItem  (gtheMenus[kOptionsMenu],  kDither,              gDither);
    
    if (gColorAvail)  {
        EnableItem (gtheMenus[kOptionsMenu], kOpColor);
        CheckItem  (gtheMenus[khOPColorMenu],gOPColor.menuIndex,true);
 
        EnableItem (gtheMenus[kOptionsMenu], kHiliteColor);
        CheckItem  (gtheMenus[khHiliteMenu], gHiliteColor.menuIndex,true);
        }
    else  {
        DisableItem(gtheMenus[khFGColorMenu], kCustomColor);
        DisableItem(gtheMenus[khFGColorMenu], kCustomColor);
 
        DisableItem(gtheMenus[kOptionsMenu], kOpColor);
        DisableItem(gtheMenus[kOptionsMenu], kHiliteColor);
        }
    
    if ((gTrapSelect == kCopyDeepMask) || (gTrapSelect == kCopyBits))  {
        EnableItem (gtheMenus[kOptionsMenu],  kCopyModeSelect);
        EnableItem (gtheMenus[kOptionsMenu],  kMaskRgnSelect);
        CheckItem  (gtheMenus[khMaskRgnMenu], gRList[kMskRgn].type,true);
 
        if (gTrapSelect == kCopyBits)  
            DisableItem(gtheMenus[kOptionsMenu], kMskAttributes );
        }
    else {
        DisableItem(gtheMenus[kOptionsMenu], kCopyModeSelect);
        DisableItem(gtheMenus[kOptionsMenu], kMaskRgnSelect);
        }
} 
 
 
/*--------------------------------------------------------------------------------------*/
void AdjustMenus()
/*
    AdjustMenus will properly activate/deactivate/update each menu item in each 
    of the menus to properly reflect the available selections with respect to the
    currently active window.
*/
{
    WindowPtr   theActiveWindow;
    
    theActiveWindow = FrontWindow();        
    
    if (IsDAWindow(theActiveWindow)) 
         AdjustMenusForDA();
    else AdjustMenusForApp(); 
}
 
 
/*--------------------------------------------------------------------------------------*/
void DoMenuCommand(long menuData)
{
    short       theMenu;
    short       theItem;
    Str255      theName;
    short       theRefNum;
    Boolean     imageChanged = true;
    OSErr       result       = noErr;
    
    theMenu = HiWord(menuData);
    theItem = LoWord(menuData);
 
    switch (theMenu)  { 
        case kAppleMenuID:
            switch ( theItem )  {
                case kAboutBox:     AboutBitBlitz();        break;
                default:
                    GetItem(GetMHandle(kAppleMenuID), theItem, theName);
                    theRefNum = OpenDeskAcc(theName);
                    break;
                }
            break;
            
        case kFileMenuID:
            switch ( theItem )  {
                case kNew:          break;
                case kOpen:         break;
                case kClose:        break;
                case kSave:         break;
                case kSaveAs:       break;
                case kPageSetUp:    break;
                case kPrint:        break;
                case kQuit:         gFinished = true;       break;
                }
            break;
            
        case kEditMenuID:
            switch ( theItem )  {
                case kUndo:         break;
                case kCut:          break;
                case kCopy:         break;
                case kPaste:        break;
                case kClear:        break;
                }
            break;
 
        case kOptionsMenuID:
            switch ( theItem )  {
                case kSrcAttributes:  ChangeWindowAttributes(kSrcWindow);   break;
                case kMskAttributes:  ChangeWindowAttributes(kMskWindow);   break;
                case kDstAttributes:  ChangeWindowAttributes(kDstWindow);   break;
                case kTrapSelect:     SelectTrap();                         break;
                case kUseScreenBits:  gUseScreenBits = !gUseScreenBits;
                                      CheckItem (gtheMenus[kOptionsMenu],kUseScreenBits,gUseScreenBits);
                                      DrawBuffer(kBitWindow);
                                      DrawWindow(kBitWindow);
                                      break;
                case kDither:         gDither = !gDither;
                                      CheckItem (gtheMenus[kOptionsMenu],kDither,gDither);
                                      if ((gCopyMode == srcCopy) || (gCopyMode == ditherCopy)) {
                                        if (gDither)
                                            gCopyMode = ditherCopy;
                                        else
                                            gCopyMode = srcCopy;
                                        }
                                      DrawBuffer(kBitWindow);
                                      DrawWindow(kBitWindow);
                                      break;
                }
            break;
        
        case khCopyModeMenuID:  
            CheckItem(gtheMenus[khCopyModeMenu],CopyMode2ModeMenuItem(gCopyMode),false);
            CheckItem(gtheMenus[khCopyModeMenu],theItem,true);
            gCopyMode = ModeMenuItem2CopyMode(theItem);
            DrawBuffer(kBitWindow);
            DrawWindow(kBitWindow);
            break;      
 
        case khClipRgnMenuID:   
            CheckItem (gtheMenus[khClipRgnMenu],gRList[kClpRgn].type,false);
            SelectRgn (kClpRgn,theItem);    
            CheckItem (gtheMenus[khClipRgnMenu],gRList[kClpRgn].type,true);
            break;      
 
        case khVisRgnMenuID:    
            CheckItem (gtheMenus[khVisRgnMenu],gRList[kVisRgn].type,false);
            SelectRgn (kVisRgn,theItem);    
            CheckItem (gtheMenus[khVisRgnMenu],gRList[kVisRgn].type,true);
            break;      
 
        case khMaskRgnMenuID:   
            CheckItem (gtheMenus[khMaskRgnMenu],gRList[kMskRgn].type,false);
            SelectRgn (kMskRgn,theItem);    
            CheckItem (gtheMenus[khMaskRgnMenu],gRList[kMskRgn].type,true);
            break;      
 
        case khFGColorMenuID:
            CheckItem (gtheMenus[khFGColorMenu],gFGColor.menuIndex,false);
            SelectFGColor(theItem); 
            CheckItem (gtheMenus[khFGColorMenu],gFGColor.menuIndex,true);
            break;
            
        case khBKColorMenuID:   
            CheckItem (gtheMenus[khBKColorMenu],gBKColor.menuIndex,false);
            SelectBKColor(theItem); 
            CheckItem (gtheMenus[khBKColorMenu],gBKColor.menuIndex,true);
            break;
 
        case khOPColorMenuID:   
            CheckItem (gtheMenus[khOPColorMenu],gOPColor.menuIndex,false);
            SelectOPColor(theItem); 
            CheckItem (gtheMenus[khOPColorMenu],gOPColor.menuIndex,true);
            break;
 
        case khHiliteMenuID :   
            CheckItem (gtheMenus[khHiliteMenu],gHiliteColor.menuIndex,false);
            SelectHiliteColor(theItem); 
            CheckItem (gtheMenus[khHiliteMenu],gHiliteColor.menuIndex,true);
            break;
        }
    HiliteMenu(0);                  
}
 
 
/*--------------------------------------------------------------------------------------*/
void DoGrowWindow(WindowPtr  theWindow, EventRecord  *theEvent)
{
    long    newSize;
    Point   newDimen, oldDimen;
    
    
    if (theWindow != FrontWindow()) 
        SelectWindow(theWindow);
    else
        SetPort(theWindow);
        
    newSize = GrowWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
    
    if (newSize != 0)  {
        SetCursor(*GetCursor(watchCursor));
 
        newDimen.h = LoWord(newSize);
        newDimen.v = HiWord(newSize);
        
        if ((theWindow == gWList[kSrcWindow].window) || (theWindow == gWList[kMskWindow].window)) {
            SetPort(gWList[kSrcWindow].window);
            if (ResizeTestWindow(&newDimen,kSrcWindow)) { 
                oldDimen.h = gWList[kSrcWindow].window->portRect.right  - gWList[kSrcWindow].window->portRect.left;
                oldDimen.v = gWList[kSrcWindow].window->portRect.bottom - gWList[kSrcWindow].window->portRect.top;
 
                SetPort(gWList[kMskWindow].window);
                if (ResizeTestWindow(&newDimen,kMskWindow))  {
                    SizeWindow(gWList[kMskWindow].window,newDimen.h,newDimen.v,false);
                    SizeWindow(gWList[kSrcWindow].window,newDimen.h,newDimen.v,false);
                    }
                else {
                    SetPort(gWList[kSrcWindow].window);
                    ResizeTestWindow(&oldDimen,kSrcWindow);
                    }
                }
            }
 
        if ((theWindow == gWList[kDstWindow].window) || (theWindow == gWList[kBitWindow].window)) {
            SetPort(gWList[kDstWindow].window);
            if (ResizeTestWindow(&newDimen,kDstWindow))  {
                oldDimen.h = gWList[kDstWindow].window->portRect.right  - gWList[kDstWindow].window->portRect.left;
                oldDimen.v = gWList[kDstWindow].window->portRect.bottom - gWList[kDstWindow].window->portRect.top;
                
                SetPort(gWList[kBitWindow].window);
                if (ResizeTestWindow(&newDimen,kBitWindow))  {
                    SizeWindow(gWList[kBitWindow].window,newDimen.h,newDimen.v,false);
                    SizeWindow(gWList[kDstWindow].window,newDimen.h,newDimen.v,false);
                    UpdateRgnSettings();
                    }
                else {
                    SetPort(gWList[kDstWindow].window);
                    ResizeTestWindow(&oldDimen,kDstWindow);
                    }
                }
            }
                
        SetPort(theWindow);
                        
        DrawBuffer(kBitWindow);
        DrawWindow(kSrcWindow);
        DrawWindow(kMskWindow);
        DrawWindow(kDstWindow);
        DrawWindow(kBitWindow);
        
        InitCursor();
        }
}
 
 
/*--------------------------------------------------------------------------------------*/
short abs(short a)
{
    return((a<0)?-a:a);
}
 
/*--------------------------------------------------------------------------------------*/
Boolean AlmostEqualPt(Point *pt1, Point *pt2, short tolerance)
/*
//   AlmostEqualPt() determines if two points are equal within the specified tolerance.
*/
{
    return ((abs(pt2->h - pt1->h) < tolerance) && (abs(pt2->v - pt1->v) < tolerance));
}
 
/*--------------------------------------------------------------------------------------*/
void DoMouseDown(EventRecord  *theEvent)
{
    short       thePart;
    WindowPtr   theWindow;
    register    i;
 
 
    gDoubleClick  = ((theEvent->when - gLastTime) <= GetDblTime());
    gDoubleClick  = ( (gDoubleClick) && AlmostEqualPt(&gLastPoint,&theEvent->where,3));
 
    thePart = FindWindow(theEvent->where, &theWindow);
    switch ( thePart )  {
        case inMenuBar: 
           AdjustMenus();
           DoMenuCommand(MenuSelect(theEvent->where));
           break;
           
        case inSysWindow:       
           SystemClick( theEvent, theWindow );
           break;
           
        case inContent:
            if (theWindow != FrontWindow()) 
                SelectWindow(theWindow);
            else  {
                SetPort(theWindow);
                if (gDoubleClick)  
                    for (i=kSrcWindow; i<=kBitWindow;  i++)
                        if (theWindow == gWList[i].window)
                            if (i<kBitWindow)
                                ChangeWindowAttributes(i);
                            else
                                SysBeep(10);
                }
            break;
           
        case inDrag:                
            DragWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
            if (gUseScreenBits)  {
                for (i=kSrcWindow; i<=kDstWindow;  i++)
                    DrawWindow(i);
                DrawBuffer(kBitWindow);
                DrawWindow(kBitWindow);
                }
            break;
           
        case inGrow:
            DoGrowWindow(theWindow, theEvent);
            break;
           
        case inZoomIn:
        case inZoomOut:
            if ( TrackBox(theWindow, theEvent->where, thePart) ) 
            {
                SetPort(theWindow);             
                ZoomWindow(theWindow, thePart, true);   
                InvalRect(&theWindow->portRect);    
            }
            break;
        }
    
    gLastTime  = theEvent->when;
    gLastPoint = theEvent->where;
}
 
 
/*--------------------------------------------------------------------------------------*/
void DoKeyDown( theEvent )
    EventRecord *theEvent;
{
    char        theKey;
 
    gCmdOn  = ( theEvent->modifiers & cmdKey );
    theKey  = theEvent->message & charCodeMask;
 
    if ((gCmdOn) && (theEvent->what == keyDown))  {
        AdjustMenus();                      
        DoMenuCommand( MenuKey(theKey) );
        }
}
 
 
/*--------------------------------------------------------------------------------------*/
void DoUpdate(EventRecord   *theEvent)
{
    WindowPtr   theWindow;
 
    theWindow   = (WindowPtr)theEvent->message;
    
    if (theWindow != nil)  {
        BeginUpdate(theWindow);
        
        if (theWindow == gWList[kSrcWindow].window)
            DrawWindow(kSrcWindow);
        else if (theWindow == gWList[kMskWindow].window) 
            DrawWindow(kMskWindow);
        else if (theWindow == gWList[kDstWindow].window) 
            DrawWindow(kDstWindow);
        else if (theWindow == gWList[kBitWindow].window) 
            DrawWindow(kBitWindow);
        
        EndUpdate(theWindow);
        }
}
 
 
/*--------------------------------------------------------------------------------------*/
void DoEvent(EventRecord  *theEvent)
{
    switch (theEvent->what)  {
        case nullEvent:
            break;
    
        case mouseDown: 
            DoMouseDown(theEvent);  
            break;
            
        case keyDown:
        case autoKey:   
            DoKeyDown(theEvent);
            break;
            
        case activateEvt:
            InitCursor();
            break;
            
        case updateEvt:
            DoUpdate(theEvent); 
            break;
            
        case diskEvt:
            break;
        }
} 
 
 
 
/*--------------------------------------------------------------------------------------*/
void MainLoop()
{
    EventRecord     theEvent;
 
    do  {
        if (gWNEAvailable)
            WaitNextEvent(everyEvent, &theEvent, LONG_MAX, nil);
        else  {
            SystemTask();
            GetNextEvent(everyEvent, &theEvent);
            }
        
        DoEvent(&theEvent);
        
        } while (! gFinished);
        
}
 
 
/*--------------------------------------------------------------------------------------*/
main()
{
    SysEnvRec   theWorld;
    
            /*  Perform standard mac initialization. */         
    InitMac();      
    
 
    SysEnvirons(1, &theWorld);
    
    
    if (theWorld.systemVersion < 0x0700)  {
        NeedSystem7Dlog();
        ExitToShell();
        }   
 
    
    InitTestGlobals();
    InitAppMenus();
                
            /*  Initialize all of the app's windows' structures. */         
    InitTestWindowAttributes();
    InitColorSettings();
    InitRgnSettings();
    
            /*  If there is not enough memory to bring up windows exit. */          
    if (CreateTestWindows())    
        MainLoop();
        
    DisposeRgnSettings();
    DisposeTestWindows();
    ExitToShell();
}