/*
 *  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:  cDoRequest.c         Handles setting up and removal of requesters.
 */


#include "Cells.h"
#include "cRequest.h"


EXTREQUEST *ActiveRequest;      /* The currently active requester */


#define REQUEST     theRequest->er_Request
#define STRINFO     ((struct StringInfo *)theGadget->SpecialInfo)


/*
 *  DoReqGadgetDown()
 *
 *  If a requester is active, and there is a gadget down routine for the
 *  requeter, call the routine passing the gadget and message pointers
 */

void DoReqGadgetDown(theGadget,theMessage)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
{
   if (ActiveRequest && ActiveRequest->er_GadgetDown)
      (*(ActiveRequest->er_GadgetDown))(theGadget,theMessage);
}


/*
 *  DoReqGadgetUp()
 *
 *  If there is an active requester and it has a gadget up routine, call
 *  the routine passing along the gadget and message pointers.
 *  If a quit is in progress and the active requester has been removed
 *  by the gadget up event, set the NotDone flag.
 */

int DoReqGadgetUp(theGadget,theMessage,NotDone)
struct Gadget *theGadget;
struct IntuiMessage *theMessage;
int NotDone;
{
   if (ActiveRequest && ActiveRequest->er_GadgetUp)
      (*(ActiveRequest->er_GadgetUp))(theGadget,theMessage);
   if (QuitInProgress && ActiveRequest == NULL) NotDone = FALSE;
   return(NotDone);
}


/*
 *  DoReqMouseMove()
 *
 *  If there is an active requester and it has a mouse move routine, 
 *  call the routine passing the mouse position and the message pointer.
 */

void DoReqMouseMove(MouseX,MouseY,theMessage)
short MouseX,MouseY;
struct IntuiMessage *theMessage;
{
   if (ActiveRequest && ActiveRequest->er_MouseMove)
      (*(ActiveRequest->er_MouseMove))(MouseX,MouseY,theMessage);
}


/*
 *  RemoveRequest()
 *
 *  End the specified requester and clear the active request pointer.
 */

void RemoveRequest(theRequest)
struct Requester *theRequest;
{
   EndRequest(theRequest,myWindow);
   ActiveRequest = NULL;
}


/*
 *  AddRequest()
 *
 *  If there is already an active requester, remove it.
 *  Set the requester's gadget down, gadget up and mouse move routines
 *    to the ones specified.
 *  Center the requester in the board area of the screen, making sure it
 *    does not fall off the left or top the the screen.
 *  Open the requester, if possible.
 *  If the requester could not be openned,
 *    try to free memory from the Help system, and try again.
 *  If the requester is up, set the active requester pointer,
 *  otherwise give an error message
 */

void AddRequest(theRequest,FuncGD,FuncGU,FuncMM)
EXTREQUEST *theRequest;
FUNCTION FuncGD,FuncGU,FuncMM;
{
   int ReqSet;

   if (ActiveRequest) RemoveRequest(ActiveRequest);
   theRequest->er_GadgetDown = FuncGD;
   theRequest->er_GadgetUp   = FuncGU;
   theRequest->er_MouseMove  = FuncMM;
   REQUEST.LeftEdge = (BOARDW - REQUEST.Width)  / 2;
   REQUEST.TopEdge  = (BOARDH - REQUEST.Height) / 2;
   if (REQUEST.LeftEdge < 0) REQUEST.LeftEdge = 0;
   if (REQUEST.TopEdge  < 0) REQUEST.TopEdge  = 0;
   ReqSet = Request(theRequest,myWindow);
   if (!ReqSet)
   {
      if (CanClearHelpLines()) ReqSet = Request(theRequest,myWindow);
      if (!ReqSet && CanClearHelpTopics())
         ReqSet = Request(theRequest,myWindow);
   }
   if (ReqSet) ActiveRequest = theRequest;
     else DoError("Not enough Memory to open that Requester");
}


/*
 *  RefreshRequest()
 *
 *  Refresh the specified gadgets of the specified requester.
 */

void RefreshRequest(theRequest,First,Last)
EXTREQUEST *theRequest;
int First,Last;
{
   struct Gadget *theGadget = REQUEST.ReqGadget;
   
   if (Last == NULL) Last = First;
   RefreshGList(&(theGadget[First]),myWindow,theRequest,First-Last);
}


/*
 *  DoReqSet()
 *
 *  If the request has a gadget that should be activated when the
 *  requester becomes active, activate it.
 */

void DoReqSet(theRequest)
EXTREQUEST *theRequest;
{
   if (theRequest && theRequest->er_ActiveGadget)
      ActivateGadget(theRequest->er_ActiveGadget,myWindow,theRequest);
}


/*
 *  SetStringInfo()
 *
 *  If a string and gadget were specified
 *    copy the string into the gadget's buffer
 *    record the length of the new contents of the string
 *    set the display position to the begining of the string.
 */

void SetStringInfo(theGadget,theString)
struct Gadget *theGadget;
char *theString;
{
   if (theString && theGadget)
   {
      strncpy(STRINFO->Buffer,theString,STRINFO->MaxChars);
      STRINFO->Buffer[STRINFO->MaxChars-1] = '\0';
      STRINFO->BufferPos = STRINFO->NumChars = strlen(STRINFO->Buffer);
      STRINFO->DispPos = STRINFO->UndoPos = 0;
   }
}
