sw/inc/unotext.hxx                 |   31 +++-
 sw/inc/unotextrange.hxx            |   28 +++
 sw/source/core/unocore/unoobj2.cxx |  267 ++++++++++++++++---------------------
 sw/source/core/unocore/unotext.cxx |  231 ++++++++++++++------------------
 4 files changed, 269 insertions(+), 288 deletions(-)

New commits:
commit 168eb2e64b7ad08645f62b45e15af2ee7260100c
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sun Jun 23 19:44:06 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Jun 24 09:20:05 2024 +0200

    tdf#144208 speedup doc with lots of redline(15)
    
    SwXText is heavily used. Reduce the allocation cost of
    this class by de-pimpl'ing this class.
    
    Change-Id: I01b06c978075ae312131dfff29b4f304caf69e18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169359
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/sw/inc/unotext.hxx b/sw/inc/unotext.hxx
index 67a3c60bddb1..73fc1e4c57ba 100644
--- a/sw/inc/unotext.hxx
+++ b/sw/inc/unotext.hxx
@@ -38,10 +38,13 @@ namespace com::sun::star {
     }
 }
 
+class SfxItemPropertySet;
 class SwDoc;
 class SwStartNode;
+class SwNodeRange;
 class SwPaM;
 class SwXTextCursor;
+class SwXParagraph;
 
 class SAL_DLLPUBLIC_RTTI SwXText
     : public css::lang::XTypeProvider
@@ -55,9 +58,6 @@ class SAL_DLLPUBLIC_RTTI SwXText
 
 private:
 
-    class Impl;
-    ::sw::UnoImplPtr<Impl> m_pImpl;
-
     virtual void PrepareForAttach(
             css::uno::Reference< css::text::XTextRange > & xRange,
             SwPaM const & rPam);
@@ -65,11 +65,22 @@ private:
     /// @throws css::uno::RuntimeException
     virtual bool CheckForOwnMemberMeta(
             const SwPaM & rPam, const bool bAbsorb);
+    bool CheckForOwnMember(const SwPaM & rPaM);
+    sal_Int16 ComparePositions(
+            const css::uno::Reference<css::text::XTextRange>& xPos1,
+            const css::uno::Reference<css::text::XTextRange>& xPos2);
+    rtl::Reference<SwXParagraph> finishOrAppendParagraph(
+            const css::uno::Sequence< css::beans::PropertyValue > & 
rProperties,
+            const css::uno::Reference< css::text::XTextRange >& 
xInsertPosition);
+    void ConvertCell(
+            const css::uno::Sequence< css::uno::Reference< 
css::text::XTextRange > > & rCell,
+            std::vector<SwNodeRange> & rRowNodes,
+            SwNodeRange *const pLastCell);
 
 protected:
 
-    bool            IsValid() const;
-    void            Invalidate();
+    bool            IsValid() const { return m_bIsValid; }
+    void            Invalidate() { m_bIsValid = false; }
     void            SetDoc(SwDoc *const pDoc);
 
     virtual ~SwXText();
@@ -81,8 +92,8 @@ public:
 
     SwXText(SwDoc *const pDoc, const CursorType eType);
 
-    const SwDoc*    GetDoc() const;
-          SwDoc*    GetDoc();
+    const SwDoc*    GetDoc() const { return m_pDoc; }
+          SwDoc*    GetDoc() { return m_pDoc; }
 
     // declare these here to resolve ambiguity when we declared 
rtl::Reference<subtype-of-SwXText>
     virtual void SAL_CALL acquire() override = 0;
@@ -233,6 +244,12 @@ public:
             const css::uno::Reference< css::text::XTextContent>& xSuccessor) 
override;
     virtual void SAL_CALL removeTextContentAfter(
             const css::uno::Reference< css::text::XTextContent>& xPredecessor) 
override;
+
+private:
+    SfxItemPropertySet const&   m_rPropSet;
+    const CursorType            m_eType;
+    SwDoc *                     m_pDoc;
+    bool                        m_bIsValid;
 };
 
 #endif // INCLUDED_SW_INC_UNOTEXT_HXX
diff --git a/sw/source/core/unocore/unotext.cxx 
b/sw/source/core/unocore/unotext.cxx
index 42165b110e68..edfeaf1e98c1 100644
--- a/sw/source/core/unocore/unotext.cxx
+++ b/sw/source/core/unocore/unotext.cxx
@@ -77,53 +77,56 @@ using namespace ::com::sun::star;
 
 constexpr OUString cInvalidObject = u"this object is invalid"_ustr;
 
-class SwXText::Impl
-{
-
-public:
-    SwXText &                   m_rThis;
-    SfxItemPropertySet const&   m_rPropSet;
-    const CursorType            m_eType;
-    SwDoc *                     m_pDoc;
-    bool                        m_bIsValid;
-
-    Impl(   SwXText & rThis,
-            SwDoc *const pDoc, const CursorType eType)
-        : m_rThis(rThis)
-        , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
-        , m_eType(eType)
-        , m_pDoc(pDoc)
-        , m_bIsValid(nullptr != pDoc)
-    {
-    }
-
-    /// @throws lang::IllegalArgumentException
-    /// @throws uno::RuntimeException
-    rtl::Reference<SwXParagraph>
-        finishOrAppendParagraph(
-            const uno::Sequence< beans::PropertyValue >&
-                rCharacterAndParagraphProperties,
-            const uno::Reference< text::XTextRange >& xInsertPosition);
-
-    /// @throws lang::IllegalArgumentException
-    /// @throws uno::RuntimeException
-    sal_Int16 ComparePositions(
-            const uno::Reference<text::XTextRange>& xPos1,
-            const uno::Reference<text::XTextRange>& xPos2);
-
-    /// @throws lang::IllegalArgumentException
-    /// @throws uno::RuntimeException
-    bool CheckForOwnMember(const SwPaM & rPaM);
-
-    void ConvertCell(
-            const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
-            std::vector<SwNodeRange> & rRowNodes,
-            SwNodeRange *const pLastCell);
-
-};
+//class SwXText::Impl
+//{
+//
+//public:
+//    SwXText &                   m_rThis;
+//    SfxItemPropertySet const&   m_rPropSet;
+//    const CursorType            m_eType;
+//    SwDoc *                     m_pDoc;
+//    bool                        m_bIsValid;
+//
+//    Impl(   SwXText & rThis,
+//            SwDoc *const pDoc, const CursorType eType)
+//        : m_rThis(rThis)
+//        , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
+//        , m_eType(eType)
+//        , m_pDoc(pDoc)
+//        , m_bIsValid(nullptr != pDoc)
+//    {
+//    }
+//
+//    /// @throws lang::IllegalArgumentException
+//    /// @throws uno::RuntimeException
+//    rtl::Reference<SwXParagraph>
+//        finishOrAppendParagraph(
+//            const uno::Sequence< beans::PropertyValue >&
+//                rCharacterAndParagraphProperties,
+//            const uno::Reference< text::XTextRange >& xInsertPosition);
+//
+//    /// @throws lang::IllegalArgumentException
+//    /// @throws uno::RuntimeException
+//    sal_Int16 ComparePositions(
+//            const uno::Reference<text::XTextRange>& xPos1,
+//            const uno::Reference<text::XTextRange>& xPos2);
+//
+//    /// @throws lang::IllegalArgumentException
+//    /// @throws uno::RuntimeException
+//    bool CheckForOwnMember(const SwPaM & rPaM);
+//
+//    void ConvertCell(
+//            const uno::Sequence< uno::Reference< text::XTextRange > > & 
rCell,
+//            std::vector<SwNodeRange> & rRowNodes,
+//            SwNodeRange *const pLastCell);
+//
+//};
 
 SwXText::SwXText(SwDoc *const pDoc, const CursorType eType)
-    : m_pImpl( new SwXText::Impl(*this, pDoc, eType) )
+    : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
+    , m_eType(eType)
+    , m_pDoc(pDoc)
+    , m_bIsValid(nullptr != pDoc)
 {
 }
 
@@ -131,32 +134,11 @@ SwXText::~SwXText()
 {
 }
 
-const SwDoc * SwXText::GetDoc() const
-{
-    return m_pImpl->m_pDoc;
-}
-
-SwDoc * SwXText::GetDoc()
-{
-    return m_pImpl->m_pDoc;
-}
-
-bool SwXText::IsValid() const
-{
-    return m_pImpl->m_bIsValid;
-}
-
-void SwXText::Invalidate()
-{
-    m_pImpl->m_bIsValid = false;
-}
-
 void SwXText::SetDoc(SwDoc *const pDoc)
 {
-    OSL_ENSURE(!m_pImpl->m_pDoc || !pDoc,
-        "SwXText::SetDoc: already have a doc?");
-    m_pImpl->m_pDoc = pDoc;
-    m_pImpl->m_bIsValid = (nullptr != pDoc);
+    OSL_ENSURE(!m_pDoc || !pDoc, "SwXText::SetDoc: already have a doc?");
+    m_pDoc = pDoc;
+    m_bIsValid = (nullptr != pDoc);
 }
 
 void
@@ -166,7 +148,7 @@ SwXText::PrepareForAttach(uno::Reference< text::XTextRange 
> &, const SwPaM &)
 
 bool SwXText::CheckForOwnMemberMeta(const SwPaM &, const bool)
 {
-    OSL_ENSURE(CursorType::Meta != m_pImpl->m_eType, "should not be called!");
+    OSL_ENSURE(CursorType::Meta != m_eType, "should not be called!");
     return false;
 }
 
@@ -192,7 +174,7 @@ SwXText::createXTextCursor()
     {
         SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
         SwPosition aPos(rNode);
-        xRet = new SwXTextCursor(*GetDoc(), this, m_pImpl->m_eType, aPos);
+        xRet = new SwXTextCursor(*GetDoc(), this, m_eType, aPos);
         xRet->gotoStart(false);
     }
     return xRet;
@@ -347,7 +329,7 @@ SwXText::insertString(const uno::Reference< 
text::XTextRange >& xTextRange,
     }
 
     bool bForceExpandHints( false );
-    if (CursorType::Meta == m_pImpl->m_eType)
+    if (CursorType::Meta == m_eType)
     {
         try
         {
@@ -428,7 +410,7 @@ SwXText::insertControlCharacter(
 
     if (bAbsorb && aPam.HasMark())
     {
-        m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
+        m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
         aPam.DeleteMark();
     }
 
@@ -437,13 +419,13 @@ SwXText::insertControlCharacter(
     {
         case text::ControlCharacter::PARAGRAPH_BREAK :
             // a table cell now becomes an ordinary text cell!
-            m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
-            
m_pImpl->m_pDoc->getIDocumentContentOperations().SplitNode(*aPam.GetPoint(), 
false);
+            m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
+            
m_pDoc->getIDocumentContentOperations().SplitNode(*aPam.GetPoint(), false);
             break;
         case text::ControlCharacter::APPEND_PARAGRAPH:
         {
-            m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
-            
m_pImpl->m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPam.GetPoint());
+            m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
+            
m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPam.GetPoint());
 
             SwXTextRange *const pRange =
                 dynamic_cast<SwXTextRange*>(xTextRange.get());
@@ -468,7 +450,7 @@ SwXText::insertControlCharacter(
     }
     if (cIns)
     {
-        m_pImpl->m_pDoc->getIDocumentContentOperations().InsertString(
+        m_pDoc->getIDocumentContentOperations().InsertString(
                 aPam, OUString(cIns), nInsertFlags);
     }
 
@@ -528,7 +510,7 @@ SwXText::insertTextContent(
     // xContent->attach
     const SwStartNode* pOwnStartNode = GetStartNode();
     SwStartNodeType eSearchNodeType = SwNormalStartNode;
-    switch (m_pImpl->m_eType)
+    switch (m_eType)
     {
         case CursorType::Frame:      eSearchNodeType = SwFlyStartNode;       
break;
         case CursorType::TableText:    eSearchNodeType = SwTableBoxStartNode;  
break;
@@ -869,7 +851,7 @@ SwXText::setString(const OUString& rString)
     GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::START, nullptr);
     //insert an empty paragraph at the start and at the end to ensure that
     //all tables and sections can be removed by the selecting text::XTextCursor
-    if (CursorType::Meta != m_pImpl->m_eType)
+    if (CursorType::Meta != m_eType)
     {
         SwPosition aStartPos(*pStartNode);
         const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
@@ -914,10 +896,9 @@ SwXText::setString(const OUString& rString)
 //FIXME why is CheckForOwnMember duplicated in some insert methods?
 //  Description: Checks if pRange/pCursor are member of the same text 
interface.
 //              Only one of the pointers has to be set!
-bool SwXText::Impl::CheckForOwnMember(
-    const SwPaM & rPaM)
+bool SwXText::CheckForOwnMember(const SwPaM & rPaM)
 {
-    const rtl::Reference< SwXTextCursor > 
xOwnCursor(m_rThis.createXTextCursor());
+    const rtl::Reference< SwXTextCursor > xOwnCursor(createXTextCursor());
     const SwStartNode* pOwnStartNode =
         xOwnCursor->GetPaM()->GetPointNode().StartOfSectionNode();
     SwStartNodeType eSearchNodeType = SwNormalStartNode;
@@ -957,8 +938,7 @@ bool SwXText::Impl::CheckForOwnMember(
     return (pOwnStartNode == pTmp);
 }
 
-sal_Int16
-SwXText::Impl::ComparePositions(
+sal_Int16 SwXText::ComparePositions(
     const uno::Reference<text::XTextRange>& xPos1,
     const uno::Reference<text::XTextRange>& xPos2)
 {
@@ -1016,7 +996,7 @@ SwXText::compareRegionStarts(
     const uno::Reference<text::XTextRange> xStart1 = xRange1->getStart();
     const uno::Reference<text::XTextRange> xStart2 = xRange2->getStart();
 
-    return m_pImpl->ComparePositions(xStart1, xStart2);
+    return ComparePositions(xStart1, xStart2);
 }
 
 sal_Int16 SAL_CALL
@@ -1033,7 +1013,7 @@ SwXText::compareRegionEnds(
     uno::Reference<text::XTextRange> xEnd1 = xRange1->getEnd();
     uno::Reference<text::XTextRange> xEnd2 = xRange2->getEnd();
 
-    return m_pImpl->ComparePositions(xEnd1, xEnd2);
+    return ComparePositions(xEnd1, xEnd2);
 }
 
 uno::Reference< beans::XPropertySetInfo > SAL_CALL
@@ -1041,8 +1021,7 @@ SwXText::getPropertySetInfo()
 {
     SolarMutexGuard g;
 
-    static uno::Reference< beans::XPropertySetInfo > xInfo =
-        m_pImpl->m_rPropSet.getPropertySetInfo();
+    static uno::Reference< beans::XPropertySetInfo > xInfo = 
m_rPropSet.getPropertySetInfo();
     return xInfo;
 }
 
@@ -1065,7 +1044,7 @@ SwXText::getPropertyValue(
     }
 
     SfxItemPropertyMapEntry const*const pEntry =
-        m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
+        m_rPropSet.getPropertyMap().getByName(rPropertyName);
     if (!pEntry)
         throw beans::UnknownPropertyException("Unknown property: " + 
rPropertyName);
 
@@ -1144,7 +1123,7 @@ SwXText::finishParagraph(
 {
     SolarMutexGuard g;
 
-    return m_pImpl->finishOrAppendParagraph(rProperties, uno::Reference< 
text::XTextRange >());
+    return finishOrAppendParagraph(rProperties, uno::Reference< 
text::XTextRange >());
 }
 
 uno::Reference< text::XTextRange > SAL_CALL
@@ -1154,11 +1133,11 @@ SwXText::finishParagraphInsert(
 {
     SolarMutexGuard g;
 
-    return m_pImpl->finishOrAppendParagraph(rProperties, xInsertPosition);
+    return finishOrAppendParagraph(rProperties, xInsertPosition);
 }
 
 rtl::Reference<SwXParagraph>
-SwXText::Impl::finishOrAppendParagraph(
+SwXText::finishOrAppendParagraph(
         const uno::Sequence< beans::PropertyValue > & rProperties,
         const uno::Reference< text::XTextRange >& xInsertPosition)
 {
@@ -1167,7 +1146,7 @@ SwXText::Impl::finishOrAppendParagraph(
         throw  uno::RuntimeException();
     }
 
-    const SwStartNode* pStartNode = m_rThis.GetStartNode();
+    const SwStartNode* pStartNode = GetStartNode();
     if(!pStartNode)
     {
         throw  uno::RuntimeException();
@@ -1186,7 +1165,7 @@ SwXText::Impl::finishOrAppendParagraph(
     // the document.
     if (xInsertPosition.is())
     {
-        SwUnoInternalPaM aStartPam(*m_rThis.GetDoc());
+        SwUnoInternalPaM aStartPam(*GetDoc());
         ::sw::XTextRangeToSwPaM(aStartPam, xInsertPosition);
         aPam = aStartPam;
         aPam.SetMark();
@@ -1258,7 +1237,7 @@ SwXText::Impl::finishOrAppendParagraph(
     OSL_ENSURE(pTextNode, "no SwTextNode?");
     if (pTextNode)
     {
-        xRet = SwXParagraph::CreateXParagraph(*m_pDoc, pTextNode, &m_rThis);
+        xRet = SwXParagraph::CreateXParagraph(*m_pDoc, pTextNode, this);
     }
 
     return xRet;
@@ -1283,17 +1262,17 @@ SwXText::insertTextPortion(
     bool bIllegalException = false;
     bool bRuntimeException = false;
     OUString sMessage;
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, 
nullptr);
+    m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
 
     auto& rCursor(xTextCursor->GetCursor());
-    m_pImpl->m_pDoc->DontExpandFormat( *rCursor.Start() );
+    m_pDoc->DontExpandFormat( *rCursor.Start() );
 
     if (!rText.isEmpty())
     {
         SwNodeIndex const nodeIndex(rCursor.GetPoint()->GetNode(), -1);
         const sal_Int32 nContentPos = rCursor.GetPoint()->GetContentIndex();
         SwUnoCursorHelper::DocInsertStringSplitCR(
-            *m_pImpl->m_pDoc, rCursor, rText, false);
+            *m_pDoc, rCursor, rText, false);
         SwUnoCursorHelper::SelectPam(rCursor, true);
         rCursor.GetPoint()->Assign(nodeIndex.GetNode(), SwNodeOffset(+1), 
nContentPos);
     }
@@ -1316,10 +1295,10 @@ SwXText::insertTextPortion(
         sMessage = rRuntime.Message;
         bRuntimeException = true;
     }
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
+    m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
     if (bIllegalException || bRuntimeException)
     {
-        m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
+        m_pDoc->GetIDocumentUndoRedo().Undo();
         if (bIllegalException)
         {
             throw lang::IllegalArgumentException(sMessage, nullptr, 0);
@@ -1372,7 +1351,7 @@ SwXText::insertTextContentWithProperties(
     SwRewriter aRewriter;
     aRewriter.AddRule(UndoArg1, SwResId(STR_UNDO_INSERT_TEXTBOX));
 
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, 
&aRewriter);
+    m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, &aRewriter);
 
     // Any direct formatting ending at the insert position (xRange) should not
     // be expanded to cover the inserted content (xContent)
@@ -1399,12 +1378,12 @@ SwXText::insertTextContentWithProperties(
         catch (const uno::Exception& e)
         {
             css::uno::Any anyEx = cppu::getCaughtException();
-            m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, 
&aRewriter);
+            m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, 
&aRewriter);
             throw lang::WrappedTargetRuntimeException( e.Message,
                             uno::Reference< uno::XInterface >(), anyEx );
         }
     }
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, 
&aRewriter);
+    m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, &aRewriter);
     return xInsertPosition;
 }
 
@@ -1522,7 +1501,7 @@ SwXText::convertToTextFrame(
         pEndRange->Invalidate();
     }
 
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, 
nullptr );
+    m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
     bool bIllegalException = false;
     bool bRuntimeException = false;
     OUString sMessage;
@@ -1632,9 +1611,9 @@ SwXText::convertToTextFrame(
     // tdf#115094: do nothing if we have a graphic node
     o3tl::sorted_vector<const SdrObject*> aAnchoredObjectsByPtr;
     std::set<OUString> aAnchoredObjectsByName;
-    for (size_t i = 0; i < m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
+    for (size_t i = 0; i < m_pDoc->GetSpzFrameFormats()->size(); ++i)
     {
-        const SwFrameFormat* pFrameFormat = 
(*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
+        const SwFrameFormat* pFrameFormat = (*m_pDoc->GetSpzFrameFormats())[i];
         const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
         // note: Word can do at-char anchors in text frames - sometimes!
         // see testFlyInFly for why this checks only the edges of the 
selection,
@@ -1662,7 +1641,7 @@ SwXText::convertToTextFrame(
     oAnchorCheckPam.reset(); // clear SwContentIndex before deleting nodes
 
     const rtl::Reference<SwXTextFrame> xNewFrame =
-            SwXTextFrame::CreateXTextFrame(*m_pImpl->m_pDoc, nullptr);
+            SwXTextFrame::CreateXTextFrame(*m_pDoc, nullptr);
     try
     {
         for (const beans::PropertyValue& rValue : rFrameProperties)
@@ -1691,20 +1670,20 @@ SwXText::convertToTextFrame(
                     // move the anchor to the next paragraph
                     SwFormatAnchor 
aNewAnchor(xNewFrame->GetFrameFormat()->GetAnchor());
                     aNewAnchor.SetAnchor( aMovePam.Start() );
-                    m_pImpl->m_pDoc->SetAttr(
+                    m_pDoc->SetAttr(
                         aNewAnchor, *xNewFrame->GetFrameFormat() );
 
                     // also move frames anchored to us
-                    for (size_t i = 0; i < 
m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
+                    for (size_t i = 0; i < 
m_pDoc->GetSpzFrameFormats()->size(); ++i)
                     {
-                        SwFrameFormat* pFrameFormat = 
(*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
+                        SwFrameFormat* pFrameFormat = 
(*m_pDoc->GetSpzFrameFormats())[i];
                         if ((!pFrameFormat->GetName().isEmpty() && 
aAnchoredObjectsByName.find(pFrameFormat->GetName()) != 
aAnchoredObjectsByName.end() ) ||
                             ( pFrameFormat->GetName().isEmpty() && 
aAnchoredObjectsByPtr.find(pFrameFormat->FindSdrObject()) != 
aAnchoredObjectsByPtr.end()) )
                         {
                             // copy the anchor to the next paragraph
                             SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
                             aAnchor.SetAnchor(aMovePam.Start());
-                            m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat);
+                            m_pDoc->SetAttr(aAnchor, *pFrameFormat);
                         }
                         else
                         {
@@ -1724,7 +1703,7 @@ SwXText::convertToTextFrame(
                                     {
                                         SwFormatAnchor 
aAnchor(pFrameFormat->GetAnchor());
                                         aAnchor.SetAnchor(aMovePam.Start());
-                                        m_pImpl->m_pDoc->SetAttr(aAnchor, 
*pFrameFormat);
+                                        m_pDoc->SetAttr(aAnchor, 
*pFrameFormat);
                                     }
                                 }
                             }
@@ -1732,7 +1711,7 @@ SwXText::convertToTextFrame(
                     }
                 }
             }
-            
m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pStartPam);
+            m_pDoc->getIDocumentContentOperations().DelFullPara(*pStartPam);
         }
     }
     catch (const lang::IllegalArgumentException& rIllegal)
@@ -1753,28 +1732,28 @@ SwXText::convertToTextFrame(
         if (bParaBeforeInserted)
         {
             // todo: remove paragraph before frame
-            
m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
+            
m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
         }
         if (bParaAfterInserted)
         {
             xFrameTextCursor->gotoEnd(false);
             if (!bParaBeforeInserted)
-                
m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
+                
m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
             else
             {
                 // In case the frame has a table only, the cursor points to 
the end of the first cell of the table.
                 SwPaM 
aPaM(*xFrameTextCursor->GetPaM()->GetPointNode().FindSttNodeByType(SwFlyStartNode)->EndOfSectionNode());
                 // Now we have the end of the frame -- the node before that 
will be the paragraph we want to remove.
                 aPaM.GetPoint()->Adjust(SwNodeOffset(-1));
-                
m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(aPaM);
+                m_pDoc->getIDocumentContentOperations().DelFullPara(aPaM);
             }
         }
     }
 
-    m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
+    m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
     if (bIllegalException || bRuntimeException)
     {
-        m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
+        m_pDoc->GetIDocumentUndoRedo().Undo();
         if (bIllegalException)
         {
             throw lang::IllegalArgumentException(sMessage, nullptr, 0);
@@ -1814,7 +1793,7 @@ static bool lcl_SimilarPosition( const sal_Int32 nPos1, 
const sal_Int32 nPos2 )
     return abs( nPos1 - nPos2 ) < COL_POS_FUZZY;
 }
 
-void SwXText::Impl::ConvertCell(
+void SwXText::ConvertCell(
     const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
     std::vector<SwNodeRange> & rRowNodes,
     SwNodeRange *const pLastCell)
@@ -1823,7 +1802,7 @@ void SwXText::Impl::ConvertCell(
     {
         throw lang::IllegalArgumentException(
                 u"rCell needs to contain 2 elements"_ustr,
-                uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) 
);
+                uno::Reference< text::XTextCopy >( this ), sal_Int16( 2 ) );
     }
     const uno::Reference<text::XTextRange> xStartRange = rCell[0];
     const uno::Reference<text::XTextRange> xEndRange = rCell[1];
@@ -1838,7 +1817,7 @@ void SwXText::Impl::ConvertCell(
     {
         throw lang::IllegalArgumentException(
                 u"Start or End range cannot be resolved to a SwPaM"_ustr,
-                uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) 
);
+                uno::Reference< text::XTextCopy >( this ), sal_Int16( 2 ) );
     }
 
     SwNodeRange aTmpRange(aStartCellPam.Start()->GetNode(),
@@ -2186,7 +2165,7 @@ SwXText::convertToTable(
         throw  uno::RuntimeException();
     }
 
-    IDocumentRedlineAccess & 
rIDRA(m_pImpl->m_pDoc->getIDocumentRedlineAccess());
+    IDocumentRedlineAccess & rIDRA(m_pDoc->getIDocumentRedlineAccess());
     if (!IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags()))
     {
         throw uno::RuntimeException(
@@ -2217,7 +2196,7 @@ SwXText::convertToTable(
                         ? nullptr
                         : &*aTableNodes.rbegin()->rbegin())
                     : &*aRowNodes.rbegin());
-            m_pImpl->ConvertCell(pRow[nCell], aRowNodes, pLastCell);
+            ConvertCell(pRow[nCell], aRowNodes, pLastCell);
         }
         assert(!aRowNodes.empty());
         aTableNodes.push_back(aRowNodes);
@@ -2227,7 +2206,7 @@ SwXText::convertToTable(
         aRowSeparators(rRowProperties.getLength());
     std::vector<VerticallyMergedCell> aMergedCells;
 
-    SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
+    SwTable const*const pTable = m_pDoc->TextToTable( aTableNodes );
 
     if (!pTable)
         return uno::Reference< text::XTextTable >();
@@ -2362,7 +2341,7 @@ SwXText::copyText(
         // Explicitly request copy text mode, so
         // sw::DocumentContentOperationsManager::CopyFlyInFlyImpl() will copy 
shapes anchored to
         // us, even if we have only a single paragraph.
-        m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, 
SwCopyFlags::CheckPosInFly);
+        m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, 
SwCopyFlags::CheckPosInFly);
     }
 }
 
commit ba28df4fb2c1bc151eebb2d1d2c385be0b71c49d
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sun Jun 23 14:03:18 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Jun 24 09:19:52 2024 +0200

    tdf#144208 speedup doc with lots of redline(14)
    
    SwXTextRange is heavily used. Reduce the allocation cost of
    this class by de-pimpl'ing this class.
    
    One strange thing I noticed is that the destructor of the Impl indicates
    that deleting the bookmark via deleteMark() has to happen under the 
SolarMutex,
    but there are two places in the existing code which violate this already.
    
    Change-Id: I171a0d82d6d020d9a43808c424f308722770783f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169354
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/inc/unotextrange.hxx b/sw/inc/unotextrange.hxx
index c87510f73b18..fa58a0410e08 100644
--- a/sw/inc/unotextrange.hxx
+++ b/sw/inc/unotextrange.hxx
@@ -30,14 +30,17 @@
 #include <com/sun/star/text/XRedline.hpp>
 
 #include <cppuhelper/implbase.hxx>
+#include <svl/listener.hxx>
 
 #include "pam.hxx"
 #include "unobaseclass.hxx"
+#include <optional>
 
 class SwDoc;
 class SwUnoCursor;
 class SwFrameFormat;
 class SwXText;
+class SfxItemPropertySet;
 
 class SW_DLLPUBLIC SwUnoInternalPaM final
     : public SwPaM
@@ -93,9 +96,6 @@ private:
 
     friend class SwXText;
 
-    class Impl;
-    ::sw::UnoImplPtr<Impl> m_pImpl;
-
     void    SetPositions(SwPaM const& rPam);
     //TODO: new exception type for protected content
     /// @throws css::uno::RuntimeException
@@ -103,6 +103,8 @@ private:
                 std::u16string_view aText, ::sw::DeleteAndInsertMode eMode);
     void    Invalidate();
     void    GetStartPaM(std::optional<SwPaM>& roPaM);
+    void    SetMark(::sw::mark::IMark& rMark);
+    void    InvalidateImpl();
 
     virtual ~SwXTextRange() override;
 
@@ -124,8 +126,8 @@ public:
     // only for RANGE_IS_SECTION
     SwXTextRange(SwSectionFormat& rSectionFormat);
 
-    const SwDoc& GetDoc() const;
-          SwDoc& GetDoc();
+    const SwDoc& GetDoc() const { return m_rDoc; }
+          SwDoc& GetDoc() { return m_rDoc; }
     bool GetPositions(SwPaM & rToFill,
         ::sw::TextRangeMode eMode = ::sw::TextRangeMode::RequireTextNode) 
const;
 
@@ -203,6 +205,22 @@ public:
             const OUString& rRedlineType,
             const css::uno::Sequence< css::beans::PropertyValue >& 
RedlineProperties) override;
 
+private:
+    const SfxItemPropertySet& m_rPropSet;
+    const enum RangePosition m_eRangePosition;
+    SwDoc& m_rDoc;
+    css::uno::Reference<css::text::XText> m_xParentText;
+    const SwFrameFormat* m_pTableOrSectionFormat;
+    const ::sw::mark::IMark* m_pMark;
+    struct MySvtListener : public SvtListener
+    {
+        SwXTextRange& mrTextRange;
+
+        MySvtListener(SwXTextRange& rTextRange) : mrTextRange(rTextRange) {}
+
+        virtual void Notify(const SfxHint&) override;
+    };
+    std::optional<MySvtListener> moSvtListener;
 };
 
 typedef ::cppu::WeakImplHelper
diff --git a/sw/source/core/unocore/unoobj2.cxx 
b/sw/source/core/unocore/unoobj2.cxx
index 500ecf0411d6..5a18842f6feb 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -670,90 +670,59 @@ uno::Any SAL_CALL 
SwXParagraphEnumerationImpl::nextElement()
     return aRet;
 }
 
-class SwXTextRange::Impl
-    : public SvtListener
-{
-public:
-    const SfxItemPropertySet& m_rPropSet;
-    const enum RangePosition m_eRangePosition;
-    SwDoc& m_rDoc;
-    uno::Reference<text::XText> m_xParentText;
-    const SwFrameFormat* m_pTableOrSectionFormat;
-    const ::sw::mark::IMark* m_pMark;
-
-    Impl(SwDoc& rDoc, const enum RangePosition eRange,
-            SwFrameFormat* const pTableOrSectionFormat,
-            uno::Reference<text::XText> xParent = nullptr)
-        : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
-        , m_eRangePosition(eRange)
-        , m_rDoc(rDoc)
-        , m_xParentText(std::move(xParent))
-        , m_pTableOrSectionFormat(pTableOrSectionFormat)
-        , m_pMark(nullptr)
-    {
-        if (m_pTableOrSectionFormat)
-        {
-            assert(m_eRangePosition == RANGE_IS_TABLE || m_eRangePosition == 
RANGE_IS_SECTION);
-            StartListening(pTableOrSectionFormat->GetNotifier());
-        }
-        else
-        {
-            assert(m_eRangePosition != RANGE_IS_TABLE && m_eRangePosition != 
RANGE_IS_SECTION);
-        }
-    }
-
-    virtual ~Impl() override
-    {
-        // Impl owns the bookmark; delete it here: SolarMutex is locked
-        Invalidate();
-    }
-
-    void Invalidate()
-    {
-        if (m_pMark)
-        {
-            m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
-            m_pMark = nullptr;
-        }
-        m_pTableOrSectionFormat = nullptr;
-        EndListeningAll();
-    }
-
-    const ::sw::mark::IMark* GetBookmark() const { return m_pMark; }
-    void SetMark(::sw::mark::IMark& rMark)
+void SwXTextRange::InvalidateImpl()
+{
+    if (m_pMark)
     {
-        EndListeningAll();
-        m_pTableOrSectionFormat = nullptr;
-        m_pMark = &rMark;
-        StartListening(rMark.GetNotifier());
+        m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
+        m_pMark = nullptr;
     }
+    m_pTableOrSectionFormat = nullptr;
+    moSvtListener->EndListeningAll();
+}
 
-protected:
-    virtual void Notify(const SfxHint&) override;
-};
+void SwXTextRange::SetMark(::sw::mark::IMark& rMark)
+{
+    moSvtListener->EndListeningAll();
+    m_pTableOrSectionFormat = nullptr;
+    m_pMark = &rMark;
+    moSvtListener->StartListening(rMark.GetNotifier());
+}
 
-void SwXTextRange::Impl::Notify(const SfxHint& rHint)
+void SwXTextRange::MySvtListener::Notify(const SfxHint& rHint)
 {
     if(rHint.GetId() == SfxHintId::Dying)
     {
         EndListeningAll();
-        m_pTableOrSectionFormat = nullptr;
-        m_pMark = nullptr;
+        mrTextRange.m_pTableOrSectionFormat = nullptr;
+        mrTextRange.m_pMark = nullptr;
     }
 }
 
 SwXTextRange::SwXTextRange(SwPaM const & rPam,
         const uno::Reference< text::XText > & xParent,
         const enum RangePosition eRange)
-    : m_pImpl( new SwXTextRange::Impl(rPam.GetDoc(), eRange, nullptr, xParent) 
)
-{
+    : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+    , m_eRangePosition(eRange)
+    , m_rDoc(rPam.GetDoc())
+    , m_xParentText(xParent)
+    , m_pTableOrSectionFormat(nullptr)
+    , m_pMark(nullptr)
+    , moSvtListener(std::in_place, *this)
+{
+    assert(m_eRangePosition != RANGE_IS_TABLE && m_eRangePosition != 
RANGE_IS_SECTION);
     SetPositions(rPam);
 }
 
 SwXTextRange::SwXTextRange(SwTableFormat& rTableFormat)
-    : m_pImpl(
-        new SwXTextRange::Impl(*rTableFormat.GetDoc(), RANGE_IS_TABLE, 
&rTableFormat) )
-{
+    : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+    , m_eRangePosition(RANGE_IS_TABLE)
+    , m_rDoc(*rTableFormat.GetDoc())
+    , m_pTableOrSectionFormat(&rTableFormat)
+    , m_pMark(nullptr)
+    , moSvtListener(std::in_place, *this)
+{
+    moSvtListener->StartListening(rTableFormat.GetNotifier());
     SwTable *const pTable = SwTable::FindTable( &rTableFormat );
     SwTableNode *const pTableNode = pTable->GetTableNode();
     SwPaM aPam( *pTableNode );
@@ -762,38 +731,37 @@ SwXTextRange::SwXTextRange(SwTableFormat& rTableFormat)
 }
 
 SwXTextRange::SwXTextRange(SwSectionFormat& rSectionFormat)
-    : m_pImpl(
-        new SwXTextRange::Impl(*rSectionFormat.GetDoc(), RANGE_IS_SECTION, 
&rSectionFormat) )
-{
+    : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+    , m_eRangePosition(RANGE_IS_SECTION)
+    , m_rDoc(*rSectionFormat.GetDoc())
+    , m_pTableOrSectionFormat(&rSectionFormat)
+    , m_pMark(nullptr)
+    , moSvtListener(std::in_place, *this)
+{
+    moSvtListener->StartListening(rSectionFormat.GetNotifier());
     // no SetPositions here for now
 }
 
 SwXTextRange::~SwXTextRange()
 {
-}
-
-const SwDoc& SwXTextRange::GetDoc() const
-{
-    return m_pImpl->m_rDoc;
-}
-
-SwDoc& SwXTextRange::GetDoc()
-{
-    return m_pImpl->m_rDoc;
+    // have to destruct SvtListener with SolarMutex held
+    SolarMutexGuard aGuard;
+    InvalidateImpl(); // delete bookmark under SolarMutex
+    moSvtListener.reset();
 }
 
 void SwXTextRange::Invalidate()
 {
-    m_pImpl->Invalidate();
+    InvalidateImpl();
 }
 
 void SwXTextRange::SetPositions(const SwPaM& rPam)
 {
-    m_pImpl->Invalidate();
-    IDocumentMarkAccess* const pMA = m_pImpl->m_rDoc.getIDocumentMarkAccess();
+    InvalidateImpl();
+    IDocumentMarkAccess* const pMA = m_rDoc.getIDocumentMarkAccess();
     auto pMark = pMA->makeMark(rPam, OUString(), 
IDocumentMarkAccess::MarkType::UNO_BOOKMARK, sw::mark::InsertMode::New);
     if (pMark)
-        m_pImpl->SetMark(*pMark);
+        SetMark(*pMark);
 }
 
 static void DeleteTable(SwDoc & rDoc, SwTable& rTable)
@@ -811,7 +779,7 @@ static void DeleteTable(SwDoc & rDoc, SwTable& rTable)
 void SwXTextRange::DeleteAndInsert(
         std::u16string_view aText, ::sw::DeleteAndInsertMode const eMode)
 {
-    if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+    if (RANGE_IS_TABLE == m_eRangePosition)
     {
         // setString on table not allowed
         throw uno::RuntimeException(u"not possible for table"_ustr);
@@ -820,18 +788,18 @@ void SwXTextRange::DeleteAndInsert(
     const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
     SwCursor aCursor(aPos, nullptr);
 
-    UnoActionContext aAction(& m_pImpl->m_rDoc);
+    UnoActionContext aAction(&m_rDoc);
 
-    if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition)
+    if (RANGE_IS_SECTION == m_eRangePosition)
     {
-        SwSectionNode const* pSectionNode = m_pImpl->m_pTableOrSectionFormat ?
-            static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat)->GetSectionNode() :
+        SwSectionNode const* pSectionNode = m_pTableOrSectionFormat ?
+            static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat)->GetSectionNode() :
             nullptr;
         if (!pSectionNode)
         {
             throw uno::RuntimeException(u"disposed?"_ustr);
         }
-        m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, 
nullptr);
+        m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
         SwNodeIndex const start(*pSectionNode);
         SwNodeIndex const end(*start.GetNode().EndOfSectionNode());
 
@@ -846,7 +814,7 @@ void SwXTextRange::DeleteAndInsert(
             }
             else if (SwTableNode *const pTableNode = rNode.GetTableNode())
             {
-                DeleteTable(m_pImpl->m_rDoc, pTableNode->GetTable());
+                DeleteTable(m_rDoc, pTableNode->GetTable());
                 // where does that leave index? presumably behind?
             }
             else
@@ -864,7 +832,7 @@ void SwXTextRange::DeleteAndInsert(
             {
                 if (SwTableNode *const pTableNode = 
rNode.StartOfSectionNode()->GetTableNode())
                 {
-                    DeleteTable(m_pImpl->m_rDoc, pTableNode->GetTable());
+                    DeleteTable(m_rDoc, pTableNode->GetTable());
                 }
                 else
                 {
@@ -891,25 +859,25 @@ void SwXTextRange::DeleteAndInsert(
     {
         if (!GetPositions(aCursor))
             return;
-        m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, 
nullptr);
+        m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
     }
 
     if (aCursor.HasMark())
     {
-        m_pImpl->m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor,
+        m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor,
             (!aText.empty() || eMode & 
::sw::DeleteAndInsertMode::ForceReplace) ? SwDeleteFlags::ArtificialSelection : 
SwDeleteFlags::Default);
     }
 
     if (!aText.empty())
     {
         SwUnoCursorHelper::DocInsertStringSplitCR(
-            m_pImpl->m_rDoc, aCursor, aText, bool(eMode & 
::sw::DeleteAndInsertMode::ForceExpandHints));
+            m_rDoc, aCursor, aText, bool(eMode & 
::sw::DeleteAndInsertMode::ForceExpandHints));
 
         SwUnoCursorHelper::SelectPam(aCursor, true);
         aCursor.Left(aText.size());
     }
     SetPositions(aCursor);
-    m_pImpl->m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
+    m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
 }
 
 OUString SAL_CALL
@@ -942,26 +910,25 @@ SwXTextRange::getText()
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->m_xParentText.is() && m_pImpl->m_pTableOrSectionFormat)
+    if (!m_xParentText.is() && m_pTableOrSectionFormat)
     {
         std::optional<SwPosition> oPosition;
-        if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE)
+        if (m_eRangePosition == RANGE_IS_TABLE)
         {
-            SwTable const*const pTable = SwTable::FindTable( 
m_pImpl->m_pTableOrSectionFormat );
+            SwTable const*const pTable = SwTable::FindTable( 
m_pTableOrSectionFormat );
             SwTableNode const*const pTableNode = pTable->GetTableNode();
             oPosition.emplace(*pTableNode);
         }
         else
         {
-            assert(m_pImpl->m_eRangePosition == RANGE_IS_SECTION);
-            auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat));
+            assert(m_eRangePosition == RANGE_IS_SECTION);
+            auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat));
             
oPosition.emplace(pSectFormat->GetContent().GetContentIdx()->GetNode());
         }
-        m_pImpl->m_xParentText =
-            ::sw::CreateParentXText(m_pImpl->m_rDoc, *oPosition);
+        m_xParentText = ::sw::CreateParentXText(m_rDoc, *oPosition);
     }
-    OSL_ENSURE(m_pImpl->m_xParentText.is(), "SwXTextRange::getText: no text");
-    return m_pImpl->m_xParentText;
+    OSL_ENSURE(m_xParentText.is(), "SwXTextRange::getText: no text");
+    return m_xParentText;
 }
 
 uno::Reference< text::XTextRange > SAL_CALL
@@ -970,29 +937,29 @@ SwXTextRange::getStart()
     SolarMutexGuard aGuard;
 
     uno::Reference< text::XTextRange >  xRet;
-    ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
-    if (!m_pImpl->m_xParentText.is())
+    ::sw::mark::IMark const * const pBkmk = m_pMark;
+    if (!m_xParentText.is())
     {
         getText();
     }
     if(pBkmk)
     {
         SwPaM aPam(pBkmk->GetMarkStart());
-        xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
+        xRet = new SwXTextRange(aPam, m_xParentText);
     }
-    else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+    else if (RANGE_IS_TABLE == m_eRangePosition)
     {
         // start and end are this, if it's a table
         xRet = this;
     }
-    else if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
-            && m_pImpl->m_pTableOrSectionFormat)
+    else if (RANGE_IS_SECTION == m_eRangePosition
+            && m_pTableOrSectionFormat)
     {
-        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat));
+        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat));
         SwPaM aPaM(*pSectFormat->GetContent().GetContentIdx());
         aPaM.Move( fnMoveForward, GoInContent );
         assert(aPaM.GetPoint()->GetNode() < 
*pSectFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionNode());
-        xRet = new SwXTextRange(aPaM, m_pImpl->m_xParentText);
+        xRet = new SwXTextRange(aPaM, m_xParentText);
     }
     else
     {
@@ -1007,29 +974,29 @@ SwXTextRange::getEnd()
     SolarMutexGuard aGuard;
 
     uno::Reference< text::XTextRange >  xRet;
-    ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
-    if (!m_pImpl->m_xParentText.is())
+    ::sw::mark::IMark const * const pBkmk = m_pMark;
+    if (!m_xParentText.is())
     {
         getText();
     }
     if(pBkmk)
     {
         SwPaM aPam(pBkmk->GetMarkEnd());
-        xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
+        xRet = new SwXTextRange(aPam, m_xParentText);
     }
-    else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+    else if (RANGE_IS_TABLE == m_eRangePosition)
     {
         // start and end are this, if it's a table
         xRet = this;
     }
-    else if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
-            && m_pImpl->m_pTableOrSectionFormat)
+    else if (RANGE_IS_SECTION == m_eRangePosition
+            && m_pTableOrSectionFormat)
     {
-        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat));
+        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat));
         SwPaM 
aPaM(*pSectFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionNode());
         aPaM.Move( fnMoveBackward, GoInContent );
         assert(*pSectFormat->GetContent().GetContentIdx() < 
aPaM.GetPoint()->GetNode());
-        xRet = new SwXTextRange(aPaM, m_pImpl->m_xParentText);
+        xRet = new SwXTextRange(aPaM, m_xParentText);
     }
     else
     {
@@ -1062,9 +1029,9 @@ void SAL_CALL SwXTextRange::setString(const OUString& 
rString)
 
 bool SwXTextRange::GetPositions(SwPaM& rToFill, ::sw::TextRangeMode const 
eMode) const
 {
-    if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition)
+    if (RANGE_IS_SECTION == m_eRangePosition)
     {
-        if (auto const pSectFormat = static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat))
+        if (auto const pSectFormat = static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat))
         {
             if (eMode == ::sw::TextRangeMode::AllowNonTextNode)
             {
@@ -1098,7 +1065,7 @@ bool SwXTextRange::GetPositions(SwPaM& rToFill, 
::sw::TextRangeMode const eMode)
             }
         }
     }
-    ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
+    ::sw::mark::IMark const * const pBkmk = m_pMark;
     if(pBkmk)
     {
         *rToFill.GetPoint() = pBkmk->GetMarkPos();
@@ -1145,8 +1112,8 @@ sal_Int16 SwXTextRange::compareRegionStarts(SwXTextRange& 
rhs)
 
 void SwXTextRange::GetStartPaM(std::optional<SwPaM>& roPaM)
 {
-    ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
-    if (!m_pImpl->m_xParentText.is())
+    ::sw::mark::IMark const * const pBkmk = m_pMark;
+    if (!m_xParentText.is())
     {
         getText();
     }
@@ -1154,16 +1121,16 @@ void SwXTextRange::GetStartPaM(std::optional<SwPaM>& 
roPaM)
     {
         roPaM.emplace(pBkmk->GetMarkStart());
     }
-    else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+    else if (RANGE_IS_TABLE == m_eRangePosition)
     {
         // start and end are this, if it's a table
         roPaM.emplace(GetDoc().GetNodes());
         GetPositions(*roPaM, sw::TextRangeMode::RequireTextNode);
     }
-    else if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
-            && m_pImpl->m_pTableOrSectionFormat)
+    else if (RANGE_IS_SECTION == m_eRangePosition
+            && m_pTableOrSectionFormat)
     {
-        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pImpl->m_pTableOrSectionFormat));
+        auto const pSectFormat(static_cast<SwSectionFormat 
const*>(m_pTableOrSectionFormat));
         roPaM.emplace(*pSectFormat->GetContent().GetContentIdx());
         roPaM->Move( fnMoveForward, GoInContent );
         assert(roPaM->GetPoint()->GetNode() < 
*pSectFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionNode());
@@ -1423,12 +1390,12 @@ SwXTextRange::createContentEnumeration(const OUString& 
rServiceName)
         throw uno::RuntimeException(u"unsupported service"_ustr);
     }
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
-    const auto pNewCursor(m_pImpl->m_rDoc.CreateUnoCursor(aPos));
+    const auto pNewCursor(m_rDoc.CreateUnoCursor(aPos));
     if (!GetPositions(*pNewCursor))
     {
         throw uno::RuntimeException(u"range has no positions"_ustr);
@@ -1442,24 +1409,24 @@ SwXTextRange::createEnumeration()
 {
     SolarMutexGuard g;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
-    auto pNewCursor(m_pImpl->m_rDoc.CreateUnoCursor(aPos));
+    auto pNewCursor(m_rDoc.CreateUnoCursor(aPos));
     if (!GetPositions(*pNewCursor))
     {
         throw uno::RuntimeException(u"range has no positions"_ustr);
     }
-    if (!m_pImpl->m_xParentText.is())
+    if (!m_xParentText.is())
     {
         getText();
     }
 
-    const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
+    const CursorType eSetType = (RANGE_IN_CELL == m_eRangePosition)
             ? CursorType::SelectionInTable : CursorType::Selection;
-    return SwXParagraphEnumeration::Create(m_pImpl->m_xParentText, pNewCursor, 
eSetType);
+    return SwXParagraphEnumeration::Create(m_xParentText, pNewCursor, 
eSetType);
 }
 
 uno::Type SAL_CALL SwXTextRange::getElementType()
@@ -1485,7 +1452,7 @@ SwXTextRange::getPropertySetInfo()
     SolarMutexGuard aGuard;
 
     static uno::Reference< beans::XPropertySetInfo > xRef =
-        m_pImpl->m_rPropSet.getPropertySetInfo();
+        m_rPropSet.getPropertySetInfo();
     return xRef;
 }
 
@@ -1495,13 +1462,13 @@ SwXTextRange::setPropertyValue(
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    SwUnoCursorHelper::SetPropertyValue(aPaM, m_pImpl->m_rPropSet,
+    SwUnoCursorHelper::SetPropertyValue(aPaM, m_rPropSet,
             rPropertyName, rValue);
 }
 
@@ -1510,13 +1477,13 @@ SwXTextRange::getPropertyValue(const OUString& 
rPropertyName)
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    return SwUnoCursorHelper::GetPropertyValue(aPaM, m_pImpl->m_rPropSet,
+    return SwUnoCursorHelper::GetPropertyValue(aPaM, m_rPropSet,
             rPropertyName);
 }
 
@@ -1557,13 +1524,13 @@ SwXTextRange::getPropertyState(const OUString& 
rPropertyName)
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    return SwUnoCursorHelper::GetPropertyState(aPaM, m_pImpl->m_rPropSet,
+    return SwUnoCursorHelper::GetPropertyState(aPaM, m_rPropSet,
             rPropertyName);
 }
 
@@ -1572,13 +1539,13 @@ SwXTextRange::getPropertyStates(const uno::Sequence< 
OUString >& rPropertyName)
 {
     SolarMutexGuard g;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    return SwUnoCursorHelper::GetPropertyStates(aPaM, m_pImpl->m_rPropSet,
+    return SwUnoCursorHelper::GetPropertyStates(aPaM, m_rPropSet,
             rPropertyName);
 }
 
@@ -1586,13 +1553,13 @@ void SAL_CALL SwXTextRange::setPropertyToDefault(const 
OUString& rPropertyName)
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_pImpl->m_rPropSet,
+    SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_rPropSet,
             rPropertyName);
 }
 
@@ -1601,13 +1568,13 @@ SwXTextRange::getPropertyDefault(const OUString& 
rPropertyName)
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }
     SwPaM aPaM(GetDoc().GetNodes());
     GetPositions(aPaM);
-    return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_pImpl->m_rPropSet,
+    return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_rPropSet,
             rPropertyName);
 }
 
@@ -1618,7 +1585,7 @@ SwXTextRange::makeRedline(
 {
     SolarMutexGuard aGuard;
 
-    if (!m_pImpl->GetBookmark())
+    if (!m_pMark)
     {
         throw uno::RuntimeException(u"range has no mark (table?)"_ustr);
     }

Reply via email to