tdf#158317 fix cleanup of SfxPoolItems in editeng

It is not possible to use implCreateItemEntry/implCleanupItemEntry,
that is tooling limited *by purpose* to svl/Item/ItemSet stuff.
But what I can do is to do that SfxPoolItemHolder I already
talked/thought about. It is a helper that can safely hold a
SfxPoolItem in cases where an SfxItemSet is too expensive.
Think about it as a SfxItemSet for a single item. That solves
the problem why DirectPutItemInPool/DirectRemoveItemFromPool
is used in general (each usage is a 'compromize').
Did that now, works well. Editengine is now free of
DirectPutItemInPool/DirectRemoveItemFromPool.

Replaced ::CursorMoved with checkAndDeleteEmptyAttribs since all
these got static with no longer need to DirectRemoveItemFromPool.
Corrected create/delete counters.

Change-Id: Ia6e53f48ac2e479b461546515e68697039b5b628
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159931
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
diff --git a/editeng/inc/editattr.hxx b/editeng/inc/editattr.hxx
index fcc14ba..bb609ac 100644
--- a/editeng/inc/editattr.hxx
+++ b/editeng/inc/editattr.hxx
@@ -25,6 +25,7 @@
#include <tools/color.hxx>
#include <tools/debug.hxx>
#include <tools/fontenum.hxx>
#include <svl/itemset.hxx>

class SvxFont;
class SvxFontItem;
@@ -65,7 +66,7 @@ class SfxGrabBagItem;
// bEdge: Attribute will not expand, if you want to expand just on the edge
class EditCharAttrib
{
    const SfxPoolItem*  pItem;
    SfxPoolItemHolder   maItemHolder;

    sal_Int32               nStart;
    sal_Int32               nEnd;
@@ -73,7 +74,7 @@ class EditCharAttrib
    bool                bEdge       :1;

public:
    EditCharAttrib( const SfxPoolItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttrib(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);
    virtual ~EditCharAttrib();

    EditCharAttrib(const EditCharAttrib&) = delete;
@@ -81,8 +82,9 @@ public:

    void                dumpAsXml(xmlTextWriterPtr pWriter) const;

    sal_uInt16          Which() const   { return pItem->Which(); }
    const SfxPoolItem*  GetItem() const { return pItem; }
    const SfxPoolItemHolder& GetHolder() const {  return maItemHolder; }
    const SfxPoolItem* GetItem() const { return GetHolder().getItem(); }
    sal_uInt16 Which() const { if(GetItem()) return GetItem()->Which(); return 0; }

    sal_Int32&          GetStart()                  { return nStart; }
    sal_Int32&          GetEnd()                    { return nEnd; }
@@ -153,7 +155,7 @@ inline void EditCharAttrib::Collaps( sal_Int32 nDiff )
class EditCharAttribFont final : public EditCharAttrib
{
public:
    EditCharAttribFont( const SvxFontItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribFont(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -163,7 +165,7 @@ public:
class EditCharAttribWeight final : public EditCharAttrib
{
public:
    EditCharAttribWeight( const SvxWeightItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribWeight(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -172,7 +174,7 @@ public:
class EditCharAttribItalic final : public EditCharAttrib
{
public:
    EditCharAttribItalic( const SvxPostureItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribItalic(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -182,7 +184,7 @@ public:
class EditCharAttribShadow final : public EditCharAttrib
{
public:
    EditCharAttribShadow( const SvxShadowedItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribShadow(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -192,7 +194,7 @@ public:
class EditCharAttribEscapement final : public EditCharAttrib
{
public:
    EditCharAttribEscapement( const SvxEscapementItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribEscapement(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -202,7 +204,7 @@ public:
class EditCharAttribOutline final : public EditCharAttrib
{
public:
    EditCharAttribOutline( const SvxContourItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribOutline(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -212,7 +214,7 @@ public:
class EditCharAttribStrikeout final : public EditCharAttrib
{
public:
    EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribStrikeout(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -222,7 +224,7 @@ public:
class EditCharAttribCaseMap final : public EditCharAttrib
{
public:
    EditCharAttribCaseMap( const SvxCaseMapItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribCaseMap(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -232,7 +234,7 @@ public:
class EditCharAttribUnderline final : public EditCharAttrib
{
public:
    EditCharAttribUnderline( const SvxUnderlineItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribUnderline(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -242,7 +244,7 @@ public:
class EditCharAttribOverline final : public EditCharAttrib
{
public:
    EditCharAttribOverline( const SvxOverlineItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribOverline(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -252,7 +254,7 @@ public:
class EditCharAttribEmphasisMark final : public EditCharAttrib
{
public:
    EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribEmphasisMark(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -262,7 +264,7 @@ public:
class EditCharAttribRelief final : public EditCharAttrib
{
public:
    EditCharAttribRelief( const SvxCharReliefItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribRelief(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -272,7 +274,7 @@ public:
class EditCharAttribFontHeight final : public EditCharAttrib
{
public:
    EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribFontHeight(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -282,7 +284,7 @@ public:
class EditCharAttribFontWidth final : public EditCharAttrib
{
public:
    EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribFontWidth(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -292,7 +294,7 @@ public:
class EditCharAttribColor final : public EditCharAttrib
{
public:
    EditCharAttribColor( const SvxColorItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribColor(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -301,9 +303,7 @@ public:
class EditCharAttribBackgroundColor final : public EditCharAttrib
{
public:
    EditCharAttribBackgroundColor(const SvxColorItem& rAttr,
                                  sal_Int32 nStart,
                                  sal_Int32 nEnd );
    EditCharAttribBackgroundColor(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);
    virtual void    SetFont(SvxFont& rFont, OutputDevice* pOutDev) override;
};

@@ -312,7 +312,7 @@ public:
class EditCharAttribLanguage final : public EditCharAttrib
{
public:
    EditCharAttribLanguage( const SvxLanguageItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribLanguage(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -322,7 +322,7 @@ public:
class EditCharAttribTab final : public EditCharAttrib
{
public:
    EditCharAttribTab( const SfxVoidItem& rAttr, sal_Int32 nPos );
    EditCharAttribTab(SfxItemPool&, const SfxPoolItem&, sal_Int32 nPos);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -332,7 +332,7 @@ public:
class EditCharAttribLineBreak final : public EditCharAttrib
{
public:
    EditCharAttribLineBreak( const SfxVoidItem& rAttr, sal_Int32 nPos );
    EditCharAttribLineBreak(SfxItemPool&, const SfxPoolItem&, sal_Int32 nPos);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -349,7 +349,7 @@ class EditCharAttribField final : public EditCharAttrib
    EditCharAttribField& operator = ( const EditCharAttribField& rAttr ) = delete;

public:
    EditCharAttribField( const SvxFieldItem& rAttr, sal_Int32 nPos );
    EditCharAttribField(SfxItemPool&, const SfxPoolItem&, sal_Int32 nPos);
    EditCharAttribField( const EditCharAttribField& rAttr );
    virtual ~EditCharAttribField() override;

@@ -373,7 +373,7 @@ public:
class EditCharAttribPairKerning final : public EditCharAttrib
{
public:
    EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribPairKerning(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -383,7 +383,7 @@ public:
class EditCharAttribKerning final : public EditCharAttrib
{
public:
    EditCharAttribKerning( const SvxKerningItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribKerning(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -393,7 +393,7 @@ public:
class EditCharAttribWordLineMode final : public EditCharAttrib
{
public:
    EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribWordLineMode(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);

    virtual void    SetFont( SvxFont& rFont, OutputDevice* pOutDev ) override;
};
@@ -402,7 +402,7 @@ public:
class EditCharAttribGrabBag final : public EditCharAttrib
{
public:
    EditCharAttribGrabBag( const SfxGrabBagItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    EditCharAttribGrabBag(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd);
};


diff --git a/editeng/inc/editdoc.hxx b/editeng/inc/editdoc.hxx
index e5c3abb..16eaf15 100644
--- a/editeng/inc/editdoc.hxx
+++ b/editeng/inc/editdoc.hxx
@@ -122,7 +122,6 @@ public:
    const SfxItemSet&       GetPrevParaAttribs() const  { return aPrevParaAttribs; }
    const CharAttribsType&  GetPrevCharAttribs() const  { return aPrevCharAttribs; }

    void RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const;
    void AppendCharAttrib(EditCharAttrib* pNew);
};

@@ -196,7 +195,7 @@ public:

    void            dumpAsXml(xmlTextWriterPtr pWriter) const;

    void            DeleteEmptyAttribs(  SfxItemPool& rItemPool );
    void            DeleteEmptyAttribs();

    const EditCharAttrib* FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const;
    EditCharAttrib* FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos );
@@ -206,7 +205,7 @@ public:


    void            ResortAttribs();
    void            OptimizeRanges( SfxItemPool& rItemPool );
    void            OptimizeRanges();

    sal_Int32 Count() const;

@@ -256,8 +255,8 @@ public:
    CharAttribList& GetCharAttribs()        { return aCharAttribList; }
    const CharAttribList& GetCharAttribs() const { return aCharAttribList; }

    void            ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNewChars, SfxItemPool& rItemPool );
    void            CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDelChars, SfxItemPool& rItemPool );
    void            ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNewChars );
    void            CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDelChars );
    void            AppendAttribs( ContentNode* pNextNode );
    void            CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs );

@@ -295,6 +294,8 @@ public:
    OUString Copy(sal_Int32 nPos) const;
    OUString Copy(sal_Int32 nPos, sal_Int32 nCount) const;
    sal_Unicode GetChar(sal_Int32 nPos) const;

    void checkAndDeleteEmptyAttribs() const;
};


@@ -759,9 +760,6 @@ private:
    bool            bModified:1;
    bool            bDisableAttributeExpanding:1;

private:
    void            ImplDestroyContents();

public:
                    EditDoc( SfxItemPool* pItemPool );
                    ~EditDoc();
@@ -812,8 +810,6 @@ public:
    SfxItemPool&        GetItemPool()                   { return *pItemPool; }
    const SfxItemPool&  GetItemPool() const             { return *pItemPool; }

    void RemoveItemsFromPool(const ContentNode& rNode);

    void            InsertAttrib( const SfxPoolItem& rItem, ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd );
    void            InsertAttrib( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem );
    void            InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem );
diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx
index d1d79fd..75bbcab 100644
--- a/editeng/source/editeng/editattr.cxx
+++ b/editeng/source/editeng/editattr.cxx
@@ -46,14 +46,15 @@
#include <editattr.hxx>



EditCharAttrib::EditCharAttrib( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) :
    nStart(nS), nEnd(nE), bFeature(false), bEdge(false)
EditCharAttrib::EditCharAttrib(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE )
: maItemHolder(rPool, &rItem)
, nStart(nS)
, nEnd(nE)
, bFeature(false)
, bEdge(false)
{
    pItem = &rAttr;

    assert((rAttr.Which() >= EE_ITEMS_START) && (rAttr.Which() <= EE_ITEMS_END));
    assert((rAttr.Which() < EE_FEATURE_START) || (rAttr.Which() > EE_FEATURE_END) || (nE == (nS+1)));
    assert((rItem.Which() >= EE_ITEMS_START) && (rItem.Which() <= EE_ITEMS_END));
    assert((rItem.Which() < EE_FEATURE_START) || (rItem.Which() > EE_FEATURE_END) || (nE == (nS+1)));
}

EditCharAttrib::~EditCharAttrib()
@@ -71,16 +72,16 @@ void EditCharAttrib::dumpAsXml(xmlTextWriterPtr pWriter) const
    pWriter, BAD_CAST("nStart"), "%" SAL_PRIdINT32, nStart);
    (void)xmlTextWriterWriteFormatAttribute(
    pWriter, BAD_CAST("nEnd"), "%" SAL_PRIdINT32, nEnd);
    pItem->dumpAsXml(pWriter);
    GetItem()->dumpAsXml(pWriter);
    (void)xmlTextWriterEndElement(pWriter);
}



EditCharAttribFont::EditCharAttribFont( const SvxFontItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribFont::EditCharAttribFont(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_FONTINFO || rAttr.Which() == EE_CHAR_FONTINFO_CJK || rAttr.Which() == EE_CHAR_FONTINFO_CTL);
    assert(rItem.Which() == EE_CHAR_FONTINFO || rItem.Which() == EE_CHAR_FONTINFO_CJK || rItem.Which() == EE_CHAR_FONTINFO_CTL);
}

void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* )
@@ -95,10 +96,10 @@ void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribItalic::EditCharAttribItalic( const SvxPostureItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribItalic::EditCharAttribItalic(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_ITALIC || rAttr.Which() == EE_CHAR_ITALIC_CJK || rAttr.Which() == EE_CHAR_ITALIC_CTL);
    assert(rItem.Which() == EE_CHAR_ITALIC || rItem.Which() == EE_CHAR_ITALIC_CJK || rItem.Which() == EE_CHAR_ITALIC_CTL);
}

void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* )
@@ -108,10 +109,10 @@ void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribWeight::EditCharAttribWeight( const SvxWeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribWeight::EditCharAttribWeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_WEIGHT || rAttr.Which() == EE_CHAR_WEIGHT_CJK || rAttr.Which() == EE_CHAR_WEIGHT_CTL);
    assert(rItem.Which() == EE_CHAR_WEIGHT || rItem.Which() == EE_CHAR_WEIGHT_CJK || rItem.Which() == EE_CHAR_WEIGHT_CTL);
}

void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* )
@@ -121,10 +122,10 @@ void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribUnderline::EditCharAttribUnderline( const SvxUnderlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribUnderline::EditCharAttribUnderline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_UNDERLINE);
    assert(rItem.Which() == EE_CHAR_UNDERLINE);
}

void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )
@@ -138,10 +139,10 @@ void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )



EditCharAttribOverline::EditCharAttribOverline( const SvxOverlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribOverline::EditCharAttribOverline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_OVERLINE);
    assert(rItem.Which() == EE_CHAR_OVERLINE);
}

void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )
@@ -153,10 +154,10 @@ void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )



EditCharAttribFontHeight::EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribFontHeight::EditCharAttribFontHeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_FONTHEIGHT || rAttr.Which() == EE_CHAR_FONTHEIGHT_CJK || rAttr.Which() == EE_CHAR_FONTHEIGHT_CTL);
    assert(rItem.Which() == EE_CHAR_FONTHEIGHT || rItem.Which() == EE_CHAR_FONTHEIGHT_CJK || rItem.Which() == EE_CHAR_FONTHEIGHT_CTL);
}

void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* )
@@ -167,10 +168,10 @@ void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribFontWidth::EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribFontWidth::EditCharAttribFontWidth(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_FONTWIDTH);
    assert(rItem.Which() == EE_CHAR_FONTWIDTH);
}

void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* )
@@ -180,10 +181,10 @@ void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* )



EditCharAttribStrikeout::EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribStrikeout::EditCharAttribStrikeout(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_STRIKEOUT);
    assert(rItem.Which() == EE_CHAR_STRIKEOUT);
}

void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* )
@@ -193,10 +194,10 @@ void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribCaseMap::EditCharAttribCaseMap( const SvxCaseMapItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribCaseMap::EditCharAttribCaseMap(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_CASEMAP);
    assert(rItem.Which() == EE_CHAR_CASEMAP);
}

void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* )
@@ -206,10 +207,10 @@ void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribColor::EditCharAttribColor( const SvxColorItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribColor::EditCharAttribColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_COLOR);
    assert(rItem.Which() == EE_CHAR_COLOR);
}

void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* )
@@ -219,13 +220,10 @@ void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* )
}


EditCharAttribBackgroundColor::EditCharAttribBackgroundColor(
                                const SvxColorItem& rAttr,
                                  sal_Int32 _nStart,
                                  sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribBackgroundColor::EditCharAttribBackgroundColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_BKGCOLOR);
    assert(rItem.Which() == EE_CHAR_BKGCOLOR);
}

void EditCharAttribBackgroundColor::SetFont( SvxFont& rFont, OutputDevice* )
@@ -235,10 +233,10 @@ void EditCharAttribBackgroundColor::SetFont( SvxFont& rFont, OutputDevice* )
    rFont.SetFillColor(aColor);
}

EditCharAttribLanguage::EditCharAttribLanguage( const SvxLanguageItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribLanguage::EditCharAttribLanguage(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert((rAttr.Which() == EE_CHAR_LANGUAGE) || (rAttr.Which() == EE_CHAR_LANGUAGE_CJK) || (rAttr.Which() == EE_CHAR_LANGUAGE_CTL));
    assert((rItem.Which() == EE_CHAR_LANGUAGE) || (rItem.Which() == EE_CHAR_LANGUAGE_CJK) || (rItem.Which() == EE_CHAR_LANGUAGE_CTL));
}

void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* )
@@ -248,10 +246,10 @@ void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribShadow::EditCharAttribShadow( const SvxShadowedItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribShadow::EditCharAttribShadow(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_SHADOW);
    assert(rItem.Which() == EE_CHAR_SHADOW);
}

void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* )
@@ -261,10 +259,10 @@ void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribEscapement::EditCharAttribEscapement( const SvxEscapementItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribEscapement::EditCharAttribEscapement(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_ESCAPEMENT);
    assert(rItem.Which() == EE_CHAR_ESCAPEMENT);
}

void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev )
@@ -278,10 +276,10 @@ void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev )



EditCharAttribOutline::EditCharAttribOutline( const SvxContourItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribOutline::EditCharAttribOutline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_OUTLINE);
    assert(rItem.Which() == EE_CHAR_OUTLINE);
}

void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* )
@@ -291,8 +289,8 @@ void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribTab::EditCharAttribTab( const SfxVoidItem& rAttr, sal_Int32 nPos )
    : EditCharAttrib( rAttr, nPos, nPos+1 )
EditCharAttribTab::EditCharAttribTab(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos)
: EditCharAttrib(rPool, rItem, nPos, nPos+1)
{
    SetFeature( true );
}
@@ -303,8 +301,8 @@ void EditCharAttribTab::SetFont( SvxFont&, OutputDevice* )



EditCharAttribLineBreak::EditCharAttribLineBreak( const SfxVoidItem& rAttr, sal_Int32 nPos )
    : EditCharAttrib( rAttr, nPos, nPos+1 )
EditCharAttribLineBreak::EditCharAttribLineBreak(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos)
: EditCharAttrib(rPool, rItem, nPos, nPos+1)
{
    SetFeature( true );
}
@@ -315,8 +313,8 @@ void EditCharAttribLineBreak::SetFont( SvxFont&, OutputDevice* )



EditCharAttribField::EditCharAttribField( const SvxFieldItem& rAttr, sal_Int32 nPos )
    : EditCharAttrib( rAttr, nPos, nPos+1 )
EditCharAttribField::EditCharAttribField(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos)
: EditCharAttrib(rPool, rItem, nPos, nPos+1)
{
    SetFeature( true ); // !!!
}
@@ -348,9 +346,9 @@ void EditCharAttribField::Reset()
    mxFldLineStyle.reset();
}

EditCharAttribField::EditCharAttribField( const EditCharAttribField& rAttr )
    : EditCharAttrib( *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd() ),
        aFieldValue( rAttr.aFieldValue )
EditCharAttribField::EditCharAttribField(const EditCharAttribField& rAttr)
: EditCharAttrib(rAttr.GetHolder().getPool(), *rAttr.GetHolder().getItem(), rAttr.GetStart(), rAttr.GetEnd())
, aFieldValue( rAttr.aFieldValue )
{
    // Use this constructor only for temporary Objects, Item is not pooled.
    mxTxtColor = rAttr.mxTxtColor;
@@ -388,10 +386,10 @@ bool EditCharAttribField::operator == ( const EditCharAttribField& rAttr ) const



EditCharAttribPairKerning::EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
: EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribPairKerning::EditCharAttribPairKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_PAIRKERNING);
    assert(rItem.Which() == EE_CHAR_PAIRKERNING);
}

void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* )
@@ -401,10 +399,10 @@ void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribKerning::EditCharAttribKerning( const SvxKerningItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
: EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribKerning::EditCharAttribKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_KERNING);
    assert(rItem.Which() == EE_CHAR_KERNING);
}

void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* )
@@ -414,10 +412,10 @@ void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribWordLineMode::EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
: EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribWordLineMode::EditCharAttribWordLineMode(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_WLM);
    assert(rItem.Which() == EE_CHAR_WLM);
}

void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* )
@@ -427,10 +425,10 @@ void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribEmphasisMark::EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribEmphasisMark::EditCharAttribEmphasisMark(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_EMPHASISMARK);
    assert(rItem.Which() == EE_CHAR_EMPHASISMARK);
}

void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* )
@@ -440,10 +438,10 @@ void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* )



EditCharAttribRelief::EditCharAttribRelief( const SvxCharReliefItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribRelief::EditCharAttribRelief(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_RELIEF);
    assert(rItem.Which() == EE_CHAR_RELIEF);
}

void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* )
@@ -452,10 +450,10 @@ void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* )
}


EditCharAttribGrabBag::EditCharAttribGrabBag( const SfxGrabBagItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd )
    : EditCharAttrib( rAttr, _nStart, _nEnd )
EditCharAttribGrabBag::EditCharAttribGrabBag(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd)
: EditCharAttrib(rPool, rItem, _nStart, _nEnd)
{
    assert(rAttr.Which() == EE_CHAR_GRABBAG);
    assert(rItem.Which() == EE_CHAR_GRABBAG);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx
index 7a5d70b..d892bd1 100644
--- a/editeng/source/editeng/editdoc.cxx
+++ b/editeng/source/editeng/editdoc.cxx
@@ -222,152 +222,149 @@ const SfxItemInfo aItemInfos[EDITITEMCOUNT] =
EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE )
{
    // Create a new attribute in the pool
    const SfxPoolItem& rNew = rPool.DirectPutItemInPool( rAttr );

    EditCharAttrib* pNew = nullptr;
    switch( rNew.Which() )
    switch( rAttr.Which() )
    {
        case EE_CHAR_LANGUAGE:
        case EE_CHAR_LANGUAGE_CJK:
        case EE_CHAR_LANGUAGE_CTL:
        {
            pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE );
            return new EditCharAttribLanguage(rPool, rAttr, nS, nE);
        }
        break;
        case EE_CHAR_COLOR:
        {
            pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE );
            return new EditCharAttribColor(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_FONTINFO:
        case EE_CHAR_FONTINFO_CJK:
        case EE_CHAR_FONTINFO_CTL:
        {
            pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE );
            return new EditCharAttribFont(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_FONTHEIGHT:
        case EE_CHAR_FONTHEIGHT_CJK:
        case EE_CHAR_FONTHEIGHT_CTL:
        {
            pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE );
            return new EditCharAttribFontHeight(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_FONTWIDTH:
        {
            pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE );
            return new EditCharAttribFontWidth(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_WEIGHT:
        case EE_CHAR_WEIGHT_CJK:
        case EE_CHAR_WEIGHT_CTL:
        {
            pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE );
            return new EditCharAttribWeight(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_UNDERLINE:
        {
            pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE );
            return new EditCharAttribUnderline(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_OVERLINE:
        {
            pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE );
            return new EditCharAttribOverline(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_EMPHASISMARK:
        {
            pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE );
            return new EditCharAttribEmphasisMark(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_RELIEF:
        {
            pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE );
            return new EditCharAttribRelief(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_STRIKEOUT:
        {
            pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE );
            return new EditCharAttribStrikeout(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_ITALIC:
        case EE_CHAR_ITALIC_CJK:
        case EE_CHAR_ITALIC_CTL:
        {
            pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE );
            return new EditCharAttribItalic(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_OUTLINE:
        {
            pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE );
            return new EditCharAttribOutline(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_SHADOW:
        {
            pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE );
            return new EditCharAttribShadow(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_ESCAPEMENT:
        {
            pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE );
            return new EditCharAttribEscapement(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_PAIRKERNING:
        {
            pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE );
            return new EditCharAttribPairKerning(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_KERNING:
        {
            pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE );
            return new EditCharAttribKerning(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_WLM:
        {
            pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE );
            return new EditCharAttribWordLineMode(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_XMLATTRIBS:
        {
            pNew = new EditCharAttrib( rNew, nS, nE );  // Attribute is only for holding XML information...
            return new EditCharAttrib(rPool, rAttr, nS, nE);  // Attribute is only for holding XML information...
        }
        break;
        case EE_CHAR_CASEMAP:
        {
            pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE );
            return new EditCharAttribCaseMap(rPool, rAttr, nS, nE );
        }
        break;
        case EE_CHAR_GRABBAG:
        {
            pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE );
            return new EditCharAttribGrabBag(rPool, rAttr, nS, nE );
        }
        break;
        case EE_FEATURE_TAB:
        {
            pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS );
            return new EditCharAttribTab(rPool, rAttr, nS );
        }
        break;
        case EE_FEATURE_LINEBR:
        {
            pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS );
            return new EditCharAttribLineBreak(rPool, rAttr, nS );
        }
        break;
        case EE_FEATURE_FIELD:
        {
            pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS );
            return new EditCharAttribField(rPool, rAttr, nS );
        }
        break;
        case EE_CHAR_BKGCOLOR:
        {
            pNew = new EditCharAttribBackgroundColor( static_cast<const SvxColorItem&>(rNew), nS, nE );
            return new EditCharAttribBackgroundColor(rPool, rAttr, nS, nE );
        }
        break;
        default:
        {
            OSL_FAIL( "Invalid Attribute!" );
        }
        break;
    }
    return pNew;

    OSL_FAIL( "Invalid Attribute!" );
    return nullptr;
}

TextPortionList::TextPortionList()
@@ -812,12 +809,6 @@ ContentAttribsInfo::ContentAttribsInfo( SfxItemSet aParaAttribs ) :
{
}

void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const
{
    for (const std::unique_ptr<EditCharAttrib>& rAttrib : aPrevCharAttribs)
        rPool.DirectRemoveItemFromPool(*rAttrib->GetItem());
}

void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew)
{
    aPrevCharAttribs.push_back(std::unique_ptr<EditCharAttrib>(pNew));
@@ -1212,7 +1203,7 @@ ContentNode::~ContentNode()
{
}

void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool )
void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew )
{
    if ( !nNew )
        return;
@@ -1330,7 +1321,6 @@ void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& 
        {
            OSL_FAIL( "Empty Attribute after ExpandAttribs?" );
            bResort = true;
            rItemPool.DirectRemoveItemFromPool( *pAttrib->GetItem() );
            rAttribs.erase(rAttribs.begin()+nAttr);
        }
        else
@@ -1354,7 +1344,7 @@ void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& 
#endif
}

void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool )
void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted )
{
    if ( !nDeleted )
        return;
@@ -1426,7 +1416,6 @@ void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItem
        if ( bDelAttr )
        {
            bResort = true;
            rItemPool.DirectRemoveItemFromPool( *pAttrib->GetItem() );
            rAttribs.erase(rAttribs.begin()+nAttr);
        }
        else
@@ -1813,6 +1802,14 @@ void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const
    (void)xmlTextWriterEndElement(pWriter);
}

void ContentNode::checkAndDeleteEmptyAttribs() const
{
    // Delete empty attributes, but only if paragraph is not empty!
    if (GetCharAttribs().HasEmptyAttribs() && Len())
    {
        const_cast<ContentNode*>(this)->GetCharAttribs().DeleteEmptyAttribs();
    }
}

ContentAttribs::ContentAttribs( SfxItemPool& rPool )
: pStyle(nullptr)
@@ -1934,47 +1931,9 @@ EditDoc::EditDoc( SfxItemPool* pPool ) :

EditDoc::~EditDoc()
{
    ImplDestroyContents();
}

namespace {

class RemoveEachItemFromPool
{
    EditDoc& mrDoc;
public:
    explicit RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {}
    void operator() (const std::unique_ptr<ContentNode>& rNode)
    {
        mrDoc.RemoveItemsFromPool(*rNode);
    }
};

struct ClearSpellErrorsHandler
{
    void operator() (std::unique_ptr<ContentNode> const & rNode)
    {
        rNode->DestroyWrongList();
    }
};

}

void EditDoc::ImplDestroyContents()
{
    std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this));
    maContents.clear();
}

void EditDoc::RemoveItemsFromPool(const ContentNode& rNode)
{
    for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr)
    {
        const EditCharAttrib& rAttr = *rNode.GetCharAttribs().GetAttribs()[nAttr];
        GetItemPool().DirectRemoveItemFromPool(*rAttr.GetItem());
    }
}

void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType )
{
    vcl::Font aPrevFont( rFont );
@@ -2223,7 +2182,7 @@ sal_Int32 EditDoc::GetTextLen() const

EditPaM EditDoc::Clear()
{
    ImplDestroyContents();
    maContents.clear();

    ContentNode* pNode = new ContentNode( GetItemPool() );
    Insert(0, pNode);
@@ -2235,6 +2194,17 @@ EditPaM EditDoc::Clear()
    return EditPaM( pNode, 0 );
}

namespace
{
struct ClearSpellErrorsHandler
{
    void operator() (std::unique_ptr<ContentNode> const & rNode)
    {
        rNode->DestroyWrongList();
    }
};
}

void EditDoc::ClearSpellErrors()
{
    std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler());
@@ -2257,7 +2227,7 @@ EditPaM EditDoc::RemoveText()
    SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
    vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );

    ImplDestroyContents();
    maContents.clear();

    ContentNode* pNode = new ContentNode( GetItemPool() );
    Insert(0, pNode);
@@ -2279,7 +2249,7 @@ EditPaM EditDoc::InsertText( EditPaM aPaM, std::u16string_view rStr )
    assert(aPaM.GetNode());

    aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
    aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size(), GetItemPool() );
    aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size() );
    aPaM.SetIndex( aPaM.GetIndex() + rStr.size() );

    SetModified( true );
@@ -2334,7 +2304,7 @@ EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem  )
    assert(aPaM.GetNode());

    aPaM.GetNode()->Insert( rtl::OUStringChar(CH_FEATURE), aPaM.GetIndex() );
    aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
    aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1 );

    // Create a feature-attribute for the feature...
    EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
@@ -2357,7 +2327,6 @@ EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
    pLeft->Append(pRight->GetString());

    // the one to the right disappears.
    RemoveItemsFromPool(*pRight);
    sal_Int32 nRight = GetPos( pRight );
    Remove( nRight );

@@ -2370,7 +2339,7 @@ void EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars )
{
    // Maybe remove Features!
    aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
    aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
    aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars );

    SetModified( true );
}
@@ -2405,7 +2374,6 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal
    {
        // Will become a large Attribute.
        pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
        GetItemPool().DirectRemoveItemFromPool( *(pStartingAttrib->GetItem()) );
        pNode->GetCharAttribs().Remove(pStartingAttrib);
    }
    else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
@@ -2527,7 +2495,6 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn
        {
            DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" );
            DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
            GetItemPool().DirectRemoveItemFromPool( *pAttr->GetItem() );
            rAttribs.erase(rAttribs.begin()+nAttr);
        }
        else
@@ -2808,7 +2775,7 @@ void CharAttribList::ResortAttribs()
#endif
}

void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
void CharAttribList::OptimizeRanges()
{
#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
    CharAttribList::DbgCheckAttribs(*this);
@@ -2824,7 +2791,6 @@ void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
                if (*rNext.GetItem() == *rAttr.GetItem())
                {
                    rAttr.GetEnd() = rNext.GetEnd();
                    rItemPool.DirectRemoveItemFromPool(*rNext.GetItem());
                    aAttribs.erase(aAttribs.begin()+nNext);
                }
                break;  // only 1 attr with same which can start here.
@@ -2990,25 +2956,8 @@ const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const
    return it == aAttribs.end() ? nullptr : it->get();
}

namespace {

class RemoveEmptyAttrItem
void CharAttribList::DeleteEmptyAttribs()
{
    SfxItemPool& mrItemPool;
public:
    explicit RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {}
    void operator() (const std::unique_ptr<EditCharAttrib>& r)
    {
        if (r->IsEmpty())
            mrItemPool.DirectRemoveItemFromPool(*r->GetItem());
    }
};

}

void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
{
    std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool));
    std::erase_if(aAttribs, [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } );
    bHasEmptyAttribs = false;
}
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index d27a386..4dbb93c 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -678,11 +678,6 @@ ESelection EditEngine::GetWord( const ESelection& rSelection, sal_uInt16 nWordTy
    return pE->pImpEditEngine->CreateESel( aSel );
}

void EditEngine::CursorMoved(const ContentNode* pPrevNode)
{
    pImpEditEngine->CursorMoved(pPrevNode);
}

void EditEngine::CheckIdleFormatter()
{
    pImpEditEngine->CheckIdleFormatter();
diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx
index ba3aac6..762cac1 100644
--- a/editeng/source/editeng/editobj.cxx
+++ b/editeng/source/editeng/editobj.cxx
@@ -44,30 +44,22 @@ using std::endl;
using namespace com::sun::star;


static XEditAttribute MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd )
{
    // Create the new attribute in the pool
    const SfxPoolItem& rNew = rPool.DirectPutItemInPool( rItem );

    return XEditAttribute( rNew, nStart, nEnd );
}

XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE )
    : pItem(&rAttr)
    , nStart(nS)
    , nEnd(nE)
XEditAttribute::XEditAttribute(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE)
: maItemHolder(rPool, &rItem)
, nStart(nS)
, nEnd(nE)
{
}

bool XEditAttribute::IsFeature() const
{
    sal_uInt16 nWhich = pItem->Which();
    sal_uInt16 nWhich = GetItem()->Which();
    return  ((nWhich >= EE_FEATURE_START) && (nWhich <=  EE_FEATURE_END));
}

void XEditAttribute::SetItem(const SfxPoolItem& rNew)
void XEditAttribute::SetItem(SfxItemPool& rPool, const SfxPoolItem& rItem)
{
    pItem = &rNew;
    maItemHolder = SfxPoolItemHolder(rPool, &rItem);
}

XParaPortionList::XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW,
@@ -110,9 +102,7 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse 

    for (const XEditAttribute & rAttr : rCopyFrom.maCharAttribs)
    {
        XEditAttribute aMyAttr = MakeXEditAttribute(
            rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
        maCharAttribs.push_back(aMyAttr);
        maCharAttribs.emplace_back(rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
    }

    if ( rCopyFrom.GetWrongList() )
@@ -121,8 +111,6 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse 

ContentInfo::~ContentInfo()
{
    for (auto const& charAttrib : maCharAttribs)
        aParaAttribs.GetPool()->DirectRemoveItemFromPool(*charAttrib.GetItem());
    maCharAttribs.clear();
}

@@ -376,15 +364,9 @@ TextRotation EditTextObjectImpl::GetRotation() const

XEditAttribute EditTextObjectImpl::CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd )
{
    return MakeXEditAttribute( *mpPool, rItem, nStart, nEnd );
    return XEditAttribute(*mpPool, rItem, nStart, nEnd);
}

void EditTextObjectImpl::DestroyAttrib( const XEditAttribute& rAttr )
{
    mpPool->DirectRemoveItemFromPool( *rAttr.GetItem() );
}


ContentInfo* EditTextObjectImpl::CreateAndInsertContent()
{
    maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*mpPool)));
@@ -540,7 +522,6 @@ bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich )
            XEditAttribute& rAttr = rC.maCharAttribs[--nAttr];
            if ( !_nWhich || (rAttr.GetItem()->Which() == _nWhich) )
            {
                mpPool->DirectRemoveItemFromPool(*rAttr.GetItem());
                rC.maCharAttribs.erase(rC.maCharAttribs.begin()+nAttr);
                bChanged = true;
            }
diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx
index 8a71474..fd1f143 100644
--- a/editeng/source/editeng/editobj2.hxx
+++ b/editeng/source/editeng/editobj2.hxx
@@ -47,14 +47,14 @@ class SharedStringPool;
class XEditAttribute
{
private:
    const SfxPoolItem*  pItem;
    SfxPoolItemHolder   maItemHolder;
    sal_Int32           nStart;
    sal_Int32           nEnd;

public:
    XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd );
    XEditAttribute(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd );

    const SfxPoolItem*      GetItem() const             { return pItem; }
    const SfxPoolItem*      GetItem() const             { return maItemHolder.getItem(); }

    sal_Int32&              GetStart()                  { return nStart; }
    sal_Int32&              GetEnd()                    { return nEnd; }
@@ -65,7 +65,7 @@ public:
    sal_Int32               GetLen() const              { return nEnd-nStart; }

    bool IsFeature() const;
    void SetItem(const SfxPoolItem& rNew);
    void SetItem(SfxItemPool&, const SfxPoolItem&);

    inline bool operator==( const XEditAttribute& rCompare ) const;
};
@@ -74,7 +74,7 @@ inline bool XEditAttribute::operator==( const XEditAttribute& rCompare ) const
{
    return  (nStart == rCompare.nStart) &&
            (nEnd == rCompare.nEnd) &&
            SfxPoolItem::areSame(pItem, rCompare.pItem);
            SfxPoolItem::areSame(GetItem(), rCompare.GetItem());
}

struct XParaPortion
@@ -214,7 +214,6 @@ public:

    ContentInfo*            CreateAndInsertContent();
    XEditAttribute CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd );
    void                    DestroyAttrib( const XEditAttribute& rAttr );

    ContentInfosType&       GetContents() { return maContents;}
    const ContentInfosType& GetContents() const { return maContents;}
diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx
index d957da2..5854d16 100644
--- a/editeng/source/editeng/editundo.cxx
+++ b/editeng/source/editeng/editundo.cxx
@@ -514,26 +514,8 @@ EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel,
{
}

namespace {

struct RemoveAttribsFromPool
{
    SfxItemPool& mrPool;
public:
    explicit RemoveAttribsFromPool(SfxItemPool& rPool) : mrPool(rPool) {}
    void operator() (std::unique_ptr<ContentAttribsInfo> const & rInfo)
    {
        rInfo->RemoveAllCharAttribsFromPool(mrPool);
    }
};

}

EditUndoSetAttribs::~EditUndoSetAttribs()
{
    // Get Items from Pool...
    SfxItemPool* pPool = aNewAttribs.GetPool();
    std::for_each(aPrevAttribs.begin(), aPrevAttribs.end(), RemoveAttribsFromPool(*pPool));
}

void EditUndoSetAttribs::Undo()
@@ -620,7 +602,7 @@ void EditUndoTransliteration::Undo()
    EditSelection aDelSel( aSel );
    aSel = pEE->InsertParaBreak( aSel );
    aDelSel.Max() = aSel.Min();
    aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs( pEE->GetEditDoc().GetItemPool() );
    aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs();
    EditSelection aNewSel;
    if ( pTxtObj )
    {
diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index df9f193..77dab94 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -261,8 +261,9 @@ void EditView::SetSelection( const ESelection& rESel )
    {
        // tdf#113591 Get node from EditDoc, as the selection might have a pointer to an
        // already deleted node.
        const ContentNode* pNode = pImpEditView->pEditEngine->GetEditDoc().GetEndPaM().GetNode();
        pImpEditView->pEditEngine->CursorMoved( pNode );
        const ContentNode* pNode(pImpEditView->pEditEngine->GetEditDoc().GetEndPaM().GetNode());
        if (nullptr != pNode)
            pNode->checkAndDeleteEmptyAttribs();
    }
    EditSelection aNewSelection( pImpEditView->pEditEngine->pImpEditEngine->ConvertSelection(
                                            rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos ) );
@@ -1719,7 +1720,12 @@ void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool 
        aSelection.Min() = aPaM;

    if (pImpEditView->GetEditSelection().Min() != aSelection.Min())
        pImpEditView->pEditEngine->CursorMoved(pImpEditView->GetEditSelection().Min().GetNode());
    {
        const ContentNode* pNode(pImpEditView->GetEditSelection().Min().GetNode());
        if (nullptr != pNode)
            pNode->checkAndDeleteEmptyAttribs();
    }

    pImpEditView->DrawSelectionXOR(aSelection);
    if (pImpEditView->GetEditSelection() != aSelection)
        pImpEditView->SetEditSelection(aSelection);
diff --git a/editeng/source/editeng/fieldupdater.cxx b/editeng/source/editeng/fieldupdater.cxx
index 008793a..05eca45 100644
--- a/editeng/source/editeng/fieldupdater.cxx
+++ b/editeng/source/editeng/fieldupdater.cxx
@@ -47,7 +47,7 @@ public:
                // Create a new table field with the new ID, and set it to the
                // attribute object.
                SvxFieldItem aNewItem(SvxTableField(nTab), EE_FEATURE_FIELD);
                rAttr.SetItem(pPool->DirectPutItemInPool(aNewItem));
                rAttr.SetItem(*pPool, aNewItem);
            }
        }
    }
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index 851e63c..92fb5af 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -2156,7 +2156,11 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel )
    if (!pEditEngine->GetSelectionEngine().HasAnchor())
    {
        if ( aNewEditSelection.Min() != aPaM )
            pEditEngine->CursorMoved(aNewEditSelection.Min().GetNode());
        {
            const ContentNode* pNode(aNewEditSelection.Min().GetNode());
            if (nullptr != pNode)
                pNode->checkAndDeleteEmptyAttribs();
        }
        aNewEditSelection.Min() = aPaM;
    }
    else
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index d20ed8a..e4352f2 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -617,7 +617,6 @@ private:
    // Methods...


    void                CursorMoved( const ContentNode* pPrevNode );
    void                ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreUndoCheck = false );
    void                TextModified();
    void                CalcHeight( ParaPortion* pPortion );
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index 15f6078..4b8f0a6 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -758,15 +758,6 @@ const SfxItemSet& ImpEditEngine::GetEmptyItemSet() const

//  MISC

void ImpEditEngine::CursorMoved( const ContentNode* pPrevNode )
{
    // Delete empty attributes, but only if paragraph is not empty!
    if (pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len())
    {
        const_cast<ContentNode*>(pPrevNode)->GetCharAttribs().DeleteEmptyAttribs(maEditDoc.GetItemPool());
    }
}

void ImpEditEngine::TextModified()
{
    mbFormatted = false;
@@ -949,9 +940,9 @@ EditSelection const & ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, Edit
                            break;
    }

    if ( aOldPaM != aPaM )
    if ( aOldPaM != aPaM && nullptr != aOldPaM.GetNode() )
    {
        CursorMoved( aOldPaM.GetNode() );
        aOldPaM.GetNode()->checkAndDeleteEmptyAttribs();
    }

    // May cause, a CreateAnchor or deselection all
@@ -2454,8 +2445,10 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
    EditPaM aStartPaM(aCurSel.Min());
    EditPaM aEndPaM(aCurSel.Max());

    CursorMoved( aStartPaM.GetNode() ); // only so that newly set Attributes disappear...
    CursorMoved( aEndPaM.GetNode() );   // only so that newly set Attributes disappear...
    if( nullptr != aStartPaM.GetNode() )
        aStartPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear...
    if( nullptr != aEndPaM.GetNode() )
        aEndPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear...

    OSL_ENSURE( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" );
    OSL_ENSURE( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" );
@@ -2532,7 +2525,6 @@ void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara )
        InsertUndo(std::make_unique<EditUndoDelContent>(pEditEngine, pNode, nPara));
    else
    {
        maEditDoc.RemoveItemsFromPool(*pNode);
        if ( pNode->GetStyleSheet() )
            EndListening( *pNode->GetStyleSheet() );
        delete pNode;
@@ -2979,7 +2971,9 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib
    if ( IsCallParaInsertedOrDeleted() )
        GetEditEnginePtr()->ParagraphInserted( nPos+1 );

    CursorMoved( rPaM.GetNode() );  // if empty Attributes have emerged.
    if( nullptr != rPaM.GetNode() )
        rPaM.GetNode()->checkAndDeleteEmptyAttribs(); // if empty Attributes have emerged.

    TextModified();
    return aPaM;
}
diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx
index d6e31e7..57b3d65 100644
--- a/editeng/source/editeng/impedit4.cxx
+++ b/editeng/source/editeng/impedit4.cxx
@@ -1095,9 +1095,7 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a
                        aX.GetEnd() = nEndPos-nStartPos;
                }
                DBG_ASSERT( aX.GetEnd() <= (nEndPos-nStartPos), "CreateTextObject: Attribute too long!" );
                if ( !aX.GetLen() && !bEmptyPara )
                    pTxtObj->DestroyAttrib(aX);
                else
                if ( aX.GetLen() || bEmptyPara )
                    rCAttriblist.push_back(std::move(aX));
            }
            nAttr++;
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
index abe351d..0f5af2f 100644
--- a/editeng/source/editeng/impedit5.cxx
+++ b/editeng/source/editeng/impedit5.cxx
@@ -429,8 +429,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int
        if ( nFlags & GetAttribsFlags::CHARATTRIBS )
        {
            // Make testing easier...
            const SfxItemPool& rPool = GetEditDoc().GetItemPool();
            pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool));
            pNode->GetCharAttribs().OptimizeRanges();

            const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
            for (const auto & nAttr : rAttrs)
@@ -756,7 +755,7 @@ void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& 

void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
{
    pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
    pNode->GetCharAttribs().DeleteEmptyAttribs();
    sal_Int32 nEndPos = pNode->Len();
    for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
    {
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index b3bbcbd..57e3274 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -166,7 +166,6 @@ private:
                       EditEngine&     operator=( const EditEngine& ) = delete;
    EDITENG_DLLPRIVATE bool            PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pView, vcl::Window const * pFrameWin );

    EDITENG_DLLPRIVATE void CursorMoved(const ContentNode* pPrevNode);
    EDITENG_DLLPRIVATE void CheckIdleFormatter();
    EDITENG_DLLPRIVATE bool IsIdleFormatterActive() const;
    EDITENG_DLLPRIVATE ParaPortion* FindParaPortion(ContentNode const * pNode);
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 998830c..60f028a 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -34,12 +34,30 @@ class SfxItemPool;
#ifdef DBG_UTIL
SVL_DLLPUBLIC size_t getAllocatedSfxItemSetCount();
SVL_DLLPUBLIC size_t getUsedSfxItemSetCount();
SVL_DLLPUBLIC size_t getAllocatedSfxPoolItemHolderCount();
SVL_DLLPUBLIC size_t getUsedSfxPoolItemHolderCount();
#endif

// ItemSet/ItemPool helpers
SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource, sal_uInt16 nWhich, bool bPassingOwnership);
void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource);

class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxPoolItemHolder
{
    SfxItemPool*            m_pPool;
    const SfxPoolItem*      m_pItem;
public:
    SfxPoolItemHolder(SfxItemPool&, const SfxPoolItem* = nullptr);
    SfxPoolItemHolder(const SfxPoolItemHolder&);
    ~SfxPoolItemHolder();

    const SfxPoolItemHolder& operator=(const SfxPoolItemHolder&);
    bool operator==(const SfxPoolItemHolder &) const;
    SfxItemPool& getPool() const { return *m_pPool; }
    const SfxPoolItem* getItem() const { return m_pItem; }
    sal_uInt16 Which() const { if(nullptr != m_pItem) return m_pItem->Which(); return 0; }
};

class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
{
    friend class SfxItemIter;
diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx
index c2c37c1..faedbd5 100644
--- a/svl/source/items/itempool.cxx
+++ b/svl/source/items/itempool.cxx
@@ -794,15 +794,15 @@ void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId )

const SfxPoolItem& SfxItemPool::DirectPutItemInPoolImpl(const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership)
{
    // CAUTION: Do not register the problematic pool default
    if (rItem.isExceptionalSCItem() && GetMasterPool()->newItem_UseDirect(rItem))
        return rItem;

#ifdef DBG_UTIL
    nAllDirectlyPooledSfxPoolItemCount++;
    nRemainingDirectlyPooledSfxPoolItemCount++;
#endif

    // CAUTION: Do not register the problematic pool default
    if (rItem.isExceptionalSCItem() && GetMasterPool()->newItem_UseDirect(rItem))
        return rItem;

    // make sure to use 'master'-pool, that's the one used by SfxItemSets
    const SfxPoolItem* pRetval(implCreateItemEntry(*GetMasterPool(), &rItem, nWhich, bPassingOwnership));

@@ -816,13 +816,16 @@ const SfxPoolItem& SfxItemPool::DirectPutItemInPoolImpl(const SfxPoolItem& rItem

void SfxItemPool::DirectRemoveItemFromPool(const SfxPoolItem& rItem)
{
    // CAUTION: Do not remove the problematic pool default
    if (rItem.isExceptionalSCItem() && GetMasterPool()->newItem_UseDirect(rItem))
        return;

#ifdef DBG_UTIL
    nRemainingDirectlyPooledSfxPoolItemCount--;
#endif

    // make sure to use 'master'-pool, that's the one used by SfxItemSets
    implCleanupItemEntry(*GetMasterPool(), &rItem);
    return;
}

void SfxItemPool::newItem_Callback(const SfxPoolItem& rItem) const
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index abb2644..102cf4d 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -39,8 +39,12 @@
#ifdef DBG_UTIL
static size_t nAllocatedSfxItemSetCount(0);
static size_t nUsedSfxItemSetCount(0);
static size_t nAllocatedSfxPoolItemHolderCount(0);
static size_t nUsedSfxPoolItemHolderCount(0);
size_t getAllocatedSfxItemSetCount() { return nAllocatedSfxItemSetCount; }
size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
size_t getAllocatedSfxPoolItemHolderCount() { return nAllocatedSfxPoolItemHolderCount; }
size_t getUsedSfxPoolItemHolderCount() { return nUsedSfxPoolItemHolderCount; }
#endif
// NOTE: Only needed for one Item in SC (see notes below for
// ScPatternAttr/ATTR_PATTERN). Still keep it so that when errors
@@ -48,6 +52,61 @@ size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
// fallback flag 'ITEM_CLASSIC_MODE'
static bool g_bItemClassicMode(getenv("ITEM_CLASSIC_MODE"));

SfxPoolItemHolder::SfxPoolItemHolder(SfxItemPool& rPool, const SfxPoolItem* pItem)
: m_pPool(&rPool),
  m_pItem(pItem)
{
#ifdef DBG_UTIL
    nAllocatedSfxPoolItemHolderCount++;
    nUsedSfxPoolItemHolderCount++;
#endif
    if (nullptr != m_pItem)
        m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false);
}

SfxPoolItemHolder::SfxPoolItemHolder(const SfxPoolItemHolder& rHolder)
: m_pPool(rHolder.m_pPool),
  m_pItem(rHolder.m_pItem)
{
#ifdef DBG_UTIL
    nAllocatedSfxPoolItemHolderCount++;
    nUsedSfxPoolItemHolderCount++;
#endif
    if (nullptr != m_pItem)
        m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false);
}

SfxPoolItemHolder::~SfxPoolItemHolder()
{
#ifdef DBG_UTIL
    nAllocatedSfxPoolItemHolderCount--;
#endif
    if (nullptr != m_pItem)
        implCleanupItemEntry(*m_pPool, m_pItem);
}

const SfxPoolItemHolder& SfxPoolItemHolder::operator=(const SfxPoolItemHolder& rHolder)
{
    if (this == &rHolder || *this == rHolder)
        return *this;

    if (nullptr != m_pItem)
        implCleanupItemEntry(*m_pPool, m_pItem);

    m_pPool = rHolder.m_pPool;
    m_pItem = rHolder.m_pItem;

    if (nullptr != m_pItem)
        m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false);

    return *this;
}

bool SfxPoolItemHolder::operator==(const SfxPoolItemHolder &rHolder) const
{
    return m_pPool == rHolder.m_pPool && areSfxPoolItemPtrsEqual(m_pItem, rHolder.m_pItem);
}

/**
 * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
 * the supplied SfxItemPool.
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index d7624cb..e1e12db 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -200,6 +200,10 @@ Application::~Application()
    SAL_INFO("vcl.items", "ITEM: " << getAllocatedSfxItemSetCount() << " SfxItemSets still allocated at shutdown");
    SAL_INFO("vcl.items", "ITEM: " << getUsedSfxItemSetCount() << " SfxItemSets were incarnated during runtime");

    // Same mechanism for PoolItemHolder(s)
    SAL_INFO("vcl.items", "ITEM: " << getAllocatedSfxPoolItemHolderCount() << " SfxPoolItemHolders still allocated at shutdown");
    SAL_INFO("vcl.items", "ITEM: " << getUsedSfxPoolItemHolderCount() << " SfxPoolItemHolders were incarnated during runtime");

    // Same mechanism for SfxPoolItem(s)directly put to a Pool
    SAL_INFO("vcl.items", "ITEM: " << getRemainingDirectlyPooledSfxPoolItemCount() << " SfxPoolItems still directly put in Pool at shutdown (deleted @Pool destruction)");
    SAL_INFO("vcl.items", "ITEM: " << getAllDirectlyPooledSfxPoolItemCount() << " SfxPoolItems directly put in Pool");