tdf#159023 sw_redlinehide: fix layout frames copying table into footer

Tables in footer aren't supported - if a table is pasted into the
footer, SwNodes::CopyNodes() inserts for table/cell nodes the
SwPlaceholderNodes so that the relative distance between any copied
node is the same in the target, and once the other stuff like bookmarks
and anchored flys are copied, SwNodes::DelDummyNodes() removes the
SwPlaceholderNodes.

If SwNodes::CopyNodes() is called with bNewFrames=true, it handles
creating the frames well, but with bNewFrames=false and a subsequent
MakeFrames(), the InsertCnt_() simply quits once it sees the first
SwPlaceholderNode and so no frames are created for the nodes in the
table cells.

Rearrange DocumentContentOperationsManager::CopyWithFlyInFly() to move
the MakeFrames() down below DelDummyNodes(), which requires adding a
parameter to CopyFlyInFlyImpl() to prevent it from creating frames
(anchored objects will also be created by MakeFrames() later).

(regression from commit 166b5010b402a41b192b1659093a25acf9065fd9)

Change-Id: I0ac30bec6e6423bb7d12c0a29f33848a5b61cd98
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162320
Tested-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 09e0a12..b78b6b6 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3828,12 +3828,61 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(

    if (rRg.aStart != rRg.aEnd)
    {
        ++aSavePos;
    }

#if OSL_DEBUG_LEVEL > 0
    {
        //JP 17.06.99: Bug 66973 - check count only if the selection is in
        // the same section or there's no section, because sections that are
        // not fully selected are not copied.
        const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
        SwNodeIndex aTmpI( rRg.aEnd, -1 );
        const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
        if( pSSectNd == pESectNd &&
            !rRg.aStart.GetNode().IsSectionNode() &&
            !aTmpI.GetNode().IsEndNode() )
        {
            // If the range starts with a SwStartNode, it isn't copied
            SwNodeOffset offset( (rRg.aStart.GetNode().GetNodeType() != SwNodeType::Start) ? 1 : 0 );
            OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
                    rRg.aEnd.GetIndex() - rRg.aStart.GetIndex() - 1 + offset,
                    "An insufficient number of nodes were copied!" );
        }
    }
#endif

    {
        ::sw::UndoGuard const undoGuard(rDest.GetIDocumentUndoRedo());
        // this must happen before lcl_DeleteRedlines() because it counts nodes
        CopyFlyInFlyImpl(rRg, pCopiedPaM ? &pCopiedPaM->first : nullptr,
            // see comment below regarding use of pCopiedPaM->second
            (pCopiedPaM && rRg.aStart != pCopiedPaM->first.Start()->GetNode())
                ? pCopiedPaM->second.GetNode()
                : aSavePos.GetNode(),
            bCopyFlyAtFly,
            flags,
            false);
    }

    SwNodeRange aCpyRange( aSavePos.GetNode(), rInsPos );

    if( bDelRedlines && ( RedlineFlags::DeleteRedlines & rDest.getIDocumentRedlineAccess().GetRedlineFlags() ))
        lcl_DeleteRedlines( rRg, aCpyRange );

    rDest.GetNodes().DelDummyNodes( aCpyRange );

    // tdf#159023 create layout frames after DelDummyNodes():
    // InsertCnt_() does early return on the first SwPlaceholderNode
    if (rRg.aStart != rRg.aEnd)
    {
        --aSavePos; // restore temporarily...
        bool isRecreateEndNode(false);
        if (bMakeNewFrames) // tdf#130685 only after aRedlRest
        {   // recreate from previous node (could be merged now)
            o3tl::sorted_vector<SwTextFrame*> frames;
            SwTextNode * pNode = aSavePos.GetNode().GetTextNode();
            SwTextNode *const pEndNode = rInsPos.GetTextNode();
            SwTextNode * pNode(aSavePos.GetNode().GetTextNode());
            SwTextNode *const pEndNode(rInsPos.GetTextNode());
            if (pEndNode)
            {
                SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode);
@@ -3861,7 +3910,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
                    {
                        if (pFrame->getRootFrame()->HasMergedParas())
                        {
                            auto const it = frames.find(pFrame);
                            auto const it(frames.find(pFrame));
                            if (it != frames.end())
                            {
                                frames.erase(it);
@@ -3885,50 +3934,11 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
            // if it was the first node in the document so that MakeFrames()
            // will find the existing (wasn't deleted) frame on it
            SwNodeIndex const end(rInsPos,
                    SwNodeOffset((!isRecreateEndNode || isAtStartOfSection)
                SwNodeOffset((!isRecreateEndNode || isAtStartOfSection)
                    ? 0 : +1));
            ::MakeFrames(&rDest, aSavePos.GetNode(), end.GetNode());
        }
    }

#if OSL_DEBUG_LEVEL > 0
    {
        //JP 17.06.99: Bug 66973 - check count only if the selection is in
        // the same section or there's no section, because sections that are
        // not fully selected are not copied.
        const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
        SwNodeIndex aTmpI( rRg.aEnd, -1 );
        const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
        if( pSSectNd == pESectNd &&
            !rRg.aStart.GetNode().IsSectionNode() &&
            !aTmpI.GetNode().IsEndNode() )
        {
            // If the range starts with a SwStartNode, it isn't copied
            SwNodeOffset offset( (rRg.aStart.GetNode().GetNodeType() != SwNodeType::Start) ? 1 : 0 );
            OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
                    rRg.aEnd.GetIndex() - rRg.aStart.GetIndex() - 1 + offset,
                    "An insufficient number of nodes were copied!" );
        }
    }
#endif

    {
        ::sw::UndoGuard const undoGuard(rDest.GetIDocumentUndoRedo());
        CopyFlyInFlyImpl(rRg, pCopiedPaM ? &pCopiedPaM->first : nullptr,
            // see comment below regarding use of pCopiedPaM->second
            (pCopiedPaM && rRg.aStart != pCopiedPaM->first.Start()->GetNode())
                ? pCopiedPaM->second.GetNode()
                : aSavePos.GetNode(),
            bCopyFlyAtFly,
            flags);
    }

    SwNodeRange aCpyRange( aSavePos.GetNode(), rInsPos );

    if( bDelRedlines && ( RedlineFlags::DeleteRedlines & rDest.getIDocumentRedlineAccess().GetRedlineFlags() ))
        lcl_DeleteRedlines( rRg, aCpyRange );

    rDest.GetNodes().DelDummyNodes( aCpyRange );
}

// note: for the redline Show/Hide this must be in sync with
@@ -3938,7 +3948,8 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl(
    SwPaM const*const pCopiedPaM,
    SwNode& rStartIdx,
    const bool bCopyFlyAtFly,
    SwCopyFlags const flags) const
    SwCopyFlags const flags,
    bool const bMakeNewFrames) const
{
    assert(!pCopiedPaM || pCopiedPaM->End()->GetNode() == rRg.aEnd.GetNode());

@@ -4142,7 +4153,7 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl(

        // Copy the format and set the new anchor
        aVecSwFrameFormat.push_back( rDest.getIDocumentLayoutAccess().CopyLayoutFormat( *(*it).GetFormat(),
                aAnchor, false, true ) );
                aAnchor, false, bMakeNewFrames) );
        ++it;
    }

diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index 8332cf3..3cb378f 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -111,7 +111,8 @@ public:
                            SwPaM const*const pCopiedPaM,
                            SwNode& rStartIdx,
                            const bool bCopyFlyAtFly = false,
                            SwCopyFlags flags = SwCopyFlags::Default) const;
                            SwCopyFlags flags = SwCopyFlags::Default,
                            bool bMakeNewFrames = true) const;

    /// Parameters for _Rst and lcl_SetTextFormatColl
    //originallyfrom docfmt.cxx