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,