/*
   ***************************************************************************
   *
   * Datei:
   *    RSysInitData.c
   *
   * Inhalt:
   *
   *      --- Globale Routinen ---
   *
   *    int ChooseNewFile ( char *oldfile , char *header );
   *    RSYS_ValidMemoryNode *CheckNode ( ULONG memoryptr );
   *    void BuildAllDataEntries ( void );
   *    void BuildHardwareList ( void );
   *    void BuildHelpList ( void );
   *    void BuildLibOffsetList ( void );
   *    void BuildValidAddressList ( void );
   *    void FreeAmigaGuideContextMemory ( void );
   *    void FreeHardwareData ( void );
   *    void FreeLibOffData ( void );
   *    void FreeValidAddressList ( void );
   *    void SaveConfig ( void );
   *
   *      --- Lokale  Routinen ---
   *
   *    static int AllocLineBuffer ( void );
   *    static int MarkAddress ( ULONG start , ULONG length , char type , char *comment );
   *    static int ReadCompanies ( BPTR hfile );
   *    static int ReadContextFile ( UBYTE *filename );
   *    static int ReadHardwareData ( BPTR hfile );
   *    static int ReadLibOff ( BPTR lofile );
   *    static int SplitFunction ( char *data , RSYS_FUNCTION *func , LIBRARY *lib );
   *    static STRPTR CheckHardwareEntry ( STRPTR buffer , int *type );
   *    static STRPTR CheckLibOffEntry ( STRPTR buffer , int *type );
   *    static UBYTE *myFGets ( BPTR file , STRPTR buffer , long size );
   *    static void FreeLineBuffer ( void );
   *
   * Bemerkungen:
   *    Enthält die Routinen zur Initialisierung der externen Daten.
   *
   * Erstellungsdatum:
   *    20-Jul-93    Rolf Böhme
   *
   * Änderungen:
   *    20-Jul-93    Rolf Böhme    Erstellung
   *
   ***************************************************************************
 */

#include "RSys.h"
#include "protos.h"


/*#include "I.c" */

static REMEMBER *HWKey = NULL;
static REMEMBER *LOKey = NULL;
static REMEMBER *VMKey = NULL;
static REMEMBER *ContextKey = NULL;


static char *datatype[] =
{
  "END", "MANUFACTURER", "PRODUCT", "TYPE", "NAME", "COMPANY", "UNKNOWN"
};

static char *libofftype[] =
{
  "END", "LIBNAME", "TYP", "BASE", "RSYS_FUNCTION"
};


static UBYTE *filebuffer;
#define MAXLINE 256

static int
AllocLineBuffer (void)
{
  if (filebuffer = MyAllocVec ((MAXLINE + 1) * sizeof (UBYTE), MEMF_CLEAR, NO_KILL))
    return TRUE;

  ErrorHandle ("No file buffer for reading", MEMORY_ERR, ALLOC_FAIL, NO_KILL);

  return FALSE;
}

static void
FreeLineBuffer (void)
{
  MyFreeVec (filebuffer);

  return;
}

int
ChooseNewFile (char *oldfile, char *header)
{
  char dir[MAXFULLNAME], file[MAXFULLNAME];
/*
   char *dir = NULL,
   *file = NULL;
 */
  int ok = TRUE;

  if (!SysWnd)
    return ok;

/*
   if ((dir = MyAllocVec(MAXFULLNAME, MEMF_CLEAR, NO_KILL)) &&
   (file = MyAllocVec(MAXFULLNAME, MEMF_CLEAR, NO_KILL)))
   {
 */
  strncpy (file, (char *) FilePart ((STRPTR) oldfile), MAXFULLNAME);
  strncpy (dir, oldfile, (int) ((ULONG) PathPart ((STRPTR) oldfile) - (ULONG) oldfile));

  if (GetFile (SysWnd, dir, file, "#?", header, "Load"))
    strncpy (oldfile, _fullpath, MAXFULLNAME);
  else
    ok = FALSE;
/*
   }
   else
   {
   ok = FALSE;
   ErrorHandle(oldfile, MEMORY_ERR, ALLOC_FAIL, NO_KILL);
   }

   MyFreeVec(file);
   MyFreeVec(dir);
 */

  return ok;
}


void
FreeHardwareData (void)
{
  FreeRemember (HWKEY, TRUE);
  return;
}

static UBYTE *
myFGets (BPTR file, STRPTR buffer, long size)
{
  UBYTE *retval = (UBYTE *) NULL;
  char *nlpos;

  retval = FGets (file, buffer, size);

  if (retval && (nlpos = strchr ((char *) retval, '\n')))
    *nlpos = STRINGEND;

  while (retval && strchr (";#\f\t\0", (int) (*retval)))
    {
      retval = FGets (file, buffer, size);

      if (retval && (nlpos = strchr ((char *) retval, '\n')))
	*nlpos = STRINGEND;
    }

  return retval;
}

static int
ReadCompanies (BPTR hfile)
{
  UBYTE *check;
  int count, loop = 0;

  check = myFGets (hfile, filebuffer, MAXLINE);
  if (check)
    {
      count = atoi ((char *) check);

      if (count == 0)
	return FALSE;

      if (company_str = (char **) ALLOCHW (count * sizeof (char *)))
	{
	  check = myFGets (hfile, filebuffer, MAXLINE);

	  while ((loop < count) && check)
	    {
	      if (*check)
		{
		  company_str[loop] = ALLOCHW (strlen ((char *) check) + 1);

		  if (!company_str[loop])
		    return FALSE;

		  strcpy (company_str[loop++], (char *) check);
		}

	      if (loop < count)
		check = myFGets (hfile, filebuffer, MAXLINE);
	    }

	  if ((loop < count) || (check == NULL))
	    return FALSE;

	  return TRUE;
	}
    }

  return FALSE;
}

static STRPTR
CheckHardwareEntry (STRPTR buffer, int *type)
{
  char *eqpos = NULL;
  int i;

  *type = END;

  if (!strcmp ((char *) buffer, datatype[END]))
    return (STRPTR) eqpos;

  *type = UNKNOWN;

  for (i = MANU_NR; i < UNKNOWN; i++)
    if (!strncmp ((char *) buffer, datatype[i], strlen (datatype[i])))
      {
	eqpos = strchr ((char *) buffer, '\=');

	eqpos++;

	while (*eqpos == ' ')
	  eqpos++;

	*type = i;

	return (STRPTR) eqpos;
      }

  return (STRPTR) eqpos;
}

static int
ReadHardwareData (BPTR hfile)
{
  UBYTE *check, *data;
  int count = 0, loop = 0;
  int type, err;

  check = myFGets (hfile, filebuffer, MAXLINE);
  if (check)
    {
      count = atoi ((char *) check);

      hardwarecnt = count;

      if (count == 0)
	return FALSE;

      if (manu = ALLOCHW ((count + 1) * sizeof (MANUFACTURER)))
	{
	  err = FALSE;

	  check = myFGets (hfile, filebuffer, MAXLINE);

	  while (loop < count && check && !err)
	    {
	      data = CheckHardwareEntry (check, &type);

	      switch (type)
		{
		case MANU_NR:
		  manu[loop].manu_nr = (WORD) atoi ((char *) data);
		  break;

		case PROD_NR:
		  manu[loop].prod_nr = (WORD) atoi ((char *) data);
		  break;

		case TYPE_NR:
		  manu[loop].type_nr = (WORD) atoi ((char *) data);
		  break;

		case COMPANY:
		  manu[loop].company = atoi ((char *) data);
		  break;

		case NAME_STR:
		  manu[loop].name = ALLOCHW (strlen ((char *) data) + 1);

		  if (manu[loop].name)
		    strcpy (manu[loop].name, (char *) data);
		  else
		    {
		      ErrorHandle ((char *) data, MEMORY_ERR, ALLOC_FAIL, NO_KILL);
		      err = TRUE;
		    }
		  break;

		case END:
		  loop++;
		  break;

		default:
		  ErrorHandle ((char *) check, DATA_ENTRY_ERR, TYPE_FAIL, NO_KILL);
		  break;
		}

	      if (!err)
		check = myFGets (hfile, filebuffer, MAXLINE);
	    }

	  if (err || loop < count)
	    return FALSE;

	  return TRUE;
	}
      else
	{
	  ErrorHandle ((char *) RSysFiles.Hardware, MEMORY_ERR, ALLOC_FAIL, NO_KILL);
	  return FALSE;
	}
    }

  return FALSE;
}

void
BuildHardwareList (void)
{
  int ok;
  BPTR hfile;

  DPOS;
  if (!ChooseNewFile ((char *) RSysFiles.Hardware, "Select new Hardware data file..."))
    return;

  DPOS;
  if (Flags.dummy1)
    FreeHardwareData ();

  DPOS;
  Flags.dummy1 = 0;

  DPOS;
  if (!exist ((char *) RSysFiles.Hardware))
    return;

  DPOS;
  if (!AllocLineBuffer ())
    return;

  DPOS;
  if (hfile = Open (RSysFiles.Hardware, MODE_OLDFILE))
    {
      PrintInfo ("Read hardware datas...", SPEAK, NULL);

      DPOS;
      ok = ReadCompanies (hfile);
      if (ok)
	{
	  DPOS;
	  ok = ReadHardwareData (hfile);

	  if (ok)
	    Flags.dummy1 = 1;
	  else
	    ErrorHandle ((char *) RSysFiles.Hardware, FILE_ERR, READ_FAIL, NO_KILL);
	}
      else
	ErrorHandle ((char *) RSysFiles.Hardware, FILE_ERR, READ_FAIL, NO_KILL);

      DPOS;
      Close (hfile);

      DPOS;
      if (Flags.dummy1)
	PrintInfo ("Hardware Datas updated", SPEAK, SEC);

    }
  else
    ErrorHandle ((char *) RSysFiles.Hardware, FILE_ERR, OPEN_FAIL, NO_KILL);

  DPOS;
  FreeLineBuffer ();

  DPOS;
  PrintStatistics ();

  return;
}

void
FreeLibOffData (void)
{
  FreeRemember (LOKEY, TRUE);

  return;
}

static STRPTR
CheckLibOffEntry (STRPTR buffer, int *type)
{
  char *eqpos = NULL;
  int i;

  *type = LO_END;

  if (!strcmp ((char *) buffer, libofftype[LO_END]))
    return (STRPTR) eqpos;

  *type = LO_UNKNOWN;

  for (i = LO_LIBNAME; i <= LO_FUNCTION; i++)
    if (!strncmp ((char *) buffer, libofftype[i], strlen (libofftype[i])))
      {
	eqpos = strchr ((char *) buffer, '\=');

	eqpos++;

	while (*eqpos == ' ')
	  eqpos++;

	*type = i;

	return (STRPTR) eqpos;
      }

  return (STRPTR) eqpos;
}

static int
SplitFunction (char *data, RSYS_FUNCTION * func, RSYS_LIBRARY * lib)
{
  char f[BUFSIZE], b[5], *dptr = data;
  int fc = 0, bc = 0, public, ok = TRUE;

  while ((fc < BUFSIZE - 1) && (((f[fc++] = *(dptr++))) != ','));
  f[fc - 1] = STRINGEND;

  while ((bc < 5) && ((b[bc++] = (char) (*(dptr++))) != ','));
  b[bc - 1] = STRINGEND;

  public = atoi (dptr);

  if (!(func->f_name = ALLOCLO (strlen (f) + 1)))
    ok = FALSE;
  else
    {
      strcpy (func->f_name, f);
      func->f_bias = atoi (b);
      func->f_public = (char) ((public == 1) ? 1 : 0);

      AddTail (&(lib->l_functions), &(func->f_node));
    }

  return ok;
}

static int
ReadLibOff (BPTR lofile)
{
  UBYTE *check, *data;
  int ok = TRUE;
  RSYS_FUNCTION *func = NULL;
  RSYS_LIBRARY *lib = NULL;
  int type;

  check = myFGets (lofile, filebuffer, MAXLINE);
  while (check && ok != FALSE)
    {
      data = CheckLibOffEntry (check, &type);

      switch (type)
	{
	case LO_END:
	  AddTail (&Libraries, &(lib->l_node));
	  break;

	case LO_LIBNAME:
	  lib = ALLOCLO (sizeof (RSYS_LIBRARY));

	  if (!lib)
	    ok = FALSE;
	  else
	    {
	      NewList (&(lib->l_functions));

	      lib->l_name = ALLOCLO (strlen ((char *) data) + 1);

	      if (!lib->l_name)
		ok = FALSE;
	      else
		{
		  strcpy ((char *) lib->l_name, (char *) data);
		  lib->l_node.ln_Name = (char *) lib->l_name;
		}
	    }
	  break;

	case LO_TYP:
	  lib->l_typ = (*data == 'L') ? 1 : 0;
	  break;

	case LO_BASE:
	  lib->l_base = ALLOCLO (strlen ((char *) data) + 1);

	  if (!lib->l_base)
	    ok = FALSE;
	  else
	    strcpy (lib->l_base, (char *) data);
	  break;

	case LO_FUNCTION:
	  func = ALLOCLO (sizeof (RSYS_LIBRARY));

	  if (func)
	    ok = SplitFunction ((char *) data, func, lib);
	  else
	    ok = FALSE;
	  break;

	default:
	  ErrorHandle ((char *) check, DATA_ENTRY_ERR, TYPE_FAIL, NO_KILL);
	  break;
	}

      if (ok == TRUE)
	check = myFGets (lofile, filebuffer, MAXLINE);
      else
	ErrorHandle ((char *) RSysFiles.LibOffsets, FILE_ERR, READ_FAIL, NO_KILL);
    }

  return ok;
}

void
BuildLibOffsetList (void)
{
  int ok;
  BPTR lofile;

  if (!ChooseNewFile ((char *) RSysFiles.LibOffsets, "Select new Library offsets file..."))
    return;

  if (Flags.dummy2)
    FreeLibOffData ();

  NewList (&Libraries);

  Flags.dummy2 = 0;

  if (!exist ((char *) RSysFiles.LibOffsets))
    return;

  if (!AllocLineBuffer ())
    return;

  if (lofile = Open (RSysFiles.LibOffsets, MODE_OLDFILE))
    {
      PrintInfo ("Read library offsets...", SPEAK, NULL);

      ok = ReadLibOff (lofile);
      if (ok == TRUE)
	{
	  Flags.dummy2 = 1;
	  PrintInfo ("Library offsets updated", SPEAK, SEC);
	}
      else
	ErrorHandle ((char *) RSysFiles.LibOffsets, FILE_ERR, READ_FAIL, NO_KILL);

      Close (lofile);
    }
  else
    ErrorHandle ((char *) RSysFiles.LibOffsets, FILE_ERR, OPEN_FAIL, NO_KILL);

  FreeLineBuffer ();

  PrintStatistics ();

  return;
}

void
FreeAmigaGuideContextMemory (void)
{
  FreeRemember ((REMEMBER **) & ContextKey, TRUE);

  return;
}

static int
ReadContextFile (UBYTE * filename)
{
  BPTR file;
  UBYTE *check;
  int i = 0, noerror = TRUE, retval = TRUE;

  if (exist ((char *) filename))
    {
      if (file = Open (filename, MODE_OLDFILE))
	{
	  check = myFGets (file, filebuffer, MAXLINE);

	  while ((i < MAXENTRY) && check && noerror)
	    {
	      if (context[i] = AllocRemember ((REMEMBER **) & ContextKey,
					      strlen ((char *) check) + 1,
					      MEMF_CLEAR | MEMF_PUBLIC))
		{
		  strcpy ((char *) (context[i++]), (char *) check);

		  check = myFGets (file, filebuffer, MAXLINE);
		}
	      else
		noerror = FALSE;
	    }

	  Close (file);

	  if (!noerror)
	    {
	      ErrorHandle ("AGuide nodes", MEMORY_ERR, ALLOC_FAIL, NO_KILL);
	      retval = FALSE;
	    }

	  if (!check && (i < MAXENTRY))
	    {
	      ErrorHandle ((char *) filename, DATA_ENTRY_ERR, SIZE_FAIL, NO_KILL);
	      retval = FALSE;
	    }

	  context[MAXENTRY] = (UBYTE *) NULL;

	  return retval;
	}
      else
	ErrorHandle ((char *) filename, FILE_ERR, OPEN_FAIL, NO_KILL);
    }

  return FALSE;
}

void
BuildHelpList (void)
{
  if (Flags.helpmode)
    return;

  if (!ChooseNewFile ((char *) RSysFiles.Guide, "Select AGuide documentation...") ||
      !ChooseNewFile ((char *) RSysFiles.GuideContext, "Select new Context nodes file..."))
    return;

  if (Flags.dummy3)
    FreeAmigaGuideContextMemory ();

  Flags.dummy3 = 0;

  if (!AllocLineBuffer ())
    return;

  PrintInfo ("Read context nodes...", SPEAK, NULL);

  if (!exist ((char *) RSysFiles.GuideContext) || !ReadContextFile (RSysFiles.GuideContext))
    {
      if (SysWnd)
	OffMenu (SysWnd, FULLMENUNUM (0, 1, 0));

      Flags.nohelp = 1;
    }
  else
    {
      if (SysWnd)
	OnMenu (SysWnd, FULLMENUNUM (0, 1, 0));
      Flags.dummy3 = 1;

      PrintInfo ("Context nodes updated", SPEAK, SEC);
    }

  FreeLineBuffer ();

  PrintStatistics ();

  return;
}

void
SaveConfig (void)
{
  DISKOBJECT *dop;
  char **NewToolTypes, **OldToolTypes;
  char *ToolTypes[] =
  {
  /* 00 */ "DONOTWAIT",

  /* 01 */ "CX_HOTKEY=",
  /* 02 */ "CX_CRYPT=",
  /* 03 */ "CX_FINDFILE=",
  /* 04 */ "CX_FORMAT=",
  /* 05 */ "CX_HUNKLIST=",
  /* 06 */ "CX_CRC=",
  /* 07 */ "CX_SAVEWINDOW=",
  /* 08 */ "CX_FILEREQUEST=",

  /* 09 */ "NOFASTMODE",
  /* 10 */ "NOSORT",
  /* 11 */ "WORKINGBAR",
  /* 12 */ "AUTOFRONT",
  /* 13 */ "MOUSEWINDOW",
  /* 14 */ "TOPAZFONT",
  /* 15 */ "NOSAVEASKING",
  /* 16 */ "NOAPPICON",

  /* 17 */ "BACKPATTERNCOL=",
  /* 18 */ "BACKGROUNDCOL=",
  /* 19 */ "BACKPATTERN=",
  /* 20 */ "DETAILPEN=",
  /* 21 */ "BLOCKPEN=",
  /* 22 */ "MENUPEN=",

  /* 23 */ "HARDWAREDATA=",
  /* 24 */ "LIBOFFDATA=",
  /* 25 */ "AGUIDEDOC=",
  /* 26 */ "AGUIDECONTEXT=",
  /* 27 */ "ACTIONFILE=",
  /* 28 */ "OUTWINDOW=",
  /* 29 */ "LISTHEIGHT=",

  /* 30 */ "TEXTFORMATTER",
  /* 31 */ "ICONX=",
  /* 32 */ "ICONY=",
  /* 33 */ NULL,
  };
  int i;
  REMEMBER *ToolTypeKey = NULL;

  if (dop = GetProgramIcon ())
    {
      PrintInfo ("Write Info file...", SPEAK, NULL);

      NewToolTypes = (char **) AllocRemember (&ToolTypeKey, 35 * sizeof (char *), MEMF_CLEAR | MEMF_PUBLIC);

      if (NewToolTypes)
	{
	  for (i = 0; i < 33; i++)
	    {
	      NewToolTypes[i] = AllocRemember (&ToolTypeKey, 60, MEMF_CLEAR | MEMF_PUBLIC);
	      if (!NewToolTypes[i])
		{
		  FreeDiskObject (dop);
		  FreeRemember (&ToolTypeKey, TRUE);
		  ErrorHandle ("AllocRemember()", MEMORY_ERR, ALLOC_FAIL, KILL);
		}
	    }

	  strcpy (NewToolTypes[0], ToolTypes[0]);

	  for (i = 1; i < 9; i++)
	    sprintf (NewToolTypes[i], "%s%s", ToolTypes[i], hotkey[i - 1]);

#define NEXT 9

	  if (!Flags.fastmode)
	    strcpy (NewToolTypes[NEXT + 0], ToolTypes[NEXT + 0]);
	  else
	    sprintf (NewToolTypes[NEXT + 0], "(%s)", ToolTypes[NEXT + 0]);

	  if (!Flags.sortmode)
	    strcpy (NewToolTypes[NEXT + 1], ToolTypes[NEXT + 1]);
	  else
	    sprintf (NewToolTypes[NEXT + 1], "(%s)", ToolTypes[NEXT + 1]);

	  if (Flags.workingbar)
	    strcpy (NewToolTypes[NEXT + 2], ToolTypes[NEXT + 2]);
	  else
	    sprintf (NewToolTypes[NEXT + 2], "(%s)", ToolTypes[NEXT + 2]);

	  if (Flags.autofront)
	    strcpy (NewToolTypes[NEXT + 3], ToolTypes[NEXT + 3]);
	  else
	    sprintf (NewToolTypes[NEXT + 3], "(%s)", ToolTypes[NEXT + 3]);

	  if (Flags.mousewindow)
	    strcpy (NewToolTypes[NEXT + 4], ToolTypes[NEXT + 4]);
	  else
	    sprintf (NewToolTypes[NEXT + 4], "(%s)", ToolTypes[NEXT + 4]);

	  if (Flags.sysfont)
	    strcpy (NewToolTypes[NEXT + 5], ToolTypes[NEXT + 5]);
	  else
	    sprintf (NewToolTypes[NEXT + 5], "(%s)", ToolTypes[NEXT + 5]);

	  if (!Flags.saveasking)
	    strcpy (NewToolTypes[NEXT + 6], ToolTypes[NEXT + 6]);
	  else
	    sprintf (NewToolTypes[NEXT + 6], "(%s)", ToolTypes[NEXT + 6]);

	  if (!Flags.appicon)
	    strcpy (NewToolTypes[NEXT + 7], ToolTypes[NEXT + 7]);
	  else
	    sprintf (NewToolTypes[NEXT + 7], "(%s)", ToolTypes[NEXT + 7]);

	  if (bpc)
	    sprintf (NewToolTypes[NEXT + 8], "%s%ld", ToolTypes[NEXT + 8], bpc);
	  else
	    sprintf (NewToolTypes[NEXT + 8], "(%s)", ToolTypes[NEXT + 8]);

	  if (bgc)
	    sprintf (NewToolTypes[NEXT + 9], "%s%ld", ToolTypes[NEXT + 9], bgc);
	  else
	    sprintf (NewToolTypes[NEXT + 9], "(%s)", ToolTypes[NEXT + 9]);

	  if (bpp)
	    sprintf (NewToolTypes[NEXT + 10], "%s%08lX", ToolTypes[NEXT + 10], bpp);
	  else
	    sprintf (NewToolTypes[NEXT + 10], "(%s)", ToolTypes[NEXT + 10]);

	  if (winddetail)
	    sprintf (NewToolTypes[NEXT + 11], "%s%ld", ToolTypes[NEXT + 11], winddetail);
	  else
	    sprintf (NewToolTypes[NEXT + 11], "(%s)", ToolTypes[NEXT + 11]);

	  if (windblock)
	    sprintf (NewToolTypes[NEXT + 12], "%s%ld", ToolTypes[NEXT + 12], windblock);
	  else
	    sprintf (NewToolTypes[NEXT + 12], "(%s)", ToolTypes[NEXT + 12]);

	  if (menudetail)
	    sprintf (NewToolTypes[NEXT + 13], "%s%ld", ToolTypes[NEXT + 13], menudetail);
	  else
	    sprintf (NewToolTypes[NEXT + 13], "(%s)", ToolTypes[NEXT + 13]);

	  sprintf (NewToolTypes[NEXT + 14], "%s%s", ToolTypes[NEXT + 14], RSysFiles.Hardware);
	  sprintf (NewToolTypes[NEXT + 15], "%s%s", ToolTypes[NEXT + 15], RSysFiles.LibOffsets);
	  sprintf (NewToolTypes[NEXT + 16], "%s%s", ToolTypes[NEXT + 16], RSysFiles.Guide);
	  sprintf (NewToolTypes[NEXT + 17], "%s%s", ToolTypes[NEXT + 17], RSysFiles.GuideContext);
	  sprintf (NewToolTypes[NEXT + 18], "%s%s", ToolTypes[NEXT + 18], RSysFiles.ActionFile);
	  sprintf (NewToolTypes[NEXT + 19], "%s%s", ToolTypes[NEXT + 19], autocon);

	  sprintf (NewToolTypes[NEXT + 20], "%s%ld", ToolTypes[NEXT + 20], newlvh);

	  if (!Flags.textformat)
	    strcpy (NewToolTypes[NEXT + 21], ToolTypes[NEXT + 21]);
	  else
	    sprintf (NewToolTypes[NEXT + 21], "(%s)", ToolTypes[NEXT + 21]);

	  if (iconx != NO_ICON_POSITION)
	    sprintf (NewToolTypes[NEXT + 22], "%s%ld", ToolTypes[NEXT + 22], iconx);
	  else
	    sprintf (NewToolTypes[NEXT + 22], "(%s)", ToolTypes[NEXT + 22]);

	  if (icony != NO_ICON_POSITION)
	    sprintf (NewToolTypes[NEXT + 23], "%s%ld", ToolTypes[NEXT + 23], icony);
	  else
	    sprintf (NewToolTypes[NEXT + 23], "(%s)", ToolTypes[NEXT + 23]);

	  NewToolTypes[NEXT + 24] = NULL;

	  OldToolTypes = dop->do_ToolTypes;

	  dop->do_ToolTypes = NewToolTypes;

	  if (!PutDiskObject ((STRPTR) RSysName, dop))
	    ErrorHandle (RSysName, FILE_ERR, WRITE_FAIL, NO_KILL);
	  else
	    {
	      dop->do_ToolTypes = OldToolTypes;

	      FreeRemember (&ToolTypeKey, TRUE);

	      PrintInfo ("Info file written...", SPEAK, SEC);
	    }
	}
      else
	{
	  FreeDiskObject (dop);
	  FreeRemember (&ToolTypeKey, TRUE);
	  ErrorHandle ("AllocRemember()", MEMORY_ERR, ALLOC_FAIL, KILL);
	}

      FreeDiskObject (dop);
    }

  PrintStatistics ();

  return;
}

void
FreeValidAddressList (void)
{
  FreeRemember (VMKEY, TRUE);
  return;
}

RSYS_ValidMemoryNode *
CheckNode (ULONG memoryptr)
{
  NODE *node;
  RSYS_ValidMemoryNode *vmnode;

  for (node = ValidMemoryList.lh_Head; node->ln_Succ; node = node->ln_Succ)
    {
      vmnode = (RSYS_ValidMemoryNode *) node;
      if (vmnode->vm_startaddress <= memoryptr && memoryptr <= vmnode->vm_endaddress)
	return vmnode;
    }

  return NULL;
}

static int
MarkAddress (ULONG start, ULONG length, char type, char *comment)
{
  RSYS_ValidMemoryNode *VMNode;

  if (VMNode = ALLOCVM (sizeof (RSYS_ValidMemoryNode)))
    {
      VMNode->vm_node.ln_Type = NT_USER;
      VMNode->vm_node.ln_Pri = 0;

      VMNode->vm_startaddress = start;
      VMNode->vm_endaddress = start + length;
      VMNode->vm_type = type;

      strncpy (VMNode->vm_comment, comment, BUFSIZE);

      AddTail (&ValidMemoryList, &(VMNode->vm_node));

      return TRUE;
    }
  else
    ErrorHandle ("RSYS_ValidMemoryNode", MEMORY_ERR, ALLOC_FAIL, NO_KILL);

  return FALSE;
}

void
BuildValidAddressList (void)
{
  MEMHEADER *mem;
  int ok;

  NewList (&ValidMemoryList);

  /*
   * Special case the first page of CHIP RAM
   */
  ok = MarkAddress (0, 0x1000, (char) NULL, "First page CHIP-RAM");

  /*
   * Map in the free memory
   */
  Forbid ();

  mem = (MEMHEADER *) SysBase->MemList.lh_Head;
  while (mem->mh_Node.ln_Succ && ok)
    {
      ok = MarkAddress ((ULONG) (mem->mh_Lower),
			(ULONG) (mem->mh_Upper) - (ULONG) (mem->mh_Lower),
			((MEMF_CHIP & TypeOfMem (mem->mh_Lower)) ?
			 (char) (VALID) : (char) (CACHEABLE | VALID)),
			"Memory list entry");

      mem = ok ? (MEMHEADER *) (mem->mh_Node.ln_Succ) : NULL;
    }

  Permit ();

  /*
   * Map in the autoconfig boards
   */
  if (ok && (ExpansionBase = (EXPANSIONBASE *) OpenLibrary ((STRPTR) "expansion.library", 0)))
    {
      CONFIGDEV *cd = NULL;

      while ((cd = FindConfigDev (cd, (long) (-1L), (long) (-1L))) != NULL && ok)
	{
	  /* Skip memory boards... */
	  if (!(cd->cd_Rom.er_Type & ERTF_MEMLIST))
	    ok = MarkAddress ((ULONG) (cd->cd_BoardAddr),
			      cd->cd_BoardSize,
			      (char) VALID, "Expansion memory");
	}
      CloseLibrary ((LIBRARY *) ExpansionBase);
    }

  /*
   * Now for the control areas...
   */
  if (ok)
    ok = MarkAddress (0x00BC0000, 0x00040000, (char) VALID, "Control area 1");
  if (ok)
    ok = MarkAddress (0x00D80000, 0x00080000, (char) VALID, "Control area 2");

  /*
   * and the ROM...
   */
  if (ok)
    ok = MarkAddress (0x00F80000, 0x00080000,
		      (char) (CACHEABLE | WRITEPROTECT), "ROM-address");

  /*
   * If the credit card resource, make the addresses valid...
   */
  if (ok && OpenResource ((STRPTR) "card.resource"))
    ok = MarkAddress (0x00600000, 0x00440002, (char) VALID, "Card resource range");

  /*
   * If CD-based Amiga (CDTV, A570, etc.)
   */
  if (ok && FindResident ((STRPTR) "cdstrap"))
    {
      ok = MarkAddress (0x00E00000, 0x00080000, (char) VALID, "CDTV-RAM");
      if (ok)
	ok = MarkAddress (0x00B80000, 0x00040000, (char) VALID, "CDTV-RAM");
    }

  /*
   * Check for ReKick/ZKick/KickIt
   */
  if (ok && ((((ULONG) (SysBase->LibNode.lib_Node.ln_Name)) >> 16) == 0x20))
    ok = MarkAddress ((ULONG) 0x00200000, (ULONG) 0x00080000,
		      (char) (VALID | CACHEABLE | WRITEPROTECT),
		      "KickMem-range for ZKick");

  Flags.dummy4 = (ok ? 1 : 0);

  return;
}

void
BuildAllDataEntries (void)
{
  BuildActionList ();
  BuildHelpList ();
  BuildHardwareList ();
  BuildLibOffsetList ();

  return;
}
