/*
**	termConfig.c
**
**	Configuration processing routines
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#include "termGlobal.h"

	/* Reset routine function pointer. */

typedef VOID		(* RESET)(APTR,STRPTR);

	/* Local routines. */

STATIC BYTE		ReadSystemPrefs(STRPTR Name,ULONG ID,APTR Data,LONG Size,LONG Count);

STATIC VOID		ResetSerialConfig(struct SerialSettings *SerialConfig);
STATIC VOID		ResetModem(struct ModemSettings *ModemConfig);
STATIC VOID		ResetScreen(struct ScreenSettings *ScreenConfig);
STATIC VOID		ResetTerminal(struct TerminalSettings *TerminalConfig);
STATIC VOID		ResetEmulation(struct EmulationSettings *EmulationConfig);
STATIC VOID		ResetClip(struct ClipSettings *ClipConfig);
STATIC VOID		ResetCapture(struct CaptureSettings *CaptureConfig);
STATIC VOID		ResetFile(struct FileSettings *FileConfig,STRPTR PathBuffer);
STATIC VOID		ResetPath(struct PathSettings *PathConfig,STRPTR PathBuffer);
STATIC VOID		ResetMisc(struct MiscSettings *MiscConfig);
STATIC VOID		ResetCommand(struct CommandSettings *CommandConfig);
STATIC VOID		ResetTransfer(struct TransferSettings *TransferConfig,STRPTR DefaultLib);
STATIC VOID		ResetTranslationFile(STRPTR Arg,STRPTR PathBuffer);
STATIC VOID		ResetMacroFile(STRPTR Arg,STRPTR PathBuffer);
STATIC VOID		ResetCursorFile(STRPTR Arg,STRPTR PathBuffer);
STATIC VOID		ResetFastMacroFile(STRPTR Arg,STRPTR PathBuffer);

STATIC BYTE		WriteConfigChunk(struct IFFHandle *Handle,struct Configuration *Config,BYTE Type,APTR TempBuffer,STRPTR Password);
STATIC BYTE		WriteConfigChunks(struct IFFHandle *Handle,struct Configuration *Config,APTR TempBuffer,STRPTR Password);
STATIC UBYTE	IsConfigChunk(ULONG ID);
STATIC BYTE		ReadConfigChunk(struct IFFHandle *Handle,struct Configuration *Config,UBYTE Type,LONG Len,STRPTR Password);

STATIC UWORD SizeTable[] =
{
	sizeof(struct SerialSettings),
	sizeof(struct ModemSettings),
	sizeof(struct CommandSettings),
	sizeof(struct ScreenSettings),
	sizeof(struct TerminalSettings),
	sizeof(struct PathSettings),
	sizeof(struct MiscSettings),
	sizeof(struct ClipSettings),
	sizeof(struct CaptureSettings),
	sizeof(struct FileSettings),
	sizeof(struct EmulationSettings),
	sizeof(struct TransferSettings),
	MAX_FILENAME_LENGTH,				// Translation file name
	MAX_FILENAME_LENGTH,				// Macro file name
	MAX_FILENAME_LENGTH,				// Cursor file name
	MAX_FILENAME_LENGTH,				// Fast macro file name
};

STATIC RESET ResetTable[] =
{
	(RESET)ResetSerialConfig,
	(RESET)ResetModem,
	(RESET)ResetCommand,
	(RESET)ResetScreen,
	(RESET)ResetTerminal,
	ResetPath,
	(RESET)ResetMisc,
	(RESET)ResetClip,
	(RESET)ResetCapture,
	ResetFile,
	(RESET)ResetEmulation,
	ResetTransfer,
	(RESET)ResetTranslationFile,
	(RESET)ResetMacroFile,
	(RESET)ResetCursorFile,
	(RESET)ResetFastMacroFile
};

STATIC ULONG TypeTable[] =
{
	ID_SERL,
	ID_MODM,
	ID_COMD,
	ID_SCRN,
	ID_TRML,
	ID_PATH,
	ID_MISC,
	ID_CLIP,
	ID_CPTR,
	ID_FILE,
	ID_EMLN,
	ID_XFER,
	ID_XLNM,
	ID_MFNM,
	ID_CRNM,
	ID_FMNM
};

#define NUM_STOPS (sizeof(Stops) / (2 * sizeof(ULONG)))

STATIC LONG Stops[] =
{
	ID_TERM,ID_CAT,
	ID_TERM,ID_VERS,
	ID_TERM,ID_DIAL,
	ID_TERM,ID_DATE,
	ID_TERM,ID_PHON,
	ID_TERM,ID_PSWD,

	ID_TERM,ID_SERL,
	ID_TERM,ID_MODM,
	ID_TERM,ID_COMD,
	ID_TERM,ID_SCRN,
	ID_TERM,ID_TRML,
	ID_TERM,ID_PATH,
	ID_TERM,ID_MISC,
	ID_TERM,ID_CLIP,
	ID_TERM,ID_CPTR,
	ID_TERM,ID_FILE,
	ID_TERM,ID_EMLN,
	ID_TERM,ID_XFER,
	ID_TERM,ID_WINF,
	ID_TERM,ID_GRUP,
	ID_TERM,ID_XLNM,
	ID_TERM,ID_MFNM,
	ID_TERM,ID_CRNM,
	ID_TERM,ID_FMNM
};

STATIC BYTE						FontPrefsRead		= FALSE,
								FontPrefsReadFailed	= FALSE;
STATIC struct FontPrefs			FontPrefs[3];

STATIC BYTE						ScreenModePrefsRead			= FALSE,
								ScreenModePrefsReadFailed	= FALSE;
STATIC struct ScreenModePrefs	ScreenModePrefs;

enum	{	CR_IGNORE,CR_ASCR,CR_ASCRLF };
enum	{	LF_IGNORE,LF_ASLF,LF_ASLFCR };

VOID __regargs
FinalFix(struct Configuration *Config,BOOLEAN IsPhonebook,LONG Version,LONG Revision)
{
	if(Config)
	{
		if(Version < 4 || (Version == 4 && Revision < 3))
		{
			if(Config -> TransferConfig && Config -> MiscConfig)
			{
				Config -> TransferConfig -> OverridePath	= Config -> MiscConfig -> OverridePath;
				Config -> TransferConfig -> SetArchivedBit	= Config -> MiscConfig -> SetArchivedBit;
				Config -> TransferConfig -> IdentifyFiles	= Config -> MiscConfig -> IdentifyFiles;
				Config -> TransferConfig -> TransferIcons	= Config -> MiscConfig -> TransferIcons;
				Config -> TransferConfig -> PerfMeter		= Config -> MiscConfig -> PerfMeter;
				Config -> TransferConfig -> HideUploadIcon	= Config -> MiscConfig -> HideUploadIcon;
			}
		}

		if(Version < 4 || (Version == 4 && Revision < 4))
		{
			if(Config -> TerminalConfig && Config -> MiscConfig)
				Config -> MiscConfig -> AlertMode = Config -> TerminalConfig -> AlertMode;
		}
	}
}

VOID __regargs
FixOldConfig(struct Configuration *Config,UBYTE ConfigChunkType,BOOLEAN IsPhonebook,LONG Version,LONG Revision)
{
	if((Version == 3 && Revision < 6) || Version < 3)
	{
		if(ConfigChunkType == PREF_CLIP)
			Config -> ClipConfig -> ConvertLF = TRUE;

		if(ConfigChunkType == PREF_SERIAL)
			Config -> SerialConfig -> UseOwnDevUnit = TRUE;

		if(ConfigChunkType == PREF_MISC)
			Config -> MiscConfig -> ProtectiveMode = TRUE;

		if(ConfigChunkType == PREF_SCREEN)
		{
			Config -> ScreenConfig -> UsePens	= TRUE;
			Config -> ScreenConfig -> Depth		= 0;
			Config -> ScreenConfig -> PenColourMode	= 42;	// Avoid trouble
		}

		if(ConfigChunkType == PREF_TRANSFER)
		{
			WORD i;

			Config -> TransferConfig -> MangleFileNames = FALSE;

			if(Config -> TransferConfig -> ASCIIUploadLibrary[0])
				Config -> TransferConfig -> ASCIIUploadType = XFER_XPR;

			if(Config -> TransferConfig -> ASCIIDownloadLibrary[0])
				Config -> TransferConfig -> ASCIIDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> TextUploadLibrary[0])
				Config -> TransferConfig -> TextUploadType = XFER_XPR;

			if(Config -> TransferConfig -> TextDownloadLibrary[0])
				Config -> TransferConfig -> TextDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryUploadLibrary[0])
				Config -> TransferConfig -> BinaryUploadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryDownloadLibrary[0])
				Config -> TransferConfig -> BinaryDownloadType = XFER_XPR;

			for(i = 0 ; i < strlen(Config -> TransferConfig -> DefaultLibrary) - 6 ; i++)
			{
				if(!Strnicmp(&Config -> TransferConfig -> DefaultLibrary[i],"zmodem",6))
				{
					strcpy(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature,"*\030B01");

					Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Length = strlen(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature);

					break;
				}
			}
		}

		if(ConfigChunkType == PREF_MODEM)
			Config -> ModemConfig -> AbortHangsUp = FALSE;

		if(ConfigChunkType == PREF_COMMAND && IsPhonebook)
		{
			strcpy(Config -> CommandConfig -> LoginMacro,Config -> CommandConfig -> StartupMacro);

			memset(Config -> CommandConfig -> StartupMacro,0,sizeof(Config -> CommandConfig -> StartupMacro));
		}

		if(ConfigChunkType == PREF_CAPTURE)
			Config -> CaptureConfig -> SearchHistory = 10;

		if(ConfigChunkType == PREF_EMULATION)
		{
			if(Config -> EmulationConfig -> DestructiveBackspace < 0 || Config -> EmulationConfig -> DestructiveBackspace > 2)
				Config -> EmulationConfig -> DestructiveBackspace = 1;
		}
	}

	if((Version == 4 && Revision < 1) || Version < 4)
	{
		if(ConfigChunkType == PREF_CLIP)
			Config -> ClipConfig -> ConvertLF = TRUE;

		if(ConfigChunkType == PREF_SERIAL)
		{
			Config -> SerialConfig -> xONxOFF	= FALSE;
			Config -> SerialConfig -> PassThrough	= TRUE;
		}

		if(ConfigChunkType == PREF_MISC)
			Config -> MiscConfig -> ProtectiveMode = TRUE;

		if(ConfigChunkType == PREF_MODEM)
		{
			Config -> ModemConfig -> RedialDelay	= (Config -> ModemConfig -> RedialDelay / 6) * 60 + (Config -> ModemConfig -> RedialDelay % 6) * 10;
			Config -> ModemConfig -> TimeToConnect	= (Config -> ModemConfig -> TimeToConnect / 6) * 60 + (Config -> ModemConfig -> TimeToConnect % 6) * 10;
			Config -> ModemConfig -> VerboseDialing	= FALSE;
		}

		if(ConfigChunkType == PREF_TERMINAL)
		{
			switch(Config -> TerminalConfig -> SendCR)
			{
				case CR_IGNORE:

					Config -> TerminalConfig -> SendCR = EOL_IGNORE;
					break;

				case CR_ASCR:

					Config -> TerminalConfig -> SendCR = EOL_CR;
					break;

				case CR_ASCRLF:

					Config -> TerminalConfig -> SendCR = EOL_CRLF;
					break;
			}

			switch(Config -> TerminalConfig -> ReceiveCR)
			{
				case CR_IGNORE:

					Config -> TerminalConfig -> ReceiveCR = EOL_IGNORE;
					break;

				case CR_ASCR:

					Config -> TerminalConfig -> ReceiveCR = EOL_CR;
					break;

				case CR_ASCRLF:

					Config -> TerminalConfig -> ReceiveCR = EOL_CRLF;
					break;
			}

			switch(Config -> TerminalConfig -> SendLF)
			{
				case LF_IGNORE:

					Config -> TerminalConfig -> SendLF = EOL_IGNORE;
					break;

				case LF_ASLF:

					Config -> TerminalConfig -> SendLF = EOL_LF;
					break;

				case LF_ASLFCR:

					Config -> TerminalConfig -> SendLF = EOL_LFCR;
					break;
			}

			switch(Config -> TerminalConfig -> ReceiveLF)
			{
				case LF_IGNORE:

					Config -> TerminalConfig -> ReceiveLF = EOL_IGNORE;
					break;

				case LF_ASLF:

					Config -> TerminalConfig -> ReceiveLF = EOL_LF;
					break;

				case LF_ASLFCR:

					Config -> TerminalConfig -> ReceiveLF = EOL_LFCR;
					break;
			}
		}

		if(ConfigChunkType == PREF_TRANSFER)
		{
			WORD i;

			if(Config -> TransferConfig -> ASCIIUploadLibrary[0])
				Config -> TransferConfig -> ASCIIUploadType = XFER_XPR;

			if(Config -> TransferConfig -> ASCIIDownloadLibrary[0])
				Config -> TransferConfig -> ASCIIDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> TextUploadLibrary[0])
				Config -> TransferConfig -> TextUploadType = XFER_XPR;

			if(Config -> TransferConfig -> TextDownloadLibrary[0])
				Config -> TransferConfig -> TextDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryUploadLibrary[0])
				Config -> TransferConfig -> BinaryUploadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryDownloadLibrary[0])
				Config -> TransferConfig -> BinaryDownloadType = XFER_XPR;

			for(i = 0 ; i < strlen(Config -> TransferConfig -> DefaultLibrary) - 6 ; i++)
			{
				if(!Strnicmp(&Config -> TransferConfig -> DefaultLibrary[i],"zmodem",6))
				{
					strcpy(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature,"*\030B01");

					Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Length = strlen(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature);

					break;
				}
			}

			switch(Config -> TransferConfig -> SendCR)
			{
				case CR_IGNORE:

					Config -> TransferConfig -> SendCR = EOL_IGNORE;
					break;

				case CR_ASCR:

					Config -> TransferConfig -> SendCR = EOL_CR;
					break;

				case CR_ASCRLF:

					Config -> TransferConfig -> SendCR = EOL_CRLF;
					break;
			}

			switch(Config -> TransferConfig -> ReceiveCR)
			{
				case CR_IGNORE:

					Config -> TransferConfig -> ReceiveCR = EOL_IGNORE;
					break;

				case CR_ASCR:

					Config -> TransferConfig -> ReceiveCR = EOL_CR;
					break;

				case CR_ASCRLF:

					Config -> TransferConfig -> ReceiveCR = EOL_CRLF;
					break;
			}

			switch(Config -> TransferConfig -> SendLF)
			{
				case LF_IGNORE:

					Config -> TransferConfig -> SendLF = EOL_IGNORE;
					break;

				case LF_ASLF:

					Config -> TransferConfig -> SendLF = EOL_LF;
					break;

				case LF_ASLFCR:

					Config -> TransferConfig -> SendLF = EOL_LFCR;
					break;
			}

			switch(Config -> TransferConfig -> ReceiveLF)
			{
				case LF_IGNORE:

					Config -> TransferConfig -> ReceiveLF = EOL_IGNORE;
					break;

				case LF_ASLF:

					Config -> TransferConfig -> ReceiveLF = EOL_LF;
					break;

				case LF_ASLFCR:

					Config -> TransferConfig -> ReceiveLF = EOL_LFCR;
					break;
			}
		}
	}

	if(Version == 4 && Revision < 3)
	{
		if(ConfigChunkType == PREF_CLIP)
			Config -> ClipConfig -> ConvertLF = TRUE;

		if(ConfigChunkType == PREF_SERIAL)
		{
			Config -> SerialConfig -> xONxOFF	= FALSE;
			Config -> SerialConfig -> PassThrough	= TRUE;
		}

		if(ConfigChunkType == PREF_MISC)
			Config -> MiscConfig -> ProtectiveMode = TRUE;

		if(ConfigChunkType == PREF_TRANSFER)
		{
			WORD i;

			for(i = 0 ; i < strlen(Config -> TransferConfig -> DefaultLibrary) - 6 ; i++)
			{
				if(!Strnicmp(&Config -> TransferConfig -> DefaultLibrary[i],"zmodem",6))
				{
					strcpy(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature,"*\030B01");

					Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Length = strlen(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature);

					break;
				}
			}

			if(Config -> TransferConfig -> ASCIIUploadLibrary[0])
				Config -> TransferConfig -> ASCIIUploadType = XFER_XPR;

			if(Config -> TransferConfig -> ASCIIDownloadLibrary[0])
				Config -> TransferConfig -> ASCIIDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> InternalASCIIUpload)
				Config -> TransferConfig -> ASCIIUploadType = XFER_INTERNAL;

			if(Config -> TransferConfig -> InternalASCIIDownload)
				Config -> TransferConfig -> ASCIIDownloadType = XFER_INTERNAL;

			if(Config -> TransferConfig -> TextUploadLibrary[0])
				Config -> TransferConfig -> TextUploadType = XFER_XPR;

			if(Config -> TransferConfig -> TextDownloadLibrary[0])
				Config -> TransferConfig -> TextDownloadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryUploadLibrary[0])
				Config -> TransferConfig -> BinaryUploadType = XFER_XPR;

			if(Config -> TransferConfig -> BinaryDownloadLibrary[0])
				Config -> TransferConfig -> BinaryDownloadType = XFER_XPR;
		}
	}
}

VOID __regargs
FixScreenPens(struct ScreenSettings *ScreenConfig)
{
	WORD i,Count;

	for(Count = 0, i = DETAILPEN ; i <= BARTRIMPEN ; i++)
	{
		if(ScreenConfig -> PenArray[i])
			Count++;
	}

	if(!Count)
		ScreenConfig -> UsePens = TRUE;
}

	/* ReadSystemPrefs():
	 *
	 *	Reads the system preferences settings.
	 */

STATIC BYTE
ReadSystemPrefs(STRPTR Name,ULONG ID,APTR Data,LONG Size,LONG Count)
{
	struct IFFHandle	*Handle;
	BYTE				 Success = FALSE;
	LONG				 Error = 0;

		/* Allocate an IFF handle. */

	if(Handle = AllocIFF())
	{
			/* Open the preferences settings file. */

		if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
		{
				/* Make it known as a DOS file handle. */

			InitIFFasDOS(Handle);

				/* Open the file for reading. */

			if(!(Error = OpenIFF(Handle,IFFF_READ)))
			{
					/* Stop at the `body' chunk. */

				if(!(Error = StopChunk(Handle,ID_PREF,ID)))
				{
						/* Look for it... */

					while(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
							/* Read the data. */

						if(ReadChunkBytes(Handle,Data,Size) == Size)
						{
							Success = TRUE;

							if(Count)
							{
								Count--;

								Data = (APTR)((ULONG)Data + Size);
							}
							else
								break;
						}
						else
						{
							Error = IoErr();

							Success = FALSE;

							break;
						}
					}
				}

					/* Close the handle. */

				CloseIFF(Handle);
			}

				/* Release the handle. */

			Close(Handle -> iff_Stream);
		}
		else
			Error = IoErr();

			/* Clean up. */

		FreeIFF(Handle);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

		/* Return sucess/failure. */

	return(Success);
}

STATIC VOID
ResetSerialConfig(struct SerialSettings *SerialConfig)
{
	STATIC BYTE					SerialPrefsRead			= FALSE,
								SerialPrefsReadFailed	= FALSE;
	STATIC struct SerialPrefs	SerialPrefs;

	memset(SerialConfig,0,sizeof(*SerialConfig));

		/* The program will only try to read the preferences
		 * settings once; if the first access failed, no
		 * other accesses will be made.
		 */

	if(!SerialPrefsRead && !SerialPrefsReadFailed)
		SerialPrefsReadFailed = ReadSystemPrefs("ENV:sys/serial.prefs",ID_SERL,&SerialPrefs,sizeof(SerialPrefs),1) ^ TRUE;

		/* Did we succeed in reading the file? */

	if(!SerialPrefsRead)
	{
		SerialConfig -> BaudRate			= 19200;
		SerialConfig -> BitsPerChar			= 8;
		SerialConfig -> Parity				= PARITY_NONE;
		SerialConfig -> StopBits			= 1;
		SerialConfig -> HandshakingProtocol	= HANDSHAKING_RTSCTS_DSR;
		SerialConfig -> SerialBufferSize	= 32768;
	}
	else
	{
			/* Fill in the common data. */

		SerialConfig -> BaudRate			= SerialPrefs . sp_BaudRate;
		SerialConfig -> SerialBufferSize	= SerialPrefs . sp_InputBuffer;
		SerialConfig -> BitsPerChar			= SerialPrefs . sp_BitsPerChar;
		SerialConfig -> StopBits			= SerialPrefs . sp_StopBits;

			/* Convert the handshaking mode. */

		switch(SerialPrefs . sp_InputHandshake)
		{
			case HSHAKE_NONE:

				SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;

				break;

			case HSHAKE_RTS:

				SerialConfig -> HandshakingProtocol = HANDSHAKING_RTSCTS_DSR;

				break;

			default:

				SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;

				break;
		}

			/* Convert the parity settings. */

		if(SerialPrefs . sp_Parity <= PARITY_SPACE)
			SerialConfig -> Parity = SerialPrefs . sp_Parity;
		else
			SerialConfig -> Parity = PARITY_NONE;

		SerialPrefsRead = TRUE;
	}

	strcpy(SerialConfig -> SerialDevice,SERIALNAME);

	SerialConfig -> Duplex				= DUPLEX_FULL;
	SerialConfig -> HighSpeed			= FALSE;
	SerialConfig -> Shared				= FALSE;
	SerialConfig -> BreakLength			= 250000;
	SerialConfig -> UnitNumber			= 0;
	SerialConfig -> StripBit8			= FALSE;
	SerialConfig -> CheckCarrier		= FALSE;
	SerialConfig -> xONxOFF				= FALSE;
	SerialConfig -> PassThrough			= TRUE;
	SerialConfig -> IgnoreCarrier		= FALSE;

	SerialConfig -> Quantum				= 256;

	SerialConfig -> UseNet				= FALSE;
	SerialConfig -> NetID				= 0002;

	SerialConfig -> SatisfyODURequests	= ODU_RELEASE;

	SerialConfig -> LastVersionSaved	= 0;
	SerialConfig -> LastRevisionSaved	= 0;

	SerialConfig -> DirectConnection	= FALSE;

	SerialConfig -> ReleaseODUWhenOnline	= FALSE;
	SerialConfig -> ReleaseODUWhenDialing	= FALSE;
	SerialConfig -> NoODUIfShared			= FALSE;
	SerialConfig -> Pad						= 0;
}

STATIC VOID
ResetModem(struct ModemSettings *ModemConfig)
{
	memset(ModemConfig,0,sizeof(*ModemConfig));

	strcpy(ModemConfig -> ModemInit,	"ATE1V1Q0\\r");
	strcpy(ModemConfig -> ModemExit,	"");
	strcpy(ModemConfig -> ModemHangup,	"~~~~+++~~~~ATH0\\r");
	strcpy(ModemConfig -> DialPrefix,	"ATD\\w");
	strcpy(ModemConfig -> DialSuffix,	"\\r");

	strcpy(ModemConfig -> NoCarrier,	"NO CARRIER");
	strcpy(ModemConfig -> NoDialTone,	"NO DIALTONE");
	strcpy(ModemConfig -> Connect,		"CONNECT");
	strcpy(ModemConfig -> Voice,		"VOICE");
	strcpy(ModemConfig -> Ring,			"RING");
	strcpy(ModemConfig -> Busy,			"BUSY");
	strcpy(ModemConfig -> Ok,			"OK");
	strcpy(ModemConfig -> Error,		"ERROR");

	ModemConfig -> RedialDelay			= 20;
	ModemConfig -> DialRetries			= 10;
	ModemConfig -> DialTimeout			= 60;
	ModemConfig -> ConnectAutoBaud		= FALSE;
	ModemConfig -> DropDTR				= FALSE;
	ModemConfig -> RedialAfterHangup	= FALSE;

	ModemConfig -> NoCarrierIsBusy		= TRUE;

	ModemConfig -> ConnectLimit			= 0;
	ModemConfig -> ConnectLimitMacro[0]	= 0;

	ModemConfig -> TimeToConnect		= 0;

	ModemConfig -> VerboseDialing		= FALSE;

	ModemConfig -> DialMode						= DIALMODE_PULSE;
	ModemConfig -> DoNotSendMainModemCommands	= FALSE;

	ModemConfig -> InterDialDelay		= 0;
	ModemConfig -> CharSendDelay		= 0;

	strcpy(ModemConfig -> PBX_Prefix,	"0,,,");

	ModemConfig -> PBX_Mode				= FALSE;
	ModemConfig -> Pad					= 0;
}

STATIC VOID
ResetScreen(struct ScreenSettings *ScreenConfig)
{
	ULONG			 DisplayID;
	struct Screen	*PubScreen;

	memset(ScreenConfig,0,sizeof(struct ScreenSettings));

	if(!FontPrefsRead && !FontPrefsReadFailed)
		FontPrefsReadFailed = ReadSystemPrefs("ENV:sys/font.prefs",ID_FONT,FontPrefs,sizeof(struct FontPrefs),3) ^ TRUE;
/*
	if(!ScreenModePrefsRead && !ScreenModePrefsReadFailed)
		ScreenModePrefsReadFailed = ReadSystemPrefs("ENV:sys/screenmode.prefs",ID_SCRM,&ScreenModePrefs,sizeof(ScreenModePrefs),1) ^ TRUE;

	if(!ScreenModePrefsReadFailed)
	{
		DisplayID = ScreenModePrefs . smp_DisplayID;

		if(ModeNotAvailable(DisplayID))
			DisplayID = INVALID_ID;
	}
*/
	DisplayID = INVALID_ID;

	strcpy(ScreenConfig -> FontName,"topaz.font");
	ScreenConfig -> FontHeight = 8;

	if(!FontPrefsReadFailed)
	{
		LONG i;

		for(i = 0 ; i < 3 ; i++)
		{
			if(FontPrefs[i] . fp_Type == FP_SCREENFONT)
			{
				strcpy(ScreenConfig -> FontName,FontPrefs[i] . fp_Name);
				ScreenConfig -> FontHeight = FontPrefs[i] . fp_TextAttr . ta_YSize;

				break;
			}
		}
	}

	if(DisplayID == INVALID_ID)
	{
		if(PubScreen = LockPubScreen(NULL))
		{
			DisplayID = GetVPModeID(&PubScreen -> ViewPort);

			UnlockPubScreen(NULL,PubScreen);
		}
		else
			DisplayID = DEFAULT_MONITOR_ID | HIRESLACE_KEY;
	}

	ScreenConfig -> DisplayMode			= DisplayID;
	ScreenConfig -> ColourMode			= COLOUR_AMIGA;
	ScreenConfig -> MakeScreenPublic	= TRUE;
	ScreenConfig -> ShanghaiWindows		= FALSE;
	ScreenConfig -> TitleBar			= TRUE;
	ScreenConfig -> StatusLine			= STATUSLINE_STANDARD;
	ScreenConfig -> Blinking			= TRUE;
	ScreenConfig -> FasterLayout		= TRUE;
	ScreenConfig -> UseWorkbench		= FALSE;

	ScreenConfig -> PubScreenName[0]	= 0;
	ScreenConfig -> TimeMode			= ONLINETIME_BOTH;
	ScreenConfig -> UsePens				= TRUE;
	ScreenConfig -> PenColourMode		= COLOUR_AMIGA;

	ScreenConfig -> DisplayWidth		= 0;
	ScreenConfig -> DisplayHeight		= 0;
	ScreenConfig -> OverscanType		= OSCAN_TEXT;

	ScreenConfig -> ShareScreen			= FALSE;
	ScreenConfig -> SplitStatus			= FALSE;

	ScreenConfig -> UseColours96		= FALSE;
}

STATIC VOID
ResetTerminal(struct TerminalSettings *TerminalConfig)
{
	memset(TerminalConfig,0,sizeof(struct TerminalSettings));

	if(!FontPrefsRead && !FontPrefsReadFailed)
		FontPrefsReadFailed = ReadSystemPrefs("ENV:sys/font.prefs",ID_FONT,FontPrefs,sizeof(struct FontPrefs),3) ^ TRUE;

	strcpy(TerminalConfig -> TextFontName,"topaz.font");
	TerminalConfig -> TextFontHeight = 8;

	strcpy(TerminalConfig -> IBMFontName,"IBM.font");
	TerminalConfig -> IBMFontHeight = 8;

	if(!FontPrefsReadFailed)
	{
		LONG i;

		for(i = 0 ; i < 3 ; i++)
		{
			if(FontPrefs[i] . fp_Type == FP_SYSFONT)
			{
				strcpy(TerminalConfig -> TextFontName,FontPrefs[i] . fp_Name);
				TerminalConfig -> TextFontHeight = FontPrefs[i] . fp_TextAttr . ta_YSize;

				if(TerminalConfig -> TextFontHeight == 8 || TerminalConfig -> TextFontHeight == 11)
					TerminalConfig -> IBMFontHeight = TerminalConfig -> TextFontHeight;

				break;
			}
		}
	}

	TerminalConfig -> BellMode			= BELL_AUDIBLE;
	TerminalConfig -> AlertMode			= ALERT_BEEP_SCREEN;
	TerminalConfig -> EmulationMode		= EMULATION_ANSIVT100;
	TerminalConfig -> FontMode			= FONT_STANDARD;

	TerminalConfig -> SendCR			= EOL_CR;
	TerminalConfig -> SendLF			= EOL_LF;
	TerminalConfig -> ReceiveCR			= EOL_CR;
	TerminalConfig -> ReceiveLF			= EOL_LF;

	TerminalConfig -> NumColumns		= 0;
	TerminalConfig -> NumLines			= 0;

	TerminalConfig -> KeyMapFileName[0]		= 0;
	TerminalConfig -> EmulationFileName[0]	= 0;
	TerminalConfig -> BeepFileName[0]		= 0;

	TerminalConfig -> UseTerminalTask = FALSE;
	TerminalConfig -> Pad = 0;
}

STATIC VOID
ResetEmulation(struct EmulationSettings *EmulationConfig)
{
	WORD i;

	memset(EmulationConfig,0,sizeof(*EmulationConfig));

	EmulationConfig -> CursorMode		= KEYMODE_STANDARD;
	EmulationConfig -> NumericMode		= KEYMODE_STANDARD;

	EmulationConfig -> NewLineMode		= FALSE;
	EmulationConfig -> InsertMode		= FALSE;

	EmulationConfig -> LineWrap			= TRUE;
	EmulationConfig -> CursorWrap		= FALSE;

	EmulationConfig -> FontScale		= SCALE_NORMAL;
	EmulationConfig -> ScrollMode		= SCROLL_JUMP;
	EmulationConfig -> DestructiveBackspace	= FALSE;
	EmulationConfig -> SwapBSDelete		= FALSE;
	EmulationConfig -> PrinterEnabled	= TRUE;
	EmulationConfig -> AnswerBack[0]	= 0;
	EmulationConfig -> CLSResetsCursor	= 0;

	EmulationConfig -> KeysLocked		= FALSE;
	EmulationConfig -> MaxScroll		= 0;
	EmulationConfig -> MaxJump			= 1;
	EmulationConfig -> CursorLocked		= FALSE;
	EmulationConfig -> FontLocked		= FALSE;
	EmulationConfig -> LockWrapping		= FALSE;
	EmulationConfig -> LockStyle		= FALSE;
	EmulationConfig -> LockColour		= FALSE;

	EmulationConfig -> UseStandardPens	= TRUE;

	for(i = TEXTATTR_UNDERLINE ; i <= TEXTATTR_INVERSE ; i++)
		EmulationConfig -> Attributes[i] = i;

	for(i = 0 ; i < 16 ; i++)
		EmulationConfig -> Pens[i] = i;

	EmulationConfig -> TerminalType		= TERMINAL_VT200;
}

STATIC VOID
ResetClip(struct ClipSettings *ClipConfig)
{
	memset(ClipConfig,0,sizeof(*ClipConfig));

	ClipConfig -> ClipboardUnit	= 0;
	ClipConfig -> LineDelay		= 0;
	ClipConfig -> CharDelay		= 0;

	ClipConfig -> InsertPrefix[0] = 0;
	strcpy(ClipConfig -> InsertSuffix,"\\r");

	ClipConfig -> LinePrompt[0]	= 0;
	ClipConfig -> SendTimeout	= 0;
	ClipConfig -> PacingMode	= PACE_DIRECT;
	ClipConfig -> ConvertLF		= TRUE;
}

STATIC VOID
ResetCapture(struct CaptureSettings *CaptureConfig)
{
	memset(CaptureConfig,0,sizeof(*CaptureConfig));

	CaptureConfig -> LogActions			= FALSE;
	CaptureConfig -> LogCall			= FALSE;
	CaptureConfig -> LogFileName[0]		= 0;

	CaptureConfig -> MaxBufferSize		= 0;
	CaptureConfig -> BufferEnabled		= TRUE;

	CaptureConfig -> ConnectAutoCapture	= FALSE;
	CaptureConfig -> CaptureFilterMode	= FILTER_BOTH;
	CaptureConfig -> CapturePath[0]		= 0;

	CaptureConfig -> CallLogFileName[0]	= 0;
	CaptureConfig -> BufferPath[0]		= 0;

	CaptureConfig -> AutoCaptureDate	= AUTOCAPTURE_DATE_NAME;
	CaptureConfig -> SearchHistory		= 10;

	CaptureConfig -> OpenBufferWindow		= BUFFER_END;
	CaptureConfig -> OpenBufferScreen		= BUFFER_TOP;
	CaptureConfig -> BufferScreenPosition	= SCREEN_CENTRE;
	CaptureConfig -> BufferWidth			= 80;

	CaptureConfig -> RememberBufferWindow	= FALSE;
	CaptureConfig -> RememberBufferScreen	= FALSE;

	CaptureConfig -> BufferScreenMode		= INVALID_ID;

	CaptureConfig -> ConvertChars			= FALSE;
	CaptureConfig -> BufferMode				= BUFFERMODE_FLOW;
}

STATIC VOID
ResetTranslationFile(STRPTR Arg,STRPTR PathBuffer)
{
	memset(Arg,0,MAX_FILENAME_LENGTH);

	if(!PathBuffer)
		PathBuffer = "TERM:config";

	if(!LastTranslation[0])
	{
		strcpy(LastTranslation,PathBuffer);

		AddPart(LastTranslation,"translation.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(Arg,LastTranslation);
}

STATIC VOID
ResetMacroFile(STRPTR Arg,STRPTR PathBuffer)
{
	memset(Arg,0,MAX_FILENAME_LENGTH);

	if(!PathBuffer)
		PathBuffer = "TERM:config";

	if(!LastMacros[0])
	{
		strcpy(LastMacros,PathBuffer);

		AddPart(LastMacros,"functionkeys.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(Arg,LastMacros);
}

STATIC VOID
ResetCursorFile(STRPTR Arg,STRPTR PathBuffer)
{
	memset(Arg,0,MAX_FILENAME_LENGTH);

	if(!PathBuffer)
		PathBuffer = "TERM:config";

	if(!LastCursorKeys[0])
	{
		strcpy(LastCursorKeys,PathBuffer);

		AddPart(LastCursorKeys,"cursorkeys.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(Arg,LastCursorKeys);
}

STATIC VOID
ResetFastMacroFile(STRPTR Arg,STRPTR PathBuffer)
{
	memset(Arg,0,MAX_FILENAME_LENGTH);

	if(!PathBuffer)
		PathBuffer = "TERM:config";

	if(!LastFastMacros[0])
	{
		strcpy(LastFastMacros,PathBuffer);

		AddPart(LastFastMacros,"fastmacros.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(Arg,LastFastMacros);
}

STATIC VOID
ResetFile(struct FileSettings *FileConfig,STRPTR PathBuffer)
{
	if(FileConfig)
	{
		memset(FileConfig,0,sizeof(*FileConfig));

		if(!PathBuffer)
			PathBuffer = "TERM:config";

		strcpy(FileConfig -> ProtocolFileName,"xprzmodem.library");

		if(!LastTranslation[0])
		{
			strcpy(LastTranslation,PathBuffer);

			AddPart(LastTranslation,"translation.prefs",MAX_FILENAME_LENGTH);
		}

		strcpy(FileConfig -> TranslationFileName,LastTranslation);

		if(!LastMacros[0])
		{
			strcpy(LastMacros,PathBuffer);

			AddPart(LastMacros,"functionkeys.prefs",MAX_FILENAME_LENGTH);
		}

		strcpy(FileConfig -> MacroFileName,LastMacros);

		if(!LastFastMacros[0])
		{
			strcpy(LastFastMacros,PathBuffer);

			AddPart(LastFastMacros,"fastmacros.prefs",MAX_FILENAME_LENGTH);
		}

		strcpy(FileConfig -> FastMacroFileName,LastFastMacros);

		if(!LastCursorKeys[0])
		{
			strcpy(LastCursorKeys,PathBuffer);

			AddPart(LastCursorKeys,"cursorkeys.prefs",MAX_FILENAME_LENGTH);
		}

		strcpy(FileConfig -> CursorFileName,LastCursorKeys);
	}
}

STATIC VOID
ResetPath(struct PathSettings *PathConfig,STRPTR PathBuffer)
{
	memset(PathConfig,0,sizeof(*PathConfig));

	if(!PathBuffer)
		PathBuffer = "TERM:config";

	strcpy(PathConfig -> DefaultStorage,PathBuffer);

	PathConfig -> ASCIIUploadPath[0]	= 0;
	PathConfig -> ASCIIDownloadPath[0]	= 0;
	PathConfig -> TextUploadPath[0]		= 0;
	PathConfig -> TextDownloadPath[0]	= 0;
	PathConfig -> BinaryUploadPath[0]	= 0;
	PathConfig -> BinaryDownloadPath[0]	= 0;

	strcpy(PathConfig -> HelpFile,"PROGDIR:term.guide");

	strcpy(PathConfig -> DefaultStorage,PathBuffer);

	GetEnvDOS(PathConfig -> Editor,"EDITOR");
}

STATIC VOID
ResetMisc(struct MiscSettings *MiscConfig)
{
	memset(MiscConfig,0,sizeof(*MiscConfig));

	MiscConfig -> Priority				= 1;
	MiscConfig -> BackupConfig			= FALSE;

	MiscConfig -> OpenFastMacroPanel	= FALSE;
	MiscConfig -> ReleaseDevice			= TRUE;

	MiscConfig -> TransferServer		= TRUE;
	MiscConfig -> EmulationServer		= TRUE;

	MiscConfig -> OverridePath			= TRUE;
	MiscConfig -> AutoUpload			= TRUE;
	MiscConfig -> SetArchivedBit		= FALSE;
	MiscConfig -> IdentifyFiles			= IDENTIFY_FILETYPE;
	MiscConfig -> TransferIcons			= FALSE;
	MiscConfig -> CreateIcons			= FALSE;
	MiscConfig -> SimpleIO				= FALSE;
	MiscConfig -> PerfMeter				= FALSE;

	MiscConfig -> IOBufferSize			= 32768;
	MiscConfig -> HideUploadIcon		= FALSE;

	MiscConfig -> ProtectiveMode		= TRUE;

	MiscConfig -> AlertMode				= ALERT_BEEP_SCREEN;
	MiscConfig -> RequesterMode			= REQUESTERMODE_IGNORE;
	MiscConfig -> RequesterLeft			= 0;
	MiscConfig -> RequesterTop			= 0;
	MiscConfig -> RequesterWidth		= 0;
	MiscConfig -> RequesterHeight		= 0;
}

STATIC VOID
ResetCommand(struct CommandSettings *CommandConfig)
{
	memset(CommandConfig,0,sizeof(*CommandConfig));
/*
	CommandConfig -> StartupMacro[0]	= 0;
	CommandConfig -> LogoffMacro[0]		= 0;
	CommandConfig -> LoginMacro[0]		= 0;
	CommandConfig -> UploadMacro[0]		= 0;
	CommandConfig -> DownloadMacro[0]	= 0;
*/
}

STATIC VOID
ResetTransfer(struct TransferSettings *TransferConfig,STRPTR DefaultLib)
{
	WORD i;

	memset(TransferConfig,0,sizeof(*TransferConfig));

	if(!DefaultLib)
		strcpy(TransferConfig -> DefaultLibrary,"xprzmodem.library");
	else
		strcpy(TransferConfig -> DefaultLibrary,DefaultLib);

	for(i = 0 ; i < strlen(TransferConfig -> DefaultLibrary) - 6 ; i++)
	{
		if(!Strnicmp(&TransferConfig -> DefaultLibrary[i],"zmodem",6))
		{
			strcpy(TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature,"*\030B01");

			TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Length = strlen(TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD] . Signature);

			break;
		}
	}

	strcpy(TransferConfig -> ASCIIUploadLibrary,	"xprascii.library");
	strcpy(TransferConfig -> ASCIIDownloadLibrary,	"xprascii.library");

	TransferConfig -> TextUploadLibrary[0]		= 0;
	TransferConfig -> TextDownloadLibrary[0]	= 0;

	strcpy(TransferConfig -> BinaryUploadLibrary,"run hydracom device %p speed %b line %c nocarrier rec %> send %m");
	strcpy(TransferConfig -> BinaryDownloadLibrary,"run hydracom device %p speed %b line %c nocarrier rec %> get");

	TransferConfig -> InternalASCIIUpload		= FALSE;
	TransferConfig -> InternalASCIIDownload		= FALSE;
	TransferConfig -> QuietTransfer				= FALSE;
	TransferConfig -> MangleFileNames			= FALSE;

	TransferConfig -> LinePrompt[0]				= 0;
	TransferConfig -> SendTimeout				= 0;
	TransferConfig -> PacingMode				= PACE_DIRECT;
	TransferConfig -> StripBit8					= FALSE;
	TransferConfig -> IgnoreDataPastArnold		= TRUE;
	TransferConfig -> TerminatorChar			= 0x1A;
	TransferConfig -> SendCR					= EOL_CR;
	TransferConfig -> SendLF					= EOL_LF;
	TransferConfig -> ReceiveCR					= EOL_CR;
	TransferConfig -> ReceiveLF					= EOL_LF;

	TransferConfig -> ErrorNotification			= 20;
	TransferConfig -> TransferNotification		= XFERNOTIFY_ALWAYS;

	TransferConfig -> DefaultType				= XFER_XPR;
	TransferConfig -> ASCIIDownloadType			= XFER_XPR;
	TransferConfig -> ASCIIUploadType			= XFER_XPR;
	TransferConfig -> TextDownloadType			= XFER_DEFAULT;
	TransferConfig -> TextUploadType			= XFER_DEFAULT;
	TransferConfig -> BinaryDownloadType		= XFER_DEFAULT;
	TransferConfig -> BinaryUploadType			= XFER_DEFAULT;

	memset(TransferConfig -> Signatures,0,sizeof(TransferConfig -> Signatures));

	TransferConfig -> OverridePath				= TRUE;
	TransferConfig -> SetArchivedBit			= FALSE;
	TransferConfig -> IdentifyFiles				= IDENTIFY_FILETYPE;
	TransferConfig -> TransferIcons				= FALSE;
	TransferConfig -> PerfMeter					= FALSE;
	TransferConfig -> HideUploadIcon			= FALSE;
}

	/* ResetConfig():
	 *
	 *	Initialize configuration with default values.
	 */

VOID __regargs
ResetConfig(struct Configuration *Config,STRPTR PathBuffer)
{
	if(!PathBuffer)
		PathBuffer = "TERM:config";

	ResetPath(Config -> PathConfig,PathBuffer);
	ResetFile(Config -> FileConfig,PathBuffer);

	ResetSerialConfig(Config -> SerialConfig);
	ResetModem(Config -> ModemConfig);
	ResetScreen(Config -> ScreenConfig);
	ResetTerminal(Config -> TerminalConfig);
	ResetEmulation(Config -> EmulationConfig);
	ResetClip(Config -> ClipConfig);
	ResetCapture(Config -> CaptureConfig);
	ResetMisc(Config -> MiscConfig);
	ResetCommand(Config -> CommandConfig);
	ResetTransfer(Config -> TransferConfig,Config -> FileConfig ? Config -> FileConfig -> ProtocolFileName : (STRPTR)"xprzmodem.library");

	ResetTranslationFile(Config -> TranslationFileName,PathBuffer);
	ResetMacroFile(Config -> MacroFileName,PathBuffer);
	ResetCursorFile(Config -> CursorFileName,PathBuffer);
	ResetFastMacroFile(Config -> FastMacroFileName,PathBuffer);
}

VOID __regargs
DeleteConfigEntry(struct Configuration *Config,BYTE Type)
{
	if(Type == PREF_ALL)
	{
		for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
			DeleteConfigEntry(Config,Type);
	}
	else
	{
		switch(Type)
		{
			case PREF_SERIAL:

				if(Config -> SerialConfig)
				{
					FreeVecPooled(Config -> SerialConfig);

					Config -> SerialConfig = NULL;
				}

				break;

			case PREF_MODEM:

				if(Config -> ModemConfig)
				{
					FreeVecPooled(Config -> ModemConfig);

					Config -> ModemConfig = NULL;
				}

				break;

			case PREF_COMMAND:

				if(Config -> CommandConfig)
				{
					FreeVecPooled(Config -> CommandConfig);

					Config -> CommandConfig = NULL;
				}

				break;

			case PREF_SCREEN:

				if(Config -> ScreenConfig)
				{
					FreeVecPooled(Config -> ScreenConfig);

					Config -> ScreenConfig = NULL;
				}

				break;

			case PREF_TERMINAL:

				if(Config -> TerminalConfig)
				{
					FreeVecPooled(Config -> TerminalConfig);

					Config -> TerminalConfig = NULL;
				}

				break;

			case PREF_PATH:

				if(Config -> PathConfig)
				{
					FreeVecPooled(Config -> PathConfig);

					Config -> PathConfig = NULL;
				}

				break;

			case PREF_MISC:

				if(Config -> MiscConfig)
				{
					FreeVecPooled(Config -> MiscConfig);

					Config -> MiscConfig = NULL;
				}

				break;

			case PREF_CLIP:

				if(Config -> ClipConfig)
				{
					FreeVecPooled(Config -> ClipConfig);

					Config -> ClipConfig = NULL;
				}

				break;

			case PREF_CAPTURE:

				if(Config -> CaptureConfig)
				{
					FreeVecPooled(Config -> CaptureConfig);

					Config -> CaptureConfig = NULL;
				}

				break;

			case PREF_FILE:

				if(Config -> FileConfig)
				{
					FreeVecPooled(Config -> FileConfig);

					Config -> FileConfig = NULL;
				}

				break;

			case PREF_EMULATION:

				if(Config -> EmulationConfig)
				{
					FreeVecPooled(Config -> EmulationConfig);

					Config -> EmulationConfig = NULL;
				}

				break;

			case PREF_TRANSFER:

				if(Config -> TransferConfig)
				{
					FreeVecPooled(Config -> TransferConfig);

					Config -> TransferConfig = NULL;
				}

				break;

			case PREF_TRANSLATIONFILENAME:

				if(Config -> TranslationFileName)
				{
					FreeVecPooled(Config -> TranslationFileName);

					Config -> TranslationFileName = NULL;
				}

				break;

			case PREF_MACROFILENAME:

				if(Config -> MacroFileName)
				{
					FreeVecPooled(Config -> MacroFileName);

					Config -> MacroFileName = NULL;
				}

				break;

			case PREF_CURSORFILENAME:

				if(Config -> CursorFileName)
				{
					FreeVecPooled(Config -> CursorFileName);

					Config -> CursorFileName = NULL;
				}

				break;

			case PREF_FASTMACROFILENAME:

				if(Config -> FastMacroFileName)
				{
					FreeVecPooled(Config -> FastMacroFileName);

					Config -> FastMacroFileName = NULL;
				}

				break;
		}
	}
}

VOID __regargs
ResetConfigEntry(struct Configuration *Configuration,BYTE Type,BYTE Default)
{
	if(Type == PREF_ALL)
	{
		for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
			ResetConfigEntry(Configuration,Type,Default);
	}
	else
	{
		switch(Type)
		{
			case PREF_SERIAL:

				if(Default || !Config -> SerialConfig)
					ResetSerialConfig(Configuration -> SerialConfig);
				else
					memcpy(Configuration -> SerialConfig,Config -> SerialConfig,sizeof(struct SerialSettings));

				break;

			case PREF_MODEM:

				if(Default || !Config -> ModemConfig)
					ResetModem(Configuration -> ModemConfig);
				else
					memcpy(Configuration -> ModemConfig,Config -> ModemConfig,sizeof(struct ModemSettings));

				break;

			case PREF_COMMAND:

				if(Default || !Config -> CommandConfig)
					ResetCommand(Configuration -> CommandConfig);
				else
					memcpy(Configuration -> CommandConfig,Config -> CommandConfig,sizeof(struct CommandSettings));

				break;

			case PREF_SCREEN:

				if(Default || !Config -> ScreenConfig)
					ResetScreen(Configuration -> ScreenConfig);
				else
					memcpy(Configuration -> ScreenConfig,Config -> ScreenConfig,sizeof(struct ScreenSettings));

				FixScreenPens(Configuration -> ScreenConfig);

				break;

			case PREF_TERMINAL:

				if(Default || !Config -> TerminalConfig)
					ResetTerminal(Configuration -> TerminalConfig);
				else
					memcpy(Configuration -> TerminalConfig,Config -> TerminalConfig,sizeof(struct TerminalSettings));

				break;

			case PREF_PATH:

				if(Default || !Config -> PathConfig)
					ResetPath(Configuration -> PathConfig,NULL);
				else
					memcpy(Configuration -> PathConfig,Config -> PathConfig,sizeof(struct PathSettings));

				break;

			case PREF_MISC:

				if(Default || !Config -> MiscConfig)
					ResetMisc(Configuration -> MiscConfig);
				else
					memcpy(Configuration -> MiscConfig,Config -> MiscConfig,sizeof(struct MiscSettings));

				break;

			case PREF_CLIP:

				if(Default || !Config -> ClipConfig)
					ResetClip(Configuration -> ClipConfig);
				else
					memcpy(Configuration -> ClipConfig,Config -> ClipConfig,sizeof(struct ClipSettings));

				break;

			case PREF_CAPTURE:

				if(Default || !Config -> CaptureConfig)
					ResetCapture(Configuration -> CaptureConfig);
				else
					memcpy(Configuration -> CaptureConfig,Config -> CaptureConfig,sizeof(struct CaptureSettings));

				break;

			case PREF_FILE:

				if(Default || !Config -> FileConfig)
					ResetFile(Configuration -> FileConfig,NULL);
				else
				{
					if(Configuration -> FileConfig && Config -> FileConfig)
						memcpy(Configuration -> FileConfig,Config -> FileConfig,sizeof(struct FileSettings));
				}

				break;

			case PREF_EMULATION:

				if(Default || !Config -> EmulationConfig)
					ResetEmulation(Configuration -> EmulationConfig);
				else
					memcpy(Configuration -> EmulationConfig,Config -> EmulationConfig,sizeof(struct EmulationSettings));

				break;

			case PREF_TRANSFER:

				if(Default || !Config -> TransferConfig)
					ResetTransfer(Configuration -> TransferConfig,Config -> FileConfig -> ProtocolFileName);
				else
					memcpy(Configuration -> TransferConfig,Config -> TransferConfig,sizeof(struct TransferSettings));

				break;

			case PREF_TRANSLATIONFILENAME:

				if(Default || !Config -> TranslationFileName)
					ResetTranslationFile(Configuration -> TranslationFileName,NULL);
				else
					strcpy(Configuration -> TranslationFileName,Config -> TranslationFileName);

				break;

			case PREF_MACROFILENAME:

				if(Default || !Config -> MacroFileName)
					ResetMacroFile(Configuration -> MacroFileName,NULL);
				else
					strcpy(Configuration -> MacroFileName,Config -> MacroFileName);

				break;

			case PREF_CURSORFILENAME:

				if(Default || !Config -> CursorFileName)
					ResetMacroFile(Configuration -> CursorFileName,NULL);
				else
					strcpy(Configuration -> CursorFileName,Config -> CursorFileName);

				break;

			case PREF_FASTMACROFILENAME:

				if(Default || !Config -> FastMacroFileName)
					ResetMacroFile(Configuration -> FastMacroFileName,NULL);
				else
					strcpy(Configuration -> FastMacroFileName,Config -> FastMacroFileName);

				break;
		}
	}
}

APTR __regargs
GetConfigEntry(struct Configuration *Config,BYTE Type)
{
	switch(Type)
	{
		case PREF_SERIAL:

			return(Config -> SerialConfig);

		case PREF_MODEM:

			return(Config -> ModemConfig);

		case PREF_COMMAND:

			return(Config -> CommandConfig);

		case PREF_SCREEN:

			return(Config -> ScreenConfig);

		case PREF_TERMINAL:

			return(Config -> TerminalConfig);

		case PREF_PATH:

			return(Config -> PathConfig);

		case PREF_MISC:

			return(Config -> MiscConfig);

		case PREF_CLIP:

			return(Config -> ClipConfig);

		case PREF_CAPTURE:

			return(Config -> CaptureConfig);

		case PREF_FILE:

			return(Config -> FileConfig);

		case PREF_EMULATION:

			return(Config -> EmulationConfig);

		case PREF_TRANSFER:

			return(Config -> TransferConfig);

		case PREF_TRANSLATIONFILENAME:

			return(Config -> TranslationFileName);

		case PREF_MACROFILENAME:

			return(Config -> MacroFileName);

		case PREF_CURSORFILENAME:

			return(Config -> CursorFileName);

		case PREF_FASTMACROFILENAME:

			return(Config -> FastMacroFileName);

		default:

			return(NULL);
	}
}

BYTE __regargs
CreateConfigEntry(struct Configuration *Config,BYTE Type)
{
	if(Type == PREF_ALL)
	{
		for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
		{
			if(!CreateConfigEntry(Config,Type))
			{
				DeleteConfigEntry(Config,PREF_ALL);

				return(FALSE);
			}
		}

		return(TRUE);
	}
	else
	{
		APTR Data;

		switch(Type)
		{
			case PREF_SERIAL:

				Data = Config -> SerialConfig;
				break;

			case PREF_MODEM:

				Data = Config -> ModemConfig;
				break;

			case PREF_COMMAND:

				Data = Config -> CommandConfig;
				break;

			case PREF_SCREEN:

				Data = Config -> ScreenConfig;
				break;

			case PREF_TERMINAL:

				Data = Config -> TerminalConfig;
				break;

			case PREF_PATH:

				Data = Config -> PathConfig;
				break;

			case PREF_MISC:

				Data = Config -> MiscConfig;
				break;

			case PREF_CLIP:

				Data = Config -> ClipConfig;
				break;

			case PREF_CAPTURE:

				Data = Config -> CaptureConfig;
				break;

			case PREF_FILE:

				Data = Config -> FileConfig;
				break;

			case PREF_EMULATION:

				Data = Config -> EmulationConfig;
				break;

			case PREF_TRANSFER:

				Data = Config -> TransferConfig;
				break;

			case PREF_TRANSLATIONFILENAME:

				Data = Config -> TranslationFileName;
				break;

			case PREF_MACROFILENAME:

				Data = Config -> MacroFileName;
				break;

			case PREF_CURSORFILENAME:

				Data = Config -> CursorFileName;
				break;

			case PREF_FASTMACROFILENAME:

				Data = Config -> FastMacroFileName;
				break;

			default:

				return(FALSE);
		}

		if(!Data)
		{
			if(Data = AllocVecPooled(SizeTable[Type - 1],MEMF_ANY | MEMF_CLEAR))
			{
				(*ResetTable[Type - 1])(Data,NULL);

				switch(Type)
				{
					case PREF_SERIAL:

						Config -> SerialConfig		= Data;
						break;

					case PREF_MODEM:

						Config -> ModemConfig		= Data;
						break;

					case PREF_COMMAND:

						Config -> CommandConfig		= Data;
						break;

					case PREF_SCREEN:

						Config -> ScreenConfig		= Data;
						break;

					case PREF_TERMINAL:

						Config -> TerminalConfig	= Data;
						break;

					case PREF_PATH:

						Config -> PathConfig		= Data;
						break;

					case PREF_MISC:

						Config -> MiscConfig		= Data;
						break;

					case PREF_CLIP:

						Config -> ClipConfig		= Data;
						break;

					case PREF_CAPTURE:

						Config -> CaptureConfig		= Data;
						break;

					case PREF_FILE:

						Config -> FileConfig		= Data;
						break;

					case PREF_EMULATION:

						Config -> EmulationConfig	= Data;
						break;

					case PREF_TRANSFER:

						Config -> TransferConfig	= Data;
						break;

					case PREF_TRANSLATIONFILENAME:

						Config -> TranslationFileName	= Data;
						break;

					case PREF_MACROFILENAME:

						Config -> MacroFileName	= Data;
						break;

					case PREF_CURSORFILENAME:

						Config -> CursorFileName	= Data;
						break;

					case PREF_FASTMACROFILENAME:

						Config -> FastMacroFileName	= Data;
						break;
				}

				return(TRUE);
			}
			else
				return(FALSE);
		}
		else
			return(TRUE);
	}
}

VOID __regargs
DeleteConfiguration(struct Configuration *Config)
{
	if(Config)
	{
		DeleteConfigEntry(Config,PREF_ALL);

		FreeVecPooled(Config);
	}
}

struct Configuration * __regargs
CreateConfiguration(BYTE Fill)
{
	struct Configuration *Config;

	if(Config = (struct Configuration *)AllocVecPooled(sizeof(struct Configuration),MEMF_ANY | MEMF_CLEAR))
	{
		if(Fill)
		{
			if(!CreateConfigEntry(Config,PREF_ALL))
			{
				FreeVecPooled(Config);

				return(NULL);
			}
		}

		return(Config);
	}
	else
		return(NULL);
}

STATIC BYTE
WriteConfigChunk(struct IFFHandle *Handle,struct Configuration *Config,BYTE Type,APTR TempBuffer,STRPTR Password)
{
	APTR Data;

	switch(Type)
	{
		case PREF_SERIAL:

			Data = Config -> SerialConfig;
			break;

		case PREF_MODEM:

			Data = Config -> ModemConfig;
			break;

		case PREF_COMMAND:

			Data = Config -> CommandConfig;
			break;

		case PREF_SCREEN:

			Data = Config -> ScreenConfig;
			break;

		case PREF_TERMINAL:

			Data = Config -> TerminalConfig;
			break;

		case PREF_PATH:

			Data = Config -> PathConfig;
			break;

		case PREF_MISC:

			Data = Config -> MiscConfig;
			break;

		case PREF_CLIP:

			Data = Config -> ClipConfig;
			break;

		case PREF_CAPTURE:

			Data = Config -> CaptureConfig;
			break;

			// OBSOLETE!

		case PREF_FILE:

			return(TRUE);

//			Data = Config -> FileConfig;
//			break;

		case PREF_EMULATION:

			Data = Config -> EmulationConfig;
			break;

		case PREF_TRANSFER:

			Data = Config -> TransferConfig;
			break;

		case PREF_TRANSLATIONFILENAME:

			Data = Config -> TranslationFileName;
			break;

		case PREF_MACROFILENAME:

			Data = Config -> MacroFileName;
			break;

		case PREF_CURSORFILENAME:

			Data = Config -> CursorFileName;
			break;

		case PREF_FASTMACROFILENAME:

			Data = Config -> FastMacroFileName;
			break;

		default:

			Data = NULL;
			break;
	}

	if(Data)
	{
		if(TempBuffer)
		{
			Encrypt(Data,SizeTable[Type - 1],TempBuffer,Password,20);

			Data = TempBuffer;
		}

		if(!PushChunk(Handle,0,TypeTable[Type - 1],SizeTable[Type - 1]))
		{
			if(WriteChunkRecords(Handle,Data,SizeTable[Type - 1],1) == 1)
			{
				if(!PopChunk(Handle))
					return(TRUE);
			}
		}

		return(FALSE);
	}
	else
		return(TRUE);
}

STATIC UBYTE
IsConfigChunk(ULONG ID)
{
	UBYTE Type;

	for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
	{
		if(ID == TypeTable[Type - 1])
			return(Type);
	}

	return(0);
}

STATIC BYTE
WriteConfigChunks(struct IFFHandle *Handle,struct Configuration *Config,APTR TempBuffer,STRPTR Password)
{
	UBYTE Type;

	for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
	{
		if(!WriteConfigChunk(Handle,Config,Type,TempBuffer,Password))
			return(FALSE);
	}

	return(TRUE);
}

VOID __regargs
SaveConfig(const struct Configuration *Src,struct Configuration *Dst)
{
	if(Dst -> SerialConfig && Src -> SerialConfig)
		memcpy(Dst -> SerialConfig,Src -> SerialConfig,sizeof(struct SerialSettings));

	if(Dst -> ModemConfig && Src -> ModemConfig)
		memcpy(Dst -> ModemConfig,Src -> ModemConfig,sizeof(struct ModemSettings));

	if(Dst -> ScreenConfig && Src -> ScreenConfig)
	{
		memcpy(Dst -> ScreenConfig,Src -> ScreenConfig,sizeof(struct ScreenSettings));

		FixScreenPens(Dst -> ScreenConfig);
	}

	if(Dst -> TerminalConfig && Src -> TerminalConfig)
		memcpy(Dst -> TerminalConfig,Src -> TerminalConfig,sizeof(struct TerminalSettings));

	if(Dst -> EmulationConfig && Src -> EmulationConfig)
		memcpy(Dst -> EmulationConfig,Src -> EmulationConfig,sizeof(struct EmulationSettings));

	if(Dst -> ClipConfig && Src -> ClipConfig)
		memcpy(Dst -> ClipConfig,Src -> ClipConfig,sizeof(struct ClipSettings));

	if(Dst -> CaptureConfig && Src -> CaptureConfig)
		memcpy(Dst -> CaptureConfig,Src -> CaptureConfig,sizeof(struct CaptureSettings));

	if(Dst -> CommandConfig && Src -> CommandConfig)
		memcpy(Dst -> CommandConfig,Src -> CommandConfig,sizeof(struct CommandSettings));

	if(Dst -> MiscConfig && Src -> MiscConfig)
		memcpy(Dst -> MiscConfig,Src -> MiscConfig,sizeof(struct MiscSettings));

	if(Dst -> PathConfig && Src -> PathConfig)
		memcpy(Dst -> PathConfig,Src -> PathConfig,sizeof(struct PathSettings));

	if(Dst -> FileConfig && Src -> FileConfig)
		memcpy(Dst -> FileConfig,Src -> FileConfig,sizeof(struct FileSettings));

	if(Dst -> TransferConfig && Src -> TransferConfig)
		memcpy(Dst -> TransferConfig,Src -> TransferConfig,sizeof(struct TransferSettings));

	if(Dst -> TranslationFileName && Src -> TranslationFileName)
		strcpy(Dst -> TranslationFileName,Src -> TranslationFileName);

	if(Dst -> MacroFileName && Src -> MacroFileName)
		strcpy(Dst -> MacroFileName,Src -> MacroFileName);

	if(Dst -> CursorFileName && Src -> CursorFileName)
		strcpy(Dst -> CursorFileName,Src -> CursorFileName);

	if(Dst -> FastMacroFileName && Src -> FastMacroFileName)
		strcpy(Dst -> FastMacroFileName,Src -> FastMacroFileName);
}

VOID __regargs
UpdateConfig(const struct Configuration *Src,struct Configuration *Dst)
{
	if(Src -> SerialConfig)
		memcpy(Dst -> SerialConfig,Src -> SerialConfig,sizeof(struct SerialSettings));

	if(Src -> ModemConfig)
		memcpy(Dst -> ModemConfig,Src -> ModemConfig,sizeof(struct ModemSettings));

	if(Src -> ScreenConfig)
	{
		memcpy(Dst -> ScreenConfig,Src -> ScreenConfig,sizeof(struct ScreenSettings));

		FixScreenPens(Dst -> ScreenConfig);
	}

	if(Src -> TerminalConfig)
		memcpy(Dst -> TerminalConfig,Src -> TerminalConfig,sizeof(struct TerminalSettings));

	if(Src -> EmulationConfig)
		memcpy(Dst -> EmulationConfig,Src -> EmulationConfig,sizeof(struct EmulationSettings));

	if(Src -> ClipConfig)
		memcpy(Dst -> ClipConfig,Src -> ClipConfig,sizeof(struct ClipSettings));

	if(Src -> CaptureConfig)
		memcpy(Dst -> CaptureConfig,Src -> CaptureConfig,sizeof(struct CaptureSettings));

	if(Src -> CommandConfig)
		memcpy(Dst -> CommandConfig,Src -> CommandConfig,sizeof(struct CommandSettings));

	if(Src -> MiscConfig)
		memcpy(Dst -> MiscConfig,Src -> MiscConfig,sizeof(struct MiscSettings));

	if(Src -> PathConfig)
		memcpy(Dst -> PathConfig,Src -> PathConfig,sizeof(struct PathSettings));

	if(Src -> FileConfig && Dst -> FileConfig)
		memcpy(Dst -> FileConfig,Src -> FileConfig,sizeof(struct FileSettings));

	if(Src -> TransferConfig)
		memcpy(Dst -> TransferConfig,Src -> TransferConfig,sizeof(struct TransferSettings));

	if(Src -> TranslationFileName)
		strcpy(Dst -> TranslationFileName,Src -> TranslationFileName);

	if(Src -> MacroFileName)
		strcpy(Dst -> MacroFileName,Src -> MacroFileName);

	if(Src -> CursorFileName)
		strcpy(Dst -> CursorFileName,Src -> CursorFileName);

	if(Src -> FastMacroFileName)
		strcpy(Dst -> FastMacroFileName,Src -> FastMacroFileName);
}

VOID __regargs
SwapConfig(struct Configuration *Src,struct Configuration *Dst)
{
	if(Dst -> SerialConfig && Src -> SerialConfig)
		swmem(Dst -> SerialConfig,Src -> SerialConfig,sizeof(struct SerialSettings));

	if(Dst -> ModemConfig && Src -> ModemConfig)
		swmem(Dst -> ModemConfig,Src -> ModemConfig,sizeof(struct ModemSettings));

	if(Dst -> ScreenConfig && Src -> ScreenConfig)
		swmem(Dst -> ScreenConfig,Src -> ScreenConfig,sizeof(struct ScreenSettings));

	if(Dst -> TerminalConfig && Src -> TerminalConfig)
		swmem(Dst -> TerminalConfig,Src -> TerminalConfig,sizeof(struct TerminalSettings));

	if(Dst -> EmulationConfig && Src -> EmulationConfig)
		swmem(Dst -> EmulationConfig,Src -> EmulationConfig,sizeof(struct EmulationSettings));

	if(Dst -> ClipConfig && Src -> ClipConfig)
		swmem(Dst -> ClipConfig,Src -> ClipConfig,sizeof(struct ClipSettings));

	if(Dst -> CaptureConfig && Src -> CaptureConfig)
		swmem(Dst -> CaptureConfig,Src -> CaptureConfig,sizeof(struct CaptureSettings));

	if(Dst -> CommandConfig && Src -> CommandConfig)
		swmem(Dst -> CommandConfig,Src -> CommandConfig,sizeof(struct CommandSettings));

	if(Dst -> MiscConfig && Src -> MiscConfig)
		swmem(Dst -> MiscConfig,Src -> MiscConfig,sizeof(struct MiscSettings));

	if(Dst -> PathConfig && Src -> PathConfig)
		swmem(Dst -> PathConfig,Src -> PathConfig,sizeof(struct PathSettings));

	if(Dst -> TransferConfig && Src -> TransferConfig)
		swmem(Dst -> TransferConfig,Src -> TransferConfig,sizeof(struct TransferSettings));

	if(Dst -> FileConfig && Src -> FileConfig)
		swmem(Dst -> FileConfig,Src -> FileConfig,sizeof(struct FileSettings));

	if(Dst -> TranslationFileName && Src -> TranslationFileName)
		swmem(Dst -> TranslationFileName,Src -> TranslationFileName,MAX_FILENAME_LENGTH);

	if(Dst -> MacroFileName && Src -> MacroFileName)
		swmem(Dst -> MacroFileName,Src -> MacroFileName,MAX_FILENAME_LENGTH);

	if(Dst -> CursorFileName && Src -> CursorFileName)
		swmem(Dst -> CursorFileName,Src -> CursorFileName,MAX_FILENAME_LENGTH);

	if(Dst -> FastMacroFileName && Src -> FastMacroFileName)
		swmem(Dst -> FastMacroFileName,Src -> FastMacroFileName,MAX_FILENAME_LENGTH);
}

	/* SavePhonebook(STRPTR Name):
	 *
	 *	Save the current phone book to a disk file.
	 */

BYTE __regargs
SavePhonebook(STRPTR Name)
{
	struct IFFHandle	*Handle;
	BYTE				 Success = FALSE;
	LONG				 Error = 0;

	if(Phonebook && NumPhoneEntries)
	{
		if(Handle = (struct IFFHandle *)AllocIFF())
		{
			if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
			{
				InitIFFasDOS(Handle);

				if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
				{
					if(!(Error = PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN)))
					{
						if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
						{
							if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
							{
								struct TermInfo TermInfo;

								TermInfo . Version	= CONFIG_FILE_VERSION;
								TermInfo . Revision	= CONFIG_FILE_REVISION;

								if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1) == 1)
								{
									if(!(Error = PopChunk(Handle)))
									{
										STRPTR TempBuffer = NULL;

										if(PhonePasswordUsed)
										{
											if(!(Error = PushChunk(Handle,0,ID_PSWD,20)))
											{
												Success = TRUE;

												if(WriteChunkBytes(Handle,PhonePassword,20) != 20)
													Success = FALSE;

												if(PopChunk(Handle))
													Success = FALSE;

												if(Success)
												{
													LONG Max = sizeof(struct PhoneHeader),Type;

													for(Type = PREF_SERIAL ; Type <= PREF_FASTMACROFILENAME ; Type++)
													{
														if(SizeTable[Type - 1] > Max)
															Max = SizeTable[Type - 1];
													}

													if(!(TempBuffer = AllocVecPooled(Max,MEMF_ANY)))
													{
														Error = ERR_NO_MEM;

														Success = FALSE;
													}
												}
											}
										}
										else
											Success = TRUE;

										if(Success)
										{
											Success = FALSE;

											if(!(Error = PushChunk(Handle,0,ID_DIAL,IFFSIZE_UNKNOWN)))
											{
												PhonebookGlobals Globals;

												Globals . Count			= NumPhoneEntries;
												Globals . ID			= PhonebookID;
												Globals . DefaultGroup	= PhonebookDefaultGroup;
												Globals . AutoDial		= PhonebookAutoDial;
												Globals . AutoExit		= PhonebookAutoExit;

												if(WriteChunkBytes(Handle,&Globals,sizeof(Globals)) == sizeof(Globals))
												{
													if(!(Error = PopChunk(Handle)))
													{
														if(!(Error = PopChunk(Handle)))
														{
															LONG i;

															Success = TRUE;

															for(i = 0 ; Success && i < NumPhoneEntries ; i++)
															{
																Success = FALSE;

																if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
																{
																	if(!(Error = PushChunk(Handle,0,ID_PHON,sizeof(struct PhoneHeader))))
																	{
																		if(TempBuffer)
																		{
																			Encrypt((UBYTE *)Phonebook[i] -> Header,sizeof(struct PhoneHeader),TempBuffer,PhonePassword,20);

																			if(WriteChunkRecords(Handle,TempBuffer,sizeof(struct PhoneHeader),1) == 1)
																			{
																				if(!(Error = PopChunk(Handle)))
																				{
																					if(WriteConfigChunks(Handle,Phonebook[i] -> Config,TempBuffer,PhonePassword))
																					{
																						Success = TRUE;

																						if(!Phonebook[i] -> Header -> NoRates)
																						{
																							struct TimeDateNode *TimeDateNode;

																							TimeDateNode = (struct TimeDateNode *)Phonebook[i] -> TimeDateList . mlh_Head;

																							while(TimeDateNode -> VanillaNode . ln_Succ)
																							{
																								if(!(Error = PushChunk(Handle,0,ID_DATE,IFFSIZE_UNKNOWN)))
																								{
																									if(WriteChunkBytes(Handle,&TimeDateNode -> Header,sizeof(struct TimeDateHeader)) != sizeof(struct TimeDateHeader))
																									{
																										Error = IoErr();

																										Success = FALSE;

																										break;
																									}
																									else
																									{
																										if(WriteChunkBytes(Handle,TimeDateNode -> Table,TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate)) != TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate))
																										{
																											Error = IoErr();

																											Success = FALSE;

																											break;
																										}
																									}

																									if(Success)
																									{
																										if(Error = PopChunk(Handle))
																										{
																											Success = FALSE;

																											break;
																										}
																									}

																									TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
																								}
																							}
																						}
																					}
																					else
																					{
																						Error = IoErr();

																						Success = FALSE;
																					}
																				}
																			}
																			else
																				Error = IoErr();
																		}
																		else
																		{
																			if(WriteChunkRecords(Handle,Phonebook[i] -> Header,sizeof(struct PhoneHeader),1) == 1)
																			{
																				if(!(Error = PopChunk(Handle)))
																				{
																					if(WriteConfigChunks(Handle,Phonebook[i] -> Config,NULL,NULL))
																					{
																						Success = TRUE;

																						if(!Phonebook[i] -> Header -> NoRates)
																						{
																							struct TimeDateNode *TimeDateNode;

																							TimeDateNode = (struct TimeDateNode *)Phonebook[i] -> TimeDateList . mlh_Head;

																							while(TimeDateNode -> VanillaNode . ln_Succ)
																							{
																								if(!(Error = PushChunk(Handle,0,ID_DATE,IFFSIZE_UNKNOWN)))
																								{
																									if(WriteChunkBytes(Handle,&TimeDateNode -> Header,sizeof(struct TimeDateHeader)) != sizeof(struct TimeDateHeader))
																									{
																										Error = IoErr();

																										Success = FALSE;

																										break;
																									}
																									else
																									{
																										if(WriteChunkBytes(Handle,TimeDateNode -> Table,TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate)) != TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate))
																										{
																											Error = IoErr();

																											Success = FALSE;

																											break;
																										}
																									}

																									if(Success)
																									{
																										if(Error = PopChunk(Handle))
																										{
																											Success = FALSE;

																											break;
																										}
																									}

																									TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
																								}
																							}
																						}
																					}
																					else
																					{
																						Success = FALSE;

																						Error = IoErr();
																					}
																				}
																			}
																			else
																				Error = IoErr();
																		}
																	}

																	if(Success)
																	{
																		if(Error = PopChunk(Handle))
																			Success = FALSE;
																	}
																}
															}

																// Now for the groups

															if(Success && PhoneGroupList . mlh_Head -> mln_Succ)
															{
																struct PhoneGroupNode	*GroupNode;
																struct PhoneNode		*Node;
																PhoneGroupHeader		 Header;
																BOOL					 GotData = FALSE;

																	// So the extension stuff is set to zero

																memset(&Header,0,sizeof(Header));

																	// Run down the groups

																for(GroupNode = (PhoneGroupNode *)PhoneGroupList . mlh_Head ; Success && GroupNode -> Node . ln_Succ ; GroupNode = (PhoneGroupNode *)GroupNode -> Node . ln_Succ)
																{
																		// Count the members

																	Header . Count = 0;

																	for(Node = (struct PhoneNode *)GroupNode -> GroupList . mlh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
																		Header . Count++;

																		// Open the group

																	if(Header . Count)
																	{
																		if(!GotData)
																		{
																			if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
																				GotData = TRUE;
																		}

																			// Pick up the group name

																		strcpy(Header . FullName,GroupNode -> LocalName);

																		if(!Error)
																			Error = PushChunk(Handle,0,ID_GRUP,sizeof(Header) + sizeof(LONG) * Header . Count);

																		if(!Error)
																		{
																				// First the header...

																			if(WriteChunkBytes(Handle,&Header,sizeof(Header)) == sizeof(Header))
																			{
																					// ...then the IDs of the group members

																				for(Node = (struct PhoneNode *)GroupNode -> GroupList . mlh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
																				{
																					if(WriteChunkBytes(Handle,&Node -> Entry -> Header -> ID,sizeof(ULONG)) != sizeof(ULONG))
																					{
																						Success = FALSE;
																						break;
																					}
																				}

																				if(!Success)
																				{
																					Error = IoErr();
																					break;
																				}
																			}
																			else
																			{
																				Error = IoErr();
																				Success = FALSE;
																				break;
																			}

																			if(Error = PopChunk(Handle))
																				Success = FALSE;
																		}
																		else
																			Success = FALSE;
																	}
																}

																if(Success && GotData)
																{
																	if(Error = PopChunk(Handle))
																		Success = FALSE;
																}
															}
														}
													}
												}
												else
													Error = IoErr();
											}
										}

										if(TempBuffer)
											FreeVecPooled(TempBuffer);
									}
								}
								else
									Error = IoErr();
							}
						}

						if(Success)
						{
							if(Error = PopChunk(Handle))
								Success = FALSE;
						}
					}

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}
			else
				Error = IoErr();

			FreeIFF(Handle);
		}
		else
			Error = ERR_NO_MEM;

		if(Success)
			AddProtection(Name,FIBF_EXECUTE);
		else
			DeleteFile(Name);
	}

	if(Error)
		SetIoErr(Error);

	return(Success);
}

STATIC BYTE
ReadConfigChunk(struct IFFHandle *Handle,struct Configuration *Config,UBYTE Type,LONG Len,STRPTR Password)
{
	if(CreateConfigEntry(Config,Type))
	{
		APTR Data;

		switch(Type)
		{
			case PREF_SERIAL:

				Data = Config -> SerialConfig;
				break;

			case PREF_MODEM:

				Data = Config -> ModemConfig;
				break;

			case PREF_COMMAND:

				Data = Config -> CommandConfig;
				break;

			case PREF_SCREEN:

				Data = Config -> ScreenConfig;
				break;

			case PREF_TERMINAL:

				Data = Config -> TerminalConfig;
				break;

			case PREF_PATH:

				Data = Config -> PathConfig;
				break;

			case PREF_MISC:

				Data = Config -> MiscConfig;
				break;

			case PREF_CLIP:

				Data = Config -> ClipConfig;
				break;

			case PREF_CAPTURE:

				Data = Config -> CaptureConfig;
				break;

			case PREF_FILE:

				Data = Config -> FileConfig;
				break;

			case PREF_EMULATION:

				Data = Config -> EmulationConfig;
				break;

			case PREF_TRANSFER:

				Data = Config -> TransferConfig;
				break;

			case PREF_TRANSLATIONFILENAME:

				Data = Config -> TranslationFileName;
				break;

			case PREF_MACROFILENAME:

				Data = Config -> MacroFileName;
				break;

			case PREF_CURSORFILENAME:

				Data = Config -> CursorFileName;
				break;

			case PREF_FASTMACROFILENAME:

				Data = Config -> FastMacroFileName;
				break;
		}

		Len = MIN(SizeTable[Type - 1],Len);

		if(ReadChunkBytes(Handle,Data,Len) == Len)
		{
			if(Password)
				Decrypt(Data,Len,Data,Password,20);

			if(Type == PREF_SCREEN)
				FixScreenPens(Data);

			return(TRUE);
		}
	}

	return(FALSE);
}

	/* LoadPhonebook(STRPTR Name):
	 *
	 *	Restore a phone book from a disk file.
	 */

BYTE __regargs
LoadPhonebook(STRPTR Name,PhonebookHandle *BookHandle)
{
	struct PhoneEntry	**PrivatePhonebook;
	LONG				 PrivatePhoneSize	= 0,
						 CurrentPhoneSize	= 0,
						 Count				= 0,
						 Index				= 0;
	BYTE				 Success			= FALSE,
						 LastHadTime		= TRUE,
						 UsePhonePassword	= FALSE,
						 FirstChunk			= TRUE,
						 UseOld				= FALSE;
	struct IFFHandle	*Handle;
	struct ContextNode	*Chunk;
	struct TimeDateNode	*TimeDateNode;
	UBYTE				 ConfigChunkType,
						 PasswordBuffer[20];
	BYTE				 CheckedChunk = FALSE;
	LONG				 Error = 0;
	PhonebookGlobals	 Globals;
	struct timeval		 Now;
	ULONG				 PrivatePhonebookID;
	struct MinList		 LocalPhoneGroupList;
	BOOL				 GotID = FALSE;

	NewList((struct List *)&LocalPhoneGroupList);

	GetSysTime(&Now);

	memset(&Globals,0,sizeof(Globals));

	Globals . ID			= Now . tv_secs;
	Globals . DefaultGroup	= 0;
	Globals . AutoDial		= 0;
	Globals . AutoExit		= 0;

	if(Handle = AllocIFF())
	{
		if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
		{
			InitIFFasDOS(Handle);

			if(!(Error = OpenIFF(Handle,IFFF_READ)))
			{
				if(!(Error = StopChunks(Handle,Stops,NUM_STOPS)))
				{
					struct TermInfo TermInfo;

					while(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
						Chunk = CurrentChunk(Handle);

							/* Is this the first chunk to be read? */

						if(!CheckedChunk)
						{
								/* The first chunk must be a
								 * catalog chunk, or this is
								 * not a proper phonebook file.
								 */

							if(Chunk -> cn_ID != ID_CAT)
								break;
							else
								CheckedChunk = TRUE;
						}

						if(Chunk -> cn_ID == ID_VERS)
						{
							if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if(TermInfo . Version != CONFIG_FILE_VERSION || (TermInfo . Version == CONFIG_FILE_VERSION && TermInfo . Revision > CONFIG_FILE_REVISION))
								{
									if(TermInfo . Version == 2 && TermInfo . Revision == 4)
										UseOld = TRUE;

									if(TermInfo . Version != 3)
										break;
								}
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

						if(Chunk -> cn_ID == ID_PSWD)
						{
							if(ReadChunkBytes(Handle,PasswordBuffer,20) == 20)
							{
								if(BookHandle)
								{
									if(BookHandle -> PhonePasswordUsed)
									{
										if(!memcmp(BookHandle -> PhonePassword,PasswordBuffer,20))
										{
											UsePhonePassword = TRUE;

											continue;
										}
									}
								}
								else
								{
									if(PhonePasswordUsed)
									{
										if(!memcmp(PhonePassword,PasswordBuffer,20))
										{
											UsePhonePassword = TRUE;

											continue;
										}
									}
								}

								memset(SharedBuffer,0,21);

								if(GetString(FALSE,TRUE,21,LocaleString(MSG_PHONEPANEL_PLEASE_ENTER_PASSWORD_TXT),SharedBuffer))
								{
									UBYTE AnotherBuffer[20];

									Encrypt(SharedBuffer,20,AnotherBuffer,SharedBuffer,strlen(SharedBuffer));

									if(!memcmp(PasswordBuffer,AnotherBuffer,20))
									{
										UsePhonePassword = TRUE;

										continue;
									}
									else
									{
										MyEasyRequest(Window,LocaleString(MSG_TERMPHONE_WRONG_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Name);

										break;
									}
								}
								else
									break;
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

						if(Chunk -> cn_ID == ID_DIAL)
						{
							WORD Size = MIN(sizeof(PhonebookGlobals),Chunk -> cn_Size);

							if(ReadChunkBytes(Handle,&Globals,Size) == Size)
							{
								CurrentPhoneSize = Globals . Count;

								if(Size >= sizeof(PhonebookGlobals))
									GotID = TRUE;

								PrivatePhonebookID = Globals . ID;

								if(!CurrentPhoneSize)
									break;
								else
								{
									if(!(PrivatePhonebook = CreatePhonebook(CurrentPhoneSize,&PrivatePhoneSize,TRUE)))
									{
										Error = ERR_NO_MEM;

										break;
									}
								}
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

						if(Chunk -> cn_ID == ID_PHON)
						{
							WORD Size = MIN(sizeof(struct PhoneHeader),Chunk -> cn_Size);

							if(!CurrentPhoneSize)
								break;

							if(!LastHadTime)
							{
								if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
									AddTail((struct List *)&PrivatePhonebook[Index] -> TimeDateList,&TimeDateNode -> VanillaNode);
							}

							if(!FirstChunk)
								Index++;
							else
								FirstChunk = FALSE;

							memset(PrivatePhonebook[Index] -> Header,0,sizeof(struct PhoneHeader));

							if(ReadChunkBytes(Handle,PrivatePhonebook[Index] -> Header,Size) == Size)
							{
								if(UsePhonePassword)
									Decrypt((UBYTE *)PrivatePhonebook[Index] -> Header,Size,(UBYTE *)PrivatePhonebook[Index] -> Header,PasswordBuffer,20);

								PrivatePhonebook[Index] -> Count = -1;

								if(!GotID)
									PrivatePhonebook[Index] -> Header -> ID = PrivatePhonebookID++;

								LastHadTime = FALSE;

								Count++;
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

							// Mucho importante -- must follow the phonebook entries

						if(Chunk -> cn_ID == ID_GRUP)
						{
							PhoneGroupHeader	 Header;
							struct MinList		*GroupList;

							DB(kprintf("--> ID_GRUP\n"));

							if(BookHandle)
								GroupList = BookHandle -> PhoneGroupList;
							else
								GroupList = &LocalPhoneGroupList;

							if(GroupList)
							{
								if(ReadChunkBytes(Handle,&Header,sizeof(Header)) == sizeof(Header))
								{
									PhoneGroupNode	*GroupNode;
									ULONG			 ID;
									LONG			 i;

									GroupNode = NULL;

									Success = TRUE;

									DB(kprintf("group name |%s| entries %ld\n",Header . FullName,Header . Count));

									for(i = 0 ; Success && i < Header . Count ; i++)
									{
										if(ReadChunkBytes(Handle,&ID,sizeof(ULONG)) == sizeof(ULONG))
										{
											struct PhoneNode	*Node;
											LONG				 j;

											DB(kprintf("looking for 0x%08lx\n",ID));

											for(j = 0 ; j < CurrentPhoneSize ; j++)
											{
												if(PrivatePhonebook[j] -> Header -> ID == ID)
												{
													DB(kprintf("found it |%s|\n",PrivatePhonebook[j] -> Header -> Name));

													if(!GroupNode)
													{
														if(!(GroupNode = (PhoneGroupNode *)AllocVecPooled(sizeof(PhoneGroupNode),MEMF_ANY | MEMF_CLEAR)))
														{
															Error = ERROR_NO_FREE_STORE;

															Success = FALSE;

															break;
														}

														strcpy(GroupNode -> LocalName,Header . FullName);

														GroupNode -> Node . ln_Name = GroupNode -> LocalName;

														NewList((struct List *)&GroupNode -> GroupList);

														AddTail((struct List *)&LocalPhoneGroupList,(struct Node *)GroupNode);
													}

													if(Node = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
													{
														PrivatePhonebook[j] -> ThisGroup	= GroupNode;
														PrivatePhonebook[j] -> NodeGroup	= Node;

														Node -> VanillaNode . ln_Name	= Node -> LocalName;
														Node -> Entry					= PrivatePhonebook[j];

														SPrintf(Node -> LocalName,"      %s",PrivatePhonebook[j] -> Header -> Name);

														AddTail((struct List *)&GroupNode -> GroupList,(struct Node *)Node);
													}
													else
													{
														Error = ERROR_NO_FREE_STORE;

														Success = FALSE;

														break;
													}
												}
											}
										}
										else
										{
											Error = IoErr();

											Success = FALSE;

											break;
										}
									}
								}
								else
								{
									Error = IoErr();

									Success = FALSE;
								}
							}

							if(!Success)
								break;
						}

						if(ConfigChunkType = IsConfigChunk(Chunk -> cn_ID))
						{
							if(!CurrentPhoneSize)
								break;

							if(UsePhonePassword)
							{
								if(!ReadConfigChunk(Handle,PrivatePhonebook[Index] -> Config,ConfigChunkType,Chunk -> cn_Size,PasswordBuffer))
								{
									if(Count)
										CurrentPhoneSize = Count - 1;
									else
										CurrentPhoneSize = 0;

									break;
								}
								else
									FixOldConfig(PrivatePhonebook[Index] -> Config,ConfigChunkType,TRUE,TermInfo . Version,TermInfo . Revision);
							}
							else
							{
								if(!ReadConfigChunk(Handle,PrivatePhonebook[Index] -> Config,ConfigChunkType,Chunk -> cn_Size,NULL))
								{
									if(Count)
										CurrentPhoneSize = Count - 1;
									else
										CurrentPhoneSize = 0;

									break;
								}
								else
									FixOldConfig(PrivatePhonebook[Index] -> Config,ConfigChunkType,TRUE,TermInfo . Version,TermInfo . Revision);
							}
						}

							// Special treatment for obsolete "FILE" chunk

						if(Chunk -> cn_ID == ID_FILE)
						{
							struct Configuration *Config = PrivatePhonebook[Index] -> Config;
							LONG i;

							for(i = PREF_TRANSLATIONFILENAME ; i <= PREF_FASTMACROFILENAME ; i++)
							{
								if(!CreateConfigEntry(Config,i))
								{
									Error = ERROR_NO_FREE_STORE;
									break;
								}
							}

							if(!Error)
							{
								strcpy(Config -> TranslationFileName,	Config -> FileConfig -> TranslationFileName);
								strcpy(Config -> MacroFileName,			Config -> FileConfig -> MacroFileName);
								strcpy(Config -> CursorFileName,		Config -> FileConfig -> CursorFileName);
								strcpy(Config -> FastMacroFileName,		Config -> FileConfig -> FastMacroFileName);

								DeleteConfigEntry(Config,PREF_FILE);
							}
						}

						if(Chunk -> cn_ID == ID_DATE)
						{
							if(!PrivatePhonebook[Index] -> Header -> NoRates)
							{
								WORD Count = (Chunk -> cn_Size - sizeof(struct TimeDateHeader)) / sizeof(struct TimeDate);

								if(!CurrentPhoneSize)
									break;

								if(TimeDateNode = CreateTimeDateNode(-1,-1,"",Count))
								{
									if(ReadChunkBytes(Handle,&TimeDateNode -> Header,sizeof(struct TimeDateHeader)) == sizeof(struct TimeDateHeader))
									{
										if(ReadChunkRecords(Handle,TimeDateNode -> Table,sizeof(struct TimeDate),Count) == Count)
										{
											AdaptTimeDateNode(TimeDateNode);

											AddTail((struct List *)&PrivatePhonebook[Index] -> TimeDateList,&TimeDateNode -> VanillaNode);

											LastHadTime = TRUE;
										}
										else
										{
											Error = IoErr();

											FreeTimeDateNode(TimeDateNode);
										}
									}
									else
									{
										Error = IoErr();

										FreeTimeDateNode(TimeDateNode);
									}
								}
							}
						}
					}

					if(CurrentPhoneSize && !Error)
					{
						LONG i;

						if(!LastHadTime)
						{
							if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
								AddTail((struct List *)&PrivatePhonebook[Index] -> TimeDateList,&TimeDateNode -> VanillaNode);
						}

						DB(for(i = 0 ; i < CurrentPhoneSize ; i++))
							DB(kprintf("0x%08lx |%s|\n",PrivatePhonebook[i] -> Header -> ID,PrivatePhonebook[i] -> Header -> Name));

						if(BookHandle)
						{
							BookHandle -> PhonebookID = PrivatePhonebookID;

							if(BookHandle -> Phonebook)
								DeletePhonebook(BookHandle -> Phonebook,BookHandle -> PhoneSize,TRUE);

							BookHandle -> Phonebook			= PrivatePhonebook;
							BookHandle -> PhoneSize			= PrivatePhoneSize;
							BookHandle -> NumPhoneEntries	= CurrentPhoneSize;
							BookHandle -> DefaultGroup		= Globals . DefaultGroup;
							BookHandle -> AutoDial			= Globals . AutoDial;
							BookHandle -> AutoExit			= Globals . AutoExit;

							if(BookHandle -> PhoneGroupList)
							{
								DeletePhoneGroupList(BookHandle -> PhoneGroupList);

								MoveList((struct List *)&LocalPhoneGroupList,(struct List *)BookHandle -> PhoneGroupList);
							}
							else
								DeletePhoneGroupList(&LocalPhoneGroupList);

							memcpy(BookHandle -> PhonePassword,PasswordBuffer,20);
							BookHandle -> PhonePasswordUsed = UsePhonePassword;

							for(i = BookHandle -> NumPhoneEntries ; i < BookHandle -> PhoneSize ; i++)
							{
								if(BookHandle -> Phonebook[i])
								{
									if(BookHandle -> Phonebook[i] -> Config)
										DeleteConfiguration(BookHandle -> Phonebook[i] -> Config);

									FreeVecPooled(BookHandle -> Phonebook[i]);

									BookHandle -> Phonebook[i] = NULL;
								}
							}

							for(i = 0 ; i < BookHandle -> NumPhoneEntries ; i++)
								FinalFix(BookHandle -> Phonebook[i] -> Config,TRUE,TermInfo . Version,TermInfo . Revision);
						}
						else
						{
							PhonebookID = PrivatePhonebookID;

							if(Phonebook)
								DeletePhonebook(Phonebook,PhoneSize,TRUE);

							Phonebook				= PrivatePhonebook;
							PhoneSize				= PrivatePhoneSize;
							NumPhoneEntries			= CurrentPhoneSize;
							PhonebookDefaultGroup	= Globals . DefaultGroup;
							PhonebookAutoDial		= Globals . AutoDial;
							PhonebookAutoExit		= Globals . AutoExit;

							DeletePhoneGroupList(&PhoneGroupList);

							MoveList((struct List *)&LocalPhoneGroupList,(struct List *)&PhoneGroupList);

							memcpy(PhonePassword,PasswordBuffer,20);
							PhonePasswordUsed = UsePhonePassword;

							for(i = NumPhoneEntries ; i < PhoneSize ; i++)
							{
								if(Phonebook[i])
								{
									if(Phonebook[i] -> Config)
										DeleteConfiguration(Phonebook[i] -> Config);

									FreeVecPooled(Phonebook[i]);

									Phonebook[i] = NULL;
								}
							}

							for(i = 0 ; i < NumPhoneEntries ; i++)
								FinalFix(Phonebook[i] -> Config,TRUE,TermInfo . Version,TermInfo . Revision);
						}

						FreeDialList(TRUE);

						Success = TRUE;
					}
					else
					{
						DeletePhoneGroupList(&LocalPhoneGroupList);

						if(PrivatePhoneSize)
						{
							DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);

							Success = FALSE;
						}
					}
				}

				CloseIFF(Handle);
			}

			Close(Handle -> iff_Stream);
		}
		else
			Error = IoErr();

		FreeIFF(Handle);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	if(UseOld)
		return(LoadOldPhonebook(Name,BookHandle));
	else
		return(Success);
}

	/* WriteConfig(STRPTR Name,struct Configuration *Config):
	 *
	 *	Write the configuration to a file, very much like
	 *	WriteIFFData().
	 */

BYTE __regargs
WriteConfig(STRPTR Name,struct Configuration *Config)
{
	struct IFFHandle	*Handle;
	BYTE				 Success = FALSE;
	LONG				 Error = 0;

		/* Allocate a handle. */

	if(Handle = AllocIFF())
	{
			/* Open an output stream. */

		if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
		{
				/* Tell iffparse that this is
				 * a DOS handle.
				 */

			InitIFFasDOS(Handle);

				/* Open the handle for writing. */

			if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
			{
					/* Push outmost chunk onto stack. */

				if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
				{
						/* Add a version identifier. */

					if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
					{
						struct TermInfo TermInfo;

						TermInfo . Version	= CONFIG_FILE_VERSION;
						TermInfo . Revision	= CONFIG_FILE_REVISION;

							/* Update the other configuration pointer as well. */

						Config -> SerialConfig -> LastVersionSaved	= TermVersion;
						Config -> SerialConfig -> LastRevisionSaved	= TermRevision;

							/* Write the version data. */

						if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
						{
								/* Pop the version chunk, i.e. write it to the file. */

							if(Error = PopChunk(Handle))
								Success = FALSE;
							else
							{
								if(WriteConfigChunks(Handle,Config,NULL,NULL))
								{
									LONG i;

									Success = TRUE;

									for(i = 0 ; Success && i < WINDOW_COUNT ; i++)
									{
										if(!(Error = PushChunk(Handle,0,ID_WINF,sizeof(struct WindowInfo))))
										{
											if(WriteChunkBytes(Handle,&WindowInfoTable[i],sizeof(struct WindowInfo)) == sizeof(struct WindowInfo))
											{
												if(Error = PopChunk(Handle))
													Success = FALSE;
											}
											else
											{
												Error = IoErr();

												Success = FALSE;
											}
										}
										else
											Success = FALSE;
									}
								}
							}
						}
						else
						{
							Error = IoErr();

							Success = FALSE;
						}
					}

						/* Seems that we're done, now try to pop the FORM chunk
						 * and return.
						 */

					if(Success)
					{
						if(Error = PopChunk(Handle))
							Success = FALSE;
					}
				}

					/* Close the handle (flush any pending data). */

				CloseIFF(Handle);
			}

				/* Close the DOS handle itself. */

			Close(Handle -> iff_Stream);
		}
		else
			Error = IoErr();

			/* And free the IFF handle. */

		FreeIFF(Handle);
	}
	else
		Error = ERR_NO_MEM;

	if(Success)
		AddProtection(Name,FIBF_EXECUTE);

	return(Success);
}

	/* ReadConfig(STRPTR Name,struct Configuration *Config):
	 *
	 *	Read the configuration file, very much the same as ReadIFFData().
	 */

BYTE __regargs
ReadConfig(STRPTR Name,struct Configuration *Config)
{
	struct IFFHandle	*Handle;
	BYTE				 Success	= FALSE,
						 UseOld		= FALSE;
	struct ContextNode	*Chunk;
	UBYTE				 ConfigChunkType;
	LONG				 Error = 0;

	if(Handle = AllocIFF())
	{
		if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
		{
			InitIFFasDOS(Handle);

			if(!(Error = OpenIFF(Handle,IFFF_READ)))
			{
				if(!StopChunks(Handle,Stops,NUM_STOPS))
				{
					struct TermInfo TermInfo;

					while(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
						Chunk = CurrentChunk(Handle);

							/* Oops! Some is trying to
							 * use the phone book file as
							 * a configuration file.
							 */

						if(Chunk -> cn_ID == ID_CAT)
						{
							Success = FALSE;

							break;
						}

						if(Chunk -> cn_ID == ID_VERS)
						{
							if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if(TermInfo . Version != CONFIG_FILE_VERSION || (TermInfo . Version == CONFIG_FILE_VERSION && TermInfo . Revision > CONFIG_FILE_REVISION))
								{
									if(TermInfo . Version == 2 && TermInfo . Revision == 4)
										UseOld = TRUE;

									if(TermInfo . Version != 3)
										break;
								}
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

						if(Chunk -> cn_ID == ID_WINF)
						{
							struct WindowInfo Info;

							if(ReadChunkBytes(Handle,&Info,sizeof(Info)) == sizeof(Info))
							{
								Success = TRUE;

								ReplaceWindowInfo(&Info);
							}
							else
							{
								Error = IoErr();

								Success = FALSE;
								break;
							}
						}
						else
						{
							if(ConfigChunkType = IsConfigChunk(Chunk -> cn_ID))
							{
								if(ReadConfigChunk(Handle,Config,ConfigChunkType,Chunk -> cn_Size,NULL))
								{
									FixOldConfig(Config,ConfigChunkType,FALSE,TermInfo . Version,TermInfo . Revision);

									Success = TRUE;
								}
								else
								{
									Error = IoErr();

									Success = FALSE;

									break;
								}
							}

								// Special treatment for obsolete "FILE" chunk

							if(Chunk -> cn_ID == ID_FILE)
							{
								struct Configuration *LocalConfig = Config;
								LONG i;

								for(i = PREF_TRANSLATIONFILENAME ; i <= PREF_FASTMACROFILENAME ; i++)
								{
									if(!CreateConfigEntry(LocalConfig,i))
									{
										Error = ERROR_NO_FREE_STORE;

										Success = FALSE;

										break;
									}
								}

								if(!Error)
								{
									strcpy(LocalConfig -> TranslationFileName,	LocalConfig -> FileConfig -> TranslationFileName);
									strcpy(LocalConfig -> MacroFileName,		LocalConfig -> FileConfig -> MacroFileName);
									strcpy(LocalConfig -> CursorFileName,		LocalConfig -> FileConfig -> CursorFileName);
									strcpy(LocalConfig -> FastMacroFileName,	LocalConfig -> FileConfig -> FastMacroFileName);

									DeleteConfigEntry(LocalConfig,PREF_FILE);
								}
							}
						}
					}

					if(Success)
						FinalFix(Config,FALSE,TermInfo . Version,TermInfo . Revision);
				}

				CloseIFF(Handle);
			}

			Close(Handle -> iff_Stream);
		}

		FreeIFF(Handle);
	}
	else
		Error = IoErr();

	if(Error)
		SetIoErr(Error);

	if(UseOld)
		return(ReadOldConfig(Name,Config));
	else
		return(Success);
}
