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
/
cDoMouse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
10KB
|
396 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: cDoMouse.c Handles Mouse Move and Button events
*/
#include "cGadget.h"
int MouseMoveType = MM_NONE; /* type of mouse move expected */
int ColorInUse = BRDR_WIREC; /* what color is in use */
int PenInUse = WIRE; /* what state is to be written */
static int StartingColor; /* variables for right-mouse effect */
static int ColorCount;
static short ColorX,ColorY;
static int CurrentColor;
static int OldSecs,OldMics; /* double click times */
/*
* StartMouseMoves()
*
* Start reporting mouse moves. They will be handled according to the
* MouseMoveType variable.
*/
void StartMouseMoves()
{
ModifyIDCMP(myWindow,myWindow->IDCMPFlags | MOUSEMOVE);
}
/*
* StopMouseMoves()
*
* Stop reporting mouse move events.
*/
void StopMouseMoves()
{
ModifyIDCMP(myWindow,myWindow->IDCMPFlags & ~MOUSEMOVE);
}
/*
* InBoard()
*
* Returns TRUE if the mouse position is inside the active grid area, and
* calculates the grid position (relative to GridX and GridY) of the mouse.
*/
int InBoard(Mx,My,x,y)
short Mx,My;
short *x,*y;
{
int Inside = FALSE;
if (Mx >= BoardX && Mx <= BoardW &&
My >= BoardY && My <= BoardH)
{
Inside = TRUE;
if (x) *x = (Mx - BoardX) / CellSize;
if (y) *y = (My - BoardY) / CellSize;
}
return(Inside);
}
/*
* RestrictToBoard()
*
* Calculate the nearest grid cell to the mouse position, not going
* outside of the active screen area.
*/
void RestrictToBoard(Mx,My,x,y)
short Mx,My;
short *x,*y;
{
if (Mx < BoardX) Mx = BoardX; else if (Mx > BoardW) Mx = BoardW;
if (My < BoardY) My = BoardY; else if (My > BoardH) My = BoardH;
*x = (Mx - BoardX) / CellSize;
*y = (My - BoardY) / CellSize;
}
/*
* SetPenColor()
*
* If the pen color is not alread the active color,
* Reset the current color's border pen
* Calculate the new color and pen
* Highlight the new color's gadget
* Relink the color gadgets so that the selected one is drawn last
* Redraw the gadgets (i.e., change the highlighted color)
* Set the mouse pointer to the selected color
*/
void SetPenColor(theID)
int theID;
{
short i,j;
if (theID != ColorInUse)
{
cBorder[ColorInUse].FrontPen = BOXPEN;
ColorInUse = theID - ID_BLANKC + BRDR_BLANKC;
PenInUse = ((struct Image *)(cGadget[theID].GadgetRender))->PlaneOnOff;
cBorder[ColorInUse].FrontPen = HIGHPEN;
for (i=BRDR_BLANKC,j=i-1; i<=BRDR_HEADC; i++)
{
if (i != ColorInUse)
{
cBorder[j].NextBorder = &cBorder[i];
j = i;
}
}
cBorder[j].NextBorder = &cBorder[ColorInUse];
cBorder[ColorInUse].NextBorder = NULL;
DrawBorder(wrp,cBorder[BRDR_BLANKC-1].NextBorder,0,0);
SetPointerColor(PenInUse);
}
}
/*
* ColorMouseCell()
*
* If the mouse is within the active grid area,
* calculate the screen position of the cell
* if it is not the last cell colored,
* record it as the last one colored,
* if this is the second cell colored with an electron color,
* change the electron color temporarily
* set the pen color and drawing mode
* fill the grid cell with the color
* If double buffer mode is on, update BOTH buffers
* Set the color of the cell in the grid array
* record that changes have been made.
*/
void ColorMouseCell(MouseX,MouseY,Pen)
short MouseX,MouseY;
int Pen;
{
short X,Y,x,y;
if (InBoard(MouseX,MouseY,&x,&y))
{
X = x * CellSize + BoardX + 1;
Y = y * CellSize + BoardY + 1;
if (X != ColorX || Y != ColorY || Pen != CurrentColor)
{
ColorX = X; ColorY = Y; CurrentColor = Pen;
if (ColorCount < 2)
{
ColorCount++;
if (ColorCount == 2 && (Pen == TAIL || Pen == HEAD))
Pen = (HEAD + TAIL) - Pen;
}
SetAPen(wrp,Pen);
SetDrMd(wrp,JAM1);
RectFill(wrp,X,Y,X+CellSize-2,Y+CellSize-2);
if (DBufMode)
{
SetAPen(rp,Pen); SetDrMd(rp,JAM1);
RectFill( rp,X,Y,X+CellSize-2,Y+CellSize-2);
}
SetCell(CurGen,x+GridX,y+GridY,Pen);
Changed = TRUE;
}
}
}
/*
* ColorScreenCell()
*
* If the specified cell is within the acrive area, calculate the screen
* position of the cell and color it in.
*/
void ColorScreenCell(X,Y,Pen)
short X,Y;
int Pen;
{
int x,y;
if (X >= 0 && X < GridW && Y >= 0 && Y < GridH)
{
x = BoardX + X * CellSize + 1,
y = BoardY + Y * CellSize + 1;
SetAPen(rp,Pen);
SetDrMd(rp,JAM1);
RectFill(rp,x,y,x+CellSize-2,y+CellSize-2);
}
}
/*
* Array to determine what color to change use when the right mouse button
* is clicked
*/
static UWORD PenChange[4][4] =
{
{ID_WIREC, ID_BLANKC, ID_HEADC, ID_TAILC}, /* Click w/o SelectDown */
{ID_HEADC, ID_TAILC, ID_WIREC, ID_BLANKC}, /* Double-Click w/o Select */
{ID_WIREC, ID_BLANKC, ID_WIREC, ID_WIREC}, /* Click with SelectDown */
{ID_TAILC, ID_HEADC, ID_BLANKC, ID_BLANKC} /* Double-Click with Select */
};
/*
* ChangePenColor()
*
* Offset the index value if the left button is held down.
* If the click is a double click, update the array index, and
* clear the double click counter, otherwise record the double click values.
* Set the pen to the proper value, according to the array.
*/
static void ChangePenColor(Seconds,Micros,theMessage)
int Seconds,Micros;
struct IntuiMessage *theMessage;
{
int i = 0;
if (theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON) i += 2;
if (DoubleClick(OldSecs,OldMics,Seconds,Micros))
{
i++;
OldSecs = OldMics = 0;
} else {
OldSecs = Seconds;
OldMics = Micros;
}
SetPenColor(PenChange[i][ColorInUse-BRDR_BLANKC]);
}
/*
* DoMouseMove()
*
* If a slider is active
* do the action for the proper slider,
* Otherwise,
* In DRAW mode:
* If the left button is down, fill the proper cell.
*
* In SELECT mode:
* Do the selection routine.
*
* In MOVE or COPY mode:
* Do the move or copy routine.
*/
void DoMouseMove(MouseX,MouseY,theMessage)
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
if (SliderActive)
{
if (cGadget[ID_SLIDEH].Flags & SELECTED) DoSlideH();
else if (cGadget[ID_SLIDEV].Flags & SELECTED) DoSlideV();
} else {
switch (MouseMoveType)
{
case MM_DRAW:
if (theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON)
ColorMouseCell(MouseX,MouseY,PenInUse);
break;
case MM_SELECT:
DoSelectMove(MouseX,MouseY,theMessage);
break;
case MM_MOVE:
case MM_COPY:
DoCopyMove(MouseX,MouseY);
break;
}
}
}
/*
* DoDrawButton()
*
* For a SELECTDOWN:
* if the circuit is not running and if the mouse button is within the grid,
* record the current grid for UNDO
* record the starting color and clear the cells-colored count.
* get mouse move reports in DRAW mode.
* color the selected cell
*
* For a SELECTUP:
* if the circuit is not running,
* clear the last-colored variables, and stop the mouse move reports
*
* For a MENUDOWN:
* Choose the proper new color
* clear the cells-colored count.
* If we're currently drawing (i.e., the left mouse button is down)
* change the color of the current cell.
*
* For a MENUUP:
* If we're in draw mode,
* reset the pen color to it original value.
*/
void DoDrawButton(Code,MouseX,MouseY,theMessage)
USHORT Code;
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
switch(Code)
{
case SELECTDOWN:
if (!Running)
{
if (InBoard(MouseX,MouseY,NULL,NULL))
{
StartingColor = ColorInUse; ColorCount = 0;
StartMouseMoves(); MouseMoveType = MM_DRAW;
CopyGrid(CurGen,UndoArray);
ColorMouseCell(MouseX,MouseY,PenInUse);
}
}
break;
case SELECTUP:
if (!Running)
{
ColorX = GridW; ColorY = GridH; CurrentColor = 0;
StopMouseMoves(); MouseMoveType = MM_NONE;
}
break;
case MENUDOWN:
ChangePenColor(theMessage->Seconds,theMessage->Micros,theMessage);
ColorCount = 0;
if (MouseMoveType == MM_DRAW)
ColorMouseCell(MouseX,MouseY,PenInUse);
break;
case MENUUP:
if (MouseMoveType == MM_DRAW)
{
SetPenColor(StartingColor - BRDR_BLANKC + ID_BLANKC);
CurrentColor = PenInUse; ColorCount = 0;
}
break;
}
}
/*
* DoMouseButton()
*
* Call the proper mouse button routine depending on the type of mouse
* move we are expecting.
*/
void DoMouseButton(Code,MouseX,MouseY,theMessage)
USHORT Code;
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
switch (MouseMoveType)
{
case MM_NONE:
case MM_DRAW:
DoDrawButton(Code,MouseX,MouseY,theMessage);
break;
case MM_SELECT:
DoSelectButton(Code,MouseX,MouseY,theMessage);
break;
case MM_MOVE:
case MM_COPY:
DoCopyButton(Code,MouseX,MouseY,theMessage);
break;
}
}