Kaydet (Commit) 0a906439 authored tarafından Miklos Vajna's avatar Miklos Vajna

DOCX export: allow multiple runs in w:sdt tags

Change-Id: Iec053f92ebdfb89ddd311e190609c9dd1a1c64ef
üst 7ab5fcfb
...@@ -3739,6 +3739,16 @@ DECLARE_OOXMLEXPORT_TEST(test2colHeader, "2col-header.docx") ...@@ -3739,6 +3739,16 @@ DECLARE_OOXMLEXPORT_TEST(test2colHeader, "2col-header.docx")
CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPageStyle, "HeaderIsOn")); 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(); CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -508,9 +508,16 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT ...@@ -508,9 +508,16 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
m_nHyperLinkCount = 0; 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 ); m_pSerializer->endElementNS( XML_w, XML_p );
if( !m_bAnchorLinkedToNode ) if( !m_bAnchorLinkedToNode )
WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs ); WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, /*bPara=*/true );
else else
{ {
//These should be written out to the actual Node and not to the anchor. //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 ...@@ -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 ) if( nSdtPrToken > 0 || pSdtPrDataBindingAttrs )
{ {
...@@ -597,8 +607,11 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse ...@@ -597,8 +607,11 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse
m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
// write the ending tags after the paragraph // write the ending tags after the paragraph
m_pSerializer->endElementNS( XML_w, XML_sdtContent ); if (bPara)
m_pSerializer->endElementNS( XML_w, XML_sdt ); EndSdtBlock();
else
// Support multiple runs inside a run-evel SDT: don't close the SDT block yet.
m_bStartedCharSdt = true;
// clear sdt status // clear sdt status
nSdtPrToken = 0; nSdtPrToken = 0;
...@@ -611,6 +624,12 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse ...@@ -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 ) void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
{ {
if ( pInner.get() ) if ( pInner.get() )
...@@ -945,6 +964,14 @@ void DocxAttributeOutput::EndRun() ...@@ -945,6 +964,14 @@ void DocxAttributeOutput::EndRun()
// before "postponed run start") // before "postponed run start")
m_pSerializer->mark(); // let's call it "actual 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_closeHyperlinkInPreviousRun )
{ {
if ( m_startedHyperlink ) if ( m_startedHyperlink )
...@@ -1052,9 +1079,10 @@ void DocxAttributeOutput::EndRun() ...@@ -1052,9 +1079,10 @@ void DocxAttributeOutput::EndRun()
// if there is some redlining in the document, output it // if there is some redlining in the document, output it
EndRedline( m_pRedlineData ); EndRedline( m_pRedlineData );
// enclose in a sdt block, if necessary // enclose in a sdt block, if necessary: if one is already started, then don't do it for now
if ( !m_bAnchorLinkedToNode ) // (so on export sdt blocks are never nested ATM)
WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs ); if ( !m_bAnchorLinkedToNode && !m_bStartedCharSdt )
WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs, /*bPara=*/false );
else else
{ {
//These should be written out to the actual Node and not to the anchor. //These should be written out to the actual Node and not to the anchor.
...@@ -7693,6 +7721,11 @@ void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem& rItem ) ...@@ -7693,6 +7721,11 @@ void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem& rItem )
m_aTextEffectsGrabBag.realloc(m_aTextEffectsGrabBag.getLength() + 1); m_aTextEffectsGrabBag.realloc(m_aTextEffectsGrabBag.getLength() + 1);
m_aTextEffectsGrabBag[aLength] = aPropertyValue; m_aTextEffectsGrabBag[aLength] = aPropertyValue;
} }
else if (i->first == "SdtEndBefore")
{
if (m_bStartedCharSdt)
m_bEndCharSdt = true;
}
else if (i->first == "SdtPr") else if (i->first == "SdtPr")
{ {
uno::Sequence<beans::PropertyValue> aGrabBagSdt = uno::Sequence<beans::PropertyValue> aGrabBagSdt =
...@@ -7766,6 +7799,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri ...@@ -7766,6 +7799,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
m_pSectionSpacingAttrList( NULL ), m_pSectionSpacingAttrList( NULL ),
m_pParagraphSpacingAttrList( NULL ), m_pParagraphSpacingAttrList( NULL ),
m_pHyperlinkAttrList( NULL ), m_pHyperlinkAttrList( NULL ),
m_bEndCharSdt(false),
m_bStartedCharSdt(false),
m_pColorAttrList( NULL ), m_pColorAttrList( NULL ),
m_pBackgroundAttrList( NULL ), m_pBackgroundAttrList( NULL ),
m_endPageRef( false ), m_endPageRef( false ),
......
...@@ -691,7 +691,9 @@ private: ...@@ -691,7 +691,9 @@ private:
void WritePostponedDMLDrawing(); void WritePostponedDMLDrawing();
void WritePostponedCustomShape(); 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 StartField_Impl( FieldInfos& rInfos, bool bWriteRun = false );
void DoWriteCmd( const OUString& rCmd ); void DoWriteCmd( const OUString& rCmd );
...@@ -706,6 +708,10 @@ private: ...@@ -706,6 +708,10 @@ private:
::sax_fastparser::FastAttributeList *m_pSectionSpacingAttrList; ::sax_fastparser::FastAttributeList *m_pSectionSpacingAttrList;
::sax_fastparser::FastAttributeList *m_pParagraphSpacingAttrList; ::sax_fastparser::FastAttributeList *m_pParagraphSpacingAttrList;
::sax_fastparser::FastAttributeList *m_pHyperlinkAttrList; ::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 /// Attributes of the run color
::sax_fastparser::FastAttributeList *m_pColorAttrList; ::sax_fastparser::FastAttributeList *m_pColorAttrList;
/// Attributes of the paragraph background /// Attributes of the paragraph background
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment