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,