sw/qa/extras/layout/data/tdf160958_orphans_move_section.fodt |   52 +++
 sw/qa/extras/layout/data/tdf160958_page_break.fodt           |   39 ++
 sw/qa/extras/layout/layout3.cxx                              |  162 +++++++++++
 sw/source/core/layout/sectfrm.cxx                            |   52 +++
 4 files changed, 305 insertions(+)

New commits:
commit 932a01d9752d84c1919a4e5ade7b9c194c15ceaf
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu May 30 02:23:02 2024 +0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri May 31 16:56:16 2024 +0200

    tdf#160958: merge hidden section's follows; move first-on-page section back
    
    Change-Id: I6bd6707089dcea58d5df4bef63aa769769d97ea9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168235
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168204
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/qa/extras/layout/data/tdf160958_orphans_move_section.fodt 
b/sw/qa/extras/layout/data/tdf160958_orphans_move_section.fodt
new file mode 100644
index 000000000000..1306cfa6226d
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160958_orphans_move_section.fodt
@@ -0,0 +1,52 @@
+<?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:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" 
svg:font-family="&apos;Liberation Serif&apos;" 
style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2"/>
+   <style:text-properties style:font-name="Liberation Serif" 
fo:font-size="12pt"/>
+  </style:default-style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21cm" fo:page-height="297mm" 
style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm"/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum 
consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis 
commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec 
blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur 
aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non 
pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper 
vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est 
orci.</text:p>
+   <text:p>Integer sodales tincidunt tristique. Sed a metus posuere, 
adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique 
lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget 
dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis 
mollis. Vivamus nec tellus faucibus, tempor magna nec, facilisis felis. Donec 
commodo enim a vehicula pellentesque. Nullam vehicula vestibulum est vel 
ultricies.</text:p>
+   <text:p>Aliquam velit massa, laoreet vel leo nec, volutpat facilisis eros. 
Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus et 
magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus vel 
leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus orci 
luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, fringilla 
dictum augue consectetur eget. Curabitur at ante sit amet tortor pharetra 
molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, dolor 
sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est 
elementum, euismod nulla in, mollis nunc.</text:p>
+   <text:p>He heard quiet steps behind him. That didn&apos;t bode well. Who 
could be following him this late at night and in this deadbeat part of town? 
And at this particular moment, just after he pulled off the big time and was 
making off with the greenbacks. Was there another crook who&apos;d had the same 
idea, and was now watching him and waiting for a chance to grab the fruit of 
his labor? Or did the steps behind him mean that one of many law officers in 
town was on to him and just waiting to pounce and snap those cuffs on his 
wrists? He nervously looked all around. Suddenly he saw the alley. Like 
lightning he darted off to the left and disappeared between the two warehouses 
almost falling over the trash can lying in the middle of the sidewalk. He tried 
to nervously tap his way along in the inky darkness and suddenly stiffened: it 
was a dead-end, he would have to go back the way he had come. The steps got 
louder and louder, he saw the black outline of a figure coming around the
  corner. Is this the end of the line? he thought pressing himself back against 
the wall trying to make himself invisible in the dark, was all that planning 
and energy wasted? He was dripping with sweat now, cold and wet, he could smell 
the fear coming off his clothes. Suddenly next to him, with a barely noticeable 
squeak, a door swung quietly to and fro in the night&apos;s breeze. Could this 
be the haven he&apos;d prayed for? Slowly he slid toward the door, pressing 
himself more and more into the wall, into the dark, away from his enemy. Would 
this door save his hide?</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:p>baz</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:p>baz</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:p>baz</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:p>baz</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:p>baz</text:p>
+   <text:p>foo</text:p>
+   <text:p>bar</text:p>
+   <text:section text:name="Section1">
+    <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque 
venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus 
egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In 
consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non 
pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper 
vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est 
orci.</text:p>
+    <text:p>Integer sodales tincidunt tristique. Sed a metus posuere, 
adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique 
lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget 
dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis 
mollis. Vivamus nec tellus faucibus, tempor magna nec, facilisis felis. Donec 
commodo enim a vehicula pellentesque. Nullam vehicula vestibulum est vel 
ultricies.</text:p>
+    <text:p>Aliquam velit massa, laoreet vel leo nec, volutpat facilisis eros. 
Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus et 
magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus vel 
leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus orci 
luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, fringilla 
dictum augue consectetur eget. Curabitur at ante sit amet tortor pharetra 
molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, dolor 
sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est 
elementum, euismod nulla in, mollis nunc.</text:p>
+   </text:section>
+   <text:p>baz</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/data/tdf160958_page_break.fodt 
b/sw/qa/extras/layout/data/tdf160958_page_break.fodt
new file mode 100644
index 000000000000..1d4d8863b073
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160958_page_break.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:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" 
svg:font-family="&apos;Liberation Serif&apos;" 
style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:text-properties style:use-window-font-color="true" 
style:font-name="Liberation Serif" fo:font-size="12pt"/>
+  </style:default-style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:master-page-name="">
+   <style:paragraph-properties style:page-number="auto" 
fo:break-before="page"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21cm" fo:page-height="297mm" 
style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" 
fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum 
consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis 
commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec 
blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur 
aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non 
pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper 
vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est 
orci.</text:p>
+   <text:section text:name="Section1">
+    <text:p text:style-name="P1"/>
+    <text:p/>
+    <text:p/>
+    <text:p>Integer sodales tincidunt tristique. Sed a metus posuere, 
adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique 
lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget 
dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis 
mollis. <text:soft-page-break/>Vivamus nec tellus faucibus, tempor magna nec, 
facilisis felis. Donec commodo enim a vehicula pellentesque. Nullam vehicula 
vestibulum est vel ultricies.</text:p>
+    <text:p/>
+    <text:p/>
+    <text:p/>
+   </text:section>
+   <text:p>Aliquam velit massa, laoreet vel leo nec, volutpat facilisis eros. 
Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus et 
magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus vel 
leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus orci 
luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, fringilla 
dictum augue consectetur eget. Curabitur at ante sit amet tortor pharetra 
molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, dolor 
sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est 
elementum, euismod nulla in, mollis nunc.</text:p>
+   <text:p/>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index d553162f1636..8f555e0bf6ba 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -11,6 +11,7 @@
 #include <comphelper/propertysequence.hxx>
 #include <com/sun/star/linguistic2/XHyphenator.hpp>
 #include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/XTextSectionsSupplier.hpp>
 #include <vcl/event.hxx>
 #include <vcl/scheduler.hxx>
 #include <editeng/fontitem.hxx>
@@ -2374,6 +2375,167 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf160526)
     assertXPath(pExportDump, 
"//page[2]/body/txt/anchored/SwAnchoredDrawObject"_ostr);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf160958_page_break)
+{
+    // Given a document with a section with the first paragraph having a page 
break
+    createSwDoc("tdf160958_page_break.fodt");
+    auto pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 2);
+    // A single paragraph on the first page, with 6 lines
+    assertXPath(pExportDump, "//page[1]/body/txt"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt/SwParaPortion/SwLineLayout"_ostr, 6);
+    // A section with 7 paragraphs, and two more paragraphs after the section
+    assertXPath(pExportDump, "//page[2]/body/section"_ostr, 1);
+    assertXPath(pExportDump, "//page[2]/body/section/txt"_ostr, 7);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[1]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[2]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[3]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[4]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[5]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[6]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[7]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, "//page[2]/body/txt"_ostr, 2);
+    assertXPath(pExportDump, 
"//page[2]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, "//page[2]/body/txt[2]/SwParaPortion"_ostr, 0);
+
+    // Hide the section
+    auto xTextSectionsSupplier = 
mxComponent.queryThrow<css::text::XTextSectionsSupplier>();
+    auto xSections = xTextSectionsSupplier->getTextSections();
+    CPPUNIT_ASSERT(xSections);
+    auto xSection = 
xSections->getByName(u"Section1"_ustr).queryThrow<css::beans::XPropertySet>();
+    xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(false));
+
+    discardDumpedLayout();
+    calcLayout();
+    pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 1);
+    // Three paragraphs and a hidden section on the first page
+    assertXPath(pExportDump, "//page/body/txt"_ostr, 3);
+    assertXPath(pExportDump, "//page/body/section"_ostr, 1);
+
+    assertXPath(pExportDump, "//page/body/section/infos/bounds"_ostr, 
"height"_ostr, "0");
+    assertXPath(pExportDump, 
"//page/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, "//page/body/section/txt"_ostr, 7);
+
+    assertXPath(pExportDump, 
"//page/body/txt[2]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, "//page/body/txt[3]/SwParaPortion"_ostr, 0);
+
+    // Show the section again
+    xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(true));
+
+    // Check that the layout has been restored
+    discardDumpedLayout();
+    calcLayout();
+    pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 2);
+    assertXPath(pExportDump, "//page[1]/body/txt"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, "//page[2]/body/section"_ostr, 1);
+    assertXPath(pExportDump, "//page[2]/body/section/txt"_ostr, 7);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[1]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[2]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[3]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[4]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[5]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[6]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[7]/SwParaPortion"_ostr, 0);
+    assertXPath(pExportDump, "//page[2]/body/txt"_ostr, 2);
+    assertXPath(pExportDump, 
"//page[2]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, "//page[2]/body/txt[2]/SwParaPortion"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf160958_orphans)
+{
+    // Given a document with a section which moves to the next page as a 
whole, because of orphans
+    createSwDoc("tdf160958_orphans_move_section.fodt");
+    auto pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 2);
+    // 21 paragraphs on the first page
+    assertXPath(pExportDump, "//page[1]/body/txt"_ostr, 21);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[2]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[3]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[4]/SwParaPortion/SwLineLayout"_ostr, 16);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[5]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[6]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[7]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[8]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[9]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[10]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[11]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[12]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[13]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[14]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[15]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[16]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[17]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[18]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[19]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[20]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[21]/SwParaPortion/SwLineLayout"_ostr, 1);
+    // A section and one more paragraph after the section
+    assertXPath(pExportDump, "//page[2]/body/section"_ostr, 1);
+    assertXPath(pExportDump, "//page[2]/body/section/txt"_ostr, 3);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[1]/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[2]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[3]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, "//page[2]/body/txt"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[2]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 1);
+
+    // Hide the section
+    auto xTextSectionsSupplier = 
mxComponent.queryThrow<css::text::XTextSectionsSupplier>();
+    auto xSections = xTextSectionsSupplier->getTextSections();
+    CPPUNIT_ASSERT(xSections);
+    auto xSection = 
xSections->getByName(u"Section1"_ustr).queryThrow<css::beans::XPropertySet>();
+    xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(false));
+
+    discardDumpedLayout();
+    calcLayout();
+    pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 1);
+    assertXPath(pExportDump, "//page/body/txt"_ostr, 22);
+    assertXPath(pExportDump, "//page/body/section"_ostr, 1);
+    assertXPath(pExportDump, "//page/body/section/infos/bounds"_ostr, 
"height"_ostr, "0");
+
+    // Show the section again
+    xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(true));
+
+    // Check that the layout has been restored
+    discardDumpedLayout();
+    calcLayout();
+    pExportDump = parseLayoutDump();
+    assertXPath(pExportDump, "//page"_ostr, 2);
+    assertXPath(pExportDump, "//page[1]/body/txt"_ostr, 21);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[2]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[3]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[4]/SwParaPortion/SwLineLayout"_ostr, 16);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[5]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[6]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[7]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[8]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[9]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[10]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[11]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[12]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[13]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[14]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[15]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[16]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[17]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[18]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[19]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[20]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[1]/body/txt[21]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(pExportDump, "//page[2]/body/section"_ostr, 1);
+    assertXPath(pExportDump, "//page[2]/body/section/txt"_ostr, 3);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[1]/SwParaPortion/SwLineLayout"_ostr, 6);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[2]/SwParaPortion/SwLineLayout"_ostr, 5);
+    assertXPath(pExportDump, 
"//page[2]/body/section/txt[3]/SwParaPortion/SwLineLayout"_ostr, 7);
+    assertXPath(pExportDump, "//page[2]/body/txt"_ostr, 1);
+    assertXPath(pExportDump, 
"//page[2]/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 1);
+}
+
 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 78278da9cb38..e051d056b081 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -833,6 +833,42 @@ void SwSectionFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
         setFramePrintAreaValid(true);
         return;
     }
+
+    if (!GetPrev() && !IsFollow() && IsInDocBody() && IsHiddenNow())
+    {
+        // This may be the first frame on a page, and it may had moved to that 
page because its
+        // content required that (a page break in the first paragraph, or a 
tall first line, or
+        // "do not break paragraph" setting, or the like). Try to move back, 
to allow following
+        // frames to move back, if possible. Sections cannot move back; 
workaround by a call to
+        // GetPrevSctLeaf(), which may return a candidate upper frame on a 
previous page, or it
+        // may create a new master for this at the end of the previous page. 
Cut and paste this
+        // appropriately; then drop the temporary, if needed.
+        if (SwLayoutFrame* moveBackPos = GetPrevSctLeaf())
+        {
+            SwLayoutFrame* newUpper = moveBackPos;
+            SwFrame* newSibling = nullptr;
+            const bool temporaryMasterCreated = IsFollow();
+            if (temporaryMasterCreated)
+            {
+                assert(moveBackPos == &GetPrecede()->GetFrame());
+                newUpper = moveBackPos->GetUpper();
+                newSibling = moveBackPos->GetNext(); // actually, will be also 
nullptr
+            }
+            if (newUpper != GetUpper())
+            {
+                // Can't use MoveSubTree, because the move needs to fire 
events to re-layout
+                Cut();
+                Paste(newUpper, newSibling);
+            }
+            if (temporaryMasterCreated)
+            {
+                moveBackPos->Cut();
+                DestroyFrame(moveBackPos);
+            }
+            assert(!IsFollow());
+        }
+    }
+
     LockJoin(); // I don't let myself to be destroyed on the way
 
     while( GetNext() && GetNext() == GetFollow() )
@@ -843,6 +879,17 @@ void SwSectionFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
             break;
     }
 
+    if (GetFollow() && IsHiddenNow())
+    {
+        // Merge all the follows of this hidden section
+        while (auto* follow = GetFollow())
+        {
+            MergeNext(follow);
+            if (GetFollow() == follow) // failed to merge
+                break; // avoid endless loop
+        }
+    }
+
     // OD 2004-03-15 #116561# - In online layout join the follows, if section
     // can grow.
     const SwViewShell *pSh = getRootFrame()->GetCurrShell();
@@ -2677,6 +2724,11 @@ void SwSectionFrame::SwClientNotify(const SwModify& 
rMod, const SfxHint& rHint)
     {
         InvalidateAll();
         InvalidateObjs(false);
+        {
+            // Set it to a huge positive value, to make sure a recalculation 
fires
+            SwFrameAreaDefinition::FrameAreaWriteAccess area(*this);
+            SwRectFnSet(this).SetHeight(area, 
std::numeric_limits<tools::Long>::max());
+        }
 
         for (SwFrame* pLowerFrame = Lower(); pLowerFrame; pLowerFrame = 
pLowerFrame->GetNext())
         {

Reply via email to