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

Alexandre Julliard julliard at winehq.org
Fri Feb 25 07:30:23 CST 2022


Module: wine
Branch: oldstable
Commit: e3aa6390dcd31b7698af362489cd32528dadafa9
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e3aa6390dcd31b7698af362489cd32528dadafa9

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>
(cherry picked from commit 9e4524ffb09be6bba828ea66b8fe1bb64b996b66)
Signed-off-by: Michael Stefaniuc <mstefani 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 93f2225e983..58fa5aaf3a7 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -1599,11 +1599,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);
@@ -2173,7 +2170,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 ','! */
@@ -2235,9 +2232,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);
 
@@ -2248,15 +2243,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 */
@@ -2271,13 +2264,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);
 
@@ -2332,9 +2325,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 80072a35140..d0d6f491255 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -1509,7 +1509,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];
 
@@ -1629,6 +1629,11 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
     {
       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))
@@ -1655,8 +1660,6 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
       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))
@@ -1673,7 +1676,6 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
   {
     /* Only accept non-currency characters */
     chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
-    chars.cCurrencyDigitSeparator = chars.cDigitSeparator;
   }
 
   if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
@@ -1765,12 +1767,20 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
       }
     }
     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)))
@@ -1897,7 +1907,8 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
     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++;
@@ -1909,6 +1920,21 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
         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