sw/qa/extras/layout/data/hideSection.fodt |   39 ++++++++++++++++++++++++++++++
 sw/qa/extras/layout/layout2.cxx           |   24 ++++++++++++++++++
 sw/source/core/layout/sectfrm.cxx         |    9 ------
 sw/source/core/layout/trvlfrm.cxx         |    4 ++-
 4 files changed, 67 insertions(+), 9 deletions(-)

New commits:
commit a3cc65d77ee8874c83f5c9ce52915ad16ee88989
Author:     Mike Kaganski <[email protected]>
AuthorDate: Sat Jun 21 17:25:25 2025 +0500
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Oct 14 20:05:04 2025 +0200

    tdf#166978: replace HUGE_POSITIVE hack with proper upper invalidation
    
    The problem was, that the change of section's height (either to zero
    when hiding, or from zero to some height when showing) could keep its
    upper's size unchanged and valid. Invalidating the upper's size in
    SfxHintId::SwSectionHidden handler was not enough; in the following
    layout calculation, the upper sets its mbFrameAreaSizeValid to true
    before its lowers' calculation. Then, during their calculation:
    
    * If the section was hiding, SwFrame::MakeValidZeroHeight would fail
      in ShrinkFrame, then force its height to 0 in 'if (IsLayoutFrame())'
      block, and not notify upper;
    * If the section was showing, SwSectionFrame::Grow_ could see that
      the upper has space enough for the section (e.g., when there are
      more children after this section), and also not notify upper.
    
    The HUGE_POSITIVE hack allowed to force following re-layout in some
    cases; but the bugdoc failed when the cell was initially made very
    tall, and hat to split; then the section in it was shrinked to 0,and
    that didn't cause the merge with the follow.
    
    This fixes the problem by:
    1. Removing of the HUGE_POSITIVE hack;
    2. Invalidating upper cell frame in SwSectionFrame::Grow_, similar
       to commit ee57229154a91cf632871cfcb1eb9609908f3882 (Fix #88178#:
       Sectionframe in headerframe, don't grow without invalidation,
       2001-06-13);
    3. Invalidating layout frame's upper in SwFrame::MakeValidZeroHeight,
       when ShrinkFrame didn't make it 0-height.
    
    In #3, I decided to not check the upper's kind, for robustness; if
    needed, checks may be added in follow-ups, for specific problems.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186779
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    (cherry picked from commit 4cfd0c99d1bd85a4927cb3b433b903cc26f5ef95)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186788
    Reviewed-by: Michael Stahl <[email protected]>
    (cherry picked from commit f1fa292d4a8f5553990215fb4aef919746c5bec5)
    
    Conflicts:
            sw/source/core/layout/sectfrm.cxx
    
    Change-Id: Iafdd1c41b52d2170d5dd2b3bc2cbc1a5f657c0fb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191740
    Tested-by: allotropia jenkins <[email protected]>
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/qa/extras/layout/data/hideSection.fodt 
b/sw/qa/extras/layout/data/hideSection.fodt
new file mode 100644
index 000000000000..ba953e5103e8
--- /dev/null
+++ b/sw/qa/extras/layout/data/hideSection.fodt
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+  <style:style style:name="Table1" style:family="table">
+   <style:table-properties table:align="margins"/>
+  </style:style>
+  <style:style style:name="Table1.A1" style:family="table-cell">
+   <style:table-cell-properties fo:border="0.05pt solid #000000"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <table:table table:name="Table1" table:style-name="Table1">
+    <table:table-column/>
+    <table:table-column/>
+    <table:table-row>
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:p>A1</text:p>
+     </table:table-cell>
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:section text:name="Section1">
+       <text:p>Section1: hide me</text:p>
+      </text:section>
+      <text:p>B1</text:p>
+     </table:table-cell>
+    </table:table-row>
+    <table:table-row>
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:p>A2: this row suddenly jumps to the next page</text:p>
+     </table:table-cell>
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:p>B2</text:p>
+     </table:table-cell>
+    </table:table-row>
+   </table:table>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index b98638c376a7..406df8998b1e 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -997,6 +997,30 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166691)
     assertXPath(pXmlDoc, "//page", 1);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166978)
+{
+    // Given a document with a table, which cell has a section:
+    createDoc("hideSection.fodt");
+    CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+    // Hide the section
+    uno::Reference<text::XTextSectionsSupplier> 
xTextSectionsSupplier(mxComponent, uno::UNO_QUERY_THROW);
+    auto xSections = xTextSectionsSupplier->getTextSections();
+    CPPUNIT_ASSERT(xSections);
+    uno::Reference<beans::XPropertySet> 
xSection(xSections->getByName("Section1"), uno::UNO_QUERY_THROW);
+    xSection->setPropertyValue("IsVisible", css::uno::Any(false));
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT_EQUAL(1, getPages()); // must not split the second row of 
the table to page 2
+    // Check the layout dump; the whole table must be still on the first page
+    auto pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page", 1);
+    assertXPath(pXmlDoc, "//page[1]/body/tab", 1);
+    assertXPath(pXmlDoc, "//page[1]/body/tab/row", 2);
+    assertXPathContent(pXmlDoc, "//page[1]/body/tab/row[2]/cell[1]/txt",
+                       u"A2: this row suddenly jumps to the next page");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sectfrm.cxx 
b/sw/source/core/layout/sectfrm.cxx
index bbb375678e97..ab474095b0be 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -2293,7 +2293,7 @@ SwTwips SwSectionFrame::Grow_( SwTwips nDist, bool bTst )
                         SetCompletePaint();
                         InvalidatePage();
                     }
-                    if( GetUpper() && GetUpper()->IsHeaderFrame() )
+                    if (GetUpper() && (GetUpper()->IsHeaderFrame() || 
GetUpper()->IsCellFrame()))
                         GetUpper()->InvalidateSize();
                 }
 
@@ -2686,13 +2686,6 @@ void SwSectionFrame::Modify( const SfxPoolItem* pOld, 
const SfxPoolItem * pNew )
     {
         InvalidateAll();
         InvalidateObjs(false);
-        {
-            // Set it to a huge positive value, to make sure a recalculation 
fires
-            constexpr SwTwips HUGE_POSITIVE = 10000 * 1440 / 2.54; // 100m
-            SwFrameAreaDefinition::FrameAreaWriteAccess area(*this);
-            SwRectFnSet(this).SetHeight(area, HUGE_POSITIVE);
-        }
-        GetUpper()->InvalidateSize();
 
         InvalidateFramesInSection(Lower());
         if (Lower())
diff --git a/sw/source/core/layout/trvlfrm.cxx 
b/sw/source/core/layout/trvlfrm.cxx
index 9f6e7a074943..d499efbd0c6b 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -1701,10 +1701,12 @@ void SwFrame::MakeValidZeroHeight()
         aRectFnSet.SetHeight(area, 0);
     }
     ShrinkFrame(aRectFnSet.GetHeight(getFrameArea()));
-    if (IsLayoutFrame()) // ShrinkFrame might do nothing!
+    if (IsLayoutFrame() && aRectFnSet.GetHeight(getFrameArea())) // 
ShrinkFrame might do nothing!
     {
         SwFrameAreaDefinition::FrameAreaWriteAccess area(*this);
         aRectFnSet.SetHeight(area, 0);
+        if (GetUpper())
+            GetUpper()->InvalidateSize();
     }
     setFrameAreaSizeValid(true);
     setFramePrintAreaValid(true);

Reply via email to