[Libreoffice-commits] core.git: Branch 'libreoffice-4-4' - formula/source include/formula

Winfried Donkers winfrieddonkers at libreoffice.org
Tue Feb 17 05:22:02 PST 2015


 formula/source/core/api/FormulaCompiler.cxx |   13 -
 formula/source/core/api/token.cxx           |  343 ++++++++++++++++++++--------
 include/formula/tokenarray.hxx              |   47 +++
 3 files changed, 299 insertions(+), 104 deletions(-)

New commits:
commit 1706760769018662a50b494b2e4a0ca85c93ca42
Author: Winfried Donkers <winfrieddonkers at libreoffice.org>
Date:   Fri Aug 8 17:39:04 2014 +0200

    fdo#81596 export to OOXML that need argument changes
    
    Reviewed-on: https://gerrit.libreoffice.org/10831
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>
    (cherry picked from commit 4feaf96f50fa89eccb4e7a638220099e9a8482f1)
    
    sensible indenting, fdo#81596 related
    
    (cherry picked from commit 3dd241c52d6db424bd4696ff8f223976542e411b)
    
    simplify RewriteMissing() and switch in Add...(), fdo#81596 related
    
    (cherry picked from commit 14aabee5a73e57e26b2062b1ebf00c3f1dff1250)
    
    write TRUE() for 2nd IF() parameter, fdo#81596 related
    
    (cherry picked from commit 8f031861f590ba914321816657a003375d93ef5d)
    
    f7eb11a950b45793d04837d02f9546a93673fa2f
    f2ca37e1fda87ce56282fc2d2fc57a0784851139
    52d0b43b19e10bee82109b635b3b7ce4f43650a3
    
    Change-Id: I3a99e416be9f3f04175939e4560f8f7c55497185
    Reviewed-on: https://gerrit.libreoffice.org/14388
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 5b2e8ea..5cb40fc 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1742,9 +1742,16 @@ void FormulaCompiler::CreateStringFromTokenArray( OUStringBuffer& rBuffer )
     if (bODFF || FormulaGrammar::isPODF( meGrammar) )
     {
         // Scan token array for missing args and re-write if present.
-        MissingConvention aConv( bODFF);
-        if (pArr->NeedsPofRewrite( aConv))
-            pArr = pArr->RewriteMissingToPof( aConv);
+        MissingConventionODF aConv( bODFF);
+        if (pArr->NeedsPodfRewrite( aConv))
+            pArr = pArr->RewriteMissing( aConv );
+    }
+    else if ( FormulaGrammar::isOOXML( meGrammar ) )
+    {
+        // Scan token array for missing args and rewrite if present.
+        MissingConventionOOXML aConv;
+        if (pArr->NeedsOoxmlRewrite( aConv))
+            pArr = pArr->RewriteMissing( aConv );
     }
 
     // At least one character per token, plus some are references, some are
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 92486dc..a414a4b 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -995,11 +995,9 @@ bool FormulaTokenArray::HasMatrixDoubleRefOps()
     return false;
 }
 
+// --- Formula rewrite of a token array
 
-
-// --- POF (plain old formula) rewrite of a token array ---------------------
-
-inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
+inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp ) const
 {
     switch (eOp)
     {
@@ -1011,7 +1009,62 @@ inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
             return true;
         case ocMissing:
         case ocLog:
-            return !isODFF();   // rewrite only for PODF
+            return isPODF();    // rewrite only for PODF
+        default:
+            return false;
+    }
+}
+
+/*
+ * fdo 81596
+Test status ( . : in progress , v : tested , - not applicable )
+finished:
+- ocCosecant:          // for OOXML not rewritten anymore
+- ocSecant:            // for OOXML not rewritten anymore
+- ocCot:               // for OOXML not rewritten anymore
+- ocCosecantHyp:       // for OOXML not rewritten anymore
+- ocSecantHyp:         // for OOXML not rewritten anymore
+- ocCotHyp:            // for OOXML not rewritten anymore
+- ocArcCot:            // for OOXML not rewritten anymore
+- ocArcCotHyp:         // ACOTH(x), not needed for Excel2013 and later
+- ocChose:             // CHOOSE() - no rewrite needed, it seems
+v ocEuroConvert:
+v ocIf:
+v ocRound:
+v ocRoundUp:
+v ocRoundDown:
+v ocGammaDist:
+v ocPoissonDist:
+v ocNormDist:
+v ocLogNormDist:
+
+To be implemented yet:
+  ocExternal:    ?
+  ocMacro:       ?
+  ocIndex:       INDEX() ?
+  ocFDist:             // later, fdo40835
+*/
+inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp ) const
+{
+    switch (eOp)
+    {
+        case ocIf:
+
+        case ocExternal:
+        case ocEuroConvert:
+        case ocMacro:
+
+        case ocRound:
+        case ocRoundUp:
+        case ocRoundDown:
+
+        case ocIndex:
+
+        case ocGammaDist:
+        case ocPoissonDist:
+        case ocNormDist:
+        case ocLogNormDist:
+            return true;
         default:
             return false;
     }
@@ -1035,51 +1088,129 @@ void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const Missi
     if ( !mpFunc )
         return;
 
-    switch (mpFunc->GetOpCode())
+    switch (rConv.getConvention())
     {
-        case ocGammaDist:
-            if (mnCurArg == 2)
-            {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
-            }
-            break;
-        case ocPoissonDist:
-            if (mnCurArg == 1)
-            {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
-            }
-            break;
-        case ocNormDist:
-            if ( mnCurArg == 2 )
-            {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
-            }
-            break;
-        case ocLogNormDist:
-            if ( mnCurArg == 0 )
-            {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
-            }
-            if ( mnCurArg <= 1 )
+        case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
+        case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
             {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
+                switch (mpFunc->GetOpCode())
+                {
+                    case ocGammaDist:
+                        if (mnCurArg == 2)
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
+                        }
+                        break;
+                    case ocPoissonDist:
+                        if (mnCurArg == 1)
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
+                        }
+                        break;
+                    case ocNormDist:
+                        if ( mnCurArg == 2 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
+                        }
+                        break;
+                    case ocLogNormDist:
+                        if ( mnCurArg == 0 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
+                        }
+                        if ( mnCurArg <= 1 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
+                        }
+                        break;
+                    case ocLog:
+                        if ( rConv.isPODF() && mnCurArg == 0 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 10.0 );     // 2nd, basis 10
+                        }
+                        break;
+                    default:
+                        break;
+                }
             }
             break;
-        case ocLog:
-            if ( !rConv.isODFF() && mnCurArg == 0 )
+        case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
             {
-                pNewArr->AddOpCode( ocSep );
-                pNewArr->AddDouble( 10.0 );     // 2nd, basis 10
+                switch (mpFunc->GetOpCode())
+                {
+                    case ocIf:
+                        if( mnCurArg == 0 )
+                        {
+                            // Excel needs at least two parameters in IF function
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddOpCode( ocTrue );   // 2nd, true() as function
+                            pNewArr->AddOpCode( ocOpen );   // so the result is of logical type
+                            pNewArr->AddOpCode( ocClose );  // and survives roundtrip
+                        }
+                        break;
+
+                    case ocEuroConvert:
+                        if ( mnCurArg == 2 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 0.0 );      // 4th, FullPrecision = false()
+                        }
+                        break;
+
+                    case ocPoissonDist:
+                        if (mnCurArg == 1)
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
+                        }
+                        break;
+
+                    case ocGammaDist:
+                    case ocNormDist:
+                        if (mnCurArg == 2)
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
+                        }
+                        break;
+
+                    case ocLogNormDist:
+                        if ( mnCurArg == 0 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
+                        }
+                        if ( mnCurArg <= 1 )
+                        {
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
+                        }
+                        break;
+
+                    case ocRound:
+                    case ocRoundUp:
+                    case ocRoundDown:
+                        if( mnCurArg == 0 )
+                        {
+                            // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
+                            pNewArr->AddOpCode( ocSep );
+                            pNewArr->AddDouble( 0.0 );      // 2nd, 0.0
+                        }
+                        break;
+
+                    default:
+                        break;
+                }
             }
             break;
-        default:
-            break;
     }
+
 }
 
 inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
@@ -1124,61 +1255,87 @@ bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const Missin
     bool bRet = false;
     const OpCode eOp = mpFunc->GetOpCode();
 
-    // Add for both, PODF and ODFF
-    switch (eOp)
+    switch (rConv.getConvention())
     {
-        case ocAddress:
-            return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
-        default:
+        case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
+            {
+                // Add for ODFF
+                switch (eOp)
+                {
+                    case ocAddress:
+                        return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
+                    default:
+                        break;
+                }
+            }
+            break;
+        case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
+            {
+                // Add for PODF
+                switch (eOp)
+                {
+                    case ocAddress:
+                        return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
+                    case ocFixed:
+                        return AddDefaultArg( pNewArr, 1, 2.0 );
+                    case ocBetaDist:
+                    case ocBetaInv:
+                    case ocRMZ:     // PMT
+                        return AddDefaultArg( pNewArr, 3, 0.0 );
+                    case ocZinsZ:   // IPMT
+                    case ocKapz:    // PPMT
+                        return AddDefaultArg( pNewArr, 4, 0.0 );
+                    case ocBW:      // PV
+                    case ocZW:      // FV
+                        bRet |= AddDefaultArg( pNewArr, 2, 0.0 );   // pmt
+                        bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // [fp]v
+                        break;
+                    case ocZins:    // RATE
+                        bRet |= AddDefaultArg( pNewArr, 1, 0.0 );   // pmt
+                        bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // fv
+                        bRet |= AddDefaultArg( pNewArr, 4, 0.0 );   // type
+                        break;
+                    case ocExternal:
+                        return AddMissingExternal( pNewArr );
+
+                        // --- more complex cases ---
+
+                    case ocOffset:
+                        // FIXME: rather tough.
+                        // if arg 3 (height) omitted, export arg1 (rows)
+                        break;
+                    default:
+                        break;
+                }
+            }
+            break;
+        case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
+            {
+                switch (eOp)
+                {
+                    case ocExternal:
+                        return AddMissingExternal( pNewArr );
+                    default:
+                        break;
+                }
+            }
             break;
     }
 
-    if (rConv.isODFF())
-    {
-        // Add for ODFF
-    }
-    else
-    {
-        // Add for PODF
-        switch (eOp)
-        {
-            case ocFixed:
-                return AddDefaultArg( pNewArr, 1, 2.0 );
-            case ocBetaDist:
-            case ocBetaInv:
-            case ocRMZ:     // PMT
-                return AddDefaultArg( pNewArr, 3, 0.0 );
-            case ocZinsZ:   // IPMT
-            case ocKapz:    // PPMT
-                return AddDefaultArg( pNewArr, 4, 0.0 );
-            case ocBW:      // PV
-            case ocZW:      // FV
-                bRet |= AddDefaultArg( pNewArr, 2, 0.0 );   // pmt
-                bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // [fp]v
-                break;
-            case ocZins:    // RATE
-                bRet |= AddDefaultArg( pNewArr, 1, 0.0 );   // pmt
-                bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // fv
-                bRet |= AddDefaultArg( pNewArr, 4, 0.0 );   // type
-                break;
-            case ocExternal:
-                return AddMissingExternal( pNewArr );
-
-                // --- more complex cases ---
+    return bRet;
+}
 
-            case ocOffset:
-                // FIXME: rather tough.
-                // if arg 3 (height) omitted, export arg1 (rows)
-                break;
-            default:
-                break;
-        }
+bool FormulaTokenArray::NeedsPodfRewrite( const MissingConventionODF & rConv )
+{
+    for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
+    {
+        if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
+            return true;
     }
-
-    return bRet;
+    return false;
 }
 
-bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
+bool FormulaTokenArray::NeedsOoxmlRewrite( const MissingConventionOOXML & rConv )
 {
     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
     {
@@ -1189,7 +1346,7 @@ bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
 }
 
 
-FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvention & rConv )
+FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & rConv )
 {
     const size_t nAlloc = 256;
     FormulaMissingContext aCtx[ nAlloc ];
@@ -1232,12 +1389,12 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvent
                 ++nFn;      // all following operations on _that_ function
                 pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
                 pCtx[ nFn ].mnCurArg = 0;
-                if (pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress && !rConv.isODFF())
+                if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
                     pOcas[ nOcas++ ] = nFn;     // entering ADDRESS() if PODF
                 break;
             case ocClose:
                 pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
-                DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissingToPof: underflow");
+                DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissing: underflow");
                 if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
                     --nOcas;                    // leaving ADDRESS()
                 if (nFn > 0)
@@ -1252,7 +1409,7 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvent
                 }
                 break;
             case ocMissing:
-                if (bAdd)
+                if ( bAdd )
                     bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
                 break;
             default:
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index c6433aa..ceb8425 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -55,12 +55,39 @@ class FormulaMissingContext;
 
 class FORMULA_DLLPUBLIC MissingConvention
 {
-    bool    mbODFF;     /// TRUE: ODFF, FALSE: PODF
 public:
-    explicit    MissingConvention( bool bODFF ) : mbODFF(bODFF) {}
+    enum Convention
+    {
+        FORMULA_MISSING_CONVENTION_PODF,
+        FORMULA_MISSING_CONVENTION_ODFF,
+        FORMULA_MISSING_CONVENTION_OOXML
+    };
+    explicit            MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
+    inline  bool        isPODF() const  { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
+    inline  Convention  getConvention() const { return meConvention; }
+private:
+    Convention meConvention;
+};
+
+class FORMULA_DLLPUBLIC MissingConventionODF : public MissingConvention
+{
+public:
+    explicit    MissingConventionODF( bool bODFF ) :
+        MissingConvention( bODFF ?
+                MissingConvention::FORMULA_MISSING_CONVENTION_ODFF :
+                MissingConvention::FORMULA_MISSING_CONVENTION_PODF)
+        {
+        }
+    // Implementation and usage only in token.cxx
+    inline  bool    isRewriteNeeded( OpCode eOp ) const;
+};
+
+class FORMULA_DLLPUBLIC MissingConventionOOXML : public MissingConvention
+{
+public:
+    explicit    MissingConventionOOXML() : MissingConvention( MissingConvention::FORMULA_MISSING_CONVENTION_OOXML) {}
     // Implementation and usage only in token.cxx
     inline  bool    isRewriteNeeded( OpCode eOp ) const;
-    inline  bool    isODFF() const { return mbODFF; }
 };
 
 class FORMULA_DLLPUBLIC FormulaTokenArray
@@ -238,15 +265,19 @@ public:
     FormulaTokenArray& operator=( const FormulaTokenArray& );
 
     /** Determines if this formula needs any changes to convert it to something
-        previous versions of OOo could consume (Plain Old Formula). */
-            bool                NeedsPofRewrite(const MissingConvention & rConv);
+        previous versions of OOo could consume (Plain Old Formula, pre-ODFF, or
+        also ODFF) */
+    bool                NeedsPodfRewrite( const MissingConventionODF & rConv );
+
+    /** Determines if this formula needs any changes to convert it to OOXML. */
+    bool                NeedsOoxmlRewrite( const MissingConventionOOXML & rConv );
 
-    /** Rewrites to Plain Old Formula, substituting missing parameters. The
+    /** Rewrites to Plain Old Formula or OOXML, substituting missing parameters. The
         FormulaTokenArray* returned is new'ed. */
-            FormulaTokenArray*  RewriteMissingToPof(const MissingConvention & rConv);
+    FormulaTokenArray*  RewriteMissing( const MissingConvention & rConv );
 
     /** Determines if this formula may be followed by a reference. */
-            bool                MayReferenceFollow();
+    bool                MayReferenceFollow();
 };
 
 inline OpCode FormulaTokenArray::GetOuterFuncOpCode()


More information about the Libreoffice-commits mailing list