[Libreoffice-commits] core.git: Branch 'libreoffice-5-3' - sc/inc sc/source

Eike Rathke erack at redhat.com
Tue Jan 10 19:59:30 UTC 2017


 sc/inc/formulacell.hxx              |    9 +++++++-
 sc/source/core/data/column.cxx      |    2 -
 sc/source/core/data/formulacell.cxx |   40 ++++++++++++++++++++++++++++--------
 sc/source/core/tool/refdata.cxx     |    4 +++
 4 files changed, 45 insertions(+), 10 deletions(-)

New commits:
commit 540e9f5f290b5801c10fa3a6e3ad9046607dcd9c
Author: Eike Rathke <erack at redhat.com>
Date:   Mon Jan 9 19:47:06 2017 +0100

    Resolves: tdf#104711 adjust range reference constructed of named anchors
    
    A constructed range reference of named anchors (i.e. extended during
    expression compilation) forms a range listened at that needs to be
    adjusted if the cell is shifted and one or both anchor parts are
    individually named relative references.
    
    Currently the resulting range (ScComplexRefData aka DoubleRef) does not
    know to distinguish between whether its anchors are the result of a
    literal range in a named expression or the result of individually named
    anchors, so such RelName DoubleRef needs to be adjusted unconditionally
    when shifting or moving the formula cell.
    
    Change-Id: I75e2cc79ac60116671acce7641567337d5f5f7ed
    (cherry picked from commit 439b2a134218b93e6ca9fa23005b89c19498f586)
    Reviewed-on: https://gerrit.libreoffice.org/32923
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 960a753..71812a2 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -243,7 +243,14 @@ public:
        It is similar to HasOneReference(), but more general.
      */
     bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
-    bool            HasRelNameReference() const;
+
+    enum class RelNameRef
+    {
+        NONE,   ///< no relative reference from named expression
+        SINGLE, ///< only single cell relative reference
+        DOUBLE  ///< at least one range relative reference from named expression
+    };
+    RelNameRef      HasRelNameReference() const;
 
     bool UpdateReference(
         const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 7ffafda..ac65f8a 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2834,7 +2834,7 @@ struct SetDirtyIfPostponedHandler
 {
     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
     {
-        if (pCell->IsPostponedDirty() || pCell->HasRelNameReference())
+        if (pCell->IsPostponedDirty() || (pCell->HasRelNameReference() != ScFormulaCell::RelNameRef::NONE))
             pCell->SetDirty();
     }
 };
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index bf6fc4e..b19bfba 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2906,18 +2906,34 @@ ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
     return false;
 }
 
-bool ScFormulaCell::HasRelNameReference() const
+ScFormulaCell::RelNameRef ScFormulaCell::HasRelNameReference() const
 {
+    RelNameRef eRelNameRef = RelNameRef::NONE;
     pCode->Reset();
     formula::FormulaToken* t;
     while ( ( t = pCode->GetNextReferenceRPN() ) != nullptr )
     {
-        if ( t->GetSingleRef()->IsRelName() ||
-                (t->GetType() == formula::svDoubleRef &&
-                t->GetDoubleRef()->Ref2.IsRelName()) )
-            return true;
+        switch (t->GetType())
+        {
+            case formula::svSingleRef:
+                if (t->GetSingleRef()->IsRelName() && eRelNameRef == RelNameRef::NONE)
+                    eRelNameRef = RelNameRef::SINGLE;
+            break;
+            case formula::svDoubleRef:
+                if (t->GetDoubleRef()->Ref1.IsRelName() || t->GetDoubleRef()->Ref2.IsRelName())
+                    // May originate from individual cell names, in which case
+                    // it needs recompilation.
+                    return RelNameRef::DOUBLE;
+                /* TODO: have an extra flag at ScComplexRefData if range was
+                 * extended? or too cumbersome? might narrow recompilation to
+                 * only needed cases.
+                 * */
+            break;
+            default:
+                ;   // nothing
+        }
     }
-    return false;
+    return eRelNameRef;
 }
 
 bool ScFormulaCell::UpdatePosOnShift( const sc::RefUpdateContext& rCxt )
@@ -3122,7 +3138,13 @@ bool ScFormulaCell::UpdateReferenceOnShift(
         bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
 
         // RelNameRefs are always moved
-        bool bHasRelName = HasRelNameReference();
+        bool bHasRelName = false;
+        if (!bRecompile)
+        {
+            RelNameRef eRelNameRef = HasRelNameReference();
+            bHasRelName = (eRelNameRef != RelNameRef::NONE);
+            bRecompile = (eRelNameRef == RelNameRef::DOUBLE);
+        }
         // Reference changed and new listening needed?
         // Except in Insert/Delete without specialties.
         bNewListening = (bRefModified || bRecompile
@@ -3246,7 +3268,9 @@ bool ScFormulaCell::UpdateReferenceOnMove(
         bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
 
         // RelNameRefs are always moved
-        bHasRelName = HasRelNameReference();
+        RelNameRef eRelNameRef = HasRelNameReference();
+        bHasRelName = (eRelNameRef != RelNameRef::NONE);
+        bCompile |= (eRelNameRef == RelNameRef::DOUBLE);
         // Reference changed and new listening needed?
         // Except in Insert/Delete without specialties.
         bNewListening = (bRefModified || bColRowNameCompile
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index 53bf2e4..d972893 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -455,6 +455,10 @@ ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const
     if (rRef.IsFlag3D())
         Ref1.SetFlag3D( true);
 
+    // Inherit RelNameRef from extending part.
+    if (rRef.IsRelName())
+        Ref2.SetRelName(true);
+
     SetRange(aAbsRange, rPos);
 
     return *this;


More information about the Libreoffice-commits mailing list