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

Eike Rathke erack at redhat.com
Fri May 27 16:44:45 UTC 2016


 formula/source/core/api/token.cxx |   50 +++++++++++++++++++++++++++++++++-----
 include/formula/tokenarray.hxx    |    2 +
 2 files changed, 46 insertions(+), 6 deletions(-)

New commits:
commit acb0f28e97874b22bd899e5cf04f2a8363a42e7a
Author: Eike Rathke <erack at redhat.com>
Date:   Fri May 27 18:05:01 2016 +0200

    omit DCOUNT or DCOUNTA 2nd argument if 0 when writing ODFF or OOXML, tdf#70806
    
    Change-Id: I2833a1005c6941e66a09172b337e23b0bf7f2002
    (cherry picked from commit a88ee01b8683ded7d9da6dbcbf4d3e0c2ed4cadc)
    Reviewed-on: https://gerrit.libreoffice.org/25559
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 8cbceb3..b1a1f00 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -1056,6 +1056,9 @@ inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp ) const
         case ocMissing:
         case ocLog:
             return isPODF();    // rewrite only for PODF
+        case ocDBCount:
+        case ocDBCount2:
+            return isODFF();    // rewrite only for ODFF
         default:
             return false;
     }
@@ -1092,6 +1095,9 @@ inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp )
         case ocPoissonDist:
         case ocNormDist:
         case ocLogNormDist:
+
+        case ocDBCount:
+        case ocDBCount2:
             return true;
         default:
             return false;
@@ -1379,15 +1385,26 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
 {
     const size_t nAlloc = 256;
     FormulaMissingContext aCtx[ nAlloc ];
+
+    /* TODO: with some effort we might be able to merge the two almost
+     * identical function stacks into one and generalize things, otherwise
+     * adding yet another "omit argument" would be copypasta. */
+
     int aOpCodeAddressStack[ nAlloc ];  // use of ADDRESS() function
     const int nOmitAddressArg = 3;      // ADDRESS() 4th parameter A1/R1C1
+
+    int aOpCodeDcountStack[ nAlloc ];   // use of DCOUNT()/DCOUNTA() function
+    const int nOmitDcountArg = 1;       // DCOUNT() and DCOUNTA() 2nd parameter DatabaseField if 0
+
     sal_uInt16 nTokens = GetLen() + 1;
     FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
     int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
+    int* pOcds = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeDcountStack[0]);
     // Never go below 0, never use 0, mpFunc always NULL.
     pCtx[0].Clear();
     int nFn = 0;
     int nOcas = 0;
+    int nOcds = 0;
 
     FormulaTokenArray *pNewArr = new FormulaTokenArray;
     // At least ScRecalcMode::ALWAYS needs to be set.
@@ -1412,20 +1429,39 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
                     bAdd = false;
             }
         }
+        // Strip the 2nd argument (leaving empty) of DCOUNT() and DCOUNTA() if
+        // it is 0.
+        for (int i = nOcds; i-- > 0 && bAdd; )
+        {
+            if (pCtx[ pOcds[ i ] ].mnCurArg == nOmitDcountArg)
+            {
+                // Omit only a literal 0 value, nothing else.
+                if (pOcds[ i ] == nFn && pCur->GetOpCode() == ocPush && pCur->GetDouble() == 0.0)
+                    bAdd = false;
+            }
+        }
         switch ( pCur->GetOpCode() )
         {
             case ocOpen:
-                ++nFn;      // all following operations on _that_ function
-                pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
-                pCtx[ nFn ].mnCurArg = 0;
-                if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
-                    pOcas[ nOcas++ ] = nFn;     // entering ADDRESS() if PODF
-                break;
+                {
+                    ++nFn;      // all following operations on _that_ function
+                    pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
+                    pCtx[ nFn ].mnCurArg = 0;
+                    OpCode eOp;
+                    if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
+                        pOcas[ nOcas++ ] = nFn;     // entering ADDRESS() if PODF
+                    else if ((rConv.isODFF() || rConv.isOOXML()) && pCtx[ nFn ].mpFunc &&
+                            ((eOp = pCtx[ nFn ].mpFunc->GetOpCode()) == ocDBCount || eOp == ocDBCount2))
+                        pOcds[ nOcds++ ] = nFn;     // entering DCOUNT() or DCOUNTA() if ODFF or OOXML
+                }
+            break;
             case ocClose:
                 pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
                 SAL_WARN_IF(nFn <= 0, "formula.core", "FormulaTokenArray::RewriteMissing: underflow");
                 if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
                     --nOcas;                    // leaving ADDRESS()
+                else if (nOcds > 0 && pOcds[ nOcds-1 ] == nFn)
+                    --nOcds;                    // leaving DCOUNT() or DCOUNTA()
                 if (nFn > 0)
                     --nFn;
                 break;
@@ -1474,6 +1510,8 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
         }
     }
 
+    if (pOcds != &aOpCodeDcountStack[0])
+        delete [] pOcas;
     if (pOcas != &aOpCodeAddressStack[0])
         delete [] pOcas;
     if (pCtx != &aCtx[0])
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index cd0f430..3faadec 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -72,6 +72,8 @@ public:
     };
     explicit            MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
     inline  bool        isPODF() const  { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
+    inline  bool        isODFF() const  { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; }
+    inline  bool        isOOXML() const  { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; }
     inline  Convention  getConvention() const { return meConvention; }
 private:
     Convention meConvention;


More information about the Libreoffice-commits mailing list