summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Francis <dennisfrancis.in@gmail.com>2016-04-15 21:43:42 +0530
committerEike Rathke <erack@redhat.com>2016-11-10 15:11:28 +0000
commit06d3294502413a231e5c5265609862c7f67a2f2b (patch)
tree10ae793388158381a933632457d0eb17726586b9
parent5e416099f088a2f8a8980e08e3d5b731da0a6d9c (diff)
Refactor ScAttrArray for tdf#50916
For a default column, now ScAttrArray does not store the default format. So the case of default pattern from 0 to MAXROW is represented as nCount = 0 and pData = nullptr in ScAttrArray. A new ScAttrArray object (aNextColAttrArray) is introduced as a member of ScTable. This is used to store the formatting of *unallocated* columns (whose indices are from aCol.size() to MAXCOL). In next patches for this bug, I plan to refactor table*.cxx functions related to formatting such that : 1) In formatting setter functions, if colspan of the input range spans the colrange(aCol.size() to MAXCOL) then instead of allocating columns, apply that formatting to aNextColAttrArray. 2) In formatting getter (const) functions, if requested colspan has some intersection with the colrange(aCol.size() to MAXCOL) then use the formatting info stored in aNextColAttrArray to calculate the formatting of the input range. 3) In general setter (non-const) functions if we really need to allocate new columns (example, when data is entered), use the formatting info stored in aNextColAttrArray to create pAttrArray of the new column. Change-Id: Ieb56f853209b396d92fdb2c27e39361703576423 Reviewed-on: https://gerrit.libreoffice.org/27828 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r--sc/inc/attarray.hxx38
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/source/core/data/attarray.cxx423
-rw-r--r--sc/source/core/data/column.cxx22
-rw-r--r--sc/source/core/data/column2.cxx2
-rw-r--r--sc/source/core/data/column3.cxx4
-rw-r--r--sc/source/core/data/dociter.cxx14
-rw-r--r--sc/source/core/data/document.cxx27
-rw-r--r--sc/source/core/data/fillinfo.cxx18
-rw-r--r--sc/source/core/data/table1.cxx5
-rw-r--r--sc/source/core/data/table2.cxx7
12 files changed, 477 insertions, 89 deletions
diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index 2b440402e0d0..49626ea9e124 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -100,12 +100,13 @@ friend class ScHorizontalAttrIterator;
void RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
const ScPatternAttr* pPattern, ScEditDataArray* pDataArray );
+ void SetDefaultIfNotInit( SCSIZE nNeeded = 1 );
ScAttrArray(const ScAttrArray&) = delete;
ScAttrArray& operator=(const ScAttrArray&) = delete;
public:
- ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc );
+ ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc, ScAttrArray* pNextColAttrArray = nullptr, bool bCreateEmpty = false );
~ScAttrArray();
void SetTab(SCTAB nNewTab) { nTab = nNewTab; }
@@ -205,23 +206,30 @@ public:
class ScAttrIterator
{
const ScAttrArray* pArray;
+ const ScPatternAttr* pDefPattern;
SCSIZE nPos;
SCROW nRow;
SCROW nEndRow;
public:
- inline ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd );
+ inline ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern );
inline const ScPatternAttr* Next( SCROW& rTop, SCROW& rBottom );
inline const ScPatternAttr* Resync( SCROW nRow, SCROW& rTop, SCROW& rBottom );
SCROW GetNextRow() const { return nRow; }
};
-inline ScAttrIterator::ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd ) :
+inline ScAttrIterator::ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern ) :
pArray( pNewArray ),
+ pDefPattern( pDefaultPattern ),
nRow( nStart ),
nEndRow( nEnd )
{
- if ( nStart > 0 )
- pArray->Search( nStart, nPos );
+ if ( pArray->nCount )
+ {
+ if ( nStart > 0 )
+ pArray->Search( nStart, nPos );
+ else
+ nPos = 0;
+ }
else
nPos = 0;
}
@@ -229,6 +237,21 @@ inline ScAttrIterator::ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStar
inline const ScPatternAttr* ScAttrIterator::Next( SCROW& rTop, SCROW& rBottom )
{
const ScPatternAttr* pRet;
+ if ( !pArray->nCount )
+ {
+ if ( !nPos )
+ {
+ ++nPos;
+ if ( nRow > MAXROW )
+ return nullptr;
+ rTop = nRow;
+ rBottom = std::min( nEndRow, MAXROW );
+ nRow = rBottom + 1;
+ return pDefPattern;
+ }
+ return nullptr;
+ }
+
if ( nPos < pArray->nCount && nRow <= nEndRow )
{
rTop = nRow;
@@ -245,6 +268,11 @@ inline const ScPatternAttr* ScAttrIterator::Next( SCROW& rTop, SCROW& rBottom )
inline const ScPatternAttr* ScAttrIterator::Resync( SCROW nRowP, SCROW& rTop, SCROW& rBottom )
{
nRow = nRowP;
+ if ( !pArray->nCount )
+ {
+ nPos = 0;
+ return Next( rTop, rBottom );
+ }
// Chances are high that the pattern changed on nRowP introduced a span
// starting right there. Assume that Next() was called so nPos already
// advanced. Another high chance is that the change extended a previous or
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 345dea26004f..c5940b0926db 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -186,7 +186,7 @@ public:
ScColumn();
~ScColumn();
- void Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc);
+ void Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc, bool bEmptyAttrArray = false);
ScDocument& GetDoc() { return *pDocument;}
const ScDocument& GetDoc() const { return *pDocument;}
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 350dcbd4c1b5..aab14535441b 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -25,6 +25,7 @@
#include <tools/gen.hxx>
#include <tools/color.hxx>
#include <com/sun/star/uno/Sequence.hxx>
+#include "attarray.hxx"
#include "column.hxx"
#include "colcontainer.hxx"
#include "sortparam.hxx"
@@ -206,7 +207,10 @@ private:
bool mbPageBreaksValid:1;
bool mbForceBreaks:1;
+ ScAttrArray aNextColAttrArray;
+
friend class ScDocument; // for FillInfo
+friend class ScColumn;
friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator;
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 2afe4c3d13c1..c402ddebe454 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -49,16 +49,40 @@
using ::editeng::SvxBorderLine;
-ScAttrArray::ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc ) :
+ScAttrArray::ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc, ScAttrArray* pNextColAttrArray, bool bCreateEmpty ) :
nCol( nNewCol ),
nTab( nNewTab ),
pDocument( pDoc ),
- nCount(1),
- nLimit(1),
- pData(new ScAttrEntry[1])
+ nCount(0),
+ nLimit(0),
+ pData(nullptr)
{
- pData[0].nRow = MAXROW;
- pData[0].pPattern = pDocument->GetDefPattern(); // no put
+ if ( nCol != -1 && !bCreateEmpty && pNextColAttrArray )
+ {
+ nCount = pNextColAttrArray->nCount;
+ nLimit = pNextColAttrArray->nCount;
+ if ( nCount )
+ {
+ bool bNumFormatChanged;
+ ScAddress aAdrStart( nCol, 0, nTab );
+ ScAddress aAdrEnd( nCol, 0, nTab );
+ pData = new ScAttrEntry[nCount];
+ for ( size_t nIdx = 0; nIdx < nCount; ++nIdx )
+ {
+ pData[nIdx].nRow = pNextColAttrArray->pData[nIdx].nRow;
+ ScPatternAttr aNewPattern( *(pNextColAttrArray->pData[nIdx].pPattern) );
+ pData[nIdx].pPattern = static_cast<const ScPatternAttr*>( &pDocument->GetPool()->Put( aNewPattern ) );
+ bNumFormatChanged = false;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ pData[nIdx].pPattern->GetItemSet(), pDocument->GetDefPattern()->GetItemSet() ) )
+ {
+ aAdrStart.SetRow( nIdx ? pData[nIdx-1].nRow+1 : 0 );
+ aAdrEnd.SetRow( pData[nIdx].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ }
+ }
+ }
+ }
}
ScAttrArray::~ScAttrArray()
@@ -102,6 +126,19 @@ void ScAttrArray::TestData() const
}
#endif
+void ScAttrArray::SetDefaultIfNotInit( SCSIZE nNeeded )
+{
+ if ( pData )
+ return;
+
+ SCSIZE nNewLimit = ( SC_ATTRARRAY_DELTA > nNeeded ) ? SC_ATTRARRAY_DELTA : nNeeded;
+ pData = new ScAttrEntry[nNewLimit];
+ pData[0].nRow = MAXROW;
+ pData[0].pPattern = pDocument->GetDefPattern(); // no put
+ nCount = 1;
+ nLimit = nNewLimit;
+}
+
void ScAttrArray::Reset( const ScPatternAttr* pPattern )
{
ScDocumentPool* pDocPool = pDocument->GetPool();
@@ -112,13 +149,16 @@ void ScAttrArray::Reset( const ScPatternAttr* pPattern )
{
// ensure that attributing changes text width of cell
const ScPatternAttr* pOldPattern = pData[i].pPattern;
- bool bNumFormatChanged;
- if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
- pPattern->GetItemSet(), pOldPattern->GetItemSet() ) )
+ if ( nCol != -1 )
{
- aAdrStart.SetRow( i ? pData[i-1].nRow+1 : 0 );
- aAdrEnd .SetRow( pData[i].nRow );
- pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ bool bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ pPattern->GetItemSet(), pOldPattern->GetItemSet() ) )
+ {
+ aAdrStart.SetRow( i ? pData[i-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[i].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ }
}
pDocPool->Remove(*pOldPattern);
}
@@ -203,6 +243,12 @@ bool ScAttrArray::Search( SCROW nRow, SCSIZE& nIndex ) const
const ScPatternAttr* ScAttrArray::GetPattern( SCROW nRow ) const
{
+ if ( !pData )
+ {
+ if ( !ValidRow( nRow ) )
+ return nullptr;
+ return pDocument->GetDefPattern();
+ }
SCSIZE i;
if (Search( nRow, i ))
return pData[i].pPattern;
@@ -213,6 +259,14 @@ const ScPatternAttr* ScAttrArray::GetPattern( SCROW nRow ) const
const ScPatternAttr* ScAttrArray::GetPatternRange( SCROW& rStartRow,
SCROW& rEndRow, SCROW nRow ) const
{
+ if ( !pData )
+ {
+ if ( !ValidRow( nRow ) )
+ return nullptr;
+ rStartRow = 0;
+ rEndRow = MAXROW;
+ return pDocument->GetDefPattern();
+ }
SCSIZE nIndex;
if ( Search( nRow, nIndex ) )
{
@@ -338,6 +392,7 @@ void ScAttrArray::SetPattern( SCROW nRow, const ScPatternAttr* pPattern, bool bP
void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
const ScPatternAttr* pPattern, ScEditDataArray* pDataArray )
{
+ assert( nCol != -1 );
for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
{
ScAddress aPos(nCol, nRow, nTab);
@@ -363,7 +418,21 @@ void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
bool ScAttrArray::Reserve( SCSIZE nReserve )
{
- if ( nLimit < nReserve )
+ if ( !pData && nReserve )
+ {
+ if( ScAttrEntry* pNewData = new (std::nothrow) ScAttrEntry[nReserve] )
+ {
+ nLimit = nReserve;
+ nCount = 1;
+ pData = pNewData;
+ pData[0].nRow = MAXROW;
+ pData[0].pPattern = pDocument->GetDefPattern(); // no put
+ return true;
+ }
+ else
+ return false;
+ }
+ else if ( nLimit < nReserve )
{
if( ScAttrEntry* pNewData = new (std::nothrow) ScAttrEntry[nReserve] )
{
@@ -393,6 +462,7 @@ void ScAttrArray::SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPattern
else
{
SCSIZE nNeeded = nCount + 2;
+ SetDefaultIfNotInit( nNeeded );
if ( nLimit < nNeeded )
{
nLimit += SC_ATTRARRAY_DELTA;
@@ -428,16 +498,18 @@ void ScAttrArray::SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPattern
// otherwise, conditional formats need to be reset or deleted
while ( ns <= nEndRow )
{
- const SfxItemSet& rNewSet = pPattern->GetItemSet();
- const SfxItemSet& rOldSet = pData[nx].pPattern->GetItemSet();
-
- bool bNumFormatChanged;
- if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
- rNewSet, rOldSet ) )
+ if ( nCol != -1 )
{
- aAdrStart.SetRow( std::max(nStartRow,ns) );
- aAdrEnd .SetRow( std::min(nEndRow,pData[nx].nRow) );
- pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ const SfxItemSet& rNewSet = pPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pData[nx].pPattern->GetItemSet();
+ bool bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( std::max(nStartRow,ns) );
+ aAdrEnd .SetRow( std::min(nEndRow,pData[nx].nRow) );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ }
}
ns = pData[nx].nRow + 1;
nx++;
@@ -544,7 +616,7 @@ void ScAttrArray::SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPattern
// Remove character attributes from these cells if the pattern
// is applied during normal session.
- if (pDataArray)
+ if (pDataArray && nCol != -1)
RemoveCellCharAttribs(nStartRow, nEndRow, pPattern, pDataArray);
nCount++;
@@ -564,6 +636,7 @@ void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, ScStyleSheet*
{
if (ValidRow(nStartRow) && ValidRow(nEndRow))
{
+ SetDefaultIfNotInit();
SCSIZE nPos;
SCROW nStart=0;
if (!Search( nStartRow, nPos ))
@@ -599,18 +672,21 @@ void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, ScStyleSheet*
}
else
{
- // ensure attributing changes text width of cell; otherwise
- // there aren't (yet) template format changes
- const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
- const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
-
- bool bNumFormatChanged;
- if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
- rNewSet, rOldSet ) )
+ if ( nCol != -1 )
{
- aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
- aAdrEnd .SetRow( pData[nPos].nRow );
- pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ // ensure attributing changes text width of cell; otherwise
+ // there aren't (yet) template format changes
+ const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
+
+ bool bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[nPos].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ }
}
pDocument->GetPool()->Remove(*pData[nPos].pPattern);
@@ -658,6 +734,7 @@ void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow,
{
SCSIZE nPos;
SCROW nStart=0;
+ SetDefaultIfNotInit();
if (!Search( nStartRow, nPos ))
{
OSL_FAIL("Search failure");
@@ -786,6 +863,7 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, SfxItemPoolCac
{
SCSIZE nPos;
SCROW nStart=0;
+ SetDefaultIfNotInit();
if (!Search( nStartRow, nPos ))
{
OSL_FAIL("Search Failure");
@@ -814,18 +892,21 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, SfxItemPoolCac
}
else
{
- // ensure attributing changes text-width of cell
+ if ( nCol != -1 )
+ {
+ // ensure attributing changes text-width of cell
- const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
- const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
+ const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
- bool bNumFormatChanged;
- if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
- rNewSet, rOldSet ) )
- {
- aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
- aAdrEnd .SetRow( pData[nPos].nRow );
- pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ bool bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[nPos].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+ }
}
pDocument->GetPool()->Remove(*pData[nPos].pPattern);
@@ -906,9 +987,9 @@ void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW nEndRow,
{
if (ValidRow(nStartRow) && ValidRow(nEndRow))
{
- SCSIZE nPos;
+ SCSIZE nPos = 0;
SCROW nStart=0;
- if (!Search( nStartRow, nPos ))
+ if ( pData && !Search( nStartRow, nPos ) )
{
OSL_FAIL("Search failure");
return;
@@ -917,7 +998,11 @@ void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW nEndRow,
do
{
// similar patterns must not be repeated
- const ScPatternAttr* pPattern = pData[nPos].pPattern;
+ const ScPatternAttr* pPattern = nullptr;
+ if ( pData )
+ pPattern = pData[nPos].pPattern;
+ else
+ pPattern = pDocument->GetDefPattern();
if ( pPattern != rState.pOld1 && pPattern != rState.pOld2 )
{
const SfxItemSet& rThisSet = pPattern->GetItemSet();
@@ -941,7 +1026,10 @@ void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW nEndRow,
rState.pOld1 = pPattern;
}
- nStart = pData[nPos].nRow + 1;
+ if ( pData )
+ nStart = pData[nPos].nRow + 1;
+ else
+ nStart = MAXROW + 1;
++nPos;
}
while (nStart <= nEndRow);
@@ -1055,7 +1143,7 @@ void ScAttrArray::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLine
pPattern = GetPattern( nStartRow );
lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true, 0 );
}
- else
+ else if ( pData ) // non-default pattern
{
pPattern = GetPattern( nStartRow );
lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true,
@@ -1076,6 +1164,10 @@ void ScAttrArray::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLine
pPattern = GetPattern( nEndRow );
lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, false, 0 );
}
+ else
+ {
+ lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pDocument->GetDefPattern(), bLeft, nDistRight, true, 0 );
+ }
}
// apply border
@@ -1157,7 +1249,7 @@ void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInf
{
if (nStartRow == nEndRow)
ApplyFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight, true, 0 );
- else
+ else if ( pData )
{
ApplyFrame( pLineOuter, pLineInner, nStartRow, nStartRow, bLeft, nDistRight,
true, nEndRow-nStartRow );
@@ -1188,12 +1280,19 @@ void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInf
ApplyFrame( pLineOuter, pLineInner, nEndRow, nEndRow, bLeft, nDistRight, false, 0 );
}
+ else
+ {
+ ApplyFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight, true, 0 );
+ }
}
// Test if field contains specific attribute
bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const
{
+ if ( !pData )
+ return false;
+
SCSIZE nStartIndex;
SCSIZE nEndIndex;
Search( nRow1, nStartIndex );
@@ -1255,7 +1354,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) cons
bool bContainsCondFormat =
!static_cast<const ScCondFormatItem&>(pPattern->GetItem( ATTR_CONDITIONAL )).GetCondFormatData().empty();
- if ( bContainsCondFormat )
+ if ( bContainsCondFormat && nCol != -1 ) // pDocument->GetCondResult() is valid only for real columns.
{
SCROW nRowStartCond = std::max<SCROW>( nRow1, i ? pData[i-1].nRow + 1: 0 );
SCROW nRowEndCond = std::min<SCROW>( nRow2, pData[i].nRow );
@@ -1340,12 +1439,17 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) cons
bool ScAttrArray::IsMerged( SCROW nRow ) const
{
- SCSIZE nIndex;
- Search(nRow, nIndex);
- const ScMergeAttr& rItem =
- static_cast<const ScMergeAttr&>(pData[nIndex].pPattern->GetItem(ATTR_MERGE));
+ if ( pData )
+ {
+ SCSIZE nIndex;
+ Search(nRow, nIndex);
+ const ScMergeAttr& rItem =
+ static_cast<const ScMergeAttr&>(pData[nIndex].pPattern->GetItem(ATTR_MERGE));
+
+ return rItem.IsMerged();
+ }
- return rItem.IsMerged();
+ return static_cast<const ScMergeAttr&>(pDocument->GetDefPattern()->GetItem(ATTR_MERGE)).IsMerged();
}
/**
@@ -1355,6 +1459,8 @@ bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
SCCOL& rPaintCol, SCROW& rPaintRow,
bool bRefresh )
{
+ assert( nCol != -1 );
+ SetDefaultIfNotInit();
const ScPatternAttr* pPattern;
const ScMergeAttr* pItem;
SCSIZE nStartIndex;
@@ -1404,6 +1510,8 @@ bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
void ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW nEndRow)
{
+ assert( nCol != -1 );
+ SetDefaultIfNotInit();
const ScPatternAttr* pPattern;
const ScMergeAttr* pItem;
SCSIZE nIndex;
@@ -1461,6 +1569,7 @@ void ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW nEndRow)
void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
const ScPatternAttr* pWantedPattern, bool bDefault )
{
+ SetDefaultIfNotInit();
const ScPatternAttr* pOldPattern;
const ScMergeFlagAttr* pItem;
@@ -1515,6 +1624,7 @@ void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
bool ScAttrArray::ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
{
+ SetDefaultIfNotInit();
const ScPatternAttr* pOldPattern;
ScMF nOldValue;
@@ -1551,6 +1661,7 @@ bool ScAttrArray::ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
bool ScAttrArray::RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
{
+ SetDefaultIfNotInit();
const ScPatternAttr* pOldPattern;
ScMF nOldValue;
@@ -1587,6 +1698,7 @@ bool ScAttrArray::RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
void ScAttrArray::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
{
+ SetDefaultIfNotInit();
SCSIZE nIndex;
SCROW nRow;
SCROW nThisRow;
@@ -1616,6 +1728,7 @@ void ScAttrArray::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16*
void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement )
{
+ SetDefaultIfNotInit();
SCSIZE nIndex;
Search( nStartRow, nIndex );
SCROW nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
@@ -1680,6 +1793,14 @@ SCsROW ScAttrArray::GetNextUnprotected( SCsROW nRow, bool bUp ) const
long nRet = nRow;
if (ValidRow(nRow))
{
+ if ( !pData )
+ {
+ if ( bUp )
+ return -1;
+ else
+ return MAXROW+1;
+ }
+
SCSIZE nIndex;
Search(nRow, nIndex);
while (static_cast<const ScProtectionAttr&>(pData[nIndex].pPattern->
@@ -1706,6 +1827,7 @@ SCsROW ScAttrArray::GetNextUnprotected( SCsROW nRow, bool bUp ) const
void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
{
+ SetDefaultIfNotInit();
SCROW nStart = 0;
SCSIZE nPos = 0;
while (nPos < nCount)
@@ -1742,6 +1864,18 @@ void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBo
bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const
{
+ if ( !pData )
+ {
+ const ScStyleSheet* pStyle = pDocument->GetDefPattern()->GetStyleSheet();
+ if ( pStyle )
+ {
+ pStyle->SetUsage( ScStyleSheet::USED );
+ if ( pStyle == &rStyle )
+ return true;
+ }
+ return false;
+ }
+
bool bIsUsed = false;
SCSIZE nPos = 0;
@@ -1764,6 +1898,9 @@ bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const
bool ScAttrArray::IsEmpty() const
{
+ if ( !pData )
+ return true;
+
if (nCount == 1)
{
if ( pData[0].pPattern != pDocument->GetDefPattern() )
@@ -1777,6 +1914,9 @@ bool ScAttrArray::IsEmpty() const
bool ScAttrArray::GetFirstVisibleAttr( SCROW& rFirstRow ) const
{
+ if ( !pData )
+ return false;
+
OSL_ENSURE( nCount, "nCount == 0" );
bool bFound = false;
@@ -1812,6 +1952,12 @@ const SCROW SC_VISATTR_STOP = 84;
bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData ) const
{
+ if ( !pData )
+ {
+ rLastRow = nLastData;
+ return false;
+ }
+
OSL_ENSURE( nCount, "nCount == 0" );
// #i30830# changed behavior:
@@ -1868,6 +2014,9 @@ bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData ) const
bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
{
+ if ( !pData )
+ return pDocument->GetDefPattern()->IsVisible();
+
SCSIZE nIndex;
Search( nStartRow, nIndex );
SCROW nThisStart = nStartRow;
@@ -1887,6 +2036,50 @@ bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
bool ScAttrArray::IsVisibleEqual( const ScAttrArray& rOther,
SCROW nStartRow, SCROW nEndRow ) const
{
+ if ( !pData && !rOther.pData )
+ {
+ const ScPatternAttr* pDefPattern1 = pDocument->GetDefPattern();
+ const ScPatternAttr* pDefPattern2 = rOther.pDocument->GetDefPattern();
+ return ( pDefPattern1 == pDefPattern2 || pDefPattern1->IsVisibleEqual( *pDefPattern2 ) );
+ }
+
+ {
+ const ScAttrArray* pNonDefault = nullptr;
+ const ScPatternAttr* pDefPattern = nullptr;
+ bool bDefNonDefCase = false;
+ if ( !pData && rOther.pData )
+ {
+ pNonDefault = &rOther;
+ pDefPattern = pDocument->GetDefPattern();
+ bDefNonDefCase = true;
+ }
+ else if ( pData && !rOther.pData )
+ {
+ pNonDefault = this;
+ pDefPattern = rOther.pDocument->GetDefPattern();
+ bDefNonDefCase = true;
+ }
+
+ if ( bDefNonDefCase )
+ {
+ bool bEqual = true;
+ SCSIZE nPos = 0;
+ if ( nStartRow > 0 )
+ pNonDefault->Search( nStartRow, nPos );
+
+ while ( nPos < pNonDefault->nCount && bEqual )
+ {
+ const ScPatternAttr* pNonDefPattern = pNonDefault->pData[nPos].pPattern;
+ bEqual = ( pNonDefPattern == pDefPattern ||
+ pNonDefPattern->IsVisibleEqual( *pDefPattern ) );
+
+ if ( pNonDefault->pData[nPos].nRow >= nEndRow ) break;
+ ++nPos;
+ }
+ return bEqual;
+ }
+ }
+
bool bEqual = true;
SCSIZE nThisPos = 0;
SCSIZE nOtherPos = 0;
@@ -1923,6 +2116,48 @@ bool ScAttrArray::IsVisibleEqual( const ScAttrArray& rOther,
bool ScAttrArray::IsAllEqual( const ScAttrArray& rOther, SCROW nStartRow, SCROW nEndRow ) const
{
// summarised with IsVisibleEqual
+ if ( !pData && !rOther.pData )
+ {
+ const ScPatternAttr* pDefPattern1 = pDocument->GetDefPattern();
+ const ScPatternAttr* pDefPattern2 = rOther.pDocument->GetDefPattern();
+ return ( pDefPattern1 == pDefPattern2 );
+ }
+
+ {
+ const ScAttrArray* pNonDefault = nullptr;
+ const ScPatternAttr* pDefPattern = nullptr;
+ bool bDefNonDefCase = false;
+ if ( !pData && rOther.pData )
+ {
+ pNonDefault = &rOther;
+ pDefPattern = pDocument->GetDefPattern();
+ bDefNonDefCase = true;
+ }
+ else if ( pData && !rOther.pData )
+ {
+ pNonDefault = this;
+ pDefPattern = rOther.pDocument->GetDefPattern();
+ bDefNonDefCase = true;
+ }
+
+ if ( bDefNonDefCase )
+ {
+ bool bEqual = true;
+ SCSIZE nPos = 0;
+ if ( nStartRow > 0 )
+ pNonDefault->Search( nStartRow, nPos );
+
+ while ( nPos < pNonDefault->nCount && bEqual )
+ {
+ const ScPatternAttr* pNonDefPattern = pNonDefault->pData[nPos].pPattern;
+ bEqual = ( pNonDefPattern == pDefPattern );
+
+ if ( pNonDefault->pData[nPos].nRow >= nEndRow ) break;
+ ++nPos;
+ }
+ return bEqual;
+ }
+ }
bool bEqual = true;
SCSIZE nThisPos = 0;
@@ -1989,6 +2224,10 @@ bool ScAttrArray::TestInsertRow( SCSIZE nSize ) const
// MAXROW + 1 - nSize = 1st row pushed out
+ if ( !pData )
+ return !static_cast<const ScMergeFlagAttr&>(pDocument->GetDefPattern()->
+ GetItem(ATTR_MERGE_FLAG)).IsVerOverlapped();
+
SCSIZE nFirstLost = nCount-1;
while ( nFirstLost && pData[nFirstLost-1].nRow >= sal::static_int_cast<SCROW>(MAXROW + 1 - nSize) )
--nFirstLost;
@@ -2002,6 +2241,7 @@ bool ScAttrArray::TestInsertRow( SCSIZE nSize ) const
void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize )
{
+ SetDefaultIfNotInit();
if (!pData)
return;
@@ -2013,6 +2253,8 @@ void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize )
bool bDoMerge = static_cast<const ScMergeAttr&>( pData[nIndex].pPattern->GetItem(ATTR_MERGE)).IsMerged();
+ assert( !bDoMerge || nCol != -1 );
+
SCSIZE nRemove = 0;
SCSIZE i;
for (i = nIndex; i < nCount-1; i++)
@@ -2050,6 +2292,7 @@ void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize )
void ScAttrArray::DeleteRow( SCROW nStartRow, SCSIZE nSize )
{
+ SetDefaultIfNotInit();
bool bFirst=true;
SCSIZE nStartIndex = 0;
SCSIZE nEndIndex = 0;
@@ -2097,6 +2340,7 @@ void ScAttrArray::DeleteRow( SCROW nStartRow, SCSIZE nSize )
void ScAttrArray::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex )
{
+ SetDefaultIfNotInit();
ScDocumentPool* pDocPool = pDocument->GetPool();
for (SCSIZE i = nStartIndex; i <= nEndIndex; i++)
pDocPool->Remove(*pData[i].pPattern);
@@ -2107,7 +2351,9 @@ void ScAttrArray::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex )
void ScAttrArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
{
- RemoveAreaMerge( nStartRow, nEndRow ); // remove from combined flags
+ SetDefaultIfNotInit();
+ if ( nCol != -1 )
+ RemoveAreaMerge( nStartRow, nEndRow ); // remove from combined flags
if ( !HasAttrib( nStartRow, nEndRow, HasAttrFlags::Overlapped | HasAttrFlags::AutoFilter) )
SetPatternArea( nStartRow, nEndRow, pDocument->GetDefPattern() );
@@ -2117,6 +2363,7 @@ void ScAttrArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
void ScAttrArray::DeleteHardAttr(SCROW nStartRow, SCROW nEndRow)
{
+ SetDefaultIfNotInit();
const ScPatternAttr* pDefPattern = pDocument->GetDefPattern();
SCSIZE nIndex;
@@ -2160,6 +2407,7 @@ void ScAttrArray::DeleteHardAttr(SCROW nStartRow, SCROW nEndRow)
*/
void ScAttrArray::MoveTo(SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray)
{
+ SetDefaultIfNotInit();
SCROW nStart = nStartRow;
for (SCSIZE i = 0; i < nCount; i++)
{
@@ -2190,6 +2438,14 @@ void ScAttrArray::CopyArea(
ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
bool bSamePool = (pSourceDocPool==pDestDocPool);
+ if ( !pData )
+ {
+ const ScPatternAttr* pNewPattern = static_cast<const ScPatternAttr*>(
+ &pDestDocPool->GetDefaultItem( ATTR_PATTERN ));
+ rAttrArray.SetPatternArea(nDestStart, nDestEnd, pNewPattern);
+ return;
+ }
+
for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
{
if (pData[i].nRow >= nStartRow)
@@ -2262,6 +2518,20 @@ void ScAttrArray::CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, long nDy, ScAttr
ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
bool bSamePool = (pSourceDocPool==pDestDocPool);
+ if ( !pData )
+ {
+ const ScPatternAttr* pNewPattern;
+ if (bSamePool)
+ pNewPattern = static_cast<const ScPatternAttr*>(
+ &pDestDocPool->Put(*pDocument->GetDefPattern()));
+ else
+ pNewPattern = pDocument->GetDefPattern()->PutInPool( rAttrArray.pDocument, pDocument );
+
+ rAttrArray.SetPatternAreaSafe(nDestStart, nDestEnd, pNewPattern, false);
+ return;
+ }
+
+
for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
{
if (pData[i].nRow >= nStartRow)
@@ -2297,6 +2567,15 @@ SCsROW ScAttrArray::SearchStyle(
return nRow;
}
+ if ( !pData )
+ {
+ if (pDocument->GetDefPattern()->GetStyleSheet() == pSearchStyle)
+ return nRow;
+
+ nRow = bUp ? -1 : MAXROW + 1;
+ return nRow;
+ }
+
SCSIZE nIndex;
Search(nRow, nIndex);
const ScPatternAttr* pPattern = pData[nIndex].pPattern;
@@ -2354,6 +2633,33 @@ bool ScAttrArray::SearchStyleRange(
SCsROW nStartRow = SearchStyle( rRow, pSearchStyle, bUp, pMarkArray );
if (ValidRow(nStartRow))
{
+ if ( !pData )
+ {
+ rRow = nStartRow;
+ if (bUp)
+ {
+ rEndRow = 0;
+ if (pMarkArray)
+ {
+ SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, true );
+ if (nMarkEnd>rEndRow)
+ rEndRow = nMarkEnd;
+ }
+ }
+ else
+ {
+ rEndRow = MAXROW;
+ if (pMarkArray)
+ {
+ SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, false );
+ if (nMarkEnd<rEndRow)
+ rEndRow = nMarkEnd;
+ }
+ }
+
+ return true;
+ }
+
SCSIZE nIndex;
Search(nStartRow,nIndex);
@@ -2390,6 +2696,9 @@ bool ScAttrArray::SearchStyleRange(
SCSIZE ScAttrArray::Count( SCROW nStartRow, SCROW nEndRow ) const
{
+ if ( !pData )
+ return 1;
+
SCSIZE nIndex1, nIndex2;
if( !Search( nStartRow, nIndex1 ) )
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index e8a537a15a59..7ffafdabb92b 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -21,6 +21,7 @@
#include "scitems.hxx"
#include "formulacell.hxx"
#include "document.hxx"
+#include "table.hxx"
#include "docpool.hxx"
#include "attarray.hxx"
#include "patattr.hxx"
@@ -103,12 +104,15 @@ ScColumn::~ScColumn()
delete pAttrArray;
}
-void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
+void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc, bool bEmptyAttrArray)
{
nCol = nNewCol;
nTab = nNewTab;
pDocument = pDoc;
- pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
+ if ( !bEmptyAttrArray )
+ pAttrArray = new ScAttrArray( nCol, nTab, pDocument, &pDocument->maTabs[nTab]->aNextColAttrArray, bEmptyAttrArray );
+ else
+ pAttrArray = new ScAttrArray( nCol, nTab, pDocument, nullptr, true );
}
SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
@@ -385,7 +389,7 @@ const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRo
const ScPatternAttr* pMaxPattern = nullptr;
size_t nMaxCount = 0;
- ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
+ ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow, pDocument->GetDefPattern() );
const ScPatternAttr* pPattern;
SCROW nAttrRow1 = 0, nAttrRow2 = 0;
@@ -613,7 +617,7 @@ const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool&
SCROW nBottom;
while (bEqual && aMultiIter.Next( nTop, nBottom ))
{
- ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
+ ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom, pDocument->GetDefPattern() );
SCROW nRow;
SCROW nDummy;
const ScPatternAttr* pPattern;
@@ -639,7 +643,7 @@ const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRo
const ScStyleSheet* pStyle = nullptr;
const ScStyleSheet* pNewStyle;
- ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
+ ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2, pDocument->GetDefPattern() );
SCROW nRow;
SCROW nDummy;
const ScPatternAttr* pPattern;
@@ -1752,7 +1756,7 @@ void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
{
// This is the scenario table, the data is copied into it
- ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW, pDocument->GetDefPattern() );
SCROW nStart = -1, nEnd = -1;
const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
while (pPattern)
@@ -1780,7 +1784,7 @@ void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
{
// This is the scenario table, the data is copied to the other
- ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW, pDocument->GetDefPattern() );
SCROW nStart = -1, nEnd = -1;
const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
while (pPattern)
@@ -1805,7 +1809,7 @@ void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
{
bool bOk = true;
- ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW, pDocument->GetDefPattern() );
SCROW nStart = 0, nEnd = 0;
const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
while (pPattern && bOk)
@@ -1823,7 +1827,7 @@ void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
{
ScRange aRange( nCol, 0, nTab );
- ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW, pDocument->GetDefPattern() );
SCROW nStart = -1, nEnd = -1;
const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
while (pPattern)
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 581607e9475d..b0135692b4b5 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -786,7 +786,7 @@ void ScColumn::GetOptimalHeight(
sc::RowHeightContext& rCxt, SCROW nStartRow, SCROW nEndRow, sal_uInt16 nMinHeight, SCROW nMinStart )
{
ScFlatUInt16RowSegments& rHeights = rCxt.getHeightArray();
- ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow );
+ ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow, pDocument->GetDefPattern() );
SCROW nStart = -1;
SCROW nEnd = -1;
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index b8042604ad7b..8a81dcb47a16 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1545,7 +1545,7 @@ void ScColumn::MixData(
ScAttrIterator* ScColumn::CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const
{
- return new ScAttrIterator( pAttrArray, nStartRow, nEndRow );
+ return new ScAttrIterator( pAttrArray, nStartRow, nEndRow, pDocument->GetDefPattern() );
}
namespace {
@@ -2347,7 +2347,7 @@ void ScColumn::RemoveProtected( SCROW nStartRow, SCROW nEndRow )
FormulaToValueHandler aFunc;
sc::CellStoreType::const_iterator itPos = maCells.begin();
- ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
+ ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow, pDocument->GetDefPattern() );
SCROW nTop = -1;
SCROW nBottom = -1;
const ScPatternAttr* pPattern = aAttrIter.Next( nTop, nBottom );
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index a682a5ea2a81..8bbb121de8fe 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -2300,14 +2300,24 @@ void ScHorizontalAttrIterator::InitForNextRow(bool bInitialization)
SCSIZE nIndex;
if (bInitialization)
{
- pArray->Search( nStartRow, nIndex );
+ if ( pArray->nCount )
+ pArray->Search( nStartRow, nIndex );
+ else
+ nIndex = 0;
pIndices[nPos] = nIndex;
pHorizEnd[nPos] = MAXCOL+1; // only for OSL_ENSURE
}
else
nIndex = ++pIndices[nPos];
- if ( nIndex < pArray->nCount )
+ if ( !nIndex && !pArray->nCount )
+ {
+ SCROW nThisEnd = MAXROW;
+ pNextEnd[nPos] = nThisEnd;
+ OSL_ENSURE( pNextEnd[nPos] >= nRow, "Sequence out of order" );
+ ppPatterns[nPos] = nullptr;
+ }
+ else if ( nIndex < pArray->nCount )
{
const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
SCROW nThisEnd = pArray->pData[nIndex].nRow;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 0d653d07721f..3bf5e8af9c37 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5373,16 +5373,26 @@ void ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
ScAttrArray* pAttrArray = maTabs[nTab]->aCol[nOldCol].pAttrArray;
SCSIZE nIndex;
- pAttrArray->Search( nOldRow, nIndex );
+ if ( pAttrArray->nCount )
+ pAttrArray->Search( nOldRow, nIndex );
+ else
+ nIndex = 0;
SCROW nAttrPos = nOldRow;
while (nAttrPos<=nEndRow)
{
OSL_ENSURE( nIndex < pAttrArray->nCount, "Wrong index in AttrArray" );
- if (static_cast<const ScMergeFlagAttr&>(pAttrArray->pData[nIndex].pPattern->
- GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
+ bool bHorOverlapped;
+ if ( pAttrArray->nCount )
+ bHorOverlapped = static_cast<const ScMergeFlagAttr&>(pAttrArray->pData[nIndex].pPattern->
+ GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped();
+ else
+ bHorOverlapped = static_cast<const ScMergeFlagAttr&>(GetDefPattern()->
+ GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped();
+ if ( bHorOverlapped )
{
- SCROW nLoopEndRow = std::min( nEndRow, pAttrArray->pData[nIndex].nRow );
+ SCROW nEndRowSeg = (pAttrArray->nCount) ? pAttrArray->pData[nIndex].nRow : MAXROW;
+ SCROW nLoopEndRow = std::min( nEndRow, nEndRowSeg );
for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
{
SCCOL nTempCol = nOldCol;
@@ -5394,8 +5404,13 @@ void ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
rStartCol = nTempCol;
}
}
- nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
- ++nIndex;
+ if ( pAttrArray->nCount )
+ {
+ nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
+ ++nIndex;
+ }
+ else
+ nAttrPos = MAXROW + 1;
}
}
}
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index 9f2ebca39264..d8ec3ed9eec3 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -499,12 +499,24 @@ void ScDocument::FillInfo(
SCROW nThisRow;
SCSIZE nIndex;
- (void) pThisAttrArr->Search( nCurRow, nIndex );
+ if ( pThisAttrArr->nCount )
+ (void) pThisAttrArr->Search( nCurRow, nIndex );
+ else
+ nIndex = 0;
do
{
- nThisRow=pThisAttrArr->pData[nIndex].nRow; // End of range
- const ScPatternAttr* pPattern=pThisAttrArr->pData[nIndex].pPattern;
+ const ScPatternAttr* pPattern = nullptr;
+ if ( pThisAttrArr->nCount )
+ {
+ nThisRow = pThisAttrArr->pData[nIndex].nRow; // End of range
+ pPattern = pThisAttrArr->pData[nIndex].pPattern;
+ }
+ else
+ {
+ nThisRow = MAXROW;
+ pPattern = GetDefPattern();
+ }
const SvxBrushItem* pBackground = static_cast<const SvxBrushItem*>(
&pPattern->GetItem(ATTR_BACKGROUND));
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 7d3d94a26509..bf227d3aa5ea 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -287,7 +287,8 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
bPrintEntireSheet(true),
bActiveScenario(false),
mbPageBreaksValid(false),
- mbForceBreaks(false)
+ mbForceBreaks(false),
+ aNextColAttrArray(static_cast<SCCOL>(-1), nNewTab, pDoc, nullptr, true)
{
if (bColInfo)
@@ -328,7 +329,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
}
for (SCCOL k=0; k<=MAXCOL; k++)
- aCol[k].Init( k, nTab, pDocument );
+ aCol[k].Init( k, nTab, pDocument, true );
}
ScTable::~ScTable()
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 55afa01a540e..0f817d94fdf7 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1936,8 +1936,13 @@ bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
OSL_FAIL("ScTable::ExtendMerge: invalid column number");
return false;
}
+ if ( nStartCol >= aCol.size() )
+ {
+ OSL_FAIL("ScTable::ExtendMerge: invalid nStartCol");
+ return false;
+ }
bool bFound = false;
- SCCOL nOldEndX = rEndCol;
+ SCCOL nOldEndX = std::min( rEndCol, static_cast<SCCOL>(aCol.size()-1) );
SCROW nOldEndY = rEndRow;
for (SCCOL i=nStartCol; i<=nOldEndX; i++)
bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh );