[Libreoffice-commits] core.git: 2 commits - include/svl sc/inc sc/Library_sc.mk sc/qa sc/source svl/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Mar 14 21:16:30 PDT 2014


 include/svl/listener.hxx            |    2 
 sc/Library_sc.mk                    |    1 
 sc/inc/brdcst.hxx                   |    6 -
 sc/inc/cellsuno.hxx                 |    2 
 sc/inc/chartlis.hxx                 |    2 
 sc/inc/column.hxx                   |    3 
 sc/inc/document.hxx                 |    2 
 sc/inc/formulacell.hxx              |    2 
 sc/inc/lookupcache.hxx              |    2 
 sc/inc/mtvcellfunc.hxx              |   10 +++
 sc/inc/refhint.hxx                  |   62 +++++++++++++++++++
 sc/inc/simplehintids.hxx            |   22 ++++++
 sc/inc/table.hxx                    |   10 +++
 sc/inc/tokenarray.hxx               |   10 +++
 sc/qa/unit/ucalc.hxx                |    2 
 sc/qa/unit/ucalc_formula.cxx        |  116 ++++++++++++++++++++++++++++++++++++
 sc/source/core/data/bcaslot.cxx     |   42 +++++++++++++
 sc/source/core/data/colorscale.cxx  |    4 -
 sc/source/core/data/column.cxx      |   92 ++++++++++++++++++++++++++++
 sc/source/core/data/documen7.cxx    |   54 ++++++++++++++++
 sc/source/core/data/formulacell.cxx |   25 ++++++-
 sc/source/core/data/table2.cxx      |   20 ++++++
 sc/source/core/inc/bcaslot.hxx      |    4 +
 sc/source/core/tool/chartlis.cxx    |    2 
 sc/source/core/tool/lookupcache.cxx |    2 
 sc/source/core/tool/refhint.cxx     |   36 +++++++++++
 sc/source/core/tool/token.cxx       |   39 ++++++++++++
 sc/source/ui/docshell/servobj.cxx   |    2 
 sc/source/ui/inc/servobj.hxx        |    2 
 sc/source/ui/undo/undoblk.cxx       |   10 +++
 sc/source/ui/unoobj/cellsuno.cxx    |    2 
 svl/source/notify/broadcast.cxx     |    2 
 svl/source/notify/listener.cxx      |   10 ---
 33 files changed, 572 insertions(+), 30 deletions(-)

New commits:
commit 88955714d345d8584e86ae34bf5f5d1f3f4af9f7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Mar 14 23:15:32 2014 -0400

    fdo#71491: Adjust reference during undo of drag-n-drop of cell range.
    
    Also with this commit, the signature of SvtListener::Notify() changes,
    by dropping the first argument which nobody uses.  This change was necessary
    in order to call it directly without needing to pass any broadcaster instance.
    
    Change-Id: I6a1e97f0fb1e070d1d8f7db614690b04c9e8024e

diff --git a/include/svl/listener.hxx b/include/svl/listener.hxx
index c871023..1c98458 100644
--- a/include/svl/listener.hxx
+++ b/include/svl/listener.hxx
@@ -45,7 +45,7 @@ public:
 
     bool HasBroadcaster() const;
 
-    virtual void        Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+    virtual void Notify( const SfxHint& rHint );
 };
 
 
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index efc7d5e..9aebd45 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -258,6 +258,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/tool/recursionhelper \
     sc/source/core/tool/refdata \
     sc/source/core/tool/reffind \
+    sc/source/core/tool/refhint \
     sc/source/core/tool/refreshtimer \
     sc/source/core/tool/reftokenhelper \
     sc/source/core/tool/refupdat \
diff --git a/sc/inc/brdcst.hxx b/sc/inc/brdcst.hxx
index beef774..b328bec 100644
--- a/sc/inc/brdcst.hxx
+++ b/sc/inc/brdcst.hxx
@@ -21,16 +21,12 @@
 
 #include "global.hxx"
 #include "address.hxx"
+#include <simplehintids.hxx>
 #include <tools/rtti.hxx>
 #include <svl/hint.hxx>
-#include <svl/smplhint.hxx>
 
 class SvtBroadcaster;
 
-#define SC_HINT_DATACHANGED SFX_HINT_DATACHANGED
-#define SC_HINT_TABLEOPDIRTY    SFX_HINT_USER00
-#define SC_HINT_CALCALL         SFX_HINT_USER01
-
 class ScHint : public SfxSimpleHint
 {
     ScAddress   aAddress;
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx
index 9ab5b27..09e112e 100644
--- a/sc/inc/cellsuno.hxx
+++ b/sc/inc/cellsuno.hxx
@@ -115,7 +115,7 @@ class ScLinkListener : public SvtListener
 public:
                     ScLinkListener(const Link& rL) : aLink(rL) {}
     virtual         ~ScLinkListener();
-    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+    virtual void Notify( const SfxHint& rHint );
 };
 
 typedef ::com::sun::star::uno::Reference<
diff --git a/sc/inc/chartlis.hxx b/sc/inc/chartlis.hxx
index ea80fa7..d04a1ab 100644
--- a/sc/inc/chartlis.hxx
+++ b/sc/inc/chartlis.hxx
@@ -92,7 +92,7 @@ public:
 
     bool            IsUno() const   { return (pUnoData != NULL); }
 
-    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+    virtual void Notify( const SfxHint& rHint );
     void            StartListeningTo();
     void            EndListeningTo();
     void            ChangeListening( const ScRangeListRef& rRangeListRef,
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index de28214..c9e9757 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -61,6 +61,7 @@ struct RowSpan;
 class RowHeightContext;
 class CompileFormulaContext;
 struct SetFormulaDirtyContext;
+class RefMovedHint;
 
 }
 
@@ -462,6 +463,8 @@ public:
     void        StartNeededListeners(); // only for cells where NeedsListening()==true
     void        SetDirtyIfPostponed();
     void BroadcastRecalcOnRefMove();
+    void BroadcastRefMoved( const sc::RefMovedHint& rHint );
+    void TransferListeners( ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta );
 
     void CompileDBFormula( sc::CompileFormulaContext& rCxt );
     void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 2d39f5a..05afc1c 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -77,6 +77,7 @@ class DocumentLinkManager;
 class CellValues;
 class RowHeightContext;
 struct SetFormulaDirtyContext;
+class RefMovedHint;
 
 }
 
@@ -1829,6 +1830,7 @@ public:
     void                Broadcast( const ScHint& rHint );
 
     void BroadcastCells( const ScRange& rRange, sal_uLong nHint );
+    void BroadcastRefMoved( const sc::RefMovedHint& rHint );
 
                         /// only area, no cell broadcast
     void                AreaBroadcast( const ScHint& rHint );
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 9b47046..81dd1fd 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -314,7 +314,7 @@ public:
     void            SetPreviousTrack( ScFormulaCell* pF );
     void            SetNextTrack( ScFormulaCell* pF );
 
-    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
+    virtual void Notify( const SfxHint& rHint );
     void SetCompile( bool bVal );
     ScDocument* GetDocument() const;
     void            SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
diff --git a/sc/inc/lookupcache.hxx b/sc/inc/lookupcache.hxx
index 0b6c53b..2f73930 100644
--- a/sc/inc/lookupcache.hxx
+++ b/sc/inc/lookupcache.hxx
@@ -120,7 +120,7 @@ public:
                             ScLookupCache( ScDocument * pDoc, const ScRange & rRange );
     virtual                 ~ScLookupCache();
     /// Remove from document structure and delete (!) cache on modify hint.
-    virtual void            Notify( SvtBroadcaster & rBC, const SfxHint &  rHint );
+    virtual void Notify( const SfxHint& rHint );
 
     /// @returns document address in o_rAddress if Result==FOUND
             Result          lookup( ScAddress & o_rResultAddress,
diff --git a/sc/inc/mtvcellfunc.hxx b/sc/inc/mtvcellfunc.hxx
index d5e7921..092dcf7 100644
--- a/sc/inc/mtvcellfunc.hxx
+++ b/sc/inc/mtvcellfunc.hxx
@@ -187,6 +187,16 @@ ProcessNote(
         CellNoteStoreType, cellnote_block, _FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
 }
 
+template<typename _FuncElem>
+typename BroadcasterStoreType::iterator
+ProcessBroadcaster(
+    const BroadcasterStoreType::iterator& it, BroadcasterStoreType& rStore, SCROW nRow1, SCROW nRow2, _FuncElem& rFuncElem)
+{
+    FuncElseNoOp<size_t> aElse;
+    return ProcessElements1<
+        BroadcasterStoreType, broadcaster_block, _FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
+}
+
 }
 
 #endif
diff --git a/sc/inc/refhint.hxx b/sc/inc/refhint.hxx
new file mode 100644
index 0000000..ec56735
--- /dev/null
+++ b/sc/inc/refhint.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_REFHINT_HXX
+#define SC_REFHINT_HXX
+
+#include <address.hxx>
+#include <simplehintids.hxx>
+
+namespace sc {
+
+class RefHint : public SfxSimpleHint
+{
+public:
+    enum Type { Moved };
+
+private:
+    Type meType;
+
+    RefHint(); // disabled
+
+protected:
+    RefHint( Type eType );
+
+public:
+    virtual ~RefHint() = 0;
+
+    Type getType() const;
+};
+
+class RefMovedHint : public RefHint
+{
+    ScRange maRange;
+    ScAddress maMoveDelta;
+
+public:
+
+    RefMovedHint( const ScRange& rRange, const ScAddress& rMove );
+    virtual ~RefMovedHint();
+
+    /**
+     * Get the source range from which the references have moved.
+     */
+    const ScRange& getRange() const;
+
+    /**
+     * Get the movement vector.
+     */
+    const ScAddress& getDelta() const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/simplehintids.hxx b/sc/inc/simplehintids.hxx
new file mode 100644
index 0000000..ecf2f93
--- /dev/null
+++ b/sc/inc/simplehintids.hxx
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_SIMPLEHINTIDS_HXX
+#define SC_SIMPLEHINTIDS_HXX
+
+#include <svl/smplhint.hxx>
+
+#define SC_HINT_DATACHANGED     SFX_HINT_DATACHANGED
+#define SC_HINT_TABLEOPDIRTY    SFX_HINT_USER00
+#define SC_HINT_CALCALL         SFX_HINT_USER01
+#define SC_HINT_REFERENCE       SFX_HINT_USER02
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 8cf0fb1..ce58c20 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -72,6 +72,7 @@ class CellValues;
 class RowHeightContext;
 class CompileFormulaContext;
 struct SetFormulaDirtyContext;
+class RefMovedHint;
 
 }
 
@@ -896,6 +897,15 @@ public:
      */
     void BroadcastRecalcOnRefMove();
 
+    /**
+     * Broadcast all listeners of specified range that the range have moved.
+     */
+    void BroadcastRefMoved( const sc::RefMovedHint& rHint );
+
+    void TransferListeners(
+        ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+        SCCOL nColDelta, SCROW nRowDelta );
+
     void TransferCellValuesTo( SCCOL nCol, SCROW nRow, size_t nLen, sc::CellValues& rDest );
     void CopyCellValuesFrom( SCCOL nCol, SCROW nRow, const sc::CellValues& rSrc );
 
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 312e63a..eb68997 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -144,6 +144,16 @@ public:
         const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos );
 
     /**
+     * Move reference positions that are within specified moved range.
+     *
+     * @param rPos position of this formula cell
+     * @param rMovedRange range that has been moved.
+     * @param rDelta movement vector.
+     */
+    void MoveReference(
+        const ScAddress& rPos, const ScRange& rMovedRange, const ScAddress& rDelta );
+
+    /**
      * Adjust all references in named expression. In named expression, we only
      * update absolute positions, and leave relative positions intact.
      *
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 4578fd9..cccddb0 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -446,6 +446,23 @@ void ScBroadcastAreaSlot::EraseArea( ScBroadcastAreas::iterator& rIter )
     }
 }
 
+void ScBroadcastAreaSlot::GetAllListeners( const ScRange& rRange, std::vector<SvtListener*>& rListeners )
+{
+    for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()),
+            aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter )
+    {
+        if (isMarkedErased( aIter))
+            continue;
+
+        ScBroadcastArea* pArea = (*aIter).mpArea;
+        const ScRange& rAreaRange = pArea->GetRange();
+        if (!rAreaRange.Intersects(rRange))
+            continue;
+
+        SvtBroadcaster::ListenersType& rLst = pArea->GetBroadcaster().GetAllListeners();
+        std::copy(rLst.begin(), rLst.end(), std::back_inserter(rListeners));
+    }
+}
 
 void ScBroadcastAreaSlot::FinallyEraseAreas()
 {
@@ -976,4 +993,29 @@ void ScBroadcastAreaSlotMachine::FinallyEraseAreas( ScBroadcastAreaSlot* pSlot )
     maAreasToBeErased.swap( aCopy);
 }
 
+std::vector<SvtListener*> ScBroadcastAreaSlotMachine::GetAllListeners( const ScRange& rRange )
+{
+    std::vector<SvtListener*> aRet;
+
+    SCTAB nEndTab = rRange.aEnd.Tab();
+    for (TableSlotsMap::const_iterator iTab( aTableSlotsMap.lower_bound( rRange.aStart.Tab()));
+            iTab != aTableSlotsMap.end() && (*iTab).first <= nEndTab; ++iTab)
+    {
+        ScBroadcastAreaSlot** ppSlots = (*iTab).second->getSlots();
+        SCSIZE nStart, nEnd, nRowBreak;
+        ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+        SCSIZE nOff = nStart;
+        SCSIZE nBreak = nOff + nRowBreak;
+        ScBroadcastAreaSlot** pp = ppSlots + nOff;
+        while ( nOff <= nEnd )
+        {
+            ScBroadcastAreaSlot* p = *pp;
+            p->GetAllListeners(rRange, aRet);
+            ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak);
+        }
+    }
+
+    return aRet;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx
index 5409c6b..b50ea9f 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -33,7 +33,7 @@ public:
     ScFormulaListener(ScFormulaCell* pCell);
     virtual ~ScFormulaListener();
 
-    void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+    void Notify( const SfxHint& rHint );
 
     bool NeedsRepaint() const;
 };
@@ -129,7 +129,7 @@ ScFormulaListener::~ScFormulaListener()
     std::for_each(maCells.begin(), maCells.end(), StopListeningCell(mpDoc, this));
 }
 
-void ScFormulaListener::Notify(SvtBroadcaster&, const SfxHint&)
+void ScFormulaListener::Notify( const SfxHint& )
 {
     mbDirty = true;
 }
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 2e9192d..8b6aa9d 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -42,6 +42,7 @@
 #include "sharedformula.hxx"
 #include "refupdatecontext.hxx"
 #include <listenercontext.hxx>
+#include <refhint.hxx>
 
 #include <svl/poolcach.hxx>
 #include <svl/zforlist.hxx>
@@ -3446,6 +3447,97 @@ void ScColumn::BroadcastRecalcOnRefMove()
     BroadcastCells(aFunc.getDirtyRows(), SC_HINT_DATACHANGED);
 }
 
+namespace {
+
+class BroadcastRefMovedHandler
+{
+    const sc::RefMovedHint& mrHint;
+public:
+    BroadcastRefMovedHandler( const sc::RefMovedHint& rHint ) : mrHint(rHint) {}
+
+    void operator() ( size_t, SvtBroadcaster* p )
+    {
+        p->Broadcast(mrHint);
+    }
+};
+
+}
+
+void ScColumn::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+    const ScRange& rRange = rHint.getRange();
+    SCROW nRow1 = rRange.aStart.Row();
+    SCROW nRow2 = rRange.aEnd.Row();
+
+    // Notify all listeners within specified rows.
+    BroadcastRefMovedHandler aFunc(rHint);
+    sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
+}
+
+namespace {
+
+class TransferListenersHandler
+{
+    sc::BroadcasterStoreType& mrDestBroadcasters;
+    sc::BroadcasterStoreType::iterator miDestPos;
+    SCROW mnRowDelta; /// Add this to the source row to get the destination row.
+
+public:
+    TransferListenersHandler( sc::BroadcasterStoreType& rDestBrd, SCROW nRowDelta ) :
+        mrDestBroadcasters(rDestBrd), miDestPos(rDestBrd.begin()), mnRowDelta(nRowDelta) {}
+
+    void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
+    {
+        assert(pBroadcaster);
+
+        SvtBroadcaster::ListenersType& rLis = pBroadcaster->GetAllListeners();
+        if (rLis.empty())
+            // No listeners to transfer.
+            return;
+
+        SCROW nDestRow = nRow + mnRowDelta;
+
+        sc::BroadcasterStoreType::position_type aPos = mrDestBroadcasters.position(miDestPos, nDestRow);
+        miDestPos = aPos.first;
+        SvtBroadcaster* pDestBrd = NULL;
+        if (aPos.first->type == sc::element_type_broadcaster)
+        {
+            // Existing broadcaster.
+            pDestBrd = sc::broadcaster_block::at(*aPos.first->data, aPos.second);
+        }
+        else
+        {
+            // No existing broadcaster. Create a new one.
+            assert(aPos.first->type == sc::element_type_empty);
+            pDestBrd = new SvtBroadcaster;
+            miDestPos = mrDestBroadcasters.set(miDestPos, nDestRow, pDestBrd);
+        }
+
+        // Transfer all listeners from the source to the destination.
+        SvtBroadcaster::ListenersType::iterator it = rLis.begin(), itEnd = rLis.end();
+        for (; it != itEnd; ++it)
+        {
+            SvtListener* pLis = *it;
+            pLis->EndListening(*pBroadcaster);
+            pLis->StartListening(*pDestBrd);
+        }
+
+        // At this point, the source broadcaster should have no more listeners.
+        assert(!pBroadcaster->HasListeners());
+    }
+};
+
+}
+
+void ScColumn::TransferListeners(
+    ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
+{
+    TransferListenersHandler aFunc(rDestCol.maBroadcasters, nRowDelta);
+    sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
+
+    maBroadcasters.set_empty(nRow1, nRow2); // Remove all source broadcaster.
+}
+
 void ScColumn::CalcAll()
 {
     CalcAllHandler aFunc;
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 0faa829..d48acbf 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -37,6 +37,7 @@
 #include "tokenarray.hxx"
 #include "listenercontext.hxx"
 #include "formulagroup.hxx"
+#include <refhint.hxx>
 
 #include <tools/shl.hxx>
 
@@ -129,6 +130,59 @@ void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
     BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
 }
 
+void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+    if (!pBASM)
+        // clipboard or undo document.
+        return;
+
+    const ScRange& rSrcRange = rHint.getRange(); // old range
+    const ScAddress& rDelta = rHint.getDelta();
+
+    // Get all area listeners that listens on the old range, and end their listening.
+    std::vector<SvtListener*> aAreaListeners = pBASM->GetAllListeners(rSrcRange);
+    {
+        std::vector<SvtListener*>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            SvtListener* p = *it;
+            pBASM->EndListeningArea(rSrcRange, p);
+            p->Notify(rHint); // Adjust the references.
+        }
+    }
+
+    for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
+    {
+        ScTable* pTab = FetchTable(nTab);
+        if (!pTab)
+            continue;
+
+        SCTAB nDestTab = nTab + rDelta.Tab();
+        ScTable* pDestTab = FetchTable(nDestTab);
+        if (!pDestTab)
+            continue;
+
+        // Adjust the references.
+        pTab->BroadcastRefMoved(rHint);
+        // Move the listeners from the old location to the new.
+        pTab->TransferListeners(
+            *pDestTab, rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
+            rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), rDelta.Col(), rDelta.Row());
+    }
+
+    // Re-start area listeners on the new range.
+    ScRange aNewRange = rSrcRange;
+    aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+    {
+        std::vector<SvtListener*>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            SvtListener* p = *it;
+            pBASM->StartListeningArea(aNewRange, p);
+        }
+    }
+}
+
 void ScDocument::AreaBroadcast( const ScHint& rHint )
 {
     if ( !pBASM )
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 957d8b2..2eedc52 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -55,6 +55,7 @@
 #include "scopetools.hxx"
 #include "refupdatecontext.hxx"
 #include <tokenstringcontext.hxx>
+#include <refhint.hxx>
 
 #include <boost/scoped_ptr.hpp>
 
@@ -1867,12 +1868,30 @@ bool ScFormulaCell::IsInChangeTrack() const
     return bInChangeTrack;
 }
 
-void ScFormulaCell::Notify( SvtBroadcaster&, const SfxHint& rHint)
+void ScFormulaCell::Notify( const SfxHint& rHint )
 {
+    const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+    if (!pSimpleHint)
+        return;
+
+    sal_uLong nHint = pSimpleHint->GetId();
+    if (nHint == SC_HINT_REFERENCE)
+    {
+        const sc::RefHint& rRefHint = static_cast<const sc::RefHint&>(rHint);
+
+        if (rRefHint.getType() == sc::RefHint::Moved)
+        {
+            // One of the references has moved.
+
+            const sc::RefMovedHint& rRefMoved = static_cast<const sc::RefMovedHint&>(rRefHint);
+            pCode->MoveReference(aPos, rRefMoved.getRange(), rRefMoved.getDelta());
+        }
+
+        return;
+    }
+
     if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
     {
-        const ScHint* p = PTR_CAST( ScHint, &rHint );
-        sal_uLong nHint = (p ? p->GetId() : 0);
         if (nHint & (SC_HINT_DATACHANGED | SC_HINT_TABLEOPDIRTY))
         {
             bool bForceTrack = false;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index a1e9bf1..3eb4962 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -50,6 +50,7 @@
 #include "refupdatecontext.hxx"
 #include "scopetools.hxx"
 #include <rowheightcontext.hxx>
+#include <refhint.hxx>
 
 #include "scitems.hxx"
 #include <editeng/boxitem.hxx>
@@ -1716,6 +1717,25 @@ void ScTable::BroadcastRecalcOnRefMove()
         aCol[i].BroadcastRecalcOnRefMove();
 }
 
+void ScTable::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+    const ScRange& rRange = rHint.getRange();
+    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+        aCol[nCol].BroadcastRefMoved(rHint);
+}
+
+void ScTable::TransferListeners(
+    ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+    SCCOL nColDelta, SCROW nRowDelta )
+{
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+    {
+        ScColumn& rSrcCol = aCol[nCol];
+        ScColumn& rDestCol = rDestTab.aCol[nCol+nColDelta];
+        rSrcCol.TransferListeners(rDestCol, nRow1, nRow2, nRowDelta);
+    }
+}
+
 void ScTable::SetLoadingMedium(bool bLoading)
 {
     mpRowHeights->enableTreeSearch(!bLoading);
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
index 6974acf..9bd416c 100644
--- a/sc/source/core/inc/bcaslot.hxx
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -210,6 +210,8 @@ public:
         Meant to be used internally and from ScBroadcastAreaSlotMachine only.
      */
     void                EraseArea( ScBroadcastAreas::iterator& rIter );
+
+    void GetAllListeners( const ScRange& rRange, std::vector<SvtListener*>& rListeners );
 };
 
 
@@ -304,6 +306,8 @@ public:
                                             ScBroadcastAreas::iterator& rIter );
     // only for ScBroadcastAreaSlot
     void                FinallyEraseAreas( ScBroadcastAreaSlot* pSlot );
+
+    std::vector<SvtListener*> GetAllListeners( const ScRange& rRange );
 };
 
 
diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx
index 3cc5b8f..db5c6cf 100644
--- a/sc/source/core/tool/chartlis.cxx
+++ b/sc/source/core/tool/chartlis.cxx
@@ -202,7 +202,7 @@ uno::Reference< chart::XChartData > ScChartListener::GetUnoSource() const
     return uno::Reference< chart::XChartData >();
 }
 
-void ScChartListener::Notify( SvtBroadcaster&, const SfxHint& rHint )
+void ScChartListener::Notify( const SfxHint& rHint )
 {
     const ScHint* p = dynamic_cast<const ScHint*>(&rHint);
     if (p && (p->GetId() & SC_HINT_DATACHANGED))
diff --git a/sc/source/core/tool/lookupcache.cxx b/sc/source/core/tool/lookupcache.cxx
index 914b188..ac92fe6 100644
--- a/sc/source/core/tool/lookupcache.cxx
+++ b/sc/source/core/tool/lookupcache.cxx
@@ -110,7 +110,7 @@ bool ScLookupCache::insert( const ScAddress & rResultAddress,
 }
 
 
-void ScLookupCache::Notify( SvtBroadcaster & /* rBC */ , const SfxHint &  rHint )
+void ScLookupCache::Notify( const SfxHint& rHint )
 {
     if (!mpDoc->IsInDtorClear())
     {
diff --git a/sc/source/core/tool/refhint.cxx b/sc/source/core/tool/refhint.cxx
new file mode 100644
index 0000000..eb07b4fe
--- /dev/null
+++ b/sc/source/core/tool/refhint.cxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <refhint.hxx>
+
+namespace sc {
+
+RefHint::RefHint( Type eType ) : SfxSimpleHint(SC_HINT_REFERENCE), meType(eType) {}
+RefHint::~RefHint() {}
+
+RefHint::Type RefHint::getType() const { return meType; }
+
+RefMovedHint::RefMovedHint( const ScRange& rRange, const ScAddress& rMove ) :
+    RefHint(Moved), maRange(rRange), maMoveDelta(rMove) {}
+
+RefMovedHint::~RefMovedHint() {}
+
+const ScRange& RefMovedHint::getRange() const
+{
+    return maRange;
+}
+
+const ScAddress& RefMovedHint::getDelta() const
+{
+    return maMoveDelta;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3856bac..75f8bc0 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2845,6 +2845,45 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
     return aRes;
 }
 
+void ScTokenArray::MoveReference(
+    const ScAddress& rPos, const ScRange& rMovedRange, const ScAddress& rDelta )
+{
+    FormulaToken** p = pCode;
+    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        switch ((*p)->GetType())
+        {
+            case svSingleRef:
+            {
+                ScToken* pToken = static_cast<ScToken*>(*p);
+                ScSingleRefData& rRef = pToken->GetSingleRef();
+                ScAddress aAbs = rRef.toAbs(rPos);
+                if (rMovedRange.In(aAbs))
+                {
+                    aAbs.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+                    rRef.SetAddress(aAbs, rPos);
+                }
+            }
+            break;
+            case svDoubleRef:
+            {
+                ScToken* pToken = static_cast<ScToken*>(*p);
+                ScComplexRefData& rRef = pToken->GetDoubleRef();
+                ScRange aAbs = rRef.toAbs(rPos);
+                if (rMovedRange.In(aAbs))
+                {
+                    aAbs.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+                    rRef.SetRange(aAbs, rPos);
+                }
+            }
+            break;
+            default:
+                ;
+        }
+    }
+}
+
 namespace {
 
 bool adjustSingleRefInName(
diff --git a/sc/source/ui/docshell/servobj.cxx b/sc/source/ui/docshell/servobj.cxx
index 9cedad4..071d2ba 100644
--- a/sc/source/ui/docshell/servobj.cxx
+++ b/sc/source/ui/docshell/servobj.cxx
@@ -61,7 +61,7 @@ ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder()
     //! do NOT access pObj
 }
 
-void ScServerObjectSvtListenerForwarder::Notify( SvtBroadcaster& /* rBC */, const SfxHint& rHint)
+void ScServerObjectSvtListenerForwarder::Notify( const SfxHint& rHint )
 {
     pObj->Notify( aBroadcaster, rHint);
 }
diff --git a/sc/source/ui/inc/servobj.hxx b/sc/source/ui/inc/servobj.hxx
index 376984d..a35bcaf 100644
--- a/sc/source/ui/inc/servobj.hxx
+++ b/sc/source/ui/inc/servobj.hxx
@@ -36,7 +36,7 @@ class ScServerObjectSvtListenerForwarder : public SvtListener
 public:
                     ScServerObjectSvtListenerForwarder( ScServerObject* pObjP);
     virtual         ~ScServerObjectSvtListenerForwarder();
-    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
+    virtual void Notify( const SfxHint& rHint );
 };
 
 class ScServerObject : public ::sfx2::SvLinkSource, public SfxListener
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 17b3520..68bdbe7 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -48,6 +48,7 @@
 #include "clipparam.hxx"
 #include "sc.hrc"
 #include <rowheightcontext.hxx>
+#include <refhint.hxx>
 
 #include <set>
 
@@ -1251,6 +1252,15 @@ void ScUndoDragDrop::Undo()
     maPaintRanges.RemoveAll();
 
     BeginUndo();
+
+    // Notify all listeners of the destination range, and have them update their references.
+    ScDocument* pDoc = pDocShell->GetDocument();
+    SCCOL nColDelta = aSrcRange.aStart.Col() - aDestRange.aStart.Col();
+    SCROW nRowDelta = aSrcRange.aStart.Row() - aDestRange.aStart.Row();
+    SCTAB nTabDelta = aSrcRange.aStart.Tab() - aDestRange.aStart.Tab();
+    sc::RefMovedHint aHint(aDestRange, ScAddress(nColDelta, nRowDelta, nTabDelta));
+    pDoc->BroadcastRefMoved(aHint);
+
     DoUndo(aDestRange);
     if (bCut)
         DoUndo(aSrcRange);
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 9c84753..5bb1309 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -891,7 +891,7 @@ ScLinkListener::~ScLinkListener()
 {
 }
 
-void ScLinkListener::Notify( SvtBroadcaster&, const SfxHint& rHint )
+void ScLinkListener::Notify( const SfxHint& rHint )
 {
     aLink.Call( (SfxHint*)&rHint );
 }
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 19abe38..753cbc8 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -132,7 +132,7 @@ void SvtBroadcaster::Broadcast( const SfxHint &rHint )
             ++dest;
 
         if (dest == maDestructedListeners.end() || *dest != *it)
-            (*it)->Notify(*this, rHint);
+            (*it)->Notify(rHint);
     }
 }
 
diff --git a/svl/source/notify/listener.cxx b/svl/source/notify/listener.cxx
index 59d3ef9..66207bf 100644
--- a/svl/source/notify/listener.cxx
+++ b/svl/source/notify/listener.cxx
@@ -80,15 +80,7 @@ bool SvtListener::HasBroadcaster() const
     return !maBroadcasters.empty();
 }
 
-void SvtListener::Notify( SvtBroadcaster&
-#ifdef DBG_UTIL
-rBC
-#endif
-, const SfxHint& )
-{
-    DBG_ASSERT( IsListening( rBC ),
-                "notification from unregistered broadcaster" );
-}
+void SvtListener::Notify( const SfxHint& ) {}
 
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 980898058f1411d234c009caaae58b29eb3420c8
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Mar 14 09:47:25 2014 -0400

    fdo#71491: Write test for this.
    
    Change-Id: I20de3d5c3c254b2ce96678553d91492dc95e2c39

diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 8c3ec8f..81e915f 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -119,6 +119,7 @@ public:
     void testFormulaRefUpdateRange();
     void testFormulaRefUpdateSheets();
     void testFormulaRefUpdateMove();
+    void testFormulaRefUpdateMoveUndo();
     void testFormulaRefUpdateNamedExpression();
     void testMultipleOperations();
     void testFuncCOLUMN();
@@ -362,6 +363,7 @@ public:
     CPPUNIT_TEST(testFormulaRefUpdateRange);
     CPPUNIT_TEST(testFormulaRefUpdateSheets);
     CPPUNIT_TEST(testFormulaRefUpdateMove);
+    CPPUNIT_TEST(testFormulaRefUpdateMoveUndo);
     CPPUNIT_TEST(testFormulaRefUpdateNamedExpression);
     CPPUNIT_TEST(testMultipleOperations);
     CPPUNIT_TEST(testFuncCOLUMN);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 4dd1acd..f939698 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1571,6 +1571,122 @@ void Test::testFormulaRefUpdateMove()
     m_pDoc->DeleteTab(0);
 }
 
+void Test::testFormulaRefUpdateMoveUndo()
+{
+    m_pDoc->InsertTab(0, "Test");
+
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+    // Set values in A1:A4.
+    m_pDoc->SetValue(ScAddress(0,0,0), 1.0);
+    m_pDoc->SetValue(ScAddress(0,1,0), 2.0);
+    m_pDoc->SetValue(ScAddress(0,2,0), 3.0);
+    m_pDoc->SetValue(ScAddress(0,3,0), 4.0);
+
+    // Set formulas with single cell references in A6:A8.
+    m_pDoc->SetString(ScAddress(0,5,0), "=A1");
+    CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "A1"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    m_pDoc->SetString(ScAddress(0,6,0), "=A1+A2+A3");
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "A1+A2+A3"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    m_pDoc->SetString(ScAddress(0,7,0), "=A1+A3+A4");
+    CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "A1+A3+A4"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    // Set formulas with range references in A10:A12.
+    m_pDoc->SetString(ScAddress(0,9,0), "=SUM(A1:A2)");
+    CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(A1:A2)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    m_pDoc->SetString(ScAddress(0,10,0), "=SUM(A1:A3)");
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(A1:A3)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    m_pDoc->SetString(ScAddress(0,11,0), "=SUM(A1:A4)");
+    CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    // Move A1:A3 to C1:C3. Note that A4 remains.
+    ScDocFunc& rFunc = getDocShell().GetDocFunc();
+    bool bMoved = rFunc.MoveBlock(ScRange(0,0,0,0,2,0), ScAddress(2,0,0), true, true, false, true);
+    CPPUNIT_ASSERT(bMoved);
+
+    CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "C1"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "C1+C2+C3"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "C1+C3+A4"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(C1:C2)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(C1:C3)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    // Undo the move.
+    SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
+    CPPUNIT_ASSERT(pUndoMgr);
+    pUndoMgr->Undo();
+
+    CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "A1"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "A1+A2+A3"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "A1+A3+A4"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(A1:A2)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(A1:A3)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+    if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+        CPPUNIT_FAIL("Wrong formula.");
+
+    // Make sure the broadcasters are still valid by changing the value of A1.
+    m_pDoc->SetValue(ScAddress(0,0,0), 20);
+
+    CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+    CPPUNIT_ASSERT_EQUAL( 6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+    CPPUNIT_ASSERT_EQUAL(27.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+
+    CPPUNIT_ASSERT_EQUAL(22.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+    CPPUNIT_ASSERT_EQUAL(25.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+    CPPUNIT_ASSERT_EQUAL(29.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+
+    m_pDoc->DeleteTab(0);
+}
+
 void Test::testFormulaRefUpdateNamedExpression()
 {
     m_pDoc->InsertTab(0, "Formula");


More information about the Libreoffice-commits mailing list