tdf#153613 tdf#146984 writerfilter: split para after anchors

Even though the w:br occurs in the paragraph before the anchors,
the anchors stay on the first page, and don't move to the second page
(unless it is the last paragraph in the section/document,
which is not yet handled.)

make CppunitTest_sw_ooxmlexport18 \
    CPPUNIT_TEST_NAME=testTdf153613_textboxAfterPgBreak3

Change-Id: Icfc7e2a5d7657f1eb8f94263a4bfc8dcca7e52de
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148897
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf153613_textboxAfterPgBreak3.docx b/sw/qa/extras/ooxmlexport/data/tdf153613_textboxAfterPgBreak3.docx
new file mode 100644
index 0000000..a282dea
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf153613_textboxAfterPgBreak3.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
index 460f409..c30e555 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
@@ -217,6 +217,16 @@ DECLARE_OOXMLEXPORT_TEST(testTdf153613_textboxAfterPgBreak2, "tdf153613_textboxA
    assertXPathContent(pLayout, "//page[2]/body/txt", "There should be no prior carriage return.");
}

DECLARE_OOXMLEXPORT_TEST(testTdf153613_textboxAfterPgBreak3, "tdf153613_textboxAfterPgBreak3.docx")
{
    // All anchored TO-character shapes stay on the first page, before the page break.
    CPPUNIT_ASSERT_EQUAL(2, getPages());
    CPPUNIT_ASSERT_EQUAL(3, getParagraphs());

    const auto& pLayout = parseLayoutDump();
    assertXPath(pLayout, "//page[2]//anchored", 0);
}

DECLARE_OOXMLEXPORT_TEST(testTdf153613_sdtAfterPgBreak, "tdf153613_sdtAfterPgBreak.docx")
{
    CPPUNIT_ASSERT_EQUAL(2, getPages());
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index c526968..800ae25 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3635,7 +3635,7 @@ void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape)
    {
        // If there is a deferred page break, handle it now, so that the
        // started shape will be on the correct page.
        if (m_pImpl->isBreakDeferred(PAGE_BREAK))
        if (m_pImpl->isBreakDeferred(PAGE_BREAK) && !m_pImpl->IsBreakDeferredByAnchor())
        {
            // RTF doesn't properly report IsFirstRun, so in order to prevent regressions
            // always split the paragraph for RTF since that is the way it has been done lately.
@@ -3645,6 +3645,9 @@ void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape)
                finishParagraph();
                lcl_startParagraphGroup();
            }
            else
                m_pImpl->SetIsBreakDeferredByAnchor();

        }
        m_pImpl->PushShapeContext( xShape );
        lcl_startParagraphGroup();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 62dda7d..f33d3c3 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1477,6 +1477,7 @@ void DomainMapper_Impl::clearDeferredBreak(BreakType deferredBreakType)
        break;
    case PAGE_BREAK:
        m_bIsPageBreakDeferred = false;
        m_bIsBreakDeferredByAnchor = false;
        break;
    default:
        break;
@@ -1488,6 +1489,17 @@ void DomainMapper_Impl::clearDeferredBreaks()
    m_nLineBreaksDeferred = 0;
    m_bIsColumnBreakDeferred = false;
    m_bIsPageBreakDeferred = false;
    m_bIsBreakDeferredByAnchor = false;
}

bool DomainMapper_Impl::IsBreakDeferredByAnchor()
{
    return m_bIsBreakDeferredByAnchor;
}

void DomainMapper_Impl::SetIsBreakDeferredByAnchor()
{
    m_bIsBreakDeferredByAnchor = true;
}

void DomainMapper_Impl::setSdtEndDeferred(bool bSdtEndDeferred)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 234ae94..050a510 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -487,6 +487,7 @@ private:
    bool                                                                            m_bIsColumnBreakDeferred;
    bool                                                                            m_bIsPageBreakDeferred;
    sal_Int32                                                                       m_nLineBreaksDeferred;
    bool                                                                            m_bIsBreakDeferredByAnchor;
    /// If we want to set "sdt end" on the next character context.
    bool                                                                            m_bSdtEndDeferred;
    /// If we want to set "paragraph sdt end" on the next paragraph context.
@@ -755,6 +756,8 @@ public:
    bool isBreakDeferred( BreakType deferredBreakType );
    void clearDeferredBreaks();
    void clearDeferredBreak(BreakType deferredBreakType);
    bool IsBreakDeferredByAnchor();
    void SetIsBreakDeferredByAnchor();

    void setSdtEndDeferred(bool bSdtEndDeferred);
    bool isSdtEndDeferred() const;