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/awt/CharSet.hpp>
13 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
14 #include <com/sun/star/text/XTextDocument.hpp>
15 #include <com/sun/star/text/WrapTextMode.hpp>
17 #include <comphelper/propertyvalue.hxx>
20 #include <formatcontentcontrol.hxx>
22 #include <itabenum.hxx>
24 #include <frameformats.hxx>
25 #include <formatflysplit.hxx>
26 #include <IDocumentLayoutAccess.hxx>
27 #include <rootfrm.hxx>
28 #include <pagefrm.hxx>
30 #include <IDocumentSettingAccess.hxx>
31 #include <sortedobjs.hxx>
32 #include <fmtwrapinfluenceonobjpos.hxx>
37 #include <fmtftntx.hxx>
42 * Covers sw/source/filter/ww8/ fixes.
44 * Note that these tests are meant to be simple: either load a file and assert some result or build
45 * a document model with code, export and assert that result.
47 * Keep using the various sw_<format>import/export suites for multiple filter calls inside a single
50 class Test
: public SwModelTestBase
54 : SwModelTestBase(u
"/sw/qa/filter/ww8/data/"_ustr
)
59 CPPUNIT_TEST_FIXTURE(Test
, testNegativePageBorderDocImport
)
61 // Given a document with a border distance that is larger than the margin, when loading that
63 createSwDoc("negative-page-border.doc");
65 // Then make sure we map that to a negative border distance (move border from the edge of body
66 // frame towards the center of the page, not towards the edge of the page):
67 uno::Reference
<container::XNameAccess
> xStyleFamily
= getStyles(u
"PageStyles"_ustr
);
68 uno::Reference
<beans::XPropertySet
> xStyle(xStyleFamily
->getByName(u
"Standard"_ustr
),
70 auto nTopMargin
= xStyle
->getPropertyValue(u
"TopMargin"_ustr
).get
<sal_Int32
>();
71 // Without the accompanying fix in place, this test would have failed with:
74 // i.e. the border properties influenced the margin, which was 284 twips in the sprmSDyaTop
76 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(501), nTopMargin
);
77 auto aTopBorder
= xStyle
->getPropertyValue(u
"TopBorder"_ustr
).get
<table::BorderLine2
>();
78 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(159), aTopBorder
.LineWidth
);
79 auto nTopBorderDistance
= xStyle
->getPropertyValue(u
"TopBorderDistance"_ustr
).get
<sal_Int32
>();
80 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(-646), nTopBorderDistance
);
83 CPPUNIT_TEST_FIXTURE(Test
, testPlainTextContentControlExport
)
85 // Given a document with a plain text content control around a text portion:
87 uno::Reference
<lang::XMultiServiceFactory
> xMSF(mxComponent
, uno::UNO_QUERY
);
88 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
89 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
90 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
91 xText
->insertString(xCursor
, u
"test"_ustr
, /*bAbsorb=*/false);
92 xCursor
->gotoStart(/*bExpand=*/false);
93 xCursor
->gotoEnd(/*bExpand=*/true);
94 uno::Reference
<text::XTextContent
> xContentControl(
95 xMSF
->createInstance(u
"com.sun.star.text.ContentControl"_ustr
), uno::UNO_QUERY
);
96 uno::Reference
<beans::XPropertySet
> xContentControlProps(xContentControl
, uno::UNO_QUERY
);
97 xContentControlProps
->setPropertyValue(u
"PlainText"_ustr
, uno::Any(true));
98 xText
->insertTextContent(xCursor
, xContentControl
, /*bAbsorb=*/true);
100 // When exporting to DOCX:
101 save(u
"Office Open XML Text"_ustr
);
103 // Then make sure the expected markup is used:
104 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
105 // Without the accompanying fix in place, this test would have failed with:
108 // - XPath '//w:sdt/w:sdtPr/w:text' number of nodes is incorrect
109 // i.e. the plain text content control was turned into a rich text one on export.
110 assertXPath(pXmlDoc
, "//w:sdt/w:sdtPr/w:text", 1);
113 CPPUNIT_TEST_FIXTURE(Test
, testDocxComboBoxContentControlExport
)
115 // Given a document with a combo box content control around a text portion:
117 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
118 pWrtShell
->InsertContentControl(SwContentControlType::COMBO_BOX
);
120 // When exporting to DOCX:
121 save(u
"Office Open XML Text"_ustr
);
123 // Then make sure the expected markup is used:
124 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
125 // Without the accompanying fix in place, this test would have failed with:
128 // - XPath '//w:sdt/w:sdtPr/w:comboBox' number of nodes is incorrect
129 // i.e. the combo box content control was turned into a drop-down one on export.
130 assertXPath(pXmlDoc
, "//w:sdt/w:sdtPr/w:comboBox", 1);
133 CPPUNIT_TEST_FIXTURE(Test
, testDocxHyperlinkShape
)
135 // Given a document with a hyperlink at char positions 0 -> 6 and a shape with text anchored at
138 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
139 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
140 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
141 xText
->insertString(xCursor
, u
"beforeafter"_ustr
, /*bAbsorb=*/false);
142 xCursor
->gotoStart(/*bExpand=*/false);
143 xCursor
->goRight(/*nCount=*/6, /*bExpand=*/true);
144 uno::Reference
<beans::XPropertySet
> xCursorProps(xCursor
, uno::UNO_QUERY
);
145 xCursorProps
->setPropertyValue(u
"HyperLinkURL"_ustr
, uno::Any(u
"http://www.example.com/"_ustr
));
146 xCursor
->gotoStart(/*bExpand=*/false);
147 xCursor
->goRight(/*nCount=*/6, /*bExpand=*/false);
148 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
149 uno::Reference
<drawing::XShape
> xShape(
150 xFactory
->createInstance(u
"com.sun.star.drawing.RectangleShape"_ustr
), uno::UNO_QUERY
);
151 xShape
->setSize(awt::Size(5000, 5000));
152 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
153 xShapeProps
->setPropertyValue(u
"AnchorType"_ustr
,
154 uno::Any(text::TextContentAnchorType_AT_CHARACTER
));
155 uno::Reference
<text::XTextContent
> xShapeContent(xShape
, uno::UNO_QUERY
);
156 xText
->insertTextContent(xCursor
, xShapeContent
, /*bAbsorb=*/false);
157 xShapeProps
->setPropertyValue(u
"TextBox"_ustr
, uno::Any(true));
159 // When saving this document to DOCX, then make sure we don't crash on export (due to an
160 // assertion failure for not-well-formed XML output):
161 save(u
"Office Open XML Text"_ustr
);
164 CPPUNIT_TEST_FIXTURE(Test
, testDocxContentControlDropdownEmptyDisplayText
)
166 // Given a document with a dropdown content control, the only list item has no display text
169 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
170 pWrtShell
->InsertContentControl(SwContentControlType::DROP_DOWN_LIST
);
172 // When saving to DOCX:
173 save(u
"Office Open XML Text"_ustr
);
175 // Then make sure that no display text attribute is written:
176 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
177 // Without the accompanying fix in place, this test would have failed with:
178 // - XPath '//w:sdt/w:sdtPr/w:dropDownList/w:listItem' unexpected 'displayText' attribute
179 // i.e. we wrote an empty attribute instead of omitting it.
180 assertXPathNoAttribute(pXmlDoc
, "//w:sdt/w:sdtPr/w:dropDownList/w:listItem", "displayText");
183 CPPUNIT_TEST_FIXTURE(Test
, testDocxSymbolFontExport
)
185 // Create document with symbol character and font Wingdings
187 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
188 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
189 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
191 xText
->insertString(xCursor
, u
""_ustr
, true);
193 uno::Reference
<text::XTextRange
> xRange
= xCursor
;
194 uno::Reference
<beans::XPropertySet
> xTextProps(xRange
, uno::UNO_QUERY
);
195 xTextProps
->setPropertyValue(u
"CharFontName"_ustr
, uno::Any(u
"Wingdings"_ustr
));
196 xTextProps
->setPropertyValue(u
"CharFontNameAsian"_ustr
, uno::Any(u
"Wingdings"_ustr
));
197 xTextProps
->setPropertyValue(u
"CharFontNameComplex"_ustr
, uno::Any(u
"Wingdings"_ustr
));
198 xTextProps
->setPropertyValue(u
"CharFontCharSet"_ustr
, uno::Any(awt::CharSet::SYMBOL
));
200 // When exporting to DOCX:
201 save(u
"Office Open XML Text"_ustr
);
203 // Then make sure the expected markup is used:
204 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
206 assertXPath(pXmlDoc
, "//w:p/w:r/w:sym", 1);
207 assertXPath(pXmlDoc
, "//w:p/w:r/w:sym[1]", "font", u
"Wingdings");
208 assertXPath(pXmlDoc
, "//w:p/w:r/w:sym[1]", "char", u
"f0e0");
211 CPPUNIT_TEST_FIXTURE(Test
, testDocxFloatingTableExport
)
213 // Given a document with a floating table:
215 SwDoc
* pDoc
= getSwDoc();
216 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
218 SwInsertTableOptions
aTableOptions(SwInsertTableFlags::DefaultBorder
, 0);
219 pWrtShell
->InsertTable(aTableOptions
, 1, 1);
220 pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
);
224 SwFlyFrameAttrMgr
aMgr(true, pWrtShell
, Frmmgr_Type::TEXT
, nullptr);
225 pWrtShell
->StartAllAction();
226 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PARA
, aMgr
.GetPos(), aMgr
.GetSize());
227 // Mark it as a floating table:
228 auto& rFlys
= *pDoc
->GetSpzFrameFormats();
229 auto pFly
= rFlys
[0];
230 SwAttrSet
aSet(pFly
->GetAttrSet());
231 aSet
.Put(SwFormatFlySplit(true));
232 pDoc
->SetAttr(aSet
, *pFly
);
233 pWrtShell
->EndAllAction();
235 // When saving to docx:
236 save(u
"Office Open XML Text"_ustr
);
238 // Then make sure we write a floating table, not a textframe containing a table:
239 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
240 // Without the accompanying fix in place, this test would have failed with:
241 // - XPath '//w:tbl/w:tblPr/w:tblpPr' number of nodes is incorrect
242 // i.e. no floating table was exported.
243 assertXPath(pXmlDoc
, "//w:tbl/w:tblPr/w:tblpPr", 1);
246 CPPUNIT_TEST_FIXTURE(Test
, testDocFloatingTableImport
)
248 // Given a document with 2 pages:
249 createSwDoc("floattable-compat14.doc");
251 // When laying out that document:
254 // Make sure that the table is split between page 1 and page 2:
255 SwDoc
* pDoc
= getSwDoc();
256 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
257 auto pPage1
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
258 CPPUNIT_ASSERT(pPage1
);
259 // Without the accompanying fix in place, this test would have failed, the fly frame was not
260 // split between page 1 and page 2.
261 CPPUNIT_ASSERT(pPage1
->GetNext());
264 CPPUNIT_TEST_FIXTURE(Test
, testWrapThroughLayoutInCell
)
266 // Given a document with a shape, "keep inside text boundaries" is off, wrap type is set to
269 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
270 uno::Reference
<drawing::XShape
> xShape(
271 xFactory
->createInstance(u
"com.sun.star.drawing.RectangleShape"_ustr
), uno::UNO_QUERY
);
272 xShape
->setSize(awt::Size(10000, 10000));
273 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
274 xShapeProps
->setPropertyValue(u
"AnchorType"_ustr
,
275 uno::Any(text::TextContentAnchorType_AT_CHARACTER
));
276 xShapeProps
->setPropertyValue(u
"Surround"_ustr
, uno::Any(text::WrapTextMode_THROUGH
));
277 xShapeProps
->setPropertyValue(u
"HoriOrientRelation"_ustr
,
278 uno::Any(text::RelOrientation::FRAME
));
279 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
280 xDrawPageSupplier
->getDrawPage()->add(xShape
);
282 // When saving to docx:
283 save(u
"Office Open XML Text"_ustr
);
285 // Then make sure that layoutInCell is undoing the effect of the import-time tweak:
286 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
287 // Without the accompanying fix in place, this test would have failed with:
290 // - attribute 'layoutInCell' of '//wp:anchor' incorrect value.
291 // i.e. layoutInCell was disabled, leading to bad layout in Word.
292 assertXPath(pXmlDoc
, "//wp:anchor", "layoutInCell", u
"1");
295 CPPUNIT_TEST_FIXTURE(Test
, test3Endnotes
)
297 // Given a DOC file with 3 endnotes:
298 createSwDoc("3endnotes.doc");
300 // When laying out that document:
303 // Then make sure that all 3 endnotes are on the last page, like in Word:
304 SwDoc
* pDoc
= getSwDoc();
305 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
306 SwPageFrame
* pPage
= pLayout
->GetLastPage();
307 SwContentFrame
* pLastContent
= pPage
->FindLastBodyContent();
308 SwFrame
* pSectionFrame
= pLastContent
->GetNext();
309 auto pColumnFrame
= pSectionFrame
->GetLower()->DynCastColumnFrame();
310 SwFootnoteContFrame
* pFootnoteCont
= pColumnFrame
->FindFootnoteCont();
312 for (SwFrame
* pLower
= pFootnoteCont
->GetLower(); pLower
; pLower
= pLower
->GetNext())
316 // Without the accompanying fix in place, this test would have failed with:
319 // i.e. only 1 endnote was on the last page, the other 2 was not moved to the end of the
320 // document, which is incorrect.
321 CPPUNIT_ASSERT_EQUAL(3, nEndnotes
);
324 CPPUNIT_TEST_FIXTURE(Test
, testDoNotBreakWrappedTables
)
326 // Given a document with the DO_NOT_BREAK_WRAPPED_TABLES compat mode enabled:
328 SwDoc
* pDoc
= getSwDoc();
329 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
330 rIDSA
.set(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
, true);
332 // When saving to docx:
333 save(u
"Office Open XML Text"_ustr
);
335 // Then make sure the compat flag is serialized:
336 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/settings.xml"_ustr
);
337 // Without the accompanying fix in place, this test would have failed with:
340 // - XPath '/w:settings/w:compat/w:doNotBreakWrappedTables' number of nodes is incorrect
341 // i.e. <w:doNotBreakWrappedTables> was not written.
342 assertXPath(pXmlDoc
, "/w:settings/w:compat/w:doNotBreakWrappedTables", 1);
345 CPPUNIT_TEST_FIXTURE(Test
, testAllowTextAfterFloatingTableBreak
)
347 // Given a document with the ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK compat mode enabled:
349 SwDoc
* pDoc
= getSwDoc();
350 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
351 rIDSA
.set(DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK
, true);
353 // When saving to docx:
354 save(u
"Office Open XML Text"_ustr
);
356 // Then make sure the compat flag is serialized:
357 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/settings.xml"_ustr
);
358 // Without the accompanying fix in place, this test would have failed with:
361 // - XPath '/w:settings/w:compat/w:compatSetting[@w:name='allowTextAfterFloatingTableBreak']' number of nodes is incorrect
362 // i.e. the compat flag was lost on export.
364 "/w:settings/w:compat/w:compatSetting[@w:name='allowTextAfterFloatingTableBreak']",
368 CPPUNIT_TEST_FIXTURE(Test
, testDOCfDontBreakWrappedTables
)
370 // Given a document with fDontBreakWrappedTables:
371 // When importing that document:
372 createSwDoc("dont-break-wrapped-tables.doc");
374 // Then make sure that the matching compat flag is set:
375 SwDoc
* pDoc
= getSwDoc();
376 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
377 bool bDontBreakWrappedTables
= rIDSA
.get(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
);
378 // Without the accompanying fix in place, this test would have failed, the compat flag was not
380 CPPUNIT_ASSERT(bDontBreakWrappedTables
);
383 CPPUNIT_TEST_FIXTURE(Test
, testDOCFloatingTableHiddenAnchor
)
385 // Given a document with a normal table and a floating table with a hidden anchor:
386 createSwDoc("floattable-hidden-anchor.doc");
388 // When laying out that document:
389 xmlDocUniquePtr pLayout
= parseLayoutDump();
391 // Then make sure that both tables are visible:
392 // Without the accompanying fix in place, this test would have failed with:
395 // i.e. the floating table was lost.
396 assertXPath(pLayout
, "//tab", 2);
399 CPPUNIT_TEST_FIXTURE(Test
, testDOCVerticalFlyOffset
)
401 // Given a document with 2 pages, a floating table on the first page and an inline table on the
403 createSwDoc("floattable-vertical-fly-offset.doc");
405 // When laying out that document:
408 // Then make sure that the tables don't overlap:
409 SwDoc
* pDoc
= getSwDoc();
410 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
411 auto pPage1
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
412 CPPUNIT_ASSERT(pPage1
);
413 CPPUNIT_ASSERT(pPage1
->GetSortedObjs());
414 const SwSortedObjs
& rPage1Objs
= *pPage1
->GetSortedObjs();
415 // Page 1 has a floating table:
416 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs
.size());
417 auto pPage2
= dynamic_cast<SwPageFrame
*>(pPage1
->GetNext());
418 // Without the accompanying fix in place, this test would have failed, there was no second page.
419 CPPUNIT_ASSERT(pPage2
);
420 SwFrame
* pBody2
= pPage2
->GetLower();
421 SwFrame
* pTable2
= pBody2
->GetLower();
422 CPPUNIT_ASSERT(pTable2
);
423 // Page 2 starts with an inline table:
424 CPPUNIT_ASSERT(pTable2
->IsTabFrame());
427 CPPUNIT_TEST_FIXTURE(Test
, testFloattableThenFloattable
)
429 // Given a document that contains a floating table, immediately followed by an other floating
431 // When importing the document & laying it out:
432 createSwDoc("floattable-then-floattable.doc");
435 // Then make sure that the two floating table has different anchors:
436 SwDoc
* pDoc
= getSwDoc();
437 auto& rFlys
= *pDoc
->GetSpzFrameFormats();
438 auto pFly1
= rFlys
[0];
439 SwNodeOffset nFly1Anchor
= pFly1
->GetAttrSet().GetAnchor().GetAnchorContentNode()->GetIndex();
440 auto pFly2
= rFlys
[1];
441 SwNodeOffset nFly2Anchor
= pFly2
->GetAttrSet().GetAnchor().GetAnchorContentNode()->GetIndex();
442 // Without the accompanying fix in place, this test would have failed with:
445 // i.e. the two anchor positions were the same instead of first anchor followed by the second
447 CPPUNIT_ASSERT_EQUAL(nFly1Anchor
+ 1, nFly2Anchor
);
450 CPPUNIT_TEST_FIXTURE(Test
, testFloattableOverlapNeverDOCXExport
)
452 // Given a document with a floating table, overlap is not allowed:
454 SwDoc
* pDoc
= getSwDoc();
455 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
456 pWrtShell
->Insert2(u
"before table"_ustr
);
458 SwInsertTableOptions
aTableOptions(SwInsertTableFlags::DefaultBorder
, 0);
459 pWrtShell
->InsertTable(aTableOptions
, /*nRows=*/1, /*nCols=*/1);
460 pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
);
463 // Wrap the table in a text frame:
464 SwFlyFrameAttrMgr
aMgr(true, pWrtShell
, Frmmgr_Type::TEXT
, nullptr);
465 pWrtShell
->StartAllAction();
466 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PARA
, aMgr
.GetPos(), aMgr
.GetSize());
467 pWrtShell
->EndAllAction();
468 // Allow the text frame to split:
469 pWrtShell
->StartAllAction();
470 auto& rFlys
= *pDoc
->GetSpzFrameFormats();
471 auto pFly
= rFlys
[0];
472 SwAttrSet
aSet(pFly
->GetAttrSet());
473 aSet
.Put(SwFormatFlySplit(true));
474 // Don't allow overlap:
475 SwFormatWrapInfluenceOnObjPos aInfluence
;
476 aInfluence
.SetAllowOverlap(false);
477 aSet
.Put(aInfluence
);
478 pDoc
->SetAttr(aSet
, *pFly
);
479 pWrtShell
->EndAllAction();
481 // When saving to DOCX:
482 save(u
"Office Open XML Text"_ustr
);
484 // Then make sure that the overlap=never markup is written:
485 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
486 // Without the accompanying fix in place, this test would have failed with:
489 // - XPath '//w:tblPr/w:tblOverlap' number of nodes is incorrect
490 // i.e. <w:tblOverlap> was not written.
491 assertXPath(pXmlDoc
, "//w:tblPr/w:tblOverlap", "val", u
"never");
494 CPPUNIT_TEST_FIXTURE(Test
, testFloattableOverlapNeverDOCImport
)
496 // Given a document with two floating tables, the second has sprmTFNoAllowOverlap=1 set:
497 // When importing that document:
498 createSwDoc("floattable-tbl-overlap.doc");
500 // Then make sure the second table is marked as "can't overlap":
501 SwDoc
* pDoc
= getSwDoc();
502 sw::FrameFormats
<sw::SpzFrameFormat
*>& rFlys
= *pDoc
->GetSpzFrameFormats();
503 sw::SpzFrameFormat
* pFly
= rFlys
[1];
504 // Without the accompanying fix in place, this test would have failed, the fly had the default
506 CPPUNIT_ASSERT(!pFly
->GetAttrSet().GetWrapInfluenceOnObjPos().GetAllowOverlap());
509 CPPUNIT_TEST_FIXTURE(Test
, testFloattableFootnote
)
511 // Given a document with a floating table and a footnote inside:
512 // When importing that document:
513 createSwDoc("floattable-footnote.doc");
515 // Then make sure we both have a fly frame and a footnote:
516 SwDoc
* pDoc
= getSwDoc();
517 sw::FrameFormats
<sw::SpzFrameFormat
*>& rFlys
= *pDoc
->GetSpzFrameFormats();
518 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rFlys
.size());
519 SwFootnoteIdxs
& rFootnotes
= pDoc
->GetFootnoteIdxs();
520 // Without the accompanying fix in place, this test would have failed with:
523 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rFootnotes
.size());
526 CPPUNIT_TEST_FIXTURE(Test
, testSplitFlyInInlineTableDOC
)
528 // Outer inline table on pages 1 -> 2 -> 3, inner floating table on pages 2 -> 3:
529 // When laying out that document:
530 createSwDoc("floattable-in-inlinetable.doc");
532 SwDoc
* pDoc
= getSwDoc();
533 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
534 auto pPage1
= pLayout
->Lower()->DynCastPageFrame();
535 CPPUNIT_ASSERT(pPage1
);
537 SwFrame
* pBody
= pPage1
->FindBodyCont();
538 auto pTab
= pBody
->GetLower()->DynCastTabFrame();
539 CPPUNIT_ASSERT(!pTab
->GetPrecede());
540 CPPUNIT_ASSERT(pTab
->GetFollow());
542 auto pPage2
= pPage1
->GetNext()->DynCastPageFrame();
543 CPPUNIT_ASSERT(pPage2
);
545 SwFrame
* pBody
= pPage2
->FindBodyCont();
546 auto pTab
= pBody
->GetLower()->DynCastTabFrame();
547 CPPUNIT_ASSERT(pTab
->GetPrecede());
548 // Without the accompanying fix in place, this test would have failed, the outer table was
549 // missing on page 3.
550 CPPUNIT_ASSERT(pTab
->GetFollow());
552 auto pPage3
= pPage2
->GetNext()->DynCastPageFrame();
553 CPPUNIT_ASSERT(pPage3
);
555 SwFrame
* pBody
= pPage3
->FindBodyCont();
556 auto pTab
= pBody
->GetLower()->DynCastTabFrame();
557 CPPUNIT_ASSERT(pTab
->GetPrecede());
558 CPPUNIT_ASSERT(!pTab
->GetFollow());
562 CPPUNIT_TEST_FIXTURE(Test
, testNullPointerDereference
)
564 // Given a document with multiple pages:
565 // When loading that document:
566 // Without the accompanying fix in place, this test would have crashed due to null pointer access
567 createSwDoc("null-pointer-dereference.doc");
568 CPPUNIT_ASSERT_EQUAL(6, getPages());
571 CPPUNIT_TEST_FIXTURE(Test
, testEndnotesAtSectEnd
)
573 // Given a document, endnotes at collected at section end:
575 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
576 pWrtShell
->SplitNode();
577 pWrtShell
->Up(/*bSelect=*/false);
578 pWrtShell
->Insert(u
"x"_ustr
);
579 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/true, 1, /*bBasicCall=*/false);
580 SwSectionData
aSection(SectionType::Content
, pWrtShell
->GetUniqueSectionName());
581 pWrtShell
->StartAction();
582 SfxItemSetFixed
<RES_FTN_AT_TXTEND
, RES_FRAMEDIR
> aSet(pWrtShell
->GetAttrPool());
583 aSet
.Put(SwFormatEndAtTextEnd(FTNEND_ATTXTEND
));
584 pWrtShell
->InsertSection(aSection
, &aSet
);
585 pWrtShell
->EndAction();
586 pWrtShell
->InsertFootnote(OUString(), /*bEndNote=*/true);
588 // When saving to DOCX:
589 save(u
"Office Open XML Text"_ustr
);
591 // Then make sure the endnote position is section end:
592 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/settings.xml"_ustr
);
593 OUString aPos
= getXPath(pXmlDoc
, "/w:settings/w:endnotePr/w:pos", "val");
594 // Without the accompanying fix in place, this test would have failed with:
595 // - XPath '/w:settings/w:endnotePr/w:pos' number of nodes is incorrect
596 // i.e. the default position was used: document end.
597 CPPUNIT_ASSERT_EQUAL(u
"sectEnd"_ustr
, aPos
);
600 CPPUNIT_TEST_FIXTURE(Test
, testContentControlPDFDropDownEmptyItem
)
602 // Given a document with a dropdown content control, one item is empty, which can't be saved to
605 uno::Reference
<lang::XMultiServiceFactory
> xMSF(mxComponent
, uno::UNO_QUERY
);
606 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
607 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
608 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
609 xText
->insertString(xCursor
, u
"test"_ustr
, /*bAbsorb=*/false);
610 xCursor
->gotoStart(/*bExpand=*/false);
611 xCursor
->gotoEnd(/*bExpand=*/true);
612 uno::Reference
<text::XTextContent
> xContentControl(
613 xMSF
->createInstance(u
"com.sun.star.text.ContentControl"_ustr
), uno::UNO_QUERY
);
614 uno::Reference
<beans::XPropertySet
> xContentControlProps(xContentControl
, uno::UNO_QUERY
);
616 uno::Sequence
<beans::PropertyValues
> aListItems
= {
618 comphelper::makePropertyValue(u
"DisplayText"_ustr
, uno::Any(u
"red"_ustr
)),
619 comphelper::makePropertyValue(u
"Value"_ustr
, uno::Any(u
"R"_ustr
)),
622 comphelper::makePropertyValue(u
"DisplayText"_ustr
, uno::Any(u
""_ustr
)),
623 comphelper::makePropertyValue(u
"Value"_ustr
, uno::Any(u
""_ustr
)),
626 xContentControlProps
->setPropertyValue(u
"ListItems"_ustr
, uno::Any(aListItems
));
628 xText
->insertTextContent(xCursor
, xContentControl
, /*bAbsorb=*/true);
630 // When saving to DOCX:
631 save(u
"Office Open XML Text"_ustr
);
633 // Then make sure we only emit 1 list item:
634 xmlDocUniquePtr pXmlDoc
= parseExport(u
"word/document.xml"_ustr
);
635 // Without the accompanying fix in place, this test would have failed with:
638 // i.e. we emitted an empty list item, so the result can't be opened in Word.
639 assertXPath(pXmlDoc
, "//w:dropDownList/w:listItem", 1);
642 CPPUNIT_TEST_FIXTURE(Test
, tdf71749_with_footnote
)
644 // Without the fix in place,
645 // loading the document would hang.
646 createSwDoc("tdf71749_with_footnote.doc");
647 CPPUNIT_ASSERT_EQUAL(1, getPages());
650 CPPUNIT_TEST_FIXTURE(Test
, tdf71749_without_footnote
)
652 // Without the fix in place,
653 // loading the document would hang.
654 createSwDoc("tdf71749_without_footnote.doc");
655 CPPUNIT_ASSERT_EQUAL(1, getPages());
659 CPPUNIT_PLUGIN_IMPLEMENT();
661 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */