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

#include "termGlobal.h"

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

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

		if(Node = (struct MacroNode *)AllocVec(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
SaveFastMacros(STRPTR Name)
{
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;

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

			if(!OpenIFF(Handle,IFFF_WRITE))
			{
				if(!PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN))
				{
					if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
					{
						if(!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(PopChunk(Handle))
									Success = FALSE;
								else
								{
									struct MacroNode *Node;

									Node = (struct MacroNode *)FastMacroList . lh_Head;

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

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

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

															break;
														}
														else
															Success = TRUE;
													}
												}
											}

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

													break;
												}
											}
										}

										Node = Node -> mn_Succ;
									}
								}
							}
						}

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

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

				CloseIFF(Handle);
			}

			Close(Handle -> iff_Stream);
		}

		FreeIFF(Handle);
	}

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

	return(Success);
}

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

BYTE
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;

	NewList(&NewFastMacroList);

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

			if(!OpenIFF(Handle,IFFF_READ))
			{
				if(!StopChunks(Handle,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))
									break;
							}
							else
								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
								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
										break;
								}
								else
									break;
							}
							else
								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);
		}

		FreeIFF(Handle);
	}

	return(Success);
}
