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

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

APTR BT_SemUpdate,BT_SemPrint,BT_SemObtain,BT_SemRelease,BT_SemRemove,BT_SemExit;
APTR semtext,semlist;

APTR semcount;
int  semcnt;

struct Remember *SemRememberKey;

__asm LONG semlist_dspfunc(register __a2 char **array, register __a1 struct SemEntry *sementry, register __a0 struct Hook *hook) {
        if (sementry) {
                *array++ = sementry->sm_address;
                *array++ = sementry->sm_name;
                *array++ = sementry->sm_nestcount;
                *array++ = sementry->sm_queuecount;
                *array++ = sementry->sm_owner;
                *array  = NULL;
        } else {
                *array++ = ESC "bAddress";
                *array++ = ESC "bName";
                *array++ = ESC "bNest";
                *array++ = ESC "bQueue";
                *array++ = ESC "bOwner";
                *array++ = NULL;
        }
        return(0);
}

struct Hook semlist_dsphook = {
 {NULL, NULL},
 (ULONG (* )())semlist_dspfunc,
 NULL, NULL
};

void FreeSemaphores (void) {
   MyFreeStructs (&SemRememberKey, semtext, semlist);
}

int GetSemaphores (struct SemEntry **first) {
   struct SignalSemaphore  *sem;
   struct SemEntry         *sementry,*previous = NULL;

   int semcnt = 0;
   *first = 0;

   if (clientstate) {
      if (SendDaemon ("GetSemList")) {
         while ((sementry = AllocRemember (&SemRememberKey, sizeof (struct SemEntry), MEMF_ANY|MEMF_CLEAR)) \
           && (ReceiveDecodedEntry ((UBYTE *) sementry, sizeof (struct SemEntry)))) {
            IsHex (sementry->sm_address, (long *) &sementry->sm_adr);

            if (! *first)
               *first = sementry;
            if (previous)
               previous->sm_next = sementry;

            semcnt++;
            previous = sementry;
         }
      }
   } else {
      sem = FIRSTSEMAPHORE;
   
      while ((sem->ss_Link.ln_Succ != 0) && (sementry = AllocRemember (&SemRememberKey, sizeof (struct SemEntry), MEMF_ANY|MEMF_CLEAR))) {
         if (! *first)
            *first = sementry;
         if (previous)
            previous->sm_next = sementry;
   
         sementry->sm_adr = sem;
   
                sprintf (sementry->sm_address, "$%08x", sem);
                strncpy (sementry->sm_name, nonetest (sem->ss_Link.ln_Name), FILENAMELENGTH);
                sprintf (sementry->sm_nestcount, "%3d ", sem->ss_NestCount);
         if (sem->ss_Owner) {
                sprintf (sementry->sm_queuecount, "%3d ", sem->ss_QueueCount);
                strncpy (sementry->sm_owner, nonetest (GetTaskName (sem->ss_Owner)), NODENAMELENGTH);
         } else {
                strcpy (sementry->sm_queuecount, "--- ");
                strcpy (sementry->sm_owner, "-----");
         }
   
         semcnt++;
         previous = sementry;
         sem = (struct SignalSemaphore *) sem->ss_Link.ln_Succ;
      }
   }
   return (semcnt);
}

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

   handle = HandlePrintStart (filename);
   if ((handle) && (PrintOneLine (handle, "\n  Address  Name                           Nest Queue Owner\n\n"))) {
      if (! WI_Semaphores) {
         i = GetSemaphores (&entryp);
      }
      if (i) {
         for (i=0;;i++) {
            if (WI_Semaphores)
               DoMethod (semlist,MUIM_List_GetEntry,i,&entryp);
            if (!entryp) break;

            if (strcmp (entryp->sm_owner, "<none>"))
               sprintf (tmpstr2, " %ls %-30ls %4ls %5ls %ls\n", entryp->sm_address, entryp->sm_name, entryp->sm_nestcount, entryp->sm_queuecount, entryp->sm_owner);
            else
               sprintf (tmpstr2, " %ls %-30ls %4ls  ---  -----\n", entryp->sm_address, entryp->sm_name, entryp->sm_nestcount);

            if (! (PrintOneLine (handle, tmpstr2)))
               break;

            if (! WI_Semaphores)
               entryp = entryp->sm_next;
         }
      }
   }
   HandlePrintStop();
}

void ShowSemaphores (void) {
   struct   SemEntry    *sem;

        ApplicationSleep();
        set (semlist,MUIA_List_Quiet,TRUE);
        set (BT_SemObtain, MUIA_Disabled, TRUE);
        set (BT_SemRelease, MUIA_Disabled, TRUE);
        set (BT_SemRemove, MUIA_Disabled, TRUE);

   FreeSemaphores();
   semcnt = GetSemaphores (&sem);

   while (sem) {
      InsertBottomEntry (semlist, (APTR *) &sem);
      sem = sem->sm_next;
   }

   SetCountText (semcount, semcnt);
        AwakeApplication();
        set (semlist,MUIA_List_Quiet,FALSE);
}

void SendSemList (void) {
   struct   SemEntry    *sem;

   FreeSemaphores();
   GetSemaphores (&sem);

   while (sem) {
      SendEncodedEntry ((UBYTE *) sem, sizeof (struct SemEntry));
      sem = sem->sm_next;
   }
   FreeSemaphores();
}

