sw/CppunitTest_sw_ooxmlexport23.mk | 18 sw/CppunitTest_sw_ooxmlexport24.mk | 18 sw/Module_sw.mk | 2 sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 801 ---------------------- sw/qa/extras/ooxmlexport/ooxmlexport23.cxx | 897 +++++++++++++++++++++++++ sw/qa/extras/ooxmlexport/ooxmlexport24.cxx | 1031 +++++++++++++++++++++++++++++ sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 843 ----------------------- 7 files changed, 1969 insertions(+), 1641 deletions(-)
New commits: commit 27731badb6c91b1767114f7a4f36dd42c1316cd8 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Tue Apr 15 20:59:35 2025 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Apr 16 08:43:21 2025 +0200 CppunitTest_sw_ooxmlexport9: split in two it already has 99 tests Change-Id: I285ab56f70f3170e9ea547a8cae2d3754a1846ad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184242 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/CppunitTest_sw_ooxmlexport24.mk b/sw/CppunitTest_sw_ooxmlexport24.mk new file mode 100644 index 000000000000..879eaea31ae7 --- /dev/null +++ b/sw/CppunitTest_sw_ooxmlexport24.mk @@ -0,0 +1,18 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call sw_ooxmlexport_test,24)) + +$(eval $(call gb_CppunitTest_use_custom_headers,sw_ooxmlexport24,\ + officecfg/registry \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk index 19cb55b88e27..a6376dc0742b 100644 --- a/sw/Module_sw.mk +++ b/sw/Module_sw.mk @@ -101,6 +101,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\ CppunitTest_sw_ooxmlexport21 \ CppunitTest_sw_ooxmlexport22 \ CppunitTest_sw_ooxmlexport23 \ + CppunitTest_sw_ooxmlexport24 \ CppunitTest_sw_ooxmlexport_template \ CppunitTest_sw_ooxmlfieldexport \ CppunitTest_sw_ooxmllinks \ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport24.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport24.cxx new file mode 100644 index 000000000000..cacc795e54a5 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/ooxmlexport24.cxx @@ -0,0 +1,1031 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <swmodeltestbase.hxx> + +#include <config_fonts.h> + +#include <com/sun/star/text/XFootnote.hpp> +#include <com/sun/star/text/XPageCursor.hpp> +#include <com/sun/star/text/XTextColumns.hpp> +#include <com/sun/star/text/XTextViewCursorSupplier.hpp> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> +#include <com/sun/star/text/XEndnotesSupplier.hpp> +#include <com/sun/star/text/XFootnotesSupplier.hpp> +#include <com/sun/star/view/XFormLayerAccess.hpp> +#include <com/sun/star/view/XViewSettingsSupplier.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/text/XTextFieldsSupplier.hpp> +#include <com/sun/star/text/XTextFramesSupplier.hpp> +#include <com/sun/star/text/XTextSectionsSupplier.hpp> +#include <com/sun/star/text/XTextTablesSupplier.hpp> +#include <com/sun/star/style/LineSpacing.hpp> +#include <com/sun/star/style/LineSpacingMode.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/text/XTextTable.hpp> + +#include <tools/UnitConversion.hxx> + +#include <ftninfo.hxx> + +class Test : public SwModelTestBase +{ +public: + Test() + : SwModelTestBase(u"/sw/qa/extras/ooxmlexport/data/"_ustr, u"Office Open XML Text"_ustr) + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testTdf104115) +{ + loadAndSave("tdf104115.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + // This found 0 nodes: the custom geometry was not written for the Bezier + // curve -> Word refused to open the document. + assertXPath(pXmlDoc, "//a:custGeom", 1); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf103651, "tdf103651.docx") +{ + uno::Reference<beans::XPropertySet> xTextField + = getProperty<uno::Reference<beans::XPropertySet>>(getRun(getParagraph(1), 1), + u"TextField"_ustr); + OUString sContent; + xTextField->getPropertyValue(u"Content"_ustr) >>= sContent; + // Comment in the first paragraph should not have smiley ( 0xf04a ). + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), sContent.indexOf(u'\xf04a')); + + // this document has a w:kern setting in the DocDefault character properties. Ensure it applies. + CPPUNIT_ASSERT(getProperty<bool>(getRun(getParagraph(1), 1), u"CharAutoKerning"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf99227) +{ + loadAndSave("tdf99227.docx"); + // A drawing anchored as character to a footnote caused write past end of document.xml at export to docx. + // After that, importing after export failed with + // SAXParseException: '[word/document.xml line 2]: Extra content at the end of the document', Stream 'word / document.xml', + // and before commit ebf767eeb2a169ba533e1b2ffccf16f41d95df35, the drawing was silently lost. + xmlDocUniquePtr pXmlDoc = parseExport(u"word/footnotes.xml"_ustr); + + assertXPath(pXmlDoc, "//w:footnote/w:p/w:r/w:drawing", 1); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf37153, "tdf37153_considerWrapOnObjPos.docx") +{ + CPPUNIT_ASSERT_EQUAL(text::WrapTextMode_THROUGH, + getProperty<text::WrapTextMode>(getShape(1), u"Surround"_ustr)); + + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), + uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::VertOrientation::BOTTOM, + getProperty<sal_Int16>(xTable->getCellByName(u"A1"_ustr), u"VertOrient"_ustr)); + + //For MSO compatibility, the textbox should be at the top of the cell, not at the bottom - despite VertOrientation::BOTTOM + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + sal_Int32 nFlyTop + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt/anchored/fly/infos/bounds", "top") + .toInt32(); + CPPUNIT_ASSERT_MESSAGE("FlyTop should be 2865, not 5649", nFlyTop < sal_Int32(3000)); + sal_Int32 nTextTop + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[2]/txt[1]/infos/bounds", "top").toInt32(); + CPPUNIT_ASSERT_MESSAGE("TextTop should be 3856", nTextTop > 3000); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf112446_frameStyle, "tdf112446_frameStyle.docx") +{ + CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::NONE, + getProperty<sal_Int16>(getShape(1), u"HoriOrient"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf82173_footnoteStyle, "tdf82173_footnoteStyle.docx") +{ + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); + + uno::Reference<text::XText> xFootnoteText; + xFootnotes->getByIndex(0) >>= xFootnoteText; + // This was footnote text, which didn't match with newly created footnotes + CPPUNIT_ASSERT_EQUAL( + u"Footnote"_ustr, + getProperty<OUString>(getParagraphOfText(1, xFootnoteText), u"ParaStyleName"_ustr)); + + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"CharacterStyles"_ustr)->getByName(u"Footnote Symbol"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(58), + getProperty<sal_Int32>(xPageStyle, u"CharEscapementHeight"_ustr)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); + + xPageStyle.set(getStyles(u"CharacterStyles"_ustr)->getByName(u"Footnote anchor"_ustr), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(58), + getProperty<sal_Int32>(xPageStyle, u"CharEscapementHeight"_ustr)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); + + //tdf#118361 - in RTL locales, the footnote separator should still be left aligned. + uno::Any aPageStyle = getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Footnote separator LTR", sal_Int16(0), + getProperty<sal_Int16>(aPageStyle, u"FootnoteLineAdjust"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf82173_endnoteStyle, "tdf82173_endnoteStyle.docx") +{ + uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes(); + uno::Reference<text::XFootnote> xEndnote; + xEndnotes->getByIndex(0) >>= xEndnote; + // character properties were previously not assigned to the footnote/endnote in-text anchor. + CPPUNIT_ASSERT_EQUAL(24.0f, getProperty<float>(xEndnote->getAnchor(), u"CharHeight"_ustr)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, + getProperty<Color>(xEndnote->getAnchor(), u"CharColor"_ustr)); + + uno::Reference<text::XText> xEndnoteText; + xEndnotes->getByIndex(0) >>= xEndnoteText; + // This was Endnote Symbol + CPPUNIT_ASSERT_EQUAL(u"Endnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xEndnoteText), + u"ParaStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(Color(0x993300), getProperty<Color>(getParagraphOfText(1, xEndnoteText), + u"CharColor"_ustr)); + + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"CharacterStyles"_ustr)->getByName(u"Endnote Symbol"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(58), + getProperty<sal_Int32>(xPageStyle, u"CharEscapementHeight"_ustr)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTMAGENTA, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); + + xPageStyle.set(getStyles(u"CharacterStyles"_ustr)->getByName(u"Endnote anchor"_ustr), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(58), + getProperty<sal_Int32>(xPageStyle, u"CharEscapementHeight"_ustr)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTMAGENTA, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf55427_footnote2endnote) +{ + auto verify = [this](bool bIsExport = false) { + CPPUNIT_ASSERT_EQUAL(4, getPages()); + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"ParagraphStyles"_ustr)->getByName(u"Footnote"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Footnote style is rose color", Color(0xFF007F), + getProperty<Color>(xPageStyle, u"CharColor"_ustr)); + xPageStyle.set(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Endnote"_ustr), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Endnote style is cyan3 color", Color(0x2BD0D2), + getProperty<Color>(xPageStyle, u"CharColor"_ustr)); + + SwDoc* pDoc = getSwDoc(); + // 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().m_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().m_aFormat.GetNumberingType()); + + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); + + uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes(); + 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 (!bIsExport) + { + 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", u"1"_ustr, + xFootnote->getAnchor()->getString()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("original endnote's number", u"i"_ustr, + xEndnote->getAnchor()->getString()); + + uno::Reference<text::XText> xFootnoteText; + xFootnotes->getByIndex(0) >>= xFootnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "original footnote style", u"Footnote"_ustr, + getProperty<OUString>(getParagraphOfText(1, xFootnoteText), u"ParaStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "original endnote style", u"Endnote"_ustr, + getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr)); + } + 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", u"i"_ustr, + xEndnote->getAnchor()->getString()); + xEndnotes->getByIndex(4) >>= xEndnote; + CPPUNIT_ASSERT_EQUAL_MESSAGE("original endnote's new number", u"v"_ustr, + xEndnote->getAnchor()->getString()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "retained footnote style", u"Footnote"_ustr, + getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr)); + xEndnotes->getByIndex(4) >>= xEndnoteText; + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "original endnote style", u"Endnote"_ustr, + getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr)); + } + }; + createSwDoc("tdf55427_footnote2endnote.odt"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf104162, "tdf104162.docx") +{ + // This crashed: the comment field contained a table with a <w:hideMark/>. + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XElementAccess> xTextFields(xTextFieldsSupplier->getTextFields()); + CPPUNIT_ASSERT(xTextFields->hasElements()); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf104150, "tdf104150.docx") +{ + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); + // This was 0xff0000, i.e. red: background shape wasn't ignored. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1), + getProperty<sal_Int32>(xPageStyle, u"BackColor"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf103976, "tdf103976.docx") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), + uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); + // This was 0, table style inheritance went wrong and w:afterLines had priority over w:after. + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(convertTwipToMm100(60)), + getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); + + // tdf#116549: heading 2 style should not have a bottom border. + uno::Reference<beans::XPropertySet> xStyle( + getStyles(u"ParagraphStyles"_ustr)->getByName(u"Heading 2"_ustr), uno::UNO_QUERY); + table::BorderLine2 aBottomBorder + = getProperty<table::BorderLine2>(xStyle, u"BottomBorder"_ustr); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aBottomBorder.LineWidth); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf106001, "tdf106001.docx") +{ + // This was 0 (1 on UI), while Word treats outliers as 100 (outlier = not in [1..600]) + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int16>(100), + getProperty<sal_Int16>(getRun(getParagraph(1), 1), u"CharScaleWidth"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf106001_2) +{ + loadAndSave("tdf106001-2.odt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // In test ODT CharScaleWidth = 900, this was not changed upon OOXML export to stay in [1..600], now it's clamped to 600 + // Note: we disregard what's set in pPr / rPr and only care about r / rPr + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:rPr/w:w", "val", u"600"); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf99074, "tdf99074.docx") +{ + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<view::XViewSettingsSupplier> const xController(xModel->getCurrentController(), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> const xViewSettings(xController->getViewSettings()); + + // The behavior changed - Word 2013 and 2016 ignore this setting on + // import, and instead honor the user's setting. + // Let's ignore the <w:view w:val="web"/> too. + CPPUNIT_ASSERT(!getProperty<bool>(xViewSettings, u"ShowOnlineLayout"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testDefaultSectBreakCols, "default-sect-break-cols.docx") +{ + // First problem: the first two paragraphs did not have their own text section, so the whole document had two columns. + uno::Reference<beans::XPropertySet> xTextSection + = getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(1, u"First."_ustr), + u"TextSection"_ustr); + CPPUNIT_ASSERT(xTextSection.is()); + uno::Reference<text::XTextColumns> xTextColumns + = getProperty<uno::Reference<text::XTextColumns>>(xTextSection, u"TextColumns"_ustr); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns->getColumnCount()); + + // Second problem: the page style had two columns, while it shouldn't have any. + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); + xTextColumns = getProperty<uno::Reference<text::XTextColumns>>(xPageStyle, u"TextColumns"_ustr); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), xTextColumns->getColumnCount()); + // Check for the Column Separator value.It should be FALSE as the document does not contain separator line. + bool bValue = getProperty<bool>(xTextColumns, u"SeparatorLineIsOn"_ustr); + CPPUNIT_ASSERT(!bValue); +} + +DECLARE_OOXMLEXPORT_TEST(testMultiColumnSeparator, "multi-column-separator-with-line.docx") +{ + uno::Reference<beans::XPropertySet> xTextSection + = getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(1, u"First data."_ustr), + u"TextSection"_ustr); + CPPUNIT_ASSERT(xTextSection.is()); + uno::Reference<text::XTextColumns> xTextColumns + = getProperty<uno::Reference<text::XTextColumns>>(xTextSection, u"TextColumns"_ustr); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns->getColumnCount()); + // Check for the Column Separator value.It should be TRUE as the document contains separator line. + bool bValue = getProperty<bool>(xTextColumns, u"SeparatorLineIsOn"_ustr); + CPPUNIT_ASSERT(bValue); +} + +DECLARE_OOXMLEXPORT_TEST(testUnbalancedColumns, "unbalanced-columns.docx") +{ + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), + uno::UNO_QUERY); + // This was false, last section was balanced, but it's unbalanced in Word. + CPPUNIT_ASSERT_EQUAL( + true, getProperty<bool>(xTextSections->getByIndex(2), u"DontBalanceTextColumns"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf121670_columnsInSectionsOnly, + "tdf121670_columnsInSectionsOnly.docx") +{ + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "DontBalanceTextColumns?", true, + getProperty<bool>(xTextSections->getByIndex(0), u"DontBalanceTextColumns"_ustr)); + + uno::Reference<beans::XPropertySet> xTextSection + = getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(2), u"TextSection"_ustr); + CPPUNIT_ASSERT(xTextSection.is()); + uno::Reference<text::XTextColumns> xTextColumns + = getProperty<uno::Reference<text::XTextColumns>>(xTextSection, u"TextColumns"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("# of columns", sal_Int16(3), xTextColumns->getColumnCount()); + + xTextSection.set( + getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(3), u"TextSection"_ustr)); + CPPUNIT_ASSERT(xTextSection.is()); + xTextColumns.set( + getProperty<uno::Reference<text::XTextColumns>>(xTextSection, u"TextColumns"_ustr)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("# of columns", sal_Int16(0), xTextColumns->getColumnCount()); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf106492) +{ + loadAndSave("tdf106492.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + // This was 4: an additional sectPr was added to the document. + assertXPath(pXmlDoc, "//w:sectPr", 3); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf107104, "tdf107104.docx") +{ + CPPUNIT_ASSERT(getShape(1)->getSize().Width > 0); + // This failed: the second arrow was invisible because it had zero width. + CPPUNIT_ASSERT(getShape(2)->getSize().Width > 0); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf107033, "tdf107033.docx") +{ + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); + // This was 0: footnote separator was disabled even in case the document + // had no footnotes. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(25), + getProperty<sal_Int32>(xPageStyle, u"FootnoteLineRelativeWidth"_ustr)); +} + +#if HAVE_MORE_FONTS +CPPUNIT_TEST_FIXTURE(Test, testTdf107889) +{ + auto verify = [this]() { + // This was 1, multi-page table was imported as a non-split fly. + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//tab", 2); + }; + createSwDoc("tdf107889.docx"); + verify(); + saveAndReload(u"Office Open XML Text"_ustr); + verify(); +} +#endif + +CPPUNIT_TEST_FIXTURE(Test, testTdf107837) +{ + loadAndReload("tdf107837.odt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), + uno::UNO_QUERY); + // This was true, a balanced section from ODF turned into a non-balanced one after OOXML roundtrip. + CPPUNIT_ASSERT_EQUAL( + false, getProperty<bool>(xTextSections->getByIndex(0), u"DontBalanceTextColumns"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf107684) +{ + loadAndReload("tdf107684.odt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/styles.xml"_ustr); + // This was 1, <w:outlineLvl> was duplicated for Heading1. + assertXPath(pXmlDoc, "//w:style[@w:styleId='Heading1']/w:pPr/w:outlineLvl", 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf107618) +{ + loadAndReload("tdf107618.doc"); + // This was false, header was lost on export. + uno::Reference<beans::XPropertySet> xPageStyle( + getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPageStyle, u"HeaderIsOn"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf108682, "tdf108682.docx") +{ + auto aLineSpacing = getProperty<style::LineSpacing>(getParagraph(1), u"ParaLineSpacing"_ustr); + // This was style::LineSpacingMode::PROP. + CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::FIX, aLineSpacing.Mode); + // 260 twips in mm100, this was a negative value. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(459), aLineSpacing.Height); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf100075, "tdf100075.docx") +{ + uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), + uno::UNO_QUERY); + + // There are two frames in document + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xIndexAccess->getCount()); + + uno::Reference<beans::XPropertySet> xFrame1(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xFrame2(xIndexAccess->getByIndex(1), uno::UNO_QUERY); + + // Ensure that frame#1 height is more that frame#2: if no hRul attribute + // defined, MS Word will use hRul=auto if height is not defined, + // and hRul=atLeast if height is provided. So frame#1 should be higher + CPPUNIT_ASSERT(getProperty<sal_Int32>(xFrame1, u"Height"_ustr) + > getProperty<sal_Int32>(xFrame2, u"Height"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf105095, "tdf105095.docx") +{ + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); + uno::Reference<text::XTextRange> xTextRange(xFootnotes->getByIndex(0), uno::UNO_QUERY); + // This failed, tab between the footnote number and the footnote content + // was lost on import. + CPPUNIT_ASSERT_EQUAL(u" footnote"_ustr, xTextRange->getString()); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf106062_nonHangingFootnote) +{ + loadAndReload("tdf106062_nonHangingFootnote.odt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); + uno::Reference<text::XTextRange> xTextRange(xFootnotes->getByIndex(0), uno::UNO_QUERY); + // This failed, tab between the footnote number and the footnote content was lost on import. + CPPUNIT_ASSERT_MESSAGE("Footnote starts with a tab", xTextRange->getString().startsWith(" ")); +} + +DECLARE_OOXMLEXPORT_TEST(testActiveXTextfield, "activex_textbox.docx") +{ + uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape.is()); + + // Check control type + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.TextField"_ustr))); + + // Check textfield is multi-line + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPropertySet, u"MultiLine"_ustr)); + + uno::Reference<drawing::XControlShape> xControlShape2(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape2.is()); + + // Check control type + uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape2->getControl(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo2(xPropertySet2, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo2->supportsService(u"com.sun.star.form.component.TextField"_ustr))); + + // Check textfield is single-line + CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xPropertySet2, u"MultiLine"_ustr)); + + // Don't open in design mode when form controls exist + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<view::XFormLayerAccess> xFormLayerAccess(xModel->getCurrentController(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(!xFormLayerAccess->isFormDesignMode()); +} + +DECLARE_OOXMLEXPORT_TEST(testActiveXCheckbox, "activex_checkbox.docx") +{ + uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape.is()); + + // Check control type + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); + + // Check custom label + CPPUNIT_ASSERT_EQUAL(u"Custom Caption"_ustr, + getProperty<OUString>(xPropertySet, u"Label"_ustr)); + + // Check background color (highlight system color) + CPPUNIT_ASSERT_EQUAL(Color(0x316AC5), + getProperty<Color>(xPropertySet, u"BackgroundColor"_ustr)); + + // Check Text color (active border system color) + CPPUNIT_ASSERT_EQUAL(Color(0xD4D0C8), getProperty<Color>(xPropertySet, u"TextColor"_ustr)); + + // Check state of the checkbox + CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xPropertySet, u"State"_ustr)); + + // Check anchor type + uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::TextContentAnchorType_AT_CHARACTER, + getProperty<text::TextContentAnchorType>(xPropertySet2, u"AnchorType"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testActiveXControlAlign) +{ + loadAndReload("activex_control_align.odt"); + CPPUNIT_ASSERT_EQUAL(2, getShapes()); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // First check box aligned as a floating object + uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY_THROW); + + // Check whether we have the right control + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); + CPPUNIT_ASSERT_EQUAL(u"Floating Check Box"_ustr, + getProperty<OUString>(xPropertySet, u"Label"_ustr)); + + // Check anchor type + uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::TextContentAnchorType_AT_CHARACTER, + getProperty<text::TextContentAnchorType>(xPropertySet2, u"AnchorType"_ustr)); + + // Also check position and size + uno::Reference<drawing::XShape> xShape(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape.is()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4470), xShape->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1427), xShape->getSize().Height); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5126), xShape->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2341), xShape->getPosition().Y); + + // Second check box aligned inline / as character + xControlShape.set(getShape(2), uno::UNO_QUERY_THROW); + + // Check whether we have the right control + xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); + xServiceInfo.set(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); + CPPUNIT_ASSERT_EQUAL(u"Inline Check Box"_ustr, + getProperty<OUString>(xPropertySet, u"Label"_ustr)); + + // Check anchor type + xPropertySet2.set(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::TextContentAnchorType_AS_CHARACTER, + getProperty<text::TextContentAnchorType>(xPropertySet2, u"AnchorType"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(text::VertOrientation::TOP), + getProperty<sal_Int32>(xPropertySet2, u"VertOrient"_ustr)); + + // Also check position and size + xShape.set(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape.is()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4410), xShape->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1083), xShape->getSize().Height); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xShape->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1085), xShape->getPosition().Y); + + // Also check the specific OOXML elements + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + // For inline controls use w:object as parent element and pictureFrame shapetype + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object/v:shapetype", "spt", u"75"); + // For floating controls use w:pict as parent element and hostControl shapetype + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict/v:shapetype", "spt", u"201"); + + // Have different shape ids + CPPUNIT_ASSERT(getXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object/v:shape", "id") + != getXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict/v:shape", "id")); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf109184, "tdf109184.docx") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), + uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + + // Before table background color was white, should be transparent (auto). + uno::Reference<text::XTextRange> xCell1(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, getProperty<Color>(xCell1, u"BackColor"_ustr)); + + // Cell with auto color but with 15% fill, shouldn't be transparent. + uno::Reference<text::XTextRange> xCell2(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(Color(0xd8d8d8), getProperty<Color>(xCell2, u"BackColor"_ustr)); + + // Cell with color defined (red). + uno::Reference<text::XTextRange> xCell3(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xCell3, u"BackColor"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf111964) +{ + loadAndSave("tdf111964.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + // Unicode spaces that are not XML whitespace must not be trimmed + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[6]/w:t", vEnSpaces); +} + +DECLARE_OOXMLEXPORT_TEST(testWatermark, "watermark-shapetype.docx") +{ + uno::Reference<drawing::XShape> xShape1(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape1.is()); + uno::Reference<beans::XPropertySet> xPropertySet1(xShape1, uno::UNO_QUERY); + + uno::Reference<drawing::XShape> xShape2(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape2.is()); + uno::Reference<beans::XPropertySet> xPropertySet2(xShape2, uno::UNO_QUERY); + + CPPUNIT_ASSERT_EQUAL(xPropertySet1->getPropertyValue(u"TextAutoGrowHeight"_ustr), + xPropertySet2->getPropertyValue(u"TextAutoGrowHeight"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testActiveXControlAtRunEnd) +{ + loadAndReload("activex_control_at_run_end.odt"); + CPPUNIT_ASSERT_EQUAL(2, getShapes()); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // Two issues were here: + // 1) second shape was not export (it is anchored to the end of the run) + // 2) inline property was inherited to the second shape by mistake + + // First checkbox is the inlined one + uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape.is()); + + // Check whether we have the right control + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); + CPPUNIT_ASSERT_EQUAL(u"Inline Checkbox"_ustr, + getProperty<OUString>(xPropertySet, u"Label"_ustr)); + + // Check anchor type + uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::TextContentAnchorType_AS_CHARACTER, + getProperty<text::TextContentAnchorType>(xPropertySet2, u"AnchorType"_ustr)); + + // Second check box anchored to character + xControlShape.set(getShape(2), uno::UNO_QUERY); + + // Check whether we have the right control + xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); + xServiceInfo.set(xPropertySet, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); + CPPUNIT_ASSERT_EQUAL(u"Floating Checkbox"_ustr, + getProperty<OUString>(xPropertySet, u"Label"_ustr)); + + // Check anchor type + xPropertySet2.set(xControlShape, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + text::TextContentAnchorType_AT_CHARACTER, + getProperty<text::TextContentAnchorType>(xPropertySet2, u"AnchorType"_ustr)); +} + +DECLARE_OOXMLEXPORT_TEST(testActiveXOptionButtonGroup, "activex_option_button_group.docx") +{ + // Optionbutton groups were not handled + // The two optionbutton should have the same group name + static constexpr OUString sGroupName = u"GroupX"_ustr; + + uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape.is()); + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sGroupName, getProperty<OUString>(xPropertySet, u"GroupName"_ustr)); + + xControlShape.set(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT(xControlShape.is()); + xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sGroupName, getProperty<OUString>(xPropertySet, u"GroupName"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, tdf112169) +{ + loadAndSave("tdf112169.odt"); + CPPUNIT_ASSERT_EQUAL(1, getShapes()); + CPPUNIT_ASSERT_EQUAL(6, getPages()); + // LO crashed while export because of character background color handling + + //tdf76683 - Cannot be negative number - use firstLine instead of hanging + xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr); + assertXPathNoAttribute(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:pPr/w:ind", + "hanging"); + assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:pPr/w:ind", "firstLine", u"360"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf103090) +{ + loadAndSave("tdf103090.odt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + // Get bookmark name + OUString bookmarkName = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:bookmarkStart", "name"); + + // Ensure that name has no spaces + CPPUNIT_ASSERT(bookmarkName.indexOf(" ") < 0); + + // Get PAGEREF field + OUString fieldName = getXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[2]/w:instrText"); + + // Ensure that PAGEREF field refers exactly our bookmark + OUString expectedFieldName = " PAGEREF " + bookmarkName + " \h "; + CPPUNIT_ASSERT_EQUAL(expectedFieldName, fieldName); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf107111) +{ + loadAndSave("tdf107111.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + // Ensure that hyperlink and its properties are in place. + assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:hyperlink/w:r/w:rPr", 1); + + // Ensure that hyperlink properties do not contain <w:webHidden/>. + assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:hyperlink/w:r/w:rPr/w:webHidden", 0); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf90789, "tdf90789.docx") +{ + uno::Reference<text::XTextContent> xShape(getShape(1), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xShape->getAnchor() != nullptr); + + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(), + uno::UNO_QUERY_THROW); + xCtrl->select(uno::Any(xShape->getAnchor())); + + uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl, + uno::UNO_QUERY_THROW); + uno::Reference<text::XTextViewCursor> xTextCursor(xTextViewCursorSupplier->getViewCursor(), + uno::UNO_SET_THROW); + uno::Reference<text::XPageCursor> xPageCursor(xTextCursor, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), xPageCursor->getPage()); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf90789_2, "tdf90789-2.docx") +{ + // Section break before frame and shape was ignored + CPPUNIT_ASSERT_EQUAL(3, getPages()); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf104354_2, "tdf104354-2.docx") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), + uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); + + // top margin of the first paragraph and bottom margin of the last paragraph + // is zero, when auto spacing is used. + + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(494), + getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(494), + getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(494), + getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaBottomMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(494), + getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaBottomMargin"_ustr)); + + // top margin is not auto spacing + uno::Reference<text::XTextRange> xCell2(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(847), + getProperty<sal_Int32>(getParagraphOfText(1, xCell2->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell2->getText()), u"ParaBottomMargin"_ustr)); + + // bottom margin is not auto spacing + uno::Reference<text::XTextRange> xCell3(xTable->getCellByName(u"A3"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell3->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(847), + getProperty<sal_Int32>(getParagraphOfText(1, xCell3->getText()), u"ParaBottomMargin"_ustr)); + + // auto spacing, if the paragraph contains footnotes + uno::Reference<text::XTextRange> xCell4(xTable->getCellByName(u"A4"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell4->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell4->getText()), u"ParaBottomMargin"_ustr)); + + // auto spacing is explicitly disabled, and no margins are defined. + xCell.set(xTable->getCellByName(u"A5"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaBottomMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaBottomMargin"_ustr)); + + // auto spacing on a paragraph + uno::Reference<text::XTextTable> xTable2(xTables->getByIndex(1), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell5(xTable2->getCellByName(u"A1"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell5->getText()), u"ParaTopMargin"_ustr)); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraphOfText(1, xCell5->getText()), u"ParaBottomMargin"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf137593) +{ + loadAndSave("tdf137593.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + // zero auto spacing, if the first paragraph contains text boxes + // This was 280. + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl[1]/w:tr/w:tc/w:p[1]/w:pPr/w:spacing", "before", + u"0"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf115557) +{ + loadAndSave("tdf115557.docx"); + // A chart anchored to a footnote multiplied during import + xmlDocUniquePtr pXmlDoc = parseExport(u"word/footnotes.xml"_ustr); + + assertXPath(pXmlDoc, "//w:footnote/w:p/w:r/w:drawing", 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testAlignmentRelativeFromTopMarginDML) +{ + loadAndSave("tdf137641_RelativeFromTopMargin.docx"); + // Import as DML. + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + assertXPath(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"top"); + assertXPath(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"bottom"); + assertXPath(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"center"); +} + +CPPUNIT_TEST_FIXTURE(Test, testAlignmentRelativeFromTopMarginVML) +{ + loadAndSave("tdf137642_Vertical_Alignment_toppage.docx"); + // Import as VML. + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + assertXPath(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"top"); + assertXPath(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"bottom"); + assertXPath(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV", + "relativeFrom", u"topMargin"); + assertXPathContent(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" + "wp:anchor/wp:positionV/wp:align", + u"center"); +} + +CPPUNIT_TEST_FIXTURE(Test, testVmlShapeWithTextbox) +{ + loadAndSave("tdf41466_testVmlShapeWithTextbox.docx"); + // Import as VML. + // tdf#41466: check whether VML DOCX shape with text is imported as shape with a text frame + // (text box). These kind of shapes were imported only as text frames previously, losing the + // preset shape geometry, in this case "wedgeRectCallout". + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + + // the wrong value was "rect" instead of "wedgeRectCallout" + assertXPath(pXmlDoc, + "/w:document/w:body/w:p/w:r/" + "mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/" + "wps:spPr/a:prstGeom", + "prst", u"wedgeRectCallout"); +} + +CPPUNIT_TEST_FIXTURE(Test, testLayoutFlowAltAlone) +{ + loadAndSave("layout-flow-alt-alone.docx"); + // moved from oox/qa/unit/vml.cxx + // FIXME: now the DML part is checked, but we should check VML part in Fallback (too) + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + assertXPath(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/" + "a:graphic/a:graphicData/wps:wsp/wps:bodyPr", + "vert", u"vert270"); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index 58be11a12b37..892ccd637db3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -11,35 +11,25 @@ #include <config_fonts.h> -#include <com/sun/star/text/XFootnote.hpp> -#include <com/sun/star/text/XPageCursor.hpp> #include <com/sun/star/text/XTextColumns.hpp> -#include <com/sun/star/text/XTextViewCursorSupplier.hpp> #include <com/sun/star/style/BreakType.hpp> -#include <com/sun/star/style/PageStyleLayout.hpp> #include <com/sun/star/text/HoriOrientation.hpp> #include <com/sun/star/text/RelOrientation.hpp> -#include <com/sun/star/text/VertOrientation.hpp> #include <com/sun/star/text/WrapTextMode.hpp> -#include <com/sun/star/view/XFormLayerAccess.hpp> -#include <com/sun/star/view/XViewSettingsSupplier.hpp> -#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/text/XTextFramesSupplier.hpp> +#include <com/sun/star/text/XTextTablesSupplier.hpp> +#include <com/sun/star/text/XTextSectionsSupplier.hpp> #include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/style/LineSpacingMode.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp> -#include <com/sun/star/drawing/XControlShape.hpp> #include <com/sun/star/packages/zip/ZipFileAccess.hpp> #include <com/sun/star/text/XTextTable.hpp> #include <sfx2/docfile.hxx> #include <sfx2/docfilt.hxx> #include <comphelper/processfactory.hxx> -#include <tools/UnitConversion.hxx> -#include <o3tl/string_view.hxx> #include <docsh.hxx> -#include <ftninfo.hxx> -#include <unotxdoc.hxx> class Test : public SwModelTestBase { @@ -796,833 +786,6 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf103982) CPPUNIT_ASSERT(!getProperty<bool>(xPropertySet, u"Shadow"_ustr)); } -CPPUNIT_TEST_FIXTURE(Test, testTdf104115) -{ - loadAndSave("tdf104115.docx"); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - // This found 0 nodes: the custom geometry was not written for the Bezier - // curve -> Word refused to open the document. - assertXPath(pXmlDoc, "//a:custGeom", 1); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf103651, "tdf103651.docx") -{ - uno::Reference<beans::XPropertySet> xTextField = getProperty< uno::Reference<beans::XPropertySet> >(getRun(getParagraph(1), 1), u"TextField"_ustr); - OUString sContent; - xTextField->getPropertyValue(u"Content"_ustr) >>= sContent; - // Comment in the first paragraph should not have smiley ( 0xf04a ). - CPPUNIT_ASSERT_EQUAL( sal_Int32( -1 ) , sContent.indexOf( u'\xf04a' )); - - // this document has a w:kern setting in the DocDefault character properties. Ensure it applies. - CPPUNIT_ASSERT(getProperty<bool>(getRun(getParagraph(1), 1), u"CharAutoKerning"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf99227) -{ - loadAndSave("tdf99227.docx"); - // A drawing anchored as character to a footnote caused write past end of document.xml at export to docx. - // After that, importing after export failed with - // SAXParseException: '[word/document.xml line 2]: Extra content at the end of the document', Stream 'word / document.xml', - // and before commit ebf767eeb2a169ba533e1b2ffccf16f41d95df35, the drawing was silently lost. - xmlDocUniquePtr pXmlDoc = parseExport(u"word/footnotes.xml"_ustr); - - assertXPath(pXmlDoc, "//w:footnote/w:p/w:r/w:drawing", 1); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf37153, "tdf37153_considerWrapOnObjPos.docx") -{ - CPPUNIT_ASSERT_EQUAL(text::WrapTextMode_THROUGH, getProperty<text::WrapTextMode>(getShape(1), u"Surround"_ustr)); - - uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::VertOrientation::BOTTOM, getProperty<sal_Int16>(xTable->getCellByName(u"A1"_ustr), u"VertOrient"_ustr)); - - //For MSO compatibility, the textbox should be at the top of the cell, not at the bottom - despite VertOrientation::BOTTOM - xmlDocUniquePtr pXmlDoc = parseLayoutDump(); - sal_Int32 nFlyTop = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt/anchored/fly/infos/bounds", "top").toInt32(); - CPPUNIT_ASSERT_MESSAGE("FlyTop should be 2865, not 5649", nFlyTop < sal_Int32(3000)); - sal_Int32 nTextTop = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[2]/txt[1]/infos/bounds", "top").toInt32(); - CPPUNIT_ASSERT_MESSAGE("TextTop should be 3856", nTextTop > 3000); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf112446_frameStyle, "tdf112446_frameStyle.docx") -{ - CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::NONE, getProperty<sal_Int16>(getShape(1), u"HoriOrient"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf82173_footnoteStyle, "tdf82173_footnoteStyle.docx") -{ - uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); - - uno::Reference<text::XText> xFootnoteText; - xFootnotes->getByIndex(0) >>= xFootnoteText; - // This was footnote text, which didn't match with newly created footnotes - CPPUNIT_ASSERT_EQUAL(u"Footnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xFootnoteText), u"ParaStyleName"_ustr)); - - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"CharacterStyles"_ustr)->getByName(u"Footnote Symbol"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL( sal_Int32(58), getProperty< sal_Int32 >(xPageStyle, u"CharEscapementHeight"_ustr) ); - CPPUNIT_ASSERT_EQUAL( COL_LIGHTGREEN, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); - - xPageStyle.set(getStyles(u"CharacterStyles"_ustr)->getByName(u"Footnote anchor"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL( sal_Int32(58), getProperty< sal_Int32 >(xPageStyle, u"CharEscapementHeight"_ustr) ); - CPPUNIT_ASSERT_EQUAL( COL_LIGHTGREEN, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); - - //tdf#118361 - in RTL locales, the footnote separator should still be left aligned. - uno::Any aPageStyle = getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Footnote separator LTR", sal_Int16(0), getProperty<sal_Int16>(aPageStyle, u"FootnoteLineAdjust"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf82173_endnoteStyle, "tdf82173_endnoteStyle.docx") -{ - uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes(); - uno::Reference<text::XFootnote> xEndnote; - xEndnotes->getByIndex(0) >>= xEndnote; - // character properties were previously not assigned to the footnote/endnote in-text anchor. - CPPUNIT_ASSERT_EQUAL( 24.0f, getProperty< float >(xEndnote->getAnchor(), u"CharHeight"_ustr) ); - CPPUNIT_ASSERT_EQUAL( COL_LIGHTRED, getProperty<Color>(xEndnote->getAnchor(), u"CharColor"_ustr)); - - uno::Reference<text::XText> xEndnoteText; - xEndnotes->getByIndex(0) >>= xEndnoteText; - // This was Endnote Symbol - CPPUNIT_ASSERT_EQUAL(u"Endnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x993300), getProperty<Color>(getParagraphOfText(1, xEndnoteText), u"CharColor"_ustr)); - - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"CharacterStyles"_ustr)->getByName(u"Endnote Symbol"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL( sal_Int32(58), getProperty< sal_Int32 >(xPageStyle, u"CharEscapementHeight"_ustr) ); - CPPUNIT_ASSERT_EQUAL( COL_LIGHTMAGENTA, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); - - xPageStyle.set(getStyles(u"CharacterStyles"_ustr)->getByName(u"Endnote anchor"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL( sal_Int32(58), getProperty< sal_Int32 >(xPageStyle, u"CharEscapementHeight"_ustr) ); - CPPUNIT_ASSERT_EQUAL( COL_LIGHTMAGENTA, getProperty<Color>(xPageStyle, u"CharColor"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf55427_footnote2endnote) -{ - auto verify = [this](bool bIsExport = false) { - CPPUNIT_ASSERT_EQUAL(4, getPages()); - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Footnote"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL_MESSAGE( "Footnote style is rose color", Color(0xFF007F), getProperty<Color>(xPageStyle, u"CharColor"_ustr)); - xPageStyle.set(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Endnote"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL_MESSAGE( "Endnote style is cyan3 color", Color(0x2BD0D2), getProperty<Color>(xPageStyle, u"CharColor"_ustr)); - - SwDoc* pDoc = getSwDoc(); - // 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().m_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().m_aFormat.GetNumberingType() ); - - uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); - - uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes(); - 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 (!bIsExport) - { - 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", u"1"_ustr, xFootnote->getAnchor()->getString() ); - CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's number", u"i"_ustr, xEndnote->getAnchor()->getString() ); - - uno::Reference<text::XText> xFootnoteText; - xFootnotes->getByIndex(0) >>= xFootnoteText; - CPPUNIT_ASSERT_EQUAL_MESSAGE( "original footnote style", u"Footnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xFootnoteText), u"ParaStyleName"_ustr) ); - CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", u"Endnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr) ); - } - 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", u"i"_ustr, xEndnote->getAnchor()->getString() ); - xEndnotes->getByIndex(4) >>= xEndnote; - CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote's new number", u"v"_ustr, xEndnote->getAnchor()->getString() ); - - CPPUNIT_ASSERT_EQUAL_MESSAGE( "retained footnote style", u"Footnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr) ); - xEndnotes->getByIndex(4) >>= xEndnoteText; - CPPUNIT_ASSERT_EQUAL_MESSAGE( "original endnote style", u"Endnote"_ustr, getProperty<OUString>(getParagraphOfText(1, xEndnoteText), u"ParaStyleName"_ustr) ); - } - }; - createSwDoc("tdf55427_footnote2endnote.odt"); - verify(); - saveAndReload(mpFilter); - verify(/*bIsExport*/ true); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf104162, "tdf104162.docx") -{ - // This crashed: the comment field contained a table with a <w:hideMark/>. - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XElementAccess> xTextFields(xTextFieldsSupplier->getTextFields()); - CPPUNIT_ASSERT(xTextFields->hasElements()); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf104150, "tdf104150.docx") -{ - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); - // This was 0xff0000, i.e. red: background shape wasn't ignored. - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1), getProperty<sal_Int32>(xPageStyle, u"BackColor"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf103976, "tdf103976.docx") -{ - uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); - // This was 0, table style inheritance went wrong and w:afterLines had priority over w:after. - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(convertTwipToMm100(60)), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); - - // tdf#116549: heading 2 style should not have a bottom border. - uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Heading 2"_ustr), uno::UNO_QUERY); - table::BorderLine2 aBottomBorder = getProperty<table::BorderLine2>(xStyle, u"BottomBorder"_ustr); - CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aBottomBorder.LineWidth); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf106001, "tdf106001.docx") -{ - // This was 0 (1 on UI), while Word treats outliers as 100 (outlier = not in [1..600]) - CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int16>( 100 ), getProperty<sal_Int16>(getRun(getParagraph(1), 1), u"CharScaleWidth"_ustr )); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf106001_2) -{ - loadAndSave("tdf106001-2.odt"); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - // In test ODT CharScaleWidth = 900, this was not changed upon OOXML export to stay in [1..600], now it's clamped to 600 - // Note: we disregard what's set in pPr / rPr and only care about r / rPr - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:rPr/w:w","val",u"600"); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf99074, "tdf99074.docx") -{ - uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); - uno::Reference<view::XViewSettingsSupplier> const xController( - xModel->getCurrentController(), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> const xViewSettings( - xController->getViewSettings()); - - // The behavior changed - Word 2013 and 2016 ignore this setting on - // import, and instead honor the user's setting. - // Let's ignore the <w:view w:val="web"/> too. - CPPUNIT_ASSERT(!getProperty<bool>(xViewSettings, u"ShowOnlineLayout"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testDefaultSectBreakCols, "default-sect-break-cols.docx") -{ - // First problem: the first two paragraphs did not have their own text section, so the whole document had two columns. - uno::Reference<beans::XPropertySet> xTextSection = getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(1, u"First."_ustr), u"TextSection"_ustr); - CPPUNIT_ASSERT(xTextSection.is()); - uno::Reference<text::XTextColumns> xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xTextSection, u"TextColumns"_ustr); - CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns->getColumnCount()); - - // Second problem: the page style had two columns, while it shouldn't have any. - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); - xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xPageStyle, u"TextColumns"_ustr); - CPPUNIT_ASSERT_EQUAL(sal_Int16(0), xTextColumns->getColumnCount()); - // Check for the Column Separator value.It should be FALSE as the document does not contain separator line. - bool bValue = getProperty< bool >(xTextColumns, u"SeparatorLineIsOn"_ustr); - CPPUNIT_ASSERT(!bValue) ; -} - -DECLARE_OOXMLEXPORT_TEST(testMultiColumnSeparator, "multi-column-separator-with-line.docx") -{ - uno::Reference<beans::XPropertySet> xTextSection = getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(1, u"First data."_ustr), u"TextSection"_ustr); - CPPUNIT_ASSERT(xTextSection.is()); - uno::Reference<text::XTextColumns> xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xTextSection, u"TextColumns"_ustr); - CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns->getColumnCount()); - // Check for the Column Separator value.It should be TRUE as the document contains separator line. - bool bValue = getProperty< bool >(xTextColumns, u"SeparatorLineIsOn"_ustr); - CPPUNIT_ASSERT(bValue); -} - -DECLARE_OOXMLEXPORT_TEST(testUnbalancedColumns, "unbalanced-columns.docx") -{ - uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY); - // This was false, last section was balanced, but it's unbalanced in Word. - CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextSections->getByIndex(2), u"DontBalanceTextColumns"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf121670_columnsInSectionsOnly, "tdf121670_columnsInSectionsOnly.docx") -{ - uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL_MESSAGE("DontBalanceTextColumns?", true, getProperty<bool>(xTextSections->getByIndex(0), u"DontBalanceTextColumns"_ustr)); - - uno::Reference<beans::XPropertySet> xTextSection = getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(2), u"TextSection"_ustr); - CPPUNIT_ASSERT(xTextSection.is()); - uno::Reference<text::XTextColumns> xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xTextSection, u"TextColumns"_ustr); - CPPUNIT_ASSERT_EQUAL_MESSAGE("# of columns", sal_Int16(3), xTextColumns->getColumnCount()); - - xTextSection.set( getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(3), u"TextSection"_ustr) ); - CPPUNIT_ASSERT(xTextSection.is()); - xTextColumns.set( getProperty< uno::Reference<text::XTextColumns> >(xTextSection, u"TextColumns"_ustr) ); - CPPUNIT_ASSERT_EQUAL_MESSAGE("# of columns", sal_Int16(0), xTextColumns->getColumnCount()); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf106492) -{ - loadAndSave("tdf106492.docx"); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - // This was 4: an additional sectPr was added to the document. - assertXPath(pXmlDoc, "//w:sectPr", 3); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf107104, "tdf107104.docx") -{ - CPPUNIT_ASSERT(getShape(1)->getSize().Width > 0); - // This failed: the second arrow was invisible because it had zero width. - CPPUNIT_ASSERT(getShape(2)->getSize().Width > 0); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf107033, "tdf107033.docx") -{ - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); - // This was 0: footnote separator was disabled even in case the document - // had no footnotes. - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(25), getProperty<sal_Int32>(xPageStyle, u"FootnoteLineRelativeWidth"_ustr)); -} - -#if HAVE_MORE_FONTS -CPPUNIT_TEST_FIXTURE(Test, testTdf107889) -{ - auto verify = [this]() { - // This was 1, multi-page table was imported as a non-split fly. - xmlDocUniquePtr pXmlDoc = parseLayoutDump(); - assertXPath(pXmlDoc, "//tab", 2); - }; - createSwDoc("tdf107889.docx"); - verify(); - saveAndReload(u"Office Open XML Text"_ustr); - verify(); -} -#endif - -CPPUNIT_TEST_FIXTURE(Test, testTdf107837) -{ - loadAndReload("tdf107837.odt"); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY); - // This was true, a balanced section from ODF turned into a non-balanced one after OOXML roundtrip. - CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTextSections->getByIndex(0), u"DontBalanceTextColumns"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf107684) -{ - loadAndReload("tdf107684.odt"); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/styles.xml"_ustr); - // This was 1, <w:outlineLvl> was duplicated for Heading1. - assertXPath(pXmlDoc, "//w:style[@w:styleId='Heading1']/w:pPr/w:outlineLvl", 1); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf107618) -{ - loadAndReload("tdf107618.doc"); - // This was false, header was lost on export. - uno::Reference<beans::XPropertySet> xPageStyle(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPageStyle, u"HeaderIsOn"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf108682, "tdf108682.docx") -{ - auto aLineSpacing = getProperty<style::LineSpacing>(getParagraph(1), u"ParaLineSpacing"_ustr); - // This was style::LineSpacingMode::PROP. - CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::FIX, aLineSpacing.Mode); - // 260 twips in mm100, this was a negative value. - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(459), aLineSpacing.Height); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf100075, "tdf100075.docx") -{ - uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY); - - // There are two frames in document - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xIndexAccess->getCount()); - - uno::Reference<beans::XPropertySet> xFrame1(xIndexAccess->getByIndex(0), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xFrame2(xIndexAccess->getByIndex(1), uno::UNO_QUERY); - - // Ensure that frame#1 height is more that frame#2: if no hRul attribute - // defined, MS Word will use hRul=auto if height is not defined, - // and hRul=atLeast if height is provided. So frame#1 should be higher - CPPUNIT_ASSERT(getProperty<sal_Int32>(xFrame1, u"Height"_ustr) > getProperty<sal_Int32>(xFrame2, u"Height"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf105095, "tdf105095.docx") -{ - uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); - uno::Reference<text::XTextRange> xTextRange(xFootnotes->getByIndex(0), uno::UNO_QUERY); - // This failed, tab between the footnote number and the footnote content - // was lost on import. - CPPUNIT_ASSERT_EQUAL( u" footnote"_ustr, xTextRange->getString() ); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf106062_nonHangingFootnote) -{ - loadAndReload("tdf106062_nonHangingFootnote.odt"); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes(); - uno::Reference<text::XTextRange> xTextRange(xFootnotes->getByIndex(0), uno::UNO_QUERY); - // This failed, tab between the footnote number and the footnote content was lost on import. - CPPUNIT_ASSERT_MESSAGE( "Footnote starts with a tab", xTextRange->getString().startsWith(" ") ); -} - -DECLARE_OOXMLEXPORT_TEST( testActiveXTextfield, "activex_textbox.docx" ) -{ - uno::Reference<drawing::XControlShape> xControlShape( getShape(1), uno::UNO_QUERY ); - CPPUNIT_ASSERT( xControlShape.is() ); - - // Check control type - uno::Reference<beans::XPropertySet> xPropertySet( xControlShape->getControl(), uno::UNO_QUERY ); - uno::Reference<lang::XServiceInfo> xServiceInfo( xPropertySet, uno::UNO_QUERY ); - CPPUNIT_ASSERT_EQUAL( true, bool( xServiceInfo->supportsService ( u"com.sun.star.form.component.TextField"_ustr ) ) ); - - // Check textfield is multi-line - CPPUNIT_ASSERT_EQUAL( true, getProperty<bool>(xPropertySet, u"MultiLine"_ustr) ); - - uno::Reference<drawing::XControlShape> xControlShape2( getShape(2), uno::UNO_QUERY ); - CPPUNIT_ASSERT( xControlShape2.is() ); - - // Check control type - uno::Reference<beans::XPropertySet> xPropertySet2( xControlShape2->getControl(), uno::UNO_QUERY ); - uno::Reference<lang::XServiceInfo> xServiceInfo2( xPropertySet2, uno::UNO_QUERY ); - CPPUNIT_ASSERT_EQUAL( true, bool( xServiceInfo2->supportsService ( u"com.sun.star.form.component.TextField"_ustr ) ) ); - - // Check textfield is single-line - CPPUNIT_ASSERT_EQUAL( false, getProperty<bool>(xPropertySet2, u"MultiLine"_ustr) ); - - // Don't open in design mode when form controls exist - uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); - uno::Reference<view::XFormLayerAccess> xFormLayerAccess(xModel->getCurrentController(), uno::UNO_QUERY); - CPPUNIT_ASSERT( !xFormLayerAccess->isFormDesignMode() ); -} - -DECLARE_OOXMLEXPORT_TEST( testActiveXCheckbox, "activex_checkbox.docx" ) -{ - uno::Reference<drawing::XControlShape> xControlShape( getShape(1), uno::UNO_QUERY ); - CPPUNIT_ASSERT( xControlShape.is() ); - - // Check control type - uno::Reference<beans::XPropertySet> xPropertySet( xControlShape->getControl(), uno::UNO_QUERY ); - uno::Reference<lang::XServiceInfo> xServiceInfo( xPropertySet, uno::UNO_QUERY ); - CPPUNIT_ASSERT_EQUAL( true, bool( xServiceInfo->supportsService( u"com.sun.star.form.component.CheckBox"_ustr ) ) ); - - // Check custom label - CPPUNIT_ASSERT_EQUAL( u"Custom Caption"_ustr, getProperty<OUString>(xPropertySet, u"Label"_ustr) ); - - // Check background color (highlight system color) - CPPUNIT_ASSERT_EQUAL( Color( 0x316AC5 ), getProperty<Color>(xPropertySet, u"BackgroundColor"_ustr) ); - - // Check Text color (active border system color) - CPPUNIT_ASSERT_EQUAL(Color(0xD4D0C8), getProperty<Color>(xPropertySet, u"TextColor"_ustr)); - - // Check state of the checkbox - CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xPropertySet, u"State"_ustr)); - - // Check anchor type - uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,u"AnchorType"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testActiveXControlAlign) -{ - loadAndReload("activex_control_align.odt"); - CPPUNIT_ASSERT_EQUAL(2, getShapes()); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - // First check box aligned as a floating object - uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY_THROW); - - // Check whether we have the right control - uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); - uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(true, bool(xServiceInfo->supportsService( u"com.sun.star.form.component.CheckBox"_ustr))); - CPPUNIT_ASSERT_EQUAL(u"Floating Check Box"_ustr, getProperty<OUString>(xPropertySet, u"Label"_ustr)); - - // Check anchor type - uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,u"AnchorType"_ustr)); - - // Also check position and size - uno::Reference<drawing::XShape> xShape(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT(xShape.is()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(4470), xShape->getSize().Width); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1427), xShape->getSize().Height); - CPPUNIT_ASSERT_EQUAL(sal_Int32(5126), xShape->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2341), xShape->getPosition().Y); - - // Second check box aligned inline / as character - xControlShape.set(getShape(2), uno::UNO_QUERY_THROW); - - // Check whether we have the right control - xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); - xServiceInfo.set(xPropertySet, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); - CPPUNIT_ASSERT_EQUAL(u"Inline Check Box"_ustr, getProperty<OUString>(xPropertySet, u"Label"_ustr)); - - // Check anchor type - xPropertySet2.set(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AS_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,u"AnchorType"_ustr)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(text::VertOrientation::TOP),getProperty<sal_Int32>(xPropertySet2,u"VertOrient"_ustr)); - - // Also check position and size - xShape.set(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT(xShape.is()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(4410), xShape->getSize().Width); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1083), xShape->getSize().Height); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xShape->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-1085), xShape->getPosition().Y); - - // Also check the specific OOXML elements - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - CPPUNIT_ASSERT(pXmlDoc); - // For inline controls use w:object as parent element and pictureFrame shapetype - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object", 1); - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object/v:shapetype", "spt", u"75"); - // For floating controls use w:pict as parent element and hostControl shapetype - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict", 1); - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict/v:shapetype", "spt", u"201"); - - // Have different shape ids - CPPUNIT_ASSERT(getXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:object/v:shape", "id") != - getXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/w:pict/v:shape", "id")); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf109184, "tdf109184.docx") -{ - uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - - // Before table background color was white, should be transparent (auto). - uno::Reference<text::XTextRange> xCell1(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, getProperty<Color>(xCell1, u"BackColor"_ustr)); - - // Cell with auto color but with 15% fill, shouldn't be transparent. - uno::Reference<text::XTextRange> xCell2(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(Color(0xd8d8d8), getProperty<Color>(xCell2, u"BackColor"_ustr)); - - // Cell with color defined (red). - uno::Reference<text::XTextRange> xCell3(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xCell3, u"BackColor"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf111964) -{ - loadAndSave("tdf111964.docx"); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - // Unicode spaces that are not XML whitespace must not be trimmed - assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[6]/w:t", vEnSpaces); -} - -DECLARE_OOXMLEXPORT_TEST(testWatermark, "watermark-shapetype.docx") -{ - uno::Reference<drawing::XShape> xShape1(getShape(1), uno::UNO_QUERY); - CPPUNIT_ASSERT(xShape1.is()); - uno::Reference<beans::XPropertySet> xPropertySet1(xShape1, uno::UNO_QUERY); - - uno::Reference<drawing::XShape> xShape2(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT(xShape2.is()); - uno::Reference<beans::XPropertySet> xPropertySet2(xShape2, uno::UNO_QUERY); - - CPPUNIT_ASSERT_EQUAL(xPropertySet1->getPropertyValue(u"TextAutoGrowHeight"_ustr), xPropertySet2->getPropertyValue(u"TextAutoGrowHeight"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testActiveXControlAtRunEnd) -{ - loadAndReload("activex_control_at_run_end.odt"); - CPPUNIT_ASSERT_EQUAL(2, getShapes()); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - // Two issues were here: - // 1) second shape was not export (it is anchored to the end of the run) - // 2) inline property was inherited to the second shape by mistake - - // First checkbox is the inlined one - uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); - CPPUNIT_ASSERT(xControlShape.is()); - - // Check whether we have the right control - uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); - uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(true, bool(xServiceInfo->supportsService( u"com.sun.star.form.component.CheckBox"_ustr))); - CPPUNIT_ASSERT_EQUAL(u"Inline Checkbox"_ustr, getProperty<OUString>(xPropertySet, u"Label"_ustr)); - - // Check anchor type - uno::Reference<beans::XPropertySet> xPropertySet2(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AS_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,u"AnchorType"_ustr)); - - // Second check box anchored to character - xControlShape.set(getShape(2), uno::UNO_QUERY); - - // Check whether we have the right control - xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); - xServiceInfo.set(xPropertySet, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(true, bool(xServiceInfo->supportsService(u"com.sun.star.form.component.CheckBox"_ustr))); - CPPUNIT_ASSERT_EQUAL(u"Floating Checkbox"_ustr, getProperty<OUString>(xPropertySet, u"Label"_ustr)); - - // Check anchor type - xPropertySet2.set(xControlShape, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,u"AnchorType"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testActiveXOptionButtonGroup, "activex_option_button_group.docx") -{ - // Optionbutton groups were not handled - // The two optionbutton should have the same group name - static constexpr OUString sGroupName = u"GroupX"_ustr; - - uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY); - CPPUNIT_ASSERT(xControlShape.is()); - uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sGroupName, getProperty<OUString>(xPropertySet, u"GroupName"_ustr)); - - xControlShape.set(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT(xControlShape.is()); - xPropertySet.set(xControlShape->getControl(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sGroupName, getProperty<OUString>(xPropertySet, u"GroupName"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, tdf112169) -{ - loadAndSave("tdf112169.odt"); - CPPUNIT_ASSERT_EQUAL(1, getShapes()); - CPPUNIT_ASSERT_EQUAL(6, getPages()); - // LO crashed while export because of character background color handling - - //tdf76683 - Cannot be negative number - use firstLine instead of hanging - xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr); - assertXPathNoAttribute(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:pPr/w:ind", "hanging"); - assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:pPr/w:ind", "firstLine",u"360"); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf103090) -{ - loadAndSave("tdf103090.odt"); - CPPUNIT_ASSERT_EQUAL(1, getPages()); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - - // Get bookmark name - OUString bookmarkName = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:bookmarkStart", "name"); - - // Ensure that name has no spaces - CPPUNIT_ASSERT(bookmarkName.indexOf(" ") < 0); - - // Get PAGEREF field - OUString fieldName = getXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[2]/w:instrText"); - - // Ensure that PAGEREF field refers exactly our bookmark - OUString expectedFieldName = " PAGEREF " + bookmarkName + " \h "; - CPPUNIT_ASSERT_EQUAL(expectedFieldName, fieldName); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf107111) -{ - loadAndSave("tdf107111.docx"); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - - // Ensure that hyperlink and its properties are in place. - assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:hyperlink/w:r/w:rPr", 1); - - // Ensure that hyperlink properties do not contain <w:webHidden/>. - assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:hyperlink/w:r/w:rPr/w:webHidden", 0); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf90789, "tdf90789.docx") -{ - uno::Reference<text::XTextContent> xShape(getShape(1), uno::UNO_QUERY_THROW); - CPPUNIT_ASSERT(xShape->getAnchor() != nullptr); - - uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(), uno::UNO_QUERY_THROW); - xCtrl->select(uno::Any(xShape->getAnchor())); - - uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl, uno::UNO_QUERY_THROW); - uno::Reference<text::XTextViewCursor> xTextCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_SET_THROW); - uno::Reference<text::XPageCursor> xPageCursor(xTextCursor, uno::UNO_QUERY_THROW); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), xPageCursor->getPage()); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf90789_2, "tdf90789-2.docx") -{ - // Section break before frame and shape was ignored - CPPUNIT_ASSERT_EQUAL( 3, getPages() ); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf104354_2, "tdf104354-2.docx") -{ - uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); - - // top margin of the first paragraph and bottom margin of the last paragraph - // is zero, when auto spacing is used. - - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaBottomMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaBottomMargin"_ustr)); - - // top margin is not auto spacing - uno::Reference<text::XTextRange> xCell2(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(847), getProperty<sal_Int32>(getParagraphOfText(1, xCell2->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell2->getText()), u"ParaBottomMargin"_ustr)); - - // bottom margin is not auto spacing - uno::Reference<text::XTextRange> xCell3(xTable->getCellByName(u"A3"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell3->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(847), getProperty<sal_Int32>(getParagraphOfText(1, xCell3->getText()), u"ParaBottomMargin"_ustr)); - - // auto spacing, if the paragraph contains footnotes - uno::Reference<text::XTextRange> xCell4(xTable->getCellByName(u"A4"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell4->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell4->getText()), u"ParaBottomMargin"_ustr)); - - // auto spacing is explicitly disabled, and no margins are defined. - xCell.set(xTable->getCellByName(u"A5"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), u"ParaBottomMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), u"ParaBottomMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(3, xCell->getText()), u"ParaBottomMargin"_ustr)); - - // auto spacing on a paragraph - uno::Reference<text::XTextTable> xTable2(xTables->getByIndex(1), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xCell5(xTable2->getCellByName(u"A1"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell5->getText()), u"ParaTopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell5->getText()), u"ParaBottomMargin"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf137593) -{ - loadAndSave("tdf137593.docx"); - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - - // zero auto spacing, if the first paragraph contains text boxes - // This was 280. - assertXPath(pXmlDoc, "/w:document/w:body/w:tbl[1]/w:tr/w:tc/w:p[1]/w:pPr/w:spacing", "before", u"0"); -} - -CPPUNIT_TEST_FIXTURE(Test, testTdf115557) -{ - loadAndSave("tdf115557.docx"); - // A chart anchored to a footnote multiplied during import - xmlDocUniquePtr pXmlDoc = parseExport(u"word/footnotes.xml"_ustr); - - assertXPath(pXmlDoc, "//w:footnote/w:p/w:r/w:drawing", 1); -} - -CPPUNIT_TEST_FIXTURE(Test, testAlignmentRelativeFromTopMarginDML) -{ - loadAndSave("tdf137641_RelativeFromTopMargin.docx"); - // Import as DML. - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - - assertXPath(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV", - "relativeFrom", u"topMargin"); - assertXPathContent(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV/wp:align", - u"top"); - assertXPath(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV", - "relativeFrom", u"topMargin"); - assertXPathContent(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV/wp:align", - u"bottom"); - assertXPath(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV", - "relativeFrom", u"topMargin"); - assertXPathContent(pXmlDoc, - "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV/wp:align", - u"center"); -} - -CPPUNIT_TEST_FIXTURE(Test, testAlignmentRelativeFromTopMarginVML) -{ - loadAndSave("tdf137642_Vertical_Alignment_toppage.docx"); - // Import as VML. - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - - assertXPath(pXmlDoc, - "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV", - "relativeFrom", u"topMargin"); - assertXPathContent(pXmlDoc, - "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV/wp:align", - u"top"); - assertXPath(pXmlDoc, - "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV", - "relativeFrom", u"topMargin"); - assertXPathContent(pXmlDoc, - "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/" - "wp:anchor/wp:positionV/wp:align", - u"bottom"); - assertXPath(pXmlDoc, - "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/" -e ... etc. - the rest is truncated