include/svl/itempool.hxx                      |    2 
 include/svl/poolitem.hxx                      |    3 
 sc/inc/attarray.hxx                           |   54 +--
 sc/inc/column.hxx                             |   26 -
 sc/inc/docpool.hxx                            |    6 
 sc/inc/document.hxx                           |   16 
 sc/inc/global.hxx                             |    2 
 sc/inc/patattr.hxx                            |  132 +++++---
 sc/inc/poolcach.hxx                           |   28 -
 sc/inc/scitems.hxx                            |   80 ++--
 sc/inc/table.hxx                              |    4 
 sc/qa/unit/subsequent_export_test.cxx         |    2 
 sc/qa/unit/subsequent_export_test4.cxx        |    4 
 sc/qa/unit/subsequent_filters_test2.cxx       |    4 
 sc/qa/unit/ucalc.cxx                          |   28 -
 sc/qa/unit/ucalc_DocumentThemes.cxx           |    2 
 sc/qa/unit/ucalc_copypaste.cxx                |   10 
 sc/qa/unit/ucalc_formula.cxx                  |    3 
 sc/source/core/data/attarray.cxx              |  422 +++++++++++---------------
 sc/source/core/data/column.cxx                |   71 ++--
 sc/source/core/data/column2.cxx               |   21 -
 sc/source/core/data/column3.cxx               |    6 
 sc/source/core/data/column4.cxx               |   18 -
 sc/source/core/data/dociter.cxx               |    8 
 sc/source/core/data/docpool.cxx               |   69 ----
 sc/source/core/data/documen2.cxx              |   18 +
 sc/source/core/data/documen4.cxx              |    3 
 sc/source/core/data/document.cxx              |   57 ---
 sc/source/core/data/document10.cxx            |    4 
 sc/source/core/data/drwlayer.cxx              |    2 
 sc/source/core/data/fillinfo.cxx              |    4 
 sc/source/core/data/global.cxx                |   18 -
 sc/source/core/data/patattr.cxx               |  340 +++++++++++++++++---
 sc/source/core/data/poolcach.cxx              |   85 +----
 sc/source/core/data/stlpool.cxx               |    3 
 sc/source/core/data/table2.cxx                |   39 +-
 sc/source/core/data/table3.cxx                |   48 +-
 sc/source/core/data/table4.cxx                |    6 
 sc/source/core/data/validat.cxx               |    2 
 sc/source/core/tool/ddelink.cxx               |    4 
 sc/source/core/tool/editutil.cxx              |    3 
 sc/source/core/tool/interpr1.cxx              |    2 
 sc/source/filter/dif/difimp.cxx               |    2 
 sc/source/filter/excel/xehelper.cxx           |    8 
 sc/source/filter/excel/xestyle.cxx            |    5 
 sc/source/filter/excel/xicontent.cxx          |    2 
 sc/source/filter/excel/xistyle.cxx            |   10 
 sc/source/filter/inc/xistyle.hxx              |    2 
 sc/source/filter/lotus/lotattr.cxx            |    4 
 sc/source/filter/lotus/op.cxx                 |    2 
 sc/source/filter/oox/sheetdatabuffer.cxx      |    7 
 sc/source/filter/oox/stylesbuffer.cxx         |   14 
 sc/source/filter/orcus/interface.cxx          |    8 
 sc/source/filter/qpro/qprostyle.cxx           |    2 
 sc/source/filter/rtf/eeimpars.cxx             |    7 
 sc/source/filter/xml/xmlcelli.cxx             |    2 
 sc/source/filter/xml/xmlimprt.cxx             |    4 
 sc/source/ui/Accessibility/AccessibleText.cxx |   24 +
 sc/source/ui/app/inputhdl.cxx                 |    4 
 sc/source/ui/app/scmod.cxx                    |    3 
 sc/source/ui/cctrl/dpcontrol.cxx              |    2 
 sc/source/ui/docshell/arealink.cxx            |    2 
 sc/source/ui/docshell/dbdocimp.cxx            |    2 
 sc/source/ui/docshell/docfunc.cxx             |    6 
 sc/source/ui/docshell/docsh.cxx               |    2 
 sc/source/ui/docshell/docsh2.cxx              |    2 
 sc/source/ui/docshell/docsh3.cxx              |    6 
 sc/source/ui/docshell/docsh5.cxx              |    4 
 sc/source/ui/docshell/docsh6.cxx              |    4 
 sc/source/ui/docshell/docsh8.cxx              |    2 
 sc/source/ui/docshell/impex.cxx               |    2 
 sc/source/ui/inc/undoblk.hxx                  |    7 
 sc/source/ui/inc/undocell.hxx                 |    8 
 sc/source/ui/pagedlg/scuitphfedit.cxx         |   10 
 sc/source/ui/undo/undoblk.cxx                 |    4 
 sc/source/ui/undo/undoblk3.cxx                |   34 --
 sc/source/ui/undo/undocell.cxx                |   27 -
 sc/source/ui/undo/undostyl.cxx                |    2 
 sc/source/ui/unoobj/cellsuno.cxx              |   14 
 sc/source/ui/unoobj/docuno.cxx                |    3 
 sc/source/ui/unoobj/funcuno.cxx               |    2 
 sc/source/ui/unoobj/styleuno.cxx              |    4 
 sc/source/ui/unoobj/textuno.cxx               |   29 +
 sc/source/ui/vba/vbarange.cxx                 |    3 
 sc/source/ui/view/dbfunc3.cxx                 |    2 
 sc/source/ui/view/formatsh.cxx                |    8 
 sc/source/ui/view/gridwin4.cxx                |    5 
 sc/source/ui/view/output2.cxx                 |    8 
 sc/source/ui/view/preview.cxx                 |    3 
 sc/source/ui/view/printfun.cxx                |    7 
 sc/source/ui/view/spelleng.cxx                |   14 
 sc/source/ui/view/tabvwsha.cxx                |    8 
 sc/source/ui/view/viewfun2.cxx                |    4 
 sc/source/ui/view/viewfunc.cxx                |   19 -
 svl/source/items/itempool.cxx                 |   22 -
 svl/source/items/itemset.cxx                  |   41 --
 svl/source/items/poolitem.cxx                 |    1 
 97 files changed, 1085 insertions(+), 1007 deletions(-)

New commits:
commit 2e1f9da8a6359c8909e087a92239aefd4851b116
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Sat Dec 23 15:52:06 2023 +0100
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Thu Dec 28 19:38:15 2023 +0100

    Decouple ScPatternAttr from SfxItemPool
    
    ScPatternAttr is traditionally derived from SfxPoolItem
    (or better: SfxSetItem) and held in the ScDocumentPool
    as Item.
    
    This is only because of 'using' the 'poolable'
    functionality of the Item/ItemSet/ItemPool mechanism.
    Lots of hacks were added to sc and Item/ItemSet/
    ItemPool to make that 'work' which shows already that
    this relationship is not optimal.
    
    It uses DirectPutItemInPool/DirectRemoveItemFromPool
    to do so, also with massive overhead to do that (and
    with not much success). The RefCnt in the SfxPoolItem
    that is used for this never worked reliably, so the
    SfxItemPool was (ab)used as garbage collector (all
    Items added and never removed get deleted at last
    for good when the Pool goes down). For this reasons
    and to be able to further get ItemSets modernized
    I changed this. I did two big changes here:
    
    (1) No longer derive ScPatternAttr from SfxItemSet/
        SfxSetItem, no longer hold as SfxPoolItem
    
    (2) Add tooling to reliably control the lifetime of
        ScPatternAttr instances and ther uniqueness/
        reusage for memory reasons
    
    It is now a regular non-derived class. The SfxItemSet
    formally derived from SfxSetItem is now a member. The
    RefCnt is now also a member (so independent from
    size/data type of SfxPoolItem). All in all it's pretty
    much the same size as before.
    
    To support handling it I created a CellAttributeHelper
    that is at/owned by ScDocument and takes over tooling
    to handle the ScPatternAttr. It supports to guarantee
    the uniqueness of incarnated ScPatternAttr instances for
    a ScDocument by providing helpers like registerAndCheck
    and doUnregister. It hosts the default CellAttribute/
    ScPatternAttr. That default handling was anyways not
    using the standard default-handling of Items/Pools.
    
    I adapted whole SC to use that mainly by replacing calls
    to DirectPutItemInPool with registerAndCheck and
    DirectRemoveItemFromPool with doUnregister, BUT: This
    was not sufficient, the RefCnt kept to be broken.
    
    For that reason I decided to also do (2) in this change:
    I added a CellAttributeHolder that owns/regulates the
    lifetime of a single ScPatternAttr. Originally it also
    contained the CellAttributeHolder, but after some
    thoughts I decided that this is not needed - if there
    is no ScPatternAttr set, no CellAttributeHolder is
    needed for safe cleanup at destruction of the helper.
    
    So I moved/added the CellAttributeHolder to ScPatternAttr
    where it belongs more naturally anyways. The big plus is
    that CellAttributeHolder is just one ptr, so not bigger
    than having a simple ScPatternAttr*. That way, e.g.
    ScAttrEntry in ScAttrArray did not 'grow' at all. In
    principle all places where a ScPatternAttr* is used can
    now be replaced by using a CellAttributeHolder, except
    for construction. It is capable to be initialized with
    either ScPatternAttr instances from the heap (it creates
    a copy that then gets RefCounted) or allocated (it
    supports ownership change at construction time).
    
    Note that ScAttrEntry started to get more a C++ class
    in that change, it has a constructor. I did not change
    the SCROW member, but that should also be done.
    
    Also made registerAndCheck/doUnregister private in
    CellAttributeHelper and exclusively used by
    CellAttributeHolder. That way the RefCnt works, and a
    lot of code gets much simpler (check ScItemPoolCache,
    it's now straightforward) and safer and ~ScPatternAttr()
    uses now a hard
        assert(!isRegistered());
    which shows that RefCnt works now (the 1st time?).
    
    There can be done more (see ToDo section below) but I
    myself will concentrate on getting ItemSets forward.
    
    This decoupling makes both involved mechanisms more safe,
    less complex and more stable. It also opens up
    possibilities to further optimize ScPatternAttr in SC
    without further hacking Item/ItemSet/ItemPool stuff.
    
    NOTE: ScPatternAttr *should* be renamed to 'CellAttribute'
    which describes what it is. The experiencd devs may know
    what it does, but it is a hindrance for understanding for
    attacting new devs. I already used now names like
    CellAttributeHelper/CellAttributeHolder etc., but
    abstained from renaming ScPatternAttr, see ToDo list below.
    
    SfxItemSet discussion:
    
    ScPatternAttr still contains a SfxItemSet, or better, a
    SfxSetItem. For that reason it still depends on access to
    an SfxItemPool (so there is acces in CellAttributeHelper).
    
    This is in principle not needed - no Item (in the range
    [ATTR_PATTERN_START .. ATTR_PATTERN_END]) needs that.
    In principle ScPatternAttr could now do it's own handling
    of those needed Items, however this might be done (linear
    array, hash-by-WhichID, ...). The Items get translated
    to and from this to the rest of the office anyways.
    
    Note that *merging* of SfxItemSets is *still* needed what
    means to have WhichID slots in SfxItemState::DONTCARE,
    see note in ScPatternAttr::ScPatternAttr about that. And
    there is also the Surrogates stuff which would have to be
    checked.
    
    The other extreme is to use SfxItemSet *more*, e.g. directly
    derive from SfxItemSet what would make stuff easier, maybe
    even get back to using the 'regular' Items like all office,
    I doubt that that would be much slower, so why...?
    
    Also possible is to remove that range of Items exclusively
    used by ScPatternAttr from ScDocumentPool *completely* and
    create an own Pool for them, owned by CellAttributeHelper.
    That Pool might even be static global, so all SC Docs could
    share all those Items - maybe even the ScPatternAttr
    themselves (except the default per document). That would
    remove the dependency of ScPatternAttr from a Pool
    completely.
    
    ToDo-List:
    - rename ScPatternAttr to CellAttribute or similar
    - use SfxItemSetFixed with range [ATTR_PATTERN_START
      .. ATTR_PATTERN_END] instead of regular SfxItemSet
      (if the copy-construtor works now...?)
    - maybe create own/separate Pool for exclusive Items
    - make ScAttrEntry more a C++ class by moving SCROW
      to the private section, add get/set methods and
      adapt SC
    
    Had to add some more usages of CellAttributeHolder
    to the SC Sort mechanism, there were situations where
    the sorted ScPatternAttr were replaced in the Table,
    but the 'sorted' ones were just ScPatternAttr*, thus
    deleting the valid ones in the Table already. Using
    CellAttributeHolder makes this safe, too.
    
    Added a small, one-entry cache to CellAttributeHelper
    to buffer the last found buffered ScPattrnAttr. It
    has a HitRate of ca. 5-6% and brings the UnitTest
    testSheetCellRangeProperties from 0m48,710s to
    0m37,556s. Not too massive, but erery bit counts :-)
    Also shows that after that change optimizations in
    the now split functionality is possible and easy.
    
    Change-Id: I268a7b2a943ce5ddfe3c75b5e648c0f6b0cedb85
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161244
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/include/svl/itempool.hxx b/include/svl/itempool.hxx
index f5949f1700c8..2e6c5a9a38d3 100644
--- a/include/svl/itempool.hxx
+++ b/include/svl/itempool.hxx
@@ -247,8 +247,6 @@ public:
 
 protected:
     const SfxPoolItem&      DirectPutItemInPoolImpl( const SfxPoolItem&, 
sal_uInt16 nWhich = 0, bool bPassingOwnership = false );
-    virtual void newItem_Callback(const SfxPoolItem& rItem) const;
-    virtual bool newItem_UseDirect(const SfxPoolItem& rItem) const;
 
 private:
     const SfxItemPool&              operator=(const SfxItemPool &) = delete;
diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx
index af993096e655..ce65d63709cf 100644
--- a/include/svl/poolitem.hxx
+++ b/include/svl/poolitem.hxx
@@ -134,7 +134,6 @@ class SVL_DLLPUBLIC SfxPoolItem
     bool        m_bStaticDefault : 1;       // bit 1
     bool        m_bPoolDefault : 1;         // bit 2
     bool        m_bRegisteredAtPool : 1;    // bit 3
-    bool        m_bExceptionalSCItem : 1;   // bit 4
     bool        m_bIsSetItem : 1;           // bit 5
 
 protected:
@@ -155,7 +154,6 @@ protected:
     void setStaticDefault() { m_bStaticDefault = true; }
     void setPoolDefault() { m_bPoolDefault = true; }
     void setRegisteredAtPool(bool bNew) { m_bRegisteredAtPool = bNew; }
-    void setExceptionalSCItem() { m_bExceptionalSCItem = true; }
     void setIsSetItem() { m_bIsSetItem = true; }
 
 public:
@@ -174,7 +172,6 @@ public:
     bool isStaticDefault() const { return m_bStaticDefault; }
     bool isPoolDefault() const { return m_bPoolDefault; }
     bool isRegisteredAtPool() const { return m_bRegisteredAtPool; }
-    bool isExceptionalSCItem() const { return m_bExceptionalSCItem; }
     bool isSetItem() const { return m_bIsSetItem; }
 
     // version that allows nullptrs
diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx
index a7e1c08a9f49..c1f9195e6445 100644
--- a/sc/inc/attarray.hxx
+++ b/sc/inc/attarray.hxx
@@ -67,24 +67,38 @@ struct ScLineFlags
 struct ScMergePatternState
 {
     std::optional<SfxItemSet> pItemSet;
-    const ScPatternAttr* pOld1;     ///< existing objects, temporary
-    const ScPatternAttr* pOld2;
+    CellAttributeHolder aOld1;     ///< existing objects, temporary
+    CellAttributeHolder aOld2;
 
     bool mbValidPatternId;
     sal_uInt64 mnPatternId;
 
-    ScMergePatternState() : pOld1(nullptr), pOld2(nullptr),
+    ScMergePatternState() : aOld1(), aOld2(),
                         mbValidPatternId(true), mnPatternId(0) {}
 };
 
 // we store an array of these where the pattern applies to all rows up till 
nEndRow
-struct ScAttrEntry
+class ScAttrEntry
 {
+    CellAttributeHolder     aPattern;
+
+public:
+    ScAttrEntry()
+    : aPattern()
+    , nEndRow(0)
+    {}
+
     SCROW                   nEndRow;
-    const ScPatternAttr*    pPattern;
+
+    const CellAttributeHolder& getCellAttributeHolder() const { return 
aPattern; }
+    void setCellAttributeHolder(const CellAttributeHolder& rNew) { aPattern = 
rNew; }
+
+    const ScPatternAttr* getScPatternAttr() const { return 
aPattern.getScPatternAttr(); }
+    void setScPatternAttr(const ScPatternAttr* pNew, bool bPassingOwnership = 
false) { aPattern.setScPatternAttr(pNew, bPassingOwnership); }
+
     bool operator==( const ScAttrEntry& other ) const
     {
-        return nEndRow == other.nEndRow && SfxPoolItem::areSame(pPattern, 
other.pPattern);
+        return nEndRow == other.nEndRow && 
CellAttributeHolder::areSame(&aPattern, &other.aPattern);
     }
 };
 
@@ -125,7 +139,7 @@ public:
 #if DEBUG_SC_TESTATTRARRAY
     void    TestData() const;
 #endif
-    void    Reset( const ScPatternAttr* pPattern);
+    void    Reset(const CellAttributeHolder& rPattern);
     bool    Concat(SCSIZE nPos);
 
     const ScPatternAttr* GetPattern( SCROW nRow ) const;
@@ -144,18 +158,12 @@ public:
     void    ApplyBlockFrame(const SvxBoxItem& rLineOuter, const 
SvxBoxInfoItem* pLineInner,
                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL 
nDistRight);
 
-    void    SetPattern( SCROW nRow, const ScPatternAttr* pPattern, bool 
bPutToPool = false )
-    { SetPatternAreaImpl(nRow, nRow, pPattern, bPutToPool, nullptr, 
/*bPassingOwnership*/false); }
-    const ScPatternAttr* SetPattern( SCROW nRow, 
std::unique_ptr<ScPatternAttr> pPattern, bool bPutToPool = false )
-    { return SetPatternAreaImpl(nRow, nRow, pPattern.release(), bPutToPool, 
nullptr, /*bPassingOwnership*/true); }
-    void    SetPatternArea( SCROW nStartRow, SCROW nEndRow, 
std::unique_ptr<ScPatternAttr> pPattern,
-                            bool bPutToPool = false, ScEditDataArray* 
pDataArray = nullptr)
-    { SetPatternAreaImpl(nStartRow, nEndRow, pPattern.release(), bPutToPool, 
pDataArray, /*bPassingOwnership*/true); }
-    void    SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr* pPattern,
-                            bool bPutToPool = false, ScEditDataArray* 
pDataArray = nullptr)
-    { SetPatternAreaImpl(nStartRow, nEndRow, pPattern, bPutToPool, pDataArray, 
/*bPassingOwnership*/false); }
+    void    SetPattern( SCROW nRow, const CellAttributeHolder& rPattern )
+    { SetPatternAreaImpl(nRow, nRow, rPattern, nullptr); }
+    void    SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
CellAttributeHolder& rPattern, ScEditDataArray* pDataArray = nullptr)
+    { SetPatternAreaImpl(nStartRow, nEndRow, rPattern, pDataArray); }
     void    ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const 
ScStyleSheet& rStyle );
-    void    ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, ScItemPoolCache* 
pCache,
+    void    ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, ScItemPoolCache& 
rCache,
                             ScEditDataArray* pDataArray = nullptr, bool* const 
pIsChanged = nullptr );
     void    SetAttrEntries(std::vector<ScAttrEntry> && vNewData);
     void    ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow,
@@ -196,8 +204,7 @@ public:
     void    FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, 
ScFlatBoolRowSegments& rUsedRows, bool bReset );
     bool    IsStyleSheetUsed( const ScStyleSheet& rStyle ) const;
 
-    void    SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
-                                    const ScPatternAttr* pWantedPattern, bool 
bDefault );
+    void    SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow, const 
CellAttributeHolder& rWantedPattern );
     void    CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, tools::Long nDy, 
ScAttrArray& rAttrArray );
 
     bool    IsEmpty() const;
@@ -227,9 +234,8 @@ public:
     SCSIZE  Count( SCROW nRow1, SCROW nRow2 ) const;
 
 private:
-    const ScPatternAttr* SetPatternAreaImpl( SCROW nStartRow, SCROW nEndRow, 
const ScPatternAttr* pPattern,
-                            bool bPutToPool = false, ScEditDataArray* 
pDataArray = nullptr,
-                            bool bPassingPatternOwnership = false );
+    const ScPatternAttr* SetPatternAreaImpl(
+        SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, 
ScEditDataArray* pDataArray = nullptr);
 };
 
 //                              Iterator for attributes
@@ -287,7 +293,7 @@ inline const ScPatternAttr* ScAttrIterator::Next( SCROW& 
rTop, SCROW& rBottom )
     {
         rTop = nRow;
         rBottom = std::min( pArray->mvData[nPos].nEndRow, nEndRow );
-        pRet = pArray->mvData[nPos].pPattern;
+        pRet = pArray->mvData[nPos].getScPatternAttr();
         nRow = rBottom + 1;
         ++nPos;
     }
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 914199be25b5..87273f0f83ba 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -100,7 +100,8 @@ struct ScInterpreterContext;
 
 struct ScNeededSizeOptions
 {
-    const ScPatternAttr* pPattern;
+    CellAttributeHolder aPattern;
+
     bool                bFormula;
     bool                bSkipMerged;
     bool                bGetFont;
@@ -144,7 +145,7 @@ public:
 
     const ScPatternAttr*    GetPattern( SCROW nRow ) const;
     const ScPatternAttr*    GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow 
) const;
-    SCROW       ApplySelectionCache( ScItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged,
+    SCROW       ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged,
                                      SCCOL nCol );
     void        ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
                                   ScEditDataArray* pDataArray = nullptr,
@@ -541,9 +542,9 @@ public:
 
     void        ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr );
     void        ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr );
-    const ScPatternAttr* SetPattern( SCROW nRow, 
std::unique_ptr<ScPatternAttr> );
-    void        SetPattern( SCROW nRow, const ScPatternAttr& );
-    void        SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& );
+    void        SetPattern( SCROW nRow, const CellAttributeHolder& rHolder );
+    void        SetPattern( SCROW nRow, const ScPatternAttr& rPattern );
+    void        SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
CellAttributeHolder& );
     void        ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
                             const ScPatternAttr& rPattern, SvNumFormatType 
nNewType );
 
@@ -575,7 +576,7 @@ public:
 
     void        RemoveProtected( SCROW nStartRow, SCROW nEndRow );
 
-    SCROW       ApplySelectionCache( ScItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged );
+    SCROW       ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged );
     void DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, 
bool bBroadcast );
 
     void        ClearSelectionItems( const sal_uInt16* pWhich, const 
ScMarkData& rMark );
@@ -1031,20 +1032,19 @@ inline void ScColumn::ClearItems( SCROW nStartRow, 
SCROW nEndRow, const sal_uInt
     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
 }
 
-inline const ScPatternAttr* ScColumn::SetPattern( SCROW nRow, 
std::unique_ptr<ScPatternAttr> pPatAttr )
+inline void ScColumn::SetPattern( SCROW nRow, const CellAttributeHolder& 
rHolder )
 {
-    return pAttrArray->SetPattern( nRow, std::move(pPatAttr), 
true/*bPutToPool*/ );
+    return pAttrArray->SetPattern( nRow, rHolder );
 }
 
-inline void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
+inline void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPattern )
 {
-    pAttrArray->SetPattern( nRow, &rPatAttr, true/*bPutToPool*/ );
+    pAttrArray->SetPattern( nRow, CellAttributeHolder(&rPattern) );
 }
 
-inline void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
-                                const ScPatternAttr& rPatAttr )
+inline void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow, const 
CellAttributeHolder& rHolder )
 {
-    pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, 
true/*bPutToPool*/ );
+    pAttrArray->SetPatternArea( nStartRow, nEndRow, rHolder );
 }
 
 inline void ScColumnData::SetAttrEntries(std::vector<ScAttrEntry> && vNewData)
diff --git a/sc/inc/docpool.hxx b/sc/inc/docpool.hxx
index c73d034f2fb2..614e3d4229b8 100644
--- a/sc/inc/docpool.hxx
+++ b/sc/inc/docpool.hxx
@@ -29,7 +29,6 @@ class ScDocument;
 class SC_DLLPUBLIC ScDocumentPool final : public SfxItemPool
 {
     std::vector<SfxPoolItem*> mvPoolDefaults;
-    sal_uInt64 mnCurrentMaxKey;
 
 public:
             ScDocumentPool();
@@ -40,15 +39,10 @@ public:
     virtual rtl::Reference<SfxItemPool> Clone() const override;
     virtual MapUnit             GetMetric( sal_uInt16 nWhich ) const override;
 
-    void StyleDeleted( const ScStyleSheet* pStyle );      // delete 
templates(?) in organizer
-    void CellStyleCreated( std::u16string_view rName, const ScDocument& rDoc );
     virtual bool GetPresentation( const SfxPoolItem&  rItem,
                                   MapUnit          ePresentationMetric,
                                   OUString&           rText,
                                   const IntlWrapper& rIntl ) const override;
-private:
-    virtual void newItem_Callback(const SfxPoolItem& rItem) const override;
-    virtual bool newItem_UseDirect(const SfxPoolItem& rItem) const override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 11b65e9262c0..d94b0ef4fb53 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -355,6 +355,14 @@ public:
         ETERNAL     /// no new listeners are setup, no broadcast/notify
     };
 
+private:
+    // needs to be shared to allow the bIsClip/bIsUndo mechanism to
+    // do the right thing (SCDOCMODE_CLIP, SCDOCMODE_UNDO)
+    mutable std::shared_ptr<CellAttributeHelper> mpCellAttributeHelper;
+
+public:
+    SC_DLLPUBLIC CellAttributeHelper& getCellAttributeHelper() const;
+
 private:
     rtl::Reference<ScPoolHelper> mxPoolHelper;
 
@@ -1939,8 +1947,8 @@ public:
                                          SCTAB nTab, ScMF nFlags );
 
     SC_DLLPUBLIC void    SetPattern( const ScAddress&, const ScPatternAttr& 
rAttr );
-    SC_DLLPUBLIC const ScPatternAttr* SetPattern( SCCOL nCol, SCROW nRow, 
SCTAB nTab, std::unique_ptr<ScPatternAttr> pAttr );
-    SC_DLLPUBLIC const ScPatternAttr* SetPattern( const ScAddress& rPos, 
std::unique_ptr<ScPatternAttr> pAttr );
+    SC_DLLPUBLIC void    SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const 
CellAttributeHolder& rHolder );
+    SC_DLLPUBLIC void    SetPattern( const ScAddress& rPos, const 
CellAttributeHolder& rHolder );
     SC_DLLPUBLIC void    SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const 
ScPatternAttr& rAttr );
 
     void                 AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL 
nEndCol, SCROW nEndRow,
@@ -2090,7 +2098,6 @@ public:
     void            StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& 
rY2, SCTAB nTab );
     void            ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& 
rY2, SCTAB nTab );
 
-    SC_DLLPUBLIC ScPatternAttr*     GetDefPattern() const;
     SC_DLLPUBLIC ScDocumentPool*    GetPool();
     SC_DLLPUBLIC ScStyleSheetPool*  GetStyleSheetPool() const;
     void GetUnprotectedCells( ScRangeList& rRange, SCTAB nTab ) const;
@@ -2142,9 +2149,6 @@ public:
                                             SCCOL nEndCol, SCROW nEndRow, 
SCTAB nTab, bool bHiddenAsZero = true ) const;
     SC_DLLPUBLIC ScRange         GetRange( SCTAB nTab, const tools::Rectangle& 
rMMRect, bool bHiddenAsZero = true ) const;
 
-    void                         UpdStlShtPtrsFrmNms();
-    void                         StylesToNames();
-
     SC_DLLPUBLIC void            CopyStdStylesFrom( const ScDocument& rSrcDoc 
);
 
     static sal_uInt16            GetSrcVersion() { return nSrcVer; }
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index fe7b8bb407b2..1539858434bc 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -603,7 +603,7 @@ public:
     static void             InitAddIns();
     SC_DLLPUBLIC static void Clear();                    // at the end of the 
program
 
-    static void             InitTextHeight(const SfxItemPool* pPool);
+    static void             InitTextHeight(SfxItemPool& rPool);
     static SvxBrushItem*    GetEmptyBrushItem() { return 
xEmptyBrushItem.get(); }
     static SvxBrushItem*    GetButtonBrushItem();
 
diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx
index d6536551f965..361ed40cd25b 100644
--- a/sc/inc/patattr.hxx
+++ b/sc/inc/patattr.hxx
@@ -21,13 +21,14 @@
 
 #include <optional>
 
-#include <svl/setitem.hxx>
 #include <svl/itemset.hxx>
 #include <svl/languageoptions.hxx>
 #include <tools/degree.hxx>
 #include <editeng/svxenum.hxx>
 #include "scdllapi.h"
 #include "fonthelper.hxx"
+#include "scitems.hxx"
+#include <unordered_set>
 
 namespace vcl { class Font; }
 namespace model { class ComplexColor; }
@@ -50,43 +51,106 @@ enum class ScAutoFontColorMode
     IgnoreAll    ///< like DISPLAY, but ignore stored font and background 
colors
 };
 
-class SC_DLLPUBLIC ScPatternAttr final : public SfxSetItem
+class ScPatternAttr;
+
+class SC_DLLPUBLIC CellAttributeHelper final
 {
-    std::optional<OUString>  pName;
-    mutable std::optional<bool> mxVisible;
-    ScStyleSheet*              pStyle;
-    sal_uInt64                 mnPAKey;
+    friend class CellAttributeHolder;
+
+    SfxItemPool&                                        mrSfxItemPool;
+    mutable ScPatternAttr*                              mpDefaultCellAttribute;
+    mutable std::unordered_set<const ScPatternAttr*>    
maRegisteredCellAttributes;
+    mutable const ScPatternAttr*                        mpLastHit;
+    mutable sal_uInt64                                  mnCurrentMaxKey;
+
+    // only to be used from CellAttributeHolder, so private
+    const ScPatternAttr* registerAndCheck(const ScPatternAttr& rCandidate, 
bool bPassingOwnership) const;
+    void doUnregister(const ScPatternAttr& rCandidate);
+
 public:
-                            ScPatternAttr(SfxItemSet&& pItemSet, const 
OUString& rStyleName);
-                            ScPatternAttr(SfxItemSet&& pItemSet);
-                            ScPatternAttr(SfxItemPool* pItemPool);
-                            ScPatternAttr(const ScPatternAttr& rPatternAttr);
+    explicit CellAttributeHelper(SfxItemPool& rSfxItemPool);
+    ~CellAttributeHelper();
+
+    const ScPatternAttr& getDefaultCellAttribute() const;
+    SfxItemPool& GetPool() const { return mrSfxItemPool; }
 
-    virtual ScPatternAttr*  Clone( SfxItemPool *pPool = nullptr ) const 
override;
+    void CellStyleDeleted(const ScStyleSheet& rStyle);
+    void CellStyleCreated(ScDocument& rDoc, std::u16string_view rName);
+    void UpdateAllStyleSheets(ScDocument& rDoc);
+    void AllStylesToNames();
+};
 
-    virtual bool            operator==(const SfxPoolItem& rCmp) const override;
+class SC_DLLPUBLIC CellAttributeHolder final
+{
+    const ScPatternAttr*    mpScPatternAttr;
 
-    const SfxPoolItem&      GetItem( sal_uInt16 nWhichP ) const
-                                        { return GetItemSet().Get(nWhichP); }
-    template<class T> const T& GetItem( TypedWhichId<T> nWhich ) const
-    { return static_cast<const T&>(GetItem(sal_uInt16(nWhich))); }
+public:
+    CellAttributeHolder(const ScPatternAttr* pScPatternAttr = nullptr, bool 
bPassingOwnership = false);
+    CellAttributeHolder(const CellAttributeHolder& rHolder);
+    ~CellAttributeHolder();
 
-    static const SfxPoolItem& GetItem( sal_uInt16 nWhich, const SfxItemSet& 
rItemSet, const SfxItemSet* pCondSet );
-    template<class T> static const T& GetItem( TypedWhichId<T> nWhich, const 
SfxItemSet& rItemSet, const SfxItemSet* pCondSet )
-    { return static_cast<const T&>(GetItem(sal_uInt16(nWhich), rItemSet, 
pCondSet)); }
+    const CellAttributeHolder& operator=(const CellAttributeHolder& rHolder);
+    bool operator==(const CellAttributeHolder& rHolder) const;
 
-    const SfxPoolItem&      GetItem( sal_uInt16 nWhich, const SfxItemSet* 
pCondSet ) const;
-    template<class T> const T& GetItem( TypedWhichId<T> nWhich, const 
SfxItemSet* pCondSet  ) const
-    { return static_cast<const T&>(GetItem(sal_uInt16(nWhich), pCondSet)); }
+    const ScPatternAttr* getScPatternAttr() const { return mpScPatternAttr; }
+    void setScPatternAttr(const ScPatternAttr* pNew, bool bPassingOwnership = 
false);
 
-                            /// @param pWhich are no ranges, but single IDs, 
0-terminated
-    bool                    HasItemsSet( const sal_uInt16* pWhich ) const;
-    void                    ClearItems( const sal_uInt16* pWhich );
+    bool operator!() const { return nullptr == mpScPatternAttr; }
+    explicit operator bool() const { return nullptr != mpScPatternAttr; }
 
-    void                    DeleteUnchanged( const ScPatternAttr* pOldAttrs );
+    // version that allows nullptrs
+    static bool areSame(const CellAttributeHolder* p1, const 
CellAttributeHolder* p2);
+};
+
+class SC_DLLPUBLIC ScPatternAttr final
+{
+    friend class CellAttributeHelper;
+
+    SfxItemSet                  maLocalSfxItemSet;
+    std::optional<OUString>     pName;
+    mutable std::optional<bool> mxVisible;
+    ScStyleSheet*               pStyle;
+    CellAttributeHelper*        pCellAttributeHelper;
+    sal_uInt64                  mnPAKey;
+    mutable size_t              mnRefCount;
+#ifdef DBG_UTIL
+    sal_uInt32                  m_nSerialNumber;
+    bool                        m_bDeleted;
+#endif
+
+public:
+    ScPatternAttr(CellAttributeHelper& rHelper, const SfxItemSet* pItemSet = 
nullptr, const OUString* pStyleName = nullptr);
+    ScPatternAttr(const ScPatternAttr& rPatternAttr);
+    ~ScPatternAttr();
+
+    virtual bool operator==(const ScPatternAttr& rCmp) const;
+
+    // version that allows nullptrs
+    static bool areSame(const ScPatternAttr* pItem1, const ScPatternAttr* 
pItem2);
+    bool isRegistered() const { return 0 != mnRefCount; }
+    bool isDefault() const { return this == 
&pCellAttributeHelper->getDefaultCellAttribute(); }
+    CellAttributeHelper& getCellAttributeHelper() const { return 
*pCellAttributeHelper; }
+
+    const SfxItemSet& GetItemSet() const { return maLocalSfxItemSet; }
+    SfxItemSet& GetItemSet() { return maLocalSfxItemSet; }
+
+    const SfxPoolItem& GetItem(sal_uInt16 nWhichP) const { return 
maLocalSfxItemSet.Get(nWhichP); }
+    template<class T> const T& GetItem( TypedWhichId<T> nWhich ) const
+        { return static_cast<const T&>(GetItem(sal_uInt16(nWhich))); }
+    static const SfxPoolItem& GetItem(sal_uInt16 nWhich, const SfxItemSet& 
rItemSet, const SfxItemSet* pCondSet);
+    template<class T> static const T& GetItem(TypedWhichId<T> nWhich, const 
SfxItemSet& rItemSet, const SfxItemSet* pCondSet)
+        { return static_cast<const T&>(GetItem(sal_uInt16(nWhich), rItemSet, 
pCondSet)); }
+    const SfxPoolItem& GetItem( sal_uInt16 nWhich, const SfxItemSet* pCondSet 
) const;
+    template<class T> const T& GetItem(TypedWhichId<T> nWhich, const 
SfxItemSet* pCondSet) const
+        { return static_cast<const T&>(GetItem(sal_uInt16(nWhich), pCondSet)); 
}
+
+    /// @param pWhich are no ranges, but single IDs, 0-terminated
+    bool HasItemsSet( const sal_uInt16* pWhich ) const;
+    void ClearItems( const sal_uInt16* pWhich );
+    void DeleteUnchanged( const ScPatternAttr* pOldAttrs );
 
     static SvxCellOrientation GetCellOrientation( const SfxItemSet& rItemSet, 
const SfxItemSet* pCondSet );
-    SvxCellOrientation      GetCellOrientation( const SfxItemSet* pCondSet = 
nullptr ) const;
+    SvxCellOrientation GetCellOrientation( const SfxItemSet* pCondSet = 
nullptr ) const;
 
     /** Static helper function to fill a font object from the passed item set. 
*/
     static void fillFontOnly(vcl::Font& rFont, const SfxItemSet& rItemSet,
@@ -119,7 +183,7 @@ public:
                     const Color* pBackConfigColor = nullptr,
                     const Color* pTextConfigColor = nullptr) const
     {
-        fillColor(rComplexColor, GetItemSet(), eAutoMode, pCondSet, 
pBackConfigColor, pTextConfigColor);
+        fillColor(rComplexColor, maLocalSfxItemSet, eAutoMode, pCondSet, 
pBackConfigColor, pTextConfigColor);
     }
 
     void fillFontOnly(vcl::Font& rFont,
@@ -128,7 +192,7 @@ public:
                     const SfxItemSet* pCondSet = nullptr,
                     SvtScriptType nScript = SvtScriptType::NONE) const
     {
-        fillFontOnly(rFont, GetItemSet(), pOutDev, pScale, pCondSet, nScript);
+        fillFontOnly(rFont, maLocalSfxItemSet, pOutDev, pScale, pCondSet, 
nScript);
     }
 
     /** Fills a font object from the own item set. */
@@ -140,7 +204,7 @@ public:
                     const Color* pBackConfigColor = nullptr,
                     const Color* pTextConfigColor = nullptr) const
     {
-        fillFont(rFont, GetItemSet(), eAutoMode, pOutDev, pScale, pCondSet, 
nScript, pBackConfigColor, pTextConfigColor);
+        fillFont(rFont, maLocalSfxItemSet, eAutoMode, pOutDev, pScale, 
pCondSet, nScript, pBackConfigColor, pTextConfigColor);
     }
 
     /** Converts all Calc items contained in rSrcSet to edit engine items and 
puts them into rEditSet. */
@@ -155,7 +219,7 @@ public:
 
     void                    FillEditParaItems( SfxItemSet* pSet ) const;
 
-    ScPatternAttr*          PutInPool( ScDocument* pDestDoc, ScDocument* 
pSrcDoc ) const;
+    CellAttributeHolder     MigrateToDocument( ScDocument* pDestDoc, 
ScDocument* pSrcDoc ) const;
 
     void                    SetStyleSheet(ScStyleSheet* pNewStyle, bool 
bClearDirectFormat = true);
     const ScStyleSheet*     GetStyleSheet() const  { return pStyle; }
@@ -180,12 +244,6 @@ public:
     void                    SetPAKey(sal_uInt64 nKey);
     sal_uInt64              GetPAKey() const;
 
-    // TODO: tdf#135215: This is a band-aid to detect changes and invalidate 
the hash,
-    // a proper way would be probably to override SfxItemSet::Changed(), but 
6cb400f41df0dd10
-    // hardcoded SfxSetItem to contain SfxItemSet.
-    SfxItemSet& GetItemSet() { mxVisible.reset(); return 
SfxSetItem::GetItemSet(); }
-    using SfxSetItem::GetItemSet;
-
 private:
     bool                    CalcVisible() const;
 };
diff --git a/sc/inc/poolcach.hxx b/sc/inc/poolcach.hxx
index 6e3c3deda916..5b9057b7faf3 100644
--- a/sc/inc/poolcach.hxx
+++ b/sc/inc/poolcach.hxx
@@ -19,35 +19,33 @@
 #pragma once
 
 #include "scdllapi.h"
+#include "patattr.hxx"
 #include <vector>
 
-class SfxItemPool;
+class CellAttributeHelper;
 class SfxItemSet;
 class SfxPoolItem;
-class ScPatternAttr;
 
 class ScItemPoolCache
 {
     struct SfxItemModifyImpl
     {
-        const ScPatternAttr  *pOrigItem;
-        ScPatternAttr        *pPoolItem;
+        const CellAttributeHolder aOriginal;
+        const CellAttributeHolder aModified;
+        SfxItemModifyImpl(const CellAttributeHolder& a, const 
CellAttributeHolder &b) : aOriginal(a), aModified(b) {}
     };
 
-    SfxItemPool             *pPool;
-    std::vector<SfxItemModifyImpl>
-                             m_aCache;
-    const SfxItemSet        *pSetToPut;
-    const SfxPoolItem       *pItemToPut;
+    CellAttributeHelper&        rHelper;
+    std::vector<SfxItemModifyImpl> m_aCache;
+    const SfxItemSet*           pSetToPut;
+    const SfxPoolItemHolder     aItemToPut;
 
 public:
-                            ScItemPoolCache( SfxItemPool *pPool,
-                                              const SfxPoolItem *pPutItem );
-                            ScItemPoolCache( SfxItemPool *pPool,
-                                              const SfxItemSet *pPutSet );
-                            ~ScItemPoolCache();
+    ScItemPoolCache( CellAttributeHelper& rHelper, const SfxPoolItem& rPutItem 
);
+    ScItemPoolCache( CellAttributeHelper& rHelper, const SfxItemSet& rPutSet );
+    ~ScItemPoolCache();
 
-    const ScPatternAttr&    ApplyTo( const ScPatternAttr& rSetItem );
+    const CellAttributeHolder& ApplyTo( const CellAttributeHolder& rSetItem );
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/scitems.hxx b/sc/inc/scitems.hxx
index dd91e2f63a3c..538624e4c5cb 100644
--- a/sc/inc/scitems.hxx
+++ b/sc/inc/scitems.hxx
@@ -162,48 +162,46 @@ constexpr TypedWhichId<ScCondFormatItem> ATTR_CONDITIONAL 
(154);
 constexpr TypedWhichId<SfxStringItem> ATTR_HYPERLINK (155);
 
 constexpr sal_uInt16 ATTR_PATTERN_END(155);     // end cell-attribute-pattern
-
-constexpr TypedWhichId<ScPatternAttr> ATTR_PATTERN (156);
                                         // page attributes
-constexpr TypedWhichId<SvxLRSpaceItem> ATTR_LRSPACE (157);    // editor: 
PageDesc-TabPage
-constexpr TypedWhichId<SvxULSpaceItem> ATTR_ULSPACE (158);
-constexpr TypedWhichId<SvxPageItem> ATTR_PAGE (159);
-constexpr TypedWhichId<SvxPaperBinItem> ATTR_PAGE_PAPERBIN (160);
-constexpr TypedWhichId<SvxSizeItem> ATTR_PAGE_SIZE (161);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HORCENTER (162);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_VERCENTER (163);
-
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_ON (164);     // editor: 
header/footer-page
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_DYNAMIC (165);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED (166);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED_FIRST (167);
-
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NOTES (168);     // editor: table
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_GRID (169);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HEADERS (170);
-constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_CHARTS (171);
-constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_OBJECTS (172);
-constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_DRAWINGS (173);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_TOPDOWN (174);
-constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALE (175);
-constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALETOPAGES (176);
-constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_FIRSTPAGENO (177);
-
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERLEFT (178);     // 
contents of header/
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERLEFT (179);     // footer 
(left)
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERRIGHT (180);    // 
contents of header/
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERRIGHT (181);    // footer 
(right)
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERFIRST (182);    // 
contents of header/
-constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERFIRST (183);    // footer 
(first page)
-constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_HEADERSET (184);     // the 
corresponding sets
-constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_FOOTERSET (185);
-
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_FORMULAS (186);
-constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NULLVALS (187);
-
-constexpr TypedWhichId<ScPageScaleToItem> ATTR_PAGE_SCALETO (188);     // 
#i8868# scale printout to width/height
-
-constexpr TypedWhichId<SfxBoolItem> ATTR_HIDDEN (189);
+constexpr TypedWhichId<SvxLRSpaceItem> ATTR_LRSPACE (156);    // editor: 
PageDesc-TabPage
+constexpr TypedWhichId<SvxULSpaceItem> ATTR_ULSPACE (157);
+constexpr TypedWhichId<SvxPageItem> ATTR_PAGE (158);
+constexpr TypedWhichId<SvxPaperBinItem> ATTR_PAGE_PAPERBIN (159);
+constexpr TypedWhichId<SvxSizeItem> ATTR_PAGE_SIZE (160);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HORCENTER (161);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_VERCENTER (162);
+
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_ON (163);     // editor: 
header/footer-page
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_DYNAMIC (164);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED (165);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED_FIRST (166);
+
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NOTES (167);     // editor: table
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_GRID (168);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HEADERS (169);
+constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_CHARTS (170);
+constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_OBJECTS (171);
+constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_DRAWINGS (172);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_TOPDOWN (173);
+constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALE (174);
+constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALETOPAGES (175);
+constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_FIRSTPAGENO (176);
+
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERLEFT (177);     // 
contents of header/
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERLEFT (178);     // footer 
(left)
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERRIGHT (179);    // 
contents of header/
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERRIGHT (180);    // footer 
(right)
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERFIRST (181);    // 
contents of header/
+constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERFIRST (182);    // footer 
(first page)
+constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_HEADERSET (183);     // the 
corresponding sets
+constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_FOOTERSET (184);
+
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_FORMULAS (185);
+constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NULLVALS (186);
+
+constexpr TypedWhichId<ScPageScaleToItem> ATTR_PAGE_SCALETO (187);     // 
#i8868# scale printout to width/height
+
+constexpr TypedWhichId<SfxBoolItem> ATTR_HIDDEN (188);
 
 constexpr sal_uInt16 ATTR_ENDINDEX(ATTR_HIDDEN);        // end of pool-range
 
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 3b47a52c0ab8..72e78b195986 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -780,7 +780,7 @@ public:
     void        SetAttrEntries( SCCOL nStartCol, SCCOL nEndCol, 
std::vector<ScAttrEntry> && vNewData);
 
     void        SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr 
);
-    const ScPatternAttr* SetPattern( SCCOL nCol, SCROW nRow, 
std::unique_ptr<ScPatternAttr> );
+    void        SetPattern( SCCOL nCol, SCROW nRow, const CellAttributeHolder& 
rHolder );
     void        SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr 
);
     void        ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
                             const ScPatternAttr& rPattern, SvNumFormatType 
nNewType );
@@ -810,7 +810,7 @@ public:
     bool        ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, 
SCROW nEndRow, ScMF nFlags );
     bool        RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, 
SCROW nEndRow, ScMF nFlags );
 
-    void        ApplySelectionCache( ScItemPoolCache* pCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray = nullptr, bool* const 
pIsChanged = nullptr );
+    void        ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray = nullptr, bool* const 
pIsChanged = nullptr );
     void        DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& 
rMark, bool bBroadcast = true );
 
     void        ClearSelectionItems( const sal_uInt16* pWhich, const 
ScMarkData& rMark );
diff --git a/sc/qa/unit/subsequent_export_test.cxx 
b/sc/qa/unit/subsequent_export_test.cxx
index 30600191d54a..4fc83ab7df9f 100644
--- a/sc/qa/unit/subsequent_export_test.cxx
+++ b/sc/qa/unit/subsequent_export_test.cxx
@@ -1740,7 +1740,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testRichTextExportODS)
         pEditText = pDoc->GetEditText(ScAddress(1, 8, 0));
         CPPUNIT_ASSERT_MESSAGE("Incorrect B9 value.", 
aCheckFunc.checkB9(pEditText));
 
-        ScPatternAttr aCellFontColor(pDoc->GetPool());
+        ScPatternAttr aCellFontColor(pDoc->getCellAttributeHelper());
         aCellFontColor.GetItemSet().Put(SvxColorItem(COL_BLUE, 
ATTR_FONT_COLOR));
         // Set font color of B10 to blue.
         pDoc->ApplyPattern(1, 9, 0, aCellFontColor);
diff --git a/sc/qa/unit/subsequent_export_test4.cxx 
b/sc/qa/unit/subsequent_export_test4.cxx
index 95c7057aef2d..41d76cc9698d 100644
--- a/sc/qa/unit/subsequent_export_test4.cxx
+++ b/sc/qa/unit/subsequent_export_test4.cxx
@@ -223,7 +223,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf143979)
         sal_uInt32 nFormat;
         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
         pFormatter->PutEntry(aCode, nCheckPos, nType, nFormat);
-        ScPatternAttr aNewAttrs(pDoc->GetPool());
+        ScPatternAttr aNewAttrs(pDoc->getCellAttributeHelper());
         SfxItemSet& rSet = aNewAttrs.GetItemSet();
         rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
         pDoc->ApplyPattern(0, 0, 0, aNewAttrs);
@@ -1418,7 +1418,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testWholeRowBold)
         ScDocument* pDoc = getScDoc();
 
         // Make entire second row bold.
-        ScPatternAttr boldAttr(pDoc->GetPool());
+        ScPatternAttr boldAttr(pDoc->getCellAttributeHelper());
         boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, 
ATTR_FONT_WEIGHT));
         pDoc->ApplyPatternAreaTab(0, 1, pDoc->MaxCol(), 1, 0, boldAttr);
     }
diff --git a/sc/qa/unit/subsequent_filters_test2.cxx 
b/sc/qa/unit/subsequent_filters_test2.cxx
index 22339c010e8f..31dae9282166 100644
--- a/sc/qa/unit/subsequent_filters_test2.cxx
+++ b/sc/qa/unit/subsequent_filters_test2.cxx
@@ -1637,10 +1637,10 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest2, 
testBackColorFilter)
     createScDoc();
     ScDocument* pDoc = getScDoc();
 
-    ScPatternAttr aPattern1(pDoc->GetPool());
+    ScPatternAttr aPattern1(pDoc->getCellAttributeHelper());
     aPattern1.GetItemSet().Put(SvxBrushItem(aBackColor1, ATTR_BACKGROUND));
 
-    ScPatternAttr aPattern2(pDoc->GetPool());
+    ScPatternAttr aPattern2(pDoc->getCellAttributeHelper());
     aPattern2.GetItemSet().Put(SvxBrushItem(aBackColor2, ATTR_BACKGROUND));
 
     // Apply the pattern to cell A1:A2
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index c75742eabdfc..370f2d1f5c80 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1187,7 +1187,7 @@ CPPUNIT_TEST_FIXTURE(Test, testHorizontalAttrIterator)
     m_pDoc->InsertTab(0, "Test");
 
     // Set the background color of B2:C3,D2,E3,C4:D4,B5:D5 to blue
-    ScPatternAttr aCellBackColor(m_pDoc->GetPool());
+    ScPatternAttr aCellBackColor(m_pDoc->getCellAttributeHelper());
     aCellBackColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(1, 1, 2, 2, 0, aCellBackColor);
     m_pDoc->ApplyPatternAreaTab(3, 1, 3, 1, 0, aCellBackColor);
@@ -1210,7 +1210,7 @@ CPPUNIT_TEST_FIXTURE(Test, testHorizontalAttrIterator)
         size_t nCheckPos = 0;
         for (const ScPatternAttr* pAttr = aIter.GetNext(nCol1, nCol2, nRow); 
pAttr; pAttr = aIter.GetNext(nCol1, nCol2, nRow))
         {
-            if (SfxPoolItem::areSame( pAttr, m_pDoc->GetDefPattern()))
+            if (pAttr->isDefault())
                 continue;
             CPPUNIT_ASSERT_MESSAGE("Iteration longer than expected.", 
nCheckPos < nCheckLen);
             CPPUNIT_ASSERT_EQUAL(aChecks[nCheckPos][0], 
static_cast<int>(nCol1));
@@ -1235,7 +1235,7 @@ CPPUNIT_TEST_FIXTURE(Test, 
testIteratorsUnallocatedColumnsAttributes)
     CPPUNIT_ASSERT_EQUAL(allocatedColsCount, 
m_pDoc->GetAllocatedColumnsCount(0));
 
     // Make entire second row and third row bold.
-    ScPatternAttr boldAttr(m_pDoc->GetPool());
+    ScPatternAttr boldAttr(m_pDoc->getCellAttributeHelper());
     boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT));
     m_pDoc->ApplyPatternAreaTab(0, 1, m_pDoc->MaxCol(), 2, 0, boldAttr);
 
@@ -1293,15 +1293,15 @@ CPPUNIT_TEST_FIXTURE(Test, testIteratorsDefPattern)
     // Set cells as bold, default allocated, bold, default unallocated.
     SCCOL firstCol = 100;
     SCCOL lastCol = 103;
-    ScPatternAttr boldAttr(m_pDoc->GetPool());
+    ScPatternAttr boldAttr(m_pDoc->getCellAttributeHelper());
     boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT));
     m_pDoc->ApplyPattern(100, 0, 0, boldAttr);
     m_pDoc->ApplyPattern(102, 0, 0, boldAttr);
 
     CPPUNIT_ASSERT_EQUAL(SCCOL(102 + 1), m_pDoc->GetAllocatedColumnsCount(0));
     const ScPatternAttr* pattern = m_pDoc->GetPattern(100, 0, 0);
-    const ScPatternAttr* defPattern = m_pDoc->GetDefPattern();
-    CPPUNIT_ASSERT(!SfxPoolItem::areSame(pattern, defPattern));
+    const ScPatternAttr* 
defPattern(&m_pDoc->getCellAttributeHelper().getDefaultCellAttribute()); 
//GetDefPattern();
+    CPPUNIT_ASSERT(!ScPatternAttr::areSame(pattern, defPattern));
     CPPUNIT_ASSERT_EQUAL(pattern, m_pDoc->GetPattern(102, 0, 0));
     CPPUNIT_ASSERT_EQUAL(defPattern, m_pDoc->GetPattern(101, 0, 0));
     CPPUNIT_ASSERT_EQUAL(defPattern, m_pDoc->GetPattern(103, 0, 0));
@@ -3481,7 +3481,7 @@ CPPUNIT_TEST_FIXTURE(Test, testAutoFilterTimeValue)
     // Apply the "hour:minute:second" format to A2:A3.
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     sal_uInt32 nFormat = pFormatter->GetFormatIndex(NF_TIME_HH_MMSS, 
LANGUAGE_ENGLISH_US);
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
 
@@ -3634,7 +3634,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf76441)
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     pFormatter->PutEntry( aCode, nCheckPos, nType, nFormat );
 
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
     {
@@ -3672,7 +3672,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf76836)
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     pFormatter->PutEntry( aCode, nCheckPos, nType, nFormat );
 
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
 
@@ -3705,7 +3705,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf142186)
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     pFormatter->PutEntry( aCode, nCheckPos, nType, nFormat );
 
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
     {
@@ -3759,7 +3759,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf126342)
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     pFormatter->PutEntry( aCode, nCheckPos, nType, nFormat );
 
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
     m_pDoc->ApplyPattern(0, 0, 0, aNewAttrs);
@@ -3892,7 +3892,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateFilterContains)
     // Set the fields as dates.
     SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable();
     sal_uInt32 nFormat = pFormatter->GetFormatIndex(NF_DATE_DIN_YYMMDD, 
LANGUAGE_ENGLISH_US);
-    ScPatternAttr aNewAttrs(m_pDoc->GetPool());
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     SfxItemSet& rSet = aNewAttrs.GetItemSet();
     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
     m_pDoc->ApplyPatternAreaTab(0, 1, 0, 5, 0, aNewAttrs); // apply it to A1:A6
@@ -6657,7 +6657,7 @@ CPPUNIT_TEST_FIXTURE(Test, testProtectedSheetEditByRow)
 
     {
         // Remove protected flags from rows 2-5.
-        ScPatternAttr aAttr(m_pDoc->GetPool());
+        ScPatternAttr aAttr(m_pDoc->getCellAttributeHelper());
         aAttr.GetItemSet().Put(ScProtectionAttr(false));
         m_pDoc->ApplyPatternAreaTab(0, 1, m_pDoc->MaxCol(), 4, 0, aAttr);
 
@@ -6733,7 +6733,7 @@ CPPUNIT_TEST_FIXTURE(Test, testProtectedSheetEditByColumn)
 
     {
         // Remove protected flags from columns B to E.
-        ScPatternAttr aAttr(m_pDoc->GetPool());
+        ScPatternAttr aAttr(m_pDoc->getCellAttributeHelper());
         aAttr.GetItemSet().Put(ScProtectionAttr(false));
         m_pDoc->ApplyPatternAreaTab(1, 0, 4, m_pDoc->MaxRow(), 0, aAttr);
 
diff --git a/sc/qa/unit/ucalc_DocumentThemes.cxx 
b/sc/qa/unit/ucalc_DocumentThemes.cxx
index d0bd29052c16..2a05badedc65 100644
--- a/sc/qa/unit/ucalc_DocumentThemes.cxx
+++ b/sc/qa/unit/ucalc_DocumentThemes.cxx
@@ -57,7 +57,7 @@ CPPUNIT_TEST_FIXTURE(DocumentThemesTest, testChangeTheme)
     auto eBackgroundThemeType = model::ThemeColorType::Accent5;
     auto eCellTextThemeType = model::ThemeColorType::Accent2;
 
-    ScPatternAttr aNewPattern(m_pDoc->GetPool());
+    ScPatternAttr aNewPattern(m_pDoc->getCellAttributeHelper());
     {
         model::ComplexColor aComplexColor;
         aComplexColor.setThemeColor(eBackgroundThemeType);
diff --git a/sc/qa/unit/ucalc_copypaste.cxx b/sc/qa/unit/ucalc_copypaste.cxx
index bec9bb499b94..b673ad7de3a1 100644
--- a/sc/qa/unit/ucalc_copypaste.cxx
+++ b/sc/qa/unit/ucalc_copypaste.cxx
@@ -1609,7 +1609,7 @@ void TestCopyPaste::executeCopyPasteSpecial(const SCTAB 
srcSheet, const SCTAB de
     m_pDoc->SetString(10, 17, srcSheet, "=SUM(Range_aCa5_aCa10)");
 
     // add patterns
-    ScPatternAttr aCellBlueColor(m_pDoc->GetPool());
+    ScPatternAttr aCellBlueColor(m_pDoc->getCellAttributeHelper());
     aCellBlueColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(1, 2, 1, 4, srcSheet, aCellBlueColor);
 
@@ -1624,12 +1624,12 @@ void TestCopyPaste::executeCopyPasteSpecial(const SCTAB 
srcSheet, const SCTAB de
     CPPUNIT_ASSERT_MESSAGE("SrcSheet.B6 has no pattern", !pItem);
 
     // row 2 on empty cell
-    ScPatternAttr aCellGreenColor(m_pDoc->GetPool());
+    ScPatternAttr aCellGreenColor(m_pDoc->getCellAttributeHelper());
     aCellGreenColor.GetItemSet().Put(SvxBrushItem(COL_GREEN, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(5, 4, 5, 4, srcSheet, aCellGreenColor);
 
     // row 4 for multi range row selection
-    ScPatternAttr aCellRedColor(m_pDoc->GetPool());
+    ScPatternAttr aCellRedColor(m_pDoc->getCellAttributeHelper());
     aCellRedColor.GetItemSet().Put(SvxBrushItem(COL_RED, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(3, 6, 4, 6, srcSheet, aCellRedColor);
 
@@ -9345,7 +9345,7 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, 
testCopyPasteSkipEmpty)
     m_pDoc->SetString(ScAddress(1, 4, 0), "E");
 
     // Set the background color of B1:B5 to blue.
-    ScPatternAttr aCellBackColor(m_pDoc->GetPool());
+    ScPatternAttr aCellBackColor(m_pDoc->getCellAttributeHelper());
     aCellBackColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(1, 0, 1, 4, 0, aCellBackColor);
 
@@ -10723,7 +10723,7 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, 
testUndoBackgroundColor)
     m_pDoc->SetValue(ScAddress(3, 4, 0), 3.0); // D5
 
     // Add patterns
-    ScPatternAttr aCellBlueColor(m_pDoc->GetPool());
+    ScPatternAttr aCellBlueColor(m_pDoc->getCellAttributeHelper());
     aCellBlueColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND));
     m_pDoc->ApplyPatternAreaTab(0, 3, m_pDoc->MaxCol(), 3, 0, aCellBlueColor);
 
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index feb0e8fef22a..105c7e4a772d 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -4257,8 +4257,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, 
testFormulaRefUpdateValidity)
     sal_uInt32 nIndex = m_pDoc->AddValidationEntry(aData);
     SfxUInt32Item aItem(ATTR_VALIDDATA, nIndex);
 
-    ScPatternAttr aNewAttrs(
-        SfxItemSet(*m_pDoc->GetPool(), svl::Items<ATTR_PATTERN_START, 
ATTR_PATTERN_END>));
+    ScPatternAttr aNewAttrs(m_pDoc->getCellAttributeHelper());
     aNewAttrs.GetItemSet().Put(aItem);
 
     m_pDoc->ApplyPattern(0, 1, 0, aNewAttrs);
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 7124e78be37e..4b9bbc7a4e2c 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -62,11 +62,11 @@ ScAttrArray::ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, 
ScDocument& rDoc, ScAttr
     for ( size_t nIdx = 0; nIdx < pDefaultColAttrArray->mvData.size(); ++nIdx )
     {
         mvData[nIdx].nEndRow = pDefaultColAttrArray->mvData[nIdx].nEndRow;
-        ScPatternAttr aNewPattern( 
*(pDefaultColAttrArray->mvData[nIdx].pPattern) );
-        mvData[nIdx].pPattern = &rDocument.GetPool()->DirectPutItemInPool( 
aNewPattern );
+        
mvData[nIdx].setScPatternAttr(pDefaultColAttrArray->mvData[nIdx].getScPatternAttr());
         bool bNumFormatChanged = false;
         if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
-             mvData[nIdx].pPattern->GetItemSet(), 
rDocument.GetDefPattern()->GetItemSet() ) )
+             mvData[nIdx].getScPatternAttr()->GetItemSet(),
+             
rDocument.getCellAttributeHelper().getDefaultCellAttribute().GetItemSet() ) )
         {
             aAdrStart.SetRow( nIdx ? mvData[nIdx-1].nEndRow+1 : 0 );
             aAdrEnd.SetRow( mvData[nIdx].nEndRow );
@@ -80,10 +80,6 @@ ScAttrArray::~ScAttrArray()
 #if DEBUG_SC_TESTATTRARRAY
     TestData();
 #endif
-
-    ScDocumentPool* pDocPool = rDocument.GetPool();
-    for (auto const & rEntry : mvData)
-        pDocPool->DirectRemoveItemFromPool(*rEntry.pPattern);
 }
 
 #if DEBUG_SC_TESTATTRARRAY
@@ -97,8 +93,6 @@ void ScAttrArray::TestData() const
         if (nPos > 0)
             if (mvData[nPos].pPattern == mvData[nPos-1].pPattern || 
mvData[nPos].nRow <= mvData[nPos-1].nRow)
                 ++nErr;
-        if (mvData[nPos].pPattern->Which() != ATTR_PATTERN)
-            ++nErr;
     }
     if ( nPos && mvData[nPos-1].nRow != rDocument.MaxRow() )
         ++nErr;
@@ -116,19 +110,22 @@ void ScAttrArray::SetDefaultIfNotInit( SCSIZE nNeeded )
     mvData.reserve( nNewLimit );
     mvData.emplace_back();
     mvData[0].nEndRow = rDocument.MaxRow();
-    mvData[0].pPattern = rDocument.GetDefPattern(); // no put
+    
mvData[0].setScPatternAttr(&rDocument.getCellAttributeHelper().getDefaultCellAttribute());
 // no put
 }
 
-void ScAttrArray::Reset( const ScPatternAttr* pPattern )
+void ScAttrArray::Reset(const CellAttributeHolder& rPattern)
 {
-    ScDocumentPool*      pDocPool = rDocument.GetPool();
+    const ScPatternAttr* pPattern(rPattern.getScPatternAttr());
+    if (nullptr == pPattern)
+        return;
+
     ScAddress            aAdrStart( nCol, 0, nTab );
     ScAddress            aAdrEnd  ( nCol, 0, nTab );
 
     for (SCSIZE i=0; i<mvData.size(); i++)
     {
         // ensure that attributing changes text width of cell
-        const ScPatternAttr* pOldPattern = mvData[i].pPattern;
+        const ScPatternAttr* pOldPattern(mvData[i].getScPatternAttr());
         if ( nCol != -1 )
         {
             bool bNumFormatChanged;
@@ -140,16 +137,14 @@ void ScAttrArray::Reset( const ScPatternAttr* pPattern )
                 rDocument.InvalidateTextWidth( &aAdrStart, &aAdrEnd, 
bNumFormatChanged );
             }
         }
-        pDocPool->DirectRemoveItemFromPool(*pOldPattern);
     }
     mvData.resize(0);
 
     rDocument.SetStreamValid(nTab, false);
 
     mvData.resize(1);
-    const ScPatternAttr* pNewPattern = 
&pDocPool->DirectPutItemInPool(*pPattern);
     mvData[0].nEndRow = rDocument.MaxRow();
-    mvData[0].pPattern = pNewPattern;
+    mvData[0].setScPatternAttr(pPattern);
 }
 
 bool ScAttrArray::Concat(SCSIZE nPos)
@@ -159,10 +154,9 @@ bool ScAttrArray::Concat(SCSIZE nPos)
     {
         if (nPos > 0)
         {
-            if (SfxPoolItem::areSame(mvData[nPos - 1].pPattern, 
mvData[nPos].pPattern))
+            if (ScPatternAttr::areSame(mvData[nPos - 1].getScPatternAttr(), 
mvData[nPos].getScPatternAttr()))
             {
                 mvData[nPos - 1].nEndRow = mvData[nPos].nEndRow;
-                
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
                 mvData.erase(mvData.begin() + nPos);
                 nPos--;
                 bRet = true;
@@ -170,10 +164,9 @@ bool ScAttrArray::Concat(SCSIZE nPos)
         }
         if (nPos + 1 < mvData.size())
         {
-            if (SfxPoolItem::areSame(mvData[nPos + 1].pPattern, 
mvData[nPos].pPattern))
+            if (ScPatternAttr::areSame(mvData[nPos + 1].getScPatternAttr(), 
mvData[nPos].getScPatternAttr()))
             {
                 mvData[nPos].nEndRow = mvData[nPos + 1].nEndRow;
-                
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
                 mvData.erase(mvData.begin() + nPos + 1);
                 bRet = true;
             }
@@ -246,11 +239,11 @@ const ScPatternAttr* ScAttrArray::GetPattern( SCROW nRow 
) const
     {
         if ( !rDocument.ValidRow(nRow) )
             return nullptr;
-        return rDocument.GetDefPattern();
+        return &rDocument.getCellAttributeHelper().getDefaultCellAttribute();
     }
     SCSIZE i;
     if (Search( nRow, i ))
-        return mvData[i].pPattern;
+        return mvData[i].getScPatternAttr();
     else
         return nullptr;
 }
@@ -264,7 +257,7 @@ const ScPatternAttr* ScAttrArray::GetPatternRange( SCROW& 
rStartRow,
             return nullptr;
         rStartRow = 0;
         rEndRow = rDocument.MaxRow();
-        return rDocument.GetDefPattern();
+        return &rDocument.getCellAttributeHelper().getDefaultCellAttribute();
     }
     SCSIZE nIndex;
     if ( Search( nRow, nIndex ) )
@@ -274,7 +267,7 @@ const ScPatternAttr* ScAttrArray::GetPatternRange( SCROW& 
rStartRow,
         else
             rStartRow = 0;
         rEndRow = mvData[nIndex].nEndRow;
-        return mvData[nIndex].pPattern;
+        return mvData[nIndex].getScPatternAttr();
     }
     return nullptr;
 }
@@ -296,7 +289,7 @@ void ScAttrArray::AddCondFormat( SCROW nStartRow, SCROW 
nEndRow, sal_uInt32 nInd
 
         // changed to create pNewPattern only if needed, else use already
         // existing pPattern. This shows by example how to avoid that special
-        // handling of ATTR_PATTERN/ScPatternAttr in SC and massive
+        // handling of ScPatternAttr in SC and massive
         // incarnations/destructions of that Item (which contains an ItemSet)
         std::unique_ptr<ScPatternAttr> pNewPattern;
         if(pPattern)
@@ -329,16 +322,16 @@ void ScAttrArray::AddCondFormat( SCROW nStartRow, SCROW 
nEndRow, sal_uInt32 nInd
         }
         else
         {
-            pNewPattern.reset( new ScPatternAttr( rDocument.GetPool() ) );
+            pNewPattern.reset( new ScPatternAttr( 
rDocument.getCellAttributeHelper() ) );
             ScCondFormatItem aItem(nIndex);
             pNewPattern->GetItemSet().Put( aItem );
             nTempEndRow = nEndRow;
         }
 
         if (pNewPattern)
-            SetPatternArea( nTempStartRow, nTempEndRow, 
std::move(pNewPattern), true );
+            SetPatternArea( nTempStartRow, nTempEndRow, 
CellAttributeHolder(pNewPattern.release(), true) );
         else
-            SetPatternArea( nTempStartRow, nTempEndRow, pPattern, true );
+            SetPatternArea( nTempStartRow, nTempEndRow, 
CellAttributeHolder(pPattern) );
 
         nTempStartRow = nTempEndRow + 1;
     }
@@ -370,12 +363,12 @@ void ScAttrArray::RemoveCondFormat( SCROW nStartRow, 
SCROW nEndRow, sal_uInt32 n
             nTempEndRow = std::min<SCROW>( nPatternEndRow, nEndRow );
             if (const ScCondFormatItem* pItem = 
pPattern->GetItemSet().GetItemIfSet( ATTR_CONDITIONAL ))
             {
-                auto pPatternAttr = std::make_unique<ScPatternAttr>( *pPattern 
);
                 if (nIndex == 0)
                 {
                     ScCondFormatItem aItem;
-                    pPatternAttr->GetItemSet().Put( aItem );
-                    SetPatternArea( nTempStartRow, nTempEndRow, 
std::move(pPatternAttr), true );
+                    ScPatternAttr* pTemp(new ScPatternAttr(*pPattern));
+                    pTemp->GetItemSet().Put( aItem );
+                    SetPatternArea( nTempStartRow, nTempEndRow, 
CellAttributeHolder(pTemp, true) );
                 }
                 else
                 {
@@ -386,8 +379,9 @@ void ScAttrArray::RemoveCondFormat( SCROW nStartRow, SCROW 
nEndRow, sal_uInt32 n
                         ScCondFormatIndexes 
aNewCondFormatData(rCondFormatData);
                         
aNewCondFormatData.erase_at(std::distance(rCondFormatData.begin(), itr));
                         ScCondFormatItem aItem( std::move(aNewCondFormatData) 
);
-                        pPatternAttr->GetItemSet().Put( aItem );
-                        SetPatternArea( nTempStartRow, nTempEndRow, 
std::move(pPatternAttr), true );
+                        ScPatternAttr* pTemp(new ScPatternAttr(*pPattern));
+                        pTemp->GetItemSet().Put( aItem );
+                        SetPatternArea( nTempStartRow, nTempEndRow, 
CellAttributeHolder(pTemp, true) );
                     }
                 }
             }
@@ -441,7 +435,7 @@ bool ScAttrArray::Reserve( SCSIZE nReserve )
             mvData.reserve(nReserve);
             mvData.emplace_back();
             mvData[0].nEndRow = rDocument.MaxRow();
-            mvData[0].pPattern = rDocument.GetDefPattern(); // no put
+            
mvData[0].setScPatternAttr(&rDocument.getCellAttributeHelper().getDefaultCellAttribute());
 // no put
             return true;
         } catch (std::bad_alloc const &) {
             return false;
@@ -460,20 +454,17 @@ bool ScAttrArray::Reserve( SCSIZE nReserve )
         return false;
 }
 
-const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW nStartRow, SCROW 
nEndRow, const ScPatternAttr* pPattern,
-                                 bool bPutToPool, ScEditDataArray* pDataArray, 
bool bPassingOwnership )
+const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(
+    SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, 
ScEditDataArray* pDataArray)
 {
+    const ScPatternAttr* pPattern(rPattern.getScPatternAttr());
+    if (nullptr == pPattern)
+        return nullptr;
+
     if (rDocument.ValidRow(nStartRow) && rDocument.ValidRow(nEndRow))
     {
-        if (bPutToPool)
-        {
-            if (bPassingOwnership)
-                pPattern = 
&rDocument.GetPool()->DirectPutItemInPool(std::unique_ptr<ScPatternAttr>(const_cast<ScPatternAttr*>(pPattern)));
-            else
-                pPattern = 
&rDocument.GetPool()->DirectPutItemInPool(*pPattern);
-        }
         if ((nStartRow == 0) && (nEndRow == rDocument.MaxRow()))
-            Reset(pPattern);
+            Reset(rPattern);
         else
         {
             SCSIZE nNeeded = mvData.size() + 2;
@@ -507,7 +498,7 @@ const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW 
nStartRow, SCROW nEnd
                 if ( nCol != -1 && !bIsLoading )
                 {
                     const SfxItemSet& rNewSet = pPattern->GetItemSet();
-                    const SfxItemSet& rOldSet = 
mvData[nx].pPattern->GetItemSet();
+                    const SfxItemSet& rOldSet = 
mvData[nx].getScPatternAttr()->GetItemSet();
                     bool bNumFormatChanged;
                     if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
                             rNewSet, rOldSet ) )
@@ -529,7 +520,7 @@ const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW 
nStartRow, SCROW nEnd
             if ( nStartRow > 0 )
             {
                 nInsert = rDocument.MaxRow() + 1;
-                if ( !SfxPoolItem::areSame(mvData[ni].pPattern, pPattern ) )
+                if ( !ScPatternAttr::areSame(mvData[ni].getScPatternAttr(), 
pPattern ) )
                 {
                     if ( ni == 0 || (mvData[ni-1].nEndRow < nStartRow - 1) )
                     {   // may be a split or a simple insert or just a shrink,
@@ -542,7 +533,7 @@ const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW 
nStartRow, SCROW nEnd
                     else if (mvData[ni - 1].nEndRow == nStartRow - 1)
                         nInsert = ni;
                 }
-                if ( ni > 0 && SfxPoolItem::areSame(mvData[ni-1].pPattern, 
pPattern) )
+                if ( ni > 0 && 
ScPatternAttr::areSame(mvData[ni-1].getScPatternAttr(), pPattern) )
                 {   // combine
                     mvData[ni-1].nEndRow = nEndRow;
                     nInsert = rDocument.MaxRow() + 1;
@@ -557,11 +548,11 @@ const ScPatternAttr* 
ScAttrArray::SetPatternAreaImpl(SCROW nStartRow, SCROW nEnd
                 nj++;
             if ( !bSplit )
             {
-                if ( nj < mvData.size() && 
SfxPoolItem::areSame(mvData[nj].pPattern, pPattern ) )
+                if ( nj < mvData.size() && 
ScPatternAttr::areSame(mvData[nj].getScPatternAttr(), pPattern ) )
                 {   // combine
                     if ( ni > 0 )
                     {
-                        if ( SfxPoolItem::areSame(mvData[ni-1].pPattern, 
pPattern ) )
+                        if ( 
ScPatternAttr::areSame(mvData[ni-1].getScPatternAttr(), pPattern ) )
                         {   // adjacent entries
                             mvData[ni-1].nEndRow = mvData[nj].nEndRow;
                             nj++;
@@ -575,21 +566,12 @@ const ScPatternAttr* 
ScAttrArray::SetPatternAreaImpl(SCROW nStartRow, SCROW nEnd
                 else if ( ni > 0 && ni == nInsert )
                     mvData[ni-1].nEndRow = nStartRow - 1;   // shrink
             }
-            ScDocumentPool* pDocPool = rDocument.GetPool();
-            if ( bSplit )
-            {   // duplicate split entry in pool
-                pDocPool->DirectPutItemInPool( *mvData[ni-1].pPattern );
-            }
             if ( ni < nj )
             {   // remove middle entries
-                for ( SCSIZE nk=ni; nk<nj; nk++)
-                {   // remove entries from pool
-                    pDocPool->DirectRemoveItemFromPool( *mvData[nk].pPattern );
-                }
                 if ( !bCombined )
                 {   // replace one entry
                     mvData[ni].nEndRow = nEndRow;
-                    mvData[ni].pPattern = pPattern;
+                    mvData[ni].setScPatternAttr(pPattern);
                     ni++;
                     nInsert = rDocument.MaxRow() + 1;
                 }
@@ -614,7 +596,7 @@ const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW 
nStartRow, SCROW nEnd
                 if ( nInsert )
                     mvData[nInsert-1].nEndRow = nStartRow - 1;
                 mvData[nInsert].nEndRow = nEndRow;
-                mvData[nInsert].pPattern = pPattern;
+                mvData[nInsert].setScPatternAttr(pPattern);
 
                 // Remove character attributes from these cells if the pattern
                 // is applied during normal session.
@@ -651,7 +633,7 @@ void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW 
nEndRow, const ScStyleS
 
     do
     {
-        const ScPatternAttr* pOldPattern = mvData[nPos].pPattern;
+        const ScPatternAttr* pOldPattern = mvData[nPos].getScPatternAttr();
         std::unique_ptr<ScPatternAttr> pNewPattern(new 
ScPatternAttr(*pOldPattern));
         pNewPattern->SetStyleSheet(const_cast<ScStyleSheet*>(&rStyle));
         SCROW nY1 = nStart;
@@ -668,7 +650,7 @@ void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW 
nEndRow, const ScStyleS
         {
             if (nY1 < nStartRow) nY1=nStartRow;
             if (nY2 > nEndRow) nY2=nEndRow;
-            SetPatternArea( nY1, nY2, std::move(pNewPattern), true );
+            SetPatternArea( nY1, nY2, 
CellAttributeHolder(pNewPattern.release(), true) );
             Search( nStart, nPos );
         }
         else
@@ -690,8 +672,7 @@ void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW 
nEndRow, const ScStyleS
                 }
             }
 
-            
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
-            mvData[nPos].pPattern = 
&rDocument.GetPool()->DirectPutItemInPool(*pNewPattern);
+            mvData[nPos].setScPatternAttr(pNewPattern.release(), true);
             if (Concat(nPos))
                 Search(nStart, nPos);
             else
@@ -746,7 +727,7 @@ void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, 
SCROW nEndRow,
 
     do
     {
-        const ScPatternAttr*    pOldPattern = mvData[nPos].pPattern;
+        const ScPatternAttr*    pOldPattern = mvData[nPos].getScPatternAttr();
         const SfxItemSet&       rOldSet = pOldPattern->GetItemSet();
         const SvxBoxItem*       pBoxItem = rOldSet.GetItemIfSet( ATTR_BORDER );
         const SvxLineItem*      pTLBRItem = rOldSet.GetItemIfSet( 
ATTR_BORDER_TLBR );
@@ -821,15 +802,13 @@ void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, 
SCROW nEndRow,
             {
                 if (nY1 < nStartRow) nY1=nStartRow;
                 if (nY2 > nEndRow) nY2=nEndRow;
-                SetPatternArea( nY1, nY2, std::move(pNewPattern), true );
+                SetPatternArea( nY1, nY2, 
CellAttributeHolder(pNewPattern.release(), true) );
                 Search( nStart, nPos );
             }
             else
             {
                 // remove from pool ?
-                
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
-                mvData[nPos].pPattern =
-                            
&rDocument.GetPool()->DirectPutItemInPool(std::move(pNewPattern));
+                mvData[nPos].setScPatternAttr(pNewPattern.release(), true);
 
                 if (Concat(nPos))
                     Search(nStart, nPos);
@@ -846,7 +825,7 @@ void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, 
SCROW nEndRow,
     while ((nStart <= nEndRow) && (nPos < mvData.size()));
 }
 
-void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, 
ScItemPoolCache* pCache, ScEditDataArray* pDataArray, bool* const pIsChanged )
+void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, 
ScItemPoolCache& rCache, ScEditDataArray* pDataArray, bool* const pIsChanged )
 {
 #if DEBUG_SC_TESTATTRARRAY
     TestData();
@@ -869,9 +848,10 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW 
nEndRow, ScItemPoolCach
 
     do
     {
-        const ScPatternAttr& rOldPattern = *mvData[nPos].pPattern;
-        const ScPatternAttr& rNewPattern = pCache->ApplyTo( rOldPattern );
-        if (!SfxPoolItem::areSame(rNewPattern, rOldPattern))
+        const CellAttributeHolder& 
rOldPattern(mvData[nPos].getCellAttributeHolder());
+        const CellAttributeHolder& rNewPattern(rCache.ApplyTo( rOldPattern ));
+
+        if (!CellAttributeHolder::areSame(&rNewPattern, &rOldPattern))
         {
             SCROW nY1 = nStart;
             SCROW nY2 = mvData[nPos].nEndRow;
@@ -884,7 +864,7 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW 
nEndRow, ScItemPoolCach
             {
                 if (nY1 < nStartRow) nY1=nStartRow;
                 if (nY2 > nEndRow) nY2=nEndRow;
-                SetPatternArea( nY1, nY2, &rNewPattern, false, pDataArray );
+                SetPatternArea( nY1, nY2, rNewPattern, pDataArray );
                 Search( nStart, nPos );
             }
             else
@@ -893,8 +873,8 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW 
nEndRow, ScItemPoolCach
                 {
                     // ensure attributing changes text-width of cell
 
-                    const SfxItemSet& rNewSet = rNewPattern.GetItemSet();
-                    const SfxItemSet& rOldSet = rOldPattern.GetItemSet();
+                    const SfxItemSet& rNewSet = 
rNewPattern.getScPatternAttr()->GetItemSet();
+                    const SfxItemSet& rOldSet = 
rOldPattern.getScPatternAttr()->GetItemSet();
 
                     bool bNumFormatChanged;
                     if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
@@ -906,8 +886,7 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW 
nEndRow, ScItemPoolCach
                     }
                 }
 
-                
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
-                mvData[nPos].pPattern = &rNewPattern;
+                mvData[nPos].setCellAttributeHolder(rNewPattern);
                 if (Concat(nPos))
                     Search(nStart, nPos);
                 else
@@ -931,10 +910,6 @@ void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW 
nEndRow, ScItemPoolCach
 
 void ScAttrArray::SetAttrEntries(std::vector<ScAttrEntry> && vNewData)
 {
-    ScDocumentPool* pDocPool = rDocument.GetPool();
-    for (auto const & rEntry : mvData)
-        pDocPool->DirectRemoveItemFromPool(*rEntry.pPattern);
-
     mvData = std::move(vNewData);
 
 #ifdef DBG_UTIL
@@ -1000,12 +975,12 @@ void ScAttrArray::MergePatternArea( SCROW nStartRow, 
SCROW nEndRow,
     do
     {
         // similar patterns must not be repeated
-        const ScPatternAttr* pPattern = nullptr;
+        const ScPatternAttr* 
pPattern(&rDocument.getCellAttributeHelper().getDefaultCellAttribute());
         if ( !mvData.empty() )
-            pPattern = mvData[nPos].pPattern;
-        else
-            pPattern = rDocument.GetDefPattern();
-        if ( !SfxPoolItem::areSame(pPattern, rState.pOld1) && 
!SfxPoolItem::areSame(pPattern, rState.pOld2) )
+            pPattern = mvData[nPos].getScPatternAttr();
+
+        if ( !ScPatternAttr::areSame(pPattern, rState.aOld1.getScPatternAttr())
+            && !ScPatternAttr::areSame(pPattern, 
rState.aOld2.getScPatternAttr()) )
         {
             const SfxItemSet& rThisSet = pPattern->GetItemSet();
             if (rState.pItemSet)
@@ -1024,8 +999,8 @@ void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW 
nEndRow,
                 rState.mnPatternId = pPattern->GetPAKey();
             }
 
-            rState.pOld2 = rState.pOld1;
-            rState.pOld1 = pPattern;
+            rState.aOld2 = rState.aOld1;
+            rState.aOld1 = pPattern;
         }
 
         if ( !mvData.empty() )
@@ -1156,7 +1131,7 @@ void ScAttrArray::MergeBlockFrame( SvxBoxItem* 
pLineOuter, SvxBoxInfoItem* pLine
         Search( nEndRow-1, nEndIndex );
         for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
         {
-            pPattern = mvData[i].pPattern;
+            pPattern = mvData[i].getScPatternAttr();
             lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, 
nDistRight, false,
                             nEndRow - std::min( mvData[i].nEndRow, 
static_cast<SCROW>(nEndRow-1) ) );
             // nDistBottom here always > 0
@@ -1167,7 +1142,7 @@ void ScAttrArray::MergeBlockFrame( SvxBoxItem* 
pLineOuter, SvxBoxInfoItem* pLine
     }
     else
     {
-        lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, 
rDocument.GetDefPattern(), bLeft, nDistRight, true, 0 );
+        lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, 
&rDocument.getCellAttributeHelper().getDefaultCellAttribute(), bLeft, 
nDistRight, true, 0 );
     }
 }
 
@@ -1237,8 +1212,8 @@ bool ScAttrArray::ApplyFrame( const SvxBoxItem&     
rBoxItem,
     }
     else
     {
-        ScItemPoolCache aCache( rDocument.GetPool(), &aNewFrame );
-        ApplyCacheArea( nStartRow, nEndRow, &aCache );
+        ScItemPoolCache aCache( rDocument.getCellAttributeHelper(), aNewFrame 
);
+        ApplyCacheArea( nStartRow, nEndRow, aCache );
 
         return true;
     }
@@ -1410,7 +1385,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, 
HasAttrFlags nMask ) cons
 {
     if (mvData.empty())
     {
-        return HasAttrib_Impl(rDocument.GetDefPattern(), nMask, 0, 
rDocument.MaxRow(), 0);
+        return 
HasAttrib_Impl(&rDocument.getCellAttributeHelper().getDefaultCellAttribute(), 
nMask, 0, rDocument.MaxRow(), 0);
     }
 
     SCSIZE nStartIndex;
@@ -1424,7 +1399,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, 
HasAttrFlags nMask ) cons
 
     for (SCSIZE i=nStartIndex; i<=nEndIndex && !bFound; i++)
     {
-        const ScPatternAttr* pPattern = mvData[i].pPattern;
+        const ScPatternAttr* pPattern = mvData[i].getScPatternAttr();
         bFound = HasAttrib_Impl(pPattern, nMask, nRow1, nRow2, i);
     }
 
@@ -1439,7 +1414,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow, HasAttrFlags 
nMask, SCROW* nStartRow, S
             *nStartRow = 0;
         if( nEndRow )
             *nEndRow = rDocument.MaxRow();
-        return HasAttrib_Impl(rDocument.GetDefPattern(), nMask, 0, 
rDocument.MaxRow(), 0);
+        return 
HasAttrib_Impl(&rDocument.getCellAttributeHelper().getDefaultCellAttribute(), 
nMask, 0, rDocument.MaxRow(), 0);
     }
 
     SCSIZE nIndex;
@@ -1448,7 +1423,7 @@ bool ScAttrArray::HasAttrib( SCROW nRow, HasAttrFlags 
nMask, SCROW* nStartRow, S
         *nStartRow = nIndex > 0 ? mvData[nIndex-1].nEndRow+1 : 0;
     if( nEndRow )
         *nEndRow = mvData[nIndex].nEndRow;
-    const ScPatternAttr* pPattern = mvData[nIndex].pPattern;
+    const ScPatternAttr* pPattern = mvData[nIndex].getScPatternAttr();
     return HasAttrib_Impl(pPattern, nMask, nRow, nRow, nIndex);
 }
 
@@ -1458,12 +1433,12 @@ bool ScAttrArray::IsMerged( SCROW nRow ) const
     {
         SCSIZE nIndex;
         Search(nRow, nIndex);
-        const ScMergeAttr& rItem = 
mvData[nIndex].pPattern->GetItem(ATTR_MERGE);
+        const ScMergeAttr& rItem = 
mvData[nIndex].getScPatternAttr()->GetItem(ATTR_MERGE);
 
         return rItem.IsMerged();
     }
 
-    return rDocument.GetDefPattern()->GetItem(ATTR_MERGE).IsMerged();
+    return 
rDocument.getCellAttributeHelper().getDefaultCellAttribute().GetItem(ATTR_MERGE).IsMerged();
 }
 
 /**
@@ -1485,7 +1460,7 @@ bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW 
nStartRow, SCROW nEndRow,
 
     for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
     {
-        pPattern = mvData[i].pPattern;
+        pPattern = mvData[i].getScPatternAttr();
         pItem = &pPattern->GetItem( ATTR_MERGE );
         SCCOL  nCountX = pItem->GetColMerge();
         SCROW  nCountY = pItem->GetRowMerge();
@@ -1541,7 +1516,7 @@ void ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW 
nEndRow)
         if (nThisEnd > nEndRow)
             nThisEnd = nEndRow;
 
-        pPattern = mvData[nIndex].pPattern;
+        pPattern = mvData[nIndex].getScPatternAttr();
         pItem = &pPattern->GetItem( ATTR_MERGE );
         SCCOL  nCountX = pItem->GetColMerge();
         SCROW  nCountY = pItem->GetRowMerge();
@@ -1560,7 +1535,7 @@ void ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW 
nEndRow)
             for (SCROW nThisRow = nThisStart; nThisRow <= nThisEnd; nThisRow++)
                 rDocument.ApplyAttr( nThisCol, nThisRow, nTab, *pAttr );
 
-            ScPatternAttr aNewPattern( rDocument.GetPool() );
+            ScPatternAttr aNewPattern( rDocument.getCellAttributeHelper() );
             SfxItemSet*     pSet = &aNewPattern.GetItemSet();
             pSet->Put( *pFlagAttr );
             rDocument.ApplyPatternAreaTab( nThisCol, nThisStart, nMergeEndCol, 
nMergeEndRow,
@@ -1577,51 +1552,40 @@ void ScAttrArray::RemoveAreaMerge(SCROW nStartRow, 
SCROW nEndRow)
     }
 }
 
-void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
-                        const ScPatternAttr* pWantedPattern, bool bDefault )
+void ScAttrArray::SetPatternAreaSafe(SCROW nStartRow, SCROW nEndRow, const 
CellAttributeHolder& rWantedPattern)
 {
     SetDefaultIfNotInit();
-    const ScPatternAttr*    pOldPattern;
-    const ScMergeFlagAttr*  pItem;
+    const ScMergeFlagAttr* pItem;
 
     SCSIZE  nIndex;
     SCROW   nRow;
     SCROW   nThisRow;
-    bool    bFirstUse = true;
 
     Search( nStartRow, nIndex );
     nThisRow = (nIndex>0) ? mvData[nIndex-1].nEndRow+1 : 0;
     while ( nThisRow <= nEndRow )
     {
-        pOldPattern = mvData[nIndex].pPattern;
-        if (!SfxPoolItem::areSame(pOldPattern, pWantedPattern)) // FIXME: 
else-branch?
+        const CellAttributeHolder& 
rOldPattern(mvData[nIndex].getCellAttributeHolder());
+        if (!CellAttributeHolder::areSame(&rOldPattern, &rWantedPattern)) // 
FIXME: else-branch?
         {
             if (nThisRow < nStartRow) nThisRow = nStartRow;
             nRow = mvData[nIndex].nEndRow;
             SCROW nAttrRow = std::min( nRow, nEndRow );
-            pItem = &pOldPattern->GetItem( ATTR_MERGE_FLAG );
+            pItem = &rOldPattern.getScPatternAttr()->GetItem( ATTR_MERGE_FLAG 
);
 
             if (pItem->IsOverlapped() || pItem->HasAutoFilter())
             {
                 //  default-constructing a ScPatternAttr for DeleteArea 
doesn't work
                 //  because it would have no cell style information.
-                //  Instead, the document's GetDefPattern is copied. Since it 
is passed as
+                //  Instead, the document's 
getCellAttributeHelper().getDefaultCellAttribute() is copied. Since it is 
passed as
                 //  pWantedPattern, no special treatment of default is needed 
here anymore.
-                std::unique_ptr<ScPatternAttr> pNewPattern(new ScPatternAttr( 
*pWantedPattern ));
+                ScPatternAttr* pNewPattern(new 
ScPatternAttr(*rWantedPattern.getScPatternAttr()));
                 pNewPattern->GetItemSet().Put( *pItem );
-                SetPatternArea( nThisRow, nAttrRow, std::move(pNewPattern), 
true );
+                SetPatternArea( nThisRow, nAttrRow, 
CellAttributeHolder(pNewPattern, true) );
             }
             else
             {
-                if ( !bDefault )
-                {
-                    if (bFirstUse)
-                        bFirstUse = false;
-                    else
-                        // it's in the pool
-                        rDocument.GetPool()->DirectPutItemInPool( 
*pWantedPattern );
-                }
-                SetPatternArea( nThisRow, nAttrRow, pWantedPattern );
+                SetPatternArea(nThisRow, nAttrRow, rWantedPattern);
             }
 
             Search( nThisRow, nIndex );   // data changed
@@ -1649,15 +1613,15 @@ bool ScAttrArray::ApplyFlags( SCROW nStartRow, SCROW 
nEndRow, ScMF nFlags )
 
     while ( nThisRow <= nEndRow )
     {
-        pOldPattern = mvData[nIndex].pPattern;
+        pOldPattern = mvData[nIndex].getScPatternAttr();
         nOldValue = pOldPattern->GetItem( ATTR_MERGE_FLAG ).GetValue();
         if ( (nOldValue | nFlags) != nOldValue )
         {
             nRow = mvData[nIndex].nEndRow;
             SCROW nAttrRow = std::min( nRow, nEndRow );
-            auto pNewPattern = std::make_unique<ScPatternAttr>(*pOldPattern);
+            ScPatternAttr* pNewPattern(new ScPatternAttr(*pOldPattern));
             pNewPattern->GetItemSet().Put( ScMergeFlagAttr( nOldValue | nFlags 
) );
-            SetPatternArea( nThisRow, nAttrRow, std::move(pNewPattern), true );
+            SetPatternArea( nThisRow, nAttrRow, 
CellAttributeHolder(pNewPattern, true) );
             Search( nThisRow, nIndex );  // data changed
             bChanged = true;
         }
@@ -1686,15 +1650,15 @@ bool ScAttrArray::RemoveFlags( SCROW nStartRow, SCROW 
nEndRow, ScMF nFlags )
 
     while ( nThisRow <= nEndRow )
     {
-        pOldPattern = mvData[nIndex].pPattern;
+        pOldPattern = mvData[nIndex].getScPatternAttr();
         nOldValue = pOldPattern->GetItem( ATTR_MERGE_FLAG ).GetValue();
         if ( (nOldValue & ~nFlags) != nOldValue )
         {
             nRow = mvData[nIndex].nEndRow;
             SCROW nAttrRow = std::min( nRow, nEndRow );
-            auto pNewPattern = std::make_unique<ScPatternAttr>(*pOldPattern);
+            ScPatternAttr* pNewPattern(new ScPatternAttr(*pOldPattern));
             pNewPattern->GetItemSet().Put( ScMergeFlagAttr( nOldValue & 
~nFlags ) );
-            SetPatternArea( nThisRow, nAttrRow, std::move(pNewPattern), true );
+            SetPatternArea( nThisRow, nAttrRow, 
CellAttributeHolder(pNewPattern, true) );
             Search( nThisRow, nIndex );  // data changed
             bChanged = true;
         }
@@ -1719,15 +1683,15 @@ void ScAttrArray::ClearItems( SCROW nStartRow, SCROW 
nEndRow, const sal_uInt16*
 
     while ( nThisRow <= nEndRow )
     {
-        const ScPatternAttr* pOldPattern = mvData[nIndex].pPattern;
+        const ScPatternAttr* pOldPattern = mvData[nIndex].getScPatternAttr();
         if ( pOldPattern->HasItemsSet( pWhich ) )
         {
-            auto pNewPattern = std::make_unique<ScPatternAttr>(*pOldPattern);
+            ScPatternAttr* pNewPattern(new ScPatternAttr(*pOldPattern));
             pNewPattern->ClearItems( pWhich );
 
             nRow = mvData[nIndex].nEndRow;
             SCROW nAttrRow = std::min( nRow, nEndRow );
-            SetPatternArea( nThisRow, nAttrRow, std::move(pNewPattern), true );
+            SetPatternArea( nThisRow, nAttrRow, 
CellAttributeHolder(pNewPattern, true) );
             Search( nThisRow, nIndex );  // data changed
         }
 
@@ -1746,7 +1710,7 @@ void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW 
nEndRow, bool bIncrement
 
     while ( nThisStart <= nEndRow )
     {
-        const ScPatternAttr* pOldPattern = mvData[nIndex].pPattern;
+        const ScPatternAttr* pOldPattern = mvData[nIndex].getScPatternAttr();
         const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
         const SvxHorJustifyItem* pItem;
 
@@ -1782,12 +1746,12 @@ void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW 
nEndRow, bool bIncrement
         {
             SCROW nThisEnd = mvData[nIndex].nEndRow;
             SCROW nAttrRow = std::min( nThisEnd, nEndRow );
-            auto pNewPattern = std::make_unique<ScPatternAttr>(*pOldPattern);
+            ScPatternAttr* pNewPattern(new ScPatternAttr(*pOldPattern));
             pNewPattern->GetItemSet().Put( ScIndentItem( nNewValue ) );
             if ( bNeedJust )
                 pNewPattern->GetItemSet().Put(
                                 SvxHorJustifyItem( SvxCellHorJustify::Left, 
ATTR_HOR_JUSTIFY ) );
-            SetPatternArea( nThisStart, nAttrRow, std::move(pNewPattern), true 
);
+            SetPatternArea( nThisStart, nAttrRow, 
CellAttributeHolder(pNewPattern, true) );
 
             nThisStart = nThisEnd + 1;
             Search( nThisStart, nIndex ); // data changed
@@ -1815,8 +1779,7 @@ SCROW ScAttrArray::GetNextUnprotected( SCROW nRow, bool 
bUp ) const
 
         SCSIZE nIndex;
         Search(nRow, nIndex);
-        while (mvData[nIndex].pPattern->
-                GetItem(ATTR_PROTECTION).GetProtection())
+        while 
(mvData[nIndex].getScPatternAttr()->GetItem(ATTR_PROTECTION).GetProtection())
         {
             if (bUp)
             {
@@ -1845,20 +1808,19 @@ void ScAttrArray::FindStyleSheet( const 
SfxStyleSheetBase* pStyleSheet, ScFlatBo
     while (nPos < mvData.size())
     {
         SCROW nEnd = mvData[nPos].nEndRow;
-        if (mvData[nPos].pPattern->GetStyleSheet() == pStyleSheet)
+        if (mvData[nPos].getScPatternAttr()->GetStyleSheet() == pStyleSheet)
         {
             rUsedRows.setTrue(nStart, nEnd);
 
             if (bReset)
             {
-                ScPatternAttr aNewPattern(*mvData[nPos].pPattern);
-                
rDocument.GetPool()->DirectRemoveItemFromPool(*mvData[nPos].pPattern);
-                aNewPattern.SetStyleSheet( static_cast<ScStyleSheet*>(
+                ScPatternAttr* pNewPattern(new 
ScPatternAttr(*mvData[nPos].getScPatternAttr()));
+                pNewPattern->SetStyleSheet( static_cast<ScStyleSheet*>(
                     rDocument.GetStyleSheetPool()->
                         Find( ScResId(STR_STYLENAME_STANDARD),
                               SfxStyleFamily::Para,
                               SfxStyleSearchBits::Auto | 
SfxStyleSearchBits::ScStandard ) ) );
-                mvData[nPos].pPattern = 
&rDocument.GetPool()->DirectPutItemInPool(aNewPattern);
+                mvData[nPos].setScPatternAttr(pNewPattern, true);
 
                 if (Concat(nPos))
                 {
@@ -1876,7 +1838,7 @@ bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& 
rStyle ) const
 {
     if ( mvData.empty() )
     {
-        const ScStyleSheet* pStyle = 
rDocument.GetDefPattern()->GetStyleSheet();
+        const ScStyleSheet* pStyle = 
rDocument.getCellAttributeHelper().getDefaultCellAttribute().GetStyleSheet();
         if ( pStyle )
         {
             pStyle->SetUsage( ScStyleSheet::Usage::USED );
@@ -1891,7 +1853,7 @@ bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& 
rStyle ) const
 
     while ( nPos < mvData.size() )
     {
-        const ScStyleSheet* pStyle = mvData[nPos].pPattern->GetStyleSheet();
+        const ScStyleSheet* pStyle = 
mvData[nPos].getScPatternAttr()->GetStyleSheet();
         if ( pStyle )
         {
             pStyle->SetUsage( ScStyleSheet::Usage::USED );
@@ -1913,7 +1875,7 @@ bool ScAttrArray::IsEmpty() const
 
     if (mvData.size() == 1)
     {
-        return SfxPoolItem::areSame(mvData[0].pPattern, 
rDocument.GetDefPattern());
+        return mvData[0].getScPatternAttr()->isDefault();
     }
     else
         return false;
@@ -1931,14 +1893,14 @@ bool ScAttrArray::GetFirstVisibleAttr( SCROW& rFirstRow 
) const
     // Entries at the end are not skipped, GetFirstVisibleAttr may be larger 
than GetLastVisibleAttr.
 
     SCSIZE nVisStart = 1;
-    while ( nVisStart < mvData.size() && 
mvData[nVisStart].pPattern->IsVisibleEqual(*mvData[nVisStart-1].pPattern) )
+    while ( nVisStart < mvData.size() && 
mvData[nVisStart].getScPatternAttr()->IsVisibleEqual(*mvData[nVisStart-1].getScPatternAttr())
 )
         ++nVisStart;
     if ( nVisStart >= mvData.size() || mvData[nVisStart-1].nEndRow > 0 )   // 
more than 1 row?
         nStart = nVisStart;
 
     while ( nStart < mvData.size() && !bFound )
     {
-        if ( mvData[nStart].pPattern->IsVisible() )
+        if ( mvData[nStart].getScPatternAttr()->IsVisible() )
         {
             rFirstRow = nStart ? ( mvData[nStart-1].nEndRow + 1 ) : 0;
             bFound = true;
@@ -1995,7 +1957,7 @@ bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, 
SCROW nLastData, bool bSk
             // find range of visually equal formats
             SCSIZE nEndPos = nPos;
             while ( nEndPos < mvData.size()-1 &&
-                    
mvData[nEndPos].pPattern->IsVisibleEqual(*mvData[nEndPos+1].pPattern))
+                    
mvData[nEndPos].getScPatternAttr()->IsVisibleEqual(*mvData[nEndPos+1].getScPatternAttr()))
                 ++nEndPos;
             SCROW nAttrStartRow = ( nPos > 0 ) ? ( mvData[nPos-1].nEndRow + 1) 
: 0;
             if ( nAttrStartRow <= nLastData )
@@ -2003,7 +1965,7 @@ bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, 
SCROW nLastData, bool bSk
             SCROW nAttrSize = mvData[nEndPos].nEndRow + 1 - nAttrStartRow;
             if ( nAttrSize >= SC_VISATTR_STOP )
                 break;  // while, ignore this range and below
-            else if ( mvData[nEndPos].pPattern->IsVisible() )
+            else if ( mvData[nEndPos].getScPatternAttr()->IsVisible() )
             {
                 rLastRow = mvData[nEndPos].nEndRow;
                 bFound = true;
@@ -2013,8 +1975,8 @@ bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, 
SCROW nLastData, bool bSk
     }
     else
     {
-        if ((nPos > 0 && mvData[nPos-1].pPattern->IsVisible())
-                || (nPos > 1 && 
!mvData[nPos-1].pPattern->IsVisibleEqual(*mvData[nPos-2].pPattern)))
+        if ((nPos > 0 && mvData[nPos-1].getScPatternAttr()->IsVisible())
+                || (nPos > 1 && 
!mvData[nPos-1].getScPatternAttr()->IsVisibleEqual(*mvData[nPos-2].getScPatternAttr())))
         {
             rLastRow = mvData[nPos-1].nEndRow;
             return true;
@@ -2027,7 +1989,7 @@ bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, 
SCROW nLastData, bool bSk
 bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
 {
     if ( mvData.empty() )
-        return rDocument.GetDefPattern()->IsVisible();
+        return 
rDocument.getCellAttributeHelper().getDefaultCellAttribute().IsVisible();
 
     SCSIZE nIndex;
     Search( nStartRow, nIndex );
@@ -2035,7 +1997,7 @@ bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, 
SCROW nEndRow ) const
     bool bFound = false;
     while ( nIndex < mvData.size() && nThisStart <= nEndRow && !bFound )
     {
-        if ( mvData[nIndex].pPattern->IsVisible() )
+        if ( mvData[nIndex].getScPatternAttr()->IsVisible() )
             bFound = true;
 
         nThisStart = mvData[nIndex].nEndRow + 1;
@@ -2050,9 +2012,9 @@ bool ScAttrArray::IsVisibleEqual( const ScAttrArray& 
rOther,
 {
     if ( mvData.empty() && rOther.mvData.empty() )
     {
-        const ScPatternAttr* pDefPattern1 = rDocument.GetDefPattern();
-        const ScPatternAttr* pDefPattern2 = rOther.rDocument.GetDefPattern();
-        return ( SfxPoolItem::areSame(pDefPattern1, pDefPattern2) || 
pDefPattern1->IsVisibleEqual( *pDefPattern2 ) );
+        const ScPatternAttr* 
pDefPattern1(&rDocument.getCellAttributeHelper().getDefaultCellAttribute());
+        const ScPatternAttr* 
pDefPattern2(&rOther.rDocument.getCellAttributeHelper().getDefaultCellAttribute());
+        return ( ScPatternAttr::areSame(pDefPattern1, pDefPattern2) || 
pDefPattern1->IsVisibleEqual( *pDefPattern2 ) );
     }
 
     {
@@ -2062,13 +2024,13 @@ bool ScAttrArray::IsVisibleEqual( const ScAttrArray& 
rOther,
         if ( mvData.empty() && !rOther.mvData.empty() )
         {
             pNonDefault = &rOther;
-            pDefPattern = rDocument.GetDefPattern();
+            pDefPattern = 
&rDocument.getCellAttributeHelper().getDefaultCellAttribute();
             bDefNonDefCase = true;
         }
         else if ( !mvData.empty() && rOther.mvData.empty() )
         {
             pNonDefault = this;
-            pDefPattern = rOther.rDocument.GetDefPattern();
+            pDefPattern = 
&rOther.rDocument.getCellAttributeHelper().getDefaultCellAttribute();
             bDefNonDefCase = true;
         }
 
@@ -2081,9 +2043,8 @@ bool ScAttrArray::IsVisibleEqual( const ScAttrArray& 
rOther,
 
             while ( nPos < pNonDefault->Count() && bEqual )
             {
-                const ScPatternAttr* pNonDefPattern = 
pNonDefault->mvData[nPos].pPattern;
-                bEqual = ( SfxPoolItem::areSame(pNonDefPattern, pDefPattern) ||
-                           pNonDefPattern->IsVisibleEqual( *pDefPattern ) );
+                const ScPatternAttr* pNonDefPattern = 
pNonDefault->mvData[nPos].getScPatternAttr();
+                bEqual = ScPatternAttr::areSame(pNonDefPattern, pDefPattern) 
|| pNonDefPattern->IsVisibleEqual( *pDefPattern );
 
                 if ( pNonDefault->mvData[nPos].nEndRow >= nEndRow ) break;
                 ++nPos;
@@ -2105,10 +2066,9 @@ bool ScAttrArray::IsVisibleEqual( const ScAttrArray& 
rOther,
     {
         SCROW nThisRow = mvData[nThisPos].nEndRow;
         SCROW nOtherRow = rOther.mvData[nOtherPos].nEndRow;
-        const ScPatternAttr* pThisPattern = mvData[nThisPos].pPattern;
-        const ScPatternAttr* pOtherPattern = rOther.mvData[nOtherPos].pPattern;
-        bEqual = ( SfxPoolItem::areSame(pThisPattern, pOtherPattern) ||
-                    pThisPattern->IsVisibleEqual(*pOtherPattern) );
+        const ScPatternAttr* pThisPattern = 
mvData[nThisPos].getScPatternAttr();
+        const ScPatternAttr* pOtherPattern = 
rOther.mvData[nOtherPos].getScPatternAttr();
+        bEqual = ( ScPatternAttr::areSame(pThisPattern, pOtherPattern) || 
pThisPattern->IsVisibleEqual(*pOtherPattern) );
 
         if ( nThisRow >= nOtherRow )
         {
@@ -2130,9 +2090,9 @@ bool ScAttrArray::IsAllEqual( const ScAttrArray& rOther, 
SCROW nStartRow, SCROW
     // summarised with IsVisibleEqual
     if ( mvData.empty() && rOther.mvData.empty() )
     {
-        const ScPatternAttr* pDefPattern1 = rDocument.GetDefPattern();
-        const ScPatternAttr* pDefPattern2 = rOther.rDocument.GetDefPattern();
-        return SfxPoolItem::areSame(pDefPattern1, pDefPattern2);
+        const ScPatternAttr* 
pDefPattern1(&rDocument.getCellAttributeHelper().getDefaultCellAttribute());
+        const ScPatternAttr* 
pDefPattern2(&rOther.rDocument.getCellAttributeHelper().getDefaultCellAttribute());
+        return ScPatternAttr::areSame(pDefPattern1, pDefPattern2);
     }
 
     {
@@ -2142,13 +2102,13 @@ bool ScAttrArray::IsAllEqual( const ScAttrArray& 
rOther, SCROW nStartRow, SCROW
         if ( mvData.empty() && !rOther.mvData.empty() )
         {
             pNonDefault = &rOther;
-            pDefPattern = rDocument.GetDefPattern();
+            pDefPattern = 
&rDocument.getCellAttributeHelper().getDefaultCellAttribute();
             bDefNonDefCase = true;
         }
         else if ( !mvData.empty() && rOther.mvData.empty() )
         {
             pNonDefault = this;
-            pDefPattern = rOther.rDocument.GetDefPattern();
+            pDefPattern = 
&rOther.rDocument.getCellAttributeHelper().getDefaultCellAttribute();
             bDefNonDefCase = true;
         }
 
@@ -2161,8 +2121,8 @@ bool ScAttrArray::IsAllEqual( const ScAttrArray& rOther, 
SCROW nStartRow, SCROW
 
             while ( nPos < pNonDefault->Count() && bEqual )
             {
-                const ScPatternAttr* pNonDefPattern = 
pNonDefault->mvData[nPos].pPattern;
-                bEqual = SfxPoolItem::areSame( pNonDefPattern, pDefPattern );
+                const ScPatternAttr* pNonDefPattern = 
pNonDefault->mvData[nPos].getScPatternAttr();
+                bEqual = ScPatternAttr::areSame( pNonDefPattern, pDefPattern );
 
-e 
... etc. - the rest is truncated

Reply via email to