2 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of the LibreOffice project.
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include <string_view>
14 #include <com/sun/star/awt/FontWeight.hpp>
15 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
16 #include <com/sun/star/drawing/FillStyle.hpp>
17 #include <com/sun/star/i18n/TextConversionOption.hpp>
18 #include <com/sun/star/style/CaseMap.hpp>
19 #include <vcl/errcode.hxx>
20 #include <tools/gen.hxx>
21 #include <swmodeltestbase.hxx>
24 #include <shellio.hxx>
26 #include <drawdoc.hxx>
28 #include <redline.hxx>
29 #include <section.hxx>
30 #include <fmtclds.hxx>
31 #include <dcontact.hxx>
32 #include <textboxhelper.hxx>
35 #include <swacorr.hxx>
36 #include <swmodule.hxx>
38 #include <charatr.hxx>
39 #include <editeng/acorrcfg.hxx>
40 #include <unotools/streamwrap.hxx>
41 #include <unocrsr.hxx>
42 #include <unocrsrhelper.hxx>
45 #include <IDocumentMarkAccess.hxx>
46 #include <IDocumentSettingAccess.hxx>
47 #include <pagedesc.hxx>
48 #include <PostItMgr.hxx>
49 #include <AnnotationWin.hxx>
50 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
51 #include <com/sun/star/awt/FontUnderline.hpp>
52 #include <com/sun/star/text/XTextColumns.hpp>
53 #include <vcl/TypeSerializer.hxx>
55 #include <svx/svdpage.hxx>
56 #include <svx/svdview.hxx>
57 #include <svl/itemiter.hxx>
58 #include <svx/svxids.hrc>
59 #include <unotools/localfilehelper.hxx>
60 #include <vcl/filter/PDFiumLibrary.hxx>
62 #include <editeng/eeitem.hxx>
63 #include <editeng/scripttypeitem.hxx>
64 #include <editeng/fontitem.hxx>
65 #include <editeng/lrspitem.hxx>
66 #include <editeng/opaqitem.hxx>
67 #include <editeng/protitem.hxx>
68 #include <editeng/ulspitem.hxx>
69 #include <editeng/wghtitem.hxx>
70 #include <i18nutil/transliteration.hxx>
71 #include <i18nutil/searchopt.hxx>
74 #include <txatbase.hxx>
76 #include <IDocumentDrawModelAccess.hxx>
77 #include <IDocumentFieldsAccess.hxx>
78 #include <IDocumentRedlineAccess.hxx>
79 #include <IDocumentState.hxx>
80 #include <unofldmid.h>
81 #include <UndoManager.hxx>
85 #include <tblafmt.hxx>
87 #include <com/sun/star/lang/Locale.hpp>
88 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
89 #include <com/sun/star/util/XNumberFormatTypes.hpp>
90 #include <com/sun/star/util/NumberFormat.hpp>
91 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
92 #include <com/sun/star/util/SearchAlgorithms2.hpp>
93 #include <com/sun/star/util/SearchFlags.hpp>
94 #include <com/sun/star/util/SearchAlgorithms.hpp>
95 #include <com/sun/star/sdb/DatabaseContext.hpp>
96 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
97 #include <com/sun/star/sdbc/XDataSource.hpp>
98 #include <com/sun/star/text/XParagraphCursor.hpp>
99 #include <com/sun/star/util/XPropertyReplace.hpp>
100 #include <com/sun/star/beans/PropertyAttribute.hpp>
101 #include <com/sun/star/text/XTextField.hpp>
102 #include <com/sun/star/text/TextMarkupType.hpp>
103 #include <com/sun/star/chart2/data/XDataSource.hpp>
104 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
105 #include <com/sun/star/drawing/XShape.hpp>
106 #include <com/sun/star/text/XTextTable.hpp>
107 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
108 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
109 #include <com/sun/star/text/XPageCursor.hpp>
110 #include <o3tl/cppunittraitshelper.hxx>
111 #include <o3tl/unit_conversion.hxx>
112 #include <osl/file.hxx>
113 #include <osl/thread.hxx>
114 #include <paratr.hxx>
115 #include <drawfont.hxx>
116 #include <txtfrm.hxx>
117 #include <txttypes.hxx>
118 #include <SwPortionHandler.hxx>
120 #include <swdtflvr.hxx>
121 #include <editeng/svxenum.hxx>
122 #include <comphelper/propertysequence.hxx>
123 #include <sfx2/classificationhelper.hxx>
124 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
125 #include <sfx2/docfilt.hxx>
126 #include <sfx2/viewfrm.hxx>
127 #include <sfx2/dispatch.hxx>
128 #include <comphelper/configurationhelper.hxx>
129 #include <editeng/unolingu.hxx>
130 #include <vcl/scheduler.hxx>
131 #include <config_features.h>
132 #include <sfx2/watermarkitem.hxx>
133 #include <sfx2/fcontnr.hxx>
134 #include <sfx2/docfile.hxx>
135 #include <test/htmltesttools.hxx>
136 #include <fmthdft.hxx>
137 #include <iodetect.hxx>
138 #include <wrthtml.hxx>
140 #include <frameformats.hxx>
142 #include <unotxdoc.hxx>
143 #include <comphelper/processfactory.hxx>
144 #include <rootfrm.hxx>
148 constexpr OUStringLiteral DATA_DIRECTORY
= u
"/sw/qa/extras/uiwriter/data/";
150 sal_Int32
lcl_getAttributeIDFromHints(const SwpHints
& hints
)
152 for (size_t i
= 0; i
< hints
.Count(); ++i
)
154 const SwTextAttr
* hint
= hints
.Get(i
);
155 if (hint
->Which() == RES_TXTATR_AUTOFMT
)
157 const SwFormatAutoFormat
& rFmt
= hint
->GetAutoFormat();
158 SfxItemIter
aIter(*rFmt
.GetStyleHandle());
159 return aIter
.GetCurItem()->Which();
166 class SwUiWriterTest4
: public SwModelTestBase
, public HtmlTestTools
173 void testBookmarkCollapsed();
174 void testRemoveBookmarkText();
175 void testRemoveBookmarkTextAndAddNew();
176 void testRemoveBookmarkTextAndAddNewAfterReload();
179 void testTdf88453Table();
180 void testClassificationPaste();
181 void testSmallCaps();
185 void testTdf84695NormalChar();
186 void testTdf84695Tab();
187 void testTableStyleUndo();
188 void testRedlineCopyPaste();
189 void testTdf135260();
190 void testRedlineParam();
191 void testRedlineViewAuthor();
194 void testRedlineTimestamp();
195 void testCursorWindows();
196 void testLandscape();
198 void testTdf104032();
199 void testTdf104440();
200 void testTdf104425();
201 void testTdf104814();
202 void testTableRedlineRedoCrash();
203 void testTableRemoveHasTextChangesOnly();
204 void testTableRemoveHasTextChangesOnly2();
205 void testTdf147182_AcceptAllChangesInTableSelection();
207 void testTdf35021_tabOverMarginDemo();
208 void testTdf106701_tabOverMarginAutotab();
209 void testTdf104492();
210 void testTdf107025();
211 void testTdf107362();
212 void testTdf105417();
213 void testTdf105625();
214 void testTdf125151_protected();
215 void testTdf125151_protectedB();
216 void testTdf106736();
218 void testTdf112025();
221 void testTdf113877_mergeDocs(const char* aDestDoc
, const char* aInsertDoc
);
222 void testTdf113877();
223 void testTdf113877NoMerge();
224 void testTdf113877_default_style();
225 void testTdf113877_Standard_style();
226 void testTdf113877_blank_bold_on();
227 void testTdf113877_blank_bold_off();
229 void testMsWordCompTrailingBlanks();
230 void testCreateDocxAnnotation();
231 void testTdf107976();
232 void testTdf142157();
233 void testTdf116640();
234 void testTdf108524();
235 void testRhbz1810732();
236 void testTableInSection();
237 void testTableInNestedSection();
238 void testTableInSectionInTable();
239 void testSectionInTableInTable();
240 void testSectionInTableInTable2();
241 void testSectionInTableInTable3();
242 void testSectionInTableInTable4();
243 void testTdf112160();
244 void testLinesMoveBackwardsInSectionInTable();
245 void testTdf112741();
246 void testTdf112860();
247 void testTdf113287();
248 void testTdf113445();
249 void testTdf113686();
250 void testFontEmbedding();
251 void testLinesInSectionInTable();
252 void testParagraphOfTextRange();
253 void testTdf99689TableOfContents();
254 void testTdf99689TableOfFigures();
255 void testTdf99689TableOfTables();
256 void testTdf112448();
257 void testTdf113790();
258 void testTdf108048();
259 void testTdf114306();
260 void testTdf114306_2();
261 void testTdf113481();
262 void testTdf115013();
263 void testTdf114536();
264 void testTdf115065();
265 void testTdf84806_MovingMultipleTableRows();
266 void testTdf147181_TrackedMovingOfMultipleTableRows();
267 void testTdf115132();
268 void testXDrawPagesSupplier();
269 void testTdf116403();
270 void testHtmlCopyImages();
271 void testTdf116789();
274 void testTdf108423();
275 void testTdf106164();
279 void testTdf133524();
280 void testTdf133524_Romanian();
281 void testTdf128860();
282 void testTdf123786();
283 void testTdf133589();
284 void testTdf143176();
285 void testInconsistentBookmark();
286 void testInsertLongDateFormat();
287 void testSpellOnlineParameter();
288 void testRedlineAutoCorrect();
289 void testRedlineAutoCorrect2();
290 void testEmojiAutoCorrect();
291 void testTdf129270();
292 void testInsertPdf();
293 void testTdf143760WrapContourToOff();
294 void testHatchFill();
295 void testTdf62032ApplyStyle();
297 CPPUNIT_TEST_SUITE(SwUiWriterTest4
);
298 CPPUNIT_TEST(testTdf96515
);
299 CPPUNIT_TEST(testTdf96943
);
300 CPPUNIT_TEST(testTdf96536
);
301 CPPUNIT_TEST(testTdf96479
);
302 CPPUNIT_TEST(testBookmarkCollapsed
);
303 CPPUNIT_TEST(testRemoveBookmarkText
);
304 CPPUNIT_TEST(testRemoveBookmarkTextAndAddNew
);
305 CPPUNIT_TEST(testRemoveBookmarkTextAndAddNewAfterReload
);
306 CPPUNIT_TEST(testTdf96961
);
307 CPPUNIT_TEST(testTdf88453
);
308 CPPUNIT_TEST(testTdf88453Table
);
309 CPPUNIT_TEST(testClassificationPaste
);
310 CPPUNIT_TEST(testSmallCaps
);
311 CPPUNIT_TEST(testTdf98987
);
312 CPPUNIT_TEST(testTdf99004
);
313 CPPUNIT_TEST(testTdf84695
);
314 CPPUNIT_TEST(testTdf84695NormalChar
);
315 CPPUNIT_TEST(testTdf84695Tab
);
316 CPPUNIT_TEST(testTableStyleUndo
);
317 CPPUNIT_TEST(testRedlineCopyPaste
);
318 CPPUNIT_TEST(testTdf135260
);
319 CPPUNIT_TEST(testRedlineParam
);
320 CPPUNIT_TEST(testRedlineViewAuthor
);
321 CPPUNIT_TEST(testTdf91292
);
322 CPPUNIT_TEST(testTdf78727
);
323 CPPUNIT_TEST(testRedlineTimestamp
);
324 CPPUNIT_TEST(testCursorWindows
);
325 CPPUNIT_TEST(testLandscape
);
326 CPPUNIT_TEST(testTdf95699
);
327 CPPUNIT_TEST(testTdf104032
);
328 CPPUNIT_TEST(testTdf104440
);
329 CPPUNIT_TEST(testTdf104425
);
330 CPPUNIT_TEST(testTdf104814
);
331 CPPUNIT_TEST(testTableRedlineRedoCrash
);
332 CPPUNIT_TEST(testTableRemoveHasTextChangesOnly
);
333 CPPUNIT_TEST(testTableRemoveHasTextChangesOnly2
);
334 CPPUNIT_TEST(testTdf147182_AcceptAllChangesInTableSelection
);
335 CPPUNIT_TEST(testTdf66405
);
336 CPPUNIT_TEST(testTdf35021_tabOverMarginDemo
);
337 CPPUNIT_TEST(testTdf106701_tabOverMarginAutotab
);
338 CPPUNIT_TEST(testTdf104492
);
339 CPPUNIT_TEST(testTdf107025
);
340 CPPUNIT_TEST(testTdf107362
);
341 CPPUNIT_TEST(testTdf105417
);
342 CPPUNIT_TEST(testTdf105625
);
343 CPPUNIT_TEST(testTdf125151_protected
);
344 CPPUNIT_TEST(testTdf125151_protectedB
);
345 CPPUNIT_TEST(testTdf106736
);
346 CPPUNIT_TEST(testTdf58604
);
347 CPPUNIT_TEST(testTdf112025
);
348 CPPUNIT_TEST(testTdf72942
);
349 CPPUNIT_TEST(testTdf113877
);
350 CPPUNIT_TEST(testTdf113877NoMerge
);
351 CPPUNIT_TEST(testTdf113877_default_style
);
352 CPPUNIT_TEST(testTdf113877_Standard_style
);
353 CPPUNIT_TEST(testTdf113877_blank_bold_on
);
354 CPPUNIT_TEST(testTdf113877_blank_bold_off
);
355 CPPUNIT_TEST(testMsWordCompTrailingBlanks
);
356 CPPUNIT_TEST(testCreateDocxAnnotation
);
357 CPPUNIT_TEST(testTdf107976
);
358 CPPUNIT_TEST(testTdf142157
);
359 CPPUNIT_TEST(testTdf116640
);
360 CPPUNIT_TEST(testTdf108524
);
361 CPPUNIT_TEST(testRhbz1810732
);
362 CPPUNIT_TEST(testTableInSection
);
363 CPPUNIT_TEST(testTableInNestedSection
);
364 CPPUNIT_TEST(testTableInSectionInTable
);
365 CPPUNIT_TEST(testSectionInTableInTable
);
366 CPPUNIT_TEST(testSectionInTableInTable2
);
367 CPPUNIT_TEST(testSectionInTableInTable3
);
368 CPPUNIT_TEST(testSectionInTableInTable4
);
369 CPPUNIT_TEST(testTdf112160
);
370 CPPUNIT_TEST(testLinesMoveBackwardsInSectionInTable
);
371 CPPUNIT_TEST(testTdf112741
);
372 CPPUNIT_TEST(testTdf112860
);
373 CPPUNIT_TEST(testTdf113287
);
374 CPPUNIT_TEST(testTdf113445
);
375 CPPUNIT_TEST(testTdf113686
);
376 CPPUNIT_TEST(testFontEmbedding
);
377 CPPUNIT_TEST(testLinesInSectionInTable
);
378 CPPUNIT_TEST(testParagraphOfTextRange
);
379 CPPUNIT_TEST(testTdf99689TableOfContents
);
380 CPPUNIT_TEST(testTdf99689TableOfFigures
);
381 CPPUNIT_TEST(testTdf99689TableOfTables
);
382 CPPUNIT_TEST(testTdf112448
);
383 CPPUNIT_TEST(testTdf113790
);
384 CPPUNIT_TEST(testTdf108048
);
385 CPPUNIT_TEST(testTdf114306
);
386 CPPUNIT_TEST(testTdf114306_2
);
387 CPPUNIT_TEST(testTdf113481
);
388 CPPUNIT_TEST(testTdf115013
);
389 CPPUNIT_TEST(testTdf114536
);
390 CPPUNIT_TEST(testTdf115065
);
391 CPPUNIT_TEST(testTdf84806_MovingMultipleTableRows
);
392 CPPUNIT_TEST(testTdf147181_TrackedMovingOfMultipleTableRows
);
393 CPPUNIT_TEST(testTdf115132
);
394 CPPUNIT_TEST(testXDrawPagesSupplier
);
395 CPPUNIT_TEST(testTdf116403
);
396 CPPUNIT_TEST(testHtmlCopyImages
);
397 CPPUNIT_TEST(testTdf116789
);
398 CPPUNIT_TEST(testTdf91801
);
399 CPPUNIT_TEST(testTdf51223
);
400 CPPUNIT_TEST(testInconsistentBookmark
);
401 CPPUNIT_TEST(testTdf108423
);
402 CPPUNIT_TEST(testTdf106164
);
403 CPPUNIT_TEST(testTdf54409
);
404 CPPUNIT_TEST(testTdf38394
);
405 CPPUNIT_TEST(testTdf59666
);
406 CPPUNIT_TEST(testTdf133524
);
407 CPPUNIT_TEST(testTdf133524_Romanian
);
408 CPPUNIT_TEST(testTdf128860
);
409 CPPUNIT_TEST(testTdf123786
);
410 CPPUNIT_TEST(testTdf133589
);
411 CPPUNIT_TEST(testTdf143176
);
412 CPPUNIT_TEST(testInsertLongDateFormat
);
413 CPPUNIT_TEST(testSpellOnlineParameter
);
414 CPPUNIT_TEST(testRedlineAutoCorrect
);
415 CPPUNIT_TEST(testRedlineAutoCorrect2
);
416 CPPUNIT_TEST(testEmojiAutoCorrect
);
417 CPPUNIT_TEST(testTdf129270
);
418 CPPUNIT_TEST(testInsertPdf
);
419 CPPUNIT_TEST(testTdf143760WrapContourToOff
);
420 CPPUNIT_TEST(testHatchFill
);
421 CPPUNIT_TEST(testTdf62032ApplyStyle
);
422 CPPUNIT_TEST_SUITE_END();
425 static void lcl_selectCharacters(SwPaM
& rPaM
, sal_Int32 first
, sal_Int32 end
)
427 rPaM
.GetPoint()->nContent
.Assign(rPaM
.GetContentNode(), first
);
429 rPaM
.GetPoint()->nContent
.Assign(rPaM
.GetContentNode(), end
);
432 void SwUiWriterTest4::testTdf96515()
434 // Enable hide whitespace mode.
435 SwDoc
* pDoc
= createSwDoc();
436 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
437 SwViewOption
aViewOptions(*pWrtShell
->GetViewOptions());
438 aViewOptions
.SetHideWhitespaceMode(true);
439 pWrtShell
->ApplyViewOptions(aViewOptions
);
440 CPPUNIT_ASSERT(pWrtShell
->GetViewOptions()->IsWhitespaceHidden());
442 // Insert a new paragraph at the end of the document.
443 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
444 uno::Reference
<text::XParagraphAppend
> xParagraphAppend(xTextDocument
->getText(),
446 xParagraphAppend
->finishParagraph(uno::Sequence
<beans::PropertyValue
>());
449 // This was 2, a new page was created for the new paragraph.
450 CPPUNIT_ASSERT_EQUAL(1, getPages());
453 void SwUiWriterTest4::testTdf96943()
455 // Enable hide whitespace mode.
456 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf96943.odt");
457 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
458 SwViewOption
aViewOptions(*pWrtShell
->GetViewOptions());
459 aViewOptions
.SetHideWhitespaceMode(true);
460 pWrtShell
->ApplyViewOptions(aViewOptions
);
462 // Insert a new character at the end of the document.
463 pWrtShell
->SttEndDoc(/*bStt=*/false);
464 pWrtShell
->Insert("d");
466 // This was 2, a new page was created for the new layout line.
467 CPPUNIT_ASSERT_EQUAL(1, getPages());
470 void SwUiWriterTest4::testTdf96536()
472 // Enable hide whitespace mode.
473 SwDoc
* pDoc
= createSwDoc();
474 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
475 SwViewOption
aViewOptions(*pWrtShell
->GetViewOptions());
476 aViewOptions
.SetHideWhitespaceMode(true);
477 pWrtShell
->ApplyViewOptions(aViewOptions
);
478 CPPUNIT_ASSERT(pWrtShell
->GetViewOptions()->IsWhitespaceHidden());
480 // Insert a page break and go back to the first page.
481 pWrtShell
->InsertPageBreak();
482 pWrtShell
->SttEndDoc(/*bStt=*/true);
484 sal_Int32 nSingleParaPageHeight
= parseDump("/root/page[1]/infos/bounds", "height").toInt32();
485 discardDumpedLayout();
487 // Insert a 2nd paragraph at the end of the first page, so the page height grows at least twice...
488 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
489 uno::Reference
<text::XParagraphAppend
> xParagraphAppend(xTextDocument
->getText(),
491 const uno::Reference
<text::XTextRange
> xInsertPos
= getRun(getParagraph(1), 1);
492 xParagraphAppend
->finishParagraphInsert(uno::Sequence
<beans::PropertyValue
>(), xInsertPos
);
494 CPPUNIT_ASSERT(parseDump("/root/page[1]/infos/bounds", "height").toInt32()
495 >= 2 * nSingleParaPageHeight
);
496 discardDumpedLayout();
498 // ... and then delete the 2nd paragraph, which shrinks the page to the previous size.
499 uno::Reference
<lang::XComponent
> xParagraph(getParagraph(2), uno::UNO_QUERY
);
500 xParagraph
->dispose();
502 CPPUNIT_ASSERT_EQUAL(nSingleParaPageHeight
,
503 parseDump("/root/page[1]/infos/bounds", "height").toInt32());
506 void SwUiWriterTest4::testTdf96479()
508 // We want to verify the empty input text field in the bookmark
509 static const OUString emptyInputTextField
510 = OUStringChar(CH_TXT_ATR_INPUTFIELDSTART
) + OUStringChar(CH_TXT_ATR_INPUTFIELDEND
);
512 SwDoc
* pDoc
= createSwDoc();
514 // So we can clean up all references for reload
517 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
519 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
520 sw::mark::IMark
* pMark
= rIDMA
.makeMark(
521 aPaM
, "original", IDocumentMarkAccess::MarkType::BOOKMARK
, ::sw::mark::InsertMode::New
);
522 CPPUNIT_ASSERT(!pMark
->IsExpanded());
523 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
525 // Get helper objects
526 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
527 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
529 // Create cursor from bookmark
530 uno::Reference
<text::XTextContent
> xTextContent(
531 xBookmarksSupplier
->getBookmarks()->getByName("original"), uno::UNO_QUERY
);
532 uno::Reference
<text::XTextRange
> xRange
= xTextContent
->getAnchor();
533 uno::Reference
<text::XTextCursor
> xCursor
534 = xRange
->getText()->createTextCursorByRange(xRange
);
535 CPPUNIT_ASSERT(xCursor
->isCollapsed());
538 xRange
->getText()->removeTextContent(xTextContent
);
539 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA
.getBookmarksCount());
541 // Insert replacement bookmark
542 uno::Reference
<text::XTextContent
> xBookmarkNew(
543 xFactory
->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY
);
544 uno::Reference
<container::XNamed
> xBookmarkName(xBookmarkNew
, uno::UNO_QUERY
);
545 xBookmarkName
->setName("replacement");
546 CPPUNIT_ASSERT(xCursor
->isCollapsed());
547 // Force bookmark expansion
548 xCursor
->getText()->insertString(xCursor
, ".", true);
549 xCursor
->getText()->insertTextContent(xCursor
, xBookmarkNew
, true);
550 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
551 auto mark
= *(rIDMA
.getBookmarksBegin());
552 CPPUNIT_ASSERT(mark
->IsExpanded());
554 // Create and insert input textfield with some content
555 uno::Reference
<text::XTextField
> xTextField(
556 xFactory
->createInstance("com.sun.star.text.TextField.Input"), uno::UNO_QUERY
);
557 uno::Reference
<text::XTextCursor
> xCursorNew(
558 xBookmarkNew
->getAnchor()->getText()->createTextCursorByRange(
559 xBookmarkNew
->getAnchor()));
560 CPPUNIT_ASSERT(!xCursorNew
->isCollapsed());
561 xCursorNew
->getText()->insertTextContent(xCursorNew
, xTextField
, true);
562 xBookmarkNew
= uno::Reference
<text::XTextContent
>(
563 xBookmarksSupplier
->getBookmarks()->getByName("replacement"), uno::UNO_QUERY
);
564 xCursorNew
= xBookmarkNew
->getAnchor()->getText()->createTextCursorByRange(
565 xBookmarkNew
->getAnchor());
566 CPPUNIT_ASSERT(!xCursorNew
->isCollapsed());
568 // Can't check the actual content of the text node via UNO
569 mark
= *(rIDMA
.getBookmarksBegin());
570 CPPUNIT_ASSERT(mark
->IsExpanded());
571 SwPaM
pam(mark
->GetMarkStart(), mark
->GetMarkEnd());
572 // Check for the actual bug, which didn't include CH_TXT_ATR_INPUTFIELDEND in the bookmark
573 CPPUNIT_ASSERT_EQUAL(emptyInputTextField
, pam
.GetText());
577 // Save and load cycle
578 // Actually not needed, but the bug symptom of a missing bookmark
579 // occurred because a broken bookmark was saved and loading silently
580 // dropped the broken bookmark!
581 reload("writer8", "testTdf96479.odt");
582 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
583 CPPUNIT_ASSERT(pTextDoc
);
584 pDoc
= pTextDoc
->GetDocShell()->GetDoc();
586 // Lookup "replacement" bookmark
587 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
588 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
589 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
590 CPPUNIT_ASSERT(xBookmarksSupplier
->getBookmarks()->hasByName("replacement"));
592 uno::Reference
<text::XTextContent
> xTextContent(
593 xBookmarksSupplier
->getBookmarks()->getByName("replacement"), uno::UNO_QUERY
);
594 uno::Reference
<text::XTextRange
> xRange
= xTextContent
->getAnchor();
595 uno::Reference
<text::XTextCursor
> xCursor
596 = xRange
->getText()->createTextCursorByRange(xRange
);
597 CPPUNIT_ASSERT(!xCursor
->isCollapsed());
599 // Verify bookmark content via text node / PaM
600 auto mark
= *(rIDMA
.getBookmarksBegin());
601 CPPUNIT_ASSERT(mark
->IsExpanded());
602 SwPaM
pam(mark
->GetMarkStart(), mark
->GetMarkEnd());
603 CPPUNIT_ASSERT_EQUAL(emptyInputTextField
, pam
.GetText());
607 // If you resave original document the bookmark will be changed from
609 // <text:p text:style-name="Standard">
610 // <text:bookmark-start text:name="test"/>
611 // <text:bookmark-end text:name="test"/>
617 // <text:p text:style-name="Standard">
618 // <text:bookmark text:name="test"/>
622 void SwUiWriterTest4::testBookmarkCollapsed()
625 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "collapsed_bookmark.odt");
626 CPPUNIT_ASSERT(pDoc
);
628 // save original document
629 utl::TempFile aTempFile
;
630 save("writer8", aTempFile
);
632 // load only content.xml from the resaved document
633 if (xmlDocUniquePtr pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml"))
635 const OString
aPath("/office:document-content/office:body/office:text/text:p");
637 const int pos1
= getXPathPosition(pXmlDoc
, aPath
, "bookmark");
638 CPPUNIT_ASSERT_EQUAL(0, pos1
); // found, and it is first
640 CPPUNIT_ASSERT_ASSERTION_FAIL(
641 getXPathPosition(pXmlDoc
, aPath
, "bookmark-start")); // not found
642 CPPUNIT_ASSERT_ASSERTION_FAIL(
643 getXPathPosition(pXmlDoc
, aPath
, "bookmark-end")); // not found
647 // 1. Open a new writer document
648 // 2. Enter the text "abcdef"
650 // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
651 // 5. Open the navigator (F5)
652 // Select the bookmark "test" using the navigator.
653 // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
654 // 7. Save the document:
655 // <text:p text:style-name="Standard">
656 // <text:bookmark-start text:name="test"/>
657 // <text:bookmark-end text:name="test"/>
661 void SwUiWriterTest4::testRemoveBookmarkText()
665 // create a text document with "abcdef"
666 SwDoc
* pDoc
= createSwDoc();
669 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
671 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "abcdef");
674 // mark "abc" with "testBookmark" bookmark
676 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
679 lcl_selectCharacters(aPaM
, 0, 3);
680 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
681 sw::mark::IMark
* pMark
682 = rIDMA
.makeMark(aPaM
, "testBookmark", IDocumentMarkAccess::MarkType::BOOKMARK
,
683 ::sw::mark::InsertMode::New
);
686 CPPUNIT_ASSERT(pMark
->IsExpanded());
687 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
690 // remove text marked with bookmark
692 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
695 lcl_selectCharacters(aPaM
, 0, 3);
696 pDoc
->getIDocumentContentOperations().DeleteRange(aPaM
);
698 // verify: bookmark is still exist
699 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
700 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
705 utl::TempFile aTempFile
;
706 save("writer8", aTempFile
);
708 // load only content.xml from the resaved document
709 if (xmlDocUniquePtr pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml"))
711 const OString
aPath("/office:document-content/office:body/office:text/text:p");
713 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc
, aPath
, "bookmark")); // not found
714 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-start");
715 const int pos3
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-end");
717 CPPUNIT_ASSERT_EQUAL(0, pos2
); // found, and it is first
718 CPPUNIT_ASSERT_EQUAL(1, pos3
); // found, and it is second
722 // 1. Open a new writer document
723 // 2. Enter the text "abcdef"
725 // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
726 // 5. Open the navigator (F5)
727 // Select the bookmark "test" using the navigator.
728 // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
732 // bookmark = ThisComponent.getBookmarks().getByName("test")
733 // bookmark.getAnchor().setString("abc")
736 // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
737 // 7. Save the document:
738 // <text:p text:style-name="Standard">
739 // <text:bookmark-start text:name="test"/>
741 // <text:bookmark-end text:name="test"/>
745 void SwUiWriterTest4::testRemoveBookmarkTextAndAddNew()
749 // create a text document with "abcdef"
750 SwDoc
* pDoc
= createSwDoc();
752 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
754 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "abcdef");
757 // mark "abc" with "testBookmark" bookmark
759 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
762 lcl_selectCharacters(aPaM
, 0, 3);
763 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
764 sw::mark::IMark
* pMark
765 = rIDMA
.makeMark(aPaM
, "testBookmark", IDocumentMarkAccess::MarkType::BOOKMARK
,
766 ::sw::mark::InsertMode::New
);
769 CPPUNIT_ASSERT(pMark
->IsExpanded());
770 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
773 // remove text marked with bookmark
775 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
778 lcl_selectCharacters(aPaM
, 0, 3);
779 pDoc
->getIDocumentContentOperations().DeleteRange(aPaM
);
781 // verify: bookmark is still exist
782 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
783 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
786 // write "abc" to area marked with "testBookmark" bookmark
788 // Get helper objects
789 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
,
792 // Create cursor from bookmark
793 uno::Reference
<text::XTextContent
> xTextContent(
794 xBookmarksSupplier
->getBookmarks()->getByName("testBookmark"), uno::UNO_QUERY
);
795 uno::Reference
<text::XTextRange
> xRange
= xTextContent
->getAnchor();
796 CPPUNIT_ASSERT_EQUAL(OUString(""), xRange
->getString());
799 xRange
->setString("abc");
801 // verify: bookmark is still exist
802 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
803 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
808 utl::TempFile aTempFile
;
809 save("writer8", aTempFile
);
811 // load only content.xml from the resaved document
812 if (xmlDocUniquePtr pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml"))
814 const OString
aPath("/office:document-content/office:body/office:text/text:p");
816 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc
, aPath
, "bookmark")); // not found
817 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-start");
818 const int pos3
= getXPathPosition(pXmlDoc
, aPath
, "text");
819 const int pos4
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-end");
821 CPPUNIT_ASSERT_EQUAL(0, pos2
);
822 CPPUNIT_ASSERT_EQUAL(1, pos3
);
823 CPPUNIT_ASSERT_EQUAL(2, pos4
);
828 // <text:p text:style-name="Standard">
829 // <text:bookmark-start text:name="test"/>
830 // <text:bookmark-end text:name="test"/>
837 // bookmark = ThisComponent.getBookmarks().getByName("test")
838 // bookmark.getAnchor().setString("abc")
841 // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
842 // 3. Save the document:
843 // <text:p text:style-name="Standard">
844 // <text:bookmark text:name="test"/>
848 void SwUiWriterTest4::testRemoveBookmarkTextAndAddNewAfterReload()
851 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "collapsed_bookmark.odt");
852 CPPUNIT_ASSERT(pDoc
);
854 // write "abc" to area marked with "testBookmark" bookmark
856 // Get helper objects
857 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
859 // Create cursor from bookmark
860 uno::Reference
<text::XTextContent
> xTextContent(
861 xBookmarksSupplier
->getBookmarks()->getByName("test"), uno::UNO_QUERY
);
862 uno::Reference
<text::XTextRange
> xRange
= xTextContent
->getAnchor();
863 CPPUNIT_ASSERT_EQUAL(OUString(""), xRange
->getString());
866 xRange
->setString("abc");
868 // verify: bookmark is still exist
869 IDocumentMarkAccess
& rIDMA
= *pDoc
->getIDocumentMarkAccess();
870 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA
.getBookmarksCount());
873 // save original document
874 utl::TempFile aTempFile
;
875 save("writer8", aTempFile
);
877 // load only content.xml from the resaved document
878 if (xmlDocUniquePtr pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml"))
880 const OString
aPath("/office:document-content/office:body/office:text/text:p");
882 const int pos1
= getXPathPosition(pXmlDoc
, aPath
, "bookmark");
883 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "text");
885 CPPUNIT_ASSERT_EQUAL(0, pos1
);
886 CPPUNIT_ASSERT_EQUAL(1, pos2
);
888 CPPUNIT_ASSERT_ASSERTION_FAIL(
889 getXPathPosition(pXmlDoc
, aPath
, "bookmark-start")); // not found
890 CPPUNIT_ASSERT_ASSERTION_FAIL(
891 getXPathPosition(pXmlDoc
, aPath
, "bookmark-end")); // not found
895 void SwUiWriterTest4::testTdf96961()
897 // Insert a page break.
898 SwDoc
* pDoc
= createSwDoc();
899 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
900 pWrtShell
->InsertPageBreak();
902 // Enable hide whitespace mode.
903 SwViewOption
aViewOptions(*pWrtShell
->GetViewOptions());
904 aViewOptions
.SetHideWhitespaceMode(true);
905 pWrtShell
->ApplyViewOptions(aViewOptions
);
909 // Assert that the height of the last page is larger than the height of other pages.
910 sal_Int32 nOther
= parseDump("/root/page[1]/infos/bounds", "height").toInt32();
911 sal_Int32 nLast
= parseDump("/root/page[2]/infos/bounds", "height").toInt32();
912 CPPUNIT_ASSERT(nLast
> nOther
);
915 void SwUiWriterTest4::testTdf88453()
917 createSwDoc(DATA_DIRECTORY
, "tdf88453.odt");
919 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
920 // This was 0: the table does not fit the first page, but it wasn't split
921 // to continue on the second page.
922 assertXPath(pXmlDoc
, "/root/page[2]/body/tab", 1);
925 void SwUiWriterTest4::testTdf88453Table()
927 createSwDoc(DATA_DIRECTORY
, "tdf88453-table.odt");
929 // This was 2: layout could not split the large outer table in the document
931 CPPUNIT_ASSERT_EQUAL(3, getPages());
936 int checkShells(const SwDocShell
* pSource
, const SwDocShell
* pDestination
)
938 return int(SfxClassificationHelper::CheckPaste(pSource
->getDocProperties(),
939 pDestination
->getDocProperties()));
943 void SwUiWriterTest4::testClassificationPaste()
945 SwDocShell
* pSourceShell
= createSwDoc()->GetDocShell();
946 uno::Reference
<lang::XComponent
> xSourceComponent
= mxComponent
;
949 SwDocShell
* pDestinationShell
= createSwDoc()->GetDocShell();
951 // Not classified source, not classified destination.
952 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None
),
953 checkShells(pSourceShell
, pDestinationShell
));
955 // Classified source, not classified destination.
956 uno::Sequence
<beans::PropertyValue
> aInternalOnly
957 = comphelper::InitPropertySequence({ { "Name", uno::makeAny(OUString("Internal Only")) } });
958 dispatchCommand(xSourceComponent
, ".uno:ClassificationApply", aInternalOnly
);
959 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::TargetDocNotClassified
),
960 checkShells(pSourceShell
, pDestinationShell
));
962 // Classified source and classified destination -- internal only has a higher level than confidential.
963 uno::Sequence
<beans::PropertyValue
> aConfidential
964 = comphelper::InitPropertySequence({ { "Name", uno::makeAny(OUString("Confidential")) } });
965 dispatchCommand(mxComponent
, ".uno:ClassificationApply", aConfidential
);
966 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow
),
967 checkShells(pSourceShell
, pDestinationShell
));
969 xSourceComponent
->dispose();
972 void SwUiWriterTest4::testSmallCaps()
974 // Create a document, add some characters and select them.
976 SwDoc
* pDoc
= createSwDoc();
977 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
978 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
979 pWrtShell
->Insert("text");
982 // Dispatch the command to make them formatted small capitals.
983 dispatchCommand(mxComponent
, ".uno:SmallCaps", {});
985 // This was css::style::CaseMap::NONE as the shell didn't handle the command.
986 CPPUNIT_ASSERT_EQUAL(css::style::CaseMap::SMALLCAPS
,
987 getProperty
<sal_Int16
>(getRun(getParagraph(1), 1), "CharCaseMap"));
990 void SwUiWriterTest4::testTdf98987()
992 createSwDoc(DATA_DIRECTORY
, "tdf98987.docx");
994 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
995 assertXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/SdrObject", "name",
997 sal_Int32 nRectangle1
998 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/bounds", "top")
1000 assertXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name",
1002 sal_Int32 nRectangle2
1003 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top")
1005 CPPUNIT_ASSERT_GREATER(nRectangle1
, nRectangle2
);
1007 assertXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/SdrObject", "name",
1009 sal_Int32 nRectangle3
1010 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/bounds", "top")
1012 // This failed: the 3rd rectangle had a smaller "top" value than the 2nd one, it even overlapped with the 1st one.
1013 CPPUNIT_ASSERT_GREATER(nRectangle2
, nRectangle3
);
1016 void SwUiWriterTest4::testTdf99004()
1018 createSwDoc(DATA_DIRECTORY
, "tdf99004.docx");
1020 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1021 sal_Int32 nTextbox1Top
1022 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/fly/infos/bounds", "top").toInt32();
1023 sal_Int32 nTextBox1Height
1024 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32();
1025 sal_Int32 nTextBox1Bottom
= nTextbox1Top
+ nTextBox1Height
;
1027 assertXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name",
1029 sal_Int32 nRectangle2Top
1030 = getXPath(pXmlDoc
, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top")
1032 // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
1033 CPPUNIT_ASSERT(nTextBox1Bottom
< nRectangle2Top
);
1036 void SwUiWriterTest4::testTdf84695()
1038 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf84695.odt");
1039 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1040 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1041 SdrObject
* pObject
= pPage
->GetObj(1);
1042 SwContact
* pTextBox
= static_cast<SwContact
*>(pObject
->GetUserCall());
1043 // First, make sure that pTextBox is a fly frame (textbox of a shape).
1044 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT
), pTextBox
->GetFormat()->Which());
1047 pWrtShell
->SelectObj(Point(), 0, pObject
);
1049 // Now Enter + a key should add some text.
1050 SwXTextDocument
* pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1051 CPPUNIT_ASSERT(pXTextDocument
);
1052 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
1053 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'a', 0);
1054 Scheduler::ProcessEventsToIdle();
1056 uno::Reference
<text::XTextRange
> xShape(getShape(1), uno::UNO_QUERY
);
1057 // This was empty, Enter did not start the fly frame edit mode.
1058 CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape
->getString());
1061 void SwUiWriterTest4::testTdf84695NormalChar()
1063 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf84695.odt");
1064 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1065 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1066 SdrObject
* pObject
= pPage
->GetObj(1);
1067 SwContact
* pTextBox
= static_cast<SwContact
*>(pObject
->GetUserCall());
1068 // First, make sure that pTextBox is a fly frame (textbox of a shape).
1069 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT
), pTextBox
->GetFormat()->Which());
1072 pWrtShell
->SelectObj(Point(), 0, pObject
);
1074 // Now pressing 'a' should add a character.
1075 SwXTextDocument
* pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1076 CPPUNIT_ASSERT(pXTextDocument
);
1077 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'a', 0);
1078 Scheduler::ProcessEventsToIdle();
1080 uno::Reference
<text::XTextRange
> xShape(getShape(1), uno::UNO_QUERY
);
1081 // This was empty, pressing a normal character did not start the fly frame edit mode.
1082 CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape
->getString());
1085 void SwUiWriterTest4::testTdf84695Tab()
1087 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf84695-tab.odt");
1088 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1089 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1090 SdrObject
* pObject
= pPage
->GetObj(0);
1091 SwContact
* pShape
= static_cast<SwContact
*>(pObject
->GetUserCall());
1092 // First, make sure that pShape is a draw shape.
1093 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_DRAWFRMFMT
), pShape
->GetFormat()->Which());
1096 pWrtShell
->SelectObj(Point(), 0, pObject
);
1098 // Now pressing 'tab' should jump to the other shape.
1099 SwXTextDocument
* pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
1100 CPPUNIT_ASSERT(pXTextDocument
);
1101 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_TAB
);
1102 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_TAB
);
1103 Scheduler::ProcessEventsToIdle();
1105 // And finally make sure the selection has changed.
1106 const SdrMarkList
& rMarkList
= pWrtShell
->GetDrawView()->GetMarkedObjectList();
1107 SwContact
* pOtherShape
1108 = static_cast<SwContact
*>(rMarkList
.GetMark(0)->GetMarkedSdrObj()->GetUserCall());
1109 // This failed, 'tab' didn't do anything -> the selected shape was the same.
1110 CPPUNIT_ASSERT(pOtherShape
!= pShape
);
1113 void SwUiWriterTest4::testTableStyleUndo()
1115 SwDoc
* pDoc
= createSwDoc();
1116 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1118 sal_Int32 nStyleCount
= pDoc
->GetTableStyles().size();
1119 SwTableAutoFormat
* pStyle
= pDoc
->MakeTableStyle("Test Style");
1120 SvxBrushItem
aBackground(Color(0xFF00FF), RES_BACKGROUND
);
1121 pStyle
->GetBoxFormat(0).SetBackground(aBackground
);
1123 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
+ 1);
1124 rUndoManager
.Undo();
1125 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
);
1126 rUndoManager
.Redo();
1127 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
+ 1);
1128 // check if attributes are preserved
1129 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1130 CPPUNIT_ASSERT(pStyle
);
1131 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground
));
1133 pDoc
->DelTableStyle("Test Style");
1134 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
);
1135 rUndoManager
.Undo();
1136 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
+ 1);
1137 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1138 // check if attributes are preserved
1139 CPPUNIT_ASSERT(pStyle
);
1140 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground
));
1141 rUndoManager
.Redo();
1142 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
);
1144 // undo delete so we can replace the style
1145 rUndoManager
.Undo();
1146 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc
->GetTableStyles().size()), nStyleCount
+ 1);
1147 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1148 CPPUNIT_ASSERT(pStyle
);
1149 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground
));
1151 SwTableAutoFormat
aNewStyle("Test Style2");
1152 SvxBrushItem
aBackground2(Color(0x00FF00), RES_BACKGROUND
);
1153 aNewStyle
.GetBoxFormat(0).SetBackground(aBackground2
);
1155 pDoc
->ChgTableStyle("Test Style", aNewStyle
);
1156 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1157 CPPUNIT_ASSERT(pStyle
);
1158 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground2
));
1159 rUndoManager
.Undo();
1160 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1161 CPPUNIT_ASSERT(pStyle
);
1162 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground
));
1163 rUndoManager
.Redo();
1164 pStyle
= pDoc
->GetTableStyles().FindAutoFormat(u
"Test Style");
1165 CPPUNIT_ASSERT(pStyle
);
1166 CPPUNIT_ASSERT(bool(pStyle
->GetBoxFormat(0).GetBackground() == aBackground2
));
1169 void SwUiWriterTest4::testRedlineCopyPaste()
1171 // regressed in tdf#106746
1172 SwDoc
* pDoc
= createSwDoc();
1174 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
1177 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "abzdezgh");
1178 SwTextNode
* pTextNode
= aPaM
.GetNode().GetTextNode();
1180 // Turn on track changes, make changes, turn off track changes
1181 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1182 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1183 lcl_selectCharacters(aPaM
, 2, 3);
1184 pDoc
->getIDocumentContentOperations().ReplaceRange(aPaM
, "c", false);
1185 lcl_selectCharacters(aPaM
, 6, 7);
1186 pDoc
->getIDocumentContentOperations().ReplaceRange(aPaM
, "f", false);
1187 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(false));
1189 // Create the clipboard document.
1191 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1193 // Select the whole content, copy, delete the original and paste the copied content
1194 pWrtShell
->SelAll();
1195 pWrtShell
->Copy(aClipboard
);
1196 pWrtShell
->Delete();
1197 pWrtShell
->Paste(aClipboard
);
1199 // With the bug this is "abzcdefgh", ie. contains the first deleted piece, too
1200 CPPUNIT_ASSERT_EQUAL(OUString("abcdefgh"), pTextNode
->GetText());
1203 void SwUiWriterTest4::testTdf135260()
1205 SwDoc
* pDoc
= createSwDoc();
1206 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1207 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
1208 pWrtShell
->Insert("test");
1210 // Turn on track changes
1211 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1212 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1214 for (int i
= 0; i
< 4; i
++)
1216 pWrtShell
->DelLeft();
1219 SwEditShell
* const pEditShell(pDoc
->GetEditShell());
1220 // accept all redlines
1221 while (pEditShell
->GetRedlineCount())
1222 pEditShell
->AcceptRedline(0);
1224 // Without the fix in place, this test would have failed with
1227 CPPUNIT_ASSERT_EQUAL(OUString(""), getParagraph(1)->getString());
1230 void SwUiWriterTest4::testRedlineParam()
1232 // Create a document with minimal content.
1233 SwDoc
* pDoc
= createSwDoc();
1234 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1235 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
1236 pWrtShell
->Insert("middle");
1238 // Turn on track changes, and add changes to the start and end of the document.
1239 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1240 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1241 pWrtShell
->StartOfSection();
1242 pWrtShell
->Insert("aaa");
1243 pWrtShell
->EndOfSection();
1244 pWrtShell
->Insert("zzz");
1246 const SwRedlineTable
& rTable
= pDoc
->getIDocumentRedlineAccess().GetRedlineTable();
1247 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(2), rTable
.size());
1249 // Select the first redline.
1250 pWrtShell
->StartOfSection();
1251 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
1252 { { "NextTrackedChange",
1253 uno::makeAny(o3tl::narrowing
<sal_uInt16
>(rTable
[0]->GetId())) } }));
1254 dispatchCommand(mxComponent
, ".uno:NextTrackedChange", aPropertyValues
);
1255 Scheduler::ProcessEventsToIdle();
1256 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
1257 // This failed: the parameter wasn't handled so the next change (zzz) was
1258 // selected, not the first one (aaa).
1259 CPPUNIT_ASSERT_EQUAL(OUString("aaa"), pShellCursor
->GetText());
1261 // Select the second redline.
1262 pWrtShell
->StartOfSection();
1263 aPropertyValues
= comphelper::InitPropertySequence(
1264 { { "NextTrackedChange", uno::makeAny(o3tl::narrowing
<sal_uInt16
>(rTable
[1]->GetId())) } });
1265 dispatchCommand(mxComponent
, ".uno:NextTrackedChange", aPropertyValues
);
1266 Scheduler::ProcessEventsToIdle();
1267 pShellCursor
= pWrtShell
->getShellCursor(false);
1268 CPPUNIT_ASSERT_EQUAL(OUString("zzz"), pShellCursor
->GetText());
1270 // Move the cursor to the start again, and reject the second change.
1271 pWrtShell
->StartOfSection();
1272 aPropertyValues
= comphelper::InitPropertySequence(
1273 { { "RejectTrackedChange",
1274 uno::makeAny(o3tl::narrowing
<sal_uInt16
>(rTable
[1]->GetId())) } });
1275 dispatchCommand(mxComponent
, ".uno:RejectTrackedChange", aPropertyValues
);
1276 Scheduler::ProcessEventsToIdle();
1277 pShellCursor
= pWrtShell
->getShellCursor(false);
1279 // This was 'middlezzz', the uno command rejected the redline under the
1280 // cursor, instead of the requested one.
1281 CPPUNIT_ASSERT_EQUAL(OUString("aaamiddle"),
1282 pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1285 void SwUiWriterTest4::testRedlineViewAuthor()
1287 // Test that setting an author at an SwView level has effect.
1289 // Create a document with minimal content.
1290 SwDoc
* pDoc
= createSwDoc();
1291 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1292 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
1293 pWrtShell
->Insert("middle");
1294 SwView
* pView
= pDocShell
->GetView();
1295 const OUString
aAuthor("A U. Thor");
1296 pView
->SetRedlineAuthor(aAuthor
);
1297 pDocShell
->SetView(pView
);
1299 // Turn on track changes, and add changes to the start of the document.
1300 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1301 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1302 pWrtShell
->StartOfSection();
1303 pWrtShell
->Insert("aaa");
1305 // Now assert that SwView::SetRedlineAuthor() had an effect.
1306 const SwRedlineTable
& rTable
= pDoc
->getIDocumentRedlineAccess().GetRedlineTable();
1307 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(1), rTable
.size());
1308 SwRangeRedline
* pRedline
= rTable
[0];
1309 // This was 'Unknown Author' instead of 'A U. Thor'.
1310 CPPUNIT_ASSERT_EQUAL(aAuthor
, pRedline
->GetAuthorString());
1312 // Insert a comment and assert that SwView::SetRedlineAuthor() affects this as well.
1313 dispatchCommand(mxComponent
, ".uno:.uno:InsertAnnotation", {});
1314 uno::Reference
<text::XTextFieldsSupplier
> xTextFieldsSupplier(mxComponent
, uno::UNO_QUERY
);
1315 uno::Reference
<container::XEnumerationAccess
> xFieldsAccess(
1316 xTextFieldsSupplier
->getTextFields());
1317 uno::Reference
<container::XEnumeration
> xFields(xFieldsAccess
->createEnumeration());
1318 uno::Reference
<beans::XPropertySet
> xField(xFields
->nextElement(), uno::UNO_QUERY
);
1319 // This was 'Unknown Author' instead of 'A U. Thor'.
1320 CPPUNIT_ASSERT_EQUAL(aAuthor
, xField
->getPropertyValue("Author").get
<OUString
>());
1322 //Reset the redline author after using it, otherwise, it might interfere with other unittests
1323 pView
->SetRedlineAuthor("Unknown Author");
1324 pDocShell
->SetView(pView
);
1327 void SwUiWriterTest4::testTdf91292()
1329 createSwDoc(DATA_DIRECTORY
, "tdf91292_paraBackground.docx");
1330 uno::Reference
<beans::XPropertySet
> xPropertySet(getParagraph(1), uno::UNO_QUERY
);
1331 CPPUNIT_ASSERT_EQUAL_MESSAGE("Solid background color", drawing::FillStyle_SOLID
,
1332 getProperty
<drawing::FillStyle
>(xPropertySet
, "FillStyle"));
1333 CPPUNIT_ASSERT_EQUAL_MESSAGE("Background Color", static_cast<sal_Int32
>(0x5C2D91),
1334 getProperty
<sal_Int32
>(xPropertySet
, "FillColor"));
1336 // remove background color
1337 xPropertySet
->setPropertyValue("FillStyle", uno::makeAny(drawing::FillStyle_NONE
));
1339 // Save it and load it back.
1340 reload("Office Open XML Text", "tdf91292_paraBackground.docx");
1342 xPropertySet
.set(getParagraph(1), uno::UNO_QUERY
);
1343 CPPUNIT_ASSERT_EQUAL_MESSAGE("No background color", drawing::FillStyle_NONE
,
1344 getProperty
<drawing::FillStyle
>(xPropertySet
, "FillStyle"));
1347 void SwUiWriterTest4::testTdf78727()
1349 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf78727.docx");
1350 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1351 // This was 1: make sure we don't loose the TextBox anchored inside the
1352 // table that is moved inside a text frame.
1353 CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage
) > 1);
1356 void SwUiWriterTest4::testRedlineTimestamp()
1358 // Test that a redline timestamp's second is not always 0.
1360 // Create a document with minimal content.
1361 SwDoc
* pDoc
= createSwDoc();
1362 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1363 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
1364 pWrtShell
->Insert("middle");
1366 // Turn on track changes, and add changes to the start and to the end of
1368 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1369 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1370 pWrtShell
->StartOfSection();
1371 pWrtShell
->Insert("aaa");
1372 osl::Thread::wait(std::chrono::seconds(1));
1373 pWrtShell
->EndOfSection();
1374 pWrtShell
->Insert("zzz");
1376 // Inserting additional characters at the start changed the table size to
1377 // 3, i.e. the first and the second "aaa" wasn't combined.
1378 pWrtShell
->StartOfSection();
1379 pWrtShell
->Insert("aaa");
1381 // Now assert that at least one of the seconds are not 0.
1382 const SwRedlineTable
& rTable
= pDoc
->getIDocumentRedlineAccess().GetRedlineTable();
1383 if (rTable
.size() >= 2
1384 && rTable
[0]->GetRedlineData().GetTimeStamp().GetMin()
1385 != rTable
[1]->GetRedlineData().GetTimeStamp().GetMin())
1386 // The relatively rare case when waiting for a second also changes the minute.
1389 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(2), rTable
.size());
1390 sal_uInt16 nSec1
= rTable
[0]->GetRedlineData().GetTimeStamp().GetSec();
1391 sal_uInt16 nSec2
= rTable
[1]->GetRedlineData().GetTimeStamp().GetSec();
1392 // This failed, seconds was always 0.
1393 CPPUNIT_ASSERT(nSec1
!= 0 || nSec2
!= 0);
1396 void SwUiWriterTest4::testCursorWindows()
1398 // Create a new document with one window.
1399 SwDoc
* pDoc
= createSwDoc();
1400 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1401 SwWrtShell
* pWrtShell1
= pDocShell
->GetWrtShell();
1403 // Create a second view and type something.
1404 pDocShell
->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(
1405 SID_NEWWINDOW
, SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
);
1406 SwWrtShell
* pWrtShell2
= pDocShell
->GetWrtShell();
1407 OUString
aText("foo");
1408 pWrtShell2
->Insert(aText
);
1410 // Assert that only the cursor of the actual window move, not other cursors.
1411 SwShellCursor
* pShellCursor1
= pWrtShell1
->getShellCursor(false);
1412 SwShellCursor
* pShellCursor2
= pWrtShell2
->getShellCursor(false);
1413 // This was 3, not 0 -- cursor of the other window moved.
1414 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), pShellCursor1
->Start()->nContent
.GetIndex());
1415 CPPUNIT_ASSERT_EQUAL(aText
.getLength(), pShellCursor2
->Start()->nContent
.GetIndex());
1418 void SwUiWriterTest4::testLandscape()
1420 // Set page orientation to landscape.
1421 SwDoc
* pDoc
= createSwDoc();
1422 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
1423 comphelper::InitPropertySequence({ { "AttributePage.Landscape", uno::Any(true) } }));
1424 dispatchCommand(mxComponent
, ".uno:AttributePage", aPropertyValues
);
1425 Scheduler::ProcessEventsToIdle();
1427 // Assert that the document model was modified.
1428 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
1429 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
1430 size_t nPageDesc
= pWrtShell
->GetCurPageDesc();
1431 // This failed, page was still portrait.
1432 CPPUNIT_ASSERT(pWrtShell
->GetPageDesc(nPageDesc
).GetLandscape());
1435 void SwUiWriterTest4::testTdf95699()
1437 // Open the document with single FORMCHECKBOX field, select all and copy to clipboard
1438 // then check that clipboard contains the FORMCHECKBOX in text body.
1439 // Previously that failed.
1440 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf95699.odt");
1441 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1442 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess
->getAllMarksCount());
1444 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1445 pWrtShell
->SelAll();
1446 pWrtShell
->Copy(aClipboard
);
1447 pMarkAccess
= aClipboard
.getIDocumentMarkAccess();
1448 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess
->getAllMarksCount());
1449 ::sw::mark::IFieldmark
* pFieldMark
1450 = pMarkAccess
->getFieldmarkAfter(SwPosition(pDoc
->GetNodes().GetEndOfExtras()));
1451 CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"),
1452 pFieldMark
->GetFieldname());
1455 void SwUiWriterTest4::testTdf104032()
1457 // Open the document with FORMCHECKBOX field, select it and copy to clipboard
1458 // Go to end of document and paste it, then undo
1459 // Previously that asserted in debug build.
1460 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf104032.odt");
1461 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1463 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1464 pWrtShell
->StartOfSection();
1465 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1466 pWrtShell
->Copy(aClipboard
);
1467 pWrtShell
->EndOfSection();
1468 pWrtShell
->Paste(aClipboard
);
1469 rUndoManager
.Undo();
1472 void SwUiWriterTest4::testTdf104440()
1474 createSwDoc(DATA_DIRECTORY
, "tdf104440.odt");
1475 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1476 xmlXPathObjectPtr pXmlObj
= getXPathNode(pXmlDoc
, "//page[2]/body/txt/anchored");
1477 xmlNodeSetPtr pXmlNodes
= pXmlObj
->nodesetval
;
1478 // This was 0: both Text Frames in the document were anchored to a
1479 // paragraph on page 1, while we expect that the second Text Frame is
1480 // anchored to a paragraph on page 2.
1481 CPPUNIT_ASSERT_EQUAL(1, xmlXPathNodeSetGetLength(pXmlNodes
));
1482 xmlXPathFreeObject(pXmlObj
);
1485 void SwUiWriterTest4::testTdf104425()
1487 createSwDoc(DATA_DIRECTORY
, "tdf104425.odt");
1488 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1489 // The document contains one top-level 1-cell table with minimum row height set to 70 cm,
1490 // and the cell contents does not exceed the minimum row height.
1491 // It should span over 3 pages.
1492 assertXPath(pXmlDoc
, "//page", 3);
1494 = getXPath(pXmlDoc
, "//page[1]/body/tab/row/infos/bounds", "height").toInt32();
1496 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/infos/bounds", "height").toInt32();
1498 = getXPath(pXmlDoc
, "//page[3]/body/tab/row/infos/bounds", "height").toInt32();
1499 double fSumHeight_mm
= o3tl::convert
<double>(nHeight1
+ nHeight2
+ nHeight3
, o3tl::Length::twip
,
1501 CPPUNIT_ASSERT_DOUBLES_EQUAL(700.0, fSumHeight_mm
, 0.05);
1504 // accepting change tracking gets stuck on change
1505 void SwUiWriterTest4::testTdf104814()
1507 SwDoc
* const pDoc1(createSwDoc(DATA_DIRECTORY
, "tdf104814.docx"));
1509 SwEditShell
* const pEditShell(pDoc1
->GetEditShell());
1511 // accept all redlines
1512 while (pEditShell
->GetRedlineCount())
1513 pEditShell
->AcceptRedline(0);
1516 // crash at redo of accepting table change tracking imported from DOCX
1517 void SwUiWriterTest4::testTableRedlineRedoCrash()
1519 SwDoc
* const pDoc(createSwDoc(DATA_DIRECTORY
, "TC-table-del-add.docx"));
1520 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1522 // accept all redlines, Undo and accept all redlines again
1524 IDocumentRedlineAccess
& rIDRA(pDoc
->getIDocumentRedlineAccess());
1525 rIDRA
.AcceptAllRedline(/*bAccept=*/true);
1527 rUndoManager
.Undo();
1529 // without the fix, it crashes
1530 rIDRA
.AcceptAllRedline(true);
1533 void SwUiWriterTest4::testTableRemoveHasTextChangesOnly()
1535 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "TC-table-del-add.docx");
1536 CPPUNIT_ASSERT(pDoc
);
1537 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1538 CPPUNIT_ASSERT(pWrtShell
);
1540 // disable Record Changes
1541 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
1542 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1543 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1545 // 4 rows in Show Changes mode
1546 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1547 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1549 // Accepting tracked deletions results 3 rows
1550 IDocumentRedlineAccess
& rIDRA(pDoc
->getIDocumentRedlineAccess());
1551 rIDRA
.AcceptAllRedline(/*bAccept=*/true);
1552 Scheduler::ProcessEventsToIdle();
1553 discardDumpedLayout();
1554 pXmlDoc
= parseLayoutDump();
1555 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 3);
1557 // Undo: 4 rows again
1558 pDoc
->GetIDocumentUndoRedo().Undo();
1559 discardDumpedLayout();
1560 pXmlDoc
= parseLayoutDump();
1561 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1563 // Accepting again: 3 rows (Undo of HasTextChangesOnly is correct)
1564 rIDRA
.AcceptAllRedline(/*bAccept=*/true);
1565 Scheduler::ProcessEventsToIdle();
1566 discardDumpedLayout();
1567 pXmlDoc
= parseLayoutDump();
1568 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 3);
1570 // Undo: 4 rows again
1571 pDoc
->GetIDocumentUndoRedo().Undo();
1572 discardDumpedLayout();
1573 pXmlDoc
= parseLayoutDump();
1574 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1576 // Move the cursor after the redline, and insert some text without change tracking
1577 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1578 pWrtShell
->Insert("X");
1580 // Accepting again: 4 rows (extra text keeps the deleted row)
1581 rIDRA
.AcceptAllRedline(/*bAccept=*/true);
1582 Scheduler::ProcessEventsToIdle();
1583 discardDumpedLayout();
1584 pXmlDoc
= parseLayoutDump();
1585 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1587 // delete the extra text with change tracking:
1588 // this resulted tracked row deletion again, because of missing
1589 // removing of HasTextChangeOnly SwTabLine property at accepting deletions previously
1591 // disable Record Changes
1592 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
1593 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1594 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1596 dispatchCommand(mxComponent
, ".uno:SwBackSpace", {});
1597 rIDRA
.AcceptAllRedline(/*bAccept=*/true);
1598 Scheduler::ProcessEventsToIdle();
1599 discardDumpedLayout();
1600 pXmlDoc
= parseLayoutDump();
1602 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1605 void SwUiWriterTest4::testTableRemoveHasTextChangesOnly2()
1607 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "TC-table-del-add.docx");
1608 CPPUNIT_ASSERT(pDoc
);
1609 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1610 CPPUNIT_ASSERT(pWrtShell
);
1612 // disable Record Changes
1613 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
1614 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1615 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1617 // check redline count
1618 SwEditShell
* const pEditShell(pDoc
->GetEditShell());
1619 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1621 // 4 rows in Show Changes mode
1622 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1623 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1625 // Move the cursor to the tracked insertion, after the first redline to activate the
1626 // acception of the whole table row insertion with a single "Accept Change"
1627 pWrtShell
->Down(/*bSelect=*/false);
1628 pWrtShell
->Down(/*bSelect=*/false);
1629 pWrtShell
->Down(/*bSelect=*/false);
1630 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1631 Scheduler::ProcessEventsToIdle();
1632 dispatchCommand(mxComponent
, ".uno:AcceptTrackedChange", {});
1633 Scheduler::ProcessEventsToIdle();
1634 discardDumpedLayout();
1635 pXmlDoc
= parseLayoutDump();
1636 // Accepting tracked insertion results still 4 rows, but less redlines
1637 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1638 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(11), pEditShell
->GetRedlineCount());
1640 // Undo: 4 rows again
1641 pDoc
->GetIDocumentUndoRedo().Undo();
1642 discardDumpedLayout();
1643 pXmlDoc
= parseLayoutDump();
1644 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1645 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1647 // To check Undo of HasTextChangesOnly reject the same row results 3 rows
1648 dispatchCommand(mxComponent
, ".uno:Escape", {});
1649 dispatchCommand(mxComponent
, ".uno:RejectTrackedChange", {});
1650 Scheduler::ProcessEventsToIdle();
1651 discardDumpedLayout();
1652 pXmlDoc
= parseLayoutDump();
1653 // This was 4 (lost HasTextChangesOnly)
1654 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 3);
1656 // Undo: 4 rows again
1657 pDoc
->GetIDocumentUndoRedo().Undo();
1658 discardDumpedLayout();
1659 pXmlDoc
= parseLayoutDump();
1660 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1661 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1664 void SwUiWriterTest4::testTdf147182_AcceptAllChangesInTableSelection()
1666 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "TC-table-del-add.docx");
1667 CPPUNIT_ASSERT(pDoc
);
1668 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1669 CPPUNIT_ASSERT(pWrtShell
);
1671 // check redline count
1672 SwEditShell
* const pEditShell(pDoc
->GetEditShell());
1673 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1675 // 4 rows in Show Changes mode
1676 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1677 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1679 // Select the first table to get a table selection
1680 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
1681 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
1682 dispatchCommand(mxComponent
, ".uno:AcceptTrackedChange", {});
1683 Scheduler::ProcessEventsToIdle();
1684 discardDumpedLayout();
1685 pXmlDoc
= parseLayoutDump();
1686 // Accepting tracked changes in the selected table results 3 rows
1687 // This was 4 (only text changes of the first selected cell were accepted)
1688 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 3);
1689 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(8), pEditShell
->GetRedlineCount());
1691 // Undo: 4 rows again
1692 pDoc
->GetIDocumentUndoRedo().Undo();
1693 discardDumpedLayout();
1694 pXmlDoc
= parseLayoutDump();
1695 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1696 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1698 // To check Undo of HasTextChangesOnly reject the same row results 3 rows
1699 dispatchCommand(mxComponent
, ".uno:Escape", {});
1700 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
1701 dispatchCommand(mxComponent
, ".uno:SelectAll", {});
1702 dispatchCommand(mxComponent
, ".uno:RejectTrackedChange", {});
1703 Scheduler::ProcessEventsToIdle();
1704 discardDumpedLayout();
1705 pXmlDoc
= parseLayoutDump();
1706 // This was 4 (only text changes of the first selected cell were rejected)
1707 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 3);
1709 // Undo: 4 rows again
1710 pDoc
->GetIDocumentUndoRedo().Undo();
1711 discardDumpedLayout();
1712 pXmlDoc
= parseLayoutDump();
1713 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row", 4);
1714 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(14), pEditShell
->GetRedlineCount());
1717 void SwUiWriterTest4::testTdf66405()
1719 // Imported formula should have zero margins
1720 createSwDoc(DATA_DIRECTORY
, "tdf66405.docx");
1721 uno::Reference
<text::XTextEmbeddedObjectsSupplier
> xEmbeddedObjectsSupplier(mxComponent
,
1723 uno::Reference
<container::XNameAccess
> xEmbeddedObjects
1724 = xEmbeddedObjectsSupplier
->getEmbeddedObjects();
1725 uno::Reference
<beans::XPropertySet
> xFormula
;
1726 xEmbeddedObjects
->getByName(xEmbeddedObjects
->getElementNames()[0]) >>= xFormula
;
1727 uno::Reference
<beans::XPropertySet
> xComponent
;
1728 xFormula
->getPropertyValue("Component") >>= xComponent
;
1730 // Test embedded object's margins
1731 sal_Int32 nLeftMargin
, nRightMargin
, nTopMargin
, nBottomMargin
;
1732 xFormula
->getPropertyValue("LeftMargin") >>= nLeftMargin
;
1733 xFormula
->getPropertyValue("RightMargin") >>= nRightMargin
;
1734 xFormula
->getPropertyValue("TopMargin") >>= nTopMargin
;
1735 xFormula
->getPropertyValue("BottomMargin") >>= nBottomMargin
;
1736 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin
);
1737 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin
);
1738 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin
);
1739 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin
);
1741 // Test embedded object component's margins
1742 xComponent
->getPropertyValue("LeftMargin") >>= nLeftMargin
;
1743 xComponent
->getPropertyValue("RightMargin") >>= nRightMargin
;
1744 xComponent
->getPropertyValue("TopMargin") >>= nTopMargin
;
1745 xComponent
->getPropertyValue("BottomMargin") >>= nBottomMargin
;
1746 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin
);
1747 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin
);
1748 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin
);
1749 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin
);
1752 void SwUiWriterTest4::testTdf35021_tabOverMarginDemo()
1755 createSwDoc(DATA_DIRECTORY
, "tdf35021_tabOverMarginDemo.doc");
1757 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1758 // Tabs should go past the margin @ ~3381
1759 sal_Int32 nMargin
= getXPath(pXmlDoc
, "//body/txt[1]/infos/prtBounds", "width").toInt32();
1760 // left tab was 3381 because it got its own full line
1762 = getXPath(pXmlDoc
, "//SwLinePortion[@type='PortionType::TabLeft']", "width").toInt32();
1763 CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~4479", nMargin
< nWidth
);
1764 // center tab was 842
1766 = getXPath(pXmlDoc
, "//SwLinePortion[@type='PortionType::TabCenter']", "width").toInt32();
1767 CPPUNIT_ASSERT_MESSAGE("Center Tab width is ~3521", nMargin
< nWidth
);
1768 // right tab was probably the same as center tab.
1769 nWidth
= getXPath(pXmlDoc
, "//SwLinePortion[@type='PortionType::TabRight']", "width").toInt32();
1770 CPPUNIT_ASSERT_MESSAGE("Right Tab width is ~2907", sal_Int32(2500) < nWidth
);
1771 // decimal tab was 266
1773 = getXPath(pXmlDoc
, "//SwLinePortion[@type='PortionType::TabDecimal']", "width").toInt32();
1774 CPPUNIT_ASSERT_MESSAGE("Decimal Tab width is ~4096", nMargin
< nWidth
);
1778 void SwUiWriterTest4::testTdf106701_tabOverMarginAutotab()
1780 createSwDoc(DATA_DIRECTORY
, "tdf106701_tabOverMarginAutotab.doc");
1782 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1783 // The right margin is ~3378
1784 sal_Int32 nRightMargin
= getXPath(pXmlDoc
, "//body/txt[1]/infos/prtBounds", "width").toInt32();
1785 // Automatic tabstops should never be affected by tabOverMargin compatibility
1786 // The 1st line's width previously was ~9506
1787 sal_Int32 nWidth
= getXPath(pXmlDoc
, "//LineBreak[1]", "nWidth").toInt32();
1788 CPPUNIT_ASSERT_MESSAGE("1st line's width is less than the right margin", nWidth
< nRightMargin
);
1791 void SwUiWriterTest4::testTdf104492()
1793 createSwDoc(DATA_DIRECTORY
, "tdf104492.docx");
1794 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1795 // The document should split table over 3 pages.
1796 assertXPath(pXmlDoc
, "//page", 3);
1799 void SwUiWriterTest4::testTdf107025()
1801 // Tdf107025 - characters advance with wrong distance, so that
1802 // they are cluttered because of negative value or
1803 // break into multiple lines because of overflow.
1804 // The test document uses DFKAI-SB shipped with Windows.
1805 createSwDoc(DATA_DIRECTORY
, "tdf107025.odt");
1806 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1807 // Verify the number of characters in each line.
1808 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1809 getXPath(pXmlDoc
, "(//SwLinePortion)[1]", "length").toInt32());
1810 CPPUNIT_ASSERT_EQUAL(sal_Int32(9),
1811 getXPath(pXmlDoc
, "(//SwLinePortion)[2]", "length").toInt32());
1813 // Do the subsequent test only if the first line can be displayed,
1814 // in case that the required font does not exist.
1815 sal_Int32 nWidth1
= getXPath(pXmlDoc
, "(//SwLinePortion)[1]", "width").toInt32();
1819 CPPUNIT_ASSERT(!parseDump("(//SwLinePortion)[2]", "width").isEmpty());
1820 // Width of the second line is expected to be 9 times of the first.
1821 sal_Int32 nWidth2
= getXPath(pXmlDoc
, "(//SwLinePortion)[2]", "width").toInt32();
1823 CPPUNIT_ASSERT_EQUAL(sal_Int32(9), nWidth2
/ nWidth1
);
1826 void SwUiWriterTest4::testTdf107362()
1828 createSwDoc(DATA_DIRECTORY
, "tdf107362.odt");
1829 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1831 = getXPath(pXmlDoc
, "(//Text[@nType='PortionType::Text'])[1]", "nHeight").toInt32();
1833 = getXPath(pXmlDoc
, "(//Text[@nType='PortionType::Text'])[1]", "nWidth").toInt32();
1835 = getXPath(pXmlDoc
, "(//Text[@nType='PortionType::Text'])[2]", "nWidth").toInt32();
1836 sal_Int32 nLineWidth
= getXPath(pXmlDoc
, "//LineBreak", "nWidth").toInt32();
1837 sal_Int32 nKernWidth
= nLineWidth
- nWidth1
- nWidth2
;
1838 // Test only if fonts are available
1839 if (nWidth1
> 500 && nWidth2
> 200)
1841 // Kern width should be smaller than 1/3 of the CJK font height.
1842 CPPUNIT_ASSERT(nKernWidth
* 3 < nHeight
);
1846 void SwUiWriterTest4::testTdf105417()
1848 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf105417.odt");
1849 CPPUNIT_ASSERT(pDoc
);
1850 SwView
* pView
= pDoc
->GetDocShell()->GetView();
1851 CPPUNIT_ASSERT(pView
);
1852 uno::Reference
<linguistic2::XHyphenator
> xHyphenator
= LinguMgr::GetHyphenator();
1853 CPPUNIT_ASSERT(xHyphenator
.is());
1854 // If there are no English hyphenation rules installed, we can't test
1856 if (!xHyphenator
->hasLocale(lang::Locale("en", "US", OUString())))
1859 uno::Reference
<linguistic2::XLinguProperties
> xLinguProperties(LinguMgr::GetLinguPropertySet());
1860 // Automatic hyphenation means not opening a dialog, but going ahead
1861 // non-interactively.
1862 xLinguProperties
->setIsHyphAuto(true);
1863 SwHyphWrapper
aWrap(pView
, xHyphenator
, /*bStart=*/false, /*bOther=*/true,
1864 /*bSelection=*/false);
1865 // This never returned, it kept trying to hyphenate the last word
1866 // (greenbacks) again and again.
1867 aWrap
.SpellDocument();
1870 void SwUiWriterTest4::testTdf105625()
1872 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf105625.fodt");
1873 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1874 uno::Reference
<uno::XComponentContext
> xComponentContext(
1875 comphelper::getProcessComponentContext());
1876 // Ensure correct initial setting
1877 comphelper::ConfigurationHelper::writeDirectKey(
1878 xComponentContext
, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
1879 css::uno::Any(false), comphelper::EConfigurationModes::Standard
);
1880 // We should be able to edit at positions adjacent to fields.
1881 // Check if the start and the end of the 1st paragraph are not protected
1882 // (they are adjacent to FORMCHECKBOX)
1883 pWrtShell
->SttPara();
1884 CPPUNIT_ASSERT_EQUAL(false, pWrtShell
->HasReadonlySel());
1885 pWrtShell
->EndPara();
1886 CPPUNIT_ASSERT_EQUAL(false, pWrtShell
->HasReadonlySel());
1887 // 2nd paragraph - FORMTEXT
1888 pWrtShell
->Down(/*bSelect=*/false);
1889 // Check selection across FORMTEXT field boundary - must be read-only
1890 pWrtShell
->SttPara();
1891 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1892 CPPUNIT_ASSERT_EQUAL(true, pWrtShell
->HasReadonlySel());
1893 // Test deletion of whole field with single backspace
1894 // Previously it only removed right boundary of FORMTEXT, or failed removal at all
1895 const IDocumentMarkAccess
* pMarksAccess
= pDoc
->getIDocumentMarkAccess();
1896 sal_Int32 nMarksBefore
= pMarksAccess
->getAllMarksCount();
1897 pWrtShell
->EndPara();
1898 pWrtShell
->DelLeft();
1899 sal_Int32 nMarksAfter
= pMarksAccess
->getAllMarksCount();
1900 CPPUNIT_ASSERT_EQUAL(nMarksBefore
, nMarksAfter
+ 1);
1903 void SwUiWriterTest4::testTdf125151_protected()
1905 // Similar to testTdf105625 except this is in a protected section,
1906 // so read-only is already true when fieldmarks are considered.
1907 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf125151_protected.fodt");
1908 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1909 uno::Reference
<uno::XComponentContext
> xComponentContext(
1910 comphelper::getProcessComponentContext());
1911 // Ensure correct initial setting
1912 comphelper::ConfigurationHelper::writeDirectKey(
1913 xComponentContext
, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
1914 css::uno::Any(false), comphelper::EConfigurationModes::Standard
);
1915 pWrtShell
->Down(/*bSelect=*/false);
1916 // The cursor moved inside of the FieldMark textbox.
1917 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell
->HasReadonlySel());
1918 // Move left to the start/definition of the textbox
1919 pWrtShell
->Left(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1920 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell
->HasReadonlySel());
1923 void SwUiWriterTest4::testTdf125151_protectedB()
1925 // Similar to testTdf105625 except this is protected with the Protect_Form compat setting
1926 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf125151_protectedB.fodt");
1927 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
1928 uno::Reference
<uno::XComponentContext
> xComponentContext(
1929 comphelper::getProcessComponentContext());
1930 // Ensure correct initial setting
1931 comphelper::ConfigurationHelper::writeDirectKey(
1932 xComponentContext
, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
1933 css::uno::Any(false), comphelper::EConfigurationModes::Standard
);
1934 // The cursor starts inside of the FieldMark textbox.
1935 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell
->HasReadonlySel());
1936 // Move left to the start/definition of the textbox
1937 pWrtShell
->Left(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1938 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell
->HasReadonlySel());
1941 void SwUiWriterTest4::testTdf106736()
1943 createSwDoc(DATA_DIRECTORY
, "tdf106736-grid.odt");
1944 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1946 = getXPath(pXmlDoc
, "(//Text[@nType='PortionType::TabLeft'])[1]", "nWidth").toInt32();
1947 // In tdf106736, width of tab overflow so that it got
1948 // width value around 9200, expected value is around 103
1949 CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~103", nWidth
< 150);
1952 void SwUiWriterTest4::testMsWordCompTrailingBlanks()
1954 // The option is true in settings.xml
1955 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "MsWordCompTrailingBlanksTrue.odt");
1956 CPPUNIT_ASSERT_EQUAL(true, pDoc
->getIDocumentSettingAccess().get(
1957 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
));
1959 // Check that trailing spaces spans have no width if option is enabled
1961 CPPUNIT_ASSERT_EQUAL(OUString(), parseDump("/root/page/body/txt[2]/Text[4]", "nWidth"));
1962 CPPUNIT_ASSERT_EQUAL(OUString(), parseDump("/root/page/body/txt[2]/Text[5]", "nWidth"));
1963 CPPUNIT_ASSERT_EQUAL(OUString(), parseDump("/root/page/body/txt[3]/Text[4]", "nWidth"));
1964 CPPUNIT_ASSERT_EQUAL(OUString(), parseDump("/root/page/body/txt[3]/Text[5]", "nWidth"));
1966 // The option is false in settings.xml
1967 pDoc
= createSwDoc(DATA_DIRECTORY
, "MsWordCompTrailingBlanksFalse.odt");
1968 CPPUNIT_ASSERT_EQUAL(false, pDoc
->getIDocumentSettingAccess().get(
1969 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
));
1971 // Check that trailing spaces spans have width if option is disabled
1972 CPPUNIT_ASSERT(!parseDump("/root/page/body/txt[2]/Text[4]", "nWidth").isEmpty());
1973 CPPUNIT_ASSERT(!parseDump("/root/page/body/txt[2]/Text[5]", "nWidth").isEmpty());
1974 CPPUNIT_ASSERT(!parseDump("/root/page/body/txt[3]/Text[4]", "nWidth").isEmpty());
1975 CPPUNIT_ASSERT(!parseDump("/root/page/body/txt[3]/Text[5]", "nWidth").isEmpty());
1977 // MsWordCompTrailingBlanks option should be false by default in new documents
1978 pDoc
= createSwDoc();
1979 CPPUNIT_ASSERT_EQUAL(false, pDoc
->getIDocumentSettingAccess().get(
1980 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
));
1982 // The option should be true if a .docx, .doc or .rtf document is opened
1983 pDoc
= createSwDoc(DATA_DIRECTORY
, "MsWordCompTrailingBlanks.docx");
1984 CPPUNIT_ASSERT_EQUAL(true, pDoc
->getIDocumentSettingAccess().get(
1985 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
));
1988 void SwUiWriterTest4::testCreateDocxAnnotation()
1992 // insert an annotation with a text
1993 const OUString
aSomeText("some text");
1994 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
1995 { "Text", uno::makeAny(aSomeText
) },
1996 { "Author", uno::makeAny(OUString("me")) },
1998 dispatchCommand(mxComponent
, ".uno:InsertAnnotation", aPropertyValues
);
2000 // Save it as DOCX & load it again
2001 reload("Office Open XML Text", "create-docx-annotation.docx");
2003 // get the annotation
2004 uno::Reference
<text::XTextFieldsSupplier
> xTextFieldsSupplier(mxComponent
, uno::UNO_QUERY
);
2005 uno::Reference
<container::XEnumerationAccess
> xFieldsAccess(
2006 xTextFieldsSupplier
->getTextFields());
2007 uno::Reference
<container::XEnumeration
> xFields(xFieldsAccess
->createEnumeration());
2008 uno::Reference
<beans::XPropertySet
> xField(xFields
->nextElement(), uno::UNO_QUERY
);
2010 // this was empty instead of "some text"
2011 CPPUNIT_ASSERT_EQUAL(aSomeText
, xField
->getPropertyValue("Content").get
<OUString
>());
2014 void SwUiWriterTest4::testTdf107976()
2016 // Create a document and create two transferables.
2017 SwDoc
* pDoc
= createSwDoc();
2018 SwWrtShell
& rShell
= *pDoc
->GetDocShell()->GetWrtShell();
2019 rtl::Reference
<SwTransferable
> pTransferable(new SwTransferable(rShell
));
2020 rtl::Reference
<SwTransferable
> pTransferable2(new SwTransferable(rShell
));
2021 // Now close the document.
2022 mxComponent
->dispose();
2023 mxComponent
.clear();
2024 // This failed: the first shell had a pointer to the deleted shell.
2025 CPPUNIT_ASSERT(!pTransferable
->GetShell());
2026 CPPUNIT_ASSERT(!pTransferable2
->GetShell());
2029 void SwUiWriterTest4::testTdf58604()
2032 // Allow linebreak character follows hanging punctuation immediately instead of
2033 // breaking at the start of the next line.
2034 createSwDoc(DATA_DIRECTORY
, "tdf58604.odt");
2035 CPPUNIT_ASSERT_EQUAL(
2036 OUString("PortionType::Break"),
2037 parseDump("(/root/page/body/txt/LineBreak[1]/preceding::Text)[last()]", "nType"));
2041 void SwUiWriterTest4::testTdf112025()
2043 createSwDoc(DATA_DIRECTORY
, "fdo112025.odt");
2044 const int numberOfParagraphs
= getParagraphs();
2045 CPPUNIT_ASSERT_EQUAL(1, numberOfParagraphs
);
2047 // get a page cursor
2048 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
2049 uno::Reference
<text::XTextViewCursorSupplier
> xTextViewCursorSupplier(
2050 xModel
->getCurrentController(), uno::UNO_QUERY
);
2051 uno::Reference
<text::XPageCursor
> xCursor(xTextViewCursorSupplier
->getViewCursor(),
2053 xCursor
->jumpToEndOfPage();
2055 OUString insertFileid
= m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "fdo112025-insert.docx";
2056 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
2057 comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid
) } }));
2058 dispatchCommand(mxComponent
, ".uno:InsertDoc", aPropertyValues
);
2059 // something has been inserted + an additional paragraph
2060 CPPUNIT_ASSERT_GREATER(numberOfParagraphs
, getParagraphs());
2062 uno::Reference
<beans::XPropertySet
> xStyle(getStyles("PageStyles")->getByName("Standard"),
2064 CPPUNIT_ASSERT_EQUAL(true, getProperty
<bool>(xStyle
, "IsLandscape"));
2067 void SwUiWriterTest4::testTdf72942()
2069 createSwDoc(DATA_DIRECTORY
, "fdo72942.docx");
2071 // get a page cursor
2072 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
2073 uno::Reference
<text::XTextViewCursorSupplier
> xTextViewCursorSupplier(
2074 xModel
->getCurrentController(), uno::UNO_QUERY
);
2075 uno::Reference
<text::XPageCursor
> xCursor(xTextViewCursorSupplier
->getViewCursor(),
2077 xCursor
->jumpToEndOfPage();
2079 OUString insertFileid
= m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "fdo72942-insert.docx";
2080 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
2081 comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid
) } }));
2082 dispatchCommand(mxComponent
, ".uno:InsertDoc", aPropertyValues
);
2084 // check styles of paragraphs added from [fdo72942.docx]
2085 const uno::Reference
<text::XTextRange
> xRun1
= getRun(getParagraph(1), 1);
2086 CPPUNIT_ASSERT_EQUAL(OUString("Default English (Liberation serif) text with "),
2087 xRun1
->getString());
2088 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"),
2089 getProperty
<OUString
>(xRun1
, "CharFontName"));
2091 const uno::Reference
<text::XTextRange
> xRun2
= getRun(getParagraph(2), 1);
2092 CPPUNIT_ASSERT_EQUAL(OUString("Header 1 English text (Liberation sans) with "),
2093 xRun2
->getString());
2094 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty
<OUString
>(xRun2
, "CharFontName"));
2096 // check styles of paragraphs added from [fdo72942-insert.docx]
2097 const uno::Reference
<text::XTextRange
> xRun3
= getRun(getParagraph(4), 1);
2098 CPPUNIT_ASSERT_EQUAL(OUString("Default German text (Calibri) with "), xRun3
->getString());
2099 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"),
2100 getProperty
<OUString
>(xRun3
, "CharFontName"));
2102 const uno::Reference
<text::XTextRange
> xRun4
= getRun(getParagraph(5), 1);
2103 CPPUNIT_ASSERT_EQUAL(OUString("Header 1 German text (Calibri Light) with "),
2104 xRun4
->getString());
2105 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty
<OUString
>(xRun4
, "CharFontName"));
2108 void SwUiWriterTest4::testTdf114306()
2110 createSwDoc(DATA_DIRECTORY
, "fdo114306.odt");
2111 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2113 // There are 2 long paragraphs in cell A1.
2114 // A part of paragraph 2 should flow over to the second page but
2115 // *not* the whole paragraph. There should be 2 paragraphs on
2116 // page 1 and 1 paragraph on page 2.
2117 assertXPath(pXmlDoc
, "/root/page[1]/body/tab[1]/row[1]/cell[1]/txt", 2);
2118 assertXPath(pXmlDoc
, "/root/page[2]/body/tab[1]/row[1]/cell[1]/txt", 1);
2121 void SwUiWriterTest4::testTdf114306_2()
2123 // tdf#114306 fix unexpected page break in row-spanned table
2124 // load regression document without writer crash
2125 createSwDoc(DATA_DIRECTORY
, "fdo114306_2.odt");
2127 // correct number of pages
2128 CPPUNIT_ASSERT_EQUAL(4, getPages());
2131 void SwUiWriterTest4::testTdf113877_mergeDocs(const char* aDestDoc
, const char* aInsertDoc
)
2133 createSwDoc(DATA_DIRECTORY
, aDestDoc
);
2135 // set a page cursor into the end of the document
2136 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
2137 uno::Reference
<text::XTextViewCursorSupplier
> xTextViewCursorSupplier(
2138 xModel
->getCurrentController(), uno::UNO_QUERY
);
2139 uno::Reference
<text::XPageCursor
> xCursor(xTextViewCursorSupplier
->getViewCursor(),
2141 xCursor
->jumpToEndOfPage();
2143 // insert the same document at current cursor position
2145 const OUString insertFileid
2146 = m_directories
.getURLFromSrc(DATA_DIRECTORY
) + OUString::createFromAscii(aInsertDoc
);
2147 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
2148 comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid
) } }));
2149 dispatchCommand(mxComponent
, ".uno:InsertDoc", aPropertyValues
);
2153 // During insert of the document with list inside into the main document inside the list
2154 // we should merge both lists into one, when they have the same list properties
2155 void SwUiWriterTest4::testTdf113877()
2157 testTdf113877_mergeDocs("tdf113877_insert_numbered_list.odt",
2158 "tdf113877_insert_numbered_list.odt");
2160 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2161 const OUString listId4
= getProperty
<OUString
>(getParagraph(4), "ListId");
2162 const OUString listId5
= getProperty
<OUString
>(getParagraph(5), "ListId");
2163 const OUString listId6
= getProperty
<OUString
>(getParagraph(6), "ListId");
2164 const OUString listId7
= getProperty
<OUString
>(getParagraph(7), "ListId");
2166 // the initial list with 4 list items
2167 CPPUNIT_ASSERT_EQUAL(listId1
, listId4
);
2169 // the last of the first list, and the first of the inserted list
2170 CPPUNIT_ASSERT_EQUAL(listId4
, listId5
);
2171 CPPUNIT_ASSERT_EQUAL(listId5
, listId6
);
2172 CPPUNIT_ASSERT_EQUAL(listId6
, listId7
);
2175 // The same test as testTdf113877() but merging of two list should not be performed.
2176 void SwUiWriterTest4::testTdf113877NoMerge()
2178 testTdf113877_mergeDocs("tdf113877_insert_numbered_list.odt",
2179 "tdf113877_insert_numbered_list_abcd.odt");
2181 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2182 const OUString listId4
= getProperty
<OUString
>(getParagraph(4), "ListId");
2183 const OUString listId5
= getProperty
<OUString
>(getParagraph(5), "ListId");
2184 const OUString listId6
= getProperty
<OUString
>(getParagraph(6), "ListId");
2185 const OUString listId7
= getProperty
<OUString
>(getParagraph(7), "ListId");
2187 // the initial list with 4 list items
2188 CPPUNIT_ASSERT_EQUAL(listId1
, listId4
);
2190 // the last of the first list, and the first of the inserted list
2191 CPPUNIT_ASSERT(listId4
!= listId5
);
2192 CPPUNIT_ASSERT_EQUAL(listId5
, listId6
);
2193 CPPUNIT_ASSERT(listId6
!= listId7
);
2196 // Related test to testTdf113877(): Inserting into empty document a new document with list.
2197 // Insert position has NO its own paragraph style ("Standard" will be used).
2199 // Resulting document should be the same for following tests:
2200 // - testTdf113877_default_style()
2201 // - testTdf113877_Standard_style()
2203 void SwUiWriterTest4::testTdf113877_default_style()
2205 testTdf113877_mergeDocs("tdf113877_blank.odt", "tdf113877_insert_numbered_list_abcd.odt");
2207 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2208 const OUString listId2
= getProperty
<OUString
>(getParagraph(2), "ListId");
2209 const OUString listId3
= getProperty
<OUString
>(getParagraph(3), "ListId");
2211 CPPUNIT_ASSERT_EQUAL(listId1
, listId2
);
2212 CPPUNIT_ASSERT_EQUAL(listId1
, listId3
);
2215 // Related test to testTdf113877(): Inserting into empty document a new document with list.
2216 // Insert position has its own paragraph style derived from "Standard", but this style is the same as "Standard".
2218 // Resulting document should be the same for following tests:
2219 // - testTdf113877_default_style()
2220 // - testTdf113877_Standard_style()
2222 void SwUiWriterTest4::testTdf113877_Standard_style()
2224 testTdf113877_mergeDocs("tdf113877_blank_ownStandard.odt",
2225 "tdf113877_insert_numbered_list_abcd.odt");
2227 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2228 const OUString listId2
= getProperty
<OUString
>(getParagraph(2), "ListId");
2229 const OUString listId3
= getProperty
<OUString
>(getParagraph(3), "ListId");
2231 CPPUNIT_ASSERT_EQUAL(listId1
, listId2
);
2232 CPPUNIT_ASSERT_EQUAL(listId1
, listId3
);
2235 void SwUiWriterTest4::testTdf113877_blank_bold_on()
2237 testTdf113877_mergeDocs("tdf113877_blank_bold_on.odt",
2238 "tdf113877_insert_numbered_list_abcd.odt");
2240 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2241 const OUString listId2
= getProperty
<OUString
>(getParagraph(2), "ListId");
2242 const OUString listId3
= getProperty
<OUString
>(getParagraph(3), "ListId");
2244 CPPUNIT_ASSERT_EQUAL(listId1
, listId2
);
2245 CPPUNIT_ASSERT_EQUAL(listId1
, listId3
);
2248 void SwUiWriterTest4::testTdf113877_blank_bold_off()
2250 testTdf113877_mergeDocs("tdf113877_blank_bold_off.odt",
2251 "tdf113877_insert_numbered_list_abcd.odt");
2253 const OUString listId1
= getProperty
<OUString
>(getParagraph(1), "ListId");
2254 const OUString listId2
= getProperty
<OUString
>(getParagraph(2), "ListId");
2255 const OUString listId3
= getProperty
<OUString
>(getParagraph(3), "ListId");
2257 CPPUNIT_ASSERT_EQUAL(listId1
, listId2
);
2258 CPPUNIT_ASSERT_EQUAL(listId1
, listId3
);
2261 // just care that this does crash/assert
2262 void SwUiWriterTest4::testRhbz1810732()
2264 createSwDoc(DATA_DIRECTORY
, "tdf113877_blank.odt");
2266 // set a page cursor into the end of the document
2267 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
2268 uno::Reference
<text::XTextViewCursorSupplier
> xTextViewCursorSupplier(
2269 xModel
->getCurrentController(), uno::UNO_QUERY
);
2270 uno::Reference
<text::XPageCursor
> xCursor(xTextViewCursorSupplier
->getViewCursor(),
2272 xCursor
->jumpToEndOfPage();
2274 // insert the same document at current cursor position
2276 const OUString insertFileid
2277 = m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "rhbz1810732.docx";
2278 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
2279 comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid
) } }));
2280 dispatchCommand(mxComponent
, ".uno:InsertDoc", aPropertyValues
);
2284 void SwUiWriterTest4::testTdf142157()
2288 const OUString insertFileid
= m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "tdf142157.odt";
2289 uno::Sequence
<beans::PropertyValue
> aPropertyValues(
2290 comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid
) } }));
2291 dispatchCommand(mxComponent
, ".uno:InsertDoc", aPropertyValues
);
2293 uno::Reference
<text::XTextSectionsSupplier
> xTextSectionsSupplier(mxComponent
, uno::UNO_QUERY
);
2294 uno::Reference
<container::XIndexAccess
> xSections(xTextSectionsSupplier
->getTextSections(),
2297 // Without the fix in place, this test would have failed with
2300 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
2303 void SwUiWriterTest4::testTdf116640()
2307 uno::Sequence
<beans::PropertyValue
> aArgs(
2308 comphelper::InitPropertySequence({ { "Columns", uno::makeAny(sal_Int32(2)) } }));
2310 dispatchCommand(mxComponent
, ".uno:InsertSection", aArgs
);
2311 Scheduler::ProcessEventsToIdle();
2313 uno::Reference
<text::XTextSectionsSupplier
> xTextSectionsSupplier(mxComponent
, uno::UNO_QUERY
);
2314 uno::Reference
<container::XIndexAccess
> xSections(xTextSectionsSupplier
->getTextSections(),
2316 uno::Reference
<beans::XPropertySet
> xTextSection(xSections
->getByIndex(0), uno::UNO_QUERY
);
2318 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
2320 uno::Reference
<text::XTextColumns
> xTextColumns
2321 = getProperty
<uno::Reference
<text::XTextColumns
>>(xTextSection
, "TextColumns");
2322 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns
->getColumnCount());
2324 dispatchCommand(mxComponent
, ".uno:Undo", {});
2325 Scheduler::ProcessEventsToIdle();
2327 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
2329 dispatchCommand(mxComponent
, ".uno:Redo", {});
2330 Scheduler::ProcessEventsToIdle();
2332 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
2334 dispatchCommand(mxComponent
, ".uno:Undo", {});
2335 Scheduler::ProcessEventsToIdle();
2337 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
2340 void SwUiWriterTest4::testTdf108524()
2342 createSwDoc(DATA_DIRECTORY
, "tdf108524.odt");
2343 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2344 // In total we expect two cells containing a section.
2345 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
2347 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
2348 // This was 0, section wasn't split, instead it was only on the first page
2349 // and it was cut off.
2350 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
2353 void SwUiWriterTest4::testLinesInSectionInTable()
2355 // This is similar to testTdf108524(), but the page boundary now is not in
2356 // the middle of a multi-line paragraph: the section only contains oneliner
2357 // paragraphs instead.
2358 createSwDoc(DATA_DIRECTORY
, "lines-in-section-in-table.odt");
2359 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2360 // In total we expect two cells containing a section.
2361 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
2363 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
2364 // This was 0, section wasn't split, instead it was only on the first page
2365 // and it was cut off.
2366 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
2369 void SwUiWriterTest4::testLinesMoveBackwardsInSectionInTable()
2372 // Assert that paragraph "4" is on page 1 and "5" is on page 2.
2373 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "lines-in-section-in-table.odt");
2374 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2375 assertXPath(pXmlDoc
, "/root/page", 2);
2376 SwNodeOffset
nPara4Node(
2377 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
2379 CPPUNIT_ASSERT_EQUAL(OUString("4"), pDoc
->GetNodes()[nPara4Node
]->GetTextNode()->GetText());
2380 SwNodeOffset
nPara5Node(
2381 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
2383 CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc
->GetNodes()[nPara5Node
]->GetTextNode()->GetText());
2385 // Remove paragraph "4".
2386 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2387 while (pWrtShell
->GetCursor()->GetNode().GetIndex() < nPara4Node
)
2388 pWrtShell
->Down(/*bSelect=*/false);
2389 pWrtShell
->EndPara();
2390 pWrtShell
->Up(/*bSelect=*/true);
2391 pWrtShell
->DelLeft();
2393 // Assert that paragraph "5" is now moved back to page 1 and is the last paragraph there.
2394 discardDumpedLayout();
2395 pXmlDoc
= parseLayoutDump();
2396 SwNodeOffset
nPage1LastNode(
2397 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
2399 // This was "3", paragraph "4" was deleted, but "5" was not moved backwards from page 2.
2400 CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
2404 void SwUiWriterTest4::testTableInSection()
2407 // The document has a section, containing a table that spans over 2 pages.
2408 createSwDoc(DATA_DIRECTORY
, "table-in-sect.odt");
2409 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2410 // In total we expect 4 cells.
2411 assertXPath(pXmlDoc
, "/root/page/body/section/tab/row/cell", 4);
2413 // Assert that on both pages the section contains 2 cells.
2414 assertXPath(pXmlDoc
, "/root/page[1]/body/section/tab/row/cell", 2);
2415 assertXPath(pXmlDoc
, "/root/page[2]/body/section/tab/row/cell", 2);
2419 void SwUiWriterTest4::testTableInNestedSection()
2422 // The document has a nested section, containing a table that spans over 2 pages.
2423 // This crashed the layout.
2424 createSwDoc(DATA_DIRECTORY
, "rhbz739252-3.odt");
2425 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2426 // Make sure the table is inside a section and spans over 2 pages.
2427 assertXPath(pXmlDoc
, "//page[1]//section/tab", 1);
2428 assertXPath(pXmlDoc
, "//page[2]//section/tab", 1);
2432 void SwUiWriterTest4::testTdf112741()
2435 createSwDoc(DATA_DIRECTORY
, "tdf112741.fodt");
2436 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2437 // This was 5 pages.
2438 assertXPath(pXmlDoc
, "//page", 4);
2439 assertXPath(pXmlDoc
, "//page[1]/body/tab/row/cell/tab/row/cell/section", 1);
2440 assertXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row/cell/section", 1);
2441 // This failed, 3rd page contained no sections.
2442 assertXPath(pXmlDoc
, "//page[3]/body/tab/row/cell/tab/row/cell/section", 1);
2443 assertXPath(pXmlDoc
, "//page[4]/body/tab/row/cell/tab/row/cell/section", 1);
2447 void SwUiWriterTest4::testTdf112860()
2450 // The document has a split section inside a nested table, and also a table
2452 // This crashed the layout.
2453 createSwDoc(DATA_DIRECTORY
, "tdf112860.fodt");
2457 void SwUiWriterTest4::testTdf113287()
2460 createSwDoc(DATA_DIRECTORY
, "tdf113287.fodt");
2461 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2462 assertXPath(pXmlDoc
, "//page", 2);
2464 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/infos/bounds", "top").toUInt32();
2465 sal_uInt32 nSectionTop
2466 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/section/infos/bounds", "top")
2468 // Make sure section frame is inside the cell frame.
2469 // Expected greater than 4593, was only 3714.
2470 CPPUNIT_ASSERT_GREATER(nCellTop
, nSectionTop
);
2474 void SwUiWriterTest4::testTdf113445()
2477 // Force multiple-page view.
2478 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf113445.fodt");
2479 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
2480 SwView
* pView
= pDocShell
->GetView();
2481 pView
->SetViewLayout(/*nColumns=*/2, /*bBookMode=*/false);
2484 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2485 assertXPath(pXmlDoc
, "//page", 2);
2486 sal_uInt32 nPage1Left
= getXPath(pXmlDoc
, "//page[1]/infos/bounds", "left").toUInt32();
2487 sal_uInt32 nPage2Left
= getXPath(pXmlDoc
, "//page[2]/infos/bounds", "left").toUInt32();
2488 // Make sure that page 2 is on the right hand side of page 1, not below it.
2489 CPPUNIT_ASSERT_GREATER(nPage1Left
, nPage2Left
);
2491 // Insert a new paragraph at the start of the document.
2492 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2493 pWrtShell
->StartOfSection();
2494 pWrtShell
->SplitNode();
2495 discardDumpedLayout();
2496 pXmlDoc
= parseLayoutDump();
2498 // Make sure that Table2:C5 and Table2:D5 has its section frame inside the cell frame.
2499 sal_uInt32 nCell3Top
2500 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/infos/bounds", "top")
2502 sal_uInt32 nSection3Top
2503 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/section/infos/bounds",
2506 CPPUNIT_ASSERT_GREATER(nCell3Top
, nSection3Top
);
2507 sal_uInt32 nCell4Top
2508 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/infos/bounds", "top")
2510 sal_uInt32 nSection4Top
2511 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/section/infos/bounds",
2514 CPPUNIT_ASSERT_GREATER(nCell4Top
, nSection4Top
);
2515 // Also check if the two cells in the same row have the same top position.
2516 // This was 4818, expected only 1672.
2517 CPPUNIT_ASSERT_EQUAL(nCell3Top
, nCell4Top
);
2521 void SwUiWriterTest4::testTdf113686()
2524 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf113686.fodt");
2525 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2526 assertXPath(pXmlDoc
, "/root/page", 2);
2527 SwNodeOffset
nPage1LastNode(
2528 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/txt[last()]",
2531 CPPUNIT_ASSERT_EQUAL(OUString("Table2:A1-P10"),
2532 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
2533 SwNodeOffset
nPage2FirstNode(
2534 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
2536 CPPUNIT_ASSERT_EQUAL(OUString("Table1:A1"),
2537 pDoc
->GetNodes()[nPage2FirstNode
]->GetTextNode()->GetText());
2540 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2541 while (pWrtShell
->GetCursor()->Start()->nNode
.GetIndex() < nPage1LastNode
)
2542 pWrtShell
->Down(/*bSelect=*/false);
2543 pWrtShell
->EndPara();
2544 for (int i
= 0; i
< 3; ++i
)
2545 pWrtShell
->Up(/*bSelect=*/true);
2546 pWrtShell
->DelLeft();
2548 // Assert that the second page is removed.
2549 discardDumpedLayout();
2550 pXmlDoc
= parseLayoutDump();
2551 // This was still 2, content from 2nd page was not moved.
2552 assertXPath(pXmlDoc
, "/root/page", 1);
2556 void SwUiWriterTest4::testTableInSectionInTable()
2559 // The document has a table, containing a section, containing a nested
2561 // This crashed the layout.
2562 createSwDoc(DATA_DIRECTORY
, "i95698.odt");
2566 void SwUiWriterTest4::testSectionInTableInTable()
2569 // The document has a nested table, containing a multi-line section at a
2571 // This crashed the layout later in SwFrame::IsFootnoteAllowed().
2572 createSwDoc(DATA_DIRECTORY
, "tdf112109.fodt");
2576 void SwUiWriterTest4::testSectionInTableInTable2()
2579 createSwDoc(DATA_DIRECTORY
, "split-section-in-nested-table.fodt");
2580 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2581 sal_uInt32 nSection1
2582 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
2583 sal_uInt32 nSection1Follow
2584 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "follow")
2586 // This failed, the section wasn't split inside a nested table.
2587 sal_uInt32 nSection2
2588 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
2589 sal_uInt32 nSection2Precede
2590 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "precede")
2593 // Make sure that the first's follow and the second's precede is correct.
2594 CPPUNIT_ASSERT_EQUAL(nSection2
, nSection1Follow
);
2595 CPPUNIT_ASSERT_EQUAL(nSection1
, nSection2Precede
);
2599 void SwUiWriterTest4::testSectionInTableInTable3()
2602 createSwDoc(DATA_DIRECTORY
, "tdf113153.fodt");
2604 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
2605 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
2607 uno::Reference
<container::XNamed
> xTable(xTables
->getByIndex(1), uno::UNO_QUERY
);
2608 CPPUNIT_ASSERT_EQUAL(OUString("Table16"), xTable
->getName());
2610 uno::Reference
<text::XTextTable
> xRowSupplier(xTable
, uno::UNO_QUERY
);
2611 uno::Reference
<table::XTableRows
> xRows
= xRowSupplier
->getRows();
2612 uno::Reference
<beans::XPropertySet
> xRow(xRows
->getByIndex(1), uno::UNO_QUERY
);
2613 xRow
->setPropertyValue("IsSplitAllowed", uno::makeAny(true));
2614 // This never returned.
2617 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2618 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
2619 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
2620 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
2621 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
2622 sal_uInt32 nTable2Follow
= getXPath(pXmlDoc
, "//page[2]//body/tab", "follow").toUInt32();
2623 sal_uInt32 nTable3
= getXPath(pXmlDoc
, "//page[3]//body/tab", "id").toUInt32();
2624 sal_uInt32 nTable3Precede
= getXPath(pXmlDoc
, "//page[3]//body/tab", "precede").toUInt32();
2626 // Make sure the outer table frames are linked together properly.
2627 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
2628 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
2629 CPPUNIT_ASSERT_EQUAL(nTable3
, nTable2Follow
);
2630 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable3Precede
);
2634 void SwUiWriterTest4::testSectionInTableInTable4()
2637 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf113520.fodt");
2638 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2639 assertXPath(pXmlDoc
, "/root/page", 3);
2640 SwNodeOffset
nPage1LastNode(
2641 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[last()]",
2644 CPPUNIT_ASSERT_EQUAL(OUString("Section1:P10"),
2645 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
2646 SwNodeOffset
nPage3FirstNode(
2647 getXPath(pXmlDoc
, "/root/page[3]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[1]",
2650 CPPUNIT_ASSERT_EQUAL(OUString("Section1:P23"),
2651 pDoc
->GetNodes()[nPage3FirstNode
]->GetTextNode()->GetText());
2654 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2655 while (pWrtShell
->GetCursor()->Start()->nNode
.GetIndex() < nPage1LastNode
)
2656 pWrtShell
->Down(/*bSelect=*/false);
2657 pWrtShell
->EndPara();
2658 while (pWrtShell
->GetCursor()->End()->nNode
.GetIndex() < nPage3FirstNode
)
2659 pWrtShell
->Down(/*bSelect=*/true);
2660 pWrtShell
->EndPara(/*bSelect=*/true);
2661 pWrtShell
->DelLeft();
2663 // Assert that the page is removed.
2664 discardDumpedLayout();
2665 pXmlDoc
= parseLayoutDump();
2666 // This was 3, page 2 was emptied, but it wasn't removed.
2667 assertXPath(pXmlDoc
, "/root/page", 2);
2669 // Make sure the outer table frames are linked together properly.
2670 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
2671 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
2672 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
2673 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
2674 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
2675 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
2679 void SwUiWriterTest4::testTdf112160()
2682 // Assert that the A2 cell is on page 1.
2683 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf112160.fodt");
2684 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2685 SwNodeOffset
nA2CellNode(getXPath(pXmlDoc
,
2686 "/root/page[1]/body/tab/row[2]/cell[1]/section/txt[last()]",
2689 CPPUNIT_ASSERT_EQUAL(OUString("Table1.A2"),
2690 pDoc
->GetNodes()[nA2CellNode
]->GetTextNode()->GetText());
2692 // Append a new paragraph to the end of the A2 cell.
2693 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2694 while (pWrtShell
->GetCursor()->GetNode().GetIndex() < nA2CellNode
)
2695 pWrtShell
->Down(/*bSelect=*/false);
2696 pWrtShell
->EndPara();
2697 pWrtShell
->SplitNode();
2699 // Assert that after A2 got extended, D2 stays on page 1.
2700 discardDumpedLayout();
2701 pXmlDoc
= parseLayoutDump();
2702 sal_uInt32 nD2CellNode
2703 = getXPath(pXmlDoc
, "/root/page[1]/body/tab/row[2]/cell[last()]/section/txt[last()]",
2706 // This was Table1.C2, Table1.D2 was moved to the next page, unexpected.
2707 CPPUNIT_ASSERT_EQUAL(OUString("Table1.D2"),
2708 pDoc
->GetNodes()[SwNodeOffset(nD2CellNode
)]->GetTextNode()->GetText());
2712 void SwUiWriterTest4::testTdf114536()
2714 // This crashed in SwTextFormatter::MergeCharacterBorder() due to a
2716 createSwDoc(DATA_DIRECTORY
, "tdf114536.odt");
2719 void SwUiWriterTest4::testParagraphOfTextRange()
2721 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "paragraph-of-text-range.odt");
2724 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2725 pWrtShell
->Down(/*bSelect=*/false);
2726 CPPUNIT_ASSERT(pWrtShell
->IsCursorInTable());
2727 // Enter the section.
2728 pWrtShell
->Down(/*bSelect=*/false);
2729 CPPUNIT_ASSERT(pWrtShell
->IsDirectlyInSection());
2731 // Assert that we get the right paragraph object.
2732 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
2733 uno::Reference
<text::XTextViewCursorSupplier
> xController(xModel
->getCurrentController(),
2735 uno::Reference
<text::XTextRange
> xViewCursor
= xController
->getViewCursor();
2736 // This failed as there were no TextParagraph property.
2738 = getProperty
<uno::Reference
<text::XTextRange
>>(xViewCursor
->getStart(), "TextParagraph");
2739 CPPUNIT_ASSERT_EQUAL(OUString("In section"), xParagraph
->getString());
2742 void SwUiWriterTest4::testTdf99689TableOfContents()
2744 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf99689.odt");
2745 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2746 pWrtShell
->GotoNextTOXBase();
2747 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
2748 pWrtShell
->UpdateTableOf(*pTOXBase
);
2749 SwCursorShell
* pShell(pDoc
->GetEditShell());
2750 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetNode().GetTextNode();
2751 SwNodeIndex
aIdx(*pTitleNode
);
2753 pDoc
->GetNodes().GoNext(&aIdx
);
2755 // skip the first header. No attributes there.
2756 // next node should contain superscript
2757 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2758 CPPUNIT_ASSERT(pNext
->HasHints());
2759 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2760 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2762 // next node should contain subscript
2763 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2764 CPPUNIT_ASSERT(pNext
->HasHints());
2765 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2766 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2769 void SwUiWriterTest4::testTdf99689TableOfFigures()
2771 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf99689_figures.odt");
2772 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2773 pWrtShell
->GotoNextTOXBase();
2774 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
2775 pWrtShell
->UpdateTableOf(*pTOXBase
);
2776 SwCursorShell
* pShell(pDoc
->GetEditShell());
2777 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetNode().GetTextNode();
2778 SwNodeIndex
aIdx(*pTitleNode
);
2781 // next node should contain subscript
2782 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2783 CPPUNIT_ASSERT(pNext
->HasHints());
2784 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2785 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2787 // next node should contain superscript
2788 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2789 CPPUNIT_ASSERT(pNext
->HasHints());
2790 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2791 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2794 void SwUiWriterTest4::testTdf99689TableOfTables()
2796 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf99689_tables.odt");
2797 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2798 pWrtShell
->GotoNextTOXBase();
2799 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
2800 pWrtShell
->UpdateTableOf(*pTOXBase
);
2801 SwCursorShell
* pShell(pDoc
->GetEditShell());
2802 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetNode().GetTextNode();
2803 SwNodeIndex
aIdx(*pTitleNode
);
2806 // next node should contain superscript
2807 SwTextNode
* pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2808 CPPUNIT_ASSERT(pNext
->HasHints());
2809 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2810 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2812 // next node should contain subscript
2813 pNext
= static_cast<SwTextNode
*>(pDoc
->GetNodes().GoNext(&aIdx
));
2814 CPPUNIT_ASSERT(pNext
->HasHints());
2815 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
2816 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
2819 // tdf#112448: Fix: take correct line height
2821 // When line metrics is not calculated we need to call CalcRealHeight()
2822 // before usage of the Height() and GetRealHeight().
2823 void SwUiWriterTest4::testTdf112448()
2825 createSwDoc(DATA_DIRECTORY
, "tdf112448.odt");
2827 // check actual number of line breaks in the paragraph
2828 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
2829 assertXPath(pXmlDoc
, "/root/page/body/txt/LineBreak", 2);
2832 void SwUiWriterTest4::testTdf113790()
2834 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf113790.docx");
2835 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2836 // Create the clipboard document.
2838 aClipboard
.SetClipBoard(true);
2840 // Go to fourth line - to "ABCD" bulleted list item
2841 pWrtShell
->Down(/*bSelect=*/false, 4);
2842 pWrtShell
->SelPara(nullptr);
2843 CPPUNIT_ASSERT_EQUAL(OUString("ABCD"), pWrtShell
->GetSelText());
2844 pWrtShell
->Copy(aClipboard
);
2846 // Go down to next-to-last (empty) line above "Title3"
2847 pWrtShell
->Down(/*bSelect=*/false, 4);
2848 pWrtShell
->Paste(aClipboard
);
2850 // Save it as DOCX & load it again
2851 reload("Office Open XML Text", "tdf113790.docx");
2852 CPPUNIT_ASSERT(dynamic_cast<SwXTextDocument
*>(mxComponent
.get()));
2855 void SwUiWriterTest4::testTdf108048()
2859 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
2860 { "Kind", uno::makeAny(sal_Int16(3)) },
2861 { "TemplateName", uno::makeAny(OUString("Default Page Style")) },
2863 uno::makeAny(sal_uInt16(6)) }, // Even number to avoid auto-inserted blank page
2864 { "PageNumberFilled", uno::makeAny(true) },
2866 dispatchCommand(mxComponent
, ".uno:InsertBreak", aPropertyValues
);
2867 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
2868 CPPUNIT_ASSERT_EQUAL(2, getPages());
2870 // The inserted page must have page number set to 6
2871 uno::Reference
<text::XTextRange
> xPara
= getParagraph(2);
2872 sal_uInt16 nPageNumber
= getProperty
<sal_uInt16
>(xPara
, "PageNumberOffset");
2873 CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), nPageNumber
);
2876 void SwUiWriterTest4::testTdf113481()
2878 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf113481-IVS.odt");
2879 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2881 // One backspace should completely remove the CJK ideograph variation sequence
2882 pWrtShell
->EndPara();
2883 // Before: U+8FBA U+E0102. After: empty
2884 pWrtShell
->DelLeft();
2885 const uno::Reference
<text::XTextRange
> xPara1
= getParagraph(1);
2886 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara1
->getString().getLength());
2888 // In case that weak script is treated as CJK script, remove one character.
2889 pWrtShell
->Down(false);
2890 pWrtShell
->EndPara();
2891 // Before: U+4E2D U+2205 U+FE00. After: U+4E2D U+2205
2892 if (pWrtShell
->GetScriptType() == SvtScriptType::ASIAN
)
2894 pWrtShell
->DelLeft();
2895 const uno::Reference
<text::XTextRange
> xPara2
= getParagraph(2);
2896 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xPara2
->getString().getLength());
2897 CPPUNIT_ASSERT_EQUAL(u
'\x2205', xPara2
->getString()[1]);
2900 // Characters of other scripts, remove one character.
2901 pWrtShell
->Down(false);
2902 pWrtShell
->EndPara();
2903 // Before: U+1820 U+180B. After: U+1820
2904 pWrtShell
->DelLeft();
2905 const uno::Reference
<text::XTextRange
> xPara3
= getParagraph(3);
2906 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPara3
->getString().getLength());
2907 CPPUNIT_ASSERT_EQUAL(u
'\x1820', xPara3
->getString()[0]);
2910 void SwUiWriterTest4::testTdf115013()
2912 const OUString
sColumnName("Name with spaces, \"quotes\" and \\backslashes");
2914 utl::TempFile
aTempDir(nullptr, true);
2915 aTempDir
.EnableKillingFile();
2916 const OUString aWorkDir
= aTempDir
.GetURL();
2918 //create new writer document
2919 SwDoc
* pDoc
= createSwDoc();
2922 // Load and register data source
2923 const OUString
aDataSourceURI(m_directories
.getURLFromSrc(DATA_DIRECTORY
)
2924 + "datasource.ods");
2925 OUString sDataSource
= SwDBManager::LoadAndRegisterDataSource(aDataSourceURI
, &aWorkDir
);
2926 CPPUNIT_ASSERT(!sDataSource
.isEmpty());
2928 // Insert a new field type for the mailmerge field
2930 aDBData
.sDataSource
= sDataSource
;
2931 aDBData
.sCommand
= "Sheet1";
2932 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2933 CPPUNIT_ASSERT(pWrtShell
);
2934 SwDBFieldType
* pFieldType
= static_cast<SwDBFieldType
*>(
2935 pWrtShell
->InsertFieldType(SwDBFieldType(pDoc
, sColumnName
, aDBData
)));
2936 CPPUNIT_ASSERT(pFieldType
);
2938 // Insert the field into document
2939 SwDBField
aField(pFieldType
);
2940 pWrtShell
->InsertField2(aField
);
2942 // Save it as DOCX & load it again
2943 reload("Office Open XML Text", "mm-field.docx");
2945 auto pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
2946 CPPUNIT_ASSERT(pXTextDocument
);
2947 pDoc
= pXTextDocument
->GetDocShell()->GetDoc();
2948 CPPUNIT_ASSERT(pDoc
);
2949 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2950 CPPUNIT_ASSERT(pWrtShell
);
2951 SwPaM
* pCursor
= pDoc
->GetEditShell()->GetCursor();
2952 CPPUNIT_ASSERT(pCursor
);
2954 // Get the field at the beginning of the document
2955 SwDBField
* pField
= dynamic_cast<SwDBField
*>(SwCursorShell::GetFieldAtCursor(pCursor
, true));
2956 CPPUNIT_ASSERT(pField
);
2957 OUString sColumn
= static_cast<SwDBFieldType
*>(pField
->GetTyp())->GetColumnName();
2958 // The column name must come correct after round trip
2959 CPPUNIT_ASSERT_EQUAL(sColumnName
, sColumn
);
2962 void SwUiWriterTest4::testTdf115065()
2964 // In the document, the tables have table style assigned
2965 // Source table (first one) has two rows;
2966 // destination (second one) has only one row
2967 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf115065.odt");
2968 CPPUNIT_ASSERT(pDoc
);
2969 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2970 CPPUNIT_ASSERT(pWrtShell
);
2972 pWrtShell
->GotoTable("Table2");
2973 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
2974 // Destination point is the middle of the first cell of second table
2975 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
2977 pWrtShell
->GotoTable("Table1");
2978 aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
2979 // Source point is the middle of the first cell of first table
2980 Point
ptFrom(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
2982 pWrtShell
->SelTableCol();
2983 // The copy operation (or closing document after that) segfaulted
2984 pWrtShell
->Copy(*pWrtShell
, ptFrom
, ptTo
);
2987 void SwUiWriterTest4::testTdf84806_MovingMultipleTableRows()
2989 // Moving of multiple table rows.
2990 // Source table (first one) has two rows;
2991 // destination (second one) has only one row
2992 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf115065.odt");
2993 CPPUNIT_ASSERT(pDoc
);
2994 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
2995 CPPUNIT_ASSERT(pWrtShell
);
2997 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
2998 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
3000 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
3001 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
3002 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
3003 CPPUNIT_ASSERT(xTableNames
->hasByName("Table2"));
3004 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
3005 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
3006 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
3007 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
3009 // without redlining
3010 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
3011 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
3013 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
3015 pWrtShell
->GotoTable("Table2");
3016 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
3017 // Destination point is the middle of the first cell of second table
3018 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
3020 // Move rows of the first table into the second table
3021 pWrtShell
->GotoTable("Table1");
3022 pWrtShell
->SelTable();
3023 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
3024 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
3026 // This was 2 tables
3027 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables
->getCount());
3028 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
3030 // Undo results 2 tables
3031 rUndoManager
.Undo();
3032 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
3034 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
3035 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
3036 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
3037 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
3038 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
3040 // FIXME assert with Redo()
3043 void SwUiWriterTest4::testTdf147181_TrackedMovingOfMultipleTableRows()
3045 // Tracked moving of multiple table rows.
3046 // Source table (first one) has two rows;
3047 // destination (second one) has only one row
3048 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf115065.odt");
3049 CPPUNIT_ASSERT(pDoc
);
3050 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3051 CPPUNIT_ASSERT(pWrtShell
);
3053 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
3054 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
3056 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
3057 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
3058 CPPUNIT_ASSERT(xTableNames
->hasByName("Table1"));
3059 CPPUNIT_ASSERT(xTableNames
->hasByName("Table2"));
3060 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
3061 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
3062 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
3063 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
3065 // FIXME: doesn't work with empty rows, yet
3066 pWrtShell
->Insert("x");
3067 pWrtShell
->Down(false);
3068 pWrtShell
->Insert("x");
3071 dispatchCommand(mxComponent
, ".uno:TrackChanges", {});
3072 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3073 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
3076 CPPUNIT_ASSERT_MESSAGE(
3077 "redlines should be visible",
3078 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
3080 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
3082 pWrtShell
->GotoTable("Table2");
3083 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
3084 // Destination point is the middle of the first cell of second table
3085 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
3087 // Move rows of the first table into the second table
3088 pWrtShell
->GotoTable("Table1");
3089 pWrtShell
->SelTable();
3090 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
3091 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
3093 // still 2 tables, but the second one has got 3 rows
3094 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
3095 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
3096 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
3098 // accept changes results 1 table (removing moved table)
3099 dispatchCommand(mxComponent
, ".uno:AcceptAllTrackedChanges", {});
3100 Scheduler::ProcessEventsToIdle();
3101 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
3103 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables2
->getCount());
3104 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
3106 // Undo results 2 tables
3107 rUndoManager
.Undo();
3108 rUndoManager
.Undo();
3109 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
3110 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName("Table1"), uno::UNO_QUERY
);
3111 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName("Table2"), uno::UNO_QUERY
);
3112 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
3113 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
3115 // reject changes results 2 table again, with the original row counts
3116 dispatchCommand(mxComponent
, ".uno:RejectAllTrackedChanges", {});
3117 uno::Reference
<container::XIndexAccess
> xTables3(xTablesSupplier
->getTextTables(),
3119 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables3
->getCount());
3120 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
3121 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
3124 void SwUiWriterTest4::testTdf115132()
3126 SwDoc
* pDoc
= createSwDoc();
3127 CPPUNIT_ASSERT(pDoc
);
3128 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3129 CPPUNIT_ASSERT(pWrtShell
);
3131 std::vector
<OUString
> vTestTableNames
;
3133 // Create an empty paragraph that will separate first table from the rest
3134 pWrtShell
->SplitNode();
3135 pWrtShell
->StartOfSection();
3136 // Create a table at the start of document body
3137 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
3138 const SwTable
* pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
3139 const SwTableFormat
* pFormat
= pTable
->GetFrameFormat();
3140 CPPUNIT_ASSERT(pFormat
);
3141 vTestTableNames
.push_back(pFormat
->GetName());
3142 pWrtShell
->EndOfSection();
3143 // Create a table after a paragraph
3144 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
3145 pFormat
= pTable
->GetFrameFormat();
3146 CPPUNIT_ASSERT(pFormat
);
3147 vTestTableNames
.push_back(pFormat
->GetName());
3148 // Create a table immediately after the previous
3149 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
3150 pFormat
= pTable
->GetFrameFormat();
3151 CPPUNIT_ASSERT(pFormat
);
3152 vTestTableNames
.push_back(pFormat
->GetName());
3153 // Create a nested table in the middle of last row
3154 pWrtShell
->GotoTable(vTestTableNames
.back());
3155 for (int i
= 0; i
< 4; ++i
)
3156 pWrtShell
->GoNextCell(false);
3157 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
3158 pFormat
= pTable
->GetFrameFormat();
3159 CPPUNIT_ASSERT(pFormat
);
3160 vTestTableNames
.push_back(pFormat
->GetName());
3162 // Now check that in any cell in all tables we don't go out of a cell
3163 // using Delete or Backspace. We test cases when a table is the first node;
3164 // when we are in a first/middle/last cell in a row; when there's a paragraph
3165 // before/after this cell; when there's another table before/after this cell;
3167 for (const auto& rTableName
: vTestTableNames
)
3169 pWrtShell
->GotoTable(rTableName
);
3172 const SwStartNode
* pNd
= pWrtShell
->GetCursor()->GetNode().FindTableBoxStartNode();
3173 pWrtShell
->DelRight();
3174 CPPUNIT_ASSERT_EQUAL(pNd
, pWrtShell
->GetCursor()->GetNode().FindTableBoxStartNode());
3175 pWrtShell
->DelLeft();
3176 CPPUNIT_ASSERT_EQUAL(pNd
, pWrtShell
->GetCursor()->GetNode().FindTableBoxStartNode());
3177 } while (pWrtShell
->GoNextCell(false));
3181 void SwUiWriterTest4::testXDrawPagesSupplier()
3184 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
3185 CPPUNIT_ASSERT_MESSAGE("XDrawPagesSupplier interface is unavailable", xDrawPagesSupplier
.is());
3186 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
3187 CPPUNIT_ASSERT(xDrawPages
.is());
3188 CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be only a single DrawPage in Writer documents",
3189 sal_Int32(1), xDrawPages
->getCount());
3190 uno::Any aDrawPage
= xDrawPages
->getByIndex(0);
3191 uno::Reference
<drawing::XDrawPage
> xDrawPageFromXDrawPages(aDrawPage
, uno::UNO_QUERY
);
3192 CPPUNIT_ASSERT(xDrawPageFromXDrawPages
.is());
3194 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
3195 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
3196 CPPUNIT_ASSERT_EQUAL_MESSAGE(
3197 "The DrawPage accessed using XDrawPages must be the same as using XDrawPageSupplier",
3198 xDrawPage
.get(), xDrawPageFromXDrawPages
.get());
3201 void SwUiWriterTest4::testTdf116403()
3203 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf116403-considerborders.odt");
3204 // Check that before ToX update, the tab stop position is the old one
3205 uno::Reference
<text::XTextRange
> xParagraph
= getParagraph(2, "1\t1");
3206 auto aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, "ParaTabStops");
3207 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
3208 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(17000), aTabs
[0].Position
);
3210 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3211 const SwTOXBase
* pTOX
= pWrtShell
->GetTOX(0);
3212 CPPUNIT_ASSERT(pTOX
);
3213 pWrtShell
->UpdateTableOf(*pTOX
);
3215 xParagraph
= getParagraph(2, "1\t1");
3216 aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, "ParaTabStops");
3217 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
3218 // This was still 17000, refreshing ToX didn't take borders spacings and widths into account
3219 CPPUNIT_ASSERT_EQUAL_MESSAGE("Page borders must be considered for right-aligned tabstop",
3220 static_cast<sal_Int32
>(17000 - 2 * 500 - 2 * 1),
3224 void SwUiWriterTest4::testHtmlCopyImages()
3226 // Load a document with an image.
3227 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "image.odt");
3229 // Trigger the copy part of HTML copy&paste.
3230 WriterRef xWrt
= new SwHTMLWriter(/*rBaseURL=*/OUString());
3231 CPPUNIT_ASSERT(xWrt
.is());
3233 xWrt
->m_bWriteClipboardDoc
= true;
3234 xWrt
->m_bWriteOnlyFirstTable
= false;
3235 xWrt
->SetShowProgress(false);
3237 SvFileStream
aStream(maTempFile
.GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
3238 SwWriter
aWrt(aStream
, *pDoc
);
3241 htmlDocUniquePtr pHtmlDoc
= parseHtml(maTempFile
);
3242 CPPUNIT_ASSERT(pHtmlDoc
);
3244 // This failed, image was lost during HTML copy.
3245 OUString aImage
= getXPath(pHtmlDoc
, "/html/body/p/img", "src");
3246 // Also make sure that the image is not embedded (e.g. Word doesn't handle
3247 // embedded images).
3248 CPPUNIT_ASSERT(aImage
.startsWith("file:///"));
3251 void SwUiWriterTest4::testTdf116789()
3253 createSwDoc(DATA_DIRECTORY
, "tdf116789.fodt");
3254 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
3255 uno::Reference
<text::XText
> xText1
;
3256 uno::Reference
<text::XText
> xText2
;
3258 uno::Reference
<text::XTextContent
> xBookmark(
3259 xBookmarksSupplier
->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY
);
3260 xText1
= xBookmark
->getAnchor()->getText();
3263 uno::Reference
<text::XTextContent
> xBookmark(
3264 xBookmarksSupplier
->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY
);
3265 xText2
= xBookmark
->getAnchor()->getText();
3267 // This failed, we got two different SwXCell for the same bookmark anchor text.
3268 CPPUNIT_ASSERT_EQUAL(xText1
, xText2
);
3271 void SwUiWriterTest4::testTdf91801()
3273 // Tests calculation with several user field variables without prior user fields
3274 createSwDoc(DATA_DIRECTORY
, "tdf91801.fodt");
3275 uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(1), uno::UNO_QUERY
);
3276 uno::Reference
<table::XCell
> xCell(xTable
->getCellByName("A1"));
3277 CPPUNIT_ASSERT_EQUAL(555.0, xCell
->getValue());
3280 void SwUiWriterTest4::testTdf51223()
3282 SwDoc
* pDoc
= createSwDoc();
3283 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3284 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
3285 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3286 pWrtShell
->Insert("i");
3287 pWrtShell
->SplitNode(true);
3288 CPPUNIT_ASSERT_EQUAL(OUString("I"),
3289 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3290 rUndoManager
.Undo();
3291 CPPUNIT_ASSERT_EQUAL(OUString("i"),
3292 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3295 void SwUiWriterTest4::testFontEmbedding()
3297 #if HAVE_MORE_FONTS && !defined(MACOSX)
3298 createSwDoc(DATA_DIRECTORY
, "testFontEmbedding.odt");
3300 OString
aContentBaseXpath("/office:document-content/office:font-face-decls");
3301 OString
aSettingsBaseXpath("/office:document-settings/office:settings/config:config-item-set");
3303 xmlDocUniquePtr pXmlDoc
;
3304 uno::Sequence
<beans::PropertyValue
> aDescriptor
;
3305 utl::TempFile aTempFile
;
3306 aTempFile
.EnableKillingFile();
3308 // Get document settings
3309 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY_THROW
);
3310 uno::Reference
<beans::XPropertySet
> xProps(
3311 xFactory
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW
);
3313 // Check font embedding state
3314 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue("EmbedFonts").get
<bool>());
3315 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue("EmbedOnlyUsedFonts").get
<bool>());
3316 // Font scripts should be enabled by default, however this has no effect unless "EmbedOnlyUsedFonts" is enabled
3317 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedLatinScriptFonts").get
<bool>());
3318 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedAsianScriptFonts").get
<bool>());
3319 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue("EmbedComplexScriptFonts").get
<bool>());
3321 // CASE 1 - no font embedding enabled
3323 // Save the document
3324 uno::Reference
<frame::XStorable
> xStorable(mxComponent
, uno::UNO_QUERY
);
3325 xStorable
->storeToURL(aTempFile
.GetURL(), aDescriptor
);
3326 CPPUNIT_ASSERT(aTempFile
.IsValid());
3328 // Check setting - No font embedding should be enabled
3329 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "settings.xml");
3330 CPPUNIT_ASSERT(pXmlDoc
);
3332 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "false");
3334 // Check content - No font-face-src nodes should be present
3335 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml");
3336 CPPUNIT_ASSERT(pXmlDoc
);
3338 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
3339 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
3342 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
3343 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
3344 assertXPath(pXmlDoc
,
3346 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
3348 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
3349 assertXPath(pXmlDoc
,
3351 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
3353 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
3354 assertXPath(pXmlDoc
,
3356 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
3358 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
3359 assertXPath(pXmlDoc
,
3360 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 0);
3361 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
3362 assertXPath(pXmlDoc
,
3363 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
3365 // CASE 2 - font embedding enabled, but embed used fonts disabled
3367 // Enable font embedding, disable embedding used font only
3368 xProps
->setPropertyValue("EmbedFonts", uno::makeAny(true));
3369 xProps
->setPropertyValue("EmbedOnlyUsedFonts", uno::makeAny(false));
3371 // Save the document again
3372 xStorable
->storeToURL(aTempFile
.GetURL(), aDescriptor
);
3373 CPPUNIT_ASSERT(aTempFile
.IsValid());
3375 // Check setting - font embedding should be enabled + embed only used fonts and scripts
3376 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "settings.xml");
3377 CPPUNIT_ASSERT(pXmlDoc
);
3379 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "true");
3381 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
3384 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
3387 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
3390 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
3393 // Check content - font-face-src should be present only for "Liberation Sans" fonts
3395 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml");
3396 CPPUNIT_ASSERT(pXmlDoc
);
3398 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
3399 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
3402 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 1);
3403 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
3404 assertXPath(pXmlDoc
,
3406 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
3408 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
3409 assertXPath(pXmlDoc
,
3411 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
3413 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
3414 assertXPath(pXmlDoc
,
3416 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
3418 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
3419 assertXPath(pXmlDoc
,
3420 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
3421 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
3422 assertXPath(pXmlDoc
,
3423 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 1);
3425 // CASE 3 - font embedding enabled, embed only used fonts enabled
3427 // Enable font embedding and setting to embed used fonts only
3428 xProps
->setPropertyValue("EmbedFonts", uno::makeAny(true));
3429 xProps
->setPropertyValue("EmbedOnlyUsedFonts", uno::makeAny(true));
3430 xProps
->setPropertyValue("EmbedLatinScriptFonts", uno::makeAny(true));
3431 xProps
->setPropertyValue("EmbedAsianScriptFonts", uno::makeAny(true));
3432 xProps
->setPropertyValue("EmbedComplexScriptFonts", uno::makeAny(true));
3434 // Save the document again
3435 xStorable
->storeToURL(aTempFile
.GetURL(), aDescriptor
);
3436 CPPUNIT_ASSERT(aTempFile
.IsValid());
3438 // Check setting - font embedding should be enabled + embed only used fonts and scripts
3439 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "settings.xml");
3440 CPPUNIT_ASSERT(pXmlDoc
);
3442 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", "true");
3444 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
3447 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
3450 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
3453 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
3456 // Check content - font-face-src should be present only for "Liberation Sans" fonts
3458 pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml");
3459 CPPUNIT_ASSERT(pXmlDoc
);
3461 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
3462 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
3465 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
3466 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
3467 assertXPath(pXmlDoc
,
3469 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
3471 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
3472 assertXPath(pXmlDoc
,
3474 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
3476 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
3477 assertXPath(pXmlDoc
,
3479 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
3481 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
3482 assertXPath(pXmlDoc
,
3483 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
3484 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
3485 assertXPath(pXmlDoc
,
3486 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
3490 // Unit test for fix inconsistent bookmark behavior around at-char/as-char anchored frames
3492 // We have a placeholder character in the sw doc model for as-char anchored frames,
3493 // so it's possible to have a bookmark before/after the frame or a non-collapsed bookmark
3494 // which covers the frame. The same is not true for at-char anchored frames,
3495 // where the anchor points to a doc model position, but there is no placeholder character.
3496 // If a bookmark is created covering the start and end of the anchor of the frame,
3497 // internally we create a collapsed bookmark which has the same position as the anchor of the frame.
3498 // When this doc model is handled by SwXParagraph::createEnumeration(),
3499 // first the frame and then the bookmark is appended to the text portion enumeration,
3500 // so your bookmark around the frame is turned into a collapsed bookmark after the frame.
3501 // (The same happens when we roundtrip an ODT document representing this doc model.)
3503 // Fix the problem by inserting collapsed bookmarks with affected anchor positions
3504 // (same position is the anchor for an at-char frame) into the enumeration in two stages:
3505 // first the start of them before frames and then the end of them + other bookmarks.
3506 // This way UNO API users get their non-collapsed bookmarks around at-char anchored frames,
3507 // similar to as-char ones.
3508 void SwUiWriterTest4::testInconsistentBookmark()
3510 // create test document with text and bookmark
3512 SwDoc
* pDoc(createSwDoc(DATA_DIRECTORY
, "testInconsistentBookmark.ott"));
3513 IDocumentMarkAccess
& rIDMA(*pDoc
->getIDocumentMarkAccess());
3514 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
3515 SwCursor
aPaM(SwPosition(aIdx
), nullptr);
3517 aPaM
.MovePara(GoCurrPara
, fnParaStart
);
3518 aPaM
.MovePara(GoCurrPara
, fnParaEnd
);
3519 rIDMA
.makeMark(aPaM
, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK
,
3520 ::sw::mark::InsertMode::New
);
3525 // save document and verify the bookmark scoup
3528 utl::TempFile aTempFile
;
3529 save("writer8", aTempFile
);
3531 // load only content.xml
3532 if (xmlDocUniquePtr pXmlDoc
= parseExportInternal(aTempFile
.GetURL(), "content.xml"))
3534 const OString
aPath("/office:document-content/office:body/office:text/text:p");
3536 const int pos1
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-start");
3537 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "control");
3538 const int pos3
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-end");
3540 CPPUNIT_ASSERT_GREATER(pos1
, pos2
);
3541 CPPUNIT_ASSERT_GREATER(pos2
, pos3
);
3546 void SwUiWriterTest4::testSpellOnlineParameter()
3548 SwDoc
* pDoc
= createSwDoc();
3549 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3550 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
3551 bool bSet
= pOpt
->IsOnlineSpell();
3553 uno::Sequence
<beans::PropertyValue
> params
3554 = comphelper::InitPropertySequence({ { "Enable", uno::makeAny(!bSet
) } });
3555 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
3556 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
3558 // set the same state as now and we don't expect any change (no-toggle)
3559 params
= comphelper::InitPropertySequence({ { "Enable", uno::makeAny(!bSet
) } });
3560 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
3561 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
3564 void SwUiWriterTest4::testRedlineAutoCorrect()
3566 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "redline-autocorrect.fodt");
3568 dispatchCommand(mxComponent
, ".uno:GoToEndOfDoc", {});
3570 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3572 // show tracked deletion with enabled change tracking
3573 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
3574 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
3575 pWrtShell
->SetRedlineFlags(nMode
);
3576 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
3578 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3579 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
3581 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3582 pWrtShell
->AutoCorrect(corr
, ' ');
3583 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3585 // tdf#83419 This was "Ts " removing the deletion of "t" silently by sentence capitalization
3586 OUString
sReplaced("ts ");
3587 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3589 // hide delete redlines
3590 pWrtShell
->SetRedlineFlags(nMode
& ~RedlineFlags::ShowDelete
);
3592 // repeat it with not visible redlining
3593 dispatchCommand(mxComponent
, ".uno:Undo", {});
3595 pWrtShell
->AutoCorrect(corr
, ' ');
3596 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3599 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3601 // show delete redlines
3602 pWrtShell
->SetRedlineFlags(nMode
);
3603 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3605 // This still keep the tracked deletion, capitalize only the visible text "s"
3606 // with tracked deletion of the original character
3608 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3610 // repeat it with visible redlining and word auto replacement of "tset"
3611 dispatchCommand(mxComponent
, ".uno:Undo", {});
3612 dispatchCommand(mxComponent
, ".uno:Undo", {});
3614 pWrtShell
->Insert("et");
3615 pWrtShell
->AutoCorrect(corr
, ' ');
3616 // This was "Ttest" removing the tracked deletion silently.
3617 // Don't replace, if a redline starts or ends within the text.
3618 sReplaced
= "tset ";
3619 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3620 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3622 // Otherwise replace it
3623 pWrtShell
->Insert("tset");
3624 pWrtShell
->AutoCorrect(corr
, ' ');
3625 sReplaced
= "tset test ";
3626 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3627 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3629 // Including capitalization
3630 pWrtShell
->Insert("end. word");
3631 pWrtShell
->AutoCorrect(corr
, ' ');
3632 sReplaced
= "tset test end. Word ";
3633 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3634 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3636 // tracked deletions after the correction point doesn't affect autocorrect
3637 dispatchCommand(mxComponent
, ".uno:GoToStartOfDoc", {});
3638 pWrtShell
->Insert("a");
3639 pWrtShell
->AutoCorrect(corr
, ' ');
3640 sReplaced
= "A tset test end. Word ";
3641 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3642 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3645 void SwUiWriterTest4::testRedlineAutoCorrect2()
3647 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "redline-autocorrect2.fodt");
3648 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3650 dispatchCommand(mxComponent
, ".uno:GoToEndOfDoc", {});
3652 // show tracked deletion
3653 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
3654 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
3655 pWrtShell
->SetRedlineFlags(nMode
);
3656 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
3658 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3659 pWrtShell
->Insert("...");
3660 pWrtShell
->AutoCorrect(corr
, ' ');
3661 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3663 // This was "LoremLorem,โฆ," (duplicating the deleted comma, but without deletion)
3664 // Don't replace, if a redline starts or ends within the text.
3665 OUString sReplaced
= "Lorem,... ";
3666 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3667 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3670 pWrtShell
->Insert("Lorem,...");
3671 pWrtShell
->AutoCorrect(corr
, ' ');
3672 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3673 sReplaced
= u
"Lorem,... Lorem,โฆ ";
3674 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3677 void SwUiWriterTest4::testEmojiAutoCorrect()
3679 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "redline-autocorrect2.fodt");
3680 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3682 // Emoji replacement (:snowman: -> โ)
3684 // without change tracking
3685 CPPUNIT_ASSERT(!(pWrtShell
->GetRedlineFlags() & RedlineFlags::On
));
3686 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3687 pWrtShell
->Insert(":snowman");
3688 pWrtShell
->AutoCorrect(corr
, ':');
3689 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3690 OUString sReplaced
= u
"โLorem,";
3691 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3692 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3694 // with change tracking (showing redlines)
3695 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
3696 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
3697 pWrtShell
->SetRedlineFlags(nMode
);
3698 CPPUNIT_ASSERT(nMode
& RedlineFlags::On
);
3699 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
3701 pWrtShell
->Insert(":snowman");
3702 pWrtShell
->AutoCorrect(corr
, ':');
3703 sReplaced
= u
"โโLorem,";
3704 nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3706 // tdf#140674 This was ":snowman:" instead of autocorrect
3707 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3710 void SwUiWriterTest4::testTdf108423()
3712 SwDoc
* pDoc
= createSwDoc();
3713 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3714 // testing autocorrect of i' -> I' on start of first paragraph
3715 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3716 pWrtShell
->Insert("i");
3717 const sal_Unicode cChar
= '\'';
3718 pWrtShell
->AutoCorrect(corr
, cChar
);
3719 // The word "i" should be capitalized due to autocorrect, followed by a typographical apostrophe
3720 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3721 OUString
sIApostrophe(u
"I\u2019");
3722 CPPUNIT_ASSERT_EQUAL(sIApostrophe
,
3723 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3724 pWrtShell
->Insert(" i");
3725 pWrtShell
->AutoCorrect(corr
, cChar
);
3726 OUString
sText(sIApostrophe
+ u
" " + sIApostrophe
);
3727 CPPUNIT_ASSERT_EQUAL(sText
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3730 void SwUiWriterTest4::testTdf106164()
3732 SwDoc
* pDoc
= createSwDoc();
3733 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3734 // testing autocorrect of we're -> We're on start of first paragraph
3735 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3736 pWrtShell
->Insert(u
"we\u2019re");
3737 const sal_Unicode cChar
= ' ';
3738 pWrtShell
->AutoCorrect(corr
, cChar
);
3739 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3740 CPPUNIT_ASSERT_EQUAL(OUString(u
"We\u2019re "),
3741 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3744 void SwUiWriterTest4::testTdf54409()
3746 SwDoc
* pDoc
= createSwDoc();
3747 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3748 // testing autocorrect of "tset -> "test with typographical double quotation mark U+201C
3749 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3750 pWrtShell
->Insert(u
"\u201Ctset");
3751 const sal_Unicode cChar
= ' ';
3752 pWrtShell
->AutoCorrect(corr
, cChar
);
3753 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3754 OUString
sReplaced(u
"\u201Ctest ");
3755 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3756 // testing autocorrect of test" -> test" with typographical double quotation mark U+201D
3757 pWrtShell
->Insert(u
"and tset\u201D");
3758 pWrtShell
->AutoCorrect(corr
, cChar
);
3759 OUString
sReplaced2(sReplaced
+ u
"and test\u201D ");
3760 CPPUNIT_ASSERT_EQUAL(sReplaced2
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3761 // testing autocorrect of "tset" -> "test" with typographical double quotation mark U+201C and U+201D
3762 pWrtShell
->Insert(u
"\u201Ctset\u201D");
3763 pWrtShell
->AutoCorrect(corr
, cChar
);
3764 OUString
sReplaced3(sReplaced2
+ u
"\u201Ctest\u201D ");
3765 CPPUNIT_ASSERT_EQUAL(sReplaced3
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3768 void SwUiWriterTest4::testTdf38394()
3770 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf38394.fodt");
3771 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3772 // testing autocorrect of French l'" -> l'ยซ (instead of l'ยป)
3773 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3774 pWrtShell
->Insert(u
"l\u2019");
3775 const sal_Unicode cChar
= '"';
3776 pWrtShell
->AutoCorrect(corr
, cChar
);
3777 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3778 OUString
sReplaced(u
"l\u2019ยซย ");
3779 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3780 // tdf#132301 autocorrect of qu'ยซ
3781 pWrtShell
->Insert(u
" qu\u2019");
3782 pWrtShell
->AutoCorrect(corr
, cChar
);
3783 sReplaced
+= u
" qu\u2019ยซย ";
3784 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3787 void SwUiWriterTest4::testTdf59666()
3789 SwDoc
* pDoc
= createSwDoc();
3790 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3791 // testing missing autocorrect of single Greek letters
3792 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3793 pWrtShell
->Insert(u
"\u03C0");
3794 const sal_Unicode cChar
= ' ';
3795 pWrtShell
->AutoCorrect(corr
, cChar
);
3796 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3797 CPPUNIT_ASSERT_EQUAL(OUString(u
"\u03C0 "),
3798 static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3801 void SwUiWriterTest4::testTdf133524()
3803 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf133524.fodt");
3804 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3805 // 1. Testing autocorrect of >> and <<
3806 // Example: ยปwordยซ
3807 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3809 pWrtShell
->Insert(u
">");
3810 pWrtShell
->AutoCorrect(corr
, '>');
3811 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3812 OUString
sReplaced(u
"ยป");
3813 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3815 pWrtShell
->Insert(u
"word<");
3816 pWrtShell
->AutoCorrect(corr
, '<');
3817 sReplaced
+= u
"wordยซ";
3818 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3819 // 2. Testing autocorrect of " to >> and << inside โ...โ
3820 // Example: โSentence and ยปwordยซ.โ
3821 // opening primary level quote
3822 pWrtShell
->Insert(u
" ");
3823 pWrtShell
->AutoCorrect(corr
, '"');
3824 sReplaced
+= u
" โ";
3825 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3826 // opening second level quote
3827 pWrtShell
->Insert(u
"Sentence and ");
3828 pWrtShell
->AutoCorrect(corr
, '"');
3829 sReplaced
+= u
"Sentence and ยป";
3830 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3831 // closing second level quote
3832 pWrtShell
->Insert(u
"word");
3833 pWrtShell
->AutoCorrect(corr
, '"');
3834 sReplaced
+= u
"wordยซ";
3835 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3836 // closing primary level quote
3837 pWrtShell
->Insert(u
".");
3838 pWrtShell
->AutoCorrect(corr
, '"');
3839 sReplaced
+= u
".โ";
3840 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3841 // tdf#134940 avoid premature replacement of "--" in "-->"
3842 pWrtShell
->Insert(u
" --");
3843 pWrtShell
->AutoCorrect(corr
, '>');
3844 OUString
sReplaced2(sReplaced
+ u
" -->");
3845 // This was "โ>" instead of "-->"
3846 CPPUNIT_ASSERT_EQUAL(sReplaced2
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3847 pWrtShell
->AutoCorrect(corr
, ' ');
3848 sReplaced
+= u
" โ ";
3849 // This was "โ>" instead of "โ"
3850 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3853 void SwUiWriterTest4::testTdf133524_Romanian()
3855 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf133524_ro.fodt");
3856 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3857 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3858 // 1. Testing autocorrect of " to << and >> inside โ...โ
3859 // Example: โSentence and ยซwordยป.โ
3860 // opening primary level quote
3861 pWrtShell
->AutoCorrect(corr
, '"');
3862 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3863 OUString
sReplaced(u
"โ");
3864 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3865 // opening second level quote
3866 pWrtShell
->Insert(u
"Sentence and ");
3867 pWrtShell
->AutoCorrect(corr
, '"');
3868 sReplaced
+= u
"Sentence and ยซ";
3869 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3870 // closing second level quote
3871 pWrtShell
->Insert(u
"word");
3872 pWrtShell
->AutoCorrect(corr
, '"');
3873 sReplaced
+= u
"wordยป";
3874 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3875 // closing primary level quote
3876 pWrtShell
->Insert(u
".");
3877 pWrtShell
->AutoCorrect(corr
, '"');
3878 sReplaced
+= u
".โ";
3879 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3880 // 2. Testing recognition of closing double quotation mark โ
3881 pWrtShell
->Insert(u
" ");
3882 pWrtShell
->AutoCorrect(corr
, '"');
3883 sReplaced
+= u
" โ";
3884 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3885 // 3. Testing recognition of alternative closing double quotation mark โ
3886 pWrtShell
->Insert(u
"Alternative.โ ");
3887 pWrtShell
->AutoCorrect(corr
, '"');
3888 sReplaced
+= u
"Alternative.โ โ";
3889 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3892 void SwUiWriterTest4::testTdf128860()
3894 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf128860.fodt");
3895 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3896 // Second level ending quote: โword' -> ,wordโ
3897 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3898 pWrtShell
->Insert(u
"โword");
3899 pWrtShell
->AutoCorrect(corr
, '\'');
3900 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3901 OUString
sReplaced(u
"โwordโ");
3902 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3903 // Us apostrophe without preceding starting quote: word' -> wordโ
3904 pWrtShell
->Insert(u
" word");
3905 pWrtShell
->AutoCorrect(corr
, '\'');
3906 sReplaced
+= u
" wordโ";
3907 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3908 // But only after letters: word.' -> word.โ
3909 pWrtShell
->Insert(u
" word.");
3910 pWrtShell
->AutoCorrect(corr
, '\'');
3911 sReplaced
+= u
" word.โ";
3912 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3915 void SwUiWriterTest4::testTdf123786()
3917 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf123786.fodt");
3918 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3919 // Second level ending quote: โword' -> โwordโ
3920 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3921 pWrtShell
->Insert(u
"โัะปะพะฒะพ");
3922 pWrtShell
->AutoCorrect(corr
, '\'');
3923 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3924 OUString
sReplaced(u
"โัะปะพะฒะพโ");
3925 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3926 // Us apostrophe without preceding starting quote: word' -> wordโ
3927 pWrtShell
->Insert(u
" ัะปะพะฒะพ");
3928 pWrtShell
->AutoCorrect(corr
, '\'');
3929 sReplaced
+= u
" ัะปะพะฒะพโ";
3930 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3931 // But only after letters: word.' -> word.โ
3932 pWrtShell
->Insert(u
" ัะปะพะฒะพ.");
3933 pWrtShell
->AutoCorrect(corr
, '\'');
3934 sReplaced
+= u
" ัะปะพะฒะพ.โ";
3935 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3938 void SwUiWriterTest4::testTdf133589()
3940 // Hungarian test document with right-to-left paragraph setting
3941 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf133589.fodt");
3942 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
3943 // translitere words to Old Hungarian
3944 SwAutoCorrect
corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
3945 pWrtShell
->Insert(u
"szรฉkely");
3946 pWrtShell
->AutoCorrect(corr
, ' ');
3947 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetNode().GetIndex();
3948 OUString
sReplaced(u
"๐ณฅ๐ณ๐ณ๐ณ๐ณ ");
3949 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3950 // disambiguate consonants: asszony -> asz|szony
3951 pWrtShell
->Insert(u
"asszony");
3952 pWrtShell
->AutoCorrect(corr
, ' ');
3953 sReplaced
+= u
"๐ณ๐ณฅ๐ณฅ๐ณ๐ณ ";
3954 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3955 // disambiguate consonants: kosszarv -> kos|szarv
3956 // (add explicit ZWSP temporarily for consonant disambiguation, because the requested
3957 // hu_HU hyphenation dictionary isn't installed on all testing platform)
3958 // pWrtShell->Insert(u"kosszarv");
3959 pWrtShell
->Insert(u
"kosโszarv");
3960 pWrtShell
->AutoCorrect(corr
, ' ');
3961 sReplaced
+= u
"๐ณ๐ณ๐ณค๐ณฅ๐ณ๐ณข๐ณฎ ";
3962 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3963 // transliterate numbers to Old Hungarian
3964 pWrtShell
->Insert(u
"2020");
3965 pWrtShell
->AutoCorrect(corr
, ' ');
3966 sReplaced
+= u
"๐ณบ๐ณบ๐ณฟ๐ณผ๐ณผ ";
3967 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3969 // tdf#147546 transliterate punctuation marks
3972 pWrtShell
->Insert(u
"Kรฉrdลjel");
3973 pWrtShell
->AutoCorrect(corr
, '?');
3974 sReplaced
+= u
"๐ฒ๐ณ๐ณข๐ณ๐ณ๐ณ๐ณ๐ณ";
3975 OUString
sReplaced2(sReplaced
+ "?");
3976 CPPUNIT_ASSERT_EQUAL(sReplaced2
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3977 pWrtShell
->AutoCorrect(corr
, ' ');
3978 sReplaced
+= u
"โธฎ ";
3979 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3981 pWrtShell
->Insert(u
"Vesszล");
3982 pWrtShell
->AutoCorrect(corr
, ',');
3983 sReplaced
+= u
"๐ฒฎ๐ณ๐ณฅ๐ณฅ๐ณ";
3984 sReplaced2
= sReplaced
+ ",";
3985 CPPUNIT_ASSERT_EQUAL(sReplaced2
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3986 pWrtShell
->AutoCorrect(corr
, ' ');
3987 sReplaced
+= u
"โน ";
3988 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3990 pWrtShell
->Insert(u
"pontosvesszล");
3991 pWrtShell
->AutoCorrect(corr
, ';');
3992 sReplaced
+= u
"๐ณ ๐ณ๐ณ๐ณฆ๐ณ๐ณค๐ณฎ๐ณ๐ณฅ๐ณฅ๐ณ";
3993 sReplaced2
= sReplaced
+ ";";
3994 CPPUNIT_ASSERT_EQUAL(sReplaced2
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3995 pWrtShell
->AutoCorrect(corr
, ' ');
3996 sReplaced
+= u
"โ ";
3997 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
3999 pWrtShell
->Insert(u
"โidรฉzลjelโ");
4000 pWrtShell
->AutoCorrect(corr
, ' ');
4001 sReplaced
+= u
"โน๐ณ๐ณ๐ณ๐ณฏ๐ณ๐ณ๐ณ๐ณโ ";
4002 CPPUNIT_ASSERT_EQUAL(sReplaced
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
4005 void SwUiWriterTest4::testTdf143176()
4007 // Hungarian test document with right-to-left paragraph setting
4008 createSwDoc(DATA_DIRECTORY
, "tdf143176.fodt");
4010 // transliterate the document to Old Hungarian (note: it only works
4011 // with right-to-left text direction and Default Paragraph Style)
4012 dispatchCommand(mxComponent
, ".uno:AutoFormatApply", {});
4014 // This was the original "Lorem ipsum..."
4015 CPPUNIT_ASSERT_EQUAL(OUString(u
"๐ฒ๐ณ๐ณข๐ณ๐ณ ๐ณ๐ณ ๐ณค๐ณช๐ณ ๐ณ๐ณ๐ณ๐ณ๐ณข "
4016 u
"๐ณค๐ณ๐ณฆ ๐ณ๐ณ๐ณ๐ณฆโน"),
4017 getParagraph(1)->getString());
4018 CPPUNIT_ASSERT_EQUAL(OUString(u
"๐ณ๐ณ๐ณ๐ณค๐ณ๐ณ๐ณฆ๐ณ๐ณฆ๐ณช๐ณข "
4019 u
"๐ณ๐ณ๐ณ๐ณ ๐ณ๐ณค๐ณ๐ณ๐ณ๐ณ ๐ณ๐ณ๐ณ๐ณฆ."),
4020 getParagraph(2)->getString());
4023 void SwUiWriterTest4::testInsertLongDateFormat()
4025 // only for Hungarian, yet
4026 createSwDoc(DATA_DIRECTORY
, "tdf133524.fodt");
4027 dispatchCommand(mxComponent
, ".uno:InsertDateField", {});
4028 // Make sure that the document starts with a field now, and its expanded string value contains space
4029 const uno::Reference
<text::XTextRange
> xField
= getRun(getParagraph(1), 1);
4030 CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty
<OUString
>(xField
, "TextPortionType"));
4031 // the date format was "YYYY-MM-DD", but now "YYYY. MMM DD."
4032 CPPUNIT_ASSERT(xField
->getString().indexOf(" ") > -1);
4035 void SwUiWriterTest4::testTdf129270()
4037 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf129270.odt");
4038 CPPUNIT_ASSERT(pDoc
);
4039 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
4040 CPPUNIT_ASSERT(pWrtShell
);
4041 SwXTextDocument
* pXTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
4042 CPPUNIT_ASSERT(pXTextDocument
);
4044 // Go to document end
4045 pWrtShell
->SttEndDoc(/*bStt=*/false);
4048 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
4049 Scheduler::ProcessEventsToIdle();
4051 // Numbering for previous outline should remain the same "2"
4052 CPPUNIT_ASSERT_EQUAL(OUString("2"), getProperty
<OUString
>(getParagraph(4), "ListLabelString"));
4054 // Numbering for newly created outline should be "2.1"
4055 CPPUNIT_ASSERT_EQUAL(OUString("2.1"),
4056 getProperty
<OUString
>(getParagraph(5), "ListLabelString"));
4059 void SwUiWriterTest4::testInsertPdf()
4061 auto pPdfium
= vcl::pdf::PDFiumLibrary::get();
4069 // insert the PDF into the document
4070 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
4072 uno::Any(m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "hello-world.pdf") } }));
4073 dispatchCommand(mxComponent
, ".uno:InsertGraphic", aArgs
);
4075 // Save and load cycle
4076 reload("writer8", "testInsertPdf.odt");
4078 uno::Reference
<drawing::XShape
> xShape
= getShape(1);
4079 // Assert that we have a replacement graphics
4080 auto xReplacementGraphic
4081 = getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, "ReplacementGraphic");
4082 CPPUNIT_ASSERT(xReplacementGraphic
.is());
4084 auto xGraphic
= getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, "Graphic");
4085 CPPUNIT_ASSERT(xGraphic
.is());
4086 // Assert that the graphic is a PDF
4087 CPPUNIT_ASSERT_EQUAL(OUString("application/pdf"), getProperty
<OUString
>(xGraphic
, "MimeType"));
4090 void SwUiWriterTest4::testTdf143760WrapContourToOff()
4092 // Actually, this is an ooxmlexport test. It is here because here is a ready environment
4093 // to change a shape by dispatchCommand.
4094 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf143760_ContourToWrapOff.docx");
4095 CPPUNIT_ASSERT(pDoc
);
4096 CPPUNIT_ASSERT_EQUAL(true, getProperty
<bool>(getShape(1), "SurroundContour"));
4099 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
4100 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
4101 SdrObject
* pObject
= pPage
->GetObj(0);
4102 CPPUNIT_ASSERT(pObject
);
4103 SdrView
* pView
= pWrtShell
->GetDrawView();
4104 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
4107 dispatchCommand(mxComponent
, ".uno:WrapOff", {});
4108 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), "SurroundContour"));
4110 // Without fix this had failed, because the shape was written to file with contour.
4111 reload("Office Open XML Text", "tdf143760_ContourToWrapOff.docx");
4112 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), "SurroundContour"));
4115 void SwUiWriterTest4::testHatchFill()
4119 // Add a rectangle shape to the document.
4120 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
4121 uno::Reference
<drawing::XShape
> xShape(
4122 xFactory
->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY
);
4123 xShape
->setSize(awt::Size(10000, 10000));
4124 xShape
->setPosition(awt::Point(1000, 1000));
4125 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
4126 xShapeProps
->setPropertyValue("FillStyle", uno::makeAny(drawing::FillStyle_HATCH
));
4127 xShapeProps
->setPropertyValue("FillHatchName", uno::makeAny(OUString("Black 0 Degrees")));
4128 xShapeProps
->setPropertyValue("FillBackground", uno::makeAny(false));
4129 xShapeProps
->setPropertyValue("FillTransparence", uno::makeAny(sal_Int32(30)));
4130 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
4131 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
4132 xDrawPage
->add(xShape
);
4134 // Save it as DOCX and load it again.
4135 reload("Office Open XML Text", "hatchFill.docx");
4136 CPPUNIT_ASSERT_EQUAL(1, getShapes());
4138 // tdf#127989 Without fix this had failed, because the background of the hatch was not set as 'no background'.
4139 CPPUNIT_ASSERT(!getProperty
<bool>(getShape(1), "FillBackground"));
4141 // tdf#146822 Without fix this had failed, because the transparency value of the hatch was not exported.
4142 CPPUNIT_ASSERT_EQUAL(sal_Int32(30), getProperty
<sal_Int32
>(getShape(1), "FillTransparence"));
4145 void SwUiWriterTest4::testTdf62032ApplyStyle()
4147 SwDoc
* pDoc
= createSwDoc(DATA_DIRECTORY
, "tdf62032_apply_style.odt");
4148 SwWrtShell
* pWrtSh
= pDoc
->GetDocShell()->GetWrtShell();
4150 pWrtSh
->Down(/*bSelect=*/false);
4152 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
4153 { "Style", uno::Any(OUString("A 2")) },
4154 { "FamilyName", uno::Any(OUString("ParagraphStyles")) },
4156 dispatchCommand(mxComponent
, ".uno:StyleApply", aPropertyValues
);
4158 // Without the fix in place, it fails with:
4161 CPPUNIT_ASSERT_EQUAL(OUString("1.1"),
4162 getProperty
<OUString
>(getParagraph(2), "ListLabelString").trim());
4165 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest4
);
4166 CPPUNIT_PLUGIN_IMPLEMENT();
4168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */