home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d502
/
cells.lha
/
CELLS
/
CELLSSource.lzh
/
cSelect.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
10KB
|
436 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: cSelect.c Handles the SELECT command.
*/
#include "cGadget.h"
int SelectType;
static short BoxX,BoxY,BoxW,BoxH; /* position ans size of select box */
static short SelectX,SelectY,SelectPen; /* last selection and pen */
extern short OffMC; /* offset within state array */
/*
* InvertGadget()
*
* Inverts the specified gadget on the control panel be inverting its
* bounding rectangle.
*/
void InvertGadget(theGadget)
struct Gadget *theGadget;
{
short x = theGadget->LeftEdge,
y = theGadget->TopEdge,
w = theGadget->Width,
h = theGadget->Height;
SetAPen(wrp,0xFF);
SetDrMd(wrp,COMPLEMENT);
RectFill(wrp,x,y,x+w-1,y+h-1);
theGadget->MyFlags ^= BUTTON_SELECTED;
}
/*
* BoxCell()
*
* Draw a border around the specified cell in the specified Rast Port.
*/
void BoxCell(rp,x,y,Pen)
struct RastPort *rp;
short x,y;
int Pen;
{
short X = x * CellSize + BoardX + 1;
short Y = y * CellSize + BoardY + 1;
SetAPen(rp,Pen);
SetDrMd(rp,JAM1);
Move(rp,X,Y);
Draw(rp,X,Y+CellSize-2);
Draw(rp,X+CellSize-2,Y+CellSize-2);
Draw(rp,X+CellSize-2,Y);
Draw(rp,X+1,Y);
}
/*
* InvertBox()
*
* Invert the seletion box's boundary.
*/
void InvertBox()
{
short X = BoxX * CellSize + BoardX;
short Y = BoxY * CellSize + BoardY;
short W = BoxW * CellSize;
short H = BoxH * CellSize;
wrp->Mask = SELECTPEN|GRID;
SetAPen(wrp,SELECTPEN|GRID);
SetDrMd(wrp,COMPLEMENT);
Move(wrp,X,Y);
Draw(wrp,X,Y+H);
Draw(wrp,X+W,Y+H);
Draw(wrp,X+W,Y);
Draw(wrp,X+1,Y);
wrp->Mask = 0xFF;
}
/*
* SelectMouseCell()
*
* If the mouse event is inside the grid area
* If the selected cell is not the last selected cell,
* Record that this cell is selected
* Record wether we are selecting or deselecting, if necessary
* Get the current cell's color
* If we are adding to the selection
* Box in the newly selected cell (in both buffers)
* Set the cell in the selected cell array
* Otherwise (unselecting)
* Put the cell back to normal (in both buffers)
* Clear the cell from the selected array
*/
void SelectMouseCell(MouseX,MouseY,SetPen)
short MouseX,MouseY;
int SetPen;
{
short x,y;
int Pen;
if (InBoard(MouseX,MouseY,&x,&y))
{
if (x != SelectX || y != SelectY)
{
SelectX = x; SelectY = y;
x += GridX; y+= GridY;
if (SetPen) SelectPen = (CellColor(NewGen,x,y) == 0);
Pen = CellColor(CurGen,x,y);
if (SelectPen)
{
BoxCell(wrp,SelectX,SelectY,MOVEPEN);
if (DBufMode) BoxCell(rp,SelectX,SelectY,MOVEPEN);
SetCell(NewGen,x,y,Pen);
} else {
BoxCell(wrp,SelectX,SelectY,Pen);
if (DBufMode) BoxCell(rp,SelectX,SelectY,Pen);
SetCell(NewGen,x,y,0);
}
}
}
}
/*
* CancelSelect()
*
* If we are moving or copying, cancel the move or copy.
* Otherwise (we are in Select mode),
* Stop getting mouse moves, and don't buffer moves
* Put the SELECT button back to normal
* Put the pointer back to the drawing color
* Refresh any selected cells to their normal colors
*/
void CancelSelect()
{
switch(MouseMoveType)
{
case MM_MOVE:
case MM_COPY:
CancelMoveCopy(MouseMoveType);
break;
default:
StopMouseMoves(); MouseMoveType = MM_NONE; BufferMouse = FALSE;
InvertGadget(&cGadget[ID_SELECT]); SelectType = SEL_NONE;
SetPointerColor(PenInUse);
RefreshSelect(CurGen);
break;
}
}
/*
* StartSelectBox()
*
* If the mouse event is within the grid area
* Buffer mouse moves, and start getting mouse events
* Set the select type to BOX type
* record the initial position and size of the box,
* Begin inverting the box
*/
static void StartSelectBox(MouseX,MouseY)
short MouseX,MouseY;
{
short x,y;
if (InBoard(MouseX,MouseY,&x,&y))
{
BufferMouse = TRUE; StartMouseMoves();
SelectType = SEL_BOX;
BoxX = x; BoxY = y; BoxW = 1; BoxH = 1;
SelectX = x; SelectY = y;
InvertBox();
}
}
/*
* FinishSelectBox()
*
* Stop getting mouse moves, and remove the box outline
* For each cell in the box
* If the cell is not a blank cell, or we are going with ALL cells
* If we are clearing from the selection
* Clear the cell frlom the selection and put back its normal colors
* Otherwise
* Set the select array to the selected color
* Mark the cell as in the selection
* Update the screen once all the changes have been made
*/
static void FinishSelectBox(MouseX,MouseY,theMessage)
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
register short X,Y;
register short i;
int DoAll = (theMessage->Qualifier & SHIFTKEYS);
int ClearCells = (theMessage->Qualifier & ALTKEYS);
StopMouseMoves(); BufferMouse = FALSE;
InvertBox();
SelectType = SEL_WAIT;
for (Y=BoxY; Y<BoxY+BoxH; Y++)
{
for (X=BoxX, i=GridX+X+MAXGRIDW*(GridY+Y); X<BoxX+BoxW; X++,i++)
{
if (CurGen[i] != BLANK || DoAll)
{
if (ClearCells)
{
NewGen[i] = 0;
BoxCell(rp,X,Y,CurGen[i]);
} else {
NewGen[i] = CurGen[i];
BoxCell(rp,X,Y,MOVEPEN);
}
}
}
}
UpdateScreen();
}
/*
* SizeSelectBox()
*
* Find the closest cell to the mouse position
* If the new position is not the same as the old one
* Remove the old box outline
* Update the box size
* Draw the new box outline
*/
static void SizeSelectBox(MouseX,MouseY)
short MouseX,MouseY;
{
short x,y;
RestrictToBoard(MouseX,MouseY,&x,&y);
if (x != BoxX + BoxW - 1 || y != BoxY + BoxH - 1)
{
InvertBox();
if (x < BoxX) BoxX = x;
if (y < BoxY) BoxY = y;
BoxW = x - BoxX + 1;
BoxH = y - BoxY + 1;
InvertBox();
}
}
/*
* MoveSelectBox()
*
* Find the closes cell to the mouse position
* If it is not the same as the old position
* Calculate the new box position
* If the position has changed
* Remove the old box outline, move the box, and draw the new outline
*/
static void MoveSelectBox(MouseX,MouseY)
short MouseX,MouseY;
{
short x,y;
RestrictToBoard(MouseX,MouseY,&x,&y);
if (x != BoxX + BoxW - 1 || y != BoxY + BoxH - 1)
{
x = x - BoxW + 1;
y = y - BoxH + 1;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x != BoxX || y != BoxY)
{
InvertBox();
BoxX = x; BoxY = y;
InvertBox();
}
}
}
/*
* DoSelectMove()
*
* If we are dragging a box, size the box
* If we are selecting cells, select them
* If we are repositioning the box, do so
*/
void DoSelectMove(MouseX,MouseY,theMessage)
{
switch(SelectType)
{
case SEL_BOX:
SizeSelectBox(MouseX,MouseY);
break;
case SEL_CELLS:
SelectMouseCell(MouseX,MouseY,FALSE);
break;
case SEL_REPOSITION:
MoveSelectBox(MouseX,MouseY);
break;
}
}
/*
* DoSelectButton()
*
* For a SELECTDOWN:
* if we aren't doing something already, start a selection box
*
* For a SELECTUP:
* If we have a select box in action, finish it
*
* For a MENUDOWN:
* If we are not doing anything else:
* Start getting mouse moves,
* Select the cell at the current position, and record that position
* If we are dragging a select box, start repositioning it
*
* For a MENUUP:
* If we are selecting cells,
* stop getting mouse moves and go back to waiting
* If we are repositioning the selection box:
* go back to resizing the box
*/
void DoSelectButton(Code,MouseX,MouseY,theMessage)
USHORT Code;
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
switch(Code)
{
case SELECTDOWN:
if (SelectType == SEL_WAIT) StartSelectBox(MouseX,MouseY);
break;
case SELECTUP:
if (SelectType == SEL_BOX || SelectType == SEL_REPOSITION)
FinishSelectBox(MouseX,MouseY,theMessage);
break;
case MENUDOWN:
switch(SelectType)
{
case SEL_WAIT:
StartMouseMoves();
SelectMouseCell(MouseX,MouseY,TRUE);
SelectType = SEL_CELLS;
SelectX = GridW; SelectY = GridH;
break;
case SEL_BOX:
SelectType = SEL_REPOSITION;
MoveSelectBox(MouseX,MouseY);
break;
}
break;
case MENUUP:
switch(SelectType)
{
case SEL_CELLS:
StopMouseMoves();
SelectType = SEL_WAIT;
break;
case SEL_REPOSITION:
SelectType = SEL_BOX;
SizeSelectBox(MouseX,MouseY);
break;
}
break;
}
}
/*
* DoSelect()
*
* If a selection is already in progress, cancel the selection.
* If a move or copy is in progress cancel it, then start a new selection
* Otherwise
* Put the pointer color back to normal and invert the SELECT button
* Set the flags to Select mode
* Clear the select grid to zero, and clear the offset counter
*/
void DoSelect()
{
switch(MouseMoveType)
{
case MM_SELECT:
CancelSelect();
break;
case MM_MOVE:
case MM_COPY:
CancelSelect();
default:
RestorePointerColor();
InvertGadget(&cGadget[ID_SELECT]);
SelectType = SEL_WAIT; MouseMoveType = MM_SELECT;
ZeroGrid(NewGen); OffMC = 0;
break;
}
}