diff options
author | Eike Rathke [er] <erAck@sun.com> | 2010-07-16 15:58:36 +0200 |
---|---|---|
committer | Eike Rathke [er] <erAck@sun.com> | 2010-07-16 15:58:36 +0200 |
commit | 98cdf3324314ebf7ee69605af2a8fc28be092528 (patch) | |
tree | d65a24b2527fbfa240a7bf5323fd3f929876a6ed | |
parent | d5d147219645771f745d46db17d6fd2c31347aae (diff) |
calc56: #i113139# various performance improvements for 1MB rows, especially with large hidden segments
-rw-r--r-- | sc/inc/document.hxx | 1 | ||||
-rw-r--r-- | sc/inc/table.hxx | 46 | ||||
-rw-r--r-- | sc/source/core/data/documen3.cxx | 83 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 54 | ||||
-rw-r--r-- | sc/source/core/data/fillinfo.cxx | 20 | ||||
-rw-r--r-- | sc/source/core/data/markdata.cxx | 60 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 38 | ||||
-rw-r--r-- | sc/source/core/data/table5.cxx | 52 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLStylesExportHelper.cxx | 27 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLStylesExportHelper.hxx | 1 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlexprt.cxx | 7 | ||||
-rw-r--r-- | sc/source/ui/inc/viewdata.hxx | 18 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin4.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/view/output.cxx | 14 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 161 |
16 files changed, 398 insertions, 198 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index f7ae5e63f165..304a9d1df0f7 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1276,6 +1276,7 @@ public: SC_DLLPUBLIC USHORT GetColWidth( SCCOL nCol, SCTAB nTab ) const; SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero = true ) const; + SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero = true ) const; SC_DLLPUBLIC ULONG GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const; SCROW GetRowForHeight( SCTAB nTab, ULONG nHeight ) const; ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, double fScale ) const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 78e5875b6879..5f42a2f37247 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -628,12 +628,12 @@ public: // nPPT fuer Test auf Veraenderung void SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual ); - USHORT GetColWidth( SCCOL nCol ); - SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCROW* pStartRow = NULL, SCROW* pEndRow = NULL, bool bHiddenAsZero = true ); - ULONG GetRowHeight( SCROW nStartRow, SCROW nEndRow ); - ULONG GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ); - ULONG GetColOffset( SCCOL nCol ); - ULONG GetRowOffset( SCROW nRow ); + USHORT GetColWidth( SCCOL nCol ) const; + SC_DLLPUBLIC USHORT GetRowHeight( SCROW nRow, SCROW* pStartRow = NULL, SCROW* pEndRow = NULL, bool bHiddenAsZero = true ) 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; /** * Get the last row such that the height of row 0 to the end row is as @@ -643,7 +643,7 @@ public: * * @return SCROW last row of the range within specified height. */ - SCROW GetRowForHeight(ULONG nHeight); + SCROW GetRowForHeight(ULONG nHeight) const; USHORT GetOriginalWidth( SCCOL nCol ) const; USHORT GetOriginalHeight( SCROW nRow ) const; @@ -711,33 +711,33 @@ public: ::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); + bool RowHidden(SCROW nRow, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL) const; + bool RowHidden(SCROW nRow, SCROW& rLastRow) const; + bool HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const; + bool ColHidden(SCCOL nCol, SCCOL& rLastCol) const; + bool ColHidden(SCCOL nCol, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL) const; void SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden); void SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden); void CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol); void CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow); void CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset); - SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow); - SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow); - SCROW CountVisibleRows(SCROW nStartRow, SCROW nEndRow); - sal_uInt32 GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow); + SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const; + SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const; + SCROW CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const; + sal_uInt32 GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) const; - SCCOLROW LastHiddenColRow(SCCOLROW nPos, bool bCol); + SCCOLROW LastHiddenColRow(SCCOLROW nPos, bool bCol) const; - bool RowFiltered(SCROW nRow, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL); - bool ColFiltered(SCCOL nCol, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL); - bool HasFilteredRows(SCROW nStartRow, SCROW nEndRow); + bool RowFiltered(SCROW nRow, SCROW* pFirstRow = NULL, SCROW* pLastRow = NULL) const; + bool ColFiltered(SCCOL nCol, SCCOL* pFirstCol = NULL, SCCOL* pLastCol = NULL) const; + bool HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const; void CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol); void CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow); void SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered); void SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered); - SCROW FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow); - SCROW LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow); - SCROW CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow); + SCROW FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const; + SCROW LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const; + SCROW CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const; void SyncColRowFlags(); diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 1861988d78aa..29f59352695d 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -1546,6 +1546,48 @@ void ScDocument::ResetEmbedded() aEmbedRange = ScRange(); } + +/** Similar to ScViewData::AddPixelsWhile(), but add height twips and only + while result is less than nStopTwips. + */ +void lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable ) +{ + SCROW nRow = rPosY; + bool bStop = false; + while (rTwips < nStopTwips && nRow <= nEndRow && !bStop) + { + SCROW nHeightEndRow; + USHORT nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow); + if (nHeightEndRow > nEndRow) + nHeightEndRow = nEndRow; + if (!nHeight) + nRow = nHeightEndRow + 1; + else + { + SCROW nRows = nHeightEndRow - nRow + 1; + sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows; + if (nAdd + rTwips >= nStopTwips) + { + sal_Int64 nDiff = nAdd + rTwips - nStopTwips; + nRows -= nDiff / nHeight; + nAdd = nHeight * nRows; + // We're looking for a value that satisfies loop condition. + if (nAdd + rTwips >= nStopTwips) + { + --nRows; + nAdd -= nHeight; + } + bStop = true; + } + rTwips += static_cast<long>(nAdd); + nRow += nRows; + } + } + if (nRow > rPosY) + --nRow; + rPosY = nRow; +} + ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect ) { ScTable* pTable = pTab[nTab]; @@ -1602,43 +1644,18 @@ ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect ) nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS); SCROW nY1 = 0; - 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; - } - else - bEnd = TRUE; - } - if (!bEnd) - nY1 = MAXROW; // all hidden down to the bottom + // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2) + lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable); + if (nY1 < MAXROW) + ++nY1; // original loop ended on last evaluated +1 unless that was MAXROW nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS); SCROW nY2 = nY1; - bEnd = FALSE; - 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; - } - else - bEnd = TRUE; - } - if (!bEnd) - nY2 = MAXROW; // all hidden down to the bottom + // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips) + lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable); + if (nY2 < MAXROW) + ++nY2; // original loop ended on last evaluated +1 unless that was MAXROW return ScRange( nX1,nY1,nTab, nX2,nY2,nTab ); } diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index eee87317c258..a4f8833f6caa 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -3174,7 +3174,16 @@ USHORT ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) co { if ( ValidTab(nTab) && pTab[nTab] ) return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero ); - DBG_ERROR("Falsche Tabellennummer"); + DBG_ERROR("Wrong sheet number"); + return 0; +} + + +USHORT ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const +{ + if ( ValidTab(nTab) && pTab[nTab] ) + return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero ); + DBG_ERROR("Wrong sheet number"); return 0; } @@ -3697,24 +3706,35 @@ SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const { - if ( ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetRowFlagsArray() && pTab[nTab]->mpRowHeights ) - { - BYTE nStartFlags = pTab[nTab]->GetRowFlags(nStart); - USHORT nStartHeight = pTab[nTab]->GetOriginalHeight(nStart); - for (SCROW nRow = nStart + 1; nRow <= MAXROW; nRow++) + const ScBitMaskCompressedArray< SCROW, BYTE> * pRowFlagsArray; + if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) && + pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows ) + { + size_t nIndex; // ignored + SCROW nFlagsEndRow; + SCROW nHiddenEndRow; + SCROW nHeightEndRow; + BYTE nFlags; + bool bHidden; + USHORT nHeight; + BYTE nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow); + bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow); + USHORT nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false); + SCROW nRow; + while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW) { - size_t nIndex; // ignored - SCROW nFlagsEndRow; - SCROW nHeightEndRow; - BYTE nFlags = pTab[nTab]->GetRowFlagsArray()->GetValue( nRow, nIndex, nFlagsEndRow ); - USHORT nHeight = pTab[nTab]->GetRowHeight(nRow, NULL, &nHeightEndRow); - if (((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || - ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || - (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || - (!bCareManualSize && ((nStartHeight != nHeight)))) + if (nFlagsEndRow < nRow) + nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow); + if (nHiddenEndRow < nRow) + bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow); + if (nHeightEndRow < nRow) + nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false); + if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || + ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || + (bStartHidden != bHidden) || + (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || + (!bCareManualSize && ((nStartHeight != nHeight)))) return nRow; - - nRow = std::min( nFlagsEndRow, nHeightEndRow ); } return MAXROW+1; } diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 8418cb3c3a25..99da4979a1b6 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -219,6 +219,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX nArrY=0; SCROW nYExtra = nY2+1; + USHORT nDocHeight = ScGlobal::nStdRowHeight; + SCROW nDocHeightEndRow = -1; for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++) { if (nSignedY >= 0) @@ -226,11 +228,13 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX else nY = MAXROW+1; // ungueltig - USHORT nDocHeight; - if (ValidRow(nY)) - nDocHeight = GetRowHeight( nY, nTab ); - else - nDocHeight = ScGlobal::nStdRowHeight; + if (nY > nDocHeightEndRow) + { + if (ValidRow(nY)) + nDocHeight = GetRowHeight( nY, nTab, NULL, &nDocHeightEndRow ); + else + nDocHeight = ScGlobal::nStdRowHeight; + } if ( nArrY==0 || nDocHeight || nY > MAXROW ) { @@ -384,11 +388,15 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX nArrY = 1; SCSIZE nUIndex; + bool bHiddenRow = true; + SCROW nHiddenEndRow = -1; (void) pThisCol->Search( nY1, nUIndex ); while ( nUIndex < pThisCol->nCount && (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 ) { - if ( !RowHidden( nThisRow,nTab ) ) + if (nThisRow > nHiddenEndRow) + bHiddenRow = RowHidden( nThisRow, nTab, nHiddenEndRow); + if ( !bHiddenRow ) { while ( pRowInfo[nArrY].nRowNo < nThisRow ) ++nArrY; diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx index baf3f4cf3f95..d6ea90f1cacf 100644 --- a/sc/source/core/data/markdata.cxx +++ b/sc/source/core/data/markdata.cxx @@ -429,18 +429,28 @@ SCCOLROW ScMarkData::GetMarkColumnRanges( SCCOLROW* pRanges ) if (!bMultiMarked) return 0; - DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0"); + DBG_ASSERT(pMultiSel, "bMultiMarked, but pMultiSel == 0"); + + const SCCOLROW nMultiStart = aMultiRange.aStart.Col(); + const SCCOLROW nMultiEnd = aMultiRange.aEnd.Col(); + if (nMultiStart == 0 && nMultiEnd == MAXCOL) + { + // One or more entire rows. + pRanges[0] = 0; + pRanges[1] = MAXCOL; + return 1; + } SCCOLROW nRangeCnt = 0; - SCCOLROW nStart = 0; - while (nStart<=MAXCOL) + SCCOLROW nStart = nMultiStart; + while (nStart <= nMultiEnd) { - while (nStart<MAXCOL && !pMultiSel[nStart].HasMarks()) + while (nStart < nMultiEnd && !pMultiSel[nStart].HasMarks()) ++nStart; if (pMultiSel[nStart].HasMarks()) { SCCOLROW nEnd = nStart; - while (nEnd<MAXCOL && pMultiSel[nEnd].HasMarks()) + while (nEnd < nMultiEnd && pMultiSel[nEnd].HasMarks()) ++nEnd; if (!pMultiSel[nEnd].HasMarks()) --nEnd; @@ -450,7 +460,7 @@ SCCOLROW ScMarkData::GetMarkColumnRanges( SCCOLROW* pRanges ) nStart = nEnd+1; } else - nStart = MAXCOL+1; + nStart = nMultiEnd+1; } return nRangeCnt; @@ -464,37 +474,51 @@ SCCOLROW ScMarkData::GetMarkRowRanges( SCCOLROW* pRanges ) if (!bMultiMarked) return 0; - DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0"); + DBG_ASSERT(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - // Welche Zeilen sind markiert? + // Which rows are marked? - BOOL* bRowMarked = new BOOL[MAXROW+1]; + // Optimized to not loop over MAXCOL*MAXROW as worst case, i.e. Ctrl+A + + const SCCOLROW nMultiStart = aMultiRange.aStart.Row(); + const SCCOLROW nMultiEnd = aMultiRange.aEnd.Row(); + + BOOL* bRowMarked = new BOOL[MAXROWCOUNT]; + memset( bRowMarked, 0, sizeof(BOOL) * MAXROWCOUNT); SCROW nRow; SCCOL nCol; - for (nRow=0; nRow<=MAXROW; nRow++) - bRowMarked[nRow] = FALSE; SCROW nTop, nBottom; - for (nCol=0; nCol<=MAXCOL; nCol++) + for (nCol = aMultiRange.aStart.Col(); nCol <= aMultiRange.aEnd.Col(); ++nCol) { ScMarkArrayIter aMarkIter( &pMultiSel[nCol] ); while (aMarkIter.Next( nTop, nBottom )) for (nRow=nTop; nRow<=nBottom; nRow++) bRowMarked[nRow] = TRUE; + if (nTop == nMultiStart && nBottom == nMultiEnd) + break; // for, all relevant rows marked + } + + if (nTop == nMultiStart && nBottom == nMultiEnd) + { + pRanges[0] = nTop; + pRanges[1] = nBottom; + delete[] bRowMarked; + return 1; } - // zu Bereichen zusammenfassen + // Combine to ranges of rows. SCCOLROW nRangeCnt = 0; - SCCOLROW nStart = 0; - while (nStart<=MAXROW) + SCCOLROW nStart = nMultiStart; + while (nStart <= nMultiEnd) { - while (nStart<MAXROW && !bRowMarked[nStart]) + while (nStart < nMultiEnd && !bRowMarked[nStart]) ++nStart; if (bRowMarked[nStart]) { SCCOLROW nEnd = nStart; - while (nEnd<MAXROW && bRowMarked[nEnd]) + while (nEnd < nMultiEnd && bRowMarked[nEnd]) ++nEnd; if (!bRowMarked[nEnd]) --nEnd; @@ -504,7 +528,7 @@ SCCOLROW ScMarkData::GetMarkRowRanges( SCCOLROW* pRanges ) nStart = nEnd+1; } else - nStart = MAXROW+1; + nStart = nMultiEnd+1; } delete[] bRowMarked; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 9bd5b031fde5..b8bd9037c900 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2241,7 +2241,7 @@ void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, BOOL bManual ) } -USHORT ScTable::GetColWidth( SCCOL nCol ) +USHORT ScTable::GetColWidth( SCCOL nCol ) const { DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer"); @@ -2315,34 +2315,50 @@ USHORT ScTable::GetCommonWidth( SCCOL nEndCol ) } -USHORT ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) +USHORT ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const { - DBG_ASSERT(VALIDROW(nRow),"Falsche Zeilennummer"); + DBG_ASSERT(VALIDROW(nRow),"Invalid row number"); if (VALIDROW(nRow) && mpRowHeights) { - if (bHiddenAsZero && RowHidden(nRow)) + if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow)) return 0; else { ScFlatUInt16RowSegments::RangeData aData; if (!mpRowHeights->getRangeData(nRow, aData)) + { + if (pStartRow) + *pStartRow = nRow; + if (pEndRow) + *pEndRow = nRow; // TODO: What should we return in case the search fails? return 0; + } + // If bHiddenAsZero, pStartRow and pEndRow were initialized to + // boundaries of a non-hidden segment. Assume that the previous and + // next segment are hidden then and limit the current height + // segment. if (pStartRow) - *pStartRow = aData.mnRow1; + *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1); if (pEndRow) - *pEndRow = aData.mnRow2; + *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2); return aData.mnValue; } } else + { + if (pStartRow) + *pStartRow = nRow; + if (pEndRow) + *pEndRow = nRow; return (USHORT) ScGlobal::nStdRowHeight; + } } -ULONG ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) +ULONG ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const { DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); @@ -2368,7 +2384,7 @@ ULONG ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) } -ULONG ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) +ULONG ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const { DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); @@ -3036,7 +3052,7 @@ void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos } -ULONG ScTable::GetRowOffset( SCROW nRow ) +ULONG ScTable::GetRowOffset( SCROW nRow ) const { ULONG n = 0; if ( mpHiddenRows && mpRowHeights ) @@ -3059,7 +3075,7 @@ ULONG ScTable::GetRowOffset( SCROW nRow ) return n; } -SCROW ScTable::GetRowForHeight(ULONG nHeight) +SCROW ScTable::GetRowForHeight(ULONG nHeight) const { sal_uInt32 nSum = 0; @@ -3086,7 +3102,7 @@ SCROW ScTable::GetRowForHeight(ULONG nHeight) } -ULONG ScTable::GetColOffset( SCCOL nCol ) +ULONG ScTable::GetColOffset( SCCOL nCol ) const { ULONG n = 0; if ( pColWidth ) diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx index 2635b5821e4f..e7ee96367785 100644 --- a/sc/source/core/data/table5.cxx +++ b/sc/source/core/data/table5.cxx @@ -355,7 +355,7 @@ bool ScTable::HasRowPageBreak(SCROW nRow) const if (!ValidRow(nRow)) return false; - return maRowPageBreaks.count(nRow) > 0; + return maRowPageBreaks.find(nRow) != maRowPageBreaks.end(); } bool ScTable::HasColPageBreak(SCCOL nCol) const @@ -363,7 +363,7 @@ bool ScTable::HasColPageBreak(SCCOL nCol) const if (!ValidCol(nCol)) return false; - return maColPageBreaks.count(nCol) > 0; + return maColPageBreaks.find(nCol) != maColPageBreaks.end(); } bool ScTable::HasRowManualBreak(SCROW nRow) const @@ -371,7 +371,7 @@ bool ScTable::HasRowManualBreak(SCROW nRow) const if (!ValidRow(nRow)) return false; - return maRowManualBreaks.count(nRow) > 0; + return maRowManualBreaks.find(nRow) != maRowManualBreaks.end(); } bool ScTable::HasColManualBreak(SCCOL nCol) const @@ -379,7 +379,7 @@ bool ScTable::HasColManualBreak(SCCOL nCol) const if (!ValidCol(nCol)) return false; - return (maColManualBreaks.count(nCol) > 0); + return maColManualBreaks.find(nCol) != maColManualBreaks.end(); } SCROW ScTable::GetNextManualBreak(SCROW nRow) const @@ -483,15 +483,27 @@ Sequence<TablePageBreakData> ScTable::GetRowBreakData() const return aSeq; } -bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) +bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const { if (!ValidRow(nRow)) + { + if (pFirstRow) + *pFirstRow = nRow; + if (pLastRow) + *pLastRow = nRow; return true; + } ScFlatBoolRowSegments::RangeData aData; if (!mpHiddenRows->getRangeData(nRow, aData)) + { // search failed. + if (pFirstRow) + *pFirstRow = nRow; + if (pLastRow) + *pLastRow = nRow; return true; + } if (pFirstRow) *pFirstRow = aData.mnRow1; @@ -502,7 +514,7 @@ bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) } -bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) +bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) const { rLastRow = nRow; if (!ValidRow(nRow)) @@ -517,7 +529,7 @@ bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) return aData.mbValue; } -bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) +bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nStartRow; while (nRow <= nEndRow) @@ -532,7 +544,7 @@ bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) return false; } -bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) +bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) const { rLastCol = nCol; if (!ValidCol(nCol)) @@ -546,7 +558,7 @@ bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) return aData.mbValue; } -bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) +bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const { if (!ValidCol(nCol)) return true; @@ -627,7 +639,7 @@ void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, } } -SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nStartRow; ScFlatBoolRowSegments::RangeData aData; @@ -650,7 +662,7 @@ SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) return ::std::numeric_limits<SCROW>::max(); } -SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nEndRow; ScFlatBoolRowSegments::RangeData aData; @@ -673,7 +685,7 @@ SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) return ::std::numeric_limits<SCROW>::max(); } -SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const { SCROW nCount = 0; SCROW nRow = nStartRow; @@ -694,7 +706,7 @@ SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) return nCount; } -sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) +sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) const { sal_uInt32 nHeight = 0; SCROW nRow = nStartRow; @@ -717,7 +729,7 @@ sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) return nHeight; } -SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) +SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const { if (bCol) { @@ -741,7 +753,7 @@ SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) return ::std::numeric_limits<SCCOLROW>::max(); } -bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) +bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const { if (!ValidRow(nRow)) return false; @@ -759,7 +771,7 @@ bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) return aData.mbValue; } -bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) +bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const { if (!ValidCol(nCol)) return false; @@ -777,7 +789,7 @@ bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) return aData.mbValue; } -bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) +bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nStartRow; while (nRow <= nEndRow) @@ -837,7 +849,7 @@ void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered) mpFilteredCols->setFalse(nStartCol, nEndCol); } -SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nStartRow; ScFlatBoolRowSegments::RangeData aData; @@ -860,7 +872,7 @@ SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) return ::std::numeric_limits<SCROW>::max(); } -SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const { SCROW nRow = nEndRow; ScFlatBoolRowSegments::RangeData aData; @@ -883,7 +895,7 @@ SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) return ::std::numeric_limits<SCROW>::max(); } -SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) +SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const { SCROW nCount = 0; SCROW nRow = nStartRow; diff --git a/sc/source/filter/xml/XMLStylesExportHelper.cxx b/sc/source/filter/xml/XMLStylesExportHelper.cxx index f8bafa32f205..66f3ea613a3a 100644 --- a/sc/source/filter/xml/XMLStylesExportHelper.cxx +++ b/sc/source/filter/xml/XMLStylesExportHelper.cxx @@ -1234,10 +1234,31 @@ void ScRowStyles::AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nFie const sal_Int32 nStringIndex) { DBG_ASSERT(static_cast<size_t>(nTable) < aTables.size(), "wrong table"); - DBG_ASSERT(aTables[nTable].size() >= static_cast<sal_uInt32>(nField), "wrong field"); - if (aTables[nTable].size() == static_cast<sal_uInt32>(nField)) + DBG_ASSERT(aTables[nTable].size() >= static_cast<size_t>(nField), "wrong field"); + if (aTables[nTable].size() == static_cast<size_t>(nField)) aTables[nTable].push_back(nStringIndex); - aTables[nTable][nField] = nStringIndex; + else + aTables[nTable][nField] = nStringIndex; +} + +void ScRowStyles::AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nStartField, + const sal_Int32 nStringIndex, const sal_Int32 nEndField) +{ + DBG_ASSERT( nStartField <= nEndField, "bad field range"); + DBG_ASSERT(static_cast<size_t>(nTable) < aTables.size(), "wrong table"); + DBG_ASSERT(aTables[nTable].size() >= static_cast<size_t>(nStartField), "wrong field"); + ScMysalInt32Vec& rTable = aTables[nTable]; + size_t nSize = rTable.size(); + if (nSize == static_cast<size_t>(nStartField)) + rTable.insert( rTable.end(), static_cast<size_t>(nEndField - nStartField + 1), nStringIndex); + else + { + size_t nField = static_cast<size_t>(nStartField); + for ( ; nField < nSize && nField <= static_cast<size_t>(nEndField); ++nField) + rTable[nField] = nStringIndex; + if (nField <= static_cast<size_t>(nEndField)) + rTable.insert( rTable.end(), static_cast<size_t>(nEndField - nField + 1), nStringIndex); + } } rtl::OUString* ScRowStyles::GetStyleName(const sal_Int32 nTable, const sal_Int32 nField) diff --git a/sc/source/filter/xml/XMLStylesExportHelper.hxx b/sc/source/filter/xml/XMLStylesExportHelper.hxx index 34672aeef96e..79b19b7ce9ab 100644 --- a/sc/source/filter/xml/XMLStylesExportHelper.hxx +++ b/sc/source/filter/xml/XMLStylesExportHelper.hxx @@ -286,6 +286,7 @@ public: virtual void AddNewTable(const sal_Int32 nTable, const sal_Int32 nFields); sal_Int32 GetStyleNameIndex(const sal_Int32 nTable, const sal_Int32 nField); void AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nField, const sal_Int32 nStringIndex); + void AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nStartField, const sal_Int32 nStringIndex, const sal_Int32 nEndField); virtual rtl::OUString* GetStyleName(const sal_Int32 nTable, const sal_Int32 nField); }; diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 0563f6430063..b34abb29443c 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -2576,14 +2576,13 @@ void ScXMLExport::_ExportAutoStyles() } sal_Int32 nOld(nRow); nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow), false); - for (sal_Int32 i = nOld + 1; i < nRow; ++i) - pRowStyles->AddFieldStyleName(nTable, i, nIndex); + if (nRow > nOld + 1) + pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1); } if (aCellAddress.EndRow > nRows) { sal_Int32 nIndex(pRowStyles->GetStyleNameIndex(nTable, nRows)); - for (sal_Int32 i = nRows + 1; i <= aCellAddress.EndRow; ++i) - pRowStyles->AddFieldStyleName(nTable, i, nIndex); + pRowStyles->AddFieldStyleName(nTable, nRows + 1, nIndex, aCellAddress.EndRow); } } } diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index 106d196a8175..fb9c674a4488 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -482,6 +482,24 @@ public: BOOL IsSelCtrlMouseClick() { return bSelCtrlMouseClick; } static inline long ToPixel( USHORT nTwips, double nFactor ); + + /** while (rScrY <= nEndPixels && rPosY <= nEndRow) add pixels of row + heights converted with nPPTY to rScrY, optimized for row height + segments. Upon return rPosY is the last row evaluated <= nEndRow, rScrY + may be > nEndPixels! + */ + static void AddPixelsWhile( long & rScrY, long nEndPixels, + SCROW & rPosY, SCROW nEndRow, double nPPTY, + const ScDocument * pDoc, SCTAB nTabNo ); + + /** while (rScrY <= nEndPixels && rPosY >= nStartRow) add pixels of row + heights converted with nPPTY to rScrY, optimized for row height + segments. Upon return rPosY is the last row evaluated >= nStartRow, + rScrY may be > nEndPixels! + */ + static void AddPixelsWhileBackward( long & rScrY, long nEndPixels, + SCROW & rPosY, SCROW nStartRow, double nPPTY, + const ScDocument * pDoc, SCTAB nTabNo ); }; diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index c284045c5b11..3fb2c74a9954 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -592,7 +592,7 @@ ScUndoDeleteMulti::ScUndoDeleteMulti( ScDocShell* pNewDocShell, __EXPORT ScUndoDeleteMulti::~ScUndoDeleteMulti() { - delete pRanges; + delete [] pRanges; } String __EXPORT ScUndoDeleteMulti::GetComment() const diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 6bf27387314a..ba73fbf00269 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -401,17 +401,13 @@ void __EXPORT ScGridWindow::Paint( const Rectangle& rRect ) nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX ); } - long nScrY = ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY ); - while ( nScrY <= aPixRect.Top() && nY1 < MAXROW ) - { - ++nY1; - nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY ); - } + long nScrY = 0; + ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab); SCROW nY2 = nY1; - while ( nScrY <= aPixRect.Bottom() && nY2 < MAXROW ) + if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW) { ++nY2; - nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY2, nTab ), nPPTY ); + ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab); } Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index 961572fc0185..7b27ddf3f8cc 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -489,6 +489,8 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) // Horizontale Linien // + bool bHiddenRow = true; + SCROW nHiddenEndRow = -1; nPosY = nScrY; for (nArrY=1; nArrY+1<nArrCount; nArrY++) { @@ -503,9 +505,17 @@ void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage ) { for (SCROW i = nYplus1; i <= MAXROW; ++i) { + if (i > nHiddenEndRow) + bHiddenRow = pDoc->RowHidden(i, nTab, nHiddenEndRow); + /* TODO: optimize the row break thing for large hidden + * segments where HasRowBreak() has to be called + * nevertheless for each row, as a row break is drawn also + * for hidden rows, above them. This needed to be done only + * once per hidden segment, maybe giving manual breaks + * priority. Something like GetNextRowBreak() and + * GetNextManualRowBreak(). */ nBreak = pDoc->HasRowBreak(i, nTab); - bool bHidden = pDoc->RowHidden(i, nTab); - if (nBreak || !bHidden) + if (!bHiddenRow || nBreak) break; } diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index c034836d4d4a..38d5aa60eaeb 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1696,50 +1696,32 @@ SCROW ScViewData::CellsAtY( SCsROW nPosY, SCsROW nDir, ScVSplitPos eWhichY, USHO if (pView) ((ScViewData*)this)->aScrSize.Height() = pView->GetGridHeight(eWhichY); - SCROW nY; - USHORT nScrPosY = 0; - if (nScrSizeY == SC_SIZE_NONE) nScrSizeY = (USHORT) aScrSize.Height(); - if (nDir==1) - nY = nPosY; // vorwaerts - else - nY = nPosY-1; // rueckwaerts - - BOOL bOut = FALSE; - for ( ; nScrPosY<=nScrSizeY && !bOut; nY+=nDir ) - { - SCsROW nRowNo = nY; - if ( nRowNo < 0 || nRowNo > MAXROW ) - bOut = TRUE; - else - { - USHORT nTSize = pDoc->GetRowHeight( nRowNo, nTabNo ); - if (nTSize) - { - long nSizeYPix = ToPixel( nTSize, nPPTY ); - nScrPosY = sal::static_int_cast<USHORT>( nScrPosY + (USHORT) nSizeYPix ); - } - else if ( nDir == 1 && nRowNo < MAXROW ) - { - // skip multiple hidden rows (forward only for now) - SCROW nNext = pDoc->FirstVisibleRow(nRowNo + 1, MAXROW, nTabNo); - if ( nNext > MAXROW ) - { - // same behavior as without the optimization: set bOut with nY=MAXROW+1 - nY = MAXROW+1; - bOut = TRUE; - } - else - nY = nNext - 1; // +=nDir advances to next visible row - } - } - } + SCROW nY; if (nDir==1) + { + // forward + nY = nPosY; + long nScrPosY = 0; + AddPixelsWhile( nScrPosY, nScrSizeY, nY, MAXROW, nPPTY, pDoc, nTabNo); + // Original loop ended on last evaluated +1 or if that was MAXROW even + // on MAXROW+2. + nY += (nY == MAXROW ? 2 : 1); nY -= nPosY; + } else + { + // backward + nY = nPosY-1; + long nScrPosY = 0; + AddPixelsWhileBackward( nScrPosY, nScrSizeY, nY, 0, nPPTY, pDoc, nTabNo); + // Original loop ended on last evaluated -1 or if that was 0 even on + // -2. + nY -= (nY == 0 ? 2 : 1); nY = (nPosY-1)-nY; + } if (nY>0) --nY; return nY; @@ -1855,16 +1837,10 @@ BOOL ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich, } if (nClickY > 0) - { - while ( rPosY<=MAXROW && nClickY >= nScrY ) - { - nScrY += ToPixel( pDoc->GetRowHeight( rPosY, nTabNo ), nPPTY ); - ++rPosY; - } - --rPosY; - } + AddPixelsWhile( nScrY, nClickY, rPosY, MAXROW, nPPTY, pDoc, nTabNo ); else { + /* TODO: could need some "SubPixelsWhileBackward" method */ while ( rPosY>0 && nClickY < nScrY ) { --rPosY; @@ -1984,20 +1960,24 @@ void ScViewData::SetPosY( ScVSplitPos eWhich, SCROW nNewPosY ) SCROW nOldPosY = pThisTab->nPosY[eWhich]; long nTPosY = pThisTab->nTPosY[eWhich]; long nPixPosY = pThisTab->nPixPosY[eWhich]; - SCROW i; + SCROW i, nHeightEndRow; if ( nNewPosY > nOldPosY ) for ( i=nOldPosY; i<nNewPosY; i++ ) { - long nThis = pDoc->GetRowHeight( i,nTabNo ); - nTPosY -= nThis; - nPixPosY -= ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY); + long nThis = pDoc->GetRowHeight( i, nTabNo, NULL, &nHeightEndRow ); + SCROW nRows = std::min( nNewPosY, nHeightEndRow + 1) - i; + i = nHeightEndRow; + nTPosY -= nThis * nRows; + nPixPosY -= ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY) * nRows; } else for ( i=nNewPosY; i<nOldPosY; i++ ) { - long nThis = pDoc->GetRowHeight( i,nTabNo ); - nTPosY += nThis; - nPixPosY += ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY); + long nThis = pDoc->GetRowHeight( i, nTabNo, NULL, &nHeightEndRow ); + SCROW nRows = std::min( nOldPosY, nHeightEndRow + 1) - i; + i = nHeightEndRow; + nTPosY += nThis * nRows; + nPixPosY += ToPixel(sal::static_int_cast<USHORT>(nThis), nPPTY) * nRows; } pThisTab->nPosY[eWhich] = nNewPosY; @@ -3118,5 +3098,82 @@ ScAddress ScViewData::GetCurPos() const } +// static +void ScViewData::AddPixelsWhile( long & rScrY, long nEndPixels, SCROW & rPosY, + SCROW nEndRow, double nPPTY, const ScDocument * pDoc, SCTAB nTabNo ) +{ + SCROW nRow = rPosY; + while (rScrY <= nEndPixels && nRow <= nEndRow) + { + SCROW nHeightEndRow; + USHORT nHeight = pDoc->GetRowHeight( nRow, nTabNo, NULL, &nHeightEndRow); + if (nHeightEndRow > nEndRow) + nHeightEndRow = nEndRow; + if (!nHeight) + nRow = nHeightEndRow + 1; + else + { + SCROW nRows = nHeightEndRow - nRow + 1; + sal_Int64 nPixel = ToPixel( nHeight, nPPTY); + sal_Int64 nAdd = nPixel * nRows; + if (nAdd + rScrY > nEndPixels) + { + sal_Int64 nDiff = rScrY + nAdd - nEndPixels; + nRows -= nDiff / nPixel; + nAdd = nPixel * nRows; + // We're looking for a value that satisfies loop condition. + if (nAdd + rScrY <= nEndPixels) + { + ++nRows; + nAdd += nPixel; + } + } + rScrY += static_cast<long>(nAdd); + nRow += nRows; + } + } + if (nRow > rPosY) + --nRow; + rPosY = nRow; +} +// static +void ScViewData::AddPixelsWhileBackward( long & rScrY, long nEndPixels, + SCROW & rPosY, SCROW nStartRow, double nPPTY, const ScDocument * pDoc, + SCTAB nTabNo ) +{ + SCROW nRow = rPosY; + while (rScrY <= nEndPixels && nRow >= nStartRow) + { + SCROW nHeightStartRow; + USHORT nHeight = pDoc->GetRowHeight( nRow, nTabNo, &nHeightStartRow, NULL); + if (nHeightStartRow < nStartRow) + nHeightStartRow = nStartRow; + if (!nHeight) + nRow = nHeightStartRow - 1; + else + { + SCROW nRows = nRow - nHeightStartRow + 1; + sal_Int64 nPixel = ToPixel( nHeight, nPPTY); + sal_Int64 nAdd = nPixel * nRows; + if (nAdd + rScrY > nEndPixels) + { + sal_Int64 nDiff = nAdd + rScrY - nEndPixels; + nRows -= nDiff / nPixel; + nAdd = nPixel * nRows; + // We're looking for a value that satisfies loop condition. + if (nAdd + rScrY <= nEndPixels) + { + ++nRows; + nAdd += nPixel; + } + } + rScrY += static_cast<long>(nAdd); + nRow -= nRows; + } + } + if (nRow < rPosY) + ++nRow; + rPosY = nRow; +} |