sw/source/core/inc/flowfrm.hxx     |    3 ++
 sw/source/core/layout/calcmove.cxx |   49 +++++++++++++++++++++++++---------
 sw/source/core/layout/flowfrm.cxx  |   52 +++++++++++++++++++++++++++++++++----
 sw/source/core/layout/fly.cxx      |    5 ++-
 sw/source/core/layout/frmtool.cxx  |    2 -
 5 files changed, 90 insertions(+), 21 deletions(-)

New commits:
commit 75a0e9c5f8b364e194e087a6255f8174f55bbda6
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Dec 6 14:20:22 2024 +0100
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Tue Dec 24 14:10:17 2024 +0100

    sw: layout: ignore Keep-With-Next on hidden frames, part2
    
    SwFrame::PrepareMake(), SwContentFrame::MakeAll(),
    SwContentFrame::WouldFit_()
    
    Change-Id: I2a909ac6d147668dddece97bd99e31fdddcf20eb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177976
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit a08b8fa2d01e630ef876b7944c37f0b6de09d407)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177996
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/sw/source/core/layout/calcmove.cxx 
b/sw/source/core/layout/calcmove.cxx
index e04edcddd5a9..338030c7c03d 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -304,9 +304,17 @@ void SwFrame::PrepareMake(vcl::RenderContext* 
pRenderContext)
 
         // There is no format of previous frame, if current frame is a table
         // frame and its previous frame wants to keep with it.
-        const bool bFormatPrev = !bTab ||
-                                 !GetPrev() ||
-                                 
!GetPrev()->GetAttrSet()->GetKeep().GetValue();
+        bool bFormatPrev{!bTab};
+        if (!bFormatPrev)
+        {
+            SwFrame const* pPrev{this};
+            do
+            {
+                pPrev = pPrev->GetPrev();
+            }
+            while (pPrev && pPrev->IsHiddenNow());
+            bFormatPrev = pPrev && !pPrev->GetAttrSet()->GetKeep().GetValue();
+        }
         if ( bFormatPrev )
         {
             SwFrame *pFrame = GetUpper()->Lower();
@@ -1351,7 +1359,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* 
/*pRenderContext*/)
         oNotify->SetBordersJoinedWithPrev();
     }
 
-    const bool bKeep = IsKeep(rAttrs.GetAttrSet().GetKeep(), GetBreakItem());
+    const bool bKeep{!isHiddenNow && IsKeep(rAttrs.GetAttrSet().GetKeep(), 
GetBreakItem())};
 
     std::unique_ptr<SwSaveFootnoteHeight> pSaveFootnote;
     if ( bFootnote )
@@ -1767,7 +1775,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* 
/*pRenderContext*/)
 
         if( nBottomDist >= 0 )
         {
-            if ( bKeep && bMoveable )
+            if (bKeep && bMoveable && !isHiddenNow)
             {
                 // We make sure the successor will be formatted the same.
                 // This way, we keep control until (almost) everything is 
stable,
@@ -2094,8 +2102,18 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
     const SwFrame *pTmpPrev = pNewUpper->Lower();
     if( pTmpPrev && pTmpPrev->IsFootnoteFrame() )
         pTmpPrev = static_cast<const SwFootnoteFrame*>(pTmpPrev)->Lower();
-    while ( pTmpPrev && pTmpPrev->GetNext() )
-        pTmpPrev = pTmpPrev->GetNext();
+    {
+        SwFrame const* pTmpNonHidden{pTmpPrev && pTmpPrev->IsHiddenNow() ? 
nullptr : pTmpPrev};
+        while (pTmpPrev && pTmpPrev->GetNext())
+        {
+            pTmpPrev = pTmpPrev->GetNext();
+            if (!pTmpPrev->IsHiddenNow())
+            {
+                pTmpNonHidden = pTmpPrev;
+            }
+        }
+        pTmpPrev = pTmpNonHidden;
+    }
 
     // tdf#156727 if the previous one has keep-with-next, ignore it on this 
one!
     bool const isIgnoreKeep(pTmpPrev && pTmpPrev->IsFlowFrame()
@@ -2104,6 +2122,14 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
 
     do
     {
+        if (pFrame->IsHiddenNow())
+        {   // shortcut
+            assert(pFrame == this);
+            bRet = true;
+            pFrame = nullptr;
+            break;
+        }
+
         // #i46181#
         SwTwips nSecondCheck = 0;
         SwTwips nOldSpace = nSpace;
@@ -2269,8 +2295,8 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
                     return true;
                 }
             }
-            SwFrame *pNxt;
-            if( nullptr != (pNxt = pFrame->FindNext()) && 
pNxt->IsContentFrame() &&
+            SwFrame *const pNxt{pFrame->FindNextIgnoreHidden()};
+            if (nullptr != pNxt && pNxt->IsContentFrame() &&
                 ( !pFootnoteFrame || ( pNxt->IsInFootnote() &&
                   pNxt->FindFootnoteFrame()->GetAttr() == 
pFootnoteFrame->GetAttr() ) ) )
             {
@@ -2296,10 +2322,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
                     pTmpPrev = nullptr;
                 else
                 {
-                    if (pFrame->IsHiddenNow())
-                        pTmpPrev = lcl_NotHiddenPrev( pFrame );
-                    else
-                        pTmpPrev = pFrame;
+                    pTmpPrev = pFrame;
                 }
                 pFrame = static_cast<SwContentFrame*>(pNxt);
             }
commit ea2d36e7cc290200609da2ab133e1f682dd4a22b
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Dec 6 14:10:32 2024 +0100
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Tue Dec 24 14:10:08 2024 +0100

    sw: layout: ignore Keep-With-Next on hidden frames, part1
    
    When a frame is hidden, don't consider it when evaluating keep-with-next
    attributes - this was the case for content in hidden sections before
    commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1
    
    ~SwFrameNotify() invalidating position of hidden frame with keep
    attribute causes layout loops.
    
    Also skip hidden frames in SwFlowFrame::IsKeepFwdMoveAllowed(),
    SwFlowFrame::CheckKeep(), SwFlowFrame::IsPrevObjMove(),
    SwFlowFrame::MoveBwd(), CalcContent().
    
    Change-Id: I68556ba0a8e016d962399f3ce199e5eda0378867
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177975
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit cd8468bcba952ab9b0d6ca97152a63d7469a9209)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177995
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/sw/source/core/inc/flowfrm.hxx b/sw/source/core/inc/flowfrm.hxx
index 154fd37febf2..c8ca0b55cd06 100644
--- a/sw/source/core/inc/flowfrm.hxx
+++ b/sw/source/core/inc/flowfrm.hxx
@@ -184,6 +184,9 @@ public:
                 SvxFormatBreakItem const& rBreak,
                 bool bBreakCheck = false ) const;
 
+    SwFrame * FindPrevIgnoreHidden() const;
+    SwFrame * FindNextIgnoreHidden() const;
+
     bool HasLockedFollow() const;
 
     bool HasParaSpaceAtPages( bool bSct ) const;
diff --git a/sw/source/core/layout/flowfrm.cxx 
b/sw/source/core/layout/flowfrm.cxx
index b45c8d100fcb..8a2bab2647bb 100644
--- a/sw/source/core/layout/flowfrm.cxx
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -131,7 +131,9 @@ bool SwFlowFrame::IsKeepFwdMoveAllowed( bool 
bIgnoreMyOwnKeepValue )
         if ( bIgnoreMyOwnKeepValue && pFrame->GetIndPrev() )
             pFrame = pFrame->GetIndPrev();
         do
-        {   if ( pFrame->GetAttrSet()->GetKeep().GetValue() )
+        {
+            if (pFrame->GetAttrSet()->GetKeep().GetValue()
+                || pFrame->IsHiddenNow())
                 pFrame = pFrame->GetIndPrev();
             else
                 return true;
@@ -150,22 +152,42 @@ void SwFlowFrame::CheckKeep()
     // it's possible for the whole troop to move back.
     SwFrame *pPre = m_rThis.GetIndPrev();
     assert(pPre);
+    while (pPre && pPre->IsHiddenNow())
+    {
+        pPre = pPre->GetIndPrev();
+    }
+    if (!pPre)
+    {
+        return;
+    }
     if( pPre->IsSctFrame() )
     {
         SwFrame *pLast = static_cast<SwSectionFrame*>(pPre)->FindLastContent();
+        while (pLast && pLast->IsHiddenNow())
+        {
+            pLast = pLast->GetIndPrev();
+        }
         if( pLast && pLast->FindSctFrame() == pPre )
             pPre = pLast;
         else
             return;
     }
-    SwFrame* pTmp;
+    SwFrame* pTmp{pPre};
     bool bKeep;
     while ( (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
-            nullptr != ( pTmp = pPre->GetIndPrev() ) )
+            nullptr != (pTmp = pTmp->GetIndPrev()) )
     {
+        if (pTmp->IsHiddenNow())
+        {
+            continue;
+        }
         if( pTmp->IsSctFrame() )
         {
             SwFrame *pLast = 
static_cast<SwSectionFrame*>(pTmp)->FindLastContent();
+            while (pLast && pLast->IsHiddenNow())
+            {
+                pLast = pLast->GetIndPrev();
+            }
             if( pLast && pLast->FindSctFrame() == pTmp )
                 pTmp = pLast;
             else
@@ -338,6 +360,26 @@ bool SwFlowFrame::IsKeep(SvxFormatKeepItem const& rKeep,
     return bKeep;
 }
 
+SwFrame * SwFlowFrame::FindPrevIgnoreHidden() const
+{
+    SwFrame * pRet{m_rThis.FindPrev()};
+    while (pRet && pRet->IsHiddenNow())
+    {
+        pRet = pRet->FindPrev();
+    }
+    return pRet;
+}
+
+SwFrame * SwFlowFrame::FindNextIgnoreHidden() const
+{
+    SwFrame * pRet{m_rThis.FindNext()};
+    while (pRet && pRet->IsHiddenNow())
+    {
+        pRet = pRet->FindNext();
+    }
+    return pRet;
+}
+
 sal_uInt8 SwFlowFrame::BwdMoveNecessary( const SwPageFrame *pPage, const 
SwRect &rRect )
 {
     // The return value helps deciding whether we need to flow back (3),
@@ -1188,7 +1230,7 @@ bool SwFlowFrame::IsPrevObjMove() const
     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
         return false;
 
-    SwFrame *pPre = m_rThis.FindPrev();
+    SwFrame *const pPre{FindPrevIgnoreHidden()};
 
     if ( pPre && pPre->GetDrawObjs() )
     {
@@ -2616,7 +2658,7 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat )
     // keep with next frame and next frame is locked.
     // i#38232 - If next frame is a table, do *not* check,
     // if it's locked.
-    if ( pNewUpper && !IsFollow() &&
+    if ( pNewUpper && !IsFollow() && !m_rThis.IsHiddenNow() &&
          m_rThis.GetAttrSet()->GetKeep().GetValue() && m_rThis.GetIndNext() )
     {
         SwFrame* pIndNext = m_rThis.GetIndNext();
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 313f047ece98..f4cefef5ae29 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -1698,9 +1698,10 @@ void CalcContent( SwLayoutFrame *pLay, bool bNoColl )
             // frame due to its keep-attribute, if it can't move forward.
             // #i57765# - do not consider invalid previous
             // frame, if current frame has a column/page break before 
attribute.
-            SwFrame* pTmpPrev = pFrame->FindPrev();
+            assert(pFrame->IsFlowFrame());
+            SwFlowFrame* pTmpFlowFrame = SwFlowFrame::CastFlowFrame(pFrame);
+            SwFrame* pTmpPrev = pTmpFlowFrame->FindPrevIgnoreHidden();
             SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && 
pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr;
-            SwFlowFrame* pTmpFlowFrame     = pFrame->IsFlowFrame() ? 
SwFlowFrame::CastFlowFrame(pFrame) : nullptr;
 
             bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame &&
                                !pTmpFlowFrame->IsFollow() &&
diff --git a/sw/source/core/layout/frmtool.cxx 
b/sw/source/core/layout/frmtool.cxx
index 05b968737cc3..95c008a8af42 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -155,7 +155,7 @@ void SwFrameNotify::ImplDestroy()
             {
                 if ( mbInvaKeep )
                 {
-                    SwFrame *pPre = mpFrame->FindPrev();
+                    SwFrame *pPre = pFlow->FindPrevIgnoreHidden();
                     if ( pPre && pPre->IsFlowFrame() )
                     {
                         // 1. pPre wants to keep with me:

Reply via email to