limit Interpret() for dirty cells only to the given row range (bsc#1197497)

ScColumn::InterpretDirtyCells() already takes a row range, and Interpret()
can take a range inside a formula group, so don't lose the information
in DirtyCellInterpreter, otherwise a whole large formula could be
interpreted when just a subset would be enough.

Change-Id: I93e5a7a212976be6fd588de6f68204cd1a271348
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133305
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 8d5a936..3c75230 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -103,13 +103,46 @@

namespace {

struct DirtyCellInterpreter
class DirtyCellInterpreter
{
public:
    void operator() (size_t, ScFormulaCell* p)
    {
        if (p->GetDirty())
        if(!p->GetDirty())
            return;
        // Interpret() takes a range in a formula group, so group those together.
        if( firstCell != nullptr && p->GetCellGroup() == p->GetCellGroup()
            && p->aPos.Row() == lastPos.Row() + 1 )
        {
            assert( p->aPos.Tab() == lastPos.Tab() && p->aPos.Col() == lastPos.Col());
            lastPos = p->aPos; // Extend range.
            return;
        }
        flushPending();
        if( !p->GetCellGroup())
        {
            p->Interpret();
            return;
        }
        firstCell = p;
        lastPos = p->aPos;

    }
    ~DirtyCellInterpreter()
    {
        flushPending();
    }
private:
    void flushPending()
    {
        if(firstCell == nullptr)
            return;
        SCROW firstRow = firstCell->GetCellGroup()->mpTopCell->aPos.Row();
        firstCell->Interpret(firstCell->aPos.Row() - firstRow, lastPos.Row() - firstRow);
        firstCell = nullptr;
    }
    ScFormulaCell* firstCell = nullptr;
    ScAddress lastPos;
};

}