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

Reply via email to