/**
 * 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 "scout_ports.h"

extern struct ExecBase        *SysBase;
extern struct Library         *GfxBase;
extern struct IntuitionBase   *IntuitionBase;

int  portcnt;
struct Remember *PortRememberKey;

__asm LONG portlist_dspfunc(register __a2 char **array, register __a1 struct PortEntry *portentry, register __a0 struct Hook *hook) {
   if (portentry) {
      *array++ = portentry->pt_address;
      *array++ = portentry->pt_name;
      *array++ = portentry->pt_pri;
      *array++ = portentry->pt_sigbit;
      *array++ = portentry->pt_sigtask;
      *array   = NULL;
   } else {
      *array++ = ESC "bAddress";
      *array++ = ESC "bln_Name";
      *array++ = ESC "bln_Pri";
      *array++ = ESC "bmp_SigBit";
      *array++ = ESC "bmp_SigTask";
      *array++ = NULL;
   }
   return(0);
}

struct Hook portlist_dsphook = {
 {NULL, NULL},
 (ULONG (* )())portlist_dspfunc,
 NULL, NULL
};

void FreePorts (void) {
   MyFreeStructs (&PortRememberKey, porttext, portlist);
}

int GetPorts (struct PortEntry **first) {
   struct   MsgPort     *port;
   struct   PortEntry   *portentry,*previous = NULL;

   int portcnt = 0;
   *first = 0;

   if (clientstate) {
      if (SendDaemon ("GetPortList")) {
         while ((portentry = AllocRemember (&PortRememberKey, sizeof (struct PortEntry), MEMF_ANY|MEMF_CLEAR)) \
           && (ReceiveDecodedEntry ((UBYTE *) portentry, sizeof (struct PortEntry)))) {
            IsHex (portentry->pt_address, (long *) &portentry->pt_adr);

            if (! *first)
               *first = portentry;
            if (previous)
               previous->pt_next = portentry;

            portcnt++;
            previous = portentry;
         }
      }
   } else {
      port = FIRSTPORT;
   
      while ((port->mp_Node.ln_Succ != 0) && (portentry = AllocRemember (&PortRememberKey, sizeof (struct PortEntry), MEMF_ANY|MEMF_CLEAR))) {
         if (! *first)
            *first = portentry;
         if (previous)
            previous->pt_next = portentry;
   
         portentry->pt_adr = port;
   
         sprintf (portentry->pt_address, "$%08x", port);
         strncpy (portentry->pt_name, nonetest (port->mp_Node.ln_Name), 25);
         sprintf (portentry->pt_pri, "%4d ", port->mp_Node.ln_Pri);
         sprintf (portentry->pt_sigbit, "%3d", port->mp_SigBit);
         strncpy (portentry->pt_sigtask, nonetest (GetTaskName ((struct Task *) port->mp_SigTask)), NODENAMELENGTH - 1);
         healstring (portentry->pt_sigtask);
   
         portcnt++;
         previous = portentry;
         port = (struct MsgPort *) port->mp_Node.ln_Succ;
      }
   }
   return (portcnt);
}

void PrintPorts (char *filename) {
   int i=1;
   BPTR handle;
   struct PortEntry *entryp;

   handle = HandlePrintStart (filename);
   if ((handle) && (PrintOneLine (handle, "\n  Address  Name                       Pri SigBit SigTask\n\n"))) {
      if (! WI_Ports) {
         i = GetPorts (&entryp);
      }
      if (i) {
         for (i=0;;i++) {
            if (WI_Ports)
               DoMethod (portlist,MUIM_List_GetEntry,i,&entryp);
            if (!entryp) break;

            sprintf (tmpstr2, " %ls %-25.25ls %4ls %3ls   %-26.26ls\n", entryp->pt_address, entryp->pt_name, entryp->pt_pri, entryp->pt_sigbit, entryp->pt_sigtask);
            if (! (PrintOneLine (handle, tmpstr2)))
               break;

            if (! WI_Ports)
               entryp = entryp->pt_next;
         }
      }
   }
   HandlePrintStop();
}

void ShowPorts (void) {
   struct   PortEntry   *port;

   ApplicationSleep();
   set(portlist,MUIA_List_Quiet,TRUE);
   set(portlist,MUIA_List_CompareHook,portlist_cmphook_ptr);
   set(BT_PortRemove, MUIA_Disabled, TRUE);
   set(BT_PortPriority, MUIA_Disabled, TRUE);
   set(BT_PortMore, MUIA_Disabled, TRUE);

   FreePorts();
   portcnt = GetPorts (&port);

   while (port) {
      InsertSortedEntry (portlist, (APTR *) &port);
      port = port->pt_next;
   }

   SetCountText (portcount, portcnt);
   AwakeApplication();
   set(portlist,MUIA_List_Quiet,FALSE);
}

void SendPortList (void) {
   struct   PortEntry   *port;

   FreePorts();
   GetPorts (&port);

   while (port) {
      SendEncodedEntry ((UBYTE *) port, sizeof (struct PortEntry));
      port = port->pt_next;
   }
   FreePorts();
}

void GetPortMore (struct MsgPort *port) {
   unsigned char  *title = "PORT: ";
   struct   WinFree  *ptr;

   APTR portmoretext0,portmoretext1,portmoretext2a,portmoretext2b,portmoretext3;
   APTR portmoretext4,portmoretext5;

   if (ptr = AllocWinFree()) {
      ptr->wf_Window = (APTR) WindowObject,

//      MUIA_Window_SizeGadget, FALSE,
      MUIA_HelpNode, PortsText,
      MUIA_Window_ID, MakeDetailID('.','P','O','R'),
      WindowContents, HGroup,
         Child, VGroup, MUIA_Group_SameWidth, TRUE,
            Child, MyLabel2 ("Name:"),
            Child, MyVSpace(0),
            Child, MyLabel2 ("Address:\nPri:\nType:"),
            Child, MyVSpace(0),
            Child, MyLabel2 ("TaskName:"),
            Child, MyLabel2 ("MsgList:\nHead:"),
         End,
         Child, VGroup, MUIA_Group_SameWidth, TRUE,
            Child, portmoretext0 = MyTextObject(),
            Child, HGroup,
               Child, portmoretext1 = MyTextObject2(),
               Child, VGroup,
                  Child, MyLabel ("Flags:"),
                  Child, MyLabel ("SigBit:\nSigTask:"),
               End,
               Child, VGroup, MUIA_Group_SameWidth, TRUE, MUIA_Weight, 0,
                  Child, portmoretext2a = KeyButtonF ('b', port->mp_Flags),
                  Child, portmoretext2b = MyTextObject(),
               End,
            End,
            Child, portmoretext3 = MyTextObject(),
            Child, HGroup,
               Child, portmoretext4 = MyTextObject2(),
               Child, MyLabel ("Tail:\nTailPred:"),
               Child, portmoretext5 = MyTextObject2(),
            End,
         End,
      End, End;

      if (ptr->wf_Window) {
         MySetContents (portmoretext1, ESC "r$%08x\n" ESC "c%d\n" ESC "c%s", port, port->mp_Node.ln_Pri, GetNodeType (port->mp_Node.ln_Type));
         MySetContents (portmoretext2b, ESC "c%d\n" ESC "r$%08x", port->mp_SigBit, port->mp_SigTask);
         MySetContents (portmoretext4, ESC "r$%08x\n$%08x", &port->mp_MsgList, port->mp_MsgList.lh_Head);
         MySetContents (portmoretext5, ESC "r$%08x\n$%08x", port->mp_MsgList.lh_Tail, port->mp_MsgList.lh_TailPred);

         HandleFlagsButtonPressed (portmoretext2a, ptr, "(PORT)", "mp_Flags", port->mp_Flags, NULL, (struct MaskedLongFlag *) &mp_flags, 'b');
         HandleWindowOpen (ptr, title, port->mp_Node.ln_Name);
         MySetContentsHealed (portmoretext0, "%s", port->mp_Node.ln_Name);
         MySetContentsHealed (portmoretext3, "%s", nonetest (GetTaskName (port->mp_SigTask)));
         HandleWindowClose (ptr);
      }
   }
}

