[ooo-build-commit] patches/test

Kohei Yoshida kohei at kemper.freedesktop.org
Thu May 28 22:18:43 PDT 2009


 patches/test/calc-perf-table-hidden-flags.diff | 3655 +++++++++++++++++++++++++
 1 file changed, 3655 insertions(+)

New commits:
commit b8cbd4e3c5e909265a6085be4d822535f94bf676
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 29 01:17:36 2009 -0400

    On-going work on refactoring table's hidden flags.
    
    * patches/test/calc-perf-table-hidden-flags.diff: backup patch.

diff --git a/patches/test/calc-perf-table-hidden-flags.diff b/patches/test/calc-perf-table-hidden-flags.diff
new file mode 100644
index 0000000..16de0cb
--- /dev/null
+++ b/patches/test/calc-perf-table-hidden-flags.diff
@@ -0,0 +1,3655 @@
+diff --git sc/inc/column.hxx sc/inc/column.hxx
+index 0f9586e..e5901fd 100644
+--- sc/inc/column.hxx
++++ sc/inc/column.hxx
+@@ -217,10 +217,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,
+diff --git sc/inc/document.hxx sc/inc/document.hxx
+index b016e1e..500f4e5 100644
+--- sc/inc/document.hxx
++++ sc/inc/document.hxx
+@@ -433,9 +433,6 @@ private:
+ 	// for worksheet calculate event
+ 	::std::vector< SCTAB > maTabs;
+ 
+-	inline BOOL 		RowHidden( SCROW nRow, SCTAB nTab );		// FillInfo
+-    bool                RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastHiddenRow) const;
+-
+ public:
+ 	SC_DLLPUBLIC ULONG			GetCellCount() const;		// alle Zellen
+ 	ULONG			GetWeightedCount() const;	// Formeln und Edit staerker gewichtet
+@@ -443,7 +440,6 @@ public:
+ 	DECL_LINK( GetUserDefinedColor, USHORT * );
+     BOOL        RowFiltered( SCROW nRow, SCTAB nTab ) const;    // FillInfo
+     BOOL        ColFiltered( SCCOL nCol, SCTAB nTab ) const;    // FillInfo
+-																// Numberformatter
+ 
+ public:
+ 	SC_DLLPUBLIC 				ScDocument( ScDocumentMode eMode = SCDOCMODE_DOCUMENT,
+@@ -1261,7 +1257,6 @@ public:
+                         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;
+@@ -1312,6 +1307,18 @@ public:
+     ::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);
++    sal_uInt32                  GetTotalRowHeight(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 
+@@ -1806,42 +1813,18 @@ inline void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab )
+ 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);
++    ULONG nHeight = FastGetRowHeight(nStartRow, nEndRow, nTab);
++    return nHeight * fScale;
+ }
+ 
+ inline USHORT ScDocument::FastGetRowHeight( SCROW nRow, SCTAB nTab ) const
+ {
+-    return ( pTab[nTab]->pRowFlags->GetValue(nRow) & CR_HIDDEN ) ? 0 :
+-        pTab[nTab]->pRowHeight->GetValue(nRow);
++    return pTab[nTab]->GetRowHeight(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);
++    return pTab[nTab]->GetRowForHeight(nHeight);
+ }
+ 
+ inline USHORT ScDocument::FastGetOriginalRowHeight( SCROW nRow, SCTAB nTab ) const
+diff --git sc/inc/olinetab.hxx sc/inc/olinetab.hxx
+index 592bec1..bba62f5 100644
+--- sc/inc/olinetab.hxx
++++ sc/inc/olinetab.hxx
+@@ -41,7 +41,7 @@
+ class SvStream;
+ class ScMultipleReadHeader;
+ class ScMultipleWriteHeader;
+-
++class ScTable;
+ 
+ class ScOutlineEntry : public ScDataObject
+ {
+@@ -128,9 +128,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 sc/inc/segmenttree.hxx sc/inc/segmenttree.hxx
+index c9a07af..f414002 100644
+--- sc/inc/segmenttree.hxx
++++ sc/inc/segmenttree.hxx
+@@ -31,9 +31,12 @@
+ #ifndef SC_SEGMENTTREE_HXX
+ #define SC_SEGMENTTREE_HXX
+ 
+-#include "mdds/flatsegmenttree.hxx"
+ #include "address.hxx"
+ 
++#include <memory>
++
++class ScFlatBoolSegmentsImpl;
++
+ class ScFlatBoolRowSegments
+ {
+ public:
+@@ -52,7 +55,30 @@ public:
+     bool getRangeData(SCROW nRow, RangeData& rData);
+ 
+ private:
+-    ::mdds::flat_segment_tree<SCROW, bool> maSegments;
++    ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl;
++};
++
++// ============================================================================
++
++class ScFlatBoolColSegments
++{
++public:
++    struct RangeData
++    {
++        SCCOL   mnCol1;
++        SCCOL   mnCol2;
++        bool    mbValue;
++    };
++    ScFlatBoolColSegments();
++    ~ScFlatBoolColSegments();
++
++    void setTrue(SCCOL nCol1, SCCOL nCol2);
++    void setFalse(SCCOL nCol1, SCCOL nCol2);
++    bool getValue(SCCOL nCol);
++    bool getRangeData(SCCOL nCol, RangeData& rData);
++
++private:
++    ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl;
+ };
+ 
+ 
+diff --git sc/inc/table.hxx sc/inc/table.hxx
+index a3fc5c9..355710a 100644
+--- sc/inc/table.hxx
++++ sc/inc/table.hxx
+@@ -84,6 +84,7 @@ struct ScFunctionData;
+ struct ScLineFlags;
+ class CollatorWrapper;
+ class ScFlatBoolRowSegments;
++class ScFlatBoolColSegments;
+ 
+ 
+ class ScTable
+@@ -123,6 +124,7 @@ private:
+ 
+ 	BYTE*			pColFlags;
+ 	ScBitMaskCompressedArray< SCROW, BYTE>*     pRowFlags;
++    ::boost::shared_ptr<ScFlatBoolColSegments>  mpHiddenCols;
+     ::boost::shared_ptr<ScFlatBoolRowSegments>  mpHiddenRows;
+ 
+     ::std::set<SCROW>                      maRowPageBreaks;
+@@ -450,7 +452,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,
+@@ -565,19 +567,29 @@ public:
+ 						// 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 );
++	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);
+@@ -628,6 +640,23 @@ public:
+     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);
++    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);
++
+     void        SyncColRowFlags();
+ 
+ 	void		StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
+@@ -758,7 +787,7 @@ private:
+ 
+ 	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"
+diff --git sc/source/core/data/column2.cxx sc/source/core/data/column2.cxx
+index cc8e369..721082e 100644
+--- sc/source/core/data/column2.cxx
++++ sc/source/core/data/column2.cxx
+@@ -69,6 +69,7 @@
+ #include "compiler.hxx"			// ScTokenArray GetCodeLen
+ #include "dbcolect.hxx"
+ #include "fillinfo.hxx"
++#include "segmenttree.hxx"
+ 
+ #include <math.h>
+ 
+@@ -1785,7 +1786,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;
+@@ -1793,7 +1794,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 );
+ 	}
+@@ -1801,7 +1803,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;
+@@ -1809,7 +1811,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 sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
+index aa2164e..6ceb1cd 100644
+--- sc/source/core/data/documen3.cxx
++++ sc/source/core/data/documen3.cxx
+@@ -1596,46 +1596,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)
+-	{
+-        nY1 = aIter.GetPos();
+-		nAdd = (long) *aIter;
+-		if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
++    bEnd = FALSE;
++    for (SCROW i = nY1; i <= MAXROW && !bEnd; ++i)
++    {
++        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;
++            nSize += nAdd;
++            ++nY1;
+         }
+-		else
+-			bEnd = TRUE;
+-	}
+-    if (!aIter)
+-        nY1 = aIter.GetIterEnd();   // all hidden down to the bottom
++        else
++            bEnd = TRUE;
++    }
++    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)
+-	{
+-        nY2 = aIter.GetPos();
+-		nAdd = (long) *aIter;
++    for (SCROW i = nY2; i <= MAXROW && !bEnd; ++i)
++    {
++        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 );
+ }
+@@ -1673,24 +1670,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 )
+-	{
+-        nRow = aIter.GetPos();
+-		long nAdd = *aIter;
++
++    bool bFound = false;
++    for (SCROW i = nRow; i <= MAXROW; ++i)
++    {
++        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;
+ }
+diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
+index 98001ef..e5ac2ba 100644
+--- sc/source/core/data/document.cxx
++++ sc/source/core/data/document.cxx
+@@ -100,6 +100,7 @@
+ #include <com/sun/star/container/XContainer.hpp>
+ 
+ #include <map>
++#include <limits>
+ 
+ using namespace ::com::sun::star;
+ 
+@@ -2972,8 +2973,7 @@ ULONG ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) con
+ ULONG ScDocument::FastGetRowHeight( SCROW nStartRow, SCROW nEndRow,
+         SCTAB nTab ) const
+ {
+-    return pTab[nTab]->pRowFlags->SumCoupledArrayForCondition( nStartRow,
+-            nEndRow, CR_HIDDEN, 0, *(pTab[nTab]->pRowHeight));
++	return GetRowHeight(nStartRow, nEndRow, nTab);
+ }
+ 
+ ULONG ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
+@@ -3279,6 +3279,106 @@ Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
+     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);
++}
++
++sal_uInt32 ScDocument::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
++{
++	if (!ValidTab(nTab) || !pTab[nTab])
++        return 0;
++
++    return pTab[nTab]->GetTotalRowHeight(nStartRow, nEndRow);
++}
++
+ void ScDocument::SyncColRowFlags()
+ {
+     for (SCTAB i = 0; i <= nMaxTableNumber; ++i)
+diff --git sc/source/core/data/drwlayer.cxx sc/source/core/data/drwlayer.cxx
+index 08123cd..7990987 100644
+--- sc/source/core/data/drwlayer.cxx
++++ sc/source/core/data/drwlayer.cxx
+@@ -603,12 +603,14 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData,
+ 	{
+ 		//!	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() );
+@@ -640,9 +642,9 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData,
+ 		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() );
+diff --git sc/source/core/data/fillinfo.cxx sc/source/core/data/fillinfo.cxx
+index a33a4cf..f881401 100644
+--- sc/source/core/data/fillinfo.cxx
++++ sc/source/core/data/fillinfo.cxx
+@@ -54,7 +54,6 @@
+ #include "docpool.hxx"
+ #include "conditio.hxx"
+ #include "stlpool.hxx"
+-#include "segmenttree.hxx"
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -100,11 +99,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;
+@@ -126,8 +127,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;
+@@ -144,8 +145,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->
+@@ -158,33 +159,6 @@ void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY,
+ 	rEndY = rStartY + pMerge->GetRowMerge() - 1;
+ }
+ 
+-inline BOOL ScDocument::RowHidden( SCROW nRow, SCTAB nTab )
+-{
+-    bool b = ( pTab[nTab]->pRowFlags->GetValue(nRow) & CR_HIDDEN ) != 0;
+-#if 0
+-    bool bHidden = pTab[nTab]->mpHiddenRows->getValue(nRow);
+-    if (b != bHidden)
+-        fprintf(stdout, "ScDocument::RowHidden:   bad! (table = %d; row = %ld) (hidden %d; myvalue %d)\n",
+-                nTab, nRow, b, bHidden);
+-#endif
+-	return b;
+-}
+-
+-bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastHiddenRow) const
+-{
+-    ScFlatBoolRowSegments::RangeData aData;
+-    if (!pTab[nTab]->mpHiddenRows->getRangeData(nRow, aData))
+-        return true;
+-
+-    if (!aData.mbValue)
+-        return false;
+-
+-    // This row is hidden.
+-    rLastHiddenRow = aData.mnRow2;
+-    return true;
+-}
+-
+-
+ #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
+ 
+ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
+@@ -380,7 +354,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)
+@@ -400,7 +374,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)
+diff --git sc/source/core/data/olinetab.cxx sc/source/core/data/olinetab.cxx
+index 8bd74a2..efce37b 100644
+--- sc/source/core/data/olinetab.cxx
++++ sc/source/core/data/olinetab.cxx
+@@ -44,6 +44,7 @@
+ #include "global.hxx"
+ #include "rechead.hxx"
+ #include "address.hxx"
++#include "table.hxx"
+ 
+ //------------------------------------------------------------------------
+ 
+@@ -640,8 +641,7 @@ 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;
+ 	ScSubOutlineIterator aIter( this );
+@@ -657,9 +657,7 @@ 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);
++                SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol);
+                 BOOL bAllHidden = (nEntryEnd <= nEnd && nEnd <
+                         ::std::numeric_limits<SCCOLROW>::max());
+ 
+diff --git sc/source/core/data/segmenttree.cxx sc/source/core/data/segmenttree.cxx
+index d0b2b98..b534de1 100644
+--- sc/source/core/data/segmenttree.cxx
++++ sc/source/core/data/segmenttree.cxx
+@@ -32,43 +32,68 @@
+ #include "precompiled_sc.hxx"
+ 
+ #include "segmenttree.hxx"
++#include "mdds/flatsegmenttree.hxx"
+ 
+ #define USE_TREE_SEARCH 1
+ 
+-ScFlatBoolRowSegments::ScFlatBoolRowSegments() :
+-    maSegments(0, MAXROW+1, false)
++class ScFlatBoolSegmentsImpl
++{
++public:
++    struct RangeData
++    {
++        SCCOLROW    mnPos1;
++        SCCOLROW    mnPos2;
++        bool        mbValue;
++    };
++    ScFlatBoolSegmentsImpl(SCCOLROW nMax);
++    ~ScFlatBoolSegmentsImpl();
++
++    void setTrue(SCCOLROW nPos1, SCCOLROW nPos2);
++    void setFalse(SCCOLROW nPos1, SCCOLROW nPos2);
++    bool getValue(SCCOLROW nPos);
++    bool getRangeData(SCCOLROW nPos, RangeData& rData);
++
++private:
++    ScFlatBoolSegmentsImpl();
++    ScFlatBoolSegmentsImpl(const ScFlatBoolSegmentsImpl&);
++
++    ::mdds::flat_segment_tree<SCCOLROW, bool> maSegments;
++};
++
++ScFlatBoolSegmentsImpl::ScFlatBoolSegmentsImpl(SCCOLROW nMax) :
++    maSegments(0, nMax+1, false)
+ {
+ }
+ 
+-ScFlatBoolRowSegments::~ScFlatBoolRowSegments()
++ScFlatBoolSegmentsImpl::~ScFlatBoolSegmentsImpl()
+ {
+ }
+ 
+-void ScFlatBoolRowSegments::setTrue(SCROW nRow1, SCROW nRow2)
++void ScFlatBoolSegmentsImpl::setTrue(SCCOLROW nPos1, SCCOLROW nPos2)
+ {
+-    maSegments.insert_segment(nRow1, nRow2+1, true);
++    maSegments.insert_segment(nPos1, nPos2+1, true);
+ }
+ 
+-void ScFlatBoolRowSegments::setFalse(SCROW nRow1, SCROW nRow2)
++void ScFlatBoolSegmentsImpl::setFalse(SCCOLROW nPos1, SCCOLROW nPos2)
+ {
+-    maSegments.insert_segment(nRow1, nRow2+1, false);
++    maSegments.insert_segment(nPos1, nPos2+1, false);
+ }
+ 
+-bool ScFlatBoolRowSegments::getValue(SCROW nRow)
++bool ScFlatBoolSegmentsImpl::getValue(SCCOLROW nPos)
+ {
+     bool bValue = false;
+ #if USE_TREE_SEARCH
+     if (!maSegments.is_tree_valid())
+         maSegments.build_tree();
+ 
+-    maSegments.search_tree(nRow, bValue);
++    maSegments.search_tree(nPos, bValue);
+ #else
+-    maSegments.search(nRow, bValue);
++    maSegments.search(nPos, bValue);
+ #endif
+     return bValue;
+ }
+ 
+-bool ScFlatBoolRowSegments::getRangeData(SCROW nRow, RangeData& rData)
++bool ScFlatBoolSegmentsImpl::getRangeData(SCCOLROW nPos, RangeData& rData)
+ {
+ #if USE_TREE_SEARCH
+     if (!maSegments.is_tree_valid())
+@@ -76,17 +101,93 @@ bool ScFlatBoolRowSegments::getRangeData(SCROW nRow, RangeData& rData)
+ #endif
+ 
+     bool bValue;
+-    SCROW nRow1, nRow2;
++    SCCOLROW nPos1, nPos2;
+ #if USE_TREE_SEARCH
+-    if (!maSegments.search_tree(nRow, bValue, &nRow1, &nRow2))
++    if (!maSegments.search_tree(nPos, bValue, &nPos1, &nPos2))
+         return false;
+ #else
+-    if (!maSegments.search(nRow, bValue, &nRow1, &nRow2))
++    if (!maSegments.search(nPos, bValue, &nPos1, &nPos2))
+         return false;
+ #endif
+ 
+-    rData.mnRow1 = nRow1;
+-    rData.mnRow2 = nRow2-1; // end point is not inclusive.
++    rData.mnPos1 = nPos1;
++    rData.mnPos2 = nPos2-1; // end point is not inclusive.
+     rData.mbValue = bValue;
+     return true;
+ }
++
++// ============================================================================
++
++ScFlatBoolRowSegments::ScFlatBoolRowSegments() :
++    mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXROW)))
++{
++}
++
++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.mbValue;
++    rData.mnRow1  = static_cast<SCROW>(aData.mnPos1);
++    rData.mnRow2  = static_cast<SCROW>(aData.mnPos2);
++    return true;
++}
++
++// ============================================================================
++
++ScFlatBoolColSegments::ScFlatBoolColSegments() :
++    mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXCOL)))
++{
++}
++
++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.mbValue;
++    rData.mnCol1  = static_cast<SCCOL>(aData.mnPos1);
++    rData.mnCol2  = static_cast<SCCOL>(aData.mnPos2);
++    return true;
++}
+diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
+index 9b2c376..dd4f48a 100644
+--- sc/source/core/data/table1.cxx
++++ sc/source/core/data/table1.cxx
+@@ -140,6 +140,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName,
+ 	pRowHeight( NULL ),
+ 	pColFlags( NULL ),
+ 	pRowFlags( NULL ),
++    mpHiddenCols(new ScFlatBoolColSegments),
+     mpHiddenRows(new ScFlatBoolRowSegments),
+ 	pOutlineTable( NULL ),
+ 	bTableAreaValid( FALSE ),
+@@ -885,9 +886,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;
+ 	}
+ 
+@@ -914,8 +916,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;
+@@ -925,7 +927,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)
+ 			{
+@@ -944,8 +946,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;
+@@ -1342,19 +1344,14 @@ void ScTable::ExtendPrintArea( OutputDevice* pDev,
+ 
+ 	SCSIZE nIndex;
+ 	SCCOL nPrintCol = rEndCol;
+-    SCSIZE nRowFlagsIndex;
+-    SCROW nRowFlagsEndRow;
+-    BYTE nRowFlag = pRowFlags->GetValue( nStartRow, nRowFlagsIndex, nRowFlagsEndRow);
+ 	for (SCROW nRow = nStartRow; nRow<=nEndRow; nRow++)
+ 	{
+-        if (nRow > nRowFlagsEndRow)
+-            nRowFlag = pRowFlags->GetNextValue( nRowFlagsIndex, nRowFlagsEndRow);
+-		if ( ( nRowFlag & CR_HIDDEN ) == 0 )
++		if (!RowHidden(nRow))
+ 		{
+ 			SCCOL nDataCol = rEndCol;
+ 			while (nDataCol > 0 && ( bEmpty[nDataCol] || !aCol[nDataCol].Search(nRow,nIndex) ) )
+ 				--nDataCol;
+-			if ( ( pColFlags[nDataCol] & CR_HIDDEN ) == 0 )
++            if (!ColHidden(nDataCol))
+ 			{
+ 				ScBaseCell* pCell = aCol[nDataCol].GetCell(nRow);
+ 				if (pCell)
+diff --git sc/source/core/data/table2.cxx sc/source/core/data/table2.cxx
+index 637e2b2..659af98 100644
+--- sc/source/core/data/table2.cxx
++++ sc/source/core/data/table2.cxx
+@@ -64,6 +64,49 @@
+ 
+ #include <math.h>
+ 
++
++#include <stdio.h>
++#include <string>
++#include <sys/time.h>
++
++namespace {
++
++class StackPrinter
++{
++public:
++    explicit StackPrinter(const char* msg) :
++        msMsg(msg)
++    {
++        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
++        mfStartTime = getTime();
++    }
++
++    ~StackPrinter()
++    {
++        double fEndTime = getTime();
++        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
++    }
++
++    void printTime(int line) const
++    {
++        double fEndTime = getTime();
++        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
++    }
++
++private:
++    double getTime() const
++    {
++        timeval tv;
++        gettimeofday(&tv, NULL);
++        return tv.tv_sec + tv.tv_usec / 1000000.0;
++    }
++
++    ::std::string msMsg;
++    double mfStartTime;
++};
++
++}
++
+ // STATIC DATA -----------------------------------------------------------
+ 
+ 
+@@ -353,20 +396,20 @@ 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];
+-			}
++
++        pTable->CopyColHidden(*this, 0, nCol2);
+ 
+ 		if (pRowFlags && pTable->pRowFlags && pRowHeight && pTable->pRowHeight)
+         {
+             pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2,
+-                    (CR_HIDDEN | CR_FILTERED | CR_MANUALSIZE));
++                    (CR_FILTERED | CR_MANUALSIZE));
+             pTable->pRowHeight->CopyFrom( *pRowHeight, 0, nRow2);
+         }
+ 
++        pTable->CopyRowHidden(*this, 0, nRow2);
+ 
+ 		//	ggf. Formeln durch Werte ersetzen
+ 
+@@ -646,10 +689,12 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ 			if (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth)
+ 				for (SCCOL i=nCol1; i<=nCol2; i++)
+ 				{
+-                    bool bHiddenChange = ( 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 (bHiddenChange && pCharts)
+ 						pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
+@@ -671,8 +716,10 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+                     // TODO: might need some performance improvement, block
+                     // operations instead of single GetValue()/SetValue() calls.
+                     BYTE nThisRowFlags = pRowFlags->GetValue(i);
+-					bool bHiddenChange = ( pDestTab->pRowFlags->GetValue(i) & CR_HIDDEN ) != ( nThisRowFlags & CR_HIDDEN );
++                    bool bThisHidden = RowHidden(i);
++                    bool bHiddenChange = (pDestTab->RowHidden(i) != bThisHidden);
+                     pDestTab->pRowFlags->SetValue( i, nThisRowFlags );
++                    pDestTab->SetRowHidden(i, i, bThisHidden);
+ 					//!	Aenderungen zusammenfassen?
+ 					if (bHiddenChange && pCharts)
+ 						pCharts->SetRangeDirty(ScRange( 0, i, nTab, MAXCOL, i, nTab ));
+@@ -1262,7 +1309,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 +1342,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 )
+@@ -1329,7 +1376,7 @@ 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 )
+ 	{
+@@ -1344,7 +1391,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 );
+@@ -2102,13 +2149,13 @@ void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual )
+ }
+ 
+ 
+-USHORT ScTable::GetColWidth( SCCOL nCol ) const
++USHORT ScTable::GetColWidth( SCCOL nCol )
+ {
+ 	DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
+ 
+ 	if (VALIDCOL(nCol) && pColFlags && pColWidth)
+ 	{
+-		if ( pColFlags[nCol] & CR_HIDDEN )
++        if (ColHidden(nCol))
+ 			return 0;
+ 		else
+ 			return pColWidth[nCol];
+@@ -2129,7 +2176,7 @@ USHORT ScTable::GetOriginalWidth( SCCOL nCol ) const		// immer die eingestellte
+ }
+ 
+ 
+-USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const
++USHORT ScTable::GetCommonWidth( SCCOL nEndCol )
+ {
+ 	//	get the width that is used in the largest continuous column range (up to nEndCol)
+ 
+@@ -2141,24 +2188,24 @@ USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const
+ 
+ 	USHORT nMaxWidth = 0;
+ 	USHORT nMaxCount = 0;
+-	USHORT nRangeStart = 0;
++	SCCOL nRangeStart = 0;
+ 	while ( nRangeStart <= nEndCol )
+ 	{
+ 		//	skip hidden columns
+-		while ( nRangeStart <= nEndCol && (pColFlags[nRangeStart] & CR_HIDDEN) )
++		while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
+ 			++nRangeStart;
+ 		if ( nRangeStart <= nEndCol )
+ 		{
+ 			USHORT nThisCount = 0;
+ 			USHORT nThisWidth = pColWidth[nRangeStart];
+-			USHORT nRangeEnd = nRangeStart;
++			SCCOL nRangeEnd = nRangeStart;
+ 			while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
+ 			{
+ 				++nThisCount;
+ 				++nRangeEnd;
+ 
+ 				//	skip hidden columns
+-				while ( nRangeEnd <= nEndCol && (pColFlags[nRangeEnd] & CR_HIDDEN) )
++				while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
+ 					++nRangeEnd;
+ 			}
+ 
+@@ -2176,13 +2223,13 @@ USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) const
+ }
+ 
+ 
+-USHORT ScTable::GetRowHeight( SCROW nRow ) const
++USHORT ScTable::GetRowHeight( SCROW nRow )
+ {
+ 	DBG_ASSERT(VALIDROW(nRow),"Falsche Zeilennummer");
+ 
+-	if (VALIDROW(nRow) && pRowFlags && pRowHeight)
++	if (VALIDROW(nRow) && pRowHeight)
+ 	{
+-		if ( pRowFlags->GetValue(nRow) & CR_HIDDEN )
++        if (RowHidden(nRow))
+ 			return 0;
+ 		else
+ 			return pRowHeight->GetValue(nRow);
+@@ -2192,28 +2239,53 @@ USHORT ScTable::GetRowHeight( SCROW nRow ) const
+ }
+ 
+ 
+-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) && pRowHeight)
+ 	{
+-        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 += pRowFlags->SumCoupledArrayForCondition(nRow, nLastRow, 0, 0, *pRowHeight);
++            }
++            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) && pRowHeight)
+ 	{
+-        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;
++                nHeight += pRowFlags->SumScaledCoupledArrayForCondition(
++                    nRow, nLastRow, 0, 0, *pRowHeight, fScale);
++            }
++            nRow = nLastRow + 1;
++        }
++        return nHeight;
+ 	}
+ 	else
+ 		return (ULONG) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
+@@ -2234,18 +2306,29 @@ USHORT ScTable::GetOriginalHeight( SCROW nRow ) const		// non-0 even if hidden
+ //	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 1
++    if (!ValidRow(nRow))
++        return 0;
++
++    SCROW nLastRow = -1;
++    if (!RowHidden(nRow, nLastRow) || !ValidRow(nLastRow))
++        return 0;
++
++    return nLastRow - nRow + 1;
++#else
++//  SCROW nEndRow = nRow;
++//  if ( pRowFlags )
++//  {
++//      nEndRow = pRowFlags->GetBitStateEnd( nRow, CR_HIDDEN, CR_HIDDEN);
++//      if (ValidRow(nEndRow))
++//          ++nEndRow;
++//      else
++//          nEndRow = nRow;
++//  }
++//  return nEndRow - nRow;
++#endif
+ }
+ 
+ 
+@@ -2253,9 +2336,9 @@ SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const
+ 
+ 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)
+ 		{
+ 			nRecalcLvl++;
+@@ -2268,10 +2351,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;
++            SetColHidden(nCol, nCol, !bShow);
++
+ 			if( !--nRecalcLvl )
+ 				SetDrawPageSize();
+ 
+@@ -2292,7 +2373,7 @@ 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)
+ 		{
+ 			nRecalcLvl++;
+@@ -2305,16 +2386,10 @@ void ScTable::ShowRow(SCROW nRow, BOOL bShow)
+ 					pDrawLayer->HeightChanged( nTab, nRow, -(long) pRowHeight->GetValue(nRow) );
+ 			}
+ 
++            SetRowHidden(nRow, nRow, !bShow);
+ 			if (bShow)
+-            {
+-                mpHiddenRows->setFalse(nRow, nRow);    
+-				pRowFlags->SetValue( nRow, nFlags & ~(CR_HIDDEN | CR_FILTERED));
+-            }
+-			else
+-            {    
+-                mpHiddenRows->setTrue(nRow, nRow);    
+-				pRowFlags->SetValue( nRow, nFlags | CR_HIDDEN);
+-            }
++				pRowFlags->SetValue( nRow, nFlags & ~CR_FILTERED);
++
+ 			if( !--nRecalcLvl )
+ 				SetDrawPageSize();
+ 
+@@ -2337,7 +2412,7 @@ 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);
+ 		nRecalcLvl++;
+ 		if (bWasVis != bShow)
+ 		{
+@@ -2352,16 +2427,14 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow)
+ 		}
+ 
+ 		//	Filter-Flag immer setzen, auch wenn Hidden unveraendert
++
++        SetRowHidden(nRow, nRow, !bShow);
++
+ 		if (bShow)
+-        {    
+-            mpHiddenRows->setFalse(nRow, nRow);    
+-			pRowFlags->SetValue( nRow, nFlags & ~(CR_HIDDEN | CR_FILTERED));
+-        }
++			pRowFlags->SetValue( nRow, nFlags & ~CR_FILTERED);
+ 		else
+-        {    
+-            mpHiddenRows->setTrue(nRow, nRow);    
+-			pRowFlags->SetValue( nRow, nFlags | (CR_HIDDEN | CR_FILTERED));
+-        }
++			pRowFlags->SetValue( nRow, nFlags | CR_FILTERED);
++
+ 		if( !--nRecalcLvl )
+ 			SetDrawPageSize();
+ 
+@@ -2390,12 +2463,11 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow)
+ 	nRecalcLvl++;
+ 	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 )
+ 		{
+@@ -2410,10 +2482,11 @@ void ScTable::DBShowRows(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)) );
++            pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~CR_FILTERED) );
+ 		else
+-            pRowFlags->OrValue( nStartRow, nEndRow, (CR_HIDDEN | CR_FILTERED));
++            pRowFlags->OrValue( nStartRow, nEndRow, CR_FILTERED);
+ 
+ 		if ( bChanged )
+ 		{
+@@ -2425,11 +2498,6 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow)
+ 		nStartRow = nEndRow + 1;
+ 	}
+ 
+-    if (bShow)
+-        mpHiddenRows->setFalse(nRow1, nRow2);
+-    else
+-        mpHiddenRows->setTrue(nRow1, nRow2);
+-
+ 	//	#i12341# For Show/Hide rows, the outlines are updated separately from the outside.
+ 	//	For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
+ 	//	to be done here.
+@@ -2447,12 +2515,11 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow)
+ 	nRecalcLvl++;
+ 	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 )
+ 		{
+@@ -2467,16 +2534,9 @@ 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)) );
+-            mpHiddenRows->setFalse(nStartRow, nEndRow);
+-        }
+-		else
+-        {    
+-            pRowFlags->OrValue( nStartRow, nEndRow, CR_HIDDEN);
+-            mpHiddenRows->setTrue(nStartRow, nEndRow);
+-        }
++            pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~CR_FILTERED) );
+ 
+ 		if ( bChanged )
+ 		{
+@@ -2601,7 +2661,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;
+@@ -2611,7 +2671,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;
+ }
+@@ -2619,55 +2679,59 @@ 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)
+-	{
+-        if (rY1 > 0)
++    // Column-wise expansion
++
++    while (rX1 > 0 && ColHidden(rX1-1))
++        --rX1;
++
++    while (rX2 < MAXCOL && ColHidden(rX2+1))
++        ++rX2;
++
++    // Row-wise expansion
++
++    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)
+-	{
+-        if (rY1 < rY2)
++    while ( rX2>rX1 && ColHidden(rX2) )
++        --rX2;
++    while ( rX2>rX1 && ColHidden(rX1) )
++        ++rX1;
++
++    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;
++    }
+ }
+ 
+ 
+@@ -2874,7 +2938,7 @@ void ScTable::SetDrawPageSize()
+ }
+ 
+ 
+-ULONG ScTable::GetRowOffset( SCROW nRow ) const
++ULONG ScTable::GetRowOffset( SCROW nRow )
+ {
+ 	ULONG n = 0;
+ 	if ( pRowFlags && pRowHeight )
+@@ -2884,8 +2948,7 @@ ULONG ScTable::GetRowOffset( SCROW nRow ) const
+         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");
+@@ -2898,18 +2961,60 @@ ULONG ScTable::GetRowOffset( SCROW nRow ) const
+ 	return n;
+ }
+ 
++SCROW ScTable::GetRowForHeight(ULONG nHeight)
++{
++#if 1
++    sal_uInt32 nSum = 0;
++
++    ScFlatBoolRowSegments::RangeData aData;
++    for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
++    {
++        if (!mpHiddenRows->getRangeData(nRow, aData))
++            break;
++
++        if (aData.mbValue)
++            continue;
++
++        sal_uInt32 nNew = pRowHeight->GetValue(nRow);
++        nSum += nNew;
++        if (nSum > nHeight)
++        {
++//          fprintf(stdout, "ScTable::GetRowForHeight:   hit row = %ld\n", nRow+1);
++            return nRow < MAXROW ? nRow + 1 : MAXROW;
++        }
++    }
++    return -1;
++#else
++//  ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
++//          *pRowFlags, 0, MAXROW, CR_HIDDEN, 0, *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();
++#endif
++}
++
+ 
+-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 sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
+index 9082beb..d9de9e9 100644
+--- sc/source/core/data/table3.cxx
++++ sc/source/core/data/table3.cxx
+@@ -604,10 +604,15 @@ void ScTable::SwapRow(SCROW nRow1, SCROW nRow2)
+ 	{
+ 		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);
++		BYTE nFlags1 = nRow1Flags & CR_FILTERED;
++		BYTE nFlags2 = nRow2Flags & CR_FILTERED;
++		pRowFlags->SetValue( nRow1, (nRow1Flags & ~CR_FILTERED) | nFlags2);
++		pRowFlags->SetValue( nRow2, (nRow2Flags & ~CR_FILTERED) | nFlags1);
++
++        bool bRow1Hidden = RowHidden(nRow1);
++        bool bRow2Hidden = RowHidden(nRow2);
++        SetRowHidden(nRow1, nRow1, bRow2Hidden);
++        SetRowHidden(nRow2, nRow2, bRow1Hidden);
+ 	}
+ }
+ 
+@@ -1998,8 +2003,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 );
+ 
+@@ -2007,8 +2012,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 sc/source/core/data/table5.cxx sc/source/core/data/table5.cxx
+index 618fe75..197a68e 100644
+--- sc/source/core/data/table5.cxx
++++ sc/source/core/data/table5.cxx
+@@ -53,9 +53,11 @@
+ #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;
+@@ -168,7 +170,7 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
+ 	for (nX=nStartCol; nX<=nEndCol; nX++)
+ 	{
+ 		BOOL bStartOfPage = FALSE;
+-		long nThisX = ( pColFlags[nX] & CR_HIDDEN ) ? 0 : pColWidth[nX];
++		long nThisX = ColHidden(nX) ? 0 : pColWidth[nX];
+         bool bManualBreak = HasColManualBreak(nX);
+         if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipBreaks) )
+ 		{
+@@ -185,7 +187,7 @@ 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)
+                 RemoveColBreak(++nX, true, false);
+ 			bColFound = TRUE;
+@@ -204,8 +206,7 @@ void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
+     for (SCROW nY = nStartRow; nY <= nEndRow; ++nY)
+     {
+ 		BOOL bStartOfPage = FALSE;
+-        BYTE nFlags = pRowFlags->GetValue(nY);
+-        long nThisY = (nFlags & CR_HIDDEN) ? 0 : pRowHeight->GetValue(nY);
++        long nThisY = RowHidden(nY) ? 0 : pRowHeight->GetValue(nY);
+         bool bManualBreak = HasRowManualBreak(nY);
+ 		if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipBreaks) )
+ 		{
+@@ -221,8 +222,7 @@ 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");
+@@ -416,12 +416,287 @@ Sequence<TablePageBreakData> ScTable::GetRowBreakData() const
+     return aSeq;
+ }
+ 
++//bool ScTable::RowHidden(SCROW nRow)
++//{
++//    if (!ValidRow(nRow))
++//        return true;
++//
++//#if 1
++//    SCROW nLastRow = -1;
++//    return RowHidden(nRow, nLastRow);
++//#else
++//    bool b = (pRowFlags->GetValue(nRow) & CR_HIDDEN) != 0;
++//#if 0
++//    bool bHidden = mpHiddenRows->getValue(nRow);
++//    if (b != bHidden)
++//        fprintf(stdout, "ScTable::RowHidden:   bad! (table = %d; row = %ld) (hidden %d; myvalue %d)\n",
++//                nTab, nRow, b, bHidden);
++//#endif
++//    return b;
++//#endif
++//}
++
++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);
++
++#if 0
++    // Remove this once the refactoring is complete.
++    if (bHidden)
++        pRowFlags->OrValue(nStartRow, nEndRow, CR_HIDDEN);
++    else
++        pRowFlags->AndValue(nStartRow, nEndRow, ~CR_HIDDEN);
++#endif
++}
++
++void ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
++{
++    if (bHidden)
++        mpHiddenCols->setTrue(nStartCol, nEndCol);
++    else
++        mpHiddenCols->setFalse(nStartCol, nEndCol);
++#if 0
++    for (SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol)
++    {
++        if (bHidden)
++            pColFlags[nCol] |= CR_HIDDEN;
++        else
++            pColFlags[nCol] &= ~CR_HIDDEN;
++    }
++#endif
++}
++
++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;
++    }
++}
++
++SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow)
++{
++    SCROW nRow = nStartRow;
++    ScFlatBoolRowSegments::RangeData aData;
++    while (nRow <= nEndRow)
++    {
++        if (!ValidRow(nRow))
++            return ::std::numeric_limits<SCROW>::max();
++
++        if (!mpHiddenRows->getRangeData(nRow, aData))
++            // failed to get range data.
++            return ::std::numeric_limits<SCROW>::max();
++
++        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))
++            return ::std::numeric_limits<SCROW>::max();
++
++        if (!mpHiddenRows->getRangeData(nRow, aData))
++            // failed to get range data.
++            return ::std::numeric_limits<SCROW>::max();
++
++        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 += pRowHeight->SumValues(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();
++}
++
+ void ScTable::SyncColRowFlags()
+ {
+     using ::sal::static_int_cast;
+ 
+-    // For now, we only need to sync the manual breaks.
+-
++    // 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);
+@@ -439,6 +714,48 @@ void ScTable::SyncColRowFlags()
+               itr != itrEnd; ++itr)
+             pColFlags[*itr] |= CR_MANUALBREAK;
+     }
++
++    // Hidden flags.
++    pRowFlags->AndValue(0, MAXROW, static_int_cast<BYTE>(~CR_HIDDEN));
++    for (SCCOL i = 0; i <= MAXCOL; ++i)
++        pColFlags[i] &= static_int_cast<BYTE>(~CR_HIDDEN);
++
++    {
++        // row hidden flags.
++
++        SCROW nRow = 0;
++        ScFlatBoolRowSegments::RangeData aData;
++        while (nRow <= MAXROW)
++        {
++            if (!mpHiddenRows->getRangeData(nRow, aData))
++                break;
++
++            if (aData.mbValue)
++                pRowFlags->OrValue(nRow, aData.mnRow2, static_int_cast<BYTE>(CR_HIDDEN));
++
++            nRow = aData.mnRow2 + 1;
++        }
++    }
++
++    {
++        // column hidden flags.
++
++        SCCOL nCol = 0;
++        ScFlatBoolColSegments::RangeData aData;
++        while (nCol <= MAXCOL)
++        {
++            if (!mpHiddenCols->getRangeData(nCol, aData))
++                break;
++
++            if (aData.mbValue)
++            {
++                for (SCCOL i = nCol; i <= aData.mnCol2; ++i)
++                    pColFlags[i] |= CR_HIDDEN;
++            }
++
++            nCol = aData.mnCol2 + 1;
++        }
++    }
+ }
+ 
+ void ScTable::SetPageSize( const Size& rSize )
+diff --git sc/source/core/tool/chartarr.cxx sc/source/core/tool/chartarr.cxx
+index b6163ba..ed34d0b 100644
+--- sc/source/core/tool/chartarr.cxx
++++ sc/source/core/tool/chartarr.cxx
+@@ -47,6 +47,9 @@
+ #include "cell.hxx"
+ #include "docoptio.hxx"
+ 
++#include <vector>
++
++using ::std::vector;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -166,11 +169,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 )
+ 	{
+@@ -184,17 +193,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)
+@@ -208,13 +233,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);
+ 	}
+ 
+ 		//
+@@ -237,7 +262,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();
+@@ -247,8 +272,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 );
+ 							}
+ 						}
+@@ -280,13 +305,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;
+ 			}
+@@ -306,14 +331,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);
+ 
+@@ -349,11 +374,6 @@ ScMemChart* ScChartArray::CreateMemChartSingle()
+ //        SetExtraStrings( *pMemChart );
+ 	}
+ 
+-		//	Aufraeumen
+-
+-	delete[] pRows;
+-	delete[] pCols;
+-
+ 	return pMemChart;
+ }
+ 
+diff --git sc/source/filter/excel/xetable.cxx sc/source/filter/excel/xetable.cxx
+index 8d27d2d..e289bf4 100644
+--- sc/source/filter/excel/xetable.cxx
++++ sc/source/filter/excel/xetable.cxx
+@@ -1604,8 +1604,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 );
+@@ -1830,7 +1829,7 @@ 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 );
+ 
+diff --git sc/source/filter/excel/xlescher.cxx sc/source/filter/excel/xlescher.cxx
+index 2109a0a..3a3a3c7 100644
+--- sc/source/filter/excel/xlescher.cxx
++++ sc/source/filter/excel/xlescher.cxx
+@@ -143,21 +143,38 @@ void lclGetRowFromY(
+     // 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 )
++#if 1
++    bool bFound = false;
++    for (SCROW nRow = static_cast<SCROW>(nXclStartRow); nRow <= MAXROW; ++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 = static_cast<sal_uInt16>(MAXROW);
++#else
++//  ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
++//          rDoc.GetRowFlagsArray( nScTab), static_cast<SCROW>(nXclStartRow),
++//          MAXROW, CR_HIDDEN, 0, rDoc.GetRowHeightArray( nScTab));
++//  for ( ; aIter; ++aIter )
++//  {
++//      nRowH = *aIter;
++//      if( rnStartH + nRowH > nTwipsY )
++//      {
++//          rnXclRow = static_cast< sal_uInt16 >( aIter.GetPos() );
++//          break;
++//      }
++//      rnStartH += nRowH;
++//  }
++//  if (!aIter)
++//      rnXclRow = static_cast< sal_uInt16 >( aIter.GetIterEnd() );  // down to the bottom..
++#endif
+     rnOffset = static_cast< sal_uInt16 >( nRowH ? ((nTwipsY - rnStartH) * 256.0 / nRowH + 0.5) : 0 );
+ }
+ 
+diff --git sc/source/filter/html/htmlexp.cxx sc/source/filter/html/htmlexp.cxx
+index 75f1515..581c01e 100644
+--- sc/source/filter/html/htmlexp.cxx
++++ sc/source/filter/html/htmlexp.cxx
+@@ -749,7 +749,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 += ' ') += sHTML_O_cols) += '=') += ByteString::CreateFromInt32( nColCnt );
+@@ -770,7 +770,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;
+@@ -785,14 +785,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
+             }
+@@ -801,7 +799,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 sc/source/filter/lotus/lotimpop.cxx sc/source/filter/lotus/lotimpop.cxx
+index b21b74a..75fa516 100644
+--- sc/source/filter/lotus/lotimpop.cxx
++++ sc/source/filter/lotus/lotimpop.cxx
+@@ -183,8 +183,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 sc/source/filter/lotus/op.cxx sc/source/filter/lotus/op.cxx
+index f2dc8af..dcfd4cb 100644
+--- sc/source/filter/lotus/op.cxx
++++ sc/source/filter/lotus/op.cxx
+@@ -229,7 +229,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;
+ 	}
+ 
+@@ -338,7 +338,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 sc/source/filter/rtf/expbase.cxx sc/source/filter/rtf/expbase.cxx
+index d8d39da..9b3a722 100644
+--- sc/source/filter/rtf/expbase.cxx
++++ sc/source/filter/rtf/expbase.cxx
+@@ -78,16 +78,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 sc/source/filter/starcalc/scflt.cxx sc/source/filter/starcalc/scflt.cxx
+index 371ef48..1a634d3 100644
+--- sc/source/filter/starcalc/scflt.cxx
++++ sc/source/filter/starcalc/scflt.cxx
+@@ -1551,14 +1551,12 @@ void Sc10Import::LoadTables()
+ 			rStream >> DataValue;
+ 			if (DataValue != 0)
+ 			{
+-				BYTE nFlags = 0;
+ 				bool bPageBreak   = ((DataValue & crfSoftBreak) == crfSoftBreak);
+ 				bool bManualBreak = ((DataValue & crfHardBreak) == crfHardBreak);
+-				if ((DataValue & crfHidden) == crfHidden)
+-					nFlags |= CR_HIDDEN;
++				bool bHidden = ((DataValue & crfHidden) == crfHidden);
+ 				for (SCCOL k = static_cast<SCCOL>(DataStart); k <= static_cast<SCCOL>(DataEnd); k++) 
+-                {    
+-                    pDoc->SetColFlags(k, static_cast<SCTAB> (TabNo), nFlags);
++                {
++					pDoc->SetColHidden(k, k, static_cast<SCTAB>(TabNo), bHidden);
+                     pDoc->SetColBreak(k, static_cast<SCTAB> (TabNo), bPageBreak, bManualBreak);
+                 }
+ 			}
+@@ -1603,14 +1601,12 @@ void Sc10Import::LoadTables()
+ 			rStream >> DataValue;
+ 			if (DataValue != 0)
+ 			{
+-				BYTE nFlags = 0;
+ 				bool bPageBreak   = ((DataValue & crfSoftBreak) == crfSoftBreak);
+ 				bool bManualBreak = ((DataValue & crfHardBreak) == crfHardBreak);
+-				if ((DataValue & crfHidden) == crfHidden)
+-					nFlags |= CR_HIDDEN;
++                bool bHidden      = ((DataValue & crfHidden) == crfHidden);
+                 for (SCROW l = static_cast<SCROW>(DataStart); l <= static_cast<SCROW>(DataEnd); l++) 
+                 {    
+-                    pDoc->SetRowFlags(l, static_cast<SCTAB> (TabNo), nFlags);
++                    pDoc->SetRowHidden(l, l, static_cast<SCTAB> (TabNo), bHidden);
+                     pDoc->SetRowBreak(l, static_cast<SCTAB> (TabNo), bPageBreak, bManualBreak);
+                 }
+ 			}
+diff --git sc/source/filter/xlsx/xlsx-xetable.cxx sc/source/filter/xlsx/xlsx-xetable.cxx
+index e8a208d..92dd71e 100644
+--- sc/source/filter/xlsx/xlsx-xetable.cxx
++++ sc/source/filter/xlsx/xlsx-xetable.cxx
+@@ -1541,8 +1541,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 );
+@@ -1767,7 +1766,7 @@ 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 );
+ 
+diff --git sc/source/filter/xlsx/xlsx-xlescher.cxx sc/source/filter/xlsx/xlsx-xlescher.cxx
+index 2109a0a..3a3a3c7 100644
+--- sc/source/filter/xlsx/xlsx-xlescher.cxx
++++ sc/source/filter/xlsx/xlsx-xlescher.cxx
+@@ -143,21 +143,38 @@ void lclGetRowFromY(
+     // 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 )
++#if 1
++    bool bFound = false;
++    for (SCROW nRow = static_cast<SCROW>(nXclStartRow); nRow <= MAXROW; ++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 = static_cast<sal_uInt16>(MAXROW);
++#else
++//  ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
++//          rDoc.GetRowFlagsArray( nScTab), static_cast<SCROW>(nXclStartRow),
++//          MAXROW, CR_HIDDEN, 0, rDoc.GetRowHeightArray( nScTab));
++//  for ( ; aIter; ++aIter )
++//  {
++//      nRowH = *aIter;
++//      if( rnStartH + nRowH > nTwipsY )
++//      {
++//          rnXclRow = static_cast< sal_uInt16 >( aIter.GetPos() );
++//          break;
++//      }
++//      rnStartH += nRowH;
++//  }
++//  if (!aIter)
++//      rnXclRow = static_cast< sal_uInt16 >( aIter.GetIterEnd() );  // down to the bottom..
++#endif
+     rnOffset = static_cast< sal_uInt16 >( nRowH ? ((nTwipsY - rnStartH) * 256.0 / nRowH + 0.5) : 0 );
+ }
+ 
+diff --git sc/source/filter/xml/XMLTableShapeResizer.cxx sc/source/filter/xml/XMLTableShapeResizer.cxx
+index 719ab55..43f10db 100644
+--- sc/source/filter/xml/XMLTableShapeResizer.cxx
++++ sc/source/filter/xml/XMLTableShapeResizer.cxx
+@@ -231,6 +231,8 @@ void ScMyShapeResizer::ResizeShapes()
+     								{
+     									Rectangle aRec = pDoc->GetMMRect(static_cast<SCCOL>(aItr->aStartCell.Column), static_cast<SCROW>(aItr->aStartCell.Row),
+     										static_cast<SCCOL>(aItr->aStartCell.Column), static_cast<SCROW>(aItr->aStartCell.Row), aItr->aStartCell.Sheet);
++                                        fprintf(stdout, "ScMyShapeResizer::ResizeShapes:   cell rect (%ld,%ld) - (%ld,%ld)\n",
++                                                aRec.Left(), aRec.Top(), aRec.Right(), aRec.Bottom());
+     									awt::Point aPoint(aItr->xShape->getPosition());
+     									awt::Size aSize(aItr->xShape->getSize());
+                                         if (pDoc->IsNegativePage(static_cast<SCTAB>(nOldSheet)))
+diff --git sc/source/ui/Accessibility/AccessibleCellBase.cxx sc/source/ui/Accessibility/AccessibleCellBase.cxx
+index 320f211..819fe2a 100644
+--- sc/source/ui/Accessibility/AccessibleCellBase.cxx
++++ sc/source/ui/Accessibility/AccessibleCellBase.cxx
+@@ -97,8 +97,12 @@ sal_Bool SAL_CALL ScAccessibleCellBase::isVisible(  )
+ 	{
+ 		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))
++        SCCOL nLastCol;
++        SCROW nLastRow;
++        bool bColHidden = mpDoc->ColHidden(maCellAddress.Col(), maCellAddress.Tab(), nLastCol);
++        bool bRowHidden = mpDoc->RowHidden(maCellAddress.Row(), maCellAddress.Tab(), nLastRow);
++		if (bColHidden || ((nColFlags & CR_FILTERED) == CR_FILTERED) ||
++			bRowHidden || ((nRowFlags & CR_FILTERED) == CR_FILTERED))
+ 			bVisible = sal_False;
+ 	}
+ 	return bVisible;
+diff --git sc/source/ui/app/transobj.cxx sc/source/ui/app/transobj.cxx
+index 1620f95..6542dbc 100644
+--- sc/source/ui/app/transobj.cxx
++++ sc/source/ui/app/transobj.cxx
+@@ -604,25 +604,24 @@ void ScTransferObj::InitDocShell()
+ 		//	widths / heights
+ 		//	(must be copied before CopyFromClip, for drawing objects)
+ 
+-		SCCOL nCol;
++		SCCOL nCol, nLastCol;
+ 		SCROW nRow;
+ 		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
+ 			{
+diff --git sc/source/ui/docshell/docfunc.cxx sc/source/ui/docshell/docfunc.cxx
+index 1477025..d76e73d 100644
+--- sc/source/ui/docshell/docfunc.cxx
++++ sc/source/ui/docshell/docfunc.cxx
+@@ -2927,7 +2927,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 );
+ 					}
+ 				}
+@@ -2962,8 +2964,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;
+ 
+diff --git sc/source/ui/undo/undoblk3.cxx sc/source/ui/undo/undoblk3.cxx
+index 8d9baaf..753a1a1 100644
+--- sc/source/ui/undo/undoblk3.cxx
++++ sc/source/ui/undo/undoblk3.cxx
+@@ -1081,17 +1081,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 sc/source/ui/unoobj/cellsuno.cxx sc/source/ui/unoobj/cellsuno.cxx
+index 53f0d52..59b88f4 100644
+--- sc/source/ui/unoobj/cellsuno.cxx
++++ sc/source/ui/unoobj/cellsuno.cxx
+@@ -3448,18 +3448,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
+-        {
+-			if (*aIter & CR_HIDDEN)
+-                aMarkData.SetMultiMarkArea( ScRange( 0, aIter.GetRangeStart(),
+-                            nTab, MAXCOL, aIter.GetRangeEnd(), nTab ), FALSE );
+-        } while (aIter.NextRange());
++			nCol = nLastCol + 1;
++		}
++
++		SCROW nRow = 0, nLastRow;
++		while (nRow <= MAXROW)
++		{
++			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 );
+@@ -8950,8 +8957,9 @@ void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertyMap* pMap,
+ 		}
+ 		else if ( pMap->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 ( pMap->nWID == SC_WID_UNO_OWIDTH )
+ 		{
+@@ -9110,8 +9118,9 @@ void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertyMap* pMap,
+ 		}
+ 		else if ( pMap->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 ( pMap->nWID == SC_WID_UNO_CELLFILT )
+ 		{
+diff --git sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/chart2uno.cxx
+index 9decd68..a3e9919 100644
+--- sc/source/ui/unoobj/chart2uno.cxx
++++ sc/source/ui/unoobj/chart2uno.cxx
+@@ -2885,14 +2885,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 sc/source/ui/unoobj/docuno.cxx sc/source/ui/unoobj/docuno.cxx
+index 9fac1bb..88b143d 100644
+--- sc/source/ui/unoobj/docuno.cxx
++++ sc/source/ui/unoobj/docuno.cxx
+@@ -2660,7 +2660,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 ) )
+@@ -2909,7 +2910,8 @@ 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 ) )
+diff --git sc/source/ui/view/colrowba.cxx sc/source/ui/view/colrowba.cxx
+index 3107d46..b42726e 100644
+--- sc/source/ui/view/colrowba.cxx
++++ sc/source/ui/view/colrowba.cxx
+@@ -101,7 +101,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() );
+@@ -267,7 +268,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 sc/source/ui/view/drawutil.cxx sc/source/ui/view/drawutil.cxx
+index dc19949..feba7a3 100644
+--- sc/source/ui/view/drawutil.cxx
++++ sc/source/ui/view/drawutil.cxx
+@@ -69,15 +69,22 @@ 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 )
+-	{
+-		USHORT nHeight = *aIter;
+-		nTwipsY += (long) nHeight;
+-		nPixelY += ScViewData::ToPixel( nHeight, nPPTY );
+-	}
++#if 1
++    // TODO: Check this.
++    sal_uInt32 nHeight = pDoc->GetTotalRowHeight(nStartRow, nEndRow-1, nTab);
++    nTwipsY += static_cast<long>(nHeight);
++    nPixelY += ScViewData::ToPixel(nHeight, nPPTY);
++#else
++//  ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
++//          pDoc->GetRowFlagsArray( nTab), nStartRow, nEndRow-1, CR_HIDDEN, 0,
++//          pDoc->GetRowHeightArray( nTab));
++//  for ( ; aIter; ++aIter )
++//  {
++//  	USHORT nHeight = *aIter;
++//  	nTwipsY += (long) nHeight;
++//  	nPixelY += ScViewData::ToPixel( nHeight, nPPTY );
++//  }
++#endif
+ 
+ 	MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY );
+ 	Point aPixelLog = pDev->PixelToLogic( Point( nPixelX,nPixelY ), aHMMMode );
+diff --git sc/source/ui/view/drawview.cxx sc/source/ui/view/drawview.cxx
+index 4abdd01..1d4d08d 100644
+--- sc/source/ui/view/drawview.cxx
++++ sc/source/ui/view/drawview.cxx
+@@ -197,6 +197,9 @@ void ScDrawView::AddCustomHdl()
+ 
+ 			ScTabView* pView = pViewData->GetView();
+ 			ScAddress aScAddress(nCol, nRow, nTab);
++            String aStr;
++            aScAddress.Format(aStr, SCA_ABS);
++            fprintf(stdout, "ScDrawView::AddCustomHdl:   anchor cell = '%s'\n", rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
+ 			pView->CreateAnchorHandles(aHdl, aScAddress);
+ 		}
+ 	}
+diff --git sc/source/ui/view/gridwin.cxx sc/source/ui/view/gridwin.cxx
+index ea8d3d0..3b9ed08 100644
+--- sc/source/ui/view/gridwin.cxx
++++ sc/source/ui/view/gridwin.cxx
+@@ -4616,18 +4616,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)
+@@ -4635,8 +4634,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)
+diff --git sc/source/ui/view/gridwin4.cxx sc/source/ui/view/gridwin4.cxx
+index 2e88791..54789c0 100644
+--- sc/source/ui/view/gridwin4.cxx
++++ sc/source/ui/view/gridwin4.cxx
+@@ -1377,7 +1377,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 )
+@@ -1580,7 +1580,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 );
+@@ -1767,7 +1767,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 sc/source/ui/view/olinewin.cxx sc/source/ui/view/olinewin.cxx
+index a9ed1ae..4a99450 100644
+--- sc/source/ui/view/olinewin.cxx
++++ sc/source/ui/view/olinewin.cxx
+@@ -186,10 +186,9 @@ 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
+diff --git sc/source/ui/view/output.cxx sc/source/ui/view/output.cxx
+index 1585791..4c20625 100644
+--- sc/source/ui/view/output.cxx
++++ sc/source/ui/view/output.cxx
+@@ -387,8 +387,9 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage )
+ 				{
+ 					BYTE nDocFl = pDoc->GetColFlags( nCol, nTab );
+                     nBreak = pDoc->HasColBreak(nCol, nTab);
++                    bool bHidden = pDoc->ColHidden(nCol, nTab);
+ 
+-                    if ( nBreak || !(nDocFl & CR_HIDDEN) )
++                    if ( nBreak || !bHidden )
+ 						break;
+ 					++nCol;
+ 				}
+@@ -507,7 +508,7 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage )
+                 for (SCROW i = nYplus1; i <= MAXROW; ++i)
+                 {
+                     nBreak = pDoc->HasRowBreak(i, nTab);
+-                    bool bHidden = (pDoc->GetRowFlags(i, nTab) & CR_HIDDEN);
++                    bool bHidden = pDoc->RowHidden(i, nTab);
+                     if (nBreak || !bHidden)
+                         break;
+                 }
+@@ -654,7 +655,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 sc/source/ui/view/output2.cxx sc/source/ui/view/output2.cxx
+index d01a843..11c57b2 100644
+--- sc/source/ui/view/output2.cxx
++++ sc/source/ui/view/output2.cxx
+@@ -697,7 +697,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;
+ 
+@@ -721,7 +721,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;
+ 
+@@ -729,8 +729,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;
+@@ -2016,7 +2016,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 sc/source/ui/view/prevloc.cxx sc/source/ui/view/prevloc.cxx
+index ad2731c..e05b380 100644
+--- sc/source/ui/view/prevloc.cxx
++++ sc/source/ui/view/prevloc.cxx
+@@ -602,11 +602,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 )
+@@ -623,7 +623,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);
+@@ -642,7 +642,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);
+@@ -670,11 +670,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 )
+ 	{
+@@ -688,59 +686,101 @@ void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPrev
+ 		}
+ 		if ( bHasRepRows )
+ 		{
+-			long nPosY = 0;
+-            ScCompressedArrayIterator< SCROW, BYTE> aIter(
+-                    pDoc->GetRowFlagsArray( nTab), nRepeatRowStart,
+-                    nRepeatRowEnd);
+-            do
++#if 1
++            long nPosY = 0;
++            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->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;
++            }
++#else
++//  		long nPosY = 0;
++//          ScCompressedArrayIterator< SCROW, BYTE> aIter(
++//                  pDoc->GetRowFlagsArray( nTab), nRepeatRowStart,
++//                  nRepeatRowEnd);
++//          do
++//          {
++//              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());
++#endif
+ 		}
+ 		if ( bHasMainRows )
+ 		{
+-			long nPosY = 0;
+-            ScCompressedArrayIterator< SCROW, BYTE> aIter(
+-                    pDoc->GetRowFlagsArray( nTab), nMainRowStart,
+-                    nMainRowEnd);
+-            do
++#if 1
++            long nPosY = 0;
++            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->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;
++            }
++#else
++//  		long nPosY = 0;
++//          ScCompressedArrayIterator< SCROW, BYTE> aIter(
++//                  pDoc->GetRowFlagsArray( nTab), nMainRowStart,
++//                  nMainRowEnd);
++//          do
++//          {
++//              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());
++#endif
+ 		}
+ 		rInfo.SetRowInfo( nRowCount, pRowInfo );
+ 	}
+diff --git sc/source/ui/view/printfun.cxx sc/source/ui/view/printfun.cxx
+index 2ddaa99..2a76a83 100644
+--- sc/source/ui/view/printfun.cxx
++++ sc/source/ui/view/printfun.cxx
+@@ -3072,9 +3072,10 @@ void ScPrintFunc::CalcPages()				// berechnet aPageRect und Seiten aus nZoom
+ 	nTotalY = 0;
+ 
+ 	BOOL bVisCol = FALSE;
++	SCCOL nLastCol = -1;
+ 	for (SCCOL i=nStartCol; i<=nEndCol; i++)
+ 	{
+-		BYTE nFlags = pDoc->GetColFlags(i,nPrintTab);
++		bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol);
+         bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE);
+         if ( i>nStartCol && bVisCol && bPageBreak )
+ 		{
+@@ -3082,7 +3083,7 @@ void ScPrintFunc::CalcPages()				// berechnet aPageRect und Seiten aus nZoom
+ 			++nPagesX;
+ 			bVisCol = FALSE;
+ 		}
+-		if (!(nFlags & CR_HIDDEN))
++		if (!bHidden)
+ 			bVisCol = TRUE;
+ 	}
+ 	if (bVisCol)	// auch am Ende keine leeren Seiten
+@@ -3093,38 +3094,35 @@ void ScPrintFunc::CalcPages()				// berechnet aPageRect und Seiten aus nZoom
+ 
+ 	BOOL bVisRow = FALSE;
+ 	SCROW nPageStartRow = nStartRow;
+-    ScCompressedArrayIterator< SCROW, BYTE> aIter( pDoc->GetRowFlagsArray(
+-                nPrintTab), nStartRow, nEndRow);
+-    do
+-    {
+-		BYTE nFlags = *aIter;
+-        SCROW nRangeEnd = aIter.GetRangeEnd();
+-        for (SCROW j=aIter.GetRangeStart(); j<=nRangeEnd; ++j)
+-        {
+-            bool bPageBreak = (pDoc->HasRowBreak(j, nPrintTab) & BREAK_PAGE);
+-            if ( j>nStartRow && bVisRow && bPageBreak )
+-            {
+-                pPageEndY[nTotalY] = j-1;
+-                ++nTotalY;
++	for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
++	{
++		bool bPageBreak = (pDoc->HasRowBreak(nRow, nPrintTab) & BREAK_PAGE);
++		if (nRow > nStartRow && bVisRow && bPageBreak )
++		{
++			pPageEndY[nTotalY] = nRow-1;
++			++nTotalY;
+ 
+-                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;
+-                }
++			if ( !aTableParam.bSkipEmpty ||
++					!pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) )
++			{
++				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;
++			}
+ 
+-                nPageStartRow = j;
+-                bVisRow = FALSE;
+-            }
+-            if (!(nFlags & CR_HIDDEN))
+-                bVisRow = TRUE;
+-        }
+-    } while (aIter.NextRange());
++			nPageStartRow = nRow;
++			bVisRow = FALSE;
++		}
++		SCROW nLastRow = -1;
++		if (!pDoc->RowHidden(nRow, nPrintTab, nLastRow))
++			bVisRow = TRUE;
++		else
++			// skip all hidden rows.
++			nRow = nLastRow;
++	}
+ 
+ 	if (bVisRow)
+ 	{
+diff --git sc/source/ui/view/select.cxx sc/source/ui/view/select.cxx
+index e4bb262..b04ca46 100644
+--- sc/source/ui/view/select.cxx
++++ sc/source/ui/view/select.cxx
+@@ -346,12 +346,13 @@ 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);
++//              pDoc->GetRowFlagsArray( nTab).GetLastForCondition( 0, nPosY, CR_HIDDEN, 0); // what's this trying to do here?
++                nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
+                 if (!ValidRow(nPosY))
+                     nPosY = -1;
+             }
+@@ -560,7 +561,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 );
+ 			}
+@@ -575,8 +576,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 sc/source/ui/view/tabview.cxx sc/source/ui/view/tabview.cxx
+index 83fa37b..320ff65 100644
+--- sc/source/ui/view/tabview.cxx
++++ sc/source/ui/view/tabview.cxx
+@@ -1438,7 +1438,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 );
+ 
+@@ -1527,7 +1527,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;
+ 
+diff --git sc/source/ui/view/tabview2.cxx sc/source/ui/view/tabview2.cxx
+index 7dec6f2..8eb43cd 100644
+--- sc/source/ui/view/tabview2.cxx
++++ sc/source/ui/view/tabview2.cxx
+@@ -890,31 +890,58 @@ 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)
+-	{
++#if 1
++    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);
+ 			if (nBlockY > nWindowY)
+ 				return FALSE;
+ 		}
+-	}
+-    aIter.NewLimits( nStartRow, nEndRow);
+-    for ( ; aIter; ++aIter)
+-	{
+-		USHORT nRowTwips = *aIter;
++    }
++    for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
++    {
++        USHORT nRowTwips = pDoc->GetRowHeight(nRow, nTab);
+ 		if (nRowTwips)
+ 		{
+ 			nBlockY += (long)(nRowTwips * fScaleY);
+ 			if (nBlockY > nWindowY)
+ 				return FALSE;
+ 		}
+-	}
++    }
++#else
++//  ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
++//          pDoc->GetRowFlagsArray( nTab), 0, nFixPosY-1, CR_HIDDEN, 0,
++//          pDoc->GetRowHeightArray( nTab));
++//  for ( ; aIter; ++aIter)
++//  {
++//  	//	for frozen panes, add both parts
++//  	USHORT nRowTwips = *aIter;
++//  	if (nRowTwips)
++//  	{
++//  		nBlockY += (long)(nRowTwips * fScaleY);
++//  		if (nBlockY > nWindowY)
++//  			return FALSE;
++//  	}
++//  }
++//  aIter.NewLimits( nStartRow, nEndRow);
++//  for ( ; aIter; ++aIter)
++//  {
++//  	USHORT nRowTwips = *aIter;
++//  	if (nRowTwips)
++//  	{
++//  		nBlockY += (long)(nRowTwips * fScaleY);
++//  		if (nBlockY > nWindowY)
++//  			return FALSE;
++//  	}
++//  }
++#endif
+ 
+ 	return TRUE;
+ }
+diff --git sc/source/ui/view/tabview3.cxx sc/source/ui/view/tabview3.cxx
+index d8392e5..5c305c7 100644
+--- sc/source/ui/view/tabview3.cxx
++++ sc/source/ui/view/tabview3.cxx
+@@ -1007,8 +1007,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)
+@@ -1049,8 +1049,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)
+@@ -2089,17 +2089,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)
+@@ -2107,7 +2108,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 sc/source/ui/view/viewdata.cxx sc/source/ui/view/viewdata.cxx
+index be4d659..0295dbe 100644
+--- sc/source/ui/view/viewdata.cxx
++++ sc/source/ui/view/viewdata.cxx
+@@ -1603,7 +1603,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
+@@ -1715,7 +1715,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
+@@ -1778,11 +1778,9 @@ 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 );
++
++        nOutHeight += ToPixel(
++            pDoc->GetTotalRowHeight(nY, nY+nCountY-1, nTabNo), nPPTY);
+ 
+ 		rSizeXPix = nOutWidth;
+ 		rSizeYPix = nOutHeight;
+diff --git sc/source/ui/view/viewfunc.cxx sc/source/ui/view/viewfunc.cxx
+index d8e28ce..ca18a77 100644
+--- sc/source/ui/view/viewfunc.cxx
++++ sc/source/ui/view/viewfunc.cxx
+@@ -2244,28 +2244,40 @@ 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
++#if 1
++                            for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
+                             {
+-                                BYTE nOld = *aIter;
+-                                if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) )
+-                                {
+-                                    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.
+-                                }
+-                            } while (aIter.NextRange());
++                                if (pDoc->RowHidden(nRow, nTab))
++                                    continue;
++
++                                BYTE nOld = pDoc->GetRowFlags(nRow, nTab);
++                                if (nOld & CR_MANUALSIZE)
++                                    pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
++                            }
++#else
++//                          ScCompressedArrayIterator< SCROW, BYTE> aIter(
++//                                  pDoc->GetRowFlagsArray( nTab), nStartNo,
++//                                  nEndNo);
++//                          do
++//                          {
++//                              BYTE nOld = *aIter;
++//                              if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) )
++//                              {
++//                                  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.
++//                              }
++//                          } while (aIter.NextRange());
++#endif
+ 						}
+ 
+ 						double nPPTX = GetViewData()->GetPPTX();
+@@ -2307,8 +2319,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;
+ 


More information about the ooo-build-commit mailing list