sw/inc/ndarr.hxx                  |    4 -
 sw/source/core/docnode/nodes.cxx  |  145 ++++++++++++++++++++++++--------------
 sw/source/core/layout/frmtool.cxx |    5 +
 3 files changed, 102 insertions(+), 52 deletions(-)

New commits:
commit 1ca3c0d70b31ed173a896bcb37cc731b5324a573
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Dec 21 15:19:33 2021 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Dec 23 11:14:27 2021 +0100

    tdf#135061 sw_redlinehide: create frames following hidden table
    
    When pasting, the entire document body is covered by a delete redline.
    
    The insert position is in the last node, following a table; table nodes
    do hot have any connection to frames if they are hidden by redlines,
    so MakeFrames() won't create frames for the inserted nodes.
    
    Refactor SwNodes::FindPrvNxtFrameNode() so that it can detect that table
    nodes are hidden in the current layout and continue to search in this
    case.
    
    For multiple layouts, MakeFrames() may need to use different nodes per
    layout, as the "nearest" one in one layout may be hidden in another.
    
    Change-Id: I3bb2c861c861438ac2695ab49dd91dc2bde87db4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127272
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit af4e20426ad24c6f2c0164b37472f2b7b54ecd30)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127316
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/inc/ndarr.hxx b/sw/inc/ndarr.hxx
index 6167708d0eb6..18ca83066f82 100644
--- a/sw/inc/ndarr.hxx
+++ b/sw/inc/ndarr.hxx
@@ -44,6 +44,7 @@ class SwNodeIndex;
 class SwNodeRange;
 class SwOLENode;
 class SwPaM;
+class SwRootFrame;
 class SwSectionData;
 class SwSectionFormat;
 class SwTOXBase;
@@ -307,7 +308,8 @@ public:
      forward after pEnd.
      If no valid node is found, return 0. rFrameIdx points to the node with 
frames. **/
     SwNode* FindPrvNxtFrameNode( SwNodeIndex& rFrameIdx,
-                                const SwNode* pEnd ) const;
+                                const SwNode* pEnd,
+                                SwRootFrame const* pLayout = nullptr) const;
 
     SwNode * DocumentSectionStartNode(SwNode * pNode) const;
     SwNode * DocumentSectionEndNode(SwNode * pNode) const;
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 6be389697304..708bdb71f27d 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -43,6 +43,7 @@
 #include <fmtftn.hxx>
 
 #include <docsh.hxx>
+#include <rootfrm.hxx>
 #include <txtfrm.hxx>
 
 typedef std::vector<SwStartNode*> SwStartNodePointers;
@@ -2039,7 +2040,8 @@ SwContentNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
  * @return result node; 0 if not found
  */
 SwNode* SwNodes::FindPrvNxtFrameNode( SwNodeIndex& rFrameIdx,
-                                    const SwNode* pEnd ) const
+        SwNode const*const pEnd,
+        SwRootFrame const*const pLayout) const
 {
     assert(pEnd != nullptr); // every caller currently
 
@@ -2062,53 +2064,65 @@ SwNode* SwNodes::FindPrvNxtFrameNode( SwNodeIndex& 
rFrameIdx,
                     ? pSttNd->StartOfSectionNode()->FindTableNode()
                     : pSttNd->FindTableNode();
             SwNodeIndex aIdx( rFrameIdx );
+
+            // search backward for a content or table node
+
             --aIdx;
-            SwNode *const pNd = &aIdx.GetNode();
+            pFrameNd = &aIdx.GetNode();
 
-            pFrameNd = pNd;
-            if (pFrameNd->IsContentNode())
+            do
             {
-                rFrameIdx = aIdx;
-                return pFrameNd;
-            }
-            // search forward or backward for a content node
-            pFrameNd = GoPrevSection( &aIdx, true, false );
-            if ( nullptr != pFrameNd &&
-                    ::CheckNodesRange( aIdx, rFrameIdx, true ) &&
-                    // Never out of the table at the start
-                    pFrameNd->FindTableNode() == pTableNd &&
-                    // Bug 37652: Never out of the table at the end
-                    (!pFrameNd->FindTableNode() || 
pFrameNd->FindTableBoxStartNode()
-                        == pSttNd->FindTableBoxStartNode() ) &&
-                     (!pSectNd || pSttNd->IsSectionNode() ||
-                      pSectNd->GetIndex() < pFrameNd->GetIndex())
-                    )
-            {
-                rFrameIdx = aIdx;
-            }
-            else
-            {
-                aIdx = pEnd->GetIndex() + 1;
-
-                pFrameNd = &aIdx.GetNode();
-                if (!pFrameNd->IsContentNode())
+                if (pFrameNd->IsContentNode())
                 {
-                    pFrameNd = GoNextSection( &aIdx, true, false );
-                    // NEVER leave the section when doing this!
-                    if (pFrameNd
-                        && !(::CheckNodesRange(aIdx, rFrameIdx, true)
-                             && (pFrameNd->FindTableNode() == pTableNd &&
-                                // NEVER go out of the table cell at the end
-                                (!pFrameNd->FindTableNode() || 
pFrameNd->FindTableBoxStartNode()
-                                    == pSttNd->FindTableBoxStartNode()))
-                             && (!pSectNd || pSttNd->IsSectionNode() ||
-                               pSectNd->EndOfSectionIndex() > 
pFrameNd->GetIndex()))
-                        )
+                    // TODO why does this not check for nested tables like 
forward direction
+                    rFrameIdx = aIdx;
+                    return pFrameNd;
+                }
+                else if (pFrameNd->IsEndNode() && 
pFrameNd->StartOfSectionNode()->IsTableNode())
+                {
+                    if (pLayout == nullptr
+                        || !pLayout->HasMergedParas()
+                        || 
pFrameNd->StartOfSectionNode()->GetRedlineMergeFlag() != SwNode::Merge::Hidden)
                     {
-                        pFrameNd = nullptr;
+                        pFrameNd = pFrameNd->StartOfSectionNode();
+                        rFrameIdx = *pFrameNd;
+                        return pFrameNd;
+                    }
+                    else
+                    {
+                        aIdx = *pFrameNd->StartOfSectionNode();
+                        --aIdx;
+                        pFrameNd = &aIdx.GetNode();
                     }
                 }
-                if (pFrameNd && pFrameNd->IsContentNode())
+                else
+                {
+                    pFrameNd = GoPrevSection( &aIdx, true, false );
+                    if ( nullptr != pFrameNd && !(
+                            ::CheckNodesRange( aIdx, rFrameIdx, true ) &&
+                            // Never out of the table at the start
+                            pFrameNd->FindTableNode() == pTableNd &&
+                            // Bug 37652: Never out of the table at the end
+                            (!pFrameNd->FindTableNode() || 
pFrameNd->FindTableBoxStartNode()
+                                == pSttNd->FindTableBoxStartNode() ) &&
+                             (!pSectNd || pSttNd->IsSectionNode() ||
+                              pSectNd->GetIndex() < pFrameNd->GetIndex())
+                            ))
+                    {
+                        pFrameNd = nullptr; // no preceding content node, stop 
search
+                    }
+                }
+            }
+            while (pFrameNd != nullptr);
+
+            // search forward for a content or table node
+
+            aIdx = pEnd->GetIndex() + 1;
+            pFrameNd = &aIdx.GetNode();
+
+            do
+            {
+                if (pFrameNd->IsContentNode())
                 {
                     // Undo when merging a table with one before, if there is 
also one after it.
                     // However, if the node is in a table, it needs to be 
returned if the
@@ -2123,23 +2137,54 @@ SwNode* SwNodes::FindPrvNxtFrameNode( SwNodeIndex& 
rFrameIdx,
                         rFrameIdx = *pFrameNd;
                     }
                     else
+                    {
                         rFrameIdx = aIdx;
+                    }
+                    return pFrameNd;
                 }
-                else if( pNd->IsEndNode() && 
pNd->StartOfSectionNode()->IsTableNode() )
+                else if (pFrameNd->IsTableNode())
                 {
-                    pFrameNd = pNd->StartOfSectionNode();
-                    rFrameIdx = *pFrameNd;
+                    if (pLayout == nullptr
+                        || !pLayout->HasMergedParas()
+                        || pFrameNd->GetRedlineMergeFlag() != 
SwNode::Merge::Hidden)
+                    {
+                        rFrameIdx = *pFrameNd;
+                        return pFrameNd;
+                    }
+                    else
+                    {
+                        aIdx = *pFrameNd->EndOfSectionNode();
+                        ++aIdx;
+                        pFrameNd = &aIdx.GetNode();
+                    }
                 }
                 else
                 {
+                    pFrameNd = GoNextSection( &aIdx, true, false );
+                    // NEVER leave the section when doing this!
+                    if (pFrameNd
+                        && !(::CheckNodesRange(aIdx, rFrameIdx, true)
+                             && (pFrameNd->FindTableNode() == pTableNd &&
+                                // NEVER go out of the table cell at the end
+                                (!pFrameNd->FindTableNode() || 
pFrameNd->FindTableBoxStartNode()
+                                    == pSttNd->FindTableBoxStartNode()))
+                             && (!pSectNd || pSttNd->IsSectionNode() ||
+                               pSectNd->EndOfSectionIndex() > 
pFrameNd->GetIndex()))
+                        )
+                    {
+                        pFrameNd = nullptr; // no following content node, stop 
search
+                    }
+                }
+            }
+            while (pFrameNd != nullptr);
+
+            // probably this is dead code, because the GoNextSection()
+            // should have ended up in the first text node in the table and
+            // then checked it's in a table?
+            {
                     aIdx = pEnd->GetIndex() + 1;
 
                     pFrameNd = &aIdx.GetNode();
-                    if (pFrameNd->IsTableNode())
-                    {
-                        rFrameIdx = aIdx;
-                    }
-                    else
                     {
                         pFrameNd = nullptr;
 
@@ -2157,9 +2202,9 @@ SwNode* SwNodes::FindPrvNxtFrameNode( SwNodeIndex& 
rFrameIdx,
                         {
                             rFrameIdx = aIdx;
                             pFrameNd = &aIdx.GetNode();
+                            assert(!"this isn't dead code?");
                         }
                     }
-                }
             }
         }
     }
diff --git a/sw/source/core/layout/frmtool.cxx 
b/sw/source/core/layout/frmtool.cxx
index 51ace45200bc..375c108d6558 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -69,6 +69,7 @@
 #include <undobj.hxx>
 #include <DocumentSettingManager.hxx>
 #include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
 #include <IDocumentTimerAccess.hxx>
 #include <IDocumentRedlineAccess.hxx>
 #include <IDocumentFieldsAccess.hxx>
@@ -1953,8 +1954,10 @@ void MakeFrames( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
 
     SwNodeIndex aTmp( rSttIdx );
     sal_uLong nEndIdx = rEndIdx.GetIndex();
+    // TODO for multiple layouts there should be a loop here
     SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrameNode( aTmp,
-                                            pDoc->GetNodes()[ nEndIdx-1 ]);
+                    pDoc->GetNodes()[ nEndIdx-1 ],
+                    pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
     if ( pNd )
     {
         bool bApres = aTmp < rSttIdx;

Reply via email to