sw/CppunitTest_sw_ooxmlimport.mk | 1 sw/qa/extras/ooxmlimport/data/bnc821804.docx |binary sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 111 ++++++++++++++++++++++ sw/source/core/uibase/misc/redlndlg.cxx | 2 sw/source/core/uibase/shells/textfld.cxx | 1 sw/source/core/unocore/unoredline.cxx | 1 writerfilter/source/dmapper/DomainMapper.cxx | 37 +++---- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 110 +++++++++++---------- writerfilter/source/dmapper/DomainMapper_Impl.hxx | 25 +--- writerfilter/source/dmapper/PropertyMap.hxx | 18 +++ writerfilter/source/ooxml/model.xml | 10 - 11 files changed, 223 insertions(+), 93 deletions(-)
New commits: commit c3f4ece4ca8fff2c67504e76bddf89252d75daee Author: LuboÅ¡ LuÅák <l.lu...@collabora.com> Date: Wed Oct 1 13:09:36 2014 +0200 fix docx redline import (bnc#821804) This is a squash of commits b6969634..fd26de3b. Change-Id: I8984001d7f85c00eb9b9943b25b8abb6e2ee28d3 Reviewed-on: https://gerrit.libreoffice.org/11789 Reviewed-by: Miklos Vajna <vmik...@collabora.co.uk> Tested-by: Miklos Vajna <vmik...@collabora.co.uk> diff --git a/sw/CppunitTest_sw_ooxmlimport.mk b/sw/CppunitTest_sw_ooxmlimport.mk index 2c4682b..a77787e 100644 --- a/sw/CppunitTest_sw_ooxmlimport.mk +++ b/sw/CppunitTest_sw_ooxmlimport.mk @@ -24,6 +24,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 07761dd..900a25e 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -54,11 +54,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> @@ -2284,6 +2286,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 ), 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(); diff --git a/sw/source/core/uibase/misc/redlndlg.cxx b/sw/source/core/uibase/misc/redlndlg.cxx index d3dc31f..3a062a4 100644 --- a/sw/source/core/uibase/misc/redlndlg.cxx +++ b/sw/source/core/uibase/misc/redlndlg.cxx @@ -338,6 +338,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 @@ -1092,6 +1093,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/core/uibase/shells/textfld.cxx b/sw/source/core/uibase/shells/textfld.cxx index ce20366..cace5c5 100644 --- a/sw/source/core/uibase/shells/textfld.cxx +++ b/sw/source/core/uibase/shells/textfld.cxx @@ -82,6 +82,7 @@ static OUString& lcl_AppendRedlineStr( OUString& rStr, sal_uInt16 nRedlId ) case nsRedlineType_t::REDLINE_INSERT: nResId = STR_REDLINE_INSERTED; break; case nsRedlineType_t::REDLINE_DELETE: nResId = STR_REDLINE_DELETED; break; case nsRedlineType_t::REDLINE_FORMAT: nResId = STR_REDLINE_FORMATED; break; + case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT: nResId = STR_REDLINE_FORMATED; break; case nsRedlineType_t::REDLINE_TABLE: nResId = STR_REDLINE_TABLECHG; break; case nsRedlineType_t::REDLINE_FMTCOLL: nResId = STR_REDLINE_FMTCOLLSET; break; } diff --git a/sw/source/core/unocore/unoredline.cxx b/sw/source/core/unocore/unoredline.cxx index 314178d..855d11b 100644 --- a/sw/source/core/unocore/unoredline.cxx +++ b/sw/source/core/unocore/unoredline.cxx @@ -209,6 +209,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; } diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index d97f471..90ae6e9 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -2169,9 +2169,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); @@ -2179,19 +2180,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); @@ -2199,17 +2200,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: { @@ -3288,7 +3288,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) { @@ -3328,6 +3328,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 23b976b..ffa4bae 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1625,7 +1625,7 @@ void DomainMapper_Impl::PushFootOrEndnote( bool bIsFootnote ) } } -void DomainMapper_Impl::CreateRedline( uno::Reference< text::XTextRange > xRange, RedlineParamsPtr& pRedline ) +void DomainMapper_Impl::CreateRedline( uno::Reference< text::XTextRange > xRange, RedlineParamsPtr pRedline ) { if ( pRedline.get( ) ) { @@ -1679,21 +1679,25 @@ void DomainMapper_Impl::CheckParaMarkerRedline( uno::Reference< text::XTextRange void DomainMapper_Impl::CheckRedline( uno::Reference< text::XTextRange > xRange ) { - vector<RedlineParamsPtr>::iterator pIt = m_aRedlines.top().begin( ); - vector< RedlineParamsPtr > aCleaned; + // 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( ); 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) != OOXML_mod && ((*pIt)->m_nToken & 0xffff) != OOXML_ParagraphFormat) - aCleaned.push_back(*pIt); - } - } - - m_aRedlines.top().swap( aCleaned ); } void DomainMapper_Impl::StartParaMarkerChange( ) @@ -1704,6 +1708,7 @@ void DomainMapper_Impl::StartParaMarkerChange( ) void DomainMapper_Impl::EndParaMarkerChange( ) { m_bIsParaMarkerChange = false; + m_currentRedline.reset(); } @@ -4495,36 +4500,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 = OOXML_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; } @@ -4532,9 +4544,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)); @@ -4550,9 +4561,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))); @@ -4566,46 +4576,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 3f62129..e60eab4 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -243,20 +243,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; @@ -377,6 +363,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; @@ -449,7 +437,7 @@ public: } void SetDocumentSettingsProperty( const OUString& rPropName, const css::uno::Any& rValue ); - void CreateRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > xRange, RedlineParamsPtr& pRedline ); + void CreateRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > xRange, RedlineParamsPtr pRedline ); void CheckParaMarkerRedline( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > xRange ); @@ -704,9 +692,7 @@ public: ); bool ExecuteFrameConversion(); - void AddNewRedline( ); - - RedlineParamsPtr GetTopRedline( ); + void AddNewRedline( sal_uInt32 sprmId ); sal_Int32 GetCurrentRedlineToken( ); void SetCurrentRedlineAuthor( const OUString& sAuthor ); @@ -714,7 +700,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 5c12df2..58487d6 100644 --- a/writerfilter/source/dmapper/PropertyMap.hxx +++ b/writerfilter/source/dmapper/PropertyMap.hxx @@ -71,6 +71,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; @@ -101,6 +113,9 @@ class PropertyMap : public _PropertyMap OUString m_sFootnoteFontName; ::com::sun::star::uno::Reference< ::com::sun::star::text::XFootnote > m_xFootnote; + + std::vector< RedlineParamsPtr > m_aRedlines; + protected: void Invalidate() { @@ -133,6 +148,9 @@ public: virtual void insertTableProperties( const PropertyMap* ); + const std::vector< RedlineParamsPtr >& Redlines() const { return m_aRedlines; } + std::vector< RedlineParamsPtr >& Redlines() { return m_aRedlines; } + #if OSL_DEBUG_LEVEL > 1 virtual void dumpXml( const TagLogger::Pointer_t pLogger ) const; #endif diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 36a37f6..b3f25af 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -24263,19 +24263,16 @@ </resource> <resource name="CT_RPrChange" resource="Properties" tag="character"> <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="clearProps"/> </resource> <resource name="CT_ParaRPrChange" resource="Properties" tag="character"> <element name="rPr" tokenid="ooxml:CT_ParaRPrChange_rPr"/> </resource> <resource name="CT_RunTrackChange" resource="Stream" tag="redlines"> <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" tag="redlines"> @@ -24479,6 +24476,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> @@ -24934,7 +24932,7 @@ </resource> <resource name="CT_ParaTrackChange" resource="Properties" tag="redline"> <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="ST_RubyAlign" resource="List" generated="yes">
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits