diff options
Diffstat (limited to 'sc/source/core')
37 files changed, 3057 insertions, 1797 deletions
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index 53df13b4cd62..f3443312bd4e 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -52,7 +52,7 @@ #include "markarr.hxx" #include "rechead.hxx" #include "globstr.hrc" - +#include "segmenttree.hxx" #undef DBG_INVALIDATE #define DBGOUTPUT(s) \ @@ -1727,8 +1727,7 @@ SCsROW ScAttrArray::GetNextUnprotected( SCsROW nRow, BOOL bUp ) const return nRet; } - -void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset ) +void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ) { SCROW nStart = 0; SCSIZE nPos = 0; @@ -1740,7 +1739,7 @@ void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pU // for (SCROW nRow = nStart; nRow <= nEnd; nRow++) // pUsed[nRow] = TRUE; - memset( &pUsed[nStart], TRUE, nEnd-nStart+1 ); + rUsedRows.setTrue(nStart, nEnd); if (bReset) { diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx index 48a0e8597e1c..95482b1c624b 100644 --- a/sc/source/core/data/bcaslot.cxx +++ b/sc/source/core/data/bcaslot.cxx @@ -47,8 +47,10 @@ #define BCA_SLOTS_COL ((MAXCOLCOUNT_DEFINE) / 16) #if MAXROWCOUNT_DEFINE == 32000 #define BCA_SLOTS_ROW 256 +#define BCA_SLICE 125 #else -#define BCA_SLOTS_ROW ((MAXROWCOUNT_DEFINE) / 128) +#define BCA_SLICE 128 +#define BCA_SLOTS_ROW ((MAXROWCOUNT_DEFINE) / BCA_SLICE) #endif #define BCA_SLOT_COLS ((MAXCOLCOUNT_DEFINE) / BCA_SLOTS_COL) #define BCA_SLOT_ROWS ((MAXROWCOUNT_DEFINE) / BCA_SLOTS_ROW) @@ -59,7 +61,7 @@ #if (BCA_SLOT_ROWS * BCA_SLOTS_ROW) != (MAXROWCOUNT_DEFINE) #error bad BCA_SLOTS_ROW value! #endif -// size of slot array +// size of slot array if linear #define BCA_SLOTS_DEFINE (BCA_SLOTS_COL * BCA_SLOTS_ROW) // Arbitrary 2**31/8, assuming size_t can hold at least 2^31 values and // sizeof_ptr is at most 8 bytes. You'd probably doom your machine's memory @@ -67,14 +69,60 @@ #if BCA_SLOTS_DEFINE > 268435456 #error BCA_SLOTS_DEFINE DOOMed! #endif -// type safe constant -const SCSIZE BCA_SLOTS = BCA_SLOTS_DEFINE; // STATIC DATA ----------------------------------------------------------- TYPEINIT1( ScHint, SfxSimpleHint ); TYPEINIT1( ScAreaChangedHint, SfxHint ); +struct ScSlotData +{ + SCROW nStartRow; // first row of this segment + SCROW nStopRow; // first row of next segment + SCSIZE nSlice; // slice size in this segment + SCSIZE nCumulated; // cumulated slots of previous segments + + ScSlotData( SCROW r1, SCROW r2, SCSIZE s, SCSIZE c ) : nStartRow(r1), nStopRow(r2), nSlice(s), nCumulated(c) {} +}; +typedef ::std::vector< ScSlotData > ScSlotDistribution; +#if MAXROWCOUNT_DEFINE <= 65536 +// Linear distribution. +static ScSlotDistribution aSlotDistribution( ScSlotData( 0, MAXROWCOUNT, BCA_SLOT_ROWS, 0)); +static SCSIZE nBcaSlotsRow = BCA_SLOTS_ROW; +static SCSIZE nBcaSlots = BCA_SLOTS_DEFINE; +#else +// Logarithmic or any other distribution. +// Upper sheet part usually is more populated and referenced and gets fine +// grained resolution, larger data in larger hunks. +// Could be further enhanced by also applying a different distribution of +// column slots. +static SCSIZE initSlotDistribution( ScSlotDistribution & rSD, SCSIZE & rBSR ) +{ + SCSIZE nSlots = 0; + SCROW nRow1 = 0; + SCROW nRow2 = 32*1024; + SCSIZE nSlice = 128; + // Must be sorted by row1,row2! + while (nRow2 <= MAXROWCOUNT) + { + //fprintf( stderr, "r1,r2,slice,cum: %7zu, %7zu, %7zu, %7zu\n", (size_t)nRow1, (size_t)nRow2, (size_t)nSlice, (size_t)nSlots); + // {0,32k,128,0;32k,64k,256,0+256;64k,128k,512,0+256+128;128k,256k,1024,0+256+128+128;256k,512k,2048,...;512k,1M,4096,...} + rSD.push_back( ScSlotData( nRow1, nRow2, nSlice, nSlots)); + nSlots += (nRow2 - nRow1) / nSlice; + nRow1 = nRow2; + nRow2 *= 2; + nSlice *= 2; + } + //fprintf( stderr, "Slices: %zu, slots per sheet: %zu, memory per referenced sheet: %zu\n", (size_t) nSlots, (size_t) nSlots * BCA_SLOTS_COL, (size_t) nSlots * BCA_SLOTS_COL * sizeof(void*)); + rBSR = nSlots; + return nSlots; +} +static ScSlotDistribution aSlotDistribution; +static SCSIZE nBcaSlotsRow; +static SCSIZE nBcaSlots = initSlotDistribution( aSlotDistribution, nBcaSlotsRow) * BCA_SLOTS_COL; +// Ensure that all static variables are initialized with this one call. +#endif + ScBroadcastAreaSlot::ScBroadcastAreaSlot( ScDocument* pDocument, ScBroadcastAreaSlotMachine* pBASMa ) : @@ -393,14 +441,14 @@ void ScBroadcastAreaSlot::UpdateInsert( ScBroadcastArea* pArea ) ScBroadcastAreaSlotMachine::TableSlots::TableSlots() { - ppSlots = new ScBroadcastAreaSlot* [ BCA_SLOTS ]; - memset( ppSlots, 0 , sizeof( ScBroadcastAreaSlot* ) * BCA_SLOTS ); + ppSlots = new ScBroadcastAreaSlot* [ nBcaSlots ]; + memset( ppSlots, 0 , sizeof( ScBroadcastAreaSlot* ) * nBcaSlots ); } ScBroadcastAreaSlotMachine::TableSlots::~TableSlots() { - for ( ScBroadcastAreaSlot** pp = ppSlots + BCA_SLOTS; --pp >= ppSlots; /* nothing */ ) + for ( ScBroadcastAreaSlot** pp = ppSlots + nBcaSlots; --pp >= ppSlots; /* nothing */ ) { if (*pp) delete *pp; @@ -417,16 +465,16 @@ ScBroadcastAreaSlotMachine::ScBroadcastAreaSlotMachine( pEOUpdateChain( NULL ), nInBulkBroadcast( 0 ) { - for (TableSlotsMap::iterator iTab( aTableSlotsMap.begin()); - iTab != aTableSlotsMap.end(); ++iTab) - { - delete (*iTab).second; - } } ScBroadcastAreaSlotMachine::~ScBroadcastAreaSlotMachine() { + for (TableSlotsMap::iterator iTab( aTableSlotsMap.begin()); + iTab != aTableSlotsMap.end(); ++iTab) + { + delete (*iTab).second; + } delete pBCAlways; } @@ -438,13 +486,21 @@ inline SCSIZE ScBroadcastAreaSlotMachine::ComputeSlotOffset( SCCOL nCol = rAddress.Col(); if ( !ValidRow(nRow) || !ValidCol(nCol) ) { - DBG_ASSERT( FALSE, "Row/Col ungueltig!" ); + DBG_ERRORFILE( "Row/Col invalid, using first slot!" ); return 0; } - else - return - static_cast<SCSIZE>(nRow) / BCA_SLOT_ROWS + - static_cast<SCSIZE>(nCol) / BCA_SLOT_COLS * BCA_SLOTS_ROW; + for (size_t i=0; i < aSlotDistribution.size(); ++i) + { + if (nRow < aSlotDistribution[i].nStopRow) + { + const ScSlotData& rSD = aSlotDistribution[i]; + return rSD.nCumulated + + (static_cast<SCSIZE>(nRow - rSD.nStartRow)) / rSD.nSlice + + static_cast<SCSIZE>(nCol) / BCA_SLOT_COLS * nBcaSlotsRow; + } + } + DBG_ERRORFILE( "No slot found, using last!" ); + return nBcaSlots - 1; } @@ -459,9 +515,28 @@ void ScBroadcastAreaSlotMachine::ComputeAreaPoints( const ScRange& rRange, } +inline void ComputeNextSlot( SCSIZE & nOff, SCSIZE & nBreak, ScBroadcastAreaSlot** & pp, + SCSIZE & nStart, ScBroadcastAreaSlot** const & ppSlots, SCSIZE const & nRowBreak ) +{ + if ( nOff < nBreak ) + { + ++nOff; + ++pp; + } + else + { + nStart += nBcaSlotsRow; + nOff = nStart; + pp = ppSlots + nOff; + nBreak = nOff + nRowBreak; + } +} + + void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, SvtListener* pListener ) { + //fprintf( stderr, "StartListeningArea (c,r,t): %d, %d, %d, %d, %d, %d\n", (int)rRange.aStart.Col(), (int)rRange.aStart.Row(), (int)rRange.aStart.Tab(), (int)rRange.aEnd.Col(), (int)rRange.aEnd.Row(), (int)rRange.aEnd.Tab()); if ( rRange == BCA_LISTEN_ALWAYS ) { if ( !pBCAlways ) @@ -500,18 +575,7 @@ void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, } else (*pp)->InsertListeningArea( pArea); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } } @@ -521,6 +585,7 @@ void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, SvtListener* pListener ) { + //fprintf( stderr, "EndListeningArea (c,r,t): %d, %d, %d, %d, %d, %d\n", (int)rRange.aStart.Col(), (int)rRange.aStart.Row(), (int)rRange.aStart.Tab(), (int)rRange.aEnd.Col(), (int)rRange.aEnd.Row(), (int)rRange.aEnd.Tab()); if ( rRange == BCA_LISTEN_ALWAYS ) { DBG_ASSERT( pBCAlways, "ScBroadcastAreaSlotMachine::EndListeningArea: BCA_LISTEN_ALWAYS but none established"); @@ -547,7 +612,7 @@ void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, SCSIZE nBreak = nOff + nRowBreak; ScBroadcastAreaSlot** pp = ppSlots + nOff; ScBroadcastArea* pArea = NULL; - if (nOff == 0 && nEnd == BCA_SLOTS-1) + if (nOff == 0 && nEnd == nBcaSlots-1) { // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they // happen for insertion and deletion of sheets. @@ -564,18 +629,7 @@ void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, { if ( *pp ) (*pp)->EndListeningArea( rRange, pListener, pArea ); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } } @@ -629,18 +683,7 @@ BOOL ScBroadcastAreaSlotMachine::AreaBroadcastInRange( const ScRange& rRange, { if ( *pp ) bBroadcasted |= (*pp)->AreaBroadcastInRange( rRange, rHint ); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } return bBroadcasted; @@ -660,7 +703,7 @@ void ScBroadcastAreaSlotMachine::DelBroadcastAreasInRange( SCSIZE nOff = nStart; SCSIZE nBreak = nOff + nRowBreak; ScBroadcastAreaSlot** pp = ppSlots + nOff; - if (nOff == 0 && nEnd == BCA_SLOTS-1) + if (nOff == 0 && nEnd == nBcaSlots-1) { // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they // happen for insertion and deletion of sheets. @@ -677,18 +720,7 @@ void ScBroadcastAreaSlotMachine::DelBroadcastAreasInRange( { if ( *pp ) (*pp)->DelBroadcastAreasInRange( rRange ); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } } @@ -711,7 +743,7 @@ void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas( SCSIZE nOff = nStart; SCSIZE nBreak = nOff + nRowBreak; ScBroadcastAreaSlot** pp = ppSlots + nOff; - if (nOff == 0 && nEnd == BCA_SLOTS-1) + if (nOff == 0 && nEnd == nBcaSlots-1) { // Slightly optimized for 0,0,MAXCOL,MAXROW calls as they // happen for insertion and deletion of sheets. @@ -728,18 +760,7 @@ void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas( { if ( *pp ) (*pp)->UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz ); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } } @@ -771,18 +792,7 @@ void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas( { if (*pp) (*pp)->UpdateRemoveArea( pArea); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } @@ -876,18 +886,7 @@ void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas( if (!*pp) *pp = new ScBroadcastAreaSlot( pDoc, this ); (*pp)->UpdateInsert( pArea ); - if ( nOff < nBreak ) - { - ++nOff; - ++pp; - } - else - { - nStart += BCA_SLOTS_ROW; - nOff = nStart; - pp = ppSlots + nOff; - nBreak = nOff + nRowBreak; - } + ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index a70a9b86e186..aa492630ab0e 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -277,21 +277,21 @@ void ScBaseCell::StartListeningTo( ScDocument* pDoc ) if ( rRef1.IsColRel() ) { // ColName pDoc->StartListeningArea( ScRange ( - 0, + rRef1.nCol, rRef1.nRow, rRef1.nTab, - MAXCOL, - rRef2.nRow, + rRef2.nCol, + MAXROW, rRef2.nTab ), pFormCell ); } else { // RowName pDoc->StartListeningArea( ScRange ( rRef1.nCol, - 0, + rRef1.nRow, rRef1.nTab, - rRef2.nCol, - MAXROW, + MAXCOL, + rRef2.nRow, rRef2.nTab ), pFormCell ); } } @@ -367,21 +367,21 @@ void ScBaseCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr, if ( rRef1.IsColRel() ) { // ColName pDoc->EndListeningArea( ScRange ( - 0, + rRef1.nCol, rRef1.nRow, rRef1.nTab, - MAXCOL, - rRef2.nRow, + rRef2.nCol, + MAXROW, rRef2.nTab ), pFormCell ); } else { // RowName pDoc->EndListeningArea( ScRange ( rRef1.nCol, - 0, + rRef1.nRow, rRef1.nTab, - rRef2.nCol, - MAXROW, + MAXCOL, + rRef2.nRow, rRef2.nTab ), pFormCell ); } } diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 6a5fe824197b..e9fd26ced939 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -600,13 +600,11 @@ const ScStyleSheet* ScColumn::GetAreaStyle( BOOL& rFound, SCROW nRow1, SCROW nRo return bEqual ? pStyle : NULL; } - -void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset ) +void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ) { - pAttrArray->FindStyleSheet( pStyleSheet, pUsed, bReset ); + pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset ); } - BOOL ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, BOOL bGatherAllStyles ) const { return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles ); @@ -893,11 +891,6 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster(); pCell1->TakeBroadcaster( pBC2 ); pCell2->TakeBroadcaster( pBC1 ); - - ScHint aHint1( SC_HINT_DATACHANGED, aPos1, pCell2 ); - pDocument->Broadcast( aHint1 ); - ScHint aHint2( SC_HINT_DATACHANGED, aPos2, pCell1 ); - pDocument->Broadcast( aHint2 ); } else { @@ -918,7 +911,6 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) // insert ColEntry at new position Insert( nRow2, pCell1 ); - pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED, aPos1, pDummyCell ) ); } return; @@ -999,14 +991,6 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) Delete( nRow2 ); // deletes pCell2 else if ( pNew2 ) Insert( nRow2, pNew2 ); // deletes pCell2 (if existing), inserts pNew2 - - // #64122# Bei Formeln hinterher nochmal broadcasten, damit die Formel nicht in irgendwelchen - // FormulaTrack-Listen landet, ohne die Broadcaster beruecksichtigt zu haben - // (erst hier, wenn beide Zellen eingefuegt sind) - if ( pBC1 && pFmlaCell2 ) - pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED, aPos1, pNew1 ) ); - if ( pBC2 && pFmlaCell1 ) - pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED, aPos2, pNew2 ) ); } @@ -1402,7 +1386,7 @@ void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol ) // Dies ist die Szenario-Tabelle, die Daten werden hineinkopiert ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW ); - SCROW nStart, nEnd; + SCROW nStart = -1, nEnd = -1; const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd ); while (pPattern) { @@ -1433,7 +1417,7 @@ void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const // Dies ist die Szenario-Tabelle, die Daten werden in die andere kopiert ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW ); - SCROW nStart, nEnd; + SCROW nStart = -1, nEnd = -1; const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd ); while (pPattern) { @@ -1482,7 +1466,7 @@ void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const ScRange aRange( nCol, 0, nTab ); ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW ); - SCROW nStart, nEnd; + 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 4c8de67ba271..2adf6d926f0f 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -66,6 +66,7 @@ #include "compiler.hxx" // ScTokenArray GetCodeLen #include "dbcolect.hxx" #include "fillinfo.hxx" +#include "segmenttree.hxx" #include <math.h> @@ -760,8 +761,8 @@ void ScColumn::GetOptimalHeight( SCROW nStartRow, SCROW nEndRow, USHORT* pHeight { ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow ); - SCROW nStart; - SCROW nEnd; + SCROW nStart = -1; + SCROW nEnd = -1; SCROW nEditPos = 0; SCROW nNextEnd = 0; @@ -1407,11 +1408,11 @@ BOOL ScColumn::GetPrevDataPos(SCROW& rRow) const return bFound; } -BOOL ScColumn::GetNextDataPos(SCROW& rRow) const // groesser als rRow +BOOL ScColumn::GetNextDataPos(SCROW& rRow) const // greater than rRow { SCSIZE nIndex; if (Search( rRow, nIndex )) - ++nIndex; // naechste Zelle + ++nIndex; // next cell BOOL bMore = ( nIndex < nCount ); if ( bMore ) @@ -1782,7 +1783,7 @@ void lcl_UpdateSubTotal( ScFunctionData& rData, ScBaseCell* pCell ) // Mehrfachselektion: void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark, ScFunctionData& rData, - const ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags, + ScFlatBoolRowSegments& rHiddenRows, BOOL bDoExclude, SCROW nExStartRow, SCROW nExEndRow ) { SCSIZE nIndex; @@ -1790,7 +1791,8 @@ void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark, while (aDataIter.Next( nIndex )) { SCROW nRow = pItems[nIndex].nRow; - if ( !pRowFlags || !( pRowFlags->GetValue(nRow) & CR_HIDDEN ) ) + bool bRowHidden = rHiddenRows.getValue(nRow); + if ( !bRowHidden ) if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow ) lcl_UpdateSubTotal( rData, pItems[nIndex].pCell ); } @@ -1798,7 +1800,7 @@ void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark, // bei bNoMarked die Mehrfachselektion weglassen void ScColumn::UpdateAreaFunction( ScFunctionData& rData, - const ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags, + ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow ) { SCSIZE nIndex; @@ -1806,7 +1808,8 @@ void ScColumn::UpdateAreaFunction( ScFunctionData& rData, while ( nIndex<nCount && pItems[nIndex].nRow<=nEndRow ) { SCROW nRow = pItems[nIndex].nRow; - if ( !pRowFlags || !( pRowFlags->GetValue(nRow) & CR_HIDDEN ) ) + bool bRowHidden = rHiddenRows.getValue(nRow); + if ( !bRowHidden ) lcl_UpdateSubTotal( rData, pItems[nIndex].pCell ); ++nIndex; } diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index be7211138c1d..65e896c7f2c4 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1648,8 +1648,8 @@ BOOL ScColumn::GetDataEntries(SCROW nStartRow, TypedScStrCollection& rStrings, B void ScColumn::RemoveProtected( SCROW nStartRow, SCROW nEndRow ) { ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow ); - SCROW nTop; - SCROW nBottom; + SCROW nTop = -1; + SCROW nBottom = -1; SCSIZE nIndex; const ScPatternAttr* pPattern = aAttrIter.Next( nTop, nBottom ); while (pPattern) diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 706783579a24..aa5b011da93b 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -49,6 +49,7 @@ using ::rtl::math::approxEqual; using ::std::vector; using ::rtl::OUString; +using ::std::set; // STATIC DATA ----------------------------------------------------------- @@ -345,7 +346,7 @@ BOOL ScValueIterator::GetThis(double& rValue, USHORT& rErr) if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow ) { nRow = pCol->pItems[nColRow].nRow + 1; - if ( !bSubTotal || !pDoc->pTab[nTab]->IsFiltered( nRow-1 ) ) + if ( !bSubTotal || !pDoc->pTab[nTab]->RowFiltered( nRow-1 ) ) { ScBaseCell* pCell = pCol->pItems[nColRow].pCell; ++nColRow; @@ -940,11 +941,6 @@ ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryPar } } -bool ScDBQueryDataIterator::GetThis(Value& rValue) -{ - return mpData->getCurrent(rValue); -} - bool ScDBQueryDataIterator::GetFirst(Value& rValue) { return mpData->getFirst(rValue); @@ -1071,7 +1067,7 @@ ScBaseCell* ScCellIterator::GetThis() if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow ) { nRow = pCol->pItems[nColRow].nRow; - if ( !bSubTotal || !pDoc->pTab[nTab]->IsFiltered( nRow ) ) + if ( !bSubTotal || !pDoc->pTab[nTab]->RowFiltered( nRow ) ) { ScBaseCell* pCell = pCol->pItems[nColRow].pCell; @@ -1259,14 +1255,6 @@ ScBaseCell* ScQueryCellIterator::GetNext() return GetThis(); } -ULONG ScQueryCellIterator::GetNumberFormat() -{ - ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol]; - lcl_IterGetNumberFormat( nNumFormat, pAttrArray, - nAttrEndRow, pCol->pAttrArray, nRow, pDoc ); - return nNumFormat; -} - void ScQueryCellIterator::AdvanceQueryParamEntryField() { SCSIZE nEntries = aParam.GetEntryCount(); @@ -2147,3 +2135,24 @@ const ScPatternAttr* ScAttrRectIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2, return NULL; // is nix mehr } +// ============================================================================ + +SCROW ScRowBreakIterator::NOT_FOUND = -1; + +ScRowBreakIterator::ScRowBreakIterator(set<SCROW>& rBreaks) : + mrBreaks(rBreaks), + maItr(rBreaks.begin()), maEnd(rBreaks.end()) +{ +} + +SCROW ScRowBreakIterator::first() +{ + maItr = mrBreaks.begin(); + return maItr == maEnd ? NOT_FOUND : *maItr; +} + +SCROW ScRowBreakIterator::next() +{ + ++maItr; + return maItr == maEnd ? NOT_FOUND : *maItr; +} diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index c5922aa88dcc..e8ea10f7cf52 100755..100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -188,11 +188,11 @@ ScDocument::ScDocument( ScDocumentMode eMode, // bNoSetDirty( TRUE ), bNoSetDirty( FALSE ), bInsertingFromOtherDoc( FALSE ), - bImportingXML( FALSE ), + bLoadingMedium( false ), + bImportingXML( false ), bXMLFromWrapper( FALSE ), bCalcingAfterLoad( FALSE ), bNoListening( FALSE ), - bLoadingDone( TRUE ), bIdleDisabled( FALSE ), bInLinkUpdate( FALSE ), bChartListenerCollectionNeedsUpdate( FALSE ), @@ -897,6 +897,8 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM SetNoListening( TRUE ); // noch nicht bei CopyToTable/Insert pTab[nOldPos]->CopyToTable(0, 0, MAXCOL, MAXROW, IDF_ALL, (pOnlyMarked != NULL), pTab[nNewPos], pOnlyMarked ); + pTab[nNewPos]->SetTabBgColor(pTab[nOldPos]->GetTabBgColor()); + SCsTAB nDz; /* if (nNewPos < nOldPos) nDz = ((short)nNewPos) - (short)nOldPos + 1; diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 77f59254e049..1861988d78aa 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -83,6 +83,7 @@ #include "tabprotection.hxx" #include "formulaparserpool.hxx" #include "clipparam.hxx" +#include "sheetevents.hxx" #include <memory> @@ -285,6 +286,26 @@ void ScDocument::SetScenarioData( SCTAB nTab, const String& rComment, } } +Color ScDocument::GetTabBgColor( SCTAB nTab ) const +{ + if (ValidTab(nTab) && pTab[nTab]) + return pTab[nTab]->GetTabBgColor(); + return Color(COL_AUTO); +} + +void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor ) +{ + if (ValidTab(nTab) && pTab[nTab]) + pTab[nTab]->SetTabBgColor(rColor); +} + +bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const +{ + if (ValidTab(nTab) && pTab[nTab]) + return pTab[nTab]->GetTabBgColor() == COL_AUTO; + return true; +} + void ScDocument::GetScenarioData( SCTAB nTab, String& rComment, Color& rColor, USHORT& rFlags ) const { @@ -478,6 +499,52 @@ ScFormulaParserPool& ScDocument::GetFormulaParserPool() const return *mxFormulaParserPool; } +const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const +{ + if (VALIDTAB(nTab) && pTab[nTab]) + return pTab[nTab]->GetSheetEvents(); + return NULL; +} + +void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew ) +{ + if (VALIDTAB(nTab) && pTab[nTab]) + pTab[nTab]->SetSheetEvents( pNew ); +} + +bool ScDocument::HasSheetEventScript( sal_Int32 nEvent ) const +{ + for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) + if (pTab[nTab]) + { + const ScSheetEvents* pEvents = pTab[nTab]->GetSheetEvents(); + if ( pEvents && pEvents->GetScript( nEvent ) ) + return true; + } + return false; +} + +BOOL ScDocument::HasCalcNotification( SCTAB nTab ) const +{ + if (VALIDTAB(nTab) && pTab[nTab]) + return pTab[nTab]->GetCalcNotification(); + return FALSE; +} + +void ScDocument::SetCalcNotification( SCTAB nTab ) +{ + // set only if not set before + if (VALIDTAB(nTab) && pTab[nTab] && !pTab[nTab]->GetCalcNotification()) + pTab[nTab]->SetCalcNotification(TRUE); +} + +void ScDocument::ResetCalcNotifications() +{ + for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) + if (pTab[nTab] && pTab[nTab]->GetCalcNotification()) + pTab[nTab]->SetCalcNotification(FALSE); +} + ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate ) { ScOutlineTable* pVal = NULL; @@ -1123,15 +1190,6 @@ BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem, return bFound; } -BOOL ScDocument::IsFiltered( SCROW nRow, SCTAB nTab ) const -{ - if (VALIDTAB(nTab)) - if (pTab[nTab]) - return pTab[nTab]->IsFiltered( nRow ); - DBG_ERROR("Falsche Tabellennummer"); - return 0; -} - // Outline anpassen BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow ) @@ -1544,46 +1602,43 @@ ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect ) nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS); SCROW nY1 = 0; - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - *(pTable->GetRowFlagsArray()), nY1, MAXROW, CR_HIDDEN, 0, - *(pTable->GetRowHeightArray())); bEnd = FALSE; - while (!bEnd && aIter) + for (SCROW i = nY1; i <= MAXROW && !bEnd; ++i) { - nY1 = aIter.GetPos(); - nAdd = (long) *aIter; + if (pTable->RowHidden(i)) + continue; + + nY1 = i; + nAdd = static_cast<long>(pTable->GetRowHeight(i)); if (nSize+nAdd <= nTwips+1 && nY1<MAXROW) { nSize += nAdd; ++nY1; - ++aIter; } else bEnd = TRUE; } - if (!aIter) - nY1 = aIter.GetIterEnd(); // all hidden down to the bottom + if (!bEnd) + nY1 = MAXROW; // all hidden down to the bottom nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS); SCROW nY2 = nY1; - aIter.NewLimits( nY2, MAXROW); bEnd = FALSE; - while (!bEnd && aIter) + for (SCROW i = nY2; i <= MAXROW && !bEnd; ++i) { - nY2 = aIter.GetPos(); - nAdd = (long) *aIter; + nY2 = i; + nAdd = static_cast<long>(pTable->GetRowHeight(i)); if (nSize+nAdd < nTwips && nY2<MAXROW) { nSize += nAdd; ++nY2; - ++aIter; } else bEnd = TRUE; } - if (!aIter) - nY2 = aIter.GetIterEnd(); // all hidden down to the bottom + if (!bEnd) + nY2 = MAXROW; // all hidden down to the bottom return ScRange( nX1,nY1,nTab, nX2,nY2,nTab ); } @@ -1621,24 +1676,33 @@ void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow ) SCROW nRow = 0; long nTwips = (long) (rVal / HMM_PER_TWIPS); long nSnap = 0; - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - *(pTable->GetRowFlagsArray()), nRow, MAXROW, CR_HIDDEN, 0, - *(pTable->GetRowHeightArray())); - while ( aIter ) + + bool bFound = false; + for (SCROW i = nRow; i <= MAXROW; ++i) { - nRow = aIter.GetPos(); - long nAdd = *aIter; + SCROW nLastRow; + if (pTable->RowHidden(i, NULL, &nLastRow)) + { + i = nLastRow; + continue; + } + + nRow = i; + long nAdd = pTable->GetRowHeight(i); if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow ) { nSnap += nAdd; ++nRow; - ++aIter; } else + { + bFound = true; break; + } } - if (!aIter) + if (!bFound) nRow = MAXROW; // all hidden down to the bottom + rVal = (long) ( nSnap * HMM_PER_TWIPS ); rStartRow = nRow; } @@ -1796,14 +1860,14 @@ Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, for (i=0; i<nStartCol; i++) aRect.Left() += GetColWidth(i,nTab); - aRect.Top() += FastGetRowHeight( 0, nStartRow-1, nTab); + aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab); aRect.Right() = aRect.Left(); aRect.Bottom() = aRect.Top(); for (i=nStartCol; i<=nEndCol; i++) aRect.Right() += GetColWidth(i,nTab); - aRect.Bottom() += FastGetRowHeight( nStartRow, nEndRow, nTab); + aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab); aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS); aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS); diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx index ad2ec90379df..97aae44f1a7b 100644 --- a/sc/source/core/data/documen7.cxx +++ b/sc/source/core/data/documen7.cxx @@ -52,6 +52,7 @@ #include "scmod.hxx" // SC_MOD #include "inputopt.hxx" // GetExpandRefs #include "conditio.hxx" +#include "sheetevents.hxx" #include <tools/shl.hxx> @@ -452,6 +453,8 @@ void ScDocument::TrackFormulas( ULONG nHintId ) if ( pFormulaTrack ) { erBEEPER(); + // outside the loop, check if any sheet has a "calculate" event script + bool bCalcEvent = HasSheetEventScript( SC_SHEETEVENT_CALCULATE ); SvtBroadcaster* pBC; ScFormulaCell* pTrack; ScFormulaCell* pNext; @@ -465,6 +468,9 @@ void ScDocument::TrackFormulas( ULONG nHintId ) // Repaint fuer bedingte Formate mit relativen Referenzen: if ( pCondFormList ) pCondFormList->SourceChanged( pTrack->aPos ); + // for "calculate" event, keep track of which sheets are affected by tracked formulas + if ( bCalcEvent ) + SetCalcNotification( pTrack->aPos.Tab() ); pTrack = pTrack->GetNextTrack(); } while ( pTrack ); pTrack = pFormulaTrack; diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx index 9da788fca01c..abef7d53c2af 100644 --- a/sc/source/core/data/documen9.cxx +++ b/sc/source/core/data/documen9.cxx @@ -67,7 +67,7 @@ #include "charthelper.hxx" using namespace ::com::sun::star; - +#include <stdio.h> // ----------------------------------------------------------------------- @@ -722,7 +722,19 @@ void ScDocument::UpdateFontCharSet() } } -void ScDocument::SetImportingXML( BOOL bVal ) +void ScDocument::SetLoadingMedium( bool bVal ) +{ + bLoadingMedium = bVal; + for (SCTAB nTab = 0; nTab <= MAXTAB; ++nTab) + { + if (!pTab[nTab]) + return; + + pTab[nTab]->SetLoadingMedium(bVal); + } +} + +void ScDocument::SetImportingXML( bool bVal ) { bImportingXML = bVal; if (pDrawLayer) @@ -739,6 +751,8 @@ void ScDocument::SetImportingXML( BOOL bVal ) SetLayoutRTL( nTab, TRUE ); // includes mirroring; bImportingXML must be cleared first } } + + SetLoadingMedium(bVal); } void ScDocument::SetXMLFromWrapper( BOOL bVal ) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 7c08c4327183..bef4cbf87396 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -52,6 +52,7 @@ #include <com/sun/star/text/WritingMode2.hpp> #include <com/sun/star/script/XVBACompat.hpp> +#include <com/sun/star/sheet/TablePageBreakData.hpp> #include "document.hxx" #include "table.hxx" @@ -94,8 +95,12 @@ #include "clipparam.hxx" #include <map> +#include <limits> namespace WritingMode2 = ::com::sun::star::text::WritingMode2; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::sheet::TablePageBreakData; +using ::std::set; struct ScDefaultAttr { @@ -125,6 +130,7 @@ void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck ) CreateValidTabName( aString ); // keine doppelten pTab[nTab] = new ScTable(this, nTab, aString); + pTab[nTab]->SetLoadingMedium(bLoadingMedium); ++nMaxTableNumber; } } @@ -2009,9 +2015,6 @@ void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1, while ( nFlagTab < MAXTAB && !ppClipTab[nFlagTab] ) ++nFlagTab; - const ScBitMaskCompressedArray< SCROW, BYTE> & rSourceFlags = - pCBFCP->pClipDoc->GetRowFlagsArray( nFlagTab); - SCROW nSourceRow = rClipStartRow; SCROW nSourceEnd = 0; if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count()) @@ -2021,12 +2024,15 @@ void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1, while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 ) { // skip filtered rows - nSourceRow = rSourceFlags.GetFirstForCondition( nSourceRow, nSourceEnd, CR_FILTERED, 0); + nSourceRow = pCBFCP->pClipDoc->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab); if ( nSourceRow <= nSourceEnd ) { // look for more non-filtered rows following - SCROW nFollow = rSourceFlags.GetBitStateEnd( nSourceRow, CR_FILTERED, 0) - nSourceRow; + SCROW nLastRow = nSourceRow; + pCBFCP->pClipDoc->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow); + SCROW nFollow = nLastRow - nSourceRow; + if (nFollow > nSourceEnd - nSourceRow) nFollow = nSourceEnd - nSourceRow; if (nFollow > nRow2 - nDestRow) @@ -2434,8 +2440,7 @@ void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered while ( nCountTab < MAXTAB && !pTab[nCountTab] ) ++nCountTab; - SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition( - nStartRow, nEndRow, CR_FILTERED, 0); + SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab); if ( nResult > 0 ) nClipY = nResult - 1; @@ -2474,8 +2479,13 @@ BOOL ScDocument::HasClipFilteredRows() if (!rClipRanges.Count()) return false; - return GetRowFlagsArray( nCountTab).HasCondition( rClipRanges.First()->aStart.Row(), - rClipRanges.First()->aEnd.Row(), CR_FILTERED, CR_FILTERED); + for (ScRange* p = rClipRanges.First(); p; p = rClipRanges.Next()) + { + bool bAnswer = pTab[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row()); + if (bAnswer) + return true; + } + return false; } @@ -3098,6 +3108,11 @@ void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 ); } +void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, USHORT nNewHeight ) +{ + if ( ValidTab(nTab) && pTab[nTab] ) + pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight ); +} void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bManual ) { @@ -3142,10 +3157,10 @@ USHORT ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const } -USHORT ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab ) const +USHORT ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const { if ( ValidTab(nTab) && pTab[nTab] ) - return pTab[nTab]->GetRowHeight( nRow ); + return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero ); DBG_ERROR("Falsche Tabellennummer"); return 0; } @@ -3167,11 +3182,9 @@ ULONG ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) con return 0; } -ULONG ScDocument::FastGetRowHeight( SCROW nStartRow, SCROW nEndRow, - SCTAB nTab ) const +SCROW ScDocument::GetRowForHeight( SCTAB nTab, ULONG nHeight ) const { - return pTab[nTab]->pRowFlags->SumCoupledArrayForCondition( nStartRow, - nEndRow, CR_HIDDEN, 0, *(pTab[nTab]->pRowHeight)); + return pTab[nTab]->GetRowForHeight(nHeight); } ULONG ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, @@ -3192,29 +3205,6 @@ ULONG ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, return 0; } - -const ScSummableCompressedArray< SCROW, USHORT> & ScDocument::GetRowHeightArray( - SCTAB nTab ) const -{ - const ScSummableCompressedArray< SCROW, USHORT> * pHeight; - if ( ValidTab(nTab) && pTab[nTab] ) - pHeight = pTab[nTab]->GetRowHeightArray(); - else - { - DBG_ERROR("wrong sheet number"); - pHeight = 0; - } - if (!pHeight) - { - DBG_ERROR("no row heights at sheet"); - static ScSummableCompressedArray< SCROW, USHORT> aDummy( MAXROW, - ScGlobal::nStdRowHeight); - pHeight = &aDummy; - } - return *pHeight; -} - - SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const { if ( ValidTab(nTab) && pTab[nTab] ) @@ -3397,6 +3387,259 @@ const ScBitMaskCompressedArray< SCROW, BYTE> & ScDocument::GetRowFlagsArray( return *pFlags; } +void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual); +} + +void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual); +} + +ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const +{ + ScBreakType nType = BREAK_NONE; + if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) + return nType; + + if (pTab[nTab]->HasRowPageBreak(nRow)) + nType |= BREAK_PAGE; + + if (pTab[nTab]->HasRowManualBreak(nRow)) + nType |= BREAK_MANUAL; + + return nType; +} + +ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const +{ + ScBreakType nType = BREAK_NONE; + if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) + return nType; + + if (pTab[nTab]->HasColPageBreak(nCol)) + nType |= BREAK_PAGE; + + if (pTab[nTab]->HasColManualBreak(nCol)) + nType |= BREAK_MANUAL; + + return nType; +} + +void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) +{ + if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) + return; + + pTab[nTab]->SetRowBreak(nRow, bPage, bManual); +} + +void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) +{ + if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) + return; + + pTab[nTab]->SetColBreak(nCol, bPage, bManual); +} + +void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) +{ + if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) + return; + + pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual); +} + +void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) +{ + if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) + return; + + pTab[nTab]->RemoveColBreak(nCol, bPage, bManual); +} + +Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return Sequence<TablePageBreakData>(); + + return pTab[nTab]->GetRowBreakData(); +} + +bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return false; + + return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow); +} + +bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + { + rLastRow = nRow; + return false; + } + + return pTab[nTab]->RowHidden(nRow, rLastRow); +} + + +bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return false; + + return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow); +} + +bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + { + rLastCol = nCol; + return false; + } + + return pTab[nTab]->ColHidden(nCol, rLastCol); +} + +bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + { + if (pFirstCol) + *pFirstCol = nCol; + if (pLastCol) + *pLastCol = nCol; + return false; + } + + return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol); +} + +void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden); +} + +void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden); +} + +SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return ::std::numeric_limits<SCROW>::max();; + + return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow); +} + +SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return ::std::numeric_limits<SCROW>::max();; + + return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow); +} + +SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return 0; + + return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow); +} + +bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return false; + + return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow); +} + +bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return false; + + return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow); +} + +bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return false; + + return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol); +} + +void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered); +} + +void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return; + + pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered); +} + +SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return ::std::numeric_limits<SCROW>::max();; + + return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow); +} + +SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return ::std::numeric_limits<SCROW>::max();; + + return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow); +} + +SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) +{ + if (!ValidTab(nTab) || !pTab[nTab]) + return 0; + + return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow); +} + +void ScDocument::SyncColRowFlags() +{ + for (SCTAB i = 0; i <= nMaxTableNumber; ++i) + { + if (!ValidTab(i) || !pTab[i]) + continue; + + pTab[i]->SyncColRowFlags(); + } +} SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const { @@ -3441,7 +3684,7 @@ SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const { - if ( ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetRowFlagsArray() && pTab[nTab]->GetRowHeightArray() ) + if ( ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetRowFlagsArray() && pTab[nTab]->mpRowHeights ) { BYTE nStartFlags = pTab[nTab]->GetRowFlags(nStart); USHORT nStartHeight = pTab[nTab]->GetOriginalHeight(nStart); @@ -3451,7 +3694,7 @@ SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCa SCROW nFlagsEndRow; SCROW nHeightEndRow; BYTE nFlags = pTab[nTab]->GetRowFlagsArray()->GetValue( nRow, nIndex, nFlagsEndRow ); - USHORT nHeight = pTab[nTab]->GetRowHeightArray()->GetValue( nRow, nIndex, nHeightEndRow ); + USHORT nHeight = pTab[nTab]->GetRowHeight(nRow, NULL, &nHeightEndRow); if (((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || @@ -4781,6 +5024,11 @@ void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCRO pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow ); } +void ScDocument::InvalidatePageBreaks(SCTAB nTab) +{ + if (ValidTab(nTab) && pTab[nTab]) + pTab[nTab]->InvalidatePageBreaks(); +} void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea ) { @@ -4960,6 +5208,12 @@ SfxUndoManager* ScDocument::GetUndoManager() return mpUndoManager; } +ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const +{ + if (ValidTab(nTab) && pTab[nTab]) + return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks); + return NULL; +} void ScDocument::EnableUndo( bool bVal ) { diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 5394605969d0..a2a10329cf68 100755 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -410,7 +410,7 @@ void ScDPObject::CreateOutput() nNewRow = 0; ScAddress aStart( aOutRange.aStart ); - aStart.SetRow( (USHORT) nNewRow ); + aStart.SetRow(nNewRow); pOutput->SetPosition( aStart ); //! modify aOutRange? @@ -2434,6 +2434,14 @@ void ScDPCollection::WriteRefsTo( ScDPCollection& r ) const } } +ScDPObject* ScDPCollection::GetByName(const String& rName) const +{ + for (USHORT i=0; i<nCount; i++) + if (static_cast<const ScDPObject*>(pItems[i])->GetName() == rName) + return static_cast<ScDPObject*>(pItems[i]); + return NULL; +} + String ScDPCollection::CreateNewName( USHORT nMin ) const { String aBase = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("DataPilot")); diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index 91688c6c0e2a..bdd6fd555b89 100755 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -1185,9 +1185,9 @@ void ScDPOutput::GetPositionData(const ScAddress& rPos, DataPilotTablePositionDa Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY); if (xPropSet.is()) { - sal_Int32 nDataFieldCount = 0; - Any any = xPropSet->getPropertyValue(rtl::OUString::createFromAscii("DataFieldCount")); - if ((any >>= nDataFieldCount) && nDataFieldCount > 0) + sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet, + rtl::OUString::createFromAscii(SC_UNO_DATAFIELDCOUNT) ); + if (nDataFieldCount > 0) aResData.DataFieldIndex = (nRow - nDataStartRow) % nDataFieldCount; } @@ -1267,9 +1267,9 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& if (!xPropSet.is()) return false; - sal_Int32 nDataFieldCount = 0; - Any any = xPropSet->getPropertyValue(rtl::OUString::createFromAscii("DataFieldCount")); - if (!(any >>= nDataFieldCount) || nDataFieldCount == 0) + sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet, + rtl::OUString::createFromAscii(SC_UNO_DATAFIELDCOUNT) ); + if (nDataFieldCount == 0) // No data field is present in this datapilot table. return false; diff --git a/sc/source/core/data/dptabresmember.cxx b/sc/source/core/data/dptabresmember.cxx deleted file mode 100644 index 8c3b7b164bc3..000000000000 --- a/sc/source/core/data/dptabresmember.cxx +++ /dev/null @@ -1,831 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright IBM Corporation 2009. - * Copyright 2009 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: dptabresmember.cxx,v $ - * $Revision: 1.0 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#include "dptabresmember.hxx" -// ----------------------------------------------------------------------- -ScDPResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData , - BOOL bForceSub ) : - pResultData( pData ), - aParentDimData( rParentDimData ), - /* pParentDim( pDim ), - pParentLevel( pLev ), - pMemberDesc( pDesc ),*/ - pChildDimension( NULL ), - pDataRoot( NULL ), - bHasElements( FALSE ), - bForceSubTotal( bForceSub ), - bHasHiddenDetails( FALSE ), - bInitialized( FALSE ), - nMemberStep( 1 ), - bAutoHidden( FALSE ) -{ - // pParentLevel/pMemberDesc is 0 for root members -} - -ScDPNormalResultMember::ScDPNormalResultMember( const ScDPResultData* pData, - BOOL bForceSub ) : - pResultData( pData ), - pChildDimension( NULL ), - pDataRoot( NULL ), - bHasElements( FALSE ), - bForceSubTotal( bForceSub ), - bHasHiddenDetails( FALSE ), - bInitialized( FALSE ), - nMemberStep( 1 ), - bAutoHidden( FALSE ) -{ -} - -ScDPNormalResultMember::~ScDPNormalResultMember() -{ - delete pChildDimension; - delete pDataRoot; -} - -String ScDPNormalResultMember::GetName() const -{ -// Wang Xu Ming -- 2009-6-10 -// DataPilot Migration - const ScDPMember* pMemberDesc = GetDPMember(); - // End Comments - if (pMemberDesc) - return pMemberDesc->GetNameStr(); - else - return ScGlobal::GetRscString(STR_PIVOT_TOTAL); // root member -} - -void ScDPNormalResultMember::FillItemData( ScDPItemData& rData ) const -{ -// Wang Xu Ming -- 2009-6-10 -// DataPilot Migration - const ScDPMember* pMemberDesc = GetDPMember(); -// End Comments - if (pMemberDesc) - pMemberDesc->FillItemData( rData ); - else - rData.SetString( ScGlobal::GetRscString(STR_PIVOT_TOTAL) ); // root member -} - -BOOL ScDPNormalResultMember::IsNamedItem( /*const ScDPItemData& r */SCROW nIndex ) const -{ - //! store ScDPMember pointer instead of ScDPMember ??? - const ScDPMember* pMemberDesc = GetDPMember(); - if (pMemberDesc) - return ((ScDPMember*)pMemberDesc)->IsNamedItem(/* r*/ nIndex ); - return FALSE; -} - -// Wang Xu Ming -- 2009-5-27 -// DataPilot Migration -bool ScDPNormalResultMember::IsValidEntry( const vector< SCROW >& aMembers ) const -{ - return GetEntryStatus( aMembers ) != ENTRY_INVALID; -} -// End Comments - -ENTRYSTATUS ScDPNormalResultMember::GetEntryStatus( const vector< SCROW >& aMembers ) const -{ - if ( !IsValid() ) - return ENTRY_INVALID; - - const ScDPResultDimension* pChildDim = GetChildDimension(); - if (pChildDim) - { - if (aMembers.size() < 2) - return ENTRY_INVALID; - - vector</*ScDPItemData*/SCROW>::const_iterator itr = aMembers.begin(); - vector</*ScDPItemData*/SCROW> aChildMembers(++itr, aMembers.end()); - return pChildDim->GetEntryStatus(aChildMembers); - } - else if( bHasHiddenDetails ) - return ENTRY_HASHIDDENDETAIL; - else - return ENTRY_VALID; -} - -void ScDPNormalResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, - size_t nPos, ScDPInitState& rInitState , - BOOL bInitChild /*= TRUE */) - { - // with LateInit, initialize only those members that have data - if ( pResultData->IsLateInit() ) - return; - - bInitialized = TRUE; - - if (nPos >= ppDim.size() ) - return; - - // skip child dimension if details are not shown - if ( GetDPMember() && !GetDPMember()->getShowDetails() ) - { - // Wang Xu Ming -- 2009-6-16 - // Show DataLayout dimention - nMemberStep = 1; - while ( nPos < ppDim.size() ) - { - if ( ppDim[nPos] ->getIsDataLayoutDimension() ) - { - if ( !pChildDimension ) - pChildDimension = new ScDPResultDimension( pResultData ); - pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState , FALSE ); - return; - } - else - { //find next dim - nPos ++; - nMemberStep ++; - } - } - // End Comments - bHasHiddenDetails = TRUE; // only if there is a next dimension - return; - } - - if ( bInitChild ) - { - pChildDimension = new ScDPResultDimension( pResultData ); - pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState, TRUE ); - } -} - -// Wang Xu Ming -- 2009-6-10 -// DataPilot Migration -void ScDPNormalResultMember::LateInitFrom( LateInitParams& rParams/*const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, - const vector< SCROW >& pItemData, size_t nPos, - ScDPInitState& rInitState ) -// End Comments -{ - // without LateInit, everything has already been initialized - if ( !pResultData->IsLateInit() ) - return; - - bInitialized = TRUE; - - if ( rParams.IsEnd( nPos ) /*nPos >= ppDim.size()*/) - // No next dimension. Bail out. - return; - - // skip child dimension if details are not shown - if ( GetDPMember() && !GetDPMember()->getShowDetails() ) - { - // Wang Xu Ming -- 2009-6-16 - // DataPilot Migration - // Show DataLayout dimention - nMemberStep = 1; - while ( !rParams.IsEnd( nPos ) ) - { - if ( rParams.GetDim( nPos ) ->getIsDataLayoutDimension() ) - { - if ( !pChildDimension ) - pChildDimension = new ScDPResultDimension( pResultData ); - rParams.SetInitChild( FALSE ); - pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); - return; - } - else - { //find next dim - nPos ++; - nMemberStep ++; - } - } - // End Comments - bHasHiddenDetails = TRUE; // only if there is a next dimension - return; - } - - // LateInitFrom is called several times... - if ( rParams.GetInitChild() ) - { - if ( !pChildDimension ) - pChildDimension = new ScDPResultDimension( pResultData ); - pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); - } -} - -BOOL ScDPNormalResultMember::IsSubTotalInTitle(long nMeasure) const -{ - BOOL bRet = FALSE; - if ( pChildDimension && /*pParentLevel*/GetParentLevel() && - /*pParentLevel*/GetParentLevel()->IsOutlineLayout() && /*pParentLevel*/GetParentLevel()->IsSubtotalsAtTop() ) - { - long nUserSubStart; - long nSubTotals = GetSubTotalCount( &nUserSubStart ); - nSubTotals -= nUserSubStart; // visible count - if ( nSubTotals ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nSubTotals *= pResultData->GetMeasureCount(); // number of subtotals that will be inserted - - // only a single subtotal row will be shown in the outline title row - if ( nSubTotals == 1 ) - bRet = TRUE; - } - } - return bRet; -} - -long ScDPNormalResultMember::GetSize(long nMeasure) const -{ - if ( !IsVisible() ) - return 0; - const ScDPLevel* pParentLevel = GetParentLevel(); - long nExtraSpace = 0; - if ( pParentLevel && pParentLevel->IsAddEmpty() ) - ++nExtraSpace; - - if ( pChildDimension ) - { - // outline layout takes up an extra row for the title only if subtotals aren't shown in that row - if ( pParentLevel && pParentLevel->IsOutlineLayout() && !IsSubTotalInTitle( nMeasure ) ) - ++nExtraSpace; - - long nSize = pChildDimension->GetSize(nMeasure); - long nUserSubStart; - long nUserSubCount = GetSubTotalCount( &nUserSubStart ); - nUserSubCount -= nUserSubStart; // for output size, use visible count - if ( nUserSubCount ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nSize += pResultData->GetMeasureCount() * nUserSubCount; - else - nSize += nUserSubCount; - } - return nSize + nExtraSpace; - } - else - { - if ( nMeasure == SC_DPMEASURE_ALL ) - return pResultData->GetMeasureCount() + nExtraSpace; - else - return 1 + nExtraSpace; - } -} - - -BOOL ScDPNormalResultMember::IsVisible() const -{ - // not initialized -> shouldn't be there at all - // (allocated only to preserve ordering) - const ScDPLevel* pParentLevel = GetParentLevel(); - return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid() && bInitialized; -} - -BOOL ScDPNormalResultMember::IsValid() const -{ - // non-Valid members are left out of calculation - - // was member set no invisible at the DataPilotSource? - const ScDPMember* pMemberDesc =GetDPMember(); - if ( pMemberDesc && !pMemberDesc->getIsVisible() ) - return FALSE; - - if ( bAutoHidden ) - return FALSE; - - return TRUE; -} - -BOOL ScDPNormalResultMember::HasHiddenDetails() const -{ - // bHasHiddenDetails is set only if the "show details" flag is off, - // and there was a child dimension to skip - - return bHasHiddenDetails; -} - -long ScDPNormalResultMember::GetSubTotalCount( long* pUserSubStart ) const -{ - if ( pUserSubStart ) - *pUserSubStart = 0; // default - - const ScDPLevel* pParentLevel = GetParentLevel(); - - if ( bForceSubTotal ) // set if needed for root members - return 1; // grand total is always "automatic" - else if ( pParentLevel ) - { - //! direct access via ScDPLevel - - uno::Sequence<sheet::GeneralFunction> aSeq = pParentLevel->getSubTotals(); - long nSequence = aSeq.getLength(); - if ( nSequence && aSeq[0] != sheet::GeneralFunction_AUTO ) - { - // For manual subtotals, always add "automatic" as first function - // (used for calculation, but not for display, needed for sorting, see lcl_GetForceFunc) - - ++nSequence; - if ( pUserSubStart ) - *pUserSubStart = 1; // visible subtotals start at 1 - } - return nSequence; - } - else - return 0; -} - -void ScDPNormalResultMember::ProcessData( const vector< SCROW >& aChildMembers, const ScDPResultDimension* pDataDim, - const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues ) -{ - SetHasElements(); - - if (pChildDimension) - pChildDimension->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues ); - - if ( !pDataRoot ) - { - pDataRoot = new ScDPDataMember( pResultData, NULL ); - if ( pDataDim ) - pDataRoot->InitFrom( pDataDim ); // recursive - } - - ScDPSubTotalState aSubState; // initial state - - long nUserSubCount = GetSubTotalCount(); - - // Calculate at least automatic if no subtotals are selected, - // show only own values if there's no child dimension (innermost). - if ( !nUserSubCount || !pChildDimension ) - nUserSubCount = 1; - - const ScDPLevel* pParentLevel = GetParentLevel(); - - for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" - { - // #i68338# if nUserSubCount is 1 (automatic only), don't set nRowSubTotalFunc - if ( pChildDimension && nUserSubCount > 1 ) - { - aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos ); - } - - pDataRoot->ProcessData( aDataMembers, aValues, aSubState ); - } -} - -void ScDPNormalResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences, - long& rPos, long nMeasure, BOOL bRoot, - const String* pMemberName, - const String* pMemberCaption ) -{ - // IsVisible() test is in ScDPResultDimension::FillMemberResults - // (not on data layout dimension) - - long nSize = GetSize(nMeasure); - sheet::MemberResult* pArray = pSequences->getArray(); - DBG_ASSERT( rPos+nSize <= pSequences->getLength(), "bumm" ); - - BOOL bIsNumeric = FALSE; - String aName; - if ( pMemberName ) // if pMemberName != NULL, use instead of real member name - aName = *pMemberName; - else - { - ScDPItemData aItemData; - FillItemData( aItemData ); - aName = aItemData.GetString(); - bIsNumeric = aItemData.IsValue(); - } - const ScDPDimension* pParentDim = GetParentDim(); - if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) ) - { - // Numeric group dimensions use numeric entries for proper sorting, - // but the group titles must be output as text. - bIsNumeric = FALSE; - } - - String aCaption = aName; - if ( pMemberCaption ) // use pMemberCaption if != NULL - aCaption = *pMemberCaption; - if (!aCaption.Len()) - aCaption = ScGlobal::GetRscString(STR_EMPTYDATA); - - if ( !bIsNumeric ) - { - // add a "'" character so a string isn't parsed as value in the output cell - //! have a separate bit in Flags (MemberResultFlags) instead? - aCaption.Insert( (sal_Unicode) '\'', 0 ); - } - - if ( nSize && !bRoot ) // root is overwritten by first dimension - { - pArray[rPos].Name = rtl::OUString(aName); - pArray[rPos].Caption = rtl::OUString(aCaption); - pArray[rPos].Flags |= sheet::MemberResultFlags::HASMEMBER; - - // set "continue" flag (removed for subtotals later) - for (long i=1; i<nSize; i++) - pArray[rPos+i].Flags |= sheet::MemberResultFlags::CONTINUE; - } - - const ScDPLevel* pParentLevel = GetParentLevel(); - long nExtraSpace = 0; - if ( pParentLevel && pParentLevel->IsAddEmpty() ) - ++nExtraSpace; - - BOOL bTitleLine = FALSE; - if ( pParentLevel && pParentLevel->IsOutlineLayout() ) - bTitleLine = TRUE; - - // if the subtotals are shown at the top (title row) in outline layout, - // no extra row for the subtotals is needed - BOOL bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); - - BOOL bHasChild = ( pChildDimension != NULL ); - if (bHasChild) - { - if ( bTitleLine ) // in tabular layout the title is on a separate row - ++rPos; // -> fill child dimension one row below - - if (bRoot) // same sequence for root member - pChildDimension->FillMemberResults( pSequences, rPos, nMeasure ); - else - // Wang Xu Ming -- 2009-6-16 - // DataPilot Migration - // for show details - pChildDimension->FillMemberResults( pSequences + nMemberStep/*1*/, rPos, nMeasure ); - // End Comments - - if ( bTitleLine ) // title row is included in GetSize, so the following - --rPos; // positions are calculated with the normal values - } - - rPos += nSize; - - long nUserSubStart; - long nUserSubCount = GetSubTotalCount(&nUserSubStart); - if ( nUserSubCount && pChildDimension && !bSubTotalInTitle ) - { - long nMemberMeasure = nMeasure; - long nSubSize = pResultData->GetCountForMeasure(nMeasure); - - rPos -= nSubSize * (nUserSubCount - nUserSubStart); // GetSize includes space for SubTotal - rPos -= nExtraSpace; // GetSize includes the empty line - - for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++) - { - for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nMemberMeasure = nSubCount; - - ScSubTotalFunc eForce = SUBTOTAL_FUNC_NONE; - if (bHasChild) - eForce = lcl_GetForceFunc( pParentLevel, nUserPos ); - - String aSubStr = aName; //! caption? - aSubStr += ' '; - aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce); - - pArray[rPos].Name = rtl::OUString(aName); - pArray[rPos].Caption = rtl::OUString(aSubStr); - pArray[rPos].Flags = ( pArray[rPos].Flags | - ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL) ) & - ~sheet::MemberResultFlags::CONTINUE; - - if ( nMeasure == SC_DPMEASURE_ALL ) - { - // data layout dimension is (direct/indirect) child of this. - // data layout dimension must have name for all entries. - - uno::Sequence<sheet::MemberResult>* pLayoutSeq = pSequences; - if (!bRoot) - ++pLayoutSeq; - ScDPResultDimension* pLayoutDim = pChildDimension; - while ( pLayoutDim && !pLayoutDim->IsDataLayout() ) - { - pLayoutDim = pLayoutDim->GetFirstChildDimension(); - ++pLayoutSeq; - } - if ( pLayoutDim ) - { - sheet::MemberResult* pLayoutArray = pLayoutSeq->getArray(); - String aDataName = pResultData->GetMeasureDimensionName(nMemberMeasure); - pLayoutArray[rPos].Name = rtl::OUString(aDataName); - } - } - - rPos += 1; - } - } - - rPos += nExtraSpace; // add again (subtracted above) - } -} - -void ScDPNormalResultMember::FillDataResults( const ScDPResultMember* pRefMember, - uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence, - long& rRow, long nMeasure ) const -{ - // IsVisible() test is in ScDPResultDimension::FillDataResults - // (not on data layout dimension) - const ScDPLevel* pParentLevel = GetParentLevel(); - long nStartRow = rRow; - - long nExtraSpace = 0; - if ( pParentLevel && pParentLevel->IsAddEmpty() ) - ++nExtraSpace; - - BOOL bTitleLine = FALSE; - if ( pParentLevel && pParentLevel->IsOutlineLayout() ) - bTitleLine = TRUE; - - BOOL bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); - - BOOL bHasChild = ( pChildDimension != NULL ); - if (bHasChild) - { - if ( bTitleLine ) // in tabular layout the title is on a separate row - ++rRow; // -> fill child dimension one row below - - pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure ); // doesn't modify rRow - rRow += (USHORT) GetSize( nMeasure ); - - if ( bTitleLine ) // title row is included in GetSize, so the following - --rRow; // positions are calculated with the normal values - } - - long nUserSubStart; - long nUserSubCount = GetSubTotalCount(&nUserSubStart); - if ( nUserSubCount || !bHasChild ) - { - // Calculate at least automatic if no subtotals are selected, - // show only own values if there's no child dimension (innermost). - if ( !nUserSubCount || !bHasChild ) - { - nUserSubCount = 1; - nUserSubStart = 0; - } - - long nMemberMeasure = nMeasure; - long nSubSize = pResultData->GetCountForMeasure(nMeasure); - if (bHasChild) - { - rRow -= nSubSize * ( nUserSubCount - nUserSubStart ); // GetSize includes space for SubTotal - rRow -= nExtraSpace; // GetSize includes the empty line - } - - long nMoveSubTotal = 0; - if ( bSubTotalInTitle ) - { - nMoveSubTotal = rRow - nStartRow; // force to first (title) row - rRow = nStartRow; - } - - if ( pDataRoot ) - { - ScDPSubTotalState aSubState; // initial state - - for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++) - { - if ( bHasChild && nUserSubCount > 1 ) - { - aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); - } - - for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nMemberMeasure = nSubCount; - else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) - nMemberMeasure = SC_DPMEASURE_ALL; - - DBG_ASSERT( rRow < rSequence.getLength(), "bumm" ); - uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rRow]; - long nSeqCol = 0; - pDataRoot->FillDataRow( pRefMember, rSubSeq, nSeqCol, nMemberMeasure, bHasChild, aSubState ); - - rRow += 1; - } - } - } - else - rRow += nSubSize * ( nUserSubCount - nUserSubStart ); // empty rows occur when ShowEmpty is true - - // add extra space again if subtracted from GetSize above, - // add to own size if no children - rRow += nExtraSpace; - - rRow += nMoveSubTotal; - } -} - -void ScDPNormalResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const -{ - // IsVisible() test is in ScDPResultDimension::FillDataResults - // (not on data layout dimension) - - BOOL bHasChild = ( pChildDimension != NULL ); - - long nUserSubCount = GetSubTotalCount(); - // process subtotals even if not shown -// if ( nUserSubCount || !bHasChild ) - { - // Calculate at least automatic if no subtotals are selected, - // show only own values if there's no child dimension (innermost). - if ( !nUserSubCount || !bHasChild ) - nUserSubCount = 1; - - long nMemberMeasure = nMeasure; - long nSubSize = pResultData->GetCountForMeasure(nMeasure); - - if ( pDataRoot ) - { - ScDPSubTotalState aSubState; // initial state - - for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" - { - if ( bHasChild && nUserSubCount > 1 ) - { - aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); - } - - for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nMemberMeasure = nSubCount; - else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) - nMemberMeasure = SC_DPMEASURE_ALL; - - pDataRoot->UpdateDataRow( pRefMember, nMemberMeasure, bHasChild, aSubState ); - } - } - } - } - - if (bHasChild) // child dimension must be processed last, so the column total is known - { - pChildDimension->UpdateDataResults( pRefMember, nMeasure ); - } -} - -void ScDPNormalResultMember::SortMembers( ScDPResultMember* pRefMember ) -{ - BOOL bHasChild = ( pChildDimension != NULL ); - if (bHasChild) - pChildDimension->SortMembers( pRefMember ); // sorting is done at the dimension - - if ( IsRoot() && pDataRoot ) - { - // use the row root member to sort columns - // sub total count is always 1 - - pDataRoot->SortMembers( pRefMember ); - } -} - -void ScDPNormalResultMember::DoAutoShow( ScDPResultMember* pRefMember ) -{ - BOOL bHasChild = ( pChildDimension != NULL ); - if (bHasChild) - pChildDimension->DoAutoShow( pRefMember ); // sorting is done at the dimension - - if ( IsRoot()&& pDataRoot ) - { - // use the row root member to sort columns - // sub total count is always 1 - - pDataRoot->DoAutoShow( pRefMember ); - } -} - -void ScDPNormalResultMember::ResetResults( BOOL bRoot ) -{ - if (pDataRoot) - pDataRoot->ResetResults(); - - if (pChildDimension) - pChildDimension->ResetResults(); - -// Wang Xu Ming -- 3/4/2009 -// Dim refresh and filter. SODC_19023 - // if (!bRoot) - // bHasElements = FALSE; -// End Comments -} - -void ScDPNormalResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const -{ - // IsVisible() test is in ScDPResultDimension::FillDataResults - // (not on data layout dimension) - - rTotals.SetInColRoot( IsRoot() ); - - BOOL bHasChild = ( pChildDimension != NULL ); - - long nUserSubCount = GetSubTotalCount(); - if ( nUserSubCount || !bHasChild ) - { - // Calculate at least automatic if no subtotals are selected, - // show only own values if there's no child dimension (innermost). - if ( !nUserSubCount || !bHasChild ) - nUserSubCount = 1; - - long nMemberMeasure = nMeasure; - long nSubSize = pResultData->GetCountForMeasure(nMeasure); - - if ( pDataRoot ) - { - ScDPSubTotalState aSubState; // initial state - - for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" - { - if ( bHasChild && nUserSubCount > 1 ) - { - aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel(), nUserPos ); - } - - for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) - { - if ( nMeasure == SC_DPMEASURE_ALL ) - nMemberMeasure = nSubCount; - else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) - nMemberMeasure = SC_DPMEASURE_ALL; - - pDataRoot->UpdateRunningTotals( pRefMember, nMemberMeasure, - bHasChild, aSubState, rRunning, rTotals, *this ); - } - } - } - } - - if (bHasChild) // child dimension must be processed last, so the column total is known - { - pChildDimension->UpdateRunningTotals( pRefMember, nMeasure, rRunning, rTotals ); - } -} - -void ScDPNormalResultMember::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const -{ - lcl_DumpRow( String::CreateFromAscii("ScDPResultMember"), GetName(), NULL, pDoc, rPos ); - SCROW nStartRow = rPos.Row(); - - if (pDataRoot) - pDataRoot->DumpState( pRefMember, pDoc, rPos ); - - if (pChildDimension) - pChildDimension->DumpState( pRefMember, pDoc, rPos ); - - lcl_Indent( pDoc, nStartRow, rPos ); -} - -ScDPAggData* ScDPNormalResultMember::GetColTotal( long nMeasure ) const -{ - return lcl_GetChildTotal( const_cast<ScDPAggData*>(&aColTotal), nMeasure ); -} - -void ScDPNormalResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const -{ - if (pChildDimension) - pChildDimension->FillVisibilityData(rData); -} -// Wang Xu Ming -- 2009-6-10 -// DataPilot Migration -SCROW ScDPNormalResultMember::GetDataId( ) const -{ -// TODO: - const ScDPMember* pMemberDesc = GetDPMember(); - if (pMemberDesc) - return pMemberDesc->GetItemDataId(); - return -1; -} - -// ----------------------------------------------------------------------- -ScDPHideDetailsMember:: ScDPHideDetailsMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, - BOOL bForceSub ):ScDPResultMember(pData,rParentDimData, bForceSub) -{ - pOrigMember = new ScDPNormalResultMember(pData,rParentDimData, bForceSub); - -}
\ No newline at end of file diff --git a/sc/source/core/data/dptabresmember.hxx b/sc/source/core/data/dptabresmember.hxx deleted file mode 100644 index 72657167d07d..000000000000 --- a/sc/source/core/data/dptabresmember.hxx +++ /dev/null @@ -1,161 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright IBM Corporation 2009. - * Copyright 2009 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: dptabresmember.hxx,v $ - * $Revision: 1.0 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef DPTABRESMEMBER_HXX -#define DPTABRESMEMBER_HXX - -class ScDPNormalResultMember: public ScDPResultMember -{ -private: - // Wang Xu Ming -- 2009-6-9 - // DataPilot Migration - ScDPParentDimData aParentDimData; - // End Comments - BOOL bHasElements:1; - BOOL bForceSubTotal:1; - BOOL bHasHiddenDetails:1; - BOOL bInitialized:1; - BOOL bAutoHidden:1; - ScDPAggData aColTotal; // to store column totals - -// Wang Xu Ming -- 2009-6-9 -// DataPilot Migration - USHORT nMemberStep; // step to show details -// End Comments -public: - // Wang Xu Ming -- 2009-6-9 - // DataPilot Migration - ScDPNormalResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, - BOOL bForceSub ); //! Ref - ScDPNormalResultMember( const ScDPResultData* pData, BOOL bForceSub ); - // End Comments - ~ScDPNormalResultMember(); - - // Wang Xu Ming -- 2009-6-9 - // DataPilot Migration - // Add parameter: BOOL bInitChild - void InitFrom( const ::std::vector<ScDPDimension*>& ppDim, - const ::std::vector<ScDPLevel*>& ppLev, - size_t nPos, - ScDPInitState& rInitState, - BOOL bInitChild = TRUE ); - // End Comments - // Wang Xu Ming -- 2009-6-9 - // DataPilot Migration - void LateInitFrom( - LateInitParams& rParams, - const ::std::vector< SCROW >& pItemData, - size_t nPos, - ScDPInitState& rInitState); - // End Comments - - String GetName() const; - void FillItemData( ScDPItemData& rData ) const; - BOOL IsValid() const; - BOOL IsVisible() const; - long GetSize(long nMeasure) const; - BOOL HasHiddenDetails() const; - BOOL IsSubTotalInTitle(long nMeasure) const; - -// BOOL SubTotalEnabled() const; - long GetSubTotalCount( long* pUserSubStart = NULL ) const; - -// Wang Xu Ming -- 2009-6-9 -// DataPilot Migration -// Use item index -// BOOL IsNamedItem( const ScDPItemData& r ) const; - BOOL IsNamedItem( SCROW nIndex ) const; -// End Comments - bool IsValidEntry( const ::std::vector< SCROW >& aMembers ) const; - ENTRYSTATUS GetEntryStatus( const ::std::vector<SCROW>& aMembers ) const; - - void SetHasElements() { bHasElements = TRUE; } - void SetAutoHidden() { bAutoHidden = TRUE; } - - void ProcessData( const ::std::vector<SCROW>& aChildMembers, - const ScDPResultDimension* pDataDim, - const ::std::vector<SCROW>& aDataMembers, - const ::std::vector<ScDPValueData>& aValues ); - - void FillMemberResults( com::sun::star::uno::Sequence< - com::sun::star::sheet::MemberResult>* pSequences, - long& rPos, long nMeasure, BOOL bRoot, - const String* pMemberName, - const String* pMemberCaption ); - - void FillDataResults( const ScDPResultMember* pRefMember, - com::sun::star::uno::Sequence< - com::sun::star::uno::Sequence< - com::sun::star::sheet::DataResult> >& rSequence, - long& rRow, long nMeasure ) const; - - void UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const; - void UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const; - - void SortMembers( ScDPResultMember* pRefMember ); - void DoAutoShow( ScDPResultMember* pRefMember ); - - void ResetResults( BOOL bRoot ); - - void DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const; - - // Wang Xu Ming -- 2009-6-9 - // DataPilot Migration - const ScDPDimension* GetParentDim() const { return aParentDimData.mpParentDim; } //! Ref - const ScDPLevel* GetParentLevel() const { return aParentDimData.mpParentLevel; } //! Ref - const ScDPMember* GetDPMember()const { return aParentDimData.mpMemberDesc; } //! Ref - inline SCROW GetOrder() const { return aParentDimData.mnOrder; } //! Ref - inline BOOL IsRoot() const { return GetParentLevel() == NULL; } - // End Comments - - ScDPAggData* GetColTotal( long nMeasure ) const; - - void FillVisibilityData(ScDPResultVisibilityData& rData) const; -// Wang Xu Ming -- 2009-6-10 -// DataPilot Migration - SCROW GetDataId( ) const ; -// End Comments -}; - -class ScDPHideDetailsMember: public ScDPResultMember -{ -private: - ScDPNormalResultMember * pOrigMember; -public: - ScDPHideDetailsMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, - BOOL bForceSub ); - - -}; - - -#endif //DPTABRESMEMBER_HXX diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 3d7fc007818b..4df709768279 100755..100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -592,12 +592,14 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool b { //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden) + SCCOL nLastCol; + SCROW nLastRow; if( bValid1 ) { Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); - if( (pDoc->GetColFlags( nCol1, nTab1 ) & CR_HIDDEN) == 0 ) + if (!pDoc->ColHidden(nCol1, nTab1, nLastCol)) aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4; - if( (pDoc->GetRowFlags( nRow1, nTab1 ) & CR_HIDDEN) == 0 ) + if (!pDoc->RowHidden(nRow1, nTab1, nLastRow)) aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2; TwipsToMM( aPos.X() ); TwipsToMM( aPos.Y() ); @@ -629,9 +631,9 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool b if( bValid2 ) { Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) ); - if( (pDoc->GetColFlags( nCol2, nTab2 ) & CR_HIDDEN) == 0 ) + if (!pDoc->ColHidden(nCol2, nTab2, nLastCol)) aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4; - if( (pDoc->GetRowFlags( nRow2, nTab2 ) & CR_HIDDEN) == 0 ) + if (!pDoc->RowHidden(nRow2, nTab2, nLastRow)) aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2; TwipsToMM( aPos.X() ); TwipsToMM( aPos.Y() ); @@ -735,8 +737,8 @@ BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) co } if (!bSetVer) { - nStartY = pDoc->FastGetRowHeight( 0, rRange.aStart.Row()-1, nTab); - nEndY = nStartY + pDoc->FastGetRowHeight( rRange.aStart.Row(), + nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab); + nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(), rRange.aEnd.Row(), nTab); nStartY = (long)(nStartY * HMM_PER_TWIPS); nEndY = (long)(nEndY * HMM_PER_TWIPS); @@ -817,9 +819,9 @@ BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) co { nStartY = (long) (nStartY / HMM_PER_TWIPS); nEndY = (long) (nEndY / HMM_PER_TWIPS); - SCROW nRow = pDoc->FastGetRowForHeight( nTab, nStartY); + SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY); rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0); - nRow = pDoc->FastGetRowForHeight( nTab, nEndY); + nRow = pDoc->GetRowForHeight( nTab, nEndY); rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW : (nRow>0 ? (nRow-1) : 0)); } @@ -1041,9 +1043,9 @@ void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCR for (SCsCOL s=-1; s>=nDx; s--) aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab); if (nDy > 0) - aMove.Y() += pDoc->FastGetRowHeight( nRow1, nRow1+nDy-1, nTab); + aMove.Y() += pDoc->GetRowHeight( nRow1, nRow1+nDy-1, nTab); else - aMove.Y() -= pDoc->FastGetRowHeight( nRow1+nDy, nRow1-1, nTab); + aMove.Y() -= pDoc->GetRowHeight( nRow1+nDy, nRow1-1, nTab); if ( bNegativePage ) aMove.X() = -aMove.X(); @@ -1115,9 +1117,9 @@ void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips ) Rectangle aRect; Point aTopLeft; - aRect.Top() += pDoc->FastGetRowHeight( 0, nRow-1, nTab); + aRect.Top() += pDoc->GetRowHeight( 0, nRow-1, nTab); aTopLeft.Y() = aRect.Top(); - aRect.Top() += pDoc->FastGetRowHeight(nRow,nTab); + aRect.Top() += pDoc->GetRowHeight(nRow, nTab); aRect.Bottom() = MAXMM; aRect.Left() = 0; @@ -1143,14 +1145,14 @@ BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow ) Rectangle aTestRect; - aTestRect.Top() += pDoc->FastGetRowHeight( 0, nStartRow-1, nTab); + aTestRect.Top() += pDoc->GetRowHeight( 0, nStartRow-1, nTab); if (nEndRow==MAXROW) aTestRect.Bottom() = MAXMM; else { aTestRect.Bottom() = aTestRect.Top(); - aTestRect.Bottom() += pDoc->FastGetRowHeight( nStartRow, nEndRow, nTab); + aTestRect.Bottom() += pDoc->GetRowHeight( nStartRow, nEndRow, nTab); TwipsToMM( aTestRect.Bottom() ); } @@ -1706,7 +1708,7 @@ Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, boo for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol ) aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); if( rPos.Row() > 0 ) - aTopLeft.Y() += rDoc.FastGetRowHeight( 0, rPos.Row() - 1, rPos.Tab() ); + aTopLeft.Y() += rDoc.GetRowHeight( 0, rPos.Row() - 1, rPos.Tab() ); // find bottom-right position of passed cell address ScAddress aEndPos = rPos; @@ -1721,7 +1723,7 @@ Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, boo Point aBotRight = aTopLeft; for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol ) aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); - aBotRight.Y() += rDoc.FastGetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() ); + aBotRight.Y() += rDoc.GetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() ); // twips -> 1/100 mm aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS ); diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 05e0d98c9719..8418cb3c3a25 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -52,7 +52,6 @@ #include "conditio.hxx" #include "stlpool.hxx" - // ----------------------------------------------------------------------- const USHORT ROWINFO_MAX = 1024; @@ -97,11 +96,13 @@ void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY, rStartY = nY; BOOL bHOver = pInfo->bHOverlapped; BOOL bVOver = pInfo->bVOverlapped; + SCCOL nLastCol; + SCROW nLastRow; while (bHOver) // nY konstant { --rStartX; - if (rStartX >= (SCsCOL) nX1 && (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0) + if (rStartX >= (SCsCOL) nX1 && !pDoc->ColHidden(rStartX, nTab, nLastCol)) { bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped; bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped; @@ -123,8 +124,8 @@ void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY, --nArrY; // lokale Kopie ! if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 && - (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 && - (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 && + !pDoc->ColHidden(rStartX, nTab, nLastCol) && + !pDoc->RowHidden(rStartY, nTab, nLastRow) && (SCsROW) pRowInfo[nArrY].nRowNo == rStartY) { bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped; @@ -141,8 +142,8 @@ void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY, const ScMergeAttr* pMerge; if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 && - (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 && - (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 && + !pDoc->ColHidden(rStartX, nTab, nLastCol) && + !pDoc->RowHidden(rStartY, nTab, nLastRow) && (SCsROW) pRowInfo[nArrY].nRowNo == rStartY) { pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr-> @@ -155,12 +156,6 @@ void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY, rEndY = rStartY + pMerge->GetRowMerge() - 1; } -inline BOOL ScDocument::RowHidden( SCROW nRow, SCTAB nTab ) -{ - return ( pTab[nTab]->pRowFlags->GetValue(nRow) & CR_HIDDEN ) != 0; -} - - #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x] void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, @@ -356,7 +351,7 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX nX = nArrX-1; if ( ValidCol(nX) ) { - if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // Spalte nicht versteckt + if (!ColHidden(nX, nTab)) { USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX); if (!nThisWidth) @@ -376,7 +371,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes // will disturb the output - if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // column not hidden + // TODO: Optimize this loop. + if (!ColHidden(nX, nTab)) { USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX); if (!nThisWidth) @@ -481,7 +477,9 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX do { - if ( nArrY==0 || !RowHidden( nCurRow,nTab ) ) + SCROW nLastHiddenRow = -1; + bool bRowHidden = RowHidden(nCurRow, nTab, nLastHiddenRow); + if ( nArrY==0 || !bRowHidden ) { RowInfo* pThisRowInfo = &pRowInfo[nArrY]; if (pBackground != pDefBackground) // Spalten-HG == Standard ? @@ -551,6 +549,12 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX ++nArrY; } + else if (bRowHidden && nLastHiddenRow >= 0) + { + nCurRow = nLastHiddenRow; + if (nCurRow > nThisRow) + nCurRow = nThisRow; + } ++nCurRow; } while (nCurRow <= nThisRow && nCurRow <= nYExtra); diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk index cf51e1e543a4..95ce6bcec179 100755..100644 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -98,9 +98,12 @@ SLOFILES = \ $(SLO)$/patattr.obj \ $(SLO)$/pivot2.obj \ $(SLO)$/poolhelp.obj \ + $(SLO)$/sheetevents.obj \ + $(SLO)$/segmenttree.obj \ $(SLO)$/sortparam.obj \ $(SLO)$/stlpool.obj \ $(SLO)$/stlsheet.obj \ + $(SLO)$/tabbgcolor.obj \ $(SLO)$/table1.obj \ $(SLO)$/table2.obj \ $(SLO)$/table3.obj \ @@ -128,6 +131,7 @@ EXCEPTIONSFILES= \ $(SLO)$/dptabres.obj \ $(SLO)$/dptabdat.obj \ $(SLO)$/global2.obj \ + $(SLO)$/tabbgcolor.obj \ $(SLO)$/table1.obj \ $(SLO)$/table2.obj \ $(SLO)$/table3.obj \ @@ -148,7 +152,8 @@ EXCEPTIONSFILES= \ $(SLO)$/dbdocutl.obj \ $(SLO)$/dptabsrc.obj \ $(SLO)$/drwlayer.obj \ - $(SLO)$/globalx.obj + $(SLO)$/globalx.obj \ + $(SLO)$/segmenttree.obj .IF "$(OS)$(COM)$(CPUNAME)"=="LINUXGCCSPARC" NOOPTFILES= \ @@ -164,7 +169,8 @@ EXCEPTIONSNOOPTFILES= \ .ELSE EXCEPTIONSFILES+= \ $(SLO)$/cell.obj \ - $(SLO)$/global.obj + $(SLO)$/global.obj \ + $(SLO)$/table5.obj .ENDIF # --- Tagets ------------------------------------------------------- diff --git a/sc/source/core/data/olinetab.cxx b/sc/source/core/data/olinetab.cxx index 55f7ba46b898..af444c4b2123 100644 --- a/sc/source/core/data/olinetab.cxx +++ b/sc/source/core/data/olinetab.cxx @@ -41,10 +41,11 @@ #include "global.hxx" #include "rechead.hxx" #include "address.hxx" +#include "table.hxx" //------------------------------------------------------------------------ -ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, BOOL bNewHidden ) : +ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) : nStart ( nNewStart ), nSize ( nNewSize ), bHidden ( bNewHidden ), @@ -93,12 +94,12 @@ void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize ) SetSize( nNewSize ); } -void ScOutlineEntry::SetHidden( BOOL bNewHidden ) +void ScOutlineEntry::SetHidden( bool bNewHidden ) { bHidden = bNewHidden; } -void ScOutlineEntry::SetVisible( BOOL bNewVisible ) +void ScOutlineEntry::SetVisible( bool bNewVisible ) { bVisible = bNewVisible; } @@ -637,10 +638,9 @@ BOOL ScOutlineArray::DeleteSpace( SCCOLROW nStartPos, SCSIZE nSize ) return bNeedSave; } -BOOL ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, - BOOL bShow, const ScBitMaskCompressedArray< SCCOLROW, BYTE>& rHiddenFlags ) +bool ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, ScTable& rTable, bool bCol ) { - BOOL bModified = FALSE; + bool bModified = false; ScSubOutlineIterator aIter( this ); ScOutlineEntry* pEntry; while((pEntry=aIter.GetNext())!=NULL) @@ -654,18 +654,16 @@ BOOL ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, { // #i12341# hide if all columns/rows are hidden, show if at least one // is visible - - SCCOLROW nEnd = rHiddenFlags.GetBitStateEnd( nEntryStart, - CR_HIDDEN, CR_HIDDEN); - BOOL bAllHidden = (nEntryEnd <= nEnd && nEnd < + SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol); + bool bAllHidden = (nEntryEnd <= nEnd && nEnd < ::std::numeric_limits<SCCOLROW>::max()); - BOOL bToggle = ( bShow != bAllHidden ); + bool bToggle = ( bShow != bAllHidden ); if ( bToggle ) { pEntry->SetHidden( !bShow ); SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow ); - bModified = TRUE; + bModified = true; } } } diff --git a/sc/source/core/data/segmenttree.cxx b/sc/source/core/data/segmenttree.cxx new file mode 100644 index 000000000000..86b53582d1d4 --- /dev/null +++ b/sc/source/core/data/segmenttree.cxx @@ -0,0 +1,582 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "segmenttree.hxx" + +#include <mdds/flat_segment_tree.hpp> + +#include <limits> + +using ::std::numeric_limits; + +// ============================================================================ + +template<typename _ValueType, typename _ExtValueType = _ValueType> +class ScFlatSegmentsImpl +{ +public: + typedef _ValueType ValueType; + typedef _ExtValueType ExtValueType; + + struct RangeData + { + SCCOLROW mnPos1; + SCCOLROW mnPos2; + ValueType mnValue; + }; + + ScFlatSegmentsImpl(SCCOLROW nMax, ValueType nDefault); + ScFlatSegmentsImpl(const ScFlatSegmentsImpl& r); + ~ScFlatSegmentsImpl(); + + void setValue(SCCOLROW nPos1, SCCOLROW nPos2, ValueType nValue); + ValueType getValue(SCCOLROW nPos); + ExtValueType getSumValue(SCCOLROW nPos1, SCCOLROW nPos2); + bool getRangeData(SCCOLROW nPos, RangeData& rData); + void removeSegment(SCCOLROW nPos1, SCCOLROW nPos2); + void insertSegment(SCCOLROW nPos, SCCOLROW nSize, bool bSkipStartBoundary); + + SCROW findLastNotOf(ValueType nValue) const; + + // range iteration + bool getFirst(RangeData& rData); + bool getNext(RangeData& rData); + + void enableTreeSearch(bool b) + { + mbTreeSearchEnabled = b; + } + + void setInsertFromBack(bool b) + { + mbInsertFromBack = b; + } + +private: + typedef ::mdds::flat_segment_tree<SCCOLROW, ValueType> fst_type; + fst_type maSegments; + typename fst_type::const_iterator maItr; + + bool mbTreeSearchEnabled:1; + bool mbInsertFromBack:1; +}; + +template<typename _ValueType, typename _ExtValueType> +ScFlatSegmentsImpl<_ValueType, _ExtValueType>::ScFlatSegmentsImpl(SCCOLROW nMax, ValueType nDefault) : + maSegments(0, nMax+1, nDefault), + mbTreeSearchEnabled(true), + mbInsertFromBack(false) +{ +} + +template<typename _ValueType, typename _ExtValueType> +ScFlatSegmentsImpl<_ValueType, _ExtValueType>::ScFlatSegmentsImpl(const ScFlatSegmentsImpl<_ValueType, _ExtValueType>& r) : + maSegments(r.maSegments), + mbTreeSearchEnabled(r.mbTreeSearchEnabled), + mbInsertFromBack(r.mbInsertFromBack) +{ +} + +template<typename _ValueType, typename _ExtValueType> +ScFlatSegmentsImpl<_ValueType, _ExtValueType>::~ScFlatSegmentsImpl() +{ +} + +template<typename _ValueType, typename _ExtValueType> +void ScFlatSegmentsImpl<_ValueType, _ExtValueType>::setValue(SCCOLROW nPos1, SCCOLROW nPos2, ValueType nValue) +{ + if (mbInsertFromBack) + maSegments.insert_back(nPos1, nPos2+1, nValue); + else + maSegments.insert_front(nPos1, nPos2+1, nValue); +} + +template<typename _ValueType, typename _ExtValueType> +typename ScFlatSegmentsImpl<_ValueType, _ExtValueType>::ValueType ScFlatSegmentsImpl<_ValueType, _ExtValueType>::getValue(SCCOLROW nPos) +{ + ValueType nValue = 0; + if (!mbTreeSearchEnabled) + { + maSegments.search(nPos, nValue); + return nValue; + } + + if (!maSegments.is_tree_valid()) + maSegments.build_tree(); + + maSegments.search_tree(nPos, nValue); + return nValue; +} + +template<typename _ValueType, typename _ExtValueType> +typename ScFlatSegmentsImpl<_ValueType, _ExtValueType>::ExtValueType +ScFlatSegmentsImpl<_ValueType, _ExtValueType>::getSumValue(SCCOLROW nPos1, SCCOLROW nPos2) +{ + RangeData aData; + if (!getRangeData(nPos1, aData)) + return 0; + + sal_uInt32 nValue = 0; + + SCROW nCurPos = nPos1; + SCROW nEndPos = aData.mnPos2; + while (nEndPos <= nPos2) + { + nValue += aData.mnValue * (nEndPos - nCurPos + 1); + nCurPos = nEndPos + 1; + if (!getRangeData(nCurPos, aData)) + break; + + nEndPos = aData.mnPos2; + } + if (nCurPos <= nPos2) + { + nEndPos = ::std::min(nEndPos, nPos2); + nValue += aData.mnValue * (nEndPos - nCurPos + 1); + } + return nValue; +} + +template<typename _ValueType, typename _ExtValueType> +bool ScFlatSegmentsImpl<_ValueType, _ExtValueType>::getRangeData(SCCOLROW nPos, RangeData& rData) +{ + ValueType nValue; + SCCOLROW nPos1, nPos2; + + if (mbTreeSearchEnabled) + { + if (!maSegments.is_tree_valid()) + maSegments.build_tree(); + + if (!maSegments.search_tree(nPos, nValue, &nPos1, &nPos2)) + return false; + } + else + { + // Conduct leaf-node only search. Faster when searching between range insertion. + if (!maSegments.search(nPos, nValue, &nPos1, &nPos2)) + return false; + } + + rData.mnPos1 = nPos1; + rData.mnPos2 = nPos2-1; // end point is not inclusive. + rData.mnValue = nValue; + return true; +} + +template<typename _ValueType, typename _ExtValueType> +void ScFlatSegmentsImpl<_ValueType, _ExtValueType>::removeSegment(SCCOLROW nPos1, SCCOLROW nPos2) +{ + maSegments.shift_left(nPos1, nPos2); +} + +template<typename _ValueType, typename _ExtValueType> +void ScFlatSegmentsImpl<_ValueType, _ExtValueType>::insertSegment(SCCOLROW nPos, SCCOLROW nSize, bool bSkipStartBoundary) +{ + maSegments.shift_right(nPos, nSize, bSkipStartBoundary); +} + +template<typename _ValueType, typename _ExtValueType> +SCCOLROW ScFlatSegmentsImpl<_ValueType, _ExtValueType>::findLastNotOf(ValueType nValue) const +{ + SCCOLROW nPos = numeric_limits<SCCOLROW>::max(); // position not found. + typename fst_type::const_reverse_iterator itr = maSegments.rbegin(), itrEnd = maSegments.rend(); + // Note that when searching in reverse direction, we need to skip the first + // node, since the right-most leaf node does not store a valid value. + for (++itr; itr != itrEnd; ++itr) + { + if (itr->second != nValue) + { + nPos = (--itr)->first - 1; + break; + } + } + return nPos; +} + +template<typename _ValueType, typename _ExtValueType> +bool ScFlatSegmentsImpl<_ValueType, _ExtValueType>::getFirst(RangeData& rData) +{ + maItr = maSegments.begin(); + return getNext(rData); +} + +template<typename _ValueType, typename _ExtValueType> +bool ScFlatSegmentsImpl<_ValueType, _ExtValueType>::getNext(RangeData& rData) +{ + typename fst_type::const_iterator itrEnd = maSegments.end(); + if (maItr == itrEnd) + return false; + + rData.mnPos1 = maItr->first; + rData.mnValue = maItr->second; + + ++maItr; + if (maItr == itrEnd) + return false; + + rData.mnPos2 = maItr->first - 1; + return true; +} + +// ============================================================================ + +class ScFlatUInt16SegmentsImpl : public ScFlatSegmentsImpl<sal_uInt16, sal_uInt32> +{ +public: + explicit ScFlatUInt16SegmentsImpl(SCCOLROW nMax, sal_uInt16 nDefault) : + ScFlatSegmentsImpl<sal_uInt16, sal_uInt32>(nMax, nDefault) + { + } +}; + +// ---------------------------------------------------------------------------- + +class ScFlatBoolSegmentsImpl : public ScFlatSegmentsImpl<bool> +{ +public: + explicit ScFlatBoolSegmentsImpl(SCCOLROW nMax) : + ScFlatSegmentsImpl<bool>(nMax, false) + { + } + + void setTrue(SCCOLROW nPos1, SCCOLROW nPos2); + void setFalse(SCCOLROW nPos1, SCCOLROW nPos2); +}; + +void ScFlatBoolSegmentsImpl::setTrue(SCCOLROW nPos1, SCCOLROW nPos2) +{ + setValue(nPos1, nPos2, true); +} + +void ScFlatBoolSegmentsImpl::setFalse(SCCOLROW nPos1, SCCOLROW nPos2) +{ + setValue(nPos1, nPos2, false); +} + +// ============================================================================ + +ScFlatBoolRowSegments::ForwardIterator::ForwardIterator(ScFlatBoolRowSegments& rSegs) : + mrSegs(rSegs), mnCurPos(0), mnLastPos(-1), mbCurValue(false) +{ +} + +bool ScFlatBoolRowSegments::ForwardIterator::getValue(SCROW nPos, bool& rVal) +{ + if (nPos >= mnCurPos) + // It can only go in a forward direction. + mnCurPos = nPos; + + if (mnCurPos > mnLastPos) + { + // position not in the current segment. Update the current value. + ScFlatBoolRowSegments::RangeData aData; + if (!mrSegs.getRangeData(mnCurPos, aData)) + return false; + + mbCurValue = aData.mbValue; + mnLastPos = aData.mnRow2; + } + + rVal = mbCurValue; + return true; +} + +SCROW ScFlatBoolRowSegments::ForwardIterator::getLastPos() const +{ + return mnLastPos; +} + +// ---------------------------------------------------------------------------- + +ScFlatBoolRowSegments::RangeIterator::RangeIterator(ScFlatBoolRowSegments& rSegs) : + mrSegs(rSegs) +{ +} + +bool ScFlatBoolRowSegments::RangeIterator::getFirst(RangeData& rRange) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mrSegs.mpImpl->getFirst(aData)) + return false; + + rRange.mnRow1 = static_cast<SCROW>(aData.mnPos1); + rRange.mnRow2 = static_cast<SCROW>(aData.mnPos2); + rRange.mbValue = static_cast<bool>(aData.mnValue); + return true; +} + +bool ScFlatBoolRowSegments::RangeIterator::getNext(RangeData& rRange) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mrSegs.mpImpl->getNext(aData)) + return false; + + rRange.mnRow1 = static_cast<SCROW>(aData.mnPos1); + rRange.mnRow2 = static_cast<SCROW>(aData.mnPos2); + rRange.mbValue = static_cast<bool>(aData.mnValue); + return true; +} + +// ---------------------------------------------------------------------------- + +ScFlatBoolRowSegments::ScFlatBoolRowSegments() : + mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXROW))) +{ +} + +ScFlatBoolRowSegments::ScFlatBoolRowSegments(const ScFlatBoolRowSegments& r) : + mpImpl(new ScFlatBoolSegmentsImpl(*r.mpImpl)) +{ +} + +ScFlatBoolRowSegments::~ScFlatBoolRowSegments() +{ +} + +void ScFlatBoolRowSegments::setTrue(SCROW nRow1, SCROW nRow2) +{ + mpImpl->setTrue(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2)); +} + +void ScFlatBoolRowSegments::setFalse(SCROW nRow1, SCROW nRow2) +{ + mpImpl->setFalse(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2)); +} + +bool ScFlatBoolRowSegments::getValue(SCROW nRow) +{ + return mpImpl->getValue(static_cast<SCCOLROW>(nRow)); +} + +bool ScFlatBoolRowSegments::getRangeData(SCROW nRow, RangeData& rData) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mpImpl->getRangeData(static_cast<SCCOLROW>(nRow), aData)) + return false; + + rData.mbValue = aData.mnValue; + rData.mnRow1 = static_cast<SCROW>(aData.mnPos1); + rData.mnRow2 = static_cast<SCROW>(aData.mnPos2); + return true; +} + +void ScFlatBoolRowSegments::removeSegment(SCROW nRow1, SCROW nRow2) +{ + mpImpl->removeSegment(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2)); +} + +void ScFlatBoolRowSegments::insertSegment(SCROW nRow, SCROW nSize, bool bSkipStartBoundary) +{ + mpImpl->insertSegment(static_cast<SCCOLROW>(nRow), static_cast<SCCOLROW>(nSize), bSkipStartBoundary); +} + +SCROW ScFlatBoolRowSegments::findLastNotOf(bool bValue) const +{ + return static_cast<SCROW>(mpImpl->findLastNotOf(bValue)); +} + +void ScFlatBoolRowSegments::enableTreeSearch(bool bEnable) +{ + mpImpl->enableTreeSearch(bEnable); +} + +void ScFlatBoolRowSegments::setInsertFromBack(bool bInsertFromBack) +{ + mpImpl->setInsertFromBack(bInsertFromBack); +} + +// ============================================================================ + +ScFlatBoolColSegments::ScFlatBoolColSegments() : + mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXCOL))) +{ +} + +ScFlatBoolColSegments::ScFlatBoolColSegments(const ScFlatBoolColSegments& r) : + mpImpl(new ScFlatBoolSegmentsImpl(*r.mpImpl)) +{ +} + +ScFlatBoolColSegments::~ScFlatBoolColSegments() +{ +} + +void ScFlatBoolColSegments::setTrue(SCCOL nCol1, SCCOL nCol2) +{ + mpImpl->setTrue(static_cast<SCCOLROW>(nCol1), static_cast<SCCOLROW>(nCol2)); +} + +void ScFlatBoolColSegments::setFalse(SCCOL nCol1, SCCOL nCol2) +{ + mpImpl->setFalse(static_cast<SCCOLROW>(nCol1), static_cast<SCCOLROW>(nCol2)); +} + +bool ScFlatBoolColSegments::getValue(SCCOL nCol) +{ + return mpImpl->getValue(static_cast<SCCOLROW>(nCol)); +} + +bool ScFlatBoolColSegments::getRangeData(SCCOL nCol, RangeData& rData) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mpImpl->getRangeData(static_cast<SCCOLROW>(nCol), aData)) + return false; + + rData.mbValue = aData.mnValue; + rData.mnCol1 = static_cast<SCCOL>(aData.mnPos1); + rData.mnCol2 = static_cast<SCCOL>(aData.mnPos2); + return true; +} + +void ScFlatBoolColSegments::removeSegment(SCCOL nCol1, SCCOL nCol2) +{ + mpImpl->removeSegment(static_cast<SCCOLROW>(nCol1), static_cast<SCCOLROW>(nCol2)); +} + +void ScFlatBoolColSegments::insertSegment(SCCOL nCol, SCCOL nSize, bool bSkipStartBoundary) +{ + mpImpl->insertSegment(static_cast<SCCOLROW>(nCol), static_cast<SCCOLROW>(nSize), bSkipStartBoundary); +} + +void ScFlatBoolColSegments::enableTreeSearch(bool bEnable) +{ + mpImpl->enableTreeSearch(bEnable); +} + +void ScFlatBoolColSegments::setInsertFromBack(bool bInsertFromBack) +{ + mpImpl->setInsertFromBack(bInsertFromBack); +} + +// ============================================================================ + + +// ============================================================================ + +ScFlatUInt16RowSegments::ForwardIterator::ForwardIterator(ScFlatUInt16RowSegments& rSegs) : + mrSegs(rSegs), mnCurPos(0), mnLastPos(-1), mnCurValue(0) +{ +} + +bool ScFlatUInt16RowSegments::ForwardIterator::getValue(SCROW nPos, sal_uInt16& rVal) +{ + if (nPos >= mnCurPos) + // It can only go in a forward direction. + mnCurPos = nPos; + + if (mnCurPos > mnLastPos) + { + // position not in the current segment. Update the current value. + ScFlatUInt16RowSegments::RangeData aData; + if (!mrSegs.getRangeData(mnCurPos, aData)) + return false; + + mnCurValue = aData.mnValue; + mnLastPos = aData.mnRow2; + } + + rVal = mnCurValue; + return true; +} + +SCROW ScFlatUInt16RowSegments::ForwardIterator::getLastPos() const +{ + return mnLastPos; +} + +// ---------------------------------------------------------------------------- + +ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(sal_uInt16 nDefault) : + mpImpl(new ScFlatUInt16SegmentsImpl(static_cast<SCCOLROW>(MAXROW), nDefault)) +{ +} + +ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(const ScFlatUInt16RowSegments& r) : + mpImpl(new ScFlatUInt16SegmentsImpl(*r.mpImpl)) +{ +} + +ScFlatUInt16RowSegments::~ScFlatUInt16RowSegments() +{ +} + +void ScFlatUInt16RowSegments::setValue(SCROW nRow1, SCROW nRow2, sal_uInt16 nValue) +{ + mpImpl->setValue(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2), nValue); +} + +sal_uInt16 ScFlatUInt16RowSegments::getValue(SCROW nRow) +{ + return mpImpl->getValue(static_cast<SCCOLROW>(nRow)); +} + +sal_uInt32 ScFlatUInt16RowSegments::getSumValue(SCROW nRow1, SCROW nRow2) +{ + return mpImpl->getSumValue(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2)); +} + +bool ScFlatUInt16RowSegments::getRangeData(SCROW nRow, RangeData& rData) +{ + ScFlatUInt16SegmentsImpl::RangeData aData; + if (!mpImpl->getRangeData(static_cast<SCCOLROW>(nRow), aData)) + return false; + + rData.mnRow1 = aData.mnPos1; + rData.mnRow2 = aData.mnPos2; + rData.mnValue = aData.mnValue; + return true; +} + +void ScFlatUInt16RowSegments::removeSegment(SCROW nRow1, SCROW nRow2) +{ + mpImpl->removeSegment(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2)); +} + +void ScFlatUInt16RowSegments::insertSegment(SCROW nRow, SCROW nSize, bool bSkipStartBoundary) +{ + mpImpl->insertSegment(static_cast<SCCOLROW>(nRow), static_cast<SCCOLROW>(nSize), bSkipStartBoundary); +} + +SCROW ScFlatUInt16RowSegments::findLastNotOf(sal_uInt16 nValue) const +{ + return static_cast<SCROW>(mpImpl->findLastNotOf(nValue)); +} + +void ScFlatUInt16RowSegments::enableTreeSearch(bool bEnable) +{ + mpImpl->enableTreeSearch(bEnable); +} + +void ScFlatUInt16RowSegments::setInsertFromBack(bool bInsertFromBack) +{ + mpImpl->setInsertFromBack(bInsertFromBack); +} + diff --git a/sc/source/core/data/sheetevents.cxx b/sc/source/core/data/sheetevents.cxx new file mode 100755 index 000000000000..e9e430ef85d9 --- /dev/null +++ b/sc/source/core/data/sheetevents.cxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdata.cxx,v $ + * $Revision: 1.69.32.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <tools/debug.hxx> + +#include "sheetevents.hxx" + +// ----------------------------------------------------------------------- + +// static +rtl::OUString ScSheetEvents::GetEventName(sal_Int32 nEvent) +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return rtl::OUString(); + } + + static const sal_Char* aEventNames[] = + { + "OnFocus", // SC_SHEETEVENT_FOCUS + "OnUnfocus", // SC_SHEETEVENT_UNFOCUS + "OnSelect", // SC_SHEETEVENT_SELECT + "OnDoubleClick", // SC_SHEETEVENT_DOUBLECLICK + "OnRightClick", // SC_SHEETEVENT_RIGHTCLICK + "OnChange", // SC_SHEETEVENT_CHANGE + "OnCalculate" // SC_SHEETEVENT_CALCULATE + }; + return rtl::OUString::createFromAscii(aEventNames[nEvent]); +} + +// ----------------------------------------------------------------------- + +ScSheetEvents::ScSheetEvents() : + mpScriptNames(NULL) +{ +} + +ScSheetEvents::~ScSheetEvents() +{ + Clear(); +} + +void ScSheetEvents::Clear() +{ + if (mpScriptNames) + { + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + delete mpScriptNames[nEvent]; + delete[] mpScriptNames; + mpScriptNames = NULL; + } +} + +ScSheetEvents::ScSheetEvents(const ScSheetEvents& rOther) : + mpScriptNames(NULL) +{ + *this = rOther; +} + +const ScSheetEvents& ScSheetEvents::operator=(const ScSheetEvents& rOther) +{ + Clear(); + if (rOther.mpScriptNames) + { + mpScriptNames = new rtl::OUString*[SC_SHEETEVENT_COUNT]; + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + if (rOther.mpScriptNames[nEvent]) + mpScriptNames[nEvent] = new rtl::OUString(*rOther.mpScriptNames[nEvent]); + else + mpScriptNames[nEvent] = NULL; + } + return *this; +} + +const rtl::OUString* ScSheetEvents::GetScript(sal_Int32 nEvent) const +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return NULL; + } + + if (mpScriptNames) + return mpScriptNames[nEvent]; + return NULL; +} + +void ScSheetEvents::SetScript(sal_Int32 nEvent, const rtl::OUString* pNew) +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return; + } + + if (!mpScriptNames) + { + mpScriptNames = new rtl::OUString*[SC_SHEETEVENT_COUNT]; + for (sal_Int32 nEventIdx=0; nEventIdx<SC_SHEETEVENT_COUNT; ++nEventIdx) + mpScriptNames[nEventIdx] = NULL; + } + delete mpScriptNames[nEvent]; + if (pNew) + mpScriptNames[nEvent] = new rtl::OUString(*pNew); + else + mpScriptNames[nEvent] = NULL; +} + diff --git a/sc/source/core/data/stlsheet.cxx b/sc/source/core/data/stlsheet.cxx index 4a4210a7925c..a3319eafd3fd 100644 --- a/sc/source/core/data/stlsheet.cxx +++ b/sc/source/core/data/stlsheet.cxx @@ -171,7 +171,7 @@ SfxItemSet& __EXPORT ScStyleSheet::GetItemSet() // gespeicherte Printer noch nicht geladen ist! ScDocument* pDoc = ((ScStyleSheetPool&)GetPool()).GetDocument(); - if ( pDoc && pDoc->IsLoadingDone() ) + if ( pDoc ) { // Setzen von sinnvollen Default-Werten: SvxPageItem aPageItem( ATTR_PAGE ); diff --git a/sc/source/core/data/tabbgcolor.cxx b/sc/source/core/data/tabbgcolor.cxx new file mode 100644 index 000000000000..a3d9eec16d99 --- /dev/null +++ b/sc/source/core/data/tabbgcolor.cxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tabbgcolor.hxx,v $ + * $Revision: 1.00 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "tabbgcolor.hxx" + +bool ScUndoTabColorInfo::IsDefaultOldTabBgColor() const +{ + return maOldTabBgColor == Color(COL_AUTO); +} + +bool ScUndoTabColorInfo::IsDefaultNewTabBgColor() const +{ + return maOldTabBgColor == Color(COL_AUTO); +} + +ScUndoTabColorInfo::ScUndoTabColorInfo(SCTAB nTab) : + mnTabId(nTab), + maOldTabBgColor(COL_AUTO), + maNewTabBgColor(COL_AUTO) +{ +} + +ScUndoTabColorInfo::ScUndoTabColorInfo(const ScUndoTabColorInfo& r) : + mnTabId(r.mnTabId), + maOldTabBgColor(r.maOldTabBgColor), + maNewTabBgColor(r.maNewTabBgColor) +{ +} diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index a8b819072c21..87561abf1513 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -112,6 +112,8 @@ #include "hints.hxx" // fuer Paint-Broadcast #include "prnsave.hxx" #include "tabprotection.hxx" +#include "sheetevents.hxx" +#include "segmenttree.hxx" // STATIC DATA ----------------------------------------------------------- @@ -131,14 +133,20 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, nRepeatStartY( SCROW_REPEAT_NONE ), pTabProtection( NULL ), pColWidth( NULL ), - pRowHeight( NULL ), + mpRowHeights( static_cast<ScFlatUInt16RowSegments*>(NULL) ), pColFlags( NULL ), pRowFlags( NULL ), + mpHiddenCols(new ScFlatBoolColSegments), + mpHiddenRows(new ScFlatBoolRowSegments), + mpFilteredCols(new ScFlatBoolColSegments), + mpFilteredRows(new ScFlatBoolRowSegments), pOutlineTable( NULL ), + pSheetEvents( NULL ), bTableAreaValid( FALSE ), bVisible( TRUE ), bStreamValid( FALSE ), bPendingRowHeights( FALSE ), + bCalcNotification( FALSE ), nTab( nNewTab ), nRecalcLvl( 0 ), pDocument( pDoc ), @@ -151,8 +159,10 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, nLockCount( 0 ), pScenarioRanges( NULL ), aScenarioColor( COL_LIGHTGRAY ), + aTabBgColor( COL_AUTO ), nScenarioFlags( 0 ), - bActiveScenario( FALSE ) + bActiveScenario( FALSE ), + mbPageBreaksValid(false) { if (bColInfo) @@ -169,7 +179,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, if (bRowInfo) { - pRowHeight = new ScSummableCompressedArray< SCROW, USHORT>( MAXROW, ScGlobal::nStdRowHeight); + mpRowHeights.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight)); pRowFlags = new ScBitMaskCompressedArray< SCROW, BYTE>( MAXROW, 0); } @@ -211,8 +221,8 @@ ScTable::~ScTable() delete[] pColWidth; delete[] pColFlags; - delete pRowHeight; delete pRowFlags; + delete pSheetEvents; delete pOutlineTable; delete pSearchParam; delete pSearchText; @@ -271,6 +281,22 @@ void ScTable::SetLoadingRTL( BOOL bSet ) bLoadingRTL = bSet; } +const Color& ScTable::GetTabBgColor() const +{ + return aTabBgColor; +} + +void ScTable::SetTabBgColor(const Color& rColor) +{ + if (aTabBgColor != rColor) + { + // The tab color has changed. Set this table 'modified'. + aTabBgColor = rColor; + if (IsStreamValid()) + SetStreamValid(false); + } +} + void ScTable::SetScenario( BOOL bFlag ) { bScenario = bFlag; @@ -969,9 +995,10 @@ BOOL ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark, // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist. //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ??? - if ( pRowFlags && ( pRowFlags->GetValue(nRow) & CR_HIDDEN ) ) + if (RowHidden(nRow)) return FALSE; - if ( pColFlags && ( pColFlags[nCol] & CR_HIDDEN ) ) + + if (ColHidden(nCol)) return FALSE; } @@ -998,8 +1025,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, { BOOL bUp = ( nMovY < 0 ); nRow = rMark.GetNextMarked( nCol, nRow, bUp ); - while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) || - pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) + while ( VALIDROW(nRow) && + (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) { // #53697# ausgeblendete ueberspringen (s.o.) nRow += nMovY; @@ -1009,7 +1036,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, while ( nRow < 0 || nRow > MAXROW ) { nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) ); - while ( VALIDCOL(nCol) && pColFlags && (pColFlags[nCol] & CR_HIDDEN) ) + while ( VALIDCOL(nCol) && ColHidden(nCol) ) nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) ); // #53697# skip hidden rows (see above) if (nCol < 0) { @@ -1028,8 +1055,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, else if (nRow > MAXROW) nRow = 0; nRow = rMark.GetNextMarked( nCol, nRow, bUp ); - while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) || - pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) + while ( VALIDROW(nRow) && + (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) { // #53697# ausgeblendete ueberspringen (s.o.) nRow += nMovY; @@ -1420,93 +1447,140 @@ void ScTable::ExtendPrintArea( OutputDevice* pDev, double nPPTX = aPix1000.X() / 1000.0; double nPPTY = aPix1000.Y() / 1000.0; - BOOL bEmpty[MAXCOLCOUNT]; - for (SCCOL i=0; i<=MAXCOL; i++) - bEmpty[i] = ( aCol[i].GetCellCount() == 0 ); - - SCSIZE nIndex; - SCCOL nPrintCol = rEndCol; - SCSIZE nRowFlagsIndex; - SCROW nRowFlagsEndRow; - BYTE nRowFlag = pRowFlags->GetValue( nStartRow, nRowFlagsIndex, nRowFlagsEndRow); - for (SCROW nRow = nStartRow; nRow<=nEndRow; nRow++) + // First, mark those columns that we need to skip i.e. hidden and empty columns. + + ScFlatBoolColSegments aSkipCols; + aSkipCols.setInsertFromBack(true); // speed optimazation. + aSkipCols.setFalse(0, MAXCOL); + for (SCCOL i = 0; i <= MAXCOL; ++i) { - if (nRow > nRowFlagsEndRow) - nRowFlag = pRowFlags->GetNextValue( nRowFlagsIndex, nRowFlagsEndRow); - if ( ( nRowFlag & CR_HIDDEN ) == 0 ) + SCCOL nLastCol = i; + if (ColHidden(i, NULL, &nLastCol)) + { + // Columns are hidden in this range. + aSkipCols.setTrue(i, nLastCol); + } + else { - SCCOL nDataCol = rEndCol; - while (nDataCol > 0 && ( bEmpty[nDataCol] || !aCol[nDataCol].Search(nRow,nIndex) ) ) - --nDataCol; - if ( ( pColFlags[nDataCol] & CR_HIDDEN ) == 0 ) + // These columns are visible. Check for empty columns. + for (SCCOL j = i; j <= nLastCol; ++j) { - ScBaseCell* pCell = aCol[nDataCol].GetCell(nRow); - if (pCell) - { - CellType eType = pCell->GetCellType(); - if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT - || (eType == CELLTYPE_FORMULA && !((ScFormulaCell*)pCell)->IsValue()) ) - { - BOOL bFormula = FALSE; //! uebergeben - long nPixel = pCell->GetTextWidth(); - - // Breite bereits im Idle-Handler berechnet? - if ( TEXTWIDTH_DIRTY == nPixel ) - { - ScNeededSizeOptions aOptions; - aOptions.bTotalSize = TRUE; - aOptions.bFormula = bFormula; - aOptions.bSkipMerged = FALSE; - - Fraction aZoom(1,1); - nPixel = aCol[nDataCol].GetNeededSize( nRow, - pDev,nPPTX,nPPTY,aZoom,aZoom, - TRUE, aOptions ); - pCell->SetTextWidth( (USHORT)nPixel ); - } + if (aCol[j].GetCellCount() == 0) + // empty + aSkipCols.setTrue(j,j); + } + } + i = nLastCol; + } - long nTwips = (long) (nPixel / nPPTX); - long nDocW = GetColWidth( nDataCol ); + ScFlatBoolColSegments::RangeData aColData; + for (SCCOL nCol = rEndCol; nCol >= 0; --nCol) + { + if (!aSkipCols.getRangeData(nCol, aColData)) + // Failed to get the data. This should never happen! + return; - long nMissing = nTwips - nDocW; - if ( nMissing > 0 ) - { - // look at alignment - - const ScPatternAttr* pPattern = GetPattern( nDataCol, nRow ); - const SfxItemSet* pCondSet = NULL; - if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() ) - pCondSet = pDocument->GetCondResult( nDataCol, nRow, nTab ); - - SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) - pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue(); - if ( eHorJust == SVX_HOR_JUSTIFY_CENTER ) - nMissing /= 2; // distributed into both directions - else - { - // STANDARD is LEFT (only text is handled here) - BOOL bRight = ( eHorJust == SVX_HOR_JUSTIFY_RIGHT ); - if ( IsLayoutRTL() ) - bRight = !bRight; - if ( bRight ) - nMissing = 0; // extended only to the left (logical) - } - } + if (aColData.mbValue) + { + // Skip these columns. + nCol = aColData.mnCol1; // move toward 0. + continue; + } - SCCOL nCol = nDataCol; - while (nMissing > 0 && nCol < MAXCOL) - { - ++nCol; - nMissing -= GetColWidth( nCol ); - } - if (nCol>nPrintCol) - nPrintCol = nCol; - } - } + // These are visible and non-empty columns. + for (SCCOL nDataCol = nCol; 0 <= nDataCol && nDataCol >= aColData.mnCol1; --nDataCol) + { + SCCOL nPrintCol = nDataCol; + VisibleDataCellIterator aIter(*mpHiddenRows, aCol[nDataCol]); + ScBaseCell* pCell = aIter.reset(nStartRow); + if (!pCell) + // No visible cells found in this column. Skip it. + continue; + + while (pCell) + { + SCCOL nNewCol = nDataCol; + SCROW nRow = aIter.getRow(); + if (nRow > nEndRow) + // Went past the last row position. Bail out. + break; + + MaybeAddExtraColumn(nNewCol, nRow, pDev, nPPTX, nPPTY); + if (nNewCol > nPrintCol) + nPrintCol = nNewCol; + pCell = aIter.next(); } + + if (nPrintCol > rEndCol) + // Make sure we don't shrink the print area. + rEndCol = nPrintCol; + } + nCol = aColData.mnCol1; // move toward 0. + } +} + +void ScTable::MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY) +{ + ScBaseCell* pCell = aCol[rCol].GetCell(nRow); + if (!pCell || !pCell->HasStringData()) + return; + + bool bFormula = false; //! ueberge + long nPixel = pCell->GetTextWidth(); + + // Breite bereits im Idle-Handler berechnet? + if ( TEXTWIDTH_DIRTY == nPixel ) + { + ScNeededSizeOptions aOptions; + aOptions.bTotalSize = TRUE; + aOptions.bFormula = bFormula; + aOptions.bSkipMerged = FALSE; + + Fraction aZoom(1,1); + nPixel = aCol[rCol].GetNeededSize( + nRow, pDev, nPPTX, nPPTY, aZoom, aZoom, true, aOptions ); + pCell->SetTextWidth( (USHORT)nPixel ); + } + + long nTwips = (long) (nPixel / nPPTX); + long nDocW = GetColWidth( rCol ); + + long nMissing = nTwips - nDocW; + if ( nMissing > 0 ) + { + // look at alignment + + const ScPatternAttr* pPattern = GetPattern( rCol, nRow ); + const SfxItemSet* pCondSet = NULL; + if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() ) + pCondSet = pDocument->GetCondResult( rCol, nRow, nTab ); + + SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) + pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue(); + if ( eHorJust == SVX_HOR_JUSTIFY_CENTER ) + nMissing /= 2; // distributed into both directions + else + { + // STANDARD is LEFT (only text is handled here) + bool bRight = ( eHorJust == SVX_HOR_JUSTIFY_RIGHT ); + if ( IsLayoutRTL() ) + bRight = !bRight; + if ( bRight ) + nMissing = 0; // extended only to the left (logical) } } - rEndCol = nPrintCol; + + SCCOL nNewCol = rCol; + while (nMissing > 0 && nNewCol < MAXCOL) + { + ScBaseCell* pNextCell = aCol[nNewCol+1].GetCell(nRow); + if (pNextCell && pNextCell->GetCellType() != CELLTYPE_NOTE) + // Cell content in a next column ends display of this string. + nMissing = 0; + else + nMissing -= GetColWidth(++nNewCol); + } + rCol = nNewCol; } void ScTable::DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd ) @@ -1597,7 +1671,104 @@ void ScTable::RestorePrintRanges( const ScPrintSaverTab& rSaveTab ) UpdatePageBreaks(NULL); } +SCROW ScTable::VisibleDataCellIterator::ROW_NOT_FOUND = -1; + +ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments& rRowSegs, ScColumn& rColumn) : + mrRowSegs(rRowSegs), + mrColumn(rColumn), + mpCell(NULL), + mnCurRow(ROW_NOT_FOUND), + mnUBound(ROW_NOT_FOUND) +{ +} + +ScTable::VisibleDataCellIterator::~VisibleDataCellIterator() +{ +} +ScBaseCell* ScTable::VisibleDataCellIterator::reset(SCROW nRow) +{ + if (nRow > MAXROW) + { + mnCurRow = ROW_NOT_FOUND; + return NULL; + } + ScFlatBoolRowSegments::RangeData aData; + if (!mrRowSegs.getRangeData(nRow, aData)) + { + mnCurRow = ROW_NOT_FOUND; + return NULL; + } + if (!aData.mbValue) + { + // specified row is visible. Take it. + mnCurRow = nRow; + mnUBound = aData.mnRow2; + } + else + { + // specified row is not-visible. The first visible row is the start of + // the next segment. + mnCurRow = aData.mnRow2 + 1; + mnUBound = mnCurRow; // get range data on the next iteration. + if (mnCurRow > MAXROW) + { + // Make sure the row doesn't exceed our current limit. + mnCurRow = ROW_NOT_FOUND; + return NULL; + } + } + + mpCell = mrColumn.GetCell(mnCurRow); + if (mpCell) + // First visible cell found. + return mpCell; + + // Find a first visible cell below this row (if any). + return next(); +} + +ScBaseCell* ScTable::VisibleDataCellIterator::next() +{ + if (mnCurRow == ROW_NOT_FOUND) + return NULL; + + while (mrColumn.GetNextDataPos(mnCurRow)) + { + if (mnCurRow > mnUBound) + { + // We don't know the visibility of this row range. Query it. + ScFlatBoolRowSegments::RangeData aData; + if (!mrRowSegs.getRangeData(mnCurRow, aData)) + { + mnCurRow = ROW_NOT_FOUND; + return NULL; + } + + if (aData.mbValue) + { + // This row is invisible. Skip to the last invisible row and + // try again. + mnCurRow = mnUBound = aData.mnRow2; + continue; + } + + // This row is visible. + mnUBound = aData.mnRow2; + } + + mpCell = mrColumn.GetCell(mnCurRow); + if (mpCell) + return mpCell; + } + mnCurRow = ROW_NOT_FOUND; + return NULL; +} + +SCROW ScTable::VisibleDataCellIterator::getRow() const +{ + return mnCurRow; +} diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 69d16df7be58..9bd5b031fde5 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -56,7 +56,9 @@ #include "fillinfo.hxx" #include "bcaslot.hxx" #include "postit.hxx" +#include "sheetevents.hxx" #include "globstr.hrc" +#include "segmenttree.hxx" #include <math.h> @@ -97,6 +99,27 @@ void ScTable::StartOutlineTable() } +void ScTable::SetSheetEvents( const ScSheetEvents* pNew ) +{ + delete pSheetEvents; + if (pNew) + pSheetEvents = new ScSheetEvents(*pNew); + else + pSheetEvents = NULL; + + SetCalcNotification( FALSE ); // discard notifications before the events were set + + if (IsStreamValid()) + SetStreamValid(FALSE); +} + + +void ScTable::SetCalcNotification( BOOL bSet ) +{ + bCalcNotification = bSet; +} + + BOOL ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) { BOOL bTest = TRUE; @@ -117,22 +140,28 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE InitializeNoteCaptions(); if (nStartCol==0 && nEndCol==MAXCOL) { - if (pRowHeight && pRowFlags) + if (mpRowHeights && pRowFlags) { - pRowHeight->Insert( nStartRow, nSize); + mpRowHeights->insertSegment(nStartRow, nSize, false); BYTE nNewFlags = pRowFlags->Insert( nStartRow, nSize); // only copy manual size flag, clear all others if (nNewFlags && (nNewFlags != CR_MANUALSIZE)) pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1, nNewFlags & CR_MANUALSIZE); } + if (pOutlineTable) pOutlineTable->InsertRow( nStartRow, nSize ); + + mpFilteredRows->insertSegment(nStartRow, nSize, true); + mpHiddenRows->insertSegment(nStartRow, nSize, true); } for (SCCOL j=nStartCol; j<=nEndCol; j++) aCol[j].InsertRow( nStartRow, nSize ); DecRecalcLevel( false ); + + InvalidatePageBreaks(); } @@ -143,15 +172,19 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE InitializeNoteCaptions(); if (nStartCol==0 && nEndCol==MAXCOL) { - if (pRowHeight && pRowFlags) - { - pRowHeight->Remove( nStartRow, nSize); + if (pRowFlags) pRowFlags->Remove( nStartRow, nSize); - } + + if (mpRowHeights) + mpRowHeights->removeSegment(nStartRow, nStartRow+nSize); + if (pOutlineTable) if (pOutlineTable->DeleteRow( nStartRow, nSize )) if (pUndoOutline) *pUndoOutline = TRUE; + + mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize); + mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize); } { // scope for bulk broadcast @@ -160,6 +193,8 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE aCol[j].DeleteRow( nStartRow, nSize ); } DecRecalcLevel(); + + InvalidatePageBreaks(); } @@ -195,6 +230,9 @@ void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE } if (pOutlineTable) pOutlineTable->InsertCol( nStartCol, nSize ); + + mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true); + mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true); } @@ -226,6 +264,8 @@ void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE } } DecRecalcLevel(); + + InvalidatePageBreaks(); } @@ -247,6 +287,10 @@ void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE if (pOutlineTable->DeleteCol( nStartCol, nSize )) if (pUndoOutline) *pUndoOutline = TRUE; + + SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize); + mpHiddenCols->removeSegment(nStartCol, nRmSize); + mpFilteredCols->removeSegment(nStartCol, nRmSize); } @@ -268,6 +312,8 @@ void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]); } DecRecalcLevel(); + + InvalidatePageBreaks(); } @@ -339,20 +385,21 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, // copy widths/heights, and only "hidden", "filtered" and "manual" flags // also for all preceding columns/rows, to have valid positions for drawing objects - if (pColFlags && pTable->pColFlags && pColWidth && pTable->pColWidth) + if (pColWidth && pTable->pColWidth) for (i=0; i<=nCol2; i++) - { - pTable->pColFlags[i] = pColFlags[i] & CR_HIDDEN; pTable->pColWidth[i] = pColWidth[i]; - } - if (pRowFlags && pTable->pRowFlags && pRowHeight && pTable->pRowHeight) + pTable->CopyColHidden(*this, 0, nCol2); + pTable->CopyColFiltered(*this, 0, nCol2); + + if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights) { - pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, - (CR_HIDDEN | CR_FILTERED | CR_MANUALSIZE)); - pTable->pRowHeight->CopyFrom( *pRowHeight, 0, nRow2); + pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE); + pTable->CopyRowHeight(*this, 0, nRow2, 0); } + pTable->CopyRowHidden(*this, 0, nRow2); + pTable->CopyRowFiltered(*this, 0, nRow2); // ggf. Formeln durch Werte ersetzen @@ -393,10 +440,10 @@ void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, for (i=nCol1; i<=nCol2; i++) pColWidth[i] = pTable->pColWidth[i-nDx]; - if (nCol1==0 && nCol2==MAXCOL && pRowHeight && pTable->pRowHeight && + if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights && pRowFlags && pTable->pRowFlags) { - pRowHeight->CopyFrom( *pTable->pRowHeight, nRow1, nRow2, -nDy); + CopyRowHeight(*pTable, nRow1, nRow2, -nDy); // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense for (SCROW j=nRow1; j<=nRow2; j++) { @@ -631,8 +678,10 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, // Charts muessen beim Ein-/Ausblenden angepasst werden ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection(); + bool bFlagChange = false; + BOOL bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth); - BOOL bHeight = (nCol1==0 && nCol2==MAXCOL && pRowHeight && pDestTab->pRowHeight); + BOOL bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights); if (bWidth||bHeight) { @@ -641,33 +690,77 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, if (bWidth) for (SCCOL i=nCol1; i<=nCol2; i++) { - BOOL bChange = pCharts && - ( pDestTab->pColFlags[i] & CR_HIDDEN ) != ( pColFlags[i] & CR_HIDDEN ); + bool bThisHidden = ColHidden(i); + bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden); + bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]); pDestTab->pColWidth[i] = pColWidth[i]; pDestTab->pColFlags[i] = pColFlags[i]; + pDestTab->SetColHidden(i, i, bThisHidden); //! Aenderungen zusammenfassen? - if (bChange) + if (bHiddenChange && pCharts) pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab )); + + if (bChange) + bFlagChange = true; } if (bHeight) { - pDestTab->pRowHeight->CopyFrom( *pRowHeight, nRow1, nRow2); - for (SCROW i=nRow1; i<=nRow2; i++) + bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2); + + if (bChange) + bFlagChange = true; + + pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0); + pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2); + + // Hidden flags. + for (SCROW i = nRow1; i <= nRow2; ++i) { - // TODO: might need some performance improvement, block - // operations instead of single GetValue()/SetValue() calls. - BYTE nThisRowFlags = pRowFlags->GetValue(i); - BOOL bChange = pCharts && - ( pDestTab->pRowFlags->GetValue(i) & CR_HIDDEN ) != ( nThisRowFlags & CR_HIDDEN ); - pDestTab->pRowFlags->SetValue( i, nThisRowFlags ); - //! Aenderungen zusammenfassen? - if (bChange) - pCharts->SetRangeDirty(ScRange( 0, i, nTab, MAXCOL, i, nTab )); + SCROW nThisLastRow, nDestLastRow; + bool bThisHidden = RowHidden(i, NULL, &nThisLastRow); + bool bDestHidden = pDestTab->RowHidden(i, NULL, &nDestLastRow); + + // If the segment sizes differ, we take the shorter segment of the two. + SCROW nLastRow = ::std::min(nThisLastRow, nDestLastRow); + if (nLastRow >= nRow2) + // the last row shouldn't exceed the upper bound the caller specified. + nLastRow = nRow2; + + pDestTab->SetRowHidden(i, nLastRow, bThisHidden); + + bool bThisHiddenChange = (bThisHidden != bDestHidden); + if (bThisHiddenChange && pCharts) + { + // Hidden flags differ. + pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab)); + } + + if (bThisHiddenChange) + bFlagChange = true; + + // Jump to the last row of the identical flag segment. + i = nLastRow; + } + + // Filtered flags. + for (SCROW i = nRow1; i <= nRow2; ++i) + { + SCROW nLastRow; + bool bFiltered = RowFiltered(i, NULL, &nLastRow); + if (nLastRow >= nRow2) + // the last row shouldn't exceed the upper bound the caller specified. + nLastRow = nRow2; + pDestTab->SetRowFiltered(i, nLastRow, bFiltered); + i = nLastRow; } } pDestTab->DecRecalcLevel(); } + + if (bFlagChange) + pDestTab->InvalidatePageBreaks(); + pDestTab->SetOutlineTable( pOutlineTable ); // auch nur wenn bColRowFlags } } @@ -681,7 +774,7 @@ void ScTable::UndoToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) { BOOL bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth); - BOOL bHeight = (nCol1==0 && nCol2==MAXCOL && pRowHeight && pDestTab->pRowHeight); + BOOL bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights); if (bWidth||bHeight) IncRecalcLevel(); @@ -701,8 +794,8 @@ void ScTable::UndoToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, for (SCCOL i=nCol1; i<=nCol2; i++) pDestTab->pColWidth[i] = pColWidth[i]; if (bHeight) - pDestTab->pRowHeight->CopyFrom( *pRowHeight, nRow1, nRow2); - DecRecalcLevel(); + pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0); + DecRecalcLevel(); } } } @@ -714,6 +807,16 @@ void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] ); } +void ScTable::InvalidateTableArea() +{ + bTableAreaValid = FALSE; +} + +void ScTable::InvalidatePageBreaks() +{ + mbPageBreaksValid = false; +} + void ScTable::CopyScenarioTo( ScTable* pDestTab ) const { DBG_ASSERT( bScenario, "bScenario == FALSE" ); @@ -1093,6 +1196,17 @@ void ScTable::SetRelNameDirty() } +void ScTable::SetLoadingMedium(bool bLoading) +{ + mpRowHeights->enableTreeSearch(!bLoading); + + // When loading a medium, prefer inserting row heights from the back + // position since the row heights are stored and read in ascending order + // during import. + mpRowHeights->setInsertFromBack(bLoading); +} + + void ScTable::CalcAll() { for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll(); @@ -1240,7 +1354,7 @@ BOOL ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2, SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY, - const ScPatternAttr* pPattern, const SfxItemSet* pCondSet ) const + const ScPatternAttr* pPattern, const SfxItemSet* pCondSet ) { // Rueckgabe = neues nArrY @@ -1273,7 +1387,7 @@ SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCO for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ ) { - if ( !(pRowFlags->GetValue(nRow) & CR_HIDDEN) ) + if (!RowHidden(nRow)) { BOOL bHitOne = TRUE; if ( nCol > nX2+1 ) @@ -1281,7 +1395,7 @@ SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCO // reicht die gedrehte Zelle bis in den sichtbaren Bereich? SCCOL nTouchedCol = nCol; - long nWidth = (long) ( pRowHeight->GetValue(nRow) * nFactor ); + long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor); DBG_ASSERT(nWidth <= 0, "Richtung falsch"); while ( nWidth < 0 && nTouchedCol > 0 ) { @@ -1307,9 +1421,9 @@ SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCO return nArrY; } -void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ) const +void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ) { - if ( !pColWidth || !pRowHeight || !pColFlags || !pRowFlags ) + if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags ) { DBG_ERROR( "Spalten-/Zeileninfo fehlt" ); return; @@ -1322,7 +1436,7 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC for (SCCOL nCol=0; nCol<=MAXCOL; nCol++) { - if ( !(pColFlags[nCol] & CR_HIDDEN) ) + if (!ColHidden(nCol)) { SCSIZE nArrY = 0; ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 ); @@ -1837,36 +1951,24 @@ void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, BOOL bRem double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY ) { - BOOL* pUsed = new BOOL[MAXROWCOUNT]; - memset( pUsed, 0, sizeof(BOOL) * (MAXROWCOUNT) ); + ScFlatBoolRowSegments aUsedRows; + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved); - SCCOL nCol; - for (nCol=0; nCol<=MAXCOL; nCol++) - aCol[nCol].FindStyleSheet( pStyleSheet, pUsed, bRemoved ); - - BOOL bFound = FALSE; - SCROW nStart = 0, nEnd = 0; - for (SCROW i=0; i<=MAXROW; i++) + SCROW nRow = 0; + while (nRow <= MAXROW) { - if (pUsed[i]) - { - if (!bFound) - { - nStart = i; - bFound = TRUE; - } - nEnd = i; - } - else if (bFound) - { - SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE ); - bFound = FALSE; - } - } - if (bFound) - SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE ); + ScFlatBoolRowSegments::RangeData aData; + if (!aUsedRows.getRangeData(nRow, aData)) + // search failed! + return; - delete[] pUsed; + SCROW nEndRow = aData.mnRow2; + if (aData.mbValue) + SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE); + + nRow = nEndRow + 1; + } } @@ -1948,6 +2050,8 @@ void ScTable::SetColWidth( SCCOL nCol, USHORT nNewWidth ) pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] ); pColWidth[nCol] = nNewWidth; DecRecalcLevel(); + + InvalidatePageBreaks(); } } else @@ -1959,7 +2063,7 @@ void ScTable::SetColWidth( SCCOL nCol, USHORT nNewWidth ) void ScTable::SetRowHeight( SCROW nRow, USHORT nNewHeight ) { - if (VALIDROW(nRow) && pRowHeight) + if (VALIDROW(nRow) && mpRowHeights) { if (!nNewHeight) { @@ -1967,7 +2071,7 @@ void ScTable::SetRowHeight( SCROW nRow, USHORT nNewHeight ) nNewHeight = ScGlobal::nStdRowHeight; } - USHORT nOldHeight = pRowHeight->GetValue(nRow); + sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow); if ( nNewHeight != nOldHeight ) { IncRecalcLevel(); @@ -1975,8 +2079,10 @@ void ScTable::SetRowHeight( SCROW nRow, USHORT nNewHeight ) ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) nOldHeight ); - pRowHeight->SetValue( nRow, nNewHeight); + mpRowHeights->setValue(nRow, nRow, nNewHeight); DecRecalcLevel(); + + InvalidatePageBreaks(); } } else @@ -1985,12 +2091,45 @@ void ScTable::SetRowHeight( SCROW nRow, USHORT nNewHeight ) } } +namespace { + +/** + * Check if the new pixel size is different from the old size between + * specified ranges. + */ +bool lcl_pixelSizeChanged( + ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow, + sal_uInt16 nNewHeight, double nPPTY) +{ + long nNewPix = static_cast<long>(nNewHeight * nPPTY); + + ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights); + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) + { + sal_uInt16 nHeight; + if (!aFwdIter.getValue(nRow, nHeight)) + break; + + if (nHeight != nNewHeight) + { + bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY)); + if (bChanged) + return true; + } + + // Skip ahead to the last position of the current range. + nRow = aFwdIter.getLastPos(); + } + return false; +} + +} BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeight, double /* nPPTX */, double nPPTY ) { BOOL bChanged = FALSE; - if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowHeight) + if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) { IncRecalcLevel(); InitializeNoteCaptions(); @@ -2000,8 +2139,6 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig nNewHeight = ScGlobal::nStdRowHeight; } - long nNewPix = (long) ( nNewHeight * nPPTY ); - BOOL bSingle = FALSE; // TRUE = process every row for its own ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) @@ -2010,24 +2147,17 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig if (bSingle) { - size_t nIndex; - SCROW nRegionEndRow; - USHORT nOldHeight = pRowHeight->GetValue( nStartRow, nIndex, nRegionEndRow); - if (nNewHeight == nOldHeight && nEndRow <= nRegionEndRow) + ScFlatUInt16RowSegments::RangeData aData; + mpRowHeights->getRangeData(nStartRow, aData); + if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2) bSingle = FALSE; // no difference in this range } if (bSingle) { if (nEndRow-nStartRow < 20) { - // Whether new pixel size will differ from old pixel size in any row. - ScCompressedArrayIterator< SCROW, USHORT> aIter( *pRowHeight, - nStartRow, nEndRow); - do - { - if (*aIter != nNewHeight) - bChanged = (nNewPix != (long) (*aIter * nPPTY)); - } while (!bChanged && aIter.NextRange()); + if (!bChanged) + bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY); /* #i94028# #i94991# If drawing objects are involved, each row has to be changed for its own, because each call to @@ -2039,12 +2169,12 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig for( SCROW nRow = nStartRow; nRow <= nEndRow ; ++nRow ) { pDrawLayer->HeightChanged( nTab, nRow, - ((long) nNewHeight) - ((long) pRowHeight->GetValue( nRow ))); - pRowHeight->SetValue( nRow, nNewHeight ); + static_cast<long>(nNewHeight) - static_cast<long>(mpRowHeights->getValue(nRow))); + mpRowHeights->setValue(nRow, nRow, nNewHeight); } } else - pRowHeight->SetValue( nStartRow, nEndRow, nNewHeight); + mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); } else { @@ -2059,23 +2189,22 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig { if (pDrawLayer) { - unsigned long nOldHeights = pRowHeight->SumValues( nStartRow, nEndRow); + unsigned long nOldHeights = GetRowHeight(nStartRow, nEndRow); // FIXME: should we test for overflows? long nHeightDif = (long) (unsigned long) nNewHeight * (nEndRow - nStartRow + 1) - nOldHeights; pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif ); } - // Whether new pixel size will differ from old pixel size in any row. - ScCompressedArrayIterator< SCROW, USHORT> aIter( *pRowHeight, - nStartRow, nEndRow); - do - { - if (*aIter != nNewHeight) - bChanged = (nNewPix != (long) (*aIter * nPPTY)); - } while (!bChanged && aIter.NextRange()); - pRowHeight->SetValue( nStartRow, nEndRow, nNewHeight); + + if (!bChanged) + bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY); + + mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); } DecRecalcLevel(); + + if (bChanged) + InvalidatePageBreaks(); } else { @@ -2085,6 +2214,16 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig return bChanged; } +void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeight ) +{ + if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights) + return; + + if (!nNewHeight) + nNewHeight = ScGlobal::nStdRowHeight; + + mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); +} void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual ) { @@ -2102,13 +2241,13 @@ void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual ) } -USHORT ScTable::GetColWidth( SCCOL nCol ) const +USHORT ScTable::GetColWidth( SCCOL nCol ) { DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer"); if (VALIDCOL(nCol) && pColFlags && pColWidth) { - if ( pColFlags[nCol] & CR_HIDDEN ) + if (ColHidden(nCol)) return 0; else return pColWidth[nCol]; @@ -2129,7 +2268,7 @@ USHORT ScTable::GetOriginalWidth( SCCOL nCol ) const // immer die eingest } -USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const +USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) { // get the width that is used in the largest continuous column range (up to nEndCol) @@ -2141,24 +2280,24 @@ USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const USHORT nMaxWidth = 0; USHORT nMaxCount = 0; - USHORT nRangeStart = 0; + SCCOL nRangeStart = 0; while ( nRangeStart <= nEndCol ) { // skip hidden columns - while ( nRangeStart <= nEndCol && (pColFlags[nRangeStart] & CR_HIDDEN) ) + while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) ) ++nRangeStart; if ( nRangeStart <= nEndCol ) { USHORT nThisCount = 0; USHORT nThisWidth = pColWidth[nRangeStart]; - USHORT nRangeEnd = nRangeStart; + SCCOL nRangeEnd = nRangeStart; while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth ) { ++nThisCount; ++nRangeEnd; // skip hidden columns - while ( nRangeEnd <= nEndCol && (pColFlags[nRangeEnd] & CR_HIDDEN) ) + while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) ) ++nRangeEnd; } @@ -2176,44 +2315,80 @@ USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const } -USHORT ScTable::GetRowHeight( SCROW nRow ) const +USHORT ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) { DBG_ASSERT(VALIDROW(nRow),"Falsche Zeilennummer"); - if (VALIDROW(nRow) && pRowFlags && pRowHeight) + if (VALIDROW(nRow) && mpRowHeights) { - if ( pRowFlags->GetValue(nRow) & CR_HIDDEN ) + if (bHiddenAsZero && RowHidden(nRow)) return 0; else - return pRowHeight->GetValue(nRow); + { + ScFlatUInt16RowSegments::RangeData aData; + if (!mpRowHeights->getRangeData(nRow, aData)) + // TODO: What should we return in case the search fails? + return 0; + + if (pStartRow) + *pStartRow = aData.mnRow1; + if (pEndRow) + *pEndRow = aData.mnRow2; + return aData.mnValue; + } } else return (USHORT) ScGlobal::nStdRowHeight; } -ULONG ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const +ULONG ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) { DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); - if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags && pRowHeight) + if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) { - return pRowFlags->SumCoupledArrayForCondition( nStartRow, nEndRow, - CR_HIDDEN, 0, *pRowHeight); + ULONG nHeight = 0; + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = -1; + if (!RowHidden(nRow, nLastRow)) + { + if (nLastRow > nEndRow) + nLastRow = nEndRow; + nHeight += mpRowHeights->getSumValue(nRow, nLastRow); + } + nRow = nLastRow + 1; + } + return nHeight; } else return (ULONG) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight); } -ULONG ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const +ULONG ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) { DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); - if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags && pRowHeight) + if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) { - return pRowFlags->SumScaledCoupledArrayForCondition( nStartRow, - nEndRow, CR_HIDDEN, 0, *pRowHeight, fScale); + ULONG nHeight = 0; + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = -1; + if (!RowHidden(nRow, nLastRow)) + { + if (nLastRow > nEndRow) + nLastRow = nEndRow; + sal_uInt32 nThisHeight = mpRowHeights->getSumValue(nRow, nLastRow); + nHeight += static_cast<ULONG>(nThisHeight * fScale); + } + nRow = nLastRow + 1; + } + return nHeight; } else return (ULONG) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale); @@ -2224,8 +2399,8 @@ USHORT ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hid { DBG_ASSERT(VALIDROW(nRow),"wrong row number"); - if (VALIDROW(nRow) && pRowHeight) - return pRowHeight->GetValue(nRow); + if (VALIDROW(nRow) && mpRowHeights) + return mpRowHeights->getValue(nRow); else return (USHORT) ScGlobal::nStdRowHeight; } @@ -2234,28 +2409,26 @@ USHORT ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hid // Spalten-/Zeilen-Flags -SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const +SCROW ScTable::GetHiddenRowCount( SCROW nRow ) { - SCROW nEndRow = nRow; - if ( pRowFlags ) - { - nEndRow = pRowFlags->GetBitStateEnd( nRow, CR_HIDDEN, CR_HIDDEN); - if (ValidRow(nEndRow)) - ++nEndRow; - else - nEndRow = nRow; - } - return nEndRow - nRow; + if (!ValidRow(nRow)) + return 0; + + SCROW nLastRow = -1; + if (!RowHidden(nRow, nLastRow) || !ValidRow(nLastRow)) + return 0; + + return nLastRow - nRow + 1; } //! ShowRows / DBShowRows zusammenfassen -void ScTable::ShowCol(SCCOL nCol, BOOL bShow) +void ScTable::ShowCol(SCCOL nCol, bool bShow) { - if (VALIDCOL(nCol) && pColFlags) + if (VALIDCOL(nCol)) { - BOOL bWasVis = ( pColFlags[nCol] & CR_HIDDEN ) == 0; + bool bWasVis = !ColHidden(nCol); if (bWasVis != bShow) { IncRecalcLevel(); @@ -2269,11 +2442,8 @@ void ScTable::ShowCol(SCCOL nCol, BOOL bShow) pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] ); } - if (bShow) - pColFlags[nCol] &= ~CR_HIDDEN; - else - pColFlags[nCol] |= CR_HIDDEN; - DecRecalcLevel(); + SetColHidden(nCol, nCol, !bShow); + DecRecalcLevel(); ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); if ( pCharts ) @@ -2287,12 +2457,11 @@ void ScTable::ShowCol(SCCOL nCol, BOOL bShow) } -void ScTable::ShowRow(SCROW nRow, BOOL bShow) +void ScTable::ShowRow(SCROW nRow, bool bShow) { if (VALIDROW(nRow) && pRowFlags) { - BYTE nFlags = pRowFlags->GetValue(nRow); - BOOL bWasVis = ( nFlags & CR_HIDDEN ) == 0; + bool bWasVis = !RowHidden(nRow); if (bWasVis != bShow) { IncRecalcLevel(); @@ -2301,20 +2470,23 @@ void ScTable::ShowRow(SCROW nRow, BOOL bShow) if (pDrawLayer) { if (bShow) - pDrawLayer->HeightChanged( nTab, nRow, (long) pRowHeight->GetValue(nRow) ); + pDrawLayer->HeightChanged( + nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow))); else - pDrawLayer->HeightChanged( nTab, nRow, -(long) pRowHeight->GetValue(nRow) ); + pDrawLayer->HeightChanged( + nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow))); } + SetRowHidden(nRow, nRow, !bShow); if (bShow) - pRowFlags->SetValue( nRow, nFlags & ~(CR_HIDDEN | CR_FILTERED)); - else - pRowFlags->SetValue( nRow, nFlags | CR_HIDDEN); - DecRecalcLevel(); + SetRowFiltered(nRow, nRow, false); + DecRecalcLevel(); ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); if ( pCharts ) pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab )); + + InvalidatePageBreaks(); } } else @@ -2324,12 +2496,11 @@ void ScTable::ShowRow(SCROW nRow, BOOL bShow) } -void ScTable::DBShowRow(SCROW nRow, BOOL bShow) +void ScTable::DBShowRow(SCROW nRow, bool bShow) { if (VALIDROW(nRow) && pRowFlags) { - BYTE nFlags = pRowFlags->GetValue(nRow); - BOOL bWasVis = ( nFlags & CR_HIDDEN ) == 0; + bool bWasVis = !RowHidden(nRow); IncRecalcLevel(); InitializeNoteCaptions(); if (bWasVis != bShow) @@ -2338,18 +2509,18 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow) if (pDrawLayer) { if (bShow) - pDrawLayer->HeightChanged( nTab, nRow, (long) pRowHeight->GetValue(nRow) ); + pDrawLayer->HeightChanged( + nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow))); else - pDrawLayer->HeightChanged( nTab, nRow, -(long) pRowHeight->GetValue(nRow) ); + pDrawLayer->HeightChanged( + nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow))); } } // Filter-Flag immer setzen, auch wenn Hidden unveraendert - if (bShow) - pRowFlags->SetValue( nRow, nFlags & ~(CR_HIDDEN | CR_FILTERED)); - else - pRowFlags->SetValue( nRow, nFlags | (CR_HIDDEN | CR_FILTERED)); - DecRecalcLevel(); + SetRowHidden(nRow, nRow, !bShow); + SetRowFiltered(nRow, nRow, !bShow); + DecRecalcLevel(); if (bWasVis != bShow) { @@ -2359,6 +2530,8 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow) if (pOutlineTable) UpdateOutlineRow( nRow, nRow, bShow ); + + InvalidatePageBreaks(); } } else @@ -2368,26 +2541,25 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow) } -void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) +void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow) { SCROW nStartRow = nRow1; IncRecalcLevel(); InitializeNoteCaptions(); while (nStartRow <= nRow2) { - BYTE nOldFlag = pRowFlags->GetValue(nStartRow) & CR_HIDDEN; - SCROW nEndRow = pRowFlags->GetBitStateEnd( nStartRow, CR_HIDDEN, nOldFlag); + SCROW nEndRow = -1; + bool bWasVis = !RowHidden(nStartRow, nEndRow); if (nEndRow > nRow2) nEndRow = nRow2; - BOOL bWasVis = ( nOldFlag == 0 ); BOOL bChanged = ( bWasVis != bShow ); if ( bChanged ) { ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) { - long nHeight = (long) pRowHeight->SumValues( nStartRow, nEndRow); + long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow)); if (bShow) pDrawLayer->HeightChanged( nTab, nStartRow, nHeight ); else @@ -2395,10 +2567,8 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) } } - if (bShow) - pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~(CR_HIDDEN | CR_FILTERED)) ); - else - pRowFlags->OrValue( nStartRow, nEndRow, (CR_HIDDEN | CR_FILTERED)); + SetRowHidden(nStartRow, nEndRow, !bShow); + SetRowFiltered(nStartRow, nEndRow, !bShow); if ( bChanged ) { @@ -2420,26 +2590,25 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) } -void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) +void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow) { SCROW nStartRow = nRow1; IncRecalcLevel(); InitializeNoteCaptions(); while (nStartRow <= nRow2) { - BYTE nOldFlag = pRowFlags->GetValue(nStartRow) & CR_HIDDEN; - SCROW nEndRow = pRowFlags->GetBitStateEnd( nStartRow, CR_HIDDEN, nOldFlag); + SCROW nEndRow = -1; + bool bWasVis = !RowHidden(nStartRow, nEndRow); if (nEndRow > nRow2) nEndRow = nRow2; - BOOL bWasVis = ( nOldFlag == 0 ); BOOL bChanged = ( bWasVis != bShow ); if ( bChanged ) { ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) { - long nHeight = (long) pRowHeight->SumValues( nStartRow, nEndRow); + long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow)); if (bShow) pDrawLayer->HeightChanged( nTab, nStartRow, nHeight ); else @@ -2447,16 +2616,17 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) } } + SetRowHidden(nStartRow, nEndRow, !bShow); if (bShow) - pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~(CR_HIDDEN | CR_FILTERED)) ); - else - pRowFlags->OrValue( nStartRow, nEndRow, CR_HIDDEN); + SetRowFiltered(nStartRow, nEndRow, false); if ( bChanged ) { ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); if ( pCharts ) pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab )); + + InvalidatePageBreaks(); } nStartRow = nEndRow + 1; @@ -2465,16 +2635,6 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) } -BOOL ScTable::IsFiltered(SCROW nRow) const -{ - if (VALIDROW(nRow) && pRowFlags) - return ( pRowFlags->GetValue(nRow) & CR_FILTERED ) != 0; - - DBG_ERROR("Falsche Zeilennummer oder keine Flags"); - return FALSE; -} - - void ScTable::SetColFlags( SCCOL nCol, BYTE nNewFlags ) { if (VALIDCOL(nCol) && pColFlags) @@ -2528,11 +2688,32 @@ BYTE ScTable::GetRowFlags( SCROW nRow ) const SCROW ScTable::GetLastFlaggedRow() const { - if ( !pRowFlags ) - return 0; + SCROW nLastFound = 0; + if (pRowFlags) + { + SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<BYTE>(CR_ALL) ); + if (ValidRow(nRow)) + nLastFound = nRow; + } + + if (!maRowManualBreaks.empty()) + nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin()); + + if (mpHiddenRows) + { + SCROW nRow = mpHiddenRows->findLastNotOf(false); + if (ValidRow(nRow)) + nLastFound = ::std::max(nLastFound, nRow); + } + + if (mpFilteredRows) + { + SCROW nRow = mpFilteredRows->findLastNotOf(false); + if (ValidRow(nRow)) + nLastFound = ::std::max(nLastFound, nRow); + } - SCROW nLastFound = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); - return ValidRow(nLastFound) ? nLastFound : 0; + return nLastFound; } @@ -2543,7 +2724,7 @@ SCCOL ScTable::GetLastChangedCol() const SCCOL nLastFound = 0; for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++) - if ((pColFlags[nCol] & ~CR_PAGEBREAK) || (pColWidth[nCol] != STD_COL_WIDTH)) + if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH)) nLastFound = nCol; return nLastFound; @@ -2555,11 +2736,12 @@ SCROW ScTable::GetLastChangedRow() const if ( !pRowFlags ) return 0; - SCROW nLastFlags = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); - if (!ValidRow(nLastFlags)) - nLastFlags = 0; + SCROW nLastFlags = GetLastFlaggedRow(); - SCROW nLastHeight = pRowHeight->GetLastUnequalAccess( 0, ScGlobal::nStdRowHeight); + // Find the last row position where the height is NOT the standard row + // height. + // KOHEI: Test this to make sure it does what it's supposed to. + SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight); if (!ValidRow(nLastHeight)) nLastHeight = 0; @@ -2572,7 +2754,7 @@ BOOL ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, BOOL bShow ) if (pOutlineTable && pColFlags) { ScBitMaskCompressedArray< SCCOLROW, BYTE> aArray( MAXCOL, pColFlags, MAXCOLCOUNT); - return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, aArray ); + return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true ); } else return FALSE; @@ -2582,7 +2764,7 @@ BOOL ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, BOOL bShow ) BOOL ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, BOOL bShow ) { if (pOutlineTable && pRowFlags) - return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *pRowFlags ); + return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false ); else return FALSE; } @@ -2590,54 +2772,58 @@ BOOL ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, BOOL bShow ) void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) { - if (pColFlags) - { - while ( rX1>0 ? (pColFlags[rX1-1] & CR_HIDDEN) : FALSE ) - --rX1; - while ( rX2<MAXCOL ? (pColFlags[rX2+1] & CR_HIDDEN) : FALSE ) - ++rX2; - } - if (pRowFlags) + // Column-wise expansion + + while (rX1 > 0 && ColHidden(rX1-1)) + --rX1; + + while (rX2 < MAXCOL && ColHidden(rX2+1)) + ++rX2; + + // Row-wise expansion + + if (rY1 > 0) { - if (rY1 > 0) + ScFlatBoolRowSegments::RangeData aData; + if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue) { - SCROW nStartRow = pRowFlags->GetBitStateStart( rY1-1, CR_HIDDEN, CR_HIDDEN); + SCROW nStartRow = aData.mnRow1; if (ValidRow(nStartRow)) rY1 = nStartRow; } - if (rY2 < MAXROW) - { - SCROW nEndRow = pRowFlags->GetBitStateEnd( rY2+1, CR_HIDDEN, CR_HIDDEN); - if (ValidRow(nEndRow)) - rY2 = nEndRow; - } + } + if (rY2 < MAXROW) + { + SCROW nEndRow = -1; + if (RowHidden(rY2+1, nEndRow) && ValidRow(nEndRow)) + rY2 = nEndRow; } } void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) { - if (pColFlags) - { - while ( rX2>rX1 && (pColFlags[rX2] & CR_HIDDEN) ) - --rX2; - while ( rX2>rX1 && (pColFlags[rX1] & CR_HIDDEN) ) - ++rX1; - } - if (pRowFlags) + while ( rX2>rX1 && ColHidden(rX2) ) + --rX2; + while ( rX2>rX1 && ColHidden(rX1) ) + ++rX1; + + if (rY1 < rY2) { - if (rY1 < rY2) + ScFlatBoolRowSegments::RangeData aData; + if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue) { - SCROW nStartRow = pRowFlags->GetBitStateStart( rY2, CR_HIDDEN, CR_HIDDEN); + SCROW nStartRow = aData.mnRow1; if (ValidRow(nStartRow) && nStartRow >= rY1) rY2 = nStartRow; } - if (rY1 < rY2) - { - SCROW nEndRow = pRowFlags->GetBitStateEnd( rY1, CR_HIDDEN, CR_HIDDEN); - if (ValidRow(nEndRow) && nEndRow <= rY2) - rY1 = nEndRow; - } + } + + if (rY1 < rY2) + { + SCROW nEndRow = -1; + if (RowHidden(rY1, nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2) + rY1 = nEndRow; } } @@ -2799,16 +2985,16 @@ BOOL ScTable::RefVisible(ScFormulaCell* pCell) if (pCell->HasOneReference(aRef)) { - if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab() && pRowFlags) + if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab()) { - // while ((value & CR_FILTERED) == CR_FILTERED) - // most times will be faster than - // while ((value & CR_FILTERED) == 0) - SCROW nEndRow = pRowFlags->GetBitStateEnd( aRef.aStart.Row(), - CR_FILTERED, CR_FILTERED); + SCROW nEndRow; + if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow)) + // row not filtered. + nEndRow = ::std::numeric_limits<SCROW>::max(); + if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row()) return TRUE; // at least partly visible - return FALSE; // completely unvisible + return FALSE; // completely invisible } } @@ -2850,18 +3036,17 @@ void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos } -ULONG ScTable::GetRowOffset( SCROW nRow ) const +ULONG ScTable::GetRowOffset( SCROW nRow ) { ULONG n = 0; - if ( pRowFlags && pRowHeight ) + if ( mpHiddenRows && mpRowHeights ) { if (nRow == 0) return 0; else if (nRow == 1) return GetRowHeight(0); - n = pRowFlags->SumCoupledArrayForCondition( 0, nRow-1, CR_HIDDEN, 0, - *pRowHeight); + n = GetTotalRowHeight(0, nRow-1); #ifdef DBG_UTIL if (n == ::std::numeric_limits<unsigned long>::max()) DBG_ERRORFILE("ScTable::GetRowOffset: row heights overflow"); @@ -2874,18 +3059,42 @@ ULONG ScTable::GetRowOffset( SCROW nRow ) const return n; } +SCROW ScTable::GetRowForHeight(ULONG nHeight) +{ + sal_uInt32 nSum = 0; + + ScFlatBoolRowSegments::RangeData aData; + for (SCROW nRow = 0; nRow <= MAXROW; ++nRow) + { + if (!mpHiddenRows->getRangeData(nRow, aData)) + break; + + if (aData.mbValue) + { + nRow = aData.mnRow2; + continue; + } + + sal_uInt32 nNew = mpRowHeights->getValue(nRow); + nSum += nNew; + if (nSum > nHeight) + { + return nRow < MAXROW ? nRow + 1 : MAXROW; + } + } + return -1; +} + -ULONG ScTable::GetColOffset( SCCOL nCol ) const +ULONG ScTable::GetColOffset( SCCOL nCol ) { ULONG n = 0; - if ( pColFlags && pColWidth ) + if ( pColWidth ) { SCCOL i; - BYTE* pFlags = pColFlags; - USHORT* pWidth = pColWidth; - for( i = 0; i < nCol; i++, pFlags++, pWidth++ ) - if( !( *pFlags & CR_HIDDEN ) ) - n += *pWidth; + for( i = 0; i < nCol; i++ ) + if (!ColHidden(i)) + n += pColWidth[i]; } else { diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 7d295b6286a8..bd6a2c92c442 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -208,17 +208,14 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress& rProgress ) { BOOL bByRow = aSortParam.bByRow; SCSIZE nCount = pArray->GetCount(); + SCCOLROW nStart = pArray->GetStart(); ScSortInfo** ppInfo = pArray->GetFirstArray(); - // hngngn.. Win16 legacy? Table has ULONG count but can only be initialized using USHORT :-/ - // FIXME: use std::vector instead, would be better anyway (type safe) - USHORT nArghl = (nCount > USHRT_MAX ? USHRT_MAX : static_cast<USHORT>(nCount)); - Table aTable( nArghl ); + ::std::vector<ScSortInfo*> aTable(nCount); SCSIZE nPos; for ( nPos = 0; nPos < nCount; nPos++ ) - { - aTable.Insert( ppInfo[nPos]->nOrg, (void*) ppInfo[nPos] ); - } - SCCOLROW nDest = pArray->GetStart(); + aTable[ppInfo[nPos]->nOrg - nStart] = ppInfo[nPos]; + + SCCOLROW nDest = nStart; for ( nPos = 0; nPos < nCount; nPos++, nDest++ ) { SCCOLROW nOrg = ppInfo[nPos]->nOrg; @@ -231,9 +228,9 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress& rProgress ) // neue Position des weggeswapten eintragen ScSortInfo* p = ppInfo[nPos]; p->nOrg = nDest; - p = (ScSortInfo*) aTable.Replace( nDest, (void*) p ); + ::std::swap(p, aTable[nDest-nStart]); p->nOrg = nOrg; - p = (ScSortInfo*) aTable.Replace( nOrg, (void*) p ); + ::std::swap(p, aTable[nOrg-nStart]); DBG_ASSERT( p == ppInfo[nPos], "SortReorder: nOrg MisMatch" ); } rProgress.SetStateOnPercent( nPos ); @@ -449,14 +446,17 @@ void ScTable::SwapRow(SCROW nRow1, SCROW nRow2) } } } - if (bGlobalKeepQuery && pRowFlags) + if (bGlobalKeepQuery) { - BYTE nRow1Flags = pRowFlags->GetValue(nRow1); - BYTE nRow2Flags = pRowFlags->GetValue(nRow2); - BYTE nFlags1 = nRow1Flags & ( CR_HIDDEN | CR_FILTERED ); - BYTE nFlags2 = nRow2Flags & ( CR_HIDDEN | CR_FILTERED ); - pRowFlags->SetValue( nRow1, (nRow1Flags & ~( CR_HIDDEN | CR_FILTERED )) | nFlags2); - pRowFlags->SetValue( nRow2, (nRow2Flags & ~( CR_HIDDEN | CR_FILTERED )) | nFlags1); + bool bRow1Hidden = RowHidden(nRow1); + bool bRow2Hidden = RowHidden(nRow2); + SetRowHidden(nRow1, nRow1, bRow2Hidden); + SetRowHidden(nRow2, nRow2, bRow1Hidden); + + bool bRow1Filtered = RowFiltered(nRow1); + bool bRow2Filtered = RowFiltered(nRow2); + SetRowFiltered(nRow1, nRow1, bRow2Filtered); + SetRowFiltered(nRow2, nRow2, bRow1Filtered); } } @@ -616,7 +616,7 @@ void ScTable::RemoveSubTotals( ScSubTotalParam& rParam ) if ( pCell->GetCellType() == CELLTYPE_FORMULA ) if (((ScFormulaCell*)pCell)->IsSubTotal()) { - SetRowFlags(nRow+1,GetRowFlags(nRow+1)&(~CR_MANUALBREAK)); + RemoveRowBreak(nRow+1, false, true); pDocument->DeleteRow( 0,nTab, MAXCOL,nTab, nRow, 1 ); --nEndRow; aIter = ScColumnIterator( &aCol[nCol],nRow,nEndRow ); @@ -784,9 +784,7 @@ BOOL ScTable::DoSubTotals( ScSubTotalParam& rParam ) bBlockVis = FALSE; if ( rParam.bPagebreak && nRow < MAXROW && aRowEntry.nSubStartRow != nStartRow && nLevel == 0) - SetRowFlags( aRowEntry.nSubStartRow, - GetRowFlags(aRowEntry.nSubStartRow) | - CR_MANUALBREAK); + SetRowBreak(aRowEntry.nSubStartRow, false, true); if (bSpaceLeft) { @@ -839,13 +837,6 @@ BOOL ScTable::DoSubTotals( ScSubTotalParam& rParam ) SetString( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, nTab, aOutString ); ApplyStyle( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, *pStyle ); -/* if (rParam.bPagebreak && nRow < MAXROW) - { - BYTE nFlags = GetRowFlags( nRow+1 ); - nFlags |= CR_MANUALBREAK; - SetRowFlags( nRow+1, nFlags ); - } -*/ ++nRow; ++nEndRow; aRowEntry.nSubStartRow = nRow; @@ -859,11 +850,7 @@ BOOL ScTable::DoSubTotals( ScSubTotalParam& rParam ) } } } - if (!pRowFlags) - bBlockVis = TRUE; - else - if ( (pRowFlags->GetValue(nRow) & CR_FILTERED) == 0 ) - bBlockVis = TRUE; + bBlockVis = !RowFiltered(nRow); } } else @@ -1935,8 +1922,8 @@ void ScTable::UpdateSelectionFunction( ScFunctionData& rData, SCCOL nCol; if ( rMark.IsMultiMarked() ) for (nCol=0; nCol<=MAXCOL && !rData.bError; nCol++) - if ( !pColFlags || !( pColFlags[nCol] & CR_HIDDEN ) ) - aCol[nCol].UpdateSelectionFunction( rMark, rData, pRowFlags, + if ( !pColFlags || !ColHidden(nCol) ) + aCol[nCol].UpdateSelectionFunction( rMark, rData, *mpHiddenRows, bSingle && ( nCol >= nStartCol && nCol <= nEndCol ), nStartRow, nEndRow ); @@ -1944,8 +1931,8 @@ void ScTable::UpdateSelectionFunction( ScFunctionData& rData, if ( bSingle && !rMark.IsMarkNegative() ) for (nCol=nStartCol; nCol<=nEndCol && !rData.bError; nCol++) - if ( !pColFlags || !( pColFlags[nCol] & CR_HIDDEN ) ) - aCol[nCol].UpdateAreaFunction( rData, pRowFlags, nStartRow, nEndRow ); + if ( !pColFlags || !ColHidden(nCol) ) + aCol[nCol].UpdateAreaFunction( rData, *mpHiddenRows, nStartRow, nEndRow ); } void ScTable::FindConditionalFormat( ULONG nKey, ScRangeList& rList ) diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx index a3a0153a4b97..2635b5821e4f 100644 --- a/sc/source/core/data/table5.cxx +++ b/sc/source/core/data/table5.cxx @@ -50,8 +50,15 @@ #include "brdcst.hxx" #include "tabprotection.hxx" #include "globstr.hrc" +#include "segmenttree.hxx" +#include <com/sun/star/sheet/TablePageBreakData.hpp> + +#include <algorithm> +#include <limits> using ::com::sun::star::uno::Sequence; +using ::com::sun::star::sheet::TablePageBreakData; +using ::std::set; // STATIC DATA ----------------------------------------------------------- @@ -62,8 +69,18 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) { if ( pDocument->IsImportingXML() ) return; - if ( !pUserArea && !bPageSizeValid ) - return; + + // pUserArea != NULL -> print area is specified. We need to force-update + // the page breaks. + + if (!pUserArea) + { + if (!bPageSizeValid) + return; + + if (mbPageBreaksValid) + return; + } SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()-> Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ); @@ -76,7 +93,6 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) const SfxPoolItem* pItem; SCCOL nX; - SCROW nY; SCCOL nStartCol = 0; SCROW nStartRow = 0; SCCOL nEndCol = MAXCOL; @@ -96,8 +112,9 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) // bei mehreren Bereichen nichts anzeigen: for (nX=0; nX<MAXCOL; nX++) - pColFlags[nX] &= ~CR_PAGEBREAK; - pRowFlags->AndValue( 0, MAXROW-1, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); + RemoveColBreak(nX, true, false); + + RemoveRowPageBreaks(0, MAXROW-1); return; } @@ -143,13 +160,13 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) // Anfang: Breaks loeschen for (nX=0; nX<nStartCol; nX++) - pColFlags[nX] &= ~CR_PAGEBREAK; - pRowFlags->AndValue( 0, nStartRow-1, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); + RemoveColBreak(nX, true, false); + RemoveRowPageBreaks(0, nStartRow-1); if (nStartCol > 0) - pColFlags[nStartCol] |= CR_PAGEBREAK; //! AREABREAK + SetColBreak(nStartCol, true, false); // AREABREAK if (nStartRow > 0) - pRowFlags->OrValue( nStartRow, CR_PAGEBREAK); //! AREABREAK + SetRowBreak(nStartRow, true, false); // AREABREAK // Mittelteil: Breaks verteilen @@ -159,15 +176,16 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) for (nX=nStartCol; nX<=nEndCol; nX++) { BOOL bStartOfPage = FALSE; - long nThisX = ( pColFlags[nX] & CR_HIDDEN ) ? 0 : pColWidth[nX]; - if ( (nSizeX+nThisX > nPageSizeX) || ((pColFlags[nX] & CR_MANUALBREAK) && !bSkipColBreaks) ) + long nThisX = ColHidden(nX) ? 0 : pColWidth[nX]; + bool bManualBreak = HasColManualBreak(nX); + if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks) ) { - pColFlags[nX] |= CR_PAGEBREAK; + SetColBreak(nX, true, false); nSizeX = 0; bStartOfPage = TRUE; } else if (nX != nStartCol) - pColFlags[nX] &= ~CR_PAGEBREAK; + RemoveColBreak(nX, true, false); else bStartOfPage = TRUE; @@ -175,9 +193,9 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) { // subtract size of repeat columns from page size for (SCCOL i=nRepeatStartX; i<=nRepeatEndX; i++) - nPageSizeX -= ( pColFlags[i] & CR_HIDDEN ) ? 0 : pColWidth[i]; + nPageSizeX -= ColHidden(i) ? 0 : pColWidth[i]; while (nX<=nRepeatEndX) - pColFlags[++nX] &= ~CR_PAGEBREAK; + RemoveColBreak(++nX, true, false); bColFound = TRUE; } @@ -185,23 +203,40 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) } // Remove all page breaks in range. - pRowFlags->AndValue( nStartRow+1, nEndRow, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); + RemoveRowPageBreaks(nStartRow+1, nEndRow); + // And set new page breaks. BOOL bRepeatRow = ( nRepeatStartY != SCROW_REPEAT_NONE ); BOOL bRowFound = FALSE; long nSizeY = 0; - ScCompressedArrayIterator< SCROW, BYTE> aFlagsIter( *pRowFlags, nStartRow, nEndRow); - ScCompressedArrayIterator< SCROW, USHORT> aHeightIter( *pRowHeight, nStartRow, nEndRow); - for ( ; aFlagsIter; ++aFlagsIter, ++aHeightIter) + ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows); + ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights); + SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks + for (SCROW nY = nStartRow; nY <= nEndRow; ++nY) { - nY = aFlagsIter.GetPos(); BOOL bStartOfPage = FALSE; - BYTE nFlags = *aFlagsIter; - long nThisY = (nFlags & CR_HIDDEN) ? 0 : *aHeightIter; - if ( (nSizeY+nThisY > nPageSizeY) || ((nFlags & CR_MANUALBREAK) && !bSkipRowBreaks) ) + bool bThisRowHidden = false; + aIterHidden.getValue(nY, bThisRowHidden); + long nThisY = 0; + if (!bThisRowHidden) + { + sal_uInt16 nTmp; + aIterHeights.getValue(nY, nTmp); + nThisY = static_cast<long>(nTmp); + } + + bool bManualBreak = false; + if (nNextManualBreak >= 0) + { + bManualBreak = (nY == nNextManualBreak); + if (nY >= nNextManualBreak) + // Query the next menual break position. + nNextManualBreak = GetNextManualBreak(nY+1); + } + + if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks) ) { - pRowFlags->SetValue( nY, nFlags | CR_PAGEBREAK); - aFlagsIter.Resync( nY); + SetRowBreak(nY, true, false); nSizeY = 0; bStartOfPage = TRUE; } @@ -213,21 +248,47 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) if ( bStartOfPage && bRepeatRow && nY>nRepeatStartY && !bRowFound ) { // subtract size of repeat rows from page size - unsigned long nHeights = pRowFlags->SumCoupledArrayForCondition( - nRepeatStartY, nRepeatEndY, CR_HIDDEN, 0, *pRowHeight); + unsigned long nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY); #ifdef DBG_UTIL if (nHeights == ::std::numeric_limits<unsigned long>::max()) DBG_ERRORFILE("ScTable::UpdatePageBreaks: row heights overflow"); #endif nPageSizeY -= nHeights; if (nY <= nRepeatEndY) + RemoveRowPageBreaks(nY, nRepeatEndY); + bRowFound = TRUE; + } + + if (bThisRowHidden) + { + // Hidden row range. Skip them unless there is a manual break. + SCROW nLastCommon = aIterHidden.getLastPos(); + if (nNextManualBreak >= 0) + nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1); + nY = nLastCommon; + } + else + { + // Visible row range. + + SCROW nLastHidden = aIterHidden.getLastPos(); + SCROW nLastHeight = aIterHeights.getLastPos(); + SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight); + if (nNextManualBreak >= 0) + nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1); + + if (nLastCommon > nY) { - pRowFlags->AndValue( nY, nRepeatEndY, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); - nY = nRepeatEndY + 1; - aFlagsIter.Resync( nY); - aHeightIter.Resync( nY); + long nMaxMultiple = static_cast<long>(nLastCommon - nY); + long nMultiple = (nPageSizeY - nSizeY) / nThisY; + if (nMultiple > nMaxMultiple) + nMultiple = nMaxMultiple; + if (nMultiple > 1) + { + nSizeY += nThisY * (nMultiple - 1); + nY += nMultiple - 1; + } } - bRowFound = TRUE; } nSizeY += nThisY; @@ -237,26 +298,24 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) if (nEndCol < MAXCOL) { - pColFlags[nEndCol+1] |= CR_PAGEBREAK; //! AREABREAK + SetColBreak(nEndCol+1, true, false); // AREABREAK for (nX=nEndCol+2; nX<=MAXCOL; nX++) - pColFlags[nX] &= ~CR_PAGEBREAK; + RemoveColBreak(nX, true, false); } if (nEndRow < MAXROW) { - pRowFlags->OrValue( nEndRow+1, CR_PAGEBREAK); //! AREABREAK + SetRowBreak(nEndRow+1, true, false); // AREABREAK if (nEndRow+2 <= MAXROW) - pRowFlags->AndValue( nEndRow+2, MAXROW, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); + RemoveRowPageBreaks(nEndRow+2, MAXROW); } + mbPageBreaksValid = true; } void ScTable::RemoveManualBreaks() { - if (pColFlags) - for (SCCOL nCol = 0; nCol <= MAXCOL; nCol++) - pColFlags[nCol] &= ~CR_MANUALBREAK; - - if (pRowFlags) - pRowFlags->AndValue( 0, MAXROW, sal::static_int_cast<BYTE>(~CR_MANUALBREAK) ); + maRowManualBreaks.clear(); + maColManualBreaks.clear(); + InvalidatePageBreaks(); if (IsStreamValid()) SetStreamValid(FALSE); @@ -264,22 +323,673 @@ void ScTable::RemoveManualBreaks() BOOL ScTable::HasManualBreaks() const { - if (pColFlags) - for (SCCOL nCol = 0; nCol <= MAXCOL; nCol++) - if ( pColFlags[nCol] & CR_MANUALBREAK ) - return TRUE; + return !maRowManualBreaks.empty() || !maColManualBreaks.empty(); +} + +void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const +{ + if (bPage) + rBreaks = maRowPageBreaks; + + if (bManual) + { + using namespace std; + copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(rBreaks, rBreaks.begin())); + } +} + +void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const +{ + if (bPage) + rBreaks = maColPageBreaks; - if (pRowFlags) - if (ValidRow( pRowFlags->GetLastAnyBitAccess( 0, CR_MANUALBREAK))) - return TRUE; + if (bManual) + { + using namespace std; + copy(maColManualBreaks.begin(), maColManualBreaks.end(), inserter(rBreaks, rBreaks.begin())); + } +} + +bool ScTable::HasRowPageBreak(SCROW nRow) const +{ + if (!ValidRow(nRow)) + return false; + + return maRowPageBreaks.count(nRow) > 0; +} + +bool ScTable::HasColPageBreak(SCCOL nCol) const +{ + if (!ValidCol(nCol)) + return false; + + return maColPageBreaks.count(nCol) > 0; +} + +bool ScTable::HasRowManualBreak(SCROW nRow) const +{ + if (!ValidRow(nRow)) + return false; + + return maRowManualBreaks.count(nRow) > 0; +} - return FALSE; +bool ScTable::HasColManualBreak(SCCOL nCol) const +{ + if (!ValidCol(nCol)) + return false; + + return (maColManualBreaks.count(nCol) > 0); +} + +SCROW ScTable::GetNextManualBreak(SCROW nRow) const +{ + set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow); + return itr == maRowManualBreaks.end() ? -1 : *itr; +} + +void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow) +{ + using namespace std; + + if (!ValidRow(nStartRow) || !ValidRow(nEndRow)) + return; + + set<SCROW>::iterator low = maRowPageBreaks.lower_bound(nStartRow); + set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow); + maRowPageBreaks.erase(low, high); +} + +void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual) +{ + if (!ValidRow(nRow)) + return; + + if (bPage) + maRowPageBreaks.erase(nRow); + + if (bManual) + { + maRowManualBreaks.erase(nRow); + InvalidatePageBreaks(); + } +} + +void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual) +{ + if (!ValidCol(nCol)) + return; + + if (bPage) + maColPageBreaks.erase(nCol); + + if (bManual) + { + maColManualBreaks.erase(nCol); + InvalidatePageBreaks(); + } +} + +void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual) +{ + if (!ValidRow(nRow)) + return; + + if (bPage) + maRowPageBreaks.insert(nRow); + + if (bManual) + { + maRowManualBreaks.insert(nRow); + InvalidatePageBreaks(); + } +} + +void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual) +{ + if (!ValidCol(nCol)) + return; + + if (bPage) + maColPageBreaks.insert(nCol); + + if (bManual) + { + maColManualBreaks.insert(nCol); + InvalidatePageBreaks(); + } +} + +Sequence<TablePageBreakData> ScTable::GetRowBreakData() const +{ + using ::std::copy; + using ::std::inserter; + + set<SCROW> aRowBreaks = maRowPageBreaks; + copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(aRowBreaks, aRowBreaks.begin())); + + set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end(); + Sequence<TablePageBreakData> aSeq(aRowBreaks.size()); + + for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i) + { + SCROW nRow = *itr; + TablePageBreakData aData; + aData.Position = nRow; + aData.ManualBreak = HasRowManualBreak(nRow); + aSeq[i] = aData; + } + + return aSeq; +} + +bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) +{ + if (!ValidRow(nRow)) + return true; + + ScFlatBoolRowSegments::RangeData aData; + if (!mpHiddenRows->getRangeData(nRow, aData)) + // search failed. + return true; + + if (pFirstRow) + *pFirstRow = aData.mnRow1; + if (pLastRow) + *pLastRow = aData.mnRow2; + + return aData.mbValue; +} + + +bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) +{ + rLastRow = nRow; + if (!ValidRow(nRow)) + return true; + + ScFlatBoolRowSegments::RangeData aData; + if (!mpHiddenRows->getRangeData(nRow, aData)) + // search failed. + return true; + + rLastRow = aData.mnRow2; + return aData.mbValue; +} + +bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = -1; + bool bHidden = RowHidden(nRow, nLastRow); + if (bHidden) + return true; + + nRow = nLastRow + 1; + } + return false; +} + +bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) +{ + rLastCol = nCol; + if (!ValidCol(nCol)) + return true; + + ScFlatBoolColSegments::RangeData aData; + if (!mpHiddenCols->getRangeData(nCol, aData)) + return true; + + rLastCol = aData.mnCol2; + return aData.mbValue; +} + +bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) +{ + if (!ValidCol(nCol)) + return true; + + ScFlatBoolColSegments::RangeData aData; + if (!mpHiddenCols->getRangeData(nCol, aData)) + return true; + + if (pFirstCol) + *pFirstCol = aData.mnCol1; + if (pLastCol) + *pLastCol = aData.mnCol2; + + return aData.mbValue; +} + +void ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden) +{ + if (bHidden) + mpHiddenRows->setTrue(nStartRow, nEndRow); + else + mpHiddenRows->setFalse(nStartRow, nEndRow); +} + +void ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden) +{ + if (bHidden) + mpHiddenCols->setTrue(nStartCol, nEndCol); + else + mpHiddenCols->setFalse(nStartCol, nEndCol); +} + +void ScTable::CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol) +{ + SCCOL nCol = nStartCol; + while (nCol <= nEndCol) + { + SCCOL nLastCol; + bool bHidden = rTable.ColHidden(nCol, NULL, &nLastCol); + if (nLastCol > nEndCol) + nLastCol = nEndCol; + + SetColHidden(nCol, nLastCol, bHidden); + nCol = nLastCol + 1; + } +} + +void ScTable::CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = -1; + bool bHidden = rTable.RowHidden(nRow, nLastRow); + if (nLastRow > nEndRow) + nLastRow = nEndRow; + SetRowHidden(nRow, nLastRow, bHidden); + nRow = nLastRow + 1; + } +} + +void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset) +{ + SCROW nRow = nStartRow; + ScFlatUInt16RowSegments::RangeData aSrcData; + while (nRow <= nEndRow) + { + if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData)) + // Something is wrong ! + return; + + SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset; + if (nLastRow > nEndRow) + nLastRow = nEndRow; + + mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue); + nRow = nLastRow + 1; + } +} + +SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= nEndRow) + { + if (!ValidRow(nRow)) + break; + + if (!mpHiddenRows->getRangeData(nRow, aData)) + // failed to get range data. + break; + + if (!aData.mbValue) + // visible row found + return nRow; + + nRow = aData.mnRow2 + 1; + } + + return ::std::numeric_limits<SCROW>::max(); +} + +SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nEndRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow >= nStartRow) + { + if (!ValidRow(nRow)) + break; + + if (!mpHiddenRows->getRangeData(nRow, aData)) + // failed to get range data. + break; + + if (!aData.mbValue) + // visible row found + return nRow; + + nRow = aData.mnRow1 - 1; + } + + return ::std::numeric_limits<SCROW>::max(); +} + +SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nCount = 0; + SCROW nRow = nStartRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= nEndRow) + { + if (!mpHiddenRows->getRangeData(nRow, aData)) + break; + + if (aData.mnRow2 > nEndRow) + aData.mnRow2 = nEndRow; + + if (!aData.mbValue) + nCount += aData.mnRow2 - nRow + 1; + + nRow = aData.mnRow2 + 1; + } + return nCount; +} + +sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) +{ + sal_uInt32 nHeight = 0; + SCROW nRow = nStartRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= nEndRow) + { + if (!mpHiddenRows->getRangeData(nRow, aData)) + break; + + if (aData.mnRow2 > nEndRow) + aData.mnRow2 = nEndRow; + + if (!aData.mbValue) + // visible row range. + nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2); + + nRow = aData.mnRow2 + 1; + } + + return nHeight; +} + +SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) +{ + if (bCol) + { + SCCOL nCol = static_cast<SCCOL>(nPos); + if (ColHidden(nCol)) + { + for (SCCOL i = nCol+1; i <= MAXCOL; ++i) + { + if (!ColHidden(nCol)) + return nCol - 1; + } + } + } + else + { + SCROW nRow = static_cast<SCROW>(nPos); + SCROW nLastRow; + if (RowHidden(nRow, NULL, &nLastRow)) + return static_cast<SCCOLROW>(nLastRow); + } + return ::std::numeric_limits<SCCOLROW>::max(); +} + +bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) +{ + if (!ValidRow(nRow)) + return false; + + ScFlatBoolRowSegments::RangeData aData; + if (!mpFilteredRows->getRangeData(nRow, aData)) + // search failed. + return false; + + if (pFirstRow) + *pFirstRow = aData.mnRow1; + if (pLastRow) + *pLastRow = aData.mnRow2; + + return aData.mbValue; +} + +bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) +{ + if (!ValidCol(nCol)) + return false; + + ScFlatBoolColSegments::RangeData aData; + if (!mpFilteredCols->getRangeData(nCol, aData)) + // search failed. + return false; + + if (pFirstCol) + *pFirstCol = aData.mnCol1; + if (pLastCol) + *pLastCol = aData.mnCol2; + + return aData.mbValue; +} + +bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = nRow; + bool bFiltered = RowFiltered(nRow, NULL, &nLastRow); + if (bFiltered) + return true; + + nRow = nLastRow + 1; + } + return false; +} + +void ScTable::CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol) +{ + SCCOL nCol = nStartCol; + while (nCol <= nEndCol) + { + SCCOL nLastCol; + bool bFiltered = rTable.ColFiltered(nCol, NULL, &nLastCol); + if (nLastCol > nEndCol) + nLastCol = nEndCol; + + SetColFiltered(nCol, nLastCol, bFiltered); + nCol = nLastCol + 1; + } +} + +void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + while (nRow <= nEndRow) + { + SCROW nLastRow = -1; + bool bFiltered = rTable.RowFiltered(nRow, NULL, &nLastRow); + if (nLastRow > nEndRow) + nLastRow = nEndRow; + SetRowFiltered(nRow, nLastRow, bFiltered); + nRow = nLastRow + 1; + } +} + +void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered) +{ + if (bFiltered) + mpFilteredRows->setTrue(nStartRow, nEndRow); + else + mpFilteredRows->setFalse(nStartRow, nEndRow); +} + +void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered) +{ + if (bFiltered) + mpFilteredCols->setTrue(nStartCol, nEndCol); + else + mpFilteredCols->setFalse(nStartCol, nEndCol); +} + +SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nStartRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= nEndRow) + { + if (!ValidRow(nRow)) + break; + + if (!mpFilteredRows->getRangeData(nRow, aData)) + // failed to get range data. + break; + + if (!aData.mbValue) + // non-filtered row found + return nRow; + + nRow = aData.mnRow2 + 1; + } + + return ::std::numeric_limits<SCROW>::max(); +} + +SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nRow = nEndRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow >= nStartRow) + { + if (!ValidRow(nRow)) + break; + + if (!mpFilteredRows->getRangeData(nRow, aData)) + // failed to get range data. + break; + + if (!aData.mbValue) + // non-filtered row found + return nRow; + + nRow = aData.mnRow1 - 1; + } + + return ::std::numeric_limits<SCROW>::max(); +} + +SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) +{ + SCROW nCount = 0; + SCROW nRow = nStartRow; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= nEndRow) + { + if (!mpFilteredRows->getRangeData(nRow, aData)) + break; + + if (aData.mnRow2 > nEndRow) + aData.mnRow2 = nEndRow; + + if (!aData.mbValue) + nCount += aData.mnRow2 - nRow + 1; + + nRow = aData.mnRow2 + 1; + } + return nCount; +} + +namespace { + +void lcl_syncFlags(ScFlatBoolColSegments& rColSegments, ScFlatBoolRowSegments& rRowSegments, + BYTE* pColFlags, ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags, const BYTE nFlagMask) +{ + using ::sal::static_int_cast; + + pRowFlags->AndValue(0, MAXROW, static_int_cast<BYTE>(~nFlagMask)); + for (SCCOL i = 0; i <= MAXCOL; ++i) + pColFlags[i] &= static_int_cast<BYTE>(~nFlagMask); + + { + // row hidden flags. + + SCROW nRow = 0; + ScFlatBoolRowSegments::RangeData aData; + while (nRow <= MAXROW) + { + if (!rRowSegments.getRangeData(nRow, aData)) + break; + + if (aData.mbValue) + pRowFlags->OrValue(nRow, aData.mnRow2, static_int_cast<BYTE>(nFlagMask)); + + nRow = aData.mnRow2 + 1; + } + } + + { + // column hidden flags. + + SCCOL nCol = 0; + ScFlatBoolColSegments::RangeData aData; + while (nCol <= MAXCOL) + { + if (!rColSegments.getRangeData(nCol, aData)) + break; + + if (aData.mbValue) + { + for (SCCOL i = nCol; i <= aData.mnCol2; ++i) + pColFlags[i] |= nFlagMask; + } + + nCol = aData.mnCol2 + 1; + } + } +} + +} + +void ScTable::SyncColRowFlags() +{ + using ::sal::static_int_cast; + + // Manual breaks. + pRowFlags->AndValue(0, MAXROW, static_int_cast<BYTE>(~CR_MANUALBREAK)); + for (SCCOL i = 0; i <= MAXCOL; ++i) + pColFlags[i] &= static_int_cast<BYTE>(~CR_MANUALBREAK); + + if (!maRowManualBreaks.empty()) + { + for (set<SCROW>::const_iterator itr = maRowManualBreaks.begin(), itrEnd = maRowManualBreaks.end(); + itr != itrEnd; ++itr) + pRowFlags->OrValue(*itr, static_int_cast<BYTE>(CR_MANUALBREAK)); + } + + if (!maColManualBreaks.empty()) + { + for (set<SCCOL>::const_iterator itr = maColManualBreaks.begin(), itrEnd = maColManualBreaks.end(); + itr != itrEnd; ++itr) + pColFlags[*itr] |= CR_MANUALBREAK; + } + + // Hidden flags. + lcl_syncFlags(*mpHiddenCols, *mpHiddenRows, pColFlags, pRowFlags, CR_HIDDEN); + lcl_syncFlags(*mpFilteredCols, *mpFilteredRows, pColFlags, pRowFlags, CR_FILTERED); } void ScTable::SetPageSize( const Size& rSize ) { if ( rSize.Width() != 0 && rSize.Height() != 0 ) { + if (aPageSizeTwips != rSize) + InvalidatePageBreaks(); + bPageSizeValid = TRUE; aPageSizeTwips = rSize; } diff --git a/sc/source/core/data/tabprotection.cxx b/sc/source/core/data/tabprotection.cxx index 5b87fef3151a..2709dd54d1fb 100644 --- a/sc/source/core/data/tabprotection.cxx +++ b/sc/source/core/data/tabprotection.cxx @@ -33,6 +33,7 @@ #include "tabprotection.hxx" #include "tools/debug.hxx" #include "svl/PasswordHelper.hxx" +#include <comphelper/docpasswordhelper.hxx> #include "document.hxx" #define DEBUG_TAB_PROTECTION 0 @@ -75,40 +76,6 @@ ScPassHashProtectable::~ScPassHashProtectable() // ============================================================================ -static sal_uInt16 lcl_getXLHashFromChar(const sal_Char* szPassword) -{ - sal_uInt16 cchPassword = static_cast< sal_uInt16 >( strlen(szPassword) ); - sal_uInt16 wPasswordHash = 0; - if (!cchPassword) - return wPasswordHash; - - const char* pch = &szPassword[cchPassword]; - while (pch-- != szPassword) - { - wPasswordHash = ((wPasswordHash >> 14) & 0x01) | - ((wPasswordHash << 1) & 0x7fff); - wPasswordHash ^= *pch; - } - - wPasswordHash = ((wPasswordHash >> 14) & 0x01) | - ((wPasswordHash << 1) & 0x7fff); - - wPasswordHash ^= (0x8000 | ('N' << 8) | 'K'); - wPasswordHash ^= cchPassword; - - return wPasswordHash; -} - -static Sequence<sal_Int8> lcl_getXLHash(const String& aPassText) -{ - const sal_Char* szBuf = OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr(); - sal_uInt16 nHash = lcl_getXLHashFromChar(szBuf); - Sequence<sal_Int8> aHash(2); - aHash[0] = (nHash >> 8) & 0xFF; - aHash[1] = nHash & 0xFF; - return aHash; -} - class ScTableProtectionImpl { public: @@ -146,7 +113,7 @@ Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, switch (eHash) { case PASSHASH_XL: - aHash = lcl_getXLHash(aPassText); + aHash = ::comphelper::DocPasswordHelper::GetXLHashAsSequence( aPassText, RTL_TEXTENCODING_UTF8 ); break; case PASSHASH_OOO: default: diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx index 1ecbefe4a9b1..13384b033628 100644 --- a/sc/source/core/inc/bcaslot.hxx +++ b/sc/source/core/inc/bcaslot.hxx @@ -214,10 +214,6 @@ private: +---+---+ */ - /* TODO: When going for 1M rows this will definitely need some change, or - * with lots of referred sheets even the reservation of NULL pointers would - * be a memory hog. */ - class TableSlots { public: @@ -227,7 +223,8 @@ private: /** Obtain slot pointer, no check on validity! It is assumed that - all calls are made with the result of ComputeSlotOfsset() + all calls are made with the results of ComputeSlotOffset(), + ComputeAreaPoints() and ComputeNextSlot() */ inline ScBroadcastAreaSlot* getAreaSlot( SCSIZE nOff ) { return *(ppSlots + nOff); } diff --git a/sc/source/core/inc/doubleref.hxx b/sc/source/core/inc/doubleref.hxx index e7bd2dfa6ae1..10221d942c9c 100644 --- a/sc/source/core/inc/doubleref.hxx +++ b/sc/source/core/inc/doubleref.hxx @@ -47,11 +47,10 @@ struct ScQueryParamBase; class ScDBRangeBase { public: - enum RefType { INTERNAL, EXTERNAL }; + enum RefType { INTERNAL, EXTERNAL }; // TODO: We may not need this after all... (kohei) virtual ~ScDBRangeBase() = 0; - RefType getType() const; bool fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const; virtual SCCOL getColSize() const = 0; diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx index c0ae60f13841..07b79c11b373 100644 --- a/sc/source/core/tool/addincol.cxx +++ b/sc/source/core/tool/addincol.cxx @@ -51,6 +51,7 @@ #include <com/sun/star/table/XCellRange.hpp> #include <com/sun/star/lang/Locale.hpp> #include <com/sun/star/sheet/XCompatibilityNames.hpp> +#include <com/sun/star/sheet/NoConvergenceException.hpp> #include "addincol.hxx" #include "addinhelpid.hxx" @@ -1582,9 +1583,13 @@ void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs) if ( rWrapped.TargetException.getValueType().equals( getCppuType( (lang::IllegalArgumentException*)0 ) ) ) nErrCode = errIllegalArgument; + else if ( rWrapped.TargetException.getValueType().equals( + getCppuType( (sheet::NoConvergenceException*)0 ) ) ) + nErrCode = errNoConvergence; else nErrCode = errNoValue; } + catch(uno::Exception&) { nErrCode = errNoValue; diff --git a/sc/source/core/tool/chartarr.cxx b/sc/source/core/tool/chartarr.cxx index 9e4e77b7c1d4..573763141b18 100644 --- a/sc/source/core/tool/chartarr.cxx +++ b/sc/source/core/tool/chartarr.cxx @@ -44,6 +44,9 @@ #include "cell.hxx" #include "docoptio.hxx" +#include <vector> + +using ::std::vector; // ----------------------------------------------------------------------- @@ -163,11 +166,17 @@ ScMemChart* ScChartArray::CreateMemChartSingle() SCCOL nStrCol = nCol1; // fuer Beschriftung merken SCROW nStrRow = nRow1; - // Beschriftungen auch nach HiddenCols finden - while ( (pDocument->GetColFlags( nCol1, nTab1) & CR_HIDDEN) != 0 ) - nCol1++; - nRow1 = pDocument->GetRowFlagsArray( nTab1).GetFirstForCondition( nRow1, - nRow2, CR_HIDDEN, 0); + // Skip hidden columns. + // TODO: make use of last column value once implemented. + SCCOL nLastCol = -1; + while (pDocument->ColHidden(nCol1, nTab1, nLastCol)) + ++nCol1; + + // Skip hidden rows. + SCROW nLastRow = -1; + if (pDocument->RowHidden(nRow1, nTab1, nLastRow)) + nRow1 = nLastRow + 1; + // falls alles hidden ist, bleibt die Beschriftung am Anfang if ( nCol1 <= nCol2 ) { @@ -181,17 +190,33 @@ ScMemChart* ScChartArray::CreateMemChartSingle() } SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 ); - SCCOL* pCols = new SCCOL[nTotalCols > 0 ? nTotalCols : 1]; - SCSIZE nColCount = 0; + vector<SCCOL> aCols; + aCols.reserve(nTotalCols); for (SCSIZE i=0; i<nTotalCols; i++) - if ((pDocument->GetColFlags(sal::static_int_cast<SCCOL>(nCol1+i),nTab1)&CR_HIDDEN)==0) - pCols[nColCount++] = sal::static_int_cast<SCCOL>(nCol1+i); + { + SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i); + if (!pDocument->ColHidden(nThisCol, nTab1, nLastCol)) + aCols.push_back(nThisCol); + } + SCSIZE nColCount = aCols.size(); SCSIZE nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 ); - SCROW* pRows = new SCROW[nTotalRows > 0 ? nTotalRows : 1]; - SCSIZE nRowCount = (nTotalRows ? - pDocument->GetRowFlagsArray( nTab1).FillArrayForCondition( nRow1, - nRow2, CR_HIDDEN, 0, pRows, nTotalRows) : 0); + vector<SCROW> aRows; + aRows.reserve(nTotalRows); + if (nRow1 <= nRow2) + { + // Get all visible rows between nRow1 and nRow2. + SCROW nThisRow = nRow1; + while (nThisRow <= nRow2) + { + if (pDocument->RowHidden(nThisRow, nTab1, nLastRow)) + nThisRow = nLastRow; + else + aRows.push_back(nThisRow); + ++nThisRow; + } + } + SCSIZE nRowCount = aRows.size(); // May happen at least with more than 32k rows. if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX) @@ -205,13 +230,13 @@ ScMemChart* ScChartArray::CreateMemChartSingle() { bValidData = FALSE; nColCount = 1; - pCols[0] = nStrCol; + aCols.push_back(nStrCol); } if ( !nRowCount ) { bValidData = FALSE; nRowCount = 1; - pRows[0] = nStrRow; + aRows.push_back(nStrRow); } // @@ -234,7 +259,7 @@ ScMemChart* ScChartArray::CreateMemChartSingle() { double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen - pDocument->GetCell( pCols[nCol], pRows[nRow], nTab1, pCell ); + pDocument->GetCell( aCols[nCol], aRows[nRow], nTab1, pCell ); if (pCell) { CellType eType = pCell->GetCellType(); @@ -244,8 +269,8 @@ ScMemChart* ScChartArray::CreateMemChartSingle() if ( bCalcAsShown && nVal != 0.0 ) { sal_uInt32 nFormat; - pDocument->GetNumberFormat( pCols[nCol], - pRows[nRow], nTab1, nFormat ); + pDocument->GetNumberFormat( aCols[nCol], + aRows[nRow], nTab1, nFormat ); nVal = pDocument->RoundValueAsShown( nVal, nFormat ); } } @@ -277,13 +302,13 @@ ScMemChart* ScChartArray::CreateMemChartSingle() { String aString, aColStr; if (HasColHeaders()) - pDocument->GetString( pCols[nCol], nStrRow, nTab1, aString ); + pDocument->GetString( aCols[nCol], nStrRow, nTab1, aString ); if ( !aString.Len() ) { aString = ScGlobal::GetRscString(STR_COLUMN); aString += ' '; // aString += String::CreateFromInt32( pCols[nCol]+1 ); - ScAddress aPos( pCols[ nCol ], 0, 0 ); + ScAddress aPos( aCols[ nCol ], 0, 0 ); aPos.Format( aColStr, SCA_VALID_COL, NULL ); aString += aColStr; } @@ -303,14 +328,14 @@ ScMemChart* ScChartArray::CreateMemChartSingle() String aString; if (HasRowHeaders()) { - ScAddress aAddr( nStrCol, pRows[nRow], nTab1 ); - pDocument->GetString( nStrCol, pRows[nRow], nTab1, aString ); + ScAddress aAddr( nStrCol, aRows[nRow], nTab1 ); + pDocument->GetString( nStrCol, aRows[nRow], nTab1, aString ); } if ( !aString.Len() ) { aString = ScGlobal::GetRscString(STR_ROW); aString += ' '; - aString += String::CreateFromInt32( pRows[nRow]+1 ); + aString += String::CreateFromInt32( aRows[nRow]+1 ); } pMemChart->SetRowText( static_cast<short>(nRow), aString); @@ -346,11 +371,6 @@ ScMemChart* ScChartArray::CreateMemChartSingle() // SetExtraStrings( *pMemChart ); } - // Aufraeumen - - delete[] pRows; - delete[] pCols; - return pMemChart; } diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 5f4b86b7cd18..c28d295275ae 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -121,6 +121,24 @@ enum ScanState ssStop }; +// ODFF names that are not written in the current mapping but to be recognized. +// New names will be written in a future relase, then exchange (!) with the +// names in formula/source/core/resource/core_resource.src to be able to still +// read the old names as well. +struct FunctionName +{ + const sal_Char* pName; + OpCode eOp; +}; +static const FunctionName aOdffAliases[] = { + // Renamed old names: + // XXX none yet. + // Renamed new names: + { "BINOM.DIST.RANGE", ocB }, // B -> BINOM.DIST.RANGE + { "LEGACY.TDIST", ocTDist } // TDIST -> LEGACY.TDIST +}; +static const size_t nOdffAliases = sizeof(aOdffAliases) / sizeof(aOdffAliases[0]); + static const sal_Char* pInternal[ 1 ] = { "TTT" }; using namespace ::com::sun::star::i18n; @@ -2504,7 +2522,21 @@ BOOL ScCompiler::IsOpCode( const String& rName, bool bInArray ) aToken.SetOpCode(eOp); pRawToken = aToken.Clone(); } - else + else if (mxSymbols->isODFF()) + { + for (size_t i=0; i<nOdffAliases; ++i) + { + if (rName.EqualsIgnoreCaseAscii( aOdffAliases[i].pName)) + { + ScRawToken aToken; + aToken.SetOpCode( aOdffAliases[i].eOp); + pRawToken = aToken.Clone(); + bFound = TRUE; + break; // for + } + } + } + if (!bFound) { String aIntName; if (mxSymbols->hasExternals()) @@ -2887,6 +2919,7 @@ BOOL ScCompiler::IsReference( const String& rName ) BOOL ScCompiler::IsMacro( const String& rName ) { + String aName( rName); StarBASIC* pObj = 0; SfxObjectShell* pDocSh = pDoc->GetDocumentShell(); @@ -2898,7 +2931,14 @@ BOOL ScCompiler::IsMacro( const String& rName ) else pObj = pSfxApp->GetBasic(); - SbxMethod* pMeth = (SbxMethod*) pObj->Find( rName, SbxCLASS_METHOD ); + // ODFF recommends to store user-defined functions prefixed with "USER.", + // use only unprefixed name if encountered. BASIC doesn't allow '.' in a + // function name so a function "USER.FOO" could not exist, and macro check + // is assigned the lowest priority in function name check. + if (FormulaGrammar::isODFF( GetGrammar()) && aName.EqualsIgnoreCaseAscii( "USER.", 0, 5)) + aName.Erase( 0, 5); + + SbxMethod* pMeth = (SbxMethod*) pObj->Find( aName, SbxCLASS_METHOD ); if( !pMeth ) { pSfxApp->LeaveBasicCall(); @@ -2913,7 +2953,7 @@ BOOL ScCompiler::IsMacro( const String& rName ) return FALSE; } ScRawToken aToken; - aToken.SetExternal( rName.GetBuffer() ); + aToken.SetExternal( aName.GetBuffer() ); aToken.eOp = ocMacro; pRawToken = aToken.Clone(); pSfxApp->LeaveBasicCall(); diff --git a/sc/source/core/tool/detfunc.cxx b/sc/source/core/tool/detfunc.cxx index 1f257512ae50..e86bb22646c8 100644 --- a/sc/source/core/tool/detfunc.cxx +++ b/sc/source/core/tool/detfunc.cxx @@ -359,7 +359,7 @@ Point ScDetectiveFunc::GetDrawPos( SCCOL nCol, SCROW nRow, DrawPosMode eMode ) c for ( SCCOL i = 0; i < nCol; ++i ) aPos.X() += pDoc->GetColWidth( i, nTab ); - aPos.Y() += pDoc->FastGetRowHeight( 0, nRow - 1, nTab ); + aPos.Y() += pDoc->GetRowHeight( 0, nRow - 1, nTab ); aPos.X() = static_cast< long >( aPos.X() * HMM_PER_TWIPS ); aPos.Y() = static_cast< long >( aPos.Y() * HMM_PER_TWIPS ); diff --git a/sc/source/core/tool/doubleref.cxx b/sc/source/core/tool/doubleref.cxx index 5c2d3f575654..740413ea8533 100644 --- a/sc/source/core/tool/doubleref.cxx +++ b/sc/source/core/tool/doubleref.cxx @@ -268,11 +268,6 @@ ScDBRangeBase::~ScDBRangeBase() { } -ScDBRangeBase::RefType ScDBRangeBase::getType() const -{ - return meType; -} - bool ScDBRangeBase::fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const { if (!pDBRef) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 2bf6a5680613..5c326001ff02 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -537,9 +537,14 @@ BOOL ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, BYTE* pCellArr) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateDoubleArr" ); -#if SC_ROWLIMIT_MORE_THAN_64K -#error row limit 64k + + // Old Add-Ins are hard limited to USHORT values. +#if MAXCOLCOUNT_DEFINE > USHRT_MAX +#error Add check for columns > USHRT_MAX! #endif + if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX) + return FALSE; + USHORT nCount = 0; USHORT* p = (USHORT*) pCellArr; *p++ = static_cast<USHORT>(nCol1); @@ -618,9 +623,14 @@ BOOL ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, BYTE* pCellArr) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateStringArr" ); -#if SC_ROWLIMIT_MORE_THAN_64K -#error row limit 64k + + // Old Add-Ins are hard limited to USHORT values. +#if MAXCOLCOUNT_DEFINE > USHRT_MAX +#error Add check for columns > USHRT_MAX! #endif + if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX) + return FALSE; + USHORT nCount = 0; USHORT* p = (USHORT*) pCellArr; *p++ = static_cast<USHORT>(nCol1); @@ -713,9 +723,14 @@ BOOL ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, BYTE* pCellArr) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateCellArr" ); -#if SC_ROWLIMIT_MORE_THAN_64K -#error row limit 64k + + // Old Add-Ins are hard limited to USHORT values. +#if MAXCOLCOUNT_DEFINE > USHRT_MAX +#error Add check for columns > USHRT_MAX! #endif + if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX) + return FALSE; + USHORT nCount = 0; USHORT* p = (USHORT*) pCellArr; *p++ = static_cast<USHORT>(nCol1); @@ -2125,7 +2140,7 @@ void ScInterpreter::ScExternal() if (ScGlobal::GetFuncCollection()->SearchFunc(aFuncName, nIndex)) { FuncData* pFuncData = (FuncData*)ScGlobal::GetFuncCollection()->At(nIndex); - if (nParamCount == pFuncData->GetParamCount() - 1) + if (nParamCount <= MAXFUNCPARAM && nParamCount == pFuncData->GetParamCount() - 1) { ParamType eParamType[MAXFUNCPARAM]; void* ppParam[MAXFUNCPARAM]; |