android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / qa / extras / uiwriter / uiwriter4.cxx
blobd5acadd555698d2d4cafb244d8cd80fd55fe7814
2 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
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/.
9 */
11 #include <com/sun/star/drawing/FillStyle.hpp>
12 #include <com/sun/star/style/CaseMap.hpp>
13 #include <swmodeltestbase.hxx>
14 #include <ndtxt.hxx>
15 #include <wrtsh.hxx>
16 #include <drawdoc.hxx>
17 #include <redline.hxx>
18 #include <dcontact.hxx>
19 #include <view.hxx>
20 #include <IDocumentSettingAccess.hxx>
22 #include <editeng/brushitem.hxx>
23 #include <svx/svdpage.hxx>
24 #include <svx/svdview.hxx>
26 #include <i18nutil/transliteration.hxx>
27 #include <IDocumentDrawModelAccess.hxx>
28 #include <IDocumentRedlineAccess.hxx>
29 #include <UndoManager.hxx>
30 #include <tblafmt.hxx>
32 #include <com/sun/star/text/XTextField.hpp>
33 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
34 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
35 #include <com/sun/star/text/XPageCursor.hpp>
36 #include <com/sun/star/text/XParagraphAppend.hpp>
37 #include <o3tl/cppunittraitshelper.hxx>
38 #include <osl/thread.hxx>
39 #include <hyp.hxx>
40 #include <swdtflvr.hxx>
41 #include <comphelper/propertysequence.hxx>
42 #include <sfx2/classificationhelper.hxx>
43 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
44 #include <sfx2/viewfrm.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <editeng/unolingu.hxx>
47 #include <vcl/scheduler.hxx>
48 #include <config_fonts.h>
49 #include <unotxdoc.hxx>
50 #include <unotools/transliterationwrapper.hxx>
51 #include <officecfg/Office/Writer.hxx>
53 namespace
55 void lcl_selectCharacters(SwPaM& rPaM, sal_Int32 first, sal_Int32 end)
57 rPaM.GetPoint()->nContent.Assign(rPaM.GetPointContentNode(), first);
58 rPaM.SetMark();
59 rPaM.GetPoint()->nContent.Assign(rPaM.GetPointContentNode(), end);
61 } //namespace
63 class SwUiWriterTest4 : public SwModelTestBase
65 public:
66 SwUiWriterTest4()
67 : SwModelTestBase("/sw/qa/extras/uiwriter/data/")
71 void mergeDocs(const char* aDestDoc, const char* aInsertDoc);
74 void SwUiWriterTest4::mergeDocs(const char* aDestDoc, const char* aInsertDoc)
76 createSwDoc(aDestDoc);
78 // set a page cursor into the end of the document
79 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
80 uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
81 xModel->getCurrentController(), uno::UNO_QUERY);
82 uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(),
83 uno::UNO_QUERY);
84 xCursor->jumpToEndOfPage();
86 // insert the same document at current cursor position
88 const OUString insertFileid = createFileURL(OUString::createFromAscii(aInsertDoc));
89 uno::Sequence<beans::PropertyValue> aPropertyValues(
90 comphelper::InitPropertySequence({ { "Name", uno::Any(insertFileid) } }));
91 dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
95 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96515)
97 // Enable hide whitespace mode.
98 createSwDoc();
99 SwDoc* pDoc = getSwDoc();
100 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
101 SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
102 aViewOptions.SetHideWhitespaceMode(true);
103 pWrtShell->ApplyViewOptions(aViewOptions);
104 CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsWhitespaceHidden());
106 // Insert a new paragraph at the end of the document.
107 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
108 uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(),
109 uno::UNO_QUERY);
110 xParagraphAppend->finishParagraph(uno::Sequence<beans::PropertyValue>());
111 calcLayout();
113 // This was 2, a new page was created for the new paragraph.
114 CPPUNIT_ASSERT_EQUAL(1, getPages());
117 static OUString lcl_translitTest(SwDoc& rDoc, const SwPaM& rPaM, TransliterationFlags const nType)
119 utl::TransliterationWrapper aTrans(::comphelper::getProcessComponentContext(), nType);
120 rDoc.getIDocumentContentOperations().TransliterateText(rPaM, aTrans);
121 //SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
122 return rPaM.GetMarkNode().GetTextNode()->GetText();
125 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf146449)
127 createSwDoc("tdf146449.odt");
129 auto pDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
130 CPPUNIT_ASSERT(pDoc);
131 auto pShell = pDoc->GetDocShell()->GetFEShell();
132 CPPUNIT_ASSERT(pShell);
134 auto xTextBox = getShapeByName(u"Frame1");
135 auto pObject = SdrObject::getSdrObjectFromXShape(xTextBox);
137 CPPUNIT_ASSERT(pShell->SelectObj(Point(), 0, pObject));
139 dispatchCommand(mxComponent, ".uno:Cut", {});
141 dispatchCommand(mxComponent, ".uno:Undo", {});
143 uno::Reference<beans::XPropertySet> xShapeProps(xTextBox, uno::UNO_QUERY);
144 uno::Reference<beans::XPropertySet> xFrameProps(xShapeProps->getPropertyValue("TextBoxContent"),
145 uno::UNO_QUERY);
147 const auto& nShapeZOrder = pObject->GetOrdNum();
148 const auto& nFrameZOrder = xFrameProps->getPropertyValue("ZOrder");
150 CPPUNIT_ASSERT_MESSAGE("Wrong Zorder!", nShapeZOrder < nFrameZOrder.get<sal_uInt32>());
153 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf49033)
155 createSwDoc();
156 SwDoc* pDoc = getSwDoc();
157 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
159 // Insert the test text at the end of the document.
160 pWrtShell->SttEndDoc(/*bStt=*/false);
161 pWrtShell->Insert("Mary Jones met joe Smith. Time Passed.");
162 pWrtShell->StartOfSection();
163 SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
165 using TF = TransliterationFlags;
167 /* -- Test behavior when there is no selection -- */
169 /* Move cursor between the 't' and the ' ' after 'met', nothing should change */
170 for (int i = 0; i < 14; i++)
171 pCursor->Move(fnMoveForward);
173 CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
174 CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
175 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
176 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
177 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
178 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
179 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
180 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
181 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
182 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
184 /* Move cursor between the 'h' and the '.' after 'Smith', nothing should change */
185 for (int i = 0; i < 10; i++)
186 pCursor->Move(fnMoveForward);
188 CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
189 CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
190 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
191 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
192 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
193 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
194 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
195 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
196 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
197 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
199 /* Move cursor between the 'm' and the 'e' in 'met' */
200 for (int i = 0; i < 12; i++)
201 pCursor->Move(fnMoveBackward);
203 CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
204 CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
205 CPPUNIT_ASSERT_EQUAL(OUString("Mary jones met joe smith. Time Passed."),
206 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
208 /* Undo the sentence case change to reset for the following tests */
209 pDoc->GetIDocumentUndoRedo().Undo();
211 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones Met joe Smith. Time Passed."),
212 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
213 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones MET joe Smith. Time Passed."),
214 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
215 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
216 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
218 /* -- Test behavior when there is a selection that does not cross a word boundary -- */
219 pCursor->Move(fnMoveBackward);
220 pWrtShell->SelWrd();
221 CPPUNIT_ASSERT_EQUAL(true, pCursor->HasMark());
222 CPPUNIT_ASSERT_EQUAL(true, pWrtShell->IsSelection());
224 OUString currentSelectedText;
225 pWrtShell->GetSelectedText(currentSelectedText);
226 CPPUNIT_ASSERT_EQUAL(OUString("met"), currentSelectedText);
227 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones Met joe Smith. Time Passed."),
228 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
229 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones Met joe Smith. Time Passed."),
230 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
231 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones MET joe Smith. Time Passed."),
232 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
233 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
234 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
236 /* -- Test behavior when there is a selection that does not begin at a word boundary: "et" -- */
237 for (int i = 0; i < 2; i++)
238 pCursor->Move(fnMoveBackward);
239 pCursor->SetMark();
240 for (int i = 0; i < 2; i++)
241 pCursor->Move(fnMoveForward);
242 pWrtShell->GetSelectedText(currentSelectedText);
243 CPPUNIT_ASSERT_EQUAL(OUString("et"), currentSelectedText);
244 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones mEt joe Smith. Time Passed."),
245 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
246 pDoc->GetIDocumentUndoRedo().Undo();
247 CPPUNIT_ASSERT_EQUAL(OUString("et"), currentSelectedText);
248 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones mEt joe Smith. Time Passed."),
249 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
250 pDoc->GetIDocumentUndoRedo().Undo();
251 CPPUNIT_ASSERT_EQUAL(OUString("et"), currentSelectedText);
252 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones mET joe Smith. Time Passed."),
253 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
254 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
255 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
257 /* -- Test behavior when there is a selection that crosses a word boundary -- */
258 for (int i = 0; i < 7; i++)
259 pCursor->Move(fnMoveBackward);
260 pCursor->SetMark();
261 for (int i = 0; i < 14; i++)
262 pCursor->Move(fnMoveForward);
264 pWrtShell->GetSelectedText(currentSelectedText);
265 CPPUNIT_ASSERT_EQUAL(OUString("nes met joe Sm"), currentSelectedText);
266 CPPUNIT_ASSERT_EQUAL(OUString("Mary JoNes met joe smith. Time Passed."),
267 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
268 CPPUNIT_ASSERT_EQUAL(OUString("Mary JoNes Met Joe Smith. Time Passed."),
269 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
270 CPPUNIT_ASSERT_EQUAL(OUString("Mary JoNES MET JOE SMith. Time Passed."),
271 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
272 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe smith. Time Passed."),
273 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
275 /* Reset the 's' to upper-case for the next test */
276 for (int i = 0; i < 2; i++)
277 pCursor->Move(fnMoveBackward);
278 pCursor->SetMark();
279 pCursor->Move(fnMoveForward);
280 pDoc->getIDocumentContentOperations().ReplaceRange(*pCursor, OUString('S'), false);
282 /* -- Test behavior when there is a selection that crosses a sentence boundary -- */
283 for (int i = 0; i < 4; i++)
284 pCursor->Move(fnMoveBackward);
285 pCursor->SetMark();
286 for (int i = 0; i < 22; i++)
287 pCursor->Move(fnMoveForward);
288 pWrtShell->GetSelectedText(currentSelectedText);
289 CPPUNIT_ASSERT_EQUAL(OUString("joe Smith. Time Passed"), currentSelectedText);
291 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met Joe smith. Time passed."),
292 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
294 /* Undo the sentence case change to reset for the following tests */
295 pDoc->GetIDocumentUndoRedo().Undo();
297 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met Joe Smith. Time Passed."),
298 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
299 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met JOE SMITH. TIME PASSED."),
300 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
301 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe smith. time passed."),
302 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
304 /* Undo the previous changes to reset for the following tests */
305 pDoc->GetIDocumentUndoRedo().Undo();
306 pDoc->GetIDocumentUndoRedo().Undo();
307 pDoc->GetIDocumentUndoRedo().Undo();
309 /* -- Test behavior when there is a selection that does not reach end of sentence -- */
310 for (int i = 0; i < 37; i++)
311 pCursor->Move(fnMoveBackward);
312 pCursor->SetMark();
313 for (int i = 0; i < 10; i++)
314 pCursor->Move(fnMoveForward);
315 pWrtShell->GetSelectedText(currentSelectedText);
316 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones"), currentSelectedText);
317 CPPUNIT_ASSERT_EQUAL(OUString("Mary jones met joe Smith. Time Passed."),
318 lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
319 CPPUNIT_ASSERT_EQUAL(OUString("Mary Jones met joe Smith. Time Passed."),
320 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
321 CPPUNIT_ASSERT_EQUAL(OUString("MARY JONES met joe Smith. Time Passed."),
322 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
323 CPPUNIT_ASSERT_EQUAL(OUString("mary jones met joe Smith. Time Passed."),
324 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
327 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf147196)
329 using TF = TransliterationFlags;
330 createSwDoc();
331 SwDoc* pDoc = getSwDoc();
332 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
334 // Insert the test text at the end of the document.
335 pWrtShell->SttEndDoc(/*bStt=*/false);
336 pWrtShell->Insert(
337 "2.2 Publication of information - CAA\nSection 4.2 of a CA\'s Certificate Policy and/or "
338 "Certification Practice Statement SHALL state the CA\'s policy or practice on processing "
339 "CAA Records for Fully Qualified Domain Names; that policy shall be consistent with these "
340 "Requirements. \n\nIt shall clearly specify the set of Issuer Domain Names that the CA "
341 "recognises in CAA \"issue\" or \"issuewild\" records as permitting it to issue. The CA "
342 "SHALL log all actions taken, if any, consistent with its processing practice.");
344 pWrtShell->StartOfSection();
345 SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
346 pCursor->SetMark();
347 for (int i = 0; i < 510; i++)
349 pCursor->Move(fnMoveForward);
351 CPPUNIT_ASSERT_EQUAL(
352 OUString("2.2 Publication Of Information - Caa\nSection 4.2 Of A Ca\'s Certificate Policy "
353 "And/Or Certification Practice Statement Shall State The Ca\'s Policy Or Practice "
354 "On Processing Caa Records For Fully Qualified Domain Names; That Policy Shall Be "
355 "Consistent With These Requirements. \n\nIt Shall Clearly Specify The Set Of "
356 "Issuer Domain Names That The Ca Recognises In Caa \"Issue\" Or \"Issuewild\" "
357 "Records As Permitting It To Issue. The Ca Shall Log All Actions Taken, If Any, "
358 "Consistent With Its Processing Practice."),
359 lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
362 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf148148)
364 using TF = TransliterationFlags;
365 createSwDoc();
366 SwDoc* pDoc = getSwDoc();
367 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
369 pWrtShell->SttEndDoc(/*bStt=*/false);
370 pWrtShell->Insert(" text");
372 /* Test what happens when node contains text but selection does not contain any text */
373 pWrtShell->StartOfSection();
374 SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
375 pCursor->SetMark();
376 for (int i = 0; i < 3; i++)
378 pCursor->Move(fnMoveForward);
380 CPPUNIT_ASSERT_EQUAL(OUString(" text"), lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
381 CPPUNIT_ASSERT_EQUAL(OUString(" text"), lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
382 CPPUNIT_ASSERT_EQUAL(OUString(" text"),
383 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
384 CPPUNIT_ASSERT_EQUAL(OUString(" text"),
385 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
387 /* Test what happens when node contains text but selection does not contain any text */
388 createSwDoc();
389 pDoc = getSwDoc();
390 pWrtShell = pDoc->GetDocShell()->GetWrtShell();
391 pWrtShell->SttEndDoc(/*bStt=*/false);
392 pWrtShell->Insert("text ");
394 pWrtShell->StartOfSection();
395 pCursor = pWrtShell->getShellCursor(false);
396 for (int i = 0; i < 4; i++)
398 pCursor->Move(fnMoveForward);
400 pCursor->SetMark();
401 for (int i = 0; i < 2; i++)
403 pCursor->Move(fnMoveForward);
406 CPPUNIT_ASSERT_EQUAL(OUString("text "), lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
407 CPPUNIT_ASSERT_EQUAL(OUString("text "), lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
408 CPPUNIT_ASSERT_EQUAL(OUString("text "),
409 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
410 CPPUNIT_ASSERT_EQUAL(OUString("text "),
411 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
413 /* Test what happens when node contains only non-word text but selection does not contain any text */
414 createSwDoc();
415 pDoc = getSwDoc();
416 pWrtShell = pDoc->GetDocShell()->GetWrtShell();
417 pWrtShell->SttEndDoc(/*bStt=*/false);
418 pWrtShell->Insert("-1 ");
420 pWrtShell->StartOfSection();
421 pCursor = pWrtShell->getShellCursor(false);
422 for (int i = 0; i < 2; i++)
424 pCursor->Move(fnMoveForward);
426 pCursor->SetMark();
427 for (int i = 0; i < 2; i++)
429 pCursor->Move(fnMoveForward);
432 CPPUNIT_ASSERT_EQUAL(OUString("-1 "), lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
433 CPPUNIT_ASSERT_EQUAL(OUString("-1 "), lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
434 CPPUNIT_ASSERT_EQUAL(OUString("-1 "),
435 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
436 CPPUNIT_ASSERT_EQUAL(OUString("-1 "),
437 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
439 createSwDoc();
440 pDoc = getSwDoc();
441 pWrtShell = pDoc->GetDocShell()->GetWrtShell();
442 pWrtShell->SttEndDoc(/*bStt=*/false);
443 pWrtShell->Insert(" -1");
445 pWrtShell->StartOfSection();
446 pCursor = pWrtShell->getShellCursor(false);
447 pCursor->SetMark();
448 for (int i = 0; i < 2; i++)
450 pCursor->Move(fnMoveForward);
453 CPPUNIT_ASSERT_EQUAL(OUString(" -1"), lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
454 CPPUNIT_ASSERT_EQUAL(OUString(" -1"), lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
455 CPPUNIT_ASSERT_EQUAL(OUString(" -1"),
456 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
457 CPPUNIT_ASSERT_EQUAL(OUString(" -1"),
458 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
460 /* Test what happens when node and selection contains only non-word text */
461 createSwDoc();
462 pDoc = getSwDoc();
463 pWrtShell = pDoc->GetDocShell()->GetWrtShell();
464 pWrtShell->SttEndDoc(/*bStt=*/false);
465 pWrtShell->Insert(" -1");
467 pWrtShell->StartOfSection();
468 pCursor = pWrtShell->getShellCursor(false);
469 pCursor->SetMark();
470 for (int i = 0; i < 5; i++)
472 pCursor->Move(fnMoveForward);
475 CPPUNIT_ASSERT_EQUAL(OUString(" -1"), lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
476 CPPUNIT_ASSERT_EQUAL(OUString(" -1"), lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
477 CPPUNIT_ASSERT_EQUAL(OUString(" -1"),
478 lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
479 CPPUNIT_ASSERT_EQUAL(OUString(" -1"),
480 lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
483 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96943)
485 // Enable hide whitespace mode.
486 createSwDoc("tdf96943.odt");
487 SwDoc* pDoc = getSwDoc();
488 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
489 SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
490 aViewOptions.SetHideWhitespaceMode(true);
491 pWrtShell->ApplyViewOptions(aViewOptions);
493 // Insert a new character at the end of the document.
494 pWrtShell->SttEndDoc(/*bStt=*/false);
495 pWrtShell->Insert("d");
497 // This was 2, a new page was created for the new layout line.
498 CPPUNIT_ASSERT_EQUAL(1, getPages());
501 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96536)
503 // Enable hide whitespace mode.
504 createSwDoc();
505 SwDoc* pDoc = getSwDoc();
506 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
507 SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
508 aViewOptions.SetHideWhitespaceMode(true);
509 pWrtShell->ApplyViewOptions(aViewOptions);
510 CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsWhitespaceHidden());
512 // Insert a page break and go back to the first page.
513 pWrtShell->InsertPageBreak();
514 pWrtShell->SttEndDoc(/*bStt=*/true);
515 calcLayout();
516 sal_Int32 nSingleParaPageHeight = parseDump("/root/page[1]/infos/bounds", "height").toInt32();
517 discardDumpedLayout();
519 // Insert a 2nd paragraph at the end of the first page, so the page height grows at least twice...
520 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
521 uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(),
522 uno::UNO_QUERY);
523 const uno::Reference<text::XTextRange> xInsertPos = getRun(getParagraph(1), 1);
524 xParagraphAppend->finishParagraphInsert(uno::Sequence<beans::PropertyValue>(), xInsertPos);
525 calcLayout();
526 CPPUNIT_ASSERT(parseDump("/root/page[1]/infos/bounds", "height").toInt32()
527 >= 2 * nSingleParaPageHeight);
528 discardDumpedLayout();
530 // ... and then delete the 2nd paragraph, which shrinks the page to the previous size.
531 uno::Reference<lang::XComponent> xParagraph(getParagraph(2), uno::UNO_QUERY);
532 xParagraph->dispose();
533 calcLayout();
534 CPPUNIT_ASSERT_EQUAL(nSingleParaPageHeight,
535 parseDump("/root/page[1]/infos/bounds", "height").toInt32());
538 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96479)
540 // We want to verify the empty input text field in the bookmark
541 static const OUString emptyInputTextField
542 = OUStringChar(CH_TXT_ATR_INPUTFIELDSTART) + OUStringChar(CH_TXT_ATR_INPUTFIELDEND);
544 createSwDoc();
545 SwDoc* pDoc = getSwDoc();
547 // So we can clean up all references for reload
549 // Append bookmark
550 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
551 SwPaM aPaM(aIdx);
552 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
553 sw::mark::IMark* pMark = rIDMA.makeMark(
554 aPaM, "original", IDocumentMarkAccess::MarkType::BOOKMARK, ::sw::mark::InsertMode::New);
555 CPPUNIT_ASSERT(!pMark->IsExpanded());
556 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
558 // Get helper objects
559 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
560 uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
562 // Create cursor from bookmark
563 uno::Reference<text::XTextContent> xTextContent(
564 xBookmarksSupplier->getBookmarks()->getByName("original"), uno::UNO_QUERY);
565 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
566 uno::Reference<text::XTextCursor> xCursor
567 = xRange->getText()->createTextCursorByRange(xRange);
568 CPPUNIT_ASSERT(xCursor->isCollapsed());
570 // Remove bookmark
571 xRange->getText()->removeTextContent(xTextContent);
572 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getBookmarksCount());
574 // Insert replacement bookmark
575 uno::Reference<text::XTextContent> xBookmarkNew(
576 xFactory->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
577 uno::Reference<container::XNamed> xBookmarkName(xBookmarkNew, uno::UNO_QUERY);
578 xBookmarkName->setName("replacement");
579 CPPUNIT_ASSERT(xCursor->isCollapsed());
580 // Force bookmark expansion
581 xCursor->getText()->insertString(xCursor, ".", true);
582 xCursor->getText()->insertTextContent(xCursor, xBookmarkNew, true);
583 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
584 auto mark = *(rIDMA.getBookmarksBegin());
585 CPPUNIT_ASSERT(mark->IsExpanded());
587 // Create and insert input textfield with some content
588 uno::Reference<text::XTextField> xTextField(
589 xFactory->createInstance("com.sun.star.text.TextField.Input"), uno::UNO_QUERY);
590 uno::Reference<text::XTextCursor> xCursorNew(
591 xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(
592 xBookmarkNew->getAnchor()));
593 CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
594 xCursorNew->getText()->insertTextContent(xCursorNew, xTextField, true);
595 xBookmarkNew = uno::Reference<text::XTextContent>(
596 xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
597 xCursorNew = xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(
598 xBookmarkNew->getAnchor());
599 CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
601 // Can't check the actual content of the text node via UNO
602 mark = *(rIDMA.getBookmarksBegin());
603 CPPUNIT_ASSERT(mark->IsExpanded());
604 SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
605 // Check for the actual bug, which didn't include CH_TXT_ATR_INPUTFIELDEND in the bookmark
606 CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
610 // Save and load cycle
611 // Actually not needed, but the bug symptom of a missing bookmark
612 // occurred because a broken bookmark was saved and loading silently
613 // dropped the broken bookmark!
614 saveAndReload("writer8");
615 pDoc = getSwDoc();
617 // Lookup "replacement" bookmark
618 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
619 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
620 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
621 CPPUNIT_ASSERT(xBookmarksSupplier->getBookmarks()->hasByName("replacement"));
623 uno::Reference<text::XTextContent> xTextContent(
624 xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
625 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
626 uno::Reference<text::XTextCursor> xCursor
627 = xRange->getText()->createTextCursorByRange(xRange);
628 CPPUNIT_ASSERT(!xCursor->isCollapsed());
630 // Verify bookmark content via text node / PaM
631 auto mark = *(rIDMA.getBookmarksBegin());
632 CPPUNIT_ASSERT(mark->IsExpanded());
633 SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
634 CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
638 // If you resave original document the bookmark will be changed from
640 // <text:p text:style-name="Standard">
641 // <text:bookmark-start text:name="test"/>
642 // <text:bookmark-end text:name="test"/>
643 // def
644 // </text:p>
646 // to
648 // <text:p text:style-name="Standard">
649 // <text:bookmark text:name="test"/>
650 // def
651 // </text:p>
653 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testBookmarkCollapsed)
655 // load document
656 createSwDoc("collapsed_bookmark.odt");
657 SwDoc* pDoc = getSwDoc();
658 CPPUNIT_ASSERT(pDoc);
660 // save original document
661 save("writer8");
663 // load only content.xml from the resaved document
664 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
666 const OString aPath("/office:document-content/office:body/office:text/text:p");
668 const int pos1 = getXPathPosition(pXmlDoc, aPath, "bookmark");
669 CPPUNIT_ASSERT_EQUAL(0, pos1); // found, and it is first
671 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
672 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
675 // 1. Open a new writer document
676 // 2. Enter the text "abcdef"
677 // 3. Select "abc"
678 // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
679 // 5. Open the navigator (F5)
680 // Select the bookmark "test" using the navigator.
681 // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
682 // 7. Save the document:
683 // <text:p text:style-name="Standard">
684 // <text:bookmark-start text:name="test"/>
685 // <text:bookmark-end text:name="test"/>
686 // def
687 // </text:p>
689 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkText)
691 // create document
693 // create a text document with "abcdef"
694 createSwDoc();
695 SwDoc* pDoc = getSwDoc();
698 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
699 SwPaM aPaM(aIdx);
700 pDoc->getIDocumentContentOperations().InsertString(aPaM, "abcdef");
703 // mark "abc" with "testBookmark" bookmark
705 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
706 SwPaM aPaM(aIdx);
708 lcl_selectCharacters(aPaM, 0, 3);
709 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
710 sw::mark::IMark* pMark
711 = rIDMA.makeMark(aPaM, "testBookmark", IDocumentMarkAccess::MarkType::BOOKMARK,
712 ::sw::mark::InsertMode::New);
714 // verify
715 CPPUNIT_ASSERT(pMark->IsExpanded());
716 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
719 // remove text marked with bookmark
721 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
722 SwPaM aPaM(aIdx);
724 lcl_selectCharacters(aPaM, 0, 3);
725 pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
727 // verify: bookmark is still exist
728 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
729 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
733 // save document
734 save("writer8");
736 // load only content.xml from the resaved document
737 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
739 const OString aPath("/office:document-content/office:body/office:text/text:p");
741 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark")); // not found
742 const int pos2 = getXPathPosition(pXmlDoc, aPath, "bookmark-start");
743 const int pos3 = getXPathPosition(pXmlDoc, aPath, "bookmark-end");
745 CPPUNIT_ASSERT_EQUAL(0, pos2); // found, and it is first
746 CPPUNIT_ASSERT_EQUAL(1, pos3); // found, and it is second
749 // 1. Open a new writer document
750 // 2. Enter the text "abcdef"
751 // 3. Select "abc"
752 // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
753 // 5. Open the navigator (F5)
754 // Select the bookmark "test" using the navigator.
755 // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
756 // 7. Call our macro
758 // Sub Main
759 // bookmark = ThisComponent.getBookmarks().getByName("test")
760 // bookmark.getAnchor().setString("abc")
761 // End Sub
763 // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
764 // 7. Save the document:
765 // <text:p text:style-name="Standard">
766 // <text:bookmark-start text:name="test"/>
767 // abc
768 // <text:bookmark-end text:name="test"/>
769 // def
770 // </text:p>
772 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkTextAndAddNew)
774 // create document
776 // create a text document with "abcdef"
777 createSwDoc();
778 SwDoc* pDoc = getSwDoc();
780 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
781 SwPaM aPaM(aIdx);
782 pDoc->getIDocumentContentOperations().InsertString(aPaM, "abcdef");
785 // mark "abc" with "testBookmark" bookmark
787 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
788 SwPaM aPaM(aIdx);
790 lcl_selectCharacters(aPaM, 0, 3);
791 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
792 sw::mark::IMark* pMark
793 = rIDMA.makeMark(aPaM, "testBookmark", IDocumentMarkAccess::MarkType::BOOKMARK,
794 ::sw::mark::InsertMode::New);
796 // verify
797 CPPUNIT_ASSERT(pMark->IsExpanded());
798 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
801 // remove text marked with bookmark
803 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
804 SwPaM aPaM(aIdx);
806 lcl_selectCharacters(aPaM, 0, 3);
807 pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
809 // verify: bookmark is still exist
810 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
811 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
814 // write "abc" to area marked with "testBookmark" bookmark
816 // Get helper objects
817 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent,
818 uno::UNO_QUERY);
820 // Create cursor from bookmark
821 uno::Reference<text::XTextContent> xTextContent(
822 xBookmarksSupplier->getBookmarks()->getByName("testBookmark"), uno::UNO_QUERY);
823 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
824 CPPUNIT_ASSERT_EQUAL(OUString(""), xRange->getString());
826 // write "abc"
827 xRange->setString("abc");
829 // verify: bookmark is still exist
830 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
831 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
835 // save document
836 save("writer8");
838 // load only content.xml from the resaved document
839 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
841 const OString aPath("/office:document-content/office:body/office:text/text:p");
843 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark")); // not found
844 const int pos2 = getXPathPosition(pXmlDoc, aPath, "bookmark-start");
845 const int pos3 = getXPathPosition(pXmlDoc, aPath, "text");
846 const int pos4 = getXPathPosition(pXmlDoc, aPath, "bookmark-end");
848 CPPUNIT_ASSERT_EQUAL(0, pos2);
849 CPPUNIT_ASSERT_EQUAL(1, pos3);
850 CPPUNIT_ASSERT_EQUAL(2, pos4);
853 // 1. Load document:
854 // <text:p text:style-name="Standard">
855 // <text:bookmark-start text:name="test"/>
856 // <text:bookmark-end text:name="test"/>
857 // def
858 // </text:p>
860 // 2. Call our macro
862 // Sub Main
863 // bookmark = ThisComponent.getBookmarks().getByName("test")
864 // bookmark.getAnchor().setString("abc")
865 // End Sub
867 // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
868 // 3. Save the document:
869 // <text:p text:style-name="Standard">
870 // <text:bookmark text:name="test"/>
871 // abcdef
872 // </text:p>
874 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkTextAndAddNewAfterReload)
876 // load document
877 createSwDoc("collapsed_bookmark.odt");
878 SwDoc* pDoc = getSwDoc();
879 CPPUNIT_ASSERT(pDoc);
881 // write "abc" to area marked with "testBookmark" bookmark
883 // Get helper objects
884 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
886 // Create cursor from bookmark
887 uno::Reference<text::XTextContent> xTextContent(
888 xBookmarksSupplier->getBookmarks()->getByName("test"), uno::UNO_QUERY);
889 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
890 CPPUNIT_ASSERT_EQUAL(OUString(""), xRange->getString());
892 // write "abc"
893 xRange->setString("abc");
895 // verify: bookmark is still exist
896 IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
897 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
900 // save original document
901 save("writer8");
903 // load only content.xml from the resaved document
904 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
905 const OString aPath("/office:document-content/office:body/office:text/text:p");
907 const int pos1 = getXPathPosition(pXmlDoc, aPath, "bookmark");
908 const int pos2 = getXPathPosition(pXmlDoc, aPath, "text");
910 CPPUNIT_ASSERT_EQUAL(0, pos1);
911 CPPUNIT_ASSERT_EQUAL(1, pos2);
913 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
914 CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
917 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96961)
919 // Insert a page break.
920 createSwDoc();
921 SwDoc* pDoc = getSwDoc();
922 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
923 pWrtShell->InsertPageBreak();
925 // Enable hide whitespace mode.
926 SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
927 aViewOptions.SetHideWhitespaceMode(true);
928 pWrtShell->ApplyViewOptions(aViewOptions);
930 calcLayout();
932 // Assert that the height of the last page is larger than the height of other pages.
933 sal_Int32 nOther = parseDump("/root/page[1]/infos/bounds", "height").toInt32();
934 sal_Int32 nLast = parseDump("/root/page[2]/infos/bounds", "height").toInt32();
935 CPPUNIT_ASSERT(nLast > nOther);
938 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf88453)
940 createSwDoc("tdf88453.odt");
941 calcLayout();
942 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
943 // This was 0: the table does not fit the first page, but it wasn't split
944 // to continue on the second page.
945 assertXPath(pXmlDoc, "/root/page[2]/body/tab", 1);
948 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf88453Table)
950 createSwDoc("tdf88453-table.odt");
951 calcLayout();
952 // This was 2: layout could not split the large outer table in the document
953 // into 3 pages.
954 CPPUNIT_ASSERT_EQUAL(3, getPages());
957 namespace
959 int checkShells(const SwDocShell* pSource, const SwDocShell* pDestination)
961 return int(SfxClassificationHelper::CheckPaste(pSource->getDocProperties(),
962 pDestination->getDocProperties()));
966 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testClassificationPaste)
968 createSwDoc();
969 SwDocShell* pSourceShell = getSwDoc()->GetDocShell();
970 uno::Reference<lang::XComponent> xSourceComponent = mxComponent;
971 mxComponent.clear();
973 createSwDoc();
974 SwDocShell* pDestinationShell = getSwDoc()->GetDocShell();
976 // Not classified source, not classified destination.
977 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None),
978 checkShells(pSourceShell, pDestinationShell));
980 // Classified source, not classified destination.
981 uno::Sequence<beans::PropertyValue> aInternalOnly
982 = comphelper::InitPropertySequence({ { "Name", uno::Any(OUString("Internal Only")) } });
983 dispatchCommand(xSourceComponent, ".uno:ClassificationApply", aInternalOnly);
984 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::TargetDocNotClassified),
985 checkShells(pSourceShell, pDestinationShell));
987 // Classified source and classified destination -- internal only has a higher level than confidential.
988 uno::Sequence<beans::PropertyValue> aConfidential
989 = comphelper::InitPropertySequence({ { "Name", uno::Any(OUString("Confidential")) } });
990 dispatchCommand(mxComponent, ".uno:ClassificationApply", aConfidential);
991 CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow),
992 checkShells(pSourceShell, pDestinationShell));
994 xSourceComponent->dispose();
997 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testSmallCaps)
999 // Create a document, add some characters and select them.
1000 createSwDoc();
1001 createSwDoc();
1002 SwDoc* pDoc = getSwDoc();
1003 SwDocShell* pDocShell = pDoc->GetDocShell();
1004 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1005 pWrtShell->Insert("text");
1006 pWrtShell->SelAll();
1008 // Dispatch the command to make them formatted small capitals.
1009 dispatchCommand(mxComponent, ".uno:SmallCaps", {});
1011 // This was css::style::CaseMap::NONE as the shell didn't handle the command.
1012 CPPUNIT_ASSERT_EQUAL(css::style::CaseMap::SMALLCAPS,
1013 getProperty<sal_Int16>(getRun(getParagraph(1), 1), "CharCaseMap"));
1016 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf98987)
1018 createSwDoc("tdf98987.docx");
1019 calcLayout();
1020 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1021 assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/SdrObject", "name",
1022 "Rectangle 1");
1023 sal_Int32 nRectangle1
1024 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/bounds", "top")
1025 .toInt32();
1026 assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name",
1027 "Rectangle 2");
1028 sal_Int32 nRectangle2
1029 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top")
1030 .toInt32();
1031 CPPUNIT_ASSERT_GREATER(nRectangle1, nRectangle2);
1033 assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/SdrObject", "name",
1034 "Rectangle 3");
1035 sal_Int32 nRectangle3
1036 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/bounds", "top")
1037 .toInt32();
1038 // This failed: the 3rd rectangle had a smaller "top" value than the 2nd one, it even overlapped with the 1st one.
1039 CPPUNIT_ASSERT_GREATER(nRectangle2, nRectangle3);
1042 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf99004)
1044 createSwDoc("tdf99004.docx");
1045 calcLayout();
1046 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1047 sal_Int32 nTextbox1Top
1048 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "top").toInt32();
1049 sal_Int32 nTextBox1Height
1050 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32();
1051 sal_Int32 nTextBox1Bottom = nTextbox1Top + nTextBox1Height;
1053 assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name",
1054 "Rectangle 2");
1055 sal_Int32 nRectangle2Top
1056 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top")
1057 .toInt32();
1058 // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
1059 CPPUNIT_ASSERT(nTextBox1Bottom < nRectangle2Top);
1062 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695)
1064 createSwDoc("tdf84695.odt");
1065 SwDoc* pDoc = getSwDoc();
1066 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1067 SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1068 SdrObject* pObject = pPage->GetObj(1);
1069 SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall());
1070 // First, make sure that pTextBox is a fly frame (textbox of a shape).
1071 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());
1073 // Then select it.
1074 pWrtShell->SelectObj(Point(), 0, pObject);
1076 // Now Enter + a key should add some text.
1077 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1078 CPPUNIT_ASSERT(pXTextDocument);
1079 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
1080 emulateTyping(*pXTextDocument, u"a");
1082 uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
1083 // This was empty, Enter did not start the fly frame edit mode.
1084 CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape->getString());
1087 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695NormalChar)
1089 createSwDoc("tdf84695.odt");
1090 SwDoc* pDoc = getSwDoc();
1091 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1092 SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1093 SdrObject* pObject = pPage->GetObj(1);
1094 SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall());
1095 // First, make sure that pTextBox is a fly frame (textbox of a shape).
1096 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());
1098 // Then select it.
1099 pWrtShell->SelectObj(Point(), 0, pObject);
1101 // Now pressing 'a' should add a character.
1102 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1103 CPPUNIT_ASSERT(pXTextDocument);
1104 emulateTyping(*pXTextDocument, u"a");
1106 uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
1107 // This was empty, pressing a normal character did not start the fly frame edit mode.
1108 CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape->getString());
1111 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695Tab)
1113 createSwDoc("tdf84695-tab.odt");
1114 SwDoc* pDoc = getSwDoc();
1115 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1116 SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1117 SdrObject* pObject = pPage->GetObj(0);
1118 SwContact* pShape = static_cast<SwContact*>(pObject->GetUserCall());
1119 // First, make sure that pShape is a draw shape.
1120 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_DRAWFRMFMT), pShape->GetFormat()->Which());
1122 // Then select it.
1123 pWrtShell->SelectObj(Point(), 0, pObject);
1125 // Now pressing 'tab' should jump to the other shape.
1126 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1127 CPPUNIT_ASSERT(pXTextDocument);
1128 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1129 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
1130 Scheduler::ProcessEventsToIdle();
1132 // And finally make sure the selection has changed.
1133 const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
1134 SwContact* pOtherShape
1135 = static_cast<SwContact*>(rMarkList.GetMark(0)->GetMarkedSdrObj()->GetUserCall());
1136 // This failed, 'tab' didn't do anything -> the selected shape was the same.
1137 CPPUNIT_ASSERT(pOtherShape != pShape);
1140 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTableStyleUndo)
1142 createSwDoc();
1143 SwDoc* pDoc = getSwDoc();
1144 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
1146 sal_Int32 nStyleCount = pDoc->GetTableStyles().size();
1147 SwTableAutoFormat* pStyle = pDoc->MakeTableStyle("Test Style");
1148 SvxBrushItem aBackground(Color(0xFF00FF), RES_BACKGROUND);
1149 pStyle->GetBoxFormat(0).SetBackground(aBackground);
1151 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
1152 rUndoManager.Undo();
1153 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
1154 rUndoManager.Redo();
1155 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
1156 // check if attributes are preserved
1157 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1158 CPPUNIT_ASSERT(pStyle);
1159 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
1161 pDoc->DelTableStyle("Test Style");
1162 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
1163 rUndoManager.Undo();
1164 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
1165 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1166 // check if attributes are preserved
1167 CPPUNIT_ASSERT(pStyle);
1168 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
1169 rUndoManager.Redo();
1170 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
1172 // undo delete so we can replace the style
1173 rUndoManager.Undo();
1174 CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
1175 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1176 CPPUNIT_ASSERT(pStyle);
1177 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
1179 SwTableAutoFormat aNewStyle("Test Style2");
1180 SvxBrushItem aBackground2(Color(0x00FF00), RES_BACKGROUND);
1181 aNewStyle.GetBoxFormat(0).SetBackground(aBackground2);
1183 pDoc->ChgTableStyle("Test Style", aNewStyle);
1184 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1185 CPPUNIT_ASSERT(pStyle);
1186 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground2));
1187 rUndoManager.Undo();
1188 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1189 CPPUNIT_ASSERT(pStyle);
1190 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
1191 rUndoManager.Redo();
1192 pStyle = pDoc->GetTableStyles().FindAutoFormat(u"Test Style");
1193 CPPUNIT_ASSERT(pStyle);
1194 CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground2));
1197 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineCopyPaste)
1199 // regressed in tdf#106746
1200 createSwDoc();
1201 SwDoc* pDoc = getSwDoc();
1203 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
1204 SwPaM aPaM(aIdx);
1206 pDoc->getIDocumentContentOperations().InsertString(aPaM, "abzdezgh");
1207 SwTextNode* pTextNode = aPaM.GetPointNode().GetTextNode();
1209 // Turn on track changes, make changes, turn off track changes
1210 uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
1211 xPropertySet->setPropertyValue("RecordChanges", uno::Any(true));
1212 lcl_selectCharacters(aPaM, 2, 3);
1213 pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "c", false);
1214 lcl_selectCharacters(aPaM, 6, 7);
1215 pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "f", false);
1216 xPropertySet->setPropertyValue("RecordChanges", uno::Any(false));
1218 // Create the clipboard document.
1219 SwDoc aClipboard;
1220 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1222 // Select the whole content, copy, delete the original and paste the copied content
1223 pWrtShell->SelAll();
1224 pWrtShell->Copy(aClipboard);
1225 pWrtShell->Delete();
1226 pWrtShell->Paste(aClipboard);
1228 // With the bug this is "abzcdefgh", ie. contains the first deleted piece, too
1229 CPPUNIT_ASSERT_EQUAL(OUString("abcdefgh"), pTextNode->GetText());
1232 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf135260)
1234 createSwDoc();
1235 SwDoc* pDoc = getSwDoc();
1236 SwDocShell* pDocShell = pDoc->GetDocShell();
1237 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1238 pWrtShell->Insert("test");
1240 // Turn on track changes
1241 uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
1242 xPropertySet->setPropertyValue("RecordChanges", uno::Any(true));
1244 for (int i = 0; i < 4; i++)
1246 pWrtShell->DelLeft();
1249 SwEditShell* const pEditShell(pDoc->GetEditShell());
1250 // accept all redlines
1251 while (pEditShell->GetRedlineCount())
1252 pEditShell->AcceptRedline(0);
1254 // Without the fix in place, this test would have failed with
1255 // - Expected:
1256 // - Actual : tes
1257 CPPUNIT_ASSERT_EQUAL(OUString(""), getParagraph(1)->getString());
1260 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineParam)
1262 // Create a document with minimal content.
1263 createSwDoc();
1264 SwDoc* pDoc = getSwDoc();
1265 SwDocShell* pDocShell = pDoc->GetDocShell();
1266 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1267 pWrtShell->Insert("middle");
1269 // Turn on track changes, and add changes to the start and end of the document.
1270 uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
1271 xPropertySet->setPropertyValue("RecordChanges", uno::Any(true));
1272 pWrtShell->StartOfSection();
1273 pWrtShell->Insert("aaa");
1274 pWrtShell->EndOfSection();
1275 pWrtShell->Insert("zzz");
1277 const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
1278 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size());
1280 // Select the first redline.
1281 pWrtShell->StartOfSection();
1282 uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
1283 { { "NextTrackedChange", uno::Any(o3tl::narrowing<sal_uInt16>(rTable[0]->GetId())) } }));
1284 dispatchCommand(mxComponent, ".uno:NextTrackedChange", aPropertyValues);
1285 SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
1286 // This failed: the parameter wasn't handled so the next change (zzz) was
1287 // selected, not the first one (aaa).
1288 CPPUNIT_ASSERT_EQUAL(OUString("aaa"), pShellCursor->GetText());
1290 // Select the second redline.
1291 pWrtShell->StartOfSection();
1292 aPropertyValues = comphelper::InitPropertySequence(
1293 { { "NextTrackedChange", uno::Any(o3tl::narrowing<sal_uInt16>(rTable[1]->GetId())) } });
1294 dispatchCommand(mxComponent, ".uno:NextTrackedChange", aPropertyValues);
1295 pShellCursor = pWrtShell->getShellCursor(false);
1296 CPPUNIT_ASSERT_EQUAL(OUString("zzz"), pShellCursor->GetText());
1298 // Move the cursor to the start again, and reject the second change.
1299 pWrtShell->StartOfSection();
1300 aPropertyValues = comphelper::InitPropertySequence(
1301 { { "RejectTrackedChange", uno::Any(o3tl::narrowing<sal_uInt16>(rTable[1]->GetId())) } });
1302 dispatchCommand(mxComponent, ".uno:RejectTrackedChange", aPropertyValues);
1303 pShellCursor = pWrtShell->getShellCursor(false);
1305 // This was 'middlezzz', the uno command rejected the redline under the
1306 // cursor, instead of the requested one.
1307 CPPUNIT_ASSERT_EQUAL(OUString("aaamiddle"),
1308 pShellCursor->GetPoint()->GetNode().GetTextNode()->GetText());
1311 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineViewAuthor)
1313 // Test that setting an author at an SwView level has effect.
1315 // Create a document with minimal content.
1316 createSwDoc();
1317 SwDoc* pDoc = getSwDoc();
1318 SwDocShell* pDocShell = pDoc->GetDocShell();
1319 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1320 pWrtShell->Insert("middle");
1321 SwView* pView = pDocShell->GetView();
1322 const OUString aAuthor("A U. Thor");
1323 pView->SetRedlineAuthor(aAuthor);
1324 pDocShell->SetView(pView);
1326 // Turn on track changes, and add changes to the start of the document.
1327 uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
1328 xPropertySet->setPropertyValue("RecordChanges", uno::Any(true));
1329 pWrtShell->StartOfSection();
1330 pWrtShell->Insert("aaa");
1332 // Now assert that SwView::SetRedlineAuthor() had an effect.
1333 const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
1334 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
1335 SwRangeRedline* pRedline = rTable[0];
1336 // This was 'Unknown Author' instead of 'A U. Thor'.
1337 CPPUNIT_ASSERT_EQUAL(aAuthor, pRedline->GetAuthorString());
1339 // Insert a comment and assert that SwView::SetRedlineAuthor() affects this as well.
1340 dispatchCommand(mxComponent, ".uno:.uno:InsertAnnotation", {});
1341 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
1342 uno::Reference<container::XEnumerationAccess> xFieldsAccess(
1343 xTextFieldsSupplier->getTextFields());
1344 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
1345 uno::Reference<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY);
1346 // This was 'Unknown Author' instead of 'A U. Thor'.
1347 CPPUNIT_ASSERT_EQUAL(aAuthor, xField->getPropertyValue("Author").get<OUString>());
1349 //Reset the redline author after using it, otherwise, it might interfere with other unittests
1350 pView->SetRedlineAuthor("Unknown Author");
1351 pDocShell->SetView(pView);
1354 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf91292)
1356 createSwDoc("tdf91292_paraBackground.docx");
1357 uno::Reference<beans::XPropertySet> xPropertySet(getParagraph(1), uno::UNO_QUERY);
1358 CPPUNIT_ASSERT_EQUAL_MESSAGE("Solid background color", drawing::FillStyle_SOLID,
1359 getProperty<drawing::FillStyle>(xPropertySet, "FillStyle"));
1360 CPPUNIT_ASSERT_EQUAL_MESSAGE("Background Color", Color(0x5C2D91),
1361 getProperty<Color>(xPropertySet, "FillColor"));
1363 // remove background color
1364 xPropertySet->setPropertyValue("FillStyle", uno::Any(drawing::FillStyle_NONE));
1366 // Save it and load it back.
1367 saveAndReload("Office Open XML Text");
1369 xPropertySet.set(getParagraph(1), uno::UNO_QUERY);
1370 CPPUNIT_ASSERT_EQUAL_MESSAGE("No background color", drawing::FillStyle_NONE,
1371 getProperty<drawing::FillStyle>(xPropertySet, "FillStyle"));
1374 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf78727)
1376 createSwDoc("tdf78727.docx");
1377 SwDoc* pDoc = getSwDoc();
1378 SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1379 // This was 1: make sure we don't loose the TextBox anchored inside the
1380 // table that is moved inside a text frame.
1381 CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage) > 1);
1384 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineTimestamp)
1386 // Test that a redline timestamp's second is not always 0.
1388 // Create a document with minimal content.
1389 createSwDoc();
1390 SwDoc* pDoc = getSwDoc();
1391 SwDocShell* pDocShell = pDoc->GetDocShell();
1392 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1393 pWrtShell->Insert("middle");
1395 // Turn on track changes, and add changes to the start and to the end of
1396 // the document.
1397 uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
1398 xPropertySet->setPropertyValue("RecordChanges", uno::Any(true));
1399 pWrtShell->StartOfSection();
1400 pWrtShell->Insert("aaa");
1401 osl::Thread::wait(std::chrono::seconds(1));
1402 pWrtShell->EndOfSection();
1403 pWrtShell->Insert("zzz");
1405 // Inserting additional characters at the start changed the table size to
1406 // 3, i.e. the first and the second "aaa" wasn't combined.
1407 pWrtShell->StartOfSection();
1408 pWrtShell->Insert("aaa");
1410 // Now assert that at least one of the seconds are not 0.
1411 const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
1412 if (rTable.size() >= 2
1413 && rTable[0]->GetRedlineData().GetTimeStamp().GetMin()
1414 != rTable[1]->GetRedlineData().GetTimeStamp().GetMin())
1415 // The relatively rare case when waiting for a second also changes the minute.
1416 return;
1418 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size());
1419 sal_uInt16 nSec1 = rTable[0]->GetRedlineData().GetTimeStamp().GetSec();
1420 sal_uInt16 nSec2 = rTable[1]->GetRedlineData().GetTimeStamp().GetSec();
1421 // This failed, seconds was always 0.
1422 CPPUNIT_ASSERT(nSec1 != 0 || nSec2 != 0);
1425 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testCursorWindows)
1427 // Create a new document with one window.
1428 createSwDoc();
1429 SwDoc* pDoc = getSwDoc();
1430 SwDocShell* pDocShell = pDoc->GetDocShell();
1431 SwWrtShell* pWrtShell1 = pDocShell->GetWrtShell();
1433 // Create a second view and type something.
1434 pDocShell->GetViewShell()->GetViewFrame().GetDispatcher()->Execute(
1435 SID_NEWWINDOW, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
1436 SwWrtShell* pWrtShell2 = pDocShell->GetWrtShell();
1437 OUString aText("foo");
1438 pWrtShell2->Insert(aText);
1440 // Assert that only the cursor of the actual window move, not other cursors.
1441 SwShellCursor* pShellCursor1 = pWrtShell1->getShellCursor(false);
1442 SwShellCursor* pShellCursor2 = pWrtShell2->getShellCursor(false);
1443 // This was 3, not 0 -- cursor of the other window moved.
1444 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), pShellCursor1->Start()->GetContentIndex());
1445 CPPUNIT_ASSERT_EQUAL(aText.getLength(), pShellCursor2->Start()->GetContentIndex());
1448 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testLandscape)
1450 // Set page orientation to landscape.
1451 createSwDoc();
1452 SwDoc* pDoc = getSwDoc();
1453 uno::Sequence<beans::PropertyValue> aPropertyValues(
1454 comphelper::InitPropertySequence({ { "AttributePage.Landscape", uno::Any(true) } }));
1455 dispatchCommand(mxComponent, ".uno:AttributePage", aPropertyValues);
1457 // Assert that the document model was modified.
1458 SwDocShell* pDocShell = pDoc->GetDocShell();
1459 SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
1460 size_t nPageDesc = pWrtShell->GetCurPageDesc();
1461 // This failed, page was still portrait.
1462 CPPUNIT_ASSERT(pWrtShell->GetPageDesc(nPageDesc).GetLandscape());
1465 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf95699)
1467 // Open the document with single FORMCHECKBOX field, select all and copy to clipboard
1468 // then check that clipboard contains the FORMCHECKBOX in text body.
1469 // Previously that failed.
1470 createSwDoc("tdf95699.odt");
1471 SwDoc* pDoc = getSwDoc();
1472 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1473 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1474 SwDoc aClipboard;
1475 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1476 pWrtShell->SelAll();
1477 pWrtShell->Copy(aClipboard);
1478 pMarkAccess = aClipboard.getIDocumentMarkAccess();
1479 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1480 ::sw::mark::IFieldmark* pFieldMark
1481 = pMarkAccess->getFieldmarkAfter(SwPosition(aClipboard.GetNodes().GetEndOfExtras()), false);
1482 CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"),
1483 pFieldMark->GetFieldname());
1486 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf151548_tabNavigation2)
1488 // given a form-protected doc with 2 unchecked legacy fieldmark checkboxes, 1 modern
1489 // checkbox, and a couple of other content controls that are not supposed to
1490 // have their contents selected upon entry into the control (i.e. no placeholder text).
1491 createSwDoc("tdf151548_tabNavigation2.docx");
1492 SwDoc* pDoc = getSwDoc();
1493 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1495 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1496 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getFieldmarksCount());
1498 // verify that the checkboxes start off in the unchecked state
1499 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
1501 sw::mark::ICheckboxFieldmark* pCheckBox
1502 = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(*it);
1503 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
1506 // Toggle on the legacy checkbox
1507 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE);
1508 // Tab to the next control - the modern checkbox
1509 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1510 // Tab to the next control - the second legacy checkbox, and toggle it on.
1511 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1512 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE);
1513 // Tab to the next control - a plain text control without placeholder text
1514 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1515 // Tab to the next control - a combobox with custom text
1516 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1517 Scheduler::ProcessEventsToIdle();
1519 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
1521 sw::mark::ICheckboxFieldmark* pCheckBox
1522 = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(*it);
1523 // verify that the legacy checkbox became checked by the first loop.
1524 CPPUNIT_ASSERT(pCheckBox->IsChecked());
1526 // This is where it was failing. Tab got stuck moving into the plain text/combobox,
1527 // so it could never loop around. At this point we are at the end of the loop,
1528 // so the next tab should take us back to the beginning with the first legacy checkbox.
1530 // Tab to the legacy checkbox, and toggle it off.
1531 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1532 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE);
1533 Scheduler::ProcessEventsToIdle();
1534 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
1536 // Tab to the next content control
1537 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1541 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf151548_tabNavigation)
1543 // given a form-protected doc with 4 unchecked legacy fieldmark checkboxes (and several modern
1544 // content controls which all have a tabstop of -1 to disable tabstop navigation to them)
1545 // we want to test that tab navigation completes and loops around to continue at the beginning.
1546 createSwDoc("tdf151548_tabNavigation.docm");
1547 SwDoc* pDoc = getSwDoc();
1548 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1550 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1551 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pMarkAccess->getFieldmarksCount());
1553 // Tab and toggle 4 times, verifying beforehand that the state was unchecked
1554 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
1556 sw::mark::ICheckboxFieldmark* pCheckBox
1557 = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(*it);
1558 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
1560 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // toggle checkbox on
1561 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // move to next control
1562 Scheduler::ProcessEventsToIdle();
1565 // Tab 4 more times, verifying beforehand that the checkbox had been toggle on, then toggles off
1566 // meaning that looping is working, and no other controls are reacting to the tab key.
1567 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
1569 sw::mark::ICheckboxFieldmark* pCheckBox
1570 = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(*it);
1572 CPPUNIT_ASSERT(pCheckBox->IsChecked());
1573 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // toggle checkbox off
1574 Scheduler::ProcessEventsToIdle();
1576 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
1577 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // move to next control
1581 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104032)
1583 // Open the document with FORMCHECKBOX field, select it and copy to clipboard
1584 // Go to end of document and paste it, then undo
1585 // Previously that asserted in debug build.
1586 createSwDoc("tdf104032.odt");
1587 SwDoc* pDoc = getSwDoc();
1588 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
1589 SwDoc aClipboard;
1590 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1591 pWrtShell->StartOfSection();
1592 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1593 pWrtShell->Copy(aClipboard);
1594 pWrtShell->EndOfSection();
1595 pWrtShell->Paste(aClipboard);
1596 rUndoManager.Undo();
1599 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104440)
1601 createSwDoc("tdf104440.odt");
1602 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1603 // This was 0: both Text Frames in the document were anchored to a
1604 // paragraph on page 1, while we expect that the second Text Frame is
1605 // anchored to a paragraph on page 2.
1606 assertXPath(pXmlDoc, "//page[2]/body/txt/anchored");
1609 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104425)
1611 createSwDoc("tdf104425.odt");
1612 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1613 // The document contains one top-level 1-cell table with minimum row height set to 70 cm,
1614 // and the cell contents does not exceed the minimum row height.
1615 // It should span over 3 pages.
1616 assertXPath(pXmlDoc, "//page", 3);
1617 sal_Int32 nHeight1
1618 = getXPath(pXmlDoc, "//page[1]/body/tab/row/infos/bounds", "height").toInt32();
1619 sal_Int32 nHeight2
1620 = getXPath(pXmlDoc, "//page[2]/body/tab/row/infos/bounds", "height").toInt32();
1621 sal_Int32 nHeight3
1622 = getXPath(pXmlDoc, "//page[3]/body/tab/row/infos/bounds", "height").toInt32();
1623 double fSumHeight_mm = o3tl::convert<double>(nHeight1 + nHeight2 + nHeight3, o3tl::Length::twip,
1624 o3tl::Length::mm);
1625 CPPUNIT_ASSERT_DOUBLES_EQUAL(700.0, fSumHeight_mm, 0.05);
1628 // accepting change tracking gets stuck on change
1629 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104814)
1631 createSwDoc("tdf104814.docx");
1632 SwDoc* pDoc1 = getSwDoc();
1634 SwEditShell* const pEditShell(pDoc1->GetEditShell());
1636 // accept all redlines
1637 while (pEditShell->GetRedlineCount())
1638 pEditShell->AcceptRedline(0);
1641 // crash at redo of accepting table change tracking imported from DOCX
1642 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTableRedlineRedoCrash)
1644 createSwDoc("TC-table-del-add.docx");
1645 SwDoc* pDoc = getSwDoc();
1646 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
1648 // accept all redlines, Undo and accept all redlines again
1650 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1651 rIDRA.AcceptAllRedline(/*bAccept=*/true);
1653 rUndoManager.Undo();
1655 // without the fix, it crashes
1656 rIDRA.AcceptAllRedline(true);
1659 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTableRemoveHasTextChangesOnly)
1661 createSwDoc("TC-table-del-add.docx");
1662 SwDoc* pDoc = getSwDoc();
1663 CPPUNIT_ASSERT(pDoc);
1664 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1665 CPPUNIT_ASSERT(pWrtShell);
1667 // disable Record Changes
1668 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1669 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1670 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1672 // 4 rows in Show Changes mode
1673 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1674 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1676 // Accepting tracked deletions results 3 rows
1677 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1678 rIDRA.AcceptAllRedline(/*bAccept=*/true);
1679 Scheduler::ProcessEventsToIdle();
1680 discardDumpedLayout();
1681 pXmlDoc = parseLayoutDump();
1682 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
1684 // Undo: 4 rows again
1685 pDoc->GetIDocumentUndoRedo().Undo();
1686 discardDumpedLayout();
1687 pXmlDoc = parseLayoutDump();
1688 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1690 // Accepting again: 3 rows (Undo of HasTextChangesOnly is correct)
1691 rIDRA.AcceptAllRedline(/*bAccept=*/true);
1692 Scheduler::ProcessEventsToIdle();
1693 discardDumpedLayout();
1694 pXmlDoc = parseLayoutDump();
1695 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
1697 // Undo: 4 rows again
1698 pDoc->GetIDocumentUndoRedo().Undo();
1699 discardDumpedLayout();
1700 pXmlDoc = parseLayoutDump();
1701 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1703 // Move the cursor after the redline, and insert some text without change tracking
1704 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1705 pWrtShell->Insert("X");
1707 // Accepting again: 4 rows (extra text keeps the deleted row)
1708 rIDRA.AcceptAllRedline(/*bAccept=*/true);
1709 Scheduler::ProcessEventsToIdle();
1710 discardDumpedLayout();
1711 pXmlDoc = parseLayoutDump();
1712 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1714 // delete the extra text with change tracking:
1715 // this resulted tracked row deletion again, because of missing
1716 // removing of HasTextChangeOnly SwTabLine property at accepting deletions previously
1718 // disable Record Changes
1719 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1720 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1721 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1723 dispatchCommand(mxComponent, ".uno:SwBackSpace", {});
1724 rIDRA.AcceptAllRedline(/*bAccept=*/true);
1725 Scheduler::ProcessEventsToIdle();
1726 discardDumpedLayout();
1727 pXmlDoc = parseLayoutDump();
1728 // This was 3
1729 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1732 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTableRemoveHasTextChangesOnly2)
1734 createSwDoc("TC-table-del-add.docx");
1735 SwDoc* pDoc = getSwDoc();
1736 CPPUNIT_ASSERT(pDoc);
1737 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1738 CPPUNIT_ASSERT(pWrtShell);
1740 // disable Record Changes
1741 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1742 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1743 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1745 // check redline count
1746 SwEditShell* const pEditShell(pDoc->GetEditShell());
1747 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1749 // 4 rows in Show Changes mode
1750 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1751 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1753 // Move the cursor to the tracked insertion, after the first redline to activate the
1754 // acception of the whole table row insertion with a single "Accept Change"
1755 pWrtShell->Down(/*bSelect=*/false);
1756 pWrtShell->Down(/*bSelect=*/false);
1757 pWrtShell->Down(/*bSelect=*/false);
1758 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1759 Scheduler::ProcessEventsToIdle();
1760 dispatchCommand(mxComponent, ".uno:AcceptTrackedChange", {});
1761 discardDumpedLayout();
1762 pXmlDoc = parseLayoutDump();
1763 // Accepting tracked insertion results still 4 rows, but less redlines
1764 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1765 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(11), pEditShell->GetRedlineCount());
1767 // Undo: 4 rows again
1768 pDoc->GetIDocumentUndoRedo().Undo();
1769 discardDumpedLayout();
1770 pXmlDoc = parseLayoutDump();
1771 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1772 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1774 // To check Undo of HasTextChangesOnly reject the same row results 3 rows
1775 dispatchCommand(mxComponent, ".uno:Escape", {});
1776 dispatchCommand(mxComponent, ".uno:RejectTrackedChange", {});
1777 discardDumpedLayout();
1778 pXmlDoc = parseLayoutDump();
1779 // This was 4 (lost HasTextChangesOnly)
1780 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
1782 // Undo: 4 rows again
1783 pDoc->GetIDocumentUndoRedo().Undo();
1784 discardDumpedLayout();
1785 pXmlDoc = parseLayoutDump();
1786 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1787 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1790 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf147182_AcceptAllChangesInTableSelection)
1792 createSwDoc("TC-table-del-add.docx");
1793 SwDoc* pDoc = getSwDoc();
1794 CPPUNIT_ASSERT(pDoc);
1795 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1796 CPPUNIT_ASSERT(pWrtShell);
1798 // check redline count
1799 SwEditShell* const pEditShell(pDoc->GetEditShell());
1800 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1802 // 4 rows in Show Changes mode
1803 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1804 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1806 // Select the first table to get a table selection
1807 dispatchCommand(mxComponent, ".uno:SelectAll", {});
1808 dispatchCommand(mxComponent, ".uno:SelectAll", {});
1809 dispatchCommand(mxComponent, ".uno:AcceptTrackedChange", {});
1810 discardDumpedLayout();
1811 pXmlDoc = parseLayoutDump();
1812 // Accepting tracked changes in the selected table results 3 rows
1813 // This was 4 (only text changes of the first selected cell were accepted)
1814 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
1815 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(8), pEditShell->GetRedlineCount());
1817 // Undo: 4 rows again
1818 pDoc->GetIDocumentUndoRedo().Undo();
1819 discardDumpedLayout();
1820 pXmlDoc = parseLayoutDump();
1821 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1822 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1824 // To check Undo of HasTextChangesOnly reject the same row results 3 rows
1825 dispatchCommand(mxComponent, ".uno:Escape", {});
1826 dispatchCommand(mxComponent, ".uno:SelectAll", {});
1827 dispatchCommand(mxComponent, ".uno:SelectAll", {});
1828 dispatchCommand(mxComponent, ".uno:RejectTrackedChange", {});
1829 discardDumpedLayout();
1830 pXmlDoc = parseLayoutDump();
1831 // This was 4 (only text changes of the first selected cell were rejected)
1832 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
1834 // Undo: 4 rows again
1835 pDoc->GetIDocumentUndoRedo().Undo();
1836 discardDumpedLayout();
1837 pXmlDoc = parseLayoutDump();
1838 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
1839 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
1842 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf66405)
1844 // Imported formula should have zero margins
1845 createSwDoc("tdf66405.docx");
1846 uno::Reference<text::XTextEmbeddedObjectsSupplier> xEmbeddedObjectsSupplier(mxComponent,
1847 uno::UNO_QUERY);
1848 uno::Reference<container::XNameAccess> xEmbeddedObjects
1849 = xEmbeddedObjectsSupplier->getEmbeddedObjects();
1850 uno::Reference<beans::XPropertySet> xFormula;
1851 xEmbeddedObjects->getByName(xEmbeddedObjects->getElementNames()[0]) >>= xFormula;
1852 uno::Reference<beans::XPropertySet> xComponent;
1853 xFormula->getPropertyValue("Component") >>= xComponent;
1855 // Test embedded object's margins
1856 sal_Int32 nLeftMargin, nRightMargin, nTopMargin, nBottomMargin;
1857 xFormula->getPropertyValue("LeftMargin") >>= nLeftMargin;
1858 xFormula->getPropertyValue("RightMargin") >>= nRightMargin;
1859 xFormula->getPropertyValue("TopMargin") >>= nTopMargin;
1860 xFormula->getPropertyValue("BottomMargin") >>= nBottomMargin;
1861 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
1862 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin);
1863 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin);
1864 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin);
1866 // Test embedded object component's margins
1867 xComponent->getPropertyValue("LeftMargin") >>= nLeftMargin;
1868 xComponent->getPropertyValue("RightMargin") >>= nRightMargin;
1869 xComponent->getPropertyValue("TopMargin") >>= nTopMargin;
1870 xComponent->getPropertyValue("BottomMargin") >>= nBottomMargin;
1871 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
1872 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin);
1873 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin);
1874 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin);
1877 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf35021_tabOverMarginDemo)
1879 #if HAVE_MORE_FONTS
1880 createSwDoc("tdf35021_tabOverMarginDemo.doc");
1881 calcLayout();
1882 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1883 // Tabs should go past the margin @ ~3381
1884 sal_Int32 nMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32();
1885 // left tab was 3381 because it got its own full line
1886 sal_Int32 nWidth
1887 = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabLeft']", "width").toInt32();
1888 CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~4479", nMargin < nWidth);
1889 // center tab was 842
1890 nWidth = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabCenter']", "width").toInt32();
1891 CPPUNIT_ASSERT_MESSAGE("Center Tab width is ~3521", nMargin < nWidth);
1892 // right tab was probably the same as center tab.
1893 nWidth = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabRight']", "width").toInt32();
1894 CPPUNIT_ASSERT_MESSAGE("Right Tab width is ~2907", sal_Int32(2500) < nWidth);
1895 // decimal tab was 266
1896 nWidth
1897 = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabDecimal']", "width").toInt32();
1898 CPPUNIT_ASSERT_MESSAGE("Decimal Tab width is ~4096", nMargin < nWidth);
1899 #endif
1902 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf106701_tabOverMarginAutotab)
1904 createSwDoc("tdf106701_tabOverMarginAutotab.doc");
1905 calcLayout();
1906 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1907 // The right margin is ~3378
1908 sal_Int32 nRightMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32();
1909 // Automatic tabstops should never be affected by tabOverMargin compatibility
1910 // The 1st line's width previously was ~9506
1911 sal_Int32 nWidth = getXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "width").toInt32();
1912 CPPUNIT_ASSERT_MESSAGE("1st line's width is less than the right margin", nWidth < nRightMargin);
1915 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104492)
1917 createSwDoc("tdf104492.docx");
1918 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1919 // The document should split table over 3 pages.
1920 assertXPath(pXmlDoc, "//page", 3);
1923 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107025)
1925 // Tdf107025 - characters advance with wrong distance, so that
1926 // they are cluttered because of negative value or
1927 // break into multiple lines because of overflow.
1928 // The test document uses DFKAI-SB shipped with Windows.
1929 createSwDoc("tdf107025.odt");
1930 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1931 // Verify the number of characters in each line.
1932 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1933 getXPath(pXmlDoc, "(//SwLinePortion)[1]", "length").toInt32());
1934 CPPUNIT_ASSERT_EQUAL(sal_Int32(9),
1935 getXPath(pXmlDoc, "(//SwLinePortion)[2]", "length").toInt32());
1937 // Do the subsequent test only if the first line can be displayed,
1938 // in case that the required font does not exist.
1939 sal_Int32 nWidth1 = getXPath(pXmlDoc, "(//SwLinePortion)[1]", "width").toInt32();
1940 if (!nWidth1)
1941 return;
1943 CPPUNIT_ASSERT(!parseDump("(//SwLinePortion)[2]", "width").isEmpty());
1944 sal_Int32 nWidth2 = getXPath(pXmlDoc, "(//SwLinePortion)[2]", "width").toInt32();
1945 sal_Int32 nRatio = nWidth2 / nWidth1;
1947 CPPUNIT_ASSERT(nRatio >= 9); // Occupy at least 9 cells.
1948 CPPUNIT_ASSERT(nRatio < 18); // Occupy at most 18 cells.
1951 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107362)
1953 createSwDoc("tdf107362.odt");
1954 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1955 sal_Int32 nHeight
1956 = getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[1]",
1957 "height")
1958 .toInt32();
1959 sal_Int32 nWidth1
1960 = getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[1]",
1961 "width")
1962 .toInt32();
1963 sal_Int32 nWidth2
1964 = getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[2]",
1965 "width")
1966 .toInt32();
1967 sal_Int32 nLineWidth = getXPath(pXmlDoc, "//SwParaPortion/SwLineLayout", "width").toInt32();
1968 sal_Int32 nKernWidth = nLineWidth - nWidth1 - nWidth2;
1969 // Test only if fonts are available
1970 if (nWidth1 > 500 && nWidth2 > 200)
1972 // Kern width should be smaller than 1/3 of the CJK font height.
1973 CPPUNIT_ASSERT(nKernWidth * 3 < nHeight);
1977 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf105417)
1979 createSwDoc("tdf105417.odt");
1980 SwDoc* pDoc = getSwDoc();
1981 CPPUNIT_ASSERT(pDoc);
1982 SwView* pView = pDoc->GetDocShell()->GetView();
1983 CPPUNIT_ASSERT(pView);
1984 uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
1985 CPPUNIT_ASSERT(xHyphenator.is());
1986 // If there are no English hyphenation rules installed, we can't test
1987 // hyphenation.
1988 if (!xHyphenator->hasLocale(lang::Locale("en", "US", OUString())))
1989 return;
1991 uno::Reference<linguistic2::XLinguProperties> xLinguProperties(LinguMgr::GetLinguPropertySet());
1992 // Automatic hyphenation means not opening a dialog, but going ahead
1993 // non-interactively.
1994 xLinguProperties->setIsHyphAuto(true);
1995 SwHyphWrapper aWrap(pView, xHyphenator, /*bStart=*/false, /*bOther=*/true,
1996 /*bSelection=*/false);
1997 // This never returned, it kept trying to hyphenate the last word
1998 // (greenbacks) again and again.
1999 aWrap.SpellDocument();
2002 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf105625)
2004 createSwDoc("tdf105625.fodt");
2005 SwDoc* pDoc = getSwDoc();
2006 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2007 // Ensure correct initial setting
2008 std::shared_ptr<comphelper::ConfigurationChanges> batch(
2009 comphelper::ConfigurationChanges::create());
2010 officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
2011 batch->commit();
2012 // We should be able to edit at positions adjacent to fields.
2013 // Check if the start and the end of the 1st paragraph are not protected
2014 // (they are adjacent to FORMCHECKBOX)
2015 pWrtShell->SttPara();
2016 CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
2017 pWrtShell->EndPara();
2018 CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
2019 // 2nd paragraph - FORMTEXT
2020 pWrtShell->Down(/*bSelect=*/false);
2021 // Check selection across FORMTEXT field boundary - must be read-only
2022 pWrtShell->SttPara();
2023 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
2024 CPPUNIT_ASSERT_EQUAL(true, pWrtShell->HasReadonlySel());
2025 // Test deletion of whole field with single backspace
2026 // Previously it only removed right boundary of FORMTEXT, or failed removal at all
2027 const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
2028 sal_Int32 nMarksBefore = pMarksAccess->getAllMarksCount();
2029 pWrtShell->EndPara();
2030 pWrtShell->DelLeft();
2031 sal_Int32 nMarksAfter = pMarksAccess->getAllMarksCount();
2032 CPPUNIT_ASSERT_EQUAL(nMarksBefore, nMarksAfter + 1);
2035 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf125151_protected)
2037 // Similar to testTdf105625 except this is in a protected section,
2038 // so read-only is already true when fieldmarks are considered.
2039 createSwDoc("tdf125151_protected.fodt");
2040 SwDoc* pDoc = getSwDoc();
2041 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2042 // Ensure correct initial setting
2043 std::shared_ptr<comphelper::ConfigurationChanges> batch(
2044 comphelper::ConfigurationChanges::create());
2045 officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
2046 batch->commit();
2047 pWrtShell->Down(/*bSelect=*/false);
2048 // The cursor moved inside of the FieldMark textbox.
2049 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel());
2050 // Move left to the start/definition of the textbox
2051 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2052 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
2055 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf125151_protectedB)
2057 // Similar to testTdf105625 except this is protected with the Protect_Form compat setting
2058 createSwDoc("tdf125151_protectedB.fodt");
2059 SwDoc* pDoc = getSwDoc();
2060 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2061 // Ensure correct initial setting
2062 std::shared_ptr<comphelper::ConfigurationChanges> batch(
2063 comphelper::ConfigurationChanges::create());
2064 officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
2065 batch->commit();
2066 // The cursor starts inside of the FieldMark textbox.
2067 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel());
2068 // Move left to the start/definition of the textbox
2069 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2070 CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
2073 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf106736)
2075 createSwDoc("tdf106736-grid.odt");
2076 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2077 sal_Int32 nWidth
2078 = getXPath(pXmlDoc,
2079 "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabLeft'])[1]",
2080 "width")
2081 .toInt32();
2082 // In tdf106736, width of tab overflow so that it got
2083 // width value around 9200, expected value is around 103
2084 CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~103", nWidth < 150);
2087 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testMsWordCompTrailingBlanks)
2089 // The option is true in settings.xml
2090 createSwDoc("MsWordCompTrailingBlanksTrue.odt");
2091 SwDoc* pDoc = getSwDoc();
2092 CPPUNIT_ASSERT_EQUAL(true, pDoc->getIDocumentSettingAccess().get(
2093 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
2094 calcLayout();
2095 // Check that trailing spaces spans have no width if option is enabled
2097 CPPUNIT_ASSERT_EQUAL(
2098 OUString("0"),
2099 parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]", "width"));
2100 CPPUNIT_ASSERT_EQUAL(
2101 OUString("0"),
2102 parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]", "width"));
2103 CPPUNIT_ASSERT_EQUAL(
2104 OUString("0"),
2105 parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]", "width"));
2106 CPPUNIT_ASSERT_EQUAL(
2107 OUString("0"),
2108 parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]", "width"));
2110 // The option is false in settings.xml
2111 createSwDoc("MsWordCompTrailingBlanksFalse.odt");
2112 pDoc = getSwDoc();
2113 CPPUNIT_ASSERT_EQUAL(false, pDoc->getIDocumentSettingAccess().get(
2114 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
2115 calcLayout();
2116 // Check that trailing spaces spans have width if option is disabled
2117 CPPUNIT_ASSERT(
2118 parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]", "width") != "0");
2119 CPPUNIT_ASSERT(
2120 parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]", "width") != "0");
2121 CPPUNIT_ASSERT(
2122 parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]", "width") != "0");
2123 CPPUNIT_ASSERT(
2124 parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]", "width") != "0");
2126 // MsWordCompTrailingBlanks option should be false by default in new documents
2127 createSwDoc();
2128 pDoc = getSwDoc();
2129 CPPUNIT_ASSERT_EQUAL(false, pDoc->getIDocumentSettingAccess().get(
2130 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
2132 // The option should be true if a .docx, .doc or .rtf document is opened
2133 createSwDoc("MsWordCompTrailingBlanks.docx");
2134 pDoc = getSwDoc();
2135 CPPUNIT_ASSERT_EQUAL(true, pDoc->getIDocumentSettingAccess().get(
2136 DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
2139 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testCreateDocxAnnotation)
2141 createSwDoc();
2143 // insert an annotation with a text
2144 const OUString aSomeText("some text");
2145 uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
2146 { "Text", uno::Any(aSomeText) },
2147 { "Author", uno::Any(OUString("me")) },
2149 dispatchCommand(mxComponent, ".uno:InsertAnnotation", aPropertyValues);
2151 // Save it as DOCX & load it again
2152 saveAndReload("Office Open XML Text");
2154 // get the annotation
2155 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
2156 uno::Reference<container::XEnumerationAccess> xFieldsAccess(
2157 xTextFieldsSupplier->getTextFields());
2158 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
2159 uno::Reference<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY);
2161 // this was empty instead of "some text"
2162 CPPUNIT_ASSERT_EQUAL(aSomeText, xField->getPropertyValue("Content").get<OUString>());
2165 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107976)
2167 // Create a document and create two transferables.
2168 createSwDoc();
2169 SwDoc* pDoc = getSwDoc();
2170 SwWrtShell& rShell = *pDoc->GetDocShell()->GetWrtShell();
2171 rtl::Reference<SwTransferable> pTransferable(new SwTransferable(rShell));
2172 rtl::Reference<SwTransferable> pTransferable2(new SwTransferable(rShell));
2173 // Now close the document.
2174 mxComponent->dispose();
2175 mxComponent.clear();
2176 // This failed: the first shell had a pointer to the deleted shell.
2177 CPPUNIT_ASSERT(!pTransferable->GetShell());
2178 CPPUNIT_ASSERT(!pTransferable2->GetShell());
2181 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf58604)
2183 #ifdef _WIN32
2184 // Allow linebreak character follows hanging punctuation immediately instead of
2185 // breaking at the start of the next line.
2186 createSwDoc("tdf58604.odt");
2187 CPPUNIT_ASSERT_EQUAL(
2188 OUString("PortionType::Break"),
2189 parseDump("(/root/page/body/txt/SwParaPortion/SwLineLayout[1]/child::*)[last()]", "type"));
2190 #endif
2193 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf112025)
2195 mergeDocs("fdo112025.odt", "fdo112025-insert.docx");
2197 CPPUNIT_ASSERT_EQUAL(3, getParagraphs());
2199 uno::Reference<beans::XPropertySet> xStyle(getStyles("PageStyles")->getByName("Standard"),
2200 uno::UNO_QUERY);
2201 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xStyle, "IsLandscape"));
2204 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf72942)
2206 mergeDocs("fdo72942.docx", "fdo72942-insert.docx");
2208 // check styles of paragraphs added from [fdo72942.docx]
2209 const uno::Reference<text::XTextRange> xRun1 = getRun(getParagraph(1), 1);
2210 CPPUNIT_ASSERT_EQUAL(OUString("Default English (Liberation serif) text with "),
2211 xRun1->getString());
2212 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"),
2213 getProperty<OUString>(xRun1, "CharFontName"));
2215 const uno::Reference<text::XTextRange> xRun2 = getRun(getParagraph(2), 1);
2216 CPPUNIT_ASSERT_EQUAL(OUString("Header 1 English text (Liberation sans) with "),
2217 xRun2->getString());
2218 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty<OUString>(xRun2, "CharFontName"));
2220 // check styles of paragraphs added from [fdo72942-insert.docx]
2221 const uno::Reference<text::XTextRange> xRun3 = getRun(getParagraph(4), 1);
2222 CPPUNIT_ASSERT_EQUAL(OUString("Default German text (Calibri) with "), xRun3->getString());
2223 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"),
2224 getProperty<OUString>(xRun3, "CharFontName"));
2226 const uno::Reference<text::XTextRange> xRun4 = getRun(getParagraph(5), 1);
2227 CPPUNIT_ASSERT_EQUAL(OUString("Header 1 German text (Calibri Light) with "),
2228 xRun4->getString());
2229 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty<OUString>(xRun4, "CharFontName"));
2232 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf114306)
2234 createSwDoc("fdo114306.odt");
2235 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2237 // There are 2 long paragraphs in cell A1.
2238 // A part of paragraph 2 should flow over to the second page but
2239 // *not* the whole paragraph. There should be 2 paragraphs on
2240 // page 1 and 1 paragraph on page 2.
2241 assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row[1]/cell[1]/txt", 2);
2242 assertXPath(pXmlDoc, "/root/page[2]/body/tab[1]/row[1]/cell[1]/txt", 1);
2245 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf114306_2)
2247 // tdf#114306 fix unexpected page break in row-spanned table
2248 // load regression document without writer crash
2249 createSwDoc("fdo114306_2.odt");
2251 // correct number of pages
2252 CPPUNIT_ASSERT_EQUAL(4, getPages());
2255 // During insert of the document with list inside into the main document inside the list
2256 // we should merge both lists into one, when they have the same list properties
2257 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877)
2259 mergeDocs("tdf113877_insert_numbered_list.odt", "tdf113877_insert_numbered_list.odt");
2261 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2262 const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
2263 const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
2264 const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
2265 const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
2267 // the initial list with 4 list items
2268 CPPUNIT_ASSERT_EQUAL(listId1, listId4);
2270 // the last of the first list, and the first of the inserted list
2271 CPPUNIT_ASSERT_EQUAL(listId4, listId5);
2272 CPPUNIT_ASSERT_EQUAL(listId5, listId6);
2273 CPPUNIT_ASSERT_EQUAL(listId6, listId7);
2276 // The same test as testTdf113877() but merging of two list should not be performed.
2277 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877NoMerge)
2279 mergeDocs("tdf113877_insert_numbered_list.odt", "tdf113877_insert_numbered_list_abcd.odt");
2281 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2282 const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
2283 const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
2284 const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
2285 const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
2287 // the initial list with 4 list items
2288 CPPUNIT_ASSERT_EQUAL(listId1, listId4);
2290 // the last of the first list, and the first of the inserted list
2291 CPPUNIT_ASSERT(listId4 != listId5);
2292 CPPUNIT_ASSERT_EQUAL(listId5, listId6);
2293 CPPUNIT_ASSERT(listId6 != listId7);
2296 // Related test to testTdf113877(): Inserting into empty document a new document with list.
2297 // Insert position has NO its own paragraph style ("Standard" will be used).
2299 // Resulting document should be the same for following tests:
2300 // - testTdf113877_default_style()
2301 // - testTdf113877_Standard_style()
2303 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_default_style)
2305 mergeDocs(nullptr, "tdf113877_insert_numbered_list_abcd.odt");
2307 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2308 const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
2309 const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
2311 CPPUNIT_ASSERT_EQUAL(listId1, listId2);
2312 CPPUNIT_ASSERT_EQUAL(listId1, listId3);
2315 // Related test to testTdf113877(): Inserting into empty document a new document with list.
2316 // Insert position has its own paragraph style derived from "Standard", but this style is the same as "Standard".
2318 // Resulting document should be the same for following tests:
2319 // - testTdf113877_default_style()
2320 // - testTdf113877_Standard_style()
2322 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_Standard_style)
2324 mergeDocs("tdf113877_blank_ownStandard.odt", "tdf113877_insert_numbered_list_abcd.odt");
2326 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2327 const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
2328 const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
2330 CPPUNIT_ASSERT_EQUAL(listId1, listId2);
2331 CPPUNIT_ASSERT_EQUAL(listId1, listId3);
2334 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_blank_bold_on)
2336 mergeDocs("tdf113877_blank_bold_on.odt", "tdf113877_insert_numbered_list_abcd.odt");
2338 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2339 const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
2340 const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
2342 CPPUNIT_ASSERT_EQUAL(listId1, listId2);
2343 CPPUNIT_ASSERT_EQUAL(listId1, listId3);
2346 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107975)
2348 // This test also covers tdf#117185 tdf#110442
2350 createSwDoc("tdf107975.odt");
2351 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
2353 uno::Reference<text::XTextGraphicObjectsSupplier> xTextGraphicObjectsSupplier(mxComponent,
2354 uno::UNO_QUERY);
2355 uno::Reference<container::XIndexAccess> xIndexAccess(
2356 xTextGraphicObjectsSupplier->getGraphicObjects(), uno::UNO_QUERY);
2358 uno::Reference<drawing::XShape> xShape(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
2360 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
2361 getProperty<text::TextContentAnchorType>(xShape, "AnchorType"));
2363 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2365 dispatchCommand(mxComponent, ".uno:SelectAll", {});
2367 dispatchCommand(mxComponent, ".uno:Copy", {});
2369 //Position the mouse cursor (caret) after "ABC" below the blue image
2370 dispatchCommand(mxComponent, ".uno:GoRight", {});
2371 dispatchCommand(mxComponent, ".uno:Paste", {});
2373 // without the fix, it crashes
2374 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2375 CPPUNIT_ASSERT_EQUAL(OUString("ABC"), getParagraph(1)->getString());
2376 dispatchCommand(mxComponent, ".uno:Undo", {});
2377 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2378 dispatchCommand(mxComponent, ".uno:Redo", {});
2379 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2380 dispatchCommand(mxComponent, ".uno:Undo", {});
2381 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2382 dispatchCommand(mxComponent, ".uno:Redo", {});
2383 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2384 dispatchCommand(mxComponent, ".uno:Undo", {});
2385 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2387 //try again with anchor at start of doc which is another special case
2388 xShape.set(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
2389 uno::Reference<text::XTextContent> xShapeContent(xShape, uno::UNO_QUERY);
2390 uno::Reference<text::XTextRange> const xStart = pTextDoc->getText()->getStart();
2391 xShapeContent->attach(xStart);
2393 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
2394 getProperty<text::TextContentAnchorType>(xShape, "AnchorType"));
2396 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2398 dispatchCommand(mxComponent, ".uno:SelectAll", {});
2400 dispatchCommand(mxComponent, ".uno:Copy", {});
2402 //Position the mouse cursor (caret) after "ABC" below the blue image
2403 dispatchCommand(mxComponent, ".uno:GoRight", {});
2404 dispatchCommand(mxComponent, ".uno:Paste", {});
2406 // Fails quite a lot on multiple Jenkins slaves, but entirely reliably,
2407 // with:
2408 // sw/qa/extras/uiwriter/uiwriter4.cxx(2407) : error : Assertion
2409 // - Expected: 2
2410 // - Actual : 1
2411 // i.e. the xIndexAccess->getCount() line.
2412 #if 0
2413 // without the fix, it crashes
2414 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2415 CPPUNIT_ASSERT_EQUAL(OUString("ABC"), getParagraph(1)->getString());
2416 dispatchCommand(mxComponent, ".uno:Undo", {});
2417 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2418 dispatchCommand(mxComponent, ".uno:Redo", {});
2419 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2420 dispatchCommand(mxComponent, ".uno:Undo", {});
2421 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2422 dispatchCommand(mxComponent, ".uno:Redo", {});
2423 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
2424 dispatchCommand(mxComponent, ".uno:Undo", {});
2425 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
2426 #endif
2429 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_blank_bold_off)
2431 mergeDocs("tdf113877_blank_bold_off.odt", "tdf113877_insert_numbered_list_abcd.odt");
2433 const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
2434 const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
2435 const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
2437 CPPUNIT_ASSERT_EQUAL(listId1, listId2);
2438 CPPUNIT_ASSERT_EQUAL(listId1, listId3);
2441 // just care that this does crash/assert
2442 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRhbz1810732) { mergeDocs(nullptr, "rhbz1810732.docx"); }
2444 CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf142157)
2446 mergeDocs(nullptr, "tdf142157.odt");
2448 uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
2449 uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(),
2450 uno::UNO_QUERY);
2452 // Without the fix in place, this test would have failed with
2453 // - Expected: 1
2454 // - Actual : 0
2455 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
2458 CPPUNIT_PLUGIN_IMPLEMENT();
2460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */