home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d502
/
cells.lha
/
CELLS
/
CELLSSource.lzh
/
cDoKey.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-20
|
9KB
|
358 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: cDoKey.c Handles keyboard events
*/
#include "cGadget.h"
#define ESC 0x45
#define DBUFKEY 0x35 /* 'B' key */
#define HELP 0x5F
#define DELETE 0x46
#define BACKSPACE 0x41
#define ENTER 0x43
int Shifted; /* TRUE if gadgets are shifted */
int DelayedShift; /* TRUE if gadgets should be shifted */
/* at the next opportunity */
/*
* DisableGadget()
*
* Remove the gadget, disable it, add it back in, then refresh the gadget.
* (the OffGadget call refreshes ALL the gadgets - too noisey)
*/
static void DisableGadget(theGadget)
struct Gadget *theGadget;
{
int pos;
pos = RemoveGadget(myWindow,theGadget);
theGadget->Flags |= GADGDISABLED;
AddGadget(myWindow,theGadget,pos);
RefreshGList(theGadget,myWindow,NULL,1);
}
/*
* EnableGadget()
*
* Remove the gadget, enable it, and add it back in. Clear the
* gadgets background, and then refresh the gadget.
*/
static void EnableGadget(theGadget)
struct Gadget *theGadget;
{
int x = theGadget->LeftEdge,
y = theGadget->TopEdge,
w = theGadget->Width,
h = theGadget->Height;
int pos;
pos = RemoveGadget(myWindow,theGadget);
theGadget->Flags &= ~GADGDISABLED;
AddGadget(myWindow,theGadget,pos);
SetAPen(wrp,FOREGROUND);
SetDrMd(wrp,JAM1);
RectFill(wrp,x,y,x+w-1,y+h-1);
RefreshGList(theGadget,myWindow,NULL,1);
}
/*
* SetRunning()
*
* If the START gadget is not shifted,
* turn the gadget into the STOP gadget and refresh it.
* disable the editing buttons.
* set the Running flag.
*/
void SetRunning()
{
struct Gadget *theGadget = &cGadget[ID_START];
short i;
if (theGadget->GadgetID == ID_START)
{
Forbid();
theGadget->GadgetID = ID_STOP;
theGadget->GadgetText = &cIText[TEXT_STOP];
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
for (i=ID_SAVE; i<ID_HELP; DisableGadget(&cGadget[i++]));
}
Running = TRUE;
}
/*
* SetStopped()
*
* If the START gadget is still the STOP gadget,
* turn the gadget back into the START gadget,
* enable the editing gadgets again
* Reset the Running flag.
*/
void SetStopped()
{
struct Gadget *theGadget = &cGadget[ID_START];
short i;
if (theGadget->GadgetID == ID_STOP)
{
Forbid();
theGadget->GadgetID = ID_START;
theGadget->GadgetText = &cIText[ID_START];
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
for (i=ID_SAVE; i<ID_HELP; EnableGadget(&cGadget[i++]));
}
Running = FALSE;
}
/*
* ShowShiftedGadgets()
*
* For each of the button gadgets:
* if the button is not selected and is allowed to shift, and the
* gadget is not already shifted, and if we are not running,
* or we are allowed to shift while running,
* set the gadget to the shifted name and refresh it.
* go on to the next gadget.
* if the Zoom gadget is still the Zoom gadget,
* convert it to the Shrink gadget.
*/
void ShowShiftedGadgets()
{
struct Gadget *theGadget = &cGadget[0];
while (theGadget && (theGadget->MyFlags & IS_BUTTON))
{
if ((theGadget->MyFlags & (BUTTON_NOSHIFT|BUTTON_SELECTED)) == 0 &&
theGadget->GadgetID < ID_OFFSET &&
(!Running || (theGadget->MyFlags & BUTTON_RUNSHIFT)))
{
Forbid();
theGadget->GadgetText = &cIText[theGadget->GadgetID+TEXT_OFFSET];
theGadget->GadgetID += ID_OFFSET;
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
}
theGadget = theGadget->NextGadget;
}
theGadget = &cGadget[ID_ZOOM];
if (theGadget->GadgetID == ID_ZOOM)
{
Forbid();
theGadget->GadgetRender = (APTR) &cImage[IM_SHRINK];
theGadget->GadgetID = ID_SHRINK;
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
}
}
/*
* ShowNormalGadgets()
*
* For each button gadget:
* if the button is not selected and is allowed to shift, and the
* gadget is shifted, and if we are not running,
* or we are allowed to shift while running,
* set the gadget to the unshifted name and refresh it.
* go on to the next gadget.
* if the Zoom gadget is the Shrink gadget,
* convert it to the Zoom gadget
*/
void ShowNormalGadgets()
{
struct Gadget *theGadget = &cGadget[0];
while (theGadget && (theGadget->MyFlags & IS_BUTTON))
{
if ((theGadget->MyFlags & (BUTTON_NOSHIFT|BUTTON_SELECTED)) == 0 &&
theGadget->GadgetID >= ID_OFFSET &&
(!Running || (theGadget->MyFlags & BUTTON_RUNSHIFT)))
{
Forbid();
theGadget->GadgetID -= ID_OFFSET;
theGadget->GadgetText = &cIText[theGadget->GadgetID];
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
}
theGadget = theGadget->NextGadget;
}
theGadget = &cGadget[ID_ZOOM];
if (theGadget->GadgetID == ID_SHRINK)
{
Forbid();
theGadget->GadgetRender = (APTR) &cImage[IM_ZOOM];
theGadget->GadgetID = ID_ZOOM;
if (theGadget->Flags & SELECTED) InvertGadget(theGadget);
theGadget->MyFlags &= ~BUTTON_SELECTED;
RefreshGList(theGadget,myWindow,NULL,1);
Permit();
}
}
/*
* ShiftGadgets()
*
* If no requester is active,
* if shift keys are pressed,
* if we're not already shifted, shift the gadgets
* Otherwise
* if we're already shifted, unshift the gadgets
* record the delayed shift
*/
void ShiftGadgets(keys)
ULONG keys;
{
if (ActiveRequest == NULL)
{
if (keys)
{
if (!Shifted) ShowShiftedGadgets();
Shifted = TRUE;
} else {
if (Shifted) ShowNormalGadgets();
Shifted = FALSE;
}
}
DelayedShift = (keys != 0);
}
/*
* UpdateShiftKeys()
*
* If delayed shift is different frlom the current shift, and there
* is no active gadget, update the gadgets as needed, and record the
* status.
*/
void UpdateShiftKeys()
{
if (DelayedShift != Shifted && ActiveRequest == NULL)
{
if (DelayedShift)
ShowShiftedGadgets();
else
ShowNormalGadgets();
Shifted = DelayedShift;
}
}
/*
* DoKey()
*
* Do the right thing for each of the special keys:
*
* ESC: Attempt to quit.
* DBUFKEY: Change the double-buffer mode.
* CURSORUP: Increase the generation delay time.
* CURSORDOWN: Decrease the generation delay time.
* HELP: Unshift all gadgets, and do the HELP function.
* DELETE or BACKSPACE: Do the Clear function.
* ENTER: Cancel any selection, and step the circuit.
*/
int DoKey(theCode,theMessage,NotDone)
USHORT theCode;
struct IntuiMessage *theMessage;
short NotDone;
{
switch(theCode)
{
case ESC:
NotDone = DoQuit(NotDone);
break;
case DBUFKEY:
SetDBufMode(!DBufMode);
break;
case CURSORUP:
if (GenerationDelay > 8)
GenerationDelay = GenerationDelay * 4 / 3;
else
GenerationDelay++;
break;
case CURSORDOWN:
if (GenerationDelay > 8)
GenerationDelay = GenerationDelay * 3 / 4;
else
if (GenerationDelay) GenerationDelay--;
break;
case HELP:
ShiftGadgets(FALSE);
DoHelp();
break;
case DELETE:
case BACKSPACE:
DoClear();
break;
case ENTER:
if (SelectType) CancelSelect();
StepCells();
break;
}
return(NotDone);
}
/*
* DoInactive()
*
* If the inactivated window is the CELLS window,
* fake a menu up (to finish drawing or dragging),
* fake a select up (to finish drawing or selecting),
* unshift the gadgets.
*/
void DoInactive(theWindow,theMessage)
struct Window *theWindow;
struct IntuiMessage *theMessage;
{
if (theWindow == myWindow)
{
DoMouseButton(MENUUP,theMessage->MouseX,theMessage->MouseY,theMessage);
DoMouseButton(SELECTUP,theMessage->MouseX,theMessage->MouseY,theMessage);
ShiftGadgets(FALSE);
}
}