tdf#123460 DOCX track changes: moveFrom completely

also with the paragraph mark, not leaving an empty
paragraph at the original place of the moved text.

Note: as desktop version of MSO does, but its
online version leaves empty paragraphs interestingly.

Change-Id: I03dda8997df3efbc82e936bd31a3813323e6b5ab
Reviewed-on: https://gerrit.libreoffice.org/71382
Reviewed-by: László Németh <nemeth@numbertext.org>
Tested-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf123460.docx b/sw/qa/extras/ooxmlexport/data/tdf123460.docx
new file mode 100644
index 0000000..c3b723b
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf123460.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 7d9b392f..52068e3 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -796,13 +796,13 @@ DECLARE_OOXMLIMPORT_TEST(testTdf104797, "tdf104797.docx")
    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(1), 2), "IsStart"));
    CPPUNIT_ASSERT_EQUAL( OUString( "This is a filler sentence. Will this sentence be duplicated ADDED STUFF?" ),
            getParagraph( 2 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( "This is a filler sentence." ), getRun( getParagraph( 2 ), 1 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 2 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( " Will this sentence be duplicated ADDED STUFF?" ), getRun( getParagraph( 2 ), 3 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 4 )->getString());
    CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(2), 5), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(2), 5), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(2), 5), "IsStart"));
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 1 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( "This is a filler sentence." ), getRun( getParagraph( 2 ), 2 )->getString());
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 3 )->getString());
    CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(2), 3), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(2), 3), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(2), 3), "IsStart"));
    CPPUNIT_ASSERT_EQUAL( OUString( " Will this sentence be duplicated ADDED STUFF?" ), getRun( getParagraph( 2 ), 4 )->getString());
}

DECLARE_OOXMLEXPORT_TEST(testTdf113608_runAwayNumbering, "tdf113608_runAwayNumbering.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index c3aacdc..4448275 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -239,6 +239,26 @@ DECLARE_OOXMLEXPORT_TEST(testTextInput, "textinput.odt")
    assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[5]/w:t", "SomeText");
}

DECLARE_OOXMLIMPORT_TEST(testTdf123460, "tdf123460.docx")
{
    // check paragraph mark deletion at terminating moveFrom
    CPPUNIT_ASSERT_EQUAL(true,getParagraph( 2 )->getString().startsWith("Nunc"));
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 1 )->getString());
    CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(2), 1), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(OUString("Delete"),getProperty<OUString>(getRun(getParagraph(2), 1), "RedlineType"));
    CPPUNIT_ASSERT_EQUAL(true, getRun( getParagraph( 2 ), 2 )->getString().endsWith("tellus."));
    CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 2 ), 3 )->getString());
    bool bCaught = false;
    try
    {
        getRun( getParagraph( 2 ), 4 );
    }
    catch (container::NoSuchElementException&)
    {
        bCaught = true;
    }
    CPPUNIT_ASSERT_EQUAL(true, bCaught);
}

CPPUNIT_PLUGIN_IMPLEMENT();

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 961a888..d3daa6f 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1690,6 +1690,11 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, const Proper
                }
            }

            // reset moveFrom data of non-terminating runs of the paragraph
            if ( m_pParaMarkerRedlineMoveFrom.get( ) )
            {
                m_pParaMarkerRedlineMoveFrom.clear();
            }
            CheckRedline( xTextRange );
            m_bParaChanged = true;

@@ -2063,6 +2068,8 @@ void DomainMapper_Impl::CreateRedline(uno::Reference<text::XTextRange> const& xR
                sType = getPropertyName( PROP_INSERT );
                break;
            case XML_moveFrom:
                m_pParaMarkerRedlineMoveFrom = pRedline.get();
                [[fallthrough]];
            case XML_del:
                sType = getPropertyName( PROP_DELETE );
                break;
@@ -2101,6 +2108,16 @@ void DomainMapper_Impl::CheckParaMarkerRedline( uno::Reference< text::XTextRange
            m_currentRedline.clear();
        }
    }
    else if ( m_pParaMarkerRedlineMoveFrom.get( ) )
    {
        // terminating moveFrom redline removes also the paragraph mark
        m_pParaMarkerRedlineMoveFrom->m_nToken = XML_del;
        CreateRedline( xRange, m_pParaMarkerRedlineMoveFrom );
    }
    if ( m_pParaMarkerRedlineMoveFrom.get( ) )
    {
        m_pParaMarkerRedlineMoveFrom.clear();
    }
}

void DomainMapper_Impl::CheckRedline( uno::Reference< text::XTextRange > const& xRange )
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index aabc939..7936315 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -505,6 +505,8 @@ private:
    RedlineParamsPtr                m_currentRedline;
    RedlineParamsPtr                m_pParaMarkerRedline;
    bool                            m_bIsParaMarkerChange;
    // redline data of the terminating run, if it's a moveFrom deletion
    RedlineParamsPtr                m_pParaMarkerRedlineMoveFrom;

    /// If the current paragraph has any runs.
    bool                            m_bParaChanged;
@@ -575,7 +577,7 @@ public:
    }
    void SetDocumentSettingsProperty( const OUString& rPropName, const css::uno::Any& rValue );

    static void CreateRedline(css::uno::Reference<css::text::XTextRange> const& xRange, const RedlineParamsPtr& pRedline);
    void CreateRedline(css::uno::Reference<css::text::XTextRange> const& xRange, const RedlineParamsPtr& pRedline);

    void CheckParaMarkerRedline(css::uno::Reference<css::text::XTextRange> const& xRange);