diff options
author | Justin Luth <justin_luth@sil.org> | 2017-06-10 12:12:50 +0300 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-08-17 14:13:11 +0200 |
commit | be6534dc47568dbf57057dec73ef260b63e198c0 (patch) | |
tree | 7be4dfe2624528329c2a93bb9599dc452d7afba8 | |
parent | 91f4d01af4772fe5156e59ea4f4ef771de657a57 (diff) |
tdf#55427 ww8export: treat document-end-footnotes as endnotes
MSWord has two choices for footnotes - at page-end or page-bottom.
LO has different choices for footnotes - at document-end or page-bottom.
Since document-end footnotes act like endnotes,
convert those footnotes into endnotes during DOC/DOCX/RTF export.
No matter what happens in this situation, some compromises have to be
made. The main compromise now is that the anchor numbering for endnotes
defaults to i,ii,iii while footnotes are 1,2,3. The conversion
obviously will switch to endnote style. This is user adjustable of course
and will be retained on following round-trips. Also the (footnote)
paragraph style is retained, but future endnotes will use a potentially
different endnote paragraph style.
Remedying those perceived deficiency is left as an exercise
for the motivated reader, who of course will
take into account the possibility of both endnotes and
chapter-end footnotes existing in the same document...
The unit tests' primary purpose is to ensure that footnotes following
down the endnote export path don't cause LO to crash.
Change-Id: I219d499df7981a14f824a664b15051ad10ff6642
Reviewed-on: https://gerrit.libreoffice.org/38634
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | sw/CppunitTest_sw_ww8export2.mk | 1 | ||||
-rw-r--r-- | sw/ooxmlexport_setup.mk | 1 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf55427_footnote2endnote.odt | bin | 0 -> 13291 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 57 | ||||
-rw-r--r-- | sw/qa/extras/ww8export/data/tdf55427_footnote2endnote.odt | bin | 0 -> 13291 bytes | |||
-rw-r--r-- | sw/qa/extras/ww8export/ww8export2.cxx | 58 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 8 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfattributeoutput.cxx | 3 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8atr.cxx | 2 |
9 files changed, 125 insertions, 5 deletions
diff --git a/sw/CppunitTest_sw_ww8export2.mk b/sw/CppunitTest_sw_ww8export2.mk index f5e37733c3ed..20f7df957a61 100644 --- a/sw/CppunitTest_sw_ww8export2.mk +++ b/sw/CppunitTest_sw_ww8export2.mk @@ -19,6 +19,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_ww8export2, \ comphelper \ cppu \ cppuhelper \ + editeng \ $(if $(filter WNT-TRUE,$(OS)-$(DISABLE_ATL)),,emboleobj) \ sal \ sfx \ diff --git a/sw/ooxmlexport_setup.mk b/sw/ooxmlexport_setup.mk index b421d0e1ad4f..927873992c28 100644 --- a/sw/ooxmlexport_setup.mk +++ b/sw/ooxmlexport_setup.mk @@ -13,6 +13,7 @@ define sw_ooxmlexport_libraries comphelper \ cppu \ cppuhelper \ + editeng \ sal \ sfx \ sw \ diff --git a/sw/qa/extras/ooxmlexport/data/tdf55427_footnote2endnote.odt b/sw/qa/extras/ooxmlexport/data/tdf55427_footnote2endnote.odt Binary files differnew file mode 100644 index 000000000000..7f77f6d39e02 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf55427_footnote2endnote.odt diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index 6c7da90e2d96..caecccfa0681 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -28,6 +28,7 @@ #include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/style/LineSpacingMode.hpp> +#include <ftninfo.hxx> #include <sfx2/docfile.hxx> #include <sfx2/docfilt.hxx> @@ -583,6 +584,62 @@ DECLARE_OOXMLEXPORT_TEST(testTdf82173_endnoteStyle, "tdf82173_endnoteStyle.docx" CPPUNIT_ASSERT_EQUAL( sal_Int32(0xFF00FF), getProperty< sal_Int32 >(xPageStyle, "CharColor") ); } +DECLARE_OOXMLEXPORT_TEST(testTdf55427_footnote2endnote, "tdf55427_footnote2endnote.odt") +{ + uno::Reference<beans::XPropertySet> xPageStyle(getStyles("ParagraphStyles")->getByName("Footnote"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Footnote style is rose color", sal_Int32(0xFF007F), getProperty< sal_Int32 >(xPageStyle, "CharColor") ); + xPageStyle.set(getStyles("ParagraphStyles")->getByName("Endnote"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Endnote style is cyan3 color", sal_Int32(0x2BD0D2), getProperty< sal_Int32 >(xPageStyle, "CharColor") ); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + // The footnote numbering type of ARABIC will not transfer over when those footnotes are converted to endnotes. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Footnote numbering type", SVX_NUM_ARABIC, pDoc->GetFootnoteInfo().aFormat.GetNumberingType() ); + // The original document has a real endnote using ROMAN_LOWER numbering, so that setting MUST remain unchanged. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Endnote numbering type", SVX_NUM_ROMAN_LOWER, pDoc->GetEndNoteInfo().aFormat.GetNumberingType() ); + + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes(xFootnotesSupplier->getFootnotes(), uno::UNO_QUERY); + + uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xEndnotes(xEndnotesSupplier->getEndnotes(), uno::UNO_QUERY); + uno::Reference<text::XFootnote> xEndnote; + xEndnotes->getByIndex(0) >>= xEndnote; + uno::Reference<text::XText> xEndnoteText; + xEndnotes->getByIndex(0) >>= xEndnoteText; + + // ODT footnote-at-document-end's closest DOCX match is an endnote, so the two imports will not exactly match by design. + if (!mbExported) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote count", sal_Int32(5), xFootnotes->getCount() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote count", sal_Int32(1), xEndnotes->getCount() ); + + uno::Reference<text::XFootnote> xFootnote; + xFootnotes->getByIndex(0) >>= xFootnote; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote's number", OUString("1"), xFootnote->getAnchor()->getString() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's number", OUString("i"), xEndnote->getAnchor()->getString() ); + + uno::Reference<text::XText> xFootnoteText; + xFootnotes->getByIndex(0) >>= xFootnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote style", OUString("Footnote"), getProperty<OUString>(getParagraphOfText(1, xFootnoteText), "ParaStyleName") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", OUString("Endnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + } + else + { + // These asserted items are major differences in the conversion from footnote to endnote, NOT necessary conditions for a proper functioning document. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "At-Document-End footnotes were converted into endnotes", sal_Int32(0), xFootnotes->getCount() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "At-Document-End footnotes became endnotes", sal_Int32(6), xEndnotes->getCount() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "converted footnote's number", OUString("i"), xEndnote->getAnchor()->getString() ); + xEndnotes->getByIndex(4) >>= xEndnote; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's new number", OUString("v"), xEndnote->getAnchor()->getString() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "retained footnote style", OUString("Footnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + xEndnotes->getByIndex(4) >>= xEndnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", OUString("Endnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + } +} + DECLARE_OOXMLEXPORT_TEST(testTdf104162, "tdf104162.docx") { // This crashed: the comment field contained a table with a <w:hideMark/>. diff --git a/sw/qa/extras/ww8export/data/tdf55427_footnote2endnote.odt b/sw/qa/extras/ww8export/data/tdf55427_footnote2endnote.odt Binary files differnew file mode 100644 index 000000000000..7f77f6d39e02 --- /dev/null +++ b/sw/qa/extras/ww8export/data/tdf55427_footnote2endnote.odt diff --git a/sw/qa/extras/ww8export/ww8export2.cxx b/sw/qa/extras/ww8export/ww8export2.cxx index 7ace54f52f61..cb6155cf444a 100644 --- a/sw/qa/extras/ww8export/ww8export2.cxx +++ b/sw/qa/extras/ww8export/ww8export2.cxx @@ -16,6 +16,8 @@ #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XTextTablesSupplier.hpp> #include <com/sun/star/text/XFootnote.hpp> + +#include <ftninfo.hxx> #include <pagedesc.hxx> class Test : public SwModelTestBase @@ -50,6 +52,62 @@ DECLARE_WW8EXPORT_TEST(testTdf49102_mergedCellNumbering, "tdf49102_mergedCellNum CPPUNIT_ASSERT_EQUAL( OUString("2."), parseDump("/root/page/body/tab/row[4]/cell/txt/Special[@nType='POR_NUMBER']", "rText") ); } +DECLARE_WW8EXPORT_TEST(testTdf55427_footnote2endnote, "tdf55427_footnote2endnote.odt") +{ + uno::Reference<beans::XPropertySet> xPageStyle(getStyles("ParagraphStyles")->getByName("Footnote"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Footnote style is rose color", sal_Int32(0xFF007F), getProperty< sal_Int32 >(xPageStyle, "CharColor") ); + xPageStyle.set(getStyles("ParagraphStyles")->getByName("Endnote"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Endnote style is cyan3 color", sal_Int32(0x2BD0D2), getProperty< sal_Int32 >(xPageStyle, "CharColor") ); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + // The footnote numbering type of ARABIC will not transfer over when those footnotes are converted to endnotes. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Footnote numbering type", SVX_NUM_ARABIC, pDoc->GetFootnoteInfo().aFormat.GetNumberingType() ); + // The original document has a real endnote using ROMAN_LOWER numbering, so that setting MUST remain unchanged. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Endnote numbering type", SVX_NUM_ROMAN_LOWER, pDoc->GetEndNoteInfo().aFormat.GetNumberingType() ); + + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes(xFootnotesSupplier->getFootnotes(), uno::UNO_QUERY); + + uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xEndnotes(xEndnotesSupplier->getEndnotes(), uno::UNO_QUERY); + uno::Reference<text::XFootnote> xEndnote; + xEndnotes->getByIndex(0) >>= xEndnote; + uno::Reference<text::XText> xEndnoteText; + xEndnotes->getByIndex(0) >>= xEndnoteText; + + // ODT footnote-at-document-end's closest DOC match is an endnote, so the two imports will not exactly match by design. + if (!mbExported) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote count", sal_Int32(5), xFootnotes->getCount() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote count", sal_Int32(1), xEndnotes->getCount() ); + + uno::Reference<text::XFootnote> xFootnote; + xFootnotes->getByIndex(0) >>= xFootnote; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote's number", OUString("1"), xFootnote->getAnchor()->getString() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's number", OUString("i"), xEndnote->getAnchor()->getString() ); + + uno::Reference<text::XText> xFootnoteText; + xFootnotes->getByIndex(0) >>= xFootnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote style", OUString("Footnote"), getProperty<OUString>(getParagraphOfText(1, xFootnoteText), "ParaStyleName") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", OUString("Endnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + } + else + { + // These asserted items are major differences in the conversion from footnote to endnote, NOT necessary conditions for a proper functioning document. + CPPUNIT_ASSERT_EQUAL_MESSAGE( "At-Document-End footnotes were converted into endnotes", sal_Int32(0), xFootnotes->getCount() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "At-Document-End footnotes became endnotes", sal_Int32(6), xEndnotes->getCount() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "converted footnote's number", OUString("i"), xEndnote->getAnchor()->getString() ); + xEndnotes->getByIndex(4) >>= xEndnote; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's new number", OUString("v"), xEndnote->getAnchor()->getString() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "retained footnote style", OUString("Footnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + xEndnotes->getByIndex(4) >>= xEndnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", OUString("Endnote"), getProperty<OUString>(getParagraphOfText(1, xEndnoteText), "ParaStyleName") ); + } +} + DECLARE_WW8EXPORT_TEST(testTdf107931_KERN_DocEnabled_disabledDefStyle, "testTdf107931_KERN_DocEnabled_disabledDefStyle.doc") { // Paragraph 3: the default style has kerning disabled diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 5d7490223eda..93cd4daba349 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -6917,7 +6917,7 @@ void DocxAttributeOutput::TextFootnote_Impl( const SwFormatFootnote& rFootnote ) // remember the footnote/endnote to // 1) write the footnoteReference/endnoteReference in EndRunProperties() // 2) be able to dump them all to footnotes.xml/endnotes.xml - if ( !rFootnote.IsEndNote() ) + if ( !rFootnote.IsEndNote() && m_rExport.m_pDoc->GetFootnoteInfo().ePos != FTNPOS_CHAPTER ) m_pFootnotesList->add( rFootnote ); else m_pEndnotesList->add( rFootnote ); @@ -6927,16 +6927,18 @@ void DocxAttributeOutput::FootnoteEndnoteReference() { sal_Int32 nId; const SwFormatFootnote *pFootnote = m_pFootnotesList->getCurrent( nId ); + sal_Int32 nToken = XML_footnoteReference; // both cannot be set at the same time - if they are, it's a bug if ( !pFootnote ) + { pFootnote = m_pEndnotesList->getCurrent( nId ); + nToken = XML_endnoteReference; + } if ( !pFootnote ) return; - sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference; - // write it if ( pFootnote->GetNumStr().isEmpty() ) { diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 90ac57e73142..96000d7c0c65 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -65,6 +65,7 @@ #include <fmtline.hxx> #include <breakit.hxx> #include <fmtanchr.hxx> +#include <ftninfo.hxx> #include <htmltbl.hxx> #include <ndgrf.hxx> #include <pagedesc.hxx> @@ -2658,7 +2659,7 @@ void RtfAttributeOutput::TextFootnote_Impl(const SwFormatFootnote& rFootnote) m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_SUPER " "); WriteTextFootnoteNumStr(rFootnote); m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE); - if (rFootnote.IsEndNote()) + if ( rFootnote.IsEndNote() || m_rExport.m_pDoc->GetFootnoteInfo().ePos == FTNPOS_CHAPTER ) m_aRun->append(OOO_STRING_SVTOOLS_RTF_FTNALT); m_aRun->append(' '); WriteTextFootnoteNumStr(rFootnote); diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index f16506f2f8d1..bf689fcd10df 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -3132,7 +3132,7 @@ void AttributeOutputBase::TextFootnote( const SwFormatFootnote& rFootnote ) void WW8AttributeOutput::TextFootnote_Impl( const SwFormatFootnote& rFootnote ) { WW8_WrPlcFootnoteEdn* pFootnoteEnd; - if ( rFootnote.IsEndNote() ) + if ( rFootnote.IsEndNote() || GetExport().m_pDoc->GetFootnoteInfo().ePos == FTNPOS_CHAPTER ) pFootnoteEnd = m_rWW8Export.pEdn; else pFootnoteEnd = m_rWW8Export.pFootnote; |