summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-11-07 10:10:43 +0100
committerMiklos Vajna <vmiklos@collabora.com>2019-11-07 12:27:34 +0100
commitdbe744f1deef144e205b72e5927d61a6ea47af25 (patch)
treeeb4bb249ab4124c7b85284f98b2d66727315da3c /sw
parente194b4e209277ed5beeacf8ea875daa8688ab394 (diff)
tdf#128603 sw textbox: restore shape+frame pair on undo
Undo of cut + paste restored both the shape and the frame, but the shape's content pointed to an invalid node index. Later this resulted in a crash. Make sure that in case the content of shape+frame don't match by the time the frame format pointer is set, we sync the draw format to the fly format. Change-Id: I233a504ca52698d1c514769d16c256408c29ae30 Reviewed-on: https://gerrit.libreoffice.org/82192 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/uiwriter/data2/tdf128603.odtbin0 -> 10391 bytes
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx45
-rw-r--r--sw/source/core/layout/atrfrm.cxx19
3 files changed, 64 insertions, 0 deletions
diff --git a/sw/qa/extras/uiwriter/data2/tdf128603.odt b/sw/qa/extras/uiwriter/data2/tdf128603.odt
new file mode 100644
index 000000000000..6fb758af9168
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data2/tdf128603.odt
Binary files differ
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 14f7e0a5ac6b..912695cc03d4 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -47,6 +47,7 @@
#include <AnnotationWin.hxx>
#include <PostItMgr.hxx>
#include <postithelper.hxx>
+#include <fmtcntnt.hxx>
namespace
{
@@ -2365,4 +2366,48 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128335)
pView->GetViewFrame()->GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128603)
+{
+ // Load the bugdoc, which has 3 textboxes.
+ SwDoc* pDoc = createDoc("tdf128603.odt");
+
+ // Select the 3rd textbox.
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON);
+ // Make sure SwTextShell is replaced with SwDrawShell right now, not after 120 ms, as set in the
+ // SwView ctor.
+ pView->StopShellTimer();
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
+ Scheduler::ProcessEventsToIdle();
+
+ // Cut it.
+ pView->GetViewFrame()->GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
+
+ // Paste it: this makes the 3rd textbox anchored in the 2nd one.
+ pView->GetViewFrame()->GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
+
+ // Undo all of this.
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ rUndoManager.Undo();
+ rUndoManager.Undo();
+
+ // Make sure the content indexes still match.
+ const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), rSpzFrameFormats.size());
+ const SwNodeIndex* pIndex4 = rSpzFrameFormats[4]->GetContent().GetContentIdx();
+ CPPUNIT_ASSERT(pIndex4);
+ const SwNodeIndex* pIndex5 = rSpzFrameFormats[5]->GetContent().GetContentIdx();
+ CPPUNIT_ASSERT(pIndex5);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 11
+ // - Actual : 14
+ // i.e. the shape content index and the frame content index did not match after undo, even if
+ // their "other text box format" pointers pointed to each other.
+ CPPUNIT_ASSERT_EQUAL(pIndex4->GetIndex(), pIndex5->GetIndex());
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 0014d84249b0..79235781896d 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -2489,6 +2489,7 @@ void SwFrameFormat::SetOtherTextBoxFormat( SwFrameFormat *pFormat )
{
assert( nullptr != m_pOtherTextBoxFormat );
}
+ bool bChanged = m_pOtherTextBoxFormat != pFormat;
m_pOtherTextBoxFormat = pFormat;
SdrObject* pObj = FindSdrObject();
@@ -2500,6 +2501,19 @@ void SwFrameFormat::SetOtherTextBoxFormat( SwFrameFormat *pFormat )
if (pSwFlyDraw)
pSwFlyDraw->SetTextBox(true);
}
+
+ if (m_pOtherTextBoxFormat && bChanged && Which() == RES_DRAWFRMFMT)
+ {
+ // This is a shape of a shape+frame pair and my frame has changed. Make sure my content is
+ // in sync with the frame's content.
+ if (GetAttrSet().GetContent() != m_pOtherTextBoxFormat->GetAttrSet().GetContent())
+ {
+ SwAttrSet aSet(GetAttrSet());
+ SwFormatContent aContent(m_pOtherTextBoxFormat->GetAttrSet().GetContent());
+ aSet.Put(aContent);
+ SetFormatAttr(aSet);
+ }
+ }
}
bool SwFrameFormat::supportsFullDrawingLayerFillAttributeSet() const
@@ -2799,6 +2813,11 @@ void SwFrameFormat::dumpAsXml(xmlTextWriterPtr pWriter) const
if (pWhich)
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("which"), BAD_CAST(pWhich));
+ if (m_pOtherTextBoxFormat)
+ {
+ xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("OtherTextBoxFormat"), "%p", m_pOtherTextBoxFormat);
+ }
+
GetAttrSet().dumpAsXml(pWriter);
if (const SdrObject* pSdrObject = FindSdrObject())