sw/qa/extras/unowriter/data/textboxInColumn2.fodt | 39 ++++++++++++++++++++++ sw/qa/extras/unowriter/unowriter.cxx | 19 ++++++++++ sw/source/core/doc/textboxhelper.cxx | 36 +++++++++++++++++--- 3 files changed, 89 insertions(+), 5 deletions(-)
New commits: commit eafe413cd23af4c7ac7de299c51ca436f5aab596 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Aug 15 14:53:27 2024 +0500 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Aug 27 13:22:27 2024 +0200 tdf#162480: Make sure to use correct anchor point for text box creation In the ODF import, when importing a table, initially a placeholder 1x1 table is created. When this is done from SwView::InsertMedium, frames are created for the table and its single cell at that stage. Then the actual table nodes are created, but frames are not created in parallel, until the table import is finished. Importing a text box, it used to be created anchored at the end of the document, and then the anchor was moved to the correct place. When a text box was anchored to a cell, the process was like this: the text content was inserted in the last paragraph outside of the current table; and then it was moved to the current cell. When this was done from SwView::InsertMedium, creation of the text content also created the frame; then the movement fired client notifications, including the SwFlyAtContentFrame::SwClientNotify, which needs the new anchor frame. With cell other than A1, there was no frames for the new anchor in the table, and that crashed. This change inserts the text content into the correct place from start, which avoids the need to move the anchor later. Co-authored-by: Miklos Vajna <vmik...@collabora.com> Change-Id: I9dd3a2c5527f3c2dd860244456c617558943453a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171898 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> 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/+/172058 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172101 diff --git a/sw/qa/extras/unowriter/data/textboxInColumn2.fodt b/sw/qa/extras/unowriter/data/textboxInColumn2.fodt new file mode 100644 index 000000000000..cdd9ba9999ab --- /dev/null +++ b/sw/qa/extras/unowriter/data/textboxInColumn2.fodt @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" fo:padding="1.5mm" draw:stroke="solid" svg:stroke-color="#000000" draw:fill="none" draw:textarea-vertical-align="top" draw:auto-grow-height="true" fo:min-height="0mm" fo:min-width="0mm" fo:wrap-option="wrap" style:run-through="foreground" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:flow-with-text="true"/> + </style:style> + </office:styles> + <office:automatic-styles> + <style:style style:name="gr1" style:family="graphic" style:parent-style-name="Frame"> + <style:graphic-properties draw:stroke="solid" svg:stroke-color="#000000" draw:fill="none" draw:textarea-vertical-align="top" draw:auto-grow-height="true" fo:min-height="0mm" fo:min-width="0mm" fo:wrap-option="wrap" style:run-through="foreground" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:flow-with-text="true"/> + </style:style> + </office:automatic-styles> + <office:body> + <office:text> + <table:table> + <table:table-column table:number-columns-repeated="2"/> + <table:table-row> + <table:table-cell/> + <table:table-cell> + <text:p/> + <text:p><draw:custom-shape text:anchor-type="char" draw:z-index="0" draw:name="Text Box 1" draw:style-name="gr1" svg:width="30mm" svg:x="6mm" svg:y="5mm"> + <text:p>hello</text:p> + <draw:enhanced-geometry draw:mirror-horizontal="false" draw:mirror-vertical="false" svg:viewBox="0 0 0 0" draw:text-areas="0 0 ?f3 ?f2" draw:type="ooxml-rect" draw:enhanced-path="M 0 0 L ?f3 0 ?f3 ?f2 0 ?f2 Z N"> + <draw:equation draw:name="f0" draw:formula="logwidth/2"/> + <draw:equation draw:name="f1" draw:formula="logheight/2"/> + <draw:equation draw:name="f2" draw:formula="logheight"/> + <draw:equation draw:name="f3" draw:formula="logwidth"/> + </draw:enhanced-geometry> + </draw:custom-shape></text:p> + <text:p/> + <text:p/> + </table:table-cell> + </table:table-row> + </table:table> + <text:p/> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx index 7175e702d709..a2c03bbaaf02 100644 --- a/sw/qa/extras/unowriter/unowriter.cxx +++ b/sw/qa/extras/unowriter/unowriter.cxx @@ -36,6 +36,7 @@ #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XPageCursor.hpp> +#include <comphelper/propertysequence.hxx> #include <comphelper/propertyvalue.hxx> #include <tools/UnitConversion.hxx> #include <toolkit/helper/vclunohelper.hxx> @@ -1249,6 +1250,24 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf161035) CPPUNIT_ASSERT(!xRunEnum->hasMoreElements()); // Empty enumeration for empty selection } +CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf162480) +{ + createSwDoc(); + + uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({ + { "Name", uno::Any(createFileURL(u"textboxInColumn2.fodt")) }, + }); + + // Inserting a document with text box attached in a table's second column must not crash + dispatchCommand(mxComponent, u".uno:InsertDoc"_ustr, aPropertyValues); + + auto xTextBox = getShape(1).queryThrow<css::text::XTextContent>(); + auto xTable = getParagraphOrTable(2).queryThrow<css::text::XTextTable>(); + auto xAnchorRange = xTextBox->getAnchor(); + auto xCellText = xTable->getCellByName("B1").queryThrow<css::text::XText>(); + CPPUNIT_ASSERT_EQUAL(xCellText, xAnchorRange->getText()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 253e39a29383..4aaa2d0a4a6c 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -8,6 +8,7 @@ */ #include <textboxhelper.hxx> +#include <dcontact.hxx> #include <fmtcntnt.hxx> #include <fmtanchr.hxx> #include <fmtcnct.hxx> @@ -64,6 +65,7 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo { assert(pShape); assert(pObject); + assert(pShape == ::FindFrameFormat(pObject)); // If TextBox wasn't enabled previously if (pShape->GetOtherTextBoxFormats() && pShape->GetOtherTextBoxFormats()->GetTextBox(pObject)) @@ -88,11 +90,35 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo uno::Reference<text::XTextContent> xTextFrame( SwXServiceProvider::MakeInstance(SwServiceType::TypeTextFrame, *pShape->GetDoc()), uno::UNO_QUERY); - uno::Reference<text::XTextDocument> xTextDocument( - pShape->GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY); - uno::Reference<text::XTextContentAppend> xTextContentAppend(xTextDocument->getText(), - uno::UNO_QUERY); - xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>()); + + uno::Reference<text::XTextRange> xAnchor; + uno::Reference<text::XTextContent> xAnchorProvider(pObject->getWeakUnoShape().get(), + uno::UNO_QUERY); + assert(xAnchorProvider.is()); + if (xAnchorProvider.is()) + xAnchor = xAnchorProvider->getAnchor(); + + uno::Reference<text::XTextContentAppend> xTextContentAppend; + if (xAnchor) + xTextContentAppend.set(xAnchor->getText(), uno::UNO_QUERY); + + if (!xTextContentAppend) + { + uno::Reference<text::XTextDocument> xTextDocument( + pShape->GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW); + xTextContentAppend.set(xTextDocument->getText(), uno::UNO_QUERY_THROW); + } + + if (xAnchor) + { + // insertTextContentWithProperties would fail if xAnchor is in a different XText + assert(xAnchor->getText() == xTextContentAppend); + xTextContentAppend->insertTextContentWithProperties(xTextFrame, {}, xAnchor); + } + else + { + xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>()); + } // Link FLY and DRAW formats, so it becomes a text box (needed for syncProperty calls). uno::Reference<text::XTextFrame> xRealTextFrame(xTextFrame, uno::UNO_QUERY);