[Libreoffice-commits] core.git: sc/inc sc/qa sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Feb 28 14:53:25 UTC 2019


 sc/inc/postit.hxx                   |  114 ++++++-
 sc/inc/scmod.hxx                    |    2 
 sc/qa/unit/ucalc.cxx                |   18 -
 sc/source/core/data/documen3.cxx    |    2 
 sc/source/core/data/document.cxx    |    8 
 sc/source/core/data/postit.cxx      |  568 ++++++++++++++++++++++++++++--------
 sc/source/core/tool/detfunc.cxx     |    2 
 sc/source/filter/excel/xeescher.cxx |    2 
 sc/source/filter/xml/xmlexprt.cxx   |   10 
 sc/source/ui/app/scmod.cxx          |   28 +
 sc/source/ui/docshell/docfunc.cxx   |    4 
 sc/source/ui/docshell/docsh.cxx     |   20 -
 sc/source/ui/drawfunc/futext3.cxx   |    4 
 sc/source/ui/inc/docsh.hxx          |    2 
 sc/source/ui/inc/notemark.hxx       |    3 
 sc/source/ui/inc/undocell.hxx       |   45 --
 sc/source/ui/undo/undocell.cxx      |  184 -----------
 sc/source/ui/unoobj/editsrc.cxx     |    2 
 sc/source/ui/unoobj/notesuno.cxx    |    2 
 sc/source/ui/view/drawview.cxx      |    2 
 sc/source/ui/view/gridwin.cxx       |    2 
 sc/source/ui/view/notemark.cxx      |    2 
 sc/source/ui/view/tabview5.cxx      |    2 
 sc/source/ui/view/viewfun6.cxx      |    2 
 24 files changed, 638 insertions(+), 392 deletions(-)

New commits:
commit 05602710a047c58db0ceda88bedc291420990bc1
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Feb 12 13:48:53 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu Feb 28 15:52:51 2019 +0100

    reintroduce ScCaptionPtr
    
    This basically reverts b6b1ded0a0539e7be1b5338de378a3276a6ff445, since it
    introduces tdf#118707, and I cannot reproduce any of the original problems
    when reverting.
    The patch itself is technically correct, but the problem is in the Windows
    implementation of clipboard handling, which uses delayed processing
    of setting clipboard contents. This leads to previous clipboard contents
    being deleted too late, and with shared_ptr instances of SdrCaptionObj may
    get deleted after the related SdrModel has already been deleted.
    A proper fix would be to remove the stupid delayed processing from
    the clipboard code, but that's non-trivial. If that gets fixed, the change
    removing ScCaptionPtr may most probably be applied again.
    
    Change-Id: I29634847486aa955b20483c9eb38bba4fed87187
    Reviewed-on: https://gerrit.libreoffice.org/67725
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sc/inc/postit.hxx b/sc/inc/postit.hxx
index 4700979cd04a..11c5d9b5f84b 100644
--- a/sc/inc/postit.hxx
+++ b/sc/inc/postit.hxx
@@ -36,6 +36,110 @@ class ScDocument;
 namespace tools { class Rectangle; }
 struct ScCaptionInitData;
 
+/** Some desperate attempt to fight against the caption object ownership mess,
+    to which none of shared/weak/plain pointer is a cure.
+ */
+class ScCaptionPtr
+{
+public:
+    ScCaptionPtr();
+    explicit ScCaptionPtr( SdrCaptionObj* p );
+    ScCaptionPtr( const ScCaptionPtr& r );
+    ScCaptionPtr( ScCaptionPtr&& r );
+    ~ScCaptionPtr();
+
+    ScCaptionPtr& operator=( const ScCaptionPtr& r );
+    ScCaptionPtr& operator=( ScCaptionPtr&& r );
+    explicit operator bool() const    { return mpCaption != nullptr; }
+    const SdrCaptionObj* get() const        { return mpCaption; }
+    SdrCaptionObj* get()        { return mpCaption; }
+    const SdrCaptionObj* operator->() const { return mpCaption; }
+    SdrCaptionObj* operator->() { return mpCaption; }
+    const SdrCaptionObj& operator*() const  { return *mpCaption; }
+    SdrCaptionObj& operator*()  { return *mpCaption; }
+
+    // Does not default to nullptr to make it visually obvious where such is used.
+    void reset( SdrCaptionObj* p );
+
+    /** Insert to draw page. The caption object is owned by the draw page then.
+     */
+    void insertToDrawPage( SdrPage& rDrawPage );
+
+    /** Remove from draw page. The caption object is not owned anymore by the
+        draw page then.
+     */
+    void removeFromDrawPage( SdrPage& rDrawPage );
+
+    /** Remove from draw page and free caption object if no Undo recording.
+     */
+    void removeFromDrawPageAndFree( bool bIgnoreUndo = false );
+
+    /** Release all management of the SdrCaptionObj* in all instances of this
+        list and dissolve. The SdrCaptionObj pointer returned is ready to be
+        managed elsewhere.
+     */
+    SdrCaptionObj* release();
+
+    /** Forget the SdrCaptionObj pointer in this one instance.
+        Decrements a use count but does not destroy the object, it's up to the
+        caller to manage this mess..
+     */
+    void forget();
+
+    /** Flag that this instance is in Undo, so drawing layer owns it. */
+    void setNotOwner();
+
+    oslInterlockedCount getRefs() const;
+
+private:
+
+    struct Head
+    {
+        ScCaptionPtr*       mpFirst;        ///< first in list
+        oslInterlockedCount mnRefs;         ///< use count
+
+        Head() = delete;
+        explicit Head( ScCaptionPtr* );
+    };
+
+    Head*                 mpHead;       ///< points to the "master" entry
+    mutable ScCaptionPtr* mpNext;       ///< next in list
+    SdrCaptionObj*        mpCaption;    ///< the caption object, managed by head master
+    bool                  mbNotOwner;   ///< whether this caption object is owned by something else, e.g. held in Undo
+                                            /* TODO: can that be moved to Head?
+                                             * It's unclear when to reset, so
+                                             * each instance has its own flag.
+                                             * The last reference count
+                                             * decrement automatically has the
+                                             * then current state available.
+                                             * */
+
+    void newHead();             //< Allocate a new Head and init.
+    void incRef() const;
+    bool decRef() const;        //< @returns <TRUE/> if the last reference was decremented.
+    void decRefAndDestroy();    //< Destroys caption object if the last reference was decremented.
+
+    /** Remove from current list and close gap.
+
+        Usually there are only very few instances, so maintaining a doubly
+        linked list isn't worth memory/performance wise and a simple walk does
+        it.
+     */
+    void removeFromList();
+
+    /** Replace this instance with pNew in a list, if any.
+
+        Used by move-ctor and move assignment operator.
+     */
+    void replaceInList( ScCaptionPtr* pNew );
+
+    /** Dissolve list when the caption object is released or gone. */
+    void dissolve();
+
+    /** Just clear everything, while dissolving the list. */
+    void clear();
+};
+
 /** Internal data for a cell annotation. */
 struct SC_DLLPUBLIC ScNoteData
 {
@@ -44,7 +148,7 @@ struct SC_DLLPUBLIC ScNoteData
     OUString     maDate;             /// Creation date of the note.
     OUString     maAuthor;           /// Author of the note.
     ScCaptionInitDataRef mxInitData;        /// Initial data for invisible notes without SdrObject.
-    std::shared_ptr< SdrCaptionObj >    m_pCaption;          /// Drawing object representing the cell note.
+    ScCaptionPtr        mxCaption;          /// Drawing object representing the cell note.
     bool                mbShown;            /// True = note is visible.
 
     explicit            ScNoteData( bool bShown = false );
@@ -130,12 +234,12 @@ public:
         contains initial caption data needed to construct a caption object.
         The SdrCaptionObj* returned is still managed by the underlying
         ScNoteData::ScCaptionPtr and must not be stored elsewhere. */
-    const std::shared_ptr< SdrCaptionObj>& GetCaption() const { return maNoteData.m_pCaption; }
+    SdrCaptionObj*      GetCaption() const { return maNoteData.mxCaption.get();}
     /** Returns the caption object of this note. Creates the caption object, if
         the note contains initial caption data instead of the caption.
         The SdrCaptionObj* returned is still managed by the underlying
         ScNoteData::ScCaptionPtr and must not be stored elsewhere. */
-    const std::shared_ptr< SdrCaptionObj>& GetOrCreateCaption( const ScAddress& rPos ) const;
+    SdrCaptionObj*      GetOrCreateCaption( const ScAddress& rPos ) const;
 
     /** Forgets the pointer to the note caption object.
 
@@ -163,7 +267,7 @@ private:
     /** Creates the caption object from initial caption data if existing. */
     void                CreateCaptionFromInitData( const ScAddress& rPos ) const;
     /** Creates a new caption object at the passed cell position, clones passed existing caption. */
-    void                CreateCaption( const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& pCaption );
+    void                CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption = nullptr );
     /** Removes the caption object from the drawing layer, if this note is its owner. */
     void                RemoveCaption();
 
@@ -178,7 +282,7 @@ class SC_DLLPUBLIC ScNoteUtil
 public:
 
     /** Creates and returns a caption object for a temporary caption. */
-    static std::shared_ptr< SdrCaptionObj > CreateTempCaption( ScDocument& rDoc, const ScAddress& rPos,
+    static ScCaptionPtr CreateTempCaption( ScDocument& rDoc, const ScAddress& rPos,
                             SdrPage& rDrawPage, const OUString& rUserText,
                             const tools::Rectangle& rVisRect, bool bTailFront );
 
diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx
index 7ba92a747aec..3a389ecc2d45 100644
--- a/sc/inc/scmod.hxx
+++ b/sc/inc/scmod.hxx
@@ -146,6 +146,8 @@ public:
     void                SetDragJump(
         ScDocument* pLocalDoc, const OUString& rTarget, const OUString& rText );
 
+    static ScDocument*  GetClipDoc();       // called from document - should be removed later
+
     //  X selection:
     ScSelectionTransferObj* GetSelectionTransfer() const    { return m_pSelTransfer; }
     void                SetSelectionTransfer( ScSelectionTransferObj* pNew );
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 2309488d2e6e..2446246d3c4a 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -5352,7 +5352,7 @@ void Test::testNoteLifeCycle()
 
     // Re-insert the note back to the same place.
     m_pDoc->SetNote(aPos, std::move(pNote2));
-    SdrCaptionObj* pCaption = pNote->GetOrCreateCaption(aPos).get();
+    SdrCaptionObj* pCaption = pNote->GetOrCreateCaption(aPos);
     CPPUNIT_ASSERT_MESSAGE("Failed to create a caption object.", pCaption);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("This caption should belong to the drawing layer of the document.",
                            m_pDoc->GetDrawLayer(), static_cast<ScDrawLayer*>(&pCaption->getSdrModelFromSdrObject()));
@@ -5368,7 +5368,7 @@ void Test::testNoteLifeCycle()
     ScPostIt* pClipNote = aClipDoc.GetNote(aPos);
     CPPUNIT_ASSERT_MESSAGE("Failed to copy note to the clipboard.", pClipNote);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Note on the clipboard should share the same caption object from the original.",
-                           pCaption, pClipNote->GetCaption().get());
+                           pCaption, pClipNote->GetCaption());
 
 
     // Move B2 to B3 with note, which creates an ScUndoDragDrop, and Undo.
@@ -5376,7 +5376,7 @@ void Test::testNoteLifeCycle()
     ScAddress aOrigPos(aPos);
     ScAddress aMovePos(1,2,0);
     ScPostIt* pOrigNote = m_pDoc->GetNote(aOrigPos);
-    const SdrCaptionObj* pOrigCaption = pOrigNote->GetOrCreateCaption(aOrigPos).get();
+    const SdrCaptionObj* pOrigCaption = pOrigNote->GetOrCreateCaption(aOrigPos);
     bool const bCut = true;       // like Drag&Drop
     bool bRecord = true;    // record Undo
     bool const bPaint = false;    // don't care about
@@ -5394,7 +5394,7 @@ void Test::testNoteLifeCycle()
     // The caption object should not be identical, it was newly created upon
     // Drop from clipboard.
     // pOrigCaption is a dangling pointer.
-    const SdrCaptionObj* pMoveCaption = pMoveNote->GetOrCreateCaption(aMovePos).get();
+    const SdrCaptionObj* pMoveCaption = pMoveNote->GetOrCreateCaption(aMovePos);
     CPPUNIT_ASSERT_MESSAGE("Captions identical after move.", pOrigCaption != pMoveCaption);
 
     SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
@@ -5409,7 +5409,7 @@ void Test::testNoteLifeCycle()
 
     // The caption object still should not be identical.
     // pMoveCaption is a dangling pointer.
-    pOrigCaption = pOrigNote->GetOrCreateCaption(aOrigPos).get();
+    pOrigCaption = pOrigNote->GetOrCreateCaption(aOrigPos);
     CPPUNIT_ASSERT_MESSAGE("Captions identical after move undo.", pOrigCaption != pMoveCaption);
 
 
@@ -5418,7 +5418,7 @@ void Test::testNoteLifeCycle()
     ScAddress aPosB4(1,3,0);
     ScPostIt* pNoteB4 = m_pDoc->GetOrCreateNote(aPosB4);
     CPPUNIT_ASSERT_MESSAGE("Failed to insert cell comment at B4.", pNoteB4);
-    const SdrCaptionObj* pCaptionB4 = pNoteB4->GetOrCreateCaption(aPosB4).get();
+    const SdrCaptionObj* pCaptionB4 = pNoteB4->GetOrCreateCaption(aPosB4);
     ScCellMergeOption aCellMergeOption(1,3,2,3);
     rDocFunc.MergeCells( aCellMergeOption, true /*bContents*/, bRecord, bApi, false /*bEmptyMergedCells*/ );
 
@@ -5430,7 +5430,7 @@ void Test::testNoteLifeCycle()
     // at B4 after the merge and not cloned nor recreated during Undo.
     ScPostIt* pUndoNoteB4 = m_pDoc->GetNote(aPosB4);
     CPPUNIT_ASSERT_MESSAGE("No cell comment at B4 after Undo.", pUndoNoteB4);
-    const SdrCaptionObj* pUndoCaptionB4 = pUndoNoteB4->GetCaption().get();
+    const SdrCaptionObj* pUndoCaptionB4 = pUndoNoteB4->GetCaption();
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Captions not identical after Merge Undo.", pCaptionB4, pUndoCaptionB4);
 
 
@@ -5446,7 +5446,7 @@ void Test::testNoteLifeCycle()
         ScAddress aPosB5(1,4,0);
         ScPostIt* pOtherNoteB5 = pDoc2->GetOrCreateNote(aPosB5);
         CPPUNIT_ASSERT_MESSAGE("Failed to insert cell comment at B5.", pOtherNoteB5);
-        const SdrCaptionObj* pOtherCaptionB5 = pOtherNoteB5->GetOrCreateCaption(aPosB5).get();
+        const SdrCaptionObj* pOtherCaptionB5 = pOtherNoteB5->GetOrCreateCaption(aPosB5);
         CPPUNIT_ASSERT_MESSAGE("No caption at B5.", pOtherCaptionB5);
 
         ScDocument aClipDoc2(SCDOCMODE_CLIP);
@@ -5464,7 +5464,7 @@ void Test::testNoteLifeCycle()
         pasteFromClip( m_pDoc, aPosB5, &aClipDoc2); // should not crash... tdf#104967
         ScPostIt* pNoteB5 = m_pDoc->GetNote(aPosB5);
         CPPUNIT_ASSERT_MESSAGE("Failed to paste cell comment at B5.", pNoteB5);
-        const SdrCaptionObj* pCaptionB5 = pNoteB5->GetOrCreateCaption(aPosB5).get();
+        const SdrCaptionObj* pCaptionB5 = pNoteB5->GetOrCreateCaption(aPosB5);
         CPPUNIT_ASSERT_MESSAGE("No caption at pasted B5.", pCaptionB5);
         // Do not test if  pCaptionB5 != pOtherCaptionB5  because since pDoc2
         // has been closed and the caption been deleted objects *may* be
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 8f68d5015940..a0c0bcd0f040 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -1082,7 +1082,7 @@ void ScDocument::UpdateReference(
     // After moving, no clipboard move ref-updates are possible
     if (rCxt.meMode != URM_COPY && IsClipboardSource())
     {
-        ScDocument* pClipDoc = static_cast<ScDocShell*>(mpShell)->GetClipDoc();
+        ScDocument* pClipDoc = ScModule::GetClipDoc();
         if (pClipDoc)
             pClipDoc->GetClipParam().mbCutMode = false;
     }
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 91b799f4b4ee..cf236daeda2e 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2190,7 +2190,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
     if (!pClipDoc)
     {
         SAL_WARN("sc", "CopyToClip: no ClipDoc");
-        pClipDoc = static_cast<ScDocShell*>(mpShell)->GetClipDoc();
+        pClipDoc = ScModule::GetClipDoc();
     }
 
     if (mpShell->GetMedium())
@@ -2289,7 +2289,7 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
         if (!pClipDoc)
         {
             SAL_WARN("sc", "CopyTabToClip: no ClipDoc");
-            pClipDoc = static_cast<ScDocShell*>(mpShell)->GetClipDoc();
+            pClipDoc = ScModule::GetClipDoc();
         }
 
         if (mpShell->GetMedium())
@@ -2573,7 +2573,7 @@ bool ScDocument::IsClipboardSource() const
     if (bIsClip || mpShell == nullptr)
         return false;
 
-    ScDocument* pClipDoc = static_cast<ScDocShell*>(mpShell)->GetClipDoc();
+    ScDocument* pClipDoc = ScModule::GetClipDoc();
     return pClipDoc && pClipDoc->bIsClip && pClipDoc->mxPoolHelper.is() && mxPoolHelper.is() &&
             mxPoolHelper->GetDocPool() == pClipDoc->mxPoolHelper->GetDocPool();
 }
@@ -2816,7 +2816,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
     if (!pClipDoc)
     {
         OSL_FAIL("CopyFromClip: no ClipDoc");
-        pClipDoc = static_cast<ScDocShell*>(mpShell)->GetClipDoc();
+        pClipDoc = ScModule::GetClipDoc();
     }
 
     if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx
index 43436c42dee5..69c2d4887dcc 100644
--- a/sc/source/core/data/postit.cxx
+++ b/sc/source/core/data/postit.cxx
@@ -43,7 +43,6 @@
 #include <docpool.hxx>
 #include <patattr.hxx>
 #include <drwlayer.hxx>
-#include <undocell.hxx>
 #include <userdat.hxx>
 #include <detfunc.hxx>
 #include <editutil.hxx>
@@ -160,12 +159,12 @@ public:
     /** Create a new caption. The caption will not be inserted into the document. */
     explicit            ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bTailFront );
     /** Manipulate an existing caption. */
-    explicit            ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& pCaption );
+    explicit            ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const ScCaptionPtr& xCaption );
 
     /** Returns the drawing layer page of the sheet contained in maPos. */
     SdrPage*            GetDrawPage();
     /** Returns the caption drawing object. */
-    const std::shared_ptr< SdrCaptionObj >& GetCaption() { return m_pCaption; }
+    ScCaptionPtr &      GetCaption() { return mxCaption; }
 
     /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */
     void                FitCaptionToRect( const tools::Rectangle* pVisRect = nullptr );
@@ -192,7 +191,7 @@ private:
 private:
     ScDocument&         mrDoc;
     ScAddress           maPos;
-    std::shared_ptr< SdrCaptionObj > m_pCaption;
+    ScCaptionPtr        mxCaption;
     tools::Rectangle           maPageRect;
     tools::Rectangle           maCellRect;
     bool                mbNegPage;
@@ -206,10 +205,10 @@ ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, boo
     CreateCaption( true/*bShown*/, bTailFront );
 }
 
-ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& pCaption ) :
+ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const ScCaptionPtr& xCaption ) :
     mrDoc( rDoc ),
     maPos( rPos ),
-    m_pCaption( pCaption )
+    mxCaption( xCaption )
 {
     Initialize();
 }
@@ -232,13 +231,13 @@ void ScCaptionCreator::FitCaptionToRect( const tools::Rectangle* pVisRect )
     const tools::Rectangle& rVisRect = GetVisRect( pVisRect );
 
     // tail position
-    Point aTailPos = m_pCaption->GetTailPos();
+    Point aTailPos = mxCaption->GetTailPos();
     aTailPos.setX( ::std::max( ::std::min( aTailPos.X(), rVisRect.Right() ), rVisRect.Left() ) );
     aTailPos.setY( ::std::max( ::std::min( aTailPos.Y(), rVisRect.Bottom() ), rVisRect.Top() ) );
-    m_pCaption->SetTailPos( aTailPos );
+    mxCaption->SetTailPos( aTailPos );
 
     // caption rectangle
-    tools::Rectangle aCaptRect = m_pCaption->GetLogicRect();
+    tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
     Point aCaptPos = aCaptRect.TopLeft();
     // move textbox inside right border of visible area
     aCaptPos.setX( ::std::min< long >( aCaptPos.X(), rVisRect.Right() - aCaptRect.GetWidth() ) );
@@ -250,7 +249,7 @@ void ScCaptionCreator::FitCaptionToRect( const tools::Rectangle* pVisRect )
     aCaptPos.setY( ::std::max< long >( aCaptPos.Y(), rVisRect.Top() ) );
     // update caption
     aCaptRect.SetPos( aCaptPos );
-    m_pCaption->SetLogicRect( aCaptRect );
+    mxCaption->SetLogicRect( aCaptRect );
 }
 
 void ScCaptionCreator::AutoPlaceCaption( const tools::Rectangle* pVisRect )
@@ -258,7 +257,7 @@ void ScCaptionCreator::AutoPlaceCaption( const tools::Rectangle* pVisRect )
     const tools::Rectangle& rVisRect = GetVisRect( pVisRect );
 
     // caption rectangle
-    tools::Rectangle aCaptRect = m_pCaption->GetLogicRect();
+    tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
     long nWidth = aCaptRect.GetWidth();
     long nHeight = aCaptRect.GetHeight();
 
@@ -316,7 +315,7 @@ void ScCaptionCreator::AutoPlaceCaption( const tools::Rectangle* pVisRect )
 
     // update textbox position in note caption object
     aCaptRect.SetPos( aCaptPos );
-    m_pCaption->SetLogicRect( aCaptRect );
+    mxCaption->SetLogicRect( aCaptRect );
     FitCaptionToRect( pVisRect );
 }
 
@@ -325,33 +324,33 @@ void ScCaptionCreator::UpdateCaptionPos()
     ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
 
     // update caption position
-    const Point& rOldTailPos = m_pCaption->GetTailPos();
+    const Point& rOldTailPos = mxCaption->GetTailPos();
     Point aTailPos = CalcTailPos( false );
     if( rOldTailPos != aTailPos )
     {
         // create drawing undo action
         if( pDrawLayer && pDrawLayer->IsRecording() )
-            pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *m_pCaption ) );
+            pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *mxCaption ) );
         // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
-        tools::Rectangle aCaptRect = m_pCaption->GetLogicRect();
+        tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
         long nDiffX = (rOldTailPos.X() >= 0) ? (aCaptRect.Left() - rOldTailPos.X()) : (rOldTailPos.X() - aCaptRect.Right());
         if( mbNegPage ) nDiffX = -nDiffX - aCaptRect.GetWidth();
         long nDiffY = aCaptRect.Top() - rOldTailPos.Y();
         aCaptRect.SetPos( aTailPos + Point( nDiffX, nDiffY ) );
         // set new tail position and caption rectangle
-        m_pCaption->SetTailPos( aTailPos );
-        m_pCaption->SetLogicRect( aCaptRect );
+        mxCaption->SetTailPos( aTailPos );
+        mxCaption->SetLogicRect( aCaptRect );
         // fit caption into draw page
         FitCaptionToRect();
     }
 
     // update cell position in caption user data
-    ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( m_pCaption.get(), maPos.Tab() );
+    ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( mxCaption.get(), maPos.Tab() );
     if( pCaptData && (maPos != pCaptData->maStart) )
     {
         // create drawing undo action
         if( pDrawLayer && pDrawLayer->IsRecording() )
-            pDrawLayer->AddCalcUndo( std::make_unique<ScUndoObjData>( m_pCaption.get(), pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
+            pDrawLayer->AddCalcUndo( std::make_unique<ScUndoObjData>( mxCaption.get(), pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
         // set new position
         pCaptData->maStart = maPos;
     }
@@ -373,22 +372,13 @@ void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront )
     // create the caption drawing object
     tools::Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) );
     Point aTailPos = CalcTailPos( bTailFront );
-    m_pCaption.reset(
+    mxCaption.reset(
         new SdrCaptionObj(
             *mrDoc.GetDrawLayer(), // TTTT should ret a ref?
             aTextRect,
-            aTailPos),
-        [](SdrCaptionObj* pCaptionObj){
-            SdrPage* pDrawPage(pCaptionObj->getSdrPageFromSdrObject());
-            if (pDrawPage)
-            {
-                pDrawPage->RemoveObject(pCaptionObj->GetOrdNum());
-            }
-            SdrObject* pObj = pCaptionObj;
-            SdrObject::Free(pObj);
-    });
+            aTailPos));
     // basic caption settings
-    ScCaptionUtil::SetBasicCaptionSettings( *m_pCaption, bShown );
+    ScCaptionUtil::SetBasicCaptionSettings( *mxCaption, bShown );
 }
 
 void ScCaptionCreator::Initialize()
@@ -412,7 +402,7 @@ public:
     /** Create a new caption object and inserts it into the document. */
     explicit            ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData );
     /** Manipulate an existing caption. */
-    explicit            ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& xCaption, bool bShown );
+    explicit            ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScCaptionPtr& xCaption, bool bShown );
 };
 
 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) :
@@ -424,54 +414,403 @@ ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& r
     {
         // create the caption drawing object
         CreateCaption( rNoteData.mbShown, false );
-        rNoteData.m_pCaption = GetCaption();
-        OSL_ENSURE( rNoteData.m_pCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
-        if( rNoteData.m_pCaption )
+        rNoteData.mxCaption = GetCaption();
+        OSL_ENSURE( rNoteData.mxCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
+        if( rNoteData.mxCaption )
         {
             // store note position in user data of caption object
-            ScCaptionUtil::SetCaptionUserData( *rNoteData.m_pCaption, rPos );
+            ScCaptionUtil::SetCaptionUserData( *rNoteData.mxCaption, rPos );
             // insert object into draw page
-            pDrawPage->InsertObject( rNoteData.m_pCaption.get() );
+            pDrawPage->InsertObject( rNoteData.mxCaption.get() );
         }
     }
 }
 
-ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& pCaption, bool bShown ) :
-    ScCaptionCreator( rDoc, rPos, pCaption )
+ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScCaptionPtr& xCaption, bool bShown ) :
+    ScCaptionCreator( rDoc, rPos, xCaption )
 {
     SdrPage* pDrawPage = GetDrawPage();
     OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
-    OSL_ENSURE( pCaption->getSdrPageFromSdrObject() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
-    if( pDrawPage && (pCaption->getSdrPageFromSdrObject() == pDrawPage) )
+    OSL_ENSURE( xCaption->getSdrPageFromSdrObject() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
+    if( pDrawPage && (xCaption->getSdrPageFromSdrObject() == pDrawPage) )
     {
         // store note position in user data of caption object
-        ScCaptionUtil::SetCaptionUserData( *pCaption, rPos );
+        ScCaptionUtil::SetCaptionUserData( *xCaption, rPos );
         // basic caption settings
-        ScCaptionUtil::SetBasicCaptionSettings( *pCaption, bShown );
+        ScCaptionUtil::SetBasicCaptionSettings( *xCaption, bShown );
         // set correct tail position
-        pCaption->SetTailPos( CalcTailPos( false ) );
+        xCaption->SetTailPos( CalcTailPos( false ) );
+    }
+}
+
+} // namespace
+
+ScCaptionPtr::ScCaptionPtr() :
+    mpHead(nullptr), mpNext(nullptr), mpCaption(nullptr), mbNotOwner(false)
+{
+}
+
+ScCaptionPtr::ScCaptionPtr( SdrCaptionObj* p ) :
+    mpHead(nullptr), mpNext(nullptr), mpCaption(p), mbNotOwner(false)
+{
+    if (p)
+    {
+        newHead();
+     }
+}
+
+ScCaptionPtr::ScCaptionPtr( const ScCaptionPtr& r ) :
+    mpHead(r.mpHead), mpCaption(r.mpCaption), mbNotOwner(false)
+{
+    if (r.mpCaption)
+    {
+        assert(r.mpHead);
+        r.incRef();
+        // Insert into list.
+        mpNext = r.mpNext;
+        r.mpNext = this;
+    }
+    else
+    {
+        assert(!r.mpHead);
+        mpNext = nullptr;
+    }
+}
+
+ScCaptionPtr::ScCaptionPtr( ScCaptionPtr&& r ) :
+    mpHead(r.mpHead), mpNext(r.mpNext), mpCaption(r.mpCaption), mbNotOwner(false)
+{
+    r.replaceInList( this );
+    r.mpCaption = nullptr;
+    r.mbNotOwner = false;
+}
+
+ScCaptionPtr& ScCaptionPtr::operator=( ScCaptionPtr&& r )
+{
+    assert(this != &r);
+
+    mpHead = r.mpHead;
+    mpNext = r.mpNext;
+    mpCaption = r.mpCaption;
+    mbNotOwner = r.mbNotOwner;
+
+    r.replaceInList( this );
+    r.mpCaption = nullptr;
+    r.mbNotOwner = false;
+
+    return *this;
+}
+
+ScCaptionPtr& ScCaptionPtr::operator=( const ScCaptionPtr& r )
+{
+    if (this == &r)
+        return *this;
+
+    if (mpCaption == r.mpCaption)
+    {
+        // Two lists for the same caption is bad.
+        assert(!mpCaption || mpHead == r.mpHead);
+        assert(!mpCaption);     // assigning same caption pointer within same list is weird
+        // Nullptr captions are not inserted to the list, so nothing to do here
+        // if both are.
+        return *this;
     }
+
+    // Let's find some weird usage.
+    // Assigning without head doesn't make sense unless it is a nullptr caption.
+    assert(r.mpHead || !r.mpCaption);
+    // A nullptr caption must not be in a list and thus not have a head.
+    assert(!r.mpHead || r.mpCaption);
+    // Same captions were caught above, so here different heads must be present.
+    assert(r.mpHead != mpHead);
+
+    r.incRef();
+    decRefAndDestroy();
+    removeFromList();
+
+    mpCaption = r.mpCaption;
+    mbNotOwner = r.mbNotOwner;
+    // That head is this' master.
+    mpHead = r.mpHead;
+    // Insert into list.
+    mpNext = r.mpNext;
+    r.mpNext = this;
+
+    return *this;
+}
+
+void ScCaptionPtr::setNotOwner()
+{
+    mbNotOwner = true;
+}
+
+ScCaptionPtr::Head::Head( ScCaptionPtr* p ) :
+    mpFirst(p), mnRefs(1)
+{
+}
+
+void ScCaptionPtr::newHead()
+{
+    assert(!mpHead);
+    mpHead = new Head(this);
+}
+
+void ScCaptionPtr::replaceInList( ScCaptionPtr* pNew )
+{
+    if (!mpHead && !mpNext)
+        return;
+
+    assert(mpHead);
+    assert(mpCaption == pNew->mpCaption);
+
+    ScCaptionPtr* pThat = mpHead->mpFirst;
+    while (pThat && pThat != this && pThat->mpNext != this)
+    {
+        pThat = pThat->mpNext;
+    }
+    if (pThat && pThat != this)
+    {
+        assert(pThat->mpNext == this);
+        pThat->mpNext = pNew;
+    }
+    pNew->mpNext = mpNext;
+    if (mpHead->mpFirst == this)
+        mpHead->mpFirst = pNew;
+
+    mpHead = nullptr;
+    mpNext = nullptr;
 }
 
-void removeFromDrawPageAndFree( const std::shared_ptr< SdrCaptionObj >& pCaption )
+void ScCaptionPtr::removeFromList()
 {
-    SdrPage* pDrawPage(pCaption->getSdrPageFromSdrObject());
+    if (!mpHead && !mpNext && !mpCaption)
+        return;
+
+#if OSL_DEBUG_LEVEL > 0
+    oslInterlockedCount nCount = 0;
+#endif
+    ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : nullptr);
+    while (pThat && pThat != this && pThat->mpNext != this)
+    {
+        // Use the walk to check consistency on the fly.
+        assert(pThat->mpHead == mpHead);            // all belong to the same
+        assert(pThat->mpHead || !pThat->mpNext);    // next without head is bad
+        assert(pThat->mpCaption == mpCaption);
+        pThat = pThat->mpNext;
+#if OSL_DEBUG_LEVEL > 0
+        ++nCount;
+#endif
+    }
+    assert(pThat || !mpHead);   // not found only if this was standalone
+    if (pThat)
+    {
+        if (pThat != this)
+        {
+#if OSL_DEBUG_LEVEL > 0
+            // The while loop above was not executed, and for this
+            // (pThat->mpNext) the loop below won't either.
+            ++nCount;
+#endif
+            pThat->mpNext = mpNext;
+        }
+#if OSL_DEBUG_LEVEL > 0
+        do
+        {
+            assert(pThat->mpHead == mpHead);            // all belong to the same
+            assert(pThat->mpHead || !pThat->mpNext);    // next without head is bad
+            assert(pThat->mpCaption == mpCaption);
+            ++nCount;
+        }
+        while ((pThat = pThat->mpNext) != nullptr);
+#endif
+    }
+#if OSL_DEBUG_LEVEL > 0
+    // If part of a list then refs were already decremented.
+    assert(nCount == (mpHead ? mpHead->mnRefs + 1 : 0));
+#endif
+    if (mpHead && mpHead->mpFirst == this)
+    {
+        if (mpNext)
+            mpHead->mpFirst = mpNext;
+        else
+        {
+            // The only one destroys also head.
+            assert(mpHead->mnRefs == 0);    // cough
+            delete mpHead;                  // DEAD now
+        }
+    }
+    mpHead = nullptr;
+    mpNext = nullptr;
+}
+
+void ScCaptionPtr::reset( SdrCaptionObj* p )
+{
+    assert(!p || p != mpCaption);
+#if OSL_DEBUG_LEVEL > 0
+    if (p)
+    {
+        // Check if we end up with a duplicated management in this list.
+        ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : nullptr);
+        while (pThat)
+        {
+            assert(pThat->mpCaption != p);
+            pThat = pThat->mpNext;
+        }
+    }
+#endif
+    decRefAndDestroy();
+    removeFromList();
+    mpCaption = p;
+    mbNotOwner = false;
+    if (p)
+    {
+        newHead();
+    }
+}
+
+ScCaptionPtr::~ScCaptionPtr()
+{
+    decRefAndDestroy();
+    removeFromList();
+}
+
+oslInterlockedCount ScCaptionPtr::getRefs() const
+{
+    return mpHead ? mpHead->mnRefs : 0;
+}
+
+void ScCaptionPtr::incRef() const
+{
+    if (mpHead)
+        osl_atomic_increment(&mpHead->mnRefs);
+}
+
+bool ScCaptionPtr::decRef() const
+{
+    return mpHead && mpHead->mnRefs > 0 && !osl_atomic_decrement(&mpHead->mnRefs);
+}
+
+void ScCaptionPtr::decRefAndDestroy()
+{
+    if (decRef())
+    {
+        assert(mpHead->mpFirst == this);    // this must be one and only one
+        assert(!mpNext);                    // this must be one and only one
+        assert(mpCaption);
+
+#if 0
+        // Quick workaround for when there are still cases where the caption
+        // pointer is dangling
+        mpCaption = nullptr;
+        mbNotOwner = false;
+#else
+        // Destroying Draw Undo and some other delete the SdrObject, don't
+        // attempt that twice.
+        if (mbNotOwner)
+        {
+            mpCaption = nullptr;
+            mbNotOwner = false;
+        }
+        else
+        {
+            removeFromDrawPageAndFree( true );  // ignoring Undo
+            if (mpCaption)
+            {
+                // There's no draw page associated so removeFromDrawPageAndFree()
+                // didn't do anything, but still we want to delete the caption
+                // object. release()/dissolve() also resets mpCaption.
+                SdrObject* pObj = release();
+                SdrObject::Free( pObj );
+            }
+        }
+#endif
+        delete mpHead;
+        mpHead = nullptr;
+    }
+}
+
+void ScCaptionPtr::insertToDrawPage( SdrPage& rDrawPage )
+{
+    assert(mpHead && mpCaption);
+
+    rDrawPage.InsertObject( mpCaption );
+}
+
+void ScCaptionPtr::removeFromDrawPage( SdrPage& rDrawPage )
+{
+    assert(mpHead && mpCaption);
+    SdrObject* pObj = rDrawPage.RemoveObject( mpCaption->GetOrdNum() );
+    assert(pObj == mpCaption); (void)pObj;
+}
+
+void ScCaptionPtr::removeFromDrawPageAndFree( bool bIgnoreUndo )
+{
+    assert(mpHead && mpCaption);
+    SdrPage* pDrawPage(mpCaption->getSdrPageFromSdrObject());
     SAL_WARN_IF( !pDrawPage, "sc.core", "ScCaptionPtr::removeFromDrawPageAndFree - object without drawing page");
     if (pDrawPage)
     {
         pDrawPage->RecalcObjOrdNums();
-        ScDrawLayer* pDrawLayer(dynamic_cast< ScDrawLayer* >(&pCaption->getSdrModelFromSdrObject()));
-        SAL_WARN_IF( !pDrawLayer, "sc.core", "ScCaptionPtr::removeFromDrawPageAndFree - object without drawing layer");
-        // create drawing undo action (before removing the object to have valid draw page in undo action)
-        bool bRecording = (pDrawLayer && pDrawLayer->IsRecording());
-        if (bRecording)
-            pDrawLayer->AddCalcUndo( std::make_unique<ScUndoDelSdrCaptionObj>( pCaption ));
+        bool bRecording = false;
+        if(!bIgnoreUndo)
+        {
+            ScDrawLayer* pDrawLayer(dynamic_cast< ScDrawLayer* >(&mpCaption->getSdrModelFromSdrObject()));
+            SAL_WARN_IF( !pDrawLayer, "sc.core", "ScCaptionPtr::removeFromDrawPageAndFree - object without drawing layer");
+            // create drawing undo action (before removing the object to have valid draw page in undo action)
+            bRecording = (pDrawLayer && pDrawLayer->IsRecording());
+            if (bRecording)
+                pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoDelObj>( *mpCaption ));
+        }
         // remove the object from the drawing page, delete if undo is disabled
-        pDrawPage->RemoveObject( pCaption->GetOrdNum() );
+        removeFromDrawPage( *pDrawPage );
+        // If called from outside mnRefs must be 1 to delete. If called from
+        // decRefAndDestroy() mnRefs is already 0.
+        if (!bRecording && getRefs() <= 1)
+        {
+            SdrObject* pObj = release();
+            SdrObject::Free( pObj );
+        }
     }
 }
 
-} // namespace
+SdrCaptionObj* ScCaptionPtr::release()
+{
+    SdrCaptionObj* pTmp = mpCaption;
+    dissolve();
+    return pTmp;
+}
+
+void ScCaptionPtr::forget()
+{
+    decRef();
+    removeFromList();
+    mpCaption = nullptr;
+    mbNotOwner = false;
+}
+
+void ScCaptionPtr::dissolve()
+{
+    ScCaptionPtr::Head* pHead = mpHead;
+    ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : this);
+    while (pThat)
+    {
+        assert(!pThat->mpNext || pThat->mpHead);    // next without head is bad
+        assert(pThat->mpHead == pHead);             // same head required within one list
+        ScCaptionPtr* p = pThat->mpNext;
+        pThat->clear();
+        pThat = p;
+     }
+    assert(!mpHead && !mpNext && !mpCaption);       // should had been cleared during list walk
+    delete pHead;
+}
+
+void ScCaptionPtr::clear()
+{
+    mpHead = nullptr;
+    mpNext = nullptr;
+    mpCaption = nullptr;
+    mbNotOwner = false;
+}
 
 struct ScCaptionInitData
 {
@@ -503,7 +842,7 @@ ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, sal_uInt32 nPostItI
 {
     mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId;
     AutoStamp();
-    CreateCaption( rPos, nullptr );
+    CreateCaption( rPos );
 }
 
 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote, sal_uInt32 nPostItId ) :
@@ -511,8 +850,8 @@ ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNo
     maNoteData( rNote.maNoteData )
 {
     mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId;
-    maNoteData.m_pCaption.reset();
-    CreateCaption( rPos, rNote.maNoteData.m_pCaption );
+    maNoteData.mxCaption.reset(nullptr);
+    CreateCaption( rPos, rNote.maNoteData.mxCaption.get() );
 }
 
 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption, sal_uInt32 nPostItId ) :
@@ -553,8 +892,8 @@ void ScPostIt::AutoStamp()
 
 const OutlinerParaObject* ScPostIt::GetOutlinerObject() const
 {
-    if( maNoteData.m_pCaption )
-        return maNoteData.m_pCaption->GetOutlinerParaObject();
+    if( maNoteData.mxCaption )
+        return maNoteData.mxCaption->GetOutlinerParaObject();
     if( maNoteData.mxInitData.get() )
         return maNoteData.mxInitData->mxOutlinerObj.get();
     return nullptr;
@@ -599,14 +938,14 @@ bool ScPostIt::HasMultiLineText() const
 void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText )
 {
     CreateCaptionFromInitData( rPos );
-    if( maNoteData.m_pCaption )
-        maNoteData.m_pCaption->SetText( rText );
+    if( maNoteData.mxCaption )
+        maNoteData.mxCaption->SetText( rText );
 }
 
-const std::shared_ptr< SdrCaptionObj>& ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const
+SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const
 {
     CreateCaptionFromInitData( rPos );
-    return maNoteData.m_pCaption;
+    return maNoteData.mxCaption.get();
 }
 
 void ScPostIt::ForgetCaption( bool bPreserveData )
@@ -626,13 +965,13 @@ void ScPostIt::ForgetCaption( bool bPreserveData )
         pInitData->maSimpleText = GetText();
 
         maNoteData.mxInitData.reset(pInitData);
-        maNoteData.m_pCaption.reset();
+        maNoteData.mxCaption.forget();
     }
     else
     {
         /*  This function is used in undo actions to give up the responsibility for
             the caption object which is handled by separate drawing undo actions. */
-        maNoteData.m_pCaption.reset();
+        maNoteData.mxCaption.forget();
         maNoteData.mxInitData.reset();
     }
 }
@@ -642,23 +981,23 @@ void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow )
     CreateCaptionFromInitData( rPos );
     // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
     maNoteData.mbShown = bShow;
-    if( maNoteData.m_pCaption )
-        ScCaptionUtil::SetCaptionLayer( *maNoteData.m_pCaption, bShow );
+    if( maNoteData.mxCaption )
+        ScCaptionUtil::SetCaptionLayer( *maNoteData.mxCaption, bShow );
 }
 
 void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow )
 {
     CreateCaptionFromInitData( rPos );
-    if( maNoteData.m_pCaption )
-        ScCaptionUtil::SetCaptionLayer( *maNoteData.m_pCaption, maNoteData.mbShown || bShow );
+    if( maNoteData.mxCaption )
+        ScCaptionUtil::SetCaptionLayer( *maNoteData.mxCaption, maNoteData.mbShown || bShow );
 }
 
 void ScPostIt::UpdateCaptionPos( const ScAddress& rPos )
 {
     CreateCaptionFromInitData( rPos );
-    if( maNoteData.m_pCaption )
+    if( maNoteData.mxCaption )
     {
-        ScCaptionCreator aCreator( mrDoc, rPos, maNoteData.m_pCaption );
+        ScCaptionCreator aCreator( mrDoc, rPos, maNoteData.mxCaption );
         aCreator.UpdateCaptionPos();
     }
 }
@@ -669,7 +1008,7 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
 {
     // Captions are not created in Undo documents and only rarely in Clipboard,
     // but otherwise we need caption or initial data.
-    assert((maNoteData.m_pCaption || maNoteData.mxInitData.get()) || mrDoc.IsUndo() || mrDoc.IsClipboard());
+    assert((maNoteData.mxCaption || maNoteData.mxInitData.get()) || mrDoc.IsUndo() || mrDoc.IsClipboard());
     if( maNoteData.mxInitData.get() )
     {
         /*  This function is called from ScPostIt::Clone() when copying cells
@@ -679,44 +1018,44 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
             been created already. However, for clipboard in case the
             originating document was destructed a new caption has to be
             created. */
-        OSL_ENSURE( !mrDoc.IsUndo() && (!mrDoc.IsClipboard() || !maNoteData.m_pCaption),
+        OSL_ENSURE( !mrDoc.IsUndo() && (!mrDoc.IsClipboard() || !maNoteData.mxCaption),
                 "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
 
         /*  #i104915# Never try to create notes in Undo document, leads to
             crash due to missing document members (e.g. row height array). */
-        if( !maNoteData.m_pCaption && !mrDoc.IsUndo() )
+        if( !maNoteData.mxCaption && !mrDoc.IsUndo() )
         {
             if (mrDoc.IsClipboard())
                 mrDoc.InitDrawLayer();  // ensure there is a drawing layer
 
             // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
             ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
-            if( maNoteData.m_pCaption )
+            if( maNoteData.mxCaption )
             {
                 // Prevent triple change broadcasts of the same object.
-                maNoteData.m_pCaption->getSdrModelFromSdrObject().setLock(true);
+                maNoteData.mxCaption->getSdrModelFromSdrObject().setLock(true);
                 ScCaptionInitData& rInitData = *maNoteData.mxInitData;
 
                 // transfer ownership of outliner object to caption, or set simple text
                 OSL_ENSURE( rInitData.mxOutlinerObj.get() || !rInitData.maSimpleText.isEmpty(),
                     "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
                 if (rInitData.mxOutlinerObj)
-                    maNoteData.m_pCaption->SetOutlinerParaObject( std::move(rInitData.mxOutlinerObj) );
+                    maNoteData.mxCaption->SetOutlinerParaObject( std::move(rInitData.mxOutlinerObj) );
                 else
-                    maNoteData.m_pCaption->SetText( rInitData.maSimpleText );
+                    maNoteData.mxCaption->SetText( rInitData.maSimpleText );
 
                 // copy all items or set default items; reset shadow items
-                ScCaptionUtil::SetDefaultItems( *maNoteData.m_pCaption, mrDoc );
+                ScCaptionUtil::SetDefaultItems( *maNoteData.mxCaption, mrDoc );
                 if (rInitData.mxItemSet)
-                    ScCaptionUtil::SetCaptionItems( *maNoteData.m_pCaption, *rInitData.mxItemSet );
+                    ScCaptionUtil::SetCaptionItems( *maNoteData.mxCaption, *rInitData.mxItemSet );
 
                 // set position and size of the caption object
                 if( rInitData.mbDefaultPosSize )
                 {
                     // set other items and fit caption size to text
-                    maNoteData.m_pCaption->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
-                    maNoteData.m_pCaption->SetMergedItem( makeSdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
-                    maNoteData.m_pCaption->AdjustTextFrameWidthAndHeight();
+                    maNoteData.mxCaption->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
+                    maNoteData.mxCaption->SetMergedItem( makeSdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
+                    maNoteData.mxCaption->AdjustTextFrameWidthAndHeight();
                     aCreator.AutoPlaceCaption();
                 }
                 else
@@ -726,13 +1065,13 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
                     long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X());
                     long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y();
                     tools::Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize );
-                    maNoteData.m_pCaption->SetLogicRect( aCaptRect );
+                    maNoteData.mxCaption->SetLogicRect( aCaptRect );
                     aCreator.FitCaptionToRect();
                 }
 
                 // End prevent triple change broadcasts of the same object.
-                maNoteData.m_pCaption->getSdrModelFromSdrObject().setLock(false);
-                maNoteData.m_pCaption->BroadcastObjectChange();
+                maNoteData.mxCaption->getSdrModelFromSdrObject().setLock(false);
+                maNoteData.mxCaption->BroadcastObjectChange();
             }
         }
         // forget the initial caption data struct
@@ -740,10 +1079,10 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
     }
 }
 
-void ScPostIt::CreateCaption( const ScAddress& rPos, const std::shared_ptr< SdrCaptionObj >& pCaption )
+void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
 {
-    OSL_ENSURE( !maNoteData.m_pCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
-    maNoteData.m_pCaption.reset();
+    OSL_ENSURE( !maNoteData.mxCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
+    maNoteData.mxCaption.reset(nullptr);
 
     /*  #i104915# Never try to create notes in Undo document, leads to
         crash due to missing document members (e.g. row height array). */
@@ -757,40 +1096,40 @@ void ScPostIt::CreateCaption( const ScAddress& rPos, const std::shared_ptr< SdrC
 
     // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
     ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
-    if( maNoteData.m_pCaption )
+    if( maNoteData.mxCaption )
     {
         // clone settings of passed caption
         if( pCaption )
         {
             // copy edit text object (object must be inserted into page already)
             if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
-                maNoteData.m_pCaption->SetOutlinerParaObject( std::make_unique<OutlinerParaObject>( *pOPO ) );
+                maNoteData.mxCaption->SetOutlinerParaObject( std::make_unique<OutlinerParaObject>( *pOPO ) );
             // copy formatting items (after text has been copied to apply font formatting)
-            maNoteData.m_pCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
+            maNoteData.mxCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
             // move textbox position relative to new cell, copy textbox size
             tools::Rectangle aCaptRect = pCaption->GetLogicRect();
-            Point aDist = maNoteData.m_pCaption->GetTailPos() - pCaption->GetTailPos();
+            Point aDist = maNoteData.mxCaption->GetTailPos() - pCaption->GetTailPos();
             aCaptRect.Move( aDist.X(), aDist.Y() );
-            maNoteData.m_pCaption->SetLogicRect( aCaptRect );
+            maNoteData.mxCaption->SetLogicRect( aCaptRect );
             aCreator.FitCaptionToRect();
         }
         else
         {
             // set default formatting and default position
-            ScCaptionUtil::SetDefaultItems( *maNoteData.m_pCaption, mrDoc );
+            ScCaptionUtil::SetDefaultItems( *maNoteData.mxCaption, mrDoc );
             aCreator.AutoPlaceCaption();
         }
 
         // create undo action
         if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
             if( pDrawLayer->IsRecording() )
-                pDrawLayer->AddCalcUndo( std::make_unique<ScUndoNewSdrCaptionObj>( maNoteData.m_pCaption ) );
+                pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoNewObj>( *maNoteData.mxCaption ) );
     }
 }
 
 void ScPostIt::RemoveCaption()
 {
-    if (!maNoteData.m_pCaption)
+    if (!maNoteData.mxCaption)
         return;
 
     /*  Remove caption object only, if this note is its owner (e.g. notes in
@@ -798,19 +1137,28 @@ void ScPostIt::RemoveCaption()
         them from drawing layer here). */
     // TTTT maybe no longer needed - can that still happen?
     ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
-    if (pDrawLayer == &maNoteData.m_pCaption->getSdrModelFromSdrObject())
-        removeFromDrawPageAndFree(maNoteData.m_pCaption);
+    if (pDrawLayer == &maNoteData.mxCaption->getSdrModelFromSdrObject())
+        maNoteData.mxCaption.removeFromDrawPageAndFree();
+
+    SAL_INFO("sc.core","ScPostIt::RemoveCaption - refs: " << maNoteData.mxCaption.getRefs() <<
+            "  IsUndo: " << mrDoc.IsUndo() << "  IsClip: " << mrDoc.IsClipboard() <<
+            "  Dtor: " << mrDoc.IsInDtorClear());
 
-    maNoteData.m_pCaption.reset();
+    // Forget the caption object if removeFromDrawPageAndFree() did not free it.
+    if (maNoteData.mxCaption)
+    {
+        SAL_INFO("sc.core","ScPostIt::RemoveCaption - forgetting one ref");
+        maNoteData.mxCaption.forget();
+    }
 }
 
-std::shared_ptr< SdrCaptionObj > ScNoteUtil::CreateTempCaption(
+ScCaptionPtr ScNoteUtil::CreateTempCaption(
         ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
         const OUString& rUserText, const tools::Rectangle& rVisRect, bool bTailFront )
 {
     OUStringBuffer aBuffer( rUserText );
     // add plain text of invisible (!) cell note (no formatting etc.)
-    std::shared_ptr< SdrCaptionObj > pNoteCaption;
+    SdrCaptionObj* pNoteCaption = nullptr;
     const ScPostIt* pNote = rDoc.GetNote( rPos );
     if( pNote && !pNote->IsCaptionShown() )
     {
@@ -821,7 +1169,7 @@ std::shared_ptr< SdrCaptionObj > ScNoteUtil::CreateTempCaption(
 
     // create a caption if any text exists
     if( !pNoteCaption && aBuffer.isEmpty() )
-        return std::shared_ptr< SdrCaptionObj >();
+        return ScCaptionPtr();
 
     // prepare visible rectangle (add default distance to all borders)
     tools::Rectangle aVisRect(
@@ -834,7 +1182,7 @@ std::shared_ptr< SdrCaptionObj > ScNoteUtil::CreateTempCaption(
     ScCaptionCreator aCreator( rDoc, rPos, bTailFront );
 
     // insert caption into page (needed to set caption text)
-    rDrawPage.InsertObject( aCreator.GetCaption().get() );
+    aCreator.GetCaption().insertToDrawPage( rDrawPage );
 
     SdrCaptionObj* pCaption = aCreator.GetCaption().get();  // just for ease of use
 
@@ -873,22 +1221,14 @@ ScPostIt* ScNoteUtil::CreateNoteFromCaption(
         ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj* pCaption )
 {
     ScNoteData aNoteData( true/*bShown*/ );
-    aNoteData.m_pCaption.reset(pCaption, [](SdrCaptionObj* pCaptionObj) {
-        SdrPage* pDrawPage(pCaptionObj->getSdrPageFromSdrObject());
-        if (pDrawPage)
-        {
-            pDrawPage->RemoveObject(pCaptionObj->GetOrdNum());
-        }
-        SdrObject* pObj = pCaptionObj;
-        SdrObject::Free(pObj);
-    });
+    aNoteData.mxCaption.reset( pCaption );
     ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
     pNote->AutoStamp();
 
     rDoc.SetNote(rPos, std::unique_ptr<ScPostIt>(pNote));
 
     // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
-    ScNoteCaptionCreator aCreator( rDoc, rPos, aNoteData.m_pCaption, true/*bShown*/ );
+    ScNoteCaptionCreator aCreator( rDoc, rPos, aNoteData.mxCaption, true/*bShown*/ );
 
     return pNote;
 }
diff --git a/sc/source/core/tool/detfunc.cxx b/sc/source/core/tool/detfunc.cxx
index a370aa473236..16cb31855212 100644
--- a/sc/source/core/tool/detfunc.cxx
+++ b/sc/source/core/tool/detfunc.cxx
@@ -1425,7 +1425,7 @@ void ScDetectiveFunc::UpdateAllComments( ScDocument& rDoc )
                 {
                     ScPostIt* pNote = rDoc.GetNote( pData->maStart );
                     // caption should exist, we iterate over drawing objects...
-                    OSL_ENSURE( pNote && (pNote->GetCaption().get() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" );
+                    OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" );
                     if( pNote )
                     {
                         ScCommentData aData( rDoc, pModel );
diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx
index 5c53e0588693..8abfeb098bdf 100644
--- a/sc/source/filter/excel/xeescher.cxx
+++ b/sc/source/filter/excel/xeescher.cxx
@@ -1185,7 +1185,7 @@ XclExpNote::XclExpNote(const XclExpRoot& rRoot, const ScAddress& rScPos,
             // TODO: additional text
             if( pScNote )
             {
-                if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ).get() )
+                if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) )
                 {
                     lcl_GetFromTo( rRoot, pCaption->GetLogicRect(), maScPos.Tab(), maCommentFrom, maCommentTo );
                     if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 000a48550c91..144fc4470e32 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -2357,7 +2357,7 @@ void ScXMLExport::collectAutoStyles()
                     OSL_ENSURE( pNote, "note not found" );
                     if (pNote)
                     {
-                        const std::shared_ptr< SdrCaptionObj >& pDrawObj = pNote->GetOrCreateCaption( aPos );
+                        SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
                         // all uno shapes are created anyway in CollectSharedData
                         uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
                         if (xShapeProperties.is())
@@ -2398,7 +2398,7 @@ void ScXMLExport::collectAutoStyles()
                     OSL_ENSURE( pNote, "note not found" );
                     if (pNote)
                     {
-                        const std::shared_ptr< SdrCaptionObj >& pDrawObj = pNote->GetOrCreateCaption( aPos );
+                        SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
                         uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
                         uno::Reference<beans::XPropertySet> xParaProp(
                             lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
@@ -2429,7 +2429,7 @@ void ScXMLExport::collectAutoStyles()
                     OSL_ENSURE( pNote, "note not found" );
                     if (pNote)
                     {
-                        const std::shared_ptr< SdrCaptionObj >& pDrawObj = pNote->GetOrCreateCaption( aPos );
+                        SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
                         uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
                         uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
                         ScDrawTextCursor* pCursor = ScDrawTextCursor::getImplementation( xCursorProp );
@@ -3572,7 +3572,7 @@ void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >
         // TODO : notes
         //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
         // and should be in sync with pCurrentCell
-        const std::shared_ptr< SdrCaptionObj >& pNoteCaption = pNote->GetOrCreateCaption(pCurrentCell->maCellAddress);
+        SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(pCurrentCell->maCellAddress);
         uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
         if (xCurrentShape.get()!=xShape.get())
             return;
@@ -3629,7 +3629,7 @@ void ScXMLExport::WriteAnnotation(ScMyCell& rMyCell)
 
         pCurrentCell = &rMyCell;
 
-        const std::shared_ptr< SdrCaptionObj >& pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
+        SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
         if (pNoteCaption)
         {
             uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index 6c184421f210..588307ce3fc0 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -618,6 +618,34 @@ void ScModule::SetDragJump(
     m_pDragData->aJumpText = rText;
 }
 
+ScDocument* ScModule::GetClipDoc()
+{
+    // called from document
+    SfxViewFrame* pViewFrame = nullptr;
+    ScTabViewShell* pViewShell = nullptr;
+    css::uno::Reference<css::datatransfer::XTransferable2> xTransferable;
+
+    if ((pViewShell = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current())))
+        xTransferable.set(ScTabViewShell::GetClipData(pViewShell->GetViewData().GetActiveWin()));
+    else if ((pViewShell = dynamic_cast<ScTabViewShell*>(SfxViewShell::GetFirst())))
+        xTransferable.set(ScTabViewShell::GetClipData(pViewShell->GetViewData().GetActiveWin()));
+    else if ((pViewFrame = SfxViewFrame::GetFirst()))
+    {
+        css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard =
+            pViewFrame->GetWindow().GetClipboard();
+        xTransferable.set(xClipboard.is() ? xClipboard->getContents() : nullptr, css::uno::UNO_QUERY);
+    }
+
+    const ScTransferObj* pObj = ScTransferObj::GetOwnClipboard(xTransferable);
+    if (pObj)
+    {
+        ScDocument* pDoc = pObj->GetDocument();
+        assert((!pDoc || pDoc->IsClipboard()) && "Document is not clipboard, how can that be?");
+        return pDoc;
+    }
+
+    return nullptr;
+}
 
 void ScModule::SetSelectionTransfer( ScSelectionTransferObj* pNew )
 {
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index c5c9fcc23b1e..687ac5ad7ffe 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -1202,7 +1202,7 @@ bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
     if (ScViewData* pViewData = ScDocShell::GetViewData())
     {
         if (ScDrawView* pDrawView = pViewData->GetScDrawView())
-            pDrawView->SyncForGrid( pNote->GetCaption().get() );
+            pDrawView->SyncForGrid( pNote->GetCaption());
     }
 
     rDocShell.SetDocumentModified();
@@ -1279,7 +1279,7 @@ void ScDocFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, c
         }
 
         // create the undo action
-        if( pUndoMgr && (aOldData.m_pCaption || aNewData.m_pCaption) )
+        if( pUndoMgr && (aOldData.mxCaption || aNewData.mxCaption) )
             pUndoMgr->AddUndoAction( std::make_unique<ScUndoReplaceNote>( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
 
         // repaint cell (to make note marker visible)
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index d35afd2175c2..8e66516e2442 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -108,7 +108,6 @@
 #include <optsolver.hxx>
 #include <sheetdata.hxx>
 #include <tabprotection.hxx>
-#include <transobj.hxx>
 #include <docparam.hxx>
 #include "docshimp.hxx"
 #include <sizedev.hxx>
@@ -1042,7 +1041,7 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
             // document's drawing layer pages and what not, which otherwise when
             // pasting to another document after this document was destructed would
             // attempt to access non-existing data. Preserve the text data though.
-            ScDocument* pClipDoc = GetClipDoc();
+            ScDocument* pClipDoc = ScModule::GetClipDoc();
             if (pClipDoc)
                 pClipDoc->ClosingClipboardSource();
         }
@@ -2721,23 +2720,6 @@ std::unique_ptr<ScDocFunc> ScDocShell::CreateDocFunc()
     return std::make_unique<ScDocFuncDirect>( *this );
 }
 
-ScDocument* ScDocShell::GetClipDoc()
-{
-    vcl::Window* pWin = nullptr;
-    if (ScTabViewShell* pViewShell = GetBestViewShell())
-        pWin = pViewShell->GetViewData().GetActiveWin();
-
-    const ScTransferObj* pObj = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
-    if (pObj)
-    {
-        ScDocument* pDoc = pObj->GetDocument();
-        assert((!pDoc || pDoc->IsClipboard()) && "Document is not clipboard, how can that be?");
-        return pDoc;
-    }
-
-    return nullptr;
-}
-
 ScDocShell::ScDocShell( const SfxModelFlags i_nSfxCreationFlags ) :
     SfxObjectShell( i_nSfxCreationFlags ),
     m_aDocument       ( SCDOCMODE_DOCUMENT, this ),
diff --git a/sc/source/ui/drawfunc/futext3.cxx b/sc/source/ui/drawfunc/futext3.cxx
index 43e649b687cc..5c1d3a6ed00b 100644
--- a/sc/source/ui/drawfunc/futext3.cxx
+++ b/sc/source/ui/drawfunc/futext3.cxx
@@ -58,7 +58,7 @@ void FuText::StopEditMode()
     {
         aNotePos = pCaptData->maStart;
         pNote = rDoc.GetNote( aNotePos );
-        OSL_ENSURE( pNote && (pNote->GetCaption().get() == pObject), "FuText::StopEditMode - missing or invalid cell note" );
+        OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "FuText::StopEditMode - missing or invalid cell note" );
     }
 
     ScDocShell* pDocShell = rViewData.GetDocShell();
@@ -78,7 +78,7 @@ void FuText::StopEditMode()
             /*  Note has been created before editing, if first undo action is
                 an insert action. Needed below to decide whether to drop the
                 undo if editing a new note has been cancelled. */
-            bNewNote = (pCalcUndo->GetActionCount() > 0) && dynamic_cast< ScUndoNewSdrCaptionObj* >(pCalcUndo->GetAction( 0 ));
+            bNewNote = (pCalcUndo->GetActionCount() > 0) && dynamic_cast< SdrUndoNewObj* >(pCalcUndo->GetAction( 0 ));
 
             // create a "insert note" undo action if needed
             if( bNewNote )
diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx
index e68a6d5bc560..2d8525fd7e41 100644
--- a/sc/source/ui/inc/docsh.hxx
+++ b/sc/source/ui/inc/docsh.hxx
@@ -372,8 +372,6 @@ public:
 
     ScTabViewShell* GetBestViewShell( bool bOnlyVisible = true );
 
-    ScDocument*   GetClipDoc();
-
     void            SetDocumentModifiedPending( bool bVal )
                         { m_bDocumentModifiedPending = bVal; }
     bool            IsDocumentModifiedPending() const
diff --git a/sc/source/ui/inc/notemark.hxx b/sc/source/ui/inc/notemark.hxx
index bb82f530a323..81f1d7cb2056 100644
--- a/sc/source/ui/inc/notemark.hxx
+++ b/sc/source/ui/inc/notemark.hxx
@@ -25,6 +25,7 @@
 #include <vcl/vclptr.hxx>
 #include <tools/gen.hxx>
 #include <address.hxx>
+#include <postit.hxx>
 
 namespace vcl { class Window; }
 
@@ -49,7 +50,7 @@ private:
 
     tools::Rectangle       m_aRect;
     std::unique_ptr<SdrModel>           m_pModel;
-    std::shared_ptr< SdrCaptionObj >    m_xObject;
+    ScCaptionPtr    m_xObject;
     bool            m_bVisible;
     DECL_LINK( TimeHdl, Timer*, void );
 
diff --git a/sc/source/ui/inc/undocell.hxx b/sc/source/ui/inc/undocell.hxx
index 3227c33f1635..889d0e226f72 100644
--- a/sc/source/ui/inc/undocell.hxx
+++ b/sc/source/ui/inc/undocell.hxx
@@ -34,51 +34,6 @@ class ScDocShell;
 class ScPatternAttr;
 class ScRangeName;
 
-class ScUndoSdrCaptionObj: public SdrUndoAction
-{
-protected:
-    SdrObjList* m_pObjList;
-    sal_uInt32 const  m_nOrdNum;
-    std::shared_ptr< SdrCaptionObj > m_pCaptionObj;
-
-    void UnmarkObject();
-    void BroadcastSwitchToPage();
-    OUString GetDescriptionString( const char* pStrCacheID, bool bRepeat = false ) const;
-
-public:
-    ScUndoSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >&);
-    virtual ~ScUndoSdrCaptionObj() override;
-};
-
-class ScUndoDelSdrCaptionObj: public ScUndoSdrCaptionObj
-{
-public:
-    ScUndoDelSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >& pCaptionObj);
-    virtual ~ScUndoDelSdrCaptionObj() override;
-
-    virtual void    Undo() override;
-    virtual void    Redo() override;
-
-    virtual OUString GetComment() const override;
-    virtual OUString GetSdrRepeatComment(SdrView& rView) const override;
-
-    virtual void SdrRepeat(SdrView& rView) override;
-    virtual bool CanSdrRepeat(SdrView& rView) const override;
-};
-
-
-class ScUndoNewSdrCaptionObj: public ScUndoSdrCaptionObj
-{
-public:
-    ScUndoNewSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >& pCaptionObj);
-    virtual ~ScUndoNewSdrCaptionObj() override;
-
-    virtual void    Undo() override;
-    virtual void    Redo() override;
-
-    virtual OUString GetComment() const override;
-};
-
 class ScUndoCursorAttr: public ScSimpleUndo
 {
 public:
diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx
index 5e67ccf16861..a343081d64be 100644
--- a/sc/source/ui/undo/undocell.cxx
+++ b/sc/source/ui/undo/undocell.cxx
@@ -25,12 +25,6 @@
 #include <editeng/justifyitem.hxx>
 #include <svl/zforlist.hxx>
 #include <svl/sharedstringpool.hxx>
-#include <svx/dialmgr.hxx>
-#include <svx/e3dsceneupdater.hxx>
-#include <svx/svdocapt.hxx>
-#include <svx/svdogrp.hxx>
-#include <svx/svdviter.hxx>
-#include <svx/strings.hrc>
 #include <sfx2/app.hxx>
 
 #include <attrib.hxx>
@@ -722,182 +716,22 @@ bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
 }
 
 
-ScUndoSdrCaptionObj::ScUndoSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >& pCaptionObj)
-    : SdrUndoAction(pCaptionObj->getSdrModelFromSdrObject())
-    , m_pObjList(pCaptionObj->getParentSdrObjListFromSdrObject())
-    , m_nOrdNum(pCaptionObj->GetOrdNum())
-    , m_pCaptionObj(pCaptionObj)
-{
-}
-
-ScUndoSdrCaptionObj::~ScUndoSdrCaptionObj()
-{
-}
-
-void ScUndoSdrCaptionObj::BroadcastSwitchToPage()
-{
-    if (m_pCaptionObj && m_pCaptionObj->IsInserted() && m_pCaptionObj->getSdrPageFromSdrObject())
-    {
-        SdrHint aHint(SdrHintKind::SwitchToPage, *m_pCaptionObj, m_pCaptionObj->getSdrPageFromSdrObject());
-        rMod.Broadcast(aHint);
-    }
-}
-
-void ScUndoSdrCaptionObj::UnmarkObject()
-{
-    SdrViewIter aIter( m_pCaptionObj.get() );
-    for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
-    {
-        pView->MarkObj( m_pCaptionObj.get(), pView->GetSdrPageView(), true );
-    }
-}
-
-OUString ScUndoSdrCaptionObj::GetDescriptionString(const char* pStrCacheID, bool bRepeat ) const
-{
-    const OUString rStr {SvxResId(pStrCacheID)};
-
-    const sal_Int32 nPos = rStr.indexOf("%1");
-    if (nPos < 0)
-        return rStr;
-
-    if (bRepeat)
-        return rStr.replaceAt(nPos, 2, SvxResId(STR_ObjNameSingulPlural));
-
-    return rStr.replaceAt(nPos, 2, m_pCaptionObj->TakeObjNameSingul());
-}
-
-ScUndoDelSdrCaptionObj::ScUndoDelSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >& pCaptionObj)
-    : ScUndoSdrCaptionObj(pCaptionObj)
-{
-}
-
-ScUndoDelSdrCaptionObj::~ScUndoDelSdrCaptionObj()
-{
-
-}
-
-void ScUndoDelSdrCaptionObj::Undo()
-{
-    // Trigger PageChangeCall
-    BroadcastSwitchToPage();
-
-    if (!m_pCaptionObj->IsInserted())
-    {
-        Point aOwnerAnchorPos(0, 0);
-
-        if (dynamic_cast< const SdrObjGroup* >(m_pObjList->getSdrObjectFromSdrObjList()) != nullptr)
-        {
-            aOwnerAnchorPos = m_pObjList->getSdrObjectFromSdrObjList()->GetAnchorPos();
-        }
-
-        E3DModifySceneSnapRectUpdater aUpdater(m_pObjList->getSdrObjectFromSdrObjList());
-        m_pObjList->InsertObject(m_pCaptionObj.get(), m_nOrdNum);
-
-        if(aOwnerAnchorPos.X() || aOwnerAnchorPos.Y())
-        {
-            m_pCaptionObj->NbcSetAnchorPos(aOwnerAnchorPos);
-        }
-    }
-
-}
-
-void ScUndoDelSdrCaptionObj::Redo()
-{
-    if (m_pCaptionObj->IsInserted())
-    {
-        UnmarkObject();
-        E3DModifySceneSnapRectUpdater aUpdater(m_pCaptionObj.get());
-        m_pObjList->RemoveObject(m_nOrdNum);
-    }
-
-    // Trigger PageChangeCall
-    BroadcastSwitchToPage();
-}
-
-OUString ScUndoDelSdrCaptionObj::GetComment() const
-{
-    return GetDescriptionString(STR_EditDelete);
-}
-
-void ScUndoDelSdrCaptionObj::SdrRepeat(SdrView& rView)
-{
-    rView.DeleteMarked();
-}
-
-bool ScUndoDelSdrCaptionObj::CanSdrRepeat(SdrView& rView) const
-{
-    return rView.AreObjectsMarked();
-}
-
-OUString ScUndoDelSdrCaptionObj::GetSdrRepeatComment(SdrView& /*rView*/) const
-{
-    return GetDescriptionString(STR_EditDelete, true);
-}
-
-ScUndoNewSdrCaptionObj::ScUndoNewSdrCaptionObj(const std::shared_ptr< SdrCaptionObj >& pCaptionObj)
-    : ScUndoSdrCaptionObj(pCaptionObj)
-{
-}
-
-ScUndoNewSdrCaptionObj::~ScUndoNewSdrCaptionObj()
-{
-}
-
-void ScUndoNewSdrCaptionObj::Undo()
-{
-    // Trigger PageChangeCall
-    BroadcastSwitchToPage();
-
-    if (m_pCaptionObj->IsInserted())
-    {
-        UnmarkObject();
-        m_pObjList->RemoveObject(m_nOrdNum);
-    }
-}
-
-void ScUndoNewSdrCaptionObj::Redo()
-{
-    if (!m_pCaptionObj->IsInserted())
-    {
-        Point aAnchorPos( 0, 0 );
-
-        if (dynamic_cast<const SdrObjGroup*>(m_pObjList->getSdrObjectFromSdrObjList()) != nullptr)
-        {
-            aAnchorPos = m_pCaptionObj->GetAnchorPos();
-        }
-
-        m_pObjList->InsertObject(m_pCaptionObj.get(), m_nOrdNum);
-
-        // Arcs lose position when grouped (#i45952#)
-        if ( aAnchorPos.X() || aAnchorPos.Y() )
-        {
-            m_pCaptionObj->NbcSetAnchorPos( aAnchorPos );
-        }
-    }
-
-    // Trigger PageChangeCall
-    BroadcastSwitchToPage();
-}
-
-OUString ScUndoNewSdrCaptionObj::GetComment() const
-{
-    return GetDescriptionString(STR_UndoInsertObj);
-}
-
 ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
         const ScNoteData& rNoteData, bool bInsert, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
     ScSimpleUndo( &rDocShell ),
     maPos( rPos ),
     mpDrawUndo( std::move(pDrawUndo) )
 {
-    OSL_ENSURE( rNoteData.m_pCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
+    OSL_ENSURE( rNoteData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
     if (bInsert)
     {
         maNewData = rNoteData;
+        maNewData.mxCaption.setNotOwner();
     }
     else
     {
         maOldData = rNoteData;
+        maOldData.mxCaption.setNotOwner();
     }
 }
 
@@ -909,8 +743,10 @@ ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rP
     maNewData( rNewData ),
     mpDrawUndo( std::move(pDrawUndo) )
 {
-    OSL_ENSURE( maOldData.m_pCaption || maNewData.m_pCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
+    OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
     OSL_ENSURE( !maOldData.mxInitData.get() && !maNewData.mxInitData.get(), "ScUndoReplaceNote::ScUndoReplaceNote - unexpected uninitialized note" );
+    maOldData.mxCaption.setNotOwner();
+    maNewData.mxCaption.setNotOwner();
 }
 
 ScUndoReplaceNote::~ScUndoReplaceNote()
@@ -955,13 +791,13 @@ bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
 
 OUString ScUndoReplaceNote::GetComment() const
 {
-    return ScResId( maNewData.m_pCaption ?
-        (maOldData.m_pCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
+    return ScResId( maNewData.mxCaption ?
+        (maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
 }
 
 void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
 {
-    if( rNoteData.m_pCaption )
+    if( rNoteData.mxCaption )
     {
         ScDocument& rDoc = pDocShell->GetDocument();
         OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
@@ -973,7 +809,7 @@ void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
 
 void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
 {
-    if( rNoteData.m_pCaption )
+    if( rNoteData.mxCaption )
     {
         ScDocument& rDoc = pDocShell->GetDocument();
         OSL_ENSURE( rDoc.GetNote(maPos), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
diff --git a/sc/source/ui/unoobj/editsrc.cxx b/sc/source/ui/unoobj/editsrc.cxx
index 64e028070496..2d426d10533e 100644
--- a/sc/source/ui/unoobj/editsrc.cxx
+++ b/sc/source/ui/unoobj/editsrc.cxx
@@ -135,7 +135,7 @@ std::unique_ptr<SvxEditSource> ScAnnotationEditSource::Clone() const
 SdrObject* ScAnnotationEditSource::GetCaptionObj()
 {
     ScPostIt* pNote = pDocShell->GetDocument().GetNote(aCellPos);
-    return pNote ? pNote->GetOrCreateCaption( aCellPos ).get() : nullptr;
+    return pNote ? pNote->GetOrCreateCaption( aCellPos ) : nullptr;
 }
 
 SvxTextForwarder* ScAnnotationEditSource::GetTextForwarder()
diff --git a/sc/source/ui/unoobj/notesuno.cxx b/sc/source/ui/unoobj/notesuno.cxx
index e1e2b8f25487..80bcf63c626f 100644
--- a/sc/source/ui/unoobj/notesuno.cxx
+++ b/sc/source/ui/unoobj/notesuno.cxx
@@ -216,7 +216,7 @@ uno::Reference < drawing::XShape > SAL_CALL ScAnnotationObj::getAnnotationShape(
     SolarMutexGuard aGuard;
     uno::Reference < drawing::XShape > xShape;
     if( const ScPostIt* pNote = ImplGetNote() )
-        if( SdrObject* pCaption = pNote->GetOrCreateCaption( aCellPos ).get() )
+        if( SdrObject* pCaption = pNote->GetOrCreateCaption( aCellPos ) )
             xShape.set( pCaption->getUnoShape(), uno::UNO_QUERY );
     return xShape;
 }
diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx
index 26cd3873ea61..b993fa8c6c50 100644
--- a/sc/source/ui/view/drawview.cxx
+++ b/sc/source/ui/view/drawview.cxx
@@ -871,7 +871,7 @@ void ScDrawView::DeleteMarked()
         {
             // rescue note data for undo (with pointer to caption object)
             ScNoteData aNoteData = pNote->GetNoteData();
-            OSL_ENSURE( aNoteData.m_pCaption.get() == pCaptObj, "ScDrawView::DeleteMarked - caption object does not match" );
+            OSL_ENSURE( aNoteData.mxCaption.get() == pCaptObj, "ScDrawView::DeleteMarked - caption object does not match" );
             // collect the drawing undo action created while deleting the note
             if( bUndo )
                 pDrawLayer->BeginCalcUndo(false);
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 5310e1a8cbed..cc908df98225 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -362,7 +362,7 @@ static void lcl_UnLockComment( ScDrawView* pView, const Point& rPos, const ScVie
     ScDocument& rDoc = *pViewData->GetDocument();
     ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
     ScPostIt* pNote = rDoc.GetNote( aCellPos );
-    SdrObject* pObj = pNote ? pNote->GetCaption().get() : nullptr;
+    SdrObject* pObj = pNote ? pNote->GetCaption() : nullptr;
     if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
     {
         const ScProtectionAttr* pProtAttr = rDoc.GetAttr( aCellPos, ATTR_PROTECTION );
diff --git a/sc/source/ui/view/notemark.cxx b/sc/source/ui/view/notemark.cxx
index 49901c9dff11..0868f557cfb5 100644
--- a/sc/source/ui/view/notemark.cxx
+++ b/sc/source/ui/view/notemark.cxx
@@ -65,7 +65,7 @@ ScNoteMarker::ScNoteMarker( vcl::Window* pWin, vcl::Window* pRight, vcl::Window*
 ScNoteMarker::~ScNoteMarker()
 {
     if (m_pModel)
-        m_xObject.reset();     // deleting pModel also deletes the SdrCaptionObj
+        m_xObject.release();     // deleting pModel also deletes the SdrCaptionObj
 
     InvalidateWin();
 
diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx
index bb8855ddfb03..27386dd4f5b2 100644
--- a/sc/source/ui/view/tabview5.cxx
+++ b/sc/source/ui/view/tabview5.cxx
@@ -649,7 +649,7 @@ void ScTabView::OnLOKNoteStateChanged(const ScPostIt* pNote)
     if (!comphelper::LibreOfficeKit::isActive())
         return;
 
-    const SdrCaptionObj* pCaption = pNote->GetCaption().get();
+    const SdrCaptionObj* pCaption = pNote->GetCaption();
     if (!pCaption) return;
 
     tools::Rectangle aRect = pCaption->GetLogicRect();
diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx
index 4174848fdc80..2332f88cdf05 100644
--- a/sc/source/ui/view/viewfun6.cxx
+++ b/sc/source/ui/view/viewfun6.cxx
@@ -496,7 +496,7 @@ void ScViewFunc::EditNote()
         /*  Drawing object has been created in ScDocument::GetOrCreateNote() or
             in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
             return a caption object. */
-        if( SdrCaptionObj* pCaption = pNote->GetCaption().get() )
+        if( SdrCaptionObj* pCaption = pNote->GetCaption() )
         {
             if ( ScDrawView* pScDrawView = GetScDrawView() )
                pScDrawView->SyncForGrid( pCaption );


More information about the Libreoffice-commits mailing list