/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
/* |. o.| || This program may not be distributed without the permission of   */
/* | .  | || the authors.                                                    */
/* | o  | ||                                                                 */
/* |  . |// Written by Doug Walker                                           */
/* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
/*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
/*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */

#include "netkeys.h"
#include <proto/intuition.h>

struct DChannel *chan;

struct MsgPort *lisport;

int InitDevice(void);
int TermDevice(void);

void _main(char *);

void _main(x)
char *x;
{
   short swidth;
   short exit;
   int state;
   struct Screen wbdat;
   struct MsgPort  *inputDevPort = NULL;
   struct IOStdReq *inputRequestBlock = NULL;
   struct InputEvent ie;
   struct IntuitionBase *IntuitionBase = NULL;
   struct GfxBase *GfxBase = NULL;
   UWORD *NoSprData = NULL;
   ULONG rc;

   if (
       InitDevice()                                               ||

       ((inputDevPort = CreatePort(0,0)) == NULL)                           ||

       ((inputRequestBlock = 
               CreateIOReq(inputDevPort, sizeof(struct IOStdReq))) == NULL) ||

       !(IntuitionBase = (struct IntuitionBase *)
                                       OpenLibrary("intuition.library", 0)) ||

       !(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0))   ||

       !(NoSprData = AllocMem(12, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR))        ||

      OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
   {
      goto abort;
   }

   NoSprData[0] = 0xFE00;
   NoSprData[1] = 0xFF00;
   

   /* If we have an appropriate version of intuition, ask for info */
   /* about the workbench screen                                   */
   if(IntuitionBase->LibNode.lib_Version < 33
      || !(GetScreenData((char *)&wbdat, sizeof(struct Screen), 
                              WBENCHSCREEN, NULL)))
   {
      /* Either we're running on an old version of the system, or the */
      /* GetScreenData call failed for some reason.  In either case,  */
      /* simply assume a 640x200 screen and be done with it.          */
      swidth  = 639;
   }
   else
   {
      /* Use the wb width, and STDSCREENHEIGHT. */
      swidth  = wbdat.Width-1;
   }

   inputRequestBlock->io_Command = IND_WRITEEVENT;
   inputRequestBlock->io_Flags   = 0;
   inputRequestBlock->io_Length  = IESZ;
   inputRequestBlock->io_Data    = (APTR)&ie;

   state = 0;
   mshow(GfxBase, NoSprData, 0);
   while(1)
   {
      rc = Wait(SIGBREAKF_CTRL_C | (1 << chan->port.mp_SigBit));

      if(rc & SIGBREAKF_CTRL_C)          /* Received ctrl-c */
         goto abort;

      if(DRead(chan, (char *)&ie, IESZ) != IESZ)
         goto abort;

      if(ie.ie_Class == IECLASS_NKCONTROL) /* Special 'control' record */
      {
         exit = ie.ie_Code;
         if(ie.ie_Code & IECODE_NKHOTQUIT)
         {
            mshow(GfxBase, NoSprData, 0);
            state = 0;
            continue;
         }

         if(!(ie.ie_Code & IECODE_NKHOTKEY))
         {
            IntuitionBase->MouseX = (ie.ie_X == 0 ? swidth-1 : 1);
            IntuitionBase->MouseY = ie.ie_Y;
         }

         state = 1;
         mshow(GfxBase, NoSprData, 1);
         continue;
      }
      else if(state == 0)
         continue;

      if(
         ie.ie_Class == IECLASS_RAWMOUSE &&
         (ie.ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE) &&
         ie.ie_Code == IECODE_NOBUTTON &&
         ( 
           (
              (exit & IECODE_NKRIGHT)          &&
              ie.ie_X < 0                     &&
              IntuitionBase->MouseX == 0
           )
           ||
           (
              (exit & IECODE_NKLEFT)           &&
              ie.ie_X > 0                     &&
              IntuitionBase->MouseX == swidth
           )
         )
        )
      {
         mshow(GfxBase, NoSprData, 0);
         ie.ie_X = IntuitionBase->MouseX;
         ie.ie_Y = IntuitionBase->MouseY;
         ie.ie_Class = IECLASS_NKCONTROL;
         DWrite(chan, (char *)&ie, IESZ);
         state = 0;
         continue;
      }

      ie.ie_NextEvent = NULL;
      DoIO((struct IORequest *)inputRequestBlock);
   }

abort:
   if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);

   if(GfxBase)
   {
      if(NoSprData)
      {
         mshow(GfxBase, NoSprData, 1);
         FreeMem(NoSprData, 12);
      }
      CloseLibrary((struct Library *)GfxBase);
   }

   TermDevice();

   if (inputRequestBlock != NULL)
   {
      if (inputRequestBlock->io_Device != NULL)
         CloseDevice((struct IORequest *)inputRequestBlock);
      DeleteIOReq(inputRequestBlock);
   }

   if (inputDevPort != NULL)  DeletePort(inputDevPort);
}

int InitDevice(void)
{
   struct MsgPort *myport;
   struct Message *msg;

   chan = NULL;
   lisport = NULL;

   myport = &(((struct Process *)FindTask(0L))->pr_MsgPort);
   lisport = DListen(PORT_NETKEYS);
   do
   {
      WaitPort(myport);
   }
   while(!(msg=GetMsg(myport)));

   ReplyMsg(msg);

   if(!lisport) return(1);

   Wait(1<<lisport->mp_SigBit);
   
   if(!(chan = (struct DChannel *)DAccept(lisport)))
      return(1);

   return(0);
}

int TermDevice(void)
{
   if(chan)
   {
      DClose(chan);
      chan = NULL;
   }

   if(lisport)
   {
      DUnListen(lisport);
      lisport = NULL;
   }

   return(0);
}

void MemCleanup(void);
void MemCleanup(){}
