//
// Floating point
//
static void FmtFloat(StringBuffer            & oBuffer,
                     const CDT               & oCurrentArgument,
                     const UINT_32             iFmtFlags,
                     const eFmtLengths       & oFmtLengths,
                     const CHAR_8              chExponentSymbol,
                     const eFmtSpecifier     & oFmtSpecifier,
                     INT_32                    iWidth,
                     INT_32                    iPrecision,
                     CHAR_8                    chPadSymbol)
{
	using namespace CTPP;

	/*
	 * fF  The double argument is rounded and converted to decimal notation
	 *     in the style [-]ddd.ddd, where the number of digits after the
	 *     decimal-point character is equal to the precision specification.
	 *     If the precision is missing, it is taken as 6; if the precision
	 *     is explicitly zero, no decimal-point character appears.  If a
	 *     decimal point appears, at least one digit appears before it.
	 *
	 * gG  The double argument is converted in style f or e (or F or E for G
	 *     conversions).  The precision specifies the number of significant
	 *     digits.  If the precision is missing, 6 digits are given; if the
	 *     precision is zero, it is treated as 1.  Style e is used if the
	 *     exponent from its conversion is less than -4 or greater than or
	 *     equal to the precision.  Trailing zeros are removed from the
	 *     fractional part of the result; a decimal point appears only if it
	 *     is followed by at least one digit.
	 */
//	if (iWidth == -1) { iWidth = 6; }

	INT_32 iMode;
	INT_32 iExponent = 0;
	INT_32 iSign     = 0;
	CHAR_P szEnd     = NULL;
	INT_32 iFormatPrecision;
	if (oFmtSpecifier == F_FLOAT_F)
	{
		iMode = 3;
		if (iPrecision == -1) { iPrecision = 6; }

		iFormatPrecision = iPrecision;
	}
	// Only one decision left
	else /* if (oFmtSpecifier == F_FLOAT_G) */
	{
		iMode = 2;
		if      (iPrecision == -1) { iPrecision = 6; }
		else if (iPrecision ==  0) { iPrecision = 1; }

		iFormatPrecision = iPrecision + 1;
	}

	Bigint *freelist[Kmax+1];
	for (UINT_32 iPos = 0; iPos <= Kmax; ++iPos) { freelist[iPos] = NULL; }

	W_FLOAT dData = oCurrentArgument.GetFloat();
	AllocatedBlock * aBlocks = NULL;

	CHAR_P szBuffer = ctpp_dtoa(&aBlocks, freelist, dData, iMode, iFormatPrecision, &iExponent, &iSign, &szEnd);
	bool bIsNegative = iSign < 0;
	--iExponent;

	INT_32 iPos = szEnd - szBuffer;

	// Data length
	INT_32 iFormattedLength;
	if (oFmtSpecifier == F_FLOAT_F)
	{
		if (iExponent < 0)
		{
			iFormattedLength = iPrecision + 2;
		}
		else
		{
			iFormattedLength = iPrecision + iExponent + 1;
		}

	}
	else /* if (oFmtSpecifier == F_FLOAT_G) */
	{
		/*
		 *  Style e is used if the
		 *  exponent from its conversion is less than -4 or greater than or
		 *  equal to the precision.
		 */
		if (iExponent < -4 || iExponent >= iPrecision)
		{
			// Free memory
			freedtoa(&aBlocks);

			if (iWidth == -1) { iWidth = 6; }
			FmtSci(oBuffer, oCurrentArgument, iFmtFlags, oFmtLengths, chExponentSymbol, iWidth, iPrecision, chPadSymbol);
			return;
		}

		if (iPos > iPrecision) { iPos = iPrecision; }
		else                   { iPrecision = iPos; }

		iFormattedLength = iPrecision;
		if (iExponent < 0) { iFormattedLength += 1 - iExponent; }
	}

	// Sign?
	if (bIsNegative || iFmtFlags & (F_FORCE_SIGN | F_SIGN_SPACE)) { ++iFormattedLength; }

	// Right-aligned
	if ((iFmtFlags & F_LEFT_ALIGN) != F_LEFT_ALIGN)
	{
		// Spaces, if need
		if (iWidth > iFormattedLength) { oBuffer.Append(iWidth - iFormattedLength, ' '); }
	}

	// Sign
	if      (bIsNegative)              { oBuffer.Append(1, '-'); }
	else if (iFmtFlags & F_FORCE_SIGN) { oBuffer.Append(1, '+'); }
	else if (iFmtFlags & F_SIGN_SPACE) { oBuffer.Append(1, ' '); }

	if (oFmtSpecifier == F_FLOAT_F)
	{
		// Value
		if (iExponent < 0)
		{
			const INT_32 iChars = iPrecision + iExponent + 1;

			oBuffer.Append(1, '0');
			oBuffer.Append(1, '.');
			oBuffer.Append(-iExponent - 1, '0');

			if (iChars > iPos)
			{
				oBuffer.Append(szBuffer, iPos);
				oBuffer.Append(iChars - iPos, '0');
			}
			else
			{
				oBuffer.Append(szBuffer, iChars);
			}
		}
		else
		{
			// Value
			oBuffer.Append(szBuffer, iExponent + 1);
			if (iPrecision > 0)
			{
				iPos -= iExponent;
				oBuffer.Append(1, '.');
				oBuffer.Append(szBuffer + iExponent + 1, iPos - 1);

				if (iPrecision + 1 > iPos)
				{
					oBuffer.Append(iPrecision - iPos + 1, '0');
				}
			}
		}
	}
	else /* if (oFmtSpecifier == F_FLOAT_G) */
	{
		// Value
		if (iExponent < 0)
		{
			const INT_32 iChars = (iPrecision < iPos) ? iPrecision : iPos;

			oBuffer.Append(1, '0');
			oBuffer.Append(1, '.');
			oBuffer.Append(- iExponent - 1, '0');
			oBuffer.Append(szBuffer, iChars);
		}
		else
		{
			oBuffer.Append(szBuffer, iExponent + 1);
			if (iPos > iExponent + 1)
			{
				oBuffer.Append(1, '.');
				oBuffer.Append(szBuffer + iExponent + 1, iPrecision - iExponent - 1);
			}
		}
	}

	// Free memory
	freedtoa(&aBlocks);

	// Left-aligned
	if ((iFmtFlags & F_LEFT_ALIGN) == F_LEFT_ALIGN)
	{
		// Spaces, if need
		if (iWidth > iFormattedLength) { oBuffer.Append(iWidth - iFormattedLength, ' '); }
	}
}
//
// Scientific
//
static void FmtSci(StringBuffer       & oBuffer,
                   const CDT          & oCurrentArgument,
                   const UINT_32        iFmtFlags,
                   const eFmtLengths  & oFmtLengths,
                   const CHAR_8         chExponentSymbol,
                   INT_32               iWidth,
                   INT_32               iPrecision,
                   CHAR_8               chPadSymbol)
{
	using namespace CTPP;

	/*
	 * eE  The double argument is rounded and converted in the style
	 *     [-]d.ddde+-dd where there is one digit before the decimal-point
	 *     character and the number of digits after it is equal to the pre-
	 *     cision; if the precision is missing, it is taken as 6; if the
	 *     precision is zero, no decimal-point character appears.  An E con-
	 *     version uses the letter `E' (rather than `e') to introduce the
	 *     exponent.  The exponent always contains at least two digits; if
	 *     the value is zero, the exponent is 00.
	 */

	if (iPrecision == -1) { iPrecision = 6; }
	if (iWidth == -1)     { iWidth     = 6; }

	const INT_32   iMode     = 2;
	INT_32         iExponent = 0;
	INT_32         iSign     = 0;
	CHAR_P         szEnd     = NULL;

	Bigint *freelist[Kmax+1];
	for (UINT_32 iPos = 0; iPos <= Kmax; ++iPos) { freelist[iPos] = NULL; }

	W_FLOAT dData = oCurrentArgument.GetFloat();
	AllocatedBlock * aBlocks = NULL;

	CHAR_P szBuffer = ctpp_dtoa(&aBlocks, freelist, dData, iMode, iPrecision, &iExponent, &iSign, &szEnd);
	bool bIsNegative = iSign < 0;
	--iExponent;

	// Format Exponent
	CHAR_8 szExponentBuffer[C_INT_BUFFER_LEN + 1];
	szExponentBuffer[C_INT_BUFFER_LEN] = 0;
	bool bExponentIsNegative = false;
	// Signed
	INT_32 iExponentPos = DoFormat<INT_32>(iExponent, 10, szDigitsUc, szExponentBuffer, bExponentIsNegative);

	// Atleast 2 digits in exponent
	if (iExponentPos == 1)
	{
		iExponentPos = 2;
		szExponentBuffer[C_INT_BUFFER_LEN - 2] = '0';
	}

	++iExponentPos;
	// Add exponent sign
	szExponentBuffer[C_INT_BUFFER_LEN - iExponentPos] = bExponentIsNegative ? '-' : '+';
	// Add exponent char
	++iExponentPos;
	szExponentBuffer[C_INT_BUFFER_LEN - iExponentPos] = chExponentSymbol;

	INT_32 iPos = szEnd - szBuffer;

	// Data length
	INT_32 iFormattedLength = iExponentPos + 1;
	//;// = iPos + iExponentPos + 1;
	// Precision
	if (iPrecision > iPos)
	{
		//iFormattedLength += (iPrecision - iPos);
		iFormattedLength += iPrecision;
	}
	else
	{
		iPos = iPrecision;
		iFormattedLength += iPos;
	}

	// Sign?
	if (bIsNegative || iFmtFlags & (F_FORCE_SIGN | F_SIGN_SPACE)) { ++iFormattedLength; }

	// Right-aligned
	if ((iFmtFlags & F_LEFT_ALIGN) != F_LEFT_ALIGN)
	{
		// Spaces, if need
		if (iWidth > iFormattedLength) { oBuffer.Append(iWidth - iFormattedLength, ' '); }
	}

	// Sign
	if      (bIsNegative)              { oBuffer.Append(1, '-'); }
	else if (iFmtFlags & F_FORCE_SIGN) { oBuffer.Append(1, '+'); }
	else if (iFmtFlags & F_SIGN_SPACE) { oBuffer.Append(1, ' '); }

	// Value
	oBuffer.Append(szBuffer, 1);
	oBuffer.Append(1, '.');
	oBuffer.Append(szBuffer + 1, iPos - 1);

	// Free memory
	freedtoa(&aBlocks);

	// Zeroes, if need
	if (iPrecision > iPos) { oBuffer.Append(iPrecision - iPos, '0'); }
	// Exponent
	oBuffer.Append(szExponentBuffer + C_INT_BUFFER_LEN - iExponentPos, iExponentPos);

	// Left-aligned
	if ((iFmtFlags & F_LEFT_ALIGN) == F_LEFT_ALIGN)
	{
		// Spaces, if need
		if (iWidth > iFormattedLength) { oBuffer.Append(iWidth - iFormattedLength, ' '); }
	}
}