From 10f0ace4a2ec0a67adbcc30000e9eb5ebf9efa42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Villac=C3=ADs=20Lasso?= Date: Fri, 9 Sep 2005 15:01:17 +0000 Subject: [PATCH] Make Single|Double->BSTR conversion use the specified locale for the decimal point even without the LOCALE_USE_NLS flag. Test supplied. --- dlls/oleaut32/tests/vartype.c | 20 ++++++++++++++ dlls/oleaut32/vartype.c | 49 ++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c index 38c8423b7b0..07313504d85 100644 --- a/dlls/oleaut32/tests/vartype.c +++ b/dlls/oleaut32/tests/vartype.c @@ -4596,7 +4596,10 @@ static void test_VarBstrFromR4(void) { static const WCHAR szNative[] = { '6','5','4','3','2','2','.','3','\0' }; static const WCHAR szZero[] = {'0', '\0'}; + static const WCHAR szOneHalf_English[] = { '0','.','5','\0' }; /* uses period */ + static const WCHAR szOneHalf_Spanish[] = { '0',',','5','\0' }; /* uses comma */ LCID lcid; + LCID lcid_spanish; HRESULT hres; BSTR bstr = NULL; @@ -4605,6 +4608,7 @@ static void test_VarBstrFromR4(void) CHECKPTR(VarBstrFromR4); lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + lcid_spanish = MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT); f = 654322.23456f; hres = pVarBstrFromR4(f, lcid, 0, &bstr); ok(hres == S_OK, "got hres 0x%08lx\n", hres); @@ -4626,6 +4630,22 @@ static void test_VarBstrFromR4(void) { ok(memcmp(bstr, szZero, sizeof(szZero)) == 0, "negative zero (got %s)\n", wtoascii(bstr)); } + + /* The following tests that lcid is used for decimal separator even without LOCALE_USE_NLS */ + f = 0.5; + hres = pVarBstrFromR4(f, lcid, 0, &bstr); + ok(hres == S_OK, "got hres 0x%08lx\n", hres); + if (bstr) + { + ok(memcmp(bstr, szOneHalf_English, sizeof(szOneHalf_English)) == 0, "English locale failed (got %s)\n", wtoascii(bstr)); + } + f = 0.5; + hres = pVarBstrFromR4(f, lcid_spanish, 0, &bstr); + ok(hres == S_OK, "got hres 0x%08lx\n", hres); + if (bstr) + { + ok(memcmp(bstr, szOneHalf_Spanish, sizeof(szOneHalf_Spanish)) == 0, "Spanish locale failed (got %s)\n", wtoascii(bstr)); + } } #define BSTR_DATE(dt,str) SysFreeString(bstr); bstr = NULL; \ diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c index db913eaa31a..7dca9092186 100644 --- a/dlls/oleaut32/vartype.c +++ b/dlls/oleaut32/vartype.c @@ -5442,7 +5442,54 @@ static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags, *pbstrOut = SysAllocString(numbuff); } else - *pbstrOut = SysAllocString(buff); + { + WCHAR lpDecimalSep[16]; + + /* Native oleaut32 uses the locale-specific decimal separator even in the + absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin + American locales will see "one thousand and one tenth" as "1000,1" + instead of "1000.1" (notice the comma). The following code checks for + the need to replace the decimal separator, and if so, will prepare an + appropriate NUMBERFMTW structure to do the job via GetNumberFormatW(). + */ + GetLocaleInfoW(lcid, LOCALE_SDECIMAL, lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR)); + if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0') + { + /* locale is compatible with English - return original string */ + *pbstrOut = SysAllocString(buff); + } + else + { + WCHAR *p; + WCHAR numbuff[256]; + WCHAR empty[1] = {'\0'}; + NUMBERFMTW minFormat; + + minFormat.NumDigits = 0; + minFormat.LeadingZero = 0; + minFormat.Grouping = 0; + minFormat.lpDecimalSep = lpDecimalSep; + minFormat.lpThousandSep = empty; + minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */ + + /* count number of decimal digits in string */ + p = strchrW( buff, '.' ); + if (p) minFormat.NumDigits = strlenW(p + 1); + + numbuff[0] = '\0'; + if (!GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE, + buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR))) + { + WARN("GetNumberFormatW() failed, returning raw number string instead\n"); + *pbstrOut = SysAllocString(buff); + } + else + { + TRACE("created minimal NLS string %s\n", debugstr_w(numbuff)); + *pbstrOut = SysAllocString(numbuff); + } + } + } return *pbstrOut ? S_OK : E_OUTOFMEMORY; }