diff options
author | Eike Rathke <erack@redhat.com> | 2017-10-04 23:50:31 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-10-05 09:26:30 +0200 |
commit | 5be8c9cc1b92101e6f9fe5685df86e77d3eee3cc (patch) | |
tree | 3ab94d8dde0cf5df515c46c4866c254b32a0c410 /svl/source/numbers | |
parent | 4fd81a26681063dcc0d8d2eae795d39c8d894cb8 (diff) |
Resolves: tdf#102075 support system [$-F400] time and [$-F800] long date
By substituting a (valid matching the type) format using these
special LCID modifier values with the current system locale's
format.
See ECMA-376-1:2016 18.8.31 numFmts (Number Formats) and
https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.numberingformats.aspx
which seems to be the only documentation available.
Change-Id: Ieca048a77d4ef473ae475e202557d1353ff5387d
Reviewed-on: https://gerrit.libreoffice.org/43148
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'svl/source/numbers')
-rw-r--r-- | svl/source/numbers/zforlist.cxx | 47 | ||||
-rw-r--r-- | svl/source/numbers/zformat.cxx | 61 |
2 files changed, 99 insertions, 9 deletions
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 ); |