desktop/inc/lib/init.hxx | 43 ++ editeng/source/editeng/editeng.cxx | 1 sc/CppunitTest_sc_tiledrendering.mk | 1 sc/Library_sc.mk | 1 sc/inc/document.hxx | 2 sc/inc/fillinfo.hxx | 54 +++ sc/inc/markarr.hxx | 1 sc/inc/markdata.hxx | 24 + sc/inc/markmulti.hxx | 84 +++++ sc/inc/segmenttree.hxx | 2 sc/qa/unit/tiledrendering/tiledrendering.cxx | 55 +++ sc/source/core/data/column.cxx | 52 +-- sc/source/core/data/column3.cxx | 2 sc/source/core/data/documen2.cxx | 34 +- sc/source/core/data/fillinfo.cxx | 414 +++++++++++++-------------- sc/source/core/data/markarr.cxx | 11 sc/source/core/data/markdata.cxx | 371 +++++++++++++++++++----- sc/source/core/data/markmulti.cxx | 348 ++++++++++++++++++++++ sc/source/core/data/segmenttree.cxx | 2 sc/source/core/data/table1.cxx | 11 sc/source/ui/inc/viewdata.hxx | 8 sc/source/ui/unoobj/docuno.cxx | 3 sc/source/ui/view/formatsh.cxx | 11 sc/source/ui/view/gridwin4.cxx | 93 +++++- sc/source/ui/view/tabview3.cxx | 42 ++ sc/source/ui/view/viewdata.cxx | 2 sw/source/core/crsr/viscrs.cxx | 3 sw/source/uibase/docvw/SidebarTxtControl.cxx | 5 sw/source/uibase/docvw/SidebarWin.cxx | 6 vcl/headless/svpinst.cxx | 61 +++ vcl/inc/headless/svpinst.hxx | 9 31 files changed, 1375 insertions(+), 381 deletions(-)
New commits: commit 71deb1dacf61e5f9a1d95e14453885178d5a6f53 Author: Andras Timar <[email protected]> Date: Wed Jun 1 23:24:01 2016 +0200 Linux x86 build fix Change-Id: I34a393745265b8daca832c7df896bea090bb2554 (cherry picked from commit 72d1b6663a340e745af42aaf94541e4c1309b434) diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 3bc285a..24f45db 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -1061,7 +1061,7 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice, firstCol = (firstCol >= 0 ? firstCol : nStartCol); lastCol = (lastCol >= 0 ? lastCol : nEndCol); - auto capacity = std::min(nEndRow + 3, 1002); + auto capacity = std::min(nEndRow + 3, sal_Int32(1002)); ScTableInfo aTabInfo(capacity); pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, lastCol, lastRow, nTab, fPPTX, fPPTY, false, false, NULL); commit aff7d0ff0fc241e7d062cae4a9f6b47f365a1aea Author: Ashod Nakashian <[email protected]> Date: Wed Jun 1 10:07:59 2016 -0400 LOK: calc tile rendering Change-Id: I122922ac18a652dbbce01932eaaad92ded45098d Reviewed-on: https://gerrit.libreoffice.org/25782 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit bd63faaedc6d268ca1f4552aa6d18fc74e23809c) diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index f949ef6..3bc285a 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -1061,7 +1061,8 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice, firstCol = (firstCol >= 0 ? firstCol : nStartCol); lastCol = (lastCol >= 0 ? lastCol : nEndCol); - ScTableInfo aTabInfo(nEndRow + 3); + auto capacity = std::min(nEndRow + 3, 1002); + ScTableInfo aTabInfo(capacity); pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, lastCol, lastRow, nTab, fPPTX, fPPTY, false, false, NULL); ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, commit 69ef944d9a2d868a596699658f28121edd674f23 Author: Ashod Nakashian <[email protected]> Date: Sat May 28 10:20:10 2016 -0400 bccu#1845 - Calc tile rendering very slow For some reason trying to draw exactly the region of the tile results in black tiles. That is, when the top rows and left columns are not drawn, black tiles show. This patch still reduces the time to render a given tile by limiting the bottom-most row and right-most column to the max necessary. For large tabs rendering the first few 100 rows is very fast (<100ms at most). More work is necessary to reduce drawing time for large sheets (when rendering tiles at the bottom). Still, even those slow bottom-rows are now faster with this patch. Currently the slowest function by far is ScGridWindow::DrawContent. Change-Id: I6e88c7b3a1c483bf43bfcfb38f4b41ffc08a9744 Reviewed-on: https://gerrit.libreoffice.org/25586 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 56e290acca0f51f1aa888f9e7787cfcdc6bb8fd9) diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 923316a..f949ef6 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -970,8 +970,10 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice, // page break zoom, and aLogicMode in ScViewData pViewData->SetZoom(aFracX, aFracY, true); - double fTilePosXPixel = static_cast<double>(nTilePosX) * nOutputWidth / nTileWidth; - double fTilePosYPixel = static_cast<double>(nTilePosY) * nOutputHeight / nTileHeight; + const double fTilePosXPixel = static_cast<double>(nTilePosX) * nOutputWidth / nTileWidth; + const double fTilePosYPixel = static_cast<double>(nTilePosY) * nOutputHeight / nTileHeight; + const double fTileBottomPixel = static_cast<double>(nTilePosY + nTileHeight) * nOutputHeight / nTileHeight; + const double fTileRightPixel = static_cast<double>(nTilePosX + nTileWidth) * nOutputWidth / nTileWidth; SCTAB nTab = pViewData->GetTabNo(); ScDocument* pDoc = pViewData->GetDocument(); @@ -982,14 +984,88 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice, // size of the document including drawings, charts, etc. pDoc->GetTiledRenderingArea(nTab, nEndCol, nEndRow); - double fPPTX = pViewData->GetPPTX(); - double fPPTY = pViewData->GetPPTY(); + const double fPPTX = pViewData->GetPPTX(); + const double fPPTY = pViewData->GetPPTY(); - ScTableInfo aTabInfo(nEndRow + 2); - pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, nEndCol, nEndRow, nTab, fPPTX, fPPTY, false, false, NULL); + // Calculate the tile's first and last rows. + SCROW firstRow = -1; + SCROW lastRow = -1; + double fTopOffsetPixel = 0; + + // Find the first and last rows to paint this tile. + sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight; + SCROW nDocHeightEndRow = -1; + for (SCROW nY = nStartRow; nY <= nEndRow; ++nY) + { + if (nY > nDocHeightEndRow) + { + if (ValidRow(nY)) + nDocHeight = pDoc->GetRowHeight( nY, nTab, nullptr, &nDocHeightEndRow ); + else + nDocHeight = ScGlobal::nStdRowHeight; + } + + auto rowHeight = static_cast<sal_uInt16>(nDocHeight * fPPTY); + if (fTopOffsetPixel + rowHeight >= fTilePosYPixel) + { + if (firstRow < 0) + { + firstRow = nY; + } + else if (fTopOffsetPixel + rowHeight > fTileBottomPixel) + { + lastRow = nY; + break; + } + } + + fTopOffsetPixel += rowHeight; + } + + firstRow = (firstRow >= 0 ? firstRow : nStartRow); + lastRow = (lastRow >= 0 ? lastRow : nEndRow); + + // Find the first and last cols to paint this tile. + SCCOL firstCol = -1; + SCCOL lastCol = -1; + double fLeftOffsetPixel = 0; + for (SCCOL nArrCol=nStartCol+3; nArrCol<=nEndCol+2; ++nArrCol) + { + SCCOL nX = nArrCol-1; + if ( ValidCol(nX) ) + { + if (!pDoc->ColHidden(nX, nTab)) + { + sal_uInt16 nColWidth = (sal_uInt16) (pDoc->GetColWidth( nX, nTab ) * fPPTX); + if (!nColWidth) + nColWidth = 1; + + if (fLeftOffsetPixel + nColWidth >= fTilePosXPixel) + { + if (firstCol < 0) + { + firstCol = nX; + } + else if (fLeftOffsetPixel + nColWidth > fTileRightPixel) + { + lastCol = nX; + break; + } + } + + fLeftOffsetPixel += nColWidth; + } + } + } + + firstCol = (firstCol >= 0 ? firstCol : nStartCol); + lastCol = (lastCol >= 0 ? lastCol : nEndCol); + + ScTableInfo aTabInfo(nEndRow + 3); + pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, lastCol, lastRow, nTab, fPPTX, fPPTY, false, false, NULL); ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, - -fTilePosXPixel, -fTilePosYPixel, nStartCol, nStartRow, nEndCol, nEndRow, + -fTilePosXPixel, -fTilePosYPixel, nStartCol, firstRow, lastCol, lastRow, fPPTX, fPPTY); // setup the SdrPage so that drawinglayer works correctly commit 25146c5f86369f4d77265bc34f66f65b76459ad1 Author: Ashod Nakashian <[email protected]> Date: Wed May 25 23:28:04 2016 -0400 widen table-info capacity and count to SCSIZE Change-Id: Id659978e71c7027bc1c58f0bc276da38e1ada4ba Reviewed-on: https://gerrit.libreoffice.org/25488 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 04a18136b186753cd303057155141957c9a90500) diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index 419f1c9..3b42dff 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -195,11 +195,11 @@ struct ScTableInfo { svx::frame::Array maArray; RowInfo* mpRowInfo; - sal_uInt16 mnArrCount; - sal_uInt16 mnArrCapacity; + SCSIZE mnArrCount; + SCSIZE mnArrCapacity; bool mbPageMode; - explicit ScTableInfo(const sal_uInt16 capacity = 1024); + explicit ScTableInfo(const SCSIZE capacity = 1024); ~ScTableInfo(); ScTableInfo(const ScTableInfo&) = delete; const ScTableInfo& operator=(const ScTableInfo&) = delete; diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 3235c30..cd39a36 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -1126,7 +1126,7 @@ void ScDocument::FillInfo( rArray.MirrorSelfX( true, false ); } -ScTableInfo::ScTableInfo(const sal_uInt16 capacity) +ScTableInfo::ScTableInfo(const SCSIZE capacity) : mpRowInfo(new RowInfo[capacity]) , mnArrCount(0) , mnArrCapacity(capacity) @@ -1137,7 +1137,7 @@ ScTableInfo::ScTableInfo(const sal_uInt16 capacity) ScTableInfo::~ScTableInfo() { - for( sal_uInt16 nIdx = 0; nIdx < mnArrCapacity; ++nIdx ) + for( SCSIZE nIdx = 0; nIdx < mnArrCapacity; ++nIdx ) delete [] mpRowInfo[ nIdx ].pCellInfo; delete [] mpRowInfo; } commit 372a984116506aad0af8502889c05f8dc6b42fe2 Author: Ashod Nakashian <[email protected]> Date: Tue May 24 22:01:38 2016 -0400 lok don't supress start/end when there is selection Change-Id: I347d90cfa5432e18b9a0091ab575c0833538d941 Reviewed-on: https://gerrit.libreoffice.org/25422 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit bc304ac66e56e6040bb810cfd23efbc35235eccb) diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index e25b334..50344ee 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -364,8 +364,7 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) // being edited. if (comphelper::LibreOfficeKit::isActive() && !pView->GetTextEditObject()) { - // If pSelectionRectangles is set, we're just collecting the text selections -> don't emit start/end. - if (!empty() && !pSelectionRectangles) + if (!empty()) { // The selection may be a complex polygon, emit the logical // start/end cursor rectangle of the selection as separate commit 255b41e622a89ff4bddd799839e0478b4fdfb14a Author: Ashod Nakashian <[email protected]> Date: Sat May 21 23:10:35 2016 -0400 sc lok bccu#1610 - Tiles not rendering in large spreadsheets Variable max info rows instead of hard-coded allows for collecting info on more rows. FillInfo, however, is extremely slow for large row count (a few thousand) and needs improving. Reviewed-on: https://gerrit.libreoffice.org/25293 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 4c338a328d6be0450bfdcb08876abfd149cb80ca) Change-Id: Ib0e475513bc3ba98fff66a5b9d405aeba1057331 diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index d35bb8e..419f1c9 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -195,10 +195,11 @@ struct ScTableInfo { svx::frame::Array maArray; RowInfo* mpRowInfo; - sal_uInt16 mnArrCount; + sal_uInt16 mnArrCount; + sal_uInt16 mnArrCapacity; bool mbPageMode; - explicit ScTableInfo(); + explicit ScTableInfo(const sal_uInt16 capacity = 1024); ~ScTableInfo(); ScTableInfo(const ScTableInfo&) = delete; const ScTableInfo& operator=(const ScTableInfo&) = delete; diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 4fdcbf6..3235c30 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -46,8 +46,6 @@ #include <memory> #include <o3tl/make_unique.hxx> -const sal_uInt16 ROWINFO_MAX = 1024; - enum FillInfoLinePos { FILP_TOP, @@ -209,7 +207,7 @@ bool isRotateItemUsed(ScDocumentPool *pPool) return false; } -void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, +void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, const SCSIZE nMaxRow, double fRowScale, SCROW nRow1, SCTAB nTab, SCROW& rYExtra, SCSIZE& rArrRow, SCROW& rRow2) { sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight; @@ -249,7 +247,7 @@ void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE; ++rArrRow; - if (rArrRow >= ROWINFO_MAX) + if (rArrRow >= nMaxRow) { OSL_FAIL("FillInfo: Range too big" ); rYExtra = nSignedY; // End @@ -434,7 +432,7 @@ void ScDocument::FillInfo( nArrRow=0; SCROW nYExtra = nRow2+1; - initRowInfo(this, pRowInfo, fRowScale, nRow1, + initRowInfo(this, pRowInfo, rTabInfo.mnArrCapacity, fRowScale, nRow1, nTab, nYExtra, nArrRow, nRow2); nArrCount = nArrRow; // incl. Dummys @@ -1128,17 +1126,18 @@ void ScDocument::FillInfo( rArray.MirrorSelfX( true, false ); } -ScTableInfo::ScTableInfo() - : mpRowInfo(new RowInfo[ROWINFO_MAX]) +ScTableInfo::ScTableInfo(const sal_uInt16 capacity) + : mpRowInfo(new RowInfo[capacity]) , mnArrCount(0) + , mnArrCapacity(capacity) , mbPageMode(false) { - memset(mpRowInfo, 0, ROWINFO_MAX*sizeof(RowInfo)); + memset(mpRowInfo, 0, mnArrCapacity * sizeof(RowInfo)); } ScTableInfo::~ScTableInfo() { - for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx ) + for( sal_uInt16 nIdx = 0; nIdx < mnArrCapacity; ++nIdx ) delete [] mpRowInfo[ nIdx ].pCellInfo; delete [] mpRowInfo; } diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index f927b4f..923316a 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -985,8 +985,8 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice, double fPPTX = pViewData->GetPPTX(); double fPPTY = pViewData->GetPPTY(); - ScTableInfo aTabInfo; - pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, nEndCol, nEndRow, nTab, fPPTX, fPPTY, false, false); + ScTableInfo aTabInfo(nEndRow + 2); + pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, nEndCol, nEndRow, nTab, fPPTX, fPPTY, false, false, NULL); ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, -fTilePosXPixel, -fTilePosYPixel, nStartCol, nStartRow, nEndCol, nEndRow, commit b4f78d525d97315e7ceb2f4a247916c370cf0030 Author: Caolán McNamara <[email protected]> Date: Sat Apr 9 20:39:48 2016 +0100 coverity#738785 reorg to silence Uninitialized pointer field (cherry picked from commit 3ac0778c0a2b2f693a1029b7b05c1be4f71944a9) Change-Id: If2225e77215e2a6fb6b9e9dfc6021a2c20babe50 Reviewed-on: https://gerrit.libreoffice.org/25292 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 4475acb6e52652890e5470c4cd1f4e1aaa84fbb5) diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index 94bd6b1..d35bb8e 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -29,8 +29,6 @@ #include "colorscale.hxx" #include "cellvalue.hxx" -#include <boost/noncopyable.hpp> - class SfxItemSet; class SvxBrushItem; class SvxBoxItem; @@ -96,8 +94,42 @@ struct ScIconSetInfo bool mbShowValue; }; -struct CellInfo : boost::noncopyable +struct CellInfo { + CellInfo() + : pPatternAttr(nullptr) + , pConditionSet(nullptr) + , pBackground(nullptr) // TODO: omit? + , pLinesAttr(nullptr) + , mpTLBRLine(nullptr) + , mpBLTRLine(nullptr) + , pShadowAttr(nullptr) + , pHShadowOrigin(nullptr) + , pVShadowOrigin(nullptr) + , eHShadowPart(SC_SHADOW_HSTART) + , eVShadowPart(SC_SHADOW_HSTART) + , nClipMark(SC_CLIPMARK_NONE) + , nWidth(0) + , nRotateDir(SC_ROTDIR_NONE) + , bMarked(false) + , bEmptyCellText(false) + , bMerged(false) + , bHOverlapped(false) + , bVOverlapped(false) + , bAutoFilter(false) + , bPivotButton(false) + , bPivotPopupButton(false) + , bFilterActive(false) + , bPrinted(false) // view-internal + , bHideGrid(false) // view-internal + , bEditEngine(false) // view-internal + { + } + + ~CellInfo() = default; + CellInfo(const CellInfo&) = delete; + const CellInfo& operator=(const CellInfo&) = delete; + ScRefCellValue maCell; const ScPatternAttr* pPatternAttr; @@ -139,8 +171,13 @@ struct CellInfo : boost::noncopyable const SCCOL SC_ROTMAX_NONE = SCCOL_MAX; -struct RowInfo : boost::noncopyable +struct RowInfo { + RowInfo() = default; + ~RowInfo() = default; + RowInfo(const RowInfo&) = delete; + const RowInfo& operator=(const RowInfo&) = delete; + CellInfo* pCellInfo; sal_uInt16 nHeight; @@ -154,7 +191,7 @@ struct RowInfo : boost::noncopyable bool bChanged:1; // TRUE, if not tested }; -struct ScTableInfo : boost::noncopyable +struct ScTableInfo { svx::frame::Array maArray; RowInfo* mpRowInfo; @@ -163,6 +200,8 @@ struct ScTableInfo : boost::noncopyable explicit ScTableInfo(); ~ScTableInfo(); + ScTableInfo(const ScTableInfo&) = delete; + const ScTableInfo& operator=(const ScTableInfo&) = delete; }; #endif diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index e9c7d4a..4fdcbf6 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -157,11 +157,11 @@ class RowInfoFiller { alignArray(nRow); - RowInfo* pThisRowInfo = &mpRowInfo[mnArrY]; - CellInfo* pInfo = &pThisRowInfo->pCellInfo[mnArrX]; - pInfo->maCell = rCell; - pThisRowInfo->bEmptyText = false; - pInfo->bEmptyCellText = false; + RowInfo& rThisRowInfo = mpRowInfo[mnArrY]; + CellInfo& rInfo = rThisRowInfo.pCellInfo[mnArrX]; + rInfo.maCell = rCell; + rThisRowInfo.bEmptyText = false; + rInfo.bEmptyCellText = false; ++mnArrY; } @@ -266,55 +266,27 @@ void initCellInfo(RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nRotMax, bool bPain const SvxShadowItem* pDefShadow, SCROW nBlockStartY, SCROW nBlockEndY, SCCOL nBlockStartX, SCCOL nBlockEndX) { - for (SCSIZE nArrRow = 0; nArrRow < nArrCount; nArrRow++) + for (SCSIZE nArrRow = 0; nArrRow < nArrCount; ++nArrRow) { - RowInfo* pThisRowInfo = &pRowInfo[nArrRow]; - SCROW nY = pThisRowInfo->nRowNo; - pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // to delete the caller! + RowInfo& rThisRowInfo = pRowInfo[nArrRow]; + SCROW nY = rThisRowInfo.nRowNo; + rThisRowInfo.pCellInfo = new CellInfo[nRotMax + 1 + 2]; // to delete the caller! - for (SCCOL nArrCol = 0; nArrCol <= nRotMax+2; nArrCol++) // Preassign cell info + for (SCCOL nArrCol = 0; nArrCol <= nRotMax+2; ++nArrCol) // Preassign cell info { - SCCOL nX; - if (nArrCol>0) - nX = nArrCol-1; - else - nX = MAXCOL+1; // invalid - - CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrCol]; - pInfo->bEmptyCellText = true; - pInfo->maCell.clear(); + CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrCol]; if (bPaintMarks) - pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX - && nY >= nBlockStartY && nY <= nBlockEndY ); - else - pInfo->bMarked = false; - pInfo->nWidth = 0; - - pInfo->nClipMark = SC_CLIPMARK_NONE; - pInfo->bMerged = false; - pInfo->bHOverlapped = false; - pInfo->bVOverlapped = false; - pInfo->bAutoFilter = false; - pInfo->bPivotButton = false; - pInfo->bPivotPopupButton = false; - pInfo->bFilterActive = false; - pInfo->nRotateDir = SC_ROTDIR_NONE; - - pInfo->bPrinted = false; // view-internal - pInfo->bHideGrid = false; // view-internal - pInfo->bEditEngine = false; // view-internal - - pInfo->pBackground = nullptr; //TODO: omit? - pInfo->pPatternAttr = nullptr; - pInfo->pConditionSet= nullptr; - - pInfo->pLinesAttr = nullptr; - pInfo->mpTLBRLine = nullptr; - pInfo->mpBLTRLine = nullptr; - - pInfo->pShadowAttr = pDefShadow; - pInfo->pHShadowOrigin = nullptr; - pInfo->pVShadowOrigin = nullptr; + { + SCCOL nX; + if (nArrCol>0) + nX = nArrCol-1; + else + nX = MAXCOL+1; // invalid + rInfo.bMarked = (nX >= nBlockStartX && nX <= nBlockEndX && + nY >= nBlockStartY && nY <= nBlockEndY); + } + rInfo.bEmptyCellText = true; + rInfo.pShadowAttr = pDefShadow; } } } commit 3521850fb44778aa644b4eb5511bbf0276bf51f4 Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 02:55:18 2016 +0200 add TODO comment for a bug This bug is the first one that was discovered because it is now much easier to see which parts of the code work on cells, pattern areas and whole columns/rows. Change-Id: I8f22bf421298947d65bfc2fc9c986d85169e6545 Reviewed-on: https://gerrit.libreoffice.org/23636 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit 2c69316037e29db52393d898100e6593a6cd5a24) Reviewed-on: https://gerrit.libreoffice.org/25291 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 7547ff2c31066ec1b115dcee5500b892b3d3a881) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 0b9734d..e9c7d4a 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -363,6 +363,8 @@ bool handleConditionalFormat(ScConditionalFormatList* pCondFormList, const std:: pInfo->pConditionSet = &pStyleSheet->GetItemSet(); bAnyCondition = true; + // TODO: moggi: looks like there is a but around bHidden and bHideFormula + // They are normally for the whole pattern and not for a single cell // we need to check already here for protected cells const SfxPoolItem* pItem; if ( bTabProtect && pInfo->pConditionSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SfxItemState::SET ) commit fc834ce7bc3f0c2605af1cd989de0500543ea45f Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 02:41:07 2016 +0200 extract another function from ScDocument::FillInfo Change-Id: Ief094beebbff2bce9f087853cbda6adeeafe07fc Reviewed-on: https://gerrit.libreoffice.org/23635 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit b22e51d0c60f959c2db77bd3d23119b53bd87545) Reviewed-on: https://gerrit.libreoffice.org/25290 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit ce571823e2be946308c814f600449e62f1b3a87d) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 1ee57b0..0b9734d 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -338,6 +338,68 @@ void initColWidths(RowInfo* pRowInfo, ScDocument* pDoc, double fColScale, SCTAB } } +bool handleConditionalFormat(ScConditionalFormatList* pCondFormList, const std::vector<sal_uInt32> rCondFormats, + CellInfo* pInfo, ScStyleSheetPool* pStlPool, + const ScAddress& rAddr, bool& bHidden, bool& bHideFormula, bool bTabProtect) +{ + bool bFound = false; + bool bAnyCondition = false; + for(std::vector<sal_uInt32>::const_iterator itr = rCondFormats.begin(); + itr != rCondFormats.end() && !bFound; ++itr) + { + ScConditionalFormat* pCondForm = pCondFormList->GetFormat(*itr); + if(!pCondForm) + continue; + + ScCondFormatData aData = pCondForm->GetData( + pInfo->maCell, rAddr); + if (!aData.aStyleName.isEmpty()) + { + SfxStyleSheetBase* pStyleSheet = + pStlPool->Find( aData.aStyleName, SFX_STYLE_FAMILY_PARA ); + if ( pStyleSheet ) + { + //TODO: cache Style-Sets !!! + pInfo->pConditionSet = &pStyleSheet->GetItemSet(); + bAnyCondition = true; + + // we need to check already here for protected cells + const SfxPoolItem* pItem; + if ( bTabProtect && pInfo->pConditionSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SfxItemState::SET ) + { + const ScProtectionAttr* pProtAttr = static_cast<const ScProtectionAttr*>(pItem); + bHidden = pProtAttr->GetHideCell(); + bHideFormula = pProtAttr->GetHideFormula(); + + } + bFound = true; + + } + // if style is not there, treat like no condition + } + + if(aData.pColorScale) + { + pInfo->pColorScale.reset(aData.pColorScale); + bFound = true; + } + + if(aData.pDataBar) + { + pInfo->pDataBar.reset(aData.pDataBar); + bFound = true; + } + + if(aData.pIconSet) + { + pInfo->pIconSet.reset(aData.pIconSet); + bFound = true; + } + } + + return bAnyCondition; +} + } void ScDocument::FillInfo( @@ -564,61 +626,10 @@ void ScDocument::FillInfo( pThisRowInfo->bEmptyBack = false; } - if ( bContainsCondFormat ) + if (bContainsCondFormat) { - bool bFound = false; - for(std::vector<sal_uInt32>::const_iterator itr = rCondFormats.begin(); - itr != rCondFormats.end() && !bFound; ++itr) - { - ScConditionalFormat* pCondForm = pCondFormList->GetFormat(*itr); - if(!pCondForm) - continue; - - ScCondFormatData aData = pCondForm->GetData( - pInfo->maCell, ScAddress(nX, nCurRow, nTab)); - if (!aData.aStyleName.isEmpty()) - { - SfxStyleSheetBase* pStyleSheet = - pStlPool->Find( aData.aStyleName, SFX_STYLE_FAMILY_PARA ); - if ( pStyleSheet ) - { - //TODO: cache Style-Sets !!! - pInfo->pConditionSet = &pStyleSheet->GetItemSet(); - bAnyCondition = true; - - // we need to check already here for protected cells - const SfxPoolItem* pItem; - if ( bTabProtect && pInfo->pConditionSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SfxItemState::SET ) - { - const ScProtectionAttr* pProtAttr = static_cast<const ScProtectionAttr*>(pItem); - bHidden = pProtAttr->GetHideCell(); - bHideFormula = pProtAttr->GetHideFormula(); - - } - bFound = true; - - } - // if style is not there, treat like no condition - } - - if(aData.pColorScale) - { - pInfo->pColorScale.reset(aData.pColorScale); - bFound = true; - } - - if(aData.pDataBar) - { - pInfo->pDataBar.reset(aData.pDataBar); - bFound = true; - } - - if(aData.pIconSet) - { - pInfo->pIconSet.reset(aData.pIconSet); - bFound = true; - } - } + bAnyCondition |= handleConditionalFormat(pCondFormList, rCondFormats, pInfo, pStlPool, ScAddress(nX, nCurRow, nTab), + bHidden, bHideFormula, bTabProtect); } if (bHidden || (bFormulaMode && bHideFormula && pInfo->maCell.meType == CELLTYPE_FORMULA)) commit 0f4abdf32ebc7bbf5b5168e589d093ae2914a3a6 Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 02:25:16 2016 +0200 stylistic changes in ScDocument::FillInfo Change-Id: I98bb25d414106259a809698941a000d6d0bc35e0 Reviewed-on: https://gerrit.libreoffice.org/23634 Reviewed-by: Markus Mohrhard <[email protected]> Tested-by: Markus Mohrhard <[email protected]> (cherry picked from commit b27428d2136e67ee7c7449a7db562a957af390d6) Reviewed-on: https://gerrit.libreoffice.org/25289 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 09a64f221b09683e636247b20b0b1ccdd8900039) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index cbb4dd1..1ee57b0 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -470,8 +470,9 @@ void ScDocument::FillInfo( --nCurRow; // 1 more on top else nArrRow = 1; + SCROW nThisRow = nCurRow; // end of range - SCSIZE nIndex; + SCSIZE nIndex; (void) pThisAttrArr->Search( nCurRow, nIndex ); do @@ -599,6 +600,7 @@ void ScDocument::FillInfo( } // if style is not there, treat like no condition } + if(aData.pColorScale) { pInfo->pColorScale.reset(aData.pColorScale); @@ -610,6 +612,7 @@ void ScDocument::FillInfo( pInfo->pDataBar.reset(aData.pDataBar); bFound = true; } + if(aData.pIconSet) { pInfo->pIconSet.reset(aData.pIconSet); commit 871fe705a88ab674dddc00c5547fe3f0b60cf9ee Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 02:24:54 2016 +0200 limit scope of another variable in ScDocument::FillInfo Change-Id: Ic53bcaa5e33f221a643de4e854990769b5c04a74 Reviewed-on: https://gerrit.libreoffice.org/23633 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit 8f0668a0e18f4fa01864ede5fa3f66b36bd4ad85) Reviewed-on: https://gerrit.libreoffice.org/25288 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit a7402aee62c5ddcf57bf1e7ef6c3ed7d43636650) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 2aade2a..cbb4dd1 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -465,7 +465,6 @@ void ScDocument::FillInfo( ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute nArrRow = 0; - const ScPatternAttr* pPattern; SCROW nCurRow=nRow1; // single rows if (nCurRow>0) --nCurRow; // 1 more on top @@ -478,7 +477,7 @@ void ScDocument::FillInfo( do { nThisRow=pThisAttrArr->pData[nIndex].nRow; // End of range - pPattern=pThisAttrArr->pData[nIndex].pPattern; + const ScPatternAttr* pPattern=pThisAttrArr->pData[nIndex].pPattern; const SvxBrushItem* pBackground = static_cast<const SvxBrushItem*>( &pPattern->GetItem(ATTR_BACKGROUND)); commit a9c3ce484c46132658dbb1e4162cc67ddc0e3e88 Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 02:15:07 2016 +0200 limit the scope of a few variable in ScDocument::FillInfo This makes the code at least a little bit easier to read as we can now see much easier when a variable is used to transport state between loops and when it is just a variable local to a loop Reviewed-on: https://gerrit.libreoffice.org/23632 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit 36eec4d179898302578c428564f1b60406c0716c) Reviewed-on: https://gerrit.libreoffice.org/25287 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 5345c0f7ae6d2cad6814dc112c68ba3e6239fd8f) Change-Id: Ib92ff1596bda35f9892accc820bc3596bafb7d96 diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 7ec3453..2aade2a 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -209,27 +209,28 @@ bool isRotateItemUsed(ScDocumentPool *pPool) return false; } -void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, SCROW& rY, +void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, double fRowScale, SCROW nRow1, SCTAB nTab, SCROW& rYExtra, SCSIZE& rArrRow, SCROW& rRow2) { sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight; SCROW nDocHeightEndRow = -1; for (SCsROW nSignedY=((SCsROW)nRow1)-1; nSignedY<=(SCsROW)rYExtra; nSignedY++) { + SCROW nY; if (nSignedY >= 0) - rY = (SCROW) nSignedY; + nY = (SCROW) nSignedY; else - rY = MAXROW+1; // invalid + nY = MAXROW+1; // invalid - if (rY > nDocHeightEndRow) + if (nY > nDocHeightEndRow) { - if (ValidRow(rY)) - nDocHeight = pDoc->GetRowHeight( rY, nTab, nullptr, &nDocHeightEndRow ); + if (ValidRow(nY)) + nDocHeight = pDoc->GetRowHeight( nY, nTab, nullptr, &nDocHeightEndRow ); else nDocHeight = ScGlobal::nStdRowHeight; } - if ( rArrRow==0 || nDocHeight || rY > MAXROW ) + if ( rArrRow==0 || nDocHeight || nY > MAXROW ) { RowInfo* pThisRowInfo = &pRowInfo[rArrRow]; pThisRowInfo->pCellInfo = nullptr; // is loaded below @@ -238,7 +239,7 @@ void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, SCROW& rY, if (!nHeight) nHeight = 1; - pThisRowInfo->nRowNo = rY; //TODO: case < 0 ? + pThisRowInfo->nRowNo = nY; //TODO: case < 0 ? pThisRowInfo->nHeight = nHeight; pThisRowInfo->bEmptyBack = true; pThisRowInfo->bEmptyText = true; @@ -360,11 +361,6 @@ void ScDocument::FillInfo( const SvxShadowItem* pDefShadow = static_cast<const SvxShadowItem*>( &pPool->GetDefaultItem( ATTR_SHADOW ) ); - SCROW nThisRow; - SCCOL nX; - SCROW nY; - SCsROW nSignedY; - SCCOL nArrCol; SCSIZE nArrRow; SCSIZE nArrCount; bool bAnyMerged = false; @@ -402,53 +398,8 @@ void ScDocument::FillInfo( nArrRow=0; SCROW nYExtra = nRow2+1; - sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight; - SCROW nDocHeightEndRow = -1; - for (nSignedY=((SCsROW)nRow1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++) - { - if (nSignedY >= 0) - nY = (SCROW) nSignedY; - else - nY = MAXROW+1; // invalid - - if (nY > nDocHeightEndRow) - { - if (ValidRow(nY)) - nDocHeight = GetRowHeight( nY, nTab, nullptr, &nDocHeightEndRow ); - else - nDocHeight = ScGlobal::nStdRowHeight; - } - - if ( nArrRow==0 || nDocHeight || nY > MAXROW ) - { - RowInfo* pThisRowInfo = &pRowInfo[nArrRow]; - pThisRowInfo->pCellInfo = nullptr; // is loaded below - - sal_uInt16 nHeight = (sal_uInt16) ( nDocHeight * fRowScale ); - if (!nHeight) - nHeight = 1; - - pThisRowInfo->nRowNo = nY; //TODO: case < 0 ? - pThisRowInfo->nHeight = nHeight; - pThisRowInfo->bEmptyBack = true; - pThisRowInfo->bEmptyText = true; - pThisRowInfo->bChanged = true; - pThisRowInfo->bAutoFilter = false; - pThisRowInfo->bPivotButton = false; - pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE; - - ++nArrRow; - if (nArrRow >= ROWINFO_MAX) - { - OSL_FAIL("FillInfo: Range too big" ); - nYExtra = nSignedY; // End - nRow2 = nYExtra - 1; // Adjust range - } - } - else - if (nSignedY==(SCsROW) nYExtra) // hidden additional line? - ++nYExtra; - } + initRowInfo(this, pRowInfo, fRowScale, nRow1, + nTab, nYExtra, nArrRow, nRow2); nArrCount = nArrRow; // incl. Dummys // Rotated text... @@ -482,9 +433,9 @@ void ScDocument::FillInfo( if(pCondFormList) pCondFormList->startRendering(); - for (nArrCol=0; nArrCol<=nCol2+2; nArrCol++) // left & right + 1 + for (SCCOL nArrCol=0; nArrCol<=nCol2+2; nArrCol++) // left & right + 1 { - nX = (nArrCol>0) ? nArrCol-1 : MAXCOL+1; // negative -> invalid + SCCOL nX = (nArrCol>0) ? nArrCol-1 : MAXCOL+1; // negative -> invalid if ( ValidCol(nX) ) { @@ -520,7 +471,7 @@ void ScDocument::FillInfo( --nCurRow; // 1 more on top else nArrRow = 1; - nThisRow=nCurRow; // end of range + SCROW nThisRow = nCurRow; // end of range SCSIZE nIndex; (void) pThisAttrArr->Search( nCurRow, nIndex ); @@ -757,7 +708,7 @@ void ScDocument::FillInfo( { for (nArrRow=0; nArrRow<nArrCount; nArrRow++) { - for (nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right + for (SCCOL nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right { CellInfo* pInfo = &pRowInfo[nArrRow].pCellInfo[nArrCol]; SCCOL nCol = (nArrCol>0) ? nArrCol-1 : MAXCOL+1; @@ -820,9 +771,9 @@ void ScDocument::FillInfo( for (nArrRow=0; nArrRow<nArrCount; nArrRow++) { RowInfo* pThisRowInfo = &pRowInfo[nArrRow]; - nSignedY = nArrRow ? pThisRowInfo->nRowNo : ((SCsROW)nRow1)-1; + SCsROW nSignedY = nArrRow ? pThisRowInfo->nRowNo : ((SCsROW)nRow1)-1; - for (nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right + for (SCCOL nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right { SCsCOL nSignedX = ((SCsCOL) nArrCol) - 1; CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrCol]; @@ -885,7 +836,7 @@ void ScDocument::FillInfo( bool bTop = ( nArrRow == 0 ); bool bBottom = ( nArrRow+1 == nArrCount ); - for (nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right + for (SCCOL nArrCol=nCol1; nArrCol<=nCol2+2; nArrCol++) // 1 more left and right { bool bLeft = ( nArrCol == nCol1 ); bool bRight = ( nArrCol == nCol2+2 ); commit 1f194348d5d19db7e8cbb226c4a45388b9942b63 Author: Markus Mohrhard <[email protected]> Date: Wed Mar 30 01:50:53 2016 +0200 extract another function from ScDocument::FillInfo Change-Id: Iac607e1fe915c8bc90316508c98855a60117d435 Reviewed-on: https://gerrit.libreoffice.org/23631 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit 772e66406b90bdb898e73b4fa944a6e55a42683b) Reviewed-on: https://gerrit.libreoffice.org/25286 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit b2a02da8e7866dd5ce61bf5cff56d6066f3e4a06) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index aaa05fd..7ec3453 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -318,6 +318,25 @@ void initCellInfo(RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nRotMax, bool bPain } } +void initColWidths(RowInfo* pRowInfo, ScDocument* pDoc, double fColScale, SCTAB nTab, SCCOL nCol2, SCCOL nRotMax) +{ + for (SCCOL nArrCol=nCol2+3; nArrCol<=nRotMax+2; nArrCol++) // Add remaining widths + { + SCCOL nX = nArrCol-1; + if ( ValidCol(nX) ) + { + if (!pDoc->ColHidden(nX, nTab)) + { + sal_uInt16 nThisWidth = (sal_uInt16) (pDoc->GetColWidth( nX, nTab ) * fColScale); + if (!nThisWidth) + nThisWidth = 1; + + pRowInfo[0].pCellInfo[nArrCol].nWidth = nThisWidth; + } + } + } +} + } void ScDocument::FillInfo( @@ -457,21 +476,7 @@ void ScDocument::FillInfo( initCellInfo(pRowInfo, nArrCount, nRotMax, bPaintMarks, pDefShadow, nBlockStartY, nBlockEndY, nBlockStartX, nBlockEndX); - for (nArrCol=nCol2+3; nArrCol<=nRotMax+2; nArrCol++) // Add remaining widths - { - nX = nArrCol-1; - if ( ValidCol(nX) ) - { - if (!ColHidden(nX, nTab)) - { - sal_uInt16 nThisWidth = (sal_uInt16) (GetColWidth( nX, nTab ) * fColScale); - if (!nThisWidth) - nThisWidth = 1; - - pRowInfo[0].pCellInfo[nArrCol].nWidth = nThisWidth; - } - } - } + initColWidths(pRowInfo, this, fColScale, nTab, nCol2, nRotMax); ScConditionalFormatList* pCondFormList = GetCondFormList(nTab); if(pCondFormList) commit 2914372543828b73de08ad6c50be984d7dbdb484 Author: Markus Mohrhard <[email protected]> Date: Sun Mar 27 05:11:20 2016 +0200 extract another function from ScDocument::FillInfo Change-Id: If6f898d514dc454a7f1c5448769a95269e9066d7 Reviewed-on: https://gerrit.libreoffice.org/23550 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit 5ecda97eeab36ceab022458345f2c61c31ab2d94) Reviewed-on: https://gerrit.libreoffice.org/25285 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 40b2e53d22347e625cd22f0ac8fd6c79165b3703) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index f298f26..aaa05fd 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -261,6 +261,63 @@ void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, SCROW& rY, } } +void initCellInfo(RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nRotMax, bool bPaintMarks, + const SvxShadowItem* pDefShadow, SCROW nBlockStartY, SCROW nBlockEndY, + SCCOL nBlockStartX, SCCOL nBlockEndX) +{ + for (SCSIZE nArrRow = 0; nArrRow < nArrCount; nArrRow++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrRow]; + SCROW nY = pThisRowInfo->nRowNo; + pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // to delete the caller! + + for (SCCOL nArrCol = 0; nArrCol <= nRotMax+2; nArrCol++) // Preassign cell info + { + SCCOL nX; + if (nArrCol>0) + nX = nArrCol-1; + else + nX = MAXCOL+1; // invalid + + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrCol]; + pInfo->bEmptyCellText = true; + pInfo->maCell.clear(); + if (bPaintMarks) + pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX + && nY >= nBlockStartY && nY <= nBlockEndY ); + else + pInfo->bMarked = false; + pInfo->nWidth = 0; + + pInfo->nClipMark = SC_CLIPMARK_NONE; + pInfo->bMerged = false; + pInfo->bHOverlapped = false; + pInfo->bVOverlapped = false; + pInfo->bAutoFilter = false; + pInfo->bPivotButton = false; + pInfo->bPivotPopupButton = false; + pInfo->bFilterActive = false; + pInfo->nRotateDir = SC_ROTDIR_NONE; + + pInfo->bPrinted = false; // view-internal + pInfo->bHideGrid = false; // view-internal + pInfo->bEditEngine = false; // view-internal + + pInfo->pBackground = nullptr; //TODO: omit? + pInfo->pPatternAttr = nullptr; + pInfo->pConditionSet= nullptr; + + pInfo->pLinesAttr = nullptr; + pInfo->mpTLBRLine = nullptr; + pInfo->mpBLTRLine = nullptr; + + pInfo->pShadowAttr = pDefShadow; + pInfo->pHShadowOrigin = nullptr; + pInfo->pVShadowOrigin = nullptr; + } + } +} + } void ScDocument::FillInfo( @@ -397,57 +454,8 @@ void ScDocument::FillInfo( // Allocate cell information only after the test rotation // to nRotMax due to nRotateDir Flag - - for (nArrRow=0; nArrRow<nArrCount; nArrRow++) - { - RowInfo* pThisRowInfo = &pRowInfo[nArrRow]; - nY = pThisRowInfo->nRowNo; - pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // to delete the caller! - - for (nArrCol=0; nArrCol<=nRotMax+2; nArrCol++) // Preassign cell info - { - if (nArrCol>0) - nX = nArrCol-1; - else - nX = MAXCOL+1; // invalid - - CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrCol]; - pInfo->bEmptyCellText = true; - pInfo->maCell.clear(); - if (bPaintMarks) - pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX - && nY >= nBlockStartY && nY <= nBlockEndY ); - else - pInfo->bMarked = false; - pInfo->nWidth = 0; - - pInfo->nClipMark = SC_CLIPMARK_NONE; - pInfo->bMerged = false; - pInfo->bHOverlapped = false; - pInfo->bVOverlapped = false; - pInfo->bAutoFilter = false; - pInfo->bPivotButton = false; - pInfo->bPivotPopupButton = false; - pInfo->bFilterActive = false; - pInfo->nRotateDir = SC_ROTDIR_NONE; - - pInfo->bPrinted = false; // view-internal - pInfo->bHideGrid = false; // view-internal - pInfo->bEditEngine = false; // view-internal - - pInfo->pBackground = nullptr; //TODO: omit? - pInfo->pPatternAttr = nullptr; - pInfo->pConditionSet= nullptr; - - pInfo->pLinesAttr = nullptr; - pInfo->mpTLBRLine = nullptr; - pInfo->mpBLTRLine = nullptr; - - pInfo->pShadowAttr = pDefShadow; - pInfo->pHShadowOrigin = nullptr; - pInfo->pVShadowOrigin = nullptr; - } - } + initCellInfo(pRowInfo, nArrCount, nRotMax, bPaintMarks, pDefShadow, + nBlockStartY, nBlockEndY, nBlockStartX, nBlockEndX); for (nArrCol=nCol2+3; nArrCol<=nRotMax+2; nArrCol++) // Add remaining widths { commit 3b8c064b359a0902e21ba67f87a059fa32aa1af4 Author: Markus Mohrhard <[email protected]> Date: Tue Mar 29 18:59:24 2016 +0200 that should not have become part of the previous commit Change-Id: Ia116e5f9fdbd34cd1017ec1f2dabf6e581c4c707 (cherry picked from commit 789a3e61785a2458429890e28ad9a37fab8cdade) Reviewed-on: https://gerrit.libreoffice.org/25284 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit 7c942ee446ff357d2cd874913b15b4d641ed1ba6) diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 5281a7d..f298f26 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -489,16 +489,17 @@ void ScDocument::FillInfo( ScColumn* pThisCol = &maTabs[nTab]->aCol[nX]; // Column data - nArrRow = 0; + nArrRow = 1; // Iterate between rows nY1 and nY2 and pick up non-empty // cells that are not hidden. RowInfoFiller aFunc(*this, nTab, pRowInfo, nArrCol, nArrRow); sc::ParseAllNonEmpty( - pThisCol->maCells.begin(), pThisCol->maCells, std::max<SCROW>(0 , nRow1 - 1), nYExtra, aFunc); + pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc); if (nX+1 >= nCol1) // Attribute/Blockmark from nX1-1 { ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute + nArrRow = 0; const ScPatternAttr* pPattern; SCROW nCurRow=nRow1; // single rows commit 08efe5d4add290543349b4a800ce77d9965feea5 Author: Markus Mohrhard <[email protected]> Date: Sun Mar 27 04:56:55 2016 +0200 extract another function from ScDocument::FillInfo (cherry picked from commit a70824f0220b88f3f209266f8e1cba98dc89ca8f) Reviewed-on: https://gerrit.libreoffice.org/25283 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit c8774715d10707989267b550841984cd50b07e74) Change-Id: Ifd39ec5ad7aebac532ea7145274005507a5b177f diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 0979781..5281a7d 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -135,7 +135,7 @@ class RowInfoFiller SCTAB mnTab; RowInfo* mpRowInfo; SCCOL mnArrX; - SCSIZE& mrArrY; + SCSIZE mnArrY; SCROW mnHiddenEndRow; bool mbHiddenRow; @@ -149,25 +149,25 @@ class RowInfoFiller void alignArray(size_t nRow) { - while (mpRowInfo[mrArrY].nRowNo < static_cast<SCROW>(nRow)) - ++mrArrY; + while (mpRowInfo[mnArrY].nRowNo < static_cast<SCROW>(nRow)) + ++mnArrY; } void setInfo(size_t nRow, const ScRefCellValue& rCell) { alignArray(nRow); - RowInfo* pThisRowInfo = &mpRowInfo[mrArrY]; + RowInfo* pThisRowInfo = &mpRowInfo[mnArrY]; CellInfo* pInfo = &pThisRowInfo->pCellInfo[mnArrX]; pInfo->maCell = rCell; pThisRowInfo->bEmptyText = false; pInfo->bEmptyCellText = false; - ++mrArrY; + ++mnArrY; } public: RowInfoFiller(ScDocument& rDoc, SCTAB nTab, RowInfo* pRowInfo, SCCOL nArrX, SCSIZE& rArrY) : - mrDoc(rDoc), mnTab(nTab), mpRowInfo(pRowInfo), mnArrX(nArrX), mrArrY(rArrY), + mrDoc(rDoc), mnTab(nTab), mpRowInfo(pRowInfo), mnArrX(nArrX), mnArrY(rArrY), mnHiddenEndRow(-1), mbHiddenRow(false) {} void operator() (size_t nRow, double fVal) @@ -209,6 +209,58 @@ bool isRotateItemUsed(ScDocumentPool *pPool) return false; } +void initRowInfo(ScDocument* pDoc, RowInfo* pRowInfo, SCROW& rY, + double fRowScale, SCROW nRow1, SCTAB nTab, SCROW& rYExtra, SCSIZE& rArrRow, SCROW& rRow2) +{ + sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight; + SCROW nDocHeightEndRow = -1; + for (SCsROW nSignedY=((SCsROW)nRow1)-1; nSignedY<=(SCsROW)rYExtra; nSignedY++) + { + if (nSignedY >= 0) + rY = (SCROW) nSignedY; + else + rY = MAXROW+1; // invalid + + if (rY > nDocHeightEndRow) + { + if (ValidRow(rY)) + nDocHeight = pDoc->GetRowHeight( rY, nTab, nullptr, &nDocHeightEndRow ); + else + nDocHeight = ScGlobal::nStdRowHeight; + } + + if ( rArrRow==0 || nDocHeight || rY > MAXROW ) + { + RowInfo* pThisRowInfo = &pRowInfo[rArrRow]; + pThisRowInfo->pCellInfo = nullptr; // is loaded below + + sal_uInt16 nHeight = (sal_uInt16) ( nDocHeight * fRowScale ); + if (!nHeight) + nHeight = 1; + + pThisRowInfo->nRowNo = rY; //TODO: case < 0 ? + pThisRowInfo->nHeight = nHeight; + pThisRowInfo->bEmptyBack = true; + pThisRowInfo->bEmptyText = true; + pThisRowInfo->bChanged = true; + pThisRowInfo->bAutoFilter = false; + pThisRowInfo->bPivotButton = false; + pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE; + + ++rArrRow; + if (rArrRow >= ROWINFO_MAX) + { + OSL_FAIL("FillInfo: Range too big" ); + rYExtra = nSignedY; // End + rRow2 = rYExtra - 1; // Adjust range + } + } + else + if (nSignedY==(SCsROW) rYExtra) // hidden additional line? + ++rYExtra; + } +} + } void ScDocument::FillInfo( @@ -329,7 +381,7 @@ void ScDocument::FillInfo( bool bAnyItem = isRotateItemUsed(pPool); SCCOL nRotMax = nCol2; - if ( bAnyItem && HasAttrib( 0,nRow1,nTab, MAXCOL,nRow2+1,nTab, + if ( bAnyItem && HasAttrib( 0, nRow1, nTab, MAXCOL, nRow2+1, nTab, HASATTR_ROTATE | HASATTR_CONDITIONAL ) ) { //TODO: check Conditionals also for HASATTR_ROTATE ???? @@ -437,18 +489,17 @@ void ScDocument::FillInfo( ScColumn* pThisCol = &maTabs[nTab]->aCol[nX]; // Column data - nArrRow = 1; + nArrRow = 0; // Iterate between rows nY1 and nY2 and pick up non-empty // cells that are not hidden. RowInfoFiller aFunc(*this, nTab, pRowInfo, nArrCol, nArrRow); sc::ParseAllNonEmpty( - pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc); + pThisCol->maCells.begin(), pThisCol->maCells, std::max<SCROW>(0 , nRow1 - 1), nYExtra, aFunc); if (nX+1 >= nCol1) // Attribute/Blockmark from nX1-1 { ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute - nArrRow = 0; const ScPatternAttr* pPattern; SCROW nCurRow=nRow1; // single rows if (nCurRow>0) commit 1edd1a36624a0986d742e55ea3666d8c5a13a1ab Author: Dennis Francis <[email protected]> Date: Sat Feb 6 03:12:20 2016 +0530 Refactor ScMarkData for tdf#50916 Made the container for storing multimarks dynamic. Also let the full row marks to be stored in a dedicated ScMarkArray object rather than in the multimarks container. Unit tests for ScMarkData and ScMultiSel will come in a follow up patch. Reviewed-on: https://gerrit.libreoffice.org/22163 Tested-by: Jenkins <[email protected]> Reviewed-by: Markus Mohrhard <[email protected]> (cherry picked from commit bc20c6d0f397c0c1aef6ef7d6f750c2f81af8db6) Reviewed-on: https://gerrit.libreoffice.org/25282 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit b921fbc46e7593fd2d5e5d5c88508522937fdae0) Change-Id: I300ff80bebd6f4f39c284c1e8cb7deece82c1bec diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 8304a9a..60ff984 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -165,6 +165,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/listenercontext \ sc/source/core/data/markarr \ sc/source/core/data/markdata \ + sc/source/core/data/markmulti \ sc/source/core/data/mtvelements \ sc/source/core/data/olinetab \ sc/source/core/data/pagepar \ diff --git a/sc/inc/markarr.hxx b/sc/inc/markarr.hxx index 2988fe4..386b97a 100644 --- a/sc/inc/markarr.hxx +++ b/sc/inc/markarr.hxx @@ -41,6 +41,7 @@ friend class ScDocument; // for FillInfo public: ScMarkArray(); + ScMarkArray( ScMarkArray&& rArray ); ~ScMarkArray(); void Reset( bool bMarked = false ); bool GetMark( SCROW nRow ) const; diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx index 20777a6..0392971 100644 --- a/sc/inc/markdata.hxx +++ b/sc/inc/markdata.hxx @@ -21,6 +21,8 @@ #define INCLUDED_SC_INC_MARKDATA_HXX #include "address.hxx" +#include "rangelst.hxx" +#include "markmulti.hxx" #include "scdllapi.h" #include <set> @@ -49,12 +51,17 @@ private: ScRange aMarkRange; // area ScRange aMultiRange; // maximum area altogether - ScMarkArray* pMultiSel; // multi selection + ScMultiSel aMultiSel; // multi selection bool bMarked:1; // rectangle marked bool bMultiMarked:1; bool bMarking:1; // area is being marked -> no MarkToMulti bool bMarkIsNeg:1; // cancel if multi selection + ScRangeList aTopEnvelope; // list of ranges in the top envelope of the multi selection + ScRangeList aBottomEnvelope; // list of ranges in the bottom envelope of the multi selection + ScRangeList aLeftEnvelope; // list of ranges in the left envelope of the multi selection + ScRangeList aRightEnvelope; // list of ranges in the right envelope of the multi selection + public: ScMarkData(); @@ -66,7 +73,8 @@ public: void ResetMark(); void SetMarkArea( const ScRange& rRange ); - void SetMultiMarkArea( const ScRange& rRange, bool bMark = true ); + // bSetupMulti must be set to true only for recursive calls to SetMultiMarkArea + void SetMultiMarkArea( const ScRange& rRange, bool bMark = true, bool bSetupMulti = false ); void MarkToMulti(); void MarkToSimple(); @@ -96,7 +104,8 @@ public: bool GetMarkingFlag() const { return bMarking; } // for FillInfo / Document etc. - const ScMarkArray* GetArray() const { return pMultiSel; } + const ScMultiSel& GetMultiSelData() const { return aMultiSel; } + ScMarkArray GetMarkArray( SCCOL nCol ) const; bool IsCellMarked( SCCOL nCol, SCROW nRow, bool bNoSimple = false ) const; void FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const; @@ -122,6 +131,15 @@ public: void InsertTab( SCTAB nTab ); void DeleteTab( SCTAB nTab ); + // Generate envelopes if mutimarked and fills the passed ScRange object with + // the smallest range that includes the marked area plus its envelopes. + void GetSelectionCover( ScRange& rRange ); + // Get top, bottom, left and right envelopes + const ScRangeList& GetTopEnvelope() const { return aTopEnvelope; } + const ScRangeList& GetBottomEnvelope() const { return aBottomEnvelope; } + const ScRangeList& GetLeftEnvelope() const { return aLeftEnvelope; } + const ScRangeList& GetRightEnvelope() const { return aRightEnvelope; } + // iterators for table access typedef std::set<SCTAB>::iterator iterator; typedef std::set<SCTAB>::const_iterator const_iterator; diff --git a/sc/inc/markmulti.hxx b/sc/inc/markmulti.hxx new file mode 100644 index 0000000..22f0ee5 --- /dev/null +++ b/sc/inc/markmulti.hxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SC_INC_MARKMULTI_HXX +#define INCLUDED_SC_INC_MARKMULTI_HXX + +#include "address.hxx" +#include "segmenttree.hxx" +#include "markarr.hxx" + +#include <map> + +class ScMultiSel +{ + +private: + typedef std::map<SCCOL, ScMarkArray> MapType; + MapType aMultiSelContainer; + ScMarkArray aRowSel; + +friend class ScMultiSelIter; + +public: + ScMultiSel(); + ScMultiSel( const ScMultiSel& rMultiSel ); + ~ScMultiSel(); + + ScMultiSel& operator=(const ScMultiSel& rMultiSel); + ScMultiSel& operator=(const ScMultiSel&& rMultiSel) = delete; + + SCCOL size() const + { + return static_cast<SCCOL>( aMultiSelContainer.size() ); + } + + bool HasMarks( SCCOL nCol ) const; + bool HasOneMark( SCCOL nCol, SCROW& rStartRow, SCROW& rEndRow ) const; + bool GetMark( SCCOL nCol, SCROW nRow ) const; + bool IsAllMarked( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const; + bool HasEqualRowsMarked( SCCOL nCol1, SCCOL nCol2 ) const; + SCsROW GetNextMarked( SCCOL nCol, SCsROW nRow, bool bUp ) const; + void SetMarkArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow, bool bMark ); + bool IsRowMarked( SCROW nRow ) const; + bool IsRowRangeMarked( SCROW nStartRow, SCROW nEndRow ) const; + bool IsEmpty() const { return ( !aMultiSelContainer.size() && !aRowSel.HasMarks() ); } + ScMarkArray GetMarkArray( SCCOL nCol ) const; + void Clear(); + void MarkAllCols( SCROW nStartRow, SCROW nEndRow ); + bool HasAnyMarks() const; +}; + +class ScMultiSelIter +{ + +private: + ScFlatBoolRowSegments aRowSegs; + SCROW nNextSegmentStart; +public: + ScMultiSelIter( const ScMultiSel& rMultiSel, SCCOL nCol ); + ~ScMultiSelIter(); + + bool Next( SCROW& rTop, SCROW& rBottom ); + const ScFlatBoolRowSegments& GetRowSegments() const { return aRowSegs; } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/segmenttree.hxx b/sc/inc/segmenttree.hxx index 72d45b6..3a2d128 100644 --- a/sc/inc/segmenttree.hxx +++ b/sc/inc/segmenttree.hxx @@ -68,7 +68,7 @@ public: bool setTrue(SCROW nRow1, SCROW nRow2); bool setFalse(SCROW nRow1, SCROW nRow2); - bool getRangeData(SCROW nRow, RangeData& rData); + bool getRangeData(SCROW nRow, RangeData& rData) const; bool getRangeDataLeaf(SCROW nRow, RangeData& rData); void removeSegment(SCROW nRow1, SCROW nRow2); void insertSegment(SCROW nRow, SCROW nSize, bool bSkipStartBoundary); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index d4b5a2e..18b4622 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -314,8 +314,8 @@ bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) c if (rMark.IsMultiMarked()) { - ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol ); - while (aMarkIter.Next( nTop, nBottom ) && !bFound) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom ) && !bFound) { if (pAttrArray->HasAttrib( nTop, nBottom, nMask )) bFound = true; @@ -339,11 +339,11 @@ void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkD if ( rMark.IsMultiMarked() ) { - const ScMarkArray* pArray = rMark.GetArray() + nCol; - if ( pArray->HasMarks() ) + const ScMultiSel& rMultiSel = rMark.GetMultiSelData(); + if ( rMultiSel.HasMarks( nCol ) ) { - ScMarkArrayIter aMarkIter( pArray ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMultiSel, nCol ); + while (aMultiIter.Next( nTop, nBottom )) pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep ); } } @@ -430,8 +430,8 @@ SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData if ( rMark.IsMultiMarked() ) { - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) { pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray ); bFound = true; @@ -453,8 +453,8 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark ) if ( pAttrArray && rMark.IsMultiMarked() ) { - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) pAttrArray->ChangeIndent(nTop, nBottom, bIncrement); } } @@ -466,8 +466,8 @@ void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& r if ( pAttrArray && rMark.IsMultiMarked() ) { - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) pAttrArray->ClearItems(nTop, nBottom, pWhich); } } @@ -479,8 +479,8 @@ void ScColumn::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rM if ( rMark.IsMultiMarked() ) { - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) DeleteArea(nTop, nBottom, nDelFlag, bBroadcast); } } @@ -569,8 +569,8 @@ void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& if ( rMark.IsMultiMarked() ) { - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) pAttrArray->ApplyStyleArea(nTop, nBottom, const_cast<ScStyleSheet*>(&rStyle)); } } @@ -586,8 +586,8 @@ void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark, if (rMark.IsMultiMarked()) { - ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol ); - while (aMarkIter.Next( nTop, nBottom )) + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); + while (aMultiIter.Next( nTop, nBottom )) pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly ); } } @@ -611,10 +611,10 @@ const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& const ScStyleSheet* pStyle = nullptr; const ScStyleSheet* pNewStyle; - ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol ); + ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol ); SCROW nTop; SCROW nBottom; - while (bEqual && aMarkIter.Next( nTop, nBottom )) + while (bEqual && aMultiIter.Next( nTop, nBottom )) { ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom ); SCROW nRow; @@ -1635,7 +1635,7 @@ void ScColumn::CopyToColumn( SCROW nStart, nEnd; if (pMarkData && pMarkData->IsMultiMarked()) { - ScMarkArrayIter aIter( pMarkData->GetArray()+nCol ); + ScMultiSelIter aIter( pMarkData->GetMultiSelData(), nCol ); while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 ) { @@ -3467,7 +3467,10 @@ SCsROW ScColumn::SearchStyle( if (bInSelection) { if (rMark.IsMultiMarked()) - return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, rMark.GetArray()+nCol); + { + ScMarkArray aArray(rMark.GetMarkArray(nCol)); + return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, &aArray); + } else return -1; } @@ -3482,8 +3485,11 @@ bool ScColumn::SearchStyleRange( if (bInSelection) { if (rMark.IsMultiMarked()) + { + ScMarkArray aArray(rMark.GetMarkArray(nCol)); return pAttrArray->SearchStyleRange( - rRow, rEndRow, pSearchStyle, bUp, rMark.GetArray() + nCol); + rRow, rEndRow, pSearchStyle, bUp, &aArray); + } else return false; } diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 4737121..c48c5a4 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1117,7 +1117,7 @@ void ScColumn::MixMarked( if (rMark.IsMultiMarked()) { - ScMarkArrayIter aIter( rMark.GetArray()+nCol ); + ScMultiSelIter aIter( rMark.GetMultiSelData(), nCol ); while (aIter.Next( nRow1, nRow2 )) MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, rSrcCol); } diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 33319cb..0979781 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -624,17 +624,17 @@ void ScDocument::FillInfo( if (pMarkData && pMarkData->IsMultiMarked()) { // Block marks - const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX; + ScMarkArray aThisMarkArr(pMarkData->GetMarkArray( nX )); nArrRow = 1; nCurRow = nRow1; // single rows nThisRow = nRow1; // End of range - if ( pThisMarkArr->Search( nRow1, nIndex ) ) + if ( aThisMarkArr.Search( nRow1, nIndex ) ) { do { - nThisRow=pThisMarkArr->pData[nIndex].nRow; // End of range - const bool bThisMarked=pThisMarkArr->pData[nIndex].bMarked; + nThisRow=aThisMarkArr.pData[nIndex].nRow; // End of range + const bool bThisMarked=aThisMarkArr.pData[nIndex].bMarked; do { @@ -661,7 +661,7 @@ void ScDocument::FillInfo( while (nCurRow <= nThisRow && nCurRow <= nRow2); ++nIndex; } - while ( nIndex < pThisMarkArr->nCount && nThisRow < nRow2 ); + while ( nIndex < aThisMarkArr.nCount && nThisRow < nRow2 ); } } } @@ -801,10 +801,10 @@ void ScDocument::FillInfo( && nStartY <= (SCsROW) nBlockEndY ); if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked) { - const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX; + ScMarkArray aThisMarkArr(pMarkData->GetMarkArray( nStartX )); SCSIZE nIndex; - if ( pThisMarkArr->Search( nStartY, nIndex ) ) - bCellMarked=pThisMarkArr->pData[nIndex].bMarked; + if ( aThisMarkArr.Search( nStartY, nIndex ) ) + bCellMarked=aThisMarkArr.pData[nIndex].bMarked; } pInfo->bMarked = bCellMarked; diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx index f21ce8d..66bfa0e 100644 --- a/sc/source/core/data/markarr.cxx +++ b/sc/source/core/data/markarr.cxx @@ -33,6 +33,17 @@ ScMarkArray::ScMarkArray() : // special case "no marks" with pData = NULL } +// Move constructor +ScMarkArray::ScMarkArray( ScMarkArray&& rArray ) : + nCount( rArray.nCount ), + nLimit( rArray.nLimit ), + pData( rArray.pData ) +{ + rArray.nCount = 0; + rArray.nLimit = 0; + rArray.pData = nullptr; +} + ScMarkArray::~ScMarkArray() { delete[] pData; diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx index 137a2e4..154a693 100644 --- a/sc/source/core/data/markdata.cxx +++ b/sc/source/core/data/markdata.cxx @@ -19,19 +19,21 @@ #include "markdata.hxx" #include "markarr.hxx" +#include "markmulti.hxx" #include "rangelst.hxx" +#include "segmenttree.hxx" #include <columnspanset.hxx> #include <fstalgorithm.hxx> +#include <unordered_map> #include <osl/diagnose.h> #include <mdds/flat_segment_tree.hpp> -// STATIC DATA ----------------------------------------------------------- ScMarkData::ScMarkData() : maTabMarked(), - pMultiSel( nullptr ) + aMultiSel() { ResetMark(); } @@ -40,19 +42,16 @@ ScMarkData::ScMarkData(const ScMarkData& rData) : maTabMarked( rData.maTabMarked ), aMarkRange( rData.aMarkRange ), aMultiRange( rData.aMultiRange ), - pMultiSel( nullptr ) + aMultiSel( rData.aMultiSel ), + aTopEnvelope( rData.aTopEnvelope ), + aBottomEnvelope( rData.aBottomEnvelope ), + aLeftEnvelope( rData.aLeftEnvelope ), + aRightEnvelope( rData.aRightEnvelope ) { bMarked = rData.bMarked; bMultiMarked = rData.bMultiMarked; bMarking = rData.bMarking; bMarkIsNeg = rData.bMarkIsNeg; - - if (rData.pMultiSel) - { - pMultiSel = new ScMarkArray[MAXCOLCOUNT]; - for (SCCOL j=0; j<MAXCOLCOUNT; j++) - rData.pMultiSel[j].CopyMarksTo( pMultiSel[j] ); - } } ScMarkData& ScMarkData::operator=(const ScMarkData& rData) @@ -60,40 +59,37 @@ ScMarkData& ScMarkData::operator=(const ScMarkData& rData) if ( &rData == this ) return *this; - delete[] pMultiSel; - pMultiSel = nullptr; - aMarkRange = rData.aMarkRange; aMultiRange = rData.aMultiRange; bMarked = rData.bMarked; bMultiMarked = rData.bMultiMarked; bMarking = rData.bMarking; bMarkIsNeg = rData.bMarkIsNeg; + aTopEnvelope = rData.aTopEnvelope; + aBottomEnvelope = rData.aBottomEnvelope; + aLeftEnvelope = rData.aLeftEnvelope; + aRightEnvelope = rData.aRightEnvelope; maTabMarked = rData.maTabMarked; - - if (rData.pMultiSel) - { - pMultiSel = new ScMarkArray[MAXCOLCOUNT]; - for (SCCOL j=0; j<MAXCOLCOUNT; j++) - rData.pMultiSel[j].CopyMarksTo( pMultiSel[j] ); - } + aMultiSel = rData.aMultiSel; return *this; } ScMarkData::~ScMarkData() { - delete[] pMultiSel; } void ScMarkData::ResetMark() { - delete[] pMultiSel; - pMultiSel = nullptr; + aMultiSel.Clear(); bMarked = bMultiMarked = false; bMarking = bMarkIsNeg = false; + aTopEnvelope.RemoveAll(); + aBottomEnvelope.RemoveAll(); + aLeftEnvelope.RemoveAll(); + aRightEnvelope.RemoveAll(); } void ScMarkData::SetMarkArea( const ScRange& rRange ) @@ -121,17 +117,18 @@ void ScMarkData::GetMultiMarkArea( ScRange& rRange ) const rRange = aMultiRange; } -void ScMarkData::SetMultiMarkArea( const ScRange& rRange, bool bMark ) +void ScMarkData::SetMultiMarkArea( const ScRange& rRange, bool bMark, bool bSetupMulti ) { - if (!pMultiSel) + if ( aMultiSel.IsEmpty() ) { - pMultiSel = new ScMarkArray[MAXCOL+1]; - // if simple mark range is set, copy to multi marks - if ( bMarked && !bMarkIsNeg ) + if ( bMarked && !bMarkIsNeg && !bSetupMulti ) { bMarked = false; - SetMultiMarkArea( aMarkRange ); + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + PutInOrder( nStartCol, nEndCol ); + SetMultiMarkArea( aMarkRange, true, true ); } } @@ -142,9 +139,7 @@ void ScMarkData::SetMultiMarkArea( const ScRange& rRange, bool bMark ) PutInOrder( nStartRow, nEndRow ); PutInOrder( nStartCol, nEndCol ); - SCCOL nCol; - for (nCol=nStartCol; nCol<=nEndCol; nCol++) - pMultiSel[nCol].SetMarkArea( nStartRow, nEndRow, bMark ); + aMultiSel.SetMarkArea( nStartCol, nEndCol, nStartRow, nEndRow, bMark ); if ( bMultiMarked ) // Update aMultiRange { @@ -247,27 +242,25 @@ void ScMarkData::MarkToSimple() if ( bMultiMarked ) { - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - ScRange aNew = aMultiRange; bool bOk = false; SCCOL nStartCol = aNew.aStart.Col(); SCCOL nEndCol = aNew.aEnd.Col(); - while ( nStartCol < nEndCol && !pMultiSel[nStartCol].HasMarks() ) + while ( nStartCol < nEndCol && !aMultiSel.HasMarks( nStartCol ) ) ++nStartCol; - while ( nStartCol < nEndCol && !pMultiSel[nEndCol].HasMarks() ) + while ( nStartCol < nEndCol && !aMultiSel.HasMarks( nEndCol ) ) --nEndCol; // Rows are only taken from MarkArray SCROW nStartRow, nEndRow; - if ( pMultiSel[nStartCol].HasOneMark( nStartRow, nEndRow ) ) + if ( aMultiSel.HasOneMark( nStartCol, nStartRow, nEndRow ) ) { bOk = true; SCROW nCmpStart, nCmpEnd; for (SCCOL nCol=nStartCol+1; nCol<=nEndCol && bOk; nCol++) - if ( !pMultiSel[nCol].HasOneMark( nCmpStart, nCmpEnd ) + if ( !aMultiSel.HasOneMark( nCol, nCmpStart, nCmpEnd ) || nCmpStart != nStartRow || nCmpEnd != nEndRow ) bOk = false; } @@ -298,8 +291,7 @@ bool ScMarkData::IsCellMarked( SCCOL nCol, SCROW nRow, bool bNoSimple ) const { //TODO: test here for negative Marking ? - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - return pMultiSel[nCol].GetMark( nRow ); + return aMultiSel.GetMark( nCol, nRow ); } return false; @@ -315,7 +307,7 @@ bool ScMarkData::IsColumnMarked( SCCOL nCol ) const aMarkRange.aStart.Row() == 0 && aMarkRange.aEnd.Row() == MAXROW ) return true; - if ( bMultiMarked && pMultiSel[nCol].IsAllMarked(0,MAXROW) ) + if ( bMultiMarked && aMultiSel.IsAllMarked( nCol, 0, MAXROW ) ) return true; return false; @@ -332,13 +324,7 @@ bool ScMarkData::IsRowMarked( SCROW nRow ) const return true; if ( bMultiMarked ) - { - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - for (SCCOL nCol=0; nCol<=MAXCOL; nCol++) - if (!pMultiSel[nCol].GetMark(nRow)) - return false; - return true; - } + return aMultiSel.IsRowMarked( nRow ); return false; } @@ -381,15 +367,13 @@ void ScMarkData::FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const if ( bMultiMarked ) { - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - SCTAB nTab = aMultiRange.aStart.Tab(); SCCOL nStartCol = aMultiRange.aStart.Col(); SCCOL nEndCol = aMultiRange.aEnd.Col(); for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) { - if (pMultiSel[nCol].HasMarks()) + if (aMultiSel.HasMarks( nCol )) { // Feeding column-wise fragments to ScRangeList::Join() is a // huge bottleneck, speed this up for multiple columns @@ -399,14 +383,14 @@ void ScMarkData::FillRangeListWithMarks( ScRangeList* pList, bool bClear ) const SCCOL nToCol = nCol+1; for ( ; nToCol <= nEndCol; ++nToCol) { - if (!pMultiSel[nCol].HasEqualRowsMarked( pMultiSel[nToCol])) + if (!aMultiSel.HasEqualRowsMarked(nCol, nToCol)) break; } --nToCol; ScRange aRange( nCol, 0, nTab, nToCol, 0, nTab ); SCROW nTop, nBottom; - ScMarkArrayIter aMarkIter( &pMultiSel[nCol] ); - while ( aMarkIter.Next( nTop, nBottom ) ) + ScMultiSelIter aMultiIter( aMultiSel, nCol ); + while ( aMultiIter.Next( nTop, nBottom ) ) { aRange.aStart.SetRow( nTop ); aRange.aEnd.SetRow( nBottom ); @@ -486,15 +470,17 @@ bool ScMarkData::IsAllMarked( const ScRange& rRange ) const if ( !bMultiMarked ) return false; - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - SCCOL nStartCol = rRange.aStart.Col(); SCROW nStartRow = rRange.aStart.Row(); SCCOL nEndCol = rRange.aEnd.Col(); SCROW nEndRow = rRange.aEnd.Row(); bool bOk = true; + + if ( nStartCol == 0 && nEndCol == MAXCOL ) + return aMultiSel.IsRowRangeMarked( nStartRow, nEndRow ); + for (SCCOL nCol=nStartCol; nCol<=nEndCol && bOk; nCol++) - if ( !pMultiSel[nCol].IsAllMarked( nStartRow, nEndRow ) ) + if ( !aMultiSel.IsAllMarked( nCol, nStartRow, nEndRow ) ) bOk = false; return bOk; @@ -505,9 +491,7 @@ SCsROW ScMarkData::GetNextMarked( SCCOL nCol, SCsROW nRow, bool bUp ) const if ( !bMultiMarked ) return nRow; - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - - return pMultiSel[nCol].GetNextMarked( nRow, bUp ); + return aMultiSel.GetNextMarked( nCol, nRow, bUp ); } bool ScMarkData::HasMultiMarks( SCCOL nCol ) const @@ -515,9 +499,7 @@ bool ScMarkData::HasMultiMarks( SCCOL nCol ) const if ( !bMultiMarked ) return false; - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - - return pMultiSel[nCol].HasMarks(); + return aMultiSel.HasMarks( nCol ); } bool ScMarkData::HasAnyMultiMarks() const @@ -525,13 +507,7 @@ bool ScMarkData::HasAnyMultiMarks() const if ( !bMultiMarked ) return false; - OSL_ENSURE(pMultiSel, "bMultiMarked, but pMultiSel == 0"); - - for (SCCOL nCol=0; nCol<=MAXCOL; nCol++) - if ( pMultiSel[nCol].HasMarks() ) - return true; - - return false; // no + return aMultiSel.HasAnyMarks(); } void ScMarkData::InsertTab( SCTAB nTab ) @@ -553,6 +529,261 @@ void ScMarkData::DeleteTab( SCTAB nTab ) maTabMarked.swap(tabMarked); } +static void lcl_AddRanges(ScRange& rRangeDest, const ScRange& rNewRange ) +{ + SCCOL nStartCol = rNewRange.aStart.Col(); + SCROW nStartRow = rNewRange.aStart.Row(); + SCCOL nEndCol = rNewRange.aEnd.Col(); + SCROW nEndRow = rNewRange.aEnd.Row(); + PutInOrder( nStartRow, nEndRow ); + PutInOrder( nStartCol, nEndCol ); + if ( nStartCol < rRangeDest.aStart.Col() ) + rRangeDest.aStart.SetCol( nStartCol ); + if ( nStartRow < rRangeDest.aStart.Row() ) + rRangeDest.aStart.SetRow( nStartRow ); + if ( nEndCol > rRangeDest.aEnd.Col() ) + rRangeDest.aEnd.SetCol( nEndCol ); + if ( nEndRow > rRangeDest.aEnd.Row() ) + rRangeDest.aEnd.SetRow( nEndRow ); +} + +void ScMarkData::GetSelectionCover( ScRange& rRange ) +{ + if( bMultiMarked ) + { + rRange = aMultiRange; + SCCOL nStartCol = aMultiRange.aStart.Col(), nEndCol = aMultiRange.aEnd.Col(); + PutInOrder( nStartCol, nEndCol ); + nStartCol = ( nStartCol == 0 ) ? nStartCol : nStartCol - 1; + nEndCol = ( nEndCol == MAXCOL ) ? nEndCol : nEndCol + 1; + std::unique_ptr<ScFlatBoolRowSegments> pPrevColMarkedRows; + std::unique_ptr<ScFlatBoolRowSegments> pCurColMarkedRows; + std::unordered_map<SCROW,ScFlatBoolColSegments> aRowToColSegmentsInTopEnvelope; + std::unordered_map<SCROW,ScFlatBoolColSegments> aRowToColSegmentsInBottomEnvelope; + ScFlatBoolRowSegments aNoRowsMarked; + aNoRowsMarked.setFalse( 0, MAXROW ); + + bool bPrevColUnMarked = false; + + for ( SCCOL nCol=nStartCol; nCol <= nEndCol; nCol++ ) + { + SCROW nTop, nBottom; + bool bCurColUnMarked = !aMultiSel.HasMarks( nCol ); + if ( !bCurColUnMarked ) + { + pCurColMarkedRows.reset( new ScFlatBoolRowSegments() ); + pCurColMarkedRows->setFalse( 0, MAXROW ); + ScMultiSelIter aMultiIter( aMultiSel, nCol ); + ScFlatBoolRowSegments::ForwardIterator aPrevItr ( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked ); // For finding left envelope + ScFlatBoolRowSegments::ForwardIterator aPrevItr1( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked ); // For finding right envelope + SCROW nTopPrev = 0, nBottomPrev = 0; // For right envelope + while ( aMultiIter.Next( nTop, nBottom ) ) + { + pCurColMarkedRows->setTrue( nTop, nBottom ); + if( bPrevColUnMarked && ( nCol > nStartCol )) + { + ScRange aAddRange(nCol - 1, nTop, aMultiRange.aStart.Tab(), + nCol - 1, nBottom, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Left envelope + aLeftEnvelope.Append( aAddRange ); + } + else if( nCol > nStartCol ) + { + SCROW nTop1 = nTop, nBottom1 = nTop; + while( nTop1 <= nBottom && nBottom1 <= nBottom ) + { + bool bRangeMarked = false; + aPrevItr.getValue( nTop1, bRangeMarked ); + if( bRangeMarked ) + { + nTop1 = aPrevItr.getLastPos() + 1; + nBottom1 = nTop1; + } + else + { + nBottom1 = aPrevItr.getLastPos(); + if( nBottom1 > nBottom ) + nBottom1 = nBottom; + ScRange aAddRange( nCol - 1, nTop1, aMultiRange.aStart.Tab(), + nCol - 1, nBottom1, aMultiRange.aStart.Tab() ); + lcl_AddRanges( rRange, aAddRange ); // Left envelope + aLeftEnvelope.Append( aAddRange ); + nTop1 = ++nBottom1; + } + } + while( nTopPrev <= nBottom && nBottomPrev <= nBottom ) + { + bool bRangeMarked; + aPrevItr1.getValue( nTopPrev, bRangeMarked ); + if( bRangeMarked ) + { + nBottomPrev = aPrevItr1.getLastPos(); + if( nTopPrev < nTop ) + { + if( nBottomPrev >= nTop ) + { + nBottomPrev = nTop - 1; + ScRange aAddRange( nCol, nTopPrev, aMultiRange.aStart.Tab(), + nCol, nBottomPrev, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Right envelope + aRightEnvelope.Append( aAddRange ); + nTopPrev = nBottomPrev = (nBottom + 1); + } + else + { + ScRange aAddRange( nCol, nTopPrev, aMultiRange.aStart.Tab(), + nCol, nBottomPrev, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Right envelope + aRightEnvelope.Append( aAddRange ); + nTopPrev = ++nBottomPrev; + } + } + else + nTopPrev = nBottomPrev = ( nBottom + 1 ); + } + else + { + nBottomPrev = aPrevItr1.getLastPos(); + nTopPrev = ++nBottomPrev; + } + } + } + if( nTop ) + { + ScRange aAddRange( nCol, nTop - 1, aMultiRange.aStart.Tab(), + nCol, nTop - 1, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Top envelope + aRowToColSegmentsInTopEnvelope[nTop - 1].setTrue( nCol, nCol ); + } + if( nBottom < MAXROW ) + { + ScRange aAddRange(nCol, nBottom + 1, aMultiRange.aStart.Tab(), + nCol, nBottom + 1, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Bottom envelope + aRowToColSegmentsInBottomEnvelope[nBottom + 1].setTrue( nCol, nCol ); + } + } + + while( nTopPrev <= MAXROW && nBottomPrev <= MAXROW && ( nCol > nStartCol ) ) + { + bool bRangeMarked; + aPrevItr1.getValue( nTopPrev, bRangeMarked ); + if( bRangeMarked ) + { + nBottomPrev = aPrevItr1.getLastPos(); + ScRange aAddRange(nCol, nTopPrev, aMultiRange.aStart.Tab(), + nCol, nBottomPrev, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Right envelope + aRightEnvelope.Append( aAddRange ); + nTopPrev = ++nBottomPrev; + } + else + { + nBottomPrev = aPrevItr1.getLastPos(); + nTopPrev = ++nBottomPrev; + } + } + } + else if( nCol > nStartCol ) + { + bPrevColUnMarked = true; + SCROW nTopPrev = 0, nBottomPrev = 0; + bool bRangeMarked = false; + ScFlatBoolRowSegments::ForwardIterator aPrevItr( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked ); + while( nTopPrev <= MAXROW && nBottomPrev <= MAXROW ) + { + aPrevItr.getValue(nTopPrev, bRangeMarked); + if( bRangeMarked ) + { + nBottomPrev = aPrevItr.getLastPos(); + ScRange aAddRange(nCol, nTopPrev, aMultiRange.aStart.Tab(), + nCol, nBottomPrev, aMultiRange.aStart.Tab()); + lcl_AddRanges( rRange, aAddRange ); // Right envelope + aRightEnvelope.Append( aAddRange ); + nTopPrev = ++nBottomPrev; + } + else + { + nBottomPrev = aPrevItr.getLastPos(); + nTopPrev = ++nBottomPrev; + } + } + } + if ( bCurColUnMarked ) + pPrevColMarkedRows.reset( nullptr ); + else + pPrevColMarkedRows.reset( pCurColMarkedRows.release() ); + } + for( auto& rKV : aRowToColSegmentsInTopEnvelope ) + { + SCCOL nStart = nStartCol; + ScFlatBoolColSegments::RangeData aRange; + while( nStart <= nEndCol ) + { + if( !rKV.second.getRangeData( nStart, aRange ) ) + break; + if( aRange.mbValue ) // is marked + aTopEnvelope.Append( ScRange( aRange.mnCol1, rKV.first, aMultiRange.aStart.Tab(), + aRange.mnCol2, rKV.first, aMultiRange.aStart.Tab() ) ); + nStart = aRange.mnCol2 + 1; + } + } + for( auto& rKV : aRowToColSegmentsInBottomEnvelope ) + { + SCCOL nStart = nStartCol; + ScFlatBoolColSegments::RangeData aRange; + while( nStart <= nEndCol ) + { + if( !rKV.second.getRangeData( nStart, aRange ) ) + break; + if( aRange.mbValue ) // is marked + aBottomEnvelope.Append( ScRange( aRange.mnCol1, rKV.first, aMultiRange.aStart.Tab(), + aRange.mnCol2, rKV.first, aMultiRange.aStart.Tab() ) ); + nStart = aRange.mnCol2 + 1; + } + } + } + else if( bMarked ) + { + aMarkRange.PutInOrder(); + SCROW nRow1, nRow2, nRow1New, nRow2New; + SCCOL nCol1, nCol2, nCol1New, nCol2New; + SCTAB nTab1, nTab2; + aMarkRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + nCol1New = nCol1; + nCol2New = nCol2; + nRow1New = nRow1; + nRow2New = nRow2; + // Each envelope will have zero or more ranges for single rectangle selection. + if( nCol1 > 0 ) + { + aLeftEnvelope.Append( ScRange( nCol1 - 1, nRow1, nTab1, nCol1 - 1, nRow2, nTab2 ) ); + --nCol1New; + } + if( nRow1 > 0 ) + { + aTopEnvelope.Append( ScRange( nCol1, nRow1 - 1, nTab1, nCol2, nRow1 - 1, nTab2 ) ); + --nRow1New; + } + if( nCol2 < MAXCOL ) + { + aRightEnvelope.Append( ScRange( nCol2 + 1, nRow1, nTab1, nCol2 + 1, nRow2, nTab2 ) ); + ++nCol2New; + } + if( nRow2 < MAXROW ) + { + aBottomEnvelope.Append( ScRange( nCol1, nRow2 + 1, nTab1, nCol2, nRow2 + 1, nTab2 ) ); + ++nRow2New; + } + rRange = ScRange( nCol1New, nRow1New, nTab1, nCol2New, nRow2New, nTab2 ); + } +} + +ScMarkArray ScMarkData::GetMarkArray( SCCOL nCol ) const +{ + return aMultiSel.GetMarkArray( nCol ); +} + //iterators ScMarkData::iterator ScMarkData::begin() { diff --git a/sc/source/core/data/markmulti.cxx b/sc/source/core/data/markmulti.cxx new file mode 100644 index 0000000..07502c1 --- /dev/null +++ b/sc/source/core/data/markmulti.cxx @@ -0,0 +1,348 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ... etc. - the rest is truncated
_______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
