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
/
cMove.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
8KB
|
330 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: cMove.c Handles MOVE and COPY commands.
*/
#include "cGadget.h"
short OffMC; /* Offset in state arrays of new position */
static short OffX,OffY; /* grid offsets of new cell positions */
static short BaseX,BaseY; /* original (base) position of offsets */
static short BoundX,BoundY,BoundW,BoundH;
extern ULONG Shifted;
/*
* CancelMoveCopy()
*
* Cancel mouse moves, and stop buffering the mouse
* Put the MOVE or COPY button back to normal, and cancel any selection
* Put the gadgets to their proper shifted positions
* Restore the pointer to the drawing color
* Refresh the selected cells back to their original values
* If we were moving cells,
* replace them in their original positions
* and redraw them on the screen
*/
void CancelMoveCopy(ID)
int ID;
{
StopMouseMoves(); MouseMoveType = MM_NONE; BufferMouse = FALSE;
InvertGadget(&cGadget[ID_MOVE]); SelectType = SEL_NONE;
if (Shifted) ShowShiftedGadgets(); else ShowNormalGadgets();
SetPointerColor(PenInUse);
RefreshSelect(CurGen);
if (ID == MM_MOVE)
{
ReplaceGrid(NewGen,CurGen); OffMC = 0;
RefreshSelect(CurGen);
}
}
/*
* DoMoveCopy()
*
* If the mode is currently SELECT mode:
* put the SELECT button back to normal and invert the MOVE or COPY button
* set up the UNDO array
* set the mouse move type to the specified type (MOVE or COPY)
* clear the offset values
* If we are movinf cells, clear the selected cells
* refresh the selected cells (using the new mode)
* get the bounds for the selected cells
*
* Otherwise:
* cancel the current MOVE or COPY
*/
void DoMoveCopy(ID)
int ID;
{
switch (MouseMoveType)
{
case MM_SELECT:
InvertGadget(&cGadget[ID_SELECT]);
InvertGadget(&cGadget[ID_MOVE]);
CopyGrid(CurGen,UndoArray);
MouseMoveType = ID;
OffX = OffY = OffMC = 0; BaseX = BaseY = 0;
if (ID == MM_MOVE) RemoveGrid(NewGen,CurGen);
RefreshSelect(CurGen);
GetBounds(NewGen,&BoundX,&BoundY,&BoundW,&BoundH,0);
break;
default:
CancelSelect();
break;
}
}
/*
* StartMoveCopy()
*
* If the mouse is within the grid area
* If the cell where the mouse was pressed is a selected cell
* start buffering moves, and start getting mouse moves
* set the select type
* record the base postition for the move
* refresh the cells in the new mode
*/
static void StartMoveCopy(MouseX,MouseY)
short MouseX,MouseY;
{
short x,y;
if (InBoard(MouseX,MouseY,&x,&y))
{
if (CellColor(NewGen,x+GridX-OffX,y+GridY-OffY))
{
BufferMouse = TRUE;
StartMouseMoves();
SelectType = (MouseMoveType == MM_MOVE)? SEL_MOVE: SEL_COPY;
BaseX = x - OffX; BaseY = y - OffY;
RefreshSelect(CurGen);
}
}
}
/*
* FinishMoveCopy()
*
* Stop getting mouse moves and stop buffering
* go back to waiting for somthing to happen
* refresh the selected cells in the new mode
*/
static void FinishMoveCopy(MouseX,MouseY)
short MouseX,MouseY;
{
StopMouseMoves(); BufferMouse = FALSE;
SelectType = SEL_WAIT;
RefreshSelect(CurGen);
}
/*
* CellSelected()
*
* offset the cell index to the selected cell's current location
* If the index is within the array, then return the cell state
* otherwise return 0
*/
int CellSelected(i)
short i;
{
register int Selected;
i += OffMC;
if (i >= 0 && i < ARRAYSIZE) Selected = NewGen[i]; else Selected = FALSE;
return(Selected);
}
/*
* CopySelect()
*
* Record that changes have been made
* For each cell in the selection array,
* if the index is valid and the cell is selected (i.e., being moved or
* copied), then copy the value of the cell into the current grid
*/
static void CopySelect()
{
register short i,j;
Changed = TRUE;
for (i=0,j=OffMC; i<ARRAYSIZE && j<ARRAYSIZE; i++,j++)
if (j >= 0 && NewGen[j]) CurGen[i] = NewGen[j];
}
/*
* CalcBounds()
*
* Compute the destination cell positions of the bounding box of the
* selected cells, within the screen grid area. Clip the boundary to
* the active grid.
*/
static void CalcBounds(NewOffX,NewOffY,x,y,w,h)
short NewOffX,NewOffY;
short *x,*y,*w,*h;
{
if (NewOffX < OffX)
{
*x = BoundX + NewOffX;
*w = BoundX + BoundW + OffX;
} else {
*x = BoundX + OffX;
*w = BoundX + BoundW + NewOffX;
}
if (NewOffY < OffY)
{
*y = BoundY + NewOffY;
*h = BoundY + BoundH + OffY;
} else {
*y = BoundY + OffY;
*h = BoundY + BoundH + NewOffY;
}
if (*x < GridX) *x = GridX;
if (*y < GridY) *y = GridY;
if (*w > GridX + GridW) *w = GridX + GridW;
if (*h > GridY + GridH) *h = GridY + GridH;
}
/*
* MoveSelect()
*
* Calculate the new bounding box positions and size
* Calculate the new index offset into the state array
* For each cell in the bounded part of the grid
* Get the state of the cell that used to be at the current position
* and the state of the cell now at the current position
* If the cell was selected before but is not any longer,
* replace the original cell color
* otherwise if the cell was not selected before but is now,
* color it the selection color
* Update the screen (for double buffered node)
*/
static void MoveSelect(NewOffX,NewOffY)
short NewOffX,NewOffY;
{
short x,y,w,h;
short NewOffMC;
register short X,Y;
register short i;
register int Pen1,Pen2;
int SelectPen = (SelectType == SEL_WAIT)? SELECTPEN: MOVEPEN;
CalcBounds(NewOffX,NewOffY,&x,&y,&w,&h);
NewOffMC = -(NewOffX + MAXGRIDW * NewOffY);
for (Y=y; Y<h; Y++)
{
for (X=x,i=X+MAXGRIDW*Y; X<w; X++,i++)
{
if (i+OffMC >= 0 && i+OffMC < ARRAYSIZE)
Pen1 = NewGen[i+OffMC]; else Pen1 = 0;
if (i+NewOffMC >= 0 && i+NewOffMC < ARRAYSIZE)
Pen2 = NewGen[i+NewOffMC]; else Pen2 = 0;
if (Pen1 && Pen2 == 0)
ColorScreenCell(X-GridX,Y-GridY,CurGen[i]);
else if (Pen1 == 0 && Pen2)
ColorScreenCell(X-GridX,Y-GridY,SelectPen);
}
}
UpdateScreen();
}
/*
* DoCopyMove()
*
* Find the closest board position to the current mouse position
* Get the offsets from the base position
* If the offsets have changed,
* move the selection to the new location
* change the offset values
*/
void DoCopyMove(MouseX,MouseY)
short MouseX,MouseY;
{
short dx,dy;
RestrictToBoard(MouseX,MouseY,&dx,&dy);
dx -= BaseX; dy -= BaseY;
if (dx != OffX || dy != OffY)
{
MoveSelect(dx,dy);
OffX = dx; OffY = dy;
OffMC = -(dx + MAXGRIDW * dy);
}
}
/*
* DoCopyButton()
*
* Do the right thing for each type of button event:
*
* SELECTDOWN:
* If we are not already moving or copying, start moving
*
* SELECTUP:
* Stop moving for now
*
* MENUDOWN:
* Place a copy of the selection at the current location
*
* MENUUP:
* If the left button is not down then we are done moving, so
* cancel the move or copy (without replacing the cells)
*/
void DoCopyButton(Code,MouseX,MouseY,theMessage)
USHORT Code;
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
switch(Code)
{
case SELECTDOWN:
if (SelectType == SEL_WAIT) StartMoveCopy(MouseX,MouseY);
break;
case SELECTUP:
FinishMoveCopy(MouseX,MouseY);
break;
case MENUDOWN:
CopySelect();
break;
case MENUUP:
if ((theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON) == 0)
CancelMoveCopy(MM_COPY);
break;
}
}