/*
   ***************************************************************************
   *
   * Datei:
   *    RSysList.c
   *
   * Inhalt:
   *
   *      --- Globale Routinen ---
   *
   *    int CountDevices ( long mask );
   *    int CountIntuiObjects ( int typ );
   *    int CountMemory ( void );
   *    int CountNodes ( 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"
#include "protos.h"

 /*
  * CountIntuiObjects() zählt Screens oder Fenster,
  * abhängig von Typ
  */
int
CountIntuiObjects (int typ)
{
  int wincount = 0, scrcount = 0;
  WINDOW *win;
  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;
  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 (LIST * list)
{
  int count = 0;
  NODE *node;

  Forbid ();
  {
    for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
      count++;
  }
  Permit ();

  return count;
}
 /*
  * CountNodes() of given type (GMD) 
  */
int
CountNodesType (LIST * list, UBYTE type)
{
  int count = 0;
  NODE *node;

  Forbid ();

  for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
    {
      if (node->ln_Type == type)
	count++;
    }

  Permit ();

  return count;
}


 /*
  * CountMemory() zählt die Memory-Chunks
  */
int
CountMemory (void)
{
  int count = 0;
  NODE *node;
  MEMCHUNK *Loop;

  Disable ();

  for (node = SysBase->MemList.lh_Head; node->ln_Succ; node = node->ln_Succ)
    {
      count++;
      for (Loop = ((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;
}

RSYS_ScrollEntry *SaveEntries = NULL;
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 = (RSYS_ScrollEntry *) MyAllocVec (countentries * sizeof (RSYS_ScrollEntry),
					    MEMF_CLEAR | MEMF_ANY, NO_KILL);
  if (SaveEntries)
    {
      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 (RSYS_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)
    {
      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 (RSYS_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;
}
