/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of   */
/* | .  | || the authors.                                                    */
/* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
/* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
/* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 * VERY loosely based on the input.device example by Rob Peck, 12/1/85
 */

/* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/io.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>

/* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
#define TIMEINTERVAL 1L      /* in seconds */
#define DEFLIMIT     120     /* two minute timeout */
#define ESCAPEKEY 0x45
#define DEFCMD    "NEWCLI >NIL:"
#define BANNER "[0;33mPOPCLI[0m by John Toebes - Copyright © 1986 The Software Distillery\n"
#define BANNER1 " 235 Trillingham Ln, Cary NC 27511  (919)-469-4210   BBS:(919)-471-6436\n"

/* * * * * * * * * * * GLOBAL VARIABLES * * * * * * * * * */
struct task          *buddy;
struct Interrupt      handlerStuff;
ULONG                 createclisig;
ULONG                 unblanksig;
struct MemEntry       me[10];
ULONG                 noevents;
struct Screen        *blankscreen;
struct NewScreen      NewScreen = 
   { 0, 0, 320, 200, 1, 0, 1, NULL, CUSTOMSCREEN, NULL, NULL, NULL, NULL };

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase       *GfxBase = NULL;
long                  DOSBase = 0;
extern struct Custom custom;

/* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
extern APTR             AllocMem();
extern struct MsgPort  *CreatePort();
extern struct IOStdReq *CreateStdIO();
extern struct Screen   *OpenScreen();
extern void             HandlerInterface();
extern struct task     *FindTask();

/************************************************************************/
/* the handler subroutine - called through the handler stub             */
/************************************************************************/
struct InputEvent *myhandler(ev, mydata)
struct InputEvent *ev;      /* and a pointer to a list of events */
struct MemEntry *mydata[];  /* system will pass me a pointer to my 
                             * own data space. */
   {
   register struct InputEvent *ep, *laste;

   /* run down the list of events to see if they pressed the magic button */
   for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
      {
      if ((ep->ie_Class == IECLASS_RAWKEY) &&
          (ep->ie_Code  == ESCAPEKEY)         &&
          (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND))
         {
         /* we can handle this event so take it off the chain */
         if (laste == NULL)
            ev = ep->ie_NextEvent;
         else
            laste->ie_NextEvent = ep->ie_NextEvent;
         /* now tell him to create the new cli */
         Signal(buddy, createclisig);
         }
      else
         laste = ep;

      if (ep->ie_Class != IECLASS_TIMER)
         {
         noevents = 0;
         if (blankscreen != NULL)
            Signal(buddy, unblanksig);
         }
      }

   /* pass on the pointer to the event */
   return(ev);
   }

/************************************************************************/
/* Queue a timer to go off in a given number of seconds                 */
/************************************************************************/
void QueueTimer(tr,seconds)
struct timerequest *tr;
ULONG seconds;
   {
   tr->tr_node.io_Command = TR_ADDREQUEST;   /* add a new timer request */
   tr->tr_time.tv_secs =  seconds;        	/* seconds */
   tr->tr_time.tv_micro = 0;
   SendIO( tr );
   }

/************************************************************************/
/* the main program to do the popcli stuff                              */
/************************************************************************/
void _main(cmd)
char *cmd;
   {
   long  intlimit = 0;
   ULONG sig, timersig;
   struct timerequest *timerreq;
   struct MsgPort     *timerport;
   struct MsgPort     *inputDevPort;
   struct IOStdReq    *inputRequestBlock;

   buddy = FindTask(0);
   noevents = 0;

   /* skip over any leading spaces in the command line */
   while(*cmd == ' ')
      cmd++;

   /* see if they specified a limit */
   if (*cmd)
      {
      while ((*cmd >= '0') && (*cmd <= '9'))
         intlimit = (intlimit*10) + *cmd++ - '0';
      }

   if (intlimit <= 0)
      intlimit = DEFLIMIT;

   /* now skip over any more leading spaces */
   while(*cmd == ' ')
      cmd++;

   if (*cmd <= ' ')
      cmd = DEFCMD;

   /* ugh we are reusing a variable here - so what - it saves bytes */
   sig = Output();
   Write(sig, BANNER, sizeof(BANNER));
   Write(sig, BANNER1, sizeof(BANNER1));
/* if (sig != Input())
      Close(Input());
   Close(sig); */

   SetTaskPri( buddy, 20);

   if ((inputDevPort = CreatePort(0,0)) == NULL) /* for input device */
      goto abort0;

   if ((inputRequestBlock = CreateStdIO(inputDevPort)) == 0)
      goto abort1;

   if ((timerport = CreatePort(0,0)) == NULL)
      goto abort1;

   if ((timerreq = (struct timerequest *)
                    AllocMem(sizeof(struct timerequest),
                             MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
      goto abort2;

   timerreq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
   timerreq->tr_node.io_Message.mn_Node.ln_Pri = 0;
   timerreq->tr_node.io_Message.mn_ReplyPort = timerport;

   if (OpenDevice(TIMERNAME, UNIT_VBLANK, timerreq, 0))
      goto abort;

   timersig = (1 << timerport->mp_SigBit);

   if ((sig = AllocSignal(-1)) == -1)
      goto abort;

   createclisig = 1 << sig;

   if ((sig = AllocSignal(-1)) == -1)
      goto abort;

   unblanksig = 1 << sig;

   if ((GfxBase = (struct GfxBase *)
                  OpenLibrary("graphics.library", 0)) == NULL)
      goto abort;

   if ((IntuitionBase = (struct IntuitionBase *)
                        OpenLibrary("intuition.library", 0)) == NULL)
      goto abort;

   handlerStuff.is_Data = (APTR)&me[0];
   handlerStuff.is_Code = HandlerInterface;
   handlerStuff.is_Node.ln_Pri = 51;

   if (OpenDevice("input.device",0,inputRequestBlock,0))
      goto abort;

   inputRequestBlock->io_Command = IND_ADDHANDLER;
   inputRequestBlock->io_Data    = (APTR)&handlerStuff;

   DoIO(inputRequestBlock);

   QueueTimer(timerreq, TIMEINTERVAL);

   for(;;)         /* FOREVER */
      {
      sig = Wait( createclisig | unblanksig | timersig );

      if ((sig & unblanksig) && (blankscreen != NULL))
         {
         (void) CloseScreen(blankscreen);
	 ON_DISPLAY
         blankscreen = NULL;
         }

      if (sig & createclisig)
         {
         WBenchToFront();
         (void)Execute(cmd,0,0);
         }

      if (sig & timersig)
         {
         /* get rid of the message */
         (void)GetMsg(timerport);
         QueueTimer(timerreq, TIMEINTERVAL);

         if ((noevents++ >= intlimit) && (blankscreen == NULL))
            {
            if ( (blankscreen = OpenScreen(&NewScreen)) != NULL)
               {
               SetRGB4(&blankscreen->ViewPort, 0, 0, 0, 0);
               OFF_DISPLAY
               }
            }
         }
      }

abort:
   CloseDevice(timerreq);
abort3:
/* timerreq->tr_node.io_Message.mn_Node.ln_Type = 0xff;
 * timerreq->tr_node.io_Device = (struct Device *) -1;
 * timerreq->tr_node.io_Unit = (struct Unit *) -1;
 */

   FreeMem (timerreq, sizeof(struct timerequest));
abort2:
   DeletePort(timerport);
abort1:
   if (IntuitionBase != NULL)
      CloseLibrary(IntuitionBase);

   if (GfxBase != NULL)
      CloseLibrary(GfxBase);

   DeletePort(inputDevPort);
abort0:
   XCEXIT(-1);
   }
