1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <swmodeltestbase.hxx>
12 #include <com/sun/star/beans/XPropertySet.hpp>
13 #include <com/sun/star/container/XIndexAccess.hpp>
14 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
15 #include <com/sun/star/graphic/XGraphic.hpp>
16 #include <com/sun/star/style/ParagraphAdjust.hpp>
17 #include <com/sun/star/text/TextContentAnchorType.hpp>
18 #include <com/sun/star/text/XTextDocument.hpp>
19 #include <com/sun/star/text/XTextFrame.hpp>
20 #include <com/sun/star/text/XTextTable.hpp>
21 #include <com/sun/star/text/WrapTextMode.hpp>
22 #include <com/sun/star/text/XTextField.hpp>
24 #include <comphelper/sequenceashashmap.hxx>
25 #include <o3tl/string_view.hxx>
26 #include <svx/svdpage.hxx>
29 #include <drawdoc.hxx>
30 #include <IDocumentDrawModelAccess.hxx>
31 #include <IDocumentMarkAccess.hxx>
32 #include <IDocumentSettingAccess.hxx>
33 #include <unotxdoc.hxx>
35 #include <editeng/lrspitem.hxx>
37 #include <itabenum.hxx>
39 #include <formatflysplit.hxx>
40 #include <fmtwrapinfluenceonobjpos.hxx>
41 #include <fmtftntx.hxx>
45 class Test
: public SwModelTestBase
49 : SwModelTestBase(u
"/sw/qa/extras/ww8export/data/"_ustr
, u
"MS Word 97"_ustr
)
54 CPPUNIT_TEST_FIXTURE(Test
, testTdf77964
)
56 loadAndReload("tdf77964.doc");
57 // both images were loading as AT_PARA instead of AS_CHAR. Image2 visually had text wrapping.
58 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AS_CHARACTER
, getProperty
<text::TextContentAnchorType
>(getShapeByName(u
"Image2"), u
"AnchorType"_ustr
));
61 DECLARE_WW8EXPORT_TEST(testTdf72511_editengLRSpace
, "tdf72511_editengLRSpace.doc")
63 // given a default paragraph style with a left indent of 2 inches,
64 // the comment should ignore the indent, but the textbox must not.
65 uno::Reference
<beans::XPropertySet
> xRun(
66 getProperty
<uno::Reference
<beans::XPropertySet
>>(getRun(getParagraph(1), 3), u
"TextField"_ustr
));
67 uno::Reference
<text::XText
> xComment(getProperty
<uno::Reference
<text::XText
>>(xRun
, u
"TextRange"_ustr
));
68 uno::Reference
<beans::XPropertySet
> xParagraph(getParagraphOfText(1, xComment
), uno::UNO_QUERY
);
69 // The comment was indented by 4001 (2 inches) instead of nothing
70 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xParagraph
, u
"ParaLeftMargin"_ustr
));
72 uno::Reference
<drawing::XShapes
> xGroupShape(getShape(1), uno::UNO_QUERY_THROW
);
73 uno::Reference
<drawing::XShape
> xShape2(xGroupShape
->getByIndex(1), uno::UNO_QUERY_THROW
);
74 CPPUNIT_ASSERT_EQUAL(u
"com.sun.star.drawing.TextShape"_ustr
, xShape2
->getShapeType());
75 uno::Reference
<text::XTextRange
> xTextbox(xShape2
, uno::UNO_QUERY_THROW
);
76 uno::Reference
<beans::XPropertySet
> xTBPara(xTextbox
, uno::UNO_QUERY
);
77 // Textbox paragraphs had no indent instead of 5080 (2 inches - the same as normal paragraphs).
78 CPPUNIT_ASSERT_EQUAL(sal_Int32(5080), getProperty
<sal_Int32
>(xTBPara
, u
"ParaLeftMargin"_ustr
));
79 CPPUNIT_ASSERT_EQUAL_MESSAGE("sanity check: normal paragraph's indent", sal_Int32(5080),
80 getProperty
<sal_Int32
>(getParagraph(1), u
"ParaLeftMargin"_ustr
));
83 DECLARE_WW8EXPORT_TEST(testTdf160049_anchorMargin
, "tdf160049_anchorMargin.doc")
85 // given a document with a LEFT "column/text" anchored image
87 // The image takes into account the margin, so it looks like it is in the middle of the doc,
88 // which is "Paragraph text area"/PRINT_AREA/1, not "Entire paragraph area"/FRAME/0
89 CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PRINT_AREA
,
90 getProperty
<sal_Int16
>(getShape(1), u
"HoriOrientRelation"_ustr
));
93 DECLARE_WW8EXPORT_TEST(testTdf150197_anlv2ListFormat
, "tdf150197_anlv2ListFormat.doc")
95 CPPUNIT_ASSERT_EQUAL(u
"1."_ustr
, getProperty
<OUString
>(getParagraph(2), u
"ListLabelString"_ustr
));
96 CPPUNIT_ASSERT_EQUAL(u
"2."_ustr
, getProperty
<OUString
>(getParagraph(3), u
"ListLabelString"_ustr
));
97 CPPUNIT_ASSERT_EQUAL_MESSAGE("Did you fix me? I should be 2.1", u
"4.1"_ustr
,
98 getProperty
<OUString
>(getParagraph(4), u
"ListLabelString"_ustr
));
101 DECLARE_WW8EXPORT_TEST(testTdf117994_CRnumformatting
, "tdf117994_CRnumformatting.doc")
103 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
104 assertXPath(pXmlDoc
, "//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", u
"1.");
105 //Without this fix in place, it would become 200 (and non-bold).
106 assertXPath(pXmlDoc
, "//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']/SwFont", "height", u
"160");
109 DECLARE_WW8EXPORT_TEST(testTdf151548_formFieldMacros
, "tdf151548_formFieldMacros.doc")
111 SwDoc
* pDoc
= getSwDoc();
112 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
113 for(auto aIter
= pMarkAccess
->getFieldmarksBegin(); aIter
!= pMarkAccess
->getFieldmarksEnd(); ++aIter
)
115 const OUString sName
= (*aIter
)->GetName();
116 CPPUNIT_ASSERT(sName
== "Check1" || sName
== "Check2" || sName
== "Text1" || sName
== "Dropdown1");
120 DECLARE_WW8EXPORT_TEST(testTdf141649_conditionalText
, "tdf141649_conditionalText.doc")
122 // In MS Word, the IF field is editable and requires manual update, so the most correct
123 // result is "manual refresh with F9" inside a text field,
124 // but for our purposes, a single instance of "trueResult" is appropriate.
125 getParagraph(1, u
"trueResult"_ustr
);
128 DECLARE_WW8EXPORT_TEST(testTdf91632_layoutInCellD
, "tdf91632_layoutInCellD.doc")
130 // given a table with two layoutInCell images, and cell A1 has 1/2 inch border padding (margin)
131 // - A1 contains an image, vertically aligned to the outside of the page (aka cell)
132 // - B1 contains an image, vertically aligned from top of the page (aka cell)
134 // In Microsoft's layoutInCell implementation, vertical "page" is identical to "margin",
135 // and everything (including center/bottom) actually is oriented to the top of the margin.
137 xmlDocUniquePtr pDump
= parseLayoutDump();
140 = getXPath(pDump
, "//tab/row[1]/cell[1]/txt[1]/anchored/fly/SwAnchoredObject/bounds",
143 sal_Int32 nShapeBottom
144 = getXPath(pDump
, "//tab/row[1]/cell[1]/txt[1]/anchored/fly/SwAnchoredObject/bounds",
147 // use paragraph 1 to indicate where the cell spacing/padding ends, and the text starts.
149 = getXPath(pDump
, "//tab/row[1]/cell[1]/txt[1]/infos/bounds", "top").toInt32();
150 // use paragraph 5 to prove the image is not at the bottom.
151 assertXPathContent(pDump
, "//tab/row[1]/cell[1]/txt[5]", u
"Below logo");
153 = getXPath(pDump
, "//tab/row[1]/cell[1]/txt[5]/infos/bounds", "top").toInt32();
154 CPPUNIT_ASSERT_EQUAL(nShapeTop
, nPara1Top
);
155 CPPUNIT_ASSERT(nPara5Top
> nShapeBottom
); // ShapeBottom is higher than Para5Top
157 // In the file it is specified as "page" (PAGE_FRAME), but implemented as if it were "margin"
158 // so on import we intentionally changed it to match the closest setting to the implementation.
159 const auto xShape
= getShape(1);
160 CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA
,
161 getProperty
<sal_Int16
>(xShape
, u
"VertOrientRelation"_ustr
));
163 CPPUNIT_ASSERT(getProperty
<bool>(xShape
, u
"IsFollowingTextFlow"_ustr
));
167 = getXPath(pDump
, "//tab/row[1]/cell[2]/txt[1]/anchored/fly/SwAnchoredObject/bounds",
171 = getXPath(pDump
, "//tab/row[1]/cell[2]/txt[1]/anchored/fly/SwAnchoredObject/bounds",
174 // use paragraph 1 to indicate where the cell spacing/padding ends, and the text starts.
176 = getXPath(pDump
, "//tab/row[1]/cell[2]/txt[1]/infos/bounds", "top").toInt32();
177 // use paragraph 5 to prove the image is not at the bottom.
178 assertXPathContent(pDump
, "//tab/row[1]/cell[2]/txt[5]", u
"Below image");
180 = getXPath(pDump
, "//tab[1]/row/cell[2]/txt[5]/infos/bounds", "top").toInt32();
181 CPPUNIT_ASSERT_EQUAL(nShapeTop
, nPara1Top
);
182 CPPUNIT_ASSERT(nPara5Top
> nShapeBottom
); // ShapeBottom is higher than Para5Top
184 const auto xShape2
= getShape(2);
185 CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA
,
186 getProperty
<sal_Int16
>(xShape2
, u
"VertOrientRelation"_ustr
));
188 CPPUNIT_ASSERT(getProperty
<bool>(xShape2
, u
"IsFollowingTextFlow"_ustr
));
191 DECLARE_WW8EXPORT_TEST(testTdf162541
, "tdf162541_notLayoutInCell_paraLeft.doc")
193 // Note: this file looks very strange in MS Word. The image splits the table into two...
195 // given cell B2 with a para-left para-fromTop image that is NOT layoutInCell
196 xmlDocUniquePtr pDump
= parseLayoutDump();
198 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt/anchored/fly/SwAnchoredObject/bounds",
202 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt/infos/bounds", "left").toInt32();
204 = getXPath(pDump
, "//tab/infos/bounds", "left").toInt32();
205 // The image uses the table-paragraph to orient to the left (bizarre MSO layout anomaly)
206 CPPUNIT_ASSERT(nShapeLeft
< nParaLeft
); // shape is located in column A, not column B
207 CPPUNIT_ASSERT_EQUAL(nTableLeft
, nShapeLeft
);
208 CPPUNIT_ASSERT(!getProperty
<bool>(getShape(1), u
"IsFollowingTextFlow"_ustr
));
211 DECLARE_WW8EXPORT_TEST(testTdf162542
, "tdf162542_notLayoutInCell_charLeft_wrapThrough.doc")
213 // given cell B2 with a char-oriented-left wrapThrough image that is NOT layoutInCell
214 xmlDocUniquePtr pDump
= parseLayoutDump();
216 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt[6]/anchored/fly/SwAnchoredObject/bounds",
220 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt[6]/infos/bounds", "left").toInt32();
221 CPPUNIT_ASSERT(nShapeLeft
> nPara6Left
); // nShapeLeft starts after the word "anchor"
223 // tdf#162551: The top is oriented to the top of the page - but MSO treats it as layoutInCell
225 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt[6]/anchored/fly/SwAnchoredObject/bounds",
229 = getXPath(pDump
, "//tab/row[2]/cell[2]/txt[1]/infos/bounds", "top").toInt32();
230 // layoutInCell uses the cell margin as the top-most point, not the cell edge
231 CPPUNIT_ASSERT_EQUAL(nPara1Top
, nShapeTop
); // nShapeTop starts at the cell margin"
233 // since in fact layoutInCell is supposed to be applied, we mark (and export) as layoutInCell
234 CPPUNIT_ASSERT(getProperty
<bool>(getShape(1), u
"IsFollowingTextFlow"_ustr
)); // tdf#162551
237 CPPUNIT_TEST_FIXTURE(Test
, testEndnotesAtSectEndDOC
)
239 // Given a document, endnotes at collected at section end:
242 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
243 pWrtShell
->SplitNode();
244 pWrtShell
->Up(/*bSelect=*/false);
245 pWrtShell
->Insert(u
"x"_ustr
);
246 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/true, 1, /*bBasicCall=*/false);
247 SwSectionData
aSection(SectionType::Content
, pWrtShell
->GetUniqueSectionName());
248 pWrtShell
->StartAction();
249 SfxItemSetFixed
<RES_FTN_AT_TXTEND
, RES_FRAMEDIR
> aSet(pWrtShell
->GetAttrPool());
250 aSet
.Put(SwFormatEndAtTextEnd(FTNEND_ATTXTEND
));
251 pWrtShell
->InsertSection(aSection
, &aSet
);
252 pWrtShell
->EndAction();
253 pWrtShell
->InsertFootnote(OUString(), /*bEndNote=*/true);
256 // When saving to DOC:
257 saveAndReload(u
"MS Word 97"_ustr
);
259 // Then make sure the endnote position is section end:
260 SwDoc
* pDoc
= getSwDoc();
261 SwSectionFormats
& rSections
= pDoc
->GetSections();
262 SwSectionFormat
* pFormat
= rSections
[0];
263 // Without the accompanying fix in place, this test would have failed, endnotes were at doc end.
264 CPPUNIT_ASSERT(pFormat
->GetEndAtTextEnd().IsAtEnd());
267 DECLARE_WW8EXPORT_TEST(testTdf90408
, "tdf90408.doc")
269 uno::Reference
<beans::XPropertySet
> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY_THROW
);
270 CPPUNIT_ASSERT_EQUAL_MESSAGE("checkbox is 16pt", 16.f
, getProperty
<float>(xRun
, u
"CharHeight"_ustr
));
271 xRun
.set(getRun(getParagraph(1), 2, u
"unchecked"_ustr
), uno::UNO_QUERY_THROW
);
272 CPPUNIT_ASSERT_EQUAL_MESSAGE("text is 12pt", 12.f
, getProperty
<float>(xRun
, u
"CharHeight"_ustr
));
275 DECLARE_WW8EXPORT_TEST(testTdf90408B
, "tdf90408B.doc")
277 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(mxComponent
, uno::UNO_QUERY
);
278 uno::Reference
<container::XIndexAccess
> xTables(xTextTablesSupplier
->getTextTables(), uno::UNO_QUERY
);
279 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY
);
280 uno::Reference
<text::XTextRange
> xCell(xTable
->getCellByName(u
"A1"_ustr
), uno::UNO_QUERY
);
282 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xCell
->getText(), uno::UNO_QUERY
);
283 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
284 uno::Reference
<text::XTextRange
> xPara(xParaEnum
->nextElement(), uno::UNO_QUERY
);
286 uno::Reference
<beans::XPropertySet
> xRun(getRun(xPara
, 1), uno::UNO_QUERY_THROW
);
287 CPPUNIT_ASSERT_EQUAL_MESSAGE("checkbox is 28pt", 28.f
, getProperty
<float>(xRun
, u
"CharHeight"_ustr
));
288 xRun
.set(getRun(xPara
, 2, u
" Κατάψυξη, "_ustr
), uno::UNO_QUERY_THROW
);
289 CPPUNIT_ASSERT_EQUAL_MESSAGE("text is 10pt", 10.f
, getProperty
<float>(xRun
, u
"CharHeight"_ustr
));
292 DECLARE_WW8EXPORT_TEST(testTdf155465_paraAdjustDistribute
, "tdf155465_paraAdjustDistribute.doc")
294 // Without the accompanying fix in place, this test would have failed with
295 // 'Expected: 2; Actual : 0', i.e. the first paragraph's ParaAdjust was left, not block.
296 const style::ParagraphAdjust eBlock
= style::ParagraphAdjust_BLOCK
;
297 auto nAdjust
= getProperty
<sal_Int16
>(getParagraph(1), u
"ParaAdjust"_ustr
);
298 CPPUNIT_ASSERT_EQUAL(eBlock
, static_cast<style::ParagraphAdjust
>(nAdjust
));
300 nAdjust
= getProperty
<sal_Int16
>(getParagraph(1), u
"ParaLastLineAdjust"_ustr
);
301 CPPUNIT_ASSERT_EQUAL(eBlock
, static_cast<style::ParagraphAdjust
>(nAdjust
));
303 nAdjust
= getProperty
<sal_Int16
>(getParagraph(2), u
"ParaAdjust"_ustr
);
304 CPPUNIT_ASSERT_EQUAL(eBlock
, static_cast<style::ParagraphAdjust
>(nAdjust
));
306 nAdjust
= getProperty
<sal_Int16
>(getParagraph(2), u
"ParaLastLineAdjust"_ustr
);
307 CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_LEFT
, static_cast<style::ParagraphAdjust
>(nAdjust
));
310 CPPUNIT_TEST_FIXTURE(Test
, testDontBreakWrappedTables
)
312 // Given a document with the DO_NOT_BREAK_WRAPPED_TABLES compat mode enabled:
315 SwDoc
* pDoc
= getSwDoc();
316 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
317 rIDSA
.set(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
, true);
320 // When saving to doc:
321 saveAndReload(u
"MS Word 97"_ustr
);
323 // Then make sure the compat flag is serialized:
324 SwDoc
* pDoc
= getSwDoc();
325 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
326 bool bDontBreakWrappedTables
= rIDSA
.get(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
);
327 // Without the accompanying fix in place, this test would have failed, the compat flag was not
329 CPPUNIT_ASSERT(bDontBreakWrappedTables
);
332 CPPUNIT_TEST_FIXTURE(Test
, testFloattableOverlapNeverDOCExport
)
334 // Given a document with a floating table, overlap is not allowed:
337 SwDoc
* pDoc
= getSwDoc();
338 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
339 pWrtShell
->Insert2(u
"before table"_ustr
);
341 SwInsertTableOptions
aTableOptions(SwInsertTableFlags::DefaultBorder
, 0);
342 pWrtShell
->InsertTable(aTableOptions
, /*nRows=*/1, /*nCols=*/1);
343 pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
);
346 // Wrap the table in a text frame:
347 SwFlyFrameAttrMgr
aMgr(true, pWrtShell
, Frmmgr_Type::TEXT
, nullptr);
348 pWrtShell
->StartAllAction();
349 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PARA
, aMgr
.GetPos(), aMgr
.GetSize());
350 pWrtShell
->EndAllAction();
351 // Allow the text frame to split:
352 pWrtShell
->StartAllAction();
353 sw::FrameFormats
<sw::SpzFrameFormat
*>* pFlys
= pDoc
->GetSpzFrameFormats();
354 sw::SpzFrameFormat
* pFly
= (*pFlys
)[0];
355 SwAttrSet
aSet(pFly
->GetAttrSet());
356 aSet
.Put(SwFormatFlySplit(true));
357 // Don't allow overlap:
358 SwFormatWrapInfluenceOnObjPos aInfluence
;
359 aInfluence
.SetAllowOverlap(false);
360 aSet
.Put(aInfluence
);
361 pDoc
->SetAttr(aSet
, *pFly
);
362 pWrtShell
->EndAllAction();
365 // When saving to DOC:
366 saveAndReload(u
"MS Word 97"_ustr
);
368 // Then make sure that the overlap=never markup is written:
369 SwDoc
* pDoc
= getSwDoc();
370 sw::FrameFormats
<sw::SpzFrameFormat
*>* pFlys
= pDoc
->GetSpzFrameFormats();
371 sw::SpzFrameFormat
* pFly
= (*pFlys
)[0];
372 // Without the accompanying fix in place, this test would have failed, i.e. TFNoAllowOverlap was
374 CPPUNIT_ASSERT(!pFly
->GetAttrSet().GetWrapInfluenceOnObjPos().GetAllowOverlap());
377 bool IsFirstLine(const SwTextNode
* pTextNode
)
379 const SfxPoolItem
* pItem
= pTextNode
->GetNoCondAttr(RES_MARGIN_FIRSTLINE
, false);
383 DECLARE_WW8EXPORT_TEST(testInlinePageBreakFirstLine
, "inlinePageBreakFirstLine.doc")
385 SwDoc
* pDoc
= getSwDoc();
386 const SwNodes
& rNodes
= pDoc
->GetNodes();
388 std::vector
<SwTextNode
*> aTextNodes
;
390 for (SwNodeOffset
nNode(0); nNode
< rNodes
.Count(); ++nNode
)
392 SwNode
* pNode
= pDoc
->GetNodes()[nNode
];
393 SwTextNode
* pTextNode
= pNode
->GetTextNode();
396 aTextNodes
.push_back(pTextNode
);
399 CPPUNIT_ASSERT_EQUAL(size_t(3), aTextNodes
.size());
400 CPPUNIT_ASSERT_EQUAL(u
"First line"_ustr
, aTextNodes
[0]->GetText());
401 CPPUNIT_ASSERT(IsFirstLine(aTextNodes
[0]));
402 // Here exists an inline pagebreak (a pagebreak without a paragraph before it)
403 // This text node is not indented because it is not the first line of the paragraph
404 CPPUNIT_ASSERT_EQUAL(u
"Should not be indented"_ustr
, aTextNodes
[1]->GetText());
405 CPPUNIT_ASSERT(!IsFirstLine(aTextNodes
[1]));
406 // Here is the actual second paragraph
407 CPPUNIT_ASSERT_EQUAL(u
"Should be indented"_ustr
, aTextNodes
[2]->GetText());
408 CPPUNIT_ASSERT(IsFirstLine(aTextNodes
[2]));
411 CPPUNIT_TEST_FIXTURE(Test
, testLegalNumbering
)
413 auto verify
= [this]() {
414 // Second level's numbering should use Arabic numbers for first level reference
415 auto xPara
= getParagraph(1);
416 CPPUNIT_ASSERT_EQUAL(u
"CH I"_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
417 xPara
= getParagraph(2);
418 // Without the accompanying fix in place, this test would have failed with:
419 // - Expected: Sect 1.01
420 // - Actual : Sect I.01
421 // i.e. fLegal was ignored on import/export.
422 CPPUNIT_ASSERT_EQUAL(u
"Sect 1.01"_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
423 xPara
= getParagraph(3);
424 CPPUNIT_ASSERT_EQUAL(u
"CH II"_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
425 xPara
= getParagraph(4);
426 CPPUNIT_ASSERT_EQUAL(u
"Sect 2.01"_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
429 createSwDoc("listWithLgl.doc");
431 saveAndReload(mpFilter
);
435 CPPUNIT_TEST_FIXTURE(Test
, testDOCExportDoNotMirrorRtlDrawObjs
)
437 // Given a document with a shape, anchored in an RTL paragraph, loaded from DOCX:
438 createSwDoc("draw-obj-rtl-no-mirror-vml.docx");
440 // When saving that to DOC:
441 saveAndReload(mpFilter
);
443 // Then make sure the shape is on the right margin:
444 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
445 sal_Int32 nPageRight
= getXPath(pXmlDoc
, "//page/infos/bounds", "right").toInt32();
446 sal_Int32 nBodyRight
= getXPath(pXmlDoc
, "//body/infos/bounds", "right").toInt32();
448 = getXPath(pXmlDoc
, "//SwAnchoredDrawObject/bounds", "left").toInt32();
449 CPPUNIT_ASSERT_GREATER(nBodyRight
, nShapeLeft
);
450 sal_Int32 nShapeRight
451 = getXPath(pXmlDoc
, "//SwAnchoredDrawObject/bounds", "right").toInt32();
452 // Without the accompanying fix in place, this test would have failed with:
453 // - Expected less than: 12523
455 // i.e. the shape was outside of the page right margin area, due to an unwanted mapping.
456 CPPUNIT_ASSERT_LESS(nPageRight
, nShapeRight
);
459 DECLARE_WW8EXPORT_TEST(testNonInlinePageBreakFirstLine
, "nonInlinePageBreakFirstLine.doc")
461 SwDoc
* pDoc
= getSwDoc();
462 const SwNodes
& rNodes
= pDoc
->GetNodes();
464 std::vector
<SwTextNode
*> aTextNodes
;
466 for (SwNodeOffset
nNode(0); nNode
< rNodes
.Count(); ++nNode
)
468 SwNode
* pNode
= pDoc
->GetNodes()[nNode
];
469 SwTextNode
* pTextNode
= pNode
->GetTextNode();
472 aTextNodes
.push_back(pTextNode
);
475 CPPUNIT_ASSERT_EQUAL(size_t(2), aTextNodes
.size());
476 CPPUNIT_ASSERT_EQUAL(u
"First line"_ustr
, aTextNodes
[0]->GetText());
477 CPPUNIT_ASSERT(IsFirstLine(aTextNodes
[0]));
478 // Here exists a pagebreak after a paragraph
479 // This text node is indented because it is the first line of a paragraph
480 CPPUNIT_ASSERT_EQUAL(u
"Should be indented"_ustr
, aTextNodes
[1]->GetText());
481 CPPUNIT_ASSERT(IsFirstLine(aTextNodes
[1]));
484 DECLARE_WW8EXPORT_TEST(testTdf104704_mangledFooter
, "tdf104704_mangledFooter.odt")
486 CPPUNIT_ASSERT_EQUAL(2, getPages());
489 CPPUNIT_TEST_FIXTURE(Test
, testEmptyGroup
)
491 // Given a document with an empty group
492 createSwDoc("empty_group.docx");
494 CPPUNIT_ASSERT_EQUAL(1, getPages());
495 CPPUNIT_ASSERT_EQUAL(1, getShapes());
496 SwDoc
* pDoc
= getSwDoc();
497 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
498 SdrObject
* pObject
= pPage
->GetObj(0);
500 CPPUNIT_ASSERT_EQUAL(u
"Empty group"_ustr
, pObject
->GetName());
501 CPPUNIT_ASSERT(pObject
->IsGroupObject());
502 CPPUNIT_ASSERT_EQUAL(size_t(0), pObject
->GetSubList()->GetObjCount());
504 // it must not assert/crash on save
505 saveAndReload(mpFilter
);
508 CPPUNIT_TEST_FIXTURE(Test
, testTdf135709
)
510 createSwDoc("tdf135709.odt");
511 saveAndReload("MS Word 97");
513 uno::Reference
<text::XTextFramesSupplier
> xTextFramesSupplier(mxComponent
, uno::UNO_QUERY
);
514 uno::Reference
<beans::XPropertySet
> xPropertySet(xTextFramesSupplier
->getTextFrames()->getByName("Frame1") , uno::UNO_QUERY
);
516 xPropertySet
->setPropertyValue("AnchorType",
517 uno::Any(text::TextContentAnchorType_AT_CHARACTER
));
519 text::WrapTextMode eValue
;
520 xPropertySet
->getPropertyValue("Surround") >>= eValue
;
521 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrap should be PARALLEL", text::WrapTextMode_PARALLEL
, eValue
);
524 CPPUNIT_TEST_FIXTURE(Test
, testTdf135710
)
526 // Uses same test doc as testTdf135709
527 createSwDoc("tdf135709.odt");
528 saveAndReload("MS Word 97");
530 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
532 sal_Int32 nFlyLeft
= getXPath(pXmlDoc
, "(//anchored)[1]/fly/infos/bounds", "left").toInt32();
534 // Set the anchor of the image to AT PARAGRAPH, without the fix in place this
535 // results in the picture moving to the first column
536 uno::Reference
<text::XTextFramesSupplier
> xTextFramesSupplier(mxComponent
, uno::UNO_QUERY
);
537 uno::Reference
<beans::XPropertySet
> xPropertySet(xTextFramesSupplier
->getTextFrames()->getByName("Frame1") , uno::UNO_QUERY
);
538 xPropertySet
->setPropertyValue("AnchorType",
539 uno::Any(text::TextContentAnchorType_AT_PARAGRAPH
));
540 pXmlDoc
= parseLayoutDump();
542 sal_Int32 nFlyLeftAfter
= getXPath(pXmlDoc
, "(//anchored)[1]/fly/infos/bounds", "left").toInt32();
544 // Without the fix in place this fails with
547 // i.e. the picture has moved from the second column to the first column
548 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(nFlyLeft
), static_cast<double>(nFlyLeftAfter
), 2.0);
551 CPPUNIT_TEST_FIXTURE(Test
, testTdf56738
)
553 auto verify
= [this]() {
554 uno::Reference
<text::XTextFieldsSupplier
> xTextFieldsSupplier(mxComponent
, uno::UNO_QUERY
);
555 uno::Reference
<container::XEnumerationAccess
> xFieldsAccess(xTextFieldsSupplier
->getTextFields());
556 uno::Reference
<container::XEnumeration
> xFields(xFieldsAccess
->createEnumeration());
558 // make sure we get to the correct field to test
559 CPPUNIT_ASSERT(xFields
->hasMoreElements());
560 uno::Reference
<text::XTextField
> xField
;
561 xField
.set(xFields
->nextElement(), uno::UNO_QUERY
);
562 CPPUNIT_ASSERT_EQUAL(u
"2"_ustr
, xField
->getPresentation(false));
564 CPPUNIT_ASSERT(xFields
->hasMoreElements());
565 xField
.set(xFields
->nextElement(), uno::UNO_QUERY_THROW
);
566 CPPUNIT_ASSERT_EQUAL(u
"3"_ustr
, xField
->getPresentation(false));
568 CPPUNIT_ASSERT(xFields
->hasMoreElements());
569 xField
.set(xFields
->nextElement(), uno::UNO_QUERY_THROW
);
570 OUString
sExpComment1(u
"Como eu vou saber se é a USG é anterior a 20s????"_ustr
);
571 CPPUNIT_ASSERT_EQUAL(sExpComment1
, getProperty
<OUString
>(xField
, u
"Content"_ustr
));
573 CPPUNIT_ASSERT(xFields
->hasMoreElements());
574 xField
.set(xFields
->nextElement(), uno::UNO_QUERY_THROW
);
576 OUString
sExpComment(u
"Não sei se é relevante esta pergunta. O que eu queria saber é se o médico ate\
577 nde muito parto na água. Tb posso fazer porcentagem de atendimento..."_ustr
);
579 // Without the fix in place this fails with
580 // Expected: Não sei se é relevante esta pergunta. O que eu queria saber é
581 // se o médico atende muito parto na água. Tb posso fazer porcentagem de atendimento...
582 // Actual: N縊 sei se �relevante esta pergunta. O que eu queria saber �
583 // se o m馘ico atende muito parto na 疊ua. Tb posso fazer porcentagem de atendimento...
584 // i.e. the display characters of the second comment were getting re-interpreted from Latin-1 to Shift-Js
585 CPPUNIT_ASSERT_EQUAL(sExpComment
, getProperty
<OUString
>(xField
, u
"Content"_ustr
));
588 // make sure everything survives roundtrip
589 createSwDoc("tdf56738.doc");
591 saveAndReload(mpFilter
);
595 CPPUNIT_TEST_FIXTURE(Test
, testTdf120629
)
597 createSwDoc("tdf120629.odt");
599 sal_Int16 numFormat
= getNumberingTypeOfParagraph(1);
600 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16
>(56), numFormat
);
602 saveAndReload("MS Word 97");
603 sal_Int16 numFormat_after
= getNumberingTypeOfParagraph(1);
604 // Without the fix in place this fails with
607 // i.e. numbering type gets changed to ARABIC, should stay the same
608 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16
>(56), numFormat_after
);
611 CPPUNIT_TEST_FIXTURE(Test
, testTdf54862
)
613 createSwDoc("tdf54862.doc");
614 auto verify
= [this]() {
615 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
616 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(), uno::UNO_QUERY
);
617 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables
->getCount());
619 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
621 sal_Int32 nCellA2Height
= getXPath(pXmlDoc
, "//tab/row[1]/cell[2]/infos/bounds", "height").toInt32();
622 sal_Int32 nCellB4Height
= getXPath(pXmlDoc
, "//tab/row[4]/cell[2]/infos/bounds", "height").toInt32();
624 // Without the fix in place this is this fails with:
625 // Expected: 1269, 9021
627 // i.e. Cells A2 and B4 are not vertically merged, making them the wrong height
628 CPPUNIT_ASSERT_EQUAL(sal_Int32(1269), nCellA2Height
);
629 CPPUNIT_ASSERT_EQUAL(sal_Int32(9021), nCellB4Height
);
633 saveAndReload(mpFilter
);
637 DECLARE_WW8EXPORT_TEST(testTdf85435
, "tdf85435.doc")
639 // Without the fix, this document only has one page.
640 CPPUNIT_ASSERT_EQUAL(2, getPages());
643 } // end of anonymous namespace
644 CPPUNIT_PLUGIN_IMPLEMENT();
646 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */