tdf#135412 tdf#135888 sw: fix copying of linked text-boxes

The resetLink()/restoreLinks() were added in commit
00a007be5a because testMissingPath
missing-path.docx was crashing.

But then 0bcc5b3dae refactored how linking
works and introduced the isTextBox function, which is called in the
middle of DocumentContentOperationsManager::CopyFlyInFlyImpl() after
resetLink(), and this now always returns false, the same for another
call inside CopyLayoutFormat() (when called from CopyFlyInFlyImpl()),
which causes text-boxes to be copied to 2 separate flys (tdf#135888).

The problem in tdf#135412 is that somehow when called from
SwFEShell::Paste() the content-index from the clipboard document ends up
in the SwDrawFrameFormat that is created in the target document,
and this causes crash in Undo because the node index is out of bounds.

 10 SwUndoInsLayFormat::UndoImpl (this=0x7c2a760, rContext=...) at sw/source/core/undo/undobj1.cxx:310
(rr) p rContent.GetContentIdx()->GetNode().GetDoc()->IsClipBoard()
(rr) $29 = true

It turns out that missing-path.docx doesn't crash any more without
resetLink(), and removing it fixes the 2 bugs.

Change-Id: I0c6c91a42e00b9f3b79b774c814e7323f2bb3e05
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101004
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@cib.de>
This commit is contained in:
Michael Stahl
2020-08-19 19:03:40 +02:00
committed by Michael Stahl
parent 82059a1eb5
commit 10ae7ba661
4 changed files with 4 additions and 24 deletions
+1 -4
View File
@@ -111,12 +111,9 @@ public:
/// Saves the current shape -> textbox links in a map, so they can be restored later.
static void saveLinks(const SwFrameFormats& rFormats,
std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks);
/// Reset the shape -> textbox link on the shape, and save it to the map, so it can be restored later.
static void resetLink(SwFrameFormat* pShape,
std::map<const SwFrameFormat*, SwFormatContent>& rOldContent);
/// Undo the effect of saveLinks() + individual resetLink() calls.
static void restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrameFormat*>& rNew,
SavedLink& rSavedLinks, SavedContent& rResetContent);
SavedLink& rSavedLinks);
};
#endif // INCLUDED_SW_INC_TEXTBOXHELPER_HXX
@@ -3623,7 +3623,6 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl(
SwTextBoxHelper::SavedLink aOldTextBoxes;
SwTextBoxHelper::saveLinks(*m_rDoc.GetSpzFrameFormats(), aOldTextBoxes);
SwTextBoxHelper::SavedContent aOldContent;
for ( size_t n = 0; n < nArrLen; ++n )
{
@@ -3690,9 +3689,6 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl(
}
if( bAdd )
{
// Make sure draw formats don't refer to content, so that such
// content can be removed without problems.
SwTextBoxHelper::resetLink(pFormat, aOldContent);
aSet.insert( ZSortFly( pFormat, pAnchor, nArrLen + aSet.size() ));
}
}
@@ -3863,7 +3859,7 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl(
// Re-create content property of draw formats, knowing how old shapes
// were paired with old fly formats (aOldTextBoxes) and that aSet is
// parallel with aVecSwFrameFormat.
SwTextBoxHelper::restoreLinks(aSet, aVecSwFrameFormat, aOldTextBoxes, aOldContent);
SwTextBoxHelper::restoreLinks(aSet, aVecSwFrameFormat, aOldTextBoxes);
}
/*
+1 -15
View File
@@ -684,19 +684,8 @@ void SwTextBoxHelper::saveLinks(const SwFrameFormats& rFormats,
}
}
void SwTextBoxHelper::resetLink(SwFrameFormat* pShape,
std::map<const SwFrameFormat*, SwFormatContent>& rOldContent)
{
if (pShape->Which() == RES_DRAWFRMFMT)
{
if (pShape->GetContent().GetContentIdx())
rOldContent.insert(std::make_pair(pShape, pShape->GetContent()));
pShape->ResetFormatAttr(RES_CNTNT);
}
}
void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrameFormat*>& rNew,
SavedLink& rSavedLinks, SavedContent& rResetContent)
SavedLink& rSavedLinks)
{
std::size_t i = 0;
for (const auto& rIt : rOld)
@@ -712,9 +701,6 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame
++j;
}
}
if (rResetContent.find(rIt.GetFormat()) != rResetContent.end())
const_cast<SwFrameFormat*>(rIt.GetFormat())
->SetFormatAttr(rResetContent[rIt.GetFormat()]);
++i;
}
}
+1
View File
@@ -301,6 +301,7 @@ void SwUndoInsLayFormat::UndoImpl(::sw::UndoRedoContext & rContext)
const SwFormatContent& rContent = m_pFrameFormat->GetContent();
if( rContent.GetContentIdx() ) // no content
{
assert(&rContent.GetContentIdx()->GetNodes() == &rDoc.GetNodes());
bool bRemoveIdx = true;
if( mnCursorSaveIndexPara > 0 )
{