#include "global.h"
#include "misc.h"
#include "adfile.h"

/***********************************************/

void FreeList(struct AnyNode *List)
{
	struct AnyNode *NextNode;

	while (List)
	{
		NextNode = List->Next;
		FreeVec(List);
		List = NextNode;
	}
}

/***********************************************/

char *FindSlash(char *String)
{
	while (*String && *String != '/')
		String++;
	return (String);
}

/***********************************************/

BOOL Break(void)
{
	if (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
	{
		printf("*** User abort.\n");
		return (TRUE);
	}
	return (FALSE);
}

/***********************************************/

void WriteError(char *FormatString,...)
{
	VPrintf(FormatString, ((LONG *) & FormatString) + 1);
	if (ErrorFile)
	{
		VFPrintf(ErrorFile, FormatString, ((LONG *) & FormatString) + 1);
	}
}

/***********************************************/

struct AnyNode **ListToArray(struct AnyNode *List)
{
	int ArrayEntries;
	int Index, Current;
	struct AnyNode *Node;
	struct AnyNode **Array;

	Node = List;
	ArrayEntries = 0;
	while (Node)
	{
		ArrayEntries++;
		Node = Node->Next;
	}
	if (Array = AllocVec((ArrayEntries + 1) * 4, 0))
	{
		Array[0] = (struct AnyNode *) ArrayEntries;
		Node = List;
		for (Index = 1; Node; Index++)
		{
			Array[Index] = Node;
			Node = Node->Next;
		}
		for (Current = 1; Current < ArrayEntries; Current++)
		{
			for (Index = Current + 1; Index <= ArrayEntries; Index++)
			{
				if (strcmp(Array[Index]->Name, Array[Current]->Name) < 0)
				{
					Node = Array[Index];
					Array[Index] = Array[Current];
					Array[Current] = Node;
				}
			}
			if (Break())
			{
				FreeVec(Array);
				return (NULL);
			}
		}
	}
	else
	{
		PrintFault(ERROR_NO_FREE_STORE, NULL);
	}
	return (Array);
}

/***********************************************/

BOOL ReadLine(BOOL AcceptEOF, BOOL StoreLF)
{
	int Index;
	long Character;

	Index = 0;
	while (TRUE)
	{
		if (Break())
		{
			return (FALSE);
		}
		Character = FGetC(CurrentFile);
		switch (Character)
		{
			case -1:
				if (IoErr())
				{
					PrintFault(IoErr(), CurrentSource);
				}
				else
				{
					if (!AcceptEOF)
					{
						WriteError("Error: Unexpected end of file %s\n"
								   "       Operation aborted.\n", CurrentSource);
					}
				}
				return (FALSE);

			case '\n':
				if (StoreLF)
				{
					Buffer[Index++] = '\n';
				}
				Buffer[Index] = '\0';
				CurrentLine++;
				return (TRUE);

			case '\x0c':
				if (Arguments.CED)
				{
					CurrentLine++;
				}
				if (Index)
				{
					WriteError("Error: Unexpected FormFeed in file %s"
							   "       Operation aborted.\n", CurrentSource);
					return (FALSE);
				}
				else
				{
					Buffer[0] = Character;
					return (TRUE);
				}

			default:
				Buffer[Index++] = Character;
				if (Index == MAX_LEN)
				{
					WriteError("Error: Line too long in file %s\n"
							   "       Operation aborted.\n", CurrentSource);
					return (FALSE);
				}
				break;
		}
	}
}

/***********************************************/

BOOL WriteSomething(char *FormatString,...)
{
	if (VFPrintf(HypertextFile, FormatString, ((LONG *) & FormatString) + 1) == -1)
	{
		PrintFault(IoErr(), HypertextFilename);
		return (FALSE);
	}
	return (TRUE);
}

/***********************************************/

void DosError(char *Header)
{
	PrintFault(IoErr(), Header);
	CloseAll();
	exit(10);
}

/***********************************************/

long fgetc2(void)
{
	while (TRUE)
	{
		if (Break())
		{
			return (-1);
		}
		if (Buffer[BufferIndex])
		{
			return ((long) ((unsigned char) (Buffer[BufferIndex++])));
		}
		if (!ReadLine(TRUE, TRUE))
			return (-1);
		BufferIndex = 0;
	}
}

/***********************************************/

struct AnyNode *SearchNameCase(struct AnyNode **Array, char *Name)
{
	int OldIndex;
	int Upper, Lower;
	int Index;
	int Result;

	Lower = 1;
	Upper = (int) Array[0] + 1;
	Index = 0;
	do
	{
		OldIndex = Index;
		Index = (Upper + Lower) / 2;
		if (!(Result = strcmp(Array[Index]->Name, Name)))
		{
			return (Array[Index]);
		}
		if (Result < 0)
		{
			Lower = Index;
		}
		else
		{
			Upper = Index;
		}
	}
	while (Index != OldIndex);
	return (NULL);
}

/***********************************************/

struct AnyNode *SearchNameNoCase(struct AnyNode **Array, char *Name)
{
	int Upper, Lower;
	int Index;
	int OldIndex;
	int Result;

	Lower = 1;
	Upper = (int) Array[0] + 1;
	Index = 0;
	do
	{
		OldIndex = Index;
		Index = (Upper + Lower) / 2;
		if (!(Result = stricmp(Array[Index]->Name, Name)))
		{
			return (Array[Index]);
		}
		if (Result < 0)
		{
			Lower = Index;
		}
		else
		{
			Upper = Index;
		}
	}
	while (Index != OldIndex);
	return (NULL);
}

/***********************************************/

BPTR CreateFile(char *Name)
{
	char *Temp;
	BPTR DirLock;

	Temp = Name;
	while (*Temp)
	{
		if (*Temp == '/')
		{
			*Temp = '\0';
			if (!(DirLock = Lock(Name, ACCESS_READ)))
			{
				if (!(DirLock = CreateDir(Name)))
				{
					*Temp = '/';
					return (NULL);
				}
			}
			UnLock(DirLock);
			*Temp = '/';
		}
		Temp++;
	}
	return (Open(Name, MODE_NEWFILE));
}
