[PATCH 2/2] oleaut32: Fix VarParseNumFromStr()'s handling of currency decimals.

Francois Gouget fgouget at codeweavers.com
Sat Aug 7 17:49:04 CDT 2021


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 at codeweavers.com>
---
 dlls/oleaut32/tests/vartest.c | 32 ++++++------------
 dlls/oleaut32/variant.c       | 61 ++++++++++++++++++++++++-----------
 2 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index 6dddc79e829..f6149005179 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -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);
 
 
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index fe4bdb41ed2..09c6f9dcad6 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -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 */
-- 
2.20.1



More information about the wine-devel mailing list