/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: UpdatePhone.c
 *	Created ..: Saturday 23-Mar-91 22:07
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	23-Mar-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

struct TermInfo
{
	UWORD	Version;
	UWORD	Revision;
};

extern LONG TermVersion,TermRevision;
extern UBYTE TermName[],TermDate[],TermString[];

struct Configuration
{
	/* Serial Preferences. */

	ULONG	BaudRate;
	BYTE	BitsPerChar;
	BYTE	Parity;
	BYTE	StopBits;
	BYTE	Handshaking;
	BYTE	Duplex;
	BYTE	HighSpeed;
	ULONG	BreakLength;
	UBYTE	SerialDevice[40];
	LONG	UnitNumber;

	/* Modem Preferences. */

	UBYTE	ModemInit[80];
	UBYTE 	ModemExit[80];
	UBYTE	DialPrefix[80];
	LONG	RedialDelay;
	LONG	DialRetries;
	LONG	DialTimeout;
	BYTE	ConnectAutoBaud;
	UBYTE	NoCarrier[16];
	UBYTE	Connect[16];
	UBYTE	Error[16];
	UBYTE	Voice[16];
	UBYTE	Ring[16];
	UBYTE	Busy[16];
	UBYTE	Okay[16];

	/* Transfer Preferences. */

	UBYTE	Protocol[40];

	/* Startup macro. */

	UBYTE	StartupMacro[256];

	/* Macro Preferences. */

	UBYTE	MacroFile[256];

	/* Screen Preferences. */

	ULONG	DisplayMode;
	UWORD	Colours[16];
	BYTE	MakeScreenPublic;
	BYTE	ShanghaiWindows;

	/* Terminal Preferences. */

	BYTE	CaptureFilter;
	BYTE	DestructiveBackspace;
	BYTE	AudibleBell;
	BYTE	VisibleBell;
	BYTE	EightyColumns;
	BYTE	SendCR;
	BYTE	SendLF;
	BYTE	ColourMode;
	BYTE	Emulation;
	BYTE	Font;
};

	/* A phone book entry. */

struct PhoneEntry
{
	UBYTE			Name[40];
	UBYTE			Number[40];
	UBYTE			Password[40];

	LONG			PayPerUnit;
	LONG			MinPerUnit;

	struct Configuration	Config;
};

struct NewConfiguration
{
	/* Serial Preferences. */

	ULONG	BaudRate;
	BYTE	BitsPerChar;
	BYTE	Parity;
	BYTE	StopBits;
	BYTE	Handshaking;
	BYTE	Duplex;
	BYTE	HighSpeed;
	ULONG	BreakLength;
	UBYTE	SerialDevice[40];
	LONG	UnitNumber;

	/* Modem Preferences. */

	UBYTE	ModemInit[80];
	UBYTE 	ModemExit[80];
	UBYTE 	ModemHangup[80];
	UBYTE	DialPrefix[80];
	LONG	RedialDelay;
	LONG	DialRetries;
	LONG	DialTimeout;
	BYTE	ConnectAutoCapture;
	BYTE	ConnectAutoBaud;
	BYTE	LogActions;
	UBYTE	NoCarrier[16];
	UBYTE	Connect[16];
	UBYTE	Voice[16];
	UBYTE	Ring[16];
	UBYTE	Busy[16];

	/* Transfer Preferences. */

	UBYTE	Protocol[40];

	/* Startup macro. */

	UBYTE	StartupMacro[256];

	/* Macro Preferences. */

	UBYTE	MacroFile[256];

	/* Screen Preferences. */

	ULONG	DisplayMode;
	UWORD	Colours[16];
	BYTE	MakeScreenPublic;
	BYTE	ShanghaiWindows;

	/* Terminal Preferences. */

	BYTE	CaptureFilter;
	BYTE	DestructiveBackspace;
	BYTE	AudibleBell;
	BYTE	VisibleBell;
	BYTE	EightyColumns;
	BYTE	DisableBlinking;
	BYTE	SendCR;
	BYTE	SendLF;
	BYTE	ColourMode;
	BYTE	Emulation;
	BYTE	Font;

	/* Emulation control. */

	BYTE	CursorApp;
	BYTE	FontScale;
	BYTE	JumpScroll;
	BYTE	AutoWrap;
	BYTE	CursorWrap;
	BYTE	NewLine;
	BYTE	InsertChar;
	BYTE	NumApp;

	/* Path Preferences. */

	UBYTE	DefaultStorage[256];

	UBYTE	TextUploadPath[256];
	UBYTE	TextDownloadPath[256];

	UBYTE	ASCIIUploadPath[256];
	UBYTE	ASCIIDownloadPath[256];

	UBYTE	BinaryUploadPath[256];
	UBYTE	BinaryDownloadPath[256];

	UBYTE	CapturePath[256];
	UBYTE	LogFile[256];
	UBYTE	Editor[256];
	UBYTE	BeepSound[256];
};

struct NewPhoneEntry
{
	UBYTE			Name[30];
	UBYTE			Number[40];
	UBYTE			Password[40];

	LONG			PayPerUnit[2];
	LONG			SecPerUnit[2];
	LONG			TimeOfDay[2];

	struct NewConfiguration	Config;
};

LONG __saveds		Main(VOID);
struct PhoneEntry **	CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries);
VOID			DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries);
BYTE			SavePhonebook(UBYTE *Name);
BYTE			LoadPhonebook(UBYTE *Name);

struct PhoneEntry	**Phonebook;
LONG			 PhoneSize;

LONG			 NumPhoneEntries;

struct ExecBase		*SysBase;
struct DosLibrary	*DOSBase;
struct Library		*IFFParseBase;

LONG __saveds
Main()
{
	SysBase = *(struct ExecBase **)4;

	if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36))
	{
		if(IFFParseBase = (struct Library *)OpenLibrary("iffparse.library",0))
		{
			UBYTE **ArgArray;

			if(ArgArray = (UBYTE **)AllocVec(sizeof(UBYTE *),MEMF_PUBLIC | MEMF_CLEAR))
			{
				struct RDArgs *ArgsPtr;

				if(ArgsPtr = (struct RDArgs *)ReadArgs("File",(LONG *)ArgArray,NULL))
				{
					if(ArgArray[0])
					{
						if(LoadPhonebook(ArgArray[0]))
						{
							if(!SavePhonebook(ArgArray[0]))
								Printf("\33[1mUpdatePhone:\33[0m Couldn't save file \"%s\"!\a\n",ArgArray[0]);
						}
						else
							Printf("\33[1mUpdatePhone:\33[0m Couldn't load file \"%s\"!\a\n",ArgArray[0]);

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

					FreeArgs(ArgsPtr);
				}

				FreeVec(ArgArray);
			}

			CloseLibrary(IFFParseBase);
		}

		CloseLibrary(DOSBase);
	}

	return(RETURN_OK);
}

	/* Convert(struct PhoneEntry *Src):
	 *
	 *	Convert a phonebook entry.
	 */

struct NewPhoneEntry *
Convert(struct PhoneEntry *Src)
{
	STATIC struct NewPhoneEntry Dst;

	CopyMem(Src -> Name,Dst . Name,30);

	Dst . Name[29] = 0;

	strcpy(Dst . Number,Src -> Number);

	strcpy(Dst . Password,Src -> Password);

	Dst . PayPerUnit[0] = Src -> PayPerUnit;
	Dst . SecPerUnit[0] = Src -> MinPerUnit * 60;

	Dst . Config . BaudRate			= Src -> Config . BaudRate;
	Dst . Config . BitsPerChar		= Src -> Config . BitsPerChar;
	Dst . Config . Parity			= Src -> Config . Parity;
	Dst . Config . StopBits			= Src -> Config . StopBits;
	Dst . Config . Handshaking		= Src -> Config . Handshaking;
	Dst . Config . Duplex			= Src -> Config . Duplex;
	Dst . Config . HighSpeed		= Src -> Config . HighSpeed;
	Dst . Config . BreakLength		= Src -> Config . BreakLength;

	strcpy(Dst . Config . SerialDevice,Src -> Config . SerialDevice);

	Dst . Config . UnitNumber		= Src -> Config . UnitNumber;

	strcpy(Dst . Config . ModemInit,Src -> Config . ModemInit);
	strcpy(Dst . Config . ModemExit,Src -> Config . ModemExit);
	strcpy(Dst . Config . ModemHangup,"~~~~~~+++~~ATH0\\r");
	strcpy(Dst . Config . DialPrefix,Src -> Config . DialPrefix);

	Dst . Config . RedialDelay		= Src -> Config . RedialDelay;
	Dst . Config . DialRetries		= Src -> Config . DialRetries;
	Dst . Config . DialTimeout		= Src -> Config . DialTimeout;
	Dst . Config . ConnectAutoBaud		= Src -> Config . ConnectAutoBaud;

	strcpy(Dst . Config . NoCarrier,Src -> Config . NoCarrier);
	strcpy(Dst . Config . Connect,Src -> Config . Connect);
	strcpy(Dst . Config . Voice,Src -> Config . Voice);
	strcpy(Dst . Config . Ring,Src -> Config . Ring);
	strcpy(Dst . Config . Busy,Src -> Config . Busy);

	strcpy(Dst . Config . Protocol,Src -> Config . Protocol);

	strcpy(Dst . Config . StartupMacro,Src -> Config . StartupMacro);

	strcpy(Dst . Config . MacroFile,Src -> Config . MacroFile);

	Dst . Config . DisplayMode		= Src -> Config . DisplayMode;

	CopyMem(Src -> Config . Colours,Dst . Config . Colours,sizeof(UWORD) * 16);

	Dst . Config . MakeScreenPublic		= Src -> Config . MakeScreenPublic;
	Dst . Config . ShanghaiWindows		= Src -> Config . ShanghaiWindows;

	Dst . Config . CaptureFilter		= Src -> Config . CaptureFilter;
	Dst . Config . DestructiveBackspace	= Src -> Config . DestructiveBackspace;
	Dst . Config . AudibleBell		= Src -> Config . AudibleBell;
	Dst . Config . VisibleBell		= Src -> Config . VisibleBell;
	Dst . Config . EightyColumns		= Src -> Config . EightyColumns;
	Dst . Config . SendCR			= Src -> Config . SendCR;
	Dst . Config . SendLF			= Src -> Config . SendLF;
	Dst . Config . ColourMode		= Src -> Config . ColourMode;
	Dst . Config . Emulation		= Src -> Config . Emulation;
	Dst . Config . Font			= Src -> Config . Font;

	strcpy(Dst . Config . DefaultStorage,"ENVARC:sys");

	return(&Dst);
}

	/* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
	 *
	 *	Create a new phone entry array (so-called phone book).
	 */

struct PhoneEntry **
CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
{
	struct PhoneEntry **PhoneEntry = NULL;

	if(Size)
	{
			/* Round the number of phone entries to a
			 * multiple of eight.
			 */

		*AllocSize = (((Size + 7) >> 3) << 3);

			/* Create the list of pointers. */

		if(PhoneEntry = (struct PhoneEntry **)AllocMem(*AllocSize * sizeof(struct PhoneEntry *),MEMF_PUBLIC|MEMF_CLEAR))
		{
				/* And create some entries if necessary. */

			if(CreateEntries)
			{
				LONG i;

				for(i = 0 ; i < Size ; i++)
				{
					if(!(PhoneEntry[i] = (struct PhoneEntry *)AllocMem(sizeof(struct PhoneEntry),MEMF_PUBLIC|MEMF_CLEAR)))
					{
						LONG j;

						for(j = 0 ; j < i ; j++)
							FreeMem(PhoneEntry[j],sizeof(struct PhoneEntry));

						FreeMem(PhoneEntry,*AllocSize * sizeof(struct PhoneEntry *));

						return(NULL);
					}
				}
			}
		}
	}

	return(PhoneEntry);
}

	/* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
	 *
	 *	Deallocates a given phone book and its entries if necessary.
	 */

VOID
DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries)
{
	if(FreeEntries)
	{
		LONG i;

		for(i = 0 ; i < Size ; i++)
		{
			if(PhoneBook[i])
				FreeMem(PhoneBook[i],sizeof(struct PhoneEntry));
		}
	}

	FreeMem(PhoneBook,Size * sizeof(struct PhoneEntry *));
}

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

BYTE
SavePhonebook(UBYTE *Name)
{
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;
	LONG			 i;

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

				if(!OpenIFF(Handle,IFFF_WRITE))
				{
					if(!PushChunk(Handle,'TERM','FORM',IFFSIZE_UNKNOWN))
					{
						if(!PushChunk(Handle,0,'VERS',IFFSIZE_UNKNOWN))
						{
							struct TermInfo TermInfo;

							TermInfo . Version	= TermVersion;
							TermInfo . Revision	= TermRevision;

							if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if(PopChunk(Handle))
									Success = FALSE;
								else
								{
									if(!PushChunk(Handle,0,'DIAL',IFFSIZE_UNKNOWN))
									{
										if(WriteChunkBytes(Handle,&NumPhoneEntries,sizeof(LONG)) == sizeof(LONG))
										{
											Success = TRUE;

											for(i = 0 ; i < NumPhoneEntries ; i++)
											{
												if(WriteChunkBytes(Handle,Convert(Phonebook[i]),sizeof(struct NewPhoneEntry)) != sizeof(struct NewPhoneEntry))
												{
													Success = FALSE;
													break;
												}
											}
										}

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

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

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}

			FreeIFF(Handle);
		}
	}

	if(Success)
		SetProtection(Name,FIBF_EXECUTE);

	return(Success);
}

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

BYTE
LoadPhonebook(UBYTE *Name)
{
	struct PhoneEntry	**PrivatePhonebook;
	LONG			 PrivatePhoneSize;
	LONG			 Size,i;
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;

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

			if(!OpenIFF(Handle,IFFF_READ))
			{
				if(!StopChunk(Handle,'TERM','DIAL'))
				{
					if(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
						if(ReadChunkRecords(Handle,&Size,sizeof(LONG),1))
						{
							if(Size)
							{
								if(PrivatePhonebook = CreatePhonebook(Size,&PrivatePhoneSize,TRUE))
								{
									for(i = 0 ; i < Size ; i++)
									{
										if(!ReadChunkRecords(Handle,PrivatePhonebook[i],sizeof(struct PhoneEntry),1))
										{
											if(i)
												Size = i - 1;
											else
												Size = 0;

											break;
										}
									}

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

										Phonebook = PrivatePhonebook;
										PhoneSize = PrivatePhoneSize;

										NumPhoneEntries = Size;

										Success = TRUE;
									}
									else
									{
										DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);
										Success = FALSE;
									}
								}
							}
						}
					}
				}

				CloseIFF(Handle);
			}

			Close(Handle -> iff_Stream);
		}

		FreeIFF(Handle);
	}

	return(Success);
}
