sw/inc/unotextrange.hxx            |    8 +++++---
 sw/source/core/unocore/unobkm.cxx  |    3 ++-
 sw/source/core/unocore/unoobj2.cxx |   25 ++++++++++++++++---------
 3 files changed, 23 insertions(+), 13 deletions(-)

New commits:
commit 2273885b0785b91546962925e5ec44326eb302de
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Jan 31 11:47:46 2025 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Feb 11 22:27:40 2025 +0100

    tdf#158198 sw: prevent xBookmark.getAnchor().setString("") from deleting
    
    ... the bookmark.
    
    Add a RANGE_IS_BOOKMARK to SwXTextRange and special case setString() so
    that it will do a replace, not a delete, to prevent the bookmark from
    being deleted.
    
    SwXBookmark::getAnchor() will create such a SwXTextRange.
    
    Bookmarks may be in table cells of course so we need RANGE_IN_CELL to be
    a flag now so it can be used with 2 different enum values.
    
    (regression from commit baf8d2c1c16cb3bdc4edad2560f95fea807a034f)
    
    Change-Id: I69169b9a5f6f7525715122b16de009c894246bef
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180985
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit b0d4b4664a295631ce4d8dee2ceb5cd94ae12edb)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180989
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
    (cherry picked from commit fe5635c78557ef9f51e3bac1d782cf1c8555655d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181105
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Michael Weghorn <m.wegh...@posteo.de>
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org>

diff --git a/sw/inc/unotextrange.hxx b/sw/inc/unotextrange.hxx
index 1d2265ddfec1..077bbf3e3e75 100644
--- a/sw/inc/unotextrange.hxx
+++ b/sw/inc/unotextrange.hxx
@@ -110,14 +110,15 @@ public:
     enum RangePosition
     {
         RANGE_IN_TEXT,  // "ordinary" css::text::TextRange
-        RANGE_IN_CELL,  // position created with a cell that has no uno object
         RANGE_IS_TABLE, // anchor of a table
         RANGE_IS_SECTION, // anchor of a section
+        RANGE_IS_BOOKMARK, ///< anchor of a bookmark
     };
 
     SwXTextRange(SwPaM const & rPam,
             const css::uno::Reference< css::text::XText > & xParent,
-            const enum RangePosition eRange = RANGE_IN_TEXT);
+            const enum RangePosition eRange = RANGE_IN_TEXT,
+            bool isInCell = false);
     // only for RANGE_IS_TABLE
     SwXTextRange(SwTableFormat& rTableFormat);
     // only for RANGE_IS_SECTION
@@ -130,7 +131,8 @@ public:
 
     static rtl::Reference< SwXTextRange > CreateXTextRange(
             SwDoc & rDoc,
-            const SwPosition& rPos, const SwPosition *const pMark);
+            const SwPosition& rPos, const SwPosition *const pMark,
+            RangePosition eRange = RANGE_IN_TEXT);
 
     // XServiceInfo
     virtual OUString SAL_CALL getImplementationName() override;
diff --git a/sw/source/core/unocore/unobkm.cxx 
b/sw/source/core/unocore/unobkm.cxx
index cb9b3894a72e..6f0aa41fdf70 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -272,7 +272,8 @@ uno::Reference< text::XTextRange > SAL_CALL 
SwXBookmark::getAnchor()
             *m_pImpl->m_pDoc,
             m_pImpl->m_pRegisteredBookmark->GetMarkPos(),
             (m_pImpl->m_pRegisteredBookmark->IsExpanded())
-                ? &m_pImpl->m_pRegisteredBookmark->GetOtherMarkPos() : 
nullptr);
+                ? &m_pImpl->m_pRegisteredBookmark->GetOtherMarkPos() : nullptr,
+            SwXTextRange::RANGE_IS_BOOKMARK);
 }
 
 void SAL_CALL SwXBookmark::dispose()
diff --git a/sw/source/core/unocore/unoobj2.cxx 
b/sw/source/core/unocore/unoobj2.cxx
index f043515aefb4..5fa37d8b6b98 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -676,16 +676,18 @@ class SwXTextRange::Impl
 public:
     const SfxItemPropertySet& m_rPropSet;
     const enum RangePosition m_eRangePosition;
+    bool const m_isRangeInCell; //< position created with a cell that has no 
uno object
     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,
+    Impl(SwDoc& rDoc, const enum RangePosition eRange, bool const isInCell,
             SwFrameFormat* const pTableOrSectionFormat,
             uno::Reference<text::XText> xParent = nullptr)
         : m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
         , m_eRangePosition(eRange)
+        , m_isRangeInCell(isInCell)
         , m_rDoc(rDoc)
         , m_xParentText(std::move(xParent))
         , m_pTableOrSectionFormat(pTableOrSectionFormat)
@@ -744,15 +746,16 @@ void SwXTextRange::Impl::Notify(const SfxHint& rHint)
 
 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) 
)
+        const enum RangePosition eRange,
+        bool const isInCell)
+    : m_pImpl( new SwXTextRange::Impl(rPam.GetDoc(), eRange, isInCell, 
nullptr, xParent) )
 {
     SetPositions(rPam);
 }
 
 SwXTextRange::SwXTextRange(SwTableFormat& rTableFormat)
     : m_pImpl(
-        new SwXTextRange::Impl(*rTableFormat.GetDoc(), RANGE_IS_TABLE, 
&rTableFormat) )
+        new SwXTextRange::Impl(*rTableFormat.GetDoc(), RANGE_IS_TABLE, false, 
&rTableFormat) )
 {
     SwTable *const pTable = SwTable::FindTable( &rTableFormat );
     SwTableNode *const pTableNode = pTable->GetTableNode();
@@ -763,7 +766,7 @@ SwXTextRange::SwXTextRange(SwTableFormat& rTableFormat)
 
 SwXTextRange::SwXTextRange(SwSectionFormat& rSectionFormat)
     : m_pImpl(
-        new SwXTextRange::Impl(*rSectionFormat.GetDoc(), RANGE_IS_SECTION, 
&rSectionFormat) )
+        new SwXTextRange::Impl(*rSectionFormat.GetDoc(), RANGE_IS_SECTION, 
false, &rSectionFormat) )
 {
     // no SetPositions here for now
 }
@@ -1057,7 +1060,10 @@ void SAL_CALL SwXTextRange::setString(const OUString& 
rString)
 {
     SolarMutexGuard aGuard;
 
-    DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::Default);
+    // tdf#158198 avoid deleting bookmark via setString on its anchor
+    DeleteAndInsert(rString, RANGE_IS_BOOKMARK == m_pImpl->m_eRangePosition
+                                ? ::sw::DeleteAndInsertMode::ForceReplace
+                                : ::sw::DeleteAndInsertMode::Default);
 }
 
 bool SwXTextRange::GetPositions(SwPaM& rToFill, ::sw::TextRangeMode const 
eMode) const
@@ -1232,7 +1238,8 @@ lcl_IsStartNodeInFormat(const bool bHeader, SwStartNode 
const *const pSttNode,
 
 rtl::Reference< SwXTextRange >
 SwXTextRange::CreateXTextRange(
-    SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark)
+    SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark,
+    RangePosition const eRange)
 {
     const uno::Reference<text::XText> xParentText(
             ::sw::CreateParentXText(rDoc, rPos));
@@ -1244,7 +1251,7 @@ SwXTextRange::CreateXTextRange(
     }
     const bool isCell( dynamic_cast<SwXCell*>(xParentText.get()) );
     return new SwXTextRange(*pNewCursor, xParentText,
-            isCell ? RANGE_IN_CELL : RANGE_IN_TEXT);
+            eRange, isCell);
 }
 
 namespace sw {
@@ -1401,7 +1408,7 @@ SwXTextRange::createEnumeration()
         getText();
     }
 
-    const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
+    const CursorType eSetType = m_pImpl->m_isRangeInCell
             ? CursorType::SelectionInTable : CursorType::Selection;
     return SwXParagraphEnumeration::Create(m_pImpl->m_xParentText, pNewCursor, 
eSetType);
 }

Reply via email to