//+--------------------------------------------------------------------------- // // Copyright (C) 1997, Microsoft Corporation. // // File: OutFmt.cxx // // Contents: COutputFormat // // History: 11-Jun-97 KyleP Moved from WQIter.cxx // //---------------------------------------------------------------------------- #include #pragma hdrstop static WCHAR * wcsDefaultBoolVectorPrefix = L" "; static WCHAR * wcsDefaultBoolVectorSeparator = L" "; static WCHAR * wcsDefaultBoolVectorSuffix = L" "; static WCHAR * wcsDefaultCurrencyVectorPrefix = L" "; static WCHAR * wcsDefaultCurrencyVectorSeparator = L" "; static WCHAR * wcsDefaultCurrencyVectorSuffix = L" "; static WCHAR * wcsDefaultDateVectorPrefix = L" "; static WCHAR * wcsDefaultDateVectorSeparator = L" "; static WCHAR * wcsDefaultDateVectorSuffix = L" "; static WCHAR * wcsDefaultNumberVectorPrefix = L" "; static WCHAR * wcsDefaultNumberVectorSeparator = L" "; static WCHAR * wcsDefaultNumberVectorSuffix = L" "; static WCHAR * wcsDefaultStringVectorPrefix = L" "; static WCHAR * wcsDefaultStringVectorSeparator = L" "; static WCHAR * wcsDefaultStringVectorSuffix = L" "; //+--------------------------------------------------------------------------- // // Function: COutputFormat::COutputFormat - public // // Arguments: [webServer] - makes a copy of the web server to resolve CGI // variables // // Synopsis: Constructor // // History: 96-Jan-18 DwightKr Created // 96-Feb-26 DwightKr Added vector formatting // //---------------------------------------------------------------------------- COutputFormat::COutputFormat( CWebServer & webServer ) : CWebServer( webServer ), _wcsBoolVectorPrefix( wcsDefaultBoolVectorPrefix ), _wcsBoolVectorSeparator( wcsDefaultBoolVectorSeparator ), _wcsBoolVectorSuffix( wcsDefaultBoolVectorSuffix ), _wcsCurrencyVectorPrefix( wcsDefaultCurrencyVectorPrefix ), _wcsCurrencyVectorSeparator( wcsDefaultCurrencyVectorSeparator ), _wcsCurrencyVectorSuffix( wcsDefaultCurrencyVectorSuffix ), _wcsDateVectorPrefix( wcsDefaultDateVectorPrefix ), _wcsDateVectorSeparator( wcsDefaultDateVectorSeparator ), _wcsDateVectorSuffix( wcsDefaultDateVectorSuffix ), _wcsNumberVectorPrefix( wcsDefaultNumberVectorPrefix ), _wcsNumberVectorSeparator( wcsDefaultNumberVectorSeparator ), _wcsNumberVectorSuffix( wcsDefaultNumberVectorSuffix ), _wcsStringVectorPrefix( wcsDefaultStringVectorPrefix ), _wcsStringVectorSeparator( wcsDefaultStringVectorSeparator ), _wcsStringVectorSuffix( wcsDefaultStringVectorSuffix ) { _numberFormat.lpDecimalSep = 0; _numberFormat.lpThousandSep = 0; _currencyFormat.lpDecimalSep = 0; _currencyFormat.lpThousandSep = 0; _currencyFormat.lpCurrencySymbol = 0; } //+--------------------------------------------------------------------------- // // Function: COutputFormat::GetIntegerFormat - private // // Synopsis: Formats a number and returns results in the string // buffer supplied. // // Arguments: [wcsInput] - string to convert // [wcsNumber] - output location for results // [_cwcNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::GetIntegerFormat( WCHAR * const wcsInput, WCHAR * wcsNumber, ULONG cwcNumber ) { Win4Assert( 0 != _numberFormat.lpDecimalSep ); Win4Assert( 0 != _numberFormat.lpThousandSep ); Win4Assert( InvalidLCID != GetLCID() ); ULONG numDigits = _numberFormat.NumDigits; _numberFormat.NumDigits = 0; int cwcResult = ::GetNumberFormat( GetLCID(), 0, wcsInput, &_numberFormat, wcsNumber, cwcNumber ); _numberFormat.NumDigits = numDigits; if ( 0 == cwcResult ) { THROW( CException() ); } return cwcResult - 1; } //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatNumber - public // // Synopsis: Formats a unsigned number and returns results in the string // buffer supplied. // // Arguments: [ulNumber] - number to convert // [wcsNumber] - output location for results // [cwcNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatNumber( ULONG ulNumber, WCHAR * wcsNumber, ULONG cwcNumber ) { WCHAR wcsBuffer[40]; IDQ_ultow( ulNumber, wcsBuffer ); return GetIntegerFormat( wcsBuffer, wcsNumber, cwcNumber ); } //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatNumber // // Synopsis: Formats a signed number and returns results in the string // buffer supplied. // // Arguments: [lNumber] - number to convert // [wcsNumber] - output location for results // [cwcNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatNumber( LONG lNumber, WCHAR * wcsNumber, ULONG cwcNumber ) { WCHAR wcsBuffer[40]; IDQ_ltow( lNumber, wcsBuffer ); return GetIntegerFormat( wcsBuffer, wcsNumber, cwcNumber ); } //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatNumber // // Synopsis: Formats a _int64 and returns results in the string // buffer supplied. // // Arguments: [i64Number] - number to convert // [wcsNumber] - output location for results // [cwcNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatNumber( _int64 i64Number, WCHAR * wcsNumber, ULONG cwcNumber ) { WCHAR wcsBuffer[40]; IDQ_lltow( i64Number, wcsBuffer ); return GetIntegerFormat( wcsBuffer, wcsNumber, cwcNumber ); } //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatNumber // // Synopsis: Formats a unsigned _int64 and returns results in the string // buffer supplied. // // Arguments: [ui64Number] - number to convert // [wcsNumber] - output location for results // [cwcNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatNumber( unsigned _int64 ui64Number, WCHAR * wcsNumber, ULONG cwcNumber ) { WCHAR wcsBuffer[40]; IDQ_ulltow( ui64Number, wcsBuffer ); return GetIntegerFormat( wcsBuffer, wcsNumber, cwcNumber ); } //+--------------------------------------------------------------------------- // // Method: COutputFormat::FormatFloatRaw, public // // Synopsis: Formats a floating point number and returns results in the // string buffer supplied. // // Arguments: [flt] - number to be formatted // [cchPrec] - number of digits of precision to use // [pwszNumber] - output location for results // [cchNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // Notes: GetNumberFormat isn't really very useful for numbers with // very large or small magnitudes. It gives up when there are // about 100 digits to the left of the decimal place. // // History: 96-Jan-18 DwightKr Created // 96-May-22 DwightKr Increased buffer size // 97-Mar-12 AlanW Changed signature to better handle // single-precision floating point // //---------------------------------------------------------------------------- int COutputFormat::FormatFloatRaw( double flt, unsigned cchPrec, WCHAR * pwszNumber, ULONG cchNumber ) { int iDec, fSign; char * pszCvt = _ecvt( flt, cchPrec, &iDec, &fSign ); WCHAR *pwsz = pwszNumber; if (fSign) *pwsz++ = L'-'; if (iDec <= 0) { *pwsz++ = L'.'; while (iDec < 0) { *pwsz++ = L'0'; iDec++; } } for (unsigned i=0; i< cchPrec; i++) { *pwsz++ = *pszCvt++; if (iDec && --iDec == 0) *pwsz++ = L'.'; } while (iDec > 0) { *pwsz++ = L'0'; iDec--; } *pwsz = L'\0'; int cchResult = (int)(pwsz - pwszNumber); Win4Assert ((unsigned)cchResult < cchNumber); if ((unsigned)cchResult >= cchNumber) { ciGibDebugOut((DEB_WARN, "FormatFloatRaw - string buffer overflow!\n")); cchResult = -1; } return cchResult; } //FormatFloatRaw //+--------------------------------------------------------------------------- // // Method: COutputFormat::FormatFloat, public // // Synopsis: Formats a floating point number and returns results in the // string buffer supplied. // // Arguments: [flt] - number to be formatted // [cchPrec] - number of digits of precision to use // [pwszNumber] - output location for results // [cchNumber] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // Notes: GetNumberFormat isn't really very useful for numbers with // very large or small magnitudes. It gives up when there are // about 100 digits to the left of the decimal place. // // History: 96-Jan-18 DwightKr Created // 96-May-22 DwightKr Increased buffer size // 97-Mar-12 AlanW Changed signature to better handle // single-precision floating point // //---------------------------------------------------------------------------- int COutputFormat::FormatFloat( double flt, unsigned cchPrec, WCHAR * pwszNumber, ULONG cchNumber ) { Win4Assert( 0 != _numberFormat.lpDecimalSep ); Win4Assert( 0 != _numberFormat.lpThousandSep ); Win4Assert( InvalidLCID != GetLCID() ); WCHAR pwszInput[-DBL_MIN_10_EXP + DBL_DIG + 4]; WCHAR *pwsz = pwszInput; int cch = FormatFloatRaw( flt, cchPrec, pwszInput, sizeof pwszInput / sizeof pwszInput[0]); Win4Assert( cch > 0 ); int cchResult = ::GetNumberFormat( GetLCID(), 0, pwszInput, &_numberFormat, pwszNumber, cchNumber ); if ( 0 == cchResult ) { ciGibDebugOut(( DEB_WARN, "FormatFloat - GetNumberFormat failed, error = %d\n", GetLastError() )); THROW( CException() ); } return cchResult - 1; } //FormatFloat //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatDate // // Synopsis: Formats a SYSTEMTIME and returns results in the string // buffer supplied. // // Arguments: [sysTime] - date to convert // [wcsDate] - output location for results // [cwcDate] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatDate( SYSTEMTIME & sysTime, WCHAR * wcsDate, ULONG cwcDate ) { *wcsDate = 0; Win4Assert( InvalidLCID != GetLCID() ); ULONG ulMethod = TheIDQRegParams.GetDateTimeFormatting(); // Fixed, non-localized formatting if ( IS_DATETIME_FORMATTING_FAST_LCID == ulMethod ) { if ( cwcDate < 10 ) return 0; wsprintf( wcsDate, L"%4d/%02d/%02d", (DWORD) sysTime.wYear, (DWORD) sysTime.wMonth, (DWORD) sysTime.wDay ); return 10; } // Format the date using the locale provided. ULONG ulFlags = DATE_SHORTDATE; if ( IS_DATETIME_FORMATTING_SYSTEM_LCID == ulMethod ) ulFlags |= LOCALE_NOUSEROVERRIDE; ULONG cwcUsed = GetDateFormat( GetLCID(), ulFlags, &sysTime, 0, wcsDate, cwcDate ); if ( 0 != cwcUsed ) { Win4Assert( 0 == wcsDate[cwcUsed - 1] ); // cwcUsed includes the null termination -- remove it. return cwcUsed - 1; } #if DBG == 1 ULONG error = GetLastError(); ciGibDebugOut(( DEB_ERROR, "GetDateFormat failed: 0x%x\n", error )); // ERROR_INVALID_PARAMETER indicates that the date is // bogus -- perhaps because the file was deleted. if ( ERROR_INVALID_PARAMETER != error ) Win4Assert( !"GetTimeFormat failed" ); #endif // DBG == 1 return 0; } //FormatDate //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatTime // // Synopsis: Formats a SYSTEMTIME and returns results in the string // buffer supplied. // // Arguments: [sysTime] - date to convert // [wcsTime] - output location for results // [cwcTime] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatTime( SYSTEMTIME & sysTime, WCHAR * wcsTime, ULONG cwcTime ) { *wcsTime = 0; Win4Assert( InvalidLCID != GetLCID() ); ULONG ulMethod = TheIDQRegParams.GetDateTimeFormatting(); // Fixed, non-localized formatting if ( IS_DATETIME_FORMATTING_FAST_LCID == ulMethod ) { if ( cwcTime < 8 ) return 0; wsprintf( wcsTime, L"%2d:%02d:%02d", (DWORD) sysTime.wHour, (DWORD) sysTime.wMinute, (DWORD) sysTime.wSecond ); return 8; } // Format the time using the locale provided. ULONG ulFlags = ( IS_DATETIME_FORMATTING_USER_LCID == ulMethod ) ? 0 : LOCALE_NOUSEROVERRIDE; ULONG cwcUsed = GetTimeFormat( GetLCID(), ulFlags, &sysTime, 0, wcsTime, cwcTime ); if ( 0 != cwcUsed ) { Win4Assert( 0 == wcsTime[cwcUsed - 1] ); // cwcUsed includes the null termination -- remove it. return cwcUsed - 1; } #if DBG == 1 ULONG error = GetLastError(); ciGibDebugOut(( DEB_ERROR, "GetTimeFormat failed: 0x%x\n", error )); // ERROR_INVALID_PARAMETER indicates that the date is // bogus -- perhaps because the file was deleted. if ( ERROR_INVALID_PARAMETER != error ) Win4Assert( !"GetTimeFormat failed" ); #endif // DBG == 1 return 0; } //FormatTime //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatDateTime // // Synopsis: Formats a SYSTEMTIME and returns results in the string // buffer supplied. // // Arguments: [sysTime] - date to convert // [wcsDate] - output location for results // [cwcDate] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatDateTime( SYSTEMTIME & SysTime, WCHAR * wcsDate, ULONG cwcDate ) { // // Convert UTC/GMT to local system time if set in the registry // if ( TheIDQRegParams.GetDateTimeLocal() ) { FILETIME ft, ftLocal; SystemTimeToFileTime( &SysTime, &ft ); FileTimeToLocalFileTime( &ft, &ftLocal ); FileTimeToSystemTime( &ftLocal, &SysTime ); } int cwcDateBuffer = FormatDate( SysTime, wcsDate, cwcDate ); wcsDate[cwcDateBuffer] = L' '; int cwcBuffer = max( 0, ( (int) (cwcDate - cwcDateBuffer ) ) - 2 ); int cwcTimeBuffer = FormatTime( SysTime, wcsDate+cwcDateBuffer+1, cwcBuffer ); return cwcTimeBuffer + cwcDateBuffer + 1; } //FormatDateTime //+--------------------------------------------------------------------------- // // Function: COutputFormat::FormatCurrency // // Synopsis: Formats a CY and returns results in the string // buffer supplied. // // Arguments: [cyValue] - number to convert // [wcsCurrency] - output location for results // [cwcCurrency] - length of output buffer in WCHARs // // Returns: The number of characters in the final string, less the NULL // terminator. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- int COutputFormat::FormatCurrency( CY cyValue, WCHAR * wcsCurrency, ULONG cwcCurrency ) { Win4Assert( 0 != _numberFormat.lpDecimalSep ); Win4Assert( 0 != _numberFormat.lpThousandSep ); Win4Assert( 0 != _currencyFormat.lpDecimalSep ); Win4Assert( 0 != _currencyFormat.lpThousandSep ); Win4Assert( InvalidLCID != GetLCID() ); WCHAR wcsBuffer[320]; double dblValue; VarR8FromCy( cyValue, &dblValue ); swprintf( wcsBuffer, L"%lf", dblValue ); int cwcResult = ::GetCurrencyFormat( GetLCID(), 0, wcsBuffer, &_currencyFormat, wcsCurrency, cwcCurrency ); if ( 0 == cwcResult ) { THROW( CException() ); } return cwcResult - 1; } //FormatCurrency //+--------------------------------------------------------------------------- // // Function: COutputFormat::LoadNumberFormatInfo - public // // Synopsis: Fills the numberFormat stucture with formatting information // used to subsequently format numbers. // // History: 97-Jun-24 t-elainc Created // //---------------------------------------------------------------------------- void COutputFormat::LoadNumberFormatInfo( LCID lcid ) { LoadNumberFormatInfo(lcid, LocaleToCodepage(lcid) ); } //+--------------------------------------------------------------------------- // // Function: ConvertGroupingStringToInt // // Synopsis: Converts a grouping string from the registry to an integer, // as required by the Win32 number formatting API // // History: 5-Feb-99 dlee Stole from the Win32 implementation // //---------------------------------------------------------------------------- int ConvertGroupingStringToInt( WCHAR const * pwcGrouping ) { XGrowable xDest( 1 + wcslen( pwcGrouping ) ); WCHAR * pDest = xDest.Get(); // // Filter out all non-numeric values and all zero values. // Store the result in the destination buffer. // WCHAR const * pSrc = pwcGrouping; while (0 != *pSrc) { if ( ( *pSrc < L'1' ) || ( *pSrc > L'9' ) ) { pSrc++; } else { if (pSrc != pDest) *pDest = *pSrc; pSrc++; pDest++; } } // // Make sure there is something in the destination buffer. // Also, see if we need to add a zero in the case of 3;2 becomes 320. // if ( ( pDest == xDest.Get() ) || ( *(pSrc - 1) != L'0' ) ) { *pDest = L'0'; pDest++; } // Null terminate the buffer. *pDest = 0; // Convert the string to an integer. return _wtoi( xDest.Get() ); } //ConvertGroupingStringToInt //+--------------------------------------------------------------------------- // // Function: COutputFormat::LoadNumberFormatInfo - public // // Synopsis: Fills the numberFormat stucture with formatting information // used to subsequently format numbers. // // History: 96-Jan-18 DwightKr Created // //---------------------------------------------------------------------------- void COutputFormat::LoadNumberFormatInfo( LCID lcid , ULONG codepage) { Win4Assert( InvalidLCID != lcid ); // // If we're already loaded, then don't do it again. // if ( lcid == GetLCID() && 0 != _numberFormat.lpDecimalSep ) return; delete _numberFormat.lpDecimalSep; delete _numberFormat.lpThousandSep; delete _currencyFormat.lpDecimalSep; delete _currencyFormat.lpThousandSep; _numberFormat.lpDecimalSep = 0; _numberFormat.lpThousandSep = 0; _currencyFormat.lpDecimalSep = 0; _currencyFormat.lpThousandSep = 0; Win4Assert( 0 == _numberFormat.lpDecimalSep ); Win4Assert( 0 == _numberFormat.lpThousandSep ); Win4Assert( 0 == _currencyFormat.lpDecimalSep ); Win4Assert( 0 == _currencyFormat.lpThousandSep ); SetLCID( lcid, 0, 0 ); TheFormattingCache.GetFormattingInfo( lcid, _numberFormat, _currencyFormat ); SetCodePage( codepage ); ciGibDebugOut(( DEB_ITRACE, "Using a codePage of 0x%x for locale 0x%x\n", CodePage(), GetLCID() )); } //LoadNumberFormatInfo //+--------------------------------------------------------------------------- // // Method: CFormatItem::CFormatItem, public // // Synopsis: Constructs formatting info. // // Arguments: [lcid] -- The locale to use. // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- CFormatItem::CFormatItem( LCID lcid ) : _lcid( lcid ) { WCHAR wcsBuffer[256]; RtlZeroMemory( &_numberFormat, sizeof _numberFormat ); RtlZeroMemory( &_currencyFormat, sizeof _currencyFormat ); // Get the number of decimal digits. GetLocaleInfo(lcid, LOCALE_IDIGITS, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _numberFormat.NumDigits = _wtoi(wcsBuffer); // Get the leading zero in decimal fields option. GetLocaleInfo(lcid, LOCALE_ILZERO, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _numberFormat.LeadingZero = _wtoi(wcsBuffer); // Get the negative ordering. GetLocaleInfo(lcid, LOCALE_INEGNUMBER, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _numberFormat.NegativeOrder = _wtoi(wcsBuffer); // Get the grouping left of the decimal. GetLocaleInfo(lcid, LOCALE_SGROUPING, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _numberFormat.Grouping = ConvertGroupingStringToInt( wcsBuffer ); ciGibDebugOut(( DEB_ITRACE, "grouping '%ws' -> %d\n", wcsBuffer, _numberFormat.Grouping )); // Get the decimal separator. GetLocaleInfo(lcid, LOCALE_SDECIMAL, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); XPtrST xNumDecimalSep( CopyString( wcsBuffer ) ); _numberFormat.lpDecimalSep = xNumDecimalSep.GetPointer(); // Get the thousand separator. GetLocaleInfo(lcid, LOCALE_STHOUSAND, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); XPtrST xNumThousandSep( CopyString( wcsBuffer ) ); _numberFormat.lpThousandSep = xNumThousandSep.GetPointer(); // Get the number of currency digits. GetLocaleInfo(lcid, LOCALE_ICURRDIGITS, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _currencyFormat.NumDigits = _wtoi(wcsBuffer); GetLocaleInfo(lcid, LOCALE_ILZERO, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); // Get the leading zero in currency fields option. _currencyFormat.LeadingZero = _wtoi(wcsBuffer); // Get the currency grouping left of the decimal. GetLocaleInfo(lcid, LOCALE_SMONGROUPING, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _currencyFormat.Grouping = _wtoi(wcsBuffer); // Get the currency decimal separator. GetLocaleInfo(lcid, LOCALE_SMONDECIMALSEP, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); XPtrST xCurDecimalSep( CopyString( wcsBuffer ) ); _currencyFormat.lpDecimalSep = xCurDecimalSep.GetPointer(); // Get the currency thousand separator. GetLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); XPtrST xCurThousandSep( CopyString( wcsBuffer ) ); _currencyFormat.lpThousandSep = xCurThousandSep.GetPointer(); // Get the negative ordering. GetLocaleInfo(lcid, LOCALE_INEGCURR, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _currencyFormat.NegativeOrder = _wtoi(wcsBuffer); // Get the positive ordering. GetLocaleInfo(lcid, LOCALE_ICURRENCY, wcsBuffer, sizeof(wcsBuffer) / sizeof(WCHAR)); _currencyFormat.PositiveOrder = _wtoi(wcsBuffer); _currencyFormat.lpCurrencySymbol = L""; xNumDecimalSep.Acquire(); xNumThousandSep.Acquire(); xCurDecimalSep.Acquire(); xCurThousandSep.Acquire(); } //CFormatItem //+--------------------------------------------------------------------------- // // Method: CFormatItem::~CFormatItem, public // // Synopsis: Frees formatting info. // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- CFormatItem::~CFormatItem() { delete _numberFormat.lpDecimalSep; delete _numberFormat.lpThousandSep; delete _currencyFormat.lpDecimalSep; delete _currencyFormat.lpThousandSep; } //~CFormatItem //+--------------------------------------------------------------------------- // // Method: CFormatItem::Copy, public // // Synopsis: Copies formatting info into the arguments // // Arguments: [numberFormat] -- Where the number format is copied to // [currencyFormat] -- Where the currency format is copied to // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- void CFormatItem::Copy( NUMBERFMT & numberFormat, CURRENCYFMT & currencyFormat ) const { XPtrST xNumDecimalSep( CopyString( _numberFormat.lpDecimalSep ) ); XPtrST xNumThousandSep( CopyString( _numberFormat.lpThousandSep ) ); XPtrST xCurDecimalSep( CopyString( _currencyFormat.lpDecimalSep ) ); XPtrST xCurThousandSep( CopyString( _currencyFormat.lpDecimalSep ) ); RtlCopyMemory( &numberFormat, &_numberFormat, sizeof NUMBERFMT ); RtlCopyMemory( ¤cyFormat, &_currencyFormat, sizeof CURRENCYFMT ); numberFormat.lpDecimalSep = xNumDecimalSep.Acquire(); numberFormat.lpThousandSep = xNumThousandSep.Acquire(); currencyFormat.lpDecimalSep = xCurDecimalSep.Acquire(); currencyFormat.lpThousandSep = xCurThousandSep.Acquire(); } //Copy //+--------------------------------------------------------------------------- // // Method: CFormattingCache::GetFormattingInfo, public // // Synopsis: Copies formatting info for lcid into the arguments // // Arguments: [lcid] -- Locale of info to lookup // [numberFormat] -- Where the number format is copied to // [currencyFormat] -- Where the currency format is copied to // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- void CFormattingCache::GetFormattingInfo( LCID lcid, NUMBERFMT & numberFormat, CURRENCYFMT & currencyFormat ) { CLock lock( _mutex ); for ( unsigned i = 0; i < _aItems.Count(); i++ ) { if ( _aItems[i]->GetLCID() == lcid ) { _aItems[i]->Copy( numberFormat, currencyFormat ); return; } } XPtr xItem( new CFormatItem( lcid ) ); xItem->Copy( numberFormat, currencyFormat ); _aItems.Add( xItem.GetPointer(), _aItems.Count() ); xItem.Acquire(); } //GetFormattingInfo //+--------------------------------------------------------------------------- // // Method: CFormattingCache::Purge, public // // Synopsis: Purges the cache of all entries // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- void CFormattingCache::Purge() { CLock lock( _mutex ); _aItems.Clear(); } //Purge