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
This commit is contained in:
Eike Rathke 2015-02-05 11:32:13 +01:00
parent de68bb8514
commit 47230a036f
7 changed files with 52 additions and 18 deletions

View file

@ -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;

View file

@ -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:

View file

@ -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;
};
}

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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