/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */



#include "system_headers.h"

static APTR InputPool = NULL;

__asm __saveds LONG inputlist_dspfunc(register __a2 char **array, register __a1 struct InputEntry *inputentry, register __a0 struct Hook *hook)
{
   if (inputentry) {
      *array++ = inputentry->input_address;
      *array++ = inputentry->input_name;
      *array++ = inputentry->input_type;
      *array++ = inputentry->input_pri;
      *array++ = inputentry->input_data;
      *array++ = inputentry->input_code;
      *array   = NULL;
   } else {
      *array++ = ESC "bAddress";
      *array++ = ESC "bln_Name";
      *array++ = ESC "bln_Type";
      *array++ = ESC "bln_Pri";
      *array++ = ESC "bis_Data";
      *array++ = ESC "bis_Code";
      *array   = NULL;
   }
   return(0);
}

struct Hook inputlist_dsphook = {
 {NULL, NULL},
 (ULONG (* )())inputlist_dspfunc,
 NULL, NULL
};

void FreeInputHandler (void)
{
    MyFreePoolStructs (&InputPool, inputtext, NULL, inputlist);
}

int GetInputHandler (struct InputEntry **first) {
   struct   Interrupt      *intr;
   struct   Device         *input;
   struct   InputEntry     *inputentry,*previous = NULL;
   char     *tmp;
   char     code[FILENAMELENGTH + 1];

   int inputcnt = 0;
   *first = 0;

   if (!InputPool) InputPool = tbCreatePool(MEMF_CLEAR, 4096, 4096);

   if (clientstate) {
      if (SendDaemon ("GetInputList")) {
         while ((inputentry = tbAllocPooled(InputPool, sizeof(struct InputEntry))) \
           && (ReceiveDecodedEntry ((UBYTE *) inputentry, sizeof (struct InputEntry)))) {
            IsHex (inputentry->input_address, (long *) &inputentry->input_adr);

            if (! *first)
               *first = inputentry;
            if (previous)
               previous->input_next = inputentry;

            inputcnt++;
            previous = inputentry;
         }
      }
   } else {
      if (input = (struct Device *) FindName (&SysBase->DeviceList, "input.device")) {
         tmp = (APTR) input;
         tmp += 148;    /* Mir unbekannter Offsetname! */
         if (intr = (struct Interrupt *) ((struct Interrupt *) tmp)->is_Node.ln_Succ) {
            if (intr = (struct Interrupt *) intr->is_Node.ln_Succ) {
               while ((intr->is_Node.ln_Succ != 0) && (inputentry = tbAllocPooled(InputPool, sizeof(struct InputEntry)))) {
                  if (! *first)
                     *first = inputentry;
                  if (previous)
                     previous->input_next = inputentry;

                  inputentry->input_adr = intr;

                  code[0] = '\0';
                  if (points2ram((APTR) intr->is_Code)) {
                     _sprintf (code, HELL "$%08lx" DUNKEL, intr->is_Code);
                  } else {
                     _sprintf (code, "$%08lx", intr->is_Code);
                  }
                  _sprintf (inputentry->input_address, "$%08lx", intr);
                  strncpy (inputentry->input_name, nonetest (intr->is_Node.ln_Name), 27);
                  strcpy (inputentry->input_type, GetNodeType (intr->is_Node.ln_Type));
                  _sprintf (inputentry->input_pri, "%4ld ", intr->is_Node.ln_Pri);
                  _sprintf (inputentry->input_data, "$%08lx", intr->is_Data);
                  strcpy (inputentry->input_code, code);
                  inputcnt++;

                  previous = inputentry;
                  intr = (struct Interrupt *) intr->is_Node.ln_Succ;
               }
            }
         }
      }
   }
   return (inputcnt);
}

void PrintInputHandlers (char *filename) {
   int   i=1;
   BPTR  handle;
   struct InputEntry *entryp = NULL;

   handle = HandlePrintStart (filename);
   if ((handle) && (PrintOneLine (handle, "\n  Address  Type       Pri    Data       Code     Name\n\n"))) {
      if (! WI_InputHandler) {
         i = GetInputHandler (&entryp);
      }
      if (i) {
         for (i=0;;i++) {
            if (WI_InputHandler)
               DoMethod (inputlist,MUIM_List_GetEntry,i,&entryp);
            if (!entryp) break;

            if (points2ram ((APTR) (entryp->input_adr->is_Code)))
               strcpy (tmpstr, entryp->input_code+2);
            else
               strcpy (tmpstr, entryp->input_code);

            _sprintf (tmpstr2, " %s %-9s %4s %s %-9.9s %s\n", entryp->input_address, entryp->input_type, entryp->input_pri, entryp->input_data, tmpstr, entryp->input_name);
            if (! (PrintOneLine (handle, tmpstr2)))
               break;

            if (! WI_InputHandler)
               entryp = entryp->input_next;
         }
      }
   }
   HandlePrintStop();
}

void ShowInputHandler (void) {
   struct InputEntry *input;

   ApplicationSleep();
   set (inputlist,MUIA_List_Quiet,TRUE);
   set (BT_InputRemove, MUIA_Disabled, TRUE);
   set (BT_InputPriority, MUIA_Disabled, TRUE);

   FreeInputHandler();
   inputcnt = GetInputHandler (&input);

   while (input) {
      InsertBottomEntry (inputlist, (APTR *) &input);
      input = input->input_next;
   }

   SetCountText (inputcount, inputcnt);
   AwakeApplication();
   set (inputlist,MUIA_List_Quiet,FALSE);
}

void SendInputList (void) {
   struct InputEntry *input;

   FreeInputHandler();
   inputcnt = GetInputHandler (&input);

   while (input) {
      SendEncodedEntry ((UBYTE *) input, sizeof (struct InputEntry));
      input = input->input_next;
   }
   FreeInputHandler();
}


char inputhandler_title[WINDOWTITLELEN];

void InputHandlerWindow (BOOL state) {
   if (state) {
      if (WI_InputHandler) {
         ShowInputHandler();
      } else {
         WI_InputHandler = WindowObject,
         MUIA_Window_Title, MyGetWindowTitle (inputhandler_title, "INPUTHANDLERS"),
         MUIA_HelpNode, InputHandlersText,
         MUIA_Window_ID, MakeListID('I','N','P','U'),
         WindowContents, VGroup,
            Child, inputlist = MyListviewObject ("COL=0 DELTA=8,COL=1 DELTA=8,COL=2 DELTA=8,COL=3 DELTA=8 P=\33r,COL=4 DELTA=8,COL=5",&inputlist_dsphook),
            Child, MyBelowListview (&inputtext, &inputcount),
            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_InputUpdate    = KeyButtonA (UpdateText  ,ID_INPUTUPDATE),
               Child, BT_InputPrint     = KeyButtonA (PrintText   ,ID_INPUTPRINT),
               Child, BT_InputRemove    = KeyButtonA (RemoveText  ,ID_INPUTREMOVE),
               Child, BT_InputPriority  = KeyButtonA (PriorityText,ID_INPUTPRIORITY),
               Child, BT_InputExit      = KeyButtonA (ExitText    ,ID_INPUTEXIT),
            End,
         End, End;

         DoMethod (AP_Scout,OM_ADDMEMBER,WI_InputHandler);
         DoMethod (WI_InputHandler,MUIM_Window_SetCycleChain,inputlist,BT_InputUpdate,BT_InputPrint,BT_InputRemove,BT_InputPriority,BT_InputExit,NULL);

         SetCloseRequest (WI_InputHandler,ID_INPUTEXIT);
         SetListActive (inputlist,ID_INPUTLV_ACTIVE);

         ShowInputHandler();

         SetWindowOpen (WI_InputHandler,inputlist,ID_INPUTEXIT);
      }
   } else if ((! state) && (WI_InputHandler)) {
      SetWindowClose (WI_InputHandler,TRUE);

      FreeInputHandler();

      DoMethod (AP_Scout,OM_REMMEMBER,WI_InputHandler);
      MUI_DisposeObject (WI_InputHandler);
      WI_InputHandler = NULL;
      inputlist = NULL;
   }
}

