sw/qa/extras/ooxmlexport/data/tdf69635.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 5 + sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 56 +++++++++++++++ sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 22 +++--- sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 6 - sw/qa/extras/ooxmlexport/ooxmlexport6.cxx | 2 sw/qa/extras/ooxmlexport/ooxmlexport7.cxx | 12 +-- sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 2 sw/source/filter/ww8/docxexport.cxx | 9 +- sw/source/filter/ww8/docxexport.hxx | 3 sw/source/filter/ww8/rtfexport.cxx | 10 +- sw/source/filter/ww8/rtfexport.hxx | 6 + sw/source/filter/ww8/wrtw8sty.cxx | 95 +++++++++++++++++++++++--- sw/source/filter/ww8/wrtww8.hxx | 8 +- 14 files changed, 189 insertions(+), 47 deletions(-)
New commits: commit d9caf9814696c747e4b0277bc7377ba09aead334 Author: Daniel Arato (NISZ) <arato.dan...@nisz.hu> AuthorDate: Fri Feb 5 12:07:48 2021 +0100 Commit: Tünde Tóth <toth.tu...@nisz.hu> CommitDate: Thu Oct 21 11:42:19 2021 +0200 tdf#69635 DOCX: export hidden (shared) headers/footers Exporting to .docx used to lose all header and footer content that was not visible in the document at the moment of saving. This commit forces the DocxExport class to output all headers and footers even when the "Same content on left and right pages" option is turned on. Change-Id: I6a52f216f1e1b386d887ec614198766670b5bce3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113158 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> (cherry picked from commit 88e6a1bfeac86e0c89d2ff08c908c2b5ae061177) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123970 Tested-by: Tünde Tóth <toth.tu...@nisz.hu> Reviewed-by: Tünde Tóth <toth.tu...@nisz.hu> diff --git a/sw/qa/extras/ooxmlexport/data/tdf69635.docx b/sw/qa/extras/ooxmlexport/data/tdf69635.docx new file mode 100644 index 000000000000..94cced4d2ae4 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf69635.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index a740b6295999..2ee47d611adf 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -671,7 +671,12 @@ DECLARE_OOXMLEXPORT_TEST(testTdf130167_spilloverHeaderShape, "testTdf130167_spil uno::Reference<container::XIndexAccess> xNameAccess( xTextGraphicObjectsSupplier->getGraphicObjects(), uno::UNO_QUERY); // graphics from discarded headers were being added to the text body. Reduced from 5 to 2 shapes overall. +<<<<<<< HEAD (7b6bf0 tdf#142128 sw: set author-color strikethrough for AS_CHAR im) CPPUNIT_ASSERT(xNameAccess->getCount() < 4); +======= + // CPPUNIT_ASSERT(xNameAccess->getCount() <= 4); -> What about hidden headers? + CPPUNIT_ASSERT_LESS(sal_Int32(9), xNameAccess->getCount()); +>>>>>>> CHANGE (88e6a1 tdf#69635 DOCX: export hidden (shared) headers/footers) } DECLARE_OOXMLEXPORT_TEST(testTdf124986, "tdf124986.docx") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx index 7e890145210d..a20c8bfb9fe3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx @@ -50,6 +50,62 @@ DECLARE_OOXMLEXPORT_TEST(testTdf138892_noNumbering, "tdf138892_noNumbering.docx" CPPUNIT_ASSERT_MESSAGE("Para3: <blank line>", getProperty<OUString>(getParagraph(3), "NumberingStyleName").isEmpty()); } +DECLARE_OOXMLEXPORT_TEST(testTdf141231_arabicHebrewNumbering, "tdf141231_arabicHebrewNumbering.docx") +{ + // The page's numbering type: instead of Hebrew, this was default style::NumberingType::ARABIC (4). + auto nActual = getProperty<sal_Int16>(getStyles("PageStyles")->getByName("Standard"), "NumberingType"); + CPPUNIT_ASSERT_EQUAL(style::NumberingType::NUMBER_HEBREW, nActual); + + // The footnote numbering type: instead of arabicAbjad, this was the default style::NumberingType::ARABIC. + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xFootnoteSettings = xFootnotesSupplier->getFootnoteSettings(); + nActual = getProperty<sal_Int16>(xFootnotesSupplier->getFootnoteSettings(), "NumberingType"); + CPPUNIT_ASSERT_EQUAL(style::NumberingType::CHARS_ARABIC_ABJAD, nActual); +} + +DECLARE_OOXMLEXPORT_TEST(testGutterLeft, "gutter-left.docx") +{ + uno::Reference<beans::XPropertySet> xPageStyle; + getStyles("PageStyles")->getByName("Standard") >>= xPageStyle; + sal_Int32 nGutterMargin{}; + xPageStyle->getPropertyValue("GutterMargin") >>= nGutterMargin; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1270 + // - Actual : 0 + // i.e. gutter margin was lost. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1270), nGutterMargin); +} + +CPPUNIT_TEST_FIXTURE(Test, testGutterTop) +{ + load(mpTestDocumentPath, "gutter-top.docx"); + save("Office Open XML Text", maTempFile); + mbExported = true; + xmlDocUniquePtr pXmlSettings = parseExport("word/settings.xml"); + CPPUNIT_ASSERT(pXmlSettings); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. <w:gutterAtTop> was lost. + assertXPath(pXmlSettings, "/w:settings/w:gutterAtTop", 1); +} + +DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf69635, "tdf69635.docx") +{ + xmlDocUniquePtr pXmlHeader1 = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlSettings = parseExport("word/settings.xml"); + CPPUNIT_ASSERT(pXmlHeader1); + CPPUNIT_ASSERT(pXmlSettings); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: "left" + // - Actual : "right" + assertXPathContent(pXmlHeader1, "/w:hdr/w:p/w:r/w:t", "left"); + + // Make sure "left" appears as a hidden header + assertXPath(pXmlSettings, "/w:settings/w:evenAndOddHeaders", 0); +} + DECLARE_OOXMLEXPORT_TEST(testTdf140668, "tdf140668.docx") { // Don't crash when document is opened diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index 49cc931b1b27..dcf7062eca36 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -399,10 +399,10 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testChartInFooter, "chart-in-footer.docx") // fdo#73872: document contains chart in footer. // The problem was that footer1.xml.rels files for footer1.xml // files were missing from docx file after roundtrip. - xmlDocUniquePtr pXmlDoc = parseExport("word/_rels/footer1.xml.rels"); + xmlDocUniquePtr pXmlDoc = parseExport("word/_rels/footer2.xml.rels"); - // Check footer1.xml.rels contains in doc after roundtrip. - // Check Id = rId1 in footer1.xml.rels + // Check footer2.xml.rels contains in doc after roundtrip. + // Check Id = rId1 in footer2.xml.rels assertXPath(pXmlDoc,"/rels:Relationships/rels:Relationship","Id","rId1"); assertXPath(pXmlDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", @@ -416,12 +416,12 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testChartInFooter, "chart-in-footer.docx") "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"); // check the content too - xmlDocUniquePtr pXmlDocFooter1 = parseExport("word/footer1.xml"); - assertXPath(pXmlDocFooter1, + xmlDocUniquePtr pXmlDocFooter2 = parseExport("word/footer2.xml"); + assertXPath(pXmlDocFooter2, "/w:ftr/w:p[1]/w:r/w:drawing/wp:inline/a:graphic/a:graphicData", "uri", "http://schemas.openxmlformats.org/drawingml/2006/chart"); - assertXPath(pXmlDocFooter1, + assertXPath(pXmlDocFooter2, "/w:ftr/w:p[1]/w:r/w:drawing/wp:inline/a:graphic/a:graphicData/c:chart", "id", "rId1"); @@ -837,7 +837,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testOLEObjectinHeader, "2129393649.docx") // Problem was relationship entry for oleobject from header was // exported into document.xml.rels file because of this rels file // for headers were missing from document/word/rels. - xmlDocUniquePtr pXmlDoc = parseExport("word/_rels/header1.xml.rels"); + xmlDocUniquePtr pXmlDoc = parseExport("word/_rels/header2.xml.rels"); assertXPath(pXmlDoc,"/rels:Relationships/rels:Relationship[1]","Id","rId1"); @@ -850,12 +850,12 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testOLEObjectinHeader, "2129393649.docx") "application/vnd.openxmlformats-officedocument.oleObject"); // check the content too - xmlDocUniquePtr pXmlDocHeader1 = parseExport("word/header1.xml"); - assertXPath(pXmlDocHeader1, + xmlDocUniquePtr pXmlDocHeader2 = parseExport("word/header2.xml"); + assertXPath(pXmlDocHeader2, "/w:hdr/w:tbl/w:tr[1]/w:tc[2]/w:p[1]/w:r/w:object/o:OLEObject", "ProgID", "Word.Picture.8"); - xmlDocUniquePtr pXmlDocHeader2 = parseExport("word/header2.xml"); + xmlDocUniquePtr pXmlDocHeader3 = parseExport("word/header3.xml"); assertXPath(pXmlDocHeader2, "/w:hdr/w:tbl/w:tr[1]/w:tc[2]/w:p[1]/w:r/w:object/o:OLEObject", "ProgID", @@ -1031,7 +1031,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103001, "tdf103001.docx") uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); // This failed: header reused the RelId of the body text, even if RelIds // are local to their stream. - CPPUNIT_ASSERT(xNameAccess->hasByName("word/_rels/header1.xml.rels")); + CPPUNIT_ASSERT(xNameAccess->hasByName("word/_rels/header2.xml.rels")); } DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf92521, "tdf92521.odt") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 404db9c59ef9..7021aa2c9c65 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -1031,7 +1031,7 @@ DECLARE_OOXMLEXPORT_TEST(test2colHeader, "2col-header.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testfdo83048, "fdo83048.docx") { // Issue was wrong SDT properties were getting exported for Date SDT - xmlDocUniquePtr pXmlDoc = parseExport("word/footer1.xml"); + xmlDocUniquePtr pXmlDoc = parseExport("word/footer2.xml"); // Make sure Date is inside SDT tag. // This will happen only if right SDT properties are exported. @@ -1052,7 +1052,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testSdt2Run, "sdt-2-run.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testFD083057, "fdo83057.docx") { - xmlDocUniquePtr pXmlDoc = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlDoc = parseExport("word/header2.xml"); // A fly frame was attached to a para which started with a hint (run) containing an SDT. // This SDT was handled while exporting the FLYFRAME and also the text of the run. @@ -1341,7 +1341,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf112287, "tdf112287.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testZOrderInHeader, "tdf120760_ZOrderInHeader.docx") { // tdf#120760 Check that the Z-Order of the background is smaller than the front shape's. - xmlDocUniquePtr pXml = parseExport("word/header1.xml"); + xmlDocUniquePtr pXml = parseExport("word/header2.xml"); // Get the Z-Order of the background image and of the shape in front of it. sal_Int32 nBackground = getXPath(pXml, "/w:hdr/w:p[1]/w:r[1]/w:drawing/wp:anchor", "relativeHeight").toInt32(); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx index cc63f77e5c56..21a4d11a9dde 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx @@ -852,7 +852,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testShapeThemePreservation, "shape-theme-pre DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testFDO73546, "FDO73546.docx") { - xmlDocUniquePtr pXmlDoc = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlDoc = parseExport("word/header2.xml"); assertXPath(pXmlDoc, "/w:hdr/w:p[1]/w:r[3]/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor", "distL","0"); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx index 2e8c2c45aa42..243e2371476f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx @@ -102,12 +102,12 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTextWatermark, "textWatermark.docx") //The problem was that the watermark ID was not preserved, //and Word uses the object ID to identify if it is a watermark. //It has to have the 'PowerPlusWaterMarkObject' string in it - xmlDocUniquePtr pXmlHeader1 = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlHeader2 = parseExport("word/header2.xml"); - assertXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","id","PowerPlusWaterMarkObject93701316"); + assertXPath(pXmlHeader2, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","id","PowerPlusWaterMarkObject93701316"); //The second problem was that Word uses also "o:spid" - const OUString& sSpid = getXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","spid"); + const OUString& sSpid = getXPath(pXmlHeader2, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","spid"); CPPUNIT_ASSERT(!sSpid.isEmpty()); } @@ -117,10 +117,10 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testPictureWatermark, "pictureWatermark.docx //and Word uses the object ID to identify if it is a watermark. //It has to have the 'WordPictureWaterMarkObject' string in it - xmlDocUniquePtr pXmlHeader1 = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlHeader2 = parseExport("word/header2.xml"); // Check the watermark ID - assertXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Fallback[1]/w:pict[1]/v:shape[1]","id","WordPictureWatermark11962361"); + assertXPath(pXmlHeader2, "/w:hdr[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Fallback[1]/w:pict[1]/v:shape[1]","id","WordPictureWatermark11962361"); } @@ -882,7 +882,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testfdo80895, "fdo80895.docx") // resultant shape was with <a:noFill/> prop in <wps:spPr> hence was not visible. // Checking there is a shape in header without <a:noFill/> element. - xmlDocUniquePtr pXmlDoc = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlDoc = parseExport("word/header2.xml"); assertXPath(pXmlDoc, "/w:hdr/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:noFill",0); assertXPath(pXmlDoc, "/w:hdr/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:ln/a:noFill",0); diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index 40f93ab67664..f93d5b924ea4 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -536,7 +536,7 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testfdo82492, "fdo82492.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testSdtHeader, "sdt-header.docx") { // Problem was that w:sdt elements in headers were lost on import. - xmlDocUniquePtr pXmlDoc = parseExport("word/header1.xml"); + xmlDocUniquePtr pXmlDoc = parseExport("word/header2.xml"); // This was 0, w:sdt (and then w:date) was missing. assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:date", 1); } diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 3d09820e545e..86485359b60e 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -247,12 +247,13 @@ bool DocxExport::DisallowInheritingOutlineNumbering( const SwFormat& rFormat ) } void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, - const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode ) + const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat, + sal_uInt8 nBreakCode, bool bEvenAndOddHeaders ) { m_nHeadersFootersInSection = 1; // document setting indicating the requirement of EVEN and ODD for both headers and footers - if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN )) + if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN ) && bEvenAndOddHeaders ) m_aSettings.evenAndOddHeaders = true; // Turn ON flag for 'Writing Headers \ Footers' @@ -260,7 +261,7 @@ void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, // headers if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN ) - WriteHeaderFooter( &rLeftFormat, true, "even" ); + WriteHeaderFooter( &rLeftHeaderFormat, true, "even" ); else if ( m_aSettings.evenAndOddHeaders ) { if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD ) @@ -284,7 +285,7 @@ void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, // footers if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN ) - WriteHeaderFooter( &rLeftFormat, false, "even" ); + WriteHeaderFooter( &rLeftFooterFormat, false, "even" ); else if ( m_aSettings.evenAndOddHeaders ) { if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD ) diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index f800b5018e66..e87cb3a3788d 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -161,7 +161,8 @@ public: /// Output the actual headers and footers. virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags, - const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode ) override; + const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat, + sal_uInt8 nBreakCode, bool bEvenAndOddHeaders ) override; /// Write the field virtual void OutputField( const SwField* pField, ww::eField eFieldType, diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index 7192308f0d6e..858b3a3e2884 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -286,12 +286,14 @@ void RtfExport::WriteRevTab() } void RtfExport::WriteHeadersFooters(sal_uInt8 nHeadFootFlags, const SwFrameFormat& rFormat, - const SwFrameFormat& rLeftFormat, - const SwFrameFormat& rFirstPageFormat, sal_uInt8 /*nBreakCode*/) + const SwFrameFormat& rLeftHeaderFormat, + const SwFrameFormat& rLeftFooterFormat, + const SwFrameFormat& rFirstPageFormat, sal_uInt8 /*nBreakCode*/, + bool /*bEvenAndOddHeaders*/) { // headers if (nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN) - WriteHeaderFooter(rLeftFormat, true, OOO_STRING_SVTOOLS_RTF_HEADERL); + WriteHeaderFooter(rLeftHeaderFormat, true, OOO_STRING_SVTOOLS_RTF_HEADERL); if (nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD) WriteHeaderFooter(rFormat, true, OOO_STRING_SVTOOLS_RTF_HEADER); @@ -301,7 +303,7 @@ void RtfExport::WriteHeadersFooters(sal_uInt8 nHeadFootFlags, const SwFrameForma // footers if (nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN) - WriteHeaderFooter(rLeftFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTERL); + WriteHeaderFooter(rLeftFooterFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTERL); if (nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD) WriteHeaderFooter(rFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTER); diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx index 83b9a34a9e76..9b33c1304659 100644 --- a/sw/source/filter/ww8/rtfexport.hxx +++ b/sw/source/filter/ww8/rtfexport.hxx @@ -94,8 +94,10 @@ public: /// Output the actual headers and footers. void WriteHeadersFooters(sal_uInt8 nHeadFootFlags, const SwFrameFormat& rFormat, - const SwFrameFormat& rLeftFormat, - const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode) override; + const SwFrameFormat& rLeftHeaderFormat, + const SwFrameFormat& rLeftFooterFormat, + const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode, + bool bEvenAndOddHeaders) override; /// Write the field void OutputField(const SwField* pField, ww::eField eFieldType, const OUString& rFieldCmd, diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx index 282bd90efab9..08e54ab628cf 100644 --- a/sw/source/filter/ww8/wrtw8sty.cxx +++ b/sw/source/filter/ww8/wrtw8sty.cxx @@ -1501,7 +1501,7 @@ void WW8AttributeOutput::TextVerticalAdjustment( const drawing::TextVerticalAdju } void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, - const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode ) + const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode, bool /*bEvenAndOddHeaders*/ ) { sal_uLong nCpPos = Fc2Cp( Strm().Tell() ); @@ -1509,7 +1509,7 @@ void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, if ( !(nHeadFootFlags & WW8_HEADER_EVEN) && pDop->fFacingPages ) pSepx->OutHeaderFooter( *this, true, rFormat, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode ); else - pSepx->OutHeaderFooter( *this, true, rLeftFormat, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode ); + pSepx->OutHeaderFooter( *this, true, rLeftHeaderFormat, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode ); IncrementHdFtIndex(); pSepx->OutHeaderFooter( *this, true, rFormat, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode ); @@ -1517,7 +1517,7 @@ void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, if ( !(nHeadFootFlags & WW8_FOOTER_EVEN) && pDop->fFacingPages ) pSepx->OutHeaderFooter( *this, false, rFormat, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode ); else - pSepx->OutHeaderFooter( *this, false, rLeftFormat, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode ); + pSepx->OutHeaderFooter( *this, false, rLeftFooterFormat, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode ); IncrementHdFtIndex(); pSepx->OutHeaderFooter( *this, false, rFormat, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode ); @@ -1821,10 +1821,59 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt // Header or Footer sal_uInt8 nHeadFootFlags = 0; - - const SwFrameFormat* pPdLeftFormat = bLeftRightPgChain - ? &pPd->GetFollow()->GetFirstLeft() - : &pPd->GetLeft(); + // Should we output a w:evenAndOddHeaders tag or not? + // N.B.: despite its name this tag affects _both_ headers and footers! + bool bEvenAndOddHeaders = true; + bool bEvenAndOddFooters = true; + + const SwFrameFormat* pPdLeftHeaderFormat = nullptr; + const SwFrameFormat* pPdLeftFooterFormat = nullptr; + if (bLeftRightPgChain) + { + const SwFrameFormat* pHeaderFormat = pPd->GetStashedFrameFormat(true, true, true); + const SwFrameFormat* pFooterFormat = pPd->GetStashedFrameFormat(false, true, true); + if (pHeaderFormat) + { + pPdLeftHeaderFormat = pHeaderFormat; + bEvenAndOddHeaders = false; + } + else + { + pPdLeftHeaderFormat = &pPd->GetFollow()->GetFirstLeft(); + } + if (pFooterFormat) + { + pPdLeftFooterFormat = pFooterFormat; + bEvenAndOddFooters = false; + } + else + { + pPdLeftFooterFormat = &pPd->GetFollow()->GetFirstLeft(); + } + } + else + { + const SwFrameFormat* pHeaderFormat = pPd->GetStashedFrameFormat(true, true, false); + const SwFrameFormat* pFooterFormat = pPd->GetStashedFrameFormat(false, true, false); + if (pHeaderFormat) + { + pPdLeftHeaderFormat = pHeaderFormat; + bEvenAndOddHeaders = false; + } + else + { + pPdLeftHeaderFormat = &pPd->GetLeft(); + } + if (pFooterFormat) + { + pPdLeftFooterFormat = pFooterFormat; + bEvenAndOddFooters = false; + } + else + { + pPdLeftFooterFormat = &pPd->GetLeft(); + } + } // Ensure that headers are written if section is first paragraph if ( nBreakCode != 0 || bEnsureHeaderFooterWritten ) @@ -1835,14 +1884,40 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFirstPgFormat, WW8_HEADER_FIRST ); MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFirstPgFormat, WW8_FOOTER_FIRST ); } + else + { + if ( pPd->GetStashedFrameFormat(true, true, true) && pPdLeftHeaderFormat && pPdLeftHeaderFormat->GetHeader().GetHeaderFormat() ) + { + MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftHeaderFormat, WW8_HEADER_FIRST ); + } + if ( pPd->GetStashedFrameFormat(false, true, true) && pPdLeftFooterFormat && pPdLeftFooterFormat->GetFooter().GetFooterFormat() ) + { + MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFooterFormat, WW8_FOOTER_FIRST ); + } + } + MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFormat, WW8_HEADER_ODD ); MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFormat, WW8_FOOTER_ODD ); if ( !pPd->IsHeaderShared() || bLeftRightPgChain ) - MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftFormat, WW8_HEADER_EVEN ); + { + MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftHeaderFormat, WW8_HEADER_EVEN ); + } + else if ( pPd->IsHeaderShared() && pPd->GetStashedFrameFormat(true, true, false) && pPdLeftHeaderFormat && pPdLeftHeaderFormat->GetHeader().GetHeaderFormat() ) + { + MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftHeaderFormat, WW8_HEADER_EVEN ); + bEvenAndOddHeaders = false; + } if ( !pPd->IsFooterShared() || bLeftRightPgChain ) - MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFormat, WW8_FOOTER_EVEN ); + { + MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFooterFormat, WW8_FOOTER_EVEN ); + } + else if ( pPd->IsFooterShared() && pPd->GetStashedFrameFormat(false, true, false) && pPdLeftFooterFormat && pPdLeftFooterFormat->GetFooter().GetFooterFormat() ) + { + MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFooterFormat, WW8_FOOTER_EVEN ); + bEvenAndOddFooters = false; + } } // binary filters only @@ -1873,7 +1948,7 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt MSWordSections::SetFooterFlag(nHeadFootFlags, *pPdFormat, WW8_FOOTER_ODD); } - WriteHeadersFooters( nHeadFootFlags, *pPdFormat, *pPdLeftFormat, *pPdFirstPgFormat, nBreakCode ); + WriteHeadersFooters( nHeadFootFlags, *pPdFormat, *pPdLeftHeaderFormat, *pPdLeftFooterFormat, *pPdFirstPgFormat, nBreakCode, bEvenAndOddHeaders && bEvenAndOddFooters ); SetHdFtPageRoot( pOldPageRoot ); diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index b301638e0375..dcc3e85e0148 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -781,8 +781,8 @@ public: /// Output the actual headers and footers. virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags, - const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, - sal_uInt8 nBreakCode) = 0; + const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat, + sal_uInt8 nBreakCode, bool bEvenAndOddHeaders) = 0; /// Write the field virtual void OutputField( const SwField* pField, ww::eField eFieldType, @@ -1184,8 +1184,8 @@ public: /// Output the actual headers and footers. virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags, - const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, - sal_uInt8 nBreakCode) override; + const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat, + sal_uInt8 nBreakCode, bool bEvenAndOddHeaders) override; virtual ExportFormat GetExportFormat() const override { return ExportFormat::DOC; }