summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2014-07-10 10:19:18 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2014-07-10 10:49:43 +0200
commit0a90643947e3767fd5d76784df54d7ee25e6793d (patch)
tree5f99ac3906f16b1de3f3d5c5f370ab31e879091c
parent7ab5fcfbda1898f862d599e4351db2da92027867 (diff)
DOCX export: allow multiple runs in w:sdt tags
Change-Id: Iec053f92ebdfb89ddd311e190609c9dd1a1c64ef
-rw-r--r--sw/qa/extras/ooxmlexport/data/sdt-2-run.docxbin0 -> 12849 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport.cxx10
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx49
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx8
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
new file mode 100644
index 000000000000..6063ebc41c9a
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx
Binary files differ
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