[Libreoffice-commits] core.git: include/svl include/xmloff svl/source xmloff/source

Laurent Balland-Poirier laurent.balland-poirier at laposte.net
Mon May 30 12:03:00 UTC 2016


 include/svl/zformat.hxx          |    1 
 include/xmloff/xmlnumfe.hxx      |    2 -
 include/xmloff/xmltoken.hxx      |    2 +
 svl/source/numbers/zformat.cxx   |   26 +++++++++++++-
 xmloff/source/core/xmltoken.cxx  |    2 +
 xmloff/source/style/xmlnumfe.cxx |   51 +++++++++++++++++++++------
 xmloff/source/style/xmlnumfi.cxx |   72 +++++++++++++++++++++++++++++++--------
 7 files changed, 129 insertions(+), 27 deletions(-)

New commits:
commit 1544a26ac9f7dd60605dd21e9cbe29d490aafdce
Author: Laurent Balland-Poirier <laurent.balland-poirier at laposte.net>
Date:   Wed May 11 06:54:15 2016 +0200

    tdf#99661 Add max-denominator-value attribute to number:fraction
    
    Add max-denominator-value attibute to <number:fraction> to comply with ODF 1.3
    See https://issues.oasis-open.org/browse/OFFICE-3695
    Specify loext or number according to ODF version
    This value is only used to stored the number of digits in numerator.
    No other values than 9, 99, 999,... are expected.
    
    Add loext:max-numerator-digits attributes to <number:fraction>
     to distinguish
    ??/?? and ##/## or any combination
    Not saved for ODF strict
    min-...-digits indicates the number of '?'
    max-...-digits indicates the total number of '?' and '#'
    This needs to be saved with both min-...-digits at least one
    because previous versions cannot have min-...-digits of 0. See tdf#38097
    
    Change-Id: Ibd785579aa75edc315e3bd94935a146d82bbeeef
    Reviewed-on: https://gerrit.libreoffice.org/24903
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx
index 916a0d3..b9c4101 100644
--- a/include/svl/zformat.hxx
+++ b/include/svl/zformat.hxx
@@ -250,6 +250,7 @@ public:
     short GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos ) const;
 
     OUString GetDenominatorString( sal_uInt16 nNumFor ) const;
+    OUString GetNumeratorString( sal_uInt16 nNumFor ) const;
     /** If the count of string elements (substrings, ignoring [modifiers] and
         so on) in a subformat code nNumFor (0..3) is equal to the given number.
         Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched
diff --git a/include/xmloff/xmlnumfe.hxx b/include/xmloff/xmlnumfe.hxx
index 0f9d19a..8e47ff6 100644
--- a/include/xmloff/xmlnumfe.hxx
+++ b/include/xmloff/xmlnumfe.hxx
@@ -69,7 +69,7 @@ private:
     SAL_DLLPRIVATE void WriteScientificElement_Impl( sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger,
                                         bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign );
     SAL_DLLPRIVATE void WriteFractionElement_Impl( sal_Int32 nInteger, bool bGrouping,
-                                        sal_Int32 nNumeratorDigits, sal_Int32 nDenominatorDigits, sal_Int32 nDenominator );
+                                                   const OUString& aNumeratorString, const OUString& aDenominatorString );
     SAL_DLLPRIVATE void WriteCurrencyElement_Impl( const OUString& rString,
                                         const OUString& rExt );
     SAL_DLLPRIVATE void WriteBooleanElement_Impl();
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index ccbb8cf..aaabbba 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -3259,6 +3259,8 @@ namespace xmloff { namespace token {
         XML_EXPONENT_INTERVAL,
         XML_FORCED_EXPONENT_SIGN,
         XML_MIN_DECIMAL_PLACES,
+        XML_MAX_DENOMINATOR_VALUE,
+        XML_MAX_NUMERATOR_DIGITS,
 
         XML_TOKEN_END
     };
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 0529f27..2f2d412 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -2004,7 +2004,6 @@ void lcl_GetOutputStringScientific(double fNumber, sal_uInt16 nCharCount,
                                               nPrec, rFormatter.GetNumDecimalSep()[0], true );
 }
 
-
 OUString lcl_GetDenominatorString(const ImpSvNumberformatInfo &rInfo, sal_uInt16 nAnz)
 {
     sal_uInt16 i;
@@ -2025,6 +2024,24 @@ OUString lcl_GetDenominatorString(const ImpSvNumberformatInfo &rInfo, sal_uInt16
     return aDenominatorString.makeStringAndClear();
 }
 
+OUString lcl_GetNumeratorString(const ImpSvNumberformatInfo &rInfo, sal_uInt16 nAnz)
+{
+    sal_Int16 i;
+    OUStringBuffer aNumeratorString;
+    for( i = 0; i < nAnz; i++ )
+    {
+        if( rInfo.nTypeArray[i] == NF_SYMBOLTYPE_FRAC )
+        {
+            for( i--; i >= 0 && rInfo.nTypeArray[i] == NF_SYMBOLTYPE_DIGIT ; i-- )
+            {
+                aNumeratorString.insert( 0, rInfo.sStrArray[i] );
+            }
+            i = nAnz;
+        }
+    }
+    return aNumeratorString.makeStringAndClear();
+}
+
 // TODO: More optimizations?
 void lcl_ForcedDenominator(sal_uLong &nFrac, sal_uLong &nDiv, sal_uLong nForcedDiv)
 {
@@ -2051,6 +2068,13 @@ OUString SvNumberformat::GetDenominatorString( sal_uInt16 nNumFor ) const
     return lcl_GetDenominatorString( rInfo, nAnz );
 }
 
+OUString SvNumberformat::GetNumeratorString( sal_uInt16 nNumFor ) const
+{
+    const ImpSvNumberformatInfo& rInfo = NumFor[nNumFor].Info();
+    sal_uInt16 nAnz = NumFor[nNumFor].GetCount();
+    return lcl_GetNumeratorString( rInfo, nAnz );
+}
+
 bool SvNumberformat::GetOutputString(double fNumber, sal_uInt16 nCharCount, OUString& rOutString) const
 {
     using namespace std;
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 77ff93c..847f61d 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -3255,6 +3255,8 @@ namespace xmloff { namespace token {
         TOKEN( "exponent-interval",               XML_EXPONENT_INTERVAL ),
         TOKEN( "forced-exponent-sign",            XML_FORCED_EXPONENT_SIGN ),
         TOKEN( "min-decimal-places",              XML_MIN_DECIMAL_PLACES ),
+        TOKEN( "max-denominator-value",           XML_MAX_DENOMINATOR_VALUE ),
+        TOKEN( "max-numerator-digits",            XML_MAX_NUMERATOR_DIGITS ),
 
 #if OSL_DEBUG_LEVEL > 0
         { 0, nullptr, nullptr,                       XML_TOKEN_END }
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 229237c..235920d 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -721,9 +721,22 @@ void SvXMLNumFmtExport::WriteScientificElement_Impl(
 
 void SvXMLNumFmtExport::WriteFractionElement_Impl(
                             sal_Int32 nInteger, bool bGrouping,
-                            sal_Int32 nNumeratorDigits, sal_Int32 nDenominatorDigits, sal_Int32 nDenominator )
+                            const OUString& aNumeratorString , const OUString& aDenominatorString )
 {
     FinishTextElement_Impl();
+    sal_Int32 nMaxNumeratorDigits = aNumeratorString.getLength();
+    sal_Int32 nMinNumeratorDigits = aNumeratorString.indexOf('?');
+    if ( nMinNumeratorDigits >= 0 )
+        nMinNumeratorDigits = nMaxNumeratorDigits - nMinNumeratorDigits;
+    else
+        nMinNumeratorDigits = 0;
+    sal_Int32 nMaxDenominatorDigits = aDenominatorString.getLength();
+    sal_Int32 nMinDenominatorDigits = aDenominatorString.indexOf('?');
+    if ( nMinDenominatorDigits >= 0 )
+        nMinDenominatorDigits = nMaxDenominatorDigits - nMinDenominatorDigits;
+    else
+        nMinDenominatorDigits = 0;
+    sal_Int32 nDenominator = aDenominatorString.toInt32();
 
     //  integer digits
     if ( nInteger >= 0 )        // negative = default (no integer part)
@@ -739,10 +752,17 @@ void SvXMLNumFmtExport::WriteFractionElement_Impl(
     }
 
     //  numerator digits
-    if ( nNumeratorDigits >= 0 )
+    if ( nMinNumeratorDigits == 0 ) // at least one digit to keep compatibility with previous versions
+        nMinNumeratorDigits++;
+    rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,
+                          OUString::number( nMinNumeratorDigits ) );
+    // Export only for 1.2 with extensions or 1.3 and later.
+    SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
+    if ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0)
     {
-        rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,
-                                 OUString::number( nNumeratorDigits ) );
+        // For extended ODF use loext namespace
+        rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_MAX_NUMERATOR_DIGITS,
+                              OUString::number( nMaxNumeratorDigits ) );
     }
 
     if ( nDenominator )
@@ -750,12 +770,22 @@ void SvXMLNumFmtExport::WriteFractionElement_Impl(
         rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DENOMINATOR_VALUE,
                               OUString::number( nDenominator) );
     }
-    //  I guess it's not necessary to export nDenominatorDigits
-    //  if we have a forced denominator ( remove ? )
-    if ( nDenominatorDigits >= 0 )
+    //  it's not necessary to export nDenominatorDigits
+    //  if we have a forced denominator
+    else
     {
+        if ( nMinDenominatorDigits == 0 ) // at least one digit to keep compatibility with previous versions
+            nMinDenominatorDigits++;
         rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,
-                              OUString::number( nDenominatorDigits ) );
+                              OUString::number( nMinDenominatorDigits ) );
+        if (eVersion > SvtSaveOptions::ODFSVER_012)
+        {
+            // For 1.2+ use loext namespace, for 1.3 use number namespace.
+            rExport.AddAttribute(
+                ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+                                 XML_MAX_DENOMINATOR_VALUE,
+                                 OUString::number( pow ( 10.0, nMaxDenominatorDigits ) - 1 ) ); // 9, 99 or 999
+        }
     }
 
     SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_FRACTION,
@@ -1486,10 +1516,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
                                         //  min-integer-digits attribute must be written.
                                         nInteger = -1;
                                     }
-                                    OUString aDenominatorString = rFormat.GetDenominatorString( nPart );
-                                    sal_Int32 nDenominator = aDenominatorString.toInt32();
-                                    sal_Int32 nDenominatorLength = aDenominatorString.getLength();
-                                    WriteFractionElement_Impl( nInteger, bThousand, nPrecision, nDenominatorLength, nDenominator );
+                                    WriteFractionElement_Impl( nInteger, bThousand,  rFormat.GetNumeratorString( nPart ), rFormat.GetDenominatorString( nPart ) );
                                     bAnyContent = true;
                                 }
                                 break;
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index ddd925c..b85bb13 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -95,8 +95,10 @@ struct SvXMLNumberInfo
     sal_Int32   nInteger;
     sal_Int32   nExpDigits;
     sal_Int32   nExpInterval;
-    sal_Int32   nNumerDigits;
-    sal_Int32   nDenomDigits;
+    sal_Int32   nMinNumerDigits;
+    sal_Int32   nMinDenomDigits;
+    sal_Int32   nMaxNumerDigits;
+    sal_Int32   nMaxDenomDigits;
     sal_Int32   nFracDenominator;
     sal_Int32   nMinDecimalDigits;
     bool        bGrouping;
@@ -108,7 +110,7 @@ struct SvXMLNumberInfo
 
     SvXMLNumberInfo()
     {
-        nDecimals = nInteger = nExpDigits = nExpInterval = nNumerDigits = nDenomDigits =
+        nDecimals = nInteger = nExpDigits = nExpInterval = nMinNumerDigits = nMinDenomDigits = nMaxNumerDigits = nMaxDenomDigits =
             nFracDenominator = nMinDecimalDigits = -1;
         bGrouping = bDecReplace = bDecAlign = false;
         bExpSign = true;
@@ -262,6 +264,8 @@ enum SvXMLStyleElemAttrTokens
     XML_TOK_ELEM_ATTR_FORCED_EXPONENT_SIGN,
     XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS,
     XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS,
+    XML_TOK_ELEM_ATTR_MAX_NUMERATOR_DIGITS,
+    XML_TOK_ELEM_ATTR_MAX_DENOMINATOR_VALUE,
     XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG,
     XML_TOK_ELEM_ATTR_LANGUAGE,
     XML_TOK_ELEM_ATTR_SCRIPT,
@@ -562,6 +566,9 @@ const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap()
             { XML_NAMESPACE_NUMBER, XML_FORCED_EXPONENT_SIGN,    XML_TOK_ELEM_ATTR_FORCED_EXPONENT_SIGN },
             { XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,    XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS },
             { XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,  XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS },
+            { XML_NAMESPACE_LO_EXT, XML_MAX_NUMERATOR_DIGITS,    XML_TOK_ELEM_ATTR_MAX_NUMERATOR_DIGITS },
+            { XML_NAMESPACE_LO_EXT, XML_MAX_DENOMINATOR_VALUE,   XML_TOK_ELEM_ATTR_MAX_DENOMINATOR_VALUE },
+            { XML_NAMESPACE_NUMBER, XML_MAX_DENOMINATOR_VALUE,   XML_TOK_ELEM_ATTR_MAX_DENOMINATOR_VALUE },
             { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG,        XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG     },
             { XML_NAMESPACE_NUMBER, XML_LANGUAGE,                XML_TOK_ELEM_ATTR_LANGUAGE             },
             { XML_NAMESPACE_NUMBER, XML_SCRIPT,                  XML_TOK_ELEM_ATTR_SCRIPT               },
@@ -906,6 +913,7 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
     sal_Int32 nAttrVal;
     bool bAttrBool(false);
     bool bVarDecimals = false;
+    bool bIsMaxDenominator = false;
     sal_uInt16 nAttrEnum;
     double fAttrDouble;
 
@@ -967,17 +975,31 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
                     aNumInfo.bExpSign = bAttrBool;
                 break;
             case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS:
-                if (::sax::Converter::convertNumber( nAttrVal, sValue, 1 ))  // at least one '?' (tdf#38097)
-                    aNumInfo.nNumerDigits = nAttrVal;
+                if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
+                    aNumInfo.nMinNumerDigits = nAttrVal;
+                break;
+            case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:
+                if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
+                    aNumInfo.nMinDenomDigits = nAttrVal;
                 break;
-            case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:  // while max-denominator-digits not treated (tdf#99661)
-                if (::sax::Converter::convertNumber( nAttrVal, sValue, 1 ))  // at least one '?' (tdf#38097)
-                    aNumInfo.nDenomDigits = nAttrVal;
+            case XML_TOK_ELEM_ATTR_MAX_NUMERATOR_DIGITS:
+                if (::sax::Converter::convertNumber( nAttrVal, sValue, 1 ))  // at least one '#'
+                    aNumInfo.nMaxNumerDigits = nAttrVal;
                 break;
             case XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE:
-                if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
+                if (::sax::Converter::convertNumber( nAttrVal, sValue, 1 )) // 0 is not valid
+                {
                     aNumInfo.nFracDenominator = nAttrVal;
+                    bIsMaxDenominator = false;
+                }
                 break;
+            case XML_TOK_ELEM_ATTR_MAX_DENOMINATOR_VALUE:  // part of ODF 1.3
+                if (::sax::Converter::convertNumber( nAttrVal, sValue, 1 ) && aNumInfo.nFracDenominator <= 0)
+                {   // if denominator value not yet defined
+                    aNumInfo.nFracDenominator = nAttrVal;
+                    bIsMaxDenominator = true;
+                }
+                 break;
             case XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG:
                 aLanguageTagODF.maRfcLanguageTag = sValue;
                 break;
@@ -1010,6 +1032,24 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
         else
             aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
     }
+    if ( aNumInfo.nMinDenomDigits >= 0 )
+        if ( aNumInfo.nMaxDenomDigits < aNumInfo.nMinDenomDigits )
+            aNumInfo.nMaxDenomDigits = ( aNumInfo.nMinDenomDigits ? aNumInfo.nMinDenomDigits : 1 );
+    if ( aNumInfo.nMinNumerDigits >= 0 )
+        if ( aNumInfo.nMaxNumerDigits < aNumInfo.nMinNumerDigits )
+            aNumInfo.nMaxNumerDigits = ( aNumInfo.nMinNumerDigits ? aNumInfo.nMinNumerDigits : 1 );
+    if ( bIsMaxDenominator && aNumInfo.nFracDenominator > 0 )
+    {
+        aNumInfo.nMaxDenomDigits = floor( log10( aNumInfo.nFracDenominator ) ) + 1;
+        aNumInfo.nFracDenominator = -1;  // Max denominator value only gives number of digits at denominator
+    }
+    if ( aNumInfo.nMaxDenomDigits > 0 )
+    {
+        if ( aNumInfo.nMinDenomDigits < 0 )
+            aNumInfo.nMinDenomDigits = 0;
+        else if ( aNumInfo.nMinDenomDigits > aNumInfo.nMaxDenomDigits )
+            aNumInfo.nMinDenomDigits = aNumInfo.nMaxDenomDigits;
+    }
 
     if ( !aLanguageTagODF.isEmpty() )
     {
@@ -1206,9 +1246,12 @@ void SvXMLNumFmtElementContext::EndElement()
                 //! build string and add at once
 
                 sal_Int32 i;
-                for (i=0; i<aNumInfo.nNumerDigits; i++)
+                for (i=aNumInfo.nMaxNumerDigits; i > 0; i--)
                 {
-                    rParent.AddToCode( '?' );
+                    if ( i > aNumInfo.nMinNumerDigits )
+                        rParent.AddToCode( '#' );
+                    else
+                        rParent.AddToCode( '?' );
                 }
                 rParent.AddToCode( '/' );
                 if ( aNumInfo.nFracDenominator > 0 )
@@ -1217,9 +1260,12 @@ void SvXMLNumFmtElementContext::EndElement()
                 }
                 else
                 {
-                    for (i=0; i<aNumInfo.nDenomDigits; i++)
+                    for (i=aNumInfo.nMaxDenomDigits; i > 0 ; i--)
                     {
-                        rParent.AddToCode( '?');
+                        if ( i > aNumInfo.nMinDenomDigits )
+                            rParent.AddToCode( '#' );
+                        else
+                            rParent.AddToCode( '?' );
                     }
                 }
             }


More information about the Libreoffice-commits mailing list