diff options
author | Pallavi Jadhav <pallavi.jadhav@synerzip.com> | 2014-08-13 18:14:47 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-08-18 12:52:30 +0200 |
commit | 8b9988163c0c0d158fc2d9f5272695ccfec92237 (patch) | |
tree | f9d2691b9837fc829a0fce96c879f10da6df9e75 | |
parent | a18ff3d5c75c2b468c48bd19439dee0689d24d67 (diff) |
fdo#82492 : DOCX: Corruption: File was getting corrupt fafter RT
Issue :
- In issue file there were two runs(first run=SDT, second run=Shape).
- These two runs were consecutive(no text/space/tab was there in between two runs).
- Due to such scenario, "SdtEndBefore" was not getting set on Shape.
- Hence at Export EndSdtBlock() was getting called from EndParagraph().
Due to this SDT was not getting end after first run.
In order to end SDT after run, EndSdtBlock() should get called from EndRun()
(as in Original file)
Implementation :
- Set "SdtEndBefore" on Shape in DomainMapper_Impl::PushShapeContext()
- Retrieved same property at export.
- Added export unit test case.
Note :
Added common functions at Import and Export with reference to
https://gerrit.libreoffice.org/#/c/10827/
Conflicts:
sw/source/filter/ww8/docxattributeoutput.cxx
Reviewed on:
https://gerrit.libreoffice.org/10912
Change-Id: I357d77cd179c83b8ae976db331ee46c8993b6cb8
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/fdo82492.docx | bin | 0 -> 25948 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 10 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 62 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 1 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.cxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 91 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 3 |
7 files changed, 109 insertions, 60 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/fdo82492.docx b/sw/qa/extras/ooxmlexport/data/fdo82492.docx Binary files differnew file mode 100644 index 000000000000..6533056f47cd --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/fdo82492.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index 9ab1ba22c80a..d52423f8fd75 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -610,6 +610,16 @@ DECLARE_OOXMLEXPORT_TEST(testfdo81946, "fdo81946.docx") assertXPath(pXmlDoc, "/w:hdr[1]/w:p[1]/w:sdt[1]/w:sdtContent[1]/w:r[2]/mc:AlternateContent[1]",0); } +DECLARE_OOXMLEXPORT_TEST(testfdo82492, "fdo82492.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; + + // make sure there is only one run inside first SDT after RT as in the Original file. + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt[1]/w:sdtContent/w:r",1); +} + DECLARE_OOXMLEXPORT_TEST(testSdtHeader, "sdt-header.docx") { // Problem was that w:sdt elements in headers were lost on import. diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 4ead52631169..86065cbda2e7 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1917,6 +1917,41 @@ void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData ) m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); } +void DocxAttributeOutput::GetSdtEndBefore(const SdrObject* pSdrObj) +{ + if (pSdrObj) + { + uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY_THROW); + if( xShape.is() ) + { + uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo; + if( xPropSet.is() ) + { + xPropSetInfo = xPropSet->getPropertySetInfo(); + uno::Sequence< beans::PropertyValue > aGrabBag; + if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag")) + { + xPropSet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag; + } + else if(xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("InteropGrabBag")) + { + xPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag; + } + + for (sal_Int32 nProp=0; nProp < aGrabBag.getLength(); ++nProp) + { + if ("SdtEndBefore" == aGrabBag[nProp].Name && m_bStartedCharSdt && !m_bEndCharSdt) + { + aGrabBag[nProp].Value >>= m_bEndCharSdt; + break; + } + } + } + } + } +} + void DocxAttributeOutput::WritePostponedGraphic() { for( std::list< PostponedGraphic >::const_iterator it = m_postponedGraphic->begin(); @@ -4011,32 +4046,7 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size { OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode, const SdrObject* pSdrObj ) - some stuff still missing" ); - if (pSdrObj) - { - uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY_THROW); - if( xShape.is() ) - { - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); - uno::Reference< beans::XPropertySetInfo > xPropSetInfo; - if( xPropSet.is() ) - { - xPropSetInfo = xPropSet->getPropertySetInfo(); - if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag")) - { - uno::Sequence< beans::PropertyValue > aGrabBag; - xPropSet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag; - for (sal_Int32 nProp=0; nProp < aGrabBag.getLength(); ++nProp) - { - if ("SdtEndBefore" == aGrabBag[nProp].Name && m_bStartedCharSdt && !m_bEndCharSdt) - { - aGrabBag[nProp].Value >>= m_bEndCharSdt; - break; - } - } - } - } - } - } + GetSdtEndBefore(pSdrObj); // detect mis-use of the API assert(pGrfNode || (pOLEFrmFmt && pOLENode)); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 90a31d87a70f..343afaf09213 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -959,6 +959,7 @@ public: bool GetWritingHeaderFooter( ) { return m_bWritingHeaderFooter; } void SetAlternateContentChoiceOpen( bool bAltContentChoiceOpen ) { m_bAlternateContentChoiceOpen = bAltContentChoiceOpen; } bool IsAlternateContentChoiceOpen( ) { return m_bAlternateContentChoiceOpen; } + void GetSdtEndBefore(const SdrObject* pSdrObj); }; #endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXATTRIBUTEOUTPUT_HXX diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx index 0a88a41d3483..bd34f04596b7 100644 --- a/sw/source/filter/ww8/docxsdrexport.cxx +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -810,6 +810,8 @@ void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* if (!m_pImpl->isSupportedDMLShape(xShape)) return; + m_pImpl->m_rExport.DocxAttrOutput().GetSdtEndBefore(pSdrObject); + sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer; Size aSize(pSdrObject->GetLogicRect().GetWidth(), pSdrObject->GetLogicRect().GetHeight()); startDMLAnchorInline(pFrmFmt, aSize); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 9f203a951065..0428c8752520 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1906,6 +1906,24 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape m_vTextFramesForChaining.push_back(xShape); } } + + if(IsSdtEndBefore()) + { + uno::Reference< beans::XPropertySetInfo > xPropSetInfo; + if(xShapePropertySet.is()) + { + xPropSetInfo = xShapePropertySet->getPropertySetInfo(); + if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("InteropGrabBag")) + { + uno::Sequence<beans::PropertyValue> aShapeGrabBag(1); + beans::PropertyValue aRet; + aRet.Name = "SdtEndBefore"; + aRet.Value <<= uno::makeAny(true); + aShapeGrabBag[0] = aRet; + xShapePropertySet->setPropertyValue("InteropGrabBag",uno::makeAny(aShapeGrabBag)); + } + } + } } if (!m_bInHeaderFooterImport && !checkZOrderStatus) xProps->setPropertyValue( @@ -1981,6 +1999,32 @@ void DomainMapper_Impl::PopShapeContext() m_bFrameBtLr = false; } +bool DomainMapper_Impl::IsSdtEndBefore() +{ + bool bIsSdtEndBefore = false;; + PropertyMapPtr pContext = GetTopContextOfType(CONTEXT_CHARACTER); + if(pContext) + { + uno::Sequence< beans::PropertyValue > currentCharProps = pContext->GetPropertyValues(); + for (int i =0; i< currentCharProps.getLength(); i++) + { + if (currentCharProps[i].Name == "CharInteropGrabBag") + { + uno::Sequence<beans::PropertyValue> aCharGrabBag; + currentCharProps[i].Value >>= aCharGrabBag; + for (int j=0; j < aCharGrabBag.getLength();j++) + { + if(aCharGrabBag[j].Name == "SdtEndBefore") + { + aCharGrabBag[j].Value >>= bIsSdtEndBefore; + } + } + } + } + } + return bIsSdtEndBefore; +} + sal_Int16 lcl_ParseNumberingType( const OUString& rCommand ) { sal_Int16 nRet = style::NumberingType::PAGE_DESCRIPTOR; @@ -4399,43 +4443,22 @@ void DomainMapper_Impl::ImportGraphic(writerfilter::Reference< Properties >::Po * there is no text/space/tab in between two runs. * In this case "SdtEndBefore" property needs to be set on Drawing. */ - PropertyMapPtr pContext = GetTopContextOfType(CONTEXT_CHARACTER); - if(pContext) + if(IsSdtEndBefore()) { - uno::Sequence< beans::PropertyValue > currentCharProps = pContext->GetPropertyValues(); - for (int i =0; i< currentCharProps.getLength(); i++) + uno::Reference< beans::XPropertySet > xGraphicObjectProperties(xTextContent, + uno::UNO_QUERY_THROW); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo; + if(xGraphicObjectProperties.is()) { - if (currentCharProps[i].Name == "CharInteropGrabBag") + xPropSetInfo = xGraphicObjectProperties->getPropertySetInfo(); + if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag")) { - uno::Sequence<beans::PropertyValue> aCharGrabBag; - currentCharProps[i].Value >>= aCharGrabBag; - for (int j=0; j < aCharGrabBag.getLength();j++) - { - if(aCharGrabBag[j].Name == "SdtEndBefore") - { - bool bIsSdtEndBefore = false; - aCharGrabBag[j].Value >>= bIsSdtEndBefore; - if (bIsSdtEndBefore) - { - uno::Reference< beans::XPropertySet > xGraphicObjectProperties(xTextContent, - uno::UNO_QUERY_THROW); - uno::Reference< beans::XPropertySetInfo > xPropSetInfo; - if(xGraphicObjectProperties.is()) - { - xPropSetInfo = xGraphicObjectProperties->getPropertySetInfo(); - if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag")) - { - uno::Sequence<beans::PropertyValue> aFrameGrabBag(1); - beans::PropertyValue aRet; - aRet.Name = "SdtEndBefore"; - aRet.Value <<= uno::makeAny(true); - aFrameGrabBag[0] = aRet; - xGraphicObjectProperties->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aFrameGrabBag)); - } - } - } - } - } + uno::Sequence<beans::PropertyValue> aFrameGrabBag(1); + beans::PropertyValue aRet; + aRet.Name = "SdtEndBefore"; + aRet.Value <<= uno::makeAny(true); + aFrameGrabBag[0] = aRet; + xGraphicObjectProperties->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aFrameGrabBag)); } } } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 2bb0478f2c2a..4bee8aceeedc 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -824,6 +824,9 @@ public: /// If the document needs to split paragraph. bool m_bIsSplitPara; + /// Check if "SdtEndBefore" property is set + bool IsSdtEndBefore(); + private: void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType eType); std::vector<css::uno::Reference< css::drawing::XShape > > m_vTextFramesForChaining ; |