include/svl/zforlist.hxx         |    3 
 include/svl/zformat.hxx          |   19 +++++
 sc/source/core/data/documen4.cxx |    4 +
 svl/source/numbers/zforlist.cxx  |    9 ++
 svl/source/numbers/zformat.cxx   |  147 ++++++++++++++++++++++-----------------
 5 files changed, 119 insertions(+), 63 deletions(-)

New commits:
commit 9f70f8761a8cc180171022ffcffc0094c4957057
Author: Laurent Balland-Poirier <laurent.balland-poir...@laposte.net>
Date:   Wed Feb 15 23:27:34 2017 +0100

    tdf#105657 Treat "Precision as shown" for fractions
    
    For Option "Precision as shown",
     fraction must specificly be treated
    ImpGetFractionElements retrieves values of each part
    of fraction (integer, numerator, denominator)
    independently from its exact representation
    Update: avoid include of zformat.hxx in document4.cxx
    
    Change-Id: Ia3ea2322f3d311c04ef71f3260730c7154c3dc15
    Reviewed-on: https://gerrit.libreoffice.org/34331
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 5706b29974c1c3ab0ba5a23685accf2fbebc3e06)
    Reviewed-on: https://gerrit.libreoffice.org/36365
    Tested-by: Jenkins <c...@libreoffice.org>

diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx
index ab7dd90f1426..36e468726a64 100644
--- a/include/svl/zforlist.hxx
+++ b/include/svl/zforlist.hxx
@@ -531,6 +531,9 @@ public:
                                      sal_uInt16& nPrecision, sal_uInt16& 
nAnzLeading,
                                      LanguageType eLnge = LANGUAGE_DONTKNOW );
 
+    /// Get round value with fraction representation
+    double GetRoundFractionValue( sal_uInt32 nFormat, double fValue ) const;
+
     /// Check if format code string may be deleted by user
     bool IsUserDefined( const OUString& sStr, LanguageType eLnge = 
LANGUAGE_DONTKNOW );
 
diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx
index ceba6a4993ca..f798d4090638 100644
--- a/include/svl/zformat.hxx
+++ b/include/svl/zformat.hxx
@@ -212,6 +212,9 @@ public:
                               sal_uInt16& nPrecision,
                               sal_uInt16& nAnzLeading) const;
 
+    /// Get index of subformat (0..3) according to conditions and fNumber value
+    sal_uInt16 GetSubformatIndex( double fNumber ) const;
+
     /// Count of decimal precision
     sal_uInt16 GetFormatPrecision() const   { return 
NumFor[0].Info().nCntPost; }
 
@@ -242,6 +245,9 @@ public:
     OUString GetDenominatorString( sal_uInt16 nNumFor ) const;
     OUString GetNumeratorString( sal_uInt16 nNumFor ) const;
     OUString GetIntegerFractionDelimiterString( sal_uInt16 nNumFor ) const;
+    /// Round fNumber to its fraction representation
+    double GetRoundFractionValue ( double fNumber ) 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
@@ -580,6 +586,19 @@ private:
                                  sal_uInt16 nIx,
                                  bool bInteger );
 
+    /** Calculate each element of fraction:
+     * integer part, numerator part, denominator part
+     * @param fNumber value to be represented as fraction. Will contain 
absolute fractional part
+     * @param nIx subformat number 0..3
+     * @param fIntPart integral part of fraction
+     * @param nFrac numerator of fraction
+     * @param nDic denominator of fraction
+     */
+    SVL_DLLPRIVATE void ImpGetFractionElements( double& fNumber,
+                                                sal_uInt16 nIx,
+                                                double& fIntPart,
+                                                sal_uInt64& nFrac,
+                                                sal_uInt64& nDiv ) const;
     SVL_DLLPRIVATE bool ImpGetFractionOutput(double fNumber,
                                              sal_uInt16 nIx,
                                              OUStringBuffer& OutString);
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index c503b2fa6137..09b7c543e7e8 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -672,6 +672,10 @@ double ScDocument::RoundValueAsShown( double fVal, 
sal_uInt32 nFormat ) const
                         nPrecision = sal::static_int_cast<short>( nPrecision - 
(short)floor( log10( -fVal ) ) );
                     break;
                 }
+                case css::util::NumberFormat::FRACTION:     // get value of 
fraction representation
+                {
+                    return GetFormatTable()->GetRoundFractionValue( nFormat, 
fVal );
+                }
             }
         }
         else
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index c2617a534a4b..659e1b5b340d 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -1963,6 +1963,15 @@ void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 
nFormat,
     }
 }
 
+double SvNumberFormatter::GetRoundFractionValue( sal_uInt32 nFormat, double 
fValue ) const
+{
+    const SvNumberformat* pFormat = GetFormatEntry( nFormat );
+    if ( pFormat )
+        return pFormat->GetRoundFractionValue( fValue );
+    else
+        return fValue;
+}
+
 sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const
 {
     const SvNumberformat* pFormat = GetFormatEntry( nFormat );
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 2c018f662784..103da063321f 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -2349,6 +2349,31 @@ bool SvNumberformat::GetOutputString(double fNumber, 
sal_uInt16 nCharCount, OUSt
     return true;
 }
 
+sal_uInt16 SvNumberformat::GetSubformatIndex (double fNumber ) const
+{
+    sal_uInt16 nIx; // Index of the partial format
+    double fLimit_1 = fLimit1;
+    short nCheck = ImpCheckCondition(fNumber, fLimit_1, eOp1);
+    if (nCheck == -1 || nCheck == 1) // Only 1 String or True
+    {
+        nIx = 0;
+    }
+    else
+    {
+        double fLimit_2 = fLimit2;
+        nCheck = ImpCheckCondition(fNumber, fLimit_2, eOp2);
+        if (nCheck == -1 || nCheck == 1)
+        {
+            nIx = 1;
+        }
+        else
+        {
+            nIx = 2;
+        }
+    }
+    return nIx;
+}
+
 bool SvNumberformat::GetOutputString(double fNumber,
                                      OUString& OutString,
                                      Color** ppColor)
@@ -2439,24 +2464,7 @@ bool SvNumberformat::GetOutputString(double fNumber,
     }
     if ( !bHadStandard )
     {
-        sal_uInt16 nIx; // Index of the partial format
-        short nCheck = ImpCheckCondition(fNumber, fLimit1, eOp1);
-        if (nCheck == -1 || nCheck == 1) // Only 1 String or True
-        {
-            nIx = 0;
-        }
-        else
-        {
-            nCheck = ImpCheckCondition(fNumber, fLimit2, eOp2);
-            if (nCheck == -1 || nCheck == 1)
-            {
-                nIx = 1;
-            }
-            else
-            {
-                nIx = 2;
-            }
-        }
+        sal_uInt16 nIx = GetSubformatIndex ( fNumber ); // Index of the 
partial format
         if (fNumber < 0.0 &&
                 ((nIx == 0 && IsFirstSubformatRealNegative()) || // 1st, 
usually positive subformat
                  (nIx == 1 && IsSecondSubformatRealNegative()))) // 2nd, 
usually negative subformat
@@ -2679,45 +2687,31 @@ bool SvNumberformat::ImpGetScientificOutput(double 
fNumber,
     return bRes;
 }
 
-bool SvNumberformat::ImpGetFractionOutput(double fNumber,
-                                          sal_uInt16 nIx,
-                                          OUStringBuffer& sBuff)
+double SvNumberformat::GetRoundFractionValue ( double fNumber ) const
 {
-    bool bRes = false;
-    const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
-    const sal_uInt16 nAnz = NumFor[nIx].GetCount();
-    OUStringBuffer sStr, sFrac, sDiv; // Strings, value for
-    sal_uInt64 nFrac=0, nDiv=1;       // Integral part
-    bool bSign = false;               // Numerator and denominator
-    const OUString sIntegerFormat = lcl_GetFractionIntegerString(rInfo, nAnz);
-    const OUString sNumeratorFormat = lcl_GetNumeratorString(rInfo, nAnz);
-    const OUString sDenominatorFormat = lcl_GetDenominatorString(rInfo, nAnz);
+    sal_uInt16 nIx = GetSubformatIndex ( fNumber );
+    double fIntPart = 0.0;           // integer part of fraction
+    sal_uInt64 nFrac = 0, nDiv = 1;  // numerator and denominator
+    double fSign = (fNumber < 0.0) ? -1.0 : 1.0;
+    // fNumber is modified in ImpGetFractionElements to absolute fractional 
part
+    ImpGetFractionElements ( fNumber, nIx, fIntPart, nFrac, nDiv );
+    if ( nDiv > 0 )
+        return fSign * ( fIntPart + (double)nFrac / (double)nDiv );
+    else
+        return fSign * fIntPart;
+}
 
-    if (fNumber < 0)
-    {
-        if (nIx == 0) // Not in the ones at the end
-            bSign = true; // Formats
+void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx,
+                                              double& fIntPart, sal_uInt64& 
nFrac, sal_uInt64& nDiv ) const
+{
+    if ( fNumber < 0.0 )
         fNumber = -fNumber;
-    }
-
-    double fNum = floor(fNumber); // Integral part
-
-    fNumber -= fNum; // Fractional part
-    if (fNum > D_MAX_U_INT32 || rInfo.nCntExp > 9) // Too large
-    {
-        sBuff = rScan.GetErrorString();
-        return false;
-    }
-    if (rInfo.nCntExp == 0)
-    {
-        SAL_WARN( "svl.numbers", "SvNumberformat:: Fraction, nCntExp == 0");
-        sBuff.truncate();
-        return false;
-    }
-
-    if( sal_Int32 nForcedDiv = sDenominatorFormat.toInt32() )
+    fIntPart = floor(fNumber); // Integral part
+    fNumber -= fIntPart;         // Fractional part
+    const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
+    nDiv = lcl_GetDenominatorString( rInfo, NumFor[nIx].GetCount() ).toInt32();
+    if( nDiv > 0 )
     {   // Forced Denominator
-        nDiv = (sal_uInt64) nForcedDiv;
         nFrac = (sal_uInt64)floor ( fNumber * nDiv );
         double fFracNew = (double)nFrac / (double)nDiv;
         double fFracNew1 = (double)(nFrac + 1) / (double)nDiv;
@@ -2726,14 +2720,10 @@ bool SvNumberformat::ImpGetFractionOutput(double 
fNumber,
         {
             nFrac++;
         }
-        if( nFrac >= nDiv )
-        {
-            nFrac = nDiv = 0;
-            fNum = fNum + 1.0;
-        }
     }
     else // Calculated Denominator
     {
+        nDiv = 1;
         sal_uInt64 nBasis = ((sal_uInt64)floor( pow(10.0,rInfo.nCntExp))) - 1; 
// 9, 99, 999 ,...
         sal_uInt64 nFracPrev = 1L, nDivPrev = 0, nFracNext, nDivNext, 
nPartialDenom;
         double fRemainder = fNumber;
@@ -2771,12 +2761,43 @@ bool SvNumberformat::ImpGetFractionOutput(double 
fNumber,
                 fRemainder = 0.0; // exit while loop
             }
         }
-        if (nFrac == nDiv)
-        {
-            ++fNum;
-            nFrac = 0;
-        }
     }
+    if (nFrac >= nDiv)
+    {
+        ++fIntPart;
+        nFrac = nDiv = 0;
+    }
+}
+
+bool SvNumberformat::ImpGetFractionOutput(double fNumber,
+                                          sal_uInt16 nIx,
+                                          OUStringBuffer& sBuff)
+{
+    bool bRes = false;
+    const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
+    const sal_uInt16 nAnz = NumFor[nIx].GetCount();
+    OUStringBuffer sStr, sFrac, sDiv; // Strings, value for Integral part 
Numerator and denominator
+    bool bSign = ( (fNumber < 0) && (nIx == 0) ); // sign Not in the ones at 
the end
+    const OUString sIntegerFormat = lcl_GetFractionIntegerString(rInfo, nAnz);
+    const OUString sNumeratorFormat = lcl_GetNumeratorString(rInfo, nAnz);
+    const OUString sDenominatorFormat = lcl_GetDenominatorString(rInfo, nAnz);
+
+    sal_uInt64 nFrac = 0, nDiv = 1;
+    double fNum = floor(fNumber); // Integral part
+
+    if (fNum > D_MAX_U_INT32 || rInfo.nCntExp > 9) // Too large
+    {
+        sBuff = rScan.GetErrorString();
+        return false;
+    }
+    if (rInfo.nCntExp == 0)
+    {
+        SAL_WARN( "svl.numbers", "SvNumberformat:: Fraction, nCntExp == 0");
+        sBuff.truncate();
+        return false;
+    }
+
+    ImpGetFractionElements( fNumber, nIx, fNum, nFrac, nDiv);
 
     if (rInfo.nCntPre == 0) // Improper fraction
     {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to