kernel32: Reimplement GetNumberFormatA().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-05-03 10:35:27 +02:00
parent 88a91169c5
commit b6bf69ef80
2 changed files with 53 additions and 90 deletions

View File

@ -986,96 +986,6 @@ INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime,
lpFormat, lpTimeStr, cchOut);
}
/**************************************************************************
* GetNumberFormatA (KERNEL32.@)
*
* Format a number string for a given locale.
*
* PARAMS
* lcid [I] Locale to format for
* dwFlags [I] LOCALE_ flags from "winnls.h"
* lpszValue [I] String to format
* lpFormat [I] Formatting overrides
* lpNumberStr [O] Destination for formatted string
* cchOut [I] Size of lpNumberStr, or 0 to calculate the resulting size
*
* NOTES
* - lpszValue can contain only '0' - '9', '-' and '.'.
* - If lpFormat is non-NULL, dwFlags must be 0. In this case lpszValue will
* be formatted according to the format details returned by GetLocaleInfoA().
* - This function rounds the number string if the number of decimals exceeds the
* locales normal number of decimal places.
* - If cchOut is 0, this function does not write to lpNumberStr.
* - The ANSI version of this function fails if lcid is Unicode only.
*
* RETURNS
* Success: The number of character written to lpNumberStr, or that would
* have been written, if cchOut is 0.
* Failure: 0. Use GetLastError() to determine the cause.
*/
INT WINAPI GetNumberFormatA(LCID lcid, DWORD dwFlags,
LPCSTR lpszValue, const NUMBERFMTA *lpFormat,
LPSTR lpNumberStr, int cchOut)
{
DWORD cp = CP_ACP;
WCHAR szDec[8], szGrp[8], szIn[128], szOut[128];
NUMBERFMTW fmt;
const NUMBERFMTW *pfmt = NULL;
INT iRet;
TRACE("(0x%04lx,0x%08lx,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_a(lpszValue),
lpFormat, lpNumberStr, cchOut);
if (NLS_IsUnicodeOnlyLcid(lcid))
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!(dwFlags & LOCALE_USE_CP_ACP))
{
const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags);
if (!node)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
cp = node->dwCodePage;
}
if (lpFormat)
{
memcpy(&fmt, lpFormat, sizeof(fmt));
pfmt = &fmt;
if (lpFormat->lpDecimalSep)
{
MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, ARRAY_SIZE(szDec));
fmt.lpDecimalSep = szDec;
}
if (lpFormat->lpThousandSep)
{
MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, ARRAY_SIZE(szGrp));
fmt.lpThousandSep = szGrp;
}
}
if (lpszValue)
MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, ARRAY_SIZE(szIn));
if (cchOut > (int) ARRAY_SIZE(szOut))
cchOut = ARRAY_SIZE(szOut);
szOut[0] = '\0';
iRet = GetNumberFormatW(lcid, dwFlags, lpszValue ? szIn : NULL, pfmt,
lpNumberStr ? szOut : NULL, cchOut);
if (szOut[0] && lpNumberStr)
WideCharToMultiByte(cp, 0, szOut, -1, lpNumberStr, cchOut, 0, 0);
return iRet;
}
/* Number parsing state flags */
#define NF_ISNEGATIVE 0x1 /* '-' found */
#define NF_ISREAL 0x2 /* '.' found */

View File

@ -411,6 +411,59 @@ int WINAPI SetCalendarInfoA( LCID lcid, CALID id, CALTYPE type, LPCSTR data )
}
/**************************************************************************
* GetNumberFormatA (KERNEL32.@)
*/
int WINAPI GetNumberFormatA( LCID lcid, DWORD flags, const char *value,
const NUMBERFMTA *format, char *buffer, int len )
{
UINT cp = get_lcid_codepage( lcid, flags );
WCHAR input[128], output[128];
int ret;
TRACE( "(0x%04lx,0x%08lx,%s,%p,%p,%d)\n", lcid, flags, debugstr_a(value), format, buffer, len );
if (len < 0 || (len && !buffer) || !value)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
MultiByteToWideChar( cp, 0, value, -1, input, ARRAY_SIZE(input) );
if (len > (int)ARRAY_SIZE(output)) len = ARRAY_SIZE(output);
if (format)
{
NUMBERFMTW fmt;
WCHAR fmt_decimal[4], fmt_thousand[4];
if (flags & LOCALE_NOUSEROVERRIDE)
{
SetLastError( ERROR_INVALID_FLAGS );
return 0;
}
if (!format->lpDecimalSep || !format->lpThousandSep)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
MultiByteToWideChar( cp, 0, format->lpDecimalSep, -1, fmt_decimal, ARRAY_SIZE(fmt_decimal) );
MultiByteToWideChar( cp, 0, format->lpThousandSep, -1, fmt_thousand, ARRAY_SIZE(fmt_thousand) );
fmt.NumDigits = format->NumDigits;
fmt.LeadingZero = format->LeadingZero;
fmt.Grouping = format->Grouping;
fmt.NegativeOrder = format->NegativeOrder;
fmt.lpDecimalSep = fmt_decimal;
fmt.lpThousandSep = fmt_thousand;
ret = GetNumberFormatW( lcid, flags, input, &fmt, output, len );
}
else ret = GetNumberFormatW( lcid, flags, input, NULL, output, len );
if (ret) ret = WideCharToMultiByte( cp, 0, output, -1, buffer, len, 0, 0 );
return ret;
}
/******************************************************************************
* GetGeoInfoA (KERNEL32.@)
*/