diff options
-rw-r--r-- | include/svl/zforlist.hxx | 6 | ||||
-rw-r--r-- | include/svl/zformat.hxx | 32 | ||||
-rw-r--r-- | include/xmloff/xmlnumfe.hxx | 4 | ||||
-rw-r--r-- | svl/source/numbers/zforlist.cxx | 47 | ||||
-rw-r--r-- | svl/source/numbers/zformat.cxx | 61 | ||||
-rw-r--r-- | xmloff/source/style/xmlnumfe.cxx | 23 |
6 files changed, 154 insertions, 19 deletions
diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx index 35a1bc5c50c1..19015cc1000c 100644 --- a/include/svl/zforlist.hxx +++ b/include/svl/zforlist.hxx @@ -552,6 +552,9 @@ public: /// Return the format for a format index const SvNumberformat* GetEntry( sal_uInt32 nKey ) const; + /// Obtain substituted GetFormatEntry(), i.e. system formats. + const SvNumberformat* GetSubstitutedEntry( sal_uInt32 nKey, sal_uInt32 & o_rNewKey ) const; + /// Return the format index of the standard default number format for language/country sal_uInt32 GetStandardIndex(LanguageType eLnge = LANGUAGE_DONTKNOW); @@ -904,6 +907,9 @@ private: // return position of a special character sal_Int32 ImpPosToken ( const OUStringBuffer & sFormat, sal_Unicode token, sal_Int32 nStartPos = 0 ); + // Substitute a format during GetFormatEntry(), i.e. system formats. + SvNumberformat* ImpSubstituteEntry( SvNumberformat* pFormat, sal_uInt32 * o_pRealKey = nullptr ); + public: // own static mutex, may also be used by internal class SvNumberFormatterRegistry_Impl diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx index 6fcb24dd7a24..5d0e1f288643 100644 --- a/include/svl/zformat.hxx +++ b/include/svl/zformat.hxx @@ -141,9 +141,17 @@ class SVL_DLLPUBLIC SvNumberformat { struct LocaleType { + enum class Substitute : sal_uInt8 + { + NONE, + TIME, + LONGDATE + }; + + LanguageType meLanguage; + Substitute meSubstitute; sal_uInt8 mnNumeralShape; sal_uInt8 mnCalendarType; - LanguageType meLanguage; OUString generateCode() const; @@ -184,6 +192,28 @@ public: LanguageType GetLanguage() const { return maLocale.meLanguage;} + /** If the format is a placeholder and needs to be substituted. */ + bool IsSubstituted() const + { + return maLocale.meSubstitute != LocaleType::Substitute::NONE; + } + + /** If the format is a placeholder for the sytem time format and needs to + be substituted during formatting time. + */ + bool IsSystemTimeFormat() const + { + return maLocale.meSubstitute == LocaleType::Substitute::TIME && maLocale.meLanguage == LANGUAGE_SYSTEM; + } + + /** If the format is a placeholder for the sytem long date format and needs + to be substituted during formatting time. + */ + bool IsSystemLongDateFormat() const + { + return maLocale.meSubstitute == LocaleType::Substitute::LONGDATE && maLocale.meLanguage == LANGUAGE_SYSTEM; + } + const OUString& GetFormatstring() const { return sFormatstring; } // Build a format string of application defined keywords diff --git a/include/xmloff/xmlnumfe.hxx b/include/xmloff/xmlnumfe.hxx index c3c51ea57797..79df5c853f5d 100644 --- a/include/xmloff/xmlnumfe.hxx +++ b/include/xmloff/xmlnumfe.hxx @@ -92,10 +92,10 @@ private: SAL_DLLPRIVATE void WriteRepeatedElement_Impl( sal_Unicode ch ); SAL_DLLPRIVATE bool WriteTextWithCurrency_Impl( const OUString& rString, const css::lang::Locale& rLocale ); - SAL_DLLPRIVATE void ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, + SAL_DLLPRIVATE void ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey, sal_uInt16 nPart, bool bDefPart ); - SAL_DLLPRIVATE void ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey ); + SAL_DLLPRIVATE void ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey ); public: SvXMLNumFmtExport( SvXMLExport& rExport, diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx index c573a02ba377..1a5147daaa54 100644 --- a/svl/source/numbers/zforlist.cxx +++ b/svl/source/numbers/zforlist.cxx @@ -1065,7 +1065,7 @@ bool SvNumberFormatter::IsNumberFormat(const OUString& sString, double& fOutNumber) { short FType; - const SvNumberformat* pFormat = GetFormatEntry(F_Index); + const SvNumberformat* pFormat = ImpSubstituteEntry( GetFormatEntry(F_Index)); if (!pFormat) { ChangeIntl(IniLnge); @@ -1472,7 +1472,8 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber, OUString& sOutString) { Color* pColor; - SvNumberformat* pFormat = GetFormatEntry( nFIndex ); + sal_uInt32 nRealKey = nFIndex; + SvNumberformat* pFormat = ImpSubstituteEntry( GetFormatEntry( nFIndex ), &nRealKey); if (!pFormat) { pFormat = GetFormatEntry(ZF_STANDARD); @@ -1507,8 +1508,8 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber, bPrecChanged = true; } - sal_uInt32 nKey = GetEditFormat( fOutNumber, nFIndex, eType, eLang, pFormat); - if ( nKey != nFIndex ) + sal_uInt32 nKey = GetEditFormat( fOutNumber, nRealKey, eType, eLang, pFormat); + if ( nKey != nRealKey ) { pFormat = GetFormatEntry( nKey ); } @@ -1534,6 +1535,8 @@ void SvNumberFormatter::GetOutputString(const OUString& sString, bool bUseStarFormat ) { SvNumberformat* pFormat = GetFormatEntry( nFIndex ); + // ImpSubstituteEntry() is unnecessary here because so far only numeric + // (time and date) are substituted. if (!pFormat) { pFormat = GetFormatEntry(ZF_STANDARD_TEXT); @@ -1569,7 +1572,7 @@ void SvNumberFormatter::GetOutputString(const double& fOutNumber, sOutString.clear(); return; } - SvNumberformat* pFormat = GetFormatEntry( nFIndex ); + SvNumberformat* pFormat = ImpSubstituteEntry( GetFormatEntry( nFIndex )); if (!pFormat) pFormat = GetFormatEntry(ZF_STANDARD); ChangeIntl(pFormat->GetLanguage()); @@ -2216,6 +2219,40 @@ const SvNumberformat* SvNumberFormatter::GetEntry( sal_uInt32 nKey ) const return nullptr; } +const SvNumberformat* SvNumberFormatter::GetSubstitutedEntry( sal_uInt32 nKey, sal_uInt32 & o_rNewKey ) const +{ + // A tad ugly, but GetStandardFormat() and GetFormatIndex() in + // ImpSubstituteEntry() may have to add the LANGUAGE_SYSTEM formats if not + // already present (which in practice most times they are). + SvNumberFormatter* pThis = const_cast<SvNumberFormatter*>(this); + return pThis->ImpSubstituteEntry( pThis->GetFormatEntry( nKey), &o_rNewKey); +} + +SvNumberformat* SvNumberFormatter::ImpSubstituteEntry( SvNumberformat* pFormat, sal_uInt32 * o_pRealKey ) +{ + if (!pFormat || !pFormat->IsSubstituted()) + return pFormat; + + // XXX NOTE: substitution can not be done in GetFormatEntry() as otherwise + // to be substituted formats would "vanish", i.e. from the number formatter + // dialog or when exporting to Excel. + + sal_uInt32 nKey; + if (pFormat->IsSystemTimeFormat()) + /* TODO: should we have NF_TIME_SYSTEM for consistency? */ + nKey = GetStandardFormat( css::util::NumberFormat::TIME, LANGUAGE_SYSTEM); + else if (pFormat->IsSystemLongDateFormat()) + /* TODO: either that above, or have a long option for GetStandardFormat() */ + nKey = GetFormatIndex( NF_DATE_SYSTEM_LONG, LANGUAGE_SYSTEM); + else + return pFormat; + + if (o_pRealKey) + *o_pRealKey = nKey; + SvNumberFormatTable::const_iterator it = aFTable.find( nKey); + return it == aFTable.end() ? nullptr : it->second; +} + void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, bool bNoAdditionalFormats ) { bool bOldConvertMode = pFormatScanner->GetConvertMode(); diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index d40c7d977f17..116b5e668df5 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -1208,6 +1208,24 @@ SvNumberformat::SvNumberformat(OUString& rString, } } + if (!nCheckPos && IsSubstituted()) + { + // For to be substituted formats the scanned type must match the + // substitute type. + if (IsSystemTimeFormat()) + { + if ((eType & ~css::util::NumberFormat::DEFINED) != css::util::NumberFormat::TIME) + nCheckPos = std::max<sal_Int32>( sBuff.indexOf(']') + 1, 1); + } + else if (IsSystemLongDateFormat()) + { + if ((eType & ~css::util::NumberFormat::DEFINED) != css::util::NumberFormat::DATE) + nCheckPos = std::max<sal_Int32>( sBuff.indexOf(']') + 1, 1); + } + else + assert(!"unhandled substitute"); + } + if ( bCondition && !nCheckPos ) { if ( nIndex == 1 && NumFor[0].GetCount() == 0 && @@ -1437,6 +1455,21 @@ OUString SvNumberformat::LocaleType::generateCode() const #endif sal_uInt16 n16 = static_cast<sal_uInt16>(meLanguage); + if (meLanguage == LANGUAGE_SYSTEM) + { + switch (meSubstitute) + { + case Substitute::NONE: + ; // nothing + break; + case Substitute::TIME: + n16 = static_cast<sal_uInt16>(LANGUAGE_NF_SYSTEM_TIME); + break; + case Substitute::LONGDATE: + n16 = static_cast<sal_uInt16>(LANGUAGE_NF_SYSTEM_DATE); + break; + } + } for (sal_uInt8 i = 0; i < 4; ++i) { sal_uInt8 n = static_cast<sal_uInt8>((n16 & 0xF000) >> 12); @@ -1452,18 +1485,30 @@ OUString SvNumberformat::LocaleType::generateCode() const } SvNumberformat::LocaleType::LocaleType() - : mnNumeralShape(0) + : meLanguage(LANGUAGE_DONTKNOW) + , meSubstitute(Substitute::NONE) + , mnNumeralShape(0) , mnCalendarType(0) - , meLanguage(LANGUAGE_DONTKNOW) { } SvNumberformat::LocaleType::LocaleType(sal_uInt32 nRawNum) - : mnNumeralShape(0) + : meLanguage(LANGUAGE_DONTKNOW) + , meSubstitute(Substitute::NONE) + , mnNumeralShape(0) , mnCalendarType(0) - , meLanguage(LANGUAGE_DONTKNOW) { meLanguage = static_cast<LanguageType>(nRawNum & 0x0000FFFF); + if (meLanguage == LANGUAGE_NF_SYSTEM_TIME) + { + meSubstitute = Substitute::TIME; + meLanguage = LANGUAGE_SYSTEM; + } + else if (meLanguage == LANGUAGE_NF_SYSTEM_DATE) + { + meSubstitute = Substitute::LONGDATE; + meLanguage = LANGUAGE_SYSTEM; + } nRawNum = (nRawNum >> 16); mnCalendarType = static_cast<sal_uInt8>(nRawNum & 0xFF); nRawNum = (nRawNum >> 8); @@ -4913,6 +4958,14 @@ OUString SvNumberformat::GetMappedFormatstring( const NfKeywordTable& rKeywords, LanguageType nOriginalLang /* =LANGUAGE_DONTKNOW */ ) const { OUStringBuffer aStr; + if (maLocale.meSubstitute != LocaleType::Substitute::NONE) + { + // XXX: theoretically this could clash with the first subformat's + // lcl_insertLCID() below, in practice as long as it is used for system + // time and date modifiers it shouldn't (i.e. there is no calendar or + // numeral specified as well). + aStr.append("[$-").append( maLocale.generateCode()).append(']'); + } bool bDefault[4]; // 1 subformat matches all if no condition specified, bDefault[0] = ( NumFor[1].GetCount() == 0 && eOp1 == NUMBERFORMAT_OP_NO ); diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx index a1ee8d905804..c2f1920e8bda 100644 --- a/xmloff/source/style/xmlnumfe.cxx +++ b/xmloff/source/style/xmlnumfe.cxx @@ -1040,14 +1040,14 @@ static bool lcl_IsDefaultDateFormat( const SvNumberformat& rFormat, bool bSystem // export one part (condition) -void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, +void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey, sal_uInt16 nPart, bool bDefPart ) { //! for the default part, pass the conditions from the other parts! // element name - NfIndexTableOffset eBuiltIn = pFormatter->GetIndexTableOffset( nKey ); + NfIndexTableOffset eBuiltIn = pFormatter->GetIndexTableOffset( nRealKey ); short nFmtType = 0; bool bThousand = false; @@ -1768,7 +1768,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt // export one format -void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey ) +void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey ) { const sal_uInt16 XMLNUM_MAX_PARTS = 4; bool bParts[XMLNUM_MAX_PARTS] = { false, false, false, false }; @@ -1812,7 +1812,7 @@ void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uI if (bParts[nPart]) { bool bDefault = ( nPart+1 == nUsedParts ); // last = default - ExportPart_Impl( rFormat, nKey, nPart, bDefault ); + ExportPart_Impl( rFormat, nKey, nRealKey, nPart, bDefault ); } } } @@ -1829,9 +1829,12 @@ void SvXMLNumFmtExport::Export( bool bIsAutoStyle ) bool bNext(pUsedList->GetFirstUsed(nKey)); while(bNext) { - pFormat = pFormatter->GetEntry(nKey); + // ODF has its notation of system formats, so obtain the "real" already + // substituted format but use the original key for style name. + sal_uInt32 nRealKey = nKey; + pFormat = pFormatter->GetSubstitutedEntry( nKey, nRealKey); if(pFormat) - ExportFormat_Impl( *pFormat, nKey ); + ExportFormat_Impl( *pFormat, nKey, nRealKey ); bNext = pUsedList->GetNextUsed(nKey); } if (!bIsAutoStyle) @@ -1853,8 +1856,14 @@ void SvXMLNumFmtExport::Export( bool bIsAutoStyle ) if (!pUsedList->IsUsed(nKey)) { DBG_ASSERT((pFormat->GetType() & css::util::NumberFormat::DEFINED), "a not user defined numberformat found"); + sal_uInt32 nRealKey = nKey; + if (pFormat->IsSubstituted()) + { + pFormat = pFormatter->GetSubstitutedEntry( nKey, nRealKey); // export the "real" format + assert(pFormat); + } // user-defined and used formats are exported - ExportFormat_Impl( *pFormat, nKey ); + ExportFormat_Impl( *pFormat, nKey, nRealKey ); // if it is a user-defined Format it will be added else nothing will happen pUsedList->SetUsed(nKey); } |