sw/qa/extras/ooxmlexport/data/sdt-2-run.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 10 ++++ sw/source/filter/ww8/docxattributeoutput.cxx | 49 ++++++++++++++++++---- sw/source/filter/ww8/docxattributeoutput.hxx | 8 +++ writerfilter/source/dmapper/DomainMapper.cxx | 10 ++++ writerfilter/source/dmapper/DomainMapper_Impl.cxx | 10 ++++ writerfilter/source/dmapper/DomainMapper_Impl.hxx | 6 ++ writerfilter/source/dmapper/PropertyIds.cxx | 1 writerfilter/source/dmapper/PropertyIds.hxx | 1 9 files changed, 87 insertions(+), 8 deletions(-)
New commits: commit 0a90643947e3767fd5d76784df54d7ee25e6793d Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Thu Jul 10 10:19:18 2014 +0200 DOCX export: allow multiple runs in w:sdt tags Change-Id: Iec053f92ebdfb89ddd311e190609c9dd1a1c64ef diff --git a/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx new file mode 100644 index 0000000..6063ebc Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 494b8a8..d534ed9 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -3739,6 +3739,16 @@ DECLARE_OOXMLEXPORT_TEST(test2colHeader, "2col-header.docx") CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPageStyle, "HeaderIsOn")); } +DECLARE_OOXMLEXPORT_TEST(testSdt2Run, "sdt-2-run.docx") +{ + xmlDocPtr pXmlDoc = parseExport(); + if (!pXmlDoc) + return; + + // The problem was that <w:sdt> was closed after "first", not after "second", so the second assert failed. + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r[1]/w:t", "first"); + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r[2]/w:t", "second"); +} CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 937a337..85c45da 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -508,9 +508,16 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT m_nHyperLinkCount = 0; } + if (m_bStartedCharSdt) + { + // Run-level SDT still open? Close it now. + EndSdtBlock(); + m_bStartedCharSdt = false; + } + m_pSerializer->endElementNS( XML_w, XML_p ); if( !m_bAnchorLinkedToNode ) - WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs ); + WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, /*bPara=*/true ); else { //These should be written out to the actual Node and not to the anchor. @@ -549,7 +556,10 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT } -void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs ) +void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, + ::sax_fastparser::FastAttributeList*& pSdtPrTokenChildren, + ::sax_fastparser::FastAttributeList*& pSdtPrDataBindingAttrs, + bool bPara ) { if( nSdtPrToken > 0 || pSdtPrDataBindingAttrs ) { @@ -597,8 +607,11 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // write the ending tags after the paragraph - m_pSerializer->endElementNS( XML_w, XML_sdtContent ); - m_pSerializer->endElementNS( XML_w, XML_sdt ); + if (bPara) + EndSdtBlock(); + else + // Support multiple runs inside a run-evel SDT: don't close the SDT block yet. + m_bStartedCharSdt = true; // clear sdt status nSdtPrToken = 0; @@ -611,6 +624,12 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse } } +void DocxAttributeOutput::EndSdtBlock() +{ + m_pSerializer->endElementNS( XML_w, XML_sdtContent ); + m_pSerializer->endElementNS( XML_w, XML_sdt ); +} + void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph ) { if ( pInner.get() ) @@ -945,6 +964,14 @@ void DocxAttributeOutput::EndRun() // before "postponed run start") m_pSerializer->mark(); // let's call it "actual run start" + if (m_bEndCharSdt) + { + // This is the common case: "close sdt before the current run" was requrested by the next run. + EndSdtBlock(); + m_bEndCharSdt = false; + m_bStartedCharSdt = false; + } + if ( m_closeHyperlinkInPreviousRun ) { if ( m_startedHyperlink ) @@ -1052,9 +1079,10 @@ void DocxAttributeOutput::EndRun() // if there is some redlining in the document, output it EndRedline( m_pRedlineData ); - // enclose in a sdt block, if necessary - if ( !m_bAnchorLinkedToNode ) - WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs ); + // enclose in a sdt block, if necessary: if one is already started, then don't do it for now + // (so on export sdt blocks are never nested ATM) + if ( !m_bAnchorLinkedToNode && !m_bStartedCharSdt ) + WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs, /*bPara=*/false ); else { //These should be written out to the actual Node and not to the anchor. @@ -7693,6 +7721,11 @@ void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem& rItem ) m_aTextEffectsGrabBag.realloc(m_aTextEffectsGrabBag.getLength() + 1); m_aTextEffectsGrabBag[aLength] = aPropertyValue; } + else if (i->first == "SdtEndBefore") + { + if (m_bStartedCharSdt) + m_bEndCharSdt = true; + } else if (i->first == "SdtPr") { uno::Sequence<beans::PropertyValue> aGrabBagSdt = @@ -7766,6 +7799,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_pSectionSpacingAttrList( NULL ), m_pParagraphSpacingAttrList( NULL ), m_pHyperlinkAttrList( NULL ), + m_bEndCharSdt(false), + m_bStartedCharSdt(false), m_pColorAttrList( NULL ), m_pBackgroundAttrList( NULL ), m_endPageRef( false ), diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 17bc31c..34362f3 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -691,7 +691,9 @@ private: void WritePostponedDMLDrawing(); void WritePostponedCustomShape(); - void WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs ); + void WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs, bool bPara ); + /// Closes a currently open SDT block. + void EndSdtBlock(); void StartField_Impl( FieldInfos& rInfos, bool bWriteRun = false ); void DoWriteCmd( const OUString& rCmd ); @@ -706,6 +708,10 @@ private: ::sax_fastparser::FastAttributeList *m_pSectionSpacingAttrList; ::sax_fastparser::FastAttributeList *m_pParagraphSpacingAttrList; ::sax_fastparser::FastAttributeList *m_pHyperlinkAttrList; + /// If the current SDT around runs should be ended before the current run. + bool m_bEndCharSdt; + /// If an SDT around runs is currently open. + bool m_bStartedCharSdt; /// Attributes of the run color ::sax_fastparser::FastAttributeList *m_pColorAttrList; /// Attributes of the paragraph background commit 7ab5fcfbda1898f862d599e4351db2da92027867 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Thu Jul 10 09:53:44 2014 +0200 DOCX import: handle exact end of w:sdt tags Change-Id: I5b6158281782fc07ffe0eef73ab94345563498f9 diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 98e14d7..f6a91fb 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -902,6 +902,11 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) break; case NS_ooxml::LN_CT_SdtBlock_sdtEndContent: m_pImpl->SetSdt(false); + + // It's not possible to insert the relevant property to the character context here: + // the previous, already sent character context may be still active, so the property would be lost. + m_pImpl->setSdtEndDeferred(true); + if (!m_pImpl->m_pSdtHelper->getDropDownItems().empty()) m_pImpl->m_pSdtHelper->createDropDownControl(); break; @@ -2653,6 +2658,11 @@ void DomainMapper::lcl_startCharacterGroup() if (m_pImpl->m_bFrameBtLr) // No support for this in core, work around by char rotation, as we do so for table cells already. m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION, uno::makeAny(sal_Int16(900))); + if (m_pImpl->isSdtEndDeferred()) + { + m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG); + m_pImpl->setSdtEndDeferred(false); + } } void DomainMapper::lcl_endCharacterGroup() diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 9457568..edd30e5 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -160,6 +160,7 @@ DomainMapper_Impl::DomainMapper_Impl( m_bIsFirstSection( true ), m_bIsColumnBreakDeferred( false ), m_bIsPageBreakDeferred( false ), + m_bSdtEndDeferred(false), m_bStartTOC(false), m_bStartTOCHeaderFooter(false), m_bStartedTOC(false), @@ -706,6 +707,15 @@ void DomainMapper_Impl::clearDeferredBreaks() m_bIsPageBreakDeferred = false; } +void DomainMapper_Impl::setSdtEndDeferred(bool bSdtEndDeferred) +{ + m_bSdtEndDeferred = bSdtEndDeferred; +} + +bool DomainMapper_Impl::isSdtEndDeferred() +{ + return m_bSdtEndDeferred; +} void lcl_MoveBorderPropertiesToFrame(comphelper::SequenceAsHashMap& rFrameProperties, uno::Reference<text::XTextRange> xStartTextRange, diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 778d7b0..43bedc8 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -319,6 +319,8 @@ private: bool m_bIsFirstSection; bool m_bIsColumnBreakDeferred; bool m_bIsPageBreakDeferred; + /// If we want to set "sdt end" on the next character contet. + bool m_bSdtEndDeferred; bool m_bStartTOC; bool m_bStartTOCHeaderFooter; /// If we got any text that is the pre-rendered result of the TOC field. @@ -489,6 +491,10 @@ public: bool isBreakDeferred( BreakType deferredBreakType ); void clearDeferredBreaks(); void clearDeferredBreak(BreakType deferredBreakType); + + void setSdtEndDeferred(bool bSdtEndDeferred); + bool isSdtEndDeferred(); + void finishParagraph( PropertyMapPtr pPropertyMap ); void appendTextPortion( const OUString& rString, PropertyMapPtr pPropertyMap ); void appendTextContent( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextContent >, diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx index e5b9918..8c1e42b 100644 --- a/writerfilter/source/dmapper/PropertyIds.cxx +++ b/writerfilter/source/dmapper/PropertyIds.cxx @@ -393,6 +393,7 @@ OUString PropertyNameSupplier::GetName( PropertyIds eId ) const case PROP_TABLE_INTEROP_GRAB_BAG : sName = "TableInteropGrabBag"; break; case PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING : sName = "ApplyParagraphMarkFormatToNumbering"; break; case PROP_CELL_DIRECTION: sName = "CellDirection"; break; + case PROP_SDT_END_BEFORE: sName = "SdtEndBefore"; break; } ::std::pair<PropertyNameMap_t::iterator,bool> aInsertIt = m_pImpl->aNameMap.insert( PropertyNameMap_t::value_type( eId, sName )); diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx index f1543be..635df35 100644 --- a/writerfilter/source/dmapper/PropertyIds.hxx +++ b/writerfilter/source/dmapper/PropertyIds.hxx @@ -365,6 +365,7 @@ enum PropertyIds ,PROP_INDEX_ENTRY_TYPE ,PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ,PROP_CELL_DIRECTION + ,PROP_SDT_END_BEFORE }; struct PropertyNameSupplier_Impl; class PropertyNameSupplier _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits