kernelbase: Reimplement GetCurrencyFormatW/Ex() using get_locale_info().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
56099a3124
commit
9afc20949a
|
@ -621,8 +621,8 @@
|
|||
@ stdcall -import GetConsoleTitleW(ptr long)
|
||||
@ stdcall -import GetConsoleWindow()
|
||||
@ stdcall GetCurrencyFormatA(long long str ptr ptr long)
|
||||
@ stdcall GetCurrencyFormatEx(wstr long wstr ptr ptr long)
|
||||
@ stdcall GetCurrencyFormatW(long long wstr ptr ptr long)
|
||||
@ stdcall -import GetCurrencyFormatEx(wstr long wstr ptr ptr long)
|
||||
@ stdcall -import GetCurrencyFormatW(long long wstr ptr ptr long)
|
||||
@ stdcall -import GetCurrentActCtx(ptr)
|
||||
@ stdcall -import GetCurrentConsoleFont(long long ptr)
|
||||
@ stdcall -import GetCurrentConsoleFontEx(long long ptr)
|
||||
|
|
|
@ -56,8 +56,6 @@ typedef struct _NLS_FORMAT_NODE
|
|||
LCID lcid; /* Locale Id */
|
||||
DWORD dwFlags; /* 0 or LOCALE_NOUSEROVERRIDE */
|
||||
DWORD dwCodePage; /* Default code page (if LOCALE_USE_ANSI_CP not given) */
|
||||
NUMBERFMTW fmt; /* Default format for numbers */
|
||||
CURRENCYFMTW cyfmt; /* Default format for currencies */
|
||||
LPWSTR lppszStrings[NLS_NUM_CACHED_STRINGS]; /* Default formats,day/month names */
|
||||
WCHAR szShortAM[2]; /* Short 'AM' marker */
|
||||
WCHAR szShortPM[2]; /* Short 'PM' marker */
|
||||
|
@ -208,52 +206,6 @@ static const NLS_FORMAT_NODE *NLS_GetFormats(LCID lcid, DWORD dwFlags)
|
|||
new_node->dwFlags = dwFlags;
|
||||
new_node->next = NULL;
|
||||
|
||||
GET_LOCALE_NUMBER(new_node->fmt.NumDigits, LOCALE_IDIGITS);
|
||||
GET_LOCALE_NUMBER(new_node->fmt.LeadingZero, LOCALE_ILZERO);
|
||||
GET_LOCALE_NUMBER(new_node->fmt.NegativeOrder, LOCALE_INEGNUMBER);
|
||||
|
||||
GET_LOCALE_NUMBER(new_node->fmt.Grouping, LOCALE_SGROUPING);
|
||||
if (new_node->fmt.Grouping > 9 && new_node->fmt.Grouping != 32)
|
||||
{
|
||||
WARN("LOCALE_SGROUPING (%d) unhandled, please report!\n",
|
||||
new_node->fmt.Grouping);
|
||||
new_node->fmt.Grouping = 0;
|
||||
}
|
||||
|
||||
GET_LOCALE_STRING(new_node->fmt.lpDecimalSep, LOCALE_SDECIMAL);
|
||||
GET_LOCALE_STRING(new_node->fmt.lpThousandSep, LOCALE_STHOUSAND);
|
||||
|
||||
/* Currency Format */
|
||||
new_node->cyfmt.NumDigits = new_node->fmt.NumDigits;
|
||||
new_node->cyfmt.LeadingZero = new_node->fmt.LeadingZero;
|
||||
|
||||
GET_LOCALE_NUMBER(new_node->cyfmt.Grouping, LOCALE_SGROUPING);
|
||||
|
||||
if (new_node->cyfmt.Grouping > 9)
|
||||
{
|
||||
WARN("LOCALE_SMONGROUPING (%d) unhandled, please report!\n",
|
||||
new_node->cyfmt.Grouping);
|
||||
new_node->cyfmt.Grouping = 0;
|
||||
}
|
||||
|
||||
GET_LOCALE_NUMBER(new_node->cyfmt.NegativeOrder, LOCALE_INEGCURR);
|
||||
if (new_node->cyfmt.NegativeOrder > 15)
|
||||
{
|
||||
WARN("LOCALE_INEGCURR (%d) unhandled, please report!\n",
|
||||
new_node->cyfmt.NegativeOrder);
|
||||
new_node->cyfmt.NegativeOrder = 0;
|
||||
}
|
||||
GET_LOCALE_NUMBER(new_node->cyfmt.PositiveOrder, LOCALE_ICURRENCY);
|
||||
if (new_node->cyfmt.PositiveOrder > 3)
|
||||
{
|
||||
WARN("LOCALE_IPOSCURR (%d) unhandled,please report!\n",
|
||||
new_node->cyfmt.PositiveOrder);
|
||||
new_node->cyfmt.PositiveOrder = 0;
|
||||
}
|
||||
GET_LOCALE_STRING(new_node->cyfmt.lpDecimalSep, LOCALE_SMONDECIMALSEP);
|
||||
GET_LOCALE_STRING(new_node->cyfmt.lpThousandSep, LOCALE_SMONTHOUSANDSEP);
|
||||
GET_LOCALE_STRING(new_node->cyfmt.lpCurrencySymbol, LOCALE_SCURRENCY);
|
||||
|
||||
/* Date/Time Format info, negative character, etc */
|
||||
for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++)
|
||||
{
|
||||
|
@ -301,11 +253,6 @@ static const NLS_FORMAT_NODE *NLS_GetFormats(LCID lcid, DWORD dwFlags)
|
|||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++)
|
||||
HeapFree(GetProcessHeap(), 0, new_node->lppszStrings[i]);
|
||||
HeapFree(GetProcessHeap(), 0, new_node->fmt.lpDecimalSep);
|
||||
HeapFree(GetProcessHeap(), 0, new_node->fmt.lpThousandSep);
|
||||
HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpDecimalSep);
|
||||
HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpThousandSep);
|
||||
HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpCurrencySymbol);
|
||||
HeapFree(GetProcessHeap(), 0, new_node);
|
||||
}
|
||||
}
|
||||
|
@ -985,321 +932,3 @@ INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime,
|
|||
return NLS_GetDateTimeFormatW(lcid, dwFlags|TIME_TIMEVARSONLY, lpTime,
|
||||
lpFormat, lpTimeStr, cchOut);
|
||||
}
|
||||
|
||||
/* Number parsing state flags */
|
||||
#define NF_ISNEGATIVE 0x1 /* '-' found */
|
||||
#define NF_ISREAL 0x2 /* '.' found */
|
||||
#define NF_DIGITS 0x4 /* '0'-'9' found */
|
||||
#define NF_DIGITS_OUT 0x8 /* Digits before the '.' found */
|
||||
#define NF_ROUND 0x10 /* Number needs to be rounded */
|
||||
|
||||
/* Formatting states for Currencies. We use flags to avoid code duplication. */
|
||||
#define CF_PARENS 0x1 /* Parentheses */
|
||||
#define CF_MINUS_LEFT 0x2 /* '-' to the left */
|
||||
#define CF_MINUS_RIGHT 0x4 /* '-' to the right */
|
||||
#define CF_MINUS_BEFORE 0x8 /* '-' before '$' */
|
||||
#define CF_CY_LEFT 0x10 /* '$' to the left */
|
||||
#define CF_CY_RIGHT 0x20 /* '$' to the right */
|
||||
#define CF_CY_SPACE 0x40 /* ' ' by '$' */
|
||||
|
||||
/**************************************************************************
|
||||
* GetCurrencyFormatW (KERNEL32.@)
|
||||
*
|
||||
* See GetCurrencyFormatA.
|
||||
*/
|
||||
INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags,
|
||||
LPCWSTR lpszValue, const CURRENCYFMTW *lpFormat,
|
||||
LPWSTR lpCurrencyStr, int cchOut)
|
||||
{
|
||||
static const BYTE NLS_NegCyFormats[16] =
|
||||
{
|
||||
CF_PARENS|CF_CY_LEFT, /* ($1.1) */
|
||||
CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT, /* -$1.1 */
|
||||
CF_MINUS_LEFT|CF_CY_LEFT, /* $-1.1 */
|
||||
CF_MINUS_RIGHT|CF_CY_LEFT, /* $1.1- */
|
||||
CF_PARENS|CF_CY_RIGHT, /* (1.1$) */
|
||||
CF_MINUS_LEFT|CF_CY_RIGHT, /* -1.1$ */
|
||||
CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT, /* 1.1-$ */
|
||||
CF_MINUS_RIGHT|CF_CY_RIGHT, /* 1.1$- */
|
||||
CF_MINUS_LEFT|CF_CY_RIGHT|CF_CY_SPACE, /* -1.1 $ */
|
||||
CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT|CF_CY_SPACE, /* -$ 1.1 */
|
||||
CF_MINUS_RIGHT|CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $- */
|
||||
CF_MINUS_RIGHT|CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1- */
|
||||
CF_MINUS_LEFT|CF_CY_LEFT|CF_CY_SPACE, /* $ -1.1 */
|
||||
CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT|CF_CY_SPACE, /* 1.1- $ */
|
||||
CF_PARENS|CF_CY_LEFT|CF_CY_SPACE, /* ($ 1.1) */
|
||||
CF_PARENS|CF_CY_RIGHT|CF_CY_SPACE, /* (1.1 $) */
|
||||
};
|
||||
static const BYTE NLS_PosCyFormats[4] =
|
||||
{
|
||||
CF_CY_LEFT, /* $1.1 */
|
||||
CF_CY_RIGHT, /* 1.1$ */
|
||||
CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1 */
|
||||
CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $ */
|
||||
};
|
||||
WCHAR szBuff[128], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1;
|
||||
WCHAR szNegBuff[8];
|
||||
const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc, *lpszCy, *lpszCyStart;
|
||||
DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0, dwFmt;
|
||||
INT iRet;
|
||||
|
||||
TRACE("(0x%04lx,0x%08lx,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue),
|
||||
lpFormat, lpCurrencyStr, cchOut);
|
||||
|
||||
lcid = ConvertDefaultLocale(lcid);
|
||||
if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpCurrencyStr) ||
|
||||
!IsValidLocale(lcid, 0) ||
|
||||
(lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep ||
|
||||
!lpFormat->lpCurrencySymbol || lpFormat->NegativeOrder > 15 ||
|
||||
lpFormat->PositiveOrder > 3)))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!lpFormat)
|
||||
{
|
||||
const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags);
|
||||
|
||||
if (!node)
|
||||
goto error;
|
||||
|
||||
lpFormat = &node->cyfmt;
|
||||
lpszNegStart = lpszNeg = GetNegative(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetLocaleInfoW(lcid, LOCALE_SNEGATIVESIGN|(dwFlags & LOCALE_NOUSEROVERRIDE),
|
||||
szNegBuff, ARRAY_SIZE(szNegBuff));
|
||||
lpszNegStart = lpszNeg = szNegBuff;
|
||||
}
|
||||
dwFlags &= (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP);
|
||||
|
||||
lpszNeg = lpszNeg + lstrlenW(lpszNeg) - 1;
|
||||
lpszCyStart = lpFormat->lpCurrencySymbol;
|
||||
lpszCy = lpszCyStart + lstrlenW(lpszCyStart) - 1;
|
||||
|
||||
/* Format the currency backwards into a temporary buffer */
|
||||
|
||||
szSrc = lpszValue;
|
||||
*szOut-- = '\0';
|
||||
|
||||
/* Check the number for validity */
|
||||
while (*szSrc)
|
||||
{
|
||||
if (*szSrc >= '0' && *szSrc <= '9')
|
||||
{
|
||||
dwState |= NF_DIGITS;
|
||||
if (dwState & NF_ISREAL)
|
||||
dwDecimals++;
|
||||
}
|
||||
else if (*szSrc == '-')
|
||||
{
|
||||
if (dwState)
|
||||
goto error; /* '-' not first character */
|
||||
dwState |= NF_ISNEGATIVE;
|
||||
}
|
||||
else if (*szSrc == '.')
|
||||
{
|
||||
if (dwState & NF_ISREAL)
|
||||
goto error; /* More than one '.' */
|
||||
dwState |= NF_ISREAL;
|
||||
}
|
||||
else
|
||||
goto error; /* Invalid char */
|
||||
szSrc++;
|
||||
}
|
||||
szSrc--; /* Point to last character */
|
||||
|
||||
if (!(dwState & NF_DIGITS))
|
||||
goto error; /* No digits */
|
||||
|
||||
if (dwState & NF_ISNEGATIVE)
|
||||
dwFmt = NLS_NegCyFormats[lpFormat->NegativeOrder];
|
||||
else
|
||||
dwFmt = NLS_PosCyFormats[lpFormat->PositiveOrder];
|
||||
|
||||
/* Add any trailing negative or currency signs */
|
||||
if (dwFmt & CF_PARENS)
|
||||
*szOut-- = ')';
|
||||
|
||||
while (dwFmt & (CF_MINUS_RIGHT|CF_CY_RIGHT))
|
||||
{
|
||||
switch (dwFmt & (CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT))
|
||||
{
|
||||
case CF_MINUS_RIGHT:
|
||||
case CF_MINUS_RIGHT|CF_CY_RIGHT:
|
||||
while (lpszNeg >= lpszNegStart)
|
||||
*szOut-- = *lpszNeg--;
|
||||
dwFmt &= ~CF_MINUS_RIGHT;
|
||||
break;
|
||||
|
||||
case CF_CY_RIGHT:
|
||||
case CF_MINUS_BEFORE|CF_CY_RIGHT:
|
||||
case CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT:
|
||||
while (lpszCy >= lpszCyStart)
|
||||
*szOut-- = *lpszCy--;
|
||||
if (dwFmt & CF_CY_SPACE)
|
||||
*szOut-- = ' ';
|
||||
dwFmt &= ~(CF_CY_RIGHT|CF_MINUS_BEFORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy all digits up to the decimal point */
|
||||
if (!lpFormat->NumDigits)
|
||||
{
|
||||
if (dwState & NF_ISREAL)
|
||||
{
|
||||
while (*szSrc != '.') /* Don't write any decimals or a separator */
|
||||
{
|
||||
if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
|
||||
dwState |= NF_ROUND;
|
||||
else
|
||||
dwState &= ~NF_ROUND;
|
||||
szSrc--;
|
||||
}
|
||||
szSrc--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LPWSTR lpszDec = lpFormat->lpDecimalSep + lstrlenW(lpFormat->lpDecimalSep) - 1;
|
||||
|
||||
if (dwDecimals <= lpFormat->NumDigits)
|
||||
{
|
||||
dwDecimals = lpFormat->NumDigits - dwDecimals;
|
||||
while (dwDecimals--)
|
||||
*szOut-- = '0'; /* Pad to correct number of dp */
|
||||
}
|
||||
else
|
||||
{
|
||||
dwDecimals -= lpFormat->NumDigits;
|
||||
/* Skip excess decimals, and determine if we have to round the number */
|
||||
while (dwDecimals--)
|
||||
{
|
||||
if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
|
||||
dwState |= NF_ROUND;
|
||||
else
|
||||
dwState &= ~NF_ROUND;
|
||||
szSrc--;
|
||||
}
|
||||
}
|
||||
|
||||
if (dwState & NF_ISREAL)
|
||||
{
|
||||
while (*szSrc != '.')
|
||||
{
|
||||
if (dwState & NF_ROUND)
|
||||
{
|
||||
if (*szSrc == '9')
|
||||
*szOut-- = '0'; /* continue rounding */
|
||||
else
|
||||
{
|
||||
dwState &= ~NF_ROUND;
|
||||
*szOut-- = (*szSrc)+1;
|
||||
}
|
||||
szSrc--;
|
||||
}
|
||||
else
|
||||
*szOut-- = *szSrc--; /* Write existing decimals */
|
||||
}
|
||||
szSrc--; /* Skip '.' */
|
||||
}
|
||||
while (lpszDec >= lpFormat->lpDecimalSep)
|
||||
*szOut-- = *lpszDec--; /* Write decimal separator */
|
||||
}
|
||||
|
||||
dwGroupCount = lpFormat->Grouping;
|
||||
|
||||
/* Write the remaining whole number digits, including grouping chars */
|
||||
while (szSrc >= lpszValue && *szSrc >= '0' && *szSrc <= '9')
|
||||
{
|
||||
if (dwState & NF_ROUND)
|
||||
{
|
||||
if (*szSrc == '9')
|
||||
*szOut-- = '0'; /* continue rounding */
|
||||
else
|
||||
{
|
||||
dwState &= ~NF_ROUND;
|
||||
*szOut-- = (*szSrc)+1;
|
||||
}
|
||||
szSrc--;
|
||||
}
|
||||
else
|
||||
*szOut-- = *szSrc--;
|
||||
|
||||
dwState |= NF_DIGITS_OUT;
|
||||
dwCurrentGroupCount++;
|
||||
if (szSrc >= lpszValue && dwCurrentGroupCount == dwGroupCount && *szSrc != '-')
|
||||
{
|
||||
LPWSTR lpszGrp = lpFormat->lpThousandSep + lstrlenW(lpFormat->lpThousandSep) - 1;
|
||||
|
||||
while (lpszGrp >= lpFormat->lpThousandSep)
|
||||
*szOut-- = *lpszGrp--; /* Write grouping char */
|
||||
|
||||
dwCurrentGroupCount = 0;
|
||||
}
|
||||
}
|
||||
if (dwState & NF_ROUND)
|
||||
*szOut-- = '1'; /* e.g. .6 > 1.0 */
|
||||
else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero)
|
||||
*szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */
|
||||
|
||||
/* Add any leading negative or currency sign */
|
||||
while (dwFmt & (CF_MINUS_LEFT|CF_CY_LEFT))
|
||||
{
|
||||
switch (dwFmt & (CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT))
|
||||
{
|
||||
case CF_MINUS_LEFT:
|
||||
case CF_MINUS_LEFT|CF_CY_LEFT:
|
||||
while (lpszNeg >= lpszNegStart)
|
||||
*szOut-- = *lpszNeg--;
|
||||
dwFmt &= ~CF_MINUS_LEFT;
|
||||
break;
|
||||
|
||||
case CF_CY_LEFT:
|
||||
case CF_CY_LEFT|CF_MINUS_BEFORE:
|
||||
case CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT:
|
||||
if (dwFmt & CF_CY_SPACE)
|
||||
*szOut-- = ' ';
|
||||
while (lpszCy >= lpszCyStart)
|
||||
*szOut-- = *lpszCy--;
|
||||
dwFmt &= ~(CF_CY_LEFT|CF_MINUS_BEFORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dwFmt & CF_PARENS)
|
||||
*szOut-- = '(';
|
||||
szOut++;
|
||||
|
||||
iRet = lstrlenW(szOut) + 1;
|
||||
if (cchOut)
|
||||
{
|
||||
if (iRet <= cchOut)
|
||||
memcpy(lpCurrencyStr, szOut, iRet * sizeof(WCHAR));
|
||||
else
|
||||
{
|
||||
memcpy(lpCurrencyStr, szOut, cchOut * sizeof(WCHAR));
|
||||
lpCurrencyStr[cchOut - 1] = '\0';
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
iRet = 0;
|
||||
}
|
||||
}
|
||||
return iRet;
|
||||
|
||||
error:
|
||||
SetLastError(lpFormat && dwFlags ? ERROR_INVALID_FLAGS : ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetCurrencyFormatEx (KERNEL32.@)
|
||||
*/
|
||||
int WINAPI GetCurrencyFormatEx(LPCWSTR localename, DWORD flags, LPCWSTR value,
|
||||
const CURRENCYFMTW *format, LPWSTR str, int len)
|
||||
{
|
||||
TRACE("(%s,0x%08lx,%s,%p,%p,%d)\n", debugstr_w(localename), flags,
|
||||
debugstr_w(value), format, str, len);
|
||||
|
||||
return GetCurrencyFormatW( LocaleNameToLCID(localename, 0), flags, value, format, str, len);
|
||||
}
|
||||
|
|
|
@ -1307,6 +1307,18 @@ static void test_GetCurrencyFormatA(void)
|
|||
ret = GetCurrencyFormatA(lcid, 0, "235", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$235.0");
|
||||
|
||||
format.Grouping = 31;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "1234567890", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$1,2,3,4,5,6,7,890.0");
|
||||
|
||||
format.Grouping = 312;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "1234567890", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$12,34,56,7,890.0");
|
||||
|
||||
format.Grouping = 310;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "1234567890", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$123456,7,890.0");
|
||||
|
||||
/* Grouping of a negative number */
|
||||
format.NegativeOrder = 2;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "-235", &format, buffer, ARRAY_SIZE(buffer));
|
||||
|
@ -1316,6 +1328,14 @@ static void test_GetCurrencyFormatA(void)
|
|||
format.LeadingZero = 1;
|
||||
ret = GetCurrencyFormatA(lcid, 0, ".5", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$0.5");
|
||||
ret = GetCurrencyFormatA(lcid, 0, "0.5", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$0.5");
|
||||
|
||||
format.LeadingZero = 0;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "0.5", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$.5");
|
||||
ret = GetCurrencyFormatA(lcid, 0, "0.5", &format, buffer, ARRAY_SIZE(buffer));
|
||||
expect_str(ret, buffer, "$.5");
|
||||
|
||||
format.PositiveOrder = CY_POS_RIGHT;
|
||||
ret = GetCurrencyFormatA(lcid, 0, "1", &format, buffer, ARRAY_SIZE(buffer));
|
||||
|
|
|
@ -473,8 +473,8 @@
|
|||
@ stdcall GetConsoleTitleA(ptr long)
|
||||
@ stdcall GetConsoleTitleW(ptr long)
|
||||
@ stdcall GetConsoleWindow()
|
||||
@ stdcall GetCurrencyFormatEx(wstr long wstr ptr ptr long) kernel32.GetCurrencyFormatEx
|
||||
@ stdcall GetCurrencyFormatW(long long wstr ptr ptr long) kernel32.GetCurrencyFormatW
|
||||
@ stdcall GetCurrencyFormatEx(wstr long wstr ptr ptr long)
|
||||
@ stdcall GetCurrencyFormatW(long long wstr ptr ptr long)
|
||||
@ stdcall GetCurrentActCtx(ptr)
|
||||
# @ stub GetCurrentApplicationUserModelId
|
||||
@ stdcall GetCurrentConsoleFont(long long ptr)
|
||||
|
|
|
@ -6655,6 +6655,172 @@ static int get_number_format( const NLS_LOCALE_DATA *locale, DWORD flags, const
|
|||
}
|
||||
|
||||
|
||||
static int get_currency_format( const NLS_LOCALE_DATA *locale, DWORD flags, const WCHAR *value,
|
||||
const CURRENCYFMTW *format, WCHAR *buffer, int len )
|
||||
{
|
||||
WCHAR *num, fmt_decimal[4], fmt_thousand[4], fmt_symbol[13], fmt_neg[5], grouping[20], output[256];
|
||||
const WCHAR *decimal_sep = fmt_decimal, *thousand_sep = fmt_thousand, *symbol = fmt_symbol;
|
||||
DWORD digits, lzero, pos_order, neg_order;
|
||||
int ret = 0;
|
||||
BOOL negative = (*value == '-');
|
||||
|
||||
flags &= LOCALE_NOUSEROVERRIDE;
|
||||
|
||||
if (!format)
|
||||
{
|
||||
get_locale_info( locale, 0, LOCALE_SCURRENCY | flags, fmt_symbol, ARRAY_SIZE(fmt_symbol) );
|
||||
get_locale_info( locale, 0, LOCALE_SMONGROUPING | flags, grouping, ARRAY_SIZE(grouping) );
|
||||
get_locale_info( locale, 0, LOCALE_SMONDECIMALSEP | flags, fmt_decimal, ARRAY_SIZE(fmt_decimal) );
|
||||
get_locale_info( locale, 0, LOCALE_SMONTHOUSANDSEP | flags, fmt_thousand, ARRAY_SIZE(fmt_thousand) );
|
||||
get_locale_info( locale, 0, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER | flags,
|
||||
(WCHAR *)&digits, sizeof(DWORD)/sizeof(WCHAR) );
|
||||
get_locale_info( locale, 0, LOCALE_ILZERO | LOCALE_RETURN_NUMBER | flags,
|
||||
(WCHAR *)&lzero, sizeof(DWORD)/sizeof(WCHAR) );
|
||||
get_locale_info( locale, 0, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER | flags,
|
||||
(WCHAR *)&pos_order, sizeof(DWORD)/sizeof(WCHAR) );
|
||||
get_locale_info( locale, 0, LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | flags,
|
||||
(WCHAR *)&neg_order, sizeof(DWORD)/sizeof(WCHAR) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_FLAGS );
|
||||
return 0;
|
||||
}
|
||||
decimal_sep = format->lpDecimalSep;
|
||||
thousand_sep = format->lpThousandSep;
|
||||
symbol = format->lpCurrencySymbol;
|
||||
grouping_to_string( format->Grouping, grouping );
|
||||
digits = format->NumDigits;
|
||||
lzero = format->LeadingZero;
|
||||
pos_order = format->PositiveOrder;
|
||||
neg_order = format->NegativeOrder;
|
||||
if (!decimal_sep || !thousand_sep || !symbol)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (negative)
|
||||
{
|
||||
value++;
|
||||
get_locale_info( locale, 0, LOCALE_SNEGATIVESIGN | flags, fmt_neg, ARRAY_SIZE(fmt_neg) );
|
||||
}
|
||||
|
||||
if (!(num = format_number( output + ARRAY_SIZE(output) - 20, value,
|
||||
decimal_sep, thousand_sep, grouping, digits, lzero )))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (negative)
|
||||
{
|
||||
switch (neg_order)
|
||||
{
|
||||
case 14: /* ($ 1.1) */
|
||||
num = prepend_str( num, L" " );
|
||||
/* fall through */
|
||||
case 0: /* ($1.1) */
|
||||
num = prepend_str( num, symbol );
|
||||
num = prepend_str( num, L"(" );
|
||||
wcscat( num, L")" );
|
||||
break;
|
||||
case 9: /* -$ 1.1 */
|
||||
num = prepend_str( num, L" " );
|
||||
/* fall through */
|
||||
case 1: /* -$1.1 */
|
||||
num = prepend_str( num, symbol );
|
||||
num = prepend_str( num, fmt_neg );
|
||||
break;
|
||||
case 2: /* $-1.1 */
|
||||
num = prepend_str( num, fmt_neg );
|
||||
num = prepend_str( num, symbol );
|
||||
break;
|
||||
case 11: /* $ 1.1- */
|
||||
num = prepend_str( num, L" " );
|
||||
/* fall through */
|
||||
case 3: /* $1.1- */
|
||||
num = prepend_str( num, symbol );
|
||||
wcscat( num, fmt_neg );
|
||||
break;
|
||||
case 15: /* (1.1 $) */
|
||||
wcscat( num, L" " );
|
||||
/* fall through */
|
||||
case 4: /* (1.1$) */
|
||||
wcscat( num, symbol );
|
||||
num = prepend_str( num, L"(" );
|
||||
wcscat( num, L")" );
|
||||
break;
|
||||
case 8: /* -1.1 $ */
|
||||
wcscat( num, L" " );
|
||||
/* fall through */
|
||||
case 5: /* -1.1$ */
|
||||
num = prepend_str( num, fmt_neg );
|
||||
wcscat( num, symbol );
|
||||
break;
|
||||
case 6: /* 1.1-$ */
|
||||
wcscat( num, fmt_neg );
|
||||
wcscat( num, symbol );
|
||||
break;
|
||||
case 10: /* 1.1 $- */
|
||||
wcscat( num, L" " );
|
||||
/* fall through */
|
||||
case 7: /* 1.1$- */
|
||||
wcscat( num, symbol );
|
||||
wcscat( num, fmt_neg );
|
||||
break;
|
||||
case 12: /* $ -1.1 */
|
||||
num = prepend_str( num, fmt_neg );
|
||||
num = prepend_str( num, L" " );
|
||||
num = prepend_str( num, symbol );
|
||||
break;
|
||||
case 13: /* 1.1- $ */
|
||||
wcscat( num, fmt_neg );
|
||||
wcscat( num, L" " );
|
||||
wcscat( num, symbol );
|
||||
break;
|
||||
default:
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pos_order)
|
||||
{
|
||||
case 2: /* $ 1.1 */
|
||||
num = prepend_str( num, L" " );
|
||||
/* fall through */
|
||||
case 0: /* $1.1 */
|
||||
num = prepend_str( num, symbol );
|
||||
break;
|
||||
case 3: /* 1.1 $ */
|
||||
wcscat( num, L" " );
|
||||
/* fall through */
|
||||
case 1: /* 1.1$ */
|
||||
wcscat( num, symbol );
|
||||
break;
|
||||
default:
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wcslen( num ) + 1;
|
||||
if (!len) return ret;
|
||||
lstrcpynW( buffer, num, len );
|
||||
if (ret > len)
|
||||
{
|
||||
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetNumberFormatW (kernelbase.@)
|
||||
*/
|
||||
|
@ -6692,3 +6858,42 @@ int WINAPI GetNumberFormatEx( const WCHAR *name, DWORD flags, const WCHAR *value
|
|||
TRACE( "(%s,%lx,%s,%p,%p,%d)\n", debugstr_w(name), flags, debugstr_w(value), format, buffer, len );
|
||||
return get_number_format( locale, flags, value, format, buffer, len );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetCurrencyFormatW (kernelbase.@)
|
||||
*/
|
||||
int WINAPI GetCurrencyFormatW( LCID lcid, DWORD flags, const WCHAR *value,
|
||||
const CURRENCYFMTW *format, WCHAR *buffer, int len )
|
||||
{
|
||||
const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
|
||||
|
||||
if (len < 0 || (len && !buffer) || !value || !locale)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE( "(%04lx,%lx,%s,%p,%p,%d)\n", lcid, flags, debugstr_w(value), format, buffer, len );
|
||||
return get_currency_format( locale, flags, value, format, buffer, len );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetCurrencyFormatEx (kernelbase.@)
|
||||
*/
|
||||
int WINAPI GetCurrencyFormatEx( const WCHAR *name, DWORD flags, const WCHAR *value,
|
||||
const CURRENCYFMTW *format, WCHAR *buffer, int len )
|
||||
{
|
||||
LCID lcid;
|
||||
const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
|
||||
|
||||
if (len < 0 || (len && !buffer) || !value || !locale)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE( "(%s,%lx,%s,%p,%p,%d)\n", debugstr_w(name), flags, debugstr_w(value), format, buffer, len );
|
||||
return get_currency_format( locale, flags, value, format, buffer, len );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue