CodeWarrior (OS 9)/RubberBandit.c

/*
    File:       RubberBandit.c
 
    Contains:   a simple srcXor rubber-banding example.
 
    Written by: DH
 
    Copyright:  Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                08/2000     JM              Carbonized, non-Carbon code is commented out
                                            for demonstration purposes.
                7/14/1999   KG              Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include "CarbonPrefix.h"
#include <Dialogs.h>
#include <Fonts.h>   
#include <Processes.h>
 
/* constants:           */
 
#define testDLOG    1234
#define OK_button   1
 
/* function prototypes: */
 
extern void HandleDLOG(DialogPtr theDialog);
extern pascal Boolean RubberProc(DialogPtr theDialog, EventRecord *theEvent, short *itemHit);
extern void RubberBandIt(Point anchorPt);
extern Rect *CheckRect(Rect *theRect);
extern void DrawStuff(Rect *rubberRect);
extern void FanStuff(Rect *theRect);
 
 
void main(void) 
{
    DialogPtr   theDialog = NULL;
 
    /*InitGraf(&qd.thePort);
    InitFonts();
    FlushEvents(everyEvent, 0);
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(0L);*/
    InitCursor();
    
    theDialog = GetNewDialog(testDLOG, NULL, (WindowPtr) -1L);
    if (theDialog != NULL) HandleDLOG(theDialog);
        
    ExitToShell();
}
 
 
/*  ================================================
    HandleDLOG calls ModalDialog and rubber-bands
    until the OK button is pressed.
    ================================================    */
 
void HandleDLOG(theDialog)
DialogPtr theDialog;
{
    short       itemHit;
    GrafPtr     oldPort;
    Point       anchorPt;
 
    do
    {
        ModalDialog(NULL, &itemHit);
 
        if (itemHit != OK_button)
        {
            GetPort(&oldPort);          /* Save the port, set it to our dialog, */
            //SetPort(theDialog);
            SetPortWindowPort(GetDialogWindow(theDialog));
            GetMouse(&anchorPt);        /* get the current mouse pos. and       */
            RubberBandIt(anchorPt);     /* rubber-band the image.               */
            SetPort(oldPort);           /* Restore the original port.           */
        }
    }
    while (itemHit != OK_button);
    
    DisposeDialog(theDialog);           /* Throw away the dialog.               */
}
 
 
/*  ================================================
    RubberBandIt follows the mouse and rubber-bands
    a design based on its position.  It retains
    control until the mouse button is released.
    ================================================    */
 
void RubberBandIt(anchorPt)
Point   anchorPt;
{
    Point   curMousePt = {0, 0};
    Rect    rubberRect;
    Pattern gray;
    CGrafPtr    currentPort;
    RgnHandle   rgnHandle = NewRgn();
    
    GetPort(&currentPort);
 
    PenMode(srcXor);                                /* Set pen mode to exclusive or.*/
    PenPat(&gray);
 
    GetMouse(&curMousePt);                          /* Get current mouse pos.       */
 
    rubberRect.top = anchorPt.v;                    /* Draw initial rectangle.      */
    rubberRect.left = anchorPt.h;
    rubberRect.bottom = curMousePt.v;
    rubberRect.right = curMousePt.h;
    DrawStuff(&rubberRect);
 
    while (Button())
    {
        GetMouse(&curMousePt);                      /* Get current mouse posÉ       */
 
        if (curMousePt.h != rubberRect.right ||     /* If mouse movedÉ              */
            curMousePt.v != rubberRect.bottom)
        {
            DrawStuff(&rubberRect);                 /* Erase oldÉ                   */
            rubberRect.bottom = curMousePt.v;
            rubberRect.right = curMousePt.h;
            DrawStuff(&rubberRect);                 /* and draw new.                */
            QDFlushPortBuffer(currentPort, GetPortVisibleRegion(currentPort, rgnHandle));
        }
    }
    
    DrawStuff(&rubberRect);                         /* Erase old at end.            */
    QDFlushPortBuffer(currentPort, GetPortVisibleRegion(currentPort, rgnHandle));
    DisposeRgn(rgnHandle);
}
 
 
/*  ================================================
    DrawStuff draws designs in the rectangle
    passed, using the current pen mode, etc.
    ================================================    */
 
void DrawStuff(rubberRect)
Rect    *rubberRect;
{
    Rect    curRect;
    
    curRect = *rubberRect;
    FrameRect(CheckRect(&curRect));
    FanStuff(CheckRect(&curRect));
}
 
 
/*  ================================================
    FanStuff draws a fanlike thing in the rect
    passed, using the current pen mode, etc.
    ================================================    */
 
void    FanStuff(theRect)
Rect    *theRect;
{
    short   ang;
 
    for (ang = 0; ang < 360; ang += 60)
        PaintArc(theRect, ang, 45);
}
 
 
/*  ================================================
    CheckRect makes sure that the top of the
    rectangle passed is ² the bottom and the left is
    ² the right.  FrameRect needs things this way.
    ================================================    */
 
Rect *CheckRect(theRect)
Rect    *theRect;
{
    short   temp;
 
    if (theRect->top > theRect->bottom)     /* Need to reverse top and bottom? */
    {
        temp = theRect->top;
        theRect->top = theRect->bottom;
        theRect->bottom = temp;
    }
 
    if (theRect->left > theRect->right)     /* Need to reverse left and right? */
    {
        temp = theRect->left;
        theRect->left = theRect->right;
        theRect->right = temp;
    }
    
    return theRect;                         /* This makes nested calls easier.  */
}