diff options
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 7 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtw8sty.cxx | 80 |
2 files changed, 86 insertions, 1 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index 5ef10cc73ca1..9e81f4552670 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -430,7 +430,7 @@ DECLARE_OOXMLEXPORT_TEST(testHyphenationAuto, "hyphenation.odt") assertXPath(pXmlStyles, "/w:styles/w:docDefaults/w:pPrDefault/w:pPr/w:suppressAutoHyphens", "val", "true"); } -DECLARE_OOXMLIMPORT_TEST(testContSectBreakHeaderFooter, "cont-sect-break-header-footer.docx") +DECLARE_OOXMLEXPORT_TEST(testContSectBreakHeaderFooter, "cont-sect-break-header-footer.docx") { // Load a document with a continuous section break on page 2. CPPUNIT_ASSERT_EQUAL(OUString("First page header, section 1"), @@ -454,6 +454,11 @@ DECLARE_OOXMLIMPORT_TEST(testContSectBreakHeaderFooter, "cont-sect-break-header- // the own footer text. CPPUNIT_ASSERT_EQUAL(OUString("Footer, section 3"), parseDump("/root/page[3]/footer/txt/text()")); + + // Without the export fix in place, the import-export-import test would have failed with: + // - Expected: Header, section 2 + // - Actual : First page header, section 2 + // i.e. both the header and the footer on page 3 was wrong. } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx index d04cfeb8e6f8..2908f78fef0e 100644 --- a/sw/source/filter/ww8/wrtw8sty.cxx +++ b/sw/source/filter/ww8/wrtw8sty.cxx @@ -34,6 +34,7 @@ #include <editeng/frmdiritem.hxx> #include <editeng/lrspitem.hxx> #include <editeng/ulspitem.hxx> +#include <editeng/fhgtitem.hxx> #include <doc.hxx> #include "wrtww8.hxx" #include <docary.hxx> @@ -60,6 +61,7 @@ #include <redline.hxx> #include <msfilter.hxx> #include <swmodule.hxx> +#include <charatr.hxx> #include "sprmids.hxx" @@ -1518,6 +1520,76 @@ void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, pSepx->OutHeaderFooter( *this, false, rFirstPageFormat, nCpPos, nHeadFootFlags, WW8_FOOTER_FIRST, nBreakCode ); } +namespace +{ +/** + * Find a node near the section start that has a page break, it may have a follow header/footer for + * us. + */ +bool WriteNextStyleHeaderFooter(sal_uInt8 nBreakCode, sal_uInt8 nHeadFootFlags, + const SwPageDesc* pPd, const WW8_SepInfo& rSepInfo) +{ + if (nBreakCode != 0) + { + // Not a continuous section break. + return false; + } + + if (nHeadFootFlags != 0) + { + // Would write some header/footer anyway. + return false; + } + + if (!pPd->GetFollow()) + { + // Page style has no follow style. + return false; + } + + // We start a continuous section break without headers/footers. Possibly the importer had + // headers/footers for this section break and put them to the closest page break's page style's + // next page style. See "find a node in the section that has a page break" in writerfilter/. + // Try the last-in-practice paragraph of the previous section. + const SwSectionFormat* pSection = rSepInfo.pSectionFormat; + if (pSection == reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1))) + { + return false; + } + + const SwNodeIndex* pSectionStart = pSection->GetContent().GetContentIdx(); + if (!pSectionStart) + { + return false; + } + + SwPaM aPaM(*pSectionStart); + aPaM.Move(fnMoveBackward); + if (!aPaM.GetNode().IsTextNode()) + { + return false; + } + + SwTextNode* pTextNode = aPaM.GetNode().GetTextNode(); + const SwAttrSet* pParaProps = &pTextNode->GetSwAttrSet(); + sal_uInt32 nCharHeight = pParaProps->GetSize().GetHeight(); + if (nCharHeight > 20) + { + return false; + } + + aPaM.Move(fnMoveBackward); + if (!aPaM.GetNode().IsTextNode()) + { + return false; + } + + pTextNode = aPaM.GetNode().GetTextNode(); + pParaProps = &pTextNode->GetSwAttrSet(); + return pParaProps->HasItem(RES_PAGEDESC); +} +} + void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAttrDesc* pA ) { const SwPageDesc* pPd = rSepInfo.pPageDesc; @@ -1769,6 +1841,14 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt const SwTextNode *pOldPageRoot = GetHdFtPageRoot(); SetHdFtPageRoot( rSepInfo.pPDNd ? rSepInfo.pPDNd->GetTextNode() : nullptr ); + if (GetExportFormat() == ExportFormat::DOCX + && WriteNextStyleHeaderFooter(nBreakCode, nHeadFootFlags, pPd, rSepInfo)) + { + pPdFormat = &pPd->GetFollow()->GetMaster(); + MSWordSections::SetHeaderFlag(nHeadFootFlags, *pPdFormat, WW8_HEADER_ODD); + MSWordSections::SetFooterFlag(nHeadFootFlags, *pPdFormat, WW8_FOOTER_ODD); + } + WriteHeadersFooters( nHeadFootFlags, *pPdFormat, *pPdLeftFormat, *pPdFirstPgFormat, nBreakCode ); SetHdFtPageRoot( pOldPageRoot ); |