summaryrefslogtreecommitdiff
path: root/xmloff
diff options
context:
space:
mode:
authorLaurent Balland <laurent.balland@mailo.fr>2023-01-14 15:48:12 +0100
committerEike Rathke <erack@redhat.com>2023-01-30 17:00:46 +0000
commit46b7fd59f9d0dfb5544df99494d3a3d3a372ae8b (patch)
treed446f477e8f8de4268eb77284c5913450ece088a /xmloff
parente783208906611238a9a6ce9d14029eb732fc611d (diff)
tdf#118324 Treat blank ? in integer
Restore and update change 56352 Test of https://cgit.freedesktop.org/libreoffice/core/commit/?id=8ca6468f0f4900d4d3bb45e0e938fe35c308512c is now ok Add disambiguation between '0' and '?' in integer part XML_MAX_BLANK_INTEGER_DIGITS is added for the number of '?' XML_MIN_INTEGER_DIGITS is the number of '?' and '0' This preserve compatibility with previous versions: in previous versions '?' will be transformed in '0' It also applies to scientific and fraction numbers. Integer part for number, scientific and fraction are treated the same way Include QA unit test Change-Id: Iab3127bf07223caac60e409306a1bee2edc37428 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145932 Tested-by: Jenkins Reviewed-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'xmloff')
-rw-r--r--xmloff/source/core/xmltoken.cxx1
-rw-r--r--xmloff/source/style/xmlnumfe.cxx101
-rw-r--r--xmloff/source/style/xmlnumfi.cxx29
-rw-r--r--xmloff/source/token/tokens.txt1
4 files changed, 82 insertions, 50 deletions
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index d1d2047a50b9..78ef34951013 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -3450,6 +3450,7 @@ namespace xmloff::token {
TOKEN( "zeros-numerator-digits", XML_ZEROS_NUMERATOR_DIGITS ),
TOKEN( "zeros-denominator-digits", XML_ZEROS_DENOMINATOR_DIGITS ),
TOKEN( "integer-fraction-delimiter", XML_INTEGER_FRACTION_DELIMITER ),
+ TOKEN( "max-blank-integer-digits", XML_MAX_BLANK_INTEGER_DIGITS ),
// for optional language-dependent reference formats
TOKEN( "reference-language", XML_REFERENCE_LANGUAGE ),
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 01367fe12e55..7d44f43342ef 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -532,9 +532,32 @@ void SvXMLNumFmtExport::WriteAMPMElement_Impl()
// numbers
+void SvXMLNumFmtExport::WriteIntegerElement_Impl(
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, bool bGrouping )
+{
+ // integer digits: '0' and '?'
+ if ( nInteger >= 0 ) // negative = automatic
+ {
+ rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
+ OUString::number( nInteger ) );
+ }
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
+ // blank integer digits: '?'
+ if ( nBlankInteger > 0 && ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0 ) )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_MAX_BLANK_INTEGER_DIGITS,
+ OUString::number( nBlankInteger ) );
+ }
+ // (automatic) grouping separator
+ if ( bGrouping )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
+ }
+}
+
void SvXMLNumFmtExport::WriteNumberElement_Impl(
sal_Int32 nDecimals, sal_Int32 nMinDecimals,
- sal_Int32 nInteger, const OUString& rDashStr,
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, const OUString& rDashStr,
bool bGrouping, sal_Int32 nTrailingThousands,
const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
{
@@ -547,10 +570,10 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl(
OUString::number( nDecimals ) );
}
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
if ( nMinDecimals >= 0 ) // negative = automatic
{
// Export only for 1.2 with extensions or 1.3 and later.
- SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
if (eVersion > SvtSaveOptions::ODFSVER_012)
{
// OFFICE-3860 For 1.2+ use loext namespace, for 1.3 use number namespace.
@@ -560,14 +583,6 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl(
OUString::number( nMinDecimals ) );
}
}
-
- // integer digits
- if ( nInteger >= 0 ) // negative = automatic
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
- OUString::number( nInteger ) );
- }
-
// decimal replacement (dashes) or variable decimals (#)
if ( !rDashStr.isEmpty() || nMinDecimals < nDecimals )
{
@@ -576,11 +591,7 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl(
rDashStr );
}
- // (automatic) grouping separator
- if ( bGrouping )
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
- }
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
// display-factor if there are trailing thousands separators
if ( nTrailingThousands )
@@ -626,7 +637,7 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl(
}
void SvXMLNumFmtExport::WriteScientificElement_Impl(
- sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger,
+ sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger, sal_Int32 nBlankInteger,
bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign )
{
FinishTextElement_Impl();
@@ -652,18 +663,7 @@ void SvXMLNumFmtExport::WriteScientificElement_Impl(
}
}
- // integer digits
- if ( nInteger >= 0 ) // negative = automatic
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
- OUString::number( nInteger ) );
- }
-
- // (automatic) grouping separator
- if ( bGrouping )
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
- }
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
// exponent digits
if ( nExp >= 0 )
@@ -702,10 +702,12 @@ void SvXMLNumFmtExport::WriteScientificElement_Impl(
}
void SvXMLNumFmtExport::WriteFractionElement_Impl(
- sal_Int32 nInteger, bool bGrouping,
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, bool bGrouping,
const SvNumberformat& rFormat, sal_uInt16 nPart )
{
FinishTextElement_Impl();
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
+
const OUString aNumeratorString = rFormat.GetNumeratorString( nPart );
const OUString aDenominatorString = rFormat.GetDenominatorString( nPart );
const OUString aIntegerFractionDelimiterString = rFormat.GetIntegerFractionDelimiterString( nPart );
@@ -734,21 +736,9 @@ void SvXMLNumFmtExport::WriteFractionElement_Impl(
nZerosDenominatorDigits = 0;
sal_Int32 nDenominator = aDenominatorString.toInt32();
- // integer digits
- if ( nInteger >= 0 ) // negative = default (no integer part)
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
- OUString::number( nInteger ) );
- }
-
- // (automatic) grouping separator
- if ( bGrouping )
- {
- rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
- }
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
// integer/fraction delimiter
- SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
if ( !aIntegerFractionDelimiterString.isEmpty() && aIntegerFractionDelimiterString != " "
&& ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0) )
{ // Export only for 1.2/1.3 with extensions.
@@ -1249,7 +1239,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
if ( eBuiltIn == NF_NUMBER_STANDARD )
{
// default number format contains just one number element
- WriteNumberElement_Impl( -1, -1, 1, OUString(), false, 0, aEmbeddedEntries );
+ WriteNumberElement_Impl( -1, -1, 1, -1, OUString(), false, 0, aEmbeddedEntries );
bAnyContent = true;
}
else if ( eBuiltIn == NF_BOOLEAN )
@@ -1303,6 +1293,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#"
sal_Int32 nTrailingThousands = 0; // thousands-separators after all digits
sal_Int32 nMinDecimals = nPrecision;
+ sal_Int32 nBlankInteger = 0;
OUString sCurrExt;
OUString aCalendar;
bool bImplicitOtherCalendar = false;
@@ -1327,7 +1318,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
bDecDashes = true;
nMinDecimals = 0;
}
- else if ( !bInInteger && pElemStr )
+ else if ( nFmtType != SvNumFormatType::FRACTION && !bInInteger && pElemStr )
{
for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
{
@@ -1343,9 +1334,17 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
}
}
if ( bInInteger && pElemStr )
+ {
nIntegerSymbols += pElemStr->getLength();
+ for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
+ {
+ if ( (*pElemStr)[i] == '?' )
+ nBlankInteger ++;
+ }
+ }
nTrailingThousands = 0;
break;
+ case NF_SYMBOLTYPE_FRACBLANK:
case NF_SYMBOLTYPE_DECSEP:
bInInteger = false;
break;
@@ -1507,7 +1506,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
}
break;
case NF_KEY_GENERAL :
- WriteNumberElement_Impl( -1, -1, 1, OUString(), false, 0, aEmbeddedEntries );
+ WriteNumberElement_Impl( -1, -1, 1, -1, OUString(), false, 0, aEmbeddedEntries );
bAnyContent = true;
break;
case NF_KEY_CCC:
@@ -1566,7 +1565,10 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
// only one built-in format has automatic integer digits
sal_Int32 nInteger = nLeading;
if ( eBuiltIn == NF_NUMBER_SYSTEM )
+ {
nInteger = -1;
+ nBlankInteger = -1;
+ }
// string for decimal replacement
// has to be taken from nPrecision
@@ -1578,16 +1580,16 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
if (bDecAlign && nPrecision > 0)
sDashStr = " ";
- WriteNumberElement_Impl(nDecimals, nMinDecimals, nInteger, sDashStr.makeStringAndClear(),
+ WriteNumberElement_Impl(nDecimals, nMinDecimals, nInteger, nBlankInteger, sDashStr.makeStringAndClear(),
bThousand, nTrailingThousands, aEmbeddedEntries);
bAnyContent = true;
}
break;
case SvNumFormatType::SCIENTIFIC:
- // #i43959# for scientific numbers, count all integer symbols ("0" and "#")
+ // #i43959# for scientific numbers, count all integer symbols ("0", "?" and "#")
// as integer digits: use nIntegerSymbols instead of nLeading
// nIntegerSymbols represents exponent interval (for engineering notation)
- WriteScientificElement_Impl( nPrecision, nMinDecimals, nLeading, bThousand, nExpDigits, nIntegerSymbols, bExpSign );
+ WriteScientificElement_Impl( nPrecision, nMinDecimals, nLeading, nBlankInteger, bThousand, nExpDigits, nIntegerSymbols, bExpSign );
bAnyContent = true;
break;
case SvNumFormatType::FRACTION:
@@ -1599,8 +1601,9 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
// the fraction doesn't have an integer part, and no
// min-integer-digits attribute must be written.
nInteger = -1;
+ nBlankInteger = -1;
}
- WriteFractionElement_Impl( nInteger, bThousand, rFormat, nPart );
+ WriteFractionElement_Impl( nInteger, nBlankInteger, bThousand, rFormat, nPart );
bAnyContent = true;
}
break;
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index 370af2bde369..7cb1b7d679ef 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -88,7 +88,8 @@ public:
struct SvXMLNumberInfo
{
sal_Int32 nDecimals = -1;
- sal_Int32 nInteger = -1;
+ sal_Int32 nInteger = -1; /// Total min number of digits in integer part ('0' + '?')
+ sal_Int32 nBlankInteger = -1; /// Number of '?' in integer part
sal_Int32 nExpDigits = -1;
sal_Int32 nExpInterval = -1;
sal_Int32 nMinNumerDigits = -1;
@@ -675,6 +676,11 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
aNumInfo.nInteger = nAttrVal;
break;
+ case XML_ELEMENT(LO_EXT, XML_MAX_BLANK_INTEGER_DIGITS):
+ case XML_ELEMENT(NUMBER, XML_MAX_BLANK_INTEGER_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nBlankInteger = nAttrVal;
+ break;
case XML_ELEMENT(NUMBER, XML_GROUPING):
if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
aNumInfo.bGrouping = bAttrBool;
@@ -776,6 +782,8 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
}
}
+ if ( aNumInfo.nBlankInteger > aNumInfo.nInteger )
+ aNumInfo.nInteger = aNumInfo.nBlankInteger;
if ( aNumInfo.nMinDecimalDigits == -1)
{
if ( bVarDecimals || aNumInfo.bDecReplace )
@@ -1722,6 +1730,25 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
aNumStr.stripStart('#');
}
+ if ( rInfo.nBlankInteger > 0 )
+ {
+ // Replace nBlankInteger '0' by '?'
+ sal_Int32 nIndex = 0;
+ sal_Int32 nBlanks = rInfo.nBlankInteger;
+ sal_Int32 nIntegerEnd = aNumStr.indexOf( pFormatter->GetNumDecimalSep() );
+ if ( nIntegerEnd < 0 )
+ nIntegerEnd = aNumStr.getLength();
+ while ( nIndex < nIntegerEnd && nBlanks > 0 )
+ {
+ if ( aNumStr[nIndex] == '0' )
+ {
+ aNumStr[nIndex] = '?';
+ nBlanks--;
+ }
+ nIndex++;
+ }
+ }
+
if ( bGrouping && rInfo.nExpInterval > rInfo.nInteger )
{
sal_Int32 nIndex = 0;
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index e4a0a5fe7c36..74a725d91b30 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -3206,6 +3206,7 @@ max-numerator-digits
zeros-numerator-digits
zeros-denominator-digits
integer-fraction-delimiter
+max-blank-integer-digits
reference-language
newline
creator-initials