From c916152d8562cab868d4c522748ac30029fad179 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 21 Sep 2015 07:31:33 +0200 Subject: tdf#92521 DOCX export: handle section break right after a table DocxAttributeOutput::SectionBreaks() previously only handled the text-text and text-table node transitions; implement support for table-text to avoid loosing a page break on export for the bugdoc. (View this commit with whitespace ignored to filter out the noise about SectionBreaks() now accepting non-text nodes, too.) Change-Id: Ie8a1575374a207399351635bda8c0c076ce7268d --- sw/qa/extras/ooxmlexport/data/tdf92521.odt | Bin 0 -> 8891 bytes sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 7 ++++ sw/source/filter/ww8/attributeoutputbase.hxx | 2 +- sw/source/filter/ww8/docxattributeoutput.cxx | 31 +++++++++++++----- sw/source/filter/ww8/docxattributeoutput.hxx | 2 +- sw/source/filter/ww8/docxexport.cxx | 3 ++ sw/source/filter/ww8/rtfattributeoutput.cxx | 47 ++++++++++++++------------- sw/source/filter/ww8/rtfattributeoutput.hxx | 2 +- sw/source/filter/ww8/ww8attributeoutput.hxx | 2 +- 9 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 sw/qa/extras/ooxmlexport/data/tdf92521.odt diff --git a/sw/qa/extras/ooxmlexport/data/tdf92521.odt b/sw/qa/extras/ooxmlexport/data/tdf92521.odt new file mode 100644 index 000000000000..8148e49a2275 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf92521.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index 37c19c2939c3..13592416fb31 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -812,6 +812,13 @@ DECLARE_OOXMLEXPORT_TEST(testTdf83227, "tdf83227.docx") CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName("word/media/image2.png"))); } +DECLARE_OOXMLEXPORT_TEST(testTdf92521, "tdf92521.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + // There should be a section break that's in the middle of the document: right after the table. + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:pPr/w:sectPr", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 457839c60526..a180564719fb 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -156,7 +156,7 @@ public: virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) = 0; /// Called in order to output section breaks. - virtual void SectionBreaks(const SwTextNode& rNode) = 0; + virtual void SectionBreaks(const SwNode& rNode) = 0; /// Called before we start outputting the attributes. virtual void StartParagraphProperties() = 0; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 58ae8c6ca9a3..f28b7297f643 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -794,7 +794,7 @@ void DocxAttributeOutput::EmptyParagraph() m_pSerializer->singleElementNS( XML_w, XML_p, FSEND ); } -void DocxAttributeOutput::SectionBreaks(const SwTextNode& rNode) +void DocxAttributeOutput::SectionBreaks(const SwNode& rNode) { // output page/section breaks // Writer can have them at the beginning of a paragraph, or at the end, but @@ -802,16 +802,31 @@ void DocxAttributeOutput::SectionBreaks(const SwTextNode& rNode) // paragraph in a section. To get it right, we have to switch to the next // paragraph, and detect the section breaks there. SwNodeIndex aNextIndex( rNode, 1 ); - if ( aNextIndex.GetNode().IsTextNode() ) + + if (rNode.IsTextNode()) { - const SwTextNode* pTextNode = static_cast< SwTextNode* >( &aNextIndex.GetNode() ); - m_rExport.OutputSectionBreaks( pTextNode->GetpSwAttrSet(), *pTextNode, m_tableReference->m_bTableCellOpen, pTextNode->GetText().isEmpty() ); + if (aNextIndex.GetNode().IsTextNode()) + { + const SwTextNode* pTextNode = static_cast(&aNextIndex.GetNode()); + m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode, m_tableReference->m_bTableCellOpen, pTextNode->GetText().isEmpty()); + } + else if (aNextIndex.GetNode().IsTableNode()) + { + const SwTableNode* pTableNode = static_cast(&aNextIndex.GetNode()); + const SwFrameFormat *pFormat = pTableNode->GetTable().GetFrameFormat(); + m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode); + } } - else if ( aNextIndex.GetNode().IsTableNode() ) + else if (rNode.IsEndNode()) { - const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() ); - const SwFrameFormat *pFormat = pTableNode->GetTable().GetFrameFormat(); - m_rExport.OutputSectionBreaks( &(pFormat->GetAttrSet()), *pTableNode ); + // End of something: make sure that it's the end of a table. + assert(rNode.StartOfSectionNode()->IsTableNode()); + if (aNextIndex.GetNode().IsTextNode()) + { + // Handle section break between a table and a text node following it. + const SwTextNode* pTextNode = aNextIndex.GetNode().GetTextNode(); + m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode, m_tableReference->m_bTableCellOpen, pTextNode->GetText().isEmpty()); + } } } diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index cc68dcb12fad..0bc904d2dda2 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -154,7 +154,7 @@ public: virtual void EmptyParagraph() SAL_OVERRIDE; /// Called in order to output section breaks. - virtual void SectionBreaks(const SwTextNode& rNode) SAL_OVERRIDE; + virtual void SectionBreaks(const SwNode& rNode) SAL_OVERRIDE; /// Called before we start outputting the attributes. virtual void StartParagraphProperties() SAL_OVERRIDE; diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 8fe0344feb2e..e7fa7693692a 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -499,6 +499,9 @@ void DocxExport::OutputEndNode( const SwEndNode& rEndNode ) m_pSections->AppendSection( m_pAktPageDesc, pParentFormat, nRstLnNum ); } } + else if (TXT_MAINTEXT == m_nTextTyp && rEndNode.StartOfSectionNode()->IsTableNode()) + // End node of a table: see if a section break should be written after the table. + AttrOutput().SectionBreaks(rEndNode); } void DocxExport::OutputGrfNode( const SwGrfNode& ) diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index c1ac77ee1f55..83219e973ced 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -314,33 +314,36 @@ void RtfAttributeOutput::EmptyParagraph() m_rExport.Strm().WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAR).WriteChar(' '); } -void RtfAttributeOutput::SectionBreaks(const SwTextNode& rNode) +void RtfAttributeOutput::SectionBreaks(const SwNode& rNode) { - OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty"); + if (rNode.IsTextNode()) + { + OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty"); - // output page/section breaks - SwNodeIndex aNextIndex(rNode, 1); - m_rExport.Strm().WriteCharPtr(m_aSectionBreaks.makeStringAndClear().getStr()); - m_bBufferSectionBreaks = true; + // output page/section breaks + SwNodeIndex aNextIndex(rNode, 1); + m_rExport.Strm().WriteCharPtr(m_aSectionBreaks.makeStringAndClear().getStr()); + m_bBufferSectionBreaks = true; - // output section headers / footers - if (!m_bBufferSectionHeaders) - m_rExport.Strm().WriteCharPtr(m_aSectionHeaders.makeStringAndClear().getStr()); + // output section headers / footers + if (!m_bBufferSectionHeaders) + m_rExport.Strm().WriteCharPtr(m_aSectionHeaders.makeStringAndClear().getStr()); - if (aNextIndex.GetNode().IsTextNode()) - { - const SwTextNode* pTextNode = static_cast< SwTextNode* >(&aNextIndex.GetNode()); - m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode); - // Save the current page description for now, so later we will be able to access the previous one. - m_pPrevPageDesc = pTextNode->FindPageDesc(false); - } - else if (aNextIndex.GetNode().IsTableNode()) - { - const SwTableNode* pTableNode = static_cast< SwTableNode* >(&aNextIndex.GetNode()); - const SwFrameFormat* pFormat = pTableNode->GetTable().GetFrameFormat(); - m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode); + if (aNextIndex.GetNode().IsTextNode()) + { + const SwTextNode* pTextNode = static_cast< SwTextNode* >(&aNextIndex.GetNode()); + m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode); + // Save the current page description for now, so later we will be able to access the previous one. + m_pPrevPageDesc = pTextNode->FindPageDesc(false); + } + else if (aNextIndex.GetNode().IsTableNode()) + { + const SwTableNode* pTableNode = static_cast< SwTableNode* >(&aNextIndex.GetNode()); + const SwFrameFormat* pFormat = pTableNode->GetTable().GetFrameFormat(); + m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode); + } + m_bBufferSectionBreaks = false; } - m_bBufferSectionBreaks = false; } void RtfAttributeOutput::StartParagraphProperties() diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index 9407fefb573c..abc8e2d63c00 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -53,7 +53,7 @@ public: virtual void EmptyParagraph() SAL_OVERRIDE; /// Called in order to output section breaks. - virtual void SectionBreaks(const SwTextNode& rNode) SAL_OVERRIDE; + virtual void SectionBreaks(const SwNode& rNode) SAL_OVERRIDE; /// Called before we start outputting the attributes. virtual void StartParagraphProperties() SAL_OVERRIDE; diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index 0b8765e2809f..25e3308cde75 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -36,7 +36,7 @@ public: virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) SAL_OVERRIDE; /// Called in order to output section breaks. - virtual void SectionBreaks(const SwTextNode& /*rNode*/) SAL_OVERRIDE {} + virtual void SectionBreaks(const SwNode& /*rNode*/) SAL_OVERRIDE {} /// Called before we start outputting the attributes. virtual void StartParagraphProperties() SAL_OVERRIDE {} -- cgit v1.2.3