Francois Gouget : oleaut32: Fix VarParseNumFromStr()'s handling of currency thousands separators.

Alexandre Julliard julliard at winehq.org
Fri Aug 6 16:10:39 CDT 2021


Module: wine
Branch: master
Commit: 9e4524ffb09be6bba828ea66b8fe1bb64b996b66
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=9e4524ffb09be6bba828ea66b8fe1bb64b996b66

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Fri Aug  6 12:53:09 2021 +0200

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

They are have no default, are not allowed before the first digit, are
unaffected by the presence / absence of a currency symbol, can be mixed
with regular digit separators, are incompatible with hexadecimal and
octal numbers (as are regular digit separators), and mask trailing
spaces.
Also they don't match regular spaces when set to a non-breaking space.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/oleaut32/tests/vartest.c | 19 +++++--------------
 dlls/oleaut32/variant.c       | 36 +++++++++++++++++++++++++++++++-----
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index ecc8e8b0f11..fbcfba32c80 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -1600,11 +1600,8 @@ static void test_VarParseNumFromStrEn(void)
 
   /* With flag, thousands sep. and following digits consumed */
   CONVERT("&h1,000", NUMPRS_HEX_OCT|NUMPRS_THOUSANDS);
-  if (broken(1)) /* FIXME Reenable once Wine is less broken */
   EXPECT(1,NUMPRS_HEX_OCT|NUMPRS_THOUSANDS,NUMPRS_HEX_OCT,3,4,0);
-  todo_wine ok(np.dwOutFlags == NUMPRS_HEX_OCT, "Got dwOutFlags=%08x\n", np.dwOutFlags);
-  EXPECTRGB(0,1);
-  todo_wine EXPECTRGB(1,FAILDIG);
+  EXPECTRGB(1,FAILDIG);
 
   /* With flag and decimal point, thousands sep. but not decimals consumed */
   CONVERT("1,001.0", NUMPRS_THOUSANDS);
@@ -2174,7 +2171,7 @@ static void test_VarParseNumFromStrMisc(void)
       SetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHOUSANDSEP, L"~");
       SetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, L"");
       hres = wconvert_str(L"1,000", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      todo_wine EXPECTFAIL;
+      EXPECTFAIL;
       SetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, L"~");
 
       /* But SMONTHOUSANDSEP defaults to ','! */
@@ -2236,9 +2233,7 @@ static void test_VarParseNumFromStrMisc(void)
       EXPECTRGB(4,FAILDIG);
 
       hres = wconvert_str(L"1 000", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      if (broken(1)) /* FIXME Reenable once Wine is less broken */
       EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,5,0,3);
-      todo_wine ok(np.dwOutFlags == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
       EXPECTRGB(0,1); /* Don't test extra digits, see "1,000" test */
       EXPECTRGB(4,FAILDIG);
 
@@ -2249,15 +2244,13 @@ static void test_VarParseNumFromStrMisc(void)
 
       /* But trailing ones are allowed (same as sThousand) */
       hres = wconvert_str(L"1 000 ", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      if (broken(1)) /* FIXME Reenable once Wine is less broken */
       EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,6,0,3);
-      todo_wine ok(np.dwOutFlags == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
       EXPECTRGB(0,1); /* Don't test extra digits, see "1,000" test */
       EXPECTRGB(4,FAILDIG);
 
       /* And they break NUMPRS_TRAILING_WHITE (same as sThousand) */
       hres = wconvert_str(L"1000 ", ARRAY_SIZE(rgb), NUMPRS_TRAILING_WHITE|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      todo_wine EXPECTFAIL;
+      EXPECTFAIL;
 
 
       /* NUMPRS_CURRENCY is not enough for sMonThousandSep */
@@ -2272,13 +2265,13 @@ static void test_VarParseNumFromStrMisc(void)
        */
       SetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONDECIMALSEP, L"/");
       hres = wconvert_str(L"$1|000", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      todo_wine EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,6,0,3);
+      EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,6,0,3);
       EXPECTRGB(0,1); /* Don't test extra digits, see "1,000" test */
       EXPECTRGB(4,FAILDIG);
 
       /* Mixing both thousands separators is allowed */
       hres = wconvert_str(L"1 000|000", ARRAY_SIZE(rgb), NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL, &np, rgb, LOCALE_USER_DEFAULT, 0);
-      todo_wine EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,9,0,6);
+      EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,9,0,6);
       EXPECTRGB(0,1); /* Don't test extra digits, see "1,000" test */
       EXPECTRGB(7,FAILDIG);
 
@@ -2330,9 +2323,7 @@ static void test_VarParseNumFromStrMisc(void)
       EXPECTRGB(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);
-      if (broken(1)) /* FIXME Reenable once Wine is less broken */
       EXPECT(1,NUMPRS_THOUSANDS|NUMPRS_DECIMAL|NUMPRS_CURRENCY|NUMPRS_USE_ALL,NUMPRS_THOUSANDS|NUMPRS_CURRENCY,2,0,0);
-      todo_wine ok(np.dwOutFlags == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY), "Got dwOutFlags=%08x\n", np.dwOutFlags);
       EXPECT2(1,FAILDIG);
 
 
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 264b9f6594b..2ec07817460 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -1510,7 +1510,7 @@ HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate)
 /* 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,'.',',' };
+  static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',0,'$',0,'.',',' };
   LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
   WCHAR buff[4];
 
@@ -1633,6 +1633,11 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
     {
       return DISP_E_TYPEMISMATCH; /* Not allowed before the first digit */
     }
+    else if ((pNumprs->dwInFlags & (NUMPRS_THOUSANDS|NUMPRS_CURRENCY)) == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY) &&
+             chars.cCurrencyDigitSeparator && *lpszStr == chars.cCurrencyDigitSeparator)
+    {
+      return DISP_E_TYPEMISMATCH; /* Not allowed before the first digit */
+    }
     else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
              *lpszStr == chars.cPositiveSymbol &&
              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
@@ -1659,8 +1664,6 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
       lpszStr += chars.cCurrencyLocal2 ? 2 : 1;
       /* Only accept currency characters */
       chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
-      chars.cDigitSeparator = chars.cCurrencyDigitSeparator;
-      cDigitSeparator2 = chars.cDigitSeparator == 0xa0 ? ' ' : 0;
     }
     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
              !(pNumprs->dwOutFlags & NUMPRS_PARENS))
@@ -1677,7 +1680,6 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
   {
     /* Only accept non-currency characters */
     chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
-    chars.cCurrencyDigitSeparator = chars.cDigitSeparator;
   }
 
   if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
@@ -1769,12 +1771,20 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
       }
     }
     else if (pNumprs->dwInFlags & NUMPRS_THOUSANDS &&
+             !(pNumprs->dwOutFlags & NUMPRS_HEX_OCT) &&
              ((chars.cDigitSeparator && *lpszStr == chars.cDigitSeparator) ||
               (cDigitSeparator2 && *lpszStr == cDigitSeparator2)))
     {
       pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
       cchUsed++;
     }
+    else if ((pNumprs->dwInFlags & (NUMPRS_THOUSANDS|NUMPRS_CURRENCY)) == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY) &&
+             !(pNumprs->dwOutFlags & NUMPRS_HEX_OCT) &&
+             chars.cCurrencyDigitSeparator && *lpszStr == chars.cCurrencyDigitSeparator)
+    {
+      pNumprs->dwOutFlags |= NUMPRS_THOUSANDS|NUMPRS_CURRENCY;
+      cchUsed++;
+    }
     else if (*lpszStr == chars.cDecimalPoint &&
              pNumprs->dwInFlags & NUMPRS_DECIMAL &&
              !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
@@ -1901,7 +1911,8 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
     if ((chars.cDigitSeparator && *lpszStr == chars.cDigitSeparator) ||
         (cDigitSeparator2 && *lpszStr == cDigitSeparator2))
     {
-      if (pNumprs->dwInFlags & NUMPRS_THOUSANDS)
+      if (pNumprs->dwInFlags & NUMPRS_THOUSANDS &&
+          !(pNumprs->dwOutFlags & NUMPRS_HEX_OCT))
       {
         pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
         cchUsed++;
@@ -1913,6 +1924,21 @@ HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFla
         break;
       }
     }
+    else if (*lpszStr == chars.cCurrencyDigitSeparator)
+    {
+      if ((pNumprs->dwInFlags & (NUMPRS_THOUSANDS|NUMPRS_CURRENCY)) == (NUMPRS_THOUSANDS|NUMPRS_CURRENCY) &&
+          !(pNumprs->dwOutFlags & NUMPRS_HEX_OCT))
+      {
+        pNumprs->dwOutFlags |= NUMPRS_THOUSANDS|NUMPRS_CURRENCY;
+        cchUsed++;
+        lpszStr++;
+      }
+      else
+      {
+        /* Not allowed, even with NUMPRS_TRAILING_WHITE */
+        break;
+      }
+    }
     else if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && iswspace(*lpszStr))
     {
       pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;




More information about the wine-cvs mailing list