oleaut32: Fix VarParseNumFromStr()'s handling of currency decimals.

They have no default, flag the value as a monetary amount, are
unaffected by the presence / absence of a currency symbol, and are
incompatible with hexadecimal / octal numbers.

Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Francois Gouget 2021-08-08 00:49:04 +02:00 committed by Alexandre Julliard
parent fc5e603cd3
commit caf5ab5d65
2 changed files with 51 additions and 42 deletions

View file

@ -1548,11 +1548,8 @@ static void test_VarParseNumFromStrEn(void)
/* Only integers are allowed when using an alternative radix */
CONVERT("&ha.2", NUMPRS_HEX_OCT|NUMPRS_DECIMAL);
if (broken(1)) /* FIXME Reenable once Wine is less broken */
EXPECT(1,NUMPRS_HEX_OCT|NUMPRS_DECIMAL,NUMPRS_HEX_OCT,3,4,0);
todo_wine ok(np.dwOutFlags == NUMPRS_HEX_OCT, "Got dwOutFlags=%08x\n", np.dwOutFlags);
EXPECTRGB(0,10);
todo_wine EXPECTRGB(1,FAILDIG);
EXPECT2(10,FAILDIG);
/* Except if it looks like a plain decimal number */
CONVERT("01.2", NUMPRS_HEX_OCT|NUMPRS_DECIMAL);
@ -2318,9 +2315,8 @@ static void test_VarParseNumFromStrMisc(void)
/* But not for their monetary equivalents */
hres = wconvert_str(L"~1", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY, &np, rgb, LOCALE_USER_DEFAULT, 0);
todo_wine EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY,NUMPRS_DECIMAL|NUMPRS_CURRENCY,2,0,-1);
todo_wine EXPECTRGB(0,1);
EXPECTRGB(1,FAILDIG);
EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY,NUMPRS_DECIMAL|NUMPRS_CURRENCY,2,0,-1);
EXPECT2(1,FAILDIG);
hres = wconvert_str(L"1~", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,2,0,0);
@ -2355,11 +2351,8 @@ static void test_VarParseNumFromStrMisc(void)
EXPECTRGB(2,FAILDIG);
hres = wconvert_str(L"1,2", ARRAY_SIZE(rgb), NUMPRS_DECIMAL, &np, rgb, LOCALE_USER_DEFAULT, 0);
if (broken(1)) /* FIXME Reenable once Wine is less broken */
EXPECT(2,NUMPRS_DECIMAL,NUMPRS_DECIMAL|NUMPRS_CURRENCY,3,0,-1);
todo_wine ok(np.dwOutFlags == (NUMPRS_DECIMAL|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
EXPECTRGB(0,1);
todo_wine EXPECTRGB(1,2);
EXPECT2(1,2);
EXPECTRGB(2,FAILDIG);
hres = wconvert_str(L"1.2", ARRAY_SIZE(rgb), NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
@ -2368,11 +2361,8 @@ static void test_VarParseNumFromStrMisc(void)
EXPECTRGB(2,FAILDIG);
hres = wconvert_str(L"1,2", ARRAY_SIZE(rgb), NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
if (broken(1)) /* FIXME Reenable once Wine is less broken */
EXPECT(2,NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_DECIMAL|NUMPRS_CURRENCY,3,0,-1);
todo_wine ok(np.dwOutFlags == (NUMPRS_DECIMAL|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
EXPECTRGB(0,1);
todo_wine EXPECTRGB(1,2);
EXPECT2(1,2);
EXPECTRGB(2,FAILDIG);
hres = wconvert_str(L"1.2,3", ARRAY_SIZE(rgb), NUMPRS_DECIMAL|NUMPRS_CURRENCY, &np, rgb, LOCALE_USER_DEFAULT, 0);
@ -2381,11 +2371,8 @@ static void test_VarParseNumFromStrMisc(void)
EXPECTRGB(2,FAILDIG);
hres = wconvert_str(L"1,2.3", ARRAY_SIZE(rgb), NUMPRS_DECIMAL, &np, rgb, LOCALE_USER_DEFAULT, 0);
if (broken(1)) /* FIXME Reenable once Wine is less broken */
EXPECT(2,NUMPRS_DECIMAL,NUMPRS_DECIMAL|NUMPRS_CURRENCY,3,0,-1);
todo_wine ok(np.dwOutFlags == (NUMPRS_DECIMAL|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
EXPECTRGB(0,1);
todo_wine EXPECTRGB(1,2);
EXPECT2(1,2);
EXPECTRGB(2,FAILDIG);
@ -2394,10 +2381,9 @@ static void test_VarParseNumFromStrMisc(void)
*/
SetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONDECIMALSEP, L"$");
hres = wconvert_str(L"1$99", ARRAY_SIZE(rgb), NUMPRS_DECIMAL|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
todo_wine EXPECT(3,NUMPRS_DECIMAL|NUMPRS_USE_ALL,NUMPRS_DECIMAL|NUMPRS_CURRENCY,4,0,-2);
EXPECTRGB(0,1);
todo_wine EXPECTRGB(1,9);
todo_wine EXPECTRGB(2,9);
EXPECT(3,NUMPRS_DECIMAL|NUMPRS_USE_ALL,NUMPRS_DECIMAL|NUMPRS_CURRENCY,4,0,-2);
EXPECT2(1,9);
EXPECTRGB(2,9);
EXPECTRGB(3,FAILDIG);

View file

@ -1523,7 +1523,7 @@ typedef struct tagVARIANT_NUMBER_CHARS
/* Get the valid number characters for an lcid */
static void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
{
static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',0,1,{'$',0},'.',',' };
static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',0,1,{'$',0},0,',' };
LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
WCHAR buff[4];
@ -1630,7 +1630,31 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
/* First consume all the leading symbols and space from the string */
while (1)
{
if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && iswspace(*lpszStr))
if (pNumprs->dwInFlags & NUMPRS_DECIMAL &&
(*lpszStr == chars.cDecimalPoint ||
*lpszStr == chars.cCurrencyDecimalPoint))
{
pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
if (*lpszStr == chars.cCurrencyDecimalPoint &&
chars.cDecimalPoint != chars.cCurrencyDecimalPoint)
pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
cchUsed++;
lpszStr++;
/* If we have no digits so far, skip leading zeros */
if (!pNumprs->cDig)
{
while (lpszStr[1] == '0')
{
dwState |= B_LEADING_ZERO;
cchUsed++;
lpszStr++;
pNumprs->nPwr10--;
}
}
break;
}
else if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && iswspace(*lpszStr))
{
pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
do
@ -1673,8 +1697,6 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
cchUsed += chars.sCurrencyLen;
lpszStr += chars.sCurrencyLen;
/* Only accept currency characters */
chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
}
else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
!(pNumprs->dwOutFlags & NUMPRS_PARENS))
@ -1687,27 +1709,24 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
break;
}
if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
{
/* Only accept non-currency characters */
chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
}
if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
if (!(pNumprs->dwOutFlags & NUMPRS_DECIMAL))
{
if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
{
dwState |= B_PROCESSING_HEX;
pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
cchUsed=cchUsed+2;
lpszStr=lpszStr+2;
}
else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
{
}
else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
{
dwState |= B_PROCESSING_OCT;
pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
cchUsed=cchUsed+2;
lpszStr=lpszStr+2;
}
}
/* Strip Leading zeros */
@ -1796,11 +1815,15 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
pNumprs->dwOutFlags |= NUMPRS_THOUSANDS|NUMPRS_CURRENCY;
cchUsed++;
}
else if (*lpszStr == chars.cDecimalPoint &&
pNumprs->dwInFlags & NUMPRS_DECIMAL &&
!(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
else if (pNumprs->dwInFlags & NUMPRS_DECIMAL &&
(*lpszStr == chars.cDecimalPoint ||
*lpszStr == chars.cCurrencyDecimalPoint) &&
!(pNumprs->dwOutFlags & (NUMPRS_HEX_OCT|NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
{
pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
if (*lpszStr == chars.cCurrencyDecimalPoint &&
chars.cDecimalPoint != chars.cCurrencyDecimalPoint)
pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
cchUsed++;
/* If we have no digits so far, skip leading zeros */