[Libreoffice-commits] core.git: 5 commits - sw/CppunitTest_sw_ooxmlimport.mk sw/qa sw/source writerfilter/source

Luboš Luňák l.lunak at collabora.com
Fri Oct 3 04:27:47 PDT 2014


 sw/CppunitTest_sw_ooxmlimport.mk                  |    1 
 sw/qa/extras/ooxmlimport/data/bnc821804.docx      |binary
 sw/qa/extras/ooxmlimport/ooxmlimport.cxx          |  111 ++++++++++++++++++++++
 sw/source/core/unocore/unoredline.cxx             |    1 
 sw/source/uibase/misc/redlndlg.cxx                |    2 
 sw/source/uibase/shells/textfld.cxx               |    1 
 writerfilter/source/dmapper/DomainMapper.cxx      |   37 +++----
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |  108 +++++++++++----------
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |   25 +---
 writerfilter/source/dmapper/PropertyMap.hxx       |   19 +++
 writerfilter/source/ooxml/model.xml               |   10 -
 11 files changed, 223 insertions(+), 92 deletions(-)

New commits:
commit fd26de3b4a4e8be165f7627cb22029841ba4ab31
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Fri Oct 3 13:22:18 2014 +0200

    docx redline import test (bnc#821804)
    
    Change-Id: I09749037deb44c0cd74b28af226dd4b3e34ee0d1

diff --git a/sw/CppunitTest_sw_ooxmlimport.mk b/sw/CppunitTest_sw_ooxmlimport.mk
index 682b31c..5d21e9e 100644
--- a/sw/CppunitTest_sw_ooxmlimport.mk
+++ b/sw/CppunitTest_sw_ooxmlimport.mk
@@ -25,6 +25,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_ooxmlimport, \
     unotest \
     utl \
     sw \
+    tl \
     vcl \
 	$(gb_UWINAPI) \
 ))
diff --git a/sw/qa/extras/ooxmlimport/data/bnc821804.docx b/sw/qa/extras/ooxmlimport/data/bnc821804.docx
new file mode 100644
index 0000000..9ec2e07
Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/bnc821804.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index fe0241e..adc0df2 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -56,11 +56,13 @@
 #include <com/sun/star/style/CaseMap.hpp>
 #include <com/sun/star/style/PageStyleLayout.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/util/DateTime.hpp>
 #include <vcl/svapp.hxx>
 #include <unotools/fltrcfg.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <com/sun/star/text/GraphicCrop.hpp>
 #include <swtypes.hxx>
+#include <tools/datetimeutils.hxx>
 
 #include <bordertest.hxx>
 
@@ -2375,6 +2377,115 @@ DECLARE_OOXMLIMPORT_TEST(testBnc891663, "bnc891663.docx")
     CPPUNIT_ASSERT( textNextRowTop >= imageTop + imageHeight );
 }
 
+static OString dateTimeToString( const util::DateTime& dt )
+{
+    return DateTimeToOString( DateTime( Date( dt.Day, dt.Month, dt.Year ), tools::Time( dt.Hours, dt.Minutes, dt.Seconds )));
+}
+
+DECLARE_OOXMLIMPORT_TEST(testBnc821804, "bnc821804.docx")
+{
+    CPPUNIT_ASSERT_EQUAL( OUString( "TITLE" ), getRun( getParagraph( 1 ), 1 )->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(1), 1), "RedlineType"));
+    // Redline information (SwXRedlinePortion) are separate "runs" apparently.
+    CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(1), 2), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(1), 2), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(1), 2), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown1"),getProperty<OUString>(getRun(getParagraph(1), 2), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OString("2006-08-29T09:46:00Z"),dateTimeToString(getProperty<util::DateTime>(getRun(getParagraph(1), 2), "RedlineDateTime")));
+    // So only the 3rd run is actual text (and the two runs have been merged into one, not sure why, but that shouldn't be a problem).
+    CPPUNIT_ASSERT_EQUAL(OUString(" (1st run of an insert) (2nd run of an insert)"), getRun(getParagraph(1),3)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(1), 3), "RedlineType"));
+    // And the end SwXRedlinePortion of the redline.
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(1), 4), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown1"),getProperty<OUString>(getRun(getParagraph(1), 4), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OString("2006-08-29T09:46:00Z"),dateTimeToString(getProperty<util::DateTime>(getRun(getParagraph(1), 4), "RedlineDateTime")));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(1), 4), "IsStart"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Normal text"), getRun(getParagraph(2),1)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(2), 1), "RedlineType"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Delete"),getProperty<OUString>(getRun(getParagraph(3), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown2"),getProperty<OUString>(getRun(getParagraph(3), 1), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OString("2006-08-29T09:47:00Z"),dateTimeToString(getProperty<util::DateTime>(getRun(getParagraph(3), 1), "RedlineDateTime")));
+    CPPUNIT_ASSERT_EQUAL(OUString("Deleted"), getRun(getParagraph(3),2)->getString());
+
+    // This is both inserted and formatted, so there are two SwXRedlinePortion "runs". Given that the redlines overlap and Writer core
+    // doesn't officially expect that (even though it copes, the redline info will be split depending on how Writer deal with it).
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(4), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(4), 1), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(4), 2), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(4), 2), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Inserted and formatted"), getRun(getParagraph(4),3)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(4), 4), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(4), 4), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString(" and this is only formatted"), getRun(getParagraph(4),5)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(4), 6), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(4), 6), "IsStart"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Normal text"), getRun(getParagraph(5),1)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(5), 1), "RedlineType"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Format"),getProperty<OUString>(getRun(getParagraph(6), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(6), 1), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown5"),getProperty<OUString>(getRun(getParagraph(6), 1), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OString("2006-08-29T10:02:00Z"),dateTimeToString(getProperty<util::DateTime>(getRun(getParagraph(6), 1), "RedlineDateTime")));
+    CPPUNIT_ASSERT_EQUAL(OUString("Formatted run"), getRun(getParagraph(6),2)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Format"),getProperty<OUString>(getRun(getParagraph(6), 3), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(6), 3), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString(" and normal text here "), getRun(getParagraph(6),4)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(6), 4), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(6), 5), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(6), 5), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown6"),getProperty<OUString>(getRun(getParagraph(6), 5), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OString("2006-08-29T09:48:00Z"),dateTimeToString(getProperty<util::DateTime>(getRun(getParagraph(6), 5), "RedlineDateTime")));
+    CPPUNIT_ASSERT_EQUAL(OUString("and inserted again"), getRun(getParagraph(6),6)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(6), 7), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(6), 7), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString(" and normal text again "), getRun(getParagraph(6),8)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(6), 8), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Format"),getProperty<OUString>(getRun(getParagraph(6), 9), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(6), 9), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown7"),getProperty<OUString>(getRun(getParagraph(6), 9), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OUString("and formatted"), getRun(getParagraph(6),10)->getString());
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(6), 11), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString(" and normal."), getRun(getParagraph(6),12)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(6), 12), "RedlineType"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(7), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(7), 1), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown8"),getProperty<OUString>(getRun(getParagraph(7), 1), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OUString("One insert."), getRun(getParagraph(7),2)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(7), 3), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(7), 3), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(7), 4), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(7), 4), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("unknown9"),getProperty<OUString>(getRun(getParagraph(7), 4), "RedlineAuthor"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Second insert."), getRun(getParagraph(7),5)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Insert"),getProperty<OUString>(getRun(getParagraph(7), 6), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(7), 6), "IsStart"));
+
+    // Overlapping again.
+    CPPUNIT_ASSERT_EQUAL(OUString("Delete"),getProperty<OUString>(getRun(getParagraph(8), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(8), 1), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(8), 2), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(8), 2), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Deleted and formatted"), getRun(getParagraph(8),3)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Delete"),getProperty<OUString>(getRun(getParagraph(8), 4), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(8), 4), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString(" and this is only formatted"), getRun(getParagraph(8),5)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(8), 6), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(8), 6), "IsStart"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Normal text"), getRun(getParagraph(9),1)->getString());
+    CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(9), 1), "RedlineType"));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(10), 1), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(true,getProperty<bool>(getRun(getParagraph(10), 1), "IsStart"));
+    CPPUNIT_ASSERT_EQUAL(OUString("This is only formatted."), getRun(getParagraph(10),2)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("ParagraphFormat"),getProperty<OUString>(getRun(getParagraph(10), 3), "RedlineType"));
+    CPPUNIT_ASSERT_EQUAL(false,getProperty<bool>(getRun(getParagraph(10), 3), "IsStart"));
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit c469d1463073ba312d55ae3076b86381bfe89ed8
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Fri Oct 3 13:22:18 2014 +0200

    report ParagraphFormat redline type in UNO too
    
    Change-Id: I0cf7586a154ca73ce64a2328ff8df1858e2290ac

diff --git a/sw/source/core/unocore/unoredline.cxx b/sw/source/core/unocore/unoredline.cxx
index 3575381..71dfe30 100644
--- a/sw/source/core/unocore/unoredline.cxx
+++ b/sw/source/core/unocore/unoredline.cxx
@@ -211,6 +211,7 @@ static OUString lcl_RedlineTypeToOUString(RedlineType_t eType)
         case nsRedlineType_t::REDLINE_INSERT: sRet = "Insert"; break;
         case nsRedlineType_t::REDLINE_DELETE: sRet = "Delete"; break;
         case nsRedlineType_t::REDLINE_FORMAT: sRet = "Format"; break;
+        case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT: sRet = "ParagraphFormat"; break;
         case nsRedlineType_t::REDLINE_TABLE:  sRet = "TextTable"; break;
         case nsRedlineType_t::REDLINE_FMTCOLL:sRet = "Style"; break;
     }
commit 9dbf817fe5c5253fba0831aefa17575ae0ba3af1
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Oct 1 19:12:47 2014 +0200

    handle scope of w:pPrChange and w:rPrChange properly (bnc#821804)
    
    Redlines changing formatting of runs and paragraphs are valid for the entire
    run/paragraph, not just their existence in the XML. So store them
    in the matching contexts, which will care of it, instead of the endtrackchange
    stuff.
    
    Change-Id: Ie583e4be14e8df95829852bfbbbe25aa0684f02e

diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 4ef5e71..ea439c3 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2222,9 +2222,10 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext )
     }
     break;
     case NS_ooxml::LN_endtrackchange:
-        m_pImpl->RemoveCurrentRedline( );
+        m_pImpl->RemoveTopRedline();
     break;
     case NS_ooxml::LN_CT_RPrChange_rPr:
+    {
         // Push all the current 'Character' properties to the stack, so that we don't store them
         // as 'tracked changes' by mistake
         m_pImpl->PushProperties(CONTEXT_CHARACTER);
@@ -2232,19 +2233,19 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext )
         // Resolve all the properties that are under the 'rPrChange'->'rPr' XML node
         resolveSprmProps(*this, rSprm );
 
-        if (m_pImpl->GetTopContext())
-        {
-            // Get all the properties that were processed in the 'rPrChange'->'rPr' XML node
-            uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
-
-            // Store these properties in the current redline object
-            m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
-        }
+        // Get all the properties that were processed in the 'rPrChange'->'rPr' XML node
+        uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
 
         // Pop back out the character properties that were on the run
         m_pImpl->PopProperties(CONTEXT_CHARACTER);
+
+        // Store these properties in the current redline object (do it after the PopProperties() above, since
+        // otherwise it'd be stored in the content dropped there).
+        m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
+    }
     break;
     case NS_ooxml::LN_CT_PPrChange_pPr:
+    {
         // Push all the current 'Paragraph' properties to the stack, so that we don't store them
         // as 'tracked changes' by mistake
         m_pImpl->PushProperties(CONTEXT_PARAGRAPH);
@@ -2252,17 +2253,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext )
         // Resolve all the properties that are under the 'pPrChange'->'pPr' XML node
         resolveSprmProps(*this, rSprm );
 
-        if (m_pImpl->GetTopContext())
-        {
-            // Get all the properties that were processed in the 'pPrChange'->'pPr' XML node
-            uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
-
-            // Store these properties in the current redline object
-            m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
-        }
+        // Get all the properties that were processed in the 'pPrChange'->'pPr' XML node
+        uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
 
         // Pop back out the character properties that were on the run
         m_pImpl->PopProperties(CONTEXT_PARAGRAPH);
+
+        // Store these properties in the current redline object (do it after the PopProperties() above, since
+        // otherwise it'd be stored in the content dropped there).
+        m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
+    }
     break;
     case NS_ooxml::LN_object:
     {
@@ -3444,7 +3444,7 @@ void DomainMapper::HandleRedline( Sprm& rSprm )
 {
     sal_uInt32 nSprmId = rSprm.getId();
 
-    m_pImpl->AddNewRedline( );
+    m_pImpl->AddNewRedline( nSprmId );
 
     if (nSprmId == NS_ooxml::LN_CT_PPr_pPrChange)
     {
@@ -3484,6 +3484,7 @@ void DomainMapper::HandleRedline( Sprm& rSprm )
         default: OSL_FAIL( "redline token other than mod, ins, del or table row" ); break;
     }
     m_pImpl->EndParaMarkerChange( );
+    m_pImpl->SetCurrentRedlineIsRead();
 }
 
 } //namespace dmapper
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 24889e5..eb08875 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1592,7 +1592,7 @@ void DomainMapper_Impl::PushFootOrEndnote( bool bIsFootnote )
 }
 
 void DomainMapper_Impl::CreateRedline(uno::Reference<text::XTextRange> const& xRange,
-        RedlineParamsPtr& pRedline)
+        RedlineParamsPtr pRedline)
 {
     if ( pRedline.get( ) )
     {
@@ -1646,21 +1646,25 @@ void DomainMapper_Impl::CheckParaMarkerRedline( uno::Reference< text::XTextRange
 
 void DomainMapper_Impl::CheckRedline( uno::Reference< text::XTextRange > const& xRange )
 {
+    // Writer core "officially" does not like overlapping redlines, and its UNO interface is stupid enough
+    // to not prevent that. However, in practice in fact everything appears to work fine (except for the debug warnings
+    // about redline table corruption, which may possibly be harmless in reality). So leave this as it is, since this
+    // is a better representation of how the changes happened. If this will ever become a problem, overlapping redlines
+    // will need to be merged into one, just like doing the changes in the UI does, which will lose some information
+    // (and so if that happens, it may be better to fix Writer).
+    // Create the redlines here from lowest (formats) to highest (inserts/removals) priority, since the last one is
+    // what Writer presents graphically, so this will show deletes as deleted text and not as just formatted text being there.
+    if( GetTopContextOfType(CONTEXT_PARAGRAPH) != NULL )
+        for( std::vector<RedlineParamsPtr>::const_iterator it = GetTopContextOfType(CONTEXT_PARAGRAPH)->Redlines().begin();
+             it != GetTopContextOfType(CONTEXT_PARAGRAPH)->Redlines().end(); ++it )
+            CreateRedline( xRange, *it );
+    if( GetTopContextOfType(CONTEXT_CHARACTER) != NULL )
+        for( std::vector<RedlineParamsPtr>::const_iterator it = GetTopContextOfType(CONTEXT_CHARACTER)->Redlines().begin();
+             it != GetTopContextOfType(CONTEXT_CHARACTER)->Redlines().end(); ++it )
+            CreateRedline( xRange, *it );
     std::vector<RedlineParamsPtr>::iterator pIt = m_aRedlines.top().begin( );
-    std::vector< RedlineParamsPtr > aCleaned;
     for (; pIt != m_aRedlines.top().end( ); ++pIt )
-    {
         CreateRedline( xRange, *pIt );
-
-        // Adding the non-mod redlines to the temporary vector
-        if ( pIt->get( ) )
-        {
-            if (((*pIt)->m_nToken & 0xffff) != XML_mod && ((*pIt)->m_nToken & 0xffff) != XML_ParagraphFormat)
-                aCleaned.push_back(*pIt);
-        }
-    }
-
-    m_aRedlines.top().swap( aCleaned );
 }
 
 void DomainMapper_Impl::StartParaMarkerChange( )
@@ -1671,6 +1675,7 @@ void DomainMapper_Impl::StartParaMarkerChange( )
 void DomainMapper_Impl::EndParaMarkerChange( )
 {
     m_bIsParaMarkerChange = false;
+    m_currentRedline.reset();
 }
 
 
@@ -4608,36 +4613,43 @@ bool DomainMapper_Impl::ExecuteFrameConversion()
     return bRet;
 }
 
-void DomainMapper_Impl::AddNewRedline(  )
+void DomainMapper_Impl::AddNewRedline( sal_uInt32 sprmId )
 {
     RedlineParamsPtr pNew( new RedlineParams );
     pNew->m_nToken = XML_mod;
     if ( !m_bIsParaMarkerChange )
     {
-        m_aRedlines.top().push_back( pNew );
+        // <w:rPrChange> applies to the whole <w:r>, <w:pPrChange> applies to the whole <w:p>,
+        // so keep those two in CONTEXT_CHARACTERS and CONTEXT_PARAGRAPH, which will take
+        // care of their scope (i.e. when they should be used and discarded).
+        // Let's keep the rest the same way they used to be handled (explictly dropped
+        // from a global stack by endtrackchange), but quite possibly they should not be handled
+        // that way either (I don't know).
+        if( sprmId == NS_ooxml::LN_EG_RPrContent_rPrChange )
+            GetTopContextOfType( CONTEXT_CHARACTER )->Redlines().push_back( pNew );
+        else if( sprmId == NS_ooxml::LN_CT_PPr_pPrChange )
+            GetTopContextOfType( CONTEXT_PARAGRAPH )->Redlines().push_back( pNew );
+        else
+            m_aRedlines.top().push_back( pNew );
     }
     else
     {
-        m_pParaMarkerRedline.swap( pNew );
+        m_pParaMarkerRedline = pNew;
     }
+    // Newly read data will go into this redline.
+    m_currentRedline = pNew;
 }
 
-RedlineParamsPtr DomainMapper_Impl::GetTopRedline(  )
+void DomainMapper_Impl::SetCurrentRedlineIsRead()
 {
-    RedlineParamsPtr pResult;
-    if ( !m_bIsParaMarkerChange && m_aRedlines.top().size(  ) > 0 )
-        pResult = m_aRedlines.top().back(  );
-    else if ( m_bIsParaMarkerChange )
-        pResult = m_pParaMarkerRedline;
-    return pResult;
+    m_currentRedline.reset();
 }
 
 sal_Int32 DomainMapper_Impl::GetCurrentRedlineToken(  )
 {
     sal_Int32 nToken = 0;
-    RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-    if ( pCurrent.get(  ) )
-        nToken = pCurrent->m_nToken;
+    assert( m_currentRedline.get());
+    nToken = m_currentRedline->m_nToken;
     return nToken;
 }
 
@@ -4645,9 +4657,8 @@ void DomainMapper_Impl::SetCurrentRedlineAuthor( const OUString& sAuthor )
 {
     if (!m_xAnnotationField.is())
     {
-        RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-        if ( pCurrent.get(  ) )
-            pCurrent->m_sAuthor = sAuthor;
+        assert( m_currentRedline.get());
+        m_currentRedline->m_sAuthor = sAuthor;
     }
     else
         m_xAnnotationField->setPropertyValue("Author", uno::makeAny(sAuthor));
@@ -4663,9 +4674,8 @@ void DomainMapper_Impl::SetCurrentRedlineDate( const OUString& sDate )
 {
     if (!m_xAnnotationField.is())
     {
-        RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-        if ( pCurrent.get(  ) )
-            pCurrent->m_sDate = sDate;
+        assert( m_currentRedline.get());
+        m_currentRedline->m_sDate = sDate;
     }
     else
         m_xAnnotationField->setPropertyValue("DateTimeValue", uno::makeAny(ConversionHelper::ConvertDateStringToDateTime(sDate)));
@@ -4679,46 +4689,46 @@ void DomainMapper_Impl::SetCurrentRedlineId( sal_Int32 sId )
     }
     else
     {
-        RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-        if ( pCurrent.get(  ) )
-            pCurrent->m_nId = sId;
+        // This should be an assert, but somebody had the smart idea to reuse this function also for comments and whatnot,
+        // and in some cases the id is actually not handled, which may be in fact a bug.
+        SAL_WARN( "writerfilter", !m_currentRedline.get());
+        if( m_currentRedline.get())
+            m_currentRedline->m_nId = sId;
     }
 }
 
 void DomainMapper_Impl::SetCurrentRedlineToken( sal_Int32 nToken )
 {
-    RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-    if ( pCurrent.get(  ) )
-        pCurrent->m_nToken = nToken;
+    assert( m_currentRedline.get());
+    m_currentRedline->m_nToken = nToken;
 }
 
 void DomainMapper_Impl::SetCurrentRedlineRevertProperties( const uno::Sequence<beans::PropertyValue>& aProperties )
 {
-    RedlineParamsPtr pCurrent( GetTopRedline(  ) );
-    if ( pCurrent.get(  ) )
-        pCurrent->m_aRevertProperties = aProperties;
+    assert( m_currentRedline.get());
+    m_currentRedline->m_aRevertProperties = aProperties;
 }
 
 
-void DomainMapper_Impl::RemoveCurrentRedline( )
+// This removes only the last redline stored here, those stored in contexts are automatically removed when
+// the context is destroyed.
+void DomainMapper_Impl::RemoveTopRedline( )
 {
-    if ( m_aRedlines.top().size( ) > 0 )
-    {
-        m_aRedlines.top().pop_back( );
-    }
+    assert( m_aRedlines.top().size( ) > 0 );
+    m_aRedlines.top().pop_back( );
+    m_currentRedline.reset();
 }
 
 void DomainMapper_Impl::ResetParaMarkerRedline( )
 {
     if ( m_pParaMarkerRedline.get( ) )
     {
-        RedlineParamsPtr pEmpty;
-        m_pParaMarkerRedline.swap( pEmpty );
+        m_pParaMarkerRedline.reset();
+        m_currentRedline.reset();
     }
 }
 
 
-
 void DomainMapper_Impl::ApplySettingsTable()
 {
     if (m_pSettingsTable && m_xTextFactory.is())
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 0407a08..817510c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -250,20 +250,6 @@ struct AnnotationPosition
 };
 typedef boost::unordered_map< sal_Int32, AnnotationPosition > AnnotationPositions_t;
 
-struct RedlineParams
-{
-    OUString m_sAuthor;
-    OUString m_sDate;
-    sal_Int32       m_nId;
-    sal_Int32       m_nToken;
-
-    /// This can hold properties of runs that had formatted 'track changes' properties
-    css::uno::Sequence<css::beans::PropertyValue> m_aRevertProperties;
-};
-typedef boost::shared_ptr< RedlineParams > RedlineParamsPtr;
-
-
-
 struct LineNumberSettings
 {
     bool        bIsOn;
@@ -392,6 +378,8 @@ private:
 
     // Redline stack
     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_pParaMarkerRedline;
     bool                            m_bIsParaMarkerChange;
 
@@ -466,7 +454,7 @@ public:
     }
     void SetDocumentSettingsProperty( const OUString& rPropName, const css::uno::Any& rValue );
 
-    void CreateRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > const& xRange, RedlineParamsPtr& pRedline  );
+    void CreateRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > const& xRange, RedlineParamsPtr pRedline  );
 
     void CheckParaMarkerRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > const& xRange );
 
@@ -725,9 +713,7 @@ public:
         );
     bool ExecuteFrameConversion();
 
-    void AddNewRedline( );
-
-    RedlineParamsPtr GetTopRedline( );
+    void AddNewRedline( sal_uInt32 sprmId );
 
     sal_Int32 GetCurrentRedlineToken( );
     void SetCurrentRedlineAuthor( const OUString& sAuthor );
@@ -735,7 +721,8 @@ public:
     void SetCurrentRedlineId( sal_Int32 nId );
     void SetCurrentRedlineToken( sal_Int32 nToken );
     void SetCurrentRedlineRevertProperties( const css::uno::Sequence<css::beans::PropertyValue>& aProperties );
-    void RemoveCurrentRedline( );
+    void SetCurrentRedlineIsRead();
+    void RemoveTopRedline( );
     void ResetParaMarkerRedline( );
     void SetCurrentRedlineInitials( const OUString& sInitials );
     bool IsFirstRun() { return m_bIsFirstRun;}
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index dcd313d..dd6d2a7 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -74,6 +74,18 @@ enum GrabBagType
     CHAR_GRAB_BAG
 };
 
+struct RedlineParams
+{
+    OUString m_sAuthor;
+    OUString m_sDate;
+    sal_Int32       m_nId;
+    sal_Int32       m_nToken;
+
+    /// This can hold properties of runs that had formatted 'track changes' properties
+    css::uno::Sequence<css::beans::PropertyValue> m_aRevertProperties;
+};
+typedef boost::shared_ptr< RedlineParams > RedlineParamsPtr;
+
 class PropValue
 {
     css::uno::Any m_aValue;
@@ -105,6 +117,9 @@ class PropertyMap
     std::map< PropertyIds, PropValue >                                          m_vMap;
 
     typedef std::map<PropertyIds,PropValue>::const_iterator                     MapIterator;
+
+    std::vector< RedlineParamsPtr > m_aRedlines;
+
 protected:
     void Invalidate()
     {
@@ -151,6 +166,10 @@ public:
     void                        SetFootnoteFontName( const OUString& rSet ) { m_sFootnoteFontName = rSet;}
 
     virtual void insertTableProperties( const PropertyMap* );
+
+    const std::vector< RedlineParamsPtr >& Redlines() const { return m_aRedlines; }
+    std::vector< RedlineParamsPtr >& Redlines() { return m_aRedlines; }
+
 #ifdef DEBUG_DOMAINMAPPER
     void printProperties();
 #endif
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index e2cfab9..febe5b1 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -17338,9 +17338,6 @@
     </resource>
     <resource name="CT_RPrChange" resource="Properties">
       <element name="rPr" tokenid="ooxml:CT_RPrChange_rPr"/>
-      <action name="end" action="tokenproperty"/>
-      <action name="end" action="sendPropertiesWithId" sendtokenid="ooxml:endtrackchange"/>
-      <action name="end" action="clearProps"/>
     </resource>
     <resource name="CT_ParaRPrChange" resource="Properties">
       <element name="rPr" tokenid="ooxml:CT_ParaRPrChange_rPr"/>
commit baf402008a18031f7a22a60ada85c3a5afa1b2a3
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Sun Sep 21 22:21:08 2014 +0200

    display paragraph format redline also as 'formats' rather than empty string
    
    Change-Id: I5ae5ce80fdb453fdf5de54c691de4cd0b88ad7f6

diff --git a/sw/source/uibase/misc/redlndlg.cxx b/sw/source/uibase/misc/redlndlg.cxx
index bb55453..ae71c2c 100644
--- a/sw/source/uibase/misc/redlndlg.cxx
+++ b/sw/source/uibase/misc/redlndlg.cxx
@@ -337,6 +337,7 @@ OUString SwRedlineAcceptDlg::GetActionText(const SwRangeRedline& rRedln, sal_uIn
         case nsRedlineType_t::REDLINE_INSERT:   return sInserted;
         case nsRedlineType_t::REDLINE_DELETE:   return sDeleted;
         case nsRedlineType_t::REDLINE_FORMAT:   return sFormated;
+        case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT:   return sFormated;
         case nsRedlineType_t::REDLINE_TABLE:    return sTableChgd;
         case nsRedlineType_t::REDLINE_FMTCOLL:  return sFmtCollSet;
         default:;//prevent warning
@@ -1089,6 +1090,7 @@ IMPL_LINK_NOARG(SwRedlineAcceptDlg, CommandHdl)
                             nResId = STR_REDLINE_DELETED;
                             break;
                         case nsRedlineType_t::REDLINE_FORMAT:
+                        case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT:
                             nResId = STR_REDLINE_FORMATED;
                             break;
                         case nsRedlineType_t::REDLINE_TABLE:
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index 4bc5c14..09decb8 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -90,6 +90,7 @@ static OUString lcl_BuildTitleWithRedline( const SwRangeRedline *pRedline )
             nResId = STR_REDLINE_DELETED;
             break;
         case nsRedlineType_t::REDLINE_FORMAT:
+        case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT:
             nResId = STR_REDLINE_FORMATED;
             break;
         case nsRedlineType_t::REDLINE_TABLE:
commit b6969634082730e25f99e1e0d7b900cf57a25a0a
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Oct 1 13:09:36 2014 +0200

    proper scoping for docx redline import (bnc#821804)
    
    propagateCharacterPropertiesAsSet sends the properties only when ending
    a text run (or maybe starting another one, I'm not quite sure), so it breaks
    ordering by sending them later then expected (although it worked in many cases).
    It's a question if propagateCharacterPropertiesAsSet is to be used by anything
    actually, since it seems rather broken to use it in the ooxml frontend.
    Using sendPropertiesWithId sends the properties properly at the right time,
    as one would expect. I don't know why dmapper can't simply handle this on its
    own, as I think it does handle entering and leaving other elements, but
    spending more time on it with this overdesigned abomination, oh well.
    
    Change-Id: Ie36c5f933ea3e6d789ea8f9e4ee3b60a5d1c920c

diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index ab4156e..e2cfab9 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -17339,7 +17339,7 @@
     <resource name="CT_RPrChange" resource="Properties">
       <element name="rPr" tokenid="ooxml:CT_RPrChange_rPr"/>
       <action name="end" action="tokenproperty"/>
-      <action name="end" action="propagateCharacterPropertiesAsSet" sendtokenid="ooxml:endtrackchange"/>
+      <action name="end" action="sendPropertiesWithId" sendtokenid="ooxml:endtrackchange"/>
       <action name="end" action="clearProps"/>
     </resource>
     <resource name="CT_ParaRPrChange" resource="Properties">
@@ -17347,10 +17347,10 @@
     </resource>
     <resource name="CT_RunTrackChange" resource="Stream">
       <action name="start" action="tokenproperty"/>
-      <action name="start" action="propagateCharacterPropertiesAsSet" sendtokenid="ooxml:trackchange"/>
+      <action name="start" action="sendPropertiesWithId" sendtokenid="ooxml:trackchange"/>
       <action name="start" action="clearProps"/>
       <action name="end" action="tokenproperty"/>
-      <action name="end" action="propagateCharacterPropertiesAsSet" sendtokenid="ooxml:endtrackchange"/>
+      <action name="end" action="sendPropertiesWithId" sendtokenid="ooxml:endtrackchange"/>
       <action name="end" action="clearProps"/>
     </resource>
     <resource name="EG_RangeMarkupElements" resource="Properties">
@@ -17537,6 +17537,7 @@
       <element name="checkBox" tokenid="ooxml:CT_FFData_checkBox"/>
       <element name="ddList" tokenid="ooxml:CT_FFData_ddList"/>
       <element name="textInput" tokenid="ooxml:CT_FFData_textInput"/>
+      <!-- TODO: This is possibly wrong and should be sendPropertiesWithId -->
       <action name="end" action="propagateCharacterPropertiesAsSet" sendtokenid="ooxml:ffdata"/>
       <action name="end" action="clearProps"/>
     </resource>
@@ -17976,7 +17977,7 @@
     </resource>
     <resource name="CT_ParaTrackChange" resource="Properties">
       <action name="start" action="tokenproperty"/>
-      <action name="start" action="propagateCharacterPropertiesAsSet" sendtokenid="ooxml:paratrackchange"/>
+      <action name="start" action="sendPropertiesWithId" sendtokenid="ooxml:paratrackchange"/>
       <action name="start" action="clearProps"/>
     </resource>
     <resource name="CT_RubyAlign" resource="Value">


More information about the Libreoffice-commits mailing list