windows-nt/Source/XPSP1/NT/shell/ext/cscui/filesize.cpp
2020-09-26 16:20:57 +08:00

216 lines
4.8 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: filesize.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "filesize.h"
#include "util.h"
#include <resource.h>
//-----------------------------------------------------------------------------
// class FileSize
//-----------------------------------------------------------------------------
//
// Static array of file size "order" string IDs.
// These IDs identify the "%1 KB", "%1 MB", "%1 GB" resource strings.
//
int FileSize::m_rgiOrders[IDS_ORDER_EB - IDS_ORDER_BYTES + 1];
FileSize::FileSize(
ULONGLONG ullSize
) : m_ullSize(ullSize)
{
TraceAssert(IDS_ORDER_BYTES != 0);
if (0 == m_rgiOrders[0])
{
//
// Initialize the static array of file size "order" string IDs.
//
for (int i = IDS_ORDER_BYTES; i <= IDS_ORDER_EB; i++)
{
m_rgiOrders[i - IDS_ORDER_BYTES] = i;
}
}
}
//
// FileSize assignment.
//
FileSize&
FileSize::operator = (
const FileSize& rhs
)
{
if (this != &rhs)
{
m_ullSize = rhs.m_ullSize;
}
return *this;
}
//
// The following code for converting a file size value to a text
// string (i.e. "10.5 MB") was taken from shell32.dll so that file size
// values would match those displayed in shell views. The code isn't
// my normal style but I left it "as is" so I wouldn't break it. [brianau]
//
const int MAX_INT64_SIZE = 30;
const int MAX_COMMA_NUMBER_SIZE = MAX_INT64_SIZE + 10;
//
// Convert a ULONGLONG file size value to a text string.
//
void
FileSize::CvtSizeToText(
ULONGLONG n,
LPTSTR pszBuffer
) const
{
TCHAR szTemp[MAX_INT64_SIZE];
ULONGLONG iChr;
iChr = 0;
do {
szTemp[iChr++] = (TCHAR)(TEXT('0') + (TCHAR)(n % 10));
n = n / 10;
} while (n != 0);
do {
iChr--;
*pszBuffer++ = szTemp[iChr];
} while (iChr != 0);
*pszBuffer++ = '\0';
}
//
// Convert a string to an integer (taken from shlwapi.dll).
//
int
FileSize::StrToInt(
LPCTSTR lpSrc
) const
{
int n = 0;
BOOL bNeg = FALSE;
if (*lpSrc == TEXT('-')) {
bNeg = TRUE;
lpSrc++;
}
while (IsDigit(*lpSrc)) {
n *= 10;
n += *lpSrc - TEXT('0');
lpSrc++;
}
return bNeg ? -n : n;
}
//
// Add commas where necessary to a number with more than 3 digits.
//
LPTSTR
FileSize::AddCommas(
ULONGLONG n,
LPTSTR pszResult,
int cchResult
) const
{
TCHAR szTemp[MAX_COMMA_NUMBER_SIZE];
TCHAR szSep[5];
NUMBERFMT nfmt;
nfmt.NumDigits=0;
nfmt.LeadingZero=0;
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep));
nfmt.Grouping = StrToInt(szSep);
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep));
nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
nfmt.NegativeOrder= 0;
CvtSizeToText(n, szTemp);
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, cchResult) == 0)
lstrcpy(pszResult, szTemp);
return pszResult;
}
//
// Format a file size value as a text string suitable for viewing.
//
void
FileSize::Format(
ULONGLONG ullSize,
LPTSTR pszFS,
UINT cchFS
) const
{
TraceAssert(NULL != pszFS);
TraceAssert(0 < cchFS);
int i;
ULONGLONG wInt;
ULONGLONG dw64 = ullSize;
UINT wLen, wDec;
TCHAR szTemp[MAX_COMMA_NUMBER_SIZE], szFormat[5];
if (dw64 < 1000)
{
wsprintf(szTemp, TEXT("%d"), (DWORD)(dw64));
i = 0;
}
else
{
int cOrders = ARRAYSIZE(m_rgiOrders);
for (i = 1; i < cOrders - 1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++);
/* do nothing */
wInt = dw64 >> 10;
AddCommas(wInt, szTemp, ARRAYSIZE(szTemp));
wLen = lstrlen(szTemp);
if (wLen < 3)
{
wDec = ((DWORD)(dw64 - wInt * 1024L)) * 1000 / 1024;
// At this point, wDec should be between 0 and 1000
// we want get the top one (or two) digits.
wDec /= 10;
if (wLen == 2)
wDec /= 10;
// Note that we need to set the format before getting the
// intl char.
lstrcpy(szFormat, TEXT("%02d"));
szFormat[2] = (TCHAR)(TEXT('0') + 3 - wLen);
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
szTemp+wLen, ARRAYSIZE(szTemp)-wLen);
wLen = lstrlen(szTemp);
wLen += wsprintf(szTemp+wLen, szFormat, wDec);
}
}
*pszFS = TEXT('\0');
LPTSTR pszText;
if (0 < FormatStringID(&pszText, g_hInstance, m_rgiOrders[i], szTemp))
{
lstrcpyn(pszFS, pszText, cchFS);
LocalFree(pszText);
}
}