/*
**	VSPrintf.c
**
**	Formatted output to memory
**
**	Copyright © 1990-1997 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

	/* StuffChar(REG(a3) struct FormatContext *Context,REG(d0) UBYTE Char):
	 *
	 *	Stuffs a character into the buffer, unless there is not
	 *	enough room left.
	 */

VOID ASM
StuffChar(
	REG(a3) struct FormatContext *	Context,
	REG(d0) UBYTE					Char)
{
	if(Context->Size > 0)
	{
		*Context->Index++ = Char;

		if(--Context->Size == 1)
		{
			*Context->Index = 0;
			Context->Size = 0;
		}
	}
}

	/* LimitedVSPrintf(LONG Size,STRPTR Buffer,STRPTR FormatString,...):
	 *
	 *	Like VSPrintf, but won't write more than the given number
	 *	of bytes.
	 */

VOID
LimitedVSPrintf(
	LONG	Size,
	STRPTR	Buffer,
	STRPTR	FormatString,
	va_list	VarArgs)
{
	struct FormatContext Context;

	Context.Index	= Buffer;
	Context.Size	= Size;

	#ifdef USE_GLUE
	{
		RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)StuffCharGlue,(APTR)&Context);
	}
	#else
	{
		RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)StuffChar,(APTR)&Context);
	}
	#endif	/* USE_GLUE */
}

	/* LimitedSPrintf(LONG Size,STRPTR Buffer,STRPTR FormatString,...):
	 *
	 *	Like SPrintf, but won't write more than the given number
	 *	of bytes.
	 */

VOID
LimitedSPrintf(
	LONG	Size,
	STRPTR	Buffer,
	STRPTR	FormatString,
			...)
{
	va_list VarArgs;

	va_start(VarArgs,FormatString);
	LimitedVSPrintf(Size,Buffer,FormatString,VarArgs);
	va_end(VarArgs);
}

	/* VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs):
	 *
	 *	Just like vsprintf(), but using the ROM routines.
	 */

VOID
VSPrintf(
	STRPTR	Buffer,
	STRPTR	FormatString,
	va_list	VarArgs)
{
	RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)"\x16\xC0\x4E\x75",(APTR)Buffer);
}

	/* SPrintf(STRPTR Buffer,STRPTR FormatString,...):
	 *
	 *	Just like sprintf(), but using the ROM routines.
	 */

VOID
SPrintf(
	STRPTR	Buffer,
	STRPTR	FormatString,
			...)
{
	va_list VarArgs;

	va_start(VarArgs,FormatString);
	VSPrintf(Buffer,FormatString,VarArgs);
	va_end(VarArgs);
}

	/* CountChar(REG(a3) ULONG *Count):
	 *
	 *	Counts the number of bytes to stuff into the output buffer.
	 */

VOID ASM
CountChar(REG(a3) ULONG * Count)
{
	*Count = *Count + 1;
}

	/* GetFormatLength(STRPTR FormatString,va_list VarArgs):
	 *
	 *	Before calling VSPrintf or the like, count the number of
	 *	characters that would go into the format buffer (including
	 *	the trailing NUL character).
	 */

ULONG
GetFormatLength(
	STRPTR	FormatString,
	va_list	VarArgs)
{
	ULONG Count;

	Count = 0;

	#ifdef USE_GLUE
	{
		RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CountCharGlue,(APTR)&Count);
	}
	#else
	{
		RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CountChar,(APTR)&Count);
	}
	#endif	/* USE_GLUE */

	return(Count);
}

	/* GetFormatLengthArgs(STRPTR FormatString,...):
	 *
	 *	VarArgs version of GetFormatLength.
	 */

ULONG
GetFormatLengthArgs(
	STRPTR	FormatString,
			...)
{
	va_list VarArgs;
	ULONG Count;

	va_start(VarArgs,FormatString);
	Count = GetFormatLength(FormatString,VarArgs);
	va_end(VarArgs);

	return(Count);
}

	/* LimitedStrcat(LONG Size,STRPTR To,STRPTR From):
	 *
	 *	Like strcat, but limited by the size of the
	 *	destination buffer.
	 */

VOID
LimitedStrcat(
	LONG	Size,
	STRPTR	To,
	STRPTR	From)
{
	while(*To)
	{
		To++;
		Size--;
	}

	while(*From && Size > 0)
	{
		*To++ = *From++;

		Size--;
	}

	*To = 0;
}

	/* LimitedStrcpy(LONG Size,STRPTR To,STRPTR From):
	 *
	 *	Like strcpy, but limited by the size of the
	 *	destination buffer.
	 */

VOID
LimitedStrcpy(
	LONG	Size,
	STRPTR	To,
	STRPTR	From)
{
	while(*From && Size > 0)
	{
		*To++ = *From++;

		Size--;
	}

	*To = 0;
}

	/* LimitedStrncpy(LONG Size,STRPTR To,STRPTR From):
	 *
	 *	Like strncpy, but limited by the size of the
	 *	destination buffer.
	 */

VOID
LimitedStrncpy(
	LONG	Size,
	STRPTR	To,
	STRPTR	From,
	LONG	FromSize)
{
	while(*From && Size > 0 && FromSize > 0)
	{
		*To++ = *From++;

		Size--;
		FromSize--;
	}

	*To = 0;
}
