diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-07-10 10:19:18 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-07-10 10:49:43 +0200 |
commit | 0a90643947e3767fd5d76784df54d7ee25e6793d (patch) | |
tree | 5f99ac3906f16b1de3f3d5c5f370ab31e879091c | |
parent | 7ab5fcfbda1898f862d599e4351db2da92027867 (diff) |
DOCX export: allow multiple runs in w:sdt tags
Change-Id: Iec053f92ebdfb89ddd311e190609c9dd1a1c64ef
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/sdt-2-run.docx | bin | 0 -> 12849 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 10 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 49 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 8 |
4 files changed, 59 insertions, 8 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx Binary files differnew file mode 100644 index 000000000000..6063ebc41c9a --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 494b8a862b7a..d534ed9d4afe 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 937a3375e1b8..85c45da21221 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 17bc31cfee05..34362f30ed2f 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 |