sw/qa/extras/layout/data/tdf155177-1-min.odt |binary
 sw/qa/extras/layout/layout2.cxx              |   57 +++++++++++++++++++++++++++
 sw/source/core/text/txtfrm.cxx               |   23 ----------
 sw/source/core/text/widorp.cxx               |   44 ++++++++++++++------
 sw/source/core/text/widorp.hxx               |    6 ++
 5 files changed, 94 insertions(+), 36 deletions(-)

New commits:
commit f49f87f628197bd58e5a5411a77615a677c0ff83
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Aug 25 14:20:34 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Sep 26 13:35:20 2023 +0200

    tdf#155177 sw: fix 2-line bug in WidowsAndOrphans::WouldFit()
    
    The problem is that the check if the line contains a non-fly portion
    was only done in the loop, but the first line is already handled before
    the loop, so its non-fly portions are ignored and never less than 2
    lines are moved, regardless of widow/orphan settings.
    
    (regression from commit 8c32cc17ce914188ea6783b0f79e19c5ddbf0b8d)
    
    Change-Id: Ic017a17233fcd58e22d54386650328f00fb3e9f7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156121
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit fe89122c15744afcaccaa6d6628fa0436adf12e1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156197
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/extras/layout/data/tdf155177-1-min.odt 
b/sw/qa/extras/layout/data/tdf155177-1-min.odt
new file mode 100644
index 000000000000..68363860f05d
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf155177-1-min.odt differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 1e715b17097b..a29664cf8a13 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2468,6 +2468,63 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf109077)
     CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf155177)
+{
+    createSwDoc("tdf155177-1-min.odt");
+
+    uno::Reference<beans::XPropertySet> 
xStyle(getStyles("ParagraphStyles")->getByName("Text Body"),
+                                               uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(210), getProperty<sal_Int32>(xStyle, 
"ParaTopMargin"));
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, "/root/page[2]/body/txt", 6);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[6]/SwParaPortion/SwLineLayout", 2);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[6]/SwParaPortion/SwLineLayout[2]", "portion",
+                    "long as two lines.");
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 3);
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
+                    "This paragraph is even longer so that ");
+        discardDumpedLayout();
+    }
+
+    // this should bring one line back
+    xStyle->setPropertyValue("ParaTopMargin", uno::Any(sal_Int32(200)));
+
+    Scheduler::ProcessEventsToIdle();
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, "/root/page[2]/body/txt", 7);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout", 1);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion",
+                    "This paragraph is even longer so that ");
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 2);
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
+                    "it is now three lines long though ");
+        discardDumpedLayout();
+    }
+
+    // this should bring second line back
+    xStyle->setPropertyValue("ParaTopMargin", uno::Any(sal_Int32(120)));
+
+    Scheduler::ProcessEventsToIdle();
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, "/root/page[2]/body/txt", 7);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout", 2);
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion",
+                    "This paragraph is even longer so that ");
+        assertXPath(pXmlDoc, 
"/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[2]", "portion",
+                    "it is now three lines long though ");
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 1);
+        assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
+                    "containing a single sentence.");
+        discardDumpedLayout();
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testUserFieldTypeLanguage)
 {
     // Set the system locale to German, the document will be English.
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 5906c9c9d1f3..90b0a9e743e3 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -3802,28 +3802,7 @@ sal_uInt16 SwTextFrame::FirstLineHeight() const
     for (SwLineLayout const* pLine = pPara; pLine; pLine = pLine->GetNext())
     {
         nHeight += pLine->Height();
-        bool hasNonFly(false);
-        for (SwLinePortion const* pPortion = pLine->GetFirstPortion();
-                pPortion; pPortion = pPortion->GetNextPortion())
-        {
-            switch (pPortion->GetWhichPor())
-            {
-                case PortionType::Fly:
-                case PortionType::Glue:
-                case PortionType::Margin:
-                    break;
-                default:
-                {
-                    hasNonFly = true;
-                    break;
-                }
-            }
-            if (hasNonFly)
-            {
-                break;
-            }
-        }
-        if (hasNonFly)
+        if (::sw::FindNonFlyPortion(*pLine))
         {
             break;
         }
diff --git a/sw/source/core/text/widorp.cxx b/sw/source/core/text/widorp.cxx
index b4fe1f9d4440..53d44d8f4b9f 100644
--- a/sw/source/core/text/widorp.cxx
+++ b/sw/source/core/text/widorp.cxx
@@ -527,6 +527,30 @@ bool WidowsAndOrphans::FindWidows( SwTextFrame *pFrame, 
SwTextMargin &rLine )
     return true;
 }
 
+namespace sw {
+
+auto FindNonFlyPortion(SwLineLayout const& rLine) -> bool
+{
+    for (SwLinePortion const* pPortion = rLine.GetFirstPortion();
+            pPortion; pPortion = pPortion->GetNextPortion())
+    {
+        switch (pPortion->GetWhichPor())
+        {
+            case PortionType::Fly:
+            case PortionType::Glue:
+            case PortionType::Margin:
+                break;
+            default:
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+};
+
+} // namespace sw
+
 bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, SwTwips &rMaxHeight, 
bool bTst, bool bMoveBwd )
 {
     // Here it does not matter, if pFrame is swapped or not.
@@ -546,6 +570,10 @@ bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, 
SwTwips &rMaxHeight, bool
 
     // tdf#146500 for MoveBwd(), want at least 1 line with non-fly
     bool hasNonFly(!bMoveBwd);
+    if (!hasNonFly)
+    {
+        hasNonFly = ::sw::FindNonFlyPortion(*rLine.GetCurr());
+    }
     while (nMinLines > rLine.GetLineNr() || !hasNonFly)
     {
         if( !rLine.NextLine() )
@@ -556,21 +584,9 @@ bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, 
SwTwips &rMaxHeight, bool
                 break;
         }
         nLineSum += rLine.GetLineHeight();
-        for (SwLinePortion const* pPortion = 
rLine.GetCurr()->GetFirstPortion();
-                !hasNonFly && pPortion; pPortion = pPortion->GetNextPortion())
+        if (!hasNonFly)
         {
-            switch (pPortion->GetWhichPor())
-            {
-                case PortionType::Fly:
-                case PortionType::Glue:
-                case PortionType::Margin:
-                    break;
-                default:
-                {
-                    hasNonFly = true;
-                    break;
-                }
-            }
+            hasNonFly = ::sw::FindNonFlyPortion(*rLine.GetCurr());
         }
     }
 
diff --git a/sw/source/core/text/widorp.hxx b/sw/source/core/text/widorp.hxx
index 193d27f633fe..996a7fc913bc 100644
--- a/sw/source/core/text/widorp.hxx
+++ b/sw/source/core/text/widorp.hxx
@@ -79,4 +79,10 @@ public:
     }
 };
 
+namespace sw {
+
+auto FindNonFlyPortion(SwLineLayout const& rLine) -> bool;
+
+} // namespace sw
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to