Kaydet (Commit) be6534dc authored tarafından Justin Luth's avatar Justin Luth Kaydeden (comit) Miklos Vajna

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/38634Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarJustin Luth <justin_luth@sil.org>
Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
üst 91f4d01a
......@@ -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 \
......
......@@ -13,6 +13,7 @@ define sw_ooxmlexport_libraries
comphelper \
cppu \
cppuhelper \
editeng \
sal \
sfx \
sw \
......
......@@ -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/>.
......
......@@ -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
......
......@@ -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() )
{
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment