diff options
author | Attila Szűcs <szucs.attila3@nisz.hu> | 2021-02-25 13:29:46 +0100 |
---|---|---|
committer | Gabor Kelemen <kelemen.gabor2@nisz.hu> | 2021-04-22 17:54:58 +0200 |
commit | c8e11df5226868b4f584de003b10ef41b445bb64 (patch) | |
tree | 25fd826031a42e3e7994cea3a97da2264b1359f7 | |
parent | 3ae1a48d09c94d4241c241a03e5779ba3106fd37 (diff) |
tdf#121666 DOCX export: fix missing page break
When an empty paragraph has both page break and section
break, only the section break was exported to DOCX,
the page break was not, while MSO needs that to show
all page breaks.
The DOC and RTF exports were not changed by this fix
(not sure if the problem are present with them or not).
Co-authored-by: Tibor Nagy (NISZ)
Change-Id: I5deac0390666415e36a541c731dda4bc0a2ad6ad
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111543
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit d58229d61b8bbf9eb0db841826e361940c7b2a4a)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114499
Tested-by: Gabor Kelemen <kelemen.gabor2@nisz.hu>
Reviewed-by: Gabor Kelemen <kelemen.gabor2@nisz.hu>
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf121666_lostPage.docx | bin | 0 -> 20235 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 10 | ||||
-rw-r--r-- | sw/source/filter/ww8/attributeoutputbase.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 14 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 4 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.hxx | 3 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfattributeoutput.cxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfattributeoutput.hxx | 4 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfexport.cxx | 5 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfexport.hxx | 4 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtww8.hxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8atr.cxx | 16 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8attributeoutput.hxx | 2 |
14 files changed, 55 insertions, 19 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf121666_lostPage.docx b/sw/qa/extras/ooxmlexport/data/tdf121666_lostPage.docx Binary files differnew file mode 100644 index 000000000000..195f574d1c5d --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf121666_lostPage.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index 1b9621b473b0..cbdc5e2df8d8 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -80,6 +80,16 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121374_sectionHF2, "tdf121374_sectionHF2.doc") CPPUNIT_ASSERT( xHeaderText->getString().startsWith("virkamatka-anomus") ); } +DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf121666_lostPage, "tdf121666_lostPage.docx") +{ + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r[2]/w:br", "type", "page"); + // The second page break is exported too. + // Before this fix, if a node had both section break and page break, then only the section break was exported. + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:br", "type", "page"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:pPr/w:sectPr/w:type", "val", "nextPage"); +} + DECLARE_OOXMLEXPORT_TEST(testTdf95848, "tdf95848.docx") { OUString listId; diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 89865c7de7f5..c414e39bc3ee 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -300,7 +300,7 @@ public: /// Write a section break /// msword::ColumnBreak or msword::PageBreak /// bBreakAfter: the break must be scheduled for insertion in the end of current paragraph - virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr ) = 0; + virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr, bool bExtraPageBreak = false ) = 0; // preserve page vertical alignment virtual void TextVerticalAdjustment( const css::drawing::TextVerticalAdjust) {}; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 72620895f9c8..d95a3136aeef 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -6298,7 +6298,7 @@ void DocxAttributeOutput::PageBreakBefore( bool bBreak ) FSNS( XML_w, XML_val ), "false" ); } -void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo ) +void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo, bool bExtraPageBreak) { switch ( nC ) { @@ -6349,10 +6349,22 @@ void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW m_rExport.SectionProperties( *pSectionInfo ); m_pSerializer->endElementNS( XML_w, XML_pPr ); + if (bExtraPageBreak) + { + m_pSerializer->startElementNS(XML_w, XML_r); + m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page"); + m_pSerializer->endElementNS(XML_w, XML_r); + } m_pSerializer->endElementNS( XML_w, XML_p ); } else { + if (bExtraPageBreak && m_bParagraphOpened) + { + m_pSerializer->startElementNS(XML_w, XML_r); + m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page"); + m_pSerializer->endElementNS(XML_w, XML_r); + } // postpone the output of this; it has to be done inside the // paragraph properties, so remember it until then m_pSectionInfo.reset( new WW8_SepInfo( *pSectionInfo )); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index de0e31b910f4..e94f4f580023 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -272,7 +272,7 @@ public: /// Write a section break /// msword::ColumnBreak or msword::PageBreak /// bBreakAfter: the break must be scheduled for insertion in the end of current paragraph - virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr ) override; + virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr, bool bExtraPageBreak = false ) override; // preserve DOCX page vertical alignment virtual void TextVerticalAdjustment( const css::drawing::TextVerticalAdjust ) override; diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 74f7ad317cb4..636d70d71258 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -619,11 +619,11 @@ sal_uLong DocxExport::ReplaceCr( sal_uInt8 ) void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) + const SwPageDesc* pNewPgDesc, bool bExtraPageBreak ) { // tell the attribute output that we are ready to write the section // break [has to be output inside paragraph properties] - AttrOutput().SectionBreak( msword::PageBreak, false, m_pSections->CurrentSectionInfo() ); + AttrOutput().SectionBreak( msword::PageBreak, false, m_pSections->CurrentSectionInfo(), bExtraPageBreak ); const SwSectionFormat* pFormat = GetSectionFormat( rNd ); const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd ); diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 74336b72d454..324aab6c93e0 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -217,7 +217,8 @@ protected: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) override; + const SwPageDesc* pNewPgDesc, + bool bExtraPageBreak = false) override; private: /// Setup pStyles and write styles.xml diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 10d38a569e92..1ae75ce327ea 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -1201,7 +1201,7 @@ void RtfAttributeOutput::PageBreakBefore(bool bBreak) } void RtfAttributeOutput::SectionBreak(sal_uInt8 nC, bool /*bBreakAfter*/, - const WW8_SepInfo* pSectionInfo) + const WW8_SepInfo* pSectionInfo, bool /*bExtraPageBreak*/) { switch (nC) { diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index 2493ce38fbb0..b7e0d5ed0439 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -165,8 +165,8 @@ public: /// Write a section break /// msword::ColumnBreak or msword::PageBreak - void SectionBreak(sal_uInt8 nC, bool bBreakAfter, - const WW8_SepInfo* pSectionInfo = nullptr) override; + void SectionBreak(sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr, + bool bExtraPageBreak = false) override; /// Start of the section properties. void StartSection() override; diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index 3cea7bfb88fe..85aace5b7196 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -947,7 +947,7 @@ ErrCode RtfExport::ExportDocument_Impl() void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc) + const SwPageDesc* pNewPgDesc, bool bExtraPageBreak) { const SwSectionFormat* pFormat = GetSectionFormat(rNd); const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd); @@ -962,7 +962,8 @@ void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd, // Don't insert a page break, when we're changing page style just because the next page has to be a different one. if (!m_pAttrOutput->GetPrevPageDesc() || m_pAttrOutput->GetPrevPageDesc()->GetFollow() != pNewPgDesc) - AttrOutput().SectionBreak(msword::PageBreak, false, m_pSections->CurrentSectionInfo()); + AttrOutput().SectionBreak(msword::PageBreak, false, m_pSections->CurrentSectionInfo(), + bExtraPageBreak); } bool RtfExport::DisallowInheritingOutlineNumbering(const SwFormat& rFormat) diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx index 0c0d35d1a97f..14b1d4b59069 100644 --- a/sw/source/filter/ww8/rtfexport.hxx +++ b/sw/source/filter/ww8/rtfexport.hxx @@ -123,8 +123,8 @@ protected: /// Get ready for a new section. void PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd, - const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc) override; + const SwFormatPageDesc* pNewPgDescFormat, const SwPageDesc* pNewPgDesc, + bool bExtraPageBreak = false) override; /// Return value indicates if an inherited outline numbering is suppressed. bool DisallowInheritingOutlineNumbering(const SwFormat& rFormat) override; diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 50d762f6e358..7ed6025d6892 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -844,7 +844,8 @@ protected: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) = 0; + const SwPageDesc* pNewPgDesc, + bool bExtraPageBreak = false ) = 0; /// Return value indicates if an inherited outline numbering is suppressed. virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) = 0; @@ -1109,7 +1110,8 @@ public: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) override; + const SwPageDesc* pNewPgDesc, + bool bExtraPageBreak = false ) override; static void Out_BorderLine(ww::bytes& rO, const ::editeng::SvxBorderLine* pLine, sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9, diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index 7a8026c55813..ac69fba60c13 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -465,6 +465,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode bool bNewPageDesc = false; const SfxPoolItem* pItem=nullptr; const SwFormatPageDesc *pPgDesc=nullptr; + bool bExtraPageBreakBeforeSectionBreak = false; //Output a sectionbreak if there's a new pagedescriptor. Otherwise output a //pagebreak if there is a pagebreak here, unless the new page (follow @@ -542,6 +543,14 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode bNewPageDesc = true; pPgDesc = static_cast<const SwFormatPageDesc*>(pItem); m_pCurrentPageDesc = pPgDesc->GetPageDesc(); + + // tdf#121666: nodes that have pagebreak + sectionbreak may need to export both breaks + // tested / implemented with docx format only. + // If other formats (rtf /doc) need similar fix, then that may can be done similar way. + if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false, &pItem)) + { + bExtraPageBreakBeforeSectionBreak = true; + } } else if ( SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem ) ) { @@ -632,7 +641,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode if ( bNewPageDesc && m_pCurrentPageDesc ) { - PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc ); + PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc, bExtraPageBreakBeforeSectionBreak ); } m_bBreakBefore = false; m_bPrevTextNodeIsEmpty = isTextNodeEmpty ; @@ -685,7 +694,8 @@ sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNo void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) + const SwPageDesc* pNewPgDesc, + bool /*bExtraPageBreak*/ ) { // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding // position by the occurrences of PageDesc attributes. The construction and @@ -3954,7 +3964,7 @@ void AttributeOutputBase::FormatBreak( const SvxFormatBreakItem& rBreak ) } } -void WW8AttributeOutput::SectionBreak( sal_uInt8 nC, bool /*bBreakAfter*/, const WW8_SepInfo* /*pSectionInfo*/ ) +void WW8AttributeOutput::SectionBreak( sal_uInt8 nC, bool /*bBreakAfter*/, const WW8_SepInfo* /*pSectionInfo*/, bool /*bExtraPageBreak*/ ) { m_rWW8Export.ReplaceCr( nC ); } diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index ac4e931ecf0d..7bd1dd1d1e00 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -147,7 +147,7 @@ public: /// Write a section break /// msword::ColumnBreak or msword::PageBreak - virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr ) override; + virtual void SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo = nullptr, bool bExtraPageBreak = false ) override; // preserve DOC page vertical alignment virtual void TextVerticalAdjustment( const css::drawing::TextVerticalAdjust ) override; |