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

Kohei Yoshida kohei.yoshida at collabora.com
Tue Feb 11 12:07:35 PST 2014


 sc/inc/document.hxx                             |    7 ++--
 sc/qa/unit/data/ods/formula-delete-contents.ods |binary
 sc/qa/unit/subsequent_filters-test.cxx          |   36 ++++++++++++++++++++++++
 sc/qa/unit/ucalc_formula.cxx                    |   36 ++++++++++++++++++++++++
 sc/source/core/data/column2.cxx                 |    4 +-
 sc/source/core/data/documen7.cxx                |    2 -
 sc/source/core/data/document.cxx                |    4 +-
 sc/source/ui/docshell/docsh.cxx                 |    2 -
 sc/source/ui/docshell/docsh3.cxx                |    2 -
 sc/source/ui/view/gridwin4.cxx                  |    2 -
 10 files changed, 84 insertions(+), 11 deletions(-)

New commits:
commit 2ec3127da35933fc6d5ac47ecedd0267f67c1d62
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Feb 11 13:28:47 2014 -0500

    Ensure that vector array has a numeric array of NaN's for empty range.
    
    With this change, we ensure that mpNumArray is never NULL even when the
    range consists entirely of empty cells.  For an empty range, mpNumArray
    will be non-NULL and filled with NaN's while mpStrArray will be NULL.
    
    Change-Id: If5cead26ebe917af150cf7e39e17afe3f310beb7

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 032675b..1294503 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -2047,9 +2047,10 @@ public:
     formula::VectorRefArray FetchVectorRefArray( const ScAddress& rPos, SCROW nLength );
 
     /**
-     * Called whenever the value of a cell inside the document is modified.
+     * Call this before any operations that might trigger one or more formula
+     * cells to get calculated.
      */
-    void CellContentModified();
+    void ClearFormulaContext();
 
     SvtBroadcaster* GetBroadcaster( const ScAddress& rPos );
     const SvtBroadcaster* GetBroadcaster( const ScAddress& rPos ) const;
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index a4b6289..75553ae 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -490,6 +490,42 @@ void Test::testFetchVectorRefArray()
     CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
     CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, 5.0));
 
+    // Clear everything and start over.
+    clearRange(m_pDoc, ScRange(0,0,0,MAXCOL,MAXROW,0));
+    m_pDoc->ClearFormulaContext();
+
+    // Totally empty range in a totally empty column (Column A).
+    aArray = m_pDoc->FetchVectorRefArray(ScAddress(0,0,0), 3); // A1:A3
+    CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
+    CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[0]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[1]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[2]));
+
+    // Totally empty range in a non-empty column (Column B).
+    m_pDoc->SetString(ScAddress(1,10,0), "Some text"); // B11
+    aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,0,0), 3); // B1:B3
+    CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
+    CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[0]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[1]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[2]));
+
+    aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,12,0), 3); // B13:B15
+    CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
+    CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[0]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[1]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[2]));
+
+    // These values come from a cache because of the call above.
+    aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,1,0), 3); // B2:B4
+    CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
+    CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[0]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[1]));
+    CPPUNIT_ASSERT(rtl::math::isNan(aArray.mpNumericArray[2]));
+
     m_pDoc->DeleteTab(0);
 }
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index e601540..2c3e58a 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2591,7 +2591,7 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( SCROW nRow1, SCROW nRow2
     if (pColArray)
     {
         const double* pNum = NULL;
-        if (pColArray->mpNumArray && hasNonEmpty(*pColArray->mpNumArray, nRow1, nRow2))
+        if (pColArray->mpNumArray)
             pNum = &(*pColArray->mpNumArray)[nRow1];
 
         rtl_uString** pStr = NULL;
@@ -2732,7 +2732,7 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( SCROW nRow1, SCROW nRow2
             if (!appendToBlock(pDocument, rCxt, *pColArray, nPos, nRow2+1, itBlk, maCells.end()))
                 return formula::VectorRefArray();
 
-            if (pColArray->mpStrArray)
+            if (pColArray->mpStrArray && hasNonEmpty(*pColArray->mpStrArray, nRow1, nRow2))
                 return formula::VectorRefArray(&(*pColArray->mpNumArray)[nRow1], &(*pColArray->mpStrArray)[nRow1]);
             else
                 return formula::VectorRefArray(&(*pColArray->mpNumArray)[nRow1]);
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 210d87b..ac3f3cf 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -106,7 +106,7 @@ void ScDocument::Broadcast( const ScHint& rHint )
 
 void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
 {
-    CellContentModified();
+    ClearFormulaContext();
 
     ScBulkBroadcast aBulkBroadcast(pBASM);
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 0f24c23..f825a79 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2316,7 +2316,7 @@ ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
     mpDoc->pFormatExchangeList = NULL;
 }
 
-void ScDocument::CellContentModified()
+void ScDocument::ClearFormulaContext()
 {
     mpFormulaGroupCxt.reset();
 }
@@ -3683,6 +3683,7 @@ void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
 
 void ScDocument::CalcAll()
 {
+    ClearFormulaContext();
     ClearLookupCaches();    // Ensure we don't deliver zombie data.
     sc::AutoCalcSwitch aSwitch(*this, true);
     TableContainer::iterator it = maTabs.begin();
@@ -3693,7 +3694,6 @@ void ScDocument::CalcAll()
         if (*it)
             (*it)->CalcAll();
     ClearFormulaTree();
-    mpFormulaGroupCxt.reset();
 }
 
 
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 101332d..7ceff2b 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -3091,7 +3091,7 @@ ScDocShellModificator::~ScDocShellModificator()
 void ScDocShellModificator::SetDocumentModified()
 {
     ScDocument* pDoc = rDocShell.GetDocument();
-    pDoc->CellContentModified();
+    pDoc->ClearFormulaContext();
     if ( !pDoc->IsImportingXML() )
     {
         // AutoCalcShellDisabled temporaer restaurieren
diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
index 0a18ba8..125ac0f 100644
--- a/sc/source/ui/docshell/docsh3.cxx
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -87,7 +87,7 @@ void ScDocShell::PostDataChanged()
 {
     Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
     SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED ));      // Navigator
-    aDocument.CellContentModified();
+    aDocument.ClearFormulaContext();
     //! Navigator direkt benachrichtigen!
 }
 
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 729073b..56f227d 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -882,7 +882,7 @@ void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMod
 
     // Flag drawn formula cells "unchanged".
     pDoc->ResetChanged(ScRange(nX1,nY1,nTab,nX2,nY2,nTab));
-    pDoc->CellContentModified();
+    pDoc->ClearFormulaContext();
 }
 
 void ScGridWindow::CheckNeedsRepaint()
commit b51acfb4c0c7dec0cdc3de5890ebb1c051bab509
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Feb 11 10:09:58 2014 -0500

    fdo#74014: Another attempt to reproduce this bug in test.
    
    But still not reproducible in test. Only in the UI. This is maddening.
    I give up for now.
    
    Change-Id: I88e6f4ed19856cf81abdf188dc22a5012e8c4a28

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 64212ed..032675b 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -2023,7 +2023,7 @@ public:
     formula::FormulaGrammar::Grammar  GetStorageGrammar() const
                             { return eStorageGrammar; }
 
-    SfxUndoManager*     GetUndoManager();
+    SC_DLLPUBLIC SfxUndoManager* GetUndoManager();
     bool IsInVBAMode() const;
     ScRowBreakIterator* GetRowBreakIterator(SCTAB nTab) const;
 
diff --git a/sc/qa/unit/data/ods/formula-delete-contents.ods b/sc/qa/unit/data/ods/formula-delete-contents.ods
new file mode 100644
index 0000000..4b125fd
Binary files /dev/null and b/sc/qa/unit/data/ods/formula-delete-contents.ods differ
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 83841b3..142d241 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -96,6 +96,7 @@ public:
     void testCachedFormulaResultsODS();
     void testCachedMatrixFormulaResultsODS();
     void testFormulaDepAcrossSheetsODS();
+    void testFormulaDepDeleteContentsODS();
     void testDatabaseRangesODS();
     void testDatabaseRangesXLS();
     void testDatabaseRangesXLSX();
@@ -171,6 +172,7 @@ public:
     CPPUNIT_TEST(testFunctionsExcel2010);
     CPPUNIT_TEST(testCachedFormulaResultsODS);
     CPPUNIT_TEST(testFormulaDepAcrossSheetsODS);
+    CPPUNIT_TEST(testFormulaDepDeleteContentsODS);
     CPPUNIT_TEST(testCachedMatrixFormulaResultsODS);
     CPPUNIT_TEST(testDatabaseRangesODS);
     CPPUNIT_TEST(testDatabaseRangesXLS);
@@ -641,6 +643,40 @@ void ScFiltersTest::testFormulaDepAcrossSheetsODS()
     xDocSh->DoClose();
 }
 
+void ScFiltersTest::testFormulaDepDeleteContentsODS()
+{
+    ScDocShellRef xDocSh = loadDoc("formula-delete-contents.", ODS, true);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load the file.", xDocSh.Is());
+    ScDocument* pDoc = xDocSh->GetDocument();
+
+    sc::UndoSwitch aUndoSwitch(*pDoc, true); // Enable undo.
+    sc::AutoCalcSwitch aACSwitch(*pDoc, true); // Make sure auto calc is turned on.
+
+    CPPUNIT_ASSERT_EQUAL(195.0, pDoc->GetValue(ScAddress(3,15,0))); // formula in D16
+
+    // Delete D2:D5.
+    ScDocFunc& rFunc = xDocSh->GetDocFunc();
+    ScRange aRange(3,1,0,3,4,0);
+    ScMarkData aMark;
+    aMark.SetMarkArea(aRange);
+    aMark.MarkToMulti();
+    bool bGood = rFunc.DeleteContents(aMark, IDF_ALL, true, true);
+    CPPUNIT_ASSERT(bGood);
+    CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(ScAddress(3,1,0)));
+    CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(ScAddress(3,2,0)));
+    CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(ScAddress(3,3,0)));
+    CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(ScAddress(3,4,0)));
+
+    CPPUNIT_ASSERT_EQUAL(94.0, pDoc->GetValue(ScAddress(3,15,0))); // formula in D16
+
+    SfxUndoManager* pUndoMgr = pDoc->GetUndoManager();
+    CPPUNIT_ASSERT(pUndoMgr);
+    pUndoMgr->Undo();
+    CPPUNIT_ASSERT_EQUAL(195.0, pDoc->GetValue(ScAddress(3,15,0))); // formula in D16
+
+    xDocSh->DoClose();
+}
+
 namespace {
 
 void testDBRanges_Impl(ScDocument* pDoc, sal_Int32 nFormat)


More information about the Libreoffice-commits mailing list