summaryrefslogtreecommitdiff
path: root/svl
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-10-04 23:50:31 +0200
committerEike Rathke <erack@redhat.com>2017-10-05 09:26:30 +0200
commit5be8c9cc1b92101e6f9fe5685df86e77d3eee3cc (patch)
tree3ab94d8dde0cf5df515c46c4866c254b32a0c410 /svl
parent4fd81a26681063dcc0d8d2eae795d39c8d894cb8 (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')
-rw-r--r--svl/source/numbers/zforlist.cxx47
-rw-r--r--svl/source/numbers/zformat.cxx61
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 );