/*
***************************************************************************
*
* Datei:
*    RSysList.c
*
* Inhalt:
*
*      --- Globale Routinen ---
*
*    int CountDevices ( long mask );
*    int CountIntuiObjects ( int typ );
*    int CountMemory ( void );
*    int CountNodes ( struct List *list );
*    int NoEntries ( void );
*    void KillList ( void );
*    void RefreshList ( int type );
*    void RestoreList ( void );
*    void SaveCurrentList ( void );
*
*      --- Lokale  Routinen ---
*
*
* Bemerkungen:
*    Listenverwaltung von RSys, Zählroutinen und interne Liste.
*
* Erstellungsdatum:
*    07-Jul-93    Rolf Böhme
*
* Änderungen:
*    07-Jul-93    Rolf Böhme    Erstellung
*
***************************************************************************
*/

#include "RSys.h"

   /*
    * CountIntuiObjects() zählt Screens oder Fenster,
    * abhängig von Typ
    */
int
CountIntuiObjects(int typ)
{
   int   wincount = 0,
         scrcount = 0;
   register struct Window *win;
   register struct Screen *scr;
   ULONG lock;

   lock = LockIBase(NULL);

   for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
   {
      scrcount++;

      for (win = scr->FirstWindow; win; win = win->NextWindow) wincount++;
   }

   UnlockIBase(lock);

   return ((typ == SCREENS) ? scrcount : wincount);
}

   /*
    * CountDevices() zählt im System angemeldete Devices
    * entsprechend der übergebenen Maske
    */
int
CountDevices(long mask)
{
   int   count = 0;
   struct DosList *dl;

   dl = LockDosList(mask | LDF_READ);

   while (dl = NextDosEntry(dl, mask | LDF_READ)) count++;

   UnLockDosList(mask | LDF_READ);

   return count;
}

   /*
    * CountNodes() zählt die Elemente einer Liste
    */
int
CountNodes(struct List *list)
{
   int   count = 0;
   register struct Node *node;

   Forbid();

   for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) count++;

   Permit();

   return count;
}

   /*
    * CountMemory() zählt die Memory-Chunks
    */
int
CountMemory(void)
{
   int   count = 0;
   register struct Node *node;
   register struct MemChunk *Loop;

   Disable();

   for (node = SysBase->MemList.lh_Head; node->ln_Succ; node = node->ln_Succ)
   {
      count++;
      for (Loop = ((struct MemHeader *) node)->mh_First; Loop; Loop = Loop->mc_Next) count++;
   }

   Enable();

   return count;
}

   /*
    * NoEntries() gibt FALSE zurück, falls keine Einträge zum
    * Anzeigen da sind. In diesem Falle wird das ListView auf
    * dem Hauptfenster initialisiert
    */
int
NoEntries(void)
{
   DPOS;

   if (countentries == 0)
   {
      RefreshListView();
      PrintStatistics();

      return TRUE;
   }

   PrintInfo("Creating list...", NO_SPEAK, 0);

   return FALSE;
}

   /*
    * RefreshList() erneuert die anzuzeigende Liste im
    * Hauptfenster
    */
void
RefreshList(int type)
{
   DPOS;

   if(!SysWnd) return;

   if (type <= GD_HardwareGad)
   {
      EmptyListView();
      PrintHeader((enum ListTypes)type, NULL);
   }

   topentry = 0;

   if(type < LASTTYPE) (*(EntryAttr[type].ea_func))();

   actualfindnode = GetNode(&ListeLVList, topentry);
   actualfindnodenum = topentry;

   PrintStatistics();

   return;
}

ScrollEntry *SaveEntries = NULL;
struct List SavedList;
int   SaveID;
int   Savecountentries;

   /*
    * SaveCurrentList() speichert die aktuelle Liste im
    * Hauptfenster intern ab.  Diese kann dann wieder
    * eingeladen werden
    */
void
SaveCurrentList(void)
{
   int   i;

   DPOS;

   HandleHelp(MN_SaveCurrentList);

   if (SaveEntries && (NOT(Question(SysWnd, "Internal List exist! Do you want create a new list?", YES))))
   {
      PrintStatistics();
      return;
   }

   KillList();

   SaveEntries = (ScrollEntry *) MyAllocVec(countentries * sizeof(ScrollEntry),
                                            MEMF_CLEAR | MEMF_ANY, NO_KILL);
   if (SaveEntries)
   {
      struct Node *node = ListeLVList.lh_Head;

      NewList(&SavedList);

      SaveID = LastID;
      Savecountentries = countentries;

      for (i = 0; (i < countentries) && node; i++)
      {
         CopyMem((APTR) node, (APTR) & (SaveEntries[i].se_Node), sizeof(ScrollEntry));

         AddTail(&SavedList, &SaveEntries[i].se_Node);

         node = node->ln_Succ;
      }

      PrintInfo("Current list saved", SPEAK, SEC);

      PrintStatistics();
   }

   return;
}

   /*
    * RestoreList() stellt die vorher intern abgespeicherte
    * Liste aus dem Hauptfenster wieder her und erneuert das
    * ListView
    */
void
RestoreList(void)
{
   int   i;

   DPOS;

   HandleHelp(MN_RestoreList);

   if (SaveEntries)
   {
      struct Node *node = SavedList.lh_Head;

      LastID = SaveID;
      countentries = Savecountentries;

      PrintHeader((enum ListTypes)LastID, NULL);

      EmptyListView();

      PrintInfo("Restore saved list", NO_SPEAK, 0);

      Entries = AllocScrollEntries(Savecountentries);

      for (i = 0; (i < Savecountentries) && node; i++)
      {
         CopyMem((APTR) node, (APTR) & (Entries[i].se_Node), sizeof(ScrollEntry));

         Entries[i].se_Node.ln_Name = Entries[i].se_Entry;

         AddNodeToList(i, NO_SORT, 0);

         node = node->ln_Succ;
      }

      RefreshListView();

      PrintInfo("Previous saved list restored", SPEAK, 0);
   }
   else ErrorHandle("No internal list", LIST_NODE_ERR, SAVED_FAIL, NO_KILL);

   return;
}

   /*
    * KillList() gibt den Speicher der intern abgespeicherten
    * Liste wieder frei
    */
void
KillList(void)
{
   DPOS;

   HandleHelp(MN_KillList);

   if (SaveEntries)
   {
      MyFreeVec(SaveEntries);
      SaveEntries = NULL;

      PrintInfo("Last saved list killed", SPEAK, SEC);
      PrintStatistics();
   }

   return;
}
