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>
14 #include <com/sun/star/awt/FontStrikeout.hpp>
15 #include <com/sun/star/beans/NamedValue.hpp>
16 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
17 #include <com/sun/star/drawing/XShapes.hpp>
18 #include <com/sun/star/frame/XStorable.hpp>
19 #include <com/sun/star/text/GraphicCrop.hpp>
20 #include <com/sun/star/text/RelOrientation.hpp>
21 #include <com/sun/star/text/WritingMode2.hpp>
22 #include <com/sun/star/text/XFootnotesSupplier.hpp>
23 #include <com/sun/star/text/XTextDocument.hpp>
24 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
25 #include <com/sun/star/text/XTextField.hpp>
26 #include <com/sun/star/util/XRefreshable.hpp>
29 #include <comphelper/propertysequence.hxx>
30 #include <comphelper/scopeguard.hxx>
31 #include <comphelper/sequenceashashmap.hxx>
32 #include <o3tl/string_view.hxx>
33 #include <comphelper/propertyvalue.hxx>
35 #include <unotxdoc.hxx>
40 class Test
: public SwModelTestBase
43 Test() : SwModelTestBase(u
"/sw/qa/extras/ooxmlexport/data/"_ustr
, u
"Office Open XML Text"_ustr
) {}
46 CPPUNIT_TEST_FIXTURE(Test
, testTdf150197_predefinedNumbering
)
50 // The exact numbering style doesn't matter - just any non-bullet pre-defined numbering style.
51 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
52 { "Style", uno::Any(u
"Numbering 123"_ustr
) },
53 { "FamilyName", uno::Any(u
"NumberingStyles"_ustr
) },
55 dispatchCommand(mxComponent
, u
".uno:StyleApply"_ustr
, aPropertyValues
);
57 CPPUNIT_ASSERT_EQUAL(u
"1."_ustr
, getProperty
<OUString
>(getParagraph(1), u
"ListLabelString"_ustr
));
59 saveAndReload(u
"Office Open XML Text"_ustr
);
60 CPPUNIT_ASSERT_EQUAL(u
"1."_ustr
, getProperty
<OUString
>(getParagraph(1), u
"ListLabelString"_ustr
));
63 CPPUNIT_TEST_FIXTURE(Test
, testInlineSdtHeader
)
65 // Without the accompanying fix in place, this test would have failed with an assertion failure,
66 // we produced not-well-formed XML on save.
67 loadAndSave("inline-sdt-header.docx");
70 CPPUNIT_TEST_FIXTURE(Test
, testCellSdtRedline
)
72 // Without the accompanying fix in place, this test would have failed with an assertion failure,
73 // we produced not-well-formed XML on save.
74 loadAndSave("cell-sdt-redline.docx");
77 CPPUNIT_TEST_FIXTURE(Test
, testTdf148956_directEndFormatting
)
79 auto verify
= [this](bool bIsExport
= false) {
80 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
82 // pWrtShell->EndPara(/*bSelect=*/true);
83 dispatchCommand(mxComponent
, u
".uno:GotoEndOfPara"_ustr
, {});
86 CPPUNIT_ASSERT_MESSAGE(
87 "Has direct formatting",
88 pWrtShell
->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints());
92 CPPUNIT_ASSERT_MESSAGE(
93 "Direct formatting cleared",
94 !pWrtShell
->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints());
97 pWrtShell
->SttPara(/*bSelect=*/true);
98 dispatchCommand(mxComponent
, u
".uno:ResetAttributes"_ustr
, {});
100 dispatchCommand(mxComponent
, u
".uno:GotoEndOfPara"_ustr
, {});
102 CPPUNIT_ASSERT_MESSAGE(
103 "Direct formatting cleared",
104 !pWrtShell
->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints());
106 createSwDoc("tdf148956_directEndFormatting.docx");
108 saveAndReload(mpFilter
);
109 verify(/*bIsExport*/ true);
112 DECLARE_OOXMLEXPORT_TEST(testTdf147646
, "tdf147646_mergedCellNumbering.docx")
114 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
115 //Without the fix in place, it would have failed with
119 assertXPath(pXmlDoc
, "/root/page/body/tab/row[4]/cell/txt/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']","expand",u
"2.");
122 DECLARE_OOXMLEXPORT_TEST(testTdf153526_commentInNumbering
, "tdf153526_commentInNumbering.docx")
124 // an exception was prematurely ending finishParagraph, losing numbering and CRs
125 // so before the patch, this was 6.
126 CPPUNIT_ASSERT_EQUAL(13, getParagraphs());
129 CPPUNIT_TEST_FIXTURE(Test
, testTdf153042_largeTab
)
131 createSwDoc("tdf153042_largeTab.docx");
132 // This is not the greatest test because it is slightly weird, and has a different layout
133 // in MS Word 2010/2003 than it does in Word 2019. This tests for the 2019 layout.
134 // Additionally (in Word 2019), going to paragraph properties and hitting OK changes the layout.
135 // It changes back by going to outline numbering properties and hitting OK.
137 // export does not keep the tabstop when exporting non-numbering. (Probably a good thing...)
139 xmlDocUniquePtr pLayout
= parseLayoutDump();
140 // Ensure a large tabstop is used in the pseudo-numbering (numbering::NONE followed by tabstop)
141 assertXPath(pLayout
, "//SwFixPortion", "width", u
"1701");
144 CPPUNIT_TEST_FIXTURE(Test
, testTdf153042_noTab
)
146 createSwDoc("tdf153042_noTab.docx");
147 // This is not the greatest test because it is slightly weird.
148 // It is the same as the "largeTab" file, except the paragraph properties were viewed
149 // and OK'ed, and now it looks like how Word 2010 and 2003 were laying it out.
150 // Amazingly, LO is handling both documents correctly at the moment, so let's unit test that...
152 // export does not keep the tabstop when exporting non-numbering. (Probably a good thing...)
153 xmlDocUniquePtr pLayout
= parseLayoutDump();
154 // Ensure a miniscule tab is used in the pseudo-numbering (numbering::NONE followed by tabstop)
155 assertXPath(pLayout
, "//SwFixPortion", "width", u
"10");
158 DECLARE_OOXMLEXPORT_TEST(testTdf154751_dualStrikethrough
, "tdf154751_dualStrikethrough.docx")
160 auto nStrike
= getProperty
<sal_Int16
>(getRun(getParagraph(1), 1), u
"CharStrikeout"_ustr
);
161 CPPUNIT_ASSERT_EQUAL(awt::FontStrikeout::SINGLE
, nStrike
);
164 CPPUNIT_TEST_FIXTURE(Test
, testTdf154478
)
166 loadAndSave("tdf154478.docx");
167 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/comments.xml"_ustr
);
169 OUString aValues
[5] = { u
"Comment1 seen."_ustr
, u
"Comment2 seen."_ustr
, u
"Comment3 NOTseen."_ustr
, u
"Comment4 NOTseen."_ustr
, u
"Comment5 NOTseen."_ustr
};
170 for (size_t i
= 1; i
< 6; ++i
)
172 OString sPath
= "/w:comments/w:comment[" + OString::number(i
) + "]/w:p/w:r/w:t";
174 // Without the fix in place, this test would have failed with
175 // - In <>, XPath '/w:comments/w:comment[3]/w:p/w:r/w:t' not found
176 assertXPathContent(pXmlDoc
, sPath
, aValues
[i
- 1]);
180 CPPUNIT_TEST_FIXTURE(Test
, testTdf153592_columnBreaks
)
182 loadAndSave("tdf153592_columnBreaks.docx");
184 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
185 // The two column breaks were lost on import. (I wouldn't complain if they were at 3,5)
186 assertXPath(pXmlDoc
, "//w:br", 2);
189 DECLARE_OOXMLEXPORT_TEST(testTdf104394_lostTextbox
, "tdf104394_lostTextbox.docx")
191 // This was only one page b/c the textbox was missing.
192 CPPUNIT_ASSERT_EQUAL(2, getPages());
195 DECLARE_OOXMLEXPORT_TEST(testTdf164500_framePrBeforeTable
, "tdf164500_framePrBeforeTable.docx")
197 // Should be only one page (but was two because the frame was anchored inside cell A1,
198 // and thus the width was limited by the cell width. It must be anchored before the table.
199 CPPUNIT_ASSERT_EQUAL(1, getPages());
200 CPPUNIT_ASSERT_EQUAL(1, getShapes()); // one text frame
202 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY_THROW
);
203 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(), uno::UNO_QUERY_THROW
);
204 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTables
->getCount());
207 DECLARE_OOXMLEXPORT_TEST(testTdf146984_anchorInShape
, "tdf146984_anchorInShape.docx")
209 // This was only one page b/c the page break was missing.
210 CPPUNIT_ASSERT_EQUAL(2, getPages());
213 DECLARE_OOXMLEXPORT_TEST(testTdf127622_framePr
, "tdf127622_framePr.docx")
215 // All the paragraphs end up with the same frame definition, so put them all in one frame
216 CPPUNIT_ASSERT_EQUAL(1, getShapes());
219 DECLARE_OOXMLEXPORT_TEST(testTdf105035_framePrB
, "tdf105035_framePrB.docx")
221 // The paragraphs have different frame definitions, so they must be in separate frames,
222 // and the frames must not overlap - even though their vertical positions are identical.
223 xmlDocUniquePtr pLayout
= parseLayoutDump();
224 sal_Int32 n1stFlyBottom
225 = getXPath(pLayout
, "//page[1]//anchored/fly[1]/infos/bounds", "bottom").toInt32();
227 = getXPath(pLayout
, "//page[1]//anchored/fly[2]/infos/bounds", "top").toInt32();
228 CPPUNIT_ASSERT_GREATER(n1stFlyBottom
, n2ndFlyTop
); //Top is greater than bottom
230 // Impossible layout TODO: the textboxes are in the wrong order.
231 OUString
sTextBox1(u
"Preparation of Papers for IEEE TRANSACTIONS and JOURNALS (November 2012)"_ustr
);
232 CPPUNIT_ASSERT_MESSAGE("DID YOU FIX ME? Wow - I didn't think this would be possible!",
233 !getXPathContent(pLayout
, "//page[1]//anchored/fly[1]/txt").startsWith(sTextBox1
));
236 DECLARE_OOXMLEXPORT_TEST(testTdf105035_framePrC
, "tdf105035_framePrC.docx")
238 // The paragraphs have different frame definitions, so they must be in separate frames,
239 // and the frames DO overlap this time.
240 xmlDocUniquePtr pLayout
= parseLayoutDump();
242 = getXPath(pLayout
, "//page[1]//anchored/fly[1]/infos/bounds", "top").toInt32();
244 = getXPath(pLayout
, "//page[1]//anchored/fly[2]/infos/bounds", "top").toInt32();
245 CPPUNIT_ASSERT_EQUAL(n1stFlyTop
, n2ndFlyTop
); //both frames start at the same position
248 DECLARE_OOXMLEXPORT_TEST(testTdf154129_framePr1
, "tdf154129_framePr1.docx")
250 for (size_t i
= 1; i
< 4; ++i
)
252 uno::Reference
<drawing::XShape
> xTextFrame
= getShape(i
);
253 // The anchor is defined in the style, and only the first style was checked, not the parents
254 auto nAnchor
= getProperty
<sal_Int16
>(xTextFrame
, u
"HoriOrientRelation"_ustr
);
255 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME
, nAnchor
);
256 nAnchor
= getProperty
<sal_Int16
>(xTextFrame
, u
"VertOrientRelation"_ustr
);
257 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME
, nAnchor
);
261 DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePr
, "tdf154703_framePr.docx")
263 // the frame conversion had been failing, so it imported as plain text only.
264 CPPUNIT_ASSERT_EQUAL(1, getShapes());
267 CPPUNIT_TEST_FIXTURE(Test
, testTdf154703_framePr2
)
269 auto verify
= [this](bool bIsExport
= false) {
270 // framePr frames are always imported as fully transparent
271 CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty
<sal_Int16
>(getShape(1), u
"FillTransparence"_ustr
));
273 // as opposed to testLibreOfficeHang (RTF != INVERT_BORDER_SPACING) do not duplicate left/right
274 uno::Reference
<text::XTextRange
> xTextRange(getShape(1), uno::UNO_QUERY
);
275 uno::Reference
<text::XText
> xText
= xTextRange
->getText();
276 CPPUNIT_ASSERT_EQUAL(u
"framePr"_ustr
, getParagraphOfText(1, xText
)->getString());
277 sal_Int32 nFrame
= getProperty
<sal_Int32
>(getShape(1), u
"LeftBorderDistance"_ustr
);
278 sal_Int32 nPara
= getProperty
<sal_Int32
>(getParagraphOfText(1, xText
), u
"LeftBorderDistance"_ustr
);
279 if (!bIsExport
) // RTF
280 CPPUNIT_ASSERT_EQUAL(sal_Int32(529), nFrame
+ nPara
);
282 CPPUNIT_ASSERT_EQUAL(sal_Int32(529*2), nFrame
+ nPara
);
286 // Fill the frame with a red background. It should be transferred on export to the paragraph
287 uno::Reference
<beans::XPropertySet
> xFrame(getShape(1), uno::UNO_QUERY
);
288 xFrame
->setPropertyValue(u
"FillColor"_ustr
, uno::Any(COL_RED
));
289 xFrame
->setPropertyValue(u
"FillTransparence"_ustr
, uno::Any(static_cast<sal_Int32
>(0)));
293 createSwDoc("tdf154703_framePr2.rtf");
295 saveAndReload(mpFilter
);
296 verify(/*bIsExport*/ true);
298 // exported: framed paragraphs without a background should now have a red background
299 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
300 assertXPath(pXmlDoc
, "//w:body/w:p[1]/w:pPr/w:shd", "fill", u
"800000");
301 assertXPath(pXmlDoc
, "//w:body/w:p[2]/w:pPr/w:shd", "fill", u
"548DD4"); // was blue already, no change
302 assertXPath(pXmlDoc
, "//w:body/w:p[3]/w:pPr/w:shd", "fill", u
"800000");
303 assertXPath(pXmlDoc
, "//w:body/w:p[3]/w:pPr/w:framePr", "yAlign", u
"center");
304 assertXPathNoAttribute(pXmlDoc
, "//w:body/w:p[3]/w:pPr/w:framePr", "y");
307 CPPUNIT_TEST_FIXTURE(Test
, testTdf154703_framePrWrapSpacing
)
309 loadAndSave("tdf154703_framePrWrapSpacing.docx");
310 CPPUNIT_ASSERT_EQUAL(2, getPages());
312 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
313 // before the fix, this was half of the correct value.
314 assertXPath(pXmlDoc
, "//w:body/w:p/w:pPr/w:framePr", "hSpace", u
"2552");
317 CPPUNIT_TEST_FIXTURE(Test
, testTdf154703_framePrTextDirection
)
319 createSwDoc("tdf154703_framePrTextDirection.docx");
320 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::WritingMode2::TB_RL
), getProperty
<sal_Int16
>(getShape(1), u
"WritingMode"_ustr
));
321 saveAndReload(mpFilter
);
322 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::WritingMode2::TB_RL
), getProperty
<sal_Int16
>(getShape(1), u
"WritingMode"_ustr
));
324 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
325 assertXPath(pXmlDoc
, "//w:body/w:p/w:pPr/w:textDirection", "val", u
"tbRl");
328 DECLARE_OOXMLEXPORT_TEST(testTdf153613_anchoredAfterPgBreak
, "tdf153613_anchoredAfterPgBreak.docx")
330 xmlDocUniquePtr pLayout
= parseLayoutDump();
331 // An anchored TO character image anchors before the page break.
332 assertXPath(pLayout
, "//page[1]//anchored", 1);
335 DECLARE_OOXMLEXPORT_TEST(testTdf153613_anchoredAfterPgBreak2
, "tdf153613_anchoredAfterPgBreak2.docx")
337 xmlDocUniquePtr pLayout
= parseLayoutDump();
338 // An anchored TO character image, followed by more characters moves to the following page
339 assertXPath(pLayout
, "//page[2]//anchored", 1);
342 DECLARE_OOXMLEXPORT_TEST(testTdf153613_anchoredAfterPgBreak3
, "tdf153613_anchoredAfterPgBreak3.docx")
344 xmlDocUniquePtr pLayout
= parseLayoutDump();
345 // An anchored TO character image, with setting splitPgBreakAndParaMark moves to the following page
346 assertXPath(pLayout
, "//page[2]//anchored", 1);
349 DECLARE_OOXMLEXPORT_TEST(testTdf153613_anchoredAfterPgBreak6
, "tdf153613_anchoredAfterPgBreak6.docx")
351 // An anchored TO character image, followed by more characters moves to the following page
352 // The difference from test 2 is that it is not the first character run
353 CPPUNIT_ASSERT_EQUAL(2, getPages());
354 CPPUNIT_ASSERT_EQUAL(4, getParagraphs());
356 xmlDocUniquePtr pLayout
= parseLayoutDump();
357 CPPUNIT_ASSERT_EQUAL(u
"y"_ustr
, getXPathContent(pLayout
, "//page[2]/body/txt[1]"));
358 assertXPath(pLayout
, "//page[1]//anchored", 1); // DID YOU FIX ME? This should be page[2]
361 DECLARE_OOXMLEXPORT_TEST(testTdf153613_inlineAfterPgBreak
, "tdf153613_inlineAfterPgBreak.docx")
363 xmlDocUniquePtr pLayout
= parseLayoutDump();
364 // An inline AS character image moves to the following page when after the page break.
365 assertXPath(pLayout
, "//page[2]//anchored", 1);
368 DECLARE_OOXMLEXPORT_TEST(testTdf153613_inlineAfterPgBreak2
, "tdf153613_inlineAfterPgBreak2.docx")
370 // An inline AS character image moves to the following page when after the page break.
371 // The difference from the previous test is that it is not the first character run
372 CPPUNIT_ASSERT_EQUAL(2, getPages());
373 CPPUNIT_ASSERT_EQUAL(4, getParagraphs());
375 xmlDocUniquePtr pLayout
= parseLayoutDump();
376 assertXPathContent(pLayout
, "//page[1]/body/txt[2]", u
"x");
377 assertXPath(pLayout
, "//page[2]//anchored", 1);
380 DECLARE_OOXMLEXPORT_TEST(testTdf153613_sdtAfterPgBreak
, "tdf153613_sdtAfterPgBreak.docx")
382 CPPUNIT_ASSERT_EQUAL(2, getPages());
385 DECLARE_OOXMLEXPORT_TEST(testTdf153613_textboxAfterPgBreak3
, "tdf153613_textboxAfterPgBreak3.docx")
387 // both textboxes on the second (last) page
388 CPPUNIT_ASSERT_EQUAL(2, getPages());
390 xmlDocUniquePtr pLayout
= parseLayoutDump();
391 assertXPath(pLayout
, "//page[2]/body/txt/anchored/fly", 2);
394 DECLARE_OOXMLEXPORT_TEST(testTdf153964_topMarginAfterBreak14
, "tdf153964_topMarginAfterBreak14.docx")
396 //The top margin should only apply once in a split paragraph.
397 //In this compat14 (Windows 2010) version, it applies after the break if no prior visible run.
398 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(2, u
"a w:br at the start of the document. Does it use 60 point top margin?"_ustr
), uno::UNO_QUERY
);
399 //CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty<sal_Int32>(xPara, "ParaTopMargin"));
401 xPara
.set(getParagraph(3, u
"60 pt spacing before"_ustr
), uno::UNO_QUERY
);
402 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
403 CPPUNIT_ASSERT_EQUAL(Color(0xfbe4d5), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
405 // The top margin was applied to paragraph 3, so it shouldn't apply here
406 xPara
.set(getParagraph(4, u
"column break1"_ustr
), uno::UNO_QUERY
);
407 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
408 CPPUNIT_ASSERT_EQUAL(Color(0xfbe4d5), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
410 xPara
.set(getParagraph(5, u
"60 pt followed by page break"_ustr
), uno::UNO_QUERY
);
411 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
412 CPPUNIT_ASSERT_EQUAL(Color(0xdeeaf6), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
414 // The top margin was applied to paragraph 5, so it shouldn't apply here
415 xPara
.set(getParagraph(6, u
"page break1"_ustr
), uno::UNO_QUERY
);
416 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
417 CPPUNIT_ASSERT_EQUAL(Color(0xdeeaf6), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
419 // The top margin was not applied yet, so with compat14 it should apply here.
420 xPara
.set(getParagraph(7, u
"column break2"_ustr
), uno::UNO_QUERY
);
421 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
422 CPPUNIT_ASSERT_EQUAL(Color(0xe2efd9), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
424 // In an odd twist, the w:br was actually at the end of the previous w:p, so in that case
425 // we ignore the top margin definition this time.
426 xPara
.set(getParagraph(9, u
"page break2"_ustr
), uno::UNO_QUERY
);
427 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
429 // The top margin was not applied before the column break, so with compat14 it should apply here
430 xPara
.set(getParagraph(10, u
""_ustr
), uno::UNO_QUERY
); // after column break
431 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
432 CPPUNIT_ASSERT_EQUAL(Color(0xfff2cc), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
434 // In an odd twist, the w:br was actually at the end of the previous w:p, so in that case
435 // we ignore the top margin definition this time.
436 xPara
.set(getParagraph(12, u
""_ustr
), uno::UNO_QUERY
); // after page break
437 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
440 DECLARE_OOXMLEXPORT_TEST(testTdf153964_topMarginAfterBreak15
, "tdf153964_topMarginAfterBreak15.docx")
442 //The top margin should only apply once (at most) in a split paragraph.
443 //In this compat15 (Windows 2013) version, it never applies after the break.
444 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(2, u
"a w:br at the start of the document. Does it use 60 point top margin?"_ustr
), uno::UNO_QUERY
);
445 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
447 xPara
.set(getParagraph(3, u
"60 pt spacing before"_ustr
), uno::UNO_QUERY
);
448 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
449 CPPUNIT_ASSERT_EQUAL(Color(0xfbe4d5), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
451 // The top margin was applied to paragraph 3, so it shouldn't apply here
452 xPara
.set(getParagraph(4, u
"column break1"_ustr
), uno::UNO_QUERY
);
453 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
454 CPPUNIT_ASSERT_EQUAL(Color(0xfbe4d5), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
456 xPara
.set(getParagraph(5, u
"60 pt followed by page break"_ustr
), uno::UNO_QUERY
);
457 CPPUNIT_ASSERT_EQUAL(sal_Int32(2117), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
458 CPPUNIT_ASSERT_EQUAL(Color(0xdeeaf6), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
460 // The top margin was applied to paragraph 5, so it shouldn't apply here
461 xPara
.set(getParagraph(6, u
"page break1"_ustr
), uno::UNO_QUERY
);
462 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
463 CPPUNIT_ASSERT_EQUAL(Color(0xdeeaf6), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
465 // The top margin was not applied to paragraph 6, and with compat15 it shouldn't apply here.
466 xPara
.set(getParagraph(7, u
"column break2"_ustr
), uno::UNO_QUERY
);
467 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
468 CPPUNIT_ASSERT_EQUAL(Color(0xe2efd9), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
470 // The top margin not was applied to paragraph 8, and with compat15 it shouldn't apply here.
471 xPara
.set(getParagraph(9, u
"page break2"_ustr
), uno::UNO_QUERY
);
472 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
474 // The top margin was not applied to paragraph 9, and with compat15 it shouldn't apply here.
475 xPara
.set(getParagraph(10, u
""_ustr
), uno::UNO_QUERY
); // after column break
476 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
477 CPPUNIT_ASSERT_EQUAL(Color(0xfff2cc), getProperty
<Color
>(xPara
, u
"ParaBackColor"_ustr
));
479 // The top margin was not applied to paragraph 11, and with compat15 it shouldn't apply here.
480 xPara
.set(getParagraph(12, u
""_ustr
), uno::UNO_QUERY
); // after page break
481 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaTopMargin"_ustr
));
484 DECLARE_OOXMLEXPORT_TEST(testTdf153964_numberingAfterBreak14
, "tdf153964_numberingAfterBreak14.docx")
486 //Numbering should only apply once in a split paragraph.
487 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(2, u
"How numbering affected by a column break?"_ustr
), uno::UNO_QUERY
);
488 //CPPUNIT_ASSERT_EQUAL(OUString("1."), getProperty<OUString>(xPara, "ListLabelString"));
489 xPara
.set(getParagraph(3, u
"How is numbering affected by a page break?"_ustr
), uno::UNO_QUERY
);
490 //CPPUNIT_ASSERT_EQUAL(OUString("2."), getProperty<OUString>(xPara, "ListLabelString"));
491 xPara
.set(getParagraph(4, u
"x"_ustr
), uno::UNO_QUERY
);
492 //CPPUNIT_ASSERT_EQUAL(OUString("3."), getProperty<OUString>(xPara, "ListLabelString"));
493 xPara
.set(getParagraph(5, u
"column break"_ustr
), uno::UNO_QUERY
);
494 CPPUNIT_ASSERT_EQUAL(u
""_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
495 xPara
.set(getParagraph(6, u
"y"_ustr
), uno::UNO_QUERY
);
496 //CPPUNIT_ASSERT_EQUAL(OUString("3."), getProperty<OUString>(xPara, "ListLabelString"));
497 xPara
.set(getParagraph(7, u
"page break"_ustr
), uno::UNO_QUERY
);
498 CPPUNIT_ASSERT_EQUAL(u
""_ustr
, getProperty
<OUString
>(xPara
, u
"ListLabelString"_ustr
));
501 DECLARE_OOXMLEXPORT_TEST(testTdf153964_firstIndentAfterBreak14
, "tdf153964_firstIndentAfterBreak14.docx")
503 //First line indents should only apply once in a split paragraph.
504 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(2, u
"How is first line indent affected by a column break?"_ustr
), uno::UNO_QUERY
);
505 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
506 xPara
.set(getParagraph(3, u
"How is first line indent affected by a page break?"_ustr
), uno::UNO_QUERY
);
507 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
508 xPara
.set(getParagraph(4, u
"x"_ustr
), uno::UNO_QUERY
);
509 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
510 xPara
.set(getParagraph(5, u
"column break"_ustr
), uno::UNO_QUERY
);
511 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
512 xPara
.set(getParagraph(6, u
"y"_ustr
), uno::UNO_QUERY
);
513 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
514 xPara
.set(getParagraph(7, u
"page break"_ustr
), uno::UNO_QUERY
);
515 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(xPara
, u
"ParaFirstLineIndent"_ustr
));
518 CPPUNIT_TEST_FIXTURE(Test
, testTdf148834_lineNumbering
)
520 loadAndSave("tdf148834_lineNumbering.odt");
522 xmlDocUniquePtr pStylesXml
= parseExport(u
"word/styles.xml"_ustr
);
523 // user specified: do not include in line numbering
524 assertXPath(pStylesXml
, "//w:style[@w:styleId='Normal']/w:pPr/w:suppressLineNumbers", 1);
525 // even though it matches the parent style, these should always avoid showing line numbering
526 assertXPath(pStylesXml
, "//w:style[@w:styleId='Footer']/w:pPr/w:suppressLineNumbers", 1);
527 assertXPath(pStylesXml
,
528 "//w:style[@w:styleId='0NUMBERED']/w:pPr/w:suppressLineNumbers", "val", u
"0");
531 CPPUNIT_TEST_FIXTURE(Test
, testTdf157598
)
533 loadAndSave("tdf157598.docx");
535 xmlDocUniquePtr pStylesXml
= parseExport(u
"word/styles.xml"_ustr
);
537 // Without the fix in place, this test would have failed with
540 assertXPath(pStylesXml
, "//w:style[@w:styleId='Normal']/w:rPr/w:rtl", 0);
543 CPPUNIT_TEST_FIXTURE(Test
, testTdf76022_textboxWrap
)
545 // Granted, this is an ODT with a bit of an anomaly - tables ignore fly wrapping.
546 createSwDoc("tdf76022_textboxWrap.odt");
547 CPPUNIT_ASSERT_EQUAL_MESSAGE("Did you make wrapping sane/interoperable?", 1, getPages());
549 // When saving to DOCX, the table should obey the fly wrapping
550 saveAndReload(u
"Office Open XML Text"_ustr
);
552 // The fly takes up the whole page, so the table needs to shift down to the next page.
553 CPPUNIT_ASSERT_EQUAL(2, getPages());
556 DECLARE_OOXMLEXPORT_TEST(testTdf134114_allowOverlap
, "tdf134114_allowOverlap.docx")
558 // CPPUNIT_ASSERT_EQUAL(1, getPages());
559 CPPUNIT_ASSERT(!getProperty
<bool>(getShape(1), u
"AllowOverlap"_ustr
));
560 CPPUNIT_ASSERT(getProperty
<bool>(getShape(2), u
"AllowOverlap"_ustr
));
563 CPPUNIT_TEST_FIXTURE(Test
, testTdf149551_mongolianVert
)
565 // Given a docx document with a shape with vert="mongolianVert".
566 createSwDoc("tdf149551_mongolianVert.docx");
568 // The shape is imported as custom shape with attached frame.
569 // Without fix the shape itself had WritingMode = 0 = LR_TB,
570 // the frame in it had WritingMode = 2 = TB_RL.
571 // It should be WritingMode = 3 = TB_LR in both cases.
572 const sal_Int16
eExpected(text::WritingMode2::TB_LR
);
573 CPPUNIT_ASSERT_EQUAL(eExpected
, getProperty
<sal_Int16
>(getShape(1), u
"WritingMode"_ustr
));
574 uno::Reference
<beans::XPropertySet
> xShapeProps(getShape(1), uno::UNO_QUERY
);
575 uno::Reference
<beans::XPropertySet
> xFrameProps(xShapeProps
->getPropertyValue(u
"TextBoxContent"_ustr
),
577 CPPUNIT_ASSERT_EQUAL(eExpected
, getProperty
<sal_Int16
>(xFrameProps
, u
"WritingMode"_ustr
));
579 // Such shape must have vert="mongolianVert" again after saving.
580 // Without fix the orientation was vert="vert".
581 save(u
"Office Open XML Text"_ustr
);
582 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
583 assertXPath(pXmlDoc
, "//wps:bodyPr", "vert", u
"mongolianVert");
586 CPPUNIT_TEST_FIXTURE(Test
, testTdf151912
)
588 loadAndSave("tdf151912.docx");
589 // For now just ensure roundtrip is successful
591 //tdf#151548 - ensure block SDT preserves id (instead of random re-assignment)
592 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
593 assertXPath(pXmlDoc
, "//w:sdt//w:sdtPr/w:id", "val", u
"1802566103");
596 DECLARE_OOXMLEXPORT_TEST(testTdf147724
, "tdf147724.docx")
598 xmlDocUniquePtr pLayout
= parseLayoutDump();
600 // Ensure we load field value from external XML correctly (it was "HERUNTERLADEN")
601 assertXPathContent(pLayout
, "/root/page[1]/body/txt[1]", u
"Placeholder -> *ABC*");
603 // This SDT has no storage id, it is not an error, but content can be taken from any suitable XML
604 // There 2 variants possible, both are acceptable
605 OUString sFieldResult
= getXPathContent(pLayout
, "/root/page[1]/body/txt[2]");
606 CPPUNIT_ASSERT(sFieldResult
== "Placeholder -> *HERUNTERLADEN*" || sFieldResult
== "Placeholder -> *ABC*");
609 DECLARE_OOXMLEXPORT_TEST(testTdf130782
, "chart.docx")
611 uno::Reference
<text::XTextEmbeddedObjectsSupplier
> xTEOSupplier(mxComponent
, uno::UNO_QUERY
);
612 uno::Reference
<container::XIndexAccess
> xAccess(xTEOSupplier
->getEmbeddedObjects(), uno::UNO_QUERY
);
613 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xAccess
->getCount());
614 uno::Reference
<container::XNamed
> xObj(xAccess
->getByIndex(0), uno::UNO_QUERY
);
616 // these properties were not imported
617 CPPUNIT_ASSERT_EQUAL(u
"Diagramm 1"_ustr
, xObj
->getName());
618 CPPUNIT_ASSERT_EQUAL(u
"uninspired default chart"_ustr
, getProperty
<OUString
>(xObj
, u
"Title"_ustr
));
619 CPPUNIT_ASSERT_EQUAL(u
"the description is here"_ustr
, getProperty
<OUString
>(xObj
, u
"Description"_ustr
));
622 CPPUNIT_TEST_FIXTURE(Test
, testNumberPortionFormatFromODT
)
624 // Given a document with a single paragraph, direct formatting asks 24pt font size for the
625 // numbering and the text portion:
626 createSwDoc("number-portion-format.odt");
628 // When saving to DOCX:
629 save(u
"Office Open XML Text"_ustr
);
631 // Then make sure that the paragraph marker's char format has that custom font size:
632 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
633 // Without the accompanying fix in place, this test would have failed with:
636 // - XPath '//w:pPr/w:rPr/w:sz' number of nodes is incorrect
637 // i.e. <w:sz> was missing under <w:pPr>'s <w:rPr>.
638 assertXPath(pXmlDoc
, "//w:pPr/w:rPr/w:sz", "val", u
"48");
641 CPPUNIT_TEST_FIXTURE(Test
, testParaStyleCharPosition
)
643 // Given a loaded document where the Normal paragraph style has <w:position w:val="-1">:
644 createSwDoc("para-style-char-position.docx");
646 // When saving it back to DOCX:
647 save(u
"Office Open XML Text"_ustr
);
649 // Then make sure that is not turned into a normal subscript text:
650 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/styles.xml"_ustr
);
651 // Without the accompanying fix in place, this test would have failed with:
654 // - XPath '/w:styles/w:style[@w:styleId='Normal']/w:rPr/w:position' number of nodes is incorrect
655 // i.e. we wrote <w:vertAlign w:val="subscript"> instead of <w:position>.
656 assertXPath(pXmlDoc
, "/w:styles/w:style[@w:styleId='Normal']/w:rPr/w:position", "val", u
"-1");
659 CPPUNIT_TEST_FIXTURE(Test
, testTdf150966_regularInset
)
661 // Given a docx document with a rectangular shape with height cy="900000" (EMU), tIns="180000"
662 // and bIns="360000", resulting in 360000EMU text area height.
663 createSwDoc("tdf150966_regularInset.docx");
665 // The shape is imported as custom shape with attached frame.
666 // The insets are currently imported as margin top="4.99mm" and bottom="10mm".
667 // That should result in tIns="179640" and bIns="360000" on export.
669 // Without fix the insets were tIns="359280" and bIns="539640". The text area had 1080Emu height
670 // and Word displays no text at all.
671 save(u
"Office Open XML Text"_ustr
);
672 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
673 assertXPathAttrs(pXmlDoc
, "//wps:bodyPr", { { "tIns", u
"179640" }, { "bIns", u
"360000" } });
676 CPPUNIT_TEST_FIXTURE(Test
, testTdf152636_lostPageBreak
)
678 loadAndReload("tdf152636_lostPageBreak.odt");
680 CPPUNIT_ASSERT_EQUAL(2, getPages());
683 CPPUNIT_TEST_FIXTURE(Test
, testTdf152636_lostPageBreak2
)
685 loadAndReload("tdf152636_lostPageBreak2.docx");
687 CPPUNIT_ASSERT_EQUAL(2, getPages());
690 CPPUNIT_TEST_FIXTURE(Test
, testSdtDuplicatedId
)
692 // Given a document with 2 inline <w:sdt>, with each a <w:id>:
693 createSwDoc("sdt-duplicated-id.docx");
695 // When exporting that back to DOCX:
696 save(u
"Office Open XML Text"_ustr
);
698 // Then make sure we write 2 <w:sdt> and no duplicates:
699 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
700 // Without the accompanying fix in place, this test would have failed with:
703 // i.e. grab-bags introduced 2 unwanted duplicates.
704 assertXPath(pXmlDoc
, "//w:sdt", 2);
707 CPPUNIT_TEST_FIXTURE(Test
, testImageCropping
)
709 loadAndReload("crop-roundtrip.docx");
711 // the image has no cropping after roundtrip, because it has been physically cropped
712 // NB: this test should be fixed when the core feature to show image cropped when it
713 // has the "GraphicCrop" is set is implemented
714 auto aGraphicCropStruct
= getProperty
<text::GraphicCrop
>(getShape(1), u
"GraphicCrop"_ustr
);
715 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aGraphicCropStruct
.Left
);
716 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aGraphicCropStruct
.Right
);
717 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aGraphicCropStruct
.Top
);
718 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aGraphicCropStruct
.Bottom
);
721 CPPUNIT_TEST_FIXTURE(Test
, testTdf152200
)
723 // Given a document with a fly anchored after a FORMTEXT in the end of the paragraph:
724 createSwDoc("tdf152200-field+textbox.docx");
726 // When exporting that back to DOCX:
727 save(u
"Office Open XML Text"_ustr
);
729 // Then make sure that fldChar with type 'end' goes prior to the at-char anchored fly.
730 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
731 const int nRunsBeforeFldCharEnd
= countXPathNodes(pXmlDoc
, "//w:fldChar[@w:fldCharType='end']/preceding::w:r");
732 CPPUNIT_ASSERT(nRunsBeforeFldCharEnd
);
733 const int nRunsBeforeAlternateContent
= countXPathNodes(pXmlDoc
, "//mc:AlternateContent/preceding::w:r");
734 CPPUNIT_ASSERT(nRunsBeforeAlternateContent
);
735 // Without the accompanying fix in place, this test would have failed with:
736 // - Expected greater than: 6
738 CPPUNIT_ASSERT_GREATER(nRunsBeforeFldCharEnd
, nRunsBeforeAlternateContent
);
739 // Make sure we only have one paragraph in body, and only three field characters overall,
740 // located directly in runs of this paragraph
741 assertXPath(pXmlDoc
, "/w:document/w:body/w:p");
742 assertXPath(pXmlDoc
, "/w:document/w:body/w:p/w:r/w:fldChar", 3);
743 assertXPath(pXmlDoc
, "//w:fldChar", 3); // no field characters elsewhere
746 CPPUNIT_TEST_FIXTURE(Test
, testTdf126477
)
748 loadAndReload("embedded_chart.odt");
750 uno::Reference
<text::XTextEmbeddedObjectsSupplier
> xTEOSupplier(mxComponent
, uno::UNO_QUERY
);
751 uno::Reference
<container::XNameAccess
> xAccess(xTEOSupplier
->getEmbeddedObjects());
752 uno::Sequence
<OUString
> aSeq(xAccess
->getElementNames());
754 // Check number of embedded objects.
755 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aSeq
.getLength());
757 uno::Reference
<document::XEmbeddedObjectSupplier
> xEOSupplier(xAccess
->getByName(aSeq
[0]),
759 uno::Reference
<lang::XComponent
> xObj(xEOSupplier
->getEmbeddedObject());
760 uno::Reference
<text::XTextEmbeddedObjectsSupplier
> xTEOSupplier2(xObj
, uno::UNO_QUERY
);
761 uno::Reference
<container::XNameAccess
> xAccess2(xTEOSupplier2
->getEmbeddedObjects());
762 uno::Sequence
<OUString
> aSeq2(xAccess2
->getElementNames());
764 // Without the accompanying fix in place, this test would have failed with:
767 // i.e. the chart lost in the embedded document.
768 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aSeq2
.getLength());
771 CPPUNIT_TEST_FIXTURE(Test
, testTdf152425
)
773 loadAndReload("tdf152425.docx");
775 // Check that "List Number" and "List 5" styles don't get merged
776 const OUString Para3Style
= getProperty
<OUString
>(getParagraph(3), u
"ParaStyleName"_ustr
);
777 CPPUNIT_ASSERT_EQUAL(u
"Numbering 1"_ustr
, Para3Style
);
778 const OUString Para4Style
= getProperty
<OUString
>(getParagraph(4), u
"ParaStyleName"_ustr
);
779 CPPUNIT_ASSERT_EQUAL(u
"List 5 (WW)"_ustr
, Para4Style
);
780 // Also check that "List 5" and "List Bullet 5" styles don't get merged
781 const OUString Para5Style
= getProperty
<OUString
>(getParagraph(5), u
"ParaStyleName"_ustr
);
782 CPPUNIT_ASSERT_EQUAL(u
"List 5"_ustr
, Para5Style
);
785 CPPUNIT_TEST_FIXTURE(Test
, testTdf153104
)
787 loadAndReload("tdf153104.docx");
789 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
790 OUString numId
= getXPath(pXmlDoc
, "/w:document/w:body/w:p[1]/w:pPr/w:numPr/w:numId", "val");
792 xmlDocUniquePtr pXmlNum
= parseExport(u
"word/numbering.xml"_ustr
);
793 OString numPath
= "/w:numbering/w:num[@w:numId='"
794 + OUStringToOString(numId
, RTL_TEXTENCODING_ASCII_US
) + "']/";
796 // Check that first level's w:lvlOverride/w:startOverride is written correctly:
797 // the list defines starting value of 10, which must be kept upon second level
799 // Without the fix, this would fail with
802 // - In <>, XPath '/w:numbering/w:num[@w:numId='3']/w:lvlOverride[@w:ilvl='0']/w:startOverride' number of nodes is incorrect
803 assertXPath(pXmlNum
, numPath
+ "w:lvlOverride[@w:ilvl='0']/w:startOverride", "val", u
"10");
804 assertXPath(pXmlNum
, numPath
+ "w:lvlOverride[@w:ilvl='1']/w:startOverride", "val", u
"1");
807 CPPUNIT_TEST_FIXTURE(Test
, testTdf153128
)
809 loadAndReload("tdf153128.docx");
811 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
812 sal_Int32 nFirstLineHeight
813 = getXPath(pXmlDoc
, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", "height")
815 CPPUNIT_ASSERT_GREATER(sal_Int32(0), nFirstLineHeight
);
817 // The text height is 1 pt, i.e. 20 twip; without the fix, it would fail with
818 // - Expected less than: 30
820 CPPUNIT_ASSERT_LESS(sal_Int32(30), nFirstLineHeight
);
823 CPPUNIT_TEST_FIXTURE(Test
, testExportingUnknownStyleInRedline
)
825 // This must not fail assertions
826 loadAndReload("UnknownStyleInRedline.docx");
827 // Check that the original unknown style name "UnknownStyle" is roundtripped
828 // (maybe this is wrong, because Word does not do this).
829 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
831 "/w:document/w:body/w:p/w:pPr/w:pPrChange/w:pPr/w:pStyle[@w:val='UnknownStyle']");
834 CPPUNIT_TEST_FIXTURE(Test
, testTdf148026
)
836 loadAndReload("tdf148026.fodt");
837 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
838 // Without the accompanying fix in place, this test would have failed with:
841 // - In <>, XPath '//w:hyperlink' number of nodes is incorrect
842 // i.e. a HYPERLINK field was exported instead of the hyperlink XML element.
843 assertXPath(pXmlDoc
, "//w:hyperlink", "tgtFrame", u
"_self");
846 CPPUNIT_TEST_FIXTURE(Test
, testTdf153664
)
848 loadAndReload("Table-of-Figures.odt");
849 CPPUNIT_ASSERT_EQUAL(1, getPages());
850 xmlDocUniquePtr pXmlStyles
= parseExport(u
"word/styles.xml"_ustr
);
851 CPPUNIT_ASSERT(pXmlStyles
);
852 // Without the fix this was styleId='FigureIndex1' and name was "Figure Index 1"
853 // This led to style settings being reset when ToF was updated in Word
854 // TOF's paragraph style should be exported as "table of figures" as that's the default Word style name
855 assertXPath(pXmlStyles
, "/w:styles/w:style[12]", "styleId", u
"TableofFigures");
856 assertXPath(pXmlStyles
, "/w:styles/w:style[@w:styleId='TableofFigures']/w:name", "val", u
"table of figures");
859 DECLARE_OOXMLEXPORT_TEST(testTdf124472_hyperlink
, "tdf124472.docx")
861 CPPUNIT_ASSERT_EQUAL(u
"https://www.libreoffice.org/"_ustr
,
862 getProperty
<OUString
>(getRun(getParagraph(1), 1), u
"HyperLinkURL"_ustr
));
863 CPPUNIT_ASSERT_EQUAL(u
"mailto:info@libreoffice.org"_ustr
,
864 getProperty
<OUString
>(getRun(getParagraph(2), 1), u
"HyperLinkURL"_ustr
));
865 CPPUNIT_ASSERT_EQUAL(u
""_ustr
,
866 getProperty
<OUString
>(getRun(getParagraph(3), 1), u
"HyperLinkURL"_ustr
));
869 DECLARE_OOXMLEXPORT_TEST(testTdf135786
, "tdf135786.docx")
871 // Empty first line remain, if the section's initial dummy paragraph is not deleted:
874 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
877 DECLARE_OOXMLEXPORT_TEST(testTdf155736
, "tdf155736_PageNumbers_footer.docx")
879 CPPUNIT_ASSERT_EQUAL(2, getPages());
881 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
882 assertXPath(pXmlDoc
, "/root/page[1]/footer");
883 assertXPath(pXmlDoc
, "/root/page[2]/footer");
884 //Without the fix in place, it would have failed with
885 //- Expected: Page * of *
887 assertXPathContent(pXmlDoc
, "/root/page[1]/footer/txt/text()", u
"Page * of *");
888 assertXPathContent(pXmlDoc
, "/root/page[2]/footer/txt/text()", u
"Page * of *");
891 // The following zOrder tests are checking the shapes "stacking height".
892 // getShape(nZOrder) already gets them in lowest-to-highest order,
893 // so for any overlapping shapes the highest numbered shape is expected to be the one on top.
894 // Which shape that actually is can be usually be verified based on the shape name.
895 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_duplicate
, "tdf159158_zOrder_duplicate_compat15.docx")
897 // given a yellow star with relativeHeight 2, followed by an overlapping blue star also with 2
898 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
899 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
900 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
901 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
902 // the zOrder of the stars should remain consistent between round-trips - last duplicate wins
903 // and compatibility has nothing to do with this for relativeHeight (other tests are compat12).
904 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
905 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
908 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0equalA
, "tdf159158_zOrder_1and0equalA.docx")
910 // given a yellow star with relativeHeight 1, followed by an overlapping blue star with 0
911 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
912 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
913 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
914 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
915 // 0 is treated the same as 1 - the maximum value, so blue is duplicate - last duplicate wins
916 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
917 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
920 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0equalB
, "tdf159158_zOrder_1and0equalB.docx")
922 // given a yellow star with relativeHeight 0, followed by an overlapping blue star with 1
923 // since they have the same zOrder value, last one wins, so same result as version A
924 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
925 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
926 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
927 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
928 // 1 is treated the same as 0 - the maximum value, so blue is duplicate - last duplicate wins
929 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
930 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
933 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0max
, "tdf159158_zOrder_1and0max.docx")
935 // given a yellow star with maximum relativeHeight 503316479 (1DFF FFFF)
936 // followed by an overlapping blue star with 0.
937 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
938 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
939 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
940 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
941 // 0 is treated the same as the maximum value, last duplicate wins, so blue is on top
942 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
943 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
946 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_maxLessOne
, "tdf159158_zOrder_maxLessOne.docx")
948 // given a yellow star with relativeHeight 503316479 (1DFF FFFF)
949 // followed by a partially hidden blue star with lower relativeHeight 503316478 (1DFF FFFE)
950 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
951 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
952 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
953 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
954 // since yellow is a higher value, it should be on top
955 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder0
,u
"Name"_ustr
));
956 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder1
, u
"Name"_ustr
));
959 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_max
, "tdf159158_zOrder_max.docx")
961 // given a yellow star with (one higher than maximum) relativeHeight 503316480 (1E00 0000)
962 // followed by an overlapping blue star with maximum relativeHeight 503316479 (1DFF FFFF)
963 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
964 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
965 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
966 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
967 // while yellow is a higher value, last duplicate wins, so lower value blue must be the maximum
968 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
969 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
972 CPPUNIT_TEST_FIXTURE(Test
, testTdf159158_zOrder_zIndexMax
)
974 auto verify
= [this](bool bIsExport
= false) {
975 // given a yellow star with a heaven z-index of MAX_SAL_INT32
976 // followed by overlapped blue star with a heaven z-index of MAX_SAL_INT32 - 1
977 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
978 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
979 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
980 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
981 // there is no artificial maximum for z-index. All values are unique. Yellow is on top
982 if (!bIsExport
) //somehow the name is lost on this export
984 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
985 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
989 createSwDoc("tdf159158_zOrder_zIndexMax.docx");
991 saveAndReload(mpFilter
);
992 verify(/*bIsExport*/ true);
995 CPPUNIT_TEST_FIXTURE(Test
, testTdf159158_zOrder_zIndexDuplicate_compat15
)
997 auto verify
= [this](bool bIsExport
= false) {
998 // given a yellow star with a heaven z-index of MAX_SAL_INT32 - 1
999 // followed by overlapping blue star with the same heaven z-index (last duplicate wins)
1000 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1001 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1002 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1003 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
1004 // should be the same as relativeHeight - last duplicate wins so blue is on top.
1005 if (!bIsExport
) //somehow the name is lost on this export
1007 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
1008 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
1012 createSwDoc("tdf159158_zOrder_zIndexDuplicate_compat15.docx");
1014 saveAndReload(mpFilter
);
1015 verify(/*bIsExport*/ true);
1018 CPPUNIT_TEST_FIXTURE(Test
, testTdf159158_zOrder_zIndexWins
)
1020 auto verify
= [this](bool bIsExport
= false) {
1021 // given a yellow star with relativeHeight 0 (typically a maximum value, but not today)
1022 // followed by an overlapping-everything textbox at z-index 0 (the lowest heaven-layer z-index)
1023 // followed by a partially overlapping blue star with a
1024 // seems-to-be-a-magic-number relativeHeight 251658240 (0F00 0000)
1025 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1026 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1027 uno::Reference
<beans::XPropertySet
> zOrder2(getShape(3), uno::UNO_QUERY
);
1028 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1029 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
));
1030 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty
<sal_Int32
>(zOrder2
, u
"ZOrder"_ustr
)); // higher
1031 // I'm puzzled. Somehow 0 is larger than 0EFF FFFF, but not larger than 0F00 0000
1032 // and yet the maximum value was established earlier as 1DFF FFFF. Something doesn't line up.
1033 // Perhaps 0 and 1 don't mean maximum value at all, but something completely different?
1034 CPPUNIT_ASSERT_MESSAGE("DID YOU FIX ME? I really should be yellow, not blue",
1035 "5-Point Star Yellow" != getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
1036 // CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), getProperty<OUString>(zOrder1,"Name"));
1037 // If zOrder is defined by z-index, it seems that it goes above everything set by relativeHeight
1038 if (bIsExport
) // not named on import
1039 CPPUNIT_ASSERT_EQUAL(u
"Frame1"_ustr
, getProperty
<OUString
>(zOrder2
,u
"Name"_ustr
));
1041 createSwDoc("tdf159158_zOrder_zIndexWins.docx");
1043 saveAndReload(mpFilter
);
1044 verify(/*bIsExport*/ true);
1047 CPPUNIT_TEST_FIXTURE(Test
, testTdf159158_zOrder_behindDocA
)
1049 auto verify
= [this](bool bIsExport
= false) {
1050 // given a yellow star with lowest relativeHeight 2 but behindDoc
1051 // followed by an overlapping blue star with negative z-index -1644167168.
1052 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1053 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1054 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1055 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
1056 // yellow is at the lowest hell-level possible for relativeHeight, so expected to be under blue
1057 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
1058 if (!bIsExport
) // the name is lost on export
1059 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
1062 createSwDoc("tdf159158_zOrder_behindDocA.docx");
1064 saveAndReload(mpFilter
);
1065 verify(/*bIsExport*/ true);
1068 CPPUNIT_TEST_FIXTURE(Test
, testTdf159158_zOrder_behindDocB
)
1070 auto verify
= [this](bool bIsExport
= false) {
1071 // given a yellow star with a high relativeHeight 503314431 (1DFF F7FF) but behindDoc
1072 // followed by an overlapping blue star with negative z-index -1644167168.
1073 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1074 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1075 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1076 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
1077 // yellow is at the highest hell-level possible for relativeHeight,
1078 // so you will be forgiven for thinking yellow should be on the top.
1079 // Any z-index level ends up being above any relativeHeight, so blue should still be on top
1080 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Yellow"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
1081 if (!bIsExport
) // the name is lost on export
1082 CPPUNIT_ASSERT_EQUAL(u
"5-Point Star Blue"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
1085 createSwDoc("tdf159158_zOrder_behindDocB.docx");
1087 saveAndReload(mpFilter
);
1088 verify(/*bIsExport*/ true);
1091 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_headerBehind
, "tdf159158_zOrder_headerBehind.odt")
1093 // given a blue star (not marked as behind text) anchored in the header
1094 // and an overlapping yellow rectangle anchored in the body text.
1095 // (note that in ODT format the star is on top, but for DOCX format it must be behind (hidden)
1096 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1097 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1098 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1099 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
1100 // I don't know why the star is the lowest order in ODT import (maybe header weirdness),
1101 // but it certainly needs to be the lowest on docx round-trip (also for header weirdness)
1102 CPPUNIT_ASSERT_EQUAL(u
"StarInHeader"_ustr
, getProperty
<OUString
>(zOrder0
, u
"Name"_ustr
));
1103 CPPUNIT_ASSERT_EQUAL(u
"RectangleInBody"_ustr
, getProperty
<OUString
>(zOrder1
,u
"Name"_ustr
));
1106 DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_headerBehind2
, "tdf159158_zOrder_headerBehind2.docx")
1108 // given a logo (marked as behind text) anchored in the header
1109 // and an overlapping blue rectangle anchored in the body text.
1110 uno::Reference
<beans::XPropertySet
> zOrder0(getShape(1), uno::UNO_QUERY
);
1111 uno::Reference
<beans::XPropertySet
> zOrder1(getShape(2), uno::UNO_QUERY
);
1112 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(zOrder0
, u
"ZOrder"_ustr
)); // lower
1113 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty
<sal_Int32
>(zOrder1
, u
"ZOrder"_ustr
)); // higher
1114 CPPUNIT_ASSERT_EQUAL(u
"HeaderImage"_ustr
,
1115 getProperty
<OUString
>(zOrder0
, u
"LinkDisplayName"_ustr
));
1116 CPPUNIT_ASSERT_EQUAL(u
"BodyBlueRectangle"_ustr
,
1117 getProperty
<OUString
>(zOrder1
, u
"LinkDisplayName"_ustr
));
1118 // The logo should not be opaque since it is in the header.
1119 CPPUNIT_ASSERT(!getProperty
<bool>(zOrder0
, u
"Opaque"_ustr
)); // logo should be invisible
1120 CPPUNIT_ASSERT(!getProperty
<bool>(zOrder1
, u
"Opaque"_ustr
));
1123 DECLARE_OOXMLEXPORT_TEST(testTdf155903
, "tdf155903.odt")
1125 // Without the accompanying fix in place, this test would have crashed,
1126 // because the exported file was corrupted.
1129 CPPUNIT_PLUGIN_IMPLEMENT();
1131 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */