sw/qa/writerfilter/dmapper/DomainMapper_Impl.cxx             |   23 +++++++++++
 sw/qa/writerfilter/dmapper/data/clearing-break-sect-end.docx |binary
 sw/source/writerfilter/dmapper/DomainMapper.cxx              |    4 -
 sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx         |    5 ++
 sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx         |    3 +
 5 files changed, 33 insertions(+), 2 deletions(-)

New commits:
commit e00479404af5058b982c447e485af995d552e372
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri May 31 09:00:18 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri May 31 12:58:00 2024 +0200

    tdf#161318 sw clearing break: fix this at section end
    
    Regression from commit 19bca24486315cc35f873486e6a2dd18394d0614
    (tdf#126287: docx import: use defered linebreak, 2022-02-07), the bugdoc
    has a single paragraph in the first section, containing a clearing
    break, which is lost. This leads to overlapping text as the text is
    shifted up.
    
    Seems the intention was to avoid a line break at the very end of the
    document, as that can lead to an empty page with "next page" section
    breaks, with non-clearing line breaks.
    
    Fix the problem by only doing this for non-clearing line breaks: that
    keeps the old use-case working, but the new, clearing line break then
    shifts down the text, so no text overlap happens.
    
    Switching from appendTextPortion() to HandleLineBreak() helps because
    HandleLineBreak() does exactly appendTextPortion("
") in the
    non-clearing case, but knows about the stream stack's line break clear
    status.
    
    Change-Id: I38868eeeac55e20e86b668e9baf7e0d6a4976608
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168278
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/writerfilter/dmapper/DomainMapper_Impl.cxx 
b/sw/qa/writerfilter/dmapper/DomainMapper_Impl.cxx
index 825e615fb574..963db22c4c28 100644
--- a/sw/qa/writerfilter/dmapper/DomainMapper_Impl.cxx
+++ b/sw/qa/writerfilter/dmapper/DomainMapper_Impl.cxx
@@ -411,6 +411,29 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlinedShapeThenSdt)
     CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr,
                          
xPortion->getPropertyValue("TextPortionType").get<OUString>());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testClearingBreakSectEnd)
+{
+    // Given a file with a single-paragraph section, ends with a clearing 
break:
+    // When importing that document:
+    loadFromFile(u"clearing-break-sect-end.docx");
+
+    // Then make sure the clearing break is not lost before a cont sect break:
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> 
xParaEnumAccess(xTextDocument->getText(),
+                                                                  
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = 
xParaEnumAccess->createEnumeration();
+    uno::Reference<container::XEnumerationAccess> 
xPortionEnumAccess(xParaEnum->nextElement(),
+                                                                     
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xPortionEnum = 
xPortionEnumAccess->createEnumeration();
+    uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), 
uno::UNO_QUERY);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: LineBreak
+    // - Actual  : Text
+    // i.e. the clearing break at sect end was lost, leading to text overlap.
+    CPPUNIT_ASSERT_EQUAL(u"LineBreak"_ustr,
+                         
xPortion->getPropertyValue("TextPortionType").get<OUString>());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/writerfilter/dmapper/data/clearing-break-sect-end.docx 
b/sw/qa/writerfilter/dmapper/data/clearing-break-sect-end.docx
new file mode 100644
index 000000000000..5052b2dd1649
Binary files /dev/null and 
b/sw/qa/writerfilter/dmapper/data/clearing-break-sect-end.docx differ
diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper.cxx
index 9144acaf79f7..72f88fc2a1a3 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -4347,13 +4347,13 @@ void DomainMapper::lcl_utext(const sal_Unicode *const 
data_, size_t len)
     else if (len == 1 && sText[0] == ' ')
     {
         // Clear "last" one linebreak at end of section
-        if (m_pImpl->GetIsLastParagraphInSection() && 
m_pImpl->isBreakDeferred(LINE_BREAK))
+        if (m_pImpl->GetIsLastParagraphInSection() && 
m_pImpl->isBreakDeferred(LINE_BREAK) && !m_pImpl->HasLineBreakClear())
             m_pImpl->clearDeferredBreak(LINE_BREAK);
         // And emit all other linebreaks
         while (m_pImpl->isBreakDeferred(LINE_BREAK))
         {
             m_pImpl->clearDeferredBreak(LINE_BREAK);
-            m_pImpl->appendTextPortion(u"
"_ustr, m_pImpl->GetTopContext());
+            m_pImpl->HandleLineBreak(m_pImpl->GetTopContext());
         }
     }
     else if (len == 1 && sText[0] == ' ' )
diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
index 7ce54f5ace36..32d26b03d5bb 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
@@ -5176,6 +5176,11 @@ void DomainMapper_Impl::HandleLineBreakClear(sal_Int32 
nClear)
     }
 }
 
+bool DomainMapper_Impl::HasLineBreakClear() const
+{
+    return m_StreamStateStack.top().oLineBreakClear.has_value();
+}
+
 void DomainMapper_Impl::HandleLineBreak(const PropertyMapPtr& pPropertyMap)
 {
     if (!m_StreamStateStack.top().oLineBreakClear.has_value())
diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx 
b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx
index d54b42e719dd..7962facc5252 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx
@@ -1234,6 +1234,9 @@ public:
     /// Handles <w:br w:clear="...">.
     void HandleLineBreakClear(sal_Int32 nClear);
 
+    /// Checks if we have a pending <w:br w:clear="...">.
+    bool HasLineBreakClear() const;
+
     /// Handles <w:br>.
     void HandleLineBreak(const PropertyMapPtr& pPropertyMap);
 

Reply via email to