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

Eike Rathke erack at redhat.com
Fri Feb 27 04:06:44 PST 2015


 sc/inc/tokenarray.hxx          |    3 
 sc/source/core/data/column.cxx |   29 +++++++++
 sc/source/core/tool/token.cxx  |  132 +++++++++++++++++++++++++++++++++++++++--
 3 files changed, 158 insertions(+), 6 deletions(-)

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

    Resolves: tdf#81659 handle expand reference edge correctly
    
    split formula grouping for reference edge expansion, tdf#81659 related
    
    Edge expansion may change expressions individually, which must be split
    off the group.
    
    (cherry picked from commit 0cd15b4494f8e8abe67a258fb10189135bf5a8ac)
    
    tdf#81659 check that references are at least 2 cols/rows to expand edge
    
    Needs also 0cd15b4494f8e8abe67a258fb10189135bf5a8ac if edges are to be
    expanded and formula grouping is affected.
    
    (cherry picked from commit 23b0112ecea2f8796a4e237e9061de1a36997a30)
    
    Backported.
    
    b3cee8dd214d216907248316a2ac5a290399b169
    
    Change-Id: Id4328bd8c42f2ff9f83d2edc845537971f3a39d3
    Reviewed-on: https://gerrit.libreoffice.org/14656
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 1768ba9..e134f12 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 64174ab..431e9b1 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2300,6 +2300,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;
@@ -2385,6 +2406,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 1b550af..9961b58 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2642,9 +2642,18 @@ bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
             // Selected range is only partially overlapping in vertical direction. Bail out.
             return false;
 
-        if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Col() <= rRefRange.aStart.Col())
-            // Selected range is at the left end and the edge expansion is turned off.  No expansion.
-            return false;
+        if (rCxt.mrDoc.IsExpandRefs())
+        {
+            if (rRefRange.aEnd.Col() - rRefRange.aStart.Col() < 1)
+                // Reference must be at least two columns wide.
+                return false;
+        }
+        else
+        {
+            if (rSelectedRange.aStart.Col() <= rRefRange.aStart.Col())
+                // Selected range is at the left end and the edge expansion is turned off.  No expansion.
+                return false;
+        }
 
         // Move the last column position to the right.
         SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
@@ -2658,9 +2667,18 @@ bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
             // Selected range is only partially overlapping in horizontal direction. Bail out.
             return false;
 
-        if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Row() <= rRefRange.aStart.Row())
-            // Selected range is at the top end and the edge expansion is turned off.  No expansion.
-            return false;
+        if (rCxt.mrDoc.IsExpandRefs())
+        {
+            if (rRefRange.aEnd.Row() - rRefRange.aStart.Row() < 1)
+                // Reference must be at least two rows tall.
+                return false;
+        }
+        else
+        {
+            if (rSelectedRange.aStart.Row() <= rRefRange.aStart.Row())
+                // Selected range is at the top end and the edge expansion is turned off.  No expansion.
+                return false;
+        }
 
         // Move the last row position down.
         SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
@@ -2687,6 +2705,11 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co
     if (rCxt.mnColDelta > 0)
     {
         // Insert and shift right.
+
+        if (rRefRange.aEnd.Col() - rRefRange.aStart.Col() < 1)
+            // Reference must be at least two columns wide.
+            return false;
+
         if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
             // Selected range is only partially overlapping in vertical direction. Bail out.
             return false;
@@ -2702,6 +2725,10 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co
     }
     else if (rCxt.mnRowDelta > 0)
     {
+        if (rRefRange.aEnd.Row() - rRefRange.aStart.Row() < 1)
+            // Reference must be at least two rows tall.
+            return false;
+
         if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
             // Selected range is only partially overlapping in horizontal direction. Bail out.
             return false;
@@ -3830,6 +3857,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 ScToken* pToken = static_cast<const ScToken*>(*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