sc/inc/column.hxx                |   75 ++++++++++++++++++++----------
 sc/inc/markdata.hxx              |    5 ++
 sc/inc/table.hxx                 |    2 
 sc/source/core/data/attarray.cxx |    6 +-
 sc/source/core/data/column.cxx   |   62 ++++++++++++++-----------
 sc/source/core/data/fillinfo.cxx |    2 
 sc/source/core/data/markdata.cxx |   16 ++++++
 sc/source/core/data/table1.cxx   |    6 +-
 sc/source/core/data/table2.cxx   |   95 +++++++++++++++++++++++++--------------
 9 files changed, 180 insertions(+), 89 deletions(-)

New commits:
commit 17bcf1073bf21088b9845e36fe735622d8f88fd7
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Wed Feb 16 14:14:06 2022 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Sat Mar 5 08:30:15 2022 +0100

    introduce ScColumnData for ScColumn/ScTable code sharing
    
    Since columns are allocated dynamically on demand, up until
    this commit ScTable had ScPatternAttr member for unallocated
    columns that it was using in place of those unallocated columns.
    But that meant either copy&pasting pieces of code from ScColumn,
    or having extra slightly more cumbersome shared function
    in ScColumn, or even nothing.
    
    Improve this by creating ScColumnData, which will be used as
    ScColumn base class to keep things working as before, but
    ScTable now also contains one ScColumnData instance and
    so it can also call its functions.
    
    Change-Id: If1d842c4a5aec32e2a7729358006d79cd831349f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131034
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index e23eac0fdab1..7eea78900600 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -108,7 +108,54 @@ struct ScNeededSizeOptions
     ScNeededSizeOptions();
 };
 
-class ScColumn
+// A shared implementation of some column code and data.
+// This is used by ScColumn, but also by ScTable for the unallocated
+// columns (one instance that is the default for all not-yet allocated 
columns).
+class ScColumnData
+{
+protected:
+    std::unique_ptr<ScAttrArray> pAttrArray;
+
+    ScColumnData(const ScColumnData&) = delete;
+    ScColumnData& operator= (const ScColumnData&) = delete;
+
+public:
+    ScColumnData() = default;
+    void InitAttrArray(ScAttrArray* attrArray) { pAttrArray.reset(attrArray); }
+
+    ScDocument& GetDoc() const { return pAttrArray->GetDoc(); }
+
+    ScAttrArray& AttrArray() { return *pAttrArray; }
+    const ScAttrArray& AttrArray() const { return *pAttrArray; }
+
+    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,
+                                     SCCOL nCol );
+    void        ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
+                                  ScEditDataArray* pDataArray = nullptr,
+                                  bool* const pIsChanged = nullptr);
+    void        MergePatternArea( ScMergePatternState& rState, SCROW nRow1, 
SCROW nRow2, bool bDeep ) const;
+
+    sal_uInt32  GetNumberFormat( const ScInterpreterContext& rContext, SCROW 
nRow ) const;
+    sal_uInt32  GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const;
+
+    /// Including current, may return -1
+    SCROW       GetNextUnprotected( SCROW nRow, bool bUp ) const;
+
+    const ScStyleSheet* GetStyle( SCROW nRow ) const;
+    void        ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const 
ScStyleSheet& rStyle );
+
+    bool        HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) 
const;
+
+    void        ClearSelectionItems( const sal_uInt16* pWhich, const 
ScMarkData& rMark, SCCOL nCol );
+    void        ChangeSelectionIndent( bool bIncrement, const ScMarkData& 
rMark, SCCOL nCol );
+};
+
+// Use protected inheritance to prevent publishing some internal ScColumnData
+// functions as part of ScColumn. If they should be public in ScColumn,
+// use 'using' to make them public.
+class ScColumn : protected ScColumnData
 {
     // Empty values correspond with empty cells. All non-empty cell positions
     // must have non-empty elements. For text width, the value should be
@@ -126,8 +173,6 @@ class ScColumn
     // Cell values.
     sc::CellStoreType maCells;
 
-    std::unique_ptr<ScAttrArray> pAttrArray;
-
     size_t mnBlkCountFormula;
 
     SCCOL           nCol;
@@ -156,9 +201,6 @@ friend class sc::CellValues;
 friend class sc::TableValues;
 friend class sc::CellStoreEvent;
 
-    ScColumn(const ScColumn&) = delete;
-    ScColumn& operator= (const ScColumn&) = delete;
-
     bool ParseString(
         ScCellValue& rCell,
         SCROW nRow, SCTAB nTab, const OUString& rString, 
formula::FormulaGrammar::AddressConvention eConv,
@@ -179,7 +221,7 @@ public:
 
     void        Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument& rDoc, bool 
bEmptyAttrArray);
 
-    ScDocument& GetDoc() const { return pAttrArray->GetDoc(); }
+    using ScColumnData::GetDoc;
     SCTAB GetTab() const { return nTab; }
     SCCOL GetCol() const { return nCol; }
     bool HasFiltering() const { return mbFiltering; }
@@ -204,7 +246,6 @@ public:
     void        FreeNotes();
     void        Swap( ScColumn& rOther, SCROW nRow1, SCROW nRow2, bool 
bPattern );
 
-    bool        HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) 
const;
     bool        HasAttribSelection( const ScMarkData& rMark, HasAttrFlags 
nMask ) const;
     bool        IsMerged( SCROW nRow ) const;
     bool        ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
@@ -457,16 +498,10 @@ public:
     {
         return static_cast<const T&>(GetAttr(nRow, sal_uInt16(nWhich)));
     }
-    const ScPatternAttr*    GetPattern( SCROW nRow ) const;
-    const ScPatternAttr*    GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow 
) const;
-
-    sal_uInt32  GetNumberFormat( const ScInterpreterContext& rContext, SCROW 
nRow ) const;
-    sal_uInt32  GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const;
-    // Mainly to be used by ScTable to share code.
-    static sal_uInt32 GetNumberFormat( const ScDocument& rDoc, const 
ScAttrArray* pAttrArray, SCROW nStartRow, SCROW nEndRow );
+    using ScColumnData::GetPattern;
+    using ScColumnData::GetNumberFormat;
 
     void        MergeSelectionPattern( ScMergePatternState& rState, const 
ScMarkData& rMark, bool bDeep ) const;
-    void        MergePatternArea( ScMergePatternState& rState, SCROW nRow1, 
SCROW nRow2, bool bDeep ) const;
     void        MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* 
pLineInner,
                             ScLineFlags& rFlags,
                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL 
nDistRight ) const;
@@ -475,9 +510,6 @@ public:
 
     void        ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr );
     void        ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr );
-    void        ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
-                                  ScEditDataArray* pDataArray = nullptr,
-                                  bool* const pIsChanged = nullptr);
     const ScPatternAttr* SetPattern( SCROW nRow, 
std::unique_ptr<ScPatternAttr> );
     void        SetPattern( SCROW nRow, const ScPatternAttr& );
     void        SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& );
@@ -485,14 +517,12 @@ public:
                             const ScPatternAttr& rPattern, SvNumFormatType 
nNewType );
 
     void        ApplyStyle( SCROW nRow, const ScStyleSheet* rStyle );
-    void        ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const 
ScStyleSheet& rStyle );
     void        ApplySelectionStyle(const ScStyleSheet& rStyle, const 
ScMarkData& rMark);
     void        ApplySelectionLineStyle( const ScMarkData& rMark,
                                     const ::editeng::SvxBorderLine* pLine, 
bool bColorOnly );
     void        AddCondFormat(SCROW nStartRow, SCROW nEndRow, sal_uInt32 
nIndex );
     void        RemoveCondFormat(SCROW nStartRow, SCROW nEndRow, sal_uInt32 
nIndex );
 
-    const ScStyleSheet* GetStyle( SCROW nRow ) const;
     const ScStyleSheet* GetSelectionStyle( const ScMarkData& rMark, bool& 
rFound ) const;
     const ScStyleSheet* GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) 
const;
 
@@ -534,9 +564,6 @@ public:
     void GetOptimalHeight(
         sc::RowHeightContext& rCxt, SCROW nStartRow, SCROW nEndRow, sal_uInt16 
nMinHeight, SCROW nMinStart );
 
-                /// Including current, may return -1
-    SCROW      GetNextUnprotected( SCROW nRow, bool bUp ) const;
-
     void GetFilterEntries(
         sc::ColumnBlockConstPosition& rBlockPos, SCROW nStartRow, SCROW 
nEndRow,
         ScFilterEntries& rFilterEntries, bool bFiltering );
diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx
index 6c2969e6e50a..ddc550f4bd42 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -82,6 +82,7 @@ public:
 
     const ScRange& GetMarkArea() const { return aMarkRange; }
     const ScRange& GetMultiMarkArea() const { return aMultiRange; }
+    const ScRange& GetArea() const { return bMultiMarked ? aMultiRange : 
aMarkRange; }
 
     void        SetAreaTab( SCTAB nTab );
 
@@ -131,6 +132,10 @@ public:
     bool        IsRowMarked( SCROW nRow ) const;
     bool        IsAllMarked( const ScRange& rRange ) const;     // Multi
 
+    // Returns the first column of the range [column,nLastCol] for which
+    // all those columns have equal marks. Value returned is not less than 
nMinCol.
+    SCCOL       GetStartOfEqualColumns( SCCOL nLastCol, SCCOL nMinCol = 0 ) 
const;
+
                 /// May return -1
     SCROW       GetNextMarked( SCCOL nCol, SCROW nRow, bool bUp ) const;
     bool        HasMultiMarks( SCCOL nCol ) const;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 4a8654a67344..1bc9094232a1 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -248,7 +248,7 @@ private:
     std::atomic<bool> bStreamValid;
 
     // Default attributes for the unallocated columns.
-    ScAttrArray     aDefaultColAttrArray;
+    ScColumnData    aDefaultColData;
 
 friend class ScDocument;                    // for FillInfo
 friend class ScColumn;
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 71efb305750c..4ed7b5cc5c97 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -1716,13 +1716,15 @@ void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW 
nEndRow, bool bIncrement
         sal_uInt16 nOldValue = rOldSet.Get( ATTR_INDENT ).GetValue();
         sal_uInt16 nNewValue = nOldValue;
         // To keep Increment indent from running outside the cell1659
-        tools::Long nColWidth = 
static_cast<tools::Long>(rDocument.GetColWidth(nCol,nTab));
+        tools::Long nColWidth = static_cast<tools::Long>(
+            rDocument.GetColWidth(nCol == -1 ? rDocument.MaxCol() : 
nCol,nTab));
         if ( bIncrement )
         {
             if ( nNewValue < nColWidth-SC_INDENT_STEP )
             {
                 nNewValue += SC_INDENT_STEP;
-                if ( nNewValue > nColWidth-SC_INDENT_STEP ) nNewValue = 
nColWidth-SC_INDENT_STEP;
+                if ( nNewValue > nColWidth-SC_INDENT_STEP )
+                    nNewValue = nColWidth-SC_INDENT_STEP;
             }
         }
         else
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 5b6cb6d0d824..26541603584a 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -102,12 +102,12 @@ void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, 
ScDocument& rDoc, bool bEmptyA
     nCol = nNewCol;
     nTab = nNewTab;
     if ( bEmptyAttrArray )
-        pAttrArray.reset(new ScAttrArray( nCol, nTab, rDoc, nullptr ));
+        InitAttrArray(new ScAttrArray( nCol, nTab, rDoc, nullptr ));
     else
-        pAttrArray.reset(new ScAttrArray( nCol, nTab, rDoc, 
&rDoc.maTabs[nTab]->aDefaultColAttrArray ));
+        InitAttrArray(new ScAttrArray( nCol, nTab, rDoc, 
&rDoc.maTabs[nTab]->aDefaultColData.AttrArray()));
 }
 
-SCROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
+SCROW ScColumnData::GetNextUnprotected( SCROW nRow, bool bUp ) const
 {
     return pAttrArray->GetNextUnprotected(nRow, bUp);
 }
@@ -301,7 +301,7 @@ bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& 
rMark) const
     return bOpen;
 }
 
-bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const
+bool ScColumnData::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) 
const
 {
     return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
 }
@@ -350,7 +350,7 @@ void ScColumn::MergeSelectionPattern( ScMergePatternState& 
rState, const ScMarkD
     }
 }
 
-void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, 
SCROW nRow2, bool bDeep ) const
+void ScColumnData::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, 
SCROW nRow2, bool bDeep ) const
 {
     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
 }
@@ -368,7 +368,7 @@ void ScColumn::ApplyBlockFrame(const SvxBoxItem& 
rLineOuter, const SvxBoxInfoIte
     pAttrArray->ApplyBlockFrame(rLineOuter, pLineInner, nStartRow, nEndRow, 
bLeft, nDistRight);
 }
 
-const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
+const ScPatternAttr* ScColumnData::GetPattern( SCROW nRow ) const
 {
     return pAttrArray->GetPattern( nRow );
 }
@@ -378,7 +378,7 @@ const SfxPoolItem& ScColumn::GetAttr( SCROW nRow, 
sal_uInt16 nWhich ) const
     return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
 }
 
-const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW 
nEndRow ) const
+const ScPatternAttr* ScColumnData::GetMostUsedPattern( SCROW nStartRow, SCROW 
nEndRow ) const
 {
     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     const ScPatternAttr* pMaxPattern = nullptr;
@@ -402,34 +402,35 @@ const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW 
nStartRow, SCROW nEndRo
     return pMaxPattern;
 }
 
-sal_uInt32 ScColumn::GetNumberFormat( const ScDocument& rDocument, const 
ScAttrArray* pAttrArray,
-    SCROW nStartRow, SCROW nEndRow )
+sal_uInt32 ScColumnData::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) 
const
 {
     SCROW nPatStartRow, nPatEndRow;
     const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, 
nPatEndRow, nStartRow);
-    sal_uInt32 nFormat = pPattern->GetNumberFormat(rDocument.GetFormatTable());
+    sal_uInt32 nFormat = pPattern->GetNumberFormat(GetDoc().GetFormatTable());
     while (nEndRow > nPatEndRow)
     {
         nStartRow = nPatEndRow + 1;
         pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, 
nStartRow);
-        sal_uInt32 nTmpFormat = 
pPattern->GetNumberFormat(rDocument.GetFormatTable());
+        sal_uInt32 nTmpFormat = 
pPattern->GetNumberFormat(GetDoc().GetFormatTable());
         if (nFormat != nTmpFormat)
             return 0;
     }
     return nFormat;
 }
 
-sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
+sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& 
rContext, SCROW nRow ) const
 {
-    return GetNumberFormat( GetDoc(), pAttrArray.get(), nStartRow, nEndRow );
+    return pAttrArray->GetPattern( nRow )->GetNumberFormat( 
rContext.GetFormatTable() );
 }
 
-sal_uInt32 ScColumn::GetNumberFormat( const ScInterpreterContext& rContext, 
SCROW nRow ) const
+SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray,
+                                     bool* const pIsChanged )
 {
-    return pAttrArray->GetPattern( nRow )->GetNumberFormat( 
rContext.GetFormatTable() );
+    return ScColumnData::ApplySelectionCache( pCache, rMark, pDataArray, 
pIsChanged, nCol );
 }
 
-SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged )
+SCROW ScColumnData::ApplySelectionCache( SfxItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray,
+                                         bool* const pIsChanged, SCCOL nCol )
 {
     SCROW nTop = 0;
     SCROW nBottom = 0;
@@ -453,30 +454,34 @@ SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* 
pCache, const ScMarkData&
         return nBottom;
 }
 
-void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark 
)
+void ScColumnData::ChangeSelectionIndent( bool bIncrement, const ScMarkData& 
rMark, SCCOL nCol )
 {
-    SCROW nTop;
-    SCROW nBottom;
-
+    assert(rMark.IsMultiMarked());
     if ( pAttrArray && rMark.IsMultiMarked() )
     {
         ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
+        SCROW nTop;
+        SCROW nBottom;
         while (aMultiIter.Next( nTop, nBottom ))
             pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
     }
 }
 
-void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& 
rMark )
+void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark 
)
 {
-    SCROW nTop;
-    SCROW nBottom;
+    return ScColumnData::ChangeSelectionIndent( bIncrement, rMark, nCol );
+}
 
+void ScColumnData::ClearSelectionItems( const sal_uInt16* pWhich,const 
ScMarkData& rMark, SCCOL nCol )
+{
     if (!pAttrArray)
         return;
 
     if (rMark.IsMultiMarked() )
     {
         ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
+        SCROW nTop;
+        SCROW nBottom;
         while (aMultiIter.Next( nTop, nBottom ))
             pAttrArray->ClearItems(nTop, nBottom, pWhich);
     }
@@ -490,6 +495,11 @@ void ScColumn::ClearSelectionItems( const sal_uInt16* 
pWhich,const ScMarkData& r
     }
 }
 
+void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& 
rMark )
+{
+    ScColumnData::ClearSelectionItems( pWhich, rMark, nCol );
+}
+
 void ScColumn::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& 
rMark, bool bBroadcast )
 {
     SCROW nTop;
@@ -518,7 +528,7 @@ void ScColumn::ApplyPattern( SCROW nRow, const 
ScPatternAttr& rPatAttr )
       pAttrArray->SetPattern( nRow, pNewPattern );
 }
 
-void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
+void ScColumnData::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
                                  ScEditDataArray* pDataArray, bool* const 
pIsChanged )
 {
     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
@@ -570,7 +580,7 @@ void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet* 
rStyle )
     pAttrArray->SetPattern(nRow, std::move(pNewPattern), true);
 }
 
-void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const 
ScStyleSheet& rStyle )
+void ScColumnData::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const 
ScStyleSheet& rStyle )
 {
     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, rStyle);
 }
@@ -605,7 +615,7 @@ void ScColumn::ApplySelectionLineStyle( const ScMarkData& 
rMark,
     }
 }
 
-const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
+const ScStyleSheet* ScColumnData::GetStyle( SCROW nRow ) const
 {
     return pAttrArray->GetPattern( nRow )->GetStyleSheet();
 }
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index 0e5e6664db93..e76ef808b8b6 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -453,7 +453,7 @@ void ScDocument::FillInfo(
                     pThisAttrArr = pThisCol->pAttrArray.get();
                 }
                 else
-                    pThisAttrArr = &maTabs[nTab]->aDefaultColAttrArray;
+                    pThisAttrArr = &maTabs[nTab]->aDefaultColData.AttrArray();
 
                 if (nCol+1 >= nCol1)                                // 
Attribute/Blockmark from nX1-1
                 {
diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx
index 596937e24346..54379a554705 100644
--- a/sc/source/core/data/markdata.cxx
+++ b/sc/source/core/data/markdata.cxx
@@ -590,6 +590,22 @@ bool ScMarkData::IsAllMarked( const ScRange& rRange ) const
     return bOk;
 }
 
+SCCOL ScMarkData::GetStartOfEqualColumns( SCCOL nLastCol, SCCOL nMinCol ) const
+{
+    if( !bMultiMarked )
+    {
+        if ( bMarked && !bMarkIsNeg )
+        {
+            if( aMarkRange.aEnd.Col() >= nMinCol && aMarkRange.aStart.Col() < 
nLastCol )
+                return aMarkRange.aEnd.Col() + 1;
+            if( aMarkRange.aEnd.Col() >= nLastCol && aMarkRange.aStart.Col() 
<= nMinCol )
+                return aMarkRange.aStart.Col();
+        }
+        return nMinCol;
+    }
+    return aMultiSel.GetStartOfEqualColumns( nLastCol, nMinCol );
+}
+
 SCROW ScMarkData::GetNextMarked( SCCOL nCol, SCROW nRow, bool bUp ) const
 {
     if ( !bMultiMarked )
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index ba7c18ad3722..7329b4f455b9 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -276,9 +276,9 @@ ScTable::ScTable( ScDocument& rDoc, SCTAB nNewTab, const 
OUString& rNewName,
     bActiveScenario(false),
     mbPageBreaksValid(false),
     mbForceBreaks(false),
-    bStreamValid(false),
-    aDefaultColAttrArray(static_cast<SCCOL>(-1), nNewTab, rDoc, nullptr)
+    bStreamValid(false)
 {
+    aDefaultColData.InitAttrArray(new ScAttrArray(static_cast<SCCOL>(-1), 
nNewTab, rDoc, nullptr));
     if (bColInfo)
     {
         mpColWidth.reset( new ScCompressedArray<SCCOL, sal_uInt16>( 
rDocument.MaxCol()+1, STD_COL_WIDTH ) );
@@ -1613,7 +1613,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCCOL 
nMovX, SCROW nMovY,
                     nNextRow = rMark.GetNextMarked( nCol, nNextRow, bUp );
                 if ( bUnprotected )
                     nNextRow = ( nCol <= nLastCol ) ? 
aCol[nCol].GetNextUnprotected( nNextRow, bUp ) :
-                        aDefaultColAttrArray.GetNextUnprotected( nNextRow, bUp 
);
+                        aDefaultColData.GetNextUnprotected( nNextRow, bUp );
                 pNextRows[nCol - nStartCol] = nNextRow;
 
                 if (bUp)
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index a9862090a5cc..c16bfddecc9d 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -559,7 +559,7 @@ void ScTable::CopyStaticToDocument(
         rDestCol.maCells.set_empty(nRow1, nRow2);
         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
         {
-            sal_uInt32 nNumFmt = 
aDefaultColAttrArray.GetPattern(nRow)->GetNumberFormat(
+            sal_uInt32 nNumFmt = 
aDefaultColData.GetPattern(nRow)->GetNumberFormat(
                 rDocument.GetNonThreadedContext().GetFormatTable());
             SvNumberFormatterMergeMap::const_iterator itNum = 
rMap.find(nNumFmt);
             if (itNum != rMap.end())
@@ -2173,8 +2173,7 @@ sal_uInt32 ScTable::GetNumberFormat( const 
ScInterpreterContext& rContext, const
     {
         if (rPos.Col() < GetAllocatedColumnsCount())
             return aCol[rPos.Col()].GetNumberFormat(rContext, rPos.Row());
-        return aDefaultColAttrArray.GetPattern(rPos.Row())
-            ->GetNumberFormat(rContext.GetFormatTable());
+        return aDefaultColData.GetNumberFormat(rContext, rPos.Row());
     }
     return 0;
 }
@@ -2191,7 +2190,7 @@ sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW 
nStartRow, SCROW nEndRow
 
     if (nCol < GetAllocatedColumnsCount())
         return aCol[nCol].GetNumberFormat(nStartRow, nEndRow);
-    return ScColumn::GetNumberFormat( GetDoc(), &aDefaultColAttrArray, 
nStartRow, nEndRow);
+    return aDefaultColData.GetNumberFormat(nStartRow, nEndRow);
 }
 
 void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, sal_uInt32 
nNumberFormat )
@@ -2205,9 +2204,9 @@ void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, 
sal_uInt32 nNumberFormat
 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
 {
     if (ValidColRow(nCol,nRow) && nCol < GetAllocatedColumnsCount())
-        return CreateColumnIfNotExists(nCol).GetPattern( nRow );
+        return aCol[nCol].GetPattern( nRow );
     else
-        return aDefaultColAttrArray.GetPattern( nRow );
+        return aDefaultColData.GetPattern( nRow );
 }
 
 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, 
SCROW nEndRow ) const
@@ -2216,7 +2215,7 @@ const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL 
nCol, SCROW nStartRow, S
         && nCol < GetAllocatedColumnsCount())
         return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow );
     else
-        return nullptr;
+        return aDefaultColData.GetMostUsedPattern( nStartRow, nEndRow );
 }
 
 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 
HasAttrFlags nMask ) const
@@ -2225,7 +2224,7 @@ bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL 
nCol2, SCROW nRow2, Has
         if( aCol[nCol].HasAttrib( nRow1, nRow2, nMask ))
             return true;
     if( nCol2 >= aCol.size())
-         return aDefaultColAttrArray.HasAttrib( nRow1, nRow2, nMask );
+         return aDefaultColData.HasAttrib( nRow1, nRow2, nMask );
     return false;
 }
 
@@ -2756,9 +2755,11 @@ void ScTable::MergeSelectionPattern( 
ScMergePatternState& rState, const ScMarkDa
 void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, 
SCROW nRow1,
                                                     SCCOL nCol2, SCROW nRow2, 
bool bDeep ) const
 {
-    nCol2 = ClampToAllocatedColumns(nCol2);
-    for (SCCOL i=nCol1; i<=nCol2; i++)
+    const SCCOL nEndCol = ClampToAllocatedColumns(nCol2);
+    for (SCCOL i=nCol1; i<=nEndCol; i++)
         aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
+    if (nEndCol != nCol2)
+        aDefaultColData.MergePatternArea( rState, nRow1, nRow2, bDeep );
 }
 
 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* 
pLineInner, ScLineFlags& rFlags,
@@ -2810,9 +2811,7 @@ void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW 
nStartRow, SCCOL nEndCol,
         maxCol = std::max( nStartCol, aCol.size()) - 1;
         if( maxCol >= 0 )
             CreateColumnIfNotExists(maxCol); // Allocate needed different 
columns before changing the default.
-        const SfxItemSet* pSet = &rAttr.GetItemSet();
-        SfxItemPoolCache aCache( GetDoc().GetPool(), pSet );
-        aDefaultColAttrArray.ApplyCacheArea(nStartRow, nEndRow, &aCache, 
pDataArray, pIsChanged );
+        aDefaultColData.ApplyPatternArea(nStartRow, nEndRow, rAttr, 
pDataArray, pIsChanged);
     }
     for (SCCOL i = nStartCol; i <= maxCol; i++)
         CreateColumnIfNotExists(i).ApplyPatternArea(nStartRow, nEndRow, rAttr, 
pDataArray, pIsChanged);
@@ -2901,12 +2900,12 @@ void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW 
nStartRow, SCCOL nEndCol, S
             nEndCol = aCol.size() - 1;
             for (SCCOL i = nStartCol; i <= nEndCol; i++)
                 aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
-            aDefaultColAttrArray.ApplyStyleArea(nStartRow, nEndRow, rStyle );
+            aDefaultColData.ApplyStyleArea(nStartRow, nEndRow, rStyle );
         }
         else
         {
             CreateColumnIfNotExists( nStartCol - 1 );
-            aDefaultColAttrArray.ApplyStyleArea(nStartRow, nEndRow, rStyle );
+            aDefaultColData.ApplyStyleArea(nStartRow, nEndRow, rStyle );
         }
     }
     else
@@ -2940,7 +2939,7 @@ const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW 
nRow ) const
     if ( nCol < aCol.size() )
         return aCol[nCol].GetStyle( nRow );
     else
-        return aDefaultColAttrArray.GetPattern( nRow )->GetStyleSheet();
+        return aDefaultColData.GetStyle( nRow );
 }
 
 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& 
rFound ) const
@@ -3088,36 +3087,68 @@ void ScTable::ApplySelectionCache( SfxItemPoolCache* 
pCache, const ScMarkData& r
 {
     if(!rMark.GetTableSelect(nTab))
         return;
-    assert( rMark.IsMultiMarked() );
-    SCCOL maxCol;
-    if( rMark.GetMultiMarkArea().aEnd.Col() == GetDoc().MaxCol())
+    SCCOL lastChangeCol;
+    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
     {
         // For the same unallocated columns until the end we can change just 
the default.
-        maxCol = rMark.GetMultiSelData().GetStartOfEqualColumns( 
GetDoc().MaxCol(), aCol.size()) - 1;
-        if( maxCol >= 0 )
-            CreateColumnIfNotExists(maxCol); // Allocate needed different 
columns before changing the default.
-        ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), GetDoc().MaxCol() 
);
-        SCROW nTop = 0;
-        SCROW nBottom = 0;
-        while (aMultiIter.Next( nTop, nBottom ))
-            aDefaultColAttrArray.ApplyCacheArea( nTop, nBottom, pCache, 
pDataArray, pIsChanged );
+        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
+        if( lastChangeCol >= 0 )
+            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
+        aDefaultColData.ApplySelectionCache( pCache, rMark, pDataArray, 
pIsChanged, GetDoc().MaxCol());
     }
     else // need to allocate all columns affected
-        maxCol = rMark.GetMultiMarkArea().aEnd.Col();
+    {
+        lastChangeCol = rMark.GetArea().aEnd.Col();
+        CreateColumnIfNotExists(lastChangeCol);
+    }
 
-    for (SCCOL i=0; i <= maxCol; i++)
-        CreateColumnIfNotExists(i).ApplySelectionCache( pCache, rMark, 
pDataArray, pIsChanged );
+    for (SCCOL i=0; i <= lastChangeCol; i++)
+        aCol[i].ApplySelectionCache( pCache, rMark, pDataArray, pIsChanged );
 }
 
 void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
 {
-    for (SCCOL i=0; i < aCol.size(); i++)
+    if(!rMark.GetTableSelect(nTab))
+        return;
+    SCCOL lastChangeCol;
+    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
+    {
+        // For the same unallocated columns until the end we can change just 
the default.
+        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
+        if( lastChangeCol >= 0 )
+            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
+        aDefaultColData.ChangeSelectionIndent( bIncrement, rMark, 
GetDoc().MaxCol());
+    }
+    else
+    {
+        lastChangeCol = rMark.GetArea().aEnd.Col();
+        CreateColumnIfNotExists(lastChangeCol);
+    }
+
+    for (SCCOL i=0; i <= lastChangeCol; i++)
         aCol[i].ChangeSelectionIndent( bIncrement, rMark );
 }
 
 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& 
rMark )
 {
-    for (SCCOL i=0; i < aCol.size(); i++)
+    if(!rMark.GetTableSelect(nTab))
+        return;
+    SCCOL lastChangeCol;
+    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
+    {
+        // For the same unallocated columns until the end we can change just 
the default.
+        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
+        if( lastChangeCol >= 0 )
+            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
+        aDefaultColData.ClearSelectionItems( pWhich, rMark, GetDoc().MaxCol());
+    }
+    else
+    {
+        lastChangeCol = rMark.GetArea().aEnd.Col();
+        CreateColumnIfNotExists(lastChangeCol);
+    }
+
+    for (SCCOL i=0; i <= lastChangeCol; i++)
         aCol[i].ClearSelectionItems( pWhich, rMark );
 }
 

Reply via email to