Commit c4c00040 authored by Mikołaj Zalewski's avatar Mikołaj Zalewski Committed by Alexandre Julliard

shlwapi: Make StrFormatByteSize format numbers using locale settings.

parent 593e8976
...@@ -66,48 +66,55 @@ static HRESULT WINAPI _SHStrDupAA(LPCSTR,LPSTR*); ...@@ -66,48 +66,55 @@ static HRESULT WINAPI _SHStrDupAA(LPCSTR,LPSTR*);
static HRESULT WINAPI _SHStrDupAW(LPCWSTR,LPSTR*); static HRESULT WINAPI _SHStrDupAW(LPCWSTR,LPSTR*);
/************************************************************************* static void FillNumberFmt(NUMBERFMTW *fmt, WCHAR decimal_buffer[8], WCHAR thousand_buffer[8])
* FormatInt [internal]
*
* Format an integer according to the current locale
*
* RETURNS
* The number of bytes written on success or 0 on failure
*/
static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf)
{ {
NUMBERFMTW fmt;
WCHAR decimal[8], thousand[8];
WCHAR grouping[64]; WCHAR grouping[64];
WCHAR buf[24];
WCHAR *c; WCHAR *c;
BOOL neg = (qdwValue < 0);
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_ILZERO|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt.LeadingZero, sizeof(fmt.LeadingZero)/sizeof(WCHAR)); GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_ILZERO|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt->LeadingZero, sizeof(fmt->LeadingZero)/sizeof(WCHAR));
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt.LeadingZero, sizeof(fmt.NegativeOrder)/sizeof(WCHAR)); GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt->LeadingZero, sizeof(fmt->NegativeOrder)/sizeof(WCHAR));
fmt.NumDigits = 0; fmt->NumDigits = 0;
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimal, sizeof(decimal)/sizeof(WCHAR)); GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimal_buffer, sizeof(decimal_buffer)/sizeof(WCHAR));
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousand, sizeof(thousand)/sizeof(WCHAR)); GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousand_buffer, sizeof(thousand_buffer)/sizeof(WCHAR));
fmt.lpThousandSep = thousand; fmt->lpThousandSep = thousand_buffer;
fmt.lpDecimalSep = decimal; fmt->lpDecimalSep = decimal_buffer;
/* /*
* Converting grouping string to number as described on * Converting grouping string to number as described on
* http://blogs.msdn.com/oldnewthing/archive/2006/04/18/578251.aspx * http://blogs.msdn.com/oldnewthing/archive/2006/04/18/578251.aspx
*/ */
fmt.Grouping = 0; fmt->Grouping = 0;
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping)/sizeof(WCHAR)); GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping)/sizeof(WCHAR));
for (c = grouping; *c; c++) for (c = grouping; *c; c++)
if (*c >= '0' && *c < '9') if (*c >= '0' && *c < '9')
{ {
fmt.Grouping *= 10; fmt->Grouping *= 10;
fmt.Grouping += *c - '0'; fmt->Grouping += *c - '0';
} }
if (fmt.Grouping % 10 == 0) if (fmt->Grouping % 10 == 0)
fmt.Grouping /= 10; fmt->Grouping /= 10;
else else
fmt.Grouping *= 10; fmt->Grouping *= 10;
}
/*************************************************************************
* FormatInt [internal]
*
* Format an integer according to the current locale
*
* RETURNS
* The number of bytes written on success or 0 on failure
*/
static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf)
{
NUMBERFMTW fmt;
WCHAR decimal[8], thousand[8];
WCHAR buf[24];
WCHAR *c;
BOOL neg = (qdwValue < 0);
FillNumberFmt(&fmt, decimal, thousand);
c = &buf[24]; c = &buf[24];
*(--c) = 0; *(--c) = 0;
...@@ -123,6 +130,29 @@ static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf) ...@@ -123,6 +130,29 @@ static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf)
} }
/************************************************************************* /*************************************************************************
* FormatDouble [internal]
*
* Format an integer according to the current locale. Prints the specified number of digits
* after the decimal point
*
* RETURNS
* The number of bytes written on success or 0 on failure
*/
static int FormatDouble(double value, int decimals, LPWSTR pszBuf, int cchBuf)
{
static const WCHAR flfmt[] = {'%','f',0};
WCHAR buf[64];
NUMBERFMTW fmt;
WCHAR decimal[8], thousand[8];
snprintfW(buf, 64, flfmt, value);
FillNumberFmt(&fmt, decimal, thousand);
fmt.NumDigits = decimals;
return GetNumberFormatW(LOCALE_USER_DEFAULT, 0, buf, &fmt, pszBuf, cchBuf);
}
/*************************************************************************
* SHLWAPI_ChrCmpHelperA * SHLWAPI_ChrCmpHelperA
* *
* Internal helper for SHLWAPI_ChrCmpA/ChrCMPIA. * Internal helper for SHLWAPI_ChrCmpA/ChrCMPIA.
...@@ -2251,7 +2281,7 @@ typedef struct tagSHLWAPI_BYTEFORMATS ...@@ -2251,7 +2281,7 @@ typedef struct tagSHLWAPI_BYTEFORMATS
LONGLONG dLimit; LONGLONG dLimit;
double dDivisor; double dDivisor;
double dNormaliser; double dNormaliser;
LPCWSTR lpwszFormat; int nDecimals;
WCHAR wPrefix; WCHAR wPrefix;
} SHLWAPI_BYTEFORMATS; } SHLWAPI_BYTEFORMATS;
...@@ -2273,10 +2303,6 @@ typedef struct tagSHLWAPI_BYTEFORMATS ...@@ -2273,10 +2303,6 @@ typedef struct tagSHLWAPI_BYTEFORMATS
*/ */
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax) LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
{ {
static const WCHAR wsz3_0[] = {'%','3','.','0','f',0};
static const WCHAR wsz3_1[] = {'%','3','.','1','f',0};
static const WCHAR wsz3_2[] = {'%','3','.','2','f',0};
#define KB ((ULONGLONG)1024) #define KB ((ULONGLONG)1024)
#define MB (KB*KB) #define MB (KB*KB)
#define GB (KB*KB*KB) #define GB (KB*KB*KB)
...@@ -2285,24 +2311,23 @@ LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax) ...@@ -2285,24 +2311,23 @@ LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
static const SHLWAPI_BYTEFORMATS bfFormats[] = static const SHLWAPI_BYTEFORMATS bfFormats[] =
{ {
{ 10*KB, 10.24, 100.0, wsz3_2, 'K' }, /* 10 KB */ { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
{ 100*KB, 102.4, 10.0, wsz3_1, 'K' }, /* 100 KB */ { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
{ 1000*KB, 1024.0, 1.0, wsz3_0, 'K' }, /* 1000 KB */ { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
{ 10*MB, 10485.76, 100.0, wsz3_2, 'M' }, /* 10 MB */ { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
{ 100*MB, 104857.6, 10.0, wsz3_1, 'M' }, /* 100 MB */ { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
{ 1000*MB, 1048576.0, 1.0, wsz3_0, 'M' }, /* 1000 MB */ { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
{ 10*GB, 10737418.24, 100.0, wsz3_2, 'G' }, /* 10 GB */ { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
{ 100*GB, 107374182.4, 10.0, wsz3_1, 'G' }, /* 100 GB */ { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
{ 1000*GB, 1073741824.0, 1.0, wsz3_0, 'G' }, /* 1000 GB */ { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
{ 10*TB, 10485.76, 100.0, wsz3_2, 'T' }, /* 10 TB */ { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
{ 100*TB, 104857.6, 10.0, wsz3_1, 'T' }, /* 100 TB */ { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
{ 1000*TB, 1048576.0, 1.0, wsz3_0, 'T' }, /* 1000 TB */ { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
{ 10*PB, 10737418.24, 100.00, wsz3_2, 'P' }, /* 10 PB */ { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
{ 100*PB, 107374182.4, 10.00, wsz3_1, 'P' }, /* 100 PB */ { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
{ 1000*PB, 1073741824.0, 1.00, wsz3_0, 'P' }, /* 1000 PB */ { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
{ 0, 10995116277.76, 100.00, wsz3_2, 'E' } /* EB's, catch all */ { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
}; };
WCHAR wszBuff[32];
WCHAR wszAdd[] = {' ','?','B',0}; WCHAR wszAdd[] = {' ','?','B',0};
double dBytes; double dBytes;
UINT i = 0; UINT i = 0;
...@@ -2342,10 +2367,10 @@ LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax) ...@@ -2342,10 +2367,10 @@ LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser; dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
sprintfW(wszBuff, bfFormats[i].lpwszFormat, dBytes); if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
return NULL;
wszAdd[1] = bfFormats[i].wPrefix; wszAdd[1] = bfFormats[i].wPrefix;
strcatW(wszBuff, wszAdd); StrCatBuffW(lpszDest, wszAdd, cchMax);
lstrcpynW(lpszDest, wszBuff, cchMax);
return lpszDest; return lpszDest;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment