/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: FastMacros.c
 *	Created ..: Monday 19-Aug-91 19:49
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	19-Aug-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

STATIC WORD		 Left = -1,Top = -1,Height = -1;
STATIC struct Gadget	*GadgetList = NULL;
STATIC WORD		 Dims[4] = { -1,-1,-1,-1 };

#define WIDTH	192
#define HEIGHT	99

VOID
RefreshFastWindow(WORD Height)
{
	struct Gadget		*Gadget;
	struct NewGadget	 NewGadget;
	WORD			 TopEdge = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1;

	memset(&NewGadget,0,sizeof(struct NewGadget));

	if(GadgetList)
	{
		RemoveGList(FastWindow,GadgetList,-1);

		SetAPen(FastWindow -> RPort,0);

		RectFill(FastWindow -> RPort,FastWindow -> BorderRight,FastWindow -> BorderTop,FastWindow -> Width - (FastWindow -> BorderLeft + 1),FastWindow -> Height - (FastWindow -> BorderBottom + 1));

		FreeGadgets(GadgetList);

		GadgetList = NULL;
	}

	if(Gadget = CreateContext(&GadgetList))
	{
		NewGadget . ng_Width		= 180;
		NewGadget . ng_Height		= Height - (TopEdge + 4 + 8);
		NewGadget . ng_GadgetText	= "";
		NewGadget . ng_GadgetID		= 0;
		NewGadget . ng_LeftEdge		= 6;
		NewGadget . ng_TopEdge		= 1 + TopEdge;
		NewGadget . ng_TextAttr		= &DefaultFont;
		NewGadget . ng_VisualInfo	= VisualInfo;
	
		FastGadget = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
			GTLV_Labels,	&FastMacroList,
		TAG_DONE);
	}

	if(Gadget)
	{
		AddGList(FastWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
		RefreshGList(GadgetList,FastWindow,NULL,(UWORD)-1);
		GT_RefreshWindow(FastWindow,NULL);
	}
	else
	{
		FreeGadgets(GadgetList);

		GadgetList = NULL;
	}
}

VOID
CloseFastWindow()
{
	if(FastWindow)
	{
		Left	= FastWindow -> LeftEdge;
		Top	= FastWindow -> TopEdge;
		Height	= FastWindow -> Height;

		ClearMenuStrip(FastWindow);
		CloseWindowSafely(FastWindow);

		FastWindow = NULL;
	}

	if(GadgetList)
	{
		FreeGadgets(GadgetList);

		GadgetList = NULL;
	}
}

BYTE
OpenFastWindow()
{
	if(Height == -1)
		Height = HEIGHT;

	if(Left == -1)
		Left = Screen -> Width - WIDTH;

	if(Top == -1)
		Top = (Screen -> Height - Height) >> 1;

	if(Top + Height > Screen -> Height)
	{
		if(Top >= Screen -> Height - (HEIGHT - 56))
			Top = Screen -> Height - (HEIGHT - 56);

		while(Top + Height > Screen -> Height)
			Height--;
	}

	if(Dims[0] == -1)
	{
		Dims[0] = 0;
		Dims[1] = 0;
		Dims[2] = WIDTH;
		Dims[3] = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1;
	}

	if(FastWindow = OpenWindowTags(NULL,
		WA_Width,	WIDTH,
		WA_Height,	Height,

		WA_Left,	Left,
		WA_Top,		Top,

		WA_DragBar,	TRUE,
		WA_DepthGadget,	TRUE,
		WA_CloseGadget,	TRUE,
		WA_RMBTrap,	TRUE,
		WA_Zoom,	Dims,

		WA_SizeGadget,	TRUE,
		WA_SizeBBottom,	TRUE,

		WA_MinWidth,	WIDTH,
		WA_MaxWidth,	WIDTH,

		WA_MinHeight,	HEIGHT - 56,
		WA_MaxHeight,	~0,

		WA_Title,	"Fast! Macros",

		WA_CustomScreen,Screen,
	TAG_DONE))
	{
		FastWindow -> UserPort = Window -> UserPort;

		ModifyIDCMP(FastWindow,Window -> IDCMPFlags);

		SetMenuStrip(FastWindow,Menu);

		FastWindow -> Flags &= ~WFLG_RMBTRAP;

		RefreshFastWindow(Height);

		return(TRUE);
	}

	return(FALSE);
}

struct MacroNode *
NewFastMacro(UBYTE *Macro,UBYTE *Code)
{
	struct MacroNode *Node;

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

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

		return(Node);
	}

	return(NULL);
}

VOID
RemFastMacro(struct MacroNode *Node)
{
	Remove((struct Node *)Node);

	FreeVec(Node);
}

struct MacroNode *
GetFastMacro(LONG Offset)
{
	struct MacroNode	*Node;
	LONG			 i;

	Node = (struct MacroNode *)FastMacroList . lh_Head;

	for(i = 0 ; i < Offset ; i++)
	{
		if(!Node -> mn_Succ -> mn_Succ)
			return(NULL);

		Node = Node -> mn_Succ;
	}

	return(Node);
}

VOID
ClearFastMacroList(struct List *List)
{
	struct Node *Node,*NextNode;

	Node = List -> lh_Head;

	while(Node -> ln_Succ)
	{
		NextNode = Node -> ln_Succ;

		Remove(Node);

		FreeVec(Node);

		Node = NextNode;
	}
}

LONG
GetFastMacroOffset(struct MacroNode *MacroNode)
{
	struct MacroNode	*Node;
	LONG			 Offset = 0;

	Node = (struct MacroNode *)FastMacroList . lh_Head;

	while(Node -> mn_Succ)
	{
		if(Node == MacroNode)
			return(Offset);

		Offset++;

		Node = Node -> mn_Succ;
	}

	return(~0);
}

BYTE
SaveFastMacros(UBYTE *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,'TERM',ID_CAT,IFFSIZE_UNKNOWN))
				{
					if(!PushChunk(Handle,'TERM',ID_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
								{
									struct MacroNode *Node;

									Node = (struct MacroNode *)FastMacroList . lh_Head;

									while(Node -> mn_Succ)
									{
										if(!PushChunk(Handle,'TERM',ID_FORM,IFFSIZE_UNKNOWN))
										{
											if(!PushChunk(Handle,0,'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)
		SetProtection(Name,FIBF_EXECUTE);
	else
		DeleteFile(Name);

	return(Success);
}

VOID __regargs
MoveList(struct List *From,struct List *To)
{
	struct Node *Node,*NextNode;

	Node = From -> lh_Head;

	while(NextNode = Node -> ln_Succ)
	{
		Remove(Node);

		AddTail(To,Node);

		Node = NextNode;
	}
}

BYTE
LoadFastMacros(UBYTE *Name)
{
	STATIC ULONG Stops[4] =
	{
		'TERM','VERS',
		'TERM','FAST'
	};

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

	NewList(&NewFastMacroList);

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

			if(!OpenIFF(Handle,IFFF_READ))
			{
				if(!StopChunks(Handle,&Stops[0],2))
				{
					while(!ParseIFF(Handle,IFFPARSE_SCAN))
					{
						Chunk = CurrentChunk(Handle);

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

							if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
							{
								if(TermInfo . Version > TermVersion || TermInfo . Revision > 9 || TermInfo . Revision < 6)
									break;
							}
							else
								break;
						}

						if(Chunk -> cn_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)
						{
							ClearFastMacroList(&FastMacroList);

							MoveList(&NewFastMacroList,&FastMacroList);

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

				CloseIFF(Handle);
			}

			Close(Handle -> iff_Stream);
		}

		FreeIFF(Handle);
	}

	return(Success);
}
