/*
**	termFastMacros.c
**
**	Fast! macros support routines
**
**	Copyright © 1990-1994 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* NewFastMacro(STRPTR Macro,STRPTR Code):
	 *
	 *	Create a new fast! macro node.
	 */

struct MacroNode * __regargs
NewFastMacro(STRPTR Macro,STRPTR Code)
{
	if(FastMacroCount + 1 < 10000)
	{
		struct MacroNode *Node;

		if(Node = (struct MacroNode *)AllocVecPooled(sizeof(struct MacroNode) + 21 + 257,MEMF_ANY|MEMF_CLEAR))
		{
			Node -> mn_Macro	= (STRPTR)(Node + 1);
			Node -> mn_Code		= &Node -> mn_Macro[21];

			strcpy(Node -> mn_Macro,Macro);
			strcpy(Node -> mn_Code ,Code);

			return(Node);
		}
	}

	return(NULL);
}

	/* SaveFastMacros(STRPTR Name):
	 *
	 *	Save the fast! macro list to a file.
	 */

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

	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	= TermVersion;
							TermInfo . Revision	= TermRevision;

							if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if(Error = PopChunk(Handle))
									Success = FALSE;
								else
								{
									struct MacroNode *Node;

									Node = (struct MacroNode *)FastMacroList . lh_Head;

									while(Node -> mn_Succ)
									{
										if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
										{
											if(!(Error = PushChunk(Handle,0,ID_FAST,IFFSIZE_UNKNOWN)))
											{
												if(WriteChunkBytes(Handle,Node -> mn_Macro,20) != 20)
												{
													Error = IoErr();

													Success = FALSE;

													break;
												}
												else
												{
													if(WriteChunkBytes(Handle,Node -> mn_Code,256) != 256)
													{
														Error = IoErr();

														Success = FALSE;

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

															break;
														}
														else
															Success = TRUE;
													}
												}
											}

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

													break;
												}
											}
										}

										Node = Node -> mn_Succ;
									}
								}
							}
							else
								Error = IoErr();
						}

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

					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);
}

	/* LoadFastMacros(STRPTR Name):
	 *
	 *	Restore the fast! macro list from a file.
	 */

BYTE __regargs
LoadFastMacros(STRPTR Name)
{
	STATIC ULONG Stops[6] =
	{
		ID_TERM,ID_VERS,
		ID_TERM,ID_FAST,
		ID_TERM,ID_WIND
	};

	struct List __aligned	 NewFastMacroList;
	LONG			 NewFastMacroCount = 0;
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;
	struct MacroNode	*Node;
	struct ContextNode	*Chunk;
	struct IBox		 SizeBox;
	LONG				 Error = 0;

	NewList(&NewFastMacroList);

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

			if(!(Error = OpenIFF(Handle,IFFF_READ)))
			{
				if(!(Error = StopChunks(Handle,(LONG *)Stops,3)))
				{
					while(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
						Chunk = CurrentChunk(Handle);

						if(Chunk -> cn_ID == ID_VERS)
						{
							struct TermInfo TermInfo;

							if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if((TermInfo . Version > TermVersion) || (TermInfo . Version == TermVersion && TermInfo . Revision > TermRevision) || (TermInfo . Version == 1 && TermInfo . Revision < 6))
								{
									Error = ERR_OUTDATED;

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

								break;
							}
						}

						if(Chunk -> cn_ID == ID_WIND)
						{
							if(ReadChunkBytes(Handle,&SizeBox,sizeof(struct IBox)) == sizeof(struct IBox))
							{
								FastWindowLeft		= SizeBox . Left;
								FastWindowTop		= SizeBox . Top;
								FastWindowHeight	= SizeBox . Height;
							}
							else
							{
								Error = IoErr();

								break;
							}
						}

						if(Chunk -> cn_ID == ID_FAST)
						{
							if(Node = NewFastMacro("",""))
							{
								if(ReadChunkBytes(Handle,Node -> mn_Macro,20) == 20)
								{
									if(ReadChunkBytes(Handle,Node -> mn_Code,256) == 256)
									{
										AddTail(&NewFastMacroList,(struct Node *)Node);

										NewFastMacroCount++;

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

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

									break;
								}
							}
							else
							{
								Error = ERR_NO_MEM;

								break;
							}
						}
					}

					if(Success)
					{
						if(NewFastMacroList . lh_Head -> ln_Succ)
						{
							FreeList(&FastMacroList);

							MoveList(&NewFastMacroList,&FastMacroList);

							FastMacroCount = NewFastMacroCount;
						}
					}
					else
						FreeList(&NewFastMacroList);
				}

				CloseIFF(Handle);
			}

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

		FreeIFF(Handle);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	return(Success);
}
