sc/Library_sc.mk | 1 sc/source/ui/docshell/dbdocfun.cxx | 217 ---------------------- sc/source/ui/inc/dbdocfun.hxx | 1 sc/source/ui/inc/operation/SortOperation.hxx | 41 ++++ sc/source/ui/operation/SortOperation.cxx | 263 +++++++++++++++++++++++++++ 5 files changed, 310 insertions(+), 213 deletions(-)
New commits: commit 0f38f515dea122b34bd8cf2b83e9934c9f84ddd1 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Wed Jan 28 12:22:14 2026 +0900 Commit: Miklos Vajna <[email protected]> CommitDate: Tue Feb 10 14:52:15 2026 +0100 sc: Introduce SortOperation and move the impl. from ScDBDocFunc Sort operation using implementation from ScDBDocFunc. No functional change, but logging changed to SAL_WARN. Change-Id: I6b23a3296a2bce9fdeef9c2774d6f9b34bd30da5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198732 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 652f41d9eede..74accd38dc06 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -532,6 +532,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/operation/DeleteCellOperation \ sc/source/ui/operation/DeleteContentOperation \ sc/source/ui/operation/Operation \ + sc/source/ui/operation/SortOperation \ sc/source/ui/pagedlg/areasdlg \ sc/source/ui/pagedlg/tphfedit \ sc/source/ui/sidebar/AlignmentPropertyPanel \ diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index b9baf4131982..ba79111acad3 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -58,6 +58,7 @@ #include <chartlis.hxx> #include <ChartTools.hxx> #include <SheetViewOperationsTester.hxx> +#include <operation/SortOperation.hxx> #include <memory> @@ -608,220 +609,10 @@ bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, return bDone; } -bool ScDBDocFunc::SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool bRecord, bool bPaint, bool bApi ) +bool ScDBDocFunc::SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool bRecord, bool bPaint, bool bApi) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1, - rSortParam.nCol2, rSortParam.nRow2 ); - if (!pDBData) - { - OSL_FAIL( "Sort: no DBData" ); - return false; - } - - bool bCopy = !rSortParam.bInplace; - if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 && - rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab ) - bCopy = false; - - ScSortParam aLocalParam( rSortParam ); - if ( bCopy ) - { - // Copy the data range to the destination then move the sort range to it. - ScRange aSrcRange(rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab); - ScAddress aDestPos(rSortParam.nDestCol,rSortParam.nDestRow,rSortParam.nDestTab); - - ScDocFunc& rDocFunc = rDocShell.GetDocFunc(); - bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, bRecord, bPaint, bApi); - - if (!bRet) - return false; - - aLocalParam.MoveToDest(); - nTab = aLocalParam.nDestTab; - } - - // tdf#119804: If there is a header row/column, it won't be affected by - // sorting; so we can exclude it from the test. - SCROW nStartingRowToEdit = aLocalParam.nRow1; - SCCOL nStartingColToEdit = aLocalParam.nCol1; - if ( aLocalParam.bHasHeader ) - { - if ( aLocalParam.bByRow ) - nStartingRowToEdit++; - else - nStartingColToEdit++; - } - - if (!CheckSheetViewProtection(sc::OperationType::Sort)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( - rDoc, nTab, nStartingColToEdit, nStartingRowToEdit, - aLocalParam.nCol2, aLocalParam.nRow2, true /*bNoMatrixAtAll*/); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - const ScInputOptions aInputOption = ScModule::get()->GetInputOptions(); - const bool bUpdateRefs = aInputOption.GetSortRefUpdate(); - - // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or - // column (depending on direction) in any case, not just if it has headers, - // so empty leading cells will be sorted to the end. - // aLocalParam.nCol/Row will encompass data content only, extras in - // aLocalParam.aDataAreaExtras. - bool bShrunk = false; - aLocalParam.aDataAreaExtras.resetArea(); - rDoc.ShrinkToUsedDataArea(bShrunk, nTab, aLocalParam.nCol1, aLocalParam.nRow1, - aLocalParam.nCol2, aLocalParam.nRow2, false, aLocalParam.bByRow, - !aLocalParam.bByRow, - (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? - &aLocalParam.aDataAreaExtras : nullptr)); - - SCROW nStartRow = aLocalParam.nRow1; - if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2) - ++nStartRow; - - SCCOL nOverallCol1 = aLocalParam.nCol1; - SCROW nOverallRow1 = aLocalParam.nRow1; - SCCOL nOverallCol2 = aLocalParam.nCol2; - SCROW nOverallRow2 = aLocalParam.nRow2; - if (aLocalParam.aDataAreaExtras.anyExtrasWanted()) - { - // Trailing empty excess columns/rows are excluded from being sorted, - // they stick at the end. Clip them. - const ScDataAreaExtras::Clip eClip = (aLocalParam.bByRow ? - ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col); - aLocalParam.aDataAreaExtras.GetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2, eClip); - // Make it permanent. - aLocalParam.aDataAreaExtras.SetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2); - - if (bUpdateRefs) - { - // With update references the entire range needs to be handled as - // one entity for references pointing within to be moved along, - // even when there's no data content. For huge ranges we may be - // DOOMed then. - aLocalParam.nCol1 = nOverallCol1; - aLocalParam.nRow1 = nOverallRow1; - aLocalParam.nCol2 = nOverallCol2; - aLocalParam.nRow2 = nOverallRow2; - } - } - - if (aLocalParam.aDataAreaExtras.mbCellFormats - && rDoc.HasAttrib( nOverallCol1, nStartRow, nTab, nOverallCol2, nOverallRow2, nTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped)) - { - // Merge attributes would be mixed up during sorting. - if (!bApi) - rDocShell.ErrorMessage(STR_SORT_ERR_MERGED); - return false; - } - - // execute - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - // Calculate the script types for all cells in the sort range beforehand. - // This will speed up the row height adjustment that takes place after the - // sort. - rDoc.UpdateScriptTypes( - ScAddress(aLocalParam.nCol1,nStartRow,nTab), - aLocalParam.nCol2-aLocalParam.nCol1+1, - aLocalParam.nRow2-nStartRow+1); - - // No point adjusting row heights after the sort when all rows have the same height. - bool bUniformRowHeight = rDoc.HasUniformRowHeight(nTab, nStartRow, nOverallRow2); - - bool bRepeatQuery = false; // repeat existing filter? - ScQueryParam aQueryParam; - pDBData->GetQueryParam( aQueryParam ); - if ( aQueryParam.GetEntry(0).bDoQuery ) - bRepeatQuery = true; - - sc::ReorderParam aUndoParam; - - // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set) - if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort) - { - ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true); - if (!bRepeatQuery) - bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab); - rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam); - } - - if (bRecord) - { - // Set up an undo object. - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique<sc::UndoSort>(&rDocShell, aUndoParam)); - } - - pDBData->SetSortParam(rSortParam); - // Remember additional settings on anonymous database ranges. - if (pDBData == rDoc.GetAnonymousDBData( nTab) || rDoc.GetDBCollection()->getAnonDBs().has( pDBData)) - pDBData->UpdateFromSortParam( rSortParam); - - if (SfxViewShell* pKitSomeViewForThisDoc = comphelper::LibreOfficeKit::isActive() ? - rDocShell.GetBestViewShell(false) : nullptr) - { - SfxViewShell* pViewShell = SfxViewShell::GetFirst(); - while (pViewShell) - { - ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); - if (pTabViewShell && pTabViewShell->GetDocId() == pKitSomeViewForThisDoc->GetDocId()) - { - if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)) - pPosHelper->invalidateByIndex(nStartRow); - } - pViewShell = SfxViewShell::GetNext(*pViewShell); - } - - ScTabViewShell::notifyAllViewsSheetGeomInvalidation( - pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/, - true /* bHidden */, true /* bFiltered */, true /* bGroups */, nTab); - } - - if (nStartRow <= aLocalParam.nRow2) - { - ScRange aDirtyRange( - aLocalParam.nCol1, nStartRow, nTab, - aLocalParam.nCol2, aLocalParam.nRow2, nTab); - rDoc.SetDirty( aDirtyRange, true ); - } - - if (bPaint) - { - PaintPartFlags nPaint = PaintPartFlags::Grid; - SCCOL nStartX = nOverallCol1; - SCROW nStartY = nOverallRow1; - SCCOL nEndX = nOverallCol2; - SCROW nEndY = nOverallRow2; - if ( bRepeatQuery ) - { - nPaint |= PaintPartFlags::Left; - nStartX = 0; - nEndX = rDoc.MaxCol(); - } - rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint); - } - - if (!bUniformRowHeight && nStartRow <= nOverallRow2) - rDocShell.AdjustRowHeight(nStartRow, nOverallRow2, nTab); - - aModificator.SetDocumentModified(); - - return true; + sc::SortOperation aOperation(rDocShell, nTab, rSortParam, bRecord, bPaint, bApi); + return aOperation.run(); } bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam, diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx index 3639c2d0347c..d7dd1c377573 100644 --- a/sc/source/ui/inc/dbdocfun.hxx +++ b/sc/source/ui/inc/dbdocfun.hxx @@ -47,6 +47,7 @@ namespace sc class ScDBDocFunc { friend class ScDBFunc; +friend class SortOperation; private: ScDocShell& rDocShell; diff --git a/sc/source/ui/inc/operation/SortOperation.hxx b/sc/source/ui/inc/operation/SortOperation.hxx new file mode 100644 index 000000000000..a26360254273 --- /dev/null +++ b/sc/source/ui/inc/operation/SortOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include <sal/types.h> +#include <address.hxx> + +class ScDocShell; +class ScMarkData; +class ScDocFunc; +struct ScSortParam; +enum class InsertDeleteFlags : sal_Int32; + +namespace sc +{ +/** Operation which sorts cells in a sheet. */ +class SortOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + SCTAB mnTab; + ScSortParam const& mrSortParam; + bool mbPaint; + + bool runImplementation() override; + +public: + SortOperation(ScDocShell& rDocShell, SCTAB nTab, ScSortParam const& rSortParam, bool bRecord, + bool bPaint, bool bApi); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SortOperation.cxx b/sc/source/ui/operation/SortOperation.cxx new file mode 100644 index 000000000000..a01af92b6025 --- /dev/null +++ b/sc/source/ui/operation/SortOperation.cxx @@ -0,0 +1,263 @@ +/* -*- 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/. + */ + +#include <operation/SortOperation.hxx> + +#include <docfuncutil.hxx> +#include <docfunc.hxx> +#include <editable.hxx> +#include <markdata.hxx> +#include <SheetViewOperationsTester.hxx> +#include <editable.hxx> +#include <progress.hxx> +#include <undosort.hxx> +#include <scresid.hxx> +#include <scmod.hxx> +#include <dbdata.hxx> +#include <globstr.hrc> +#include <globalnames.hxx> +#include <tabvwsh.hxx> +#include <dociter.hxx> +#include <queryentry.hxx> +#include <inputopt.hxx> + +#include <memory> + +namespace sc +{ +SortOperation::SortOperation(ScDocShell& rDocShell, SCTAB nTab, const ScSortParam& rSortParam, + bool bRecord, bool bPaint, bool bApi) + : Operation(OperationType::Sort, bRecord, bApi) + , mrDocShell(rDocShell) + , mnTab(nTab) + , mrSortParam(rSortParam) + , mbPaint(bPaint) +{ +} + +bool SortOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScDBData* pDBData = rDoc.GetDBAtArea(mnTab, mrSortParam.nCol1, mrSortParam.nRow1, + mrSortParam.nCol2, mrSortParam.nRow2); + if (!pDBData) + { + SAL_WARN("sc", "Sort: no DBData"); + return false; + } + + bool bCopy = !mrSortParam.bInplace; + if (bCopy && mrSortParam.nDestCol == mrSortParam.nCol1 + && mrSortParam.nDestRow == mrSortParam.nRow1 && mrSortParam.nDestTab == mnTab) + bCopy = false; + + ScSortParam aLocalParam(mrSortParam); + if (bCopy) + { + // Copy the data range to the destination then move the sort range to it. + ScRange aSrcRange(mrSortParam.nCol1, mrSortParam.nRow1, mnTab, mrSortParam.nCol2, + mrSortParam.nRow2, mnTab); + ScAddress aDestPos(mrSortParam.nDestCol, mrSortParam.nDestRow, mrSortParam.nDestTab); + + ScDocFunc& rDocFunc = mrDocShell.GetDocFunc(); + bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, mbRecord, mbPaint, mbApi); + + if (!bRet) + return false; + + aLocalParam.MoveToDest(); + mnTab = aLocalParam.nDestTab; + } + + // tdf#119804: If there is a header row/column, it won't be affected by + // sorting; so we can exclude it from the test. + SCROW nStartingRowToEdit = aLocalParam.nRow1; + SCCOL nStartingColToEdit = aLocalParam.nCol1; + if (aLocalParam.bHasHeader) + { + if (aLocalParam.bByRow) + nStartingRowToEdit++; + else + nStartingColToEdit++; + } + + if (!checkSheetViewProtection()) + return false; + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, mnTab, nStartingColToEdit, nStartingRowToEdit, aLocalParam.nCol2, aLocalParam.nRow2, + true /*bNoMatrixAtAll*/); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + const ScInputOptions aInputOption = ScModule::get()->GetInputOptions(); + const bool bUpdateRefs = aInputOption.GetSortRefUpdate(); + + // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or + // column (depending on direction) in any case, not just if it has headers, + // so empty leading cells will be sorted to the end. + // aLocalParam.nCol/Row will encompass data content only, extras in + // aLocalParam.aDataAreaExtras. + bool bShrunk = false; + aLocalParam.aDataAreaExtras.resetArea(); + rDoc.ShrinkToUsedDataArea( + bShrunk, mnTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2, aLocalParam.nRow2, + false, aLocalParam.bByRow, !aLocalParam.bByRow, + (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? &aLocalParam.aDataAreaExtras : nullptr)); + + SCROW nStartRow = aLocalParam.nRow1; + if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2) + ++nStartRow; + + SCCOL nOverallCol1 = aLocalParam.nCol1; + SCROW nOverallRow1 = aLocalParam.nRow1; + SCCOL nOverallCol2 = aLocalParam.nCol2; + SCROW nOverallRow2 = aLocalParam.nRow2; + if (aLocalParam.aDataAreaExtras.anyExtrasWanted()) + { + // Trailing empty excess columns/rows are excluded from being sorted, + // they stick at the end. Clip them. + const ScDataAreaExtras::Clip eClip + = (aLocalParam.bByRow ? ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col); + aLocalParam.aDataAreaExtras.GetOverallRange(nOverallCol1, nOverallRow1, nOverallCol2, + nOverallRow2, eClip); + // Make it permanent. + aLocalParam.aDataAreaExtras.SetOverallRange(nOverallCol1, nOverallRow1, nOverallCol2, + nOverallRow2); + + if (bUpdateRefs) + { + // With update references the entire range needs to be handled as + // one entity for references pointing within to be moved along, + // even when there's no data content. For huge ranges we may be + // DOOMed then. + aLocalParam.nCol1 = nOverallCol1; + aLocalParam.nRow1 = nOverallRow1; + aLocalParam.nCol2 = nOverallCol2; + aLocalParam.nRow2 = nOverallRow2; + } + } + + if (aLocalParam.aDataAreaExtras.mbCellFormats + && rDoc.HasAttrib(nOverallCol1, nStartRow, mnTab, nOverallCol2, nOverallRow2, mnTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + // Merge attributes would be mixed up during sorting. + if (!mbApi) + mrDocShell.ErrorMessage(STR_SORT_ERR_MERGED); + return false; + } + + // execute + + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + // Calculate the script types for all cells in the sort range beforehand. + // This will speed up the row height adjustment that takes place after the + // sort. + rDoc.UpdateScriptTypes(ScAddress(aLocalParam.nCol1, nStartRow, mnTab), + aLocalParam.nCol2 - aLocalParam.nCol1 + 1, + aLocalParam.nRow2 - nStartRow + 1); + + // No point adjusting row heights after the sort when all rows have the same height. + bool bUniformRowHeight = rDoc.HasUniformRowHeight(mnTab, nStartRow, nOverallRow2); + + bool bRepeatQuery = false; // repeat existing filter? + ScQueryParam aQueryParam; + pDBData->GetQueryParam(aQueryParam); + if (aQueryParam.GetEntry(0).bDoQuery) + bRepeatQuery = true; + + sc::ReorderParam aUndoParam; + + // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set) + if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort) + { + ScProgress aProgress(&mrDocShell, ScResId(STR_PROGRESS_SORTING), 0, true); + if (!bRepeatQuery) + bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, mnTab); + rDoc.Sort(mnTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam); + } + + if (mbRecord) + { + // Set up an undo object. + mrDocShell.GetUndoManager()->AddUndoAction( + std::make_unique<sc::UndoSort>(&mrDocShell, aUndoParam)); + } + + pDBData->SetSortParam(mrSortParam); + // Remember additional settings on anonymous database ranges. + if (pDBData == rDoc.GetAnonymousDBData(mnTab) + || rDoc.GetDBCollection()->getAnonDBs().has(pDBData)) + pDBData->UpdateFromSortParam(mrSortParam); + + if (SfxViewShell* pKitSomeViewForThisDoc + = comphelper::LibreOfficeKit::isActive() ? mrDocShell.GetBestViewShell(false) : nullptr) + { + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); + if (pTabViewShell && pTabViewShell->GetDocId() == pKitSomeViewForThisDoc->GetDocId()) + { + if (ScPositionHelper* pPosHelper + = pTabViewShell->GetViewData().GetLOKHeightHelper(mnTab)) + pPosHelper->invalidateByIndex(nStartRow); + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + + ScTabViewShell::notifyAllViewsSheetGeomInvalidation( + pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/, + true /* bHidden */, true /* bFiltered */, true /* bGroups */, mnTab); + } + + if (nStartRow <= aLocalParam.nRow2) + { + ScRange aDirtyRange(aLocalParam.nCol1, nStartRow, mnTab, aLocalParam.nCol2, + aLocalParam.nRow2, mnTab); + rDoc.SetDirty(aDirtyRange, true); + } + + if (mbPaint) + { + PaintPartFlags nPaint = PaintPartFlags::Grid; + SCCOL nStartX = nOverallCol1; + SCROW nStartY = nOverallRow1; + SCCOL nEndX = nOverallCol2; + SCROW nEndY = nOverallRow2; + if (bRepeatQuery) + { + nPaint |= PaintPartFlags::Left; + nStartX = 0; + nEndX = rDoc.MaxCol(); + } + mrDocShell.PostPaint(ScRange(nStartX, nStartY, mnTab, nEndX, nEndY, mnTab), nPaint); + } + + if (!bUniformRowHeight && nStartRow <= nOverallRow2) + mrDocShell.AdjustRowHeight(nStartRow, nOverallRow2, mnTab); + + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
