/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class Test : public SwModelTestBase { public: Test() : SwModelTestBase("/sw/qa/extras/ww8export/data/", "MS Word 97") { } }; CPPUNIT_TEST_FIXTURE(Test, testTdf77964) { loadAndReload("tdf77964.doc"); // both images were loading as AT_PARA instead of AS_CHAR. Image2 visually had text wrapping. CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AS_CHARACTER, getProperty(getShapeByName(u"Image2"), "AnchorType")); } DECLARE_WW8EXPORT_TEST(testTdf150197_anlv2ListFormat, "tdf150197_anlv2ListFormat.doc") { CPPUNIT_ASSERT_EQUAL(OUString("1."), getProperty(getParagraph(2), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString("2."), getProperty(getParagraph(3), "ListLabelString")); CPPUNIT_ASSERT_EQUAL_MESSAGE("Did you fix me? I should be 2.1", OUString("4.1"), getProperty(getParagraph(4), "ListLabelString")); } DECLARE_WW8EXPORT_TEST(testTdf117994_CRnumformatting, "tdf117994_CRnumformatting.doc") { CPPUNIT_ASSERT_EQUAL(OUString("1."), parseDump("//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']"_ostr, "expand"_ostr)); //Without this fix in place, it would become 200 (and non-bold). CPPUNIT_ASSERT_EQUAL(OUString("160"), parseDump("//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']/SwFont"_ostr, "height"_ostr)); } DECLARE_WW8EXPORT_TEST(testTdf151548_formFieldMacros, "tdf151548_formFieldMacros.doc") { SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); for(auto aIter = pMarkAccess->getFieldmarksBegin(); aIter != pMarkAccess->getFieldmarksEnd(); ++aIter) { const OUString sName = (*aIter)->GetName(); CPPUNIT_ASSERT(sName == "Check1" || sName == "Check2" || sName == "Text1" || sName == "Dropdown1"); } } DECLARE_WW8EXPORT_TEST(testTdf141649_conditionalText, "tdf141649_conditionalText.doc") { // In MS Word, the IF field is editable and requires manual update, so the most correct // result is "manual refresh with F9" inside a text field, // but for our purposes, a single instance of "trueResult" is appropriate. getParagraph(1, "trueResult"); } DECLARE_WW8EXPORT_TEST(testTdf90408, "tdf90408.doc") { uno::Reference xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL_MESSAGE("checkbox is 16pt", 16.f, getProperty(xRun, "CharHeight")); xRun.set(getRun(getParagraph(1), 2, "unchecked"), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL_MESSAGE("text is 12pt", 12.f, getProperty(xRun, "CharHeight")); } DECLARE_WW8EXPORT_TEST(testTdf90408B, "tdf90408B.doc") { uno::Reference xTextTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY); uno::Reference xTable(xTables->getByIndex(0), uno::UNO_QUERY); uno::Reference xCell(xTable->getCellByName("A1"), uno::UNO_QUERY); uno::Reference xParaEnumAccess(xCell->getText(), uno::UNO_QUERY); uno::Reference xParaEnum = xParaEnumAccess->createEnumeration(); uno::Reference xPara(xParaEnum->nextElement(), uno::UNO_QUERY); uno::Reference xRun(getRun(xPara, 1), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL_MESSAGE("checkbox is 28pt", 28.f, getProperty(xRun, "CharHeight")); xRun.set(getRun(xPara, 2, u" Κατάψυξη, "_ustr), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL_MESSAGE("text is 10pt", 10.f, getProperty(xRun, "CharHeight")); } DECLARE_WW8EXPORT_TEST(testTdf155465_paraAdjustDistribute, "tdf155465_paraAdjustDistribute.doc") { // Without the accompanying fix in place, this test would have failed with // 'Expected: 2; Actual : 0', i.e. the first paragraph's ParaAdjust was left, not block. const style::ParagraphAdjust eBlock = style::ParagraphAdjust_BLOCK; auto nAdjust = getProperty(getParagraph(1), "ParaAdjust"); CPPUNIT_ASSERT_EQUAL(eBlock, static_cast(nAdjust)); nAdjust = getProperty(getParagraph(1), "ParaLastLineAdjust"); CPPUNIT_ASSERT_EQUAL(eBlock, static_cast(nAdjust)); nAdjust = getProperty(getParagraph(2), "ParaAdjust"); CPPUNIT_ASSERT_EQUAL(eBlock, static_cast(nAdjust)); nAdjust = getProperty(getParagraph(2), "ParaLastLineAdjust"); CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_LEFT, static_cast(nAdjust)); } CPPUNIT_TEST_FIXTURE(Test, testDontBreakWrappedTables) { // Given a document with the DO_NOT_BREAK_WRAPPED_TABLES compat mode enabled: createSwDoc(); { SwDoc* pDoc = getSwDoc(); IDocumentSettingAccess& rIDSA = pDoc->getIDocumentSettingAccess(); rIDSA.set(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES, true); } // When saving to doc: saveAndReload("MS Word 97"); // Then make sure the compat flag is serialized: SwDoc* pDoc = getSwDoc(); IDocumentSettingAccess& rIDSA = pDoc->getIDocumentSettingAccess(); bool bDontBreakWrappedTables = rIDSA.get(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES); // Without the accompanying fix in place, this test would have failed, the compat flag was not // set. CPPUNIT_ASSERT(bDontBreakWrappedTables); } CPPUNIT_TEST_FIXTURE(Test, testFloattableOverlapNeverDOCExport) { // Given a document with a floating table, overlap is not allowed: { createSwDoc(); SwDoc* pDoc = getSwDoc(); SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); pWrtShell->Insert2("before table"); // Insert a table: SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0); pWrtShell->InsertTable(aTableOptions, /*nRows=*/1, /*nCols=*/1); pWrtShell->MoveTable(GotoPrevTable, fnTableStart); // Select table: pWrtShell->SelAll(); // Wrap the table in a text frame: SwFlyFrameAttrMgr aMgr(true, pWrtShell, Frmmgr_Type::TEXT, nullptr); pWrtShell->StartAllAction(); aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PARA, aMgr.GetPos(), aMgr.GetSize()); pWrtShell->EndAllAction(); // Allow the text frame to split: pWrtShell->StartAllAction(); sw::FrameFormats* pFlys = pDoc->GetSpzFrameFormats(); sw::SpzFrameFormat* pFly = (*pFlys)[0]; SwAttrSet aSet(pFly->GetAttrSet()); aSet.Put(SwFormatFlySplit(true)); // Don't allow overlap: SwFormatWrapInfluenceOnObjPos aInfluence; aInfluence.SetAllowOverlap(false); aSet.Put(aInfluence); pDoc->SetAttr(aSet, *pFly); pWrtShell->EndAllAction(); } // When saving to DOC: saveAndReload("MS Word 97"); // Then make sure that the overlap=never markup is written: SwDoc* pDoc = getSwDoc(); sw::FrameFormats* pFlys = pDoc->GetSpzFrameFormats(); sw::SpzFrameFormat* pFly = (*pFlys)[0]; // Without the accompanying fix in place, this test would have failed, i.e. TFNoAllowOverlap was // not written. CPPUNIT_ASSERT(!pFly->GetAttrSet().GetWrapInfluenceOnObjPos().GetAllowOverlap()); } static bool IsFirstLine(const SwTextNode* pTextNode) { const SfxPoolItem* pItem = pTextNode->GetNoCondAttr(RES_MARGIN_FIRSTLINE, false); return !!pItem; } DECLARE_WW8EXPORT_TEST(testInlinePageBreakFirstLine, "inlinePageBreakFirstLine.doc") { SwDoc* pDoc = getSwDoc(); const SwNodes& rNodes = pDoc->GetNodes(); std::vector aTextNodes; for (SwNodeOffset nNode(0); nNode < rNodes.Count(); ++nNode) { SwNode* pNode = pDoc->GetNodes()[nNode]; SwTextNode* pTextNode = pNode->GetTextNode(); if (!pTextNode) continue; aTextNodes.push_back(pTextNode); } CPPUNIT_ASSERT_EQUAL(size_t(3), aTextNodes.size()); CPPUNIT_ASSERT_EQUAL(OUString("First line"), aTextNodes[0]->GetText()); CPPUNIT_ASSERT(IsFirstLine(aTextNodes[0])); // Here exists an inline pagebreak (a pagebreak without a paragraph before it) // This text node is not indented because it is not the first line of the paragraph CPPUNIT_ASSERT_EQUAL(OUString("Should not be indented"), aTextNodes[1]->GetText()); CPPUNIT_ASSERT(!IsFirstLine(aTextNodes[1])); // Here is the actual second paragraph CPPUNIT_ASSERT_EQUAL(OUString("Should be indented"), aTextNodes[2]->GetText()); CPPUNIT_ASSERT(IsFirstLine(aTextNodes[2])); } CPPUNIT_TEST_FIXTURE(Test, testLegalNumbering) { auto verify = [this]() { // Second level's numbering should use Arabic numbers for first level reference auto xPara = getParagraph(1); CPPUNIT_ASSERT_EQUAL(OUString("CH I"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(2); // Without the accompanying fix in place, this test would have failed with: // - Expected: Sect 1.01 // - Actual : Sect I.01 // i.e. fLegal was ignored on import/export. CPPUNIT_ASSERT_EQUAL(OUString("Sect 1.01"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(3); CPPUNIT_ASSERT_EQUAL(OUString("CH II"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(4); CPPUNIT_ASSERT_EQUAL(OUString("Sect 2.01"), getProperty(xPara, "ListLabelString")); }; createSwDoc("listWithLgl.doc"); verify(); saveAndReload(mpFilter); verify(); } CPPUNIT_TEST_FIXTURE(Test, testDOCExportDoNotMirrorRtlDrawObjs) { // Given a document with a shape, anchored in an RTL paragraph, loaded from DOCX: createSwDoc("draw-obj-rtl-no-mirror-vml.docx"); // When saving that to DOC: saveAndReload(mpFilter); // Then make sure the shape is on the right margin: xmlDocUniquePtr pXmlDoc = parseLayoutDump(); sal_Int32 nPageRight = getXPath(pXmlDoc, "//page/infos/bounds"_ostr, "right"_ostr).toInt32(); sal_Int32 nBodyRight = getXPath(pXmlDoc, "//body/infos/bounds"_ostr, "right"_ostr).toInt32(); sal_Int32 nShapeLeft = getXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds"_ostr, "left"_ostr).toInt32(); CPPUNIT_ASSERT_GREATER(nBodyRight, nShapeLeft); sal_Int32 nShapeRight = getXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds"_ostr, "right"_ostr).toInt32(); // Without the accompanying fix in place, this test would have failed with: // - Expected less than: 12523 // - Actual : 12536 // i.e. the shape was outside of the page right margin area, due to an unwanted mapping. CPPUNIT_ASSERT_LESS(nPageRight, nShapeRight); } DECLARE_WW8EXPORT_TEST(testNonInlinePageBreakFirstLine, "nonInlinePageBreakFirstLine.doc") { SwDoc* pDoc = getSwDoc(); const SwNodes& rNodes = pDoc->GetNodes(); std::vector aTextNodes; for (SwNodeOffset nNode(0); nNode < rNodes.Count(); ++nNode) { SwNode* pNode = pDoc->GetNodes()[nNode]; SwTextNode* pTextNode = pNode->GetTextNode(); if (!pTextNode) continue; aTextNodes.push_back(pTextNode); } CPPUNIT_ASSERT_EQUAL(size_t(2), aTextNodes.size()); CPPUNIT_ASSERT_EQUAL(OUString("First line"), aTextNodes[0]->GetText()); CPPUNIT_ASSERT(IsFirstLine(aTextNodes[0])); // Here exists a pagebreak after a paragraph // This text node is indented because it is the first line of a paragraph CPPUNIT_ASSERT_EQUAL(OUString("Should be indented"), aTextNodes[1]->GetText()); CPPUNIT_ASSERT(IsFirstLine(aTextNodes[1])); } DECLARE_WW8EXPORT_TEST(testTdf104704_mangledFooter, "tdf104704_mangledFooter.odt") { CPPUNIT_ASSERT_EQUAL(2, getPages()); } CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */