[Libreoffice-commits] core.git: sc/inc sc/source

Eike Rathke erack at redhat.com
Mon Dec 22 12:17:41 PST 2014


 sc/inc/scmatrix.hxx              |    6 +++
 sc/source/core/data/column2.cxx  |   27 +++++++++++--
 sc/source/core/tool/interpr1.cxx |    4 +-
 sc/source/core/tool/scmatrix.cxx |   77 +++++++++++++++++++++++++++++++--------
 4 files changed, 93 insertions(+), 21 deletions(-)

New commits:
commit 069698de192ef7e8d3582398e4542c175cabb987
Author: Eike Rathke <erack at redhat.com>
Date:   Mon Dec 22 21:14:11 2014 +0100

    fdo#85258 differentiate between empty cell and empty result in matrix
    
    Change-Id: I79259224e411f9c1a6e852623d9d49cf89a03c27

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index a5117be..6bcd8857 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -278,6 +278,9 @@ public:
     /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
     void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
 
+    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
+    void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
+
     /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
     void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
 
@@ -322,6 +325,9 @@ public:
     /// @return <TRUE/> if empty or empty path.
     bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
 
+    /// @return <TRUE/> if empty, not empty result or empty path.
+    bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const;
+
     /// @return <TRUE/> if empty path.
     bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index c206867..9b0b5ef 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2066,16 +2066,23 @@ namespace {
 
 struct CellBucket
 {
+    SCSIZE mnEmpValStart;
     SCSIZE mnNumValStart;
     SCSIZE mnStrValStart;
+    SCSIZE mnEmpValCount;
     std::vector<double> maNumVals;
     std::vector<svl::SharedString> maStrVals;
 
-    CellBucket() : mnNumValStart(0), mnStrValStart(0) {}
+    CellBucket() : mnEmpValStart(0), mnNumValStart(0), mnStrValStart(0), mnEmpValCount(0) {}
 
     void flush(ScMatrix& rMat, SCSIZE nCol)
     {
-        if (!maNumVals.empty())
+        if (mnEmpValCount)
+        {
+            rMat.PutEmptyResultVector(mnEmpValCount, nCol, mnEmpValStart);
+            reset();
+        }
+        else if (!maNumVals.empty())
         {
             const double* p = &maNumVals[0];
             rMat.PutDouble(p, maNumVals.size(), nCol, mnNumValStart);
@@ -2091,7 +2098,8 @@ struct CellBucket
 
     void reset()
     {
-        mnNumValStart = mnStrValStart = 0;
+        mnEmpValStart = mnNumValStart = mnStrValStart = 0;
+        mnEmpValCount = 0;
         maNumVals.clear();
         maStrVals.clear();
     }
@@ -2163,7 +2171,18 @@ public:
 
                     if (rCell.IsEmpty())
                     {
-                        aBucket.flush(mrMat, mnMatCol);
+                        if (aBucket.mnEmpValCount && nThisRow == nPrevRow + 1)
+                        {
+                            // Secondary empty results.
+                            ++aBucket.mnEmpValCount;
+                        }
+                        else
+                        {
+                            // First empty result.
+                            aBucket.flush(mrMat, mnMatCol);
+                            aBucket.mnEmpValStart = nThisRow - mnTopRow;
+                            ++aBucket.mnEmpValCount;
+                        }
                         continue;
                     }
 
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 252d38d..326987e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1849,14 +1849,14 @@ void ScInterpreter::ScIsEmpty()
             if ( !pMat )
                 ;   // nothing
             else if ( !pJumpMatrix )
-                nRes = pMat->IsEmpty( 0, 0) ? 1 : 0;
+                nRes = pMat->IsEmptyCell( 0, 0) ? 1 : 0;
             else
             {
                 SCSIZE nCols, nRows, nC, nR;
                 pMat->GetDimensions( nCols, nRows);
                 pJumpMatrix->GetPos( nC, nR);
                 if ( nC < nCols && nR < nRows )
-                    nRes = pMat->IsEmpty( nC, nR) ? 1 : 0;
+                    nRes = pMat->IsEmptyCell( nC, nR) ? 1 : 0;
                 // else: false, not empty (which is what Xcl does)
             }
         }
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index c352ecb..af57384 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -194,6 +194,13 @@ _Comp CompareMatrixElemFunc<_Comp>::maComp;
 
 }
 
+/* TODO: it would be good if mdds had get/set<sal_uInt8> additionally to
+ * get/set<bool>, we're abusing double here. */
+typedef double TMatFlag;
+const TMatFlag SC_MATFLAG_EMPTYCELL   = 0.0;
+const TMatFlag SC_MATFLAG_EMPTYRESULT = 1.0;
+const TMatFlag SC_MATFLAG_EMPTYPATH   = 2.0;
+
 class ScMatrixImpl: private boost::noncopyable
 {
     MatrixImplType maMat;
@@ -246,6 +253,7 @@ public:
     bool IsString( SCSIZE nIndex ) const;
     bool IsString( SCSIZE nC, SCSIZE nR ) const;
     bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
+    bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const;
     bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
     bool IsValue( SCSIZE nIndex ) const;
     bool IsValue( SCSIZE nC, SCSIZE nR ) const;
@@ -259,6 +267,7 @@ public:
     void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR );
     void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR );
     void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
+    void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
     void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
     void CompareEqual();
     void CompareNotEqual();
@@ -298,7 +307,7 @@ private:
 };
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
-    maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
+    maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
     maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
@@ -452,7 +461,7 @@ void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR)
     if (ValidColRow( nC, nR))
     {
         maMat.set_empty(nR, nC);
-        maMatFlag.set(nR, nC, false); // zero flag to indicate that this is 'empty', not 'empty path'.
+        maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYCELL);
     }
     else
     {
@@ -465,7 +474,7 @@ void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
     if (ValidColRow( nC, nR))
     {
         maMat.set_empty(nR, nC);
-        maMatFlag.set(nR, nC, true); // non-zero flag to indicate empty 'path'.
+        maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYPATH);
     }
     else
     {
@@ -580,7 +589,7 @@ svl::SharedString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE
             return maMat.get_string(aPos).getString();
         case mdds::mtm::element_empty:
         {
-            if (!maMatFlag.get<bool>(nR, nC))
+            if (maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH)
                 // not an empty path.
                 return svl::SharedString::getEmptyString();
 
@@ -636,8 +645,10 @@ ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
                 aVal.aStr = maMat.get_string(aPos);
             break;
             case mdds::mtm::element_empty:
-                // Empty path equals empty plus flag.
-                aVal.nType = maMatFlag.get<bool>(nR, nC) ? SC_MATVAL_EMPTYPATH : SC_MATVAL_EMPTY;
+                /* TODO: do we need to pass the differentiation of 'empty' and
+                 * 'empty result' to the outer world anywhere? */
+                aVal.nType = maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH ? SC_MATVAL_EMPTYPATH :
+                    SC_MATVAL_EMPTY;
                 aVal.fVal = 0.0;
             default:
                 ;
@@ -673,17 +684,28 @@ bool ScMatrixImpl::IsString( SCSIZE nC, SCSIZE nR ) const
 
 bool ScMatrixImpl::IsEmpty( SCSIZE nC, SCSIZE nR ) const
 {
-    // Flag must be zero for this to be an empty element, instead of being an
-    // empty path element.
+    // Flag must indicate an empty element instead of an
+    // 'empty path' element.
+    ValidColRowReplicated( nC, nR );
+    return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
+        maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH;
+}
+
+bool ScMatrixImpl::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
+{
+    // Flag must indicate an 'empty' element instead of an
+    // 'empty result' or 'empty path' element.
     ValidColRowReplicated( nC, nR );
-    return maMat.get_type(nR, nC) == mdds::mtm::element_empty && !maMatFlag.get<bool>(nR, nC);
+    return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
+        maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYCELL;
 }
 
 bool ScMatrixImpl::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
 {
-    // 'Empty path' is empty plus non-zero flag.
+    // Flag must indicate an 'empty path' element.
     if (ValidColRowOrReplicated( nC, nR ))
-        return maMat.get_type(nR, nC) == mdds::mtm::element_empty && maMatFlag.get<bool>(nR, nC);
+        return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
+            maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH;
     else
         return true;
 }
@@ -799,8 +821,8 @@ void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
     {
         maMat.set_empty(nR, nC, nCount);
-        // zero flag to indicate that this is 'empty', not 'empty path'.
-        std::vector<bool> aVals(nCount, false);
+        // Flag to indicate that this is 'empty', not 'empty result' or 'empty path'.
+        std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYCELL);
         maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
     }
     else
@@ -809,13 +831,28 @@ void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     }
 }
 
+void ScMatrixImpl::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
+{
+    if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
+    {
+        maMat.set_empty(nR, nC, nCount);
+        // Flag to indicate that this is 'empty result', not 'empty' or 'empty path'.
+        std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYRESULT);
+        maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
+    }
+    else
+    {
+        OSL_FAIL("ScMatrixImpl::PutEmptyResultVector: dimension error");
+    }
+}
+
 void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
 {
     if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
     {
         maMat.set_empty(nR, nC, nCount);
-        // non-zero flag to indicate empty 'path'.
-        std::vector<bool> aVals(nCount, true);
+        // Flag to indicate 'empty path'.
+        std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYPATH);
         maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
     }
     else
@@ -2281,6 +2318,11 @@ bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
     return pImpl->IsEmpty(nC, nR);
 }
 
+bool ScMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
+{
+    return pImpl->IsEmptyCell(nC, nR);
+}
+
 bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsEmptyPath(nC, nR);
@@ -2341,6 +2383,11 @@ void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     pImpl->PutEmptyVector(nCount, nC, nR);
 }
 
+void ScMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
+{
+    pImpl->PutEmptyResultVector(nCount, nC, nR);
+}
+
 void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutEmptyPathVector(nCount, nC, nR);


More information about the Libreoffice-commits mailing list