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/text/XFootnote.hpp>
13 #include <com/sun/star/text/XFootnotesSupplier.hpp>
14 #include <com/sun/star/awt/FontWeight.hpp>
15 #include <com/sun/star/text/XEndnotesSupplier.hpp>
16 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
17 #include <com/sun/star/text/XTextTablesSupplier.hpp>
18 #include <com/sun/star/text/XTextTable.hpp>
19 #include <com/sun/star/text/XTextDocument.hpp>
20 #include <com/sun/star/style/TabStop.hpp>
22 #include <comphelper/sequenceashashmap.hxx>
23 #include <tools/UnitConversion.hxx>
24 #include <comphelper/propertyvalue.hxx>
26 #include <unotxdoc.hxx>
29 #include <fmtpdsc.hxx>
30 #include <IDocumentContentOperations.hxx>
31 #include <IDocumentSettingAccess.hxx>
32 #include <itabenum.hxx>
34 #include <formatflysplit.hxx>
35 #include <fmtwrapinfluenceonobjpos.hxx>
39 class Test
: public SwModelTestBase
43 : SwModelTestBase("/sw/qa/extras/rtfexport/data/", "Rich Text Format")
48 DECLARE_RTFEXPORT_TEST(testTdf100961_fixedDateTime
, "tdf100961_fixedDateTime.rtf")
50 // This should be a fixed date/time field, not the current time.
51 getParagraph(1, "05.01.19 04:06:08");
53 uno::Reference
<text::XTextFieldsSupplier
> xTFS(mxComponent
, uno::UNO_QUERY
);
54 uno::Reference
<container::XEnumeration
> xFields(xTFS
->getTextFields()->createEnumeration());
55 CPPUNIT_ASSERT_MESSAGE("constant time", getProperty
<bool>(xFields
->nextElement(), "IsFixed"));
58 DECLARE_RTFEXPORT_TEST(testTdf108949
, "tdf108949_footnoteCharFormat.odt")
60 CPPUNIT_ASSERT_EQUAL(1, getPages());
61 CPPUNIT_ASSERT_EQUAL_MESSAGE("Paragraph Numbering style", OUString(),
62 getProperty
<OUString
>(getParagraph(2), "NumberingStyleName"));
64 uno::Reference
<text::XFootnotesSupplier
> xFootnotesSupplier(mxComponent
, uno::UNO_QUERY
);
65 uno::Reference
<container::XIndexAccess
> xFootnotes
= xFootnotesSupplier
->getFootnotes();
67 uno::Reference
<text::XText
> xFootnoteText
;
68 xFootnotes
->getByIndex(0) >>= xFootnoteText
;
69 // This was green (0x00A800), the character property of the footnote character, not the footnote text
70 CPPUNIT_ASSERT_EQUAL_MESSAGE(
71 "Footnote Text color", COL_AUTO
,
72 getProperty
<Color
>(getRun(getParagraphOfText(1, xFootnoteText
), 1), "CharColor"));
75 DECLARE_RTFEXPORT_TEST(testTdf141964_numId0
, "tdf141964_numId0.rtf")
77 // Unit test added where numId is zero - which is only possible in RTF.
78 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(3, "Geschichte"), uno::UNO_QUERY
);
79 // Pre-emptive test: ensure that paragraph 3 remains numbered and numId0 doesn't mean no numbering.
80 CPPUNIT_ASSERT(!getProperty
<OUString
>(xPara
, "NumberingStyleName").isEmpty());
83 DECLARE_RTFEXPORT_TEST(testTdf108949_footnote
, "tdf108949_footnote.rtf")
85 CPPUNIT_ASSERT_EQUAL_MESSAGE("Paragraph Numbering style", OUString(),
86 getProperty
<OUString
>(getParagraph(2), "NumberingStyleName"));
88 uno::Reference
<text::XFootnotesSupplier
> xFootnotesSupplier(mxComponent
, uno::UNO_QUERY
);
89 uno::Reference
<container::XIndexAccess
> xFootnotes
= xFootnotesSupplier
->getFootnotes();
91 uno::Reference
<text::XFootnote
> xFootnote
;
92 xFootnotes
->getByIndex(0) >>= xFootnote
;
93 // The color of the footnote anchor was black (0x000000)
94 CPPUNIT_ASSERT_EQUAL_MESSAGE("Footnote Character color", Color(0xFF0000),
95 getProperty
<Color
>(xFootnote
->getAnchor(), "CharColor"));
98 DECLARE_RTFEXPORT_TEST(testTdf130817
, "tdf130817.rtf")
100 uno::Reference
<text::XEndnotesSupplier
> xEndnotesSupplier(mxComponent
, uno::UNO_QUERY
);
101 uno::Reference
<container::XIndexAccess
> xEndnotes
= xEndnotesSupplier
->getEndnotes();
103 uno::Reference
<text::XFootnote
> xEndnote1
;
104 xEndnotes
->getByIndex(0) >>= xEndnote1
;
105 uno::Reference
<text::XText
> xEndnoteText1
;
106 xEndnotes
->getByIndex(0) >>= xEndnoteText1
;
107 CPPUNIT_ASSERT_EQUAL(OUString("Titolo 1"), xEndnoteText1
->getString().trim());
108 CPPUNIT_ASSERT_EQUAL(OUString("$"), xEndnote1
->getAnchor()->getString());
110 uno::Reference
<text::XFootnote
> xEndnote2
;
111 xEndnotes
->getByIndex(1) >>= xEndnote2
;
112 uno::Reference
<text::XText
> xEndnoteText2
;
113 xEndnotes
->getByIndex(1) >>= xEndnoteText2
;
114 CPPUNIT_ASSERT_EQUAL(OUString("Titolo 2"), xEndnoteText2
->getString().trim());
115 CPPUNIT_ASSERT_EQUAL(OUString("$"), xEndnote1
->getAnchor()->getString());
118 DECLARE_RTFEXPORT_TEST(testTdf154129_transparentFrame
, "tdf154129_transparentFrame.rtf")
120 // Without the fix, this was zero, and the text frame with "Visible" just looks white.
121 CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty
<sal_Int16
>(getShape(1), "FillTransparence"));
124 DECLARE_RTFEXPORT_TEST(testTdf137683_charHighlightNone
, "tdf137683_charHighlightNone.rtf")
126 uno::Reference
<beans::XPropertySet
> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY_THROW
);
127 // This test was failing with a brown charHighlight of 8421376 (0x808000), instead of COL_TRANSPARENT (0xFFFFFFFF)
128 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharHighlight"));
131 DECLARE_RTFEXPORT_TEST(testTdf116436_tableBackground
, "tdf116436_tableBackground.odt")
133 CPPUNIT_ASSERT_EQUAL(1, getPages());
134 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(mxComponent
, uno::UNO_QUERY
);
135 uno::Reference
<container::XIndexAccess
> xTables(xTextTablesSupplier
->getTextTables(),
137 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY
);
138 uno::Reference
<table::XCell
> xCell
= xTable
->getCellByName("A1");
140 CPPUNIT_ASSERT_EQUAL(Color(0xF8DF7C), getProperty
<Color
>(xCell
, "BackColor"));
141 xCell
.set(xTable
->getCellByName("A6"));
142 CPPUNIT_ASSERT_EQUAL(Color(0x81D41A), getProperty
<Color
>(xCell
, "BackColor"));
143 xCell
.set(xTable
->getCellByName("B6"));
145 CPPUNIT_ASSERT_EQUAL(Color(0xFFFBCC), getProperty
<Color
>(xCell
, "BackColor"));
148 DECLARE_RTFEXPORT_TEST(testTdf122589_firstSection
, "tdf122589_firstSection.odt")
150 CPPUNIT_ASSERT_EQUAL(1, getPages());
151 uno::Reference
<beans::XPropertySet
> xPageStyle(getStyles("PageStyles")->getByName("Standard"),
153 uno::Reference
<text::XTextRange
> xHeaderText
154 = getProperty
<uno::Reference
<text::XTextRange
>>(xPageStyle
, "HeaderText");
155 CPPUNIT_ASSERT_EQUAL(OUString("My header"), xHeaderText
->getString());
157 CPPUNIT_ASSERT_EQUAL_MESSAGE("# of paragraphs", 2, getParagraphs());
160 DECLARE_RTFEXPORT_TEST(testTdf104035
, "tdf104035.rtf")
162 auto aTabStops
= getProperty
<uno::Sequence
<style::TabStop
>>(getParagraph(1), "ParaTabStops");
163 CPPUNIT_ASSERT(aTabStops
.hasElements());
164 // This was 3330 twips instead, as tabs were assumed to be relative.
165 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(convertTwipToMm100(450)), aTabStops
[0].Position
);
168 DECLARE_RTFEXPORT_TEST(testGraphicObjectFliph
, "graphic-object-fliph.rtf")
170 CPPUNIT_ASSERT(getProperty
<bool>(getShape(1), "HoriMirroredOnEvenPages"));
171 CPPUNIT_ASSERT(getProperty
<bool>(getShape(1), "HoriMirroredOnOddPages"));
174 DECLARE_RTFEXPORT_TEST(testTdf114333
, "tdf114333.rtf")
176 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(mxComponent
, uno::UNO_QUERY
);
177 uno::Reference
<container::XIndexAccess
> xTables(xTextTablesSupplier
->getTextTables(),
179 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY
);
180 // Check the distance from left
181 CPPUNIT_ASSERT_EQUAL(sal_Int32(8502), getProperty
<sal_Int32
>(xTable
, "LeftMargin"));
182 // This was 17000 = 8502 + 8498 on import, 15240 on export and following import
183 CPPUNIT_ASSERT_EQUAL(sal_Int32(8498), getProperty
<sal_Int32
>(xTable
, "Width"));
186 DECLARE_RTFEXPORT_TEST(testTdf115180
, "tdf115180.docx")
188 // On export to RTF, column separator positions were written without taking base width
189 // into account and then arrived huge, ~64000, which resulted in wrong table and cell widths
191 sal_Int32 rowWidth
= parseDump("/root/page/body/tab/row/infos/bounds", "width").toInt32();
192 CPPUNIT_ASSERT_EQUAL_MESSAGE("Row width", sal_Int32(9360), rowWidth
);
194 = parseDump("/root/page/body/tab/row/cell[1]/infos/bounds", "width").toInt32();
195 CPPUNIT_ASSERT_MESSAGE("First cell width", cell1Width
>= 9140);
196 CPPUNIT_ASSERT_MESSAGE("First cell width", cell1Width
<= 9142);
198 = parseDump("/root/page/body/tab/row/cell[2]/infos/bounds", "width").toInt32();
199 CPPUNIT_ASSERT_MESSAGE("Second cell width", cell2Width
>= 218);
200 CPPUNIT_ASSERT_MESSAGE("Second cell width", cell2Width
<= 220);
203 DECLARE_ODFEXPORT_TEST(testArabicZeroNumbering
, "arabic-zero-numbering.rtf")
206 = getProperty
<uno::Reference
<container::XIndexAccess
>>(getParagraph(1), "NumberingRules");
207 comphelper::SequenceAsHashMap
aMap(xNumberingRules
->getByIndex(0));
208 // Without the accompanying fix in place, this test would have failed with:
211 // i.e. numbering type was ARABIC, not ARABIC_ZERO.
212 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing
<sal_uInt16
>(style::NumberingType::ARABIC_ZERO
),
213 aMap
["NumberingType"].get
<sal_uInt16
>());
216 DECLARE_RTFEXPORT_TEST(testTdf116841
, "tdf116841.rtf")
218 // This was 0, left margin was ignored as we assumed the default is already
220 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1270),
221 getProperty
<sal_Int32
>(getParagraph(1), "ParaLeftMargin"));
224 DECLARE_RTFEXPORT_TEST(testTdf117268
, "tdf117268.rtf")
226 // Here we check that we correctly mimic Word's treatment of erroneous \itap0 inside tables.
227 // Previously, the first table was import as text, and second top-level one only imported
228 // last row with nested table (first row was also imported as text).
229 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY_THROW
);
230 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
231 uno::UNO_QUERY_THROW
);
233 // First (simple) table
234 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY_THROW
);
235 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getRows()->getCount());
236 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getColumns()->getCount());
237 uno::Reference
<text::XTextRange
> xCell(xTable
->getCellByName("A1"), uno::UNO_QUERY_THROW
);
238 CPPUNIT_ASSERT_EQUAL(OUString("Text 1"), xCell
->getString());
241 xTable
.set(xTables
->getByIndex(1), uno::UNO_QUERY_THROW
);
242 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getRows()->getCount());
243 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getColumns()->getCount());
244 xCell
.set(xTable
->getCellByName("A1"), uno::UNO_QUERY_THROW
);
245 CPPUNIT_ASSERT_EQUAL(OUString("Text 3"), xCell
->getString());
246 uno::Reference
<beans::XPropertySet
> xNestedAnchor(xTable
->getAnchor(), uno::UNO_QUERY_THROW
);
247 uno::Reference
<text::XTextRange
> xAnchorCell(xNestedAnchor
->getPropertyValue("Cell"),
248 uno::UNO_QUERY_THROW
);
251 xTable
.set(xTables
->getByIndex(2), uno::UNO_QUERY_THROW
);
252 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable
->getRows()->getCount());
253 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getColumns()->getCount());
254 xCell
.set(xTable
->getCellByName("A1"), uno::UNO_QUERY_THROW
);
255 CPPUNIT_ASSERT_EQUAL(OUString("Text 2"), xCell
->getString());
256 xCell
.set(xTable
->getCellByName("A2"), uno::UNO_QUERY_THROW
);
257 CPPUNIT_ASSERT_EQUAL(xCell
, xAnchorCell
);
260 DECLARE_RTFEXPORT_TEST(testTdf117505
, "tdf117505.odt")
262 CPPUNIT_ASSERT_EQUAL(1, getShapes());
263 CPPUNIT_ASSERT_EQUAL(1, getPages());
264 uno::Reference
<container::XNameAccess
> xPageStyles(getStyles("PageStyles"));
265 uno::Reference
<beans::XPropertySet
> xFirstPage(xPageStyles
->getByName("First Page"),
267 // This was 499, small header height resulted in visible whitespace from
268 // remaining top margin -> header content moved down.
269 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1499),
270 getProperty
<sal_Int32
>(xFirstPage
, "HeaderHeight"));
273 DECLARE_RTFEXPORT_TEST(testTdf112520
, "tdf112520.docx")
278 // Assert that the white shape is on top of the yellow one.
279 CPPUNIT_ASSERT_EQUAL(Color(0xffff00), getProperty
<Color
>(getShape(2), "FillColor"));
280 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER
,
281 getProperty
<text::TextContentAnchorType
>(getShape(2), "AnchorType"));
282 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, getProperty
<Color
>(getShape(3), "FillColor"));
283 // Without the accompanying fix in place, this test would have failed with
284 // 'expected: 4, actual: 2'.
285 // This means the draw page was 0/at-char/white, 1/at-char/yellow, 2/at-page/white,
286 // instead of the good 0/at-page/white, 1/at-char/yellow, 2/at-char/white.
287 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER
,
288 getProperty
<text::TextContentAnchorType
>(getShape(3), "AnchorType"));
291 CPPUNIT_TEST_FIXTURE(Test
, testNestedHyperlink
)
293 // Given a hyperlink contains a footnote which contains a hyperlink:
296 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
297 uno::Reference
<text::XTextContent
> xFootnote(
298 xFactory
->createInstance("com.sun.star.text.Footnote"), uno::UNO_QUERY
);
299 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
300 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
301 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
302 xText
->insertString(xCursor
, "a", /*bAbsorb=*/false);
303 xText
->insertTextContent(xCursor
, xFootnote
, /*bAbsorb=*/false);
304 xText
->insertString(xCursor
, "b", /*bAbsorb=*/false);
305 xCursor
->gotoStart(/*bExpand=*/false);
306 xCursor
->gotoEnd(/*bExpand=*/true);
307 uno::Reference
<beans::XPropertySet
> xCursorProps(xCursor
, uno::UNO_QUERY
);
308 xCursorProps
->setPropertyValue("HyperLinkURL", uno::Any(OUString("http://body.com/")));
309 uno::Reference
<text::XText
> xFootnoteText(xFootnote
, uno::UNO_QUERY
);
310 xCursor
= xFootnoteText
->createTextCursor();
311 xFootnoteText
->insertString(xCursor
, "x", /*bAbsorb=*/false);
312 xCursor
->gotoStart(/*bExpand=*/false);
313 xCursor
->gotoEnd(/*bExpand=*/true);
314 xCursorProps
.set(xCursor
, uno::UNO_QUERY
);
315 xCursorProps
->setPropertyValue("HyperLinkURL", uno::Any(OUString("http://footnote.com/")));
318 // When exporting to RTF:
319 // Without the accompanying fix in place, this test would have failed with:
321 // - Expression: xComponent.is()
322 // i.e. the RTF output was not well-formed, loading failed.
323 saveAndReload("Rich Text Format");
325 // Then make sure both hyperlinks are have the correct URLs.
326 uno::Reference
<text::XTextRange
> xParagraph
= getParagraph(1);
327 uno::Reference
<text::XTextRange
> xPortion
= getRun(xParagraph
, 1);
328 CPPUNIT_ASSERT_EQUAL(OUString("http://body.com/"),
329 getProperty
<OUString
>(xPortion
, "HyperLinkURL"));
330 auto xFootnote
= getProperty
<uno::Reference
<text::XText
>>(getRun(xParagraph
, 2), "Footnote");
331 uno::Reference
<text::XTextRange
> xFootnotePortion
= getRun(getParagraphOfText(1, xFootnote
), 1);
332 CPPUNIT_ASSERT_EQUAL(OUString("http://footnote.com/"),
333 getProperty
<OUString
>(xFootnotePortion
, "HyperLinkURL"));
336 DECLARE_RTFEXPORT_TEST(testTdf121623
, "tdf121623.rtf")
338 // This was 2, multicolumn section was ignored at the table.
339 CPPUNIT_ASSERT_EQUAL(1, getPages());
342 DECLARE_RTFEXPORT_TEST(testTdf66543
, "tdf66543.rtf")
344 // Without the accompanying fix in place, this test would have failed with
345 // 'Expected: 2; Actual : 3' after import (off-by-one), then with
346 // 'Expected: 2; Actual : 0' (export not implemented).
347 CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
348 getProperty
<sal_Int32
>(getParagraph(1), "ParaLineNumberStartValue"));
351 DECLARE_RTFEXPORT_TEST(testUlw
, "ulw.rtf")
353 // Test underlying in individual words mode.
354 CPPUNIT_ASSERT(getProperty
<bool>(getRun(getParagraph(1), 1), "CharWordMode"));
357 DECLARE_RTFEXPORT_TEST(testTdf122455
, "tdf122455.rtf")
359 // Without the accompanying fix in place, this test would have failed with
360 // 'Expected: 16; Actual : 32', the font size from a list definition
361 // leaked into the first run's character properties.
362 CPPUNIT_ASSERT_EQUAL(16.0, getProperty
<double>(getRun(getParagraph(1), 1), "CharHeight"));
365 DECLARE_RTFEXPORT_TEST(testTdf125719_case_1
, "tdf125719_case_1.rtf")
367 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL
,
368 getProperty
<float>(getRun(getParagraph(1), 1), "CharWeight"));
369 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL
,
370 getProperty
<float>(getRun(getParagraph(3), 1), "CharWeight"));
373 DECLARE_RTFEXPORT_TEST(testTdf125719_case_2
, "tdf125719_case_2.rtf")
375 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD
,
376 getProperty
<float>(getRun(getParagraph(1), 1), "CharWeight"));
377 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD
,
378 getProperty
<float>(getRun(getParagraph(3), 1), "CharWeight"));
379 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL
,
380 getProperty
<float>(getRun(getParagraph(5), 1), "CharWeight"));
383 DECLARE_RTFEXPORT_TEST(testTabs
, "tabs.rtf")
385 // Test tab alignment in decimal mode.
386 auto aTabStops
= getProperty
<uno::Sequence
<style::TabStop
>>(getParagraph(1), "ParaTabStops");
387 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabStops
.getLength());
388 const style::TabStop
& rTabStop
= aTabStops
[0];
389 CPPUNIT_ASSERT_EQUAL(style::TabAlign_DECIMAL
, rTabStop
.Alignment
);
392 DECLARE_RTFEXPORT_TEST(testTdf123703
, "tdf123703.rtf")
395 // This was 1, because of normal space character width in consecutive spaces
396 CPPUNIT_ASSERT_EQUAL(2, getPages());
399 CPPUNIT_ASSERT_EQUAL(1, getPages());
403 DECLARE_RTFEXPORT_TEST(testTdf123703_stshfdbch
, "tdf123703_stshfdbch.rtf")
406 CPPUNIT_ASSERT_EQUAL(1, getPages());
409 DECLARE_RTFEXPORT_TEST(testTdf123703_compatible
, "tdf123703_compatible.rtf")
412 // in the case of compatibility font id 31505
413 CPPUNIT_ASSERT_EQUAL(2, getPages());
416 CPPUNIT_ASSERT_EQUAL(1, getPages());
420 DECLARE_RTFEXPORT_TEST(testTdf128428_monospaced
, "tdf128428_monospaced.rtf")
423 CPPUNIT_ASSERT_EQUAL(1, getPages());
426 DECLARE_RTFEXPORT_TEST(testTdf128428_compatible_monospaced
, "tdf128428_compatible_monospaced.rtf")
429 CPPUNIT_ASSERT_EQUAL(1, getPages());
432 DECLARE_RTFEXPORT_TEST(testTdf128428_dntblnsbdb
, "tdf128428_dntblnsbdb.rtf")
435 CPPUNIT_ASSERT_EQUAL(1, getPages());
438 CPPUNIT_TEST_FIXTURE(Test
, testDontBreakWrappedTables
)
440 // Given a document with no DO_NOT_BREAK_WRAPPED_TABLES compat mode enabled:
443 SwDoc
* pDoc
= getSwDoc();
444 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
445 rIDSA
.set(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
, true);
448 // When saving to rtf:
449 saveAndReload("Rich Text Format");
451 // Then make sure \nobrkwrptbl is not written:
452 SwDoc
* pDoc
= getSwDoc();
453 IDocumentSettingAccess
& rIDSA
= pDoc
->getIDocumentSettingAccess();
454 bool bDontBreakWrappedTables
= rIDSA
.get(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
);
455 // Without the accompanying fix in place, this test would have failed, the compat flag was not
457 CPPUNIT_ASSERT(bDontBreakWrappedTables
);
460 CPPUNIT_TEST_FIXTURE(Test
, testRtlGutter
)
462 auto verify
= [this]() {
463 uno::Reference
<beans::XPropertySet
> xStandard(
464 getStyles("PageStyles")->getByName("Standard"), uno::UNO_QUERY
);
465 CPPUNIT_ASSERT(getProperty
<bool>(xStandard
, "RtlGutter"));
468 // Given a document with RTL gutter, when loading it:
469 createSwDoc("rtl-gutter.rtf");
470 // Then make sure the section's gutter is still RTL:
471 // Without the accompanying fix in place, this test would have failed as \rtlgutter was missing.
473 saveAndReload("Rich Text Format");
477 CPPUNIT_TEST_FIXTURE(Test
, testNegativePageBorder
)
480 // Given a document with a top margin and a border which has more spacing than the margin on
483 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
484 SwDocShell
* pDocShell
= pTextDoc
->GetDocShell();
485 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
486 pWrtShell
->Insert("first");
487 pWrtShell
->SplitNode();
488 pWrtShell
->Insert("second");
489 SwPageDesc
* pDesc
= pWrtShell
->FindPageDescByName("Left Page", true);
490 SwPaM
aPaM(*pWrtShell
->GetCursor()->GetPoint());
491 SwFormatPageDesc
aFormatPageDesc(pDesc
);
492 pDocShell
->GetDoc()->getIDocumentContentOperations().InsertPoolItem(aPaM
, aFormatPageDesc
);
493 uno::Reference
<beans::XPropertySet
> xPageStyle(
494 getStyles("PageStyles")->getByName("Left Page"), uno::UNO_QUERY
);
495 xPageStyle
->setPropertyValue("TopMargin", uno::Any(static_cast<sal_Int32
>(501)));
496 table::BorderLine2 aBorder
;
497 aBorder
.LineWidth
= 159;
498 aBorder
.OuterLineWidth
= 159;
499 xPageStyle
->setPropertyValue("TopBorder", uno::Any(aBorder
));
500 sal_Int32 nTopBorderDistance
= -646;
501 xPageStyle
->setPropertyValue("TopBorderDistance", uno::Any(nTopBorderDistance
));
504 // When saving that document to RTF:
505 saveAndReload("Rich Text Format");
507 // Then make sure that the border distance is negative, so the first line of body text appears
508 // on top of the page border:
509 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
510 SwDocShell
* pDocShell
= pTextDoc
->GetDocShell();
511 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
512 pWrtShell
->Down(/*bSelect=*/false);
513 OUString aPageStyle
= pWrtShell
->GetCurPageStyle();
514 uno::Reference
<beans::XPropertySet
> xPageStyle(getStyles("PageStyles")->getByName(aPageStyle
),
516 auto nTopMargin
= xPageStyle
->getPropertyValue("TopMargin").get
<sal_Int32
>();
517 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(501), nTopMargin
);
518 auto aTopBorder
= xPageStyle
->getPropertyValue("TopBorder").get
<table::BorderLine2
>();
519 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(159), aTopBorder
.LineWidth
);
520 auto nTopBorderDistance
= xPageStyle
->getPropertyValue("TopBorderDistance").get
<sal_Int32
>();
521 // Without the accompanying fix in place, this test would have failed with:
524 // i.e. the border negative distance was lost.
525 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(-646), nTopBorderDistance
);
528 CPPUNIT_TEST_FIXTURE(Test
, testTdf127806
)
530 createSwDoc("tdf127806.rtf");
531 CPPUNIT_ASSERT_EQUAL(2, getShapes());
533 CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.GroupShape"), getShape(1)->getShapeType());
534 auto xImage
= getShape(2);
535 CPPUNIT_ASSERT_EQUAL(OUString("FrameShape"), xImage
->getShapeType());
536 awt::Size
aSize(xImage
->getSize());
537 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(600), aSize
.Height
);
538 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(635), aSize
.Width
);
540 saveAndReload("Rich Text Format");
541 CPPUNIT_ASSERT_EQUAL(1, getShapes()); // FIXME: We lost one shape on export, that's sucks
543 xImage
= getShape(1);
544 CPPUNIT_ASSERT_EQUAL(OUString("FrameShape"), xImage
->getShapeType());
546 aSize
= xImage
->getSize();
547 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(600), aSize
.Height
);
548 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(635), aSize
.Width
);
551 DECLARE_RTFEXPORT_TEST(testTdf148578
, "tdf148578.rtf")
553 // \trgaph567 should affect only table cell margins (~1cm),
554 // but do not shift table, since \trleft is not provided
555 uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(1), uno::UNO_QUERY
);
557 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), getProperty
<sal_Int32
>(xTable
, "LeftMargin"));
559 uno::Reference
<text::XTextRange
> xCell(xTable
->getCellByName("A1"), uno::UNO_QUERY
);
560 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1000),
561 getProperty
<sal_Int32
>(xCell
, "LeftBorderDistance"));
562 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1000),
563 getProperty
<sal_Int32
>(xCell
, "RightBorderDistance"));
565 xCell
.set(xTable
->getCellByName("B1"), uno::UNO_QUERY
);
566 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1000),
567 getProperty
<sal_Int32
>(xCell
, "LeftBorderDistance"));
568 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1000),
569 getProperty
<sal_Int32
>(xCell
, "RightBorderDistance"));
572 DECLARE_RTFEXPORT_TEST(testInvalidParagraphStyle
, "invalidParagraphStyle.rtf")
574 // Given test has character style #30, but referred as paragraph style #30
575 // This was causing exception in finishParagraph(), so numbering and other
576 // properties were not applied. Ensure numbering is still here
577 sal_Int16 numFormat
= getNumberingTypeOfParagraph(1);
578 CPPUNIT_ASSERT_EQUAL(style::NumberingType::ARABIC
, numFormat
);
581 DECLARE_RTFEXPORT_TEST(testTdf152784_1
, "tdf152784_1.rtf")
583 // Ensure that paragraph having style with numbering does not have numbering
584 // since it is not explicitly defined in paragraph properties
585 uno::Reference
<beans::XPropertySet
> xPara(getParagraph(1, "Here should be no numbering!"),
587 CPPUNIT_ASSERT(getProperty
<OUString
>(xPara
, "NumberingStyleName").isEmpty());
590 CPPUNIT_TEST_FIXTURE(Test
, testFloatingTableExport
)
592 // Given a document with a floating table:
593 mxComponent
= loadFromDesktop("private:factory/swriter");
595 uno::Sequence
<beans::PropertyValue
> aArgs
= {
596 comphelper::makePropertyValue("Rows", static_cast<sal_Int32
>(1)),
597 comphelper::makePropertyValue("Columns", static_cast<sal_Int32
>(1)),
599 dispatchCommand(mxComponent
, ".uno:InsertTable", aArgs
);
601 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
604 comphelper::makePropertyValue("AnchorType", static_cast<sal_uInt16
>(0)),
606 dispatchCommand(mxComponent
, ".uno:InsertFrame", aArgs
);
607 // Mark it as a floating table:
608 uno::Reference
<text::XTextFramesSupplier
> xTextFramesSupplier(mxComponent
, uno::UNO_QUERY
);
609 uno::Reference
<beans::XPropertySet
> xFrame(
610 xTextFramesSupplier
->getTextFrames()->getByName("Frame1"), uno::UNO_QUERY
);
611 xFrame
->setPropertyValue("IsSplitAllowed", uno::Any(true));
612 // Originally 10, 30 & 40 twips.
613 xFrame
->setPropertyValue("VertOrientPosition", uno::Any(static_cast<sal_Int32
>(18)));
614 xFrame
->setPropertyValue("LeftMargin", uno::Any(static_cast<sal_Int32
>(53)));
615 xFrame
->setPropertyValue("RightMargin", uno::Any(static_cast<sal_Int32
>(71)));
617 // When saving to RTF:
618 saveAndReload("Rich Text Format");
620 // Then make sure the floating table is there & has the expected properties:
621 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
622 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
623 xFrame
.set(xDrawPage
->getByIndex(0), uno::UNO_QUERY
);
624 bool bIsSplitAllowed
{};
625 xFrame
->getPropertyValue("IsSplitAllowed") >>= bIsSplitAllowed
;
626 // Without the accompanying fix in place, this test would have failed, the table was not
628 CPPUNIT_ASSERT(bIsSplitAllowed
);
629 sal_Int16 nVertOrientRelation
{};
630 xFrame
->getPropertyValue("VertOrientRelation") >>= nVertOrientRelation
;
631 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME
, nVertOrientRelation
);
632 sal_Int16 nHoriOrientRelation
{};
633 xFrame
->getPropertyValue("HoriOrientRelation") >>= nHoriOrientRelation
;
634 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME
, nHoriOrientRelation
);
635 sal_Int32 nVertOrientPosition
{};
636 xFrame
->getPropertyValue("VertOrientPosition") >>= nVertOrientPosition
;
637 sal_Int32 nExpected
= 18;
638 CPPUNIT_ASSERT_EQUAL(nExpected
, nVertOrientPosition
);
639 sal_Int32 nLeftMargin
{};
640 xFrame
->getPropertyValue("LeftMargin") >>= nLeftMargin
;
642 CPPUNIT_ASSERT_EQUAL(nExpected
, nLeftMargin
);
643 sal_Int32 nRightMargin
{};
644 xFrame
->getPropertyValue("RightMargin") >>= nRightMargin
;
646 CPPUNIT_ASSERT_EQUAL(nExpected
, nRightMargin
);
649 CPPUNIT_TEST_FIXTURE(Test
, testFloattableOverlapNeverRTFExport
)
651 // Given a document with a floating table, overlap is not allowed:
654 SwDoc
* pDoc
= getSwDoc();
655 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
656 pWrtShell
->Insert2("before table");
658 SwInsertTableOptions
aTableOptions(SwInsertTableFlags::DefaultBorder
, 0);
659 pWrtShell
->InsertTable(aTableOptions
, /*nRows=*/1, /*nCols=*/1);
660 pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
);
663 // Wrap the table in a text frame:
664 SwFlyFrameAttrMgr
aMgr(true, pWrtShell
, Frmmgr_Type::TEXT
, nullptr);
665 pWrtShell
->StartAllAction();
666 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PARA
, aMgr
.GetPos(), aMgr
.GetSize());
667 pWrtShell
->EndAllAction();
668 // Allow the text frame to split:
669 pWrtShell
->StartAllAction();
670 sw::FrameFormats
<sw::SpzFrameFormat
*>* pFlys
= pDoc
->GetSpzFrameFormats();
671 sw::SpzFrameFormat
* pFly
= (*pFlys
)[0];
672 SwAttrSet
aSet(pFly
->GetAttrSet());
673 aSet
.Put(SwFormatFlySplit(true));
674 // Don't allow overlap:
675 SwFormatWrapInfluenceOnObjPos aInfluence
;
676 aInfluence
.SetAllowOverlap(false);
677 aSet
.Put(aInfluence
);
678 pDoc
->SetAttr(aSet
, *pFly
);
679 pWrtShell
->EndAllAction();
682 // When saving to RTF:
683 saveAndReload("Rich Text Format");
685 // Then make sure that the overlap=never markup is written:
686 SwDoc
* pDoc
= getSwDoc();
687 sw::FrameFormats
<sw::SpzFrameFormat
*>* pFlys
= pDoc
->GetSpzFrameFormats();
688 sw::SpzFrameFormat
* pFly
= (*pFlys
)[0];
689 // Without the accompanying fix in place, this test would have failed, i.e. \tabsnoovrlp was not
691 CPPUNIT_ASSERT(!pFly
->GetAttrSet().GetWrapInfluenceOnObjPos().GetAllowOverlap());
694 CPPUNIT_PLUGIN_IMPLEMENT();
696 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */