home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff502.lzh
/
CELLS
/
CELLSSource.lzh
/
cDoGadget.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
12KB
|
537 lines
/*
* CELLS An Implementation of the WireWorld cellular automata
* as described in Scientific American, Jan 1990.
*
* Copyright 1990 by Davide P. Cervone.
* You may use this code, provided this copyright notice is kept intact.
* See the CELLS.HELP file for complete information on distribution conditions.
*/
/*
* File: cDoGadget.c Handles main control panel gadget events
*/
#include "cGadget.h"
int Running; /* TRUE if the circuit is running */
int QuitInProgress; /* TRUE if save requester is up during a QUIT */
int SliderActive; /* TRUE if a slider knob is being dragged */
int Changed; /* TRUE if the circuit has been modified */
extern char FileName[]; /* Circuit's current name */
/*
* DoStart()
*
* If the circuit is not already running,
* cancel any selection and restore the pointer colors
* copy the current states for use by RESET
* assume that running will change the circuit
* run the circuit until done
* reset pointer to drawing color
* return FALSE if QUIT was pressed during the run
*/
static short DoStart(NotDone)
short NotDone;
{
if (!Running)
{
if (SelectType) CancelSelect();
RestorePointerColor();
CopyGrid(CurGen,ResetArray);
Changed = TRUE;
SetRunning();
NotDone = RunCells(NotDone);
SetPointerColor(PenInUse);
}
return(NotDone);
}
/*
* DoReset()
*
* If no cells selected:
* setup UNDO unless the circuit is running
* update the grid from the reset array and mark as changed
* if the circuit is running,
* set up the new generation array and linked lists
*
* If cells are selected:
* cancel the selection
*/
static void DoReset()
{
switch(SelectType)
{
case SEL_NONE:
if (!Running) CopyGrid(CurGen,UndoArray);
UpdateGrid(CurGen,ResetArray);
Changed = TRUE;
if (Running)
{
CopyGrid(CurGen,NewGen);
SetupLists(CurGen);
}
break;
case SEL_WAIT:
case SEL_MOVE:
CancelSelect();
DoSelect();
break;
}
}
/*
* DoUndo()
*
* Mark the circuit as modified
* If cells are selected:
* Undo only those that are selected, but copy the current states into
* the UNDO buffer
* Cancel the selection
* If cells are being moved or copied:
* cancel the selection and do then do the default function:
* Otherwise:
* swap the current states and the UNDO states and update the screen
*/
static void DoUndo()
{
register short x,y;
register short i;
UBYTE tmp;
Changed = TRUE;
switch(MouseMoveType)
{
case MM_SELECT:
for (y=0,i=0; y<MAXGRIDH; y++)
{
for (x=0; x<MAXGRIDW; x++,i++)
{
if (NewGen[i])
{
tmp = CurGen[i];
CurGen[i] = UndoArray[i];
UndoArray[i] = tmp;
} else {
UndoArray[i] = CurGen[i];
}
}
}
CancelSelect();
break;
case MM_MOVE:
case MM_COPY:
CancelSelect();
default:
CopyGrid(CurGen,NewGen);
UpdateGrid(CurGen,UndoArray);
CopyGrid(NewGen,UndoArray);
break;
}
}
/*
* DoClear()
*
* Mark the circuit as modified and sate the current states in the UNDO buffer
* If no cells selected:
* clear the grid and the screen
* set the pen color to WIRE
* If cells selected,
* clear only those cells that are selected
* cancel the selection
*/
void DoClear()
{
Changed = TRUE;
CopyGrid(CurGen,UndoArray);
switch(SelectType)
{
case SEL_NONE:
ClearGrid(CurGen);
ClearScreen(TRUE);
SetPenColor(ID_WIREC);
break;
case SEL_WAIT:
RemoveGrid(NewGen,CurGen);
CancelSelect();
break;
}
}
/*
* DoClip()
*
* Mark the circuit as modified and save the current states in the UNDO buffer
* If cells are selected:
* clear the grid and put back only the selected cells
* refresh the screen and cancel the selection
* If no cells are selected:
* clear all cells outside the visible area of the screen
* (no refresh is necessary since it can't be seen)
*/
static void DoClip()
{
register short x,y;
register short i;
Changed = TRUE;
CopyGrid(CurGen,UndoArray);
switch(SelectType)
{
case SEL_WAIT:
ClearGrid(CurGen);
ReplaceGrid(NewGen,CurGen);
ClearScreen(FALSE);
CancelSelect();
break;
case SEL_NONE:
for (y=0,i=0; y<MAXGRIDH; y++)
for (x=0; x<MAXGRIDW; x++,i++)
if (x < GridX || x >= GridX+GridW ||
y < GridY || y >= GridY+GridH)
CurGen[i] = BLANK;
break;
}
}
/*
* DoCenter()
*
* Cancel any selection.
* Mark the circuit as modified and copy the grid into the UNDO buffer
* Find the active area of the grid and clear the New Generation array
* (as work area). Clear the screen (it will be refrehsed later).
*
* Calculate the offset to the new center position, and the offset in
* the grid array that corresponds to it. Copy the active area of the
* circuit into the New Generation array.
*
* Set the viewing position to the new center.
* Clear the grid and update it from the new generation.
* Update the slider positions.
*/
static void DoCenter()
{
short x,y,w,h;
register short X,Y;
short dx,dy;
register short i,di;
if (SelectType) CancelSelect();
Changed = TRUE;
CopyGrid(CurGen,UndoArray);
GetBounds(CurGen,&x,&y,&w,&h,BLANK);
ClearGrid(NewGen);
ClearScreen(FALSE);
dx = (MAXGRIDW - w) / 2 - x;
dy = (MAXGRIDH - h) / 2 - y;
di = dx + MAXGRIDW * dy;
for (Y=y; Y<y+h; Y++)
for (X=x,i=X+MAXGRIDW*Y; X<x+w; X++,i++)
NewGen[i+di] = CurGen[i];
GridX = (MAXGRIDW - GridW) / 2;
GridY = (MAXGRIDH - GridH) / 2;
ClearGrid(CurGen);
UpdateGrid(CurGen,NewGen);
UpdateSliders();
}
/*
* DoWipe()
*
* Mark the circuit as changed and save the states into the UNDO buffer
* If no cells are selected, wipe the electrons off the entire grid,
* otherwise wipe the electrons off the new generation grid, and replace
* the current states by the (wiped) new generation only where the cells
* are selected. Cancel the selection.
*/
static void DoWipe()
{
Changed = TRUE;
CopyGrid(CurGen,UndoArray);
switch(SelectType)
{
case SEL_NONE:
WipeGrid(CurGen,TRUE);
break;
case SEL_WAIT:
WipeGrid(NewGen,FALSE);
ReplaceGrid(NewGen,CurGen);
CancelSelect();
break;
}
}
/*
* DoQuit()
*
* Cancel any selection.
* If changes have been made to the circuit since the last SAVE,
* Invert the QUIT button and ask if changes should be saved
* If yes, then
* if we already know the file name, we'll do the save and be done,
* otherwise we will put up the requester and need to quit later.
* do the save operation
* Otherwise ask if they really want to quit
* put the QUIT button back to normal
* Otherwise
* it is safe to quit, so do so.
*/
int DoQuit(NotDone)
int NotDone;
{
if (SelectType) CancelSelect();
if (Changed)
{
InvertGadget(&cGadget[ID_QUIT]);
RestorePointerColor();
if (DoQuestion("Save Changes before Quiting?"))
{
if (FileName[0]) NotDone = FALSE; else QuitInProgress = TRUE;
DoSave();
} else {
if (DoQuestion("Really Quit?")) NotDone = FALSE;
}
SetPointerColor(PenInUse);
InvertGadget(&cGadget[ID_QUIT]);
} else {
NotDone = FALSE;
}
return(NotDone);
}
/*
* DoGadgetUp()
*
* Do the right things for each possible button or gadget:
*
* START: start the circuit
* STEP: cancel the selection and step the circuit
* STOP: stop a running circuit
* RESET: do the Reset function
* WIPE: do the Wipe function
* RENAME: Save the circuit under a different name
* LOAD: Load a circuit or library
* NEW: Clear the grid for a new circuit
* SELECT: Start selecting cells
* MOVE: If cells are selected, move them, otherwise start selecting
* COPY: If cells are selected, copy them, otherwise start selecting
* CLEAR: Do the Clear function
* CLIP: Do the Clip function
* PART: If cells are selected, make them into a part, otherwise
* get a part from the parts list
* UNDO Do the Undo function
* CENTER: Do the Center function
* SLIDEH: The horizontal slider is done being dragged
* SLIDEV: The vertical slider is done being dragged
* ZOOM: Zoom in on the grid
* SHRINK: Zoom out from the grid
* HELP: Do the Help function
* ABOUT: Show the About box
* QUIT: Attempt to Quit from CELLS
* ARROWS: Ignore arrow up events
*/
int DoGadgetUp(theGadget,theMessage,NotDone)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
switch(theGadget->GadgetID)
{
case ID_START:
NotDone = DoStart(NotDone);
break;
case ID_STEP:
if (SelectType) CancelSelect();
StepCells();
break;
case ID_STOP:
if (Running) SetStopped();
break;
case ID_RESET:
DoReset();
break;
case ID_WIPE:
DoWipe();
break;
case ID_SAVE:
DoSave();
break;
case ID_RENAME:
DoSaveAs();
break;
case ID_LOAD:
DoLoad();
break;
case ID_NEW:
DoNew();
break;
case ID_SELECT:
DoSelect();
break;
case ID_MOVE:
if (SelectType)
DoMoveCopy(MM_MOVE);
else
DoSelect();
break;
case ID_COPY:
if (SelectType)
DoMoveCopy(MM_COPY);
else
DoSelect();
break;
case ID_CLEAR:
DoClear();
break;
case ID_CLIP:
DoClip();
break;
case ID_PART:
if (SelectType)
AddPart();
else
GetPart();
break;
case ID_UNDO:
DoUndo();
break;
case ID_CENTER:
DoCenter();
break;
case ID_SLIDEH:
StopMouseMoves(); SliderActive = FALSE;
DoSlideH();
break;
case ID_SLIDEV:
StopMouseMoves(); SliderActive = FALSE;
DoSlideV();
break;
case ID_ZOOM:
DoZoom();
break;
case ID_SHRINK:
DoShrink();
break;
case ID_HELP:
DoHelp();
break;
case ID_ABOUT:
DoAbout();
break;
case ID_QUIT:
NotDone = DoQuit(NotDone);
break;
case ID_LARROW:
case ID_RARROW:
case ID_UARROW:
case ID_DARROW:
break;
}
return(NotDone);
}
/*
* DoGadgetDown()
*
* Do the right thing for each gadget down event:
*
* SLIDEH or SLIDEV: if the knob is hit, start reporting mouse moves and
* set the slider active flag, otherwise wait for a
* gadget up event.
* Color Gadgets: Set the point in use to the selected color.
* Arrows: Scroll the correct direction.
*/
void DoGadgetDown(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
switch(theGadget->GadgetID)
{
case ID_SLIDEH:
case ID_SLIDEV:
if (cSlider[theGadget->GadgetID-ID_SLIDEH+PROP_SLIDEH].Flags & KNOBHIT)
{
StartMouseMoves();
SliderActive = TRUE;
}
break;
case ID_BLANKC:
case ID_WIREC:
case ID_TAILC:
case ID_HEADC:
SetPenColor(theGadget->GadgetID);
break;
case ID_LARROW:
DoScrollLeft(theGadget);
break;
case ID_RARROW:
DoScrollRight(theGadget);
break;
case ID_UARROW:
DoScrollUp(theGadget);
break;
case ID_DARROW:
DoScrollDown(theGadget);
break;
}
}