Resolves: tdf#88792 do not hold a ScFormulaCell** in group area listener

... as the mdds storage segment may change when a formula cell is
inserted at a position such that two segments are merged into a new one.

Change-Id: I449a89005418aff7ea12099ea931b786959dbc3b
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 1911a95..b5b9f0c 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -361,6 +361,7 @@ public:
    void        GetFormula( SCROW nRow, OUString& rFormula ) const;
    const ScFormulaCell* GetFormulaCell( SCROW nRow ) const;
    ScFormulaCell* GetFormulaCell( SCROW nRow );
    ScFormulaCell * const * GetFormulaCellBlockAddress( SCROW nRow ) const;
    CellType    GetCellType( SCROW nRow ) const;
    SCSIZE      GetCellCount() const;
    sal_uInt32 GetWeightedCount() const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index d3fe564..4c8aea4 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -79,6 +79,7 @@ struct SetFormulaDirtyContext;
class RefMovedHint;
struct SortUndoParam;
struct ReorderParam;
class FormulaGroupAreaListener;

}

@@ -266,6 +267,7 @@ friend class ScDocumentImport;
friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
friend class sc::FormulaGroupAreaListener;

    typedef ::std::vector<ScTable*> TableContainer;
private:
diff --git a/sc/inc/grouparealistener.hxx b/sc/inc/grouparealistener.hxx
index 9fa4e3d..71de7ee 100644
--- a/sc/inc/grouparealistener.hxx
+++ b/sc/inc/grouparealistener.hxx
@@ -16,6 +16,8 @@
#include <svl/listener.hxx>

class ScFormulaCell;
class ScDocument;
class ScColumn;

namespace sc {

@@ -24,7 +26,8 @@ class BulkDataHint;
class FormulaGroupAreaListener : public SvtListener
{
    ScRange maRange;
    ScFormulaCell** mppTopCell;
    const ScColumn* mpColumn;
    SCROW mnTopCellRow;
    SCROW mnGroupLen;
    bool mbStartFixed;
    bool mbEndFixed;
@@ -33,8 +36,8 @@ class FormulaGroupAreaListener : public SvtListener

public:

    FormulaGroupAreaListener(
        const ScRange& rRange, ScFormulaCell** ppTopCell, SCROW nGroupLen, bool bStartFixed, bool bEndFixed );
    FormulaGroupAreaListener( const ScRange& rRange, const ScDocument& rDocument,
            const ScAddress& rTopCellPos, SCROW nGroupLen, bool bStartFixed, bool bEndFixed );

    virtual ~FormulaGroupAreaListener();

@@ -64,6 +67,7 @@ public:
private:
    void notifyCellChange( const SfxHint& rHint, const ScAddress& rPos );
    void notifyBulkChange( const BulkDataHint& rHint );
    const ScFormulaCell* getTopCell() const;
};

}
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index a05f5da..e6857f2 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -220,6 +220,7 @@ friend class ScDocumentImport;
friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
friend class sc::FormulaGroupAreaListener;

public:
                ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 779ed16..6afb0d5 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2708,7 +2708,7 @@ void ScColumn::SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat )
    ApplyAttr(nRow, SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat));
}

const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
ScFormulaCell * const * ScColumn::GetFormulaCellBlockAddress( SCROW nRow ) const
{
    if (!ValidRow(nRow))
        return NULL;
@@ -2722,7 +2722,13 @@ const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
        // Not a formula cell.
        return NULL;

    return sc::formula_block::at(*it->data, aPos.second);
    return &sc::formula_block::at(*it->data, aPos.second);
}

const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
{
    ScFormulaCell const * const * pp = GetFormulaCellBlockAddress( nRow );
    return pp ? *pp : NULL;
}

void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index d591870..938fd4d 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -565,7 +565,7 @@ sc::FormulaGroupAreaListener* ScFormulaCellGroup::getAreaListener(
        // Insert a new one.
        it = mpImpl->maAreaListeners.insert(
            it, aKey, new sc::FormulaGroupAreaListener(
                rRange, ppTopCell, mnLength, bStartFixed, bEndFixed));
                rRange, *(*ppTopCell)->GetDocument(), (*ppTopCell)->aPos, mnLength, bStartFixed, bEndFixed));
    }

    return it->second;
diff --git a/sc/source/core/tool/grouparealistener.cxx b/sc/source/core/tool/grouparealistener.cxx
index 7f4dad6..656c931 100644
--- a/sc/source/core/tool/grouparealistener.cxx
+++ b/sc/source/core/tool/grouparealistener.cxx
@@ -15,6 +15,8 @@
#include <column.hxx>
#include <listenerquery.hxx>
#include <listenerqueryids.hxx>
#include <document.hxx>
#include <table.hxx>

namespace sc {

@@ -69,25 +71,31 @@ public:

}

FormulaGroupAreaListener::FormulaGroupAreaListener(
    const ScRange& rRange, ScFormulaCell** ppTopCell, SCROW nGroupLen, bool bStartFixed, bool bEndFixed ) :
FormulaGroupAreaListener::FormulaGroupAreaListener( const ScRange& rRange, const ScDocument& rDocument,
        const ScAddress& rTopCellPos, SCROW nGroupLen, bool bStartFixed, bool bEndFixed ) :
    maRange(rRange),
    mppTopCell(ppTopCell),
    mpColumn(NULL),
    mnTopCellRow(rTopCellPos.Row()),
    mnGroupLen(nGroupLen),
    mbStartFixed(bStartFixed),
    mbEndFixed(bEndFixed)
{
    assert(mppTopCell); // This can't be NULL.
    const ScTable* pTab = rDocument.FetchTable( rTopCellPos.Tab());
    assert(pTab);
    mpColumn = pTab->FetchColumn( rTopCellPos.Col());
    assert(mpColumn);
    SAL_INFO( "sc.core.grouparealistener",
            "FormulaGroupAreaListener ctor this " << this <<
            " range " << maRange.Format(SCA_VALID) << " *mppTopCell " << *mppTopCell << " length " << mnGroupLen);
            " range " << maRange.Format(SCA_VALID) <<
            " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);
}

FormulaGroupAreaListener::~FormulaGroupAreaListener()
{
    SAL_INFO( "sc.core.grouparealistener",
            "FormulaGroupAreaListener dtor this " << this <<
            " range " << maRange.Format(SCA_VALID) << " *mppTopCell " << *mppTopCell << " length " << mnGroupLen);
            " range " << maRange.Format(SCA_VALID) <<
            " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);
}

ScRange FormulaGroupAreaListener::getListeningRange() const
@@ -126,7 +134,7 @@ void FormulaGroupAreaListener::Query( QueryBase& rQuery ) const
    {
        case SC_LISTENER_QUERY_FORMULA_GROUP_RANGE:
        {
            ScFormulaCell* pTop = *mppTopCell;
            const ScFormulaCell* pTop = getTopCell();
            ScRange aRange(pTop->aPos);
            aRange.aEnd.IncRow(mnGroupLen-1);
            QueryRange& rQR = static_cast<QueryRange&>(rQuery);
@@ -176,10 +184,15 @@ void FormulaGroupAreaListener::collectFormulaCells(
{
    SAL_INFO( "sc.core.grouparealistener",
            "FormulaGroupAreaListener::collectFormulaCells() this " << this <<
            " range " << maRange.Format(SCA_VALID) << " *mppTopCell " << *mppTopCell << " length " << mnGroupLen);
            " range " << maRange.Format(SCA_VALID) <<
            " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);

    ScFormulaCell** pp = mppTopCell;
    ScFormulaCell** ppEnd = pp + mnGroupLen;
    ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow);
    assert(pp);
    if (!pp)
        return;

    ScFormulaCell* const * ppEnd = pp + mnGroupLen;

    if (mbStartFixed)
    {
@@ -261,8 +274,15 @@ void FormulaGroupAreaListener::collectFormulaCells(

ScAddress FormulaGroupAreaListener::getTopCellPos() const
{
    const ScFormulaCell& rFC = **mppTopCell;
    return rFC.aPos;
    const ScFormulaCell* p = getTopCell();
    return p ? p->aPos : ScAddress();
}

const ScFormulaCell* FormulaGroupAreaListener::getTopCell() const
{
    const ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow);
    assert(pp);
    return pp ? *pp : NULL;
}

const ScRange& FormulaGroupAreaListener::getRange() const