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 <com/sun/star/drawing/FillStyle.hpp>
11 #include <swmodeltestbase.hxx>
13 #include <itabenum.hxx>
16 #include <drawdoc.hxx>
18 #include <com/sun/star/text/XTextColumns.hpp>
20 #include <svx/svdpage.hxx>
21 #include <svx/svdview.hxx>
22 #include <svl/itemiter.hxx>
23 #include <vcl/filter/PDFiumLibrary.hxx>
26 #include <txatbase.hxx>
27 #include <IDocumentDrawModelAccess.hxx>
28 #include <IDocumentRedlineAccess.hxx>
29 #include <IDocumentLayoutAccess.hxx>
30 #include <UndoManager.hxx>
31 #include <unotools/syslocaleoptions.hxx>
33 #include <svl/stritem.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/dispatch.hxx>
37 #include <tools/json_writer.hxx>
38 #include <boost/property_tree/json_parser.hpp>
40 #include <com/sun/star/text/XTextTable.hpp>
41 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
42 #include <o3tl/cppunittraitshelper.hxx>
43 #include <swdtflvr.hxx>
44 #include <comphelper/propertysequence.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <comphelper/scopeguard.hxx>
48 #include <editeng/swafopt.hxx>
49 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
50 #include <vcl/scheduler.hxx>
51 #include <config_fonts.h>
52 #include <test/htmltesttools.hxx>
53 #include <wrthtml.hxx>
55 #include <rootfrm.hxx>
56 #include <unotxdoc.hxx>
58 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
59 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
60 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
61 #include <linguistic/misc.hxx>
63 #include <workctrl.hxx>
66 using namespace com::sun::star
;
67 using namespace com::sun::star::beans
;
68 using namespace com::sun::star::lang
;
69 using namespace com::sun::star::uno
;
70 using namespace com::sun::star::linguistic2
;
71 using namespace linguistic
;
75 sal_Int32
lcl_getAttributeIDFromHints(const SwpHints
& hints
)
77 for (size_t i
= 0; i
< hints
.Count(); ++i
)
79 const SwTextAttr
* hint
= hints
.Get(i
);
80 if (hint
->Which() == RES_TXTATR_AUTOFMT
)
82 const SwFormatAutoFormat
& rFmt
= hint
->GetAutoFormat();
83 SfxItemIter
aIter(*rFmt
.GetStyleHandle());
84 return aIter
.GetCurItem()->Which();
90 uno::Reference
<XLinguServiceManager2
> GetLngSvcMgr_Impl()
92 uno::Reference
<XComponentContext
> xContext(comphelper::getProcessComponentContext());
93 uno::Reference
<XLinguServiceManager2
> xRes
= LinguServiceManager::create(xContext
);
98 class SwUiWriterTest6
: public SwModelTestBase
, public HtmlTestTools
102 : SwModelTestBase("/sw/qa/extras/uiwriter/data/")
107 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116640
)
111 uno::Sequence
<beans::PropertyValue
> aArgs(
112 comphelper::InitPropertySequence({ { "Columns", uno::Any(sal_Int32(2)) } }));
114 dispatchCommand(mxComponent
, ".uno:InsertSection", aArgs
);
116 uno::Reference
<text::XTextSectionsSupplier
> xTextSectionsSupplier(mxComponent
, uno::UNO_QUERY
);
117 uno::Reference
<container::XIndexAccess
> xSections(xTextSectionsSupplier
->getTextSections(),
119 uno::Reference
<beans::XPropertySet
> xTextSection(xSections
->getByIndex(0), uno::UNO_QUERY
);
121 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
123 uno::Reference
<text::XTextColumns
> xTextColumns
124 = getProperty
<uno::Reference
<text::XTextColumns
>>(xTextSection
, "TextColumns");
125 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns
->getColumnCount());
127 dispatchCommand(mxComponent
, ".uno:Undo", {});
129 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
131 dispatchCommand(mxComponent
, ".uno:Redo", {});
133 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
135 dispatchCommand(mxComponent
, ".uno:Undo", {});
137 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
140 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf108524
)
142 createSwDoc("tdf108524.odt");
143 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
144 // In total we expect two cells containing a section.
145 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
147 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
148 // This was 0, section wasn't split, instead it was only on the first page
149 // and it was cut off.
150 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
153 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testLinesInSectionInTable
)
155 // This is similar to testTdf108524(), but the page boundary now is not in
156 // the middle of a multi-line paragraph: the section only contains oneliner
157 // paragraphs instead.
158 createSwDoc("lines-in-section-in-table.odt");
159 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
160 // In total we expect two cells containing a section.
161 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
163 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
164 // This was 0, section wasn't split, instead it was only on the first page
165 // and it was cut off.
166 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
169 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testLinesMoveBackwardsInSectionInTable
)
172 // Assert that paragraph "4" is on page 1 and "5" is on page 2.
173 createSwDoc("lines-in-section-in-table.odt");
174 SwDoc
* pDoc
= getSwDoc();
175 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
176 assertXPath(pXmlDoc
, "/root/page", 2);
177 SwNodeOffset
nPara4Node(
178 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
180 CPPUNIT_ASSERT_EQUAL(OUString("4"), pDoc
->GetNodes()[nPara4Node
]->GetTextNode()->GetText());
181 SwNodeOffset
nPara5Node(
182 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
184 CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc
->GetNodes()[nPara5Node
]->GetTextNode()->GetText());
186 // Remove paragraph "4".
187 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
188 while (pWrtShell
->GetCursor()->GetPointNode().GetIndex() < nPara4Node
)
189 pWrtShell
->Down(/*bSelect=*/false);
190 pWrtShell
->EndPara();
191 pWrtShell
->Up(/*bSelect=*/true);
192 pWrtShell
->DelLeft();
194 // Assert that paragraph "5" is now moved back to page 1 and is the last paragraph there.
195 discardDumpedLayout();
196 pXmlDoc
= parseLayoutDump();
197 SwNodeOffset
nPage1LastNode(
198 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
200 // This was "3", paragraph "4" was deleted, but "5" was not moved backwards from page 2.
201 CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
205 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInSection
)
208 // The document has a section, containing a table that spans over 2 pages.
209 createSwDoc("table-in-sect.odt");
210 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
211 // In total we expect 4 cells.
212 assertXPath(pXmlDoc
, "/root/page/body/section/tab/row/cell", 4);
214 // Assert that on both pages the section contains 2 cells.
215 assertXPath(pXmlDoc
, "/root/page[1]/body/section/tab/row/cell", 2);
216 assertXPath(pXmlDoc
, "/root/page[2]/body/section/tab/row/cell", 2);
220 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInNestedSection
)
223 // The document has a nested section, containing a table that spans over 2 pages.
224 // This crashed the layout.
225 createSwDoc("rhbz739252-3.odt");
226 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
227 // Make sure the table is inside a section and spans over 2 pages.
228 assertXPath(pXmlDoc
, "//page[1]//section/tab", 1);
229 assertXPath(pXmlDoc
, "//page[2]//section/tab", 1);
233 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112741
)
236 createSwDoc("tdf112741.fodt");
237 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
239 assertXPath(pXmlDoc
, "//page", 4);
240 assertXPath(pXmlDoc
, "//page[1]/body/tab/row/cell/tab/row/cell/section", 1);
241 assertXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row/cell/section", 1);
242 // This failed, 3rd page contained no sections.
243 assertXPath(pXmlDoc
, "//page[3]/body/tab/row/cell/tab/row/cell/section", 1);
244 assertXPath(pXmlDoc
, "//page[4]/body/tab/row/cell/tab/row/cell/section", 1);
248 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112860
)
251 // The document has a split section inside a nested table, and also a table
253 // This crashed the layout.
254 createSwDoc("tdf112860.fodt");
258 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113287
)
261 createSwDoc("tdf113287.fodt");
262 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
263 assertXPath(pXmlDoc
, "//page", 2);
265 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/infos/bounds", "top").toUInt32();
266 sal_uInt32 nSectionTop
267 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/section/infos/bounds", "top")
269 // Make sure section frame is inside the cell frame.
270 // Expected greater than 4593, was only 3714.
271 CPPUNIT_ASSERT_GREATER(nCellTop
, nSectionTop
);
275 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113445
)
278 // Force multiple-page view.
279 createSwDoc("tdf113445.fodt");
280 SwDoc
* pDoc
= getSwDoc();
281 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
282 SwView
* pView
= pDocShell
->GetView();
283 pView
->SetViewLayout(/*nColumns=*/2, /*bBookMode=*/false);
286 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
287 assertXPath(pXmlDoc
, "//page", 2);
288 sal_uInt32 nPage1Left
= getXPath(pXmlDoc
, "//page[1]/infos/bounds", "left").toUInt32();
289 sal_uInt32 nPage2Left
= getXPath(pXmlDoc
, "//page[2]/infos/bounds", "left").toUInt32();
290 // Make sure that page 2 is on the right hand side of page 1, not below it.
291 CPPUNIT_ASSERT_GREATER(nPage1Left
, nPage2Left
);
293 // Insert a new paragraph at the start of the document.
294 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
295 pWrtShell
->StartOfSection();
296 pWrtShell
->SplitNode();
297 discardDumpedLayout();
298 pXmlDoc
= parseLayoutDump();
300 // Make sure that Table2:C5 and Table2:D5 has its section frame inside the cell frame.
302 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/infos/bounds", "top")
304 sal_uInt32 nSection3Top
305 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/section/infos/bounds",
308 CPPUNIT_ASSERT_GREATER(nCell3Top
, nSection3Top
);
310 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/infos/bounds", "top")
312 sal_uInt32 nSection4Top
313 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/section/infos/bounds",
316 CPPUNIT_ASSERT_GREATER(nCell4Top
, nSection4Top
);
317 // Also check if the two cells in the same row have the same top position.
318 // This was 4818, expected only 1672.
319 CPPUNIT_ASSERT_EQUAL(nCell3Top
, nCell4Top
);
323 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113686
)
326 createSwDoc("tdf113686.fodt");
327 SwDoc
* pDoc
= getSwDoc();
328 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
329 assertXPath(pXmlDoc
, "/root/page", 2);
330 SwNodeOffset
nPage1LastNode(
331 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/txt[last()]",
334 CPPUNIT_ASSERT_EQUAL(OUString("Table2:A1-P10"),
335 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
336 SwNodeOffset
nPage2FirstNode(
337 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
339 CPPUNIT_ASSERT_EQUAL(OUString("Table1:A1"),
340 pDoc
->GetNodes()[nPage2FirstNode
]->GetTextNode()->GetText());
343 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
344 while (pWrtShell
->GetCursor()->Start()->GetNodeIndex() < nPage1LastNode
)
345 pWrtShell
->Down(/*bSelect=*/false);
346 pWrtShell
->EndPara();
347 for (int i
= 0; i
< 3; ++i
)
348 pWrtShell
->Up(/*bSelect=*/true);
349 pWrtShell
->DelLeft();
351 // Assert that the second page is removed.
352 discardDumpedLayout();
353 pXmlDoc
= parseLayoutDump();
354 // This was still 2, content from 2nd page was not moved.
355 assertXPath(pXmlDoc
, "/root/page", 1);
359 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInSectionInTable
)
362 // The document has a table, containing a section, containing a nested
364 // This crashed the layout.
365 createSwDoc("i95698.odt");
369 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable
)
372 // The document has a nested table, containing a multi-line section at a
374 // This crashed the layout later in SwFrame::IsFootnoteAllowed().
375 createSwDoc("tdf112109.fodt");
379 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable2
)
382 createSwDoc("split-section-in-nested-table.fodt");
383 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
385 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
386 sal_uInt32 nSection1Follow
387 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "follow")
389 // This failed, the section wasn't split inside a nested table.
391 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
392 sal_uInt32 nSection2Precede
393 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "precede")
396 // Make sure that the first's follow and the second's precede is correct.
397 CPPUNIT_ASSERT_EQUAL(nSection2
, nSection1Follow
);
398 CPPUNIT_ASSERT_EQUAL(nSection1
, nSection2Precede
);
402 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable3
)
405 createSwDoc("tdf113153.fodt");
407 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
408 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
410 uno::Reference
<container::XNamed
> xTable(xTables
->getByIndex(1), uno::UNO_QUERY
);
411 CPPUNIT_ASSERT_EQUAL(OUString("Table16"), xTable
->getName());
413 uno::Reference
<text::XTextTable
> xRowSupplier(xTable
, uno::UNO_QUERY
);
414 uno::Reference
<table::XTableRows
> xRows
= xRowSupplier
->getRows();
415 uno::Reference
<beans::XPropertySet
> xRow(xRows
->getByIndex(1), uno::UNO_QUERY
);
416 xRow
->setPropertyValue("IsSplitAllowed", uno::Any(true));
417 // This never returned.
420 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
421 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
422 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
423 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
424 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
425 sal_uInt32 nTable2Follow
= getXPath(pXmlDoc
, "//page[2]//body/tab", "follow").toUInt32();
426 sal_uInt32 nTable3
= getXPath(pXmlDoc
, "//page[3]//body/tab", "id").toUInt32();
427 sal_uInt32 nTable3Precede
= getXPath(pXmlDoc
, "//page[3]//body/tab", "precede").toUInt32();
429 // Make sure the outer table frames are linked together properly.
430 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
431 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
432 CPPUNIT_ASSERT_EQUAL(nTable3
, nTable2Follow
);
433 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable3Precede
);
437 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable4
)
440 createSwDoc("tdf113520.fodt");
441 SwDoc
* pDoc
= getSwDoc();
442 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
443 assertXPath(pXmlDoc
, "/root/page", 3);
444 SwNodeOffset
nPage1LastNode(
445 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[last()]",
448 CPPUNIT_ASSERT_EQUAL(OUString("Section1:P10"),
449 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
450 SwNodeOffset
nPage3FirstNode(
451 getXPath(pXmlDoc
, "/root/page[3]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[1]",
454 CPPUNIT_ASSERT_EQUAL(OUString("Section1:P23"),
455 pDoc
->GetNodes()[nPage3FirstNode
]->GetTextNode()->GetText());
458 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
459 while (pWrtShell
->GetCursor()->Start()->GetNodeIndex() < nPage1LastNode
)
460 pWrtShell
->Down(/*bSelect=*/false);
461 pWrtShell
->EndPara();
462 while (pWrtShell
->GetCursor()->End()->GetNodeIndex() < nPage3FirstNode
)
463 pWrtShell
->Down(/*bSelect=*/true);
464 pWrtShell
->EndPara(/*bSelect=*/true);
465 pWrtShell
->DelLeft();
467 // Assert that the page is removed.
468 discardDumpedLayout();
469 pXmlDoc
= parseLayoutDump();
470 // This was 3, page 2 was emptied, but it wasn't removed.
471 assertXPath(pXmlDoc
, "/root/page", 2);
473 // Make sure the outer table frames are linked together properly.
474 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
475 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
476 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
477 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
478 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
479 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
483 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112160
)
486 // Assert that the A2 cell is on page 1.
487 createSwDoc("tdf112160.fodt");
488 SwDoc
* pDoc
= getSwDoc();
489 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
490 SwNodeOffset
nA2CellNode(getXPath(pXmlDoc
,
491 "/root/page[1]/body/tab/row[2]/cell[1]/section/txt[last()]",
494 CPPUNIT_ASSERT_EQUAL(OUString("Table1.A2"),
495 pDoc
->GetNodes()[nA2CellNode
]->GetTextNode()->GetText());
497 // Append a new paragraph to the end of the A2 cell.
498 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
499 while (pWrtShell
->GetCursor()->GetPointNode().GetIndex() < nA2CellNode
)
500 pWrtShell
->Down(/*bSelect=*/false);
501 pWrtShell
->EndPara();
502 pWrtShell
->SplitNode();
504 // Assert that after A2 got extended, D2 stays on page 1.
505 discardDumpedLayout();
506 pXmlDoc
= parseLayoutDump();
507 sal_uInt32 nD2CellNode
508 = getXPath(pXmlDoc
, "/root/page[1]/body/tab/row[2]/cell[last()]/section/txt[last()]",
511 // This was Table1.C2, Table1.D2 was moved to the next page, unexpected.
512 CPPUNIT_ASSERT_EQUAL(OUString("Table1.D2"),
513 pDoc
->GetNodes()[SwNodeOffset(nD2CellNode
)]->GetTextNode()->GetText());
517 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf114536
)
519 // This crashed in SwTextFormatter::MergeCharacterBorder() due to a
521 createSwDoc("tdf114536.odt");
524 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testParagraphOfTextRange
)
526 createSwDoc("paragraph-of-text-range.odt");
527 SwDoc
* pDoc
= getSwDoc();
530 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
531 pWrtShell
->Down(/*bSelect=*/false);
532 CPPUNIT_ASSERT(pWrtShell
->IsCursorInTable());
533 // Enter the section.
534 pWrtShell
->Down(/*bSelect=*/false);
535 CPPUNIT_ASSERT(pWrtShell
->IsDirectlyInSection());
537 // Assert that we get the right paragraph object.
538 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
539 uno::Reference
<text::XTextViewCursorSupplier
> xController(xModel
->getCurrentController(),
541 uno::Reference
<text::XTextRange
> xViewCursor
= xController
->getViewCursor();
542 // This failed as there were no TextParagraph property.
544 = getProperty
<uno::Reference
<text::XTextRange
>>(xViewCursor
->getStart(), "TextParagraph");
545 CPPUNIT_ASSERT_EQUAL(OUString("In section"), xParagraph
->getString());
548 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfContents
)
550 createSwDoc("tdf99689.odt");
551 SwDoc
* pDoc
= getSwDoc();
552 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
553 pWrtShell
->GotoNextTOXBase();
554 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
555 pWrtShell
->UpdateTableOf(*pTOXBase
);
556 SwCursorShell
* pShell(pDoc
->GetEditShell());
557 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
558 SwNodeIndex
aIdx(*pTitleNode
);
560 pDoc
->GetNodes().GoNext(&aIdx
);
562 // skip the first header. No attributes there.
563 // next node should contain superscript
564 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
565 CPPUNIT_ASSERT(pNext
->HasHints());
566 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
567 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
569 // next node should contain subscript
570 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
571 CPPUNIT_ASSERT(pNext
->HasHints());
572 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
573 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
576 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfFigures
)
578 createSwDoc("tdf99689_figures.odt");
579 SwDoc
* pDoc
= getSwDoc();
580 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
581 pWrtShell
->GotoNextTOXBase();
582 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
583 pWrtShell
->UpdateTableOf(*pTOXBase
);
584 SwCursorShell
* pShell(pDoc
->GetEditShell());
585 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
586 SwNodeIndex
aIdx(*pTitleNode
);
589 // next node should contain subscript
590 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
591 CPPUNIT_ASSERT(pNext
->HasHints());
592 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
593 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
595 // next node should contain superscript
596 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
597 CPPUNIT_ASSERT(pNext
->HasHints());
598 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
599 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
602 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfTables
)
604 createSwDoc("tdf99689_tables.odt");
605 SwDoc
* pDoc
= getSwDoc();
606 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
607 pWrtShell
->GotoNextTOXBase();
608 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
609 pWrtShell
->UpdateTableOf(*pTOXBase
);
610 SwCursorShell
* pShell(pDoc
->GetEditShell());
611 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
612 SwNodeIndex
aIdx(*pTitleNode
);
615 // next node should contain superscript
616 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
617 CPPUNIT_ASSERT(pNext
->HasHints());
618 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
619 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
621 // next node should contain subscript
622 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
623 CPPUNIT_ASSERT(pNext
->HasHints());
624 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
625 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
628 // tdf#112448: Fix: take correct line height
630 // When line metrics is not calculated we need to call CalcRealHeight()
631 // before usage of the Height() and GetRealHeight().
632 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112448
)
634 createSwDoc("tdf112448.odt");
636 // check actual number of line breaks in the paragraph
637 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
638 assertXPath(pXmlDoc
, "/root/page/body/txt/SwParaPortion/SwLineLayout", 2);
641 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113790
)
643 createSwDoc("tdf113790.docx");
644 SwDoc
* pDoc
= getSwDoc();
645 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
646 // Create the clipboard document.
648 aClipboard
.SetClipBoard(true);
650 // Go to fourth line - to "ABCD" bulleted list item
651 pWrtShell
->Down(/*bSelect=*/false, 4);
652 pWrtShell
->SelPara(nullptr);
653 CPPUNIT_ASSERT_EQUAL(OUString("ABCD"), pWrtShell
->GetSelText());
654 pWrtShell
->Copy(aClipboard
);
656 // Go down to next-to-last (empty) line above "Title3"
657 pWrtShell
->Down(/*bSelect=*/false, 4);
658 pWrtShell
->Paste(aClipboard
);
660 // Save it as DOCX & load it again
661 saveAndReload("Office Open XML Text");
662 CPPUNIT_ASSERT(dynamic_cast<SwXTextDocument
*>(mxComponent
.get()));
665 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157937
)
667 createSwDoc("tdf130088.docx");
668 SwDoc
* pDoc
= getSwDoc();
669 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
672 pWrtShell
->SelPara(nullptr);
675 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
676 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
677 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
680 CPPUNIT_ASSERT_MESSAGE(
681 "redlines should be visible",
682 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
684 // cycle case with change tracking
685 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
686 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
688 // This resulted freezing
689 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
692 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157988
)
694 createSwDoc("tdf130088.docx");
695 SwDoc
* pDoc
= getSwDoc();
697 // select the second word
698 dispatchCommand(mxComponent
, ".uno:GoToNextWord", {});
699 dispatchCommand(mxComponent
, ".uno:SelectWord", {});
702 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
703 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
704 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
707 CPPUNIT_ASSERT_MESSAGE(
708 "redlines should be visible",
709 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
711 // cycle case with change tracking
713 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
715 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
717 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
719 // This was false (missing revert of the tracked change)
720 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
722 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
724 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSODALES"));
726 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
728 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
730 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
732 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
734 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
736 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
738 // tdf#141198 cycle case without selection: the word under the cursor
740 dispatchCommand(mxComponent
, ".uno:Escape", {});
742 dispatchCommand(mxComponent
, ".uno:GoRight", {});
744 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
746 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSODALES"));
748 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
750 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
752 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
754 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
756 dispatchCommand(mxComponent
, ".uno:ChangeCaseRotateCase", {});
758 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
761 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf108048
)
765 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
766 { "Kind", uno::Any(sal_Int16(3)) },
767 { "TemplateName", uno::Any(OUString("Default Page Style")) },
768 { "PageNumber", uno::Any(sal_uInt16(6)) }, // Even number to avoid auto-inserted blank page
769 { "PageNumberFilled", uno::Any(true) },
771 dispatchCommand(mxComponent
, ".uno:InsertBreak", aPropertyValues
);
772 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
773 CPPUNIT_ASSERT_EQUAL(2, getPages());
775 // The inserted page must have page number set to 6
776 uno::Reference
<text::XTextRange
> xPara
= getParagraph(2);
777 sal_uInt16 nPageNumber
= getProperty
<sal_uInt16
>(xPara
, "PageNumberOffset");
778 CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), nPageNumber
);
781 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113481
)
783 createSwDoc("tdf113481-IVS.odt");
784 SwDoc
* pDoc
= getSwDoc();
785 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
787 // One backspace should completely remove the CJK ideograph variation sequence
788 pWrtShell
->EndPara();
789 // Before: U+8FBA U+E0102. After: empty
790 pWrtShell
->DelLeft();
791 const uno::Reference
<text::XTextRange
> xPara1
= getParagraph(1);
792 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara1
->getString().getLength());
794 // In case that weak script is treated as CJK script, remove one character.
795 pWrtShell
->Down(false);
796 pWrtShell
->EndPara();
797 // Before: U+4E2D U+2205 U+FE00. After: U+4E2D U+2205
798 if (pWrtShell
->GetScriptType() == SvtScriptType::ASIAN
)
800 pWrtShell
->DelLeft();
801 const uno::Reference
<text::XTextRange
> xPara2
= getParagraph(2);
802 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xPara2
->getString().getLength());
803 CPPUNIT_ASSERT_EQUAL(u
'\x2205', xPara2
->getString()[1]);
806 // Characters of other scripts, remove one character.
807 pWrtShell
->Down(false);
808 pWrtShell
->EndPara();
809 // Before: U+1820 U+180B. After: U+1820
810 pWrtShell
->DelLeft();
811 const uno::Reference
<text::XTextRange
> xPara3
= getParagraph(3);
812 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPara3
->getString().getLength());
813 CPPUNIT_ASSERT_EQUAL(u
'\x1820', xPara3
->getString()[0]);
816 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115013
)
818 const OUString
sColumnName("Name with spaces, \"quotes\" and \\backslashes");
820 utl::TempFileNamed
aTempDir(nullptr, true);
821 aTempDir
.EnableKillingFile();
822 const OUString aWorkDir
= aTempDir
.GetURL();
824 //create new writer document
826 SwDoc
* pDoc
= getSwDoc();
829 // Load and register data source
831 = SwDBManager::LoadAndRegisterDataSource(createFileURL(u
"datasource.ods"), &aWorkDir
);
832 CPPUNIT_ASSERT(!sDataSource
.isEmpty());
834 // Insert a new field type for the mailmerge field
836 aDBData
.sDataSource
= sDataSource
;
837 aDBData
.sCommand
= "Sheet1";
838 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
839 CPPUNIT_ASSERT(pWrtShell
);
840 SwDBFieldType
* pFieldType
= static_cast<SwDBFieldType
*>(
841 pWrtShell
->InsertFieldType(SwDBFieldType(pDoc
, sColumnName
, aDBData
)));
842 CPPUNIT_ASSERT(pFieldType
);
844 // Insert the field into document
845 SwDBField
aField(pFieldType
);
846 pWrtShell
->InsertField2(aField
);
848 // Save it as DOCX & load it again
849 saveAndReload("Office Open XML Text");
851 CPPUNIT_ASSERT(pDoc
);
852 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
853 CPPUNIT_ASSERT(pWrtShell
);
854 SwPaM
* pCursor
= pDoc
->GetEditShell()->GetCursor();
855 CPPUNIT_ASSERT(pCursor
);
857 // Get the field at the beginning of the document
858 SwDBField
* pField
= dynamic_cast<SwDBField
*>(SwCursorShell::GetFieldAtCursor(pCursor
, true));
859 CPPUNIT_ASSERT(pField
);
860 OUString sColumn
= static_cast<SwDBFieldType
*>(pField
->GetTyp())->GetColumnName();
861 // The column name must come correct after round trip
862 CPPUNIT_ASSERT_EQUAL(sColumnName
, sColumn
);
865 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115065
)
867 // In the document, the tables have table style assigned
868 // Source table (first one) has two rows;
869 // destination (second one) has only one row
870 createSwDoc("tdf115065.odt");
871 SwDoc
* pDoc
= getSwDoc();
872 CPPUNIT_ASSERT(pDoc
);
873 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
874 CPPUNIT_ASSERT(pWrtShell
);
876 pWrtShell
->GotoTable("Table2");
877 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
878 // Destination point is the middle of the first cell of second table
879 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
881 pWrtShell
->GotoTable("Table1");
882 aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
883 // Source point is the middle of the first cell of first table
884 Point
ptFrom(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
886 pWrtShell
->SelTableCol();
887 // The copy operation (or closing document after that) segfaulted
888 pWrtShell
->Copy(*pWrtShell
, ptFrom
, ptTo
);
891 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf84806_MovingMultipleTableRows
)
893 // Moving of multiple table rows.
894 // Source table (first one) has two rows;
895 // destination (second one) has only one row
896 createSwDoc("tdf115065.odt");
897 SwDoc
* pDoc
= getSwDoc();
898 CPPUNIT_ASSERT(pDoc
);
899 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
900 CPPUNIT_ASSERT(pWrtShell
);
902 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
903 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
905 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
906 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
907 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
908 CPPUNIT_ASSERT(xTableNames
->hasByName("Table2"));
909 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
910 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
911 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
912 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
915 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
916 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
918 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
920 pWrtShell
->GotoTable("Table2");
921 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
922 // Destination point is the middle of the first cell of second table
923 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
925 // Move rows of the first table into the second table
926 pWrtShell
->GotoTable("Table1");
927 pWrtShell
->SelTable();
928 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
929 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
932 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables
->getCount());
933 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
935 // Undo results 2 tables
937 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
939 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
940 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
941 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
942 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
943 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
945 // FIXME assert with Redo()
948 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf147181_TrackedMovingOfMultipleTableRows
)
950 // Tracked moving of multiple table rows.
951 // Source table (first one) has two rows;
952 // destination (second one) has only one row
953 createSwDoc("tdf115065.odt");
954 SwDoc
* pDoc
= getSwDoc();
955 CPPUNIT_ASSERT(pDoc
);
956 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
957 CPPUNIT_ASSERT(pWrtShell
);
959 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
960 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
962 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
963 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
964 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
965 CPPUNIT_ASSERT(xTableNames
->hasByName("Table2"));
966 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
967 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
968 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
969 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
971 // FIXME: doesn't work with empty rows, yet
972 pWrtShell
->Insert("x");
973 pWrtShell
->Down(false);
974 pWrtShell
->Insert("x");
977 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
978 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
979 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
982 CPPUNIT_ASSERT_MESSAGE(
983 "redlines should be visible",
984 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
986 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
988 pWrtShell
->GotoTable("Table2");
989 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
990 // Destination point is the middle of the first cell of second table
991 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
993 // Move rows of the first table into the second table
994 pWrtShell
->GotoTable("Table1");
995 pWrtShell
->SelTable();
996 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
997 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
999 // still 2 tables, but the second one has got 3 rows
1000 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
1001 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1002 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
1004 // accept changes results 1 table (removing moved table)
1005 dispatchCommand(mxComponent
, ".uno:AcceptAllTrackedChanges", {});
1006 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
1008 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables2
->getCount());
1009 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
1011 // Undo results 2 tables
1012 rUndoManager
.Undo();
1013 rUndoManager
.Undo();
1014 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
1015 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1016 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
1017 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
1018 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
1020 // reject changes results 2 table again, with the original row counts
1021 dispatchCommand(mxComponent
, ".uno:RejectAllTrackedChanges", {});
1022 uno::Reference
<container::XIndexAccess
> xTables3(xTablesSupplier
->getTextTables(),
1024 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables3
->getCount());
1025 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
1026 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
1029 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157492_TrackedMovingRow
)
1032 SwDoc
* pDoc
= getSwDoc();
1033 CPPUNIT_ASSERT(pDoc
);
1034 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1035 CPPUNIT_ASSERT(pWrtShell
);
1038 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1039 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1041 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1042 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1043 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1044 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1045 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1046 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1048 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1050 // fill table with data
1051 for (int i
= 0; i
< 3; ++i
)
1053 pWrtShell
->Insert("x");
1054 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RIGHT
);
1057 Scheduler::ProcessEventsToIdle();
1059 uno::Reference
<text::XTextRange
> xCellA1(xTable1
->getCellByName("A1"), uno::UNO_QUERY
);
1060 xCellA1
->setString("A1");
1061 uno::Reference
<text::XTextRange
> xCellB1(xTable1
->getCellByName("B1"), uno::UNO_QUERY
);
1062 xCellB1
->setString("B1");
1063 uno::Reference
<text::XTextRange
> xCellC1(xTable1
->getCellByName("C1"), uno::UNO_QUERY
);
1064 xCellC1
->setString("C1");
1066 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1067 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[1]/txt", "A1");
1068 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[2]/txt", "B1");
1069 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[3]/txt", "C1");
1072 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
1073 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1074 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1076 // Move first column of the table before the third column by drag & drop
1077 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1078 SwFrame
* pPage
= pLayout
->Lower();
1079 SwFrame
* pBody
= pPage
->GetLower();
1080 SwFrame
* pTable
= pBody
->GetLower();
1081 SwFrame
* pRow1
= pTable
->GetLower();
1082 SwFrame
* pCellA1
= pRow1
->GetLower();
1083 SwFrame
* pRow3
= pRow1
->GetNext()->GetNext();
1084 SwFrame
* pCellA3
= pRow3
->GetLower();
1085 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1086 const SwRect
& rCellA3Rect
= pCellA3
->getFrameArea();
1087 Point
ptTo(rCellA3Rect
.Left() + rCellA3Rect
.Width() / 2,
1088 rCellA3Rect
.Top() + rCellA3Rect
.Height() / 2);
1089 // select first table row by using the middle point of the left border of row 1
1090 Point
ptRow(rCellA1Rect
.Left() - 5, rCellA1Rect
.Top() + rCellA1Rect
.Height() / 2);
1091 pWrtShell
->SelectTableRowCol(ptRow
);
1093 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1095 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1097 // reject changes results 4 rows again, not 5
1098 dispatchCommand(mxComponent
, ".uno:RejectAllTrackedChanges", {});
1100 xTableNames
= xTablesSupplier
->getTextTables();
1101 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1102 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1103 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getColumns()->getCount());
1104 // This was 5 (moving row without change tracking)
1105 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2
->getRows()->getCount());
1108 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf154599_MovingColumn
)
1111 SwDoc
* pDoc
= getSwDoc();
1112 CPPUNIT_ASSERT(pDoc
);
1113 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1114 CPPUNIT_ASSERT(pWrtShell
);
1116 // Create a table with less columns than rows
1117 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1118 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1120 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1121 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1122 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1123 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1124 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1125 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1127 // without redlining
1128 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1129 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1131 // Move first column of the table before the third column by drag & drop
1133 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1134 SwFrame
* pPage
= pLayout
->Lower();
1135 SwFrame
* pBody
= pPage
->GetLower();
1136 SwFrame
* pTable
= pBody
->GetLower();
1137 SwFrame
* pRow1
= pTable
->GetLower();
1138 SwFrame
* pCellA1
= pRow1
->GetLower();
1139 SwFrame
* pCellC1
= pCellA1
->GetNext()->GetNext();
1140 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1141 const SwRect
& rCellC1Rect
= pCellC1
->getFrameArea();
1142 Point
ptTo(rCellC1Rect
.Left() + rCellC1Rect
.Width() / 2,
1143 rCellC1Rect
.Top() + rCellC1Rect
.Height() / 2);
1144 // select first table column by using the middle point of the top border of column A
1145 Point
ptColumn(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1146 pWrtShell
->SelectTableRowCol(ptColumn
);
1148 // This crashed here before the fix.
1149 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1151 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1153 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1154 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1157 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf155846_MovingColumn
)
1160 SwDoc
* pDoc
= getSwDoc();
1161 CPPUNIT_ASSERT(pDoc
);
1162 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1163 CPPUNIT_ASSERT(pWrtShell
);
1166 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1167 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1169 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1170 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1171 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1172 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1173 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1174 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1176 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1178 // fill table with data
1179 for (int i
= 0; i
< 4; ++i
)
1181 pWrtShell
->Insert("x");
1182 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
);
1185 Scheduler::ProcessEventsToIdle();
1187 uno::Reference
<text::XTextRange
> xCellA1(xTable1
->getCellByName("A1"), uno::UNO_QUERY
);
1188 xCellA1
->setString("A1");
1189 uno::Reference
<text::XTextRange
> xCellA2(xTable1
->getCellByName("A2"), uno::UNO_QUERY
);
1190 xCellA2
->setString("A2");
1191 uno::Reference
<text::XTextRange
> xCellA3(xTable1
->getCellByName("A3"), uno::UNO_QUERY
);
1192 xCellA3
->setString("A3");
1193 uno::Reference
<text::XTextRange
> xCellA4(xTable1
->getCellByName("A4"), uno::UNO_QUERY
);
1194 xCellA4
->setString("A4");
1196 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1197 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[1]/txt", "A1");
1198 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[2]/cell[1]/txt", "A2");
1199 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[3]/cell[1]/txt", "A3");
1200 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[4]/cell[1]/txt", "A4");
1203 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
1204 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1205 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1207 // Move first column of the table before the third column by drag & drop
1208 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1209 SwFrame
* pPage
= pLayout
->Lower();
1210 SwFrame
* pBody
= pPage
->GetLower();
1211 SwFrame
* pTable
= pBody
->GetLower();
1212 SwFrame
* pRow1
= pTable
->GetLower();
1213 SwFrame
* pCellA1
= pRow1
->GetLower();
1214 SwFrame
* pCellC1
= pCellA1
->GetNext()->GetNext();
1215 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1216 const SwRect
& rCellC1Rect
= pCellC1
->getFrameArea();
1217 Point
ptTo(rCellC1Rect
.Left() + rCellC1Rect
.Width() / 2,
1218 rCellC1Rect
.Top() + rCellC1Rect
.Height() / 2);
1219 // select first table column by using the middle point of the top border of column A
1220 Point
ptColumn(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1221 pWrtShell
->SelectTableRowCol(ptColumn
);
1223 // This crashed here before the fix.
1224 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1226 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1228 // reject changes results 3 columns again, not 4
1229 dispatchCommand(mxComponent
, ".uno:RejectAllTrackedChanges", {});
1231 xTableNames
= xTablesSupplier
->getTextTables();
1232 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1233 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1234 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2
->getRows()->getCount());
1235 // This was 4 (moving column without change tracking)
1236 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getColumns()->getCount());
1239 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf154771_MovingMultipleColumns
)
1242 SwDoc
* pDoc
= getSwDoc();
1243 CPPUNIT_ASSERT(pDoc
);
1244 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1245 CPPUNIT_ASSERT(pWrtShell
);
1247 // Create a table with less columns than rows
1248 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1249 (void)&pWrtShell
->InsertTable(TableOpt
, 5, 4);
1251 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1252 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1253 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
1254 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
1255 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable1
->getRows()->getCount());
1256 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getColumns()->getCount());
1258 // without redlining
1259 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1260 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1262 // Move first two columns of the table before column D by drag & drop
1264 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1265 SwFrame
* pPage
= pLayout
->Lower();
1266 SwFrame
* pBody
= pPage
->GetLower();
1267 SwFrame
* pTable
= pBody
->GetLower();
1268 SwFrame
* pRow1
= pTable
->GetLower();
1269 SwFrame
* pCellA1
= pRow1
->GetLower();
1270 SwFrame
* pCellB1
= pCellA1
->GetNext();
1271 SwFrame
* pCellD1
= pCellB1
->GetNext()->GetNext();
1272 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1273 const SwRect
& rCellB1Rect
= pCellB1
->getFrameArea();
1274 const SwRect
& rCellD1Rect
= pCellD1
->getFrameArea();
1275 Point
ptTo(rCellD1Rect
.Left() + rCellD1Rect
.Width() / 2,
1276 rCellD1Rect
.Top() + rCellD1Rect
.Height() / 2);
1277 // select first two table columns by using
1278 // the middle point of the top border of column A
1279 // and middle point of the top border of column B
1280 Point
ptColumnA(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1281 const Point
ptColumnB(rCellB1Rect
.Left() + rCellB1Rect
.Width() / 2, rCellB1Rect
.Top() - 5);
1282 pWrtShell
->SelectTableRowCol(ptColumnA
, &ptColumnB
);
1284 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1285 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1287 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable1
->getRows()->getCount());
1288 // This was 5 before the fix (only the first selected column was moved, the
1289 // other ones were copied instead of moving)
1290 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getColumns()->getCount());
1293 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115132
)
1296 SwDoc
* pDoc
= getSwDoc();
1297 CPPUNIT_ASSERT(pDoc
);
1298 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1299 CPPUNIT_ASSERT(pWrtShell
);
1301 std::vector
<OUString
> vTestTableNames
;
1303 // Create an empty paragraph that will separate first table from the rest
1304 pWrtShell
->SplitNode();
1305 pWrtShell
->StartOfSection();
1306 // Create a table at the start of document body
1307 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1308 const SwTable
* pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
1309 const SwTableFormat
* pFormat
= pTable
->GetFrameFormat();
1310 CPPUNIT_ASSERT(pFormat
);
1311 vTestTableNames
.push_back(pFormat
->GetName());
1312 pWrtShell
->EndOfSection();
1313 // Create a table after a paragraph
1314 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
1315 pFormat
= pTable
->GetFrameFormat();
1316 CPPUNIT_ASSERT(pFormat
);
1317 vTestTableNames
.push_back(pFormat
->GetName());
1318 // Create a table immediately after the previous
1319 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
1320 pFormat
= pTable
->GetFrameFormat();
1321 CPPUNIT_ASSERT(pFormat
);
1322 vTestTableNames
.push_back(pFormat
->GetName());
1323 // Create a nested table in the middle of last row
1324 pWrtShell
->GotoTable(vTestTableNames
.back());
1325 for (int i
= 0; i
< 4; ++i
)
1326 pWrtShell
->GoNextCell(false);
1327 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
1328 pFormat
= pTable
->GetFrameFormat();
1329 CPPUNIT_ASSERT(pFormat
);
1330 vTestTableNames
.push_back(pFormat
->GetName());
1332 // Now check that in any cell in all tables we don't go out of a cell
1333 // using Delete or Backspace. We test cases when a table is the first node;
1334 // when we are in a first/middle/last cell in a row; when there's a paragraph
1335 // before/after this cell; when there's another table before/after this cell;
1337 for (const auto& rTableName
: vTestTableNames
)
1339 pWrtShell
->GotoTable(rTableName
);
1342 const SwStartNode
* pNd
= pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode();
1343 pWrtShell
->DelRight();
1344 CPPUNIT_ASSERT_EQUAL(pNd
,
1345 pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode());
1346 pWrtShell
->DelLeft();
1347 CPPUNIT_ASSERT_EQUAL(pNd
,
1348 pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode());
1349 } while (pWrtShell
->GoNextCell(false));
1353 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testXDrawPagesSupplier
)
1356 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
1357 CPPUNIT_ASSERT_MESSAGE("XDrawPagesSupplier interface is unavailable", xDrawPagesSupplier
.is());
1358 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
1359 CPPUNIT_ASSERT(xDrawPages
.is());
1360 CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be only a single DrawPage in Writer documents",
1361 sal_Int32(1), xDrawPages
->getCount());
1362 uno::Any aDrawPage
= xDrawPages
->getByIndex(0);
1363 uno::Reference
<drawing::XDrawPage
> xDrawPageFromXDrawPages(aDrawPage
, uno::UNO_QUERY
);
1364 CPPUNIT_ASSERT(xDrawPageFromXDrawPages
.is());
1366 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
1367 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
1368 CPPUNIT_ASSERT_EQUAL_MESSAGE(
1369 "The DrawPage accessed using XDrawPages must be the same as using XDrawPageSupplier",
1370 xDrawPage
.get(), xDrawPageFromXDrawPages
.get());
1373 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116403
)
1375 createSwDoc("tdf116403-considerborders.odt");
1376 SwDoc
* pDoc
= getSwDoc();
1377 // Check that before ToX update, the tab stop position is the old one
1378 uno::Reference
<text::XTextRange
> xParagraph
= getParagraph(2, "1\t1");
1379 auto aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, "ParaTabStops");
1380 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
1381 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(17000), aTabs
[0].Position
);
1383 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1384 const SwTOXBase
* pTOX
= pWrtShell
->GetTOX(0);
1385 CPPUNIT_ASSERT(pTOX
);
1386 pWrtShell
->UpdateTableOf(*pTOX
);
1388 xParagraph
= getParagraph(2, "1\t1");
1389 aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, "ParaTabStops");
1390 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
1391 // This was still 17000, refreshing ToX didn't take borders spacings and widths into account
1392 CPPUNIT_ASSERT_EQUAL_MESSAGE("Page borders must be considered for right-aligned tabstop",
1393 static_cast<sal_Int32
>(17000 - 2 * 500 - 2 * 1),
1397 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testHtmlCopyImages
)
1399 // Load a document with an image.
1400 createSwDoc("image.odt");
1401 SwDoc
* pDoc
= getSwDoc();
1403 // Trigger the copy part of HTML copy&paste.
1404 WriterRef xWrt
= new SwHTMLWriter(/*rBaseURL=*/OUString());
1405 CPPUNIT_ASSERT(xWrt
.is());
1407 xWrt
->m_bWriteClipboardDoc
= true;
1408 xWrt
->m_bWriteOnlyFirstTable
= false;
1409 xWrt
->SetShowProgress(false);
1411 SvFileStream
aStream(maTempFile
.GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
1412 SwWriter
aWrt(aStream
, *pDoc
);
1415 htmlDocUniquePtr pHtmlDoc
= parseHtml(maTempFile
);
1416 CPPUNIT_ASSERT(pHtmlDoc
);
1418 // This failed, image was lost during HTML copy.
1419 OUString aImage
= getXPath(pHtmlDoc
, "/html/body/p/img", "src");
1420 // Also make sure that the image is not embedded (e.g. Word doesn't handle
1421 // embedded images).
1422 CPPUNIT_ASSERT(aImage
.startsWith("file:///"));
1425 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116789
)
1427 createSwDoc("tdf116789.fodt");
1428 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
1429 uno::Reference
<text::XText
> xText1
;
1430 uno::Reference
<text::XText
> xText2
;
1432 uno::Reference
<text::XTextContent
> xBookmark(
1433 xBookmarksSupplier
->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY
);
1434 xText1
= xBookmark
->getAnchor()->getText();
1437 uno::Reference
<text::XTextContent
> xBookmark(
1438 xBookmarksSupplier
->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY
);
1439 xText2
= xBookmark
->getAnchor()->getText();
1441 // This failed, we got two different SwXCell for the same bookmark anchor text.
1442 CPPUNIT_ASSERT_EQUAL(xText1
, xText2
);
1445 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf91801
)
1447 // Tests calculation with several user field variables without prior user fields
1448 createSwDoc("tdf91801.fodt");
1449 uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(1), uno::UNO_QUERY
);
1450 uno::Reference
<table::XCell
> xCell(xTable
->getCellByName("A1"));
1451 CPPUNIT_ASSERT_EQUAL(555.0, xCell
->getValue());
1454 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf51223
)
1457 SwDoc
* pDoc
= getSwDoc();
1458 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1459 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1460 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetPointNode().GetIndex();
1461 pWrtShell
->Insert("i");
1462 pWrtShell
->SplitNode(true);
1463 CPPUNIT_ASSERT_EQUAL(OUString("I"),
1464 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
1465 rUndoManager
.Undo();
1466 CPPUNIT_ASSERT_EQUAL(OUString("i"),
1467 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
1470 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testFontEmbedding
)
1472 #if HAVE_MORE_FONTS && !defined(MACOSX)
1473 createSwDoc("testFontEmbedding.odt");
1475 OString
aContentBaseXpath("/office:document-content/office:font-face-decls");
1476 OString
aSettingsBaseXpath("/office:document-settings/office:settings/config:config-item-set");
1478 xmlDocUniquePtr pXmlDoc
;
1480 // Get document settings
1481 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY_THROW
);
1482 uno::Reference
<beans::XPropertySet
> xProps(
1483 xFactory
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW
);
1485 // Check font embedding state
1486 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue("EmbedFonts").get
<bool>());
1487 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue("EmbedOnlyUsedFonts").get
<bool>());
1488 // Font scripts should be enabled by default, however this has no effect unless "EmbedOnlyUsedFonts" is enabled
1489 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedLatinScriptFonts").get
<bool>());
1490 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedAsianScriptFonts").get
<bool>());
1491 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedComplexScriptFonts").get
<bool>());
1493 // CASE 1 - no font embedding enabled
1495 // Save the document
1497 CPPUNIT_ASSERT(maTempFile
.IsValid());
1499 // Check setting - No font embedding should be enabled
1500 pXmlDoc
= parseExport("settings.xml");
1501 CPPUNIT_ASSERT(pXmlDoc
);
1503 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "false");
1505 // Check content - No font-face-src nodes should be present
1506 pXmlDoc
= parseExport("content.xml");
1507 CPPUNIT_ASSERT(pXmlDoc
);
1509 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
1510 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
1513 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
1514 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
1515 assertXPath(pXmlDoc
,
1517 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
1519 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
1520 assertXPath(pXmlDoc
,
1522 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
1524 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
1525 assertXPath(pXmlDoc
,
1527 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
1529 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
1530 assertXPath(pXmlDoc
,
1531 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 0);
1532 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
1533 assertXPath(pXmlDoc
,
1534 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
1536 // CASE 2 - font embedding enabled, but embed used fonts disabled
1538 // Enable font embedding, disable embedding used font only
1539 xProps
->setPropertyValue("EmbedFonts", uno::Any(true));
1540 xProps
->setPropertyValue("EmbedOnlyUsedFonts", uno::Any(false));
1542 // Save the document again
1544 CPPUNIT_ASSERT(maTempFile
.IsValid());
1546 // Check setting - font embedding should be enabled + embed only used fonts and scripts
1547 pXmlDoc
= parseExport("settings.xml");
1548 CPPUNIT_ASSERT(pXmlDoc
);
1550 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "true");
1552 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
1555 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
1558 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
1561 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
1564 // Check content - font-face-src should be present only for "Liberation Sans" fonts
1566 pXmlDoc
= parseExport("content.xml");
1567 CPPUNIT_ASSERT(pXmlDoc
);
1569 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
1570 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
1573 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 1);
1574 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
1575 assertXPath(pXmlDoc
,
1577 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
1579 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
1580 assertXPath(pXmlDoc
,
1582 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
1584 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
1585 assertXPath(pXmlDoc
,
1587 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
1589 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
1590 assertXPath(pXmlDoc
,
1591 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
1592 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
1593 assertXPath(pXmlDoc
,
1594 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 1);
1596 // CASE 3 - font embedding enabled, embed only used fonts enabled
1598 // Enable font embedding and setting to embed used fonts only
1599 xProps
->setPropertyValue("EmbedFonts", uno::Any(true));
1600 xProps
->setPropertyValue("EmbedOnlyUsedFonts", uno::Any(true));
1601 xProps
->setPropertyValue("EmbedLatinScriptFonts", uno::Any(true));
1602 xProps
->setPropertyValue("EmbedAsianScriptFonts", uno::Any(true));
1603 xProps
->setPropertyValue("EmbedComplexScriptFonts", uno::Any(true));
1605 // Save the document again
1607 CPPUNIT_ASSERT(maTempFile
.IsValid());
1609 // Check setting - font embedding should be enabled + embed only used fonts and scripts
1610 pXmlDoc
= parseExport("settings.xml");
1611 CPPUNIT_ASSERT(pXmlDoc
);
1613 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "true");
1615 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
1618 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
1621 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
1624 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
1627 // Check content - font-face-src should be present only for "Liberation Sans" fonts
1629 pXmlDoc
= parseExport("content.xml");
1630 CPPUNIT_ASSERT(pXmlDoc
);
1632 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
1633 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
1636 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
1637 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
1638 assertXPath(pXmlDoc
,
1640 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
1642 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
1643 assertXPath(pXmlDoc
,
1645 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
1647 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
1648 assertXPath(pXmlDoc
,
1650 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
1652 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
1653 assertXPath(pXmlDoc
,
1654 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
1655 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
1656 assertXPath(pXmlDoc
,
1657 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
1661 // Unit test for fix inconsistent bookmark behavior around at-char/as-char anchored frames
1663 // We have a placeholder character in the sw doc model for as-char anchored frames,
1664 // so it's possible to have a bookmark before/after the frame or a non-collapsed bookmark
1665 // which covers the frame. The same is not true for at-char anchored frames,
1666 // where the anchor points to a doc model position, but there is no placeholder character.
1667 // If a bookmark is created covering the start and end of the anchor of the frame,
1668 // internally we create a collapsed bookmark which has the same position as the anchor of the frame.
1669 // When this doc model is handled by SwXParagraph::createEnumeration(),
1670 // first the frame and then the bookmark is appended to the text portion enumeration,
1671 // so your bookmark around the frame is turned into a collapsed bookmark after the frame.
1672 // (The same happens when we roundtrip an ODT document representing this doc model.)
1674 // Fix the problem by inserting collapsed bookmarks with affected anchor positions
1675 // (same position is the anchor for an at-char frame) into the enumeration in two stages:
1676 // first the start of them before frames and then the end of them + other bookmarks.
1677 // This way UNO API users get their non-collapsed bookmarks around at-char anchored frames,
1678 // similar to as-char ones.
1679 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInconsistentBookmark
)
1681 // create test document with text and bookmark
1683 createSwDoc("testInconsistentBookmark.ott");
1684 SwDoc
* pDoc
= getSwDoc();
1685 IDocumentMarkAccess
& rIDMA(*pDoc
->getIDocumentMarkAccess());
1686 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
1687 SwCursor
aPaM(SwPosition(aIdx
), nullptr);
1689 aPaM
.MovePara(GoCurrPara
, fnParaStart
);
1690 aPaM
.MovePara(GoCurrPara
, fnParaEnd
);
1691 rIDMA
.makeMark(aPaM
, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK
,
1692 ::sw::mark::InsertMode::New
);
1697 // save document and verify the bookmark scoup
1702 // load only content.xml
1703 xmlDocUniquePtr pXmlDoc
= parseExport("content.xml");
1704 const OString
aPath("/office:document-content/office:body/office:text/text:p");
1706 const int pos1
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-start");
1707 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "control");
1708 const int pos3
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-end");
1710 CPPUNIT_ASSERT_GREATER(pos1
, pos2
);
1711 CPPUNIT_ASSERT_GREATER(pos2
, pos3
);
1715 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSpellOnlineParameter
)
1718 SwDoc
* pDoc
= getSwDoc();
1719 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1720 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
1721 bool bSet
= pOpt
->IsOnlineSpell();
1723 uno::Sequence
<beans::PropertyValue
> params
1724 = comphelper::InitPropertySequence({ { "Enable", uno::Any(!bSet
) } });
1725 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1726 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
1728 // set the same state as now and we don't expect any change (no-toggle)
1729 params
= comphelper::InitPropertySequence({ { "Enable", uno::Any(!bSet
) } });
1730 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1731 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
1734 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf124603
)
1737 SwDoc
* pDoc
= getSwDoc();
1738 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1739 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
1740 uno::Sequence
<beans::PropertyValue
> params
1741 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
1742 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1744 // Automatic Spell Checking is enabled
1746 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
1748 // check available en_US dictionary and test spelling with it
1749 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
1750 uno::Reference
<XSpellChecker1
> xSpell
;
1751 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
1752 LanguageType eLang
= LanguageTag::convertToLanguageType(lang::Locale("en", "US", OUString()));
1753 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
1755 // Type a correct word
1757 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1758 emulateTyping(*pTextDoc
, u
"the ");
1759 SwCursorShell
* pShell(pDoc
->GetEditShell());
1760 SwTextNode
* pNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
1762 CPPUNIT_ASSERT_EQUAL(static_cast<SwWrongList
*>(nullptr), pNode
->GetWrong());
1764 // Create a bad word from the good: "the" -> "thex"
1766 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1767 emulateTyping(*pTextDoc
, u
"x");
1768 // tdf#92036 pending spell checking
1769 bool bPending
= !pNode
->GetWrong() || !pNode
->GetWrong()->Count();
1770 CPPUNIT_ASSERT(bPending
);
1772 // Move right, leave the bad word
1774 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1775 // tdf#92036 still pending spell checking
1776 bPending
= !pNode
->GetWrong() || !pNode
->GetWrong()->Count();
1777 CPPUNIT_ASSERT(bPending
);
1779 // Move down to trigger spell checking
1781 pWrtShell
->Down(/*bSelect=*/false, 1);
1782 Scheduler::ProcessEventsToIdle();
1783 CPPUNIT_ASSERT(pNode
->GetWrong());
1784 // This was 0 (pending spell checking)
1785 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pNode
->GetWrong()->Count());
1789 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf65535
)
1791 #if !defined(MACOSX)
1792 createSwDoc("tdf65535.fodt");
1793 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1794 SwWrtShell
* pWrtShell
= pTextDoc
->GetDocShell()->GetWrtShell();
1795 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
1796 uno::Sequence
<beans::PropertyValue
> params
1797 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
1798 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1800 // Automatic Spell Checking is enabled
1802 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
1804 // check available en_US dictionary and test spelling with it
1805 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
1806 uno::Reference
<XSpellChecker1
> xSpell
;
1807 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
1808 LanguageType eLang
= LanguageTag::convertToLanguageType(lang::Locale("en", "US", OUString()));
1809 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
1811 // trigger online spell checking by (a few) spaces to be sure to get it
1813 emulateTyping(*pTextDoc
, u
" ");
1815 // FIXME: inserting a space before the bad word removes the red underline
1816 // Insert a second space to get the red underline (back)
1818 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1819 emulateTyping(*pTextDoc
, u
" ");
1821 // Select the bad word (right to left, as during right click)
1823 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/false, 5, /*bBasicCall=*/false);
1824 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/true, 4, /*bBasicCall=*/false);
1826 // choose the word "Baaed" from the spelling suggestions of the context menu
1828 SfxViewShell
* pViewShell
= SfxViewShell::Current();
1830 static const OUStringLiteral
sApplyRule(u
"Spelling_Baaed");
1831 SfxStringItem
aApplyItem(FN_PARAM_1
, sApplyRule
);
1832 pViewShell
->GetViewFrame().GetDispatcher()->ExecuteList(
1833 SID_SPELLCHECK_APPLY_SUGGESTION
, SfxCallMode::SYNCHRON
, { &aApplyItem
});
1836 // check the replacement in the text
1838 CPPUNIT_ASSERT_EQUAL(OUString(" Baaed"), getParagraph(1)->getString());
1841 // check the remaining comment
1843 tools::JsonWriter aJsonWriter
;
1844 pTextDoc
->getPostIts(aJsonWriter
);
1845 OString pChar
= aJsonWriter
.finishAndGetAsOString();
1846 std::stringstream
aStream((std::string(pChar
)));
1847 boost::property_tree::ptree aTree
;
1848 boost::property_tree::read_json(aStream
, aTree
);
1849 OString sCommentText
;
1850 for (const boost::property_tree::ptree::value_type
& rValue
: aTree
.get_child("comments"))
1852 const boost::property_tree::ptree
& rComment
= rValue
.second
;
1853 sCommentText
= OString(rComment
.get
<std::string
>("text"));
1855 // This was false (lost comment with spelling replacement)
1856 CPPUNIT_ASSERT_EQUAL(OString("with comment"), sCommentText
);
1860 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testRedlineAutoCorrect
)
1862 createSwDoc("redline-autocorrect.fodt");
1863 SwDoc
* pDoc
= getSwDoc();
1865 dispatchCommand(mxComponent
, ".uno:GoToEndOfDoc", {});
1867 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1868 CPPUNIT_ASSERT(pWrtShell
);
1869 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1871 // show tracked deletion with enabled change tracking
1872 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
1873 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
1874 pWrtShell
->SetRedlineFlags(nMode
);
1875 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
1877 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1878 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1880 emulateTyping(*pTextDoc
, u
" ");
1882 // tdf#83419 This was "Ts " removing the deletion of "t" silently by sentence capitalization
1883 OUString
sReplaced("ts ");
1884 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1886 // hide delete redlines
1887 pWrtShell
->SetRedlineFlags(nMode
& ~RedlineFlags::ShowDelete
);
1889 // repeat it with not visible redlining
1890 dispatchCommand(mxComponent
, ".uno:Undo", {});
1892 emulateTyping(*pTextDoc
, u
" ");
1895 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1897 // show delete redlines
1898 pWrtShell
->SetRedlineFlags(nMode
);
1900 // This still keep the tracked deletion, capitalize only the visible text "s"
1901 // with tracked deletion of the original character
1903 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1905 // repeat it with visible redlining and word auto replacement of "tset"
1906 dispatchCommand(mxComponent
, ".uno:Undo", {});
1907 dispatchCommand(mxComponent
, ".uno:Undo", {});
1909 emulateTyping(*pTextDoc
, u
"et ");
1910 // This was "Ttest" removing the tracked deletion silently.
1911 // Don't replace, if a redline starts or ends within the text.
1912 sReplaced
= "tset ";
1913 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1915 // Otherwise replace it
1916 emulateTyping(*pTextDoc
, u
"tset ");
1917 sReplaced
= "tset test ";
1918 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1920 // Including capitalization
1921 emulateTyping(*pTextDoc
, u
"end. word ");
1922 sReplaced
= "tset test end. Word ";
1923 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1925 // tracked deletions after the correction point doesn't affect autocorrect
1926 dispatchCommand(mxComponent
, ".uno:GoToStartOfDoc", {});
1927 emulateTyping(*pTextDoc
, u
"a ");
1928 sReplaced
= "A tset test end. Word ";
1929 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1932 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testRedlineAutoCorrect2
)
1934 createSwDoc("redline-autocorrect2.fodt");
1935 SwDoc
* pDoc
= getSwDoc();
1936 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1937 CPPUNIT_ASSERT(pWrtShell
);
1938 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1940 dispatchCommand(mxComponent
, ".uno:GoToEndOfDoc", {});
1942 // show tracked deletion
1943 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
1944 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
1945 pWrtShell
->SetRedlineFlags(nMode
);
1946 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
1948 emulateTyping(*pTextDoc
, u
"... ");
1950 // This was "LoremLorem,…," (duplicating the deleted comma, but without deletion)
1951 // Don't replace, if a redline starts or ends within the text.
1952 OUString sReplaced
= "Lorem,... ";
1953 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1956 emulateTyping(*pTextDoc
, u
"Lorem,... ");
1957 sReplaced
= u
"Lorem,... Lorem,… ";
1958 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1961 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testEmojiAutoCorrect
)
1963 createSwDoc("redline-autocorrect3.fodt");
1964 SwDoc
* pDoc
= getSwDoc();
1965 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1966 CPPUNIT_ASSERT(pWrtShell
);
1967 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1969 // Emoji replacement (:snowman: -> ☃)
1971 // without change tracking
1972 CPPUNIT_ASSERT(!(pWrtShell
->GetRedlineFlags() & RedlineFlags::On
));
1973 emulateTyping(*pTextDoc
, u
":snowman:");
1974 OUString sReplaced
= u
"☃Lorem,";
1975 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1977 // with change tracking (showing redlines)
1978 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
1979 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
1980 pWrtShell
->SetRedlineFlags(nMode
);
1981 CPPUNIT_ASSERT(nMode
& RedlineFlags::On
);
1982 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
1984 emulateTyping(*pTextDoc
, u
":snowman:");
1985 sReplaced
= u
"☃☃Lorem,";
1987 // tdf#140674 This was ":snowman:" instead of autocorrect
1988 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
1991 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf108423
)
1994 SwDoc
* pDoc
= getSwDoc();
1995 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1996 CPPUNIT_ASSERT(pWrtShell
);
1997 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1998 // testing autocorrect of i' -> I' on start of first paragraph
1999 emulateTyping(*pTextDoc
, u
"i'");
2000 // The word "i" should be capitalized due to autocorrect, followed by a typographical apostrophe
2001 OUString
sIApostrophe(u
"I\u2019");
2002 CPPUNIT_ASSERT_EQUAL(sIApostrophe
, getParagraph(1)->getString());
2003 emulateTyping(*pTextDoc
, u
" i'");
2004 OUString
sText(sIApostrophe
+ u
" " + sIApostrophe
);
2005 CPPUNIT_ASSERT_EQUAL(sText
, getParagraph(1)->getString());
2008 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf153423
)
2011 SvxSwAutoFormatFlags
flags(*SwEditShell::GetAutoFormatFlags());
2012 comphelper::ScopeGuard
const g([=]() { SwEditShell::SetAutoFormatFlags(&flags
); });
2013 flags
.bSetNumRule
= true;
2014 SwEditShell::SetAutoFormatFlags(&flags
);
2016 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2017 emulateTyping(*pTextDoc
, u
"1. Item 1");
2019 SwXTextDocument
* pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2020 CPPUNIT_ASSERT(pXTextDocument
);
2021 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
2022 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_RETURN
);
2023 Scheduler::ProcessEventsToIdle();
2025 // Without the fix in place, this test would have failed with
2028 CPPUNIT_ASSERT_EQUAL(OUString("1."), getProperty
<OUString
>(getParagraph(1), "ListLabelString"));
2031 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf106164
)
2034 SwDoc
* pDoc
= getSwDoc();
2035 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2036 CPPUNIT_ASSERT(pWrtShell
);
2037 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2038 // testing autocorrect of we're -> We're on start of first paragraph
2039 emulateTyping(*pTextDoc
, u
"we're ");
2040 CPPUNIT_ASSERT_EQUAL(OUString(u
"We\u2019re "), getParagraph(1)->getString());
2043 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf54409
)
2046 SwDoc
* pDoc
= getSwDoc();
2047 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2048 CPPUNIT_ASSERT(pWrtShell
);
2049 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2050 // testing autocorrect of "tset -> "test with typographical double quotation mark U+201C
2051 emulateTyping(*pTextDoc
, u
"\"test ");
2052 OUString
sReplaced(u
"\u201Ctest ");
2053 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2054 // testing autocorrect of test" -> test" with typographical double quotation mark U+201D
2055 emulateTyping(*pTextDoc
, u
"and tset\" ");
2056 OUString
sReplaced2(sReplaced
+ u
"and test\u201D ");
2057 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2058 // testing autocorrect of "tset" -> "test" with typographical double quotation mark U+201C and U+201D
2059 emulateTyping(*pTextDoc
, u
"\"tset\" ");
2060 OUString
sReplaced3(sReplaced2
+ u
"\u201Ctest\u201D ");
2061 CPPUNIT_ASSERT_EQUAL(sReplaced3
, getParagraph(1)->getString());
2064 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf38394
)
2066 createSwDoc("tdf38394.fodt");
2067 SwDoc
* pDoc
= getSwDoc();
2068 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2069 CPPUNIT_ASSERT(pWrtShell
);
2070 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2071 // testing autocorrect of French l'" -> l'« (instead of l'»)
2072 emulateTyping(*pTextDoc
, u
"l'\"");
2073 OUString
sReplaced(u
"l\u2019« ");
2074 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2075 // tdf#132301 autocorrect of qu'«
2076 emulateTyping(*pTextDoc
, u
" qu'\"");
2077 sReplaced
+= u
" qu\u2019« ";
2078 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2081 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf59666
)
2084 SwDoc
* pDoc
= getSwDoc();
2085 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2086 CPPUNIT_ASSERT(pWrtShell
);
2087 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2088 // testing missing autocorrect of single Greek letters
2089 emulateTyping(*pTextDoc
, u
"π ");
2090 CPPUNIT_ASSERT_EQUAL(OUString(u
"\u03C0 "), getParagraph(1)->getString());
2093 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf133524
)
2095 createSwDoc("tdf133524.fodt");
2096 SwDoc
* pDoc
= getSwDoc();
2097 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2098 CPPUNIT_ASSERT(pWrtShell
);
2099 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2100 // 1. Testing autocorrect of >> and <<
2102 emulateTyping(*pTextDoc
, u
">>");
2103 OUString
sReplaced(u
"»");
2104 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2106 emulateTyping(*pTextDoc
, u
"word<<");
2107 sReplaced
+= u
"word«";
2108 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2109 // 2. Testing autocorrect of " to >> and << inside „...”
2110 // Example: „Sentence and »word«.”
2111 // opening primary level quote
2112 emulateTyping(*pTextDoc
, u
" \"");
2114 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2115 // opening second level quote
2116 emulateTyping(*pTextDoc
, u
"Sentence and \"");
2117 sReplaced
+= u
"Sentence and »";
2118 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2119 // closing second level quote
2120 emulateTyping(*pTextDoc
, u
"word\"");
2121 sReplaced
+= u
"word«";
2122 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2123 // closing primary level quote
2124 emulateTyping(*pTextDoc
, u
".\"");
2126 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2127 // tdf#134940 avoid premature replacement of "--" in "-->"
2128 emulateTyping(*pTextDoc
, u
" -->");
2129 OUString
sReplaced2(sReplaced
+ u
" -->");
2130 // This was "–>" instead of "-->"
2131 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2132 emulateTyping(*pTextDoc
, u
" ");
2133 sReplaced
+= u
" → ";
2134 // This was "–>" instead of "→"
2135 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2138 emulateTyping(*pTextDoc
, u
"-> ");
2140 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2141 emulateTyping(*pTextDoc
, u
"<- ");
2143 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2144 emulateTyping(*pTextDoc
, u
"<-- ");
2146 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2147 emulateTyping(*pTextDoc
, u
"<--> ");
2149 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2152 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf133524_Romanian
)
2154 createSwDoc("tdf133524_ro.fodt");
2155 SwDoc
* pDoc
= getSwDoc();
2156 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2157 CPPUNIT_ASSERT(pWrtShell
);
2158 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2159 // 1. Testing autocorrect of " to << and >> inside „...”
2160 // Example: „Sentence and «word».”
2161 // opening primary level quote
2162 emulateTyping(*pTextDoc
, u
"\"");
2163 OUString
sReplaced(u
"„");
2164 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2165 // opening second level quote
2166 emulateTyping(*pTextDoc
, u
"Sentence and \"");
2167 sReplaced
+= u
"Sentence and «";
2168 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2169 // closing second level quote
2170 emulateTyping(*pTextDoc
, u
"word\"");
2171 sReplaced
+= u
"word»";
2172 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2173 // closing primary level quote
2174 emulateTyping(*pTextDoc
, u
".\"");
2176 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2177 // 2. Testing recognition of closing double quotation mark ”
2178 emulateTyping(*pTextDoc
, u
" \"");
2180 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2181 // 3. Testing recognition of alternative closing double quotation mark “
2182 emulateTyping(*pTextDoc
, u
"Alternative.“ \"");
2183 sReplaced
+= u
"Alternative.“ „";
2184 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2187 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf128860
)
2189 createSwDoc("tdf128860.fodt");
2190 SwDoc
* pDoc
= getSwDoc();
2191 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2192 CPPUNIT_ASSERT(pWrtShell
);
2193 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2194 // Second level ending quote: ‚word' -> ,word‘
2195 emulateTyping(*pTextDoc
, u
",word'");
2196 OUString
sReplaced(u
",word\u2019");
2197 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2198 // Us apostrophe without preceding starting quote: word' -> word’
2199 emulateTyping(*pTextDoc
, u
" word'");
2200 sReplaced
+= u
" word\u2019";
2201 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2202 // But only after letters: word.' -> word.‘
2203 emulateTyping(*pTextDoc
, u
" word.'");
2204 sReplaced
+= u
" word.‘";
2205 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2208 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf123786
)
2210 createSwDoc("tdf123786.fodt");
2211 SwDoc
* pDoc
= getSwDoc();
2213 // On Windows, it will detect that system input language is en-US (despite "typing" e.g. Cyrillic characters),
2214 // and will change Russian into English (US); in the latter language,
2215 // the replacement from single quote will not become “, but ’.
2216 SvtSysLocaleOptions aOptions
;
2217 aOptions
.SetIgnoreLanguageChange(true);
2220 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2221 CPPUNIT_ASSERT(pWrtShell
);
2222 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2223 // Second level ending quote: „word' -> „word“
2224 emulateTyping(*pTextDoc
, u
"„слово'");
2225 OUString
sReplaced(u
"„слово“");
2226 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2227 // Us apostrophe without preceding starting quote: word' -> word’
2228 emulateTyping(*pTextDoc
, u
" слово'");
2229 sReplaced
+= u
" слово’";
2230 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2231 // But only after letters: word.' -> word.“
2232 emulateTyping(*pTextDoc
, u
" слово.'");
2233 sReplaced
+= u
" слово.“";
2234 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2237 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf133589
)
2239 // Hungarian test document with right-to-left paragraph setting
2240 createSwDoc("tdf133589.fodt");
2241 SwDoc
* pDoc
= getSwDoc();
2242 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2243 CPPUNIT_ASSERT(pWrtShell
);
2244 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2245 // translitere words to Old Hungarian
2246 emulateTyping(*pTextDoc
, u
"székely ");
2247 OUString
sReplaced(u
"𐳥𐳋𐳓𐳉𐳗 ");
2248 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2249 // disambiguate consonants: asszony -> asz|szony
2250 emulateTyping(*pTextDoc
, u
"asszony ");
2251 sReplaced
+= u
"𐳀𐳥𐳥𐳛𐳚 ";
2252 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2253 // disambiguate consonants: kosszarv -> kos|szarv
2254 // (add explicit ZWSP temporarily for consonant disambiguation, because the requested
2255 // hu_HU hyphenation dictionary isn't installed on all testing platform)
2256 // pWrtShell->Insert(u"kosszarv");
2257 emulateTyping(*pTextDoc
, u
"kos\u200Bszarv ");
2258 sReplaced
+= u
"𐳓𐳛𐳤𐳥𐳀𐳢𐳮 ";
2259 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2260 // transliterate numbers to Old Hungarian
2261 emulateTyping(*pTextDoc
, u
"2020 ");
2262 sReplaced
+= u
"𐳺𐳺𐳿𐳼𐳼 ";
2263 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2265 // tdf#147546 transliterate punctuation marks
2268 emulateTyping(*pTextDoc
, u
"Kérdőjel?");
2269 sReplaced
+= u
"𐲓𐳋𐳢𐳇𐳟𐳒𐳉𐳖";
2270 OUString
sReplaced2(sReplaced
+ "?");
2271 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2272 emulateTyping(*pTextDoc
, u
" ");
2274 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2276 emulateTyping(*pTextDoc
, u
"Vessző,");
2277 sReplaced
+= u
"𐲮𐳉𐳥𐳥𐳟";
2278 sReplaced2
= sReplaced
+ ",";
2279 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2280 emulateTyping(*pTextDoc
, u
" ");
2282 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2284 emulateTyping(*pTextDoc
, u
"pontosvessző;");
2285 sReplaced
+= u
"𐳠𐳛𐳙𐳦𐳛𐳤𐳮𐳉𐳥𐳥𐳟";
2286 sReplaced2
= sReplaced
+ ";";
2287 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2288 emulateTyping(*pTextDoc
, u
" ");
2290 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2292 emulateTyping(*pTextDoc
, u
"„idézőjel” ");
2293 sReplaced
+= u
"⹂𐳐𐳇𐳋𐳯𐳟𐳒𐳉𐳖‟ ";
2294 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2296 // tdf#148672 transliterate word with closing bracket
2297 emulateTyping(*pTextDoc
, u
"word] ");
2298 sReplaced
+= u
"𐳮𐳛𐳢𐳇] "; // This was "word]" (no transliteration)
2299 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2301 // tdf#148672 transliterate words with parenthesis (libnumbertext 1.0.11)
2302 emulateTyping(*pTextDoc
, u
"(word) ");
2303 sReplaced
+= u
"(𐳮𐳛𐳢𐳇) "; // This was "(word)" (no transliteration)
2304 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2306 emulateTyping(*pTextDoc
, u
"(word ");
2307 sReplaced
+= u
"(𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2308 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2310 emulateTyping(*pTextDoc
, u
"word) ");
2311 sReplaced
+= u
"𐳮𐳛𐳢𐳇) "; // This was "word)" (no transliteration)
2312 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2314 emulateTyping(*pTextDoc
, u
"{word} ");
2315 sReplaced
+= u
"{𐳮𐳛𐳢𐳇} "; // This was "(word)" (no transliteration)
2316 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2318 emulateTyping(*pTextDoc
, u
"{word ");
2319 sReplaced
+= u
"{𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2320 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2322 emulateTyping(*pTextDoc
, u
"word} ");
2323 sReplaced
+= u
"𐳮𐳛𐳢𐳇} "; // This was "word)" (no transliteration)
2324 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2326 emulateTyping(*pTextDoc
, u
"[word] ");
2327 sReplaced
+= u
"[𐳮𐳛𐳢𐳇] "; // This was "(word)" (no transliteration)
2328 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2330 emulateTyping(*pTextDoc
, u
"[word ");
2331 sReplaced
+= u
"[𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2332 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2335 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testAutoCorr
)
2338 SwDoc
* pDoc
= getSwDoc();
2339 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2340 CPPUNIT_ASSERT(pWrtShell
);
2341 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2343 //Normal AutoCorrect
2344 emulateTyping(*pTextDoc
, u
"tset ");
2345 CPPUNIT_ASSERT_EQUAL(OUString("Test "), getParagraph(1)->getString());
2347 //AutoCorrect with change style to bolt
2348 emulateTyping(*pTextDoc
, u
"Bolt ");
2349 const uno::Reference
<text::XTextRange
> xRun
= getRun(getParagraph(1), 2);
2350 CPPUNIT_ASSERT_EQUAL(OUString("Bolt"), xRun
->getString());
2351 CPPUNIT_ASSERT_EQUAL(OUString("Arial"), getProperty
<OUString
>(xRun
, "CharFontName"));
2353 //AutoCorrect inserts Table with 2 rows and 3 columns
2354 emulateTyping(*pTextDoc
, u
"4xx ");
2355 const uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(2), uno::UNO_QUERY
);
2356 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable
->getRows()->getCount());
2357 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable
->getColumns()->getCount());
2360 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf130274
)
2363 SwDoc
* pDoc
= getSwDoc();
2364 SwWrtShell
* const pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2365 CPPUNIT_ASSERT(pWrtShell
);
2366 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2368 CPPUNIT_ASSERT(!pWrtShell
->GetLayout()->IsHideRedlines());
2370 !IDocumentRedlineAccess::IsRedlineOn(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
2372 // "tset" may be replaced by the AutoCorrect in the test profile
2373 emulateTyping(*pTextDoc
, u
"tset");
2374 // select from left to right
2375 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 4, /*bBasicCall=*/false);
2376 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/true, 4, /*bBasicCall=*/false);
2378 pWrtShell
->SetRedlineFlags(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
2379 // this would crash in AutoCorrect
2380 emulateTyping(*pTextDoc
, u
".");
2382 CPPUNIT_ASSERT(!pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty());
2385 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf83260
)
2387 createSwDoc("tdf83260-1.odt");
2388 SwDoc
* pDoc
= getSwDoc();
2389 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2390 CPPUNIT_ASSERT(pWrtShell
);
2391 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2393 // enabled but not shown
2394 CPPUNIT_ASSERT(pWrtShell
->GetLayout()->IsHideRedlines());
2396 CPPUNIT_ASSERT(IDocumentRedlineAccess::IsHideChanges(
2397 pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
2400 IDocumentRedlineAccess::IsRedlineOn(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
2401 CPPUNIT_ASSERT(!pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty());
2403 // the document contains redlines that are combined with CompressRedlines()
2404 // if that happens during AutoCorrect then indexes in Undo are off -> crash
2405 emulateTyping(*pTextDoc
, u
"tset ");
2406 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
2407 auto const nActions(rUndoManager
.GetUndoActionCount());
2408 for (auto i
= nActions
; 0 < i
; --i
)
2410 rUndoManager
.Undo();
2412 // check that every text node has a layout frame
2413 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
2415 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
2417 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
2420 for (auto i
= nActions
; 0 < i
; --i
)
2422 rUndoManager
.Redo();
2424 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
2426 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
2428 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
2431 for (auto i
= nActions
; 0 < i
; --i
)
2433 rUndoManager
.Undo();
2435 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
2437 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
2439 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
2444 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf74363
)
2447 SwDoc
* pDoc
= getSwDoc();
2448 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2449 CPPUNIT_ASSERT(pWrtShell
);
2450 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2451 //testing autocorrect of initial capitals on start of first paragraph
2452 //Inserting one all-lowercase word into the first paragraph
2453 emulateTyping(*pTextDoc
, u
"testing ");
2454 //The word should be capitalized due to autocorrect
2455 CPPUNIT_ASSERT_EQUAL(OUString("Testing "), getParagraph(1)->getString());
2458 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf139922
)
2461 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2463 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
2464 Scheduler::ProcessEventsToIdle();
2466 emulateTyping(*pTextDoc
, u
"this is a SEntence. this is a SEntence.");
2468 // Without the fix in place, this test would have failed with
2469 // - Expected: This is a Sentence. This is a Sentence.
2470 // - Actual : this is a Sentence. This is a Sentence.
2471 CPPUNIT_ASSERT_EQUAL(OUString("This is a Sentence. This is a Sentence."),
2472 getParagraph(2)->getString());
2475 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf143176
)
2477 // Hungarian test document with right-to-left paragraph setting
2478 createSwDoc("tdf143176.fodt");
2480 // transliterate the document to Old Hungarian (note: it only works
2481 // with right-to-left text direction and Default Paragraph Style)
2482 dispatchCommand(mxComponent
, ".uno:AutoFormatApply", {});
2484 // This was the original "Lorem ipsum..."
2485 CPPUNIT_ASSERT_EQUAL(OUString(u
"𐲖𐳛𐳢𐳉𐳘 𐳐𐳠𐳤𐳪𐳘 𐳇𐳛𐳖𐳛𐳢 "
2487 getParagraph(1)->getString());
2488 CPPUNIT_ASSERT_EQUAL(OUString(u
"𐳄𐳛𐳙𐳤𐳉𐳄𐳦𐳉𐳦𐳪𐳢 "
2489 u
"𐳀𐳇𐳐𐳠𐳐𐳤𐳄𐳐𐳙𐳍 𐳉𐳖𐳐𐳦."),
2490 getParagraph(2)->getString());
2493 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInsertLongDateFormat
)
2495 // only for Hungarian, yet
2496 createSwDoc("tdf133524.fodt");
2497 dispatchCommand(mxComponent
, ".uno:InsertDateField", {});
2498 // Make sure that the document starts with a field now, and its expanded string value contains space
2499 const uno::Reference
<text::XTextRange
> xField
= getRun(getParagraph(1), 1);
2500 CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty
<OUString
>(xField
, "TextPortionType"));
2501 // the date format was "YYYY-MM-DD", but now "YYYY. MMM DD."
2502 CPPUNIT_ASSERT(xField
->getString().indexOf(" ") > -1);
2505 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf129270
)
2507 createSwDoc("tdf129270.odt");
2508 SwDoc
* pDoc
= getSwDoc();
2509 CPPUNIT_ASSERT(pDoc
);
2510 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2511 CPPUNIT_ASSERT(pWrtShell
);
2512 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2514 // Go to document end
2515 pWrtShell
->SttEndDoc(/*bStt=*/false);
2518 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
2519 Scheduler::ProcessEventsToIdle();
2521 // Numbering for previous outline should remain the same "2"
2522 CPPUNIT_ASSERT_EQUAL(OUString("2"), getProperty
<OUString
>(getParagraph(4), "ListLabelString"));
2524 // Numbering for newly created outline should be "2.1"
2525 CPPUNIT_ASSERT_EQUAL(OUString("2.1"),
2526 getProperty
<OUString
>(getParagraph(5), "ListLabelString"));
2529 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInsertPdf
)
2531 auto pPdfium
= vcl::pdf::PDFiumLibrary::get();
2539 // insert the PDF into the document
2540 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
2541 { { "FileName", uno::Any(createFileURL(u
"hello-world.pdf")) } }));
2542 dispatchCommand(mxComponent
, ".uno:InsertGraphic", aArgs
);
2544 // Save and load cycle
2545 saveAndReload("writer8");
2547 uno::Reference
<drawing::XShape
> xShape
= getShape(1);
2548 // Assert that we have a replacement graphics
2549 auto xReplacementGraphic
2550 = getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, "ReplacementGraphic");
2551 CPPUNIT_ASSERT(xReplacementGraphic
.is());
2553 auto xGraphic
= getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, "Graphic");
2554 CPPUNIT_ASSERT(xGraphic
.is());
2555 // Assert that the graphic is a PDF
2556 CPPUNIT_ASSERT_EQUAL(OUString("application/pdf"), getProperty
<OUString
>(xGraphic
, "MimeType"));
2559 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf143760WrapContourToOff
)
2561 // Actually, this is an ooxmlexport test. It is here because here is a ready environment
2562 // to change a shape by dispatchCommand.
2563 createSwDoc("tdf143760_ContourToWrapOff.docx");
2564 SwDoc
* pDoc
= getSwDoc();
2565 CPPUNIT_ASSERT(pDoc
);
2566 CPPUNIT_ASSERT_EQUAL(true, getProperty
<bool>(getShape(1), "SurroundContour"));
2569 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2570 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
2571 SdrObject
* pObject
= pPage
->GetObj(0);
2572 CPPUNIT_ASSERT(pObject
);
2573 SdrView
* pView
= pWrtShell
->GetDrawView();
2574 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
2577 dispatchCommand(mxComponent
, ".uno:WrapOff", {});
2578 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), "SurroundContour"));
2580 // Without fix this had failed, because the shape was written to file with contour.
2581 saveAndReload("Office Open XML Text");
2582 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), "SurroundContour"));
2585 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testHatchFill
)
2589 // Add a rectangle shape to the document.
2590 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
2591 uno::Reference
<drawing::XShape
> xShape(
2592 xFactory
->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY
);
2593 xShape
->setSize(awt::Size(10000, 10000));
2594 xShape
->setPosition(awt::Point(1000, 1000));
2595 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
2596 xShapeProps
->setPropertyValue("FillStyle", uno::Any(drawing::FillStyle_HATCH
));
2597 xShapeProps
->setPropertyValue("FillHatchName", uno::Any(OUString("Black 0 Degrees")));
2598 xShapeProps
->setPropertyValue("FillBackground", uno::Any(false));
2599 xShapeProps
->setPropertyValue("FillTransparence", uno::Any(sal_Int32(30)));
2600 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
2601 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
2602 xDrawPage
->add(xShape
);
2604 // Save it as DOCX and load it again.
2605 saveAndReload("Office Open XML Text");
2606 CPPUNIT_ASSERT_EQUAL(1, getShapes());
2608 // tdf#127989 Without fix this had failed, because the background of the hatch was not set as 'no background'.
2609 CPPUNIT_ASSERT(!getProperty
<bool>(getShape(1), "FillBackground"));
2611 // tdf#146822 Without fix this had failed, because the transparency value of the hatch was not exported.
2612 CPPUNIT_ASSERT_EQUAL(sal_Int32(30), getProperty
<sal_Int32
>(getShape(1), "FillTransparence"));
2615 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testNestedGroupTextBoxCopyCrash
)
2617 createSwDoc("tdf149550.docx");
2619 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
2620 dispatchCommand(mxComponent
, ".uno:Copy", {});
2621 // This crashed here before the fix.
2622 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2623 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_ESCAPE
);
2624 Scheduler::ProcessEventsToIdle();
2625 dispatchCommand(mxComponent
, ".uno:Paste", {});
2627 CPPUNIT_ASSERT_MESSAGE("Where is the doc, it crashed, isn't it?!", mxComponent
);
2629 auto pLayout
= parseLayoutDump();
2630 // There must be 2 textboxes!
2631 assertXPath(pLayout
, "/root/page/body/txt/anchored/fly[2]");
2634 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testCrashOnExit
)
2636 // Load the bugdoc with a table and a textbox shape inside.
2637 createSwDoc("tdf142715.odt");
2639 // Get the textbox selected
2640 CPPUNIT_ASSERT_EQUAL(1, getShapes());
2643 auto xShape
= getShape(1);
2644 uno::Reference
<beans::XPropertySet
> xProperties(xShape
, uno::UNO_QUERY
);
2646 // Check if the textbox is selected
2647 CPPUNIT_ASSERT_EQUAL(true, xProperties
->getPropertyValue("TextBox").get
<bool>());
2649 // Remove the textbox
2650 dispatchCommand(mxComponent
, ".uno:RemoveTextBox", {});
2652 CPPUNIT_ASSERT_EQUAL(false, xProperties
->getPropertyValue("TextBox").get
<bool>());
2654 // Readd the textbox (to run the textboxhelper::create() method)
2655 dispatchCommand(mxComponent
, ".uno:AddTextBox", {});
2657 CPPUNIT_ASSERT_EQUAL(true, xProperties
->getPropertyValue("TextBox").get
<bool>());
2660 saveAndReload("writer8");
2662 // Before the fix this crashed here and could not reopen.
2663 CPPUNIT_ASSERT_MESSAGE("Crash on exit, isn't it?", mxComponent
);
2666 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testCaptionShape
)
2670 // Add a caption shape to the document.
2671 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
2672 uno::Reference
<drawing::XShape
> xShape(
2673 xFactory
->createInstance("com.sun.star.drawing.CaptionShape"), uno::UNO_QUERY
);
2674 xShape
->setSize(awt::Size(10000, 10000));
2675 xShape
->setPosition(awt::Point(1000, 1000));
2676 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
2677 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
2678 xDrawPage
->add(xShape
);
2680 // Save it as DOCX and load it again.
2681 saveAndReload("Office Open XML Text");
2683 // Without fix in place, the shape was lost on export.
2684 CPPUNIT_ASSERT_EQUAL(1, getShapes());
2687 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf151828_Comment2
)
2691 // Add a basic shape to the document.
2692 uno::Sequence
<beans::PropertyValue
> aArgs(
2693 comphelper::InitPropertySequence({ { "KeyModifier", uno::Any(KEY_MOD1
) } }));
2694 dispatchCommand(mxComponent
, ".uno:BasicShapes", aArgs
);
2696 auto xBasicShape
= getShape(1);
2697 auto pObject
= SdrObject::getSdrObjectFromXShape(xBasicShape
);
2699 CPPUNIT_ASSERT_EQUAL(1, getShapes());
2701 // rename the shape name
2702 pObject
->SetName("Shape");
2705 dispatchCommand(mxComponent
, ".uno:Cut", {});
2707 CPPUNIT_ASSERT_EQUAL(0, getShapes());
2709 dispatchCommand(mxComponent
, ".uno:Paste", {});
2711 CPPUNIT_ASSERT_EQUAL(1, getShapes());
2713 // it is required to get the shape object again after paste
2714 xBasicShape
= getShape(1);
2715 pObject
= SdrObject::getSdrObjectFromXShape(xBasicShape
);
2717 // Without fix in place, the shape name was 'Shape 1' after paste.
2718 CPPUNIT_ASSERT_EQUAL(OUString("Shape"), pObject
->GetName());
2721 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf151828
)
2724 SwDoc
* pDoc
= getSwDoc();
2725 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2728 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
2729 pWrtShell
->InsertTable(TableOpt
, 1, 1);
2731 // move cursor into the table
2732 CPPUNIT_ASSERT(pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
));
2734 SwFrameFormat
* pFormat
= pWrtShell
->GetTableFormat();
2735 CPPUNIT_ASSERT(pFormat
);
2737 // set name of table to 'MyTableName'
2738 pWrtShell
->SetTableName(*pFormat
, "MyTableName");
2740 // cut and paste the table
2741 dispatchCommand(mxComponent
, ".uno:SelectTable", {});
2742 dispatchCommand(mxComponent
, ".uno:Cut", {});
2743 dispatchCommand(mxComponent
, ".uno:Paste", {});
2745 // move cursor into the pasted table
2746 CPPUNIT_ASSERT(pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
));
2748 pFormat
= pWrtShell
->GetTableFormat();
2749 CPPUNIT_ASSERT(pFormat
);
2751 // Before the fix the pasted table name was 'Table1'.
2752 CPPUNIT_ASSERT_EQUAL(OUString("MyTableName"), pFormat
->GetName());
2755 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf146178
)
2759 SwDoc
* pDoc
= getSwDoc();
2760 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2761 SwPaM
* pCursor
= pDoc
->GetEditShell()->GetCursor();
2763 // insert two fields
2764 dispatchCommand(mxComponent
, ".uno:InsertTimeField", {});
2765 dispatchCommand(mxComponent
, ".uno:InsertDateField", {});
2767 // navigate by field
2768 SwView::SetMoveType(NID_FIELD
);
2770 // set cursor to the start of the document
2771 pWrtShell
->SttEndDoc(false);
2772 // navigate to the previous field
2773 dispatchCommand(mxComponent
, ".uno:ScrollToPrevious", {});
2774 // Before the fix the position would be 0, navigation did not wrap to end of document
2775 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pCursor
->GetPoint()->GetContentIndex());
2777 // set cursor to the end of the document
2778 pWrtShell
->SttEndDoc(false);
2779 // navigate to the next field
2780 dispatchCommand(mxComponent
, ".uno:ScrollToNext", {});
2781 // Before the fix the position would be 1, navigation did not wrap to start of document
2782 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pCursor
->GetPoint()->GetContentIndex());
2785 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf155407
)
2788 SwXTextDocument
& rTextDoc
= dynamic_cast<SwXTextDocument
&>(*mxComponent
);
2791 emulateTyping(rTextDoc
, u
"Foo - 11’--’22 ");
2792 // Without the fix in place, this would fail with
2793 // - Expected: Foo – 11’—’22
2794 // - Actual : Foo – 11’--’22
2795 CPPUNIT_ASSERT_EQUAL(OUString(u
"Foo – 11’—’22 "), getParagraph(1)->getString());
2798 dispatchCommand(mxComponent
, ".uno:SelectAll", {}); // start again
2801 emulateTyping(rTextDoc
, u
"Bar -- 111--222 ");
2802 // Without the fix in place, this would fail with
2803 // - Expected: Bar – 111–222
2804 // - Actual : Bar – 111-–22
2805 CPPUNIT_ASSERT_EQUAL(OUString(u
"Bar – 111–222 "), getParagraph(1)->getString());
2809 CPPUNIT_PLUGIN_IMPLEMENT();
2811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */