sw/qa/uitest/data/tdf163325.odt    |binary
 sw/source/core/inc/flowfrm.hxx     |    3 ++
 sw/source/core/layout/calcmove.cxx |   50 +++++++++++++++++++++++++---------
 sw/source/core/layout/flowfrm.cxx  |   53 +++++++++++++++++++++++++++++++++----
 sw/source/core/layout/fly.cxx      |    5 ++-
 sw/source/core/layout/frmtool.cxx  |    2 -
 sw/source/core/layout/sectfrm.cxx  |    8 +++--
 sw/source/core/layout/tabfrm.cxx   |   14 ++++-----
 8 files changed, 104 insertions(+), 31 deletions(-)

New commits:
commit 7a7066401aefca1a2da6851c72a98ab1c0843b5a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Dec 6 14:24:12 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Dec 6 16:51:20 2024 +0100

    sw: layout: ignore Keep-With-Next on hidden frames, part3
    
    SwTabFrame: :MakeAll(), SwRowFrame::ShouldRowKeepWithNext()
    Change-Id: I7cb6e558dc05736658a9bc75d6c735e6a47062b0

diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index e57ba525df0b..c5a5897b7ccb 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2026,10 +2026,10 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
 
     const bool bLargeTable = GetTable()->GetTabLines().size() > 64;  
//arbitrary value, virtually guaranteed to be larger than one page.
     const bool bEmulateTableKeep = !bLargeTable && AreAllRowsKeepWithNext( 
GetFirstNonHeadlineRow(), /*bCheckParents=*/false );
+    bool const isHiddenNow(IsHiddenNow());
     // The beloved keep attribute
-    const bool bKeep = IsKeep(pAttrs->GetAttrSet().GetKeep(), GetBreakItem(), 
bEmulateTableKeep);
+    const bool bKeep{!isHiddenNow && IsKeep(pAttrs->GetAttrSet().GetKeep(), 
GetBreakItem(), bEmulateTableKeep)};
 
-    bool const isHiddenNow(IsHiddenNow());
     // All rows should keep together
     const bool bDontSplit = isHiddenNow
                 || (!IsFollow() && !GetFormat()->GetLayoutSplit().GetValue());
@@ -2150,9 +2150,8 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
                 }
                 aNotify.SetLowersComplete( false );
             }
-            SwFrame *pPre;
-            if ( bKeep || (nullptr != (pPre = FindPrev()) &&
-                pPre->GetAttrSet()->GetKeep().GetValue()) )
+            SwFrame const*const pPre{bKeep ? nullptr : FindPrevIgnoreHidden()};
+            if (bKeep || (nullptr != pPre && 
pPre->GetAttrSet()->GetKeep().GetValue()))
             {
                 m_bCalcLowers = true;
             }
@@ -2435,7 +2434,8 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
                             pAccess = 
std::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this);
                             pAttrs = pAccess->Get();
                         }
-                        if (IsKeep(pAttrs->GetAttrSet().GetKeep(), 
GetBreakItem(), true)
+                        if (!isHiddenNow
+                            && IsKeep(pAttrs->GetAttrSet().GetKeep(), 
GetBreakItem(), true)
                             && pLastRow->ShouldRowKeepWithNext())
                         {
                             bFormat = true;
@@ -4862,7 +4862,7 @@ bool SwRowFrame::ShouldRowKeepWithNext( const bool 
bCheckParents ) const
     const SwCellFrame* pCell = static_cast<const SwCellFrame*>(Lower());
     const SwFrame* pText = pCell->Lower();
 
-    return pText && pText->IsTextFrame() &&
+    return pText && pText->IsTextFrame() && !pText->IsHiddenNow() &&
            static_cast<const 
SwTextFrame*>(pText)->GetTextNodeForParaProps()->GetSwAttrSet().GetKeep(bCheckParents).GetValue();
 }
 
commit 4ef7153ad62dc042fe5b9f211be89a69360e0ea1
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Dec 6 14:20:22 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Dec 6 16:51:20 2024 +0100

    sw: layout: ignore Keep-With-Next on hidden frames, part2
    
    SwFrame::PrepareMake(), SwContentFrame::MakeAll(),
    SwContentFrame::WouldFit_()
    
    Change-Id: I2a909ac6d147668dddece97bd99e31fdddcf20eb

diff --git a/sw/source/core/layout/calcmove.cxx 
b/sw/source/core/layout/calcmove.cxx
index 221686d4306f..2473d8cfd8e9 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -290,9 +290,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();
@@ -1297,7 +1305,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* 
/*pRenderContext*/)
         pNotify->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 )
@@ -1715,7 +1723,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,
@@ -2049,10 +2057,29 @@ 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;
+    }
+
     do
     {
+        if (pFrame->IsHiddenNow())
+        {   // shortcut
+            assert(pFrame == this);
+            bRet = true;
+            pFrame = nullptr;
+            break;
+        }
+
         // #i46181#
         SwTwips nSecondCheck = 0;
         SwTwips nOldSpace = nSpace;
@@ -2217,8 +2244,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() ) ) )
             {
@@ -2244,10 +2271,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 648dac932228808ea1a5ce785571dd7caa075933
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Dec 6 14:10:32 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Dec 6 16:51:20 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

diff --git a/sw/source/core/inc/flowfrm.hxx b/sw/source/core/inc/flowfrm.hxx
index 078ef9326837..5859b5688bd9 100644
--- a/sw/source/core/inc/flowfrm.hxx
+++ b/sw/source/core/inc/flowfrm.hxx
@@ -183,6 +183,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 5d7ea3c02a99..d642eb26de97 100644
--- a/sw/source/core/layout/flowfrm.cxx
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -129,7 +129,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;
@@ -148,22 +150,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
@@ -179,6 +201,7 @@ bool SwFlowFrame::IsKeep(SvxFormatKeepItem const& rKeep,
         SvxFormatBreakItem const& rBreak,
         bool const bCheckIfLastRowShouldKeep) const
 {
+    assert(!m_rThis.IsHiddenNow()); // check it before?
     // 1. The keep attribute is ignored inside footnotes
     // 2. For compatibility reasons, the keep attribute is
     //    ignored for frames inside table cells
@@ -269,6 +292,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),
@@ -1074,7 +1117,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() )
     {
@@ -2428,7 +2471,7 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat )
     // keep with next frame and next frame is locked.
     // #i38232# - 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 190e799dbc56..6829f749953e 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -1510,9 +1510,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 4093623976fc..1ff2f7cb7656 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -129,7 +129,7 @@ SwFrameNotify::~SwFrameNotify() COVERITY_NOEXCEPT_FALSE
             {
                 if ( mbInvaKeep )
                 {
-                    SwFrame *pPre = mpFrame->FindPrev();
+                    SwFrame *pPre = pFlow->FindPrevIgnoreHidden();
                     if ( pPre && pPre->IsFlowFrame() )
                     {
                         // 1. pPre wants to keep with me:
commit 484619d972632d2340e4c72cb7179c33107a2d5b
Author:     Andreas Heinisch <andreas.heini...@yahoo.de>
AuthorDate: Mon Nov 25 09:17:45 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Dec 6 16:51:20 2024 +0100

    tdf#163325 - Check Lower() frame during ToC preview
    
    Change-Id: Ife0e974d66d5ddbe3c831c64e4da28442e476da4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177234
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    Tested-by: Jenkins
    (cherry picked from commit 2145204724049cad1585743c0b980ed2c6561212)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177529
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit 2d57e13895703b541b918c0933b7dc5bbe25c300)

diff --git a/sw/qa/uitest/data/tdf163325.odt b/sw/qa/uitest/data/tdf163325.odt
new file mode 100644
index 000000000000..3d2e6e8673cf
Binary files /dev/null and b/sw/qa/uitest/data/tdf163325.odt differ
diff --git a/sw/source/core/layout/sectfrm.cxx 
b/sw/source/core/layout/sectfrm.cxx
index 96fe04aa89b0..ac2120e7837b 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -2694,7 +2694,8 @@ void SwSectionFrame::Modify( const SfxPoolItem* pOld, 
const SfxPoolItem * pNew )
         }
 
         InvalidateFramesInSection(Lower());
-        Lower()->HideAndShowObjects(); // recursive
+        if (Lower())
+            Lower()->HideAndShowObjects(); // recursive
         // Check if any page-breaks have been unhidden, create the new pages.
         // Call IsHiddenNow() because a parent section could still hide.
         if (!IsFollow() && IsInDocBody() && !IsInTab() && !IsHiddenNow())
@@ -2721,8 +2722,9 @@ void SwSectionFrame::Modify( const SfxPoolItem* pOld, 
const SfxPoolItem * pNew )
                 pFirstOnPage = pFirstOnPage->GetUpper();
             }
             assert(pFirstOnPage->IsContentFrame() || 
pFirstOnPage->IsTabFrame());
-            SwColumnFrame * pColumn{Lower()->IsColumnFrame()
-                    ? static_cast<SwColumnFrame*>(Lower()) : nullptr};
+            SwColumnFrame* pColumn{ Lower() && Lower()->IsColumnFrame()
+                                        ? static_cast<SwColumnFrame*>(Lower())
+                                        : nullptr };
             auto IterateLower = [&pColumn](SwFrame *const pLowerFrame) -> 
SwFrame*
             {
                 if (pLowerFrame->GetNext())

Reply via email to