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 05fdaf4da400001866759c0a1590788f9bfa7892
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Aug 15 14:53:27 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Aug 15 21:12:41 2024 +0500

    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

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 14ffc152d921..ce63cbaa8432 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -42,6 +42,7 @@
 #include <vcl/graphicfilter.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
 
 #include <wrtsh.hxx>
 #include <ndtxt.hxx>
@@ -1200,6 +1201,24 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf129841)
     CPPUNIT_ASSERT_EQUAL(aRefColor, aColor);
 }
 
+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, ".uno:InsertDoc", aPropertyValues);
+
+    uno::Reference<text::XTextContent> xTextBox(getShape(1), 
uno::UNO_QUERY_THROW);
+    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(2), 
uno::UNO_QUERY_THROW);
+    auto xAnchorRange = xTextBox->getAnchor();
+    uno::Reference<text::XText> xCellText(xTable->getCellByName("B1"), 
uno::UNO_QUERY_THROW);
+    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 f253502e56a6..8362631ba9f6 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);

Reply via email to