diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-11-07 10:10:43 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-11-07 12:27:34 +0100 |
commit | dbe744f1deef144e205b72e5927d61a6ea47af25 (patch) | |
tree | eb4bb249ab4124c7b85284f98b2d66727315da3c /sw | |
parent | e194b4e209277ed5beeacf8ea875daa8688ab394 (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.odt | bin | 0 -> 10391 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter2.cxx | 45 | ||||
-rw-r--r-- | sw/source/core/layout/atrfrm.cxx | 19 |
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 Binary files differnew file mode 100644 index 000000000000..6fb758af9168 --- /dev/null +++ b/sw/qa/extras/uiwriter/data2/tdf128603.odt 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()) |