tdf#124491 DOCX: import tracked changes of empty paragraphs

Formatting changes of empty paragraphs weren't imported.

Change-Id: Ife7c83d52549563ab4c3a00a3daff4d8f4fa8386
Reviewed-on: https://gerrit.libreoffice.org/78233
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf124491.docx b/sw/qa/extras/ooxmlexport/data/tdf124491.docx
new file mode 100644
index 0000000..dad4d7c
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf124491.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index fc933a6..54e2002 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -883,6 +883,16 @@
    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:pPrChange/w:pPr/w:numPr/w:numId", "val", "1");
}

DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf124491, "tdf124491.docx")
{
    xmlDocPtr pXmlDoc = parseExport("word/document.xml");
    // import format change of empty lines, FIXME: change w:r with w:pPr in export
    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/*/w:rPr/w:rPrChange");
    // empty line without format change
    assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/*/w:rPrChange", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/*/*/w:rPrChange", 0);
}

DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf105485, "tdf105485.docx")
{
    xmlDocPtr pXmlDoc = parseExport("word/document.xml");
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 2585b12..8eb527e 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -784,12 +784,25 @@

    SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );

    if ( !m_bFormatAll )
    const SwPosition* pStt = rPam.Start(),
                    * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
                                                     : rPam.GetPoint();

    if ( !m_bFormatAll || pEnd->nContent == 0 )
    {
        // don't reject the format of the next paragraph (that is handled by the next redline)
        aPam.GetPoint()->nNode--;
        SwContentNode* pNode = aPam.GetPoint()->nNode.GetNode().GetContentNode();
        aPam.GetPoint()->nContent.Assign( pNode, pNode->Len() );
        if (aPam.GetPoint()->nNode > aPam.GetMark()->nNode)
        {
            aPam.GetPoint()->nNode--;
            SwContentNode* pNode = aPam.GetPoint()->nNode.GetNode().GetContentNode();
            aPam.GetPoint()->nContent.Assign( pNode, pNode->Len() );
        }
        else if (aPam.GetPoint()->nNode < aPam.GetMark()->nNode)
        {
            aPam.GetMark()->nNode--;
            SwContentNode* pNode = aPam.GetMark()->nNode.GetNode().GetContentNode();
            aPam.GetMark()->nContent.Assign( pNode, pNode->Len() );
        }
    }

    if( pColl )
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 871d847..f2cd949 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2290,6 +2290,7 @@
        m_pImpl->StartParaMarkerChange( );
        [[fallthrough]];
    case NS_ooxml::LN_CT_PPr_pPrChange:
    case NS_ooxml::LN_CT_ParaRPr_rPrChange:
    case NS_ooxml::LN_trackchange:
    case NS_ooxml::LN_EG_RPrContent_rPrChange:
    case NS_ooxml::LN_EG_RangeMarkupElements_customXmlDelRangeStart:
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 79f7116..ad8147a 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1526,6 +1526,10 @@
                    else
                        xCur->gotoEnd( false );
                    xCur->goLeft( 1 , true );
                    // Extend the redline ranges for empty paragraphs
                    if ( !m_bParaChanged && m_previousRedline.get() )
                        CreateRedline( xCur, m_previousRedline );
                    m_previousRedline.clear();
                    CheckParaMarkerRedline( xCur );
                }

@@ -2215,6 +2219,7 @@
void DomainMapper_Impl::EndParaMarkerChange( )
{
    m_bIsParaMarkerChange = false;
    m_previousRedline = m_currentRedline;
    m_currentRedline.clear();
}

@@ -5844,7 +5849,7 @@
            GetTopContextOfType( CONTEXT_CHARACTER )->Redlines().push_back( pNew );
        else if( sprmId == NS_ooxml::LN_CT_PPr_pPrChange )
            GetTopContextOfType( CONTEXT_PARAGRAPH )->Redlines().push_back( pNew );
        else
        else if( sprmId != NS_ooxml::LN_CT_ParaRPr_rPrChange )
            m_aRedlines.top().push_back( pNew );
    }
    else
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index ec1a25b..d4e4420 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -503,6 +503,7 @@
    std::stack< std::vector< RedlineParamsPtr > > m_aRedlines;
    // The redline currently read, may be also stored by a context instead of m_aRedlines.
    RedlineParamsPtr                m_currentRedline;
    RedlineParamsPtr                m_previousRedline;
    RedlineParamsPtr                m_pParaMarkerRedline;
    bool                            m_bIsParaMarkerChange;
    // redline data of the terminating run, if it's a moveFrom deletion