[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 2 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Wed Jul 17 18:31:01 PDT 2013


 sc/inc/formulacell.hxx              |   18 +
 sc/source/core/data/formulacell.cxx |  550 +++++++++++++++++++++++++++++-------
 2 files changed, 462 insertions(+), 106 deletions(-)

New commits:
commit 4efa10aebbbe8da21d3b2214cdabd6acd6079889
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 17 21:31:24 2013 -0400

    Split this method into 3.
    
    Apparently too many people have tried to cram their needs into this
    single function, which ended up making this such a monster full of
    temporary hacks.
    
    Change-Id: If8f7676a60f6017767e68252d173ca9e38b89d99

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 7012eb1..7260ea0 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -105,6 +105,24 @@ private:
                     };
     void            InterpretTail( ScInterpretTailParameter );
 
+    /**
+     * Update reference in response to cell insertion or deletion.
+     */
+    bool UpdateReferenceOnShift(
+        const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
+
+    /**
+     * Update reference in response to cell move.
+     */
+    bool UpdateReferenceOnMove(
+        const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
+
+    /**
+     * Update reference in response to cell copy-n-paste.
+     */
+    bool UpdateReferenceOnCopy(
+        const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
+
     ScFormulaCell( const ScFormulaCell& );
 public:
 
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index bd9bb6c..aa03600 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2204,25 +2204,24 @@ bool checkCompileColRowName(
 
 }
 
-bool ScFormulaCell::UpdateReference(
+bool ScFormulaCell::UpdateReferenceOnShift(
     const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
 {
+    if (rCxt.meMode != URM_INSDEL)
+        // Just in case...
+        return false;
+
     bool bCellStateChanged = false;
-    UpdateRefMode eUpdateRefMode = rCxt.meMode;
     const ScRange& rRange = rCxt.maRange;
     SCCOL nDx = rCxt.mnColDelta;
     SCROW nDy = rCxt.mnRowDelta;
     SCTAB nDz = rCxt.mnTabDelta;
-    SCCOL nCol = aPos.Col();
-    SCROW nRow = aPos.Row();
-    SCTAB nTab = aPos.Tab();
     ScAddress aUndoPos( aPos );         // position for undo cell in pUndoDoc
     if ( pUndoCellPos )
         aUndoPos = *pUndoCellPos;
     ScAddress aOldPos( aPos );
-    bool bIsInsert = (eUpdateRefMode == URM_INSDEL && nDx >= 0 && nDy >= 0 && nDz >= 0);
 
-    if (eUpdateRefMode == URM_INSDEL && rRange.In(aPos))
+    if (rRange.In(aPos))
     {
         // This formula cell itself is being shifted during cell range
         // insertion or deletion. Update its position.
@@ -2232,7 +2231,169 @@ bool ScFormulaCell::UpdateReference(
 
         bCellStateChanged = aPos != aOldPos;
     }
-    else if (rRange.In(aPos))
+
+    bool bHasRefs = false;
+    bool bHasColRowNames = false;
+    bool bOnRefMove = false;
+    if ( !pDocument->IsClipOrUndo() )
+    {
+        // Check presence of any references or column row names.
+        pCode->Reset();
+        bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
+        if (!bHasRefs)
+        {
+            pCode->Reset();
+            bHasColRowNames = (pCode->GetNextColRowName() != NULL);
+            bHasRefs = bHasRefs || bHasColRowNames;
+        }
+        bOnRefMove = pCode->IsRecalcModeOnRefMove();
+    }
+
+    if (!bHasRefs && !bOnRefMove)
+        // This formula cell contains no references, nor needs recalculating
+        // on reference update. Bail out.
+        return bCellStateChanged;
+
+    boost::scoped_ptr<ScTokenArray> pOldCode;
+    if (pUndoDoc)
+        pOldCode.reset(pCode->Clone());
+
+    ScRangeData* pSharedCode = NULL;
+    bool bValChanged = false;
+    bool bRangeModified = false;    // any range, not only shared formula
+    bool bRefSizeChanged = false;
+
+    if (bHasRefs)
+    {
+        // Update cell or range references.
+        ScCompiler aComp(pDocument, aPos, *pCode);
+        aComp.SetGrammar(pDocument->GetGrammar());
+        pSharedCode = aComp.UpdateReference(URM_INSDEL, aOldPos, rRange,
+                                         nDx, nDy, nDz,
+                                         bValChanged, bRefSizeChanged);
+        bRangeModified = aComp.HasModifiedRange();
+    }
+
+    bCellStateChanged |= bValChanged;
+
+    if (bOnRefMove)
+        // Cell may reference itself, e.g. ocColumn, ocRow without parameter
+        bOnRefMove = (bValChanged || (aPos != aOldPos));
+
+    bool bColRowNameCompile = false;
+    bool bHasRelName = false;
+    bool bNewListening = false;
+    bool bInDeleteUndo = false;
+
+    if (bHasRefs)
+    {
+        // Upon Insert ColRowNames have to be recompiled in case the
+        // insertion occurs right in front of the range.
+        if (bHasColRowNames)
+            bColRowNameCompile = checkCompileColRowName(rCxt, *pDocument, *pCode, aOldPos, aPos, bValChanged);
+
+        ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
+        bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
+
+        // RelNameRefs are always moved
+        bHasRelName = HasRelNameReference();
+        // Reference changed and new listening needed?
+        // Except in Insert/Delete without specialties.
+        bNewListening = (bRangeModified || pSharedCode || bColRowNameCompile
+                || (bValChanged && (bInDeleteUndo || bRefSizeChanged)) || bHasRelName);
+
+        if ( bNewListening )
+            EndListeningTo(pDocument, pOldCode.get(), aOldPos);
+    }
+
+    bool bNeedDirty = false;
+    // NeedDirty for changes except for Copy and Move/Insert without RelNames
+    if (bRangeModified || pSharedCode || bColRowNameCompile ||
+        (bValChanged && (bHasRelName || bInDeleteUndo || bRefSizeChanged)) || bOnRefMove)
+        bNeedDirty = true;
+
+    if (pUndoDoc && (bValChanged || pSharedCode || bOnRefMove))
+    {
+        // Copy the cell to aUndoPos, which is its current position in the document,
+        // so this works when UpdateReference is called before moving the cells
+        // (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference
+        // is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed).
+
+        // If there is already a formula cell in the undo document, don't overwrite it,
+        // the first (oldest) is the important cell.
+        if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA )
+        {
+            ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos,
+                    pOldCode.get(), eTempGrammar, cMatrixFlag );
+            pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
+            pUndoDoc->SetFormulaCell(aUndoPos, pFCell);
+        }
+    }
+
+    bValChanged = false;
+
+    if ( pSharedCode )
+    {   // Replace shared formula with own formula
+        pDocument->RemoveFromFormulaTree( this );   // update formula count
+        delete pCode;
+        pCode = pSharedCode->GetCode()->Clone();
+        // #i18937# #i110008# call MoveRelWrap, but with the old position
+        ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pSharedCode->GetMaxCol(), pSharedCode->GetMaxRow());
+        ScCompiler aComp2(pDocument, aPos, *pCode);
+        aComp2.SetGrammar(pDocument->GetGrammar());
+        aComp2.UpdateSharedFormulaReference(URM_INSDEL, aOldPos, rRange, nDx, nDy, nDz);
+        bValChanged = true;
+        bNeedDirty = true;
+    }
+
+    if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
+    {
+        CompileTokenArray( bNewListening ); // no Listening
+        bNeedDirty = true;
+    }
+
+    if ( !bInDeleteUndo )
+    {   // In ChangeTrack Delete-Reject listeners are established in
+        // InsertCol/InsertRow
+        if ( bNewListening )
+        {
+            // Inserts/Deletes re-establish listeners after all
+            // UpdateReference calls.
+            // All replaced shared formula listeners have to be
+            // established after an Insert or Delete. Do nothing here.
+            SetNeedsListening( true);
+        }
+    }
+
+    if ( bNeedDirty && (!bHasRelName || pSharedCode) )
+    {   // Cut off references, invalid or similar?
+        sc::AutoCalcSwitch(*pDocument, false);
+        SetDirty();
+    }
+
+    return bCellStateChanged;
+}
+
+bool ScFormulaCell::UpdateReferenceOnMove(
+    const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
+{
+    if (rCxt.meMode != URM_MOVE)
+        return false;
+
+    bool bCellStateChanged = false;
+    const ScRange& rRange = rCxt.maRange;
+    SCCOL nDx = rCxt.mnColDelta;
+    SCROW nDy = rCxt.mnRowDelta;
+    SCTAB nDz = rCxt.mnTabDelta;
+    SCCOL nCol = aPos.Col();
+    SCROW nRow = aPos.Row();
+    SCTAB nTab = aPos.Tab();
+    ScAddress aUndoPos( aPos );         // position for undo cell in pUndoDoc
+    if ( pUndoCellPos )
+        aUndoPos = *pUndoCellPos;
+    ScAddress aOldPos( aPos );
+
+    if (rRange.In(aPos))
     {
         // The cell is being moved or copied to a new position. I guess the
         // position has been updated prior to this call?  Determine
@@ -2249,7 +2410,7 @@ bool ScFormulaCell::UpdateReference(
         // Check presence of any references or column row names.
         pCode->Reset();
         bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
-        if ( !bHasRefs || eUpdateRefMode == URM_COPY )
+        if (!bHasRefs)
         {
             pCode->Reset();
             bHasColRowNames = (pCode->GetNextColRowName() != NULL);
@@ -2277,7 +2438,7 @@ bool ScFormulaCell::UpdateReference(
         // Update cell or range references.
         ScCompiler aComp(pDocument, aPos, *pCode);
         aComp.SetGrammar(pDocument->GetGrammar());
-        pSharedCode = aComp.UpdateReference(eUpdateRefMode, aOldPos, rRange,
+        pSharedCode = aComp.UpdateReference(URM_MOVE, aOldPos, rRange,
                                          nDx, nDy, nDz,
                                          bValChanged, bRefSizeChanged);
         bRangeModified = aComp.HasModifiedRange();
@@ -2309,14 +2470,11 @@ bool ScFormulaCell::UpdateReference(
         // Reference changed and new listening needed?
         // Except in Insert/Delete without specialties.
         bNewListening = (bRangeModified || pSharedCode || bColRowNameCompile
-                || (bValChanged && (eUpdateRefMode != URM_INSDEL ||
-                        bInDeleteUndo || bRefSizeChanged)) ||
-                (bHasRelName && eUpdateRefMode != URM_COPY))
+                || bValChanged || bHasRelName)
             // #i36299# Don't duplicate action during cut&paste / drag&drop
             // on a cell in the range moved, start/end listeners is done
             // via ScDocument::DeleteArea() and ScDocument::CopyFromClip().
-            && !(eUpdateRefMode == URM_MOVE &&
-                    pDocument->IsInsertingFromOtherDoc() && rRange.In(aPos));
+            && !(pDocument->IsInsertingFromOtherDoc() && rRange.In(aPos));
 
         if ( bNewListening )
             EndListeningTo(pDocument, pOldCode.get(), aOldPos);
@@ -2325,10 +2483,7 @@ bool ScFormulaCell::UpdateReference(
     bool bNeedDirty = false;
     // NeedDirty for changes except for Copy and Move/Insert without RelNames
     if ( bRangeModified || pSharedCode || bColRowNameCompile ||
-            (bValChanged && eUpdateRefMode != URM_COPY &&
-             (eUpdateRefMode != URM_MOVE || bHasRelName) &&
-             (!bIsInsert || bHasRelName || bInDeleteUndo ||
-              bRefSizeChanged)) || bOnRefMove)
+         (bValChanged && bHasRelName && (bHasRelName || bInDeleteUndo || bRefSizeChanged)) || bOnRefMove)
         bNeedDirty = true;
 
     if (pUndoDoc && (bValChanged || pSharedCode || bOnRefMove))
@@ -2360,7 +2515,7 @@ bool ScFormulaCell::UpdateReference(
         ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pSharedCode->GetMaxCol(), pSharedCode->GetMaxRow());
         ScCompiler aComp2(pDocument, aPos, *pCode);
         aComp2.SetGrammar(pDocument->GetGrammar());
-        aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, rRange,
+        aComp2.UpdateSharedFormulaReference(URM_MOVE, aOldPos, rRange,
             nDx, nDy, nDz );
         bValChanged = true;
         bNeedDirty = true;
@@ -2377,20 +2532,11 @@ bool ScFormulaCell::UpdateReference(
         // InsertCol/InsertRow
         if ( bNewListening )
         {
-            if ( eUpdateRefMode == URM_INSDEL )
-            {
-                // Inserts/Deletes re-establish listeners after all
-                // UpdateReference calls.
-                // All replaced shared formula listeners have to be
-                // established after an Insert or Delete. Do nothing here.
-                SetNeedsListening( true);
-            }
-            else
-                StartListeningTo( pDocument );
+            StartListeningTo( pDocument );
         }
     }
 
-    if ( bNeedDirty && (!(eUpdateRefMode == URM_INSDEL && bHasRelName) || pSharedCode) )
+    if (bNeedDirty)
     {   // Cut off references, invalid or similar?
         sc::AutoCalcSwitch(*pDocument, false);
         SetDirty();
@@ -2399,6 +2545,184 @@ bool ScFormulaCell::UpdateReference(
     return bCellStateChanged;
 }
 
+bool ScFormulaCell::UpdateReferenceOnCopy(
+    const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
+{
+    if (rCxt.meMode != URM_COPY)
+        return false;
+
+    bool bCellStateChanged = false;
+    const ScRange& rRange = rCxt.maRange;
+    SCCOL nDx = rCxt.mnColDelta;
+    SCROW nDy = rCxt.mnRowDelta;
+    SCTAB nDz = rCxt.mnTabDelta;
+    SCCOL nCol = aPos.Col();
+    SCROW nRow = aPos.Row();
+    SCTAB nTab = aPos.Tab();
+    ScAddress aUndoPos( aPos );         // position for undo cell in pUndoDoc
+    if ( pUndoCellPos )
+        aUndoPos = *pUndoCellPos;
+    ScAddress aOldPos( aPos );
+
+    if (rRange.In(aPos))
+    {
+        // The cell is being moved or copied to a new position. I guess the
+        // position has been updated prior to this call?  Determine
+        // its original position before the move which will be used to adjust
+        // relative references later.
+        aOldPos.Set( nCol - nDx, nRow - nDy, nTab - nDz );
+    }
+
+    bool bHasRefs = false;
+    bool bHasColRowNames = false;
+    bool bOnRefMove = false;
+    if ( !pDocument->IsClipOrUndo() )
+    {
+        // Check presence of any references or column row names.
+        pCode->Reset();
+        bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
+        pCode->Reset();
+        bHasColRowNames = (pCode->GetNextColRowName() != NULL);
+        bHasRefs = bHasRefs || bHasColRowNames;
+        bOnRefMove = pCode->IsRecalcModeOnRefMove();
+    }
+
+    if (!bHasRefs && !bOnRefMove)
+        // This formula cell contains no references, nor needs recalculating
+        // on reference update. Bail out.
+        return bCellStateChanged;
+
+    boost::scoped_ptr<ScTokenArray> pOldCode;
+    if (pUndoDoc)
+        pOldCode.reset(pCode->Clone());
+
+    ScRangeData* pSharedCode = NULL;
+    bool bValChanged = false;
+    bool bRangeModified = false;    // any range, not only shared formula
+    bool bRefSizeChanged = false;
+
+    if (bHasRefs)
+    {
+        // Update cell or range references.
+        ScCompiler aComp(pDocument, aPos, *pCode);
+        aComp.SetGrammar(pDocument->GetGrammar());
+        pSharedCode = aComp.UpdateReference(URM_COPY, aOldPos, rRange,
+                                         nDx, nDy, nDz,
+                                         bValChanged, bRefSizeChanged);
+        bRangeModified = aComp.HasModifiedRange();
+    }
+
+    bCellStateChanged |= bValChanged;
+
+    if (bOnRefMove)
+        // Cell may reference itself, e.g. ocColumn, ocRow without parameter
+        bOnRefMove = (bValChanged || (aPos != aOldPos));
+
+    bool bColRowNameCompile = false;
+    bool bHasRelName = false;
+    bool bNewListening = false;
+    bool bInDeleteUndo = false;
+
+    if (bHasRefs)
+    {
+        // Upon Insert ColRowNames have to be recompiled in case the
+        // insertion occurs right in front of the range.
+        if (bHasColRowNames)
+            bColRowNameCompile = checkCompileColRowName(rCxt, *pDocument, *pCode, aOldPos, aPos, bValChanged);
+
+        ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
+        bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
+
+        // RelNameRefs are always moved
+        bHasRelName = HasRelNameReference();
+        // Reference changed and new listening needed?
+        // Except in Insert/Delete without specialties.
+        bNewListening =
+            (bRangeModified || pSharedCode || bColRowNameCompile || (bValChanged && (bInDeleteUndo || bRefSizeChanged)));
+
+        if ( bNewListening )
+            EndListeningTo(pDocument, pOldCode.get(), aOldPos);
+    }
+
+    bool bNeedDirty = false;
+    // NeedDirty for changes except for Copy and Move/Insert without RelNames
+    if ( bRangeModified || pSharedCode || bColRowNameCompile || bOnRefMove)
+        bNeedDirty = true;
+
+    if (pUndoDoc && (bValChanged || pSharedCode || bOnRefMove))
+    {
+        // Copy the cell to aUndoPos, which is its current position in the document,
+        // so this works when UpdateReference is called before moving the cells
+        // (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference
+        // is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed).
+
+        // If there is already a formula cell in the undo document, don't overwrite it,
+        // the first (oldest) is the important cell.
+        if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA )
+        {
+            ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos,
+                    pOldCode.get(), eTempGrammar, cMatrixFlag );
+            pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
+            pUndoDoc->SetFormulaCell(aUndoPos, pFCell);
+        }
+    }
+
+    bValChanged = false;
+
+    if ( pSharedCode )
+    {   // Replace shared formula with own formula
+        pDocument->RemoveFromFormulaTree( this );   // update formula count
+        delete pCode;
+        pCode = pSharedCode->GetCode()->Clone();
+        // #i18937# #i110008# call MoveRelWrap, but with the old position
+        ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pSharedCode->GetMaxCol(), pSharedCode->GetMaxRow());
+        ScCompiler aComp2(pDocument, aPos, *pCode);
+        aComp2.SetGrammar(pDocument->GetGrammar());
+        aComp2.UpdateSharedFormulaReference(URM_COPY, aOldPos, rRange, nDx, nDy, nDz);
+        bValChanged = true;
+        bNeedDirty = true;
+    }
+
+    if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
+    {
+        CompileTokenArray( bNewListening ); // no Listening
+        bNeedDirty = true;
+    }
+
+    if ( !bInDeleteUndo )
+    {   // In ChangeTrack Delete-Reject listeners are established in
+        // InsertCol/InsertRow
+        if ( bNewListening )
+            StartListeningTo( pDocument );
+    }
+
+    if (bNeedDirty)
+    {   // Cut off references, invalid or similar?
+        sc::AutoCalcSwitch(*pDocument, false);
+        SetDirty();
+    }
+
+    return bCellStateChanged;
+}
+
+bool ScFormulaCell::UpdateReference(
+    const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
+{
+    switch (rCxt.meMode)
+    {
+        case URM_INSDEL:
+            return UpdateReferenceOnShift(rCxt, pUndoDoc, pUndoCellPos);
+        case URM_MOVE:
+            return UpdateReferenceOnMove(rCxt, pUndoDoc, pUndoCellPos);
+        case URM_COPY:
+            return UpdateReferenceOnCopy(rCxt, pUndoDoc, pUndoCellPos);
+        default:
+            ;
+    }
+
+    return false;
+}
+
 void ScFormulaCell::UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets)
 {
     bool bPosChanged = ( aPos.Tab() >= nTable ? true : false );
commit b4c5b83ad7036a127607fd8dee51969b79ad7612
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 17 18:46:41 2013 -0400

    Extract this code into a local function.
    
    Change-Id: I91bb3cdc31d247004e22bef734374e8a80819c3a

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index acb5d46..bd9bb6c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2117,6 +2117,93 @@ bool ScFormulaCell::HasColRowName() const
     return (pCode->GetNextColRowName() != NULL);
 }
 
+namespace {
+
+/**
+ * Check if we need to re-compile column or row names.
+ */
+bool checkCompileColRowName(
+    const sc::RefUpdateContext& rCxt, ScDocument& rDoc, ScTokenArray& rCode,
+    const ScAddress& aOldPos, const ScAddress& aPos, bool bValChanged)
+{
+    switch (rCxt.meMode)
+    {
+        case URM_INSDEL:
+        {
+            if (rCxt.mnColDelta <= 0 && rCxt.mnRowDelta <= 0)
+                return false;
+
+            ScToken* t;
+            ScRangePairList* pColList = rDoc.GetColNameRanges();
+            ScRangePairList* pRowList = rDoc.GetRowNameRanges();
+            rCode.Reset();
+            while ((t = static_cast<ScToken*>(rCode.GetNextColRowName())) != NULL)
+            {
+                ScSingleRefData& rRef = t->GetSingleRef();
+                if (rCxt.mnRowDelta > 0 && rRef.IsColRel())
+                {   // ColName
+                    ScAddress aAdr = rRef.toAbs(aPos);
+                    ScRangePair* pR = pColList->Find( aAdr );
+                    if ( pR )
+                    {   // defined
+                        if (pR->GetRange(1).aStart.Row() == rCxt.maRange.aStart.Row())
+                            return true;
+                    }
+                    else
+                    {   // on the fly
+                        if (aAdr.Row() + 1 == rCxt.maRange.aStart.Row())
+                            return true;
+                    }
+                }
+                if (rCxt.mnColDelta > 0 && rRef.IsRowRel())
+                {   // RowName
+                    ScAddress aAdr = rRef.toAbs(aPos);
+                    ScRangePair* pR = pRowList->Find( aAdr );
+                    if ( pR )
+                    {   // defined
+                        if ( pR->GetRange(1).aStart.Col() == rCxt.maRange.aStart.Col())
+                            return true;
+                    }
+                    else
+                    {   // on the fly
+                        if (aAdr.Col() + 1 == rCxt.maRange.aStart.Col())
+                            return true;
+                    }
+                }
+            }
+        }
+        case URM_MOVE:
+        {   // Recomplie for Move/D&D when ColRowName was moved or this Cell
+            // points to one and was moved.
+            bool bMoved = (aPos != aOldPos);
+            if (bMoved)
+                return true;
+
+            rCode.Reset();
+            const ScToken* t = static_cast<const ScToken*>(rCode.GetNextColRowName());
+            for (; t; t = static_cast<const ScToken*>(rCode.GetNextColRowName()))
+            {
+                const ScSingleRefData& rRef = t->GetSingleRef();
+                ScAddress aAbs = rRef.toAbs(aPos);
+                if (ValidAddress(aAbs))
+                {
+                    if (rCxt.maRange.In(aAbs))
+                        return true;
+                }
+            }
+        }
+        break;
+        case URM_COPY:
+            return bValChanged;
+        default:
+            ;
+    }
+
+    return false;
+}
+
+}
+
 bool ScFormulaCell::UpdateReference(
     const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
 {
@@ -2126,8 +2213,6 @@ bool ScFormulaCell::UpdateReference(
     SCCOL nDx = rCxt.mnColDelta;
     SCROW nDy = rCxt.mnRowDelta;
     SCTAB nDz = rCxt.mnTabDelta;
-    SCCOL nCol1 = rRange.aStart.Col();
-    SCROW nRow1 = rRange.aStart.Row();
     SCCOL nCol = aPos.Col();
     SCROW nRow = aPos.Row();
     SCTAB nTab = aPos.Tab();
@@ -2213,79 +2298,8 @@ bool ScFormulaCell::UpdateReference(
     {
         // Upon Insert ColRowNames have to be recompiled in case the
         // insertion occurs right in front of the range.
-        bColRowNameCompile =
-            (eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0));
-
-        if ( bColRowNameCompile )
-        {
-            bColRowNameCompile = false;
-            ScToken* t;
-            ScRangePairList* pColList = pDocument->GetColNameRanges();
-            ScRangePairList* pRowList = pDocument->GetRowNameRanges();
-            pCode->Reset();
-            while ( !bColRowNameCompile && (t = static_cast<ScToken*>(pCode->GetNextColRowName())) != NULL )
-            {
-                ScSingleRefData& rRef = t->GetSingleRef();
-                if ( nDy > 0 && rRef.IsColRel() )
-                {   // ColName
-                    ScAddress aAdr = rRef.toAbs(aPos);
-                    ScRangePair* pR = pColList->Find( aAdr );
-                    if ( pR )
-                    {   // defined
-                        if ( pR->GetRange(1).aStart.Row() == nRow1 )
-                            bColRowNameCompile = true;
-                    }
-                    else
-                    {   // on the fly
-                        if (aAdr.Row() + 1 == nRow1)
-                            bColRowNameCompile = true;
-                    }
-                }
-                if ( nDx > 0 && rRef.IsRowRel() )
-                {   // RowName
-                    ScAddress aAdr = rRef.toAbs(aPos);
-                    ScRangePair* pR = pRowList->Find( aAdr );
-                    if ( pR )
-                    {   // defined
-                        if ( pR->GetRange(1).aStart.Col() == nCol1 )
-                            bColRowNameCompile = true;
-                    }
-                    else
-                    {   // on the fly
-                        if (aAdr.Col() + 1 == nCol1)
-                            bColRowNameCompile = true;
-                    }
-                }
-            }
-        }
-        else if ( eUpdateRefMode == URM_MOVE )
-        {   // Recomplie for Move/D&D when ColRowName was moved or this Cell
-            // points to one and was moved.
-            bColRowNameCompile = bCompile;      // Possibly from Copy ctor
-            if ( !bColRowNameCompile )
-            {
-                bool bMoved = (aPos != aOldPos);
-                pCode->Reset();
-                ScToken* t = static_cast<ScToken*>(pCode->GetNextColRowName());
-                if ( t && bMoved )
-                    bColRowNameCompile = true;
-                while ( t && !bColRowNameCompile )
-                {
-                    ScSingleRefData& rRef = t->GetSingleRef();
-                    ScAddress aAbs = rRef.toAbs(aPos);
-                    if (ValidAddress(aAbs))
-                    {
-                        if (rRange.In(aAbs))
-                            bColRowNameCompile = true;
-                    }
-                    t = static_cast<ScToken*>(pCode->GetNextColRowName());
-                }
-            }
-        }
-        else if ( eUpdateRefMode == URM_COPY && bHasColRowNames && bValChanged )
-        {
-            bColRowNameCompile = true;
-        }
+        if (bHasColRowNames)
+            bColRowNameCompile = checkCompileColRowName(rCxt, *pDocument, *pCode, aOldPos, aPos, bValChanged);
 
         ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
         bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());


More information about the Libreoffice-commits mailing list