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

Eike Rathke erack at redhat.com
Thu Feb 26 07:18:23 PST 2015


 sc/inc/tokenarray.hxx          |    3 +
 sc/source/core/data/column.cxx |   29 ++++++++++++
 sc/source/core/tool/token.cxx  |   93 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+)

New commits:
commit 0cd15b4494f8e8abe67a258fb10189135bf5a8ac
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Feb 26 12:54:13 2015 +0100

    split formula grouping for reference edge expansion, tdf#81659 related
    
    Edge expansion may change expressions individually, which must be split
    off the group.
    
    Change-Id: Id4328bd8c42f2ff9f83d2edc845537971f3a39d3

diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 9dc94b9..4068745 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -233,6 +233,9 @@ public:
     void CheckRelativeReferenceBounds(
         const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector<SCROW>& rBounds ) const;
 
+    void CheckExpandReferenceBounds(
+        const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const;
+
     /**
      * Create a string representation of formula token array without modifying
      * the internal state of the token array.
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ab7cd69..94d753d 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2279,6 +2279,27 @@ public:
     }
 };
 
+class UpdateRefExpandGroupBoundChecker : public SharedTopFormulaCellPicker
+{
+    const sc::RefUpdateContext& mrCxt;
+    std::vector<SCROW>& mrBounds;
+
+public:
+    UpdateRefExpandGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
+        mrCxt(rCxt), mrBounds(rBounds) {}
+
+    virtual ~UpdateRefExpandGroupBoundChecker() {}
+
+    virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) SAL_OVERRIDE
+    {
+        // Check its tokens and record its reference boundaries.
+        ScFormulaCell& rCell = **ppCells;
+        const ScTokenArray& rCode = *rCell.GetCode();
+        rCode.CheckExpandReferenceBounds(
+            mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
+    }
+};
+
 class FormulaGroupPicker : public SharedTopFormulaCellPicker
 {
     std::vector<sc::FormulaGroupEntry>& mrGroups;
@@ -2364,6 +2385,14 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc
     UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
     std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
 
+    // If expand reference edges is on, splitting groups may happen anywhere
+    // where a reference points to an adjacent row of the insertion.
+    if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
+    {
+        UpdateRefExpandGroupBoundChecker aExpandChecker(rCxt, aBounds);
+        std::for_each(maCells.begin(), maCells.end(), aExpandChecker);
+    }
+
     // Do the actual splitting.
     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
 
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index b5dbee0..77489fd 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -3682,6 +3682,99 @@ void ScTokenArray::CheckRelativeReferenceBounds(
     }
 }
 
+void ScTokenArray::CheckExpandReferenceBounds(
+    const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
+{
+    const SCROW nInsRow = rCxt.maRange.aStart.Row();
+    const FormulaToken* const * p = pCode;
+    const FormulaToken* const * pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        switch ((*p)->GetType())
+        {
+            case svDoubleRef:
+            {
+                const formula::FormulaToken* pToken = *p;
+                const ScComplexRefData& rRef = *pToken->GetDoubleRef();
+                bool bStartRowRelative = rRef.Ref1.IsRowRel();
+                bool bEndRowRelative = rRef.Ref2.IsRowRel();
+
+                // For absolute references nothing needs to be done, they stay
+                // the same for all and if to be expanded the group will be
+                // adjusted later.
+                if (!bStartRowRelative && !bEndRowRelative)
+                    break;  // switch
+
+                ScRange aAbsStart(rRef.toAbs(rPos));
+                ScAddress aPos(rPos);
+                aPos.IncRow(nGroupLen);
+                ScRange aAbsEnd(rRef.toAbs(aPos));
+                // References must be at least two rows to be expandable.
+                if ((aAbsStart.aEnd.Row() - aAbsStart.aStart.Row() < 1) &&
+                        (aAbsEnd.aEnd.Row() - aAbsEnd.aStart.Row() < 1))
+                    break;  // switch
+
+                // Only need to process if an edge may be touching the
+                // insertion row anywhere within the run of the group.
+                if (!((aAbsStart.aStart.Row() <= nInsRow && nInsRow <= aAbsEnd.aStart.Row()) ||
+                            (aAbsStart.aEnd.Row() <= nInsRow && nInsRow <= aAbsEnd.aEnd.Row())))
+                    break;  // switch
+
+                SCROW nStartRow = aAbsStart.aStart.Row();
+                SCROW nEndRow = aAbsStart.aEnd.Row();
+                // Position on first relevant range.
+                SCROW nOffset = 0;
+                if (nEndRow + 1 < nInsRow)
+                {
+                    if (bEndRowRelative)
+                    {
+                        nOffset = nInsRow - nEndRow - 1;
+                        nEndRow += nOffset;
+                        if (bStartRowRelative)
+                            nStartRow += nOffset;
+                    }
+                    else    // bStartRowRelative==true
+                    {
+                        nOffset = nInsRow - nStartRow;
+                        nStartRow += nOffset;
+                        // Start is overtaking End, swap.
+                        bStartRowRelative = false;
+                        bEndRowRelative = true;
+                    }
+                }
+                for (SCROW i = nOffset; i < nGroupLen; ++i)
+                {
+                    bool bSplit = (nStartRow == nInsRow || nEndRow + 1 == nInsRow);
+                    if (bSplit)
+                        rBounds.push_back( rPos.Row() + i);
+
+                    if (bEndRowRelative)
+                        ++nEndRow;
+                    if (bStartRowRelative)
+                    {
+                        ++nStartRow;
+                        if (!bEndRowRelative && nStartRow == nEndRow)
+                        {
+                            // Start is overtaking End, swap.
+                            bStartRowRelative = false;
+                            bEndRowRelative = true;
+                        }
+                    }
+                    if (nInsRow < nStartRow || (!bStartRowRelative && nInsRow <= nEndRow))
+                    {
+                        if (bSplit && (++i < nGroupLen))
+                            rBounds.push_back( rPos.Row() + i);
+                        break;  // for, out of range now
+                    }
+                }
+            }
+            break;
+            default:
+                ;
+        }
+    }
+}
+
 namespace {
 
 void appendDouble( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, double fVal )


More information about the Libreoffice-commits mailing list