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

New commits:
commit e6eeace8879dd68760bc5e09664196e12d8fc9d5
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Aug 24 23:57:41 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Aug 25 11:54:29 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

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 ea6e13f10984..a713268d4f67 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5724,6 +5724,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;
 }
 
@@ -5897,7 +5903,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