diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-11-04 21:00:51 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-11-05 08:36:05 +0100 |
commit | f6e7683847e5c959948b55c35bc916c69beb615e (patch) | |
tree | c18089da5f29f2be8686eaabf85d2fef5b3523a5 | |
parent | c47834b494f9b94fb34e0305d106cf498a3cec81 (diff) |
tdf#128335 sw textbox: fix crash on deleting multiple shapes with textboxes
This was introduced in commit 33141f999b22ce10cdbfbd76081fff211c4b5067
(SwDrawView::DeleteMarked: delete textbox of shape as well, 2014-06-23),
the problem is that in case one shape+textframe pair is anchored in an
other textframe, which is also part of a shape+textframe pair, it
matters what order we use for deleting these objects.
What happened is that the anchor position of a 2nd textbox was updated
on the deletion (cut) of the 1st textbox, and this was not properly
restored on paste.
Fix the problem by deleting in reverse order, assuming that the
container is ordered by anchor positions.
Change-Id: I62bc12a5064ce397234999e8fd7b108f79de3c24
Reviewed-on: https://gerrit.libreoffice.org/82042
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r-- | sw/qa/extras/uiwriter/data2/tdf128335.odt | bin | 0 -> 10391 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter2.cxx | 36 | ||||
-rw-r--r-- | sw/source/core/draw/dview.cxx | 6 |
3 files changed, 41 insertions, 1 deletions
diff --git a/sw/qa/extras/uiwriter/data2/tdf128335.odt b/sw/qa/extras/uiwriter/data2/tdf128335.odt Binary files differnew file mode 100644 index 000000000000..6fb758af9168 --- /dev/null +++ b/sw/qa/extras/uiwriter/data2/tdf128335.odt diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index de1ff27bfc96..14f7e0a5ac6b 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -17,6 +17,7 @@ #include <com/sun/star/frame/DispatchHelper.hpp> #include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/text/TableColumnSeparator.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> #include <comphelper/propertysequence.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <i18nlangtag/languagetag.hxx> @@ -2329,4 +2330,39 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf118311) assertXPath(pXmlDoc, "//page[1]//body/tab", 0); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128335) +{ + // Load the bugdoc, which has 3 textboxes. + SwDoc* pDoc = createDoc("tdf128335.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); + + // Select all shapes. + uno::Reference<view::XSelectionSupplier> xSelectionSupplier( + pXTextDocument->getCurrentController(), uno::UNO_QUERY); + xSelectionSupplier->select(pXTextDocument->getDrawPages()->getByIndex(0)); + + // Cut them. + // Without the accompanying fix in place, this test would have crashed as the textboxes were + // deleted in an incorrect order. + pView->GetViewFrame()->GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx index e617a6da8dec..54f86e8abb27 100644 --- a/sw/source/core/draw/dview.cxx +++ b/sw/source/core/draw/dview.cxx @@ -975,8 +975,12 @@ void SwDrawView::DeleteMarked() ::FrameNotify( Imp().GetShell(), FLY_DRAG_END ); // Only delete these now: earlier deletion would clear the mark list as well. - for (auto& rpTextBox : aTextBoxesToDelete) + // Delete in reverse order, assuming that the container is sorted by anchor positions. + for (int i = aTextBoxesToDelete.size() - 1; i >= 0; --i) + { + SwFrameFormat*& rpTextBox = aTextBoxesToDelete[i]; pDoc->getIDocumentLayoutAccess().DelLayoutFormat(rpTextBox); + } } pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); if( pTmpRoot ) |