config_host.mk.in | 1 config_host/config_features.h.in | 6 configure.ac | 22 + dev/null |binary include/o3tl/sorted_vector.hxx | 57 ++ include/svx/svdpage.hxx | 8 include/tools/long.hxx | 1 sc/CppunitTest_sc_jumbosheets_test.mk | 1 sc/CppunitTest_sc_tablecolumnsobj.mk | 3 sc/CppunitTest_sc_tablerowsobj.mk | 3 sc/CppunitTest_sc_tablesheetobj.mk | 3 sc/Module_sc.mk | 7 sc/inc/address.hxx | 35 - sc/inc/attarray.hxx | 7 sc/inc/bigrange.hxx | 72 +-- sc/inc/chartpos.hxx | 12 sc/inc/column.hxx | 273 +++++++++++-- sc/inc/columnspanset.hxx | 2 sc/inc/compiler.hxx | 40 + sc/inc/defaultsoptions.hxx | 4 sc/inc/document.hxx | 57 +- sc/inc/externalrefmgr.hxx | 10 sc/inc/fillinfo.hxx | 98 ++++ sc/inc/markarr.hxx | 2 sc/inc/markdata.hxx | 22 - sc/inc/markmulti.hxx | 7 sc/inc/pivot.hxx | 2 sc/inc/progress.hxx | 20 sc/inc/rangelst.hxx | 2 sc/inc/rangenam.hxx | 30 + sc/inc/refdata.hxx | 12 sc/inc/segmenttree.hxx | 2 sc/inc/sheetlimits.hxx | 23 - sc/inc/table.hxx | 49 +- sc/qa/extras/sctablecolumnsobj.cxx | 4 sc/qa/extras/sctablerowsobj.cxx | 4 sc/qa/extras/sctablesheetobj.cxx | 7 sc/qa/extras/testdocuments/Ranges.xls |binary sc/qa/extras/testdocuments/ScNamedRangeObj.ods |binary sc/qa/extras/vba-macro-test.cxx | 30 - sc/qa/unit/bugfix-test.cxx | 10 sc/qa/unit/data/functions/date_time/fods/months.fods | 16 sc/qa/unit/data/functions/date_time/fods/networkdays.fods | 10 sc/qa/unit/data/functions/date_time/fods/weeks.fods | 10 sc/qa/unit/data/functions/date_time/fods/workday.fods | 10 sc/qa/unit/data/functions/date_time/fods/years.fods | 10 sc/qa/unit/data/ods/functions.ods |binary sc/qa/unit/data/ods/named-range-conflict.ods |binary sc/qa/unit/data/ods/ranges-column-2000.ods |binary sc/qa/unit/data/ods/sum-whole-column-row.ods |binary sc/qa/unit/data/ods/value-in-column-2000.ods |binary sc/qa/unit/data/xlsx/tdf109061.xlsx |binary sc/qa/unit/data/xlsx/value-in-column-2000.xlsx |binary sc/qa/unit/filters-test.cxx | 8 sc/qa/unit/helper/qahelper.cxx | 60 +- sc/qa/unit/helper/qahelper.hxx | 14 sc/qa/unit/helper/xpath.cxx | 2 sc/qa/unit/jumbosheets-test.cxx | 239 ++++++++++- sc/qa/unit/mark_test.cxx | 178 +++++--- sc/qa/unit/pivottable_filters_test.cxx | 81 +-- sc/qa/unit/range.cxx | 11 sc/qa/unit/rangelst_test.cxx | 30 - sc/qa/unit/subsequent_export_test.cxx | 214 ++++------ sc/qa/unit/subsequent_export_test2.cxx | 211 ++++------ sc/qa/unit/subsequent_filters_test.cxx | 4 sc/qa/unit/subsequent_filters_test2.cxx | 25 - sc/qa/unit/tiledrendering/tiledrendering.cxx | 84 ++-- sc/qa/unit/ucalc.cxx | 168 ++++---- sc/qa/unit/ucalc_condformat.cxx | 20 sc/qa/unit/ucalc_copypaste.cxx | 4 sc/qa/unit/ucalc_formula.cxx | 76 ++- sc/qa/unit/ucalc_sharedformula.cxx | 28 - sc/qa/unit/ucalc_sort.cxx | 4 sc/qa/unit/uicalc/data/tdf131455-fixed.ods |binary sc/qa/unit/uicalc/uicalc.cxx | 76 ++- sc/source/core/data/attarray.cxx | 30 + sc/source/core/data/bcaslot.cxx | 238 +++++++---- sc/source/core/data/bigrange.cxx | 6 sc/source/core/data/colorscale.cxx | 2 sc/source/core/data/column.cxx | 166 +------ sc/source/core/data/column2.cxx | 142 +----- sc/source/core/data/column3.cxx | 14 sc/source/core/data/column4.cxx | 5 sc/source/core/data/columnspanset.cxx | 48 +- sc/source/core/data/conditio.cxx | 4 sc/source/core/data/dociter.cxx | 8 sc/source/core/data/documen2.cxx | 26 - sc/source/core/data/documen3.cxx | 9 sc/source/core/data/documen4.cxx | 6 sc/source/core/data/documen6.cxx | 2 sc/source/core/data/document.cxx | 147 ++++--- sc/source/core/data/document10.cxx | 7 sc/source/core/data/dpcache.cxx | 2 sc/source/core/data/dpoutput.cxx | 4 sc/source/core/data/drwlayer.cxx | 22 - sc/source/core/data/fillinfo.cxx | 249 ++++++----- sc/source/core/data/formulacell.cxx | 10 sc/source/core/data/listenercontext.cxx | 2 sc/source/core/data/markarr.cxx | 8 sc/source/core/data/markdata.cxx | 74 +-- sc/source/core/data/markmulti.cxx | 32 - sc/source/core/data/segmenttree.cxx | 35 - sc/source/core/data/stlsheet.cxx | 2 sc/source/core/data/table1.cxx | 24 - sc/source/core/data/table2.cxx | 203 ++++++--- sc/source/core/data/table3.cxx | 22 - sc/source/core/data/table4.cxx | 42 +- sc/source/core/data/table5.cxx | 8 sc/source/core/data/table6.cxx | 4 sc/source/core/data/table7.cxx | 12 sc/source/core/inc/bcaslot.hxx | 29 + sc/source/core/tool/address.cxx | 97 ++-- sc/source/core/tool/chgtrack.cxx | 107 ++--- sc/source/core/tool/compiler.cxx | 156 ++++--- sc/source/core/tool/defaultsoptions.cxx | 6 sc/source/core/tool/editutil.cxx | 2 sc/source/core/tool/formulagroup.cxx | 2 sc/source/core/tool/interpr4.cxx | 9 sc/source/core/tool/progress.cxx | 8 sc/source/core/tool/rangelst.cxx | 12 sc/source/core/tool/rangenam.cxx | 75 +-- sc/source/core/tool/refdata.cxx | 13 sc/source/core/tool/refupdat.cxx | 26 - sc/source/core/tool/sharedformula.cxx | 48 -- sc/source/core/tool/token.cxx | 74 +-- sc/source/filter/excel/colrowst.cxx | 4 sc/source/filter/excel/exctools.cxx | 5 sc/source/filter/excel/frmbase.cxx | 29 - sc/source/filter/excel/impop.cxx | 12 sc/source/filter/excel/xelink.cxx | 2 sc/source/filter/excel/xestream.cxx | 11 sc/source/filter/excel/xestyle.cxx | 6 sc/source/filter/excel/xetable.cxx | 293 +++++++++----- sc/source/filter/excel/xiroot.cxx | 9 sc/source/filter/excel/xistyle.cxx | 8 sc/source/filter/html/htmlexp.cxx | 2 sc/source/filter/html/htmlimp.cxx | 2 sc/source/filter/html/htmlpars.cxx | 25 - sc/source/filter/inc/formel.hxx | 5 sc/source/filter/inc/htmlpars.hxx | 10 sc/source/filter/inc/root.hxx | 4 sc/source/filter/inc/sheetdatabuffer.hxx | 9 sc/source/filter/inc/xerecord.hxx | 15 sc/source/filter/inc/xestyle.hxx | 3 sc/source/filter/inc/xetable.hxx | 24 - sc/source/filter/inc/xiroot.hxx | 3 sc/source/filter/inc/xistyle.hxx | 2 sc/source/filter/oox/sheetdatabuffer.cxx | 12 sc/source/filter/xcl97/XclExpChangeTrack.cxx | 6 sc/source/filter/xml/XMLChangeTrackingExportHelper.cxx | 44 +- sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx | 14 sc/source/filter/xml/xmlcelli.cxx | 5 sc/source/filter/xml/xmlcoli.cxx | 2 sc/source/filter/xml/xmlimprt.cxx | 2 sc/source/filter/xml/xmlsubti.cxx | 5 sc/source/ui/Accessibility/AccessibleDocument.cxx | 1 sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx | 4 sc/source/ui/app/seltrans.cxx | 3 sc/source/ui/docshell/docfunc.cxx | 25 - sc/source/ui/docshell/docsh.cxx | 42 +- sc/source/ui/docshell/docsh3.cxx | 20 sc/source/ui/docshell/docsh5.cxx | 3 sc/source/ui/docshell/externalrefmgr.cxx | 38 + sc/source/ui/docshell/impex.cxx | 15 sc/source/ui/inc/datatableview.hxx | 12 sc/source/ui/inc/output.hxx | 2 sc/source/ui/miscdlgs/acredlin.cxx | 10 sc/source/ui/miscdlgs/conflictsdlg.cxx | 4 sc/source/ui/miscdlgs/dataproviderdlg.cxx | 3 sc/source/ui/miscdlgs/datatableview.cxx | 44 -- sc/source/ui/miscdlgs/redcom.cxx | 2 sc/source/ui/navipi/navipi.cxx | 9 sc/source/ui/optdlg/tpdefaults.cxx | 6 sc/source/ui/undo/undoblk.cxx | 5 sc/source/ui/unoobj/cellsuno.cxx | 6 sc/source/ui/unoobj/chart2uno.cxx | 5 sc/source/ui/unoobj/docuno.cxx | 10 sc/source/ui/vba/vbarange.cxx | 7 sc/source/ui/view/cellsh.cxx | 3 sc/source/ui/view/cellsh1.cxx | 8 sc/source/ui/view/cellsh2.cxx | 2 sc/source/ui/view/cliputil.cxx | 5 sc/source/ui/view/dbfunc3.cxx | 2 sc/source/ui/view/formatsh.cxx | 4 sc/source/ui/view/gridwin.cxx | 11 sc/source/ui/view/gridwin4.cxx | 10 sc/source/ui/view/gridwin5.cxx | 4 sc/source/ui/view/gridwin_dbgutil.cxx | 4 sc/source/ui/view/output.cxx | 177 ++++---- sc/source/ui/view/output2.cxx | 79 +-- sc/source/ui/view/pfuncache.cxx | 4 sc/source/ui/view/printfun.cxx | 13 sc/source/ui/view/select.cxx | 2 sc/source/ui/view/tabview.cxx | 2 sc/source/ui/view/tabview2.cxx | 51 +- sc/source/ui/view/tabview3.cxx | 9 sc/source/ui/view/tabvwsh3.cxx | 3 sc/source/ui/view/viewdata.cxx | 32 + sc/source/ui/view/viewfun2.cxx | 15 sc/source/ui/view/viewfun3.cxx | 3 sc/source/ui/view/viewfun4.cxx | 4 sc/source/ui/view/viewfun5.cxx | 2 sc/source/ui/view/viewfunc.cxx | 14 sc/source/ui/view/viewutil.cxx | 5 svx/source/svdraw/svdpage.cxx | 4 205 files changed, 3526 insertions(+), 2615 deletions(-)
New commits: commit 328198509e9cf70569e7e0228e45515e5b4249c8 Author: Luboš Luňák <[email protected]> AuthorDate: Tue Mar 8 17:53:27 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:09 2022 +0100 optimize checking for conflicting named ranges This extends 582fc887f1faafe8ff5f16a13a0208483a93353f, first check if there is any named range that could possibly conflict (which generally should be rare). Change-Id: Ia5e9e56cab29b459bcb489e871b4960ba215b665 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131219 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index 15b3823f649d..5f3b6354c967 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -375,6 +375,8 @@ private: */ ScRangeData* GetRangeData( const formula::FormulaToken& pToken ) const; + bool HasPossibleNamedRangeConflict(SCTAB nTab) const; + static const CharClass* GetCharClassEnglish(); static const CharClass* GetCharClassLocalized(); diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index d51aa85a1008..31bdd1f5a23c 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -156,6 +156,8 @@ public: SC_DLLPUBLIC static IsNameValidType IsNameValid( const OUString& rName, const ScDocument& rDoc ); + bool HasPossibleAddressConflict() const; + void CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ); #if DEBUG_FORMULA_COMPILER @@ -187,6 +189,12 @@ private: typedef ::std::map<OUString, std::unique_ptr<ScRangeData>> DataType; DataType m_Data; IndexDataType maIndexToData; + // Use for optimization, true if any of the contained names resolves + // as a valid cell address (e.g. 'day1' with 16k columns). + mutable bool mHasPossibleAddressConflict : 1; + mutable bool mHasPossibleAddressConflictDirty : 1; + + void checkHasPossibleAddressConflict() const; public: /// Map that stores non-managed pointers to ScRangeName instances. @@ -266,6 +274,13 @@ public: void clear(); bool operator== (const ScRangeName& r) const; + + bool hasPossibleAddressConflict() const + { + if( mHasPossibleAddressConflictDirty ) + checkHasPossibleAddressConflict(); + return mHasPossibleAddressConflict; + } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 70e3899ca03e..f1535a00fb9b 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -3345,17 +3345,20 @@ bool ScCompiler::ParseSingleReference( const OUString& rName, const OUString* pE return false; } - // A named range named e.g. 'num1' is valid with 1k columns, but would become a reference - // when the document is opened later with 16k columns. Resolve the conflict by not - // considering it a reference. - OUString aUpper; - bool bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, rName ); - if (bAsciiUpper || mbCharClassesDiffer) - aUpper = ScGlobal::getCharClass().uppercase( rName ); - mnCurrentSheetTab = aAddr.Tab(); // temporarily set for ParseNamedRange() - if(ParseNamedRange( aUpper, true )) // only check - return false; - mnCurrentSheetTab = -1; + if( HasPossibleNamedRangeConflict( aAddr.Tab())) + { + // A named range named e.g. 'num1' is valid with 1k columns, but would become a reference + // when the document is opened later with 16k columns. Resolve the conflict by not + // considering it a reference. + OUString aUpper; + bool bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, rName ); + if (bAsciiUpper || mbCharClassesDiffer) + aUpper = ScGlobal::getCharClass().uppercase( rName ); + mnCurrentSheetTab = aAddr.Tab(); // temporarily set for ParseNamedRange() + if(ParseNamedRange( aUpper, true )) // only check + return false; + mnCurrentSheetTab = -1; + } ScSingleRefData aRef; aRef.InitAddress( aAddr ); @@ -3587,6 +3590,17 @@ const ScRangeData* ScCompiler::GetRangeData( SCTAB& rSheet, const OUString& rUpp return pData; } +bool ScCompiler::HasPossibleNamedRangeConflict( SCTAB nTab ) const +{ + const ScRangeName* pRangeName = rDoc.GetRangeName(); + if (pRangeName && pRangeName->hasPossibleAddressConflict()) + return true; + pRangeName = rDoc.GetRangeName(nTab); + if (pRangeName && pRangeName->hasPossibleAddressConflict()) + return true; + return false; +} + bool ScCompiler::ParseNamedRange( const OUString& rUpperName, bool onlyCheck ) { // ParseNamedRange is called only from NextNewToken, with an upper-case string diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 09bef58a1bd4..89d3f9e75055 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -497,6 +497,21 @@ ScRangeData::IsNameValidType ScRangeData::IsNameValid( const OUString& rName, co return IsNameValidType::NAME_VALID; } +bool ScRangeData::HasPossibleAddressConflict() const +{ + // Similar to part of IsNameValid(), but only check if the name is a valid address. + ScAddress aAddr; + for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; ) + { + ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); + // Don't check Parse on VALID, any partial only VALID may result in + // #REF! during compile later! + if(aAddr.Parse(aUpperName, rDoc, details) != ScRefFlags::ZERO) + return true; + } + return false; +} + FormulaError ScRangeData::GetErrCode() const { return pCode ? pCode->GetCodeError() : FormulaError::NONE; @@ -654,6 +669,8 @@ public: ScRangeName::ScRangeName() {} ScRangeName::ScRangeName(const ScRangeName& r) + : mHasPossibleAddressConflict( r.mHasPossibleAddressConflict ) + , mHasPossibleAddressConflictDirty( r.mHasPossibleAddressConflictDirty ) { for (auto const& it : r.m_Data) { @@ -817,6 +834,7 @@ bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex ) if (nPos >= maIndexToData.size()) maIndexToData.resize(nPos+1, nullptr); maIndexToData[nPos] = p; + mHasPossibleAddressConflictDirty = true; } return r.second; } @@ -840,12 +858,30 @@ void ScRangeName::erase(const_iterator itr) OSL_ENSURE( 0 < nIndex && nIndex <= maIndexToData.size(), "ScRangeName::erase: bad index"); if (0 < nIndex && nIndex <= maIndexToData.size()) maIndexToData[nIndex-1] = nullptr; + if(mHasPossibleAddressConflict) + mHasPossibleAddressConflictDirty = true; } void ScRangeName::clear() { m_Data.clear(); maIndexToData.clear(); + mHasPossibleAddressConflict = false; + mHasPossibleAddressConflictDirty = false; +} + +void ScRangeName::checkHasPossibleAddressConflict() const +{ + mHasPossibleAddressConflict = false; + mHasPossibleAddressConflictDirty = false; + for (auto const& itr : m_Data) + { + if( itr.second->HasPossibleAddressConflict()) + { + mHasPossibleAddressConflict = true; + return; + } + } } bool ScRangeName::operator== (const ScRangeName& r) const commit b851357dd342b24351dfdc7c6cc68a728888ec95 Author: Luboš Luňák <[email protected]> AuthorDate: Tue Mar 8 17:08:55 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:09 2022 +0100 don't provide non-const iterators to ScRangeName internal data Also make few trivial functions inline. Change-Id: I89b11b2aa4558696d624c9bde9135b1324b8eb36 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131218 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index f7217d567e87..d51aa85a1008 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -234,13 +234,11 @@ public: void CopyUsedNames( const SCTAB nLocalTab, const SCTAB nOldTab, const SCTAB nNewTab, const ScDocument& rOldDoc, ScDocument& rNewDoc, const bool bGlobalNamesToLocal ) const; - SC_DLLPUBLIC const_iterator begin() const; - SC_DLLPUBLIC const_iterator end() const; - SC_DLLPUBLIC iterator begin(); - SC_DLLPUBLIC iterator end(); - SC_DLLPUBLIC size_t size() const; - SC_DLLPUBLIC size_t index_size() const; - bool empty() const; + SC_DLLPUBLIC const_iterator begin() const { return m_Data.begin(); } + SC_DLLPUBLIC const_iterator end() const { return m_Data.end(); } + SC_DLLPUBLIC size_t size() const { return m_Data.size(); } + SC_DLLPUBLIC size_t index_size() const { return maIndexToData.size(); } + bool empty() const { return m_Data.empty(); } /** Insert object into set. @ATTENTION: The underlying ::std::map<std::unique_ptr>::insert(p) takes @@ -264,7 +262,8 @@ public: * iterator's validity. The caller must make sure that the iterator is * valid. */ - void erase(const iterator& itr); + void erase(const_iterator itr); + void clear(); bool operator== (const ScRangeName& r) const; }; diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 11e177158148..09bef58a1bd4 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -778,41 +778,6 @@ void ScRangeName::CopyUsedNames( const SCTAB nLocalTab, const SCTAB nOldTab, con } } -ScRangeName::const_iterator ScRangeName::begin() const -{ - return m_Data.begin(); -} - -ScRangeName::const_iterator ScRangeName::end() const -{ - return m_Data.end(); -} - -ScRangeName::iterator ScRangeName::begin() -{ - return m_Data.begin(); -} - -ScRangeName::iterator ScRangeName::end() -{ - return m_Data.end(); -} - -size_t ScRangeName::size() const -{ - return m_Data.size(); -} - -size_t ScRangeName::index_size() const -{ - return maIndexToData.size(); -} - -bool ScRangeName::empty() const -{ - return m_Data.empty(); -} - bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex ) { if (!p) @@ -863,12 +828,12 @@ void ScRangeName::erase(const ScRangeData& r) void ScRangeName::erase(const OUString& rName) { - DataType::iterator itr = m_Data.find(rName); + DataType::const_iterator itr = m_Data.find(rName); if (itr != m_Data.end()) erase(itr); } -void ScRangeName::erase(const iterator& itr) +void ScRangeName::erase(const_iterator itr) { sal_uInt16 nIndex = itr->second->GetIndex(); m_Data.erase(itr); diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 305478ac483a..fad6eb0a3047 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -222,7 +222,7 @@ class EraseRangeByIterator ScRangeName& mrRanges; public: explicit EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {} - void operator() (const ScRangeName::iterator& itr) + void operator() (const ScRangeName::const_iterator& itr) { mrRanges.erase(itr); } @@ -234,8 +234,8 @@ public: */ void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId) { - ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end(); - vector<ScRangeName::iterator> v; + ScRangeName::const_iterator itr = rRanges.begin(), itrEnd = rRanges.end(); + vector<ScRangeName::const_iterator> v; for (; itr != itrEnd; ++itr) { if (hasRefsToSrcDoc(*itr->second, nFileId)) commit b3294e2a424c216e48804eeb0f78b403aa06189f Author: Luboš Luňák <[email protected]> AuthorDate: Tue Mar 8 14:37:18 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:09 2022 +0100 stop ScTable::ExtendMerge() from needless complaining With dynamic columns it is possible for it to be called for unallocated columns, and those can't be merged. Change-Id: If4a365ba175b9ea7e68704bb4db85a30e5f8a0db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131211 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index f606fdd44902..80b488703d0b 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2275,13 +2275,10 @@ bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, OSL_FAIL("ScTable::ExtendMerge: invalid column number"); return false; } - if ( nStartCol >= aCol.size() ) - { - OSL_FAIL("ScTable::ExtendMerge: invalid nStartCol"); - return false; - } + if( rEndCol >= aCol.size()) + assert( !aDefaultColData.GetAttr( nStartRow, ATTR_MERGE ).IsMerged()); bool bFound = false; - SCCOL nOldEndX = std::min( rEndCol, static_cast<SCCOL>(aCol.size()-1) ); + SCCOL nOldEndX = ClampToAllocatedColumns(rEndCol); SCROW nOldEndY = rEndRow; for (SCCOL i=nStartCol; i<=nOldEndX; i++) bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh ); commit 28bdeb7320d697fe036efadf01820ec86dd786e3 Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 19:39:36 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:09 2022 +0100 optimize ScTabView::SkipCursorVertical() for many rows Just like already done for RowHidden(), avoid repeated calls to HasAttrib() and IsVerOverlapped() that would return the same value because it's the same underlying attribute range. Change-Id: Ic270f5ba1333e15d46b5e54e14d9760602221ea7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131151 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx index f55a4ee8206e..34d1403bcc91 100644 --- a/sc/inc/attarray.hxx +++ b/sc/inc/attarray.hxx @@ -182,6 +182,7 @@ public: bool Search( SCROW nRow, SCSIZE& nIndex ) const; bool HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const; + bool HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; bool IsMerged( SCROW nRow ) const; bool ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, SCCOL& rPaintCol, SCROW& rPaintRow, diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 69b80ed00830..6cb2311de112 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -133,6 +133,11 @@ public: { return static_cast<const T&>(GetAttr(nRow, sal_uInt16(nWhich))); } + const SfxPoolItem& GetAttr( SCROW nRow, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const; + template<class T> const T& GetAttr( SCROW nRow, TypedWhichId<T> nWhich, SCROW& nStartRow, SCROW& nEndRow ) const + { + return static_cast<const T&>(GetAttr(nRow, sal_uInt16(nWhich), nStartRow, nEndRow)); + } const ScPatternAttr* GetPattern( SCROW nRow ) const; const ScPatternAttr* GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const; @@ -153,6 +158,7 @@ public: void ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle ); bool HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const; + bool HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; void ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark, SCCOL nCol ); void ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark, SCCOL nCol ); @@ -881,6 +887,11 @@ inline bool ScColumnData::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMas return pAttrArray->HasAttrib( nRow1, nRow2, nMask ); } +inline bool ScColumnData::HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow, SCROW* nEndRow ) const +{ + return pAttrArray->HasAttrib( nRow, nMask, nStartRow, nEndRow ); +} + inline bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, SCCOL& rPaintCol, SCROW& rPaintRow, bool bRefresh ) @@ -916,6 +927,11 @@ inline const SfxPoolItem& ScColumnData::GetAttr( SCROW nRow, sal_uInt16 nWhich ) return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich); } +inline const SfxPoolItem& ScColumnData::GetAttr( SCROW nRow, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const +{ + return pAttrArray->GetPatternRange( nStartRow, nEndRow, nRow )->GetItemSet().Get(nWhich); +} + inline sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const { return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 44cedc482e01..963b4d48edad 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1308,11 +1308,14 @@ public: void SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const; bool IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; - bool IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; + bool IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab, + SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; SC_DLLPUBLIC bool HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask ) const; SC_DLLPUBLIC bool HasAttrib( const ScRange& rRange, HasAttrFlags nMask ) const; + bool HasAttrib( SCCOL nCol, SCROW nRow, SCTAB nTab, HasAttrFlags nMask, + SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; SC_DLLPUBLIC void GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab, const ::editeng::SvxBorderLine** ppLeft, @@ -1747,6 +1750,13 @@ public: { return static_cast<const T*>(GetAttr(nCol, nRow, nTab, sal_uInt16(nWhich))); } + SC_DLLPUBLIC const SfxPoolItem* GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich, + SCROW& nStartRow, SCROW& nEndRow ) const; + template<class T> const T* GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedWhichId<T> nWhich, + SCROW& nStartRow, SCROW& nEndRow ) const + { + return static_cast<const T*>(GetAttr(nCol, nRow, nTab, sal_uInt16(nWhich), nStartRow, nEndRow)); + } SC_DLLPUBLIC const SfxPoolItem* GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const; template<class T> const T* GetAttr( const ScAddress& rPos, TypedWhichId<T> nWhich ) const { diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 7405d5fb90f3..bcde540de65b 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -694,6 +694,8 @@ public: bool HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, HasAttrFlags nMask ) const; bool HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) const; + bool HasAttrib( SCCOL nCol, SCROW nRow, HasAttrFlags nMask, + SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; bool IsMerged( SCCOL nCol, SCROW nRow ) const; bool ExtendMerge( SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW& rEndRow, @@ -705,6 +707,11 @@ public: { return static_cast<const T*>(GetAttr(nCol, nRow, sal_uInt16(nWhich))); } + const SfxPoolItem* GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const; + template<class T> const T* GetAttr( SCCOL nCol, SCROW nRow, TypedWhichId<T> nWhich, SCROW& nStartRow, SCROW& nEndRow ) const + { + return static_cast<const T*>(GetAttr(nCol, nRow, sal_uInt16(nWhich), nStartRow, nEndRow)); + } const ScPatternAttr* GetPattern( SCCOL nCol, SCROW nRow ) const; const ScPatternAttr* GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const; diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index 599a80251602..5af0e3b3609d 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -1420,6 +1420,27 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) cons return bFound; } +bool ScAttrArray::HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow, SCROW* nEndRow ) const +{ + if (mvData.empty()) + { + if( nStartRow ) + *nStartRow = 0; + if( nEndRow ) + *nEndRow = rDocument.MaxRow(); + return HasAttrib_Impl(rDocument.GetDefPattern(), nMask, 0, rDocument.MaxRow(), 0); + } + + SCSIZE nIndex; + Search( nRow, nIndex ); + if( nStartRow ) + *nStartRow = nIndex > 0 ? mvData[nIndex-1].nEndRow+1 : 0; + if( nEndRow ) + *nEndRow = mvData[nIndex].nEndRow; + const ScPatternAttr* pPattern = mvData[nIndex].pPattern; + return HasAttrib_Impl(pPattern, nMask, nRow, nRow, nIndex); +} + bool ScAttrArray::IsMerged( SCROW nRow ) const { if ( !mvData.empty() ) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 361a51abc9bb..ec39169c9192 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -4737,6 +4737,21 @@ const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_ return &mxPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); } +const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const +{ + if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) + { + const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich, nStartRow, nEndRow ); + if (pTemp) + return pTemp; + else + { + OSL_FAIL( "Attribute Null" ); + } + } + return &mxPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); +} + const SfxPoolItem* ScDocument::GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const { return GetAttr(rPos.Col(), rPos.Row(), rPos.Tab(), nWhich); @@ -5177,16 +5192,13 @@ void ScDocument::GetSelectionFrame( const ScMarkData& rMark, rLineInner.SetValid( SvxBoxInfoItemValidFlags::VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) ); } -bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, - SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask ) const +static HasAttrFlags OptimizeHasAttrib( HasAttrFlags nMask, ScDocumentPool* pPool ) { if ( nMask & HasAttrFlags::Rotate ) { // Is attribute used in document? // (as in fillinfo) - ScDocumentPool* pPool = mxPoolHelper->GetDocPool(); - bool bAnyItem = false; for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_ROTATE_VALUE)) { @@ -5202,12 +5214,18 @@ bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, if (!bAnyItem) nMask &= ~HasAttrFlags::Rotate; } + return nMask; +} + +bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask ) const +{ + nMask = OptimizeHasAttrib( nMask, mxPoolHelper->GetDocPool()); if (nMask == HasAttrFlags::NONE) return false; - bool bFound = false; - for (SCTAB i=nTab1; i<=nTab2 && !bFound && i < static_cast<SCTAB>(maTabs.size()); i++) + for (SCTAB i=nTab1; i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++) if (maTabs[i]) { if ( nMask & HasAttrFlags::RightOrCenter ) @@ -5217,14 +5235,46 @@ bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. if ( IsLayoutRTL(i) ) - bFound = true; + return true; } - if ( !bFound ) - bFound = maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask ); + if( maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask )) + return true; } - return bFound; + return false; +} + +bool ScDocument::HasAttrib( SCCOL nCol, SCROW nRow, SCTAB nTab, HasAttrFlags nMask, SCROW* nStartRow, SCROW* nEndRow ) const +{ + nMask = OptimizeHasAttrib( nMask, mxPoolHelper->GetDocPool()); + + if (nMask == HasAttrFlags::NONE || nTab >= static_cast<SCTAB>(maTabs.size())) + { + if( nStartRow ) + *nStartRow = 0; + if( nEndRow ) + *nEndRow = MaxRow(); + return false; + } + + if ( nMask & HasAttrFlags::RightOrCenter ) + { + // On a RTL sheet, don't start to look for the default left value + // (which is then logically right), instead always assume true. + // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. + + if ( IsLayoutRTL(nTab) ) + { + if( nStartRow ) + *nStartRow = 0; + if( nEndRow ) + *nEndRow = MaxRow(); + return true; + } + } + + return maTabs[nTab]->HasAttrib( nCol, nRow, nMask, nStartRow, nEndRow ); } bool ScDocument::HasAttrib( const ScRange& rRange, HasAttrFlags nMask ) const @@ -5738,9 +5788,11 @@ bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const } } -bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const +bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab, SCROW* nStartRow, SCROW* nEndRow ) const { - const ScMergeFlagAttr* pAttr = GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); + SCROW dummy; + const ScMergeFlagAttr* pAttr = GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG, + nStartRow ? *nStartRow : dummy, nEndRow ? *nEndRow : dummy ); if (pAttr) return pAttr->IsVerOverlapped(); else diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index bd3fd74200c2..f606fdd44902 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2174,6 +2174,15 @@ const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) return &aDefaultColData.GetAttr( nRow, nWhich ); } +const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const +{ + if (!ValidColRow(nCol, nRow)) + return nullptr; + if (nCol < GetAllocatedColumnsCount()) + return &aCol[nCol].GetAttr( nRow, nWhich, nStartRow, nEndRow ); + return &aDefaultColData.GetAttr( nRow, nWhich, nStartRow, nEndRow ); +} + sal_uInt32 ScTable::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const { if (ValidColRow(rPos.Col(), rPos.Row())) @@ -2235,6 +2244,13 @@ bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, Has return false; } +bool ScTable::HasAttrib( SCCOL nCol, SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow, SCROW* nEndRow ) const +{ + if( nCol < aCol.size()) + return aCol[nCol].HasAttrib( nRow, nMask, nStartRow, nEndRow ); + return aDefaultColData.HasAttrib( nRow, nMask, nStartRow, nEndRow ); +} + bool ScTable::HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) const { std::vector<sc::ColRowSpan> aSpans = rMark.GetMarkedColSpans(); diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx index 111b27477247..49167895a182 100644 --- a/sc/source/ui/view/tabview2.cxx +++ b/sc/source/ui/view/tabview2.cxx @@ -739,7 +739,8 @@ void ScTabView::SkipCursorHorizontal(SCCOL& rCurX, SCROW& rCurY, SCCOL nOldX, SC bool bSkipCell = false; bool bHFlip = false; - auto nMaxCol = rDoc.MaxCol(); + // search also the first unallocated column (all unallocated columns share a set of attrs) + SCCOL nMaxCol = std::min<SCCOL>( rDoc.GetAllocatedColumnsCount(nTab) + 1, rDoc.MaxCol()); do { bSkipCell = rDoc.ColHidden(rCurX, nTab) || rDoc.IsHorOverlapped(rCurX, rCurY, nTab); @@ -799,20 +800,41 @@ void ScTabView::SkipCursorVertical(SCCOL& rCurX, SCROW& rCurY, SCROW nOldY, SCRO bool bSkipCell = false; bool bVFlip = false; + // Avoid repeated calls to RowHidden(), IsVerOverlapped() and HasAttrib(). + SCROW nFirstSameHiddenRow = -1; + SCROW nLastSameHiddenRow = -1; + bool bRowHidden = false; + SCROW nFirstSameIsVerOverlapped = -1; + SCROW nLastSameIsVerOverlapped = -1; + bool bIsVerOverlapped = false; + SCROW nFirstSameHasAttribRow = -1; + SCROW nLastSameHasAttribRow = -1; + bool bHasAttribProtected = false; do { - SCROW nFirstHiddenRow = -1; - SCROW nLastHiddenRow = -1; - bSkipCell = rDoc.RowHidden(rCurY, nTab, &nFirstHiddenRow, &nLastHiddenRow); - if (!bSkipCell) + if( rCurY < nFirstSameHiddenRow || rCurY > nLastSameHiddenRow ) + bRowHidden = rDoc.RowHidden(rCurY, nTab, &nFirstSameHiddenRow, &nLastSameHiddenRow); + bSkipCell = bRowHidden; + if( !bSkipCell ) { - nFirstHiddenRow = nLastHiddenRow = -1; - bSkipCell = rDoc.IsVerOverlapped( rCurX, rCurY, nTab ); + if( rCurY < nFirstSameIsVerOverlapped || rCurY > nLastSameIsVerOverlapped ) + bIsVerOverlapped = rDoc.IsVerOverlapped(rCurX, rCurY, nTab, &nFirstSameIsVerOverlapped, &nLastSameIsVerOverlapped); + bSkipCell = bIsVerOverlapped; } if (bSkipProtected && !bSkipCell) - bSkipCell = rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected); + { + if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow ) + bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected, + &nFirstSameHasAttribRow, &nLastSameHasAttribRow); + bSkipCell = bHasAttribProtected; + } if (bSkipUnprotected && !bSkipCell) - bSkipCell = !rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected); + { + if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow ) + bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected, + &nFirstSameHasAttribRow, &nLastSameHasAttribRow); + bSkipCell = !bHasAttribProtected; + } if (bSkipCell) { @@ -834,20 +856,10 @@ void ScTabView::SkipCursorVertical(SCCOL& rCurX, SCROW& rCurY, SCROW nOldY, SCRO } } else - { - // nFirstRow/nLastRow are set only if the row is hidden, in which case we always skip, - // so as an optimization skip to the first row after the hidden range if (nMovY > 0) - if (nLastHiddenRow >= 0) - rCurY = std::min<SCROW>(nLastHiddenRow + 1, rDoc.MaxRow()); - else - ++rCurY; + ++rCurY; else - if (nFirstHiddenRow >= 0) - rCurY = std::max<SCROW>(nFirstHiddenRow - 1, 0); - else - --rCurY; - } + --rCurY; } } while (bSkipCell); commit 39324a20a3f405814ee69d6def43b9c44d94dfb3 Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 21:02:11 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 fix GetAttr() for unallocated columns Change-Id: Id7cbebf68ec3cc54d773bc5745fab192d043f952 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131150 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 6976d45cb483..69b80ed00830 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -128,6 +128,12 @@ public: ScAttrArray& AttrArray() { return *pAttrArray; } const ScAttrArray& AttrArray() const { return *pAttrArray; } + const SfxPoolItem& GetAttr( SCROW nRow, sal_uInt16 nWhich ) const; + template<class T> const T& GetAttr( SCROW nRow, TypedWhichId<T> nWhich ) const + { + return static_cast<const T&>(GetAttr(nRow, sal_uInt16(nWhich))); + } + const ScPatternAttr* GetPattern( SCROW nRow ) const; const ScPatternAttr* GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const; SCROW ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged, @@ -497,11 +503,7 @@ public: void PreprocessDBDataUpdate( sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt ); - const SfxPoolItem& GetAttr( SCROW nRow, sal_uInt16 nWhich ) const; - template<class T> const T& GetAttr( SCROW nRow, TypedWhichId<T> nWhich ) const - { - return static_cast<const T&>(GetAttr(nRow, sal_uInt16(nWhich))); - } + using ScColumnData::GetAttr; using ScColumnData::GetPattern; using ScColumnData::GetNumberFormat; @@ -909,7 +911,7 @@ inline const ScPatternAttr* ScColumnData::GetPattern( SCROW nRow ) const return pAttrArray->GetPattern( nRow ); } -inline const SfxPoolItem& ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const +inline const SfxPoolItem& ScColumnData::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const { return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich); } diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index a7fabf46d1df..361a51abc9bb 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -4724,8 +4724,7 @@ void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, S const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const { - if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && - nCol < maTabs[nTab]->GetAllocatedColumnsCount()) + if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) { const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich ); if (pTemp) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 424d00e135b8..bd3fd74200c2 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2167,10 +2167,11 @@ void ScTable::ResetChanged( const ScRange& rRange ) const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const { - if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount()) - return &aCol[nCol].GetAttr( nRow, nWhich ); - else + if (!ValidColRow(nCol, nRow)) return nullptr; + if (nCol < GetAllocatedColumnsCount()) + return &aCol[nCol].GetAttr( nRow, nWhich ); + return &aDefaultColData.GetAttr( nRow, nWhich ); } sal_uInt32 ScTable::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const commit 08769064cf1882eedf54d0e15ca3593090cbde30 Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 16:42:55 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 remove pAttrArray nullptr checks I missed these in 2e2e30d7ae445509e39ba47c1b248079f28c8d95. Change-Id: Ib0f75a2a0f018521e2468e83bdf41196f4b66c3e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131152 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index b1dff6562434..6976d45cb483 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -851,12 +851,12 @@ inline bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const inline SCSIZE ScColumn::GetPatternCount() const { - return pAttrArray ? pAttrArray->Count() : 0; + return pAttrArray->Count(); } inline SCSIZE ScColumn::GetPatternCount( SCROW nRow1, SCROW nRow2 ) const { - return pAttrArray ? pAttrArray->Count( nRow1, nRow2 ) : 0; + return pAttrArray->Count( nRow1, nRow2 ); } inline bool ScColumn::ReservePatternCount( SCSIZE nReserve ) commit 2ec4b282c41fd8072a901ae2223703ec5f062395 Author: Luboš Luňák <[email protected]> AuthorDate: Fri Mar 4 16:40:20 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 remove pAttrArray nullptr checks I don't see how it possibly could be nullptr in a correct situation, ScColumn::Init() is called right after creating ScColumn. Also make a bunch of trivial forwarding functions inline. Change-Id: I710d3cd86a660a8b4dcfbb9966a685b657b93c18 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131035 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 09945433a1be..b1dff6562434 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -817,4 +817,167 @@ private: void SetNeedsListeningGroup( SCROW nRow ); }; +inline bool ScColumn::IsEmptyAttr() const +{ + return pAttrArray->IsEmpty(); +} + +inline bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const +{ + return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow ); +} + +inline bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const +{ + return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow ); +} + +inline bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const +{ + return pAttrArray->GetFirstVisibleAttr( rFirstRow ); +} + +inline bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow ) const +{ + // row of last cell is needed + SCROW nLastData = GetLastDataPos(); // always including notes, 0 if none + return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData ); +} + +inline bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const +{ + return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow ); +} + +inline SCSIZE ScColumn::GetPatternCount() const +{ + return pAttrArray ? pAttrArray->Count() : 0; +} + +inline SCSIZE ScColumn::GetPatternCount( SCROW nRow1, SCROW nRow2 ) const +{ + return pAttrArray ? pAttrArray->Count( nRow1, nRow2 ) : 0; +} + +inline bool ScColumn::ReservePatternCount( SCSIZE nReserve ) +{ + return pAttrArray && pAttrArray->Reserve( nReserve ); +} + +inline bool ScColumn::IsMerged( SCROW nRow ) const +{ + return pAttrArray->IsMerged(nRow); +} + +inline SCROW ScColumnData::GetNextUnprotected( SCROW nRow, bool bUp ) const +{ + return pAttrArray->GetNextUnprotected(nRow, bUp); +} + +inline bool ScColumnData::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const +{ + return pAttrArray->HasAttrib( nRow1, nRow2, nMask ); +} + +inline bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, + SCCOL& rPaintCol, SCROW& rPaintRow, + bool bRefresh ) +{ + return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh ); +} + +inline void ScColumnData::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const +{ + pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep ); +} + +inline void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, + ScLineFlags& rFlags, + SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const +{ + pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight ); +} + +inline void ScColumn::ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner, + SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight) +{ + pAttrArray->ApplyBlockFrame(rLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight); +} + +inline const ScPatternAttr* ScColumnData::GetPattern( SCROW nRow ) const +{ + return pAttrArray->GetPattern( nRow ); +} + +inline const SfxPoolItem& ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const +{ + return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich); +} + +inline sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const +{ + return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() ); +} + +inline void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ) +{ + pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex ); +} + +inline void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ) +{ + pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex ); +} + +inline void ScColumnData::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle ) +{ + pAttrArray->ApplyStyleArea(nStartRow, nEndRow, rStyle); +} + +inline const ScStyleSheet* ScColumnData::GetStyle( SCROW nRow ) const +{ + return pAttrArray->GetPattern( nRow )->GetStyleSheet(); +} + +inline void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ) +{ + pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset ); +} + +inline bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const +{ + return pAttrArray->IsStyleSheetUsed( rStyle ); +} + +inline bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ) +{ + return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags ); +} + +inline bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ) +{ + return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags ); +} + +inline void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich ) +{ + pAttrArray->ClearItems( nStartRow, nEndRow, pWhich ); +} + +inline const ScPatternAttr* ScColumn::SetPattern( SCROW nRow, std::unique_ptr<ScPatternAttr> pPatAttr ) +{ + return pAttrArray->SetPattern( nRow, std::move(pPatAttr), true/*bPutToPool*/ ); +} + +inline void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr ) +{ + pAttrArray->SetPattern( nRow, &rPatAttr, true/*bPutToPool*/ ); +} + +inline void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow, + const ScPatternAttr& rPatAttr ) +{ + pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, true/*bPutToPool*/ ); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index fb29de71153d..643f1ef7538b 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -107,11 +107,6 @@ void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument& rDoc, bool bEmptyA InitAttrArray(new ScAttrArray( nCol, nTab, rDoc, &rDoc.maTabs[nTab]->aDefaultColData.AttrArray())); } -SCROW ScColumnData::GetNextUnprotected( SCROW nRow, bool bUp ) const -{ - return pAttrArray->GetNextUnprotected(nRow, bUp); -} - sc::MatrixEdge ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask, bool bNoMatrixAtAll ) const { @@ -301,11 +296,6 @@ bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const return bOpen; } -bool ScColumnData::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const -{ - return pAttrArray->HasAttrib( nRow1, nRow2, nMask ); -} - bool ScColumn::HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) const { bool bFound = false; @@ -326,13 +316,6 @@ bool ScColumn::HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) return bFound; } -bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, - SCCOL& rPaintCol, SCROW& rPaintRow, - bool bRefresh ) -{ - return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh ); -} - void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const { SCROW nTop; @@ -350,34 +333,6 @@ void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkD } } -void ScColumnData::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const -{ - pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep ); -} - -void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, - ScLineFlags& rFlags, - SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const -{ - pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight ); -} - -void ScColumn::ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner, - SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight) -{ - pAttrArray->ApplyBlockFrame(rLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight); -} - -const ScPatternAttr* ScColumnData::GetPattern( SCROW nRow ) const -{ - return pAttrArray->GetPattern( nRow ); -} - -const SfxPoolItem& ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const -{ - return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich); -} - const ScPatternAttr* ScColumnData::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const { ::std::map< const ScPatternAttr*, size_t > aAttrMap; @@ -418,11 +373,6 @@ sal_uInt32 ScColumnData::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const return nFormat; } -sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const -{ - return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() ); -} - SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged ) { @@ -562,16 +512,6 @@ void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, } } -void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ) -{ - pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex ); -} - -void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ) -{ - pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex ); -} - void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet* rStyle ) { const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow); @@ -580,11 +520,6 @@ void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet* rStyle ) pAttrArray->SetPattern(nRow, std::move(pNewPattern), true); } -void ScColumnData::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle ) -{ - pAttrArray->ApplyStyleArea(nStartRow, nEndRow, rStyle); -} - void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) { SCROW nTop; @@ -615,11 +550,6 @@ void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark, } } -const ScStyleSheet* ScColumnData::GetStyle( SCROW nRow ) const -{ - return pAttrArray->GetPattern( nRow )->GetStyleSheet(); -} - const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const { rFound = false; @@ -686,47 +616,6 @@ const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRo return bEqual ? pStyle : nullptr; } -void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ) -{ - pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset ); -} - -bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const -{ - return pAttrArray->IsStyleSheetUsed( rStyle ); -} - -bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ) -{ - return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags ); -} - -bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ) -{ - return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags ); -} - -void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich ) -{ - pAttrArray->ClearItems( nStartRow, nEndRow, pWhich ); -} - -const ScPatternAttr* ScColumn::SetPattern( SCROW nRow, std::unique_ptr<ScPatternAttr> pPatAttr ) -{ - return pAttrArray->SetPattern( nRow, std::move(pPatAttr), true/*bPutToPool*/ ); -} - -void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr ) -{ - pAttrArray->SetPattern( nRow, &rPatAttr, true/*bPutToPool*/ ); -} - -void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow, - const ScPatternAttr& rPatAttr ) -{ - pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, true/*bPutToPool*/ ); -} - void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr ) { // in order to only create a new SetItem, we don't need SfxItemPoolCache. diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 1e902dae8f22..139462db7f1f 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1290,14 +1290,6 @@ bool ScColumn::HasVisibleDataAt(SCROW nRow) const return it->type != sc::element_type_empty; } -bool ScColumn::IsEmptyAttr() const -{ - if (pAttrArray) - return pAttrArray->IsEmpty(); - else - return true; -} - bool ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const { std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow); @@ -3201,51 +3193,6 @@ void ScColumn::GetDataExtrasAt( SCROW nRow, ScDataAreaExtras& rDataAreaExtras ) } } -bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const -{ - if (pAttrArray && rCol.pAttrArray) - return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow ); - else - return !pAttrArray && !rCol.pAttrArray; -} - -bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const -{ - if (pAttrArray && rCol.pAttrArray) - return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow ); - else - return !pAttrArray && !rCol.pAttrArray; -} - -bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const -{ - if (pAttrArray) - return pAttrArray->GetFirstVisibleAttr( rFirstRow ); - else - return false; -} - -bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow ) const -{ - if (pAttrArray) - { - // row of last cell is needed - SCROW nLastData = GetLastDataPos(); // always including notes, 0 if none - - return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData ); - } - else - return false; -} - -bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const -{ - if (pAttrArray) - return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow ); - else - return false; -} - namespace { class FindUsedRowsHandler @@ -3638,19 +3585,4 @@ sal_uInt64 ScColumn::GetCodeCount() const return aFunc.getCount(); } -SCSIZE ScColumn::GetPatternCount() const -{ - return pAttrArray ? pAttrArray->Count() : 0; -} - -SCSIZE ScColumn::GetPatternCount( SCROW nRow1, SCROW nRow2 ) const -{ - return pAttrArray ? pAttrArray->Count( nRow1, nRow2 ) : 0; -} - -bool ScColumn::ReservePatternCount( SCSIZE nReserve ) -{ - return pAttrArray && pAttrArray->Reserve( nReserve ); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index bbae4747a13e..7222404c5b36 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -39,11 +39,6 @@ #include <vector> #include <cassert> -bool ScColumn::IsMerged( SCROW nRow ) const -{ - return pAttrArray->IsMerged(nRow); -} - sc::MultiDataCellState::StateType ScColumn::HasDataCellsInRange( SCROW nRow1, SCROW nRow2, SCROW* pRow1 ) const { commit 448e3fa53eba8301e89ed51ea4a4ba39d9d55d85 Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 18:52:33 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 revert/fix the incorrect fix for tdf#126904 The default cell style has protection turned off. That means that any cells that do not have a style that turns the protection on are actually not protected. So the original code was correct, it went beyond the cells explicitly saved in the file and the first "default" cell was not protected, so it was ok to jump there. Re-saving this document to xlsx and opening it in Excel has the same result. So revert the change. Keep the test, but edit the test file to actually protect cells in the default cell style too, as that way it's actually useful as a test of protected cells. And since the test for tdf#126904 is a subset of basically the same test for the same "bug" tdf#131455, keep only the larger test. Change-Id: I36f21c33aaf5a31e95aa29d616c6abdec17fcf42 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131126 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/qa/unit/uicalc/data/tdf126904.ods b/sc/qa/unit/uicalc/data/tdf126904.ods deleted file mode 100644 index 0f2cf05132c4..000000000000 Binary files a/sc/qa/unit/uicalc/data/tdf126904.ods and /dev/null differ diff --git a/sc/qa/unit/uicalc/data/tdf131455-fixed.ods b/sc/qa/unit/uicalc/data/tdf131455-fixed.ods new file mode 100644 index 000000000000..08e02804bf1b Binary files /dev/null and b/sc/qa/unit/uicalc/data/tdf131455-fixed.ods differ diff --git a/sc/qa/unit/uicalc/data/tdf131455.ods b/sc/qa/unit/uicalc/data/tdf131455.ods deleted file mode 100644 index f4d8bca66375..000000000000 Binary files a/sc/qa/unit/uicalc/data/tdf131455.ods and /dev/null differ diff --git a/sc/qa/unit/uicalc/uicalc.cxx b/sc/qa/unit/uicalc/uicalc.cxx index 7a92f711cb13..bcecaf99d67e 100644 --- a/sc/qa/unit/uicalc/uicalc.cxx +++ b/sc/qa/unit/uicalc/uicalc.cxx @@ -1112,7 +1112,9 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf119793) CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf131455) { - ScModelObj* pModelObj = createDoc("tdf131455.ods"); + // Note that tdf#131455 and tdf#126904 were actually incorrect, + // but keep the test with a fixed version of the document. + ScModelObj* pModelObj = createDoc("tdf131455-fixed.ods"); ScDocument* pDoc = pModelObj->GetDocument(); CPPUNIT_ASSERT(pDoc); @@ -1160,37 +1162,6 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf131455) CPPUNIT_ASSERT_EQUAL(sal_Int16(0), ScDocShell::GetViewData()->GetTabNo()); lcl_AssertCurrentCursorPosition(13, 4); - // Cursor can't move forward to the right - // Without the fix in place, this test would have failed with - // - Expected: 13 - // - Actual : 64 - for (size_t i = 0; i < 5; ++i) - { - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(13, 4); - } -} - -CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf126904) -{ - ScModelObj* pModelObj = createDoc("tdf126904.ods"); - ScDocument* pDoc = pModelObj->GetDocument(); - CPPUNIT_ASSERT(pDoc); - - lcl_AssertCurrentCursorPosition(0, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(1, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(4, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(5, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(8, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(9, 4); - dispatchCommand(mxComponent, ".uno:GoRight", {}); - lcl_AssertCurrentCursorPosition(12, 4); - //Cursor can't move forward to the right for (size_t i = 0; i < 5; ++i) { diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx index 0327ba410243..111b27477247 100644 --- a/sc/source/ui/view/tabview2.cxx +++ b/sc/source/ui/view/tabview2.cxx @@ -739,7 +739,7 @@ void ScTabView::SkipCursorHorizontal(SCCOL& rCurX, SCROW& rCurY, SCCOL nOldX, SC bool bSkipCell = false; bool bHFlip = false; - auto nMaxCol = rDoc.ClampToAllocatedColumns(nTab, rDoc.MaxCol()); + auto nMaxCol = rDoc.MaxCol(); do { bSkipCell = rDoc.ColHidden(rCurX, nTab) || rDoc.IsHorOverlapped(rCurX, rCurY, nTab); commit 5b490f6e43cb8111157dfddf60fe2e0d053f497c Author: Luboš Luňák <[email protected]> AuthorDate: Mon Mar 7 12:48:37 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 optimize repeated std::vector removal (tdf#126326) Also it's enough to use just pointers to the elements, no need to refcount. Change-Id: I2e6a2f981d75e3dd57aefb41ba1fdbf800fed813 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131107 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index d790ff74e7eb..dcbcba7251bb 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1753,31 +1753,31 @@ void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ) rXFIndexes.clear(); rXFIndexes.reserve( maColInfos.GetSize() ); - size_t nPos, nSize; - - // do not cache the record list size, it may change in the loop - for( nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) + if( !maColInfos.IsEmpty()) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); - xRec->ConvertXFIndexes(); - - // try to merge with previous record - if( nPos > 0 ) + XclExpColinfo* xPrevRec = maColInfos.GetRecord( 0 ); + xPrevRec->ConvertXFIndexes(); + for( size_t nPos = 1; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xPrevRec = maColInfos.GetRecord( nPos - 1 ); + XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); + xRec->ConvertXFIndexes(); + + // try to merge with previous record if( xPrevRec->TryMerge( *xRec ) ) - // adjust nPos to get the next COLINFO record at the same position - maColInfos.RemoveRecord( nPos-- ); + maColInfos.InvalidateRecord( nPos ); + else + xPrevRec = xRec; } + maColInfos.RemoveInvalidatedRecords(); } // put XF indexes into passed vector, collect use count of all different widths std::unordered_map< sal_uInt16, sal_uInt16 > aWidthMap; sal_uInt16 nMaxColCount = 0; sal_uInt16 nMaxUsedWidth = 0; - for( nPos = 0, nSize = maColInfos.GetSize(); nPos < nSize; ++nPos ) + for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); + const XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); sal_uInt16 nColCount = xRec->GetColCount(); // add XF index to passed vector @@ -1796,15 +1796,13 @@ void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ) maDefcolwidth.SetDefWidth( nMaxUsedWidth, bXLS ); // remove all default COLINFO records - nPos = 0; - while( nPos < maColInfos.GetSize() ) + for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos ) { - XclExpColinfoRef xRec = maColInfos.GetRecord( nPos ); + XclExpColinfo* xRec = maColInfos.GetRecord( nPos ); if( xRec->IsDefault( maDefcolwidth ) ) - maColInfos.RemoveRecord( nPos ); - else - ++nPos; + maColInfos.InvalidateRecord( nPos ); } + maColInfos.RemoveInvalidatedRecords(); } void XclExpColinfoBuffer::Save( XclExpStream& rStrm ) diff --git a/sc/source/filter/inc/xerecord.hxx b/sc/source/filter/inc/xerecord.hxx index 4c37f1b6e7a5..c6901e7fb022 100644 --- a/sc/source/filter/inc/xerecord.hxx +++ b/sc/source/filter/inc/xerecord.hxx @@ -24,6 +24,7 @@ #include "xlstream.hxx" #include <salhelper/simplereferenceobject.hxx> #include <rtl/ref.hxx> +#include <algorithm> // Base classes to export Excel records ======================================= @@ -385,6 +386,20 @@ public: (*aIt)->SaveXml( rStrm ); } + /** + Optimization for repeated removal. Since this is internally a vector, repeated RemoveRecord() + would repeatedly move all items after the removed position. Instead it's possible to invalidate + a record and then call RemoveInvalidatedRecords() at the end (which is necessary, the list is generally + not allowed to contain invalid entries). + */ + void InvalidateRecord( size_t nPos ) { maRecs[ nPos ] = nullptr; } + void RemoveInvalidatedRecords() + { + maRecs.erase( + std::remove_if( maRecs.begin(), maRecs.end(), [](const RecordRefType& xRec) { return xRec == nullptr; } ), + maRecs.end()); + } + private: typedef ::std::vector< RecordRefType > RecordVec; RecordVec maRecs; commit 74cf42c522e59397bb725d35c682364de032cb99 Author: Luboš Luňák <[email protected]> AuthorDate: Sun Mar 6 19:24:37 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 faster bulk insert into o3tl::sorted_vector (tdf#117366) Repeated insert() into o3tl::sorted_vector can turn out to be pathological, repeatedly moving most items aside for each element inserted. Make it possible to insert a normal vector that's been pre-sorted and made unique. 31s->9s for loading tdf#117366. Change-Id: If3a0366dd240ad46c23f5f3dc04e781b8c4b2aa2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131085 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/include/o3tl/sorted_vector.hxx b/include/o3tl/sorted_vector.hxx index 2bd8b7273a9a..13c0b25f8f0e 100644 --- a/include/o3tl/sorted_vector.hxx +++ b/include/o3tl/sorted_vector.hxx @@ -12,7 +12,9 @@ #include <vector> #include <algorithm> +#include <cassert> #include <functional> +#include <iterator> #include <memory> #include <type_traits> @@ -229,19 +231,32 @@ public: void insert(sorted_vector<Value,Compare,Find> const& rOther) { - // optimization for the rather common case that we are overwriting this with the contents - // of another sorted vector - if ( empty() ) - { - m_vector.insert(m_vector.begin(), rOther.m_vector.begin(), rOther.m_vector.end()); - } - else - { - for (const_iterator it = rOther.m_vector.begin(); it != rOther.m_vector.end(); ++it) - { - insert(*it); - } - } + // optimization for the rather common case that we are overwriting this with the contents + // of another sorted vector + if ( empty() ) + m_vector.insert(m_vector.begin(), rOther.m_vector.begin(), rOther.m_vector.end()); + else + insert_internal( rOther.m_vector ); + } + + void insert_sorted_unique_vector(const std::vector<Value>& rOther) + { + assert( std::is_sorted(rOther.begin(), rOther.end(), Compare())); + assert( std::unique(rOther.begin(), rOther.end(), compare_equal) == rOther.end()); + if ( empty() ) + m_vector.insert(m_vector.begin(), rOther.m_vector.begin(), rOther.m_vector.end()); + else + insert_internal( rOther ); + } + + void insert_sorted_unique_vector(std::vector<Value>&& rOther) + { + assert( std::is_sorted(rOther.begin(), rOther.end(), Compare())); + assert( std::unique(rOther.begin(), rOther.end(), compare_equal) == rOther.end()); + if ( empty() ) + m_vector.swap( rOther ); + else + insert_internal( rOther ); } /* Clear() elements in the vector, and free them one by one. */ @@ -266,6 +281,22 @@ public: } private: + static bool compare_equal( const Value& v1, const Value& v2 ) + { // Synthetize == check from < check for std::unique asserts above. + return !Compare()( v1, v2 ) && !Compare()( v2, v1 ); + } + + void insert_internal( const std::vector<Value>& rOther ) + { + // Do a union in one pass rather than repeated insert() that could repeatedly + // move large amounts of data. + vector_t tmp; + tmp.reserve( m_vector.size() + rOther.size()); + std::set_union( m_vector.begin(), m_vector.end(), + rOther.begin(), rOther.end(), + std::back_inserter( tmp ), Compare()); + m_vector.swap( tmp ); + } vector_t m_vector; }; diff --git a/sc/source/filter/inc/sheetdatabuffer.hxx b/sc/source/filter/inc/sheetdatabuffer.hxx index 17add16e6234..8002e6ee93f9 100644 --- a/sc/source/filter/inc/sheetdatabuffer.hxx +++ b/sc/source/filter/inc/sheetdatabuffer.hxx @@ -202,8 +202,17 @@ private: return lhs.mnEndRow<rhs.mnStartRow; } }; + struct StyleRowRangeCompEqual + { + bool operator() (const RowRangeStyle& lhs, const RowRangeStyle& rhs) const + { + return lhs.mnEndRow==rhs.mnStartRow; + } + }; typedef ::o3tl::sorted_vector< RowRangeStyle, StyleRowRangeComp > RowStyles; typedef ::std::map< sal_Int32, RowStyles > ColStyles; + typedef ::std::vector< RowRangeStyle > TmpRowStyles; + typedef ::std::map< sal_Int32, TmpRowStyles > TmpColStyles; /** Stores information about a merged cell range. */ struct MergedRange { diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx index d4d0ad87affd..b4d6158f66fe 100644 --- a/sc/source/filter/oox/sheetdatabuffer.cxx +++ b/sc/source/filter/oox/sheetdatabuffer.cxx @@ -353,6 +353,9 @@ void SheetDataBuffer::addColXfStyles() addIfNotInMyMap( getStyles(), rangeStyleListMap, rFormatKeyPair.first, rFormatKeyPair.second, rRangeList ); } // gather all ranges that have the same style and apply them in bulk + // Collect data in unsorted vectors and sort them just once at the end + // instead of possibly slow repeated inserts. + TmpColStyles tmpStylesPerColumn; for ( const auto& [rFormatKeyPair, rRanges] : rangeStyleListMap ) { for (const ScRange & rAddress : rRanges) @@ -363,9 +366,16 @@ void SheetDataBuffer::addColXfStyles() aStyleRows.mnStartRow = rAddress.aStart.Row(); aStyleRows.mnEndRow = rAddress.aEnd.Row(); for ( sal_Int32 nCol = rAddress.aStart.Col(); nCol <= rAddress.aEnd.Col(); ++nCol ) - maStylesPerColumn[ nCol ].insert( aStyleRows ); + tmpStylesPerColumn[ nCol ].push_back( aStyleRows ); } } + for( auto& rowStyles : tmpStylesPerColumn ) + { + TmpRowStyles& s = rowStyles.second; + std::sort( s.begin(), s.end(), StyleRowRangeComp()); + s.erase( std::unique( s.begin(), s.end(), StyleRowRangeCompEqual()), s.end()); + maStylesPerColumn[ rowStyles.first ].insert_sorted_unique_vector( std::move( s )); + } } void SheetDataBuffer::addColXfStyleProcessRowRanges() commit 4cb50c1081aa3f4686da8a35ca1159de7bcb750b Author: Luboš Luňák <[email protected]> AuthorDate: Sun Mar 6 15:55:10 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 don't try to spellcheck after last data cell (tdf#122827) Change-Id: I728e7f19a521f5f3583b4963d84c7d36527c8842 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131076 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index d0dbc63b8ab5..1e902dae8f22 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1068,7 +1068,6 @@ void ScColumn::GetOptimalHeight( bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& rData) const { ScDocument& rDocument = GetDoc(); - bool bStop = false; sc::CellStoreType::const_iterator it = maCells.position(nRow).first; mdds::mtv::element_t eType = it->type; if (!bInSel && it != maCells.end() && eType != sc::element_type_empty) @@ -1078,15 +1077,16 @@ bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& r rDocument.IsTabProtected(nTab)) ) return true; } - while (!bStop) + if (bInSel) { - if (bInSel) + SCROW lastDataPos = GetLastDataPos(); + for (;;) { nRow = rData.GetNextMarked(nCol, nRow, false); - if (!rDocument.ValidRow(nRow)) + if (!rDocument.ValidRow(nRow) || nRow > lastDataPos ) { nRow = GetDoc().MaxRow()+1; - bStop = true; + return false; } else { @@ -1100,7 +1100,10 @@ bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& r nRow++; } } - else if (GetNextDataPos(nRow)) + } + else + { + while (GetNextDataPos(nRow)) { it = maCells.position(it, nRow).first; eType = it->type; @@ -1111,13 +1114,9 @@ bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& r else nRow++; } - else - { - nRow = GetDoc().MaxRow()+1; - bStop = true; - } + nRow = GetDoc().MaxRow()+1; + return false; } - return false; } namespace { commit 8a5ad9e9c16088a94ba0dd7ed6ac9845f92ec650 Author: Luboš Luňák <[email protected]> AuthorDate: Sat Mar 5 17:12:39 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:08 2022 +0100 compress RowHidden()/GetRowHeight() use in excel export (tdf#126326) Change-Id: Idc6a704cfc820bbbb2b51eff8db8159c251ea9ab Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131062 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 764b69794418..44cedc482e01 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1908,7 +1908,7 @@ public: SC_DLLPUBLIC sal_uInt16 GetColWidth( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero = true ) const; SC_DLLPUBLIC tools::Long GetColWidth( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab ) const; SC_DLLPUBLIC sal_uInt16 GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero = true ) const; - SC_DLLPUBLIC sal_uInt16 GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow ) const; + SC_DLLPUBLIC sal_uInt16 GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero = true ) const; SC_DLLPUBLIC tools::Long GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero = true ) const; /** diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index ae57d12033a9..a7fabf46d1df 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -4177,10 +4177,10 @@ sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero return 0; } -sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow ) const +sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const { if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) - return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow ); + return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero ); OSL_FAIL("Wrong sheet number"); return 0; } diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index d6bb06b85ee9..d790ff74e7eb 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -2479,16 +2479,23 @@ XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt32 nXclRow, bool bRowAlwaysE const ScDocument& rDoc = GetRoot().GetDoc(); const SCTAB nScTab = GetRoot().GetCurrScTab(); + // Do not repeatedly call RowHidden() / GetRowHeight() for same values. + bool bHidden = false; + SCROW lastSameHiddenRow = -1; + sal_uInt16 nHeight = 0; + SCROW lastSameHeightRow = -1; // create the missing rows first while( nFrom <= nXclRow ) { // only create RowMap entries if it is first row in spreadsheet, // if it is the desired row, or for rows that differ from previous. - const bool bHidden = rDoc.RowHidden(nFrom, nScTab); + if( static_cast<SCROW>(nFrom) > lastSameHiddenRow ) + bHidden = rDoc.RowHidden(nFrom, nScTab, nullptr, &lastSameHiddenRow); // Always get the actual row height even if the manual size flag is // not set, to correctly export the heights of rows with wrapped // texts. - const sal_uInt16 nHeight = rDoc.GetRowHeight(nFrom, nScTab, false); + if( static_cast<SCROW>(nFrom) > lastSameHeightRow ) + nHeight = rDoc.GetRowHeight(nFrom, nScTab, nullptr, &lastSameHeightRow, false); if ( !pPrevEntry || ( nFrom == nXclRow ) || ( maOutlineBfr.IsCollapsed() ) || ( maOutlineBfr.GetLevel() != 0 ) || commit 62a25aad6d73d214d4ea6d7a50b3eee2c281cae0 Author: Luboš Luňák <[email protected]> AuthorDate: Sat Mar 5 15:47:28 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:07 2022 +0100 don't bother tracking changes if both cells are empty (tdf#141174) AppendContent() does something only if the cells differ, which can't be the case if they're both empty, so skip unallocated cells. Change-Id: I367801bac30a8ee641b4ce608392124bac6ef47a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131060 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx index 5e42548c1c74..a4e7f8bc99d4 100644 --- a/sc/source/core/tool/chgtrack.cxx +++ b/sc/source/core/tool/chgtrack.cxx @@ -2690,10 +2690,15 @@ void ScChangeTrack::AppendContentRange( const ScRange& rRange, for ( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ ) { aPos.SetTab( nTab ); - for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ ) + // AppendContent() is a no-op if both cells are empty. + SCCOL lastCol = std::max( pRefDoc->ClampToAllocatedColumns( nTab, nCol2 ), + rDoc.ClampToAllocatedColumns( nTab, nCol2 )); + for ( SCCOL nCol = nCol1; nCol <= lastCol; nCol++ ) { aPos.SetCol( nCol ); - for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ ) + SCROW lastRow = std::max( pRefDoc->GetLastDataRow( nTab, nCol, nCol, nRow2 ), + rDoc.GetLastDataRow( nTab, nCol, nCol, nRow2 )); + for ( SCROW nRow = nRow1; nRow <= lastRow; nRow++ ) { aPos.SetRow( nRow ); AppendContent( aPos, pRefDoc ); commit 114c4ea1f2bdfd372ef5b57a9b575e889704ca65 Author: Luboš Luňák <[email protected]> AuthorDate: Sat Mar 5 15:25:19 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:07 2022 +0100 don't bother scanning nonexistent data (tdf#141182) There's no point scanning for non-empty cells after the last data cell, and this avoids processing mdds structures (such as repeated creating of flat_segment_tree). Change-Id: Ibec324aa2de457e8439c38a561f55ced9f478899 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131059 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 12cffaf8b449..2163b52114cb 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -93,6 +93,8 @@ void ScColumn::BroadcastCells( const std::vector<SCROW>& rRows, SfxHintId nHint void ScColumn::BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint ) { + if( nStartRow > GetLastDataPos()) + return; sc::SingleColumnSpanSet aSpanSet(GetDoc().GetSheetLimits()); aSpanSet.scan(*this, nStartRow, nEndRow); std::vector<SCROW> aRows; diff --git a/sc/source/core/data/columnspanset.cxx b/sc/source/core/data/columnspanset.cxx index 7a4d90f65652..eb09ea26be98 100644 --- a/sc/source/core/data/columnspanset.cxx +++ b/sc/source/core/data/columnspanset.cxx @@ -25,12 +25,12 @@ namespace sc { namespace { -class ColumnScanner +class ColumnNonEmptyRangesScanner { ColumnSpanSet::ColumnSpansType& mrRanges; bool mbVal; public: - ColumnScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) : + ColumnNonEmptyRangesScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) : mrRanges(rRanges), mbVal(bVal) {} void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize) @@ -137,7 +137,10 @@ void ColumnSpanSet::scan( const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells; - ColumnScanner aScanner(rCol.maSpans, bVal); + if( nRow1 > pTab->aCol[nCol].GetLastDataPos()) + continue; + + ColumnNonEmptyRangesScanner aScanner(rCol.maSpans, bVal); ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2); } } @@ -219,11 +222,11 @@ void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) cons namespace { -class Scanner +class NonEmptyRangesScanner { SingleColumnSpanSet::ColumnSpansType& mrRanges; public: - explicit Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {} + explicit NonEmptyRangesScanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {} void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize) { @@ -258,16 +261,20 @@ void SingleColumnSpanSet::scan(const ScColumn& rColumn) void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd) { + if( nStart > rColumn.GetLastDataPos()) + return; const CellStoreType& rCells = rColumn.maCells; - Scanner aScanner(maSpans); + NonEmptyRangesScanner aScanner(maSpans); sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd); } void SingleColumnSpanSet::scan( ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd) { + if( nStart > rColumn.GetLastDataPos()) + return; const CellStoreType& rCells = rColumn.maCells; - Scanner aScanner(maSpans); + NonEmptyRangesScanner aScanner(maSpans); rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd); } commit 820d986367e86b7fca717ad7490bfc962396eac1 Author: Luboš Luňák <[email protected]> AuthorDate: Sat Mar 5 08:47:44 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:07 2022 +0100 make sc_namedrangesobj test work with 16k columns 'row1' is not a valid named range with 16k columns, it's a cell address. Since the named range is constructed by the test, not even 582fc887f1faafe8ff5f16a13a0208483a93353f can take care of it, so rename such ranges. Change-Id: I6643953d41e391c8c3cfc55768b06d61d9fcb0a2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131046 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/qa/extras/testdocuments/ScNamedRangeObj.ods b/sc/qa/extras/testdocuments/ScNamedRangeObj.ods index 39a53b27925f..6bd563623f77 100644 Binary files a/sc/qa/extras/testdocuments/ScNamedRangeObj.ods and b/sc/qa/extras/testdocuments/ScNamedRangeObj.ods differ commit dab3dec28da57f1132f5b4b194f452d12366225a Author: Luboš Luňák <[email protected]> AuthorDate: Fri Mar 4 20:42:59 2022 +0100 Commit: Luboš Luňák <[email protected]> CommitDate: Wed Mar 23 09:09:07 2022 +0100 remove more hardcoded sheet sizes from Calc tests E.g. sctablesheetobj test had the limits hardcoded, even as actual numbers. Apparently some tests cannot easily access global settings, but this at least makes it easy to check all tests after modifying ScSheetLimits::CreateDefault(). Change-Id: I6cff577fb01b1ea262dcd1f9fde24e114e19abdc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131040 Tested-by: Jenkins Reviewed-by: Luboš Luňák <[email protected]> diff --git a/sc/CppunitTest_sc_tablecolumnsobj.mk b/sc/CppunitTest_sc_tablecolumnsobj.mk index 04d41985aa22..29e65d860830 100644 --- a/sc/CppunitTest_sc_tablecolumnsobj.mk +++ b/sc/CppunitTest_sc_tablecolumnsobj.mk @@ -22,12 +22,15 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sc_tablecolumnsobj, \ $(eval $(call gb_CppunitTest_use_libraries,sc_tablecolumnsobj, \ cppu \ sal \ + salhelper \ + sc \ subsequenttest \ test \ unotest \ )) $(eval $(call gb_CppunitTest_set_include,sc_tablecolumnsobj,\ + -I$(SRCDIR)/sc/inc \ $$(INCLUDE) \ )) diff --git a/sc/CppunitTest_sc_tablerowsobj.mk b/sc/CppunitTest_sc_tablerowsobj.mk index 4c82243b4f1a..ffbd3850aebd 100644 --- a/sc/CppunitTest_sc_tablerowsobj.mk +++ b/sc/CppunitTest_sc_tablerowsobj.mk @@ -22,12 +22,15 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sc_tablerowsobj, \ $(eval $(call gb_CppunitTest_use_libraries,sc_tablerowsobj, \ cppu \ sal \ + salhelper \ + sc \ subsequenttest \ test \ unotest \ )) $(eval $(call gb_CppunitTest_set_include,sc_tablerowsobj,\ + -I$(SRCDIR)/sc/inc \ $$(INCLUDE) \ )) diff --git a/sc/CppunitTest_sc_tablesheetobj.mk b/sc/CppunitTest_sc_tablesheetobj.mk index 44e72d112bc8..52f7f427b27a 100644 --- a/sc/CppunitTest_sc_tablesheetobj.mk +++ b/sc/CppunitTest_sc_tablesheetobj.mk @@ -22,12 +22,15 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sc_tablesheetobj, \ $(eval $(call gb_CppunitTest_use_libraries,sc_tablesheetobj, \ cppu \ sal \ + salhelper \ + sc \ subsequenttest \ test \ unotest \ )) $(eval $(call gb_CppunitTest_set_include,sc_tablesheetobj,\ + -I$(SRCDIR)/sc/inc \ $$(INCLUDE) \ )) diff --git a/sc/inc/sheetlimits.hxx b/sc/inc/sheetlimits.hxx index cbc017c9d10e..1d1410b9056a 100644 --- a/sc/inc/sheetlimits.hxx +++ b/sc/inc/sheetlimits.hxx @@ -31,12 +31,13 @@ struct ScSheetLimits final : public salhelper::SimpleReferenceObject ScSheetLimits(SCCOL nMaxCol, SCROW nMaxRow) : mnMaxCol(nMaxCol) - , mnMaxRow(nMaxRow){} - - [[nodiscard]] bool ValidCol(SCCOL nCol) const + , mnMaxRow(nMaxRow) { - return ::ValidCol(nCol, mnMaxCol); } + + SC_DLLPUBLIC static ScSheetLimits CreateDefault(); + + [[nodiscard]] bool ValidCol(SCCOL nCol) const { return ::ValidCol(nCol, mnMaxCol); } [[nodiscard]] bool ValidRow(SCROW nRow) const { return ::ValidRow(nRow, mnMaxRow); } [[nodiscard]] bool ValidColRow(SCCOL nCol, SCROW nRow) const { diff --git a/sc/qa/extras/sctablecolumnsobj.cxx b/sc/qa/extras/sctablecolumnsobj.cxx index 406e559489fa..ccb96f7c786d 100644 --- a/sc/qa/extras/sctablecolumnsobj.cxx +++ b/sc/qa/extras/sctablecolumnsobj.cxx @@ -29,6 +29,8 @@ #include <com/sun/star/uno/Reference.hxx> +#include <sheetlimits.hxx> + using namespace css; namespace sc_apitest @@ -90,7 +92,7 @@ private: ScTableColumnsObj::ScTableColumnsObj() : CalcUnoApiTest("/sc/qa/extras/testdocuments") , XElementAccess(cppu::UnoType<table::XCellRange>::get()) - , XIndexAccess(1024) + , XIndexAccess(ScSheetLimits::CreateDefault().GetMaxColCount()) , XNameAccess("ABC") , XServiceInfo("ScTableColumnsObj", "com.sun.star.table.TableColumns") { diff --git a/sc/qa/extras/sctablerowsobj.cxx b/sc/qa/extras/sctablerowsobj.cxx index 5efe6bc64cac..419a326f48cd 100644 --- a/sc/qa/extras/sctablerowsobj.cxx +++ b/sc/qa/extras/sctablerowsobj.cxx @@ -28,6 +28,8 @@ #include <cppu/unotype.hxx> +#include <sheetlimits.hxx> + using namespace css; using namespace css::uno; @@ -79,7 +81,7 @@ private: ScTableRowsObj::ScTableRowsObj() : CalcUnoApiTest("/sc/qa/extras/testdocuments") , XElementAccess(cppu::UnoType<table::XCellRange>::get()) - , XIndexAccess(1048576) + , XIndexAccess(ScSheetLimits::CreateDefault().GetMaxRowCount()) , XServiceInfo("ScTableRowsObj", "com.sun.star.table.TableRows") { } diff --git a/sc/qa/extras/sctablesheetobj.cxx b/sc/qa/extras/sctablesheetobj.cxx index 3179ae54d2d3..055de3babb2b 100644 --- a/sc/qa/extras/sctablesheetobj.cxx +++ b/sc/qa/extras/sctablesheetobj.cxx @@ -48,6 +48,8 @@ #include <com/sun/star/sheet/XSpreadsheet.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> +#include <sheetlimits.hxx> + using namespace css; using namespace css::uno; @@ -248,7 +250,10 @@ private: ScTableSheetObj::ScTableSheetObj(): CalcUnoApiTest("/sc/qa/extras/testdocuments"), apitest::XCellSeries(1, 0), - apitest::XFormulaQuery(table::CellRangeAddress(0, 0, 0, 1023, 1048575), table::CellRangeAddress(0, 0, 0, 1023, 1048575), 0, 0), + apitest::XFormulaQuery( + table::CellRangeAddress(0, 0, 0, ScSheetLimits::CreateDefault().MaxCol(), ScSheetLimits::CreateDefault().MaxRow()), + table::CellRangeAddress(0, 0, 0, ScSheetLimits::CreateDefault().MaxCol(), ScSheetLimits::CreateDefault().MaxRow()), + 0, 0), apitest::XReplaceable("searchReplaceString", "replaceReplaceString"), apitest::XSearchable("test", 4) { diff --git a/sc/qa/unit/mark_test.cxx b/sc/qa/unit/mark_test.cxx index 55a13cb0da57..bca735aae202 100644 --- a/sc/qa/unit/mark_test.cxx +++ b/sc/qa/unit/mark_test.cxx @@ -96,7 +96,8 @@ class Test : public CppUnit::TestFixture public: void testSimpleMark( const ScRange& rRange, const ScRange& rSelectionCover, const ScRangeList& rLeftEnvelope, const ScRangeList& rRightEnvelope, - const ScRangeList& rTopEnvelope, const ScRangeList& rBottomEnvelope ); + const ScRangeList& rTopEnvelope, const ScRangeList& rBottomEnvelope, + const ScSheetLimits& rLimits ); void testSimpleMark_Simple(); void testSimpleMark_Column(); void testSimpleMark_Row(); @@ -147,10 +148,10 @@ static void lcl_GetSortedRanges( const ScRangeList& rRangeList, ScRangeList& rRa void Test::testSimpleMark( const ScRange& rRange, const ScRange& rSelectionCover, const ScRangeList& rLeftEnvelope, const ScRangeList& rRightEnvelope, - const ScRangeList& rTopEnvelope, const ScRangeList& rBottomEnvelope ) + const ScRangeList& rTopEnvelope, const ScRangeList& rBottomEnvelope, + const ScSheetLimits& rLimits ) { - ScSheetLimits aSheetLimits(MAXCOL, MAXROW); - ScMarkData aMark(aSheetLimits); + ScMarkData aMark(rLimits); CPPUNIT_ASSERT( !aMark.IsMarked() ); CPPUNIT_ASSERT( !aMark.IsMultiMarked() ); @@ -168,29 +169,29 @@ void Test::testSimpleMark( const ScRange& rRange, const ScRange& rSelectionCover SCCOL nOutCol2 = rRange.aStart.Col() - 1; CPPUNIT_ASSERT( aMark.IsCellMarked( nMidCol, nMidRow ) ); - if ( ValidCol( nOutCol1, MAXCOL ) && ValidRow( nOutRow1, MAXROW ) ) + if ( ValidCol( nOutCol1, rLimits.MaxCol() ) && ValidRow( nOutRow1, rLimits.MaxRow() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nOutCol1, nOutRow1 ) ); - if ( ValidCol( nOutCol2, MAXCOL ) && ValidRow( nOutRow2, MAXROW ) ) + if ( ValidCol( nOutCol2, rLimits.MaxCol() ) && ValidRow( nOutRow2, rLimits.MaxRow() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nOutCol2, nOutRow2 ) ); - if ( ValidRow( nOutRow1, MAXROW ) ) + if ( ValidRow( nOutRow1, rLimits.MaxRow() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nMidCol, nOutRow1 ) ); - if ( ValidCol( nOutCol1, MAXCOL ) ) + if ( ValidCol( nOutCol1, rLimits.MaxCol() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nOutCol1, nMidRow ) ); - if ( ValidRow( nOutRow2, MAXROW ) ) + if ( ValidRow( nOutRow2, rLimits.MaxRow() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nMidCol, nOutRow2 ) ); - if ( ValidCol( nOutCol2, MAXCOL ) ) + if ( ValidCol( nOutCol2, rLimits.MaxCol() ) ) CPPUNIT_ASSERT( !aMark.IsCellMarked( nOutCol2, nMidRow ) ); - if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW ) + if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rLimits.MaxRow() ) CPPUNIT_ASSERT( aMark.IsColumnMarked( nMidCol ) ); else CPPUNIT_ASSERT( !aMark.IsColumnMarked( nMidCol ) ); - if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL ) + if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rLimits.MaxCol() ) CPPUNIT_ASSERT( aMark.IsRowMarked( nMidRow ) ); else CPPUNIT_ASSERT( !aMark.IsRowMarked( nMidRow ) ); @@ -206,58 +207,65 @@ void Test::testSimpleMark( const ScRange& rRange, const ScRange& rSelectionCover void Test::testSimpleMark_Simple() { + ScSheetLimits limits( ScSheetLimits::CreateDefault()); testSimpleMark( ScRange( 10, 15, 0, 20, 30, 0 ), // Simple range ScRange( 9, 14, 0, 21, 31, 0 ), // Cover ScRangeList( ScRange( 9, 15, 0, 9, 30, 0 ) ), // Left envelope ScRangeList( ScRange( 21, 15, 0, 21, 30, 0 ) ), // Right envelope ScRangeList( ScRange( 10, 14, 0, 20, 14, 0 ) ), // Top envelope - ScRangeList( ScRange( 10, 31, 0, 20, 31, 0 ) ) ); // Bottom envelope + ScRangeList( ScRange( 10, 31, 0, 20, 31, 0 ) ), // Bottom envelope + limits ); } void Test::testSimpleMark_Column() { + ScSheetLimits limits( ScSheetLimits::CreateDefault()); // Column 10, rows from 15 to 30 testSimpleMark( ScRange( 10, 15, 0, 10, 30, 0 ), // Simple range ScRange( 9, 14, 0, 11, 31, 0 ), // Cover ScRangeList( ScRange( 9, 15, 0, 9, 30, 0 ) ), // Left envelope ScRangeList( ScRange( 11, 15, 0, 11, 30, 0 ) ), // Right envelope ScRangeList( ScRange( 10, 14, 0, 10, 14, 0 ) ), // Top envelope - ScRangeList( ScRange( 10, 31, 0, 10, 31, 0 ) ) ); // Bottom envelope + ScRangeList( ScRange( 10, 31, 0, 10, 31, 0 ) ), // Bottom envelope + limits ); // Full Column 10 - testSimpleMark( ScRange( 10, 0, 0, 10, MAXROW, 0 ), // Simple range - ScRange( 9, 0, 0, 11, MAXROW, 0 ), // Cover - ScRangeList( ScRange( 9, 0, 0, 9, MAXROW, 0 ) ), // Left envelope - ScRangeList( ScRange( 11, 0, 0, 11, MAXROW, 0 ) ), // Right envelope + testSimpleMark( ScRange( 10, 0, 0, 10, limits.MaxRow(), 0 ), // Simple range + ScRange( 9, 0, 0, 11, limits.MaxRow(), 0 ), // Cover + ScRangeList( ScRange( 9, 0, 0, 9, limits.MaxRow(), 0 ) ), // Left envelope + ScRangeList( ScRange( 11, 0, 0, 11, limits.MaxRow(), 0 ) ), // Right envelope ScRangeList(), // Top envelope - ScRangeList()); // Bottom envelope + ScRangeList(), // Bottom envelope + limits ); } void Test::testSimpleMark_Row() { + ScSheetLimits limits( ScSheetLimits::CreateDefault()); // Row 15, cols from 10 to 20 testSimpleMark( ScRange( 10, 15, 0, 20, 15, 0 ), // Simple range ScRange( 9, 14, 0, 21, 16, 0 ), // Cover ScRangeList( ScRange( 9, 15, 0, 9, 15, 0 ) ), // Left envelope ScRangeList( ScRange( 21, 15, 0, 21, 15, 0 ) ), // Right envelope ScRangeList( ScRange( 10, 14, 0, 20, 14, 0 ) ), // Top envelope - ScRangeList( ScRange( 10, 16, 0, 20, 16, 0 ) ) ); // Bottom envelope + ScRangeList( ScRange( 10, 16, 0, 20, 16, 0 ) ), // Bottom envelope + limits ); // Full Row 15 - testSimpleMark( ScRange( 0, 15, 0, MAXCOL, 15, 0 ), // Simple range - ScRange( 0, 14, 0, MAXCOL, 16, 0 ), // Cover + testSimpleMark( ScRange( 0, 15, 0, limits.MaxCol(), 15, 0 ), // Simple range + ScRange( 0, 14, 0, limits.MaxCol(), 16, 0 ), // Cover ScRangeList(), // Left envelope ScRangeList(), // Right envelope - ScRangeList( ScRange( 0, 14, 0, MAXCOL, 14, 0 ) ), // Top envelope - ScRangeList( ScRange( 0, 16, 0, MAXCOL, 16, 0 ) ) ); // Bottom envelope + ScRangeList( ScRange( 0, 14, 0, limits.MaxCol(), 14, 0 ) ), // Top envelope + ScRangeList( ScRange( 0, 16, 0, limits.MaxCol(), 16, 0 ) ), // Bottom envelope + limits ); } void Test::testMultiMark( const MultiMarkTestData& rMarksData ) { - - ScSheetLimits aSheetLimits(MAXCOL, MAXROW); - ScMarkData aMark(aSheetLimits); - ScMultiSel aMultiSel(aSheetLimits); + ScSheetLimits limits( ScSheetLimits::CreateDefault()); + ScMarkData aMark(limits); + ScMultiSel aMultiSel(limits); CPPUNIT_ASSERT( !aMark.IsMarked() ); CPPUNIT_ASSERT( !aMark.IsMultiMarked() ); CPPUNIT_ASSERT_EQUAL( SCCOL(0), aMultiSel.GetMultiSelectionCount() ); @@ -286,13 +294,13 @@ void Test::testMultiMark( const MultiMarkTestData& rMarksData ) for ( const auto& rCol : rAreaTestData.aColumnsWithFullMarks ) { CPPUNIT_ASSERT( aMark.IsColumnMarked( rCol ) ); - CPPUNIT_ASSERT( aMultiSel.IsAllMarked( rCol, 0, MAXROW ) ); + CPPUNIT_ASSERT( aMultiSel.IsAllMarked( rCol, 0, limits.MaxRow() ) ); } for ( const auto& rCol : rAreaTestData.aColumnsWithoutFullMarks ) { CPPUNIT_ASSERT( !aMark.IsColumnMarked( rCol ) ); - CPPUNIT_ASSERT( !aMultiSel.IsAllMarked( rCol, 0, MAXROW ) ); + CPPUNIT_ASSERT( !aMultiSel.IsAllMarked( rCol, 0, limits.MaxRow() ) ); } for ( const auto& rRow : rAreaTestData.aRowsWithFullMarks ) @@ -415,6 +423,7 @@ void Test::testMultiMark( const MultiMarkTestData& rMarksData ) void Test::testMultiMark_FourRanges() { + ScSheetLimits limits( ScSheetLimits::CreateDefault()); MultiMarkTestData aData; MarkTestData aSingle1; @@ -449,7 +458,7 @@ void Test::testMultiMark_FourRanges() aSingle1.aNextMarked.emplace_back( 15, 1, 0, 1, 5, 0 ); // Search down aSingle1.aNextMarked.emplace_back( 15, 15, 0, 0, 10, 0 ); // Search up - aSingle1.aNextMarked.emplace_back( 15, 15, 0, 1, MAXROWCOUNT, 0 ); // Search down fail + aSingle1.aNextMarked.emplace_back( 15, 15, 0, 1, limits.GetMaxRowCount(), 0 ); // Search down fail aSingle1.aNextMarked.emplace_back( 15, 4, 0, 0, -1, 0 ); // Search up fail aSingle1.aColumnsWithAtLeastOneMark.push_back( 10 ); @@ -495,7 +504,7 @@ void Test::testMultiMark_FourRanges() aSingle2.aNextMarked.emplace_back( 27, 16, 0, 0, 15, 0 ); // up ok aSingle2.aNextMarked.emplace_back( 27, 4, 0, 1, 7, 0 ); // down ok aSingle2.aNextMarked.emplace_back( 27, 4, 0, 0, -1, 0 ); // up fail - aSingle2.aNextMarked.emplace_back( 27, 16, 0, 1, MAXROWCOUNT, 0 ); // down fail + aSingle2.aNextMarked.emplace_back( 27, 16, 0, 1, limits.GetMaxRowCount(), 0 ); // down fail aSingle2.aColumnsWithAtLeastOneMark = aSingle1.aColumnsWithAtLeastOneMark; aSingle2.aColumnsWithAtLeastOneMark.push_back( 25 ); @@ -510,7 +519,7 @@ void Test::testMultiMark_FourRanges() // Full row = 20 MarkTestData aSingle3; - aSingle3.aRange = ScRange( 0, 20, 0, MAXCOL, 20, 0 ); + aSingle3.aRange = ScRange( 0, 20, 0, limits.MaxCol(), 20, 0 ); aSingle3.bMark = true; aSingle3.aInsideAddresses = aSingle2.aInsideAddresses; @@ -525,13 +534,13 @@ void Test::testMultiMark_FourRanges() aSingle3.aRowsWithFullMarks.push_back( 20 ); aSingle3.aRangesWithFullMarks = aSingle2.aRangesWithFullMarks; - aSingle3.aRangesWithFullMarks.emplace_back( 0, 20, 0, MAXCOL, 20, 0 ); + aSingle3.aRangesWithFullMarks.emplace_back( 0, 20, 0, limits.MaxCol(), 20, 0 ); aSingle3.aRangesWithFullMarks.emplace_back( 15, 20, 0, 55, 20, 0 ); aSingle3.aNextMarked.emplace_back( 15, 16, 0, 0, 10, 0 ); // up ok aSingle3.aNextMarked.emplace_back( 15, 16, 0, 1, 20, 0 ); // down ok aSingle3.aNextMarked.emplace_back( 22, 15, 0, 0, -1, 0 ); // up fail - aSingle3.aNextMarked.emplace_back( 22, 25, 0, 1, MAXROWCOUNT, 0 ); // down fail + aSingle3.aNextMarked.emplace_back( 22, 25, 0, 1, limits.GetMaxRowCount(), 0 ); // down fail aSingle3.aColumnsWithAtLeastOneMark = aSingle2.aColumnsWithAtLeastOneMark; aSingle3.aColumnsWithAtLeastOneMark.push_back( 39 ); @@ -539,7 +548,7 @@ void Test::testMultiMark_FourRanges() // Full col = 35 MarkTestData aSingle4; - aSingle4.aRange = ScRange( 35, 0, 0, 35, MAXROW, 0 ); + aSingle4.aRange = ScRange( 35, 0, 0, 35, limits.MaxRow(), 0 ); aSingle4.bMark = true; aSingle4.aInsideAddresses = aSingle3.aInsideAddresses; @@ -556,7 +565,7 @@ void Test::testMultiMark_FourRanges() aSingle4.aRowsWithFullMarks.push_back( 20 ); aSingle4.aRangesWithFullMarks = aSingle3.aRangesWithFullMarks; - aSingle4.aRangesWithFullMarks.emplace_back( 35, 0, 0, 35, MAXROW, 0 ); + aSingle4.aRangesWithFullMarks.emplace_back( 35, 0, 0, 35, limits.MaxRow(), 0 ); aSingle4.aRangesWithFullMarks.emplace_back( 35, 10, 0, 35, 25, 0 ); // Add the rectangle data to aData @@ -565,26 +574,26 @@ void Test::testMultiMark_FourRanges() ... etc. - the rest is truncated
