diff options
author | obo <obo@openoffice.org> | 2010-06-23 13:38:34 +0200 |
---|---|---|
committer | obo <obo@openoffice.org> | 2010-06-23 13:38:34 +0200 |
commit | b3579d71c6536ab1d03cc47249d582a574fd054a (patch) | |
tree | 5faa250b128f353ebfedd7481ad4ca7e8629433d | |
parent | 67cd558ced4f52b7f431e138a1071e30e88ead53 (diff) |
koheirowlimitperf: #i109369# #i109373# #i109384# #i109385# #i109386# #i109387# #i109388# #i109389# #i109391# #i109934# #i109935# #i110116# #i111531# #i111887# #i112190# #i30215# increased the row limit to 1 million, and integrated lots of speed optimization and bug fixes to ensure Calc remains usable after the row limit increase.
97 files changed, 3807 insertions, 1410 deletions
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx index 3eef919e2f1b..c5d49632292e 100644 --- a/sc/inc/address.hxx +++ b/sc/inc/address.hxx @@ -82,9 +82,10 @@ const SCSIZE SCSIZE_MAX = ::std::numeric_limits<SCSIZE>::max(); // A define to handle critical sections we hopefully don't need very often. #define SC_ROWLIMIT_MORE_THAN_32K 1 /* set to 1 if we throw the switch */ -// The maximum values. Defines are needed for preprocessor checks in -// bcaslot.cxx, otherwise type safe constants are preferred. -#define MAXROWCOUNT_DEFINE 65536 +// The maximum values. Defines are needed for preprocessor checks, for example +// in bcaslot.cxx, otherwise type safe constants are preferred. +//#define MAXROWCOUNT_DEFINE 65536 +#define MAXROWCOUNT_DEFINE 1048576 #define MAXCOLCOUNT_DEFINE 1024 // Count values @@ -123,7 +124,11 @@ const SCROW SCROW_REPEAT_NONE = SCROW_MAX; // #if SC_ROWLIMIT_MORE_THAN_64K // #error row limit 64k // #endif -#define SC_ROWLIMIT_MORE_THAN_64K 0 /* set to 1 if we throw the switch */ +#if MAXROWCOUNT_DEFINE > 65536 +#define SC_ROWLIMIT_MORE_THAN_64K 1 +#else +#define SC_ROWLIMIT_MORE_THAN_64K 0 +#endif const SCROW SCROWS64K = 65536; // === old stuff defines ===================================================== diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx index c82d607577bf..11b21bab0162 100644 --- a/sc/inc/attarray.hxx +++ b/sc/inc/attarray.hxx @@ -35,6 +35,7 @@ class ScDocument; class ScMarkArray; class ScPatternAttr; class ScStyleSheet; +class ScFlatBoolRowSegments; class Rectangle; class SfxItemPoolCache; @@ -154,7 +155,7 @@ public: BOOL bRefresh, BOOL bAttrs ); BOOL RemoveAreaMerge( SCROW nStartRow, SCROW nEndRow ); - void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset ); + void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ); BOOL IsStyleSheetUsed( const ScStyleSheet& rStyle, BOOL bGatherAllStyles ) const; void DeleteAreaSafe(SCROW nStartRow, SCROW nEndRow); diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 503f0975c5c9..af6292bbd830 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -30,7 +30,6 @@ #include "markarr.hxx" #include "global.hxx" -#include "compressedarray.hxx" #include "address.hxx" #include "rangenam.hxx" #include <tools/solar.h> @@ -65,7 +64,7 @@ class ScPostIt; struct ScFunctionData; struct ScLineFlags; struct ScMergePatternState; - +class ScFlatBoolRowSegments; #define COLUMN_DELTA 4 @@ -209,10 +208,10 @@ public: // UpdateSelectionFunction: Mehrfachselektion void UpdateSelectionFunction( const ScMarkData& rMark, ScFunctionData& rData, - const ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags, + ScFlatBoolRowSegments& rHiddenRows, BOOL bDoExclude, SCROW nExStartRow, SCROW nExEndRow ); void UpdateAreaFunction( ScFunctionData& rData, - const ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags, + ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow ); void CopyToColumn(SCROW nRow1, SCROW nRow2, USHORT nFlags, BOOL bMarked, @@ -329,7 +328,7 @@ public: const ScStyleSheet* GetSelectionStyle( const ScMarkData& rMark, BOOL& rFound ) const; const ScStyleSheet* GetAreaStyle( BOOL& rFound, SCROW nRow1, SCROW nRow2 ) const; - void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset ); + void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ); BOOL IsStyleSheetUsed( const ScStyleSheet& rStyle, BOOL bGatherAllStyles ) const; /// May return -1 if not found diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx index f7216b9cff48..d995550a2f1d 100644 --- a/sc/inc/dociter.hxx +++ b/sc/inc/dociter.hxx @@ -36,6 +36,8 @@ #include <memory> +#include <set> + class ScDocument; class ScBaseCell; class ScPatternAttr; @@ -511,6 +513,23 @@ public: const ScBaseCell* GetCell() const { return pFoundCell; } }; +// ============================================================================ + +class ScRowBreakIterator +{ +public: + static SCROW NOT_FOUND; + + explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks); + SCROW first(); + SCROW next(); + +private: + ::std::set<SCROW>& mrBreaks; + ::std::set<SCROW>::const_iterator maItr; + ::std::set<SCROW>::const_iterator maEnd; +}; + #endif diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index cf52a13aceaa..f7ae5e63f165 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -44,6 +44,7 @@ #include <memory> #include <map> +#include <set> // Wang Xu Ming -- 2009-8-17 // DataPilot Migration - Cache&&Performance @@ -144,6 +145,7 @@ class SfxUndoManager; class ScFormulaParserPool; struct ScClipParam; struct ScClipRangeNameData; +class ScRowBreakIterator; namespace com { namespace sun { namespace star { namespace lang { @@ -159,6 +161,9 @@ namespace com { namespace sun { namespace star { namespace embed { class XEmbeddedObject; } + namespace sheet { + struct TablePageBreakData; + } } } } #include <svl/zforlist.hxx> @@ -381,12 +386,12 @@ private: // kein Broadcast, keine Listener aufbauen waehrend aus einem anderen // Doc (per Filter o.ae.) inserted wird, erst bei CompileAll / CalcAfterLoad BOOL bInsertingFromOtherDoc; - BOOL bImportingXML; // special handling of formula text + bool bLoadingMedium; + bool bImportingXML; // special handling of formula text BOOL bXMLFromWrapper; // distinguish ScXMLImportWrapper from external component BOOL bCalcingAfterLoad; // in CalcAfterLoad TRUE // wenn temporaer keine Listener auf/abgebaut werden sollen BOOL bNoListening; - BOOL bLoadingDone; BOOL bIdleDisabled; BOOL bInLinkUpdate; // TableLink or AreaLink BOOL bChartListenerCollectionNeedsUpdate; @@ -428,8 +433,6 @@ private: sal_Int16 mnNamedRangesLockCount; - inline BOOL RowHidden( SCROW nRow, SCTAB nTab ); // FillInfo - public: SC_DLLPUBLIC ULONG GetCellCount() const; // alle Zellen SCSIZE GetCellCount(SCTAB nTab, SCCOL nCol) const; @@ -928,12 +931,17 @@ public: SCROW& rEndRow, BOOL bNotes = TRUE ) const; void InvalidateTableArea(); + SC_DLLPUBLIC BOOL GetDataStart( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow ) const; + /** + * Find the maximum column position that contains printable data for the + * specified row range. The final column position must be equal or less + * than the initial value of rEndCol. + */ void ExtendPrintArea( OutputDevice* pDev, SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ); - SC_DLLPUBLIC SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir ); @@ -1257,19 +1265,20 @@ public: void DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark ); void DeleteSelectionTab( SCTAB nTab, USHORT nDelFlag, const ScMarkData& rMark ); - // - SC_DLLPUBLIC void SetColWidth( SCCOL nCol, SCTAB nTab, USHORT nNewWidth ); SC_DLLPUBLIC void SetRowHeight( SCROW nRow, SCTAB nTab, USHORT nNewHeight ); SC_DLLPUBLIC void SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, USHORT nNewHeight ); - void SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bManual ); + + SC_DLLPUBLIC void SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, + USHORT nNewHeight ); + void SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bManual ); SC_DLLPUBLIC USHORT GetColWidth( SCCOL nCol, SCTAB nTab ) const; - SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCTAB nTab ) const; + SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero = true ) const; SC_DLLPUBLIC ULONG GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const; - ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, double fScale ) const; - SC_DLLPUBLIC const ScSummableCompressedArray< SCROW, USHORT> & GetRowHeightArray( SCTAB nTab ) const; + SCROW GetRowForHeight( SCTAB nTab, ULONG nHeight ) const; + ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, double fScale ) const; SC_DLLPUBLIC ULONG GetColOffset( SCCOL nCol, SCTAB nTab ) const; SC_DLLPUBLIC ULONG GetRowOffset( SCROW nRow, SCTAB nTab ) const; @@ -1278,22 +1287,6 @@ public: USHORT GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const; - // All FastGet...() methods have no check for valid nTab! - // They access ScCompressedArray objects, so using the - // single row taking ones in loops to access a sequence of - // single rows is no good idea! Use specialized range - // taking methods instead, or iterators. - SC_DLLPUBLIC ULONG FastGetRowHeight( SCROW nStartRow, SCROW nEndRow, - SCTAB nTab ) const; - inline ULONG FastGetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, - SCTAB nTab, double fScale ) const; - SC_DLLPUBLIC inline USHORT FastGetRowHeight( SCROW nRow, SCTAB nTab ) const; - inline SCROW FastGetRowForHeight( SCTAB nTab, ULONG nHeight ) const; - inline SCROW FastGetFirstNonHiddenRow( SCROW nStartRow, SCTAB nTab ) const; - /** No check for flags whether row is hidden, height value - is returned unconditionally. */ - inline USHORT FastGetOriginalRowHeight( SCROW nRow, SCTAB nTab ) const; - SCROW GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const; USHORT GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev, @@ -1330,6 +1323,44 @@ public: SC_DLLPUBLIC const ScBitMaskCompressedArray< SCROW, BYTE> & GetRowFlagsArray( SCTAB nTab ) const; SC_DLLPUBLIC ScBitMaskCompressedArray< SCROW, BYTE> & GetRowFlagsArrayModifiable( SCTAB nTab ); + SC_DLLPUBLIC void GetAllRowBreaks(::std::set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const; + SC_DLLPUBLIC void GetAllColBreaks(::std::set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const; + SC_DLLPUBLIC ScBreakType HasRowBreak(SCROW nRow, SCTAB nTab) const; + SC_DLLPUBLIC ScBreakType HasColBreak(SCCOL nCol, SCTAB nTab) const; + SC_DLLPUBLIC void SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual); + SC_DLLPUBLIC void SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual); + void RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual); + void RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual); + ::com::sun::star::uno::Sequence< + ::com::sun::star::sheet::TablePageBreakData> GetRowBreakData(SCTAB nTab) const; + + SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL); + SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow); + SC_DLLPUBLIC bool HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol); + SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL); + SC_DLLPUBLIC void SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden); + SC_DLLPUBLIC void SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden); + SC_DLLPUBLIC SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + SC_DLLPUBLIC SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + SCROW CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + + bool RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL); + bool HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + bool ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL); + SC_DLLPUBLIC void SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered); + SC_DLLPUBLIC void SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered); + SCROW FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + SCROW LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + SCROW CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab); + + /** + * Write all column row flags to table's flag data, because not all column + * row attributes are stored in the flag data members. This is necessary + * for ods export. + */ + void SyncColRowFlags(); + /// @return the index of the last row with any set flags (auto-pagebreak is ignored). SC_DLLPUBLIC SCROW GetLastFlaggedRow( SCTAB nTab ) const; @@ -1351,8 +1382,6 @@ public: BOOL GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault); BOOL GetRowDefault( SCTAB nTab, SCROW nRow, SCCOL nLastCol, SCCOL& nDefault); - BOOL IsFiltered( SCROW nRow, SCTAB nTab ) const; - BOOL UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow ); BOOL UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow ); @@ -1369,6 +1398,7 @@ public: Size GetPageSize( SCTAB nTab ) const; void SetPageSize( SCTAB nTab, const Size& rSize ); void SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ); + void InvalidatePageBreaks(SCTAB nTab); void UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea = NULL ); void RemoveManualBreaks( SCTAB nTab ); BOOL HasManualBreaks( SCTAB nTab ) const; @@ -1465,8 +1495,6 @@ public: void DoColResize( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd ); - // Idleberechnung der OutputDevice-Zelltextbreite - BOOL IsLoadingDone() const { return bLoadingDone; } void InvalidateTextWidth( const String& rStyleName ); void InvalidateTextWidth( SCTAB nTab ); void InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo, BOOL bNumFormatChanged ); @@ -1503,8 +1531,9 @@ public: BOOL GetNoSetDirty() const { return bNoSetDirty; } void SetInsertingFromOtherDoc( BOOL bVal ) { bInsertingFromOtherDoc = bVal; } BOOL IsInsertingFromOtherDoc() const { return bInsertingFromOtherDoc; } - void SetImportingXML( BOOL bVal ); - BOOL IsImportingXML() const { return bImportingXML; } + void SetLoadingMedium( bool bVal ); + void SetImportingXML( bool bVal ); + bool IsImportingXML() const { return bImportingXML; } void SetXMLFromWrapper( BOOL bVal ); BOOL IsXMLFromWrapper() const { return bXMLFromWrapper; } void SetCalcingAfterLoad( BOOL bVal ) { bCalcingAfterLoad = bVal; } @@ -1761,6 +1790,7 @@ public: SfxUndoManager* GetUndoManager(); bool IsInVBAMode() const; + ScRowBreakIterator* GetRowBreakIterator(SCTAB nTab) const; private: // CLOOK-Impl-Methoden @@ -1823,53 +1853,6 @@ inline void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab ) mSheetSortParams[ nTab ] = rParam; } - -inline ULONG ScDocument::FastGetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, - SCTAB nTab, double fScale ) const -{ - return pTab[nTab]->pRowFlags->SumScaledCoupledArrayForCondition( nStartRow, - nEndRow, CR_HIDDEN, 0, *(pTab[nTab]->pRowHeight), fScale); -} - -inline USHORT ScDocument::FastGetRowHeight( SCROW nRow, SCTAB nTab ) const -{ - return ( pTab[nTab]->pRowFlags->GetValue(nRow) & CR_HIDDEN ) ? 0 : - pTab[nTab]->pRowHeight->GetValue(nRow); -} - -inline SCROW ScDocument::FastGetRowForHeight( SCTAB nTab, ULONG nHeight ) const -{ - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - *(pTab[nTab]->pRowFlags), 0, MAXROW, CR_HIDDEN, 0, - *(pTab[nTab]->pRowHeight)); - ULONG nSum = 0; - for ( ; aIter; aIter.NextRange() ) - { - ULONG nNew = *aIter * (aIter.GetRangeEnd() - aIter.GetRangeStart() + 1); - if (nSum + nNew > nHeight) - { - for ( ; aIter && nSum <= nHeight; ++aIter ) - { - nSum += *aIter; - } - return aIter.GetPos(); - } - nSum += nNew; - } - return aIter.GetPos(); -} - -inline SCROW ScDocument::FastGetFirstNonHiddenRow( SCROW nStartRow, SCTAB nTab) const -{ - return pTab[nTab]->pRowFlags->GetFirstForCondition( nStartRow, MAXROW, - CR_HIDDEN, 0); -} - -inline USHORT ScDocument::FastGetOriginalRowHeight( SCROW nRow, SCTAB nTab ) const -{ - return pTab[nTab]->pRowHeight->GetValue(nRow); -} - #endif diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx index 23668aa6813d..8178eb4a01d2 100644 --- a/sc/inc/global.hxx +++ b/sc/inc/global.hxx @@ -203,13 +203,16 @@ const SCSIZE PIVOT_MAXPAGEFIELD = 10; // FILTERED und MANUALSIZE nur fuer Zeilen moeglich const BYTE CR_HIDDEN = 1; //const BYTE CR_MARKED = 2; -const BYTE CR_PAGEBREAK = 4; +//const BYTE CR_PAGEBREAK = 4; const BYTE CR_MANUALBREAK = 8; const BYTE CR_FILTERED = 16; const BYTE CR_MANUALSIZE = 32; +const BYTE CR_ALL = (CR_HIDDEN | CR_MANUALBREAK | CR_FILTERED | CR_MANUALSIZE); -// was davon kommt in die Datei: -#define CR_SAVEMASK ( ~CR_PAGEBREAK ) +typedef BYTE ScBreakType; +const ScBreakType BREAK_NONE = 0; +const ScBreakType BREAK_PAGE = 1; +const ScBreakType BREAK_MANUAL = 2; // Insert-/Delete-Flags const USHORT IDF_NONE = 0x0000; diff --git a/sc/inc/olinetab.hxx b/sc/inc/olinetab.hxx index 3ffc03f4a249..82a49b3ba025 100644 --- a/sc/inc/olinetab.hxx +++ b/sc/inc/olinetab.hxx @@ -30,24 +30,24 @@ #include "collect.hxx" -#include "compressedarray.hxx" #include "scdllapi.h" #define SC_OL_MAXDEPTH 7 class SvStream; +class ScTable; class ScOutlineEntry : public ScDataObject { SCCOLROW nStart; SCSIZE nSize; - BOOL bHidden; - BOOL bVisible; + bool bHidden; + bool bVisible; public: ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, - BOOL bNewHidden = FALSE ); + bool bNewHidden = FALSE ); ScOutlineEntry( const ScOutlineEntry& rEntry ); virtual ScDataObject* Clone() const; @@ -55,14 +55,14 @@ public: SCCOLROW GetStart() const { return nStart; } SCSIZE GetSize() const { return nSize; } SCCOLROW GetEnd() const { return nStart+nSize-1; } - BOOL IsHidden() const { return bHidden; } // Gruppe versteckt - BOOL IsVisible() const { return bVisible; } // Control sichtbar? + bool IsHidden() const { return bHidden; } // Gruppe versteckt + bool IsVisible() const { return bVisible; } // Control sichtbar? void Move( SCsCOLROW nDelta ); void SetSize( SCSIZE nNewSize ); void SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize ); - void SetHidden( BOOL bNewHidden ); - void SetVisible( BOOL bNewVisible ); + void SetHidden( bool bNewHidden ); + void SetVisible( bool bNewVisible ); }; @@ -123,9 +123,7 @@ public: void InsertSpace( SCCOLROW nStartPos, SCSIZE nSize ); BOOL DeleteSpace( SCCOLROW nStartPos, SCSIZE nSize ); - BOOL ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, - BOOL bShow, - const ScBitMaskCompressedArray< SCCOLROW, BYTE>& rHiddenFlags ); + bool ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, ScTable& rTable, bool bCol ); void RemoveAll(); }; diff --git a/sc/inc/segmenttree.hxx b/sc/inc/segmenttree.hxx new file mode 100644 index 000000000000..2900ad398149 --- /dev/null +++ b/sc/inc/segmenttree.hxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * 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: compressedarray.hxx,v $ + * $Revision: 1.7.32.2 $ + * + * 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 SC_SEGMENTTREE_HXX +#define SC_SEGMENTTREE_HXX + +#include "address.hxx" + +#include <memory> + +class ScFlatBoolSegmentsImpl; + +class ScFlatBoolRowSegments +{ +public: + struct RangeData + { + SCROW mnRow1; + SCROW mnRow2; + bool mbValue; + }; + + class ForwardIterator + { + public: + explicit ForwardIterator(ScFlatBoolRowSegments& rSegs); + + bool getValue(SCROW nPos, bool& rVal); + SCROW getLastPos() const; + + private: + ScFlatBoolRowSegments& mrSegs; + + SCROW mnCurPos; + SCROW mnLastPos; + bool mbCurValue; + }; + + class RangeIterator + { + public: + explicit RangeIterator(ScFlatBoolRowSegments& rSegs); + bool getFirst(RangeData& rRange); + bool getNext(RangeData& rRange); + private: + ScFlatBoolRowSegments& mrSegs; + }; + + ScFlatBoolRowSegments(); + ScFlatBoolRowSegments(const ScFlatBoolRowSegments& r); + ~ScFlatBoolRowSegments(); + + void setTrue(SCROW nRow1, SCROW nRow2); + void setFalse(SCROW nRow1, SCROW nRow2); + bool getValue(SCROW nRow); + bool getRangeData(SCROW nRow, RangeData& rData); + void removeSegment(SCROW nRow1, SCROW nRow2); + void insertSegment(SCROW nRow, SCROW nSize, bool bSkipStartBoundary); + + SCROW findLastNotOf(bool bValue) const; + + void enableTreeSearch(bool bEnable); + void setInsertFromBack(bool bInsertFromBack); + +private: + ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl; +}; + +// ============================================================================ + +class ScFlatBoolColSegments +{ +public: + struct RangeData + { + SCCOL mnCol1; + SCCOL mnCol2; + bool mbValue; + }; + ScFlatBoolColSegments(); + ScFlatBoolColSegments(const ScFlatBoolColSegments& r); + ~ScFlatBoolColSegments(); + + void setTrue(SCCOL nCol1, SCCOL nCol2); + void setFalse(SCCOL nCol1, SCCOL nCol2); + bool getValue(SCCOL nCol); + bool getRangeData(SCCOL nCol, RangeData& rData); + void removeSegment(SCCOL nCol1, SCCOL nCol2); + void insertSegment(SCCOL nCol, SCCOL nSize, bool bSkipStartBoundary); + + void enableTreeSearch(bool bEnable); + void setInsertFromBack(bool bInsertFromBack); + +private: + ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl; +}; + +// ============================================================================ + +class ScFlatUInt16SegmentsImpl; + +class ScFlatUInt16RowSegments +{ +public: + struct RangeData + { + SCROW mnRow1; + SCROW mnRow2; + sal_uInt16 mnValue; + }; + + class ForwardIterator + { + public: + explicit ForwardIterator(ScFlatUInt16RowSegments& rSegs); + + bool getValue(SCROW nPos, sal_uInt16& rVal); + SCROW getLastPos() const; + + private: + ScFlatUInt16RowSegments& mrSegs; + + SCROW mnCurPos; + SCROW mnLastPos; + sal_uInt16 mnCurValue; + }; + + ScFlatUInt16RowSegments(sal_uInt16 nDefault); + ScFlatUInt16RowSegments(const ScFlatUInt16RowSegments& r); + ~ScFlatUInt16RowSegments(); + + void setValue(SCROW nRow1, SCROW nRow2, sal_uInt16 nValue); + sal_uInt16 getValue(SCROW nRow); + sal_uInt32 getSumValue(SCROW nRow1, SCROW nRow2); + bool getRangeData(SCROW nRow, RangeData& rData); + void removeSegment(SCROW nRow1, SCROW nRow2); + void insertSegment(SCROW nRow, SCROW nSize, bool bSkipStartBoundary); + + SCROW findLastNotOf(sal_uInt16 nValue) const; + + void enableTreeSearch(bool bEnable); + void setInsertFromBack(bool bInsertFromBack); + +private: + ::std::auto_ptr<ScFlatUInt16SegmentsImpl> mpImpl; +}; + +#endif diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 6cc5a4d16aaa..78e5875b6879 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -39,12 +39,20 @@ #include "compressedarray.hxx" #include <memory> +#include <set> +#include <boost/shared_ptr.hpp> namespace utl { class SearchParam; class TextSearch; } +namespace com { namespace sun { namespace star { + namespace sheet { + struct TablePageBreakData; + } +} } } + class SfxItemSet; class SfxStyleSheetBase; class SvxBoxInfoItem; @@ -73,6 +81,9 @@ struct RowInfo; struct ScFunctionData; struct ScLineFlags; class CollatorWrapper; +class ScFlatUInt16RowSegments; +class ScFlatBoolRowSegments; +class ScFlatBoolColSegments; class ScTable @@ -112,10 +123,19 @@ private: ::std::auto_ptr<ScTableProtection> pTabProtection; USHORT* pColWidth; - ScSummableCompressedArray< SCROW, USHORT>* pRowHeight; + ::boost::shared_ptr<ScFlatUInt16RowSegments> mpRowHeights; BYTE* pColFlags; ScBitMaskCompressedArray< SCROW, BYTE>* pRowFlags; + ::boost::shared_ptr<ScFlatBoolColSegments> mpHiddenCols; + ::boost::shared_ptr<ScFlatBoolRowSegments> mpHiddenRows; + ::boost::shared_ptr<ScFlatBoolColSegments> mpFilteredCols; + ::boost::shared_ptr<ScFlatBoolRowSegments> mpFilteredRows; + + ::std::set<SCROW> maRowPageBreaks; + ::std::set<SCROW> maRowManualBreaks; + ::std::set<SCCOL> maColPageBreaks; + ::std::set<SCCOL> maColManualBreaks; ScOutlineTable* pOutlineTable; @@ -160,6 +180,7 @@ private: Color aTabBgColor; USHORT nScenarioFlags; BOOL bActiveScenario; + bool mbPageBreaksValid; friend class ScDocument; // fuer FillInfo friend class ScDocumentIterator; @@ -377,7 +398,8 @@ public: void CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const; - void InvalidateTableArea() { bTableAreaValid = FALSE; } + void InvalidateTableArea(); + void InvalidatePageBreaks(); BOOL GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const; // FALSE = leer BOOL GetTableArea( SCCOL& rEndCol, SCROW& rEndRow ) const; @@ -476,7 +498,7 @@ public: SCCOL& rCol, SCROW& rRow, ScMarkData& rMark, String& rUndoStr, ScDocument* pUndoDoc); - void FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ) const; + void FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ); void GetBorderLines( SCCOL nCol, SCROW nRow, const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, @@ -593,29 +615,49 @@ public: void SetRowHeight( SCROW nRow, USHORT nNewHeight ); BOOL SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeight, double nPPTX, double nPPTY ); + + /** + * Set specified row height to specified ranges. Don't check for drawing + * objects etc. Just set the row height. Nothing else. + * + * Note that setting a new row height via this function will not + * invalidate page breaks. + */ + void SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeight ); + // nPPT fuer Test auf Veraenderung void SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual ); - USHORT GetColWidth( SCCOL nCol ) const; - USHORT GetRowHeight( SCROW nRow ) const; - ULONG GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const; - ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const; - ULONG GetColOffset( SCCOL nCol ) const; - ULONG GetRowOffset( SCROW nRow ) const; + USHORT GetColWidth( SCCOL nCol ); + SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCROW* pStartRow = NULL, SCROW* pEndRow = NULL, bool bHiddenAsZero = true ); + ULONG GetRowHeight( SCROW nStartRow, SCROW nEndRow ); + ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ); + ULONG GetColOffset( SCCOL nCol ); + ULONG GetRowOffset( SCROW nRow ); + + /** + * Get the last row such that the height of row 0 to the end row is as + * high as possible without exceeding the specified height value. + * + * @param nHeight maximum desired height + * + * @return SCROW last row of the range within specified height. + */ + SCROW GetRowForHeight(ULONG nHeight); USHORT GetOriginalWidth( SCCOL nCol ) const; USHORT GetOriginalHeight( SCROW nRow ) const; - USHORT GetCommonWidth( SCCOL nEndCol ) const; + USHORT GetCommonWidth( SCCOL nEndCol ); - SCROW GetHiddenRowCount( SCROW nRow ) const; + SCROW GetHiddenRowCount( SCROW nRow ); - void ShowCol(SCCOL nCol, BOOL bShow); - void ShowRow(SCROW nRow, BOOL bShow); - void DBShowRow(SCROW nRow, BOOL bShow); + void ShowCol(SCCOL nCol, bool bShow); + void ShowRow(SCROW nRow, bool bShow); + void DBShowRow(SCROW nRow, bool bShow); - void ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow); - void DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow); + void ShowRows(SCROW nRow1, SCROW nRow2, bool bShow); + void DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow); void SetColFlags( SCCOL nCol, BYTE nNewFlags ); void SetRowFlags( SCROW nRow, BYTE nNewFlags ); @@ -629,15 +671,11 @@ public: /// @return the index of the last changed row (flags and row height, auto pagebreak is ignored). SCROW GetLastChangedRow() const; - BOOL IsFiltered(SCROW nRow) const; - BYTE GetColFlags( SCCOL nCol ) const; BYTE GetRowFlags( SCROW nRow ) const; const ScBitMaskCompressedArray< SCROW, BYTE> * GetRowFlagsArray() const { return pRowFlags; } - const ScSummableCompressedArray< SCROW, USHORT> * GetRowHeightArray() const - { return pRowHeight; } BOOL UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, BOOL bShow ); BOOL UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, BOOL bShow ); @@ -646,6 +684,63 @@ public: void RemoveManualBreaks(); BOOL HasManualBreaks() const; + void GetAllRowBreaks(::std::set<SCROW>& rBreaks, bool bPage, bool bManual) const; + void GetAllColBreaks(::std::set<SCCOL>& rBreaks, bool bPage, bool bManual) const; + bool HasRowPageBreak(SCROW nRow) const; + bool HasColPageBreak(SCCOL nCol) const; + bool HasRowManualBreak(SCROW nRow) const; + bool HasColManualBreak(SCCOL nCol) const; + + /** + * Get the row position of the next manual break that occurs at or below + * specified row. When no more manual breaks are present at or below + * the specified row, -1 is returned. + * + * @param nRow row at which the search begins. + * + * @return SCROW next row position with manual page break, or -1 if no + * more manual breaks are present. + */ + SCROW GetNextManualBreak(SCROW nRow) const; + + void RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow); + void RemoveRowBreak(SCROW nRow, bool bPage, bool bManual); + void RemoveColBreak(SCCOL nCol, bool bPage, bool bManual); + void SetRowBreak(SCROW nRow, bool bPage, bool bManual); + void SetColBreak(SCCOL nCol, bool bPage, bool bManual); + ::com::sun::star::uno::Sequence< + ::com::sun::star::sheet::TablePageBreakData> GetRowBreakData() const; + + bool RowHidden(SCROW nRow, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL); + bool RowHidden(SCROW nRow, SCROW& rLastRow); + bool HasHiddenRows(SCROW nStartRow, SCROW nEndRow); + bool ColHidden(SCCOL nCol, SCCOL& rLastCol); + bool ColHidden(SCCOL nCol, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL); + void SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden); + void SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden); + void CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol); + void CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow); + void CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset); + SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow); + SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow); + SCROW CountVisibleRows(SCROW nStartRow, SCROW nEndRow); + sal_uInt32 GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow); + + SCCOLROW LastHiddenColRow(SCCOLROW nPos, bool bCol); + + bool RowFiltered(SCROW nRow, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL); + bool ColFiltered(SCCOL nCol, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL); + bool HasFilteredRows(SCROW nStartRow, SCROW nEndRow); + void CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol); + void CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow); + void SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered); + void SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered); + SCROW FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow); + SCROW LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow); + SCROW CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow); + + void SyncColRowFlags(); + void StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ); void ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ); @@ -763,14 +858,65 @@ private: void StartNeededListeners(); // only for cells where NeedsListening()==TRUE void SetRelNameDirty(); + void SetLoadingMedium(bool bLoading); + SCSIZE 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 ); // idle calculation of OutputDevice text width for cell // also invalidates script type, broadcasts for "calc as shown" void InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo, BOOL bNumFormatChanged, BOOL bBroadcast ); + + /** + * In case the cell text goes beyond the column width, move the max column + * position to the right. This is called from ExtendPrintArea. + */ + void MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY); + + /** + * Use this to iterate through non-empty visible cells in a single column. + */ + class VisibleDataCellIterator + { + public: + static SCROW ROW_NOT_FOUND; + + explicit VisibleDataCellIterator(ScFlatBoolRowSegments& rRowSegs, ScColumn& rColumn); + ~VisibleDataCellIterator(); + + /** + * Set the start row position. In case there is not visible data cell + * at the specified row position, it will move to the position of the + * first visible data cell below that point. + * + * @return First visible data cell if found, or NULL otherwise. + */ + ScBaseCell* reset(SCROW nRow); + + /** + * Find the next visible data cell position. + * + * @return Next visible data cell if found, or NULL otherwise. + */ + ScBaseCell* next(); + + /** + * Get the current row position. + * + * @return Current row position, or ROW_NOT_FOUND if the iterator + * doesn't point to a valid data cell position. + */ + SCROW getRow() const; + + private: + ScFlatBoolRowSegments& mrRowSegs; + ScColumn& mrColumn; + ScBaseCell* mpCell; + SCROW mnCurRow; + SCROW mnUBound; + }; }; diff --git a/sc/prj/build.lst b/sc/prj/build.lst index 115e92990f3c..afdd953d2274 100755 --- a/sc/prj/build.lst +++ b/sc/prj/build.lst @@ -1,4 +1,4 @@ -sc sc : filter l10n vbahelper oovbaapi svx uui stoc BOOST:boost formula oox NULL +sc sc : filter l10n vbahelper oovbaapi svx uui stoc BOOST:boost formula MDDS:mdds oox NULL sc sc usr1 - all sc_mkout NULL sc sc\inc nmake - all sc_inc NULL sc sc\prj get - all sc_prj NULL 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 da1f20433d1f..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; @@ -1066,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; @@ -2134,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 2b71231c5210..e8ea10f7cf52 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 ), diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index e4741eb7b468..1861988d78aa 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -1190,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 ) @@ -1611,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 ); } @@ -1688,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; } @@ -1863,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/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..a05b321e33ee 100755..100644 --- 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? 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 7e8c00a0637f..95ce6bcec179 100644 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -99,6 +99,7 @@ SLOFILES = \ $(SLO)$/pivot2.obj \ $(SLO)$/poolhelp.obj \ $(SLO)$/sheetevents.obj \ + $(SLO)$/segmenttree.obj \ $(SLO)$/sortparam.obj \ $(SLO)$/stlpool.obj \ $(SLO)$/stlsheet.obj \ @@ -151,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= \ @@ -167,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..bd8a6cc54117 --- /dev/null +++ b/sc/source/core/data/segmenttree.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * 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: compressedarray.hxx,v $ + * $Revision: 1.7.32.2 $ + * + * 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/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/table1.cxx b/sc/source/core/data/table1.cxx index ca54da645444..87561abf1513 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -113,6 +113,7 @@ #include "prnsave.hxx" #include "tabprotection.hxx" #include "sheetevents.hxx" +#include "segmenttree.hxx" // STATIC DATA ----------------------------------------------------------- @@ -132,9 +133,13 @@ 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 ), @@ -156,7 +161,8 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, aScenarioColor( COL_LIGHTGRAY ), aTabBgColor( COL_AUTO ), nScenarioFlags( 0 ), - bActiveScenario( FALSE ) + bActiveScenario( FALSE ), + mbPageBreaksValid(false) { if (bColInfo) @@ -173,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); } @@ -215,7 +221,6 @@ ScTable::~ScTable() delete[] pColWidth; delete[] pColFlags; - delete pRowHeight; delete pRowFlags; delete pSheetEvents; delete pOutlineTable; @@ -990,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; } @@ -1019,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; @@ -1030,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) { @@ -1049,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; @@ -1441,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 ) @@ -1618,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 199d972560e3..9bd5b031fde5 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -58,6 +58,7 @@ #include "postit.hxx" #include "sheetevents.hxx" #include "globstr.hrc" +#include "segmenttree.hxx" #include <math.h> @@ -139,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(); } @@ -165,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 @@ -182,6 +193,8 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE aCol[j].DeleteRow( nStartRow, nSize ); } DecRecalcLevel(); + + InvalidatePageBreaks(); } @@ -217,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); } @@ -248,6 +264,8 @@ void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE } } DecRecalcLevel(); + + InvalidatePageBreaks(); } @@ -269,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); } @@ -290,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(); } @@ -361,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 @@ -415,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++) { @@ -653,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) { @@ -663,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 } } @@ -703,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(); @@ -723,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(); } } } @@ -736,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" ); @@ -1115,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(); @@ -1262,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 @@ -1295,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 ) @@ -1303,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 ) { @@ -1329,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; @@ -1344,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 ); @@ -1859,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; + } } @@ -1970,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 @@ -1981,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) { @@ -1989,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(); @@ -1997,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 @@ -2007,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(); @@ -2022,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) @@ -2032,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 @@ -2061,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 { @@ -2081,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 { @@ -2107,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 ) { @@ -2124,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]; @@ -2151,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) @@ -2163,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; } @@ -2198,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); @@ -2246,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; } @@ -2256,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(); @@ -2291,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 ) @@ -2309,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(); @@ -2323,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 @@ -2346,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) @@ -2360,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) { @@ -2381,6 +2530,8 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow) if (pOutlineTable) UpdateOutlineRow( nRow, nRow, bShow ); + + InvalidatePageBreaks(); } } else @@ -2390,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 @@ -2417,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 ) { @@ -2442,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 @@ -2469,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; @@ -2487,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) @@ -2550,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; + } - SCROW nLastFound = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<BYTE>(~CR_PAGEBREAK) ); - return ValidRow(nLastFound) ? nLastFound : 0; + 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); + } + + return nLastFound; } @@ -2565,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; @@ -2577,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; @@ -2594,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; @@ -2604,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; } @@ -2612,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; } } @@ -2821,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 } } @@ -2872,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"); @@ -2896,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/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/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/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/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]; diff --git a/sc/source/filter/excel/colrowst.cxx b/sc/source/filter/excel/colrowst.cxx index 3a48aa6b96ba..01587c036dea 100644 --- a/sc/source/filter/excel/colrowst.cxx +++ b/sc/source/filter/excel/colrowst.cxx @@ -207,7 +207,7 @@ void XclImpColRowSettings::Convert( SCTAB nScTab ) // row heights ------------------------------------------------------------ // #i54252# set default row height - rDoc.SetRowHeightRange( 0, MAXROW, nScTab, mnDefHeight ); + rDoc.SetRowHeightOnly( 0, MAXROW, nScTab, mnDefHeight ); if( ::get_flag( mnDefRowFlags, EXC_DEFROW_UNSYNCED ) ) // first access to row flags, do not ask for old flags rDoc.SetRowFlags( 0, MAXROW, nScTab, CR_MANUALSIZE ); @@ -258,7 +258,7 @@ void XclImpColRowSettings::Convert( SCTAB nScTab ) { DBG_ASSERT( (nScRow == 0) || (nFirstScRow >= 0), "XclImpColRowSettings::Convert - algorithm error" ); if( nScRow > 0 ) - rDoc.SetRowHeightRange( nFirstScRow, nScRow - 1, nScTab, nLastHeight ); + rDoc.SetRowHeightOnly( nFirstScRow, nScRow - 1, nScTab, nLastHeight ); nFirstScRow = nScRow; nLastHeight = nHeight; @@ -267,7 +267,7 @@ void XclImpColRowSettings::Convert( SCTAB nScTab ) // set row height of last portion if( mnLastScRow >= 0 ) - rDoc.SetRowHeightRange( nFirstScRow, mnLastScRow, nScTab, nLastHeight ); + rDoc.SetRowHeightOnly( nFirstScRow, mnLastScRow, nScTab, nLastHeight ); // ------------------------------------------------------------------------ @@ -307,7 +307,7 @@ void XclImpColRowSettings::ConvertHiddenFlags( SCTAB nScTab ) rDoc.ShowRow( nScRow, nScTab, FALSE ); // #i38093# rows hidden by filter need extra flag if( (nFirstFilterScRow <= nScRow) && (nScRow <= nLastFilterScRow) ) - rDoc.SetRowFlags( nScRow, nScTab, rDoc.GetRowFlags( nScRow, nScTab ) | CR_FILTERED ); + rDoc.SetRowFiltered(nScRow, nScRow, nScTab, true); } } diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index a4b5864668b4..0509f2afa5fa 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -146,7 +146,7 @@ void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject& rSdrObj ) void XclExpDffSheetAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit ) { - maAnchor.SetRect( GetDoc(), mnScTab, rRect, eMapUnit ); + maAnchor.SetRect( GetRoot(), mnScTab, rRect, eMapUnit ); } // ---------------------------------------------------------------------------- @@ -175,7 +175,7 @@ void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUni XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const Rectangle& rRect ) : XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_SIZELOCKED ) { - maAnchor.SetRect( GetDoc(), rRoot.GetCurrScTab(), rRect, MAP_100TH_MM ); + maAnchor.SetRect( rRoot, rRoot.GetCurrScTab(), rRect, MAP_100TH_MM ); } // ---------------------------------------------------------------------------- diff --git a/sc/source/filter/excel/xepage.cxx b/sc/source/filter/excel/xepage.cxx index 753d43e8d584..6194a04c27f6 100644 --- a/sc/source/filter/excel/xepage.cxx +++ b/sc/source/filter/excel/xepage.cxx @@ -45,9 +45,14 @@ #include "xehelper.hxx" #include "xeescher.hxx" +#include <set> +#include <limits> + #include <oox/core/tokens.hxx> using ::rtl::OString; +using ::std::set; +using ::std::numeric_limits; // Page settings records ====================================================== @@ -299,17 +304,23 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : // *** page breaks *** - ScCompressedArrayIterator< SCROW, BYTE> aIter( rDoc.GetRowFlagsArray( nScTab), 1, GetMaxPos().Row()); - do + set<SCROW> aRowBreaks; + rDoc.GetAllRowBreaks(aRowBreaks, nScTab, false, true); + + SCROW nMaxRow = numeric_limits<sal_uInt16>::max(); + for (set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end(); itr != itrEnd; ++itr) { - if (*aIter & CR_MANUALBREAK) - for (SCROW j=aIter.GetRangeStart(); j<=aIter.GetRangeEnd(); ++j) - maData.maHorPageBreaks.push_back( static_cast< sal_uInt16 >( j ) ); - } while (aIter.NextRange()); - - for( SCCOL nScCol = 1, nScMaxCol = GetMaxPos().Col(); nScCol <= nScMaxCol; ++nScCol ) - if( rDoc.GetColFlags( nScCol, nScTab ) & CR_MANUALBREAK ) - maData.maVerPageBreaks.push_back( static_cast< sal_uInt16 >( nScCol ) ); + SCROW nRow = *itr; + if (nRow > nMaxRow) + break; + + maData.maHorPageBreaks.push_back(nRow); + } + + set<SCCOL> aColBreaks; + rDoc.GetAllColBreaks(aColBreaks, nScTab, false, true); + for (set<SCCOL>::const_iterator itr = aColBreaks.begin(), itrEnd = aColBreaks.end(); itr != itrEnd; ++itr) + maData.maVerPageBreaks.push_back(*itr); } static void lcl_WriteHeaderFooter( XclExpXmlStream& rStrm ) diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index e9aaa70bceba..b5ca318a91b4 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1601,8 +1601,7 @@ XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot, mnWidth = XclTools::GetXclColumnWidth( nScWidth, GetCharWidth() ); // column flags - BYTE nScColFlags = rDoc.GetColFlags( nScCol, nScTab ); - ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, (nScColFlags & CR_HIDDEN) != 0 ); + ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) ); // outline data rOutlineBfr.Update( nScCol ); @@ -1827,23 +1826,17 @@ XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt16 nXclRow, BYTE nRowFlags = GetDoc().GetRowFlags( nScRow, nScTab ); bool bUserHeight = ::get_flag< BYTE >( nRowFlags, CR_MANUALSIZE ); - bool bHidden = ::get_flag< BYTE >( nRowFlags, CR_HIDDEN ); + bool bHidden = GetDoc().RowHidden(nScRow, nScTab); ::set_flag( mnFlags, EXC_ROW_UNSYNCED, bUserHeight ); ::set_flag( mnFlags, EXC_ROW_HIDDEN, bHidden ); // *** Row height *** ----------------------------------------------------- - USHORT nScHeight = GetDoc().GetRowHeight( nScRow, nScTab ); - if( nScHeight == 0 ) - { - ::set_flag( mnFlags, EXC_ROW_HIDDEN ); - mnHeight = EXC_ROW_DEFAULTHEIGHT; - } + if (bUserHeight) + mnHeight = GetDoc().GetRowHeight(nScRow, nScTab, false); else - { - // Calc and Excel use twips - mnHeight = static_cast< sal_uInt16 >( nScHeight ); - } + mnHeight = EXC_ROW_DEFAULTHEIGHT; + // #76250# not usable in Applix // ::set_flag( mnHeight, EXC_ROW_FLAGDEFHEIGHT, !bUserHeight ); diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index 02c5203d356a..dc87bba4c050 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -1696,7 +1696,7 @@ void XclImpChartObj::FinalizeTabChart() // create the object anchor XclObjAnchor aAnchor; - aAnchor.SetRect( GetDoc(), GetCurrScTab(), Rectangle( 1000, 500, nWidth, nHeight ), MAP_100TH_MM ); + aAnchor.SetRect( GetRoot(), GetCurrScTab(), Rectangle( 1000, 500, nWidth, nHeight ), MAP_100TH_MM ); SetAnchor( aAnchor ); } @@ -3926,7 +3926,7 @@ void XclImpSheetDrawing::ConvertObjects( XclImpDffConverter& rDffConv ) Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const { - return rAnchor.GetRect( GetDoc(), maScUsedArea.aStart.Tab(), MAP_100TH_MM ); + return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MAP_100TH_MM ); } void XclImpSheetDrawing::OnObjectInserted( const XclImpDrawObjBase& rDrawObj ) diff --git a/sc/source/filter/excel/xipage.cxx b/sc/source/filter/excel/xipage.cxx index c689d0eb7feb..38cebc2e6ca8 100644 --- a/sc/source/filter/excel/xipage.cxx +++ b/sc/source/filter/excel/xipage.cxx @@ -375,14 +375,14 @@ void XclImpPageSettings::Finalize() { SCROW nScRow = static_cast< SCROW >( *aIt ); if( nScRow <= MAXROW ) - rDoc.SetRowFlags( nScRow, nScTab, rDoc.GetRowFlags( nScRow, nScTab ) | CR_MANUALBREAK ); + rDoc.SetRowBreak(nScRow, nScTab, false, true); } for( aIt = maData.maVerPageBreaks.begin(), aEnd = maData.maVerPageBreaks.end(); aIt != aEnd; ++aIt ) { SCCOL nScCol = static_cast< SCCOL >( *aIt ); if( nScCol <= MAXCOL ) - rDoc.SetColFlags( nScCol, nScTab, rDoc.GetColFlags( nScCol, nScTab ) | CR_MANUALBREAK ); + rDoc.SetColBreak(nScCol, nScTab, false, true); } } diff --git a/sc/source/filter/excel/xlescher.cxx b/sc/source/filter/excel/xlescher.cxx index 3b4b8e29ac0b..bb77fac2be73 100644 --- a/sc/source/filter/excel/xlescher.cxx +++ b/sc/source/filter/excel/xlescher.cxx @@ -37,6 +37,7 @@ #include "xestream.hxx" #include "xistream.hxx" #include "xltools.hxx" +#include "xlroot.hxx" using ::rtl::OUString; using ::com::sun::star::uno::Reference; @@ -110,15 +111,15 @@ long lclGetYFromRow( ScDocument& rDoc, SCTAB nScTab, sal_uInt16 nXclRow, sal_uIn /** Calculates an object column position from a drawing layer X position (in twips). */ void lclGetColFromX( ScDocument& rDoc, SCTAB nScTab, sal_uInt16& rnXclCol, - sal_uInt16& rnOffset, sal_uInt16 nXclStartCol, + sal_uInt16& rnOffset, sal_uInt16 nXclStartCol, sal_uInt16 nXclMaxCol, long& rnStartW, long nX, double fScale ) { // rnStartW in conjunction with nXclStartCol is used as buffer for previously calculated width long nTwipsX = static_cast< long >( nX / fScale + 0.5 ); long nColW = 0; - for( rnXclCol = nXclStartCol; rnXclCol <= MAXCOL; ++rnXclCol ) + for( rnXclCol = nXclStartCol; rnXclCol <= nXclMaxCol; ++rnXclCol ) { - nColW = rDoc.GetColWidth( static_cast<SCCOL>(rnXclCol), nScTab ); + nColW = rDoc.GetColWidth( static_cast< SCCOL >( rnXclCol ), nScTab ); if( rnStartW + nColW > nTwipsX ) break; rnStartW += nColW; @@ -128,28 +129,27 @@ void lclGetColFromX( /** Calculates an object row position from a drawing layer Y position (in twips). */ void lclGetRowFromY( - ScDocument& rDoc, SCTAB nScTab, - sal_uInt16& rnXclRow, sal_uInt16& rnOffset, sal_uInt16 nXclStartRow, + ScDocument& rDoc, SCTAB nScTab, sal_uInt16& rnXclRow, + sal_uInt16& rnOffset, sal_uInt16 nXclStartRow, sal_uInt16 nXclMaxRow, long& rnStartH, long nY, double fScale ) { // rnStartH in conjunction with nXclStartRow is used as buffer for previously calculated height long nTwipsY = static_cast< long >( nY / fScale + 0.5 ); long nRowH = 0; - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - rDoc.GetRowFlagsArray( nScTab), static_cast<SCROW>(nXclStartRow), - MAXROW, CR_HIDDEN, 0, rDoc.GetRowHeightArray( nScTab)); - for ( ; aIter; ++aIter ) + bool bFound = false; + for( SCROW nRow = static_cast< SCROW >( nXclStartRow ); nRow <= nXclMaxRow; ++nRow ) { - nRowH = *aIter; + nRowH = rDoc.GetRowHeight( nRow, nScTab ); if( rnStartH + nRowH > nTwipsY ) { - rnXclRow = static_cast< sal_uInt16 >( aIter.GetPos() ); + rnXclRow = static_cast< sal_uInt16 >( nRow ); + bFound = true; break; } rnStartH += nRowH; } - if (!aIter) - rnXclRow = static_cast< sal_uInt16 >( aIter.GetIterEnd() ); // down to the bottom.. + if( !bFound ) + rnXclRow = nXclMaxRow; rnOffset = static_cast< sal_uInt16 >( nRowH ? ((nTwipsY - rnStartH) * 256.0 / nRowH + 0.5) : 0 ); } @@ -178,8 +178,9 @@ XclObjAnchor::XclObjAnchor() : { } -Rectangle XclObjAnchor::GetRect( ScDocument& rDoc, SCTAB nScTab, MapUnit eMapUnit ) const +Rectangle XclObjAnchor::GetRect( const XclRoot& rRoot, SCTAB nScTab, MapUnit eMapUnit ) const { + ScDocument& rDoc = rRoot.GetDoc(); double fScale = lclGetTwipsScale( eMapUnit ); Rectangle aRect( lclGetXFromCol( rDoc, nScTab, maFirst.mnCol, mnLX, fScale ), @@ -193,20 +194,24 @@ Rectangle XclObjAnchor::GetRect( ScDocument& rDoc, SCTAB nScTab, MapUnit eMapUni return aRect; } -void XclObjAnchor::SetRect( ScDocument& rDoc, SCTAB nScTab, const Rectangle& rRect, MapUnit eMapUnit ) +void XclObjAnchor::SetRect( const XclRoot& rRoot, SCTAB nScTab, const Rectangle& rRect, MapUnit eMapUnit ) { - Rectangle aRect( rRect ); + ScDocument& rDoc = rRoot.GetDoc(); + sal_uInt16 nXclMaxCol = rRoot.GetXclMaxPos().Col(); + sal_uInt16 nXclMaxRow = static_cast<sal_uInt16>( rRoot.GetXclMaxPos().Row()); + // #106948# adjust coordinates in mirrored sheets + Rectangle aRect( rRect ); if( rDoc.IsLayoutRTL( nScTab ) ) lclMirrorRectangle( aRect ); double fScale = lclGetTwipsScale( eMapUnit ); long nDummy = 0; - lclGetColFromX( rDoc, nScTab, maFirst.mnCol, mnLX, 0, nDummy, aRect.Left(), fScale ); - lclGetColFromX( rDoc, nScTab, maLast.mnCol, mnRX, maFirst.mnCol, nDummy, aRect.Right(), fScale ); + lclGetColFromX( rDoc, nScTab, maFirst.mnCol, mnLX, 0, nXclMaxCol, nDummy, aRect.Left(), fScale ); + lclGetColFromX( rDoc, nScTab, maLast.mnCol, mnRX, maFirst.mnCol, nXclMaxCol, nDummy, aRect.Right(), fScale ); nDummy = 0; - lclGetRowFromY( rDoc, nScTab, maFirst.mnRow, mnTY, 0, nDummy, aRect.Top(), fScale ); - lclGetRowFromY( rDoc, nScTab, maLast.mnRow, mnBY, maFirst.mnRow, nDummy, aRect.Bottom(), fScale ); + lclGetRowFromY( rDoc, nScTab, maFirst.mnRow, mnTY, 0, nXclMaxRow, nDummy, aRect.Top(), fScale ); + lclGetRowFromY( rDoc, nScTab, maLast.mnRow, mnBY, maFirst.mnRow, nXclMaxRow, nDummy, aRect.Bottom(), fScale ); } void XclObjAnchor::SetRect( const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY, diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx index 0ab97170621e..b4d764dc74a7 100644 --- a/sc/source/filter/html/htmlexp.cxx +++ b/sc/source/filter/html/htmlexp.cxx @@ -718,7 +718,7 @@ void ScHTMLExport::WriteTables() SCCOL nCol; for ( nCol=nStartCol; nCol<=nEndCol; nCol++ ) { - if ( !(pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) ) + if ( !pDoc->ColHidden(nCol, nTab) ) ++nColCnt; } (((aByteStrOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=') += ByteString::CreateFromInt32( nColCnt ); @@ -739,7 +739,7 @@ void ScHTMLExport::WriteTables() aByteStr += '='; for ( nCol=nStartCol; nCol<=nEndCol; nCol++ ) { - if ( pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN ) + if ( pDoc->ColHidden(nCol, nTab) ) continue; // for aByteStrOut = aByteStr; @@ -754,14 +754,12 @@ void ScHTMLExport::WriteTables() // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and // <COL WIDTH=x> specified, but needs a width at every column. bTableDataWidth = TRUE; // widths in first row - bool bHasHiddenRows = pDoc->GetRowFlagsArray( nTab).HasCondition( - nStartRow, nEndRow, CR_HIDDEN, CR_HIDDEN); + bool bHasHiddenRows = pDoc->HasHiddenRows(nStartRow, nEndRow, nTab); for ( SCROW nRow=nStartRow; nRow<=nEndRow; nRow++ ) { - if ( bHasHiddenRows && (pDoc->GetRowFlags( nRow, nTab ) & CR_HIDDEN) ) + if ( bHasHiddenRows && pDoc->RowHidden(nRow, nTab) ) { - nRow = pDoc->GetRowFlagsArray( nTab).GetFirstForCondition( - nRow+1, nEndRow, CR_HIDDEN, 0); + nRow = pDoc->FirstVisibleRow(nRow+1, nEndRow, nTab); --nRow; continue; // for } @@ -770,7 +768,7 @@ void ScHTMLExport::WriteTables() bTableDataHeight = TRUE; // height at every first cell of each row for ( SCCOL nCol2=nStartCol; nCol2<=nEndCol; nCol2++ ) { - if ( pDoc->GetColFlags( nCol2, nTab ) & CR_HIDDEN ) + if ( pDoc->ColHidden(nCol2, nTab) ) continue; // for if ( nCol2 == nEndCol ) diff --git a/sc/source/filter/inc/xlescher.hxx b/sc/source/filter/inc/xlescher.hxx index 10194ab41bc0..921da6b8741b 100644 --- a/sc/source/filter/inc/xlescher.hxx +++ b/sc/source/filter/inc/xlescher.hxx @@ -321,9 +321,9 @@ struct XclObjAnchor : public XclRange explicit XclObjAnchor(); /** Calculates a rectangle from the contained coordinates. */ - Rectangle GetRect( ScDocument& rDoc, SCTAB nScTab, MapUnit eMapUnit ) const; + Rectangle GetRect( const XclRoot& rRoot, SCTAB nScTab, MapUnit eMapUnit ) const; /** Initializes the anchor coordinates for a sheet. */ - void SetRect( ScDocument& rDoc, SCTAB nScTab, const Rectangle& rRect, MapUnit eMapUnit ); + void SetRect( const XclRoot& rRoot, SCTAB nScTab, const Rectangle& rRect, MapUnit eMapUnit ); /** Initializes the anchor coordinates for an embedded draw page. */ void SetRect( const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY, diff --git a/sc/source/filter/lotus/lotimpop.cxx b/sc/source/filter/lotus/lotimpop.cxx index 5173d5303321..2f6f81b7279c 100644 --- a/sc/source/filter/lotus/lotimpop.cxx +++ b/sc/source/filter/lotus/lotimpop.cxx @@ -180,8 +180,7 @@ void ImportLotus::Hiddencolumn( UINT16 nRecLen ) { Read( nCol ); - pD->SetColFlags( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), pD->GetColFlags( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab) ) | CR_HIDDEN ); - + pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true); nCnt--; } } diff --git a/sc/source/filter/lotus/op.cxx b/sc/source/filter/lotus/op.cxx index 0306bdc6315b..4ab0c8bb3b14 100644 --- a/sc/source/filter/lotus/op.cxx +++ b/sc/source/filter/lotus/op.cxx @@ -226,7 +226,7 @@ void OP_ColumnWidth( SvStream& r, UINT16 /*n*/ ) nBreite = ( UINT16 ) ( TWIPS_PER_CHAR * nWidthSpaces ); else { - pDoc->SetColFlags( static_cast<SCCOL> (nCol), 0, pDoc->GetColFlags( static_cast<SCCOL> (nCol), 0 ) | CR_HIDDEN ); + pDoc->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), 0, true); nBreite = nDefWidth; } @@ -335,7 +335,7 @@ void OP_HiddenCols( SvStream& r, UINT16 /*n*/ ) { if( nAkt & 0x01 ) // unterstes Bit gesetzt? // -> Hidden Col - pDoc->SetColFlags( nCount, 0, pDoc->GetColFlags( nCount, 0 ) | CR_HIDDEN ); + pDoc->SetColHidden(nCount, nCount, 0, true); nCount++; nAkt = nAkt / 2; // der Naechste bitte... diff --git a/sc/source/filter/rtf/eeimpars.cxx b/sc/source/filter/rtf/eeimpars.cxx index 86a347970ff6..7fb3d16c6c8d 100644 --- a/sc/source/filter/rtf/eeimpars.cxx +++ b/sc/source/filter/rtf/eeimpars.cxx @@ -435,7 +435,7 @@ void ScEEImport::WriteToDocument( BOOL bSizeColsRows, double nOutputFactor, SvNu for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow++ ) { USHORT nHeight = (USHORT)(ULONG) mpRowHeights->Get( nRow ); - if ( nHeight > mpDoc->FastGetRowHeight( nRow, nTab ) ) + if ( nHeight > mpDoc->GetRowHeight( nRow, nTab ) ) mpDoc->SetRowHeight( nRow, nTab, nHeight ); } } diff --git a/sc/source/filter/rtf/expbase.cxx b/sc/source/filter/rtf/expbase.cxx index 3188b4f920e7..cd3f30ef9c9f 100644 --- a/sc/source/filter/rtf/expbase.cxx +++ b/sc/source/filter/rtf/expbase.cxx @@ -75,16 +75,13 @@ BOOL ScExportBase::GetDataArea( SCTAB nTab, SCCOL& nStartCol, BOOL ScExportBase::TrimDataArea( SCTAB nTab, SCCOL& nStartCol, SCROW& nStartRow, SCCOL& nEndCol, SCROW& nEndRow ) const { - while ( nStartCol <= nEndCol && - pDoc->GetColFlags( nStartCol, nTab ) & CR_HIDDEN ) + SCCOL nLastCol; + while ( nStartCol <= nEndCol && pDoc->ColHidden(nStartCol, nTab, nLastCol)) ++nStartCol; - while ( nStartCol <= nEndCol && - pDoc->GetColFlags( nEndCol, nTab ) & CR_HIDDEN ) + while ( nStartCol <= nEndCol && pDoc->ColHidden(nEndCol, nTab, nLastCol)) --nEndCol; - nStartRow = pDoc->GetRowFlagsArray( nTab).GetFirstForCondition( nStartRow, - nEndRow, CR_HIDDEN, 0); - nEndRow = pDoc->GetRowFlagsArray( nTab).GetLastForCondition( nStartRow, - nEndRow, CR_HIDDEN, 0); + nStartRow = pDoc->FirstVisibleRow(nStartRow, nEndRow, nTab); + nEndRow = pDoc->LastVisibleRow(nStartRow, nEndRow, nTab); return nStartCol <= nEndCol && nStartRow <= nEndRow && nEndRow != ::std::numeric_limits<SCROW>::max(); } diff --git a/sc/source/filter/starcalc/scflt.cxx b/sc/source/filter/starcalc/scflt.cxx index 104d0d7fe192..c9bf2a90a7a5 100644 --- a/sc/source/filter/starcalc/scflt.cxx +++ b/sc/source/filter/starcalc/scflt.cxx @@ -1548,14 +1548,14 @@ void Sc10Import::LoadTables() rStream >> DataValue; if (DataValue != 0) { - BYTE nFlags = 0; - if ((DataValue & crfSoftBreak) == crfSoftBreak) - nFlags |= CR_PAGEBREAK; - if ((DataValue & crfHardBreak) == crfHardBreak) - nFlags |= CR_MANUALBREAK; - if ((DataValue & crfHidden) == crfHidden) - nFlags |= CR_HIDDEN; - for (SCCOL k = static_cast<SCCOL>(DataStart); k <= static_cast<SCCOL>(DataEnd); k++) pDoc->SetColFlags(k, static_cast<SCTAB> (TabNo), nFlags); + bool bPageBreak = ((DataValue & crfSoftBreak) == crfSoftBreak); + bool bManualBreak = ((DataValue & crfHardBreak) == crfHardBreak); + bool bHidden = ((DataValue & crfHidden) == crfHidden); + for (SCCOL k = static_cast<SCCOL>(DataStart); k <= static_cast<SCCOL>(DataEnd); k++) + { + pDoc->SetColHidden(k, k, static_cast<SCTAB>(TabNo), bHidden); + pDoc->SetColBreak(k, static_cast<SCTAB> (TabNo), bPageBreak, bManualBreak); + } } DataStart = DataEnd + 1; } @@ -1598,14 +1598,14 @@ void Sc10Import::LoadTables() rStream >> DataValue; if (DataValue != 0) { - BYTE nFlags = 0; - if ((DataValue & crfSoftBreak) == crfSoftBreak) - nFlags |= CR_PAGEBREAK; - if ((DataValue & crfHardBreak) == crfHardBreak) - nFlags |= CR_MANUALBREAK; - if ((DataValue & crfHidden) == crfHidden) - nFlags |= CR_HIDDEN; - for (SCROW l = static_cast<SCROW>(DataStart); l <= static_cast<SCROW>(DataEnd); l++) pDoc->SetRowFlags(l, static_cast<SCTAB> (TabNo), nFlags); + bool bPageBreak = ((DataValue & crfSoftBreak) == crfSoftBreak); + bool bManualBreak = ((DataValue & crfHardBreak) == crfHardBreak); + bool bHidden = ((DataValue & crfHidden) == crfHidden); + for (SCROW l = static_cast<SCROW>(DataStart); l <= static_cast<SCROW>(DataEnd); l++) + { + pDoc->SetRowHidden(l, l, static_cast<SCTAB> (TabNo), bHidden); + pDoc->SetRowBreak(l, static_cast<SCTAB> (TabNo), bPageBreak, bManualBreak); + } } DataStart = DataEnd + 1; } @@ -2396,7 +2396,7 @@ void Sc10Import::LoadObjects() nStartX = (long) ( nStartX * HMM_PER_TWIPS ); nStartX += (long) ( GraphHeader.x / nPPTX * HMM_PER_TWIPS ); long nSizeX = (long) ( GraphHeader.w / nPPTX * HMM_PER_TWIPS ); - long nStartY = pDoc->FastGetRowHeight( 0, + long nStartY = pDoc->GetRowHeight( 0, static_cast<SCsROW>(GraphHeader.CarretY) - 1, static_cast<SCTAB>(GraphHeader.CarretZ)); nStartY = (long) ( nStartY * HMM_PER_TWIPS ); diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index baa0a664ac53..9053e5395388 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -2507,6 +2507,7 @@ void ScXMLExport::_ExportAutoStyles() { if (pDoc) { + pDoc->SyncColRowFlags(); uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns()); if (xTableColumns.is()) { @@ -2535,7 +2536,7 @@ void ScXMLExport::_ExportAutoStyles() pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible); } sal_Int32 nOld(nColumn); - nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nColumn)); + nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn)); for (sal_Int32 i = nOld + 1; i < nColumn; ++i) pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible); } @@ -2563,7 +2564,7 @@ void ScXMLExport::_ExportAutoStyles() else pRowStyles->AddNewTable(nTable, nRows); sal_Int32 nRow = 0; - while ( /*nRow <= nRows && */nRow <= MAXROW) + while (nRow <= nRows && nRow <= MAXROW) { sal_Int32 nIndex = 0; uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY); @@ -2574,7 +2575,7 @@ void ScXMLExport::_ExportAutoStyles() pRowStyles->AddFieldStyleName(nTable, nRow, nIndex); } sal_Int32 nOld(nRow); - nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nRow), false); + nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow), false); for (sal_Int32 i = nOld + 1; i < nRow; ++i) pRowStyles->AddFieldStyleName(nTable, i, nIndex); } diff --git a/sc/source/ui/Accessibility/AccessibleCellBase.cxx b/sc/source/ui/Accessibility/AccessibleCellBase.cxx index 92ff551f2724..cc93d0a93350 100644 --- a/sc/source/ui/Accessibility/AccessibleCellBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleCellBase.cxx @@ -92,10 +92,12 @@ sal_Bool SAL_CALL ScAccessibleCellBase::isVisible( ) sal_Bool bVisible(sal_True); if (mpDoc) { - BYTE nColFlags = mpDoc->GetColFlags(maCellAddress.Col(), maCellAddress.Tab()); - BYTE nRowFlags = mpDoc->GetRowFlags(maCellAddress.Row(), maCellAddress.Tab()); - if (((nColFlags & CR_HIDDEN) == CR_HIDDEN) || ((nColFlags & CR_FILTERED) == CR_FILTERED) || - ((nRowFlags & CR_HIDDEN) == CR_HIDDEN) || ((nRowFlags & CR_FILTERED) == CR_FILTERED)) + bool bColHidden = mpDoc->ColHidden(maCellAddress.Col(), maCellAddress.Tab()); + bool bRowHidden = mpDoc->RowHidden(maCellAddress.Row(), maCellAddress.Tab()); + bool bColFiltered = mpDoc->ColFiltered(maCellAddress.Col(), maCellAddress.Tab()); + bool bRowFiltered = mpDoc->RowFiltered(maCellAddress.Row(), maCellAddress.Tab()); + + if (bColHidden || bColFiltered || bRowHidden || bRowFiltered) bVisible = sal_False; } return bVisible; diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index f6fc2cb27b71..2cabe7f9f2d6 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -289,7 +289,7 @@ sal_Bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList) const SCROW nRow(pRange->aStart.Row()); while (!bSubTotal && nRow <= nRowEnd) { - if (pDoc->IsFiltered(nRow, nTab)) + if (pDoc->RowFiltered(nRow, nTab)) bSubTotal = sal_True; else ++nRow; diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index 8f46b11236ae..272852efcf71 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -1908,21 +1908,19 @@ IMPL_LINK( ScModule, IdleHandler, Timer*, EMPTYARG ) if ( pDocSh ) { ScDocument* pDoc = pDocSh->GetDocument(); - if ( pDoc->IsLoadingDone() ) - { - BOOL bLinks = pDoc->IdleCheckLinks(); - BOOL bWidth = pDoc->IdleCalcTextWidth(); - BOOL bSpell = pDoc->ContinueOnlineSpelling(); - if ( bSpell ) - aSpellTimer.Start(); // da ist noch was - - bMore = bLinks || bWidth || bSpell; // ueberhaupt noch was? - - // While calculating a Basic formula, a paint event may have occured, - // so check the bNeedsRepaint flags for this document's views - if (bWidth) - lcl_CheckNeedsRepaint( pDocSh ); - } + + BOOL bLinks = pDoc->IdleCheckLinks(); + BOOL bWidth = pDoc->IdleCalcTextWidth(); + BOOL bSpell = pDoc->ContinueOnlineSpelling(); + if ( bSpell ) + aSpellTimer.Start(); // da ist noch was + + bMore = bLinks || bWidth || bSpell; // ueberhaupt noch was? + + // While calculating a Basic formula, a paint event may have occured, + // so check the bNeedsRepaint flags for this document's views + if (bWidth) + lcl_CheckNeedsRepaint( pDocSh ); } ULONG nOldTime = aIdleTimer.GetTimeout(); diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index a5b286e8a9ea..4b268b9da791 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -602,25 +602,23 @@ void ScTransferObj::InitDocShell() // widths / heights // (must be copied before CopyFromClip, for drawing objects) - SCCOL nCol; - SCROW nRow; + SCCOL nCol, nLastCol; SCTAB nSrcTab = aBlock.aStart.Tab(); pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab)); for (nCol=nStartX; nCol<=nEndX; nCol++) - if ( pDoc->GetColFlags( nCol, nSrcTab ) & CR_HIDDEN ) + if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) ) pDestDoc->ShowCol( nCol, 0, FALSE ); else pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) ); ScBitMaskCompressedArray< SCROW, BYTE> & rDestRowFlags = pDestDoc->GetRowFlagsArrayModifiable(0); - ScCompressedArrayIterator< SCROW, BYTE> aIter( pDoc->GetRowFlagsArray( - nSrcTab), nStartY, nEndY); - for ( ; aIter; ++aIter ) + + for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow) { - nRow = aIter.GetPos(); - BYTE nSourceFlags = *aIter; - if ( nSourceFlags & CR_HIDDEN ) + BYTE nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab); + SCROW nLastRow = -1; + if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) ) pDestDoc->ShowRow( nRow, 0, FALSE ); else { @@ -684,7 +682,7 @@ void ScTransferObj::InitDocShell() for (nCol=0; nCol<nStartX; nCol++) nPosX += pDestDoc->GetColWidth( nCol, 0 ); - nPosY += pDestDoc->FastGetRowHeight( 0, nStartY-1, 0 ); + nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 ); nPosX = (long) ( nPosX * HMM_PER_TWIPS ); nPosY = (long) ( nPosY * HMM_PER_TWIPS ); @@ -701,9 +699,9 @@ void ScTransferObj::InitDocShell() break; nSizeX += nAdd; } - for (nRow=nStartY; nRow<=nEndY; nRow++) + for (SCROW nRow=nStartY; nRow<=nEndY; nRow++) { - long nAdd = pDestDoc->FastGetRowHeight( nRow, 0 ); + long nAdd = pDestDoc->GetRowHeight( nRow, 0 ); if ( nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit? break; nSizeY += nAdd; diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 9895f0f43610..e3f94199612a 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -937,7 +937,10 @@ BOOL ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam, } if (!bCopy) + { + pDoc->InvalidatePageBreaks(nTab); pDoc->UpdatePageBreaks( nTab ); + } // #i23299# because of Subtotal functions, the whole rows must be set dirty ScRange aDirtyRange( 0 , aLocalParam.nRow1, nDestTab, diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 34c758dfc78d..27b8eef7bbd6 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -3197,7 +3197,9 @@ BOOL ScDocFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRa for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++) { BYTE nOld = pDoc->GetRowFlags(nRow,nTab); - if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) ) + SCROW nLastRow = -1; + bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow); + if ( !bHidden && ( nOld & CR_MANUALSIZE ) ) pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE ); } } @@ -3232,8 +3234,8 @@ BOOL ScDocFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRa { for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) { - if ( eMode != SC_SIZE_VISOPT || - (pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) == 0 ) + SCCOL nLastCol = -1; + if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) ) { USHORT nThisSize = nSizeTwips; @@ -3303,20 +3305,22 @@ BOOL ScDocFunc::InsertPageBreak( BOOL bColumn, const ScAddress& rPos, if (nPos == 0) return FALSE; // erste Spalte / Zeile - BYTE nFlags = bColumn ? pDoc->GetColFlags( static_cast<SCCOL>(nPos), nTab ) - : pDoc->GetRowFlags( static_cast<SCROW>(nPos), nTab ); - if (nFlags & CR_MANUALBREAK) - return TRUE; // Umbruch schon gesetzt + ScBreakType nBreak = bColumn ? + pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) : + pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); + if (nBreak & BREAK_MANUAL) + return true; if (bRecord) rDocShell.GetUndoManager()->AddUndoAction( new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, TRUE ) ); - nFlags |= CR_MANUALBREAK; if (bColumn) - pDoc->SetColFlags( static_cast<SCCOL>(nPos), nTab, nFlags ); + pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true); else - pDoc->SetRowFlags( static_cast<SCROW>(nPos), nTab, nFlags ); + pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true); + + pDoc->InvalidatePageBreaks(nTab); pDoc->UpdatePageBreaks( nTab ); if (pDoc->IsStreamValid(nTab)) @@ -3362,20 +3366,25 @@ BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos, SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) : static_cast<SCCOLROW>(rPos.Row()); - BYTE nFlags = bColumn ? pDoc->GetColFlags( static_cast<SCCOL>(nPos), nTab ) - : pDoc->GetRowFlags( static_cast<SCROW>(nPos), nTab ); - if ((nFlags & CR_MANUALBREAK)==0) - return FALSE; // kein Umbruch gesetzt + + ScBreakType nBreak; + if (bColumn) + nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab); + else + nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); + if ((nBreak & BREAK_MANUAL) == 0) + // There is no manual break. + return false; if (bRecord) rDocShell.GetUndoManager()->AddUndoAction( new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, FALSE ) ); - nFlags &= ~CR_MANUALBREAK; if (bColumn) - pDoc->SetColFlags( static_cast<SCCOL>(nPos), nTab, nFlags ); + pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true); else - pDoc->SetRowFlags( static_cast<SCROW>(nPos), nTab, nFlags ); + pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true); + pDoc->UpdatePageBreaks( nTab ); if (pDoc->IsStreamValid(nTab)) diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index ac240c32e5c5..9c45fc0093a1 100755 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -868,10 +868,33 @@ static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLa rDateConvert = static_cast<bool>(aTokens[1].toInt32()); } +namespace { + +class LoadMediumGuard +{ +public: + explicit LoadMediumGuard(ScDocument* pDoc) : + mpDoc(pDoc) + { + mpDoc->SetLoadingMedium(true); + } + + ~LoadMediumGuard() + { + mpDoc->SetLoadingMedium(false); + } +private: + ScDocument* mpDoc; +}; + +} + BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) { RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertFrom" ); + LoadMediumGuard aLoadGuard(&aDocument); + BOOL bRet = FALSE; // FALSE heisst Benutzerabbruch !! // bei Fehler: Fehler am Stream setzen!! diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index 03f4516b7281..0993d2ce4a14 100755 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -1489,12 +1489,12 @@ BOOL ScDocShell::AdjustPrintZoom( const ScRange& rRange ) SCROW nEndRow = rRange.aEnd.Row(); if ( pRepeatRow && nStartRow >= pRepeatRow->aStart.Row() ) { - nBlkTwipsY += aDocument.FastGetRowHeight( pRepeatRow->aStart.Row(), + nBlkTwipsY += aDocument.GetRowHeight( pRepeatRow->aStart.Row(), pRepeatRow->aEnd.Row(), nTab ); if ( nStartRow <= pRepeatRow->aEnd.Row() ) nStartRow = pRepeatRow->aEnd.Row() + 1; } - nBlkTwipsY += aDocument.FastGetRowHeight( nStartRow, nEndRow, nTab ); + nBlkTwipsY += aDocument.GetRowHeight( nStartRow, nEndRow, nTab ); Size aPhysPage; long nHdr, nFtr; diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 46b6b7af3a63..a17279f409a9 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -1441,7 +1441,7 @@ BOOL ScImportExport::Doc2Text( SvStream& rStrm ) for (nRow = nStartRow; nRow <= nEndRow; nRow++) { - if (bIncludeFiltered || !pDoc->IsFiltered( nRow, aRange.aStart.Tab() )) + if (bIncludeFiltered || !pDoc->RowFiltered( nRow, aRange.aStart.Tab() )) { for (nCol = nStartCol; nCol <= nEndCol; nCol++) { diff --git a/sc/source/ui/docshell/olinefun.cxx b/sc/source/ui/docshell/olinefun.cxx index 2f42c77ed5f4..822c74800ab2 100644 --- a/sc/source/ui/docshell/olinefun.cxx +++ b/sc/source/ui/docshell/olinefun.cxx @@ -420,7 +420,7 @@ BOOL ScOutlineDocFunc::SelectLevel( SCTAB nTab, BOOL bColumns, USHORT nLevel, if ( bColumns ) pDoc->ShowCol( static_cast<SCCOL>(i), nTab, bShow ); else - if ( !bShow || !pDoc->IsFiltered( i,nTab ) ) + if ( !bShow || !pDoc->RowFiltered( i,nTab ) ) pDoc->ShowRow( i, nTab, bShow ); } } @@ -518,7 +518,7 @@ BOOL ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, BOOL bRecord, } } for ( i=nMin; i<=nMax; i++ ) - if ( !pDoc->IsFiltered( i,nTab ) ) // weggefilterte nicht einblenden + if ( !pDoc->RowFiltered( i,nTab ) ) // weggefilterte nicht einblenden pDoc->ShowRow( i, nTab, TRUE ); pDoc->UpdatePageBreaks( nTab ); @@ -678,7 +678,7 @@ BOOL ScOutlineDocFunc::ShowOutline( SCTAB nTab, BOOL bColumns, USHORT nLevel, US if ( bColumns ) pDoc->ShowCol( static_cast<SCCOL>(i), nTab, TRUE ); else - if ( !pDoc->IsFiltered( i,nTab ) ) // weggefilterte nicht einblenden + if ( !pDoc->RowFiltered( i,nTab ) ) // weggefilterte nicht einblenden pDoc->ShowRow( i, nTab, TRUE ); } @@ -701,6 +701,7 @@ BOOL ScOutlineDocFunc::ShowOutline( SCTAB nTab, BOOL bColumns, USHORT nLevel, US pArray->SetVisibleBelow( nLevel, nEntry, TRUE, TRUE ); + pDoc->InvalidatePageBreaks(nTab); pDoc->UpdatePageBreaks( nTab ); if (bPaint) @@ -766,6 +767,7 @@ BOOL ScOutlineDocFunc::HideOutline( SCTAB nTab, BOOL bColumns, USHORT nLevel, US pArray->SetVisibleBelow( nLevel, nEntry, FALSE ); + pDoc->InvalidatePageBreaks(nTab); pDoc->UpdatePageBreaks( nTab ); if (bPaint) diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 4d6ef782aed6..a2283bf2b7de 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -39,6 +39,7 @@ #include <vector> #include <memory> +#include <boost/shared_ptr.hpp> // --------------------------------------------------------------------------- @@ -112,6 +113,25 @@ private: ::sdr::overlay::OverlayObjectList* mpOOHeader; ::sdr::overlay::OverlayObjectList* mpOOShrink; + ::boost::shared_ptr<Rectangle> mpAutoFillRect; + + /** + * Stores current visible column and row ranges, used to avoid expensive + * operations on objects that are outside visible area. + */ + struct VisibleRange + { + SCCOL mnCol1; + SCCOL mnCol2; + SCROW mnRow1; + SCROW mnRow2; + + VisibleRange(); + + bool isInside(SCCOL nCol, SCROW nRow) const; + }; + VisibleRange maVisibleRange; + private: ScViewData* pViewData; ScSplitPos eWhich; diff --git a/sc/source/ui/inc/viewutil.hxx b/sc/source/ui/inc/viewutil.hxx index 8b103d3761d8..eb1c6df2f902 100644 --- a/sc/source/ui/inc/viewutil.hxx +++ b/sc/source/ui/inc/viewutil.hxx @@ -68,10 +68,10 @@ public: static sal_Int32 GetTransliterationType( USHORT nSlotID ); - static bool HasFiltered( const ScRange& rRange, const ScDocument* pDoc ); + static bool HasFiltered( const ScRange& rRange, ScDocument* pDoc ); /** Fit a range to cover nRows number of unfiltered rows. @return <TRUE/> if the resulting range covers nRows unfiltered rows. */ - static bool FitToUnfilteredRows( ScRange & rRange, const ScDocument * pDoc, size_t nRows ); + static bool FitToUnfilteredRows( ScRange & rRange, ScDocument * pDoc, size_t nRows ); static void UnmarkFiltered( ScMarkData& rMark, ScDocument* pDoc ); static void HideDisabledSlot( SfxItemSet& rSet, SfxBindings& rBindings, USHORT nSlotId ); diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index a35ba96112e3..c284045c5b11 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -1148,10 +1148,10 @@ ScUndoDragDrop::ScUndoDragDrop( ScDocShell* pNewDocShell, BOOL bIncludeFiltered = bCut; if ( !bIncludeFiltered ) { - // manually find number of non-filtered rows - SCROW nPastedCount = pDocShell->GetDocument()->GetRowFlagsArray( - aSrcRange.aStart.Tab()).CountForCondition( - aSrcRange.aStart.Row(), aSrcRange.aEnd.Row(), CR_FILTERED, 0); + // find number of non-filtered rows + SCROW nPastedCount = pDocShell->GetDocument()->CountNonFilteredRows( + aSrcRange.aStart.Row(), aSrcRange.aEnd.Row(), aSrcRange.aStart.Tab()); + if ( nPastedCount == 0 ) nPastedCount = 1; aDestEnd.SetRow( aNewDestPos.Row() + nPastedCount - 1 ); diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index 4011d4755ab1..506afeac138e 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -1028,17 +1028,20 @@ void __EXPORT ScUndoAutoFormat::Redo() aDestMark.MarkToMulti(); // wie SC_SIZE_VISOPT + SCROW nLastRow = -1; for (SCROW nRow=nStartY; nRow<=nEndY; nRow++) { BYTE nOld = pDoc->GetRowFlags(nRow,nTab); - if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) ) + bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow); + if ( !bHidden && ( nOld & CR_MANUALSIZE ) ) pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE ); } pDoc->SetOptimalHeight( nStartY, nEndY, nTab, 0, &aVirtDev, nPPTX, nPPTY, aZoomX, aZoomY, FALSE ); + SCCOL nLastCol = -1; for (SCCOL nCol=nStartX; nCol<=nEndX; nCol++) - if ((pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) == 0) + if (!pDoc->ColHidden(nCol, nTab, nLastCol)) { USHORT nThisSize = STD_EXTRA_WIDTH + pDoc->GetOptimalColWidth( nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoomX, aZoomY, bFormula, diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx index 77142bb13799..cc13ce9f1412 100644 --- a/sc/source/ui/undo/undocell.cxx +++ b/sc/source/ui/undo/undocell.cxx @@ -568,6 +568,8 @@ void ScUndoPageBreak::DoChange( BOOL bInsertP ) const pViewShell->InsertPageBreak(bColumn, FALSE); else pViewShell->DeletePageBreak(bColumn, FALSE); + + pDocShell->GetDocument()->InvalidatePageBreaks(nTab); } } diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx index d550d54f1aea..0f7834b2a8df 100644 --- a/sc/source/ui/undo/undodat.cxx +++ b/sc/source/ui/undo/undodat.cxx @@ -1027,7 +1027,10 @@ void __EXPORT ScUndoQuery::Undo() pDoc->SetDBCollection( new ScDBCollection( *pUndoDB ), TRUE ); if (!bCopy) + { + pDoc->InvalidatePageBreaks(nTab); pDoc->UpdatePageBreaks( nTab ); + } ScRange aDirtyRange( 0 , aQueryParam.nRow1, nTab, MAXCOL, aQueryParam.nRow2, nTab ); diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index b62a4e4eb633..dea7cc056756 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -3377,18 +3377,25 @@ uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryVisibleC ScMarkData aMarkData(*GetMarkData()); ScDocument* pDoc = pDocShell->GetDocument(); - for (SCCOL nCol=0; nCol<=MAXCOL; nCol++) - if (pDoc->GetColFlags(nCol,nTab) & CR_HIDDEN) - aMarkData.SetMultiMarkArea( ScRange( nCol,0,nTab, nCol,MAXROW,nTab ), FALSE ); + SCCOL nCol = 0, nLastCol; + while (nCol <= MAXCOL) + { + if (pDoc->ColHidden(nCol, nTab, nLastCol)) + // hidden columns. Unselect them. + aMarkData.SetMultiMarkArea(ScRange(nCol, 0, nTab, nLastCol, MAXROW, nTab), false); - //! nur bis zur letzten selektierten Zeile testen? - ScCompressedArrayIterator< SCROW, BYTE> aIter( pDoc->GetRowFlagsArray( nTab), 0, MAXROW); - do + nCol = nLastCol + 1; + } + + SCROW nRow = 0, nLastRow; + while (nRow <= MAXROW) { - if (*aIter & CR_HIDDEN) - aMarkData.SetMultiMarkArea( ScRange( 0, aIter.GetRangeStart(), - nTab, MAXCOL, aIter.GetRangeEnd(), nTab ), FALSE ); - } while (aIter.NextRange()); + if (pDoc->RowHidden(nRow, nTab, nLastRow)) + // These rows are hidden. Unselect them. + aMarkData.SetMultiMarkArea(ScRange(0, nRow, nTab, MAXCOL, nLastRow, nTab), false); + + nRow = nLastRow + 1; + } ScRangeList aNewRanges; aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); @@ -7054,7 +7061,7 @@ uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPage SCCOL nCount = 0; SCCOL nCol; for (nCol=0; nCol<=MAXCOL; nCol++) - if (pDoc->GetColFlags( nCol, nTab ) & ( CR_PAGEBREAK | CR_MANUALBREAK )) + if (pDoc->HasColBreak(nCol, nTab)) ++nCount; sheet::TablePageBreakData aData; @@ -7063,11 +7070,11 @@ uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPage USHORT nPos = 0; for (nCol=0; nCol<=MAXCOL; nCol++) { - BYTE nFlags = pDoc->GetColFlags( nCol, nTab ); - if (nFlags & ( CR_PAGEBREAK | CR_MANUALBREAK )) + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + if (nBreak) { aData.Position = nCol; - aData.ManualBreak = ( nFlags & CR_MANUALBREAK ) != 0; + aData.ManualBreak = (nBreak & BREAK_MANUAL); pAry[nPos] = aData; ++nPos; } @@ -7096,33 +7103,7 @@ uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getRowPageBre ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ); aPrintFunc.UpdatePages(); } - - SCROW nCount = pDoc->GetRowFlagsArray( nTab).CountForAnyBitCondition( - 0, MAXROW, (CR_PAGEBREAK | CR_MANUALBREAK)); - - uno::Sequence<sheet::TablePageBreakData> aSeq(nCount); - if (nCount) - { - sheet::TablePageBreakData aData; - sheet::TablePageBreakData* pAry = aSeq.getArray(); - size_t nPos = 0; - ScCompressedArrayIterator< SCROW, BYTE> aIter( pDoc->GetRowFlagsArray( nTab), 0, MAXROW); - do - { - BYTE nFlags = *aIter; - if (nFlags & ( CR_PAGEBREAK | CR_MANUALBREAK )) - { - for (SCROW nRow = aIter.GetRangeStart(); nRow <= aIter.GetRangeEnd(); ++nRow) - { - aData.Position = nRow; - aData.ManualBreak = ( nFlags & CR_MANUALBREAK ) != 0; - pAry[nPos] = aData; - ++nPos; - } - } - } while (aIter.NextRange()); - } - return aSeq; + return pDoc->GetRowBreakData(nTab); } return uno::Sequence<sheet::TablePageBreakData>(0); } @@ -8922,8 +8903,9 @@ void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pE } else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) { - BOOL bVis = !(pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN); - ScUnoHelpFunctions::SetBoolInAny( rAny, bVis ); + SCCOL nDummy; + bool bHidden = pDoc->ColHidden(nCol, nTab, nDummy); + ScUnoHelpFunctions::SetBoolInAny( rAny, !bHidden ); } else if ( pEntry->nWID == SC_WID_UNO_OWIDTH ) { @@ -8933,13 +8915,13 @@ void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pE } else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE ) { - BOOL bBreak = ( 0 != (pDoc->GetColFlags( nCol, nTab ) & (CR_PAGEBREAK|CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( rAny, bBreak ); + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); } else if ( pEntry->nWID == SC_WID_UNO_MANPAGE ) { - BOOL bBreak = ( 0 != (pDoc->GetColFlags( nCol, nTab ) & (CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( rAny, bBreak ); + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + ScUnoHelpFunctions::SetBoolInAny(rAny, (nBreak & BREAK_MANUAL)); } else ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); @@ -9025,12 +9007,7 @@ void ScTableRowObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntr // ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; // aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, eMode, 0, TRUE, TRUE ); // SC_SIZE_DIRECT mit Groesse 0 blendet aus - BYTE nFlags = pDoc->GetRowFlags(nRow, nTab); - if (bFil) - nFlags |= CR_FILTERED; - else - nFlags &= ~CR_FILTERED; - pDoc->SetRowFlags(nRow, nTab, nFlags); + pDoc->SetRowFiltered(nRow, nRow, nTab, bFil); } else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT ) { @@ -9082,12 +9059,13 @@ void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntr } else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) { - BOOL bVis = !(pDoc->GetRowFlags( nRow, nTab ) & CR_HIDDEN); - ScUnoHelpFunctions::SetBoolInAny( rAny, bVis ); + SCROW nDummy; + bool bHidden = pDoc->RowHidden(nRow, nTab, nDummy); + ScUnoHelpFunctions::SetBoolInAny( rAny, !bHidden ); } else if ( pEntry->nWID == SC_WID_UNO_CELLFILT ) { - BOOL bVis = ((pDoc->GetRowFlags( nRow, nTab ) & CR_FILTERED) != 0); + bool bVis = pDoc->RowFiltered(nRow, nTab); ScUnoHelpFunctions::SetBoolInAny( rAny, bVis ); } else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT ) @@ -9097,13 +9075,13 @@ void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntr } else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE ) { - BOOL bBreak = ( 0 != (pDoc->GetRowFlags( nRow, nTab ) & (CR_PAGEBREAK|CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( rAny, bBreak ); + ScBreakType nBreak = pDoc->HasRowBreak(nRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); } else if ( pEntry->nWID == SC_WID_UNO_MANPAGE ) { - BOOL bBreak = ( 0 != (pDoc->GetRowFlags( nRow, nTab ) & (CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( rAny, bBreak ); + ScBreakType nBreak = (pDoc->HasRowBreak(nRow, nTab) & BREAK_MANUAL); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); } else ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 8654de8a429e..8a8081e412d3 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -2569,14 +2569,17 @@ void ScChart2DataSequence::BuildDataCache() if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) continue; + SCCOL nLastCol = -1; + SCROW nLastRow = -1; for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab) { for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) { for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) { - bool bColHidden = (m_pDocument->GetColFlags(nCol, nTab) & CR_HIDDEN); - bool bRowHidden = (m_pDocument->GetRowFlags(nRow, nTab) & CR_HIDDEN); + bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol); + bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow); + if (bColHidden || bRowHidden) { // hidden cell diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index bc32b7592dc4..6d267d4098ff 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -3054,7 +3054,8 @@ uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const rtl::OUString& aPro } else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) { - BOOL bVis = !(pDoc->GetColFlags( nStartCol, nTab ) & CR_HIDDEN); + SCCOL nLastCol; + bool bVis = !pDoc->ColHidden(nStartCol, nTab, nLastCol); ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); } else if ( aNameString.EqualsAscii( SC_UNONAME_OWIDTH ) ) @@ -3064,13 +3065,13 @@ uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const rtl::OUString& aPro } else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE ) ) { - BOOL bBreak = ( 0 != (pDoc->GetColFlags( nStartCol, nTab ) & (CR_PAGEBREAK|CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( aAny, bBreak ); + ScBreakType nBreak = pDoc->HasColBreak(nStartCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, nBreak ); } else if ( aNameString.EqualsAscii( SC_UNONAME_MANPAGE ) ) { - BOOL bBreak = ( 0 != (pDoc->GetColFlags( nStartCol, nTab ) & (CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( aAny, bBreak ); + ScBreakType nBreak = pDoc->HasColBreak(nStartCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, (nBreak & BREAK_MANUAL) ); } return aAny; @@ -3230,8 +3231,11 @@ void SAL_CALL ScTableRowsObj::setPropertyValue( sal_Int32 nNewHeight = 0; if ( pDoc->IsImportingXML() && ( aValue >>= nNewHeight ) ) { - // used to set the stored row height for rows with optimal height when loading - pDoc->SetRowHeightRange( nStartRow, nEndRow, nTab, (USHORT)HMMToTwips(nNewHeight) ); + // used to set the stored row height for rows with optimal height when loading. + + // TODO: It's probably cleaner to use a different property name + // for this. + pDoc->SetRowHeightOnly( nStartRow, nEndRow, nTab, (USHORT)HMMToTwips(nNewHeight) ); } else { @@ -3262,9 +3266,9 @@ void SAL_CALL ScTableRowsObj::setPropertyValue( { //! undo etc. if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) - pDoc->GetRowFlagsArrayModifiable( nTab).OrValue( nStartRow, nEndRow, CR_FILTERED); + pDoc->SetRowFiltered(nStartRow, nEndRow, nTab, true); else - pDoc->GetRowFlagsArrayModifiable( nTab).AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~CR_FILTERED) ); + pDoc->SetRowFiltered(nStartRow, nEndRow, nTab, false); } else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE) || aNameString.EqualsAscii( SC_UNONAME_MANPAGE) ) { @@ -3312,12 +3316,13 @@ uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const rtl::OUString& aProper } else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) { - BOOL bVis = !(pDoc->GetRowFlags( nStartRow, nTab ) & CR_HIDDEN); + SCROW nLastRow; + bool bVis = !pDoc->RowHidden(nStartRow, nTab, nLastRow); ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); } else if ( aNameString.EqualsAscii( SC_UNONAME_CELLFILT ) ) { - BOOL bVis = ((pDoc->GetRowFlags( nStartRow, nTab ) & CR_FILTERED) != 0); + bool bVis = pDoc->RowFiltered(nStartRow, nTab); ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); } else if ( aNameString.EqualsAscii( SC_UNONAME_OHEIGHT ) ) @@ -3327,13 +3332,13 @@ uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const rtl::OUString& aProper } else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE ) ) { - BOOL bBreak = ( 0 != (pDoc->GetRowFlags( nStartRow, nTab ) & (CR_PAGEBREAK|CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( aAny, bBreak ); + ScBreakType nBreak = pDoc->HasRowBreak(nStartRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, nBreak ); } else if ( aNameString.EqualsAscii( SC_UNONAME_MANPAGE ) ) { - BOOL bBreak = ( 0 != (pDoc->GetRowFlags( nStartRow, nTab ) & (CR_MANUALBREAK)) ); - ScUnoHelpFunctions::SetBoolInAny( aAny, bBreak ); + ScBreakType nBreak = pDoc->HasRowBreak(nStartRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, (nBreak & BREAK_MANUAL) ); } else if ( aNameString.EqualsAscii( SC_UNONAME_CELLBACK ) || aNameString.EqualsAscii( SC_UNONAME_CELLTRAN ) ) { diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 71d29734fc76..ccf5a3bc5b54 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -3906,16 +3906,16 @@ ScVbaRange::getPageBreak() throw (uno::RuntimeException) { ScDocument* pDoc = getDocumentFromRange( mxRange ); - BYTE nFlag = 0; + ScBreakType nBreak = BREAK_NONE; if ( !bColumn ) - nFlag = pDoc -> GetRowFlags(thisAddress.StartRow, thisAddress.Sheet); + nBreak = pDoc->HasRowBreak(thisAddress.StartRow, thisAddress.Sheet); else - nFlag = pDoc -> GetColFlags(static_cast<SCCOL>(thisAddress.StartColumn), thisAddress.Sheet); + nBreak = pDoc->HasColBreak(thisAddress.StartColumn, thisAddress.Sheet); - if ( nFlag & CR_PAGEBREAK) + if (nBreak & BREAK_PAGE) nPageBreak = excel::XlPageBreak::xlPageBreakAutomatic; - if ( nFlag & CR_MANUALBREAK) + if (nBreak & BREAK_MANUAL) nPageBreak = excel::XlPageBreak::xlPageBreakManual; } } diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index a461c54f255e..c880a29f8067 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -715,22 +715,22 @@ void ScCellShell::GetState(SfxItemSet &rSet) break; case FID_INS_ROWBRK: - if ( nPosY==0 || (pDoc->GetRowFlags(nPosY,nTab) & CR_MANUALBREAK) ) + if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) ) rSet.DisableItem( nWhich ); break; case FID_INS_COLBRK: - if ( nPosX==0 || (pDoc->GetColFlags(nPosX,nTab) & CR_MANUALBREAK) ) + if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) ) rSet.DisableItem( nWhich ); break; case FID_DEL_ROWBRK: - if ( nPosY==0 || (pDoc->GetRowFlags(nPosY,nTab) & CR_MANUALBREAK)==0 ) + if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 ) rSet.DisableItem( nWhich ); break; case FID_DEL_COLBRK: - if ( nPosX==0 || (pDoc->GetColFlags(nPosX,nTab) & CR_MANUALBREAK)==0 ) + if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 ) rSet.DisableItem( nWhich ); break; diff --git a/sc/source/ui/view/colrowba.cxx b/sc/source/ui/view/colrowba.cxx index 8916624fdb52..d802c08f642f 100644 --- a/sc/source/ui/view/colrowba.cxx +++ b/sc/source/ui/view/colrowba.cxx @@ -98,7 +98,8 @@ USHORT ScColBar::GetEntrySize( SCCOLROW nEntryNo ) { ScDocument* pDoc = pViewData->GetDocument(); SCTAB nTab = pViewData->GetTabNo(); - if ( pDoc->GetColFlags( static_cast<SCCOL>(nEntryNo), nTab ) & CR_HIDDEN ) + SCCOL nLastCol = -1; + if (pDoc->ColHidden(static_cast<SCCOL>(nEntryNo), nTab, nLastCol)) return 0; else return (USHORT) ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(nEntryNo), nTab ), pViewData->GetPPTX() ); @@ -265,7 +266,8 @@ USHORT ScRowBar::GetEntrySize( SCCOLROW nEntryNo ) { ScDocument* pDoc = pViewData->GetDocument(); SCTAB nTab = pViewData->GetTabNo(); - if ( pDoc->GetRowFlags( nEntryNo, nTab ) & CR_HIDDEN ) + SCROW nLastRow = -1; + if (pDoc->RowHidden(nEntryNo, nTab, nLastRow)) return 0; else return (USHORT) ScViewData::ToPixel( pDoc->GetOriginalHeight( nEntryNo, diff --git a/sc/source/ui/view/drawutil.cxx b/sc/source/ui/view/drawutil.cxx index 3885b0adc752..ba250767c169 100644 --- a/sc/source/ui/view/drawutil.cxx +++ b/sc/source/ui/view/drawutil.cxx @@ -66,14 +66,19 @@ void ScDrawUtil::CalcScale( ScDocument* pDoc, SCTAB nTab, nTwipsX += (long) nWidth; nPixelX += ScViewData::ToPixel( nWidth, nPPTX ); } - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - pDoc->GetRowFlagsArray( nTab), nStartRow, nEndRow-1, CR_HIDDEN, 0, - pDoc->GetRowHeightArray( nTab)); - for ( ; aIter; ++aIter ) + + for (SCROW nRow = nStartRow; nRow <= nEndRow-1; ++nRow) { - USHORT nHeight = *aIter; - nTwipsY += (long) nHeight; - nPixelY += ScViewData::ToPixel( nHeight, nPPTY ); + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow)) + { + nRow = nLastRow; + continue; + } + + USHORT nHeight = pDoc->GetRowHeight(nRow, nTab); + nTwipsY += static_cast<long>(nHeight); + nPixelY += ScViewData::ToPixel(nHeight, nPPTY); } MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY ); @@ -100,10 +105,10 @@ void ScDrawUtil::CalcScale( ScDocument* pDoc, SCTAB nTab, else rScaleY = Fraction( 1, 1 ); - // 17 bits of accuracy are needed to always hit the right part of - // cells in the last rows - rScaleX.ReduceInaccurate( 17 ); - rScaleY.ReduceInaccurate( 17 ); + // 25 bits of accuracy are needed to always hit the right part of + // cells in the last rows (was 17 before 1M rows). + rScaleX.ReduceInaccurate( 25 ); + rScaleY.ReduceInaccurate( 25 ); } diff --git a/sc/source/ui/view/drawvie4.cxx b/sc/source/ui/view/drawvie4.cxx index 8b9debdabfae..3a28096d2853 100644 --- a/sc/source/ui/view/drawvie4.cxx +++ b/sc/source/ui/view/drawvie4.cxx @@ -282,8 +282,8 @@ void ScDrawView::CalcNormScale( Fraction& rFractX, Fraction& rFractY ) const pDoc->GetTableArea( nTab, nEndCol, nEndRow ); if (nEndCol<20) nEndCol = 20; - if (nEndRow<20) - nEndRow = 20; + if (nEndRow<1000) + nEndRow = 1000; Fraction aZoom(1,1); ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev, aZoom,aZoom, diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx index cc09722530ad..1d2b797b3a9b 100644 --- a/sc/source/ui/view/drawview.cxx +++ b/sc/source/ui/view/drawview.cxx @@ -187,7 +187,7 @@ void ScDrawView::AddCustomHdl() if(nCol > 0) --nCol; - SCROW nRow = nPosY <= 0 ? 0 : pDoc->FastGetRowForHeight( nTab, + SCROW nRow = nPosY <= 0 ? 0 : pDoc->GetRowForHeight( nTab, (ULONG) nPosY); if(nRow > 0) --nRow; @@ -376,8 +376,8 @@ void ScDrawView::RecalcScale() pDoc->GetTableArea( nTab, nEndCol, nEndRow ); if (nEndCol<20) nEndCol = 20; - if (nEndRow<20) - nEndRow = 20; + if (nEndRow<1000) + nEndRow = 1000; ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev,aZoomX,aZoomY,nPPTX,nPPTY, aScaleX,aScaleY ); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index ff40bdeb7390..db72d87f30a2 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -153,7 +153,19 @@ extern USHORT nScFillModeMouseModifier; // global.cxx #define SC_FILTERLISTBOX_LINES 12 -//================================================================== +// ============================================================================ + +ScGridWindow::VisibleRange::VisibleRange() : + mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW) +{ +} + +bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const +{ + return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2; +} + +// ============================================================================ class ScFilterListBox : public ListBox { @@ -366,6 +378,7 @@ ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhic mpOODragRect( NULL ), mpOOHeader( NULL ), mpOOShrink( NULL ), + mpAutoFillRect(static_cast<Rectangle*>(NULL)), pViewData( pData ), eWhich( eWhichPos ), pNoteMarker( NULL ), @@ -1323,37 +1336,23 @@ BOOL ScGridWindow::TestMouse( const MouseEvent& rMEvt, BOOL bAction ) ScDocument* pDoc = pViewData->GetDocument(); SCTAB nTab = pViewData->GetTabNo(); BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab ); - long nLayoutSign = bLayoutRTL ? -1 : 1; // Auto-Fill ScRange aMarkRange; if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE) { - if ( aMarkRange.aStart.Tab() == pViewData->GetTabNo() ) + if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect) { - // Block-Ende wie in DrawAutoFillMark - SCCOL nX = aMarkRange.aEnd.Col(); - SCROW nY = aMarkRange.aEnd.Row(); - - Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE ); - long nSizeXPix; - long nSizeYPix; - pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); - aFillPos.X() += nSizeXPix * nLayoutSign; - aFillPos.Y() += nSizeYPix; - if ( bLayoutRTL ) - aFillPos.X() -= 1; - Point aMousePos = rMEvt.GetPosPixel(); - // Abfrage hier passend zu DrawAutoFillMark - // (ein Pixel mehr als markiert) - if ( aMousePos.X() >= aFillPos.X()-3 && aMousePos.X() <= aFillPos.X()+4 && - aMousePos.Y() >= aFillPos.Y()-3 && aMousePos.Y() <= aFillPos.Y()+4 ) + if (mpAutoFillRect->IsInside(aMousePos)) { SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ? if (bAction) { + SCCOL nX = aMarkRange.aEnd.Col(); + SCROW nY = aMarkRange.aEnd.Row(); + if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) ) pViewData->SetDragMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX ); @@ -2953,7 +2952,7 @@ void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, // clicked on selected object -> don't change anything bHitSelected = TRUE; } - else if ( pViewData->GetMarkData().IsCellMarked( (USHORT) nCellX, (USHORT) nCellY ) ) + else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) ) { // clicked on selected cell -> don't change anything bHitSelected = TRUE; @@ -2977,7 +2976,7 @@ void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, if ( !bHitDraw ) { pView->Unmark(); - pView->SetCursor( (USHORT) nCellX, (USHORT) nCellY ); + pView->SetCursor(nCellX, nCellY); if ( bWasDraw ) pViewData->GetViewShell()->SetDrawShell( FALSE ); // switch shells } @@ -4552,18 +4551,17 @@ void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, USHORT nEdges SCROW nTmp; ScDocument* pDoc = pDocSh->GetDocument(); - while ( nCol1 > 0 && ( pDoc->GetColFlags( nCol1, nTab1 ) & CR_HIDDEN ) ) + while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) ) { --nCol1; bHiddenEdge = TRUE; } - while ( nCol2 < MAXCOL && ( pDoc->GetColFlags( nCol2, nTab1 ) & CR_HIDDEN ) ) + while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) ) { ++nCol2; bHiddenEdge = TRUE; } - nTmp = pDoc->GetRowFlagsArray( nTab1).GetLastForCondition( 0, nRow1, - CR_HIDDEN, 0); + nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1); if (!ValidRow(nTmp)) nTmp = 0; if (nTmp < nRow1) @@ -4571,8 +4569,7 @@ void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, USHORT nEdges nRow1 = nTmp; bHiddenEdge = TRUE; } - nTmp = pDoc->GetRowFlagsArray( nTab1).GetFirstForCondition( nRow2, MAXROW, - CR_HIDDEN, 0); + nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1); if (!ValidRow(nTmp)) nTmp = MAXROW; if (nTmp > nRow2) @@ -5142,6 +5139,9 @@ void ScGridWindow::UpdateCursorOverlay() SCCOL nX = pViewData->GetCurX(); SCROW nY = pViewData->GetCurY(); + if (!maVisibleRange.isInside(nX, nY)) + return; + // don't show the cursor in overlapped cells ScDocument* pDoc = pViewData->GetDocument(); @@ -5317,6 +5317,7 @@ void ScGridWindow::UpdateSelectionOverlay() void ScGridWindow::DeleteAutoFillOverlay() { DELETEZ( mpOOAutoFill ); + mpAutoFillRect.reset(); } void ScGridWindow::UpdateAutoFillOverlay() @@ -5337,6 +5338,11 @@ void ScGridWindow::UpdateAutoFillOverlay() { SCCOL nX = aAutoMarkPos.Col(); SCROW nY = aAutoMarkPos.Row(); + + if (!maVisibleRange.isInside(nX, nY)) + // Autofill mark is not visible. Bail out. + return; + SCTAB nTab = pViewData->GetTabNo(); ScDocument* pDoc = pViewData->GetDocument(); BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab ); @@ -5352,7 +5358,7 @@ void ScGridWindow::UpdateAutoFillOverlay() aFillPos.Y() += nSizeYPix; aFillPos.Y() -= 2; - Rectangle aFillRect( aFillPos, Size(6,6) ); + mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6))); // #i70788# get the OverlayManager safely ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); @@ -5362,7 +5368,7 @@ void ScGridWindow::UpdateAutoFillOverlay() const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); std::vector< basegfx::B2DRange > aRanges; const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); - basegfx::B2DRange aRB(aFillRect.Left(), aFillRect.Top(), aFillRect.Right() + 1, aFillRect.Bottom() + 1); + basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1); aRB.transform(aTransform); aRanges.push_back(aRB); @@ -5377,10 +5383,10 @@ void ScGridWindow::UpdateAutoFillOverlay() mpOOAutoFill = new ::sdr::overlay::OverlayObjectList; mpOOAutoFill->append(*pOverlay); } - } - if ( aOldMode != aDrawMode ) - SetMapMode( aOldMode ); + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); + } } void ScGridWindow::DeleteDragRectOverlay() diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx index 6d9bb94eb76b..f8b5c25c4a70 100644 --- a/sc/source/ui/view/gridwin2.cxx +++ b/sc/source/ui/view/gridwin2.cxx @@ -933,7 +933,7 @@ void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, BOOL bUp ) BOOL bGrow = !bHide && nNew > nPagebreakBreak; if ( bColumn ) { - if ( pDoc->GetColFlags( static_cast<SCCOL>(nPagebreakBreak), nTab ) & CR_MANUALBREAK ) + if (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakBreak), nTab) & BREAK_MANUAL) { ScAddress aOldAddr( static_cast<SCCOL>(nPagebreakBreak), nPosY, nTab ); pViewFunc->DeletePageBreak( TRUE, TRUE, &aOldAddr, FALSE ); @@ -946,8 +946,8 @@ void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, BOOL bUp ) if ( bGrow ) { // vorigen Break auf hart, und Skalierung aendern - if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && - !(pDoc->GetColFlags( static_cast<SCCOL>(nPagebreakPrev), nTab ) & CR_MANUALBREAK) ) + bool bManualBreak = (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakPrev), nTab) & BREAK_MANUAL); + if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && !bManualBreak ) { ScAddress aPrev( static_cast<SCCOL>(nPagebreakPrev), nPosY, nTab ); pViewFunc->InsertPageBreak( TRUE, TRUE, &aPrev, FALSE ); @@ -960,7 +960,7 @@ void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, BOOL bUp ) } else { - if ( pDoc->GetRowFlags( nPagebreakBreak, nTab ) & CR_MANUALBREAK ) + if (pDoc->HasRowBreak(nPagebreakBreak, nTab) & BREAK_MANUAL) { ScAddress aOldAddr( nPosX, nPagebreakBreak, nTab ); pViewFunc->DeletePageBreak( FALSE, TRUE, &aOldAddr, FALSE ); @@ -973,8 +973,8 @@ void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, BOOL bUp ) if ( bGrow ) { // vorigen Break auf hart, und Skalierung aendern - if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && - !(pDoc->GetRowFlags( nPagebreakPrev, nTab ) & CR_MANUALBREAK) ) + bool bManualBreak = (pDoc->HasRowBreak(nPagebreakPrev, nTab) & BREAK_MANUAL); + if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && !bManualBreak ) { ScAddress aPrev( nPosX, nPagebreakPrev, nTab ); pViewFunc->InsertPageBreak( FALSE, TRUE, &aPrev, FALSE ); diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx index 5bfc0483b553..f16c2fe1ada7 100644 --- a/sc/source/ui/view/gridwin3.cxx +++ b/sc/source/ui/view/gridwin3.cxx @@ -265,7 +265,7 @@ MapMode ScGridWindow::GetDrawMapMode( BOOL bForce ) SCROW nEndRow = 0; pDoc->GetTableArea( nTab, nEndCol, nEndRow ); if (nEndCol<20) nEndCol = 20; - if (nEndRow<20) nEndRow = 20; + if (nEndRow<1000) nEndRow = 1000; ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, this, pViewData->GetZoomX(),pViewData->GetZoomY(), pViewData->GetPPTX(),pViewData->GetPPTY(), diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index f698913ea758..d8024e439173 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -449,6 +449,12 @@ void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMod SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); if (nYBottom > MAXROW) nYBottom = MAXROW; + // Store the current visible range. + maVisibleRange.mnCol1 = nPosX; + maVisibleRange.mnCol2 = nXRight; + maVisibleRange.mnRow1 = nPosY; + maVisibleRange.mnRow2 = nYBottom; + if (nX1 > nXRight || nY1 > nYBottom) return; // unsichtbar if (nX2 > nXRight) nX2 = nXRight; @@ -1086,7 +1092,7 @@ void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, if ( nBreak >= nX1 && nBreak <= nX2+1 ) { //! hidden suchen - if ( pDoc->GetColFlags( nBreak, nTab ) & CR_MANUALBREAK ) + if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL) pContentDev->SetFillColor( aManual ); else pContentDev->SetFillColor( aAutomatic ); @@ -1105,7 +1111,7 @@ void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, if ( nBreak >= nY1 && nBreak <= nY2+1 ) { //! hidden suchen - if ( pDoc->GetRowFlags( nBreak, nTab ) & CR_MANUALBREAK ) + if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL) pContentDev->SetFillColor( aManual ); else pContentDev->SetFillColor( aAutomatic ); @@ -1374,7 +1380,7 @@ Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos ) const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE )); if ( pMerge->GetColMerge() > 1 ) nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area - while ( nNextCol <= MAXCOL && (pDoc->GetColFlags( nNextCol, nTab ) & CR_HIDDEN) ) + while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) ) ++nNextCol; BOOL bNextCell = ( nNextCol <= MAXCOL ); if ( bNextCell ) @@ -1577,7 +1583,7 @@ void ScGridWindow::InvertSimple( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) { while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && - ( (pDoc->GetRowFlags( nThisY-1, nTab ) & CR_HIDDEN) || bFirstRow ) ) + (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) { --nThisY; pPattern = pDoc->GetPattern( nX, nThisY, nTab ); @@ -1764,7 +1770,7 @@ void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects ) if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) { while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && - ( (pDoc->GetRowFlags( nThisY-1, nTab ) & CR_HIDDEN) || bFirstRow ) ) + (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) { --nThisY; pPattern = pDoc->GetPattern( nX, nThisY, nTab ); diff --git a/sc/source/ui/view/hdrcont.cxx b/sc/source/ui/view/hdrcont.cxx index 6c389d496b73..25f3c1c8f10a 100644 --- a/sc/source/ui/view/hdrcont.cxx +++ b/sc/source/ui/view/hdrcont.cxx @@ -102,7 +102,7 @@ ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEn nWidth = nSmallWidth = aSize.Width(); nBigWidth = LogicToPixel( Size( GetTextWidth( - String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("88888")) ), 0 ) ).Width() + 4; + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5; SetBackground(); // sonst Probleme auf OS/2 !?!?! } diff --git a/sc/source/ui/view/olinewin.cxx b/sc/source/ui/view/olinewin.cxx index bec88920f989..b1e82fd9217f 100644 --- a/sc/source/ui/view/olinewin.cxx +++ b/sc/source/ui/view/olinewin.cxx @@ -183,16 +183,15 @@ const ScOutlineEntry* ScOutlineWindow::GetOutlineEntry( size_t nLevel, size_t nE bool ScOutlineWindow::IsHidden( SCCOLROW nColRowIndex ) const { - sal_uInt8 nFlags = mbHoriz ? - GetDoc().GetColFlags( static_cast<SCCOL>(nColRowIndex), GetTab() ) : - GetDoc().GetRowFlags( static_cast<SCROW>(nColRowIndex), GetTab() ); - return (nFlags & CR_HIDDEN) != 0; + return mbHoriz ? + GetDoc().ColHidden(static_cast<SCCOL>(nColRowIndex), GetTab()) : + GetDoc().RowHidden(static_cast<SCROW>(nColRowIndex), GetTab()); } bool ScOutlineWindow::IsFiltered( SCCOLROW nColRowIndex ) const { // columns cannot be filtered - return !mbHoriz && GetDoc().IsFiltered( static_cast<SCROW>(nColRowIndex), GetTab() ); + return !mbHoriz && GetDoc().RowFiltered( static_cast<SCROW>(nColRowIndex), GetTab() ); } bool ScOutlineWindow::IsFirstVisible( SCCOLROW nColRowIndex ) const diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index 265e54fe0e12..961572fc0185 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -322,8 +322,9 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) long nPosX; long nPosY; SCSIZE nArrY; - BYTE nOldFlags = 0; - BYTE nFlags; + ScBreakType nBreak = BREAK_NONE; + ScBreakType nBreakOld = BREAK_NONE; + BOOL bSingle; Color aPageColor; Color aManualColor; @@ -378,27 +379,27 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) if ( bPage ) { // Seitenumbrueche auch in ausgeblendeten suchen - nFlags = 0; SCCOL nCol = nXplus1; while (nCol <= MAXCOL) { - BYTE nDocFl = pDoc->GetColFlags( nCol, nTab ); - nFlags = nDocFl & ( CR_PAGEBREAK | CR_MANUALBREAK ); - if ( nFlags || !(nDocFl & CR_HIDDEN) ) + nBreak = pDoc->HasColBreak(nCol, nTab); + bool bHidden = pDoc->ColHidden(nCol, nTab); + + if ( nBreak || !bHidden ) break; ++nCol; } - if (nFlags != nOldFlags) + if (nBreak != nBreakOld) { aGrid.Flush(); - pDev->SetLineColor( (nFlags & CR_MANUALBREAK) ? aManualColor : - (nFlags) ? aPageColor : aGridColor ); - nOldFlags = nFlags; + pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor : + nBreak ? aPageColor : aGridColor ); + nBreakOld = nBreak; } } - BOOL bDraw = bGrid || nOldFlags; // einfaches Gitter nur wenn eingestellt + BOOL bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer //! Umbruch mitten in den Wiederholungsspalten liegt. @@ -409,7 +410,7 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) { if ( nX == MAXCOL ) bDraw = FALSE; - else if (pDoc->GetColFlags(nXplus1,nTab) & ( CR_PAGEBREAK | CR_MANUALBREAK )) + else if (pDoc->HasColBreak(nXplus1, nTab)) bDraw = FALSE; } #endif @@ -500,28 +501,24 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) { if ( bPage ) { - // Seitenumbrueche auch in ausgeblendeten suchen - nFlags = 0; - ScCompressedArrayIterator< SCROW, BYTE > aIter( - pDoc->GetRowFlagsArray( nTab), nYplus1, MAXROW); - do + for (SCROW i = nYplus1; i <= MAXROW; ++i) { - BYTE nDocFl = *aIter; - nFlags = nDocFl & ( CR_PAGEBREAK | CR_MANUALBREAK ); - if ( nFlags || !(nDocFl & CR_HIDDEN) ) + nBreak = pDoc->HasRowBreak(i, nTab); + bool bHidden = pDoc->RowHidden(i, nTab); + if (nBreak || !bHidden) break; - } while (aIter.NextRange()); + } - if (nFlags != nOldFlags) + if (nBreakOld != nBreak) { aGrid.Flush(); - pDev->SetLineColor( (nFlags & CR_MANUALBREAK) ? aManualColor : - (nFlags) ? aPageColor : aGridColor ); - nOldFlags = nFlags; + pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor : + (nBreak) ? aPageColor : aGridColor ); + nBreakOld = nBreak; } } - BOOL bDraw = bGrid || nOldFlags; // einfaches Gitter nur wenn eingestellt + BOOL bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer //! Umbruch mitten in den Wiederholungszeilen liegt. @@ -532,7 +529,7 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) { if ( nY == MAXROW ) bDraw = FALSE; - else if (pDoc->GetRowFlags(nYplus1,nTab) & ( CR_PAGEBREAK | CR_MANUALBREAK )) + else if (pDoc->HasRowBreak(nYplus1, nTab)) bDraw = FALSE; } #endif @@ -654,7 +651,7 @@ void ScOutputData::FindRotated() const ScPatternAttr* pPattern = pInfo->pPatternAttr; const SfxItemSet* pCondSet = pInfo->pConditionSet; - if ( !pPattern && (pDoc->GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) + if ( !pPattern && !pDoc->ColHidden(nX, nTab) ) { pPattern = pDoc->GetPattern( nX, nY, nTab ); pCondSet = pDoc->GetCondResult( nX, nY, nTab ); diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 37bc941c0f16..ef3c32abf5aa 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -844,7 +844,7 @@ BOOL ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY, while (bHOver) // nY konstant { --rOverX; - bHidden = ( (pDoc->GetColFlags(rOverX,nTab) & CR_HIDDEN) != 0 ); + bHidden = pDoc->ColHidden(rOverX, nTab); if ( !bDoMerge && !bHidden ) return FALSE; @@ -868,7 +868,7 @@ BOOL ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY, while (bVOver) { --rOverY; - bHidden = ( (pDoc->GetRowFlags(rOverY,nTab) & CR_HIDDEN) != 0 ); + bHidden = pDoc->RowHidden(rOverY, nTab); if ( !bDoMerge && !bHidden ) return FALSE; @@ -876,8 +876,8 @@ BOOL ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY, --nArrY; // lokale Kopie ! if (rOverX >= nX1 && rOverY >= nY1 && - (pDoc->GetColFlags(rOverX,nTab) & CR_HIDDEN) == 0 && - (pDoc->GetRowFlags(rOverY,nTab) & CR_HIDDEN) == 0 && + !pDoc->ColHidden(rOverX, nTab) && + !pDoc->RowHidden(rOverY, nTab) && pRowInfo[nArrY].nRowNo == rOverY) { // rVirtPosY -= pRowInfo[nArrY].nHeight; @@ -2176,7 +2176,7 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) if (bDoCell) { if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 && - (pDoc->GetColFlags(nCellX,nTab) & CR_HIDDEN) == 0 ) + !pDoc->ColHidden(nCellX, nTab) ) { CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1]; pPattern = rCellInfo.pPatternAttr; diff --git a/sc/source/ui/view/prevloc.cxx b/sc/source/ui/view/prevloc.cxx index 67e1aa86553a..fd36a1b2c1d0 100644 --- a/sc/source/ui/view/prevloc.cxx +++ b/sc/source/ui/view/prevloc.cxx @@ -350,9 +350,9 @@ Rectangle ScPreviewLocationData::GetOffsetPixel( const ScAddress& rCellPos, cons long nSizeX = (long) ( pDoc->GetColWidth( nEndCol, nTab ) * nScaleX ); SCROW nEndRow = rCellPos.Row(); - long nPosY = (long) pDoc->FastGetScaledRowHeight( rRange.aStart.Row(), + long nPosY = (long) pDoc->GetScaledRowHeight( rRange.aStart.Row(), nEndRow, nTab, nScaleY); - long nSizeY = (long) ( pDoc->FastGetRowHeight( nEndRow, nTab ) * nScaleY ); + long nSizeY = (long) ( pDoc->GetRowHeight( nEndRow, nTab ) * nScaleY ); Size aOffsetLogic( nPosX, nPosY ); Size aSizeLogic( nSizeX, nSizeY ); @@ -599,11 +599,11 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev ++nColCount; if ( bHasRepCols ) for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ ) - if ( ( pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN ) == 0 ) + if (!pDoc->ColHidden(nCol, nTab)) ++nColCount; if ( bHasMainCols ) for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ ) - if ( ( pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN ) == 0 ) + if (!pDoc->ColHidden(nCol, nTab)) ++nColCount; if ( nColCount > 0 ) @@ -620,7 +620,7 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev { long nPosX = 0; for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ ) - if ( ( pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN ) == 0 ) + if (!pDoc->ColHidden(nCol, nTab)) { USHORT nDocW = pDoc->GetColWidth( nCol, nTab ); long nNextX = nPosX + (long) (nDocW * nScaleX); @@ -639,7 +639,7 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev { long nPosX = 0; for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ ) - if ( ( pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN ) == 0 ) + if (!pDoc->ColHidden(nCol, nTab)) { USHORT nDocW = pDoc->GetColWidth( nCol, nTab ); long nNextX = nPosX + (long) (nDocW * nScaleX); @@ -667,11 +667,9 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev if ( bHasHeaderRow ) ++nRowCount; if ( bHasRepRows ) - nRowCount += pDoc->GetRowFlagsArray( nTab).CountForCondition( - nRepeatRowStart, nRepeatRowEnd, CR_HIDDEN, 0); + nRowCount += pDoc->CountVisibleRows(nRepeatRowStart, nRepeatRowEnd, nTab); if ( bHasMainRows ) - nRowCount += pDoc->GetRowFlagsArray( nTab).CountForCondition( - nMainRowStart, nMainRowEnd, CR_HIDDEN, 0); + nRowCount += pDoc->CountVisibleRows(nMainRowStart, nMainRowEnd, nTab); if ( nRowCount > 0 ) { @@ -686,58 +684,44 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev if ( bHasRepRows ) { long nPosY = 0; - ScCompressedArrayIterator< SCROW, BYTE> aIter( - pDoc->GetRowFlagsArray( nTab), nRepeatRowStart, - nRepeatRowEnd); - do + for (SCROW nRow = nRepeatRowStart; nRow <= nRepeatRowEnd; ++nRow) { - if ((*aIter & CR_HIDDEN) == 0) - { - SCROW nRangeEnd = aIter.GetRangeEnd(); - for (SCROW nRow=aIter.GetRangeStart(); nRow<=nRangeEnd; ++nRow) - { - USHORT nDocH = pDoc->FastGetOriginalRowHeight( nRow, nTab ); - long nNextY = nPosY + (long) (nDocH * nScaleY); - - long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); - long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; - pRowInfo[nRowPos].Set( FALSE, nRow, - aRepeatRect.Top() + nPixelStart, - aRepeatRect.Top() + nPixelEnd ); - - nPosY = nNextY; - ++nRowPos; - } - } - } while (aIter.NextRange()); + if (pDoc->RowHidden(nRow, nTab)) + continue; + + USHORT nDocH = pDoc->GetOriginalHeight( nRow, nTab ); + long nNextY = nPosY + (long) (nDocH * nScaleY); + + long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); + long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; + pRowInfo[nRowPos].Set( FALSE, nRow, + aRepeatRect.Top() + nPixelStart, + aRepeatRect.Top() + nPixelEnd ); + + nPosY = nNextY; + ++nRowPos; + } } if ( bHasMainRows ) { long nPosY = 0; - ScCompressedArrayIterator< SCROW, BYTE> aIter( - pDoc->GetRowFlagsArray( nTab), nMainRowStart, - nMainRowEnd); - do + for (SCROW nRow = nMainRowStart; nRow <= nMainRowEnd; ++nRow) { - if ((*aIter & CR_HIDDEN) == 0) - { - SCROW nRangeEnd = aIter.GetRangeEnd(); - for (SCROW nRow=aIter.GetRangeStart(); nRow<=nRangeEnd; ++nRow) - { - USHORT nDocH = pDoc->FastGetOriginalRowHeight( nRow, nTab ); - long nNextY = nPosY + (long) (nDocH * nScaleY); - - long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); - long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; - pRowInfo[nRowPos].Set( FALSE, nRow, - aMainRect.Top() + nPixelStart, - aMainRect.Top() + nPixelEnd ); - - nPosY = nNextY; - ++nRowPos; - } - } - } while (aIter.NextRange()); + if (pDoc->RowHidden(nRow, nTab)) + continue; + + USHORT nDocH = pDoc->GetOriginalHeight( nRow, nTab ); + long nNextY = nPosY + (long) (nDocH * nScaleY); + + long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); + long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; + pRowInfo[nRowPos].Set( FALSE, nRow, + aMainRect.Top() + nPixelStart, + aMainRect.Top() + nPixelEnd ); + + nPosY = nNextY; + ++nRowPos; + } } rInfo.SetRowInfo( nRowCount, pRowInfo ); } diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx index afe23892e786..378ea1233cf9 100644 --- a/sc/source/ui/view/printfun.cxx +++ b/sc/source/ui/view/printfun.cxx @@ -85,6 +85,8 @@ #include <vcl/lineinfo.hxx> #include <tools/pstm.hxx> +#include <boost/scoped_ptr.hpp> + #define ZOOM_MIN 10 #define GET_BOOL(set,which) ((const SfxBoolItem&)(set)->Get((which))).GetValue() @@ -1501,7 +1503,7 @@ void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY ) for (SCROW nRow=nY1; nRow<=nY2; nRow++) { - USHORT nDocH = pDoc->FastGetRowHeight( nRow, nPrintTab ); + USHORT nDocH = pDoc->GetRowHeight( nRow, nPrintTab ); if (nDocH) { long nHeight = (long) (nDocH * nScaleY); @@ -1557,7 +1559,7 @@ void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY, nEndX -= nOneX; long nPosY = nScrY - nOneY; - nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); + nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY ); rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow ); } @@ -1599,7 +1601,7 @@ void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, } long nPosY = nScrY - nOneY; - nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); + nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY ); rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ), bRepCol, bRepRow, aDrawMapMode ); @@ -2181,9 +2183,9 @@ void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCRO } if ( bCenterVer ) { - long nDataHeight = pDoc->FastGetRowHeight( nY1, nY2, nPrintTab); + long nDataHeight = pDoc->GetRowHeight( nY1, nY2, nPrintTab); if (bDoRepRow) - nDataHeight += pDoc->FastGetRowHeight( nRepeatStartRow, + nDataHeight += pDoc->GetRowHeight( nRepeatStartRow, nRepeatEndRow, nPrintTab); if (aTableParam.bHeaders) nDataHeight += (long) PRINT_HEADER_HEIGHT; @@ -2216,11 +2218,11 @@ void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCRO for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++) nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX); if (bDoRepRow) - nRepeatHeight += pDoc->FastGetScaledRowHeight( nRepeatStartRow, + nRepeatHeight += pDoc->GetScaledRowHeight( nRepeatStartRow, nRepeatEndRow, nPrintTab, nScaleY); for (SCCOL i=nX1; i<=nX2; i++) nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX); - nContentHeight += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, + nContentHeight += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); // partition the page @@ -2886,30 +2888,84 @@ void ScPrintFunc::CalcZoom( USHORT nRangeNo ) // Zoom bere if (aTableParam.bScalePageNum) { nZoom = 100; - BOOL bFound = FALSE; USHORT nPagesToFit = aTableParam.nScalePageNum; - while (!bFound) + + sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0; + while (true) { + if (nZoom <= ZOOM_MIN) + break; + CalcPages(); - if ( nPagesX * nPagesY <= nPagesToFit || nZoom <= ZOOM_MIN ) - bFound = TRUE; + bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit); + + if (bFitsPage) + { + if (nZoom == 100) + // If it fits at 100 %, it's good enough for me. + break; + + nLastFitZoom = nZoom; + nZoom = (nLastNonFitZoom + nZoom) / 2; + + if (nLastFitZoom == nZoom) + // It converged. Use this zoom level. + break; + } else - --nZoom; + { + if (nZoom - nLastFitZoom <= 1) + { + nZoom = nLastFitZoom; + CalcPages(); + break; + } + + nLastNonFitZoom = nZoom; + nZoom = (nLastFitZoom + nZoom) / 2; + } } } else if (aTableParam.bScaleTo) { nZoom = 100; - BOOL bFound = FALSE; USHORT nW = aTableParam.nScaleWidth; USHORT nH = aTableParam.nScaleHeight; - while (!bFound) + + sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0; + while (true) { + if (nZoom <= ZOOM_MIN) + break; + CalcPages(); - if ( ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH))) || (nZoom <= ZOOM_MIN) ) - bFound = TRUE; + bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH))); + + if (bFitsPage) + { + if (nZoom == 100) + // If it fits at 100 %, it's good enough for me. + break; + + nLastFitZoom = nZoom; + nZoom = (nLastNonFitZoom + nZoom) / 2; + + if (nLastFitZoom == nZoom) + // It converged. Use this zoom level. + break; + } else - --nZoom; + { + if (nZoom - nLastFitZoom <= 1) + { + nZoom = nLastFitZoom; + CalcPages(); + break; + } + + nLastNonFitZoom = nZoom; + nZoom = (nLastFitZoom + nZoom) / 2; + } } } else if (aTableParam.bScaleAll) @@ -3029,18 +3085,20 @@ void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten au nPagesY = 0; nTotalY = 0; - BOOL bVisCol = FALSE; + bool bVisCol = false; + SCCOL nLastCol = -1; for (SCCOL i=nStartCol; i<=nEndCol; i++) { - BYTE nFlags = pDoc->GetColFlags(i,nPrintTab); - if ( i>nStartCol && bVisCol && (nFlags & CR_PAGEBREAK) ) + bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol); + bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE); + if ( i>nStartCol && bVisCol && bPageBreak ) { pPageEndX[nPagesX] = i-1; ++nPagesX; - bVisCol = FALSE; + bVisCol = false; } - if (!(nFlags & CR_HIDDEN)) - bVisCol = TRUE; + if (!bHidden) + bVisCol = true; } if (bVisCol) // auch am Ende keine leeren Seiten { @@ -3048,39 +3106,60 @@ void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten au ++nPagesX; } - BOOL bVisRow = FALSE; + bool bVisRow = false; SCROW nPageStartRow = nStartRow; - ScCompressedArrayIterator< SCROW, BYTE> aIter( pDoc->GetRowFlagsArray( - nPrintTab), nStartRow, nEndRow); - do + SCROW nLastVisibleRow = -1; + + ::boost::scoped_ptr<ScRowBreakIterator> pRowBreakIter(pDoc->GetRowBreakIterator(nPrintTab)); + SCROW nNextPageBreak = pRowBreakIter->first(); + while (nNextPageBreak != ScRowBreakIterator::NOT_FOUND && nNextPageBreak < nStartRow) + // Skip until the page break position is at the start row or greater. + nNextPageBreak = pRowBreakIter->next(); + + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) { - BYTE nFlags = *aIter; - SCROW nRangeEnd = aIter.GetRangeEnd(); - for (SCROW j=aIter.GetRangeStart(); j<=nRangeEnd; ++j) + bool bPageBreak = (nNextPageBreak == nRow); + if (bPageBreak) + nNextPageBreak = pRowBreakIter->next(); + + if (nRow > nStartRow && bVisRow && bPageBreak ) { - if ( j>nStartRow && bVisRow && (nFlags & CR_PAGEBREAK) ) + pPageEndY[nTotalY] = nRow-1; + ++nTotalY; + + if ( !aTableParam.bSkipEmpty || + !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) ) { - pPageEndY[nTotalY] = j-1; - ++nTotalY; + pPageRows[nPagesY].SetStartRow( nPageStartRow ); + pPageRows[nPagesY].SetEndRow( nRow-1 ); + pPageRows[nPagesY].SetPagesX( nPagesX ); + if (aTableParam.bSkipEmpty) + lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX ); + ++nPagesY; + } - if ( !aTableParam.bSkipEmpty || - !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, j-1 ) ) - { - pPageRows[nPagesY].SetStartRow( nPageStartRow ); - pPageRows[nPagesY].SetEndRow( j-1 ); - pPageRows[nPagesY].SetPagesX( nPagesX ); - if (aTableParam.bSkipEmpty) - lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX ); - ++nPagesY; - } + nPageStartRow = nRow; + bVisRow = false; + } - nPageStartRow = j; - bVisRow = FALSE; - } - if (!(nFlags & CR_HIDDEN)) - bVisRow = TRUE; + if (nRow <= nLastVisibleRow) + { + // This row is still visible. Don't bother calling RowHidden() to + // find out, for speed optimization. + bVisRow = true; + continue; + } + + SCROW nLastRow = -1; + if (!pDoc->RowHidden(nRow, nPrintTab, NULL, &nLastRow)) + { + bVisRow = true; + nLastVisibleRow = nLastRow; } - } while (aIter.NextRange()); + else + // skip all hidden rows. + nRow = nLastRow; + } if (bVisRow) { diff --git a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx index 4887895c8e6b..b2c9ffdc1395 100644 --- a/sc/source/ui/view/select.cxx +++ b/sc/source/ui/view/select.cxx @@ -275,12 +275,12 @@ BOOL __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, BOO ScDocument* pDoc = pViewData->GetDocument(); SCTAB nTab = pViewData->GetTabNo(); if ( bLeft && !bRightScroll ) - do --nPosX; while ( nPosX>=0 && ( pDoc->GetColFlags( nPosX, nTab ) & CR_HIDDEN ) ); + do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) ); if ( bTop && !bBottomScroll ) { if (--nPosY >= 0) { - pDoc->GetRowFlagsArray( nTab).GetLastForCondition( 0, nPosY, CR_HIDDEN, 0); + nPosY = pDoc->LastVisibleRow(0, nPosY, nTab); if (!ValidRow(nPosY)) nPosY = -1; } @@ -476,7 +476,7 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol { // #94321# in SetCursorAtPoint hidden columns are skipped. // They must be skipped here too, or the result will always be the first hidden column. - do ++nPosX; while ( nPosX<nStartX && ( pDoc->GetColFlags( nPosX, nTab ) & CR_HIDDEN ) ); + do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) ); for (SCCOL i=nPosX; i<nStartX; i++) nSizeX += pDoc->GetColWidth( i, nTab ); } @@ -491,8 +491,7 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol // They must be skipped here too, or the result will always be the first hidden row. if (++nPosY < nStartY) { - nPosY = pDoc->GetRowFlagsArray( nTab).GetFirstForCondition( - nPosY, nStartY-1, CR_HIDDEN, 0); + nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab); if (!ValidRow(nPosY)) nPosY = nStartY; } diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx index 4938defa437d..0bc4617a9af4 100644 --- a/sc/source/ui/view/tabview.cxx +++ b/sc/source/ui/view/tabview.cxx @@ -1439,7 +1439,7 @@ void ScTabView::ScrollX( long nDeltaX, ScHSplitPos eWhich, BOOL bUpdBars ) SCsCOL nDir = ( nDeltaX > 0 ) ? 1 : -1; ScDocument* pDoc = aViewData.GetDocument(); SCTAB nTab = aViewData.GetTabNo(); - while ( ( pDoc->GetColFlags( nNewX, nTab ) & CR_HIDDEN ) && + while ( pDoc->ColHidden(nNewX, nTab) && nNewX+nDir >= 0 && nNewX+nDir <= MAXCOL ) nNewX = sal::static_int_cast<SCsCOL>( nNewX + nDir ); @@ -1528,7 +1528,7 @@ void ScTabView::ScrollY( long nDeltaY, ScVSplitPos eWhich, BOOL bUpdBars ) SCsROW nDir = ( nDeltaY > 0 ) ? 1 : -1; ScDocument* pDoc = aViewData.GetDocument(); SCTAB nTab = aViewData.GetTabNo(); - while ( ( pDoc->GetRowFlags( nNewY, nTab ) & CR_HIDDEN ) && + while ( pDoc->RowHidden(nNewY, nTab) && nNewY+nDir >= 0 && nNewY+nDir <= MAXROW ) nNewY += nDir; @@ -1615,7 +1615,7 @@ SCROW lcl_LastVisible( ScViewData& rViewData ) SCTAB nTab = rViewData.GetTabNo(); SCROW nVis = MAXROW; - while ( nVis > 0 && pDoc->FastGetRowHeight( nVis, nTab ) == 0 ) + while ( nVis > 0 && pDoc->GetRowHeight( nVis, nTab ) == 0 ) --nVis; return nVis; } diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx index b7a773ab2abd..674f6f8ae0ff 100644 --- a/sc/source/ui/view/tabview2.cxx +++ b/sc/source/ui/view/tabview2.cxx @@ -640,13 +640,13 @@ BOOL lcl_FitsInWindow( double fScaleX, double fScaleY, USHORT nZoom, } long nBlockY = 0; - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - pDoc->GetRowFlagsArray( nTab), 0, nFixPosY-1, CR_HIDDEN, 0, - pDoc->GetRowHeightArray( nTab)); - for ( ; aIter; ++aIter) + for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow) { + if (pDoc->RowHidden(nRow, nTab)) + continue; + // for frozen panes, add both parts - USHORT nRowTwips = *aIter; + USHORT nRowTwips = pDoc->GetRowHeight(nRow, nTab); if (nRowTwips) { nBlockY += (long)(nRowTwips * fScaleY); @@ -654,10 +654,9 @@ BOOL lcl_FitsInWindow( double fScaleX, double fScaleY, USHORT nZoom, return FALSE; } } - aIter.NewLimits( nStartRow, nEndRow); - for ( ; aIter; ++aIter) + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) { - USHORT nRowTwips = *aIter; + USHORT nRowTwips = pDoc->GetRowHeight(nRow, nTab); if (nRowTwips) { nBlockY += (long)(nRowTwips * fScaleY); diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx index 750e49ec2334..86f68a1878cc 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -968,8 +968,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, BOOL bHFlip = FALSE; do { - BYTE nColFlags = pDoc->GetColFlags( nCurX, nTab ); - bSkipCell = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); + SCCOL nLastCol = -1; + bSkipCell = pDoc->ColHidden(nCurX, nTab, nLastCol) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); if (bSkipProtected && !bSkipCell) bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); if (bSkipUnprotected && !bSkipCell) @@ -1010,8 +1010,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, BOOL bVFlip = FALSE; do { - BYTE nRowFlags = pDoc->GetRowFlags( nCurY, nTab ); - bSkipCell = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); + SCROW nLastRow = -1; + bSkipCell = pDoc->RowHidden(nCurY, nTab, nLastRow) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); if (bSkipProtected && !bSkipCell) bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); if (bSkipUnprotected && !bSkipCell) @@ -2093,17 +2093,18 @@ void ScTabView::PaintRangeFinder( long nNumber ) BOOL bHiddenEdge = FALSE; SCROW nTmp; ScDocument* pDoc = aViewData.GetDocument(); - while ( nCol1 > 0 && ( pDoc->GetColFlags( nCol1, nTab ) & CR_HIDDEN ) ) + SCCOL nLastCol = -1; + while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab, nLastCol) ) { --nCol1; bHiddenEdge = TRUE; } - while ( nCol2 < MAXCOL && ( pDoc->GetColFlags( nCol2, nTab ) & CR_HIDDEN ) ) + while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab, nLastCol) ) { ++nCol2; bHiddenEdge = TRUE; } - nTmp = pDoc->GetRowFlagsArray( nTab).GetLastForCondition( 0, nRow1, CR_HIDDEN, 0); + nTmp = pDoc->LastVisibleRow(0, nRow1, nTab); if (!ValidRow(nTmp)) nTmp = 0; if (nTmp < nRow1) @@ -2111,7 +2112,7 @@ void ScTabView::PaintRangeFinder( long nNumber ) nRow1 = nTmp; bHiddenEdge = TRUE; } - nTmp = pDoc->GetRowFlagsArray( nTab).GetFirstForCondition( nRow2, MAXROW, CR_HIDDEN, 0); + nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab); if (!ValidRow(nTmp)) nTmp = MAXROW; if (nTmp > nRow2) diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx index bc5c94c271e2..f0ac3fc42869 100644 --- a/sc/source/ui/view/tabview5.cxx +++ b/sc/source/ui/view/tabview5.cxx @@ -666,7 +666,7 @@ void ScTabView::MakeVisible( const Rectangle& rHMMRect ) if (nScrollY > 0) while (nScrollY > 0 && nPosY < MAXROW) { - nScrollY -= (long) ( pDoc->FastGetRowHeight(nPosY, nTab) * nPPTY ); + nScrollY -= (long) ( pDoc->GetRowHeight(nPosY, nTab) * nPPTY ); ++nPosY; ++nLinesY; } @@ -674,7 +674,7 @@ void ScTabView::MakeVisible( const Rectangle& rHMMRect ) while (nScrollY < 0 && nPosY > 0) { --nPosY; - nScrollY += (long) ( pDoc->FastGetRowHeight(nPosY, nTab) * nPPTY ); + nScrollY += (long) ( pDoc->GetRowHeight(nPosY, nTab) * nPPTY ); --nLinesY; } diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx index a94d73a4b022..c0af39226c3f 100644 --- a/sc/source/ui/view/tabvwshe.cxx +++ b/sc/source/ui/view/tabvwshe.cxx @@ -52,6 +52,7 @@ #include "editsh.hxx" #include "dociter.hxx" #include "inputhdl.hxx" +#include "document.hxx" //================================================================== @@ -88,6 +89,22 @@ String __EXPORT ScTabViewShell::GetSelectionText( BOOL bWholeWord ) else aRange.aEnd = aRange.aStart; } + else + { + // #i111531# with 1M rows it was necessary to limit the range + // to the actually used data area. + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + SCTAB nTab1, nTab2; + aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + if (pDoc->ShrinkToUsedDataArea( nTab1, nCol1, nRow1, nCol2, nRow2, false)) + { + aRange.aStart.SetCol( nCol1 ); + aRange.aStart.SetRow( nRow1 ); + aRange.aEnd.SetCol( nCol2 ); + aRange.aEnd.SetRow( nRow2 ); + } + } ScImportExport aObj( pDoc, aRange ); aObj.SetFormulas( GetViewData()->GetOptions().GetOption( VOPT_FORMULAS ) ); diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index b0a3635d35c7..c034836d4d4a 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1603,7 +1603,7 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, nScrPosY = 65535; else { - nTSize = pDoc->FastGetRowHeight( nY, nTabNo ); + nTSize = pDoc->GetRowHeight( nY, nTabNo ); if (nTSize) { long nSizeYPix = ToPixel( nTSize, nPPTY ); @@ -1612,7 +1612,7 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, else if ( nY < MAXROW ) { // skip multiple hidden rows (forward only for now) - SCROW nNext = pDoc->FastGetFirstNonHiddenRow( nY + 1, nTabNo ); + SCROW nNext = pDoc->FirstVisibleRow(nY + 1, MAXROW, nTabNo); if ( nNext > MAXROW ) nY = MAXROW; else @@ -1624,7 +1624,7 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, for (nY=nPosY; nY>nWhereY;) { --nY; - nTSize = pDoc->FastGetRowHeight( nY, nTabNo ); + nTSize = pDoc->GetRowHeight( nY, nTabNo ); if (nTSize) { long nSizeYPix = ToPixel( nTSize, nPPTY ); @@ -1714,8 +1714,7 @@ SCROW ScViewData::CellsAtY( SCsROW nPosY, SCsROW nDir, ScVSplitPos eWhichY, USHO bOut = TRUE; else { -// USHORT nTSize = pDoc->GetRowHeight( nRowNo, nTabNo ); - USHORT nTSize = pDoc->FastGetRowHeight( nRowNo, nTabNo ); + USHORT nTSize = pDoc->GetRowHeight( nRowNo, nTabNo ); if (nTSize) { long nSizeYPix = ToPixel( nTSize, nPPTY ); @@ -1724,7 +1723,7 @@ SCROW ScViewData::CellsAtY( SCsROW nPosY, SCsROW nDir, ScVSplitPos eWhichY, USHO else if ( nDir == 1 && nRowNo < MAXROW ) { // skip multiple hidden rows (forward only for now) - SCROW nNext = pDoc->FastGetFirstNonHiddenRow( nRowNo + 1, nTabNo ); + SCROW nNext = pDoc->FirstVisibleRow(nRowNo + 1, MAXROW, nTabNo); if ( nNext > MAXROW ) { // same behavior as without the optimization: set bOut with nY=MAXROW+1 @@ -1787,11 +1786,19 @@ BOOL ScViewData::GetMergeSizePixel( SCCOL nX, SCROW nY, long& rSizeXPix, long& r for (SCCOL i=0; i<nCountX; i++) nOutWidth += ToPixel( pDoc->GetColWidth(nX+i,nTabNo), nPPTX ); SCROW nCountY = pMerge->GetRowMerge(); - ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter( - pDoc->GetRowFlagsArray( nTabNo), nY, nY+nCountY-1, CR_HIDDEN, - 0, pDoc->GetRowHeightArray( nTabNo)); - for ( ; aIter; ++aIter ) - nOutHeight += ToPixel( *aIter, nPPTY ); + + for (SCROW nRow = nY; nRow <= nY+nCountY-1; ++nRow) + { + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTabNo, NULL, &nLastRow)) + { + nRow = nLastRow; + continue; + } + + USHORT nHeight = pDoc->GetRowHeight(nRow, nTabNo); + nOutHeight += ToPixel(nHeight, nPPTY); + } rSizeXPix = nOutWidth; rSizeYPix = nOutHeight; @@ -1851,7 +1858,7 @@ BOOL ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich, { while ( rPosY<=MAXROW && nClickY >= nScrY ) { - nScrY += ToPixel( pDoc->FastGetRowHeight( rPosY, nTabNo ), nPPTY ); + nScrY += ToPixel( pDoc->GetRowHeight( rPosY, nTabNo ), nPPTY ); ++rPosY; } --rPosY; @@ -1861,7 +1868,7 @@ BOOL ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich, while ( rPosY>0 && nClickY < nScrY ) { --rPosY; - nScrY -= ToPixel( pDoc->FastGetRowHeight( rPosY, nTabNo ), nPPTY ); + nScrY -= ToPixel( pDoc->GetRowHeight( rPosY, nTabNo ), nPPTY ); } } @@ -1981,14 +1988,14 @@ void ScViewData::SetPosY( ScVSplitPos eWhich, SCROW nNewPosY ) if ( nNewPosY > nOldPosY ) for ( i=nOldPosY; i<nNewPosY; i++ ) { - long nThis = pDoc->FastGetRowHeight( i,nTabNo ); + long nThis = pDoc->GetRowHeight( i,nTabNo ); nTPosY -= nThis; nPixPosY -= ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY); } else for ( i=nNewPosY; i<nOldPosY; i++ ) { - long nThis = pDoc->FastGetRowHeight( i,nTabNo ); + long nThis = pDoc->GetRowHeight( i,nTabNo ); nTPosY += nThis; nPixPosY += ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY); } @@ -2018,7 +2025,7 @@ void ScViewData::RecalcPixPos() // nach Zoom-Aenderungen long nPixPosY = 0; SCROW nPosY = pThisTab->nPosY[eWhich]; for (SCROW j=0; j<nPosY; j++) - nPixPosY -= ToPixel(pDoc->FastGetRowHeight(j,nTabNo), nPPTY); + nPixPosY -= ToPixel(pDoc->GetRowHeight(j,nTabNo), nPPTY); pThisTab->nPixPosY[eWhich] = nPixPosY; } } @@ -2061,7 +2068,7 @@ void ScViewData::SetScreen( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) for (nRow=nRow1; nRow<=nRow2; nRow++) { - nTSize = pDoc->FastGetRowHeight( nRow, nTabNo ); + nTSize = pDoc->GetRowHeight( nRow, nTabNo ); if (nTSize) { nSizePix = ToPixel( nTSize, nPPTY ); @@ -2103,7 +2110,7 @@ void ScViewData::SetScreenPos( const Point& rVisAreaStart ) bEnd = FALSE; while (!bEnd) { - nAdd = (long) pDoc->FastGetRowHeight(nY1,nTabNo); + nAdd = (long) pDoc->GetRowHeight(nY1,nTabNo); if (nSize+nAdd <= nTwips+1 && nY1<MAXROW) { nSize += nAdd; @@ -3055,7 +3062,7 @@ BOOL ScViewData::UpdateFixY( SCTAB nTab ) // TRUE = Wert geaendert long nNewPos = 0; for (SCROW nY=pTabData[nTab]->nPosY[SC_SPLIT_TOP]; nY<nFix; nY++) { - USHORT nTSize = pLocalDoc->FastGetRowHeight( nY, nTab ); + USHORT nTSize = pLocalDoc->GetRowHeight( nY, nTab ); if (nTSize) { long nPix = ToPixel( nTSize, nPPTY ); diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index dacb41cd1aea..24fab9ac2eba 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -1723,10 +1723,10 @@ BOOL ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos, BOOL bIncludeFiltered = bCut; if ( !bIncludeFiltered ) { - // manually find number of non-filtered rows - SCROW nPastedCount = pDocSh->GetDocument()->GetRowFlagsArray( - rSource.aStart.Tab()).CountForCondition( - rSource.aStart.Row(), rSource.aEnd.Row(), CR_FILTERED, 0); + // find number of non-filtered rows + SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows( + rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab()); + if ( nPastedCount == 0 ) nPastedCount = 1; aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 ); diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx index 9697cae3a57e..dc4e96bbbf34 100644 --- a/sc/source/ui/view/viewfun5.cxx +++ b/sc/source/ui/view/viewfun5.cxx @@ -110,7 +110,7 @@ BOOL ScViewFunc::PasteDataFormat( ULONG nFormatId, nXT += pDoc->GetColWidth(i,nTab); if (pDoc->IsNegativePage(nTab)) nXT = -nXT; - ULONG nYT = pDoc->FastGetRowHeight( 0, nPosY-1, nTab); + ULONG nYT = pDoc->GetRowHeight( 0, nPosY-1, nTab); aPos = Point( (long)(nXT * HMM_PER_TWIPS), (long)(nYT * HMM_PER_TWIPS) ); } } diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 5d3bf97aa29c..231eb4e67562 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -2195,28 +2195,19 @@ void ScViewFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pR { // fuer alle eingeblendeten CR_MANUALSIZE loeschen, // dann SetOptimalHeight mit bShrink = FALSE - ScCompressedArrayIterator< SCROW, BYTE> aIter( - pDoc->GetRowFlagsArray( nTab), nStartNo, - nEndNo); - do + for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow) { - BYTE nOld = *aIter; - if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) ) + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow)) { - SCROW nRangeEnd = aIter.GetRangeEnd(); - pDoc->SetRowFlags( aIter.GetRangeStart(), - nRangeEnd, nTab, - nOld & ~CR_MANUALSIZE); - aIter.Resync( nRangeEnd); - // Range may be extended due to merges and - // now aIter.GetRangeEnd() may point behind - // the previous row, but all flags of this - // range have the CR_MANUALSIZE bit - // removed, so it is safe to continue with - // the next range, not necessary to catch - // up with the remaining rows. + nRow = nLastRow; + continue; } - } while (aIter.NextRange()); + + BYTE nOld = pDoc->GetRowFlags(nRow, nTab); + if (nOld & CR_MANUALSIZE) + pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE); + } } double nPPTX = GetViewData()->GetPPTX(); @@ -2258,8 +2249,7 @@ void ScViewFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pR { for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) { - if ( eMode != SC_SIZE_VISOPT || - (pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) == 0 ) + if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) ) { USHORT nThisSize = nSizeTwips; diff --git a/sc/source/ui/view/viewutil.cxx b/sc/source/ui/view/viewutil.cxx index d887aec8bc5b..a6b4e320d3ab 100644 --- a/sc/source/ui/view/viewutil.cxx +++ b/sc/source/ui/view/viewutil.cxx @@ -271,20 +271,19 @@ void ScViewUtil::UnmarkFiltered( ScMarkData& rMark, ScDocument* pDoc ) for (SCTAB nTab=0; nTab<nTabCount; nTab++) if ( rMark.GetTableSelect(nTab ) ) { - ScCompressedArrayIterator<SCROW, BYTE> aIter(pDoc->GetRowFlagsArray(nTab), nStartRow, nEndRow); - do + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) { - if (*aIter & CR_FILTERED) + SCROW nLastRow = nRow; + if (pDoc->RowFiltered(nRow, nTab, NULL, &nLastRow)) { // use nStartCol/nEndCol, so the multi mark area isn't extended to all columns // (visible in repaint for indentation) - - rMark.SetMultiMarkArea( ScRange( nStartCol, aIter.GetRangeStart(), nTab, - nEndCol, aIter.GetRangeEnd(), nTab ), FALSE ); + rMark.SetMultiMarkArea( + ScRange(nStartCol, nRow, nTab, nEndCol, nLastRow, nTab), false); bChanged = true; + nRow = nLastRow; } } - while (aIter.NextRange()); } if ( bChanged && !rMark.HasAnyMultiMarks() ) @@ -295,34 +294,29 @@ void ScViewUtil::UnmarkFiltered( ScMarkData& rMark, ScDocument* pDoc ) // static -bool ScViewUtil::FitToUnfilteredRows( ScRange & rRange, const ScDocument * pDoc, size_t nRows ) +bool ScViewUtil::FitToUnfilteredRows( ScRange & rRange, ScDocument * pDoc, size_t nRows ) { SCTAB nTab = rRange.aStart.Tab(); bool bOneTabOnly = (nTab == rRange.aEnd.Tab()); // Always fit the range on its first sheet. DBG_ASSERT( bOneTabOnly, "ScViewUtil::ExtendToUnfilteredRows: works only on one sheet"); SCROW nStartRow = rRange.aStart.Row(); - // FillArrayForCondition() usually is the fastest to determine such a set - // in one pass, even if the array isn't used but the last element. - SCROW* pArr = new SCROW[nRows]; - size_t nCount = pDoc->GetRowFlagsArray( nTab).FillArrayForCondition( - nStartRow, MAXROW, CR_FILTERED, 0, pArr, nRows); - if (nCount) - rRange.aEnd.SetRow( pArr[nCount-1]); - delete [] pArr; - return nCount == nRows && bOneTabOnly; + SCROW nLastRow = pDoc->LastNonFilteredRow(nStartRow, MAXROW, nTab); + if (ValidRow(nLastRow)) + rRange.aEnd.SetRow(nLastRow); + SCROW nCount = pDoc->CountNonFilteredRows(nStartRow, MAXROW, nTab); + return static_cast<size_t>(nCount) == nRows && bOneTabOnly; } // static -bool ScViewUtil::HasFiltered( const ScRange& rRange, const ScDocument* pDoc ) +bool ScViewUtil::HasFiltered( const ScRange& rRange, ScDocument* pDoc ) { SCROW nStartRow = rRange.aStart.Row(); SCROW nEndRow = rRange.aEnd.Row(); for (SCTAB nTab=rRange.aStart.Tab(); nTab<=rRange.aEnd.Tab(); nTab++) { - if ( pDoc->GetRowFlagsArray( nTab).HasCondition( nStartRow, nEndRow, - CR_FILTERED, CR_FILTERED ) ) + if (pDoc->HasFilteredRows(nStartRow, nEndRow, nTab)) return true; } |