/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "numfmuno.hxx" #include #include #include #include #include #include using namespace com::sun::star; constexpr OUString PROPERTYNAME_FMTSTR = u"FormatString"_ustr; constexpr OUString PROPERTYNAME_LOCALE = u"Locale"_ustr; constexpr OUString PROPERTYNAME_TYPE = u"Type"_ustr; constexpr OUString PROPERTYNAME_COMMENT = u"Comment"_ustr; constexpr OUString PROPERTYNAME_CURREXT = u"CurrencyExtension"_ustr; constexpr OUString PROPERTYNAME_CURRSYM = u"CurrencySymbol"_ustr; constexpr OUString PROPERTYNAME_CURRABB = u"CurrencyAbbreviation"_ustr; constexpr OUString PROPERTYNAME_DECIMALS = u"Decimals"_ustr; constexpr OUString PROPERTYNAME_LEADING = u"LeadingZeros"_ustr; constexpr OUString PROPERTYNAME_NEGRED = u"NegativeRed"_ustr; constexpr OUString PROPERTYNAME_STDFORM = u"StandardFormat"_ustr; constexpr OUString PROPERTYNAME_THOUS = u"ThousandsSeparator"_ustr; constexpr OUString PROPERTYNAME_USERDEF = u"UserDefined"_ustr; constexpr OUString PROPERTYNAME_NOZERO = u"NoZero"_ustr; constexpr OUString PROPERTYNAME_NULLDATE = u"NullDate"_ustr; constexpr OUString PROPERTYNAME_STDDEC = u"StandardDecimals"_ustr; constexpr OUString PROPERTYNAME_TWODIGIT = u"TwoDigitDateStart"_ustr; // All without a Which-ID, Map only for PropertySetInfo static std::span lcl_GetNumberFormatPropertyMap() { static const SfxItemPropertyMapEntry aNumberFormatPropertyMap_Impl[] = { {PROPERTYNAME_FMTSTR, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_LOCALE, 0, cppu::UnoType::get(),beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_TYPE, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_COMMENT, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_CURREXT, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_CURRSYM, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_DECIMALS, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_LEADING, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_NEGRED, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_STDFORM, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_THOUS, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_USERDEF, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, {PROPERTYNAME_CURRABB, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, 0}, }; return aNumberFormatPropertyMap_Impl; } static std::span lcl_GetNumberSettingsPropertyMap() { static const SfxItemPropertyMapEntry aNumberSettingsPropertyMap_Impl[] = { {PROPERTYNAME_NOZERO, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND, 0}, {PROPERTYNAME_NULLDATE, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND, 0}, {PROPERTYNAME_STDDEC, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND, 0}, {PROPERTYNAME_TWODIGIT, 0, cppu::UnoType::get(), beans::PropertyAttribute::BOUND, 0}, }; return aNumberSettingsPropertyMap_Impl; } static LanguageType lcl_GetLanguage( const lang::Locale& rLocale ) { LanguageType eRet = LanguageTag::convertToLanguageTypeWithFallback( rLocale ); if ( eRet == LANGUAGE_NONE ) eRet = LANGUAGE_SYSTEM; //! or throw an exception? return eRet; } SvNumberFormatterServiceObj::SvNumberFormatterServiceObj() { } SvNumberFormatterServiceObj::~SvNumberFormatterServiceObj() { } // XNumberFormatter void SAL_CALL SvNumberFormatterServiceObj::attachNumberFormatsSupplier( const uno::Reference& _xSupplier ) { ::rtl::Reference< SvNumberFormatsSupplierObj > xAutoReleaseOld; // SYNCHRONIZED -> { ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); SvNumberFormatsSupplierObj* pNew = comphelper::getFromUnoTunnel( _xSupplier ); if (!pNew) throw uno::RuntimeException(); // wrong object xAutoReleaseOld = xSupplier; xSupplier = pNew; m_aMutex = xSupplier->getSharedMutex(); } // <- SYNCHRONIZED } uno::Reference SAL_CALL SvNumberFormatterServiceObj::getNumberFormatsSupplier() { ::osl::MutexGuard aGuard( m_aMutex ); return xSupplier; } sal_Int32 SAL_CALL SvNumberFormatterServiceObj::detectNumberFormat( sal_Int32 nKey, const OUString& aString ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); sal_uInt32 nUKey = nKey; double fValue = 0.0; if ( !pFormatter->IsNumberFormat(aString, nUKey, fValue) ) throw util::NotNumericException(); return nUKey; } double SAL_CALL SvNumberFormatterServiceObj::convertStringToNumber( sal_Int32 nKey, const OUString& aString ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); sal_uInt32 nUKey = nKey; double fValue = 0.0; if ( !pFormatter->IsNumberFormat(aString, nUKey, fValue) ) throw util::NotNumericException(); return fValue; } OUString SAL_CALL SvNumberFormatterServiceObj::convertNumberToString( sal_Int32 nKey, double fValue ) { ::osl::MutexGuard aGuard( m_aMutex ); OUString aRet; SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); const Color* pColor = nullptr; pFormatter->GetOutputString(fValue, nKey, aRet, &pColor); return aRet; } sal_Int32 SAL_CALL SvNumberFormatterServiceObj::queryColorForNumber( sal_Int32 nKey, double fValue, sal_Int32 aDefaultColor ) { ::osl::MutexGuard aGuard( m_aMutex ); util::Color nRet = aDefaultColor; // color = sal_Int32 SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); OUString aStr; const Color* pColor = nullptr; pFormatter->GetOutputString(fValue, nKey, aStr, &pColor); if (pColor) nRet = sal_uInt32(*pColor); // Else keep Default return nRet; } OUString SAL_CALL SvNumberFormatterServiceObj::formatString( sal_Int32 nKey, const OUString& aString ) { ::osl::MutexGuard aGuard( m_aMutex ); OUString aRet; SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) { throw uno::RuntimeException(); } const Color* pColor = nullptr; pFormatter->GetOutputString(aString, nKey, aRet, &pColor); return aRet; } sal_Int32 SAL_CALL SvNumberFormatterServiceObj::queryColorForString( sal_Int32 nKey, const OUString& aString, sal_Int32 aDefaultColor ) { ::osl::MutexGuard aGuard( m_aMutex ); util::Color nRet = aDefaultColor; // color = sal_Int32 SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) { throw uno::RuntimeException(); } OUString aStr; const Color* pColor = nullptr; pFormatter->GetOutputString(aString, nKey, aStr, &pColor); if (pColor) { nRet = sal_uInt32(*pColor); } // Else keep Default return nRet; } OUString SAL_CALL SvNumberFormatterServiceObj::getInputString( sal_Int32 nKey, double fValue ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); return pFormatter->GetInputLineString(fValue, nKey); } // XNumberFormatPreviewer OUString SAL_CALL SvNumberFormatterServiceObj::convertNumberToPreviewString( const OUString& aFormat, double fValue, const lang::Locale& nLocale, sal_Bool bAllowEnglish ) { ::osl::MutexGuard aGuard( m_aMutex ); OUString aRet; SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); const Color* pColor = nullptr; bool bOk; if ( bAllowEnglish ) bOk = pFormatter->GetPreviewStringGuess( aFormat, fValue, aRet, &pColor, eLang ); else bOk = pFormatter->GetPreviewString( aFormat, fValue, aRet, &pColor, eLang ); if (!bOk) throw util::MalformedNumberFormatException(); return aRet; } sal_Int32 SAL_CALL SvNumberFormatterServiceObj::queryPreviewColorForNumber( const OUString& aFormat, double fValue, const lang::Locale& nLocale, sal_Bool bAllowEnglish, sal_Int32 aDefaultColor ) { ::osl::MutexGuard aGuard( m_aMutex ); util::Color nRet = aDefaultColor; // color = sal_Int32 SvNumberFormatter* pFormatter = xSupplier.is() ? xSupplier->GetNumberFormatter() : nullptr; if (!pFormatter) throw uno::RuntimeException(); OUString aOutString; LanguageType eLang = lcl_GetLanguage( nLocale ); const Color* pColor = nullptr; bool bOk; if ( bAllowEnglish ) bOk = pFormatter->GetPreviewStringGuess( aFormat, fValue, aOutString, &pColor, eLang ); else bOk = pFormatter->GetPreviewString( aFormat, fValue, aOutString, &pColor, eLang ); if (!bOk) throw util::MalformedNumberFormatException(); if (pColor) nRet = sal_uInt32(*pColor); // Else keep Default return nRet; } // XServiceInfo OUString SAL_CALL SvNumberFormatterServiceObj::getImplementationName() { return u"com.sun.star.uno.util.numbers.SvNumberFormatterServiceObject"_ustr; } sal_Bool SAL_CALL SvNumberFormatterServiceObj::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence SAL_CALL SvNumberFormatterServiceObj::getSupportedServiceNames() { return { u"com.sun.star.util.NumberFormatter"_ustr }; } SvNumberFormatsObj::SvNumberFormatsObj( SvNumberFormatsSupplierObj& _rParent, ::comphelper::SharedMutex _aMutex ) :m_xSupplier( &_rParent ) ,m_aMutex(std::move( _aMutex )) { } SvNumberFormatsObj::~SvNumberFormatsObj() { } // XNumberFormats uno::Reference SAL_CALL SvNumberFormatsObj::getByKey( sal_Int32 nKey ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); const SvNumberformat* pFormat = pFormatter ? pFormatter->GetEntry(nKey) : nullptr; if (!pFormat) throw uno::RuntimeException(); return new SvNumberFormatObj( *m_xSupplier, nKey, m_aMutex ); } uno::Sequence SAL_CALL SvNumberFormatsObj::queryKeys( sal_Int16 nType, const lang::Locale& nLocale, sal_Bool bCreate ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if ( !pFormatter ) throw uno::RuntimeException(); sal_uInt32 nIndex = 0; LanguageType eLang = lcl_GetLanguage( nLocale ); SvNumberFormatTable& rTable = bCreate ? pFormatter->ChangeCL( static_cast(nType), nIndex, eLang ) : pFormatter->GetEntryTable( static_cast(nType), nIndex, eLang ); sal_uInt32 nCount = rTable.size(); uno::Sequence aSeq(nCount); sal_Int32* pAry = aSeq.getArray(); sal_uInt32 i=0; for (const auto& rEntry : rTable) { pAry[i] = rEntry.first; ++i; } return aSeq; } sal_Int32 SAL_CALL SvNumberFormatsObj::queryKey( const OUString& aFormat, const lang::Locale& nLocale, sal_Bool bScan ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); if (bScan) { //! FIXME: Something still needs to happen here ... } sal_uInt32 nRet = pFormatter->GetEntryKey( aFormat, eLang ); if (nRet == NUMBERFORMAT_ENTRY_NOT_FOUND) { // This seems to be a workaround for what maybe the bScan option was // intended for? Tokenize the format code? // The format string based search is vague and fuzzy, as it is case // sensitive, but the format string is only half way cased, the // keywords (except the "General" keyword) are uppercased and literals // of course are not. Clients using this queryKey() and if not // successful addNew() may still fail if the result of PutEntry() is // false because the format actually existed, just with a different // casing. The only clean way is to just use PutEntry() and ignore the // duplicate case, which clients can't because the API doesn't provide // the information. // Try just another possibility here, without any guarantee. // Use only ASCII upper, because keywords are only those. // Do not transliterate any quoted literals. const sal_Int32 nLen = aFormat.getLength(); OUStringBuffer aBuf(0); sal_Unicode* p = aBuf.appendUninitialized( nLen + 1); memcpy( p, aFormat.getStr(), (nLen + 1) * sizeof(sal_Unicode)); // including 0-char aBuf.setLength( nLen); assert(p == aBuf.getStr()); sal_Unicode const * const pStop = p + aBuf.getLength(); bool bQuoted = false; for ( ; p < pStop; ++p) { if (bQuoted) { // Format codes don't have embedded doubled quotes, i.e. "a""b" // is two literals displayed as `ab`. if (*p == '"') bQuoted = false; } else if (*p == '"') bQuoted = true; else if (rtl::isAsciiLowerCase(*p)) *p = rtl::toAsciiUpperCase(*p); else if (*p == '\\') ++p; // skip escaped next char // Theoretically that should cater for UTF-32 with // iterateCodePoints(), but such character would not match any // of [a-z\"] in its UTF-16 units. } nRet = pFormatter->GetEntryKey( aBuf, eLang ); } return static_cast(nRet); } sal_Int32 SAL_CALL SvNumberFormatsObj::addNew( const OUString& aFormat, const lang::Locale& nLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); sal_Int32 nRet = 0; SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); OUString aFormStr = aFormat; LanguageType eLang = lcl_GetLanguage( nLocale ); sal_uInt32 nKey = 0; sal_Int32 nCheckPos = 0; SvNumFormatType nType = SvNumFormatType::ALL; bool bOk = pFormatter->PutEntry( aFormStr, nCheckPos, nType, nKey, eLang ); if (bOk) nRet = nKey; else if (nCheckPos) { throw util::MalformedNumberFormatException(); // Invalid Format } else if (aFormStr != aFormat) { // The format exists but with a different format code string, and if it // was only uppercase vs lowercase keywords; but also syntax extensions // are possible like resulting embedded LCIDs and what not the client // doesn't know about. Silently accept instead of throwing an error. nRet = nKey; } else throw uno::RuntimeException(); // Other error (e.g. already added) return nRet; } sal_Int32 SAL_CALL SvNumberFormatsObj::addNewConverted( const OUString& aFormat, const lang::Locale& nLocale, const lang::Locale& nNewLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); sal_Int32 nRet = 0; SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); OUString aFormStr = aFormat; LanguageType eLang = lcl_GetLanguage( nLocale ); LanguageType eNewLang = lcl_GetLanguage( nNewLocale ); sal_uInt32 nKey = 0; sal_Int32 nCheckPos = 0; SvNumFormatType nType = SvNumFormatType::ALL; // This is used also when reading OOXML documents, there's no indicator // whether to convert date particle order as well, so don't. See tdf#119013 bool bOk = pFormatter->PutandConvertEntry( aFormStr, nCheckPos, nType, nKey, eLang, eNewLang, false); if (bOk || nKey > 0) nRet = nKey; else if (nCheckPos) { throw util::MalformedNumberFormatException(); // Invalid format } else throw uno::RuntimeException(); // Other error (e.g. already added) return nRet; } void SAL_CALL SvNumberFormatsObj::removeByKey( sal_Int32 nKey ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (pFormatter) { pFormatter->DeleteEntry(nKey); } } OUString SAL_CALL SvNumberFormatsObj::generateFormat( sal_Int32 nBaseKey, const lang::Locale& nLocale, sal_Bool bThousands, sal_Bool bRed, sal_Int16 nDecimals, sal_Int16 nLeading ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); OUString aRet = pFormatter->GenerateFormat(nBaseKey, eLang, bThousands, bRed, nDecimals, nLeading); return aRet; } // XNumberFormatTypes sal_Int32 SAL_CALL SvNumberFormatsObj::getStandardIndex( const lang::Locale& nLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); sal_Int32 nRet = pFormatter->GetStandardIndex(eLang); return nRet; } sal_Int32 SAL_CALL SvNumberFormatsObj::getStandardFormat( sal_Int16 nType, const lang::Locale& nLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); // Mask out "defined" bit, so type from an existing number format // can directly be used for getStandardFormat SvNumFormatType nType2 = static_cast(nType); nType2 &= ~SvNumFormatType::DEFINED; sal_Int32 nRet = pFormatter->GetStandardFormat(nType2, eLang); return nRet; } sal_Int32 SAL_CALL SvNumberFormatsObj::getFormatIndex( sal_Int16 nIndex, const lang::Locale& nLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); sal_Int32 nRet = pFormatter->GetFormatIndex( static_cast(nIndex), eLang ); return nRet; } sal_Bool SAL_CALL SvNumberFormatsObj::isTypeCompatible( sal_Int16 nOldType, sal_Int16 nNewType ) { ::osl::MutexGuard aGuard( m_aMutex ); return SvNumberFormatter::IsCompatible( static_cast(nOldType), static_cast(nNewType) ); } sal_Int32 SAL_CALL SvNumberFormatsObj::getFormatForLocale( sal_Int32 nKey, const lang::Locale& nLocale ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); LanguageType eLang = lcl_GetLanguage( nLocale ); sal_Int32 nRet = pFormatter->GetFormatForLanguageIfBuiltIn(nKey, eLang); return nRet; } // XServiceInfo OUString SAL_CALL SvNumberFormatsObj::getImplementationName() { return u"SvNumberFormatsObj"_ustr; } sal_Bool SAL_CALL SvNumberFormatsObj::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence SAL_CALL SvNumberFormatsObj::getSupportedServiceNames() { return { u"com.sun.star.util.NumberFormats"_ustr }; } SvNumberFormatObj::SvNumberFormatObj( SvNumberFormatsSupplierObj& rParent, sal_Int32 nK, ::comphelper::SharedMutex _aMutex ) :m_xSupplier( &rParent ) ,nKey( nK ) ,m_aMutex(std::move( _aMutex )) { } SvNumberFormatObj::~SvNumberFormatObj() { } // XPropertySet uno::Reference SAL_CALL SvNumberFormatObj::getPropertySetInfo() { static uno::Reference aRef = new SfxItemPropertySetInfo( lcl_GetNumberFormatPropertyMap() ); return aRef; } void SAL_CALL SvNumberFormatObj::setPropertyValue( const OUString&, const uno::Any& ) { throw beans::UnknownPropertyException(); // Everything is read-only } uno::Any SAL_CALL SvNumberFormatObj::getPropertyValue( const OUString& aPropertyName ) { ::osl::MutexGuard aGuard( m_aMutex ); uno::Any aRet; SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); const SvNumberformat* pFormat = pFormatter ? pFormatter->GetEntry(nKey) : nullptr; if (!pFormat) throw uno::RuntimeException(); bool bThousand, bRed; sal_uInt16 nDecimals, nLeading; if (aPropertyName == PROPERTYNAME_FMTSTR) { aRet <<= pFormat->GetFormatstring(); } else if (aPropertyName == PROPERTYNAME_LOCALE) { lang::Locale aLocale( LanguageTag::convertToLocale( pFormat->GetLanguage(), false)); aRet <<= aLocale; } else if (aPropertyName == PROPERTYNAME_TYPE) { aRet <<= static_cast( pFormat->GetType() ); } else if (aPropertyName == PROPERTYNAME_COMMENT) { aRet <<= pFormat->GetComment(); } else if (aPropertyName == PROPERTYNAME_STDFORM) { //! Pass through SvNumberformat Member bStandard? aRet <<= ( ( nKey % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ); } else if (aPropertyName == PROPERTYNAME_USERDEF) { aRet <<= bool( pFormat->GetType() & SvNumFormatType::DEFINED ); } else if (aPropertyName == PROPERTYNAME_DECIMALS) { pFormat->GetFormatSpecialInfo( bThousand, bRed, nDecimals, nLeading ); aRet <<= static_cast(nDecimals); } else if (aPropertyName == PROPERTYNAME_LEADING) { pFormat->GetFormatSpecialInfo( bThousand, bRed, nDecimals, nLeading ); aRet <<= static_cast(nLeading); } else if (aPropertyName == PROPERTYNAME_NEGRED) { pFormat->GetFormatSpecialInfo( bThousand, bRed, nDecimals, nLeading ); aRet <<= bRed; } else if (aPropertyName == PROPERTYNAME_THOUS) { pFormat->GetFormatSpecialInfo( bThousand, bRed, nDecimals, nLeading ); aRet <<= bThousand; } else if (aPropertyName == PROPERTYNAME_CURRSYM) { OUString aSymbol, aExt; pFormat->GetNewCurrencySymbol( aSymbol, aExt ); aRet <<= aSymbol; } else if (aPropertyName == PROPERTYNAME_CURREXT) { OUString aSymbol, aExt; pFormat->GetNewCurrencySymbol( aSymbol, aExt ); aRet <<= aExt; } else if (aPropertyName == PROPERTYNAME_CURRABB) { OUString aSymbol, aExt; bool bBank = false; pFormat->GetNewCurrencySymbol( aSymbol, aExt ); const NfCurrencyEntry* pCurr = SvNumberFormatter::GetCurrencyEntry( bBank, aSymbol, aExt, pFormat->GetLanguage() ); if ( pCurr ) aRet <<= pCurr->GetBankSymbol(); else aRet <<= OUString(); } else throw beans::UnknownPropertyException(aPropertyName); return aRet; } void SAL_CALL SvNumberFormatObj::addPropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatObj::removePropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatObj::addVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatObj::removeVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } // XPropertyAccess uno::Sequence SAL_CALL SvNumberFormatObj::getPropertyValues() { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); const SvNumberformat* pFormat = pFormatter ? pFormatter->GetEntry(nKey) : nullptr; if (!pFormat) throw uno::RuntimeException(); OUString aSymbol, aExt; OUString aAbb; bool bBank = false; pFormat->GetNewCurrencySymbol( aSymbol, aExt ); const NfCurrencyEntry* pCurr = SvNumberFormatter::GetCurrencyEntry( bBank, aSymbol, aExt, pFormat->GetLanguage() ); if ( pCurr ) aAbb = pCurr->GetBankSymbol(); OUString aFmtStr = pFormat->GetFormatstring(); OUString aComment = pFormat->GetComment(); bool bStandard = ( ( nKey % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ); //! Pass through SvNumberformat Member bStandard? bool bUserDef( pFormat->GetType() & SvNumFormatType::DEFINED ); bool bThousand, bRed; sal_uInt16 nDecimals, nLeading; pFormat->GetFormatSpecialInfo( bThousand, bRed, nDecimals, nLeading ); lang::Locale aLocale( LanguageTag( pFormat->GetLanguage()).getLocale()); uno::Sequence aSeq( comphelper::InitPropertySequence({ { PROPERTYNAME_FMTSTR, uno::Any(aFmtStr) }, { PROPERTYNAME_LOCALE, uno::Any(aLocale) }, { PROPERTYNAME_TYPE, uno::Any(sal_Int16( pFormat->GetType() )) }, { PROPERTYNAME_COMMENT, uno::Any(aComment) }, { PROPERTYNAME_STDFORM, uno::Any(bStandard) }, { PROPERTYNAME_USERDEF, uno::Any(bUserDef) }, { PROPERTYNAME_DECIMALS, uno::Any(sal_Int16( nDecimals )) }, { PROPERTYNAME_LEADING, uno::Any(sal_Int16( nLeading )) }, { PROPERTYNAME_NEGRED, uno::Any(bRed) }, { PROPERTYNAME_THOUS, uno::Any(bThousand) }, { PROPERTYNAME_CURRSYM, uno::Any(aSymbol) }, { PROPERTYNAME_CURREXT, uno::Any(aExt) }, { PROPERTYNAME_CURRABB, uno::Any(aAbb) } })); return aSeq; } void SAL_CALL SvNumberFormatObj::setPropertyValues( const uno::Sequence& ) { throw beans::UnknownPropertyException(); // Everything is read-only } // XServiceInfo OUString SAL_CALL SvNumberFormatObj::getImplementationName() { return u"SvNumberFormatObj"_ustr; } sal_Bool SAL_CALL SvNumberFormatObj::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence SAL_CALL SvNumberFormatObj::getSupportedServiceNames() { return { u"com.sun.star.util.NumberFormatProperties"_ustr }; } SvNumberFormatSettingsObj::SvNumberFormatSettingsObj( SvNumberFormatsSupplierObj& rParent, ::comphelper::SharedMutex _aMutex ) :m_xSupplier( &rParent ) ,m_aMutex(std::move( _aMutex )) { } SvNumberFormatSettingsObj::~SvNumberFormatSettingsObj() { } // XPropertySet uno::Reference SAL_CALL SvNumberFormatSettingsObj::getPropertySetInfo() { static uno::Reference aRef = new SfxItemPropertySetInfo( lcl_GetNumberSettingsPropertyMap() ); return aRef; } void SAL_CALL SvNumberFormatSettingsObj::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) { ::osl::MutexGuard aGuard( m_aMutex ); SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); if (aPropertyName == PROPERTYNAME_NOZERO) { // operator >>= shouldn't be used for bool (?) if ( auto b = o3tl::tryAccess(aValue) ) pFormatter->SetNoZero( *b ); } else if (aPropertyName == PROPERTYNAME_NULLDATE) { util::Date aDate; if ( aValue >>= aDate ) pFormatter->ChangeNullDate( aDate.Day, aDate.Month, aDate.Year ); } else if (aPropertyName == PROPERTYNAME_STDDEC) { sal_Int16 nInt16 = sal_Int16(); if ( aValue >>= nInt16 ) pFormatter->ChangeStandardPrec( nInt16 ); } else if (aPropertyName == PROPERTYNAME_TWODIGIT) { sal_Int16 nInt16 = sal_Int16(); if ( aValue >>= nInt16 ) pFormatter->SetYear2000( nInt16 ); } else throw beans::UnknownPropertyException(aPropertyName); } uno::Any SAL_CALL SvNumberFormatSettingsObj::getPropertyValue( const OUString& aPropertyName ) { ::osl::MutexGuard aGuard( m_aMutex ); uno::Any aRet; SvNumberFormatter* pFormatter = m_xSupplier->GetNumberFormatter(); if (!pFormatter) throw uno::RuntimeException(); if (aPropertyName == PROPERTYNAME_NOZERO) { aRet <<= pFormatter->GetNoZero(); } else if (aPropertyName == PROPERTYNAME_NULLDATE) { const Date& rDate = pFormatter->GetNullDate(); aRet <<= rDate.GetUNODate(); } else if (aPropertyName == PROPERTYNAME_STDDEC) aRet <<= static_cast( pFormatter->GetStandardPrec() ); else if (aPropertyName == PROPERTYNAME_TWODIGIT) aRet <<= static_cast( pFormatter->GetYear2000() ); else throw beans::UnknownPropertyException(aPropertyName); return aRet; } void SAL_CALL SvNumberFormatSettingsObj::addPropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatSettingsObj::removePropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatSettingsObj::addVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SvNumberFormatSettingsObj::removeVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } // XServiceInfo OUString SAL_CALL SvNumberFormatSettingsObj::getImplementationName() { return u"SvNumberFormatSettingsObj"_ustr; } sal_Bool SAL_CALL SvNumberFormatSettingsObj::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence SAL_CALL SvNumberFormatSettingsObj::getSupportedServiceNames() { return { u"com.sun.star.util.NumberFormatSettings"_ustr }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* com_sun_star_uno_util_numbers_SvNumberFormatterServiceObject_get_implementation(css::uno::XComponentContext*, css::uno::Sequence const &) { return cppu::acquire(new SvNumberFormatterServiceObj()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */