/*
 * Hold.c - Holds the right mouse button while making menu selections
 *
 * Bruno Costa - 14 Sep 89 - 19 Jan 91
 *
 * ( Based on PopCLI III by John Toebes )
 *
 *  Compile under Lattice C 5.02 with options -cus -v
 */

#include <exec/types.h>
#include <exec/interrupts.h>
#include <devices/inputevent.h>
#include <devices/input.h>
#include <devices/timer.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <string.h>
#include "hold.h"

#if !DETACH
BPTR _Backstdout; 		/* standard output */
#else
extern BPTR _Backstdout; 	/* standard output when run in background */
#endif
long _BackGroundIO = 1;		/* Flag to tell it if we want to do I/O   */
long _stack = 4000;		/* Amount of stack space our task needs   */
char *_procname = TASKNAME;	/* The name of the task to create         */
long _priority = 5;		/* The priority to run us at              */

extern struct DosLibrary *DosBase;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *LayersBase = NULL;

/* input handler */
extern void handler (void);


void putmsg (char *msg)
{
 if (_Backstdout)
   Write (_Backstdout, msg, strlen (msg));
}


#define loop for(;;)


void main (int argc, char *argv[])
{
 int stay = FALSE;
 ULONG sigmask;
 struct MsgPort *inputDevPort = NULL;
 struct MsgPort *myport = NULL, *port = NULL;
 struct IOStdReq *inputRequestBlock = NULL;
 struct Interrupt handlerStuff;
 struct handlerdata hd;

#if DEBUG
 _Backstdout = Output();
#endif

 /* test if hold is already installed */
 if ((port = FindPort(PORTNAME)) == NULL)
 {
   if ((port = myport = CreatePort(PORTNAME, NULL)) == NULL)
     goto abort;
   stay = TRUE;
 }

 hd.activate = ON;
 hd.hold = ON;

 while (argc-- > 1)
 {
   if (argv[argc][0] == '-')
   {
     switch (argv[argc][1])
     {
       case 'q':
         if (!stay)
         {
           putmsg (KILLMSG);
           Signal (port->mp_SigTask, 1L << port->mp_SigBit);
         }
         else
           putmsg (NOKILLMSG);

         stay = FALSE;
         break;

       case 'a':
         hd.activate = OFF;
         break;

       case 'h':
         hd.hold = OFF;
         break;
     }
   }
   else
   {
     putmsg (USAGE);
     stay = FALSE;
   }
 }

 if (stay)
   putmsg (BANNER);

 /* Let the original window go away */
 if (_Backstdout)
 {
   Close(_Backstdout);
   _Backstdout = NULL;
 }

 if (!stay)
   goto abort;

 IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library",0);
 LayersBase = (struct Library *) OpenLibrary ("layers.library",0);

 if ((inputDevPort = CreatePort (NULL, 0)) == NULL)
   goto abort;

 if ((inputRequestBlock = CreateExtIO (inputDevPort,
                                       sizeof (struct IOStdReq))) == NULL)
   goto abort;

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

 hd.ignore = 0;
 hd.actbit = AllocSignal (-1);
 hd.actmask = (1L << hd.actbit);
 hd.task = FindTask (NULL);
 hd.count = 0;
 hd.activated = FALSE;
 hd.maxtime = MAXTIME;

 handlerStuff.is_Data = (APTR) &hd;
 handlerStuff.is_Code = handler;
 handlerStuff.is_Node.ln_Pri = 55;	/* ahead of PopCLI and Intuition */

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

 DoIO ((struct IORequest *)inputRequestBlock);

 loop
 {
   sigmask = Wait (SIGBREAKF_CTRL_C | (1L << myport->mp_SigBit) | hd.actmask);

   if (sigmask & hd.actmask)
   {
     ULONG lock;
     struct Window *wd;

#if !DEBUG
     lock = LockIBase (0);
#endif
     wd = WhichWindow ();
     if (wd == IntuitionBase->ActiveWindow)
       wd = NULL;
#if !DEBUG
     UnlockIBase (lock);
#endif

#if 0
     if (wd && !(IntuitionBase->ActiveWindow->Flags & WBENCHWINDOW))
#else
     if (wd)
#endif
       ActivateWindow (wd);
   }

   if (sigmask & ((1L << myport->mp_SigBit) | SIGBREAKF_CTRL_C))
     break;
 }

abort:
 if (stay)
   FreeSignal (hd.actbit);

 if (inputRequestBlock)
 {
   if (inputRequestBlock->io_Device)
   {
     inputRequestBlock->io_Command = IND_REMHANDLER;
     inputRequestBlock->io_Data = (APTR) &handlerStuff;
     DoIO ((struct IORequest *) inputRequestBlock);
     CloseDevice ((struct IORequest *)inputRequestBlock);
   }
   DeleteExtIO (inputRequestBlock);
 }
 if (inputDevPort)
   DeletePort (inputDevPort);

 if (myport)
   DeletePort (myport);

#if !DEBUG
 if (_Backstdout)
   Close (_Backstdout);
#endif

 if (IntuitionBase)
   CloseLibrary ((struct Library *) IntuitionBase);
 if (LayersBase)
   CloseLibrary ((struct Library *)LayersBase);
}
