sc/qa/extras/sccellobj.cxx       |   48 ++++++++++++++++++++++++++++++++++++++-
 sc/source/ui/unoobj/cellsuno.cxx |    8 +++++-
 2 files changed, 54 insertions(+), 2 deletions(-)

New commits:
commit cd8f79fc01173ce66e84bef7be6bc04912e59fb0
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Aug 24 23:57:41 2025 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Mon Aug 25 14:14:07 2025 +0200

    tdf#168096: reset selection each time GetUnoText is called
    
    ScCellObj represents the whole content of the cell; and its XText
    must always cover it all. However, implementation (ScCellTextObj)
    may get its "selection" (defining the actual range) out of sync,
    after created initially, if content is changed using other objects.
    It is a modification listener; but that doesn't help, because some
    methods may manually re-assign selection after the actual content
    change: see e.g. SvxUnoTextBase::insertString.
    
    This change resets the selection of the cell object each time its
    GetUnoText method is called. The EE_PARA_MAX value assigned to
    start.nPara causes the needed processing in CheckSelection.
    
    Change-Id: I94bc55ee3df7976dcaeaa9c4878059995e885e8c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190142
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190164

diff --git a/sc/qa/extras/sccellobj.cxx b/sc/qa/extras/sccellobj.cxx
index 9a0c74888508..c475921f9a0c 100644
--- a/sc/qa/extras/sccellobj.cxx
+++ b/sc/qa/extras/sccellobj.cxx
@@ -18,13 +18,15 @@
 #include <test/text/xsimpletext.hxx>
 #include <test/util/xindent.hxx>
 
+#include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
 #include <com/sun/star/sheet/XSheetAnnotations.hpp>
 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
 #include <com/sun/star/sheet/XSpreadsheet.hpp>
 #include <com/sun/star/sheet/XSpreadsheets.hpp>
 #include <com/sun/star/table/CellAddress.hpp>
-#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
 
 using namespace css;
 using namespace css::uno;
@@ -49,6 +51,8 @@ public:
     virtual uno::Reference<uno::XInterface> getXSpreadsheet() override;
     virtual void setUp() override;
 
+    void testInsertVarious_ScCellObj();
+
     CPPUNIT_TEST_SUITE(ScCellObj);
 
     // SheetCell
@@ -87,6 +91,8 @@ public:
     CPPUNIT_TEST(testInsertString);
     CPPUNIT_TEST(testInsertControlCharacter);
 
+    CPPUNIT_TEST(testInsertVarious_ScCellObj);
+
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -132,6 +138,46 @@ void ScCellObj::setUp()
     loadFromURL(u"private:factory/scalc"_ustr);
 }
 
+void ScCellObj::testInsertVarious_ScCellObj()
+{
+    auto xText = init().queryThrow<text::XText>();
+
+    xText->setString(u"foo"_ustr);
+    CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, xText->getString());
+
+    // Test different kinds of XTextRange passed to insertString: cursor, 
start/end, itself.
+    // The test relies on createTextCursor() giving the position at the end of 
the text; this
+    // is true for Calc cells, but e.g. Writer produces cursors at the start - 
who is right?
+
+    xText->insertString(xText, u"b"_ustr, true); // must replace all
+    xText->insertString(xText->createTextCursor(), u"c"_ustr, false);
+    xText->insertString(xText->getStart(), u"a"_ustr, false);
+    xText->insertString(xText->getEnd(), u"d"_ustr, false);
+    xText->insertString(xText, u"e"_ustr, false);
+
+    // Test insertString interleaved with insertTextContent
+
+    auto makeField = [xF = 
mxComponent.queryThrow<lang::XMultiServiceFactory>()](const OUString& s)
+    {
+        auto xField = 
xF->createInstance(u"com.sun.star.text.textfield.URL"_ustr)
+                          .queryThrow<beans::XPropertySet>();
+        xField->setPropertyValue(u"URL"_ustr, 
uno::Any(u"http://www.example.org/"_ustr));
+        xField->setPropertyValue(u"Representation"_ustr, uno::Any(s));
+        return xField.queryThrow<text::XTextContent>();
+    };
+
+    xText->insertString(xText->createTextCursor(), u" 1: "_ustr, false);
+    xText->insertTextContent(xText->createTextCursor(), makeField(u"h1"_ustr), 
false);
+
+    xText->insertString(xText->getEnd(), u" 2: "_ustr, false);
+    xText->insertTextContent(xText->getEnd(), makeField(u"h2"_ustr), false);
+
+    xText->insertString(xText, u" 3: "_ustr, false);
+    xText->insertTextContent(xText, makeField(u"h3"_ustr), false);
+
+    CPPUNIT_ASSERT_EQUAL(u"abcde 1: h1 2: h2 3: h3"_ustr, xText->getString());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(ScCellObj);
 
 } // end namespace
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 3d46da6f59fc..885075f94c94 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5725,6 +5725,12 @@ SvxUnoText& ScCellObj::GetUnoText()
                 pEditSource->SetDoUpdateData(false);
         }
     }
+    else
+    {
+        // Make sure every time, that the cell object's selection covers all 
the cell's content.
+        // Selection's start.nPara == EE_PARA_MAX is handled explicitly in 
CheckSelection
+        mxUnoText->SetSelection({ EE_PARA_MAX, 0, 0, 0 });
+    }
     return *mxUnoText;
 }
 
@@ -5898,7 +5904,7 @@ void SAL_CALL ScCellObj::setString( const OUString& aText 
)
 
     // don't create pUnoText here if not there
     if (mxUnoText.is())
-        mxUnoText->SetSelection(ESelection( 0,0, 0,aText.getLength() ));
+        mxUnoText->SetSelection({ EE_PARA_MAX, 0, 0, 0 });
 }
 
 void SAL_CALL ScCellObj::insertString( const uno::Reference<text::XTextRange>& 
xRange,

Reply via email to