android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / qa / core / uwriter.cxx
blob7eea1b230e06dabc9b00f1af7a0e55f3c2090ad8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
11 #include <test/bootstrapfixture.hxx>
13 #include <com/sun/star/i18n/WordType.hpp>
15 #include <comphelper/processfactory.hxx>
16 #include <i18nutil/transliteration.hxx>
17 #include <editeng/adjustitem.hxx>
18 #include <editeng/boxitem.hxx>
19 #include <editeng/brushitem.hxx>
20 #include <editeng/colritem.hxx>
21 #include <editeng/contouritem.hxx>
22 #include <editeng/crossedoutitem.hxx>
23 #include <editeng/fhgtitem.hxx>
24 #include <editeng/fontitem.hxx>
25 #include <editeng/justifyitem.hxx>
26 #include <editeng/lineitem.hxx>
27 #include <editeng/postitem.hxx>
28 #include <editeng/shdditem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/wghtitem.hxx>
31 #include <svl/intitem.hxx>
32 #include <svx/algitem.hxx>
33 #include <svx/rotmodit.hxx>
34 #include <tools/urlobj.hxx>
35 #include <unotools/tempfile.hxx>
36 #include <unotools/transliterationwrapper.hxx>
38 #include <editeng/langitem.hxx>
39 #include <editeng/charhiddenitem.hxx>
41 #include <sfx2/docfilt.hxx>
42 #include <sfx2/docfile.hxx>
44 #include <xmloff/odffields.hxx>
46 #include <breakit.hxx>
47 #include <doc.hxx>
48 #include <IDocumentRedlineAccess.hxx>
49 #include <IDocumentFieldsAccess.hxx>
50 #include <IDocumentStatistics.hxx>
51 #include <cellfml.hxx>
52 #include <docsh.hxx>
53 #include <docstat.hxx>
54 #include <docufld.hxx>
55 #include <fmtanchr.hxx>
56 #include <ndtxt.hxx>
57 #include <shellres.hxx>
58 #include <swscanner.hxx>
59 #include <swdll.hxx>
60 #include <swtypes.hxx>
61 #include <fmtftn.hxx>
62 #include <fmtrfmrk.hxx>
63 #include <fmtinfmt.hxx>
64 #include <fchrfmt.hxx>
65 #include <fmtfld.hxx>
66 #include <redline.hxx>
67 #include <docary.hxx>
68 #include <modeltoviewhelper.hxx>
69 #include <IMark.hxx>
70 #include <ring.hxx>
71 #include <calbck.hxx>
72 #include <pagedesc.hxx>
73 #include <calc.hxx>
75 #include <tblafmt.hxx>
76 #include <unotbl.hxx>
77 #include <IDocumentMarkAccess.hxx>
78 #include <itabenum.hxx>
80 typedef tools::SvRef<SwDocShell> SwDocShellRef;
82 using namespace ::com::sun::star;
84 /* Implementation of Swdoc-Test class */
86 class SwDocTest : public test::BootstrapFixture
88 public:
89 SwDocTest()
90 : m_pDoc(nullptr)
94 virtual void setUp() override;
95 virtual void tearDown() override;
97 void testTableAutoFormats();
98 void testPageDescName();
99 void testFileNameFields();
100 void testDocStat();
101 void testModelToViewHelperPassthrough();
102 void testModelToViewHelperExpandFieldsExpandFootnote();
103 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode();
104 void testModelToViewHelperExpandFields();
105 void testModelToViewHelperExpandFieldsReplaceMode();
106 void testModelToViewHelperExpandFieldsHideInvisible();
107 void testModelToViewHelperExpandFieldsHideRedlined();
108 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote();
109 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode();
110 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote();
111 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode();
112 void testModelToViewHelperHideInvisibleHideRedlined();
113 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote();
114 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode();
115 void testModelToViewHelperExpandFieldsExpandFootnote2();
116 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2();
117 void testSwScanner();
118 void testUserPerceivedCharCount();
119 void testMergePortionsDeleteNotSorted();
120 void testGraphicAnchorDeletion();
121 void testTransliterate();
122 void testMarkMove();
123 void testFormulas();
124 void testIntrusiveRing();
125 void testClientModify();
126 void testBroadcastingModify();
127 void testWriterMultiListener();
128 void test64kPageDescs();
129 void testTdf92308();
130 void testTableCellComparison();
132 CPPUNIT_TEST_SUITE(SwDocTest);
134 CPPUNIT_TEST(testTransliterate);
135 CPPUNIT_TEST(testTableAutoFormats);
136 CPPUNIT_TEST(testPageDescName);
137 CPPUNIT_TEST(testFileNameFields);
138 CPPUNIT_TEST(testDocStat);
139 CPPUNIT_TEST(testModelToViewHelperPassthrough);
140 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote);
141 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode);
142 CPPUNIT_TEST(testModelToViewHelperExpandFields);
143 CPPUNIT_TEST(testModelToViewHelperExpandFieldsReplaceMode);
144 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisible);
145 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideRedlined);
146 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote);
147 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode);
148 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote);
149 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode);
150 CPPUNIT_TEST(testModelToViewHelperHideInvisibleHideRedlined);
151 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote);
152 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode);
153 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote2);
154 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2);
155 CPPUNIT_TEST(testSwScanner);
156 CPPUNIT_TEST(testUserPerceivedCharCount);
157 CPPUNIT_TEST(testMergePortionsDeleteNotSorted);
158 CPPUNIT_TEST(testGraphicAnchorDeletion);
159 CPPUNIT_TEST(testMarkMove);
160 CPPUNIT_TEST(testFormulas);
161 CPPUNIT_TEST(testIntrusiveRing);
162 CPPUNIT_TEST(testClientModify);
163 CPPUNIT_TEST(testBroadcastingModify);
164 CPPUNIT_TEST(testWriterMultiListener);
165 CPPUNIT_TEST(test64kPageDescs);
166 CPPUNIT_TEST(testTdf92308);
167 CPPUNIT_TEST(testTableCellComparison);
168 CPPUNIT_TEST_SUITE_END();
170 private:
171 SwDoc *m_pDoc;
172 SwDocShellRef m_xDocShRef;
175 void SwDocTest::testPageDescName()
177 ShellResource aShellResources;
179 std::vector<OUString> aResults;
181 //These names must be unique for each different combination, otherwise
182 //duplicate page description names may exist, which will causes lookup
183 //by name to be incorrect, and so the corresponding export to .odt
184 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
185 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
186 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));
188 std::sort(aResults.begin(), aResults.end());
189 aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());
191 CPPUNIT_ASSERT_EQUAL_MESSAGE("GetPageDescName results must be unique", static_cast<size_t>(3), aResults.size());
194 //See https://bugs.libreoffice.org/show_bug.cgi?id=32463
195 void SwDocTest::testFileNameFields()
197 //Here's a file name with some chars in it that will be %% encoded, when expanding
198 //SwFileNameFields we want to restore the original readable filename
199 utl::TempFileNamed aTempFile(u"demo [name]");
200 aTempFile.EnableKillingFile();
202 INetURLObject aTempFileURL(aTempFile.GetURL());
203 OUString sFileURL = aTempFileURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
204 SfxMedium aDstMed(sFileURL, StreamMode::STD_READWRITE);
206 auto pFilter = std::make_shared<SfxFilter>(
207 "Text",
208 OUString(), SfxFilterFlags::NONE, SotClipboardFormatId::NONE, OUString(), OUString(),
209 "TEXT", OUString() );
210 aDstMed.SetFilter(pFilter);
212 m_xDocShRef->DoSaveAs(aDstMed);
213 m_xDocShRef->DoSaveCompleted(&aDstMed);
215 const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();
217 SwFileNameFieldType aNameField(*m_pDoc);
220 OUString sResult(aNameField.Expand(FF_NAME));
221 OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
222 true,INetURLObject::DecodeMechanism::WithCharset));
223 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected, sResult);
227 OUString sResult(aNameField.Expand(FF_PATHNAME));
228 OUString sExpected(rUrlObj.GetFull());
229 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected, sResult);
233 OUString sResult(aNameField.Expand(FF_PATH));
234 INetURLObject aTemp(rUrlObj);
235 aTemp.removeSegment();
236 OUString sExpected(aTemp.PathToFileName());
237 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected, sResult);
241 OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
242 OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
243 true,INetURLObject::DecodeMechanism::WithCharset));
244 //Chop off .tmp
245 sExpected = sExpected.copy(0, sExpected.getLength() - 4);
246 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected, sResult);
249 m_xDocShRef->DoInitNew();
252 //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
253 //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
254 //motivation
255 void SwDocTest::testDocStat()
257 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong>(0), m_pDoc->getIDocumentStatistics().GetDocStat().nChar);
259 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
260 SwPaM aPaM(aIdx);
262 OUString sText("Hello World");
263 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sText);
265 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should still be non-updated 0 count", static_cast<sal_uLong>(0), m_pDoc->getIDocumentStatistics().GetDocStat().nChar);
267 SwDocStat aDocStat = m_pDoc->getIDocumentStatistics().GetUpdatedDocStat( false, true );
268 sal_uLong nLen = static_cast<sal_uLong>(sText.getLength());
270 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should now have updated count", nLen, aDocStat.nChar);
272 CPPUNIT_ASSERT_EQUAL_MESSAGE("And cache is updated too", nLen, m_pDoc->getIDocumentStatistics().GetDocStat().nChar);
275 //For UI character counts we should follow UAX#29 and display the user
276 //perceived characters, not the number of codepoints, nor the number of code
277 //units http://unicode.org/reports/tr29/
278 void SwDocTest::testUserPerceivedCharCount()
280 SwBreakIt *pBreakIter = SwBreakIt::Get();
282 //Grapheme example, two different unicode code-points perceived by the user as a single
283 //glyph
284 static constexpr OUStringLiteral sALEF_QAMATS = u"\u05D0\u05B8";
285 sal_Int32 nGraphemeCount = pBreakIter->getGraphemeCount(sALEF_QAMATS);
286 CPPUNIT_ASSERT_EQUAL_MESSAGE("Grapheme Count should be 1", static_cast<sal_Int32>(1), nGraphemeCount);
288 //Surrogate pair example, one single unicode code-point (U+1D11E)
289 //represented as two code units in UTF-16
290 static constexpr OUStringLiteral sGCLEF = u"\U0001D11E";
291 sal_Int32 nCount = pBreakIter->getGraphemeCount(sGCLEF);
292 CPPUNIT_ASSERT_EQUAL_MESSAGE("Surrogate Pair should be counted as single character", static_cast<sal_Int32>(1), nCount);
295 static SwTextNode* getModelToViewTestDocument(SwDoc *pDoc)
297 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
298 SwPaM aPaM(aIdx);
300 SwFormatFootnote aFootnote;
301 aFootnote.SetNumStr("foo");
303 pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
304 pDoc->getIDocumentContentOperations().InsertString(aPaM, "AAAAA BBBBB ");
305 SwTextNode* pTextNode = aPaM.GetPointNode().GetTextNode();
306 sal_Int32 nPos = aPaM.GetPoint()->GetContentIndex();
307 pTextNode->InsertItem(aFootnote, nPos, nPos);
308 pDoc->getIDocumentContentOperations().InsertString(aPaM, " CCCCC ");
309 nPos = aPaM.GetPoint()->GetContentIndex();
310 pTextNode->InsertItem(aFootnote, nPos, nPos);
311 pDoc->getIDocumentContentOperations().InsertString(aPaM, " DDDDD");
312 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>((4*5) + 5 + 2), pTextNode->GetText().getLength());
314 //set start of selection to first B
315 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 6);
316 aPaM.SetMark();
317 //set end of selection to last C
318 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 14);
319 //set character attribute hidden on range
320 SvxCharHiddenItem aHidden(true, RES_CHRATR_HIDDEN);
321 pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aHidden );
322 aPaM.DeleteMark();
324 //turn on red-lining and show changes
325 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete|RedlineFlags::ShowInsert);
326 CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn());
327 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
329 //set start of selection to last A
330 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 4);
331 aPaM.SetMark();
332 //set end of selection to second last B
333 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 9);
334 pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM); //redline-aware deletion api
335 aPaM.DeleteMark();
337 return pTextNode;
340 static SwTextNode* getModelToViewTestDocument2(SwDoc *pDoc)
342 getModelToViewTestDocument(pDoc);
344 SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
345 SwPaM aPaM(aIdx);
347 pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
348 pDoc->getIDocumentContentOperations().InsertString(aPaM, "AAAAA");
349 IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
350 sw::mark::IFieldmark *pFieldmark =
351 pMarksAccess->makeNoTextFieldBookmark(aPaM, "test", ODF_FORMDROPDOWN);
352 CPPUNIT_ASSERT(pFieldmark);
353 uno::Sequence< OUString > vListEntries { "BBBBB" };
354 (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY] <<= vListEntries;
355 (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= sal_Int32(0);
356 pDoc->getIDocumentContentOperations().InsertString(aPaM, "CCCCC");
357 SwTextNode* pTextNode = aPaM.GetPointNode().GetTextNode();
358 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11),
359 pTextNode->GetText().getLength());
361 return pTextNode;
364 void SwDocTest::testModelToViewHelperPassthrough()
366 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
368 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr, ExpandMode::PassThrough);
369 OUString sViewText = aModelToViewHelper.getViewText();
370 OUString sModelText = pTextNode->GetText();
371 CPPUNIT_ASSERT_EQUAL(sModelText, sViewText);
374 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote()
376 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
378 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
379 ExpandMode::ExpandFields | ExpandMode::ExpandFootnote);
380 OUString sViewText = aModelToViewHelper.getViewText();
381 CPPUNIT_ASSERT_EQUAL(
382 OUString("AAAAA BBBBB foo CCCCC foo DDDDD"), sViewText);
385 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode()
387 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
389 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
390 ExpandMode::ExpandFields | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
391 OUString sViewText = aModelToViewHelper.getViewText();
392 CPPUNIT_ASSERT_EQUAL(
393 OUString("AAAAA BBBBB " + OUStringChar(CHAR_ZWSP) + " CCCCC " + OUStringChar(CHAR_ZWSP) + " DDDDD"),
394 sViewText);
395 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
396 aModelToViewHelper.getFootnotePositions().size());
397 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12),
398 aModelToViewHelper.getFootnotePositions()[0]);
399 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(20),
400 aModelToViewHelper.getFootnotePositions()[1]);
401 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
402 aModelToViewHelper.getFieldPositions().size());
405 void SwDocTest::testModelToViewHelperExpandFields()
407 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
409 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr, ExpandMode::ExpandFields);
410 OUString sViewText = aModelToViewHelper.getViewText();
411 CPPUNIT_ASSERT_EQUAL(
412 OUString("AAAAA BBBBB CCCCC DDDDD"), sViewText);
415 void SwDocTest::testModelToViewHelperExpandFieldsReplaceMode()
417 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
419 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
420 ExpandMode::ExpandFields | ExpandMode::ReplaceMode);
421 OUString sViewText = aModelToViewHelper.getViewText();
422 CPPUNIT_ASSERT_EQUAL(OUString("AAAAA BBBBB CCCCC DDDDD"),
423 sViewText);
424 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
425 aModelToViewHelper.getFootnotePositions().size());
426 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
427 aModelToViewHelper.getFieldPositions().size());
430 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisible()
432 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
434 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr, ExpandMode::HideInvisible);
435 OUString sViewText = aModelToViewHelper.getViewText();
436 CPPUNIT_ASSERT_EQUAL(
437 OUString("AAAAA CCCCC " + OUStringChar(CH_TXTATR_BREAKWORD) + " DDDDD"),
438 sViewText);
441 void SwDocTest::testModelToViewHelperExpandFieldsHideRedlined()
443 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
445 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr, ExpandMode::HideDeletions);
446 OUString sViewText = aModelToViewHelper.getViewText();
447 CPPUNIT_ASSERT_EQUAL(
448 OUString("AAAABB " + OUStringChar(CH_TXTATR_BREAKWORD) + " CCCCC " + OUStringChar(CH_TXTATR_BREAKWORD) + " DDDDD"),
449 sViewText);
452 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote()
454 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
456 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
457 ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::ExpandFootnote);
458 OUString sViewText = aModelToViewHelper.getViewText();
459 CPPUNIT_ASSERT_EQUAL(OUString("AAAAA CCCCC foo DDDDD"), sViewText);
462 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode()
464 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
466 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
467 ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
468 OUString sViewText = aModelToViewHelper.getViewText();
469 CPPUNIT_ASSERT_EQUAL(
470 OUString("AAAAA CCCCC " + OUStringChar(CHAR_ZWSP) + " DDDDD"),
471 sViewText);
472 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
473 aModelToViewHelper.getFootnotePositions().size());
474 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12),
475 aModelToViewHelper.getFootnotePositions()[0]);
476 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
477 aModelToViewHelper.getFieldPositions().size());
480 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote()
482 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
484 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
485 ExpandMode::ExpandFields | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote);
486 OUString sViewText = aModelToViewHelper.getViewText();
487 CPPUNIT_ASSERT_EQUAL(
488 OUString("AAAABB foo CCCCC foo DDDDD"), sViewText);
491 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode()
493 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
495 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
496 ExpandMode::ExpandFields | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
497 OUString sViewText = aModelToViewHelper.getViewText();
498 CPPUNIT_ASSERT_EQUAL(
499 OUString("AAAABB " + OUStringChar(CHAR_ZWSP) + " CCCCC " + OUStringChar(CHAR_ZWSP) + " DDDDD"),
500 sViewText);
501 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
502 aModelToViewHelper.getFootnotePositions().size());
503 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(7),
504 aModelToViewHelper.getFootnotePositions()[0]);
505 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(15),
506 aModelToViewHelper.getFootnotePositions()[1]);
507 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
508 aModelToViewHelper.getFieldPositions().size());
511 void SwDocTest::testModelToViewHelperHideInvisibleHideRedlined()
513 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
515 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
516 ExpandMode::HideInvisible | ExpandMode::HideDeletions);
517 OUString sViewText = aModelToViewHelper.getViewText();
518 OUString aBuffer = "AAAACCCCC " +
519 OUStringChar(CH_TXTATR_BREAKWORD) +
520 " DDDDD";
521 CPPUNIT_ASSERT_EQUAL(aBuffer, sViewText);
524 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote()
526 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
528 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
529 ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote);
530 OUString sViewText = aModelToViewHelper.getViewText();
531 CPPUNIT_ASSERT_EQUAL(OUString("AAAACCCCC foo DDDDD"), sViewText);
534 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode()
536 SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
538 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
539 ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
540 OUString sViewText = aModelToViewHelper.getViewText();
541 CPPUNIT_ASSERT_EQUAL(sViewText,
542 OUString("AAAACCCCC " + OUStringChar(CHAR_ZWSP) + " DDDDD"));
543 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
544 aModelToViewHelper.getFootnotePositions().size());
545 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(10),
546 aModelToViewHelper.getFootnotePositions()[0]);
547 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
548 aModelToViewHelper.getFieldPositions().size());
551 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote2()
553 SwTextNode* pTextNode = getModelToViewTestDocument2(m_pDoc);
555 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
556 ExpandMode::ExpandFields | ExpandMode::ExpandFootnote);
557 OUString sViewText = aModelToViewHelper.getViewText();
558 CPPUNIT_ASSERT_EQUAL(OUString("AAAAABBBBBCCCCC"), sViewText);
561 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2()
563 SwTextNode* pTextNode = getModelToViewTestDocument2(m_pDoc);
565 ModelToViewHelper aModelToViewHelper(*pTextNode, nullptr,
566 ExpandMode::ExpandFields | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
567 OUString sViewText = aModelToViewHelper.getViewText();
568 CPPUNIT_ASSERT_EQUAL(
569 OUString("AAAAA" + OUStringChar(CHAR_ZWSP) + "CCCCC"),
570 sViewText);
571 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
572 aModelToViewHelper.getFootnotePositions().size());
573 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
574 aModelToViewHelper.getFieldPositions().size());
575 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5),
576 aModelToViewHelper.getFieldPositions()[0]);
579 void SwDocTest::testSwScanner()
581 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
582 SwPaM aPaM(aIdx);
584 SwTextNode* pTextNode = aPaM.GetPointNode().GetTextNode();
586 CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTextNode);
588 //See https://bugs.libreoffice.org/show_bug.cgi?id=40449
589 //See https://bugs.libreoffice.org/show_bug.cgi?id=39365
590 //Use a temporary OUString as the arg, as that's the trouble behind
591 //fdo#40449 and fdo#39365
593 SwScanner aScanner(*pTextNode,
594 "Hello World",
595 nullptr, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD, 0,
596 RTL_CONSTASCII_LENGTH("Hello World"));
598 bool bFirstOk = aScanner.NextWord();
599 CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk);
600 const OUString &rHello = aScanner.GetWord();
601 CPPUNIT_ASSERT_EQUAL(OUString("Hello"), rHello);
603 bool bSecondOk = aScanner.NextWord();
604 CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk);
605 const OUString &rWorld = aScanner.GetWord();
606 CPPUNIT_ASSERT_EQUAL(OUString("World"), rWorld);
609 //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
611 static constexpr OUStringLiteral IDEOGRAPHICFULLSTOP_D = u"\u3002D";
613 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, IDEOGRAPHICFULLSTOP_D);
615 SvxLanguageItem aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED, RES_CHRATR_CJK_LANGUAGE );
616 SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
617 m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aCJKLangItem );
618 m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aWestLangItem );
620 SwDocStat aDocStat;
621 pTextNode = aPaM.GetPointNode().GetTextNode();
622 pTextNode->CountWords(aDocStat, 0, IDEOGRAPHICFULLSTOP_D.getLength());
624 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(2), aDocStat.nChar);
625 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(2), aDocStat.nCharExcludingSpaces);
628 static constexpr OUStringLiteral test =
629 u"\u3053\u306E\u65E5\u672C\u8A9E\u306F\u6B63\u3057"
630 "\u304F\u6570\u3048\u3089\u308C\u308B\u3067\u3057"
631 "\u3087\u3046\u304B\u3002And "
632 "let's th"
633 "row some"
634 " English"
635 " in to m"
636 "ake it i"
637 "nteresti"
638 "ng. \u305D\u3057\u3066"
639 "\u3001\u307E\u305F\u65E5\u672C\u8A9E\u3000\u3000"
640 "\u3067\u3082\u4ECA\u56DE\u306F\u7A7A\u767D\u3092"
641 "\u3000\u3000\u5165\u308C\u307E\u3057\u305F\u3002"
642 " So how"
643 " does th"
644 "is do? ";
645 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
646 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, test);
648 SvxLanguageItem aCJKLangItem( LANGUAGE_JAPANESE, RES_CHRATR_CJK_LANGUAGE );
649 SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
650 m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aCJKLangItem );
651 m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aWestLangItem );
653 SwDocStat aDocStat;
654 pTextNode = aPaM.GetPointNode().GetTextNode();
655 pTextNode->CountWords(aDocStat, 0, test.getLength());
656 CPPUNIT_ASSERT_EQUAL_MESSAGE("words", static_cast<sal_uLong>(58), aDocStat.nWord);
657 CPPUNIT_ASSERT_EQUAL_MESSAGE("Asian characters and Korean syllables", static_cast<sal_uLong>(43), aDocStat.nAsianWord);
658 CPPUNIT_ASSERT_EQUAL_MESSAGE("non-whitespace chars", static_cast<sal_uLong>(105), aDocStat.nCharExcludingSpaces);
659 CPPUNIT_ASSERT_EQUAL_MESSAGE("characters", static_cast<sal_uLong>(128), aDocStat.nChar);
662 //See https://bz.apache.org/ooo/show_bug.cgi?id=89042
663 //See https://bugs.libreoffice.org/show_bug.cgi?id=53399
665 SwDocStat aDocStat;
667 static constexpr OUStringLiteral aShouldBeThree =
668 u"Should "
669 "\u2018be thr"
670 "ee\u2019";
672 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
673 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, aShouldBeThree);
674 pTextNode = aPaM.GetPointNode().GetTextNode();
675 pTextNode->CountWords(aDocStat, 0, aShouldBeThree.getLength());
676 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(3), aDocStat.nWord);
678 static constexpr OUStringLiteral aShouldBeFive =
679 u"french "
680 // << nbsp
681 "\u00AB\u00A0savoi"
682 // nnbsp
683 "r\u202fcalcu"
684 // idspace >>
685 "ler\u3000\u00BB";
687 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
688 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, aShouldBeFive);
689 pTextNode = aPaM.GetPointNode().GetTextNode();
690 aDocStat.Reset();
691 pTextNode->CountWords(aDocStat, 0, aShouldBeFive.getLength());
692 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(5), aDocStat.nWord);
695 //See https://bugs.libreoffice.org/show_bug.cgi?id=49629
697 SwDocStat aDocStat;
699 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
700 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Apple");
701 pTextNode = aPaM.GetPointNode().GetTextNode();
702 sal_Int32 nPos = aPaM.GetPoint()->GetContentIndex();
703 SwFormatFootnote aFootnote;
704 aFootnote.SetNumStr("banana");
705 SwTextAttr* pTA = pTextNode->InsertItem(aFootnote, nPos, nPos);
706 CPPUNIT_ASSERT(pTA);
707 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), pTextNode->Len()); //Apple + 0x02
708 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
709 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(1), aDocStat.nWord);
710 CPPUNIT_ASSERT_EQUAL_MESSAGE("footnote should be expanded", static_cast<sal_uLong>(11), aDocStat.nChar);
712 const sal_Int32 nNextPos = aPaM.GetPoint()->GetContentIndex();
713 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(nPos+1), nNextPos);
714 SwFormatRefMark aRef("refmark");
715 pTA = pTextNode->InsertItem(aRef, nNextPos, nNextPos);
716 CPPUNIT_ASSERT(pTA);
718 aDocStat.Reset();
719 pTextNode->SetWordCountDirty(true);
720 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
721 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(1), aDocStat.nWord);
722 CPPUNIT_ASSERT_EQUAL_MESSAGE("refmark anchor should not be counted", static_cast<sal_uLong>(11), aDocStat.nChar);
724 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
725 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Apple");
727 DateTime aDate(DateTime::SYSTEM);
728 SwPostItField aPostIt(
729 static_cast<SwPostItFieldType*>(m_pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit)), "An Author",
730 "Some Text", "Initials", "Name", aDate );
731 m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, SwFormatField(aPostIt));
733 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Apple");
734 pTextNode = aPaM.GetPointNode().GetTextNode();
735 aDocStat.Reset();
736 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
737 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(1), aDocStat.nWord);
738 CPPUNIT_ASSERT_EQUAL_MESSAGE("postit anchor should effectively not exist", static_cast<sal_uLong>(10), aDocStat.nChar);
739 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11), pTextNode->Len());
741 aDocStat.Reset();
744 //See https://bugs.libreoffice.org/show_bug.cgi?id=46757
746 SwDocStat aDocStat;
748 static constexpr OUStringLiteral aString = u"Lorem ipsum";
749 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
750 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, aString);
751 pTextNode = aPaM.GetPointNode().GetTextNode();
752 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
753 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(2), aDocStat.nWord);
755 //turn on red-lining and show changes
756 m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete|RedlineFlags::ShowInsert);
757 CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->getIDocumentRedlineAccess().IsRedlineOn());
758 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
760 //delete everything except the first word
761 aPaM.SetMark(); //set start of selection to current pos
762 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 5); //set end of selection to fifth char of current node
763 m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM); //redline-aware deletion api
764 //"real underlying text should be the same"
765 CPPUNIT_ASSERT_EQUAL(pTextNode->GetText(), OUString(aString));
767 aDocStat.Reset();
768 pTextNode->SetWordCountDirty(true);
769 pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //but word-counting the text should only count the non-deleted text
770 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(1), aDocStat.nWord);
772 pTextNode->SetWordCountDirty(true);
774 //keep red-lining on but hide changes
775 m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
776 CPPUNIT_ASSERT_MESSAGE("redlining should be still on", m_pDoc->getIDocumentRedlineAccess().IsRedlineOn());
777 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible", !IDocumentRedlineAccess::IsShowChanges(m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
779 aDocStat.Reset();
780 pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //but word-counting the text should only count the non-deleted text
781 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(1), aDocStat.nWord);
783 OUString sLorem = pTextNode->GetText();
784 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), sLorem);
786 const SwRedlineTable& rTable = m_pDoc->getIDocumentRedlineAccess().GetRedlineTable();
788 SwNodes& rNds = m_pDoc->GetNodes();
789 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
791 const SwNodeIndex* pNodeIdx = rTable[0]->GetContentIdx();
792 CPPUNIT_ASSERT(pNodeIdx);
794 pTextNode = rNds[ pNodeIdx->GetIndex() + 1 ]->GetTextNode(); //first deleted txtnode
795 CPPUNIT_ASSERT(pTextNode);
797 OUString sIpsum = pTextNode->GetText();
798 CPPUNIT_ASSERT_EQUAL(OUString(" ipsum"), sIpsum);
800 aDocStat.Reset();
801 pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //word-counting the text should only count the non-deleted text, and this whole chunk should be ignored
802 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(0), aDocStat.nWord);
803 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(0), aDocStat.nChar);
805 // https://bugs.libreoffice.org/show_bug.cgi?id=68347 we do want to count
806 // redline *added* text though
807 m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete|RedlineFlags::ShowInsert);
808 aPaM.DeleteMark();
809 aPaM.GetPoint()->nContent.Assign(aPaM.GetPointContentNode(), 0);
810 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "redline-new-text ");
811 aDocStat.Reset();
812 pTextNode = aPaM.GetPointNode().GetTextNode();
813 pTextNode->SetWordCountDirty(true);
814 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
815 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(2), aDocStat.nWord);
816 //redline-new-text Lorem ipsum
817 //+++++++++++++++++ ------
818 //select start of original text and part of deleted text
819 aDocStat.Reset();
820 pTextNode->CountWords(aDocStat, 17, 25);
821 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(5), aDocStat.nChar);
824 //See https://bugs.libreoffice.org/show_bug.cgi?id=38983
826 SwDocStat aDocStat;
828 OUString sTemplate("ThisXis a test.");
830 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
831 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', ' '));
832 pTextNode = aPaM.GetPointNode().GetTextNode();
833 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
834 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat.nWord);
835 CPPUNIT_ASSERT_EQUAL(sal_uLong(12), aDocStat.nCharExcludingSpaces);
836 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
837 aDocStat.Reset();
839 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
840 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll("X", " = "));
841 pTextNode = aPaM.GetPointNode().GetTextNode();
842 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
843 CPPUNIT_ASSERT_EQUAL(sal_uLong(5), aDocStat.nWord);
844 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
845 CPPUNIT_ASSERT_EQUAL(sal_uLong(17), aDocStat.nChar);
846 aDocStat.Reset();
848 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
849 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll("X", " _ "));
850 pTextNode = aPaM.GetPointNode().GetTextNode();
851 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
852 CPPUNIT_ASSERT_EQUAL(sal_uLong(5), aDocStat.nWord);
853 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
854 CPPUNIT_ASSERT_EQUAL(sal_uLong(17), aDocStat.nChar);
855 aDocStat.Reset();
857 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
858 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll("X", " -- "));
859 pTextNode = aPaM.GetPointNode().GetTextNode();
860 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
861 CPPUNIT_ASSERT_EQUAL(sal_uLong(5), aDocStat.nWord);
862 CPPUNIT_ASSERT_EQUAL(sal_uLong(14), aDocStat.nCharExcludingSpaces);
863 CPPUNIT_ASSERT_EQUAL(sal_uLong(18), aDocStat.nChar);
864 aDocStat.Reset();
866 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
867 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', '_'));
868 pTextNode = aPaM.GetPointNode().GetTextNode();
869 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
870 CPPUNIT_ASSERT_EQUAL(sal_uLong(3), aDocStat.nWord);
871 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
872 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
873 aDocStat.Reset();
875 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
876 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', '-'));
877 pTextNode = aPaM.GetPointNode().GetTextNode();
878 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
879 CPPUNIT_ASSERT_EQUAL(sal_uLong(3), aDocStat.nWord);
880 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
881 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
882 aDocStat.Reset();
884 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
885 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2012));
886 pTextNode = aPaM.GetPointNode().GetTextNode();
887 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
888 CPPUNIT_ASSERT_EQUAL(sal_uLong(3), aDocStat.nWord);
889 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
890 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
891 aDocStat.Reset();
893 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
894 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2015));
895 pTextNode = aPaM.GetPointNode().GetTextNode();
896 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
897 CPPUNIT_ASSERT_EQUAL(sal_uLong(3), aDocStat.nWord);
898 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
899 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
900 aDocStat.Reset();
902 //But default configuration should, msword-alike treat emdash
903 //and endash as word separators for word-counting
904 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
905 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2013));
906 pTextNode = aPaM.GetPointNode().GetTextNode();
907 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
908 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat.nWord);
909 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
910 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
911 aDocStat.Reset();
913 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
914 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2014));
915 pTextNode = aPaM.GetPointNode().GetTextNode();
916 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
917 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat.nWord);
918 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
919 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat.nChar);
920 aDocStat.Reset();
922 static constexpr OUStringLiteral sChunk = u" \u2013 ";
923 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
924 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll("X", sChunk));
925 pTextNode = aPaM.GetPointNode().GetTextNode();
926 pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
927 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat.nWord);
928 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat.nCharExcludingSpaces);
929 CPPUNIT_ASSERT_EQUAL(sal_uLong(17), aDocStat.nChar);
930 aDocStat.Reset();
934 void SwDocTest::testMergePortionsDeleteNotSorted()
936 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
937 SwPaM aPaM(aIdx);
938 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, " AABBCC");
940 SwCharFormat *const pCharFormat(m_pDoc->MakeCharFormat("foo", nullptr));
941 SwFormatCharFormat const charFormat(pCharFormat);
943 SwFormatINetFormat const inetFormat("http://example.com", "");
945 IDocumentContentOperations & rIDCO(m_pDoc->getIDocumentContentOperations());
946 aPaM.SetMark();
947 aPaM.GetPoint()->nContent = 2;
948 aPaM.GetMark()->nContent = 4;
949 rIDCO.InsertPoolItem(aPaM, charFormat);
950 aPaM.GetPoint()->nContent = 2;
951 aPaM.GetMark()->nContent = 5;
952 rIDCO.InsertPoolItem(aPaM, inetFormat);
953 aPaM.GetPoint()->nContent = 6;
954 aPaM.GetMark()->nContent = 8;
955 rIDCO.InsertPoolItem(aPaM, charFormat);
956 aPaM.GetPoint()->nContent = 4;
957 aPaM.GetMark()->nContent = 6;
958 // this triggered an STL assert in SwpHints::MergePortions()
959 rIDCO.InsertPoolItem(aPaM, charFormat);
962 //See https://bugs.libreoffice.org/show_bug.cgi?id=40599
963 void SwDocTest::testGraphicAnchorDeletion()
965 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong>(0), m_pDoc->getIDocumentStatistics().GetDocStat().nChar);
967 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
968 SwPaM aPaM(aIdx);
970 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Paragraph 1");
971 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
973 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "graphic anchor>><<graphic anchor");
974 SwNodeIndex nPara2(aPaM.GetPoint()->GetNode());
975 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
977 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Paragraph 3");
979 aPaM.GetPoint()->Assign(nPara2);
980 aPaM.GetPoint()->SetContent(RTL_CONSTASCII_LENGTH("graphic anchor>>"));
982 //Insert a graphic at X of >>X<< in paragraph 2
983 SfxItemSet aFlySet(m_pDoc->GetAttrPool(), svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>);
984 SwFormatAnchor aAnchor(RndStdIds::FLY_AS_CHAR);
985 aAnchor.SetAnchor(aPaM.GetPoint());
986 aFlySet.Put(aAnchor);
987 SwFlyFrameFormat *pFrame = m_pDoc->getIDocumentContentOperations().InsertGraphic(aPaM, OUString(), OUString(), nullptr, &aFlySet, nullptr, nullptr);
988 CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame != nullptr);
990 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 1 graphic", static_cast<size_t>(1), m_pDoc->GetFlyCount(FLYCNTTYPE_GRF));
992 //Delete >X<
993 aPaM.GetPoint()->Assign(nPara2);
994 aPaM.GetPoint()->SetContent(
995 RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
996 aPaM.SetMark();
997 aPaM.GetPoint()->Assign(nPara2);
998 aPaM.GetPoint()->SetContent(RTL_CONSTASCII_LENGTH("graphic anchor>"));
999 m_pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
1001 #ifdef DEBUG_AS_HTML
1003 SvFileStream aPasteDebug(OUString("cppunitDEBUG.html"), StreamMode::WRITE|StreamMode::TRUNC);
1004 WriterRef xWrt;
1005 GetHTMLWriter( String(), String(), xWrt );
1006 SwWriter aDbgWrt( aPasteDebug, *m_pDoc );
1007 aDbgWrt.Write( xWrt );
1009 #endif
1011 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 0 graphics", static_cast<size_t>(0), m_pDoc->GetFlyCount(FLYCNTTYPE_GRF));
1013 //Now, if instead we swap RndStdIds::FLY_AS_CHAR (inline graphic) to RndStdIds::FLY_AT_CHAR (anchored to character)
1014 //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
1015 //range to which its anchored, which is annoying.
1018 void SwDocTest::testTableAutoFormats()
1020 SwGlobals::ensure();
1022 //create new AutoFormatTable
1023 SwTableAutoFormatTable aTableAFT;
1025 //check the style size - default is expected
1026 CPPUNIT_ASSERT_EQUAL( size_t(1), aTableAFT.size() );
1028 //create new style
1029 SwTableAutoFormat aTableAF( "TestItemStyle" );
1031 //create new AutoFormat
1032 SwBoxAutoFormat aBoxAF;
1034 //SetFont
1035 SvxFontItem aFont( RES_CHRATR_FONT );
1036 aFont.SetFamily( FontFamily::FAMILY_DECORATIVE );
1037 aFont.SetPitch( FontPitch::PITCH_VARIABLE );
1038 aFont.SetCharSet( RTL_TEXTENCODING_MS_1251 );
1039 aBoxAF.SetFont( aFont );
1040 //SetHeight
1041 SvxFontHeightItem aHeight( 280, 120, RES_CHRATR_FONTSIZE );
1042 aBoxAF.SetHeight( aHeight );
1043 //SetWeight
1044 SvxWeightItem aWeight( FontWeight::WEIGHT_BOLD, RES_CHRATR_WEIGHT );
1045 aBoxAF.SetWeight( aWeight );
1046 //SetPosture
1047 SvxPostureItem aPosture( FontItalic::ITALIC_NORMAL, RES_CHRATR_POSTURE );
1048 aBoxAF.SetPosture( aPosture );
1049 //SetCJKFont
1050 SvxFontItem aCJKFont( RES_CHRATR_FONT );
1051 aCJKFont.SetFamily( FontFamily::FAMILY_MODERN );
1052 aCJKFont.SetPitch( FontPitch::PITCH_FIXED );
1053 aCJKFont.SetCharSet( RTL_TEXTENCODING_MS_1251 );
1054 aBoxAF.SetCJKFont( aCJKFont );
1055 //SetCJKHeight
1056 SvxFontHeightItem aCJKHeight( 230, 110, RES_CHRATR_FONTSIZE );
1057 aBoxAF.SetCJKHeight( aCJKHeight );
1058 //SetCJKWeight
1059 SvxWeightItem aCJKWeight( FontWeight::WEIGHT_SEMIBOLD, RES_CHRATR_WEIGHT );
1060 aBoxAF.SetCJKWeight( aCJKWeight );
1061 //SetCJKPosture
1062 SvxPostureItem aCJKPosture( FontItalic::ITALIC_OBLIQUE, RES_CHRATR_POSTURE );
1063 aBoxAF.SetCJKPosture( aCJKPosture );
1064 //SetCTLFont
1065 SvxFontItem aCTLFont( RES_CHRATR_FONT );
1066 aCTLFont.SetFamily( FontFamily::FAMILY_ROMAN );
1067 aCTLFont.SetPitch( FontPitch::PITCH_FIXED );
1068 aCTLFont.SetCharSet( RTL_TEXTENCODING_MS_1251 );
1069 aBoxAF.SetCTLFont( aCTLFont );
1070 //SetCTLHeight
1071 SvxFontHeightItem aCTLHeight( 215, 105, RES_CHRATR_FONTSIZE );
1072 aBoxAF.SetCTLHeight( aCTLHeight );
1073 //SetCTLWeight
1074 SvxWeightItem aCTLWeight( FontWeight::WEIGHT_ULTRABOLD, RES_CHRATR_WEIGHT );
1075 aBoxAF.SetCTLWeight( aCTLWeight );
1076 //SetCTLPosture
1077 SvxPostureItem aCTLPosture( FontItalic::ITALIC_OBLIQUE, RES_CHRATR_POSTURE );
1078 aBoxAF.SetCTLPosture( aCTLPosture );
1079 //SetUnderline
1080 SvxUnderlineItem aUnderline( FontLineStyle::LINESTYLE_DOTTED, RES_CHRATR_UNDERLINE );
1081 aBoxAF.SetUnderline( aUnderline );
1082 //SetOverline
1083 SvxOverlineItem aOverline( FontLineStyle::LINESTYLE_DASH, RES_CHRATR_OVERLINE );
1084 aBoxAF.SetOverline( aOverline );
1085 //SetCrossedOut
1086 SvxCrossedOutItem aCrossedOut( FontStrikeout::STRIKEOUT_BOLD, RES_CHRATR_CROSSEDOUT );
1087 aBoxAF.SetCrossedOut( aCrossedOut );
1088 //SetContour
1089 SvxContourItem aContour( true, RES_CHRATR_CONTOUR );
1090 aBoxAF.SetContour( aContour );
1091 //SetShadowed
1092 SvxShadowedItem aShadowed( false, RES_CHRATR_SHADOWED );
1093 aBoxAF.SetShadowed( aShadowed );
1094 //SetColor
1095 SvxColorItem aColor( Color(0xFF23FF), RES_CHRATR_COLOR );
1096 aBoxAF.SetColor( aColor );
1097 //SetAdjust
1098 SvxAdjustItem aAdjust( SvxAdjust::Center, RES_PARATR_ADJUST );
1099 aBoxAF.SetAdjust( aAdjust );
1100 //SetTextOrientation
1101 SvxFrameDirectionItem aTOrientation( SvxFrameDirection::Vertical_RL_TB, RES_FRAMEDIR );
1102 aBoxAF.SetTextOrientation( aTOrientation );
1103 //SetVerticalAlignment
1104 SwFormatVertOrient aVAlignment( 3, css::text::VertOrientation::CENTER, css::text::RelOrientation::PAGE_LEFT );
1105 aBoxAF.SetVerticalAlignment( aVAlignment );
1106 //SetBox
1107 SvxBoxItem aBox( RES_BOX );
1108 aBox.SetAllDistances( 5 );
1109 aBoxAF.SetBox( aBox );
1110 //SetBackground
1111 SvxBrushItem aBackground( Color(0xFF11FF), RES_BACKGROUND );
1112 aBoxAF.SetBackground( aBackground );
1113 //Set m_aTLBR
1114 SvxLineItem aTLBRLine(0); aTLBRLine.ScaleMetrics( 11,12 );
1115 aBoxAF.SetTLBR(aTLBRLine);
1116 //Set m_aBLTR
1117 SvxLineItem aBLTRLine(0); aBLTRLine.ScaleMetrics( 13,14 );
1118 aBoxAF.SetBLTR(aBLTRLine);
1119 //Set m_aHorJustify
1120 SvxHorJustifyItem aHJustify( SvxCellHorJustify::Center, 0 );
1121 aBoxAF.SetHorJustify(aHJustify);
1122 //Set m_aVerJustify
1123 SvxVerJustifyItem aVJustify( SvxCellVerJustify::Center , 0 );
1124 aBoxAF.SetVerJustify(aVJustify);
1125 //Set m_aStacked
1126 SfxBoolItem aStacked(0, true);
1127 aBoxAF.SetStacked(aStacked);
1128 //Set m_aMargin
1129 SvxMarginItem aSvxMarginItem(sal_Int16(4), sal_Int16(2), sal_Int16(3), sal_Int16(3), TypedWhichId<SvxMarginItem>(0));
1130 aBoxAF.SetMargin(aSvxMarginItem);
1131 //Set m_aLinebreak
1132 SfxBoolItem aLBreak(0, true);
1133 aBoxAF.SetLinebreak(aLBreak);
1134 //Set m_aRotateAngle
1135 SfxInt32Item aRAngle(sal_Int32(5));
1136 aBoxAF.SetRotateAngle(aRAngle);
1137 //Set m_aRotateMode
1138 SvxRotateModeItem aSvxRotateModeItem(SVX_ROTATE_MODE_CENTER, TypedWhichId<SvxRotateModeItem>(0));
1139 aBoxAF.SetRotateMode(aSvxRotateModeItem);
1140 //Set m_sNumFormatString
1141 OUString aNFString = "UnitTestFormat";
1142 aBoxAF.SetNumFormatString(aNFString);
1143 //Set m_eSysLanguage
1144 LanguageType aSLang( LANGUAGE_ENGLISH_INDIA );
1145 aBoxAF.SetSysLanguage(aSLang);
1146 //Set m_eNumFormatLanguage
1147 LanguageType aNFLang( LANGUAGE_GERMAN );
1148 aBoxAF.SetNumFormatLanguage(aNFLang);
1149 //Set m_aKeepWithNextPara
1150 SvxFormatKeepItem aKWNPara( true, 0 );
1151 aTableAF.SetKeepWithNextPara(aKWNPara);
1152 //Set m_aRepeatHeading
1153 sal_uInt16 aRHeading = 3;
1154 aTableAF.m_aRepeatHeading = aRHeading;
1155 //Set m_bLayoutSplit
1156 bool aLSplit = false;
1157 aTableAF.m_bLayoutSplit = aLSplit;
1158 //Set m_bRowSplit
1159 bool aRSplit = false;
1160 aTableAF.m_bRowSplit = aRSplit;
1161 //Set m_bCollapsingBorders
1162 bool aCBorders = false;
1163 aTableAF.m_bCollapsingBorders = aCBorders;
1164 //Set m_aShadow
1165 SvxShadowItem aShadow( 0, nullptr, 103, SvxShadowLocation::BottomLeft );
1166 aTableAF.SetShadow(aShadow);
1167 //Set bInclFont
1168 bool aIFont = false;
1169 aTableAF.m_bInclFont = aIFont;
1170 //Set bInclJustify
1171 bool aIJustify = false;
1172 aTableAF.m_bInclJustify = aIJustify;
1173 //Set bInclFrame
1174 bool aIFrame = false;
1175 aTableAF.m_bInclFrame = aIFrame;
1176 //Set bInclBackground
1177 bool aIBackground = false;
1178 aTableAF.m_bInclBackground = aIBackground;
1179 //Set bInclValueFormat
1180 bool aIVFormat = false;
1181 aTableAF.m_bInclValueFormat = aIVFormat;
1183 //set the box format to AutoFormat
1184 aTableAF.SetBoxFormat( aBoxAF, sal_uInt8(0) );
1185 //add AutoFormat to AutoFormatTable
1186 aTableAFT.AddAutoFormat( aTableAF );
1188 //check the style size
1189 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT.size() );
1191 //save the bInclFontstyles
1192 aTableAFT.Save();
1194 //check the style size after save
1195 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT.size() );
1197 //create new AutoFormatTable
1198 SwTableAutoFormatTable aLoadTAFT;
1200 //check the style size
1201 CPPUNIT_ASSERT_EQUAL( size_t(1), aLoadTAFT.size() );
1203 //load the saved styles
1204 aLoadTAFT.Load();
1206 //check the style size after load
1207 CPPUNIT_ASSERT_EQUAL( size_t(2), aLoadTAFT.size() );
1209 //assert the values
1210 SwTableAutoFormat* pLoadAF = aLoadTAFT.FindAutoFormat( u"TestItemStyle" );
1211 CPPUNIT_ASSERT( pLoadAF );
1212 //GetFont
1213 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetFont() == aFont ) );
1214 //GetHeight
1215 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetHeight() == aHeight ) );
1216 //GetWeight
1217 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetWeight() == aWeight ) );
1218 //GetPosture
1219 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetPosture() == aPosture ) );
1220 //GetCJKFont
1221 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCJKFont() == aCJKFont ) );
1222 //GetCJKHeight
1223 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCJKHeight() == aCJKHeight ) );
1224 //GetCJKWeight
1225 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCJKWeight() == aCJKWeight ) );
1226 //GetCJKPosture
1227 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCJKPosture() == aCJKPosture ) );
1228 //GetCTLFont
1229 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCTLFont() == aCTLFont ) );
1230 //GetCTLHeight
1231 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCTLHeight() == aCTLHeight ) );
1232 //GetCTLWeight
1233 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCTLWeight() == aCTLWeight ) );
1234 //GetCTLPosture
1235 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCTLPosture() == aCTLPosture ) );
1236 //GetUnderline
1237 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetUnderline() == aUnderline ) );
1238 //GetOverline
1239 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetOverline() == aOverline ) );
1240 //GetCrossedOut
1241 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetCrossedOut() == aCrossedOut ) );
1242 //GetContour
1243 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetContour() == aContour ) );
1244 //GetShadowed
1245 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetShadowed() == aShadowed ) );
1246 //GetColor
1247 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetColor() == aColor) );
1248 //GetAdjust
1249 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetAdjust() == aAdjust ) );
1250 //GetTextOrientation
1251 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetTextOrientation() == aTOrientation ) );
1252 //GetVerticalAlignment
1253 CPPUNIT_ASSERT (bool( pLoadAF->GetBoxFormat(0).GetVerticalAlignment() == aVAlignment ) );
1254 //GetBox
1255 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetBox() == aBox ) );
1256 //GetBackground
1257 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetBackground() == aBackground ) );
1258 //Get m_aTLBR
1259 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetTLBR() == aTLBRLine ) );
1260 //Get m_aBLTR
1261 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetBLTR() == aBLTRLine ) );
1262 //Get m_aHorJustify
1263 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetHorJustify() == aHJustify ) );
1264 //Get m_aVerJustify
1265 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetVerJustify() == aVJustify ) );
1266 //Get m_aStacked
1267 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetStacked() == aStacked ) );
1268 //Get m_aMargin
1269 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetMargin() == aSvxMarginItem ) );
1270 //Get m_aLinebreak
1271 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetLinebreak() == aLBreak ) );
1272 //Get m_aRotateAngle
1273 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetRotateAngle() == aRAngle ) );
1274 //Get m_aRotateMode
1275 //SvxRotateModeItem aRMode = aBoxAF.m_aRotateMode;GetRotateMode
1276 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetRotateMode() == aSvxRotateModeItem ) );
1277 //Get m_sNumFormatString
1278 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetNumFormatString() == aNFString ) );
1279 //Get m_eSysLanguage
1280 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetSysLanguage() == aSLang ) );
1281 //Get m_eNumFormatLanguage
1282 CPPUNIT_ASSERT( bool( pLoadAF->GetBoxFormat(0).GetNumFormatLanguage() == aNFLang ) );
1283 //Get m_aKeepWithNextPara
1284 CPPUNIT_ASSERT( bool( pLoadAF->GetKeepWithNextPara() == aKWNPara ) );
1285 //Get m_aRepeatHeading
1286 CPPUNIT_ASSERT( bool( pLoadAF->m_aRepeatHeading == aRHeading ) );
1287 //Get m_bLayoutSplit
1288 CPPUNIT_ASSERT( bool( pLoadAF->m_bLayoutSplit == aLSplit ) );
1289 //Get m_bRowSplit
1290 CPPUNIT_ASSERT( bool( pLoadAF->m_bRowSplit == aRSplit ) );
1291 //Get m_bCollapsingBorders
1292 CPPUNIT_ASSERT( bool( pLoadAF->m_bCollapsingBorders == aCBorders ) );
1293 //Get m_aShadow
1294 CPPUNIT_ASSERT( bool( pLoadAF->GetShadow() == aShadow ) );
1295 //Get bInclFont
1296 CPPUNIT_ASSERT( bool( pLoadAF->m_bInclFont == aIFont ) );
1297 //Get bInclJustify
1298 CPPUNIT_ASSERT( bool( pLoadAF->m_bInclJustify == aIJustify ) );
1299 //Get bInclFrame
1300 CPPUNIT_ASSERT( bool( pLoadAF->m_bInclFrame == aIFrame ) );
1301 //Get bInclBackground
1302 CPPUNIT_ASSERT( bool( pLoadAF->m_bInclBackground == aIBackground ) );
1303 //Get bInclValueFormat
1304 CPPUNIT_ASSERT( bool( pLoadAF->m_bInclValueFormat == aIVFormat ) );
1307 static OUString
1308 translitTest(SwDoc & rDoc, const SwPaM & rPaM, TransliterationFlags const nType)
1310 utl::TransliterationWrapper aTrans(
1311 ::comphelper::getProcessComponentContext(), nType);
1312 rDoc.getIDocumentContentOperations().TransliterateText(rPaM, aTrans);
1313 return rPaM.GetText();
1316 void SwDocTest::testTransliterate()
1318 // just some simple test to see if it's totally broken
1319 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1320 SwPaM aPaM(aIdx);
1321 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "foobar");
1322 aPaM.SetMark();
1323 aPaM.GetPoint()->nContent = 0;
1324 CPPUNIT_ASSERT_EQUAL(OUString("foobar"), aPaM.GetText());
1326 CPPUNIT_ASSERT_EQUAL(OUString("FOOBAR"),
1327 translitTest(*m_pDoc, aPaM,
1328 TransliterationFlags::LOWERCASE_UPPERCASE));
1329 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1330 translitTest(*m_pDoc, aPaM,
1331 TransliterationFlags::TITLE_CASE));
1332 CPPUNIT_ASSERT_EQUAL(OUString("fOOBAR"),
1333 translitTest(*m_pDoc, aPaM,
1334 TransliterationFlags::TOGGLE_CASE));
1335 CPPUNIT_ASSERT_EQUAL(OUString("foobar"),
1336 translitTest(*m_pDoc, aPaM,
1337 TransliterationFlags::UPPERCASE_LOWERCASE));
1338 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1339 translitTest(*m_pDoc, aPaM,
1340 TransliterationFlags::SENTENCE_CASE));
1341 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1342 translitTest(*m_pDoc, aPaM,
1343 TransliterationFlags::HIRAGANA_KATAKANA));
1345 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
1346 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "one (two) three");
1347 aPaM.SetMark();
1348 aPaM.GetMark()->nContent = 0;
1349 CPPUNIT_ASSERT_EQUAL(OUString("One (Two) Three"),
1350 translitTest(*m_pDoc, aPaM,
1351 TransliterationFlags::TITLE_CASE));
1354 namespace
1356 class SwTableFormulaTest : public SwTableFormula
1358 SwTableNode *m_pNode;
1359 public:
1360 SwTableFormulaTest(const OUString &rStr, SwTableNode *pNode)
1361 : SwTableFormula(rStr)
1362 , m_pNode(pNode)
1364 m_eNmType = INTRNL_NAME;
1366 virtual const SwNode* GetNodeOfFormula() const override
1368 return m_pNode;
1373 //tdf#66353 Expression is faulty
1374 void SwDocTest::testFormulas()
1376 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1377 SwPosition aPos(aIdx);
1379 const SwTable *pTable = m_pDoc->InsertTable(
1380 SwInsertTableOptions(SwInsertTableFlags::HeadlineNoBorder, 0), aPos, 1, 3, 0);
1381 SwTableNode* pTableNode = pTable->GetTableNode();
1382 SwTableFormulaTest aFormula("<\x12-1,0>+<Table1.A1>", pTableNode);
1384 aFormula.PtrToBoxNm(pTable);
1386 CPPUNIT_ASSERT_EQUAL(OUString("<?>+<Table1.?>"), aFormula.GetFormula());
1388 // tdf#61228: Evaluating non-defined function should return an error
1389 SwCalc aCalc(*m_pDoc);
1390 SwSbxValue val = aCalc.Calculate("foobar()");
1391 CPPUNIT_ASSERT(aCalc.IsCalcError());
1392 CPPUNIT_ASSERT(val.IsVoidValue());
1393 CPPUNIT_ASSERT(val.IsDouble());
1394 CPPUNIT_ASSERT_EQUAL(DBL_MAX, val.GetDouble());
1395 // Evaluating non-defined variable should return 0 without an error
1396 val = aCalc.Calculate("foobar");
1397 CPPUNIT_ASSERT(!aCalc.IsCalcError());
1398 CPPUNIT_ASSERT(val.IsVoidValue());
1399 CPPUNIT_ASSERT(val.IsLong());
1400 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), val.GetLong());
1403 void SwDocTest::testMarkMove()
1405 IDocumentMarkAccess* pMarksAccess = m_pDoc->getIDocumentMarkAccess();
1408 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1409 SwPaM aPaM(aIdx);
1410 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Paragraph 1");
1411 aPaM.SetMark();
1412 aPaM.GetMark()->nContent -= aPaM.GetMark()->GetContentIndex();
1413 pMarksAccess->makeMark(aPaM, "Para1",
1414 IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
1416 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
1417 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Paragraph 2");
1418 aPaM.SetMark();
1419 aPaM.GetMark()->nContent -= aPaM.GetMark()->GetContentIndex();
1420 pMarksAccess->makeMark(aPaM, "Para2",
1421 IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
1423 m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
1424 m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "Paragraph 3");
1425 aPaM.SetMark();
1426 aPaM.GetMark()->nContent -= aPaM.GetMark()->GetContentIndex();
1427 pMarksAccess->makeMark(aPaM, "Para3",
1428 IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
1431 // join paragraph 2 and 3 and check
1433 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -2);
1434 SwTextNode& rParaNode2 = dynamic_cast<SwTextNode&>(aIdx.GetNode());
1435 rParaNode2.JoinNext();
1437 ::sw::mark::IMark* pBM1 = *pMarksAccess->findMark("Para1");
1438 ::sw::mark::IMark* pBM2 = *pMarksAccess->findMark("Para2");
1439 ::sw::mark::IMark* pBM3 = *pMarksAccess->findMark("Para3");
1441 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM1->GetMarkStart().GetContentIndex());
1442 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM1->GetMarkEnd().GetContentIndex());
1443 CPPUNIT_ASSERT_EQUAL(
1444 pBM1->GetMarkStart().GetNodeIndex(),
1445 pBM1->GetMarkEnd().GetNodeIndex());
1447 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM2->GetMarkStart().GetContentIndex());
1448 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM2->GetMarkEnd().GetContentIndex());
1449 CPPUNIT_ASSERT_EQUAL(
1450 pBM2->GetMarkStart().GetNodeIndex(),
1451 pBM2->GetMarkEnd().GetNodeIndex());
1453 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM3->GetMarkStart().GetContentIndex());
1454 CPPUNIT_ASSERT_EQUAL(sal_Int32(22), pBM3->GetMarkEnd().GetContentIndex());
1455 CPPUNIT_ASSERT_EQUAL(
1456 pBM3->GetMarkStart().GetNodeIndex(),
1457 pBM3->GetMarkEnd().GetNodeIndex());
1459 CPPUNIT_ASSERT_EQUAL(
1460 pBM1->GetMarkStart().GetNodeIndex()+1,
1461 pBM2->GetMarkStart().GetNodeIndex());
1462 CPPUNIT_ASSERT_EQUAL(
1463 pBM2->GetMarkStart().GetNodeIndex(),
1464 pBM3->GetMarkStart().GetNodeIndex());
1466 // cut some text
1468 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1469 SwPaM aPaM(aIdx, aIdx, SwNodeOffset(-1));
1470 aPaM.GetPoint()->nContent += 5;
1471 aPaM.GetMark()->nContent += 6;
1472 m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM);
1474 pBM1 = *pMarksAccess->findMark("Para1");
1475 pBM2 = *pMarksAccess->findMark("Para2");
1476 pBM3 = *pMarksAccess->findMark("Para3");
1478 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1->GetMarkStart().GetContentIndex());
1479 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1->GetMarkEnd().GetContentIndex());
1480 CPPUNIT_ASSERT_EQUAL(
1481 pBM1->GetMarkStart().GetNodeIndex(),
1482 pBM1->GetMarkEnd().GetNodeIndex());
1484 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2->GetMarkStart().GetContentIndex());
1485 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM2->GetMarkEnd().GetContentIndex());
1486 CPPUNIT_ASSERT_EQUAL(
1487 pBM2->GetMarkStart().GetNodeIndex(),
1488 pBM2->GetMarkEnd().GetNodeIndex());
1490 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM3->GetMarkStart().GetContentIndex());
1491 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), pBM3->GetMarkEnd().GetContentIndex());
1492 CPPUNIT_ASSERT_EQUAL(
1493 pBM3->GetMarkStart().GetNodeIndex(),
1494 pBM3->GetMarkEnd().GetNodeIndex());
1496 CPPUNIT_ASSERT_EQUAL(
1497 pBM1->GetMarkStart().GetNodeIndex(),
1498 pBM2->GetMarkStart().GetNodeIndex());
1499 CPPUNIT_ASSERT_EQUAL(
1500 pBM2->GetMarkStart().GetNodeIndex(),
1501 pBM3->GetMarkStart().GetNodeIndex());
1503 // split the paragraph
1505 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1506 SwPosition aPos(aIdx);
1507 aPos.nContent += 8;
1508 m_pDoc->getIDocumentContentOperations().SplitNode(aPos, false);
1510 pBM1 = *pMarksAccess->findMark("Para1");
1511 pBM2 = *pMarksAccess->findMark("Para2");
1512 pBM3 = *pMarksAccess->findMark("Para3");
1514 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1->GetMarkStart().GetContentIndex());
1515 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1->GetMarkEnd().GetContentIndex());
1516 CPPUNIT_ASSERT_EQUAL(
1517 pBM1->GetMarkStart().GetNodeIndex(),
1518 pBM1->GetMarkEnd().GetNodeIndex());
1520 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2->GetMarkStart().GetContentIndex());
1521 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM2->GetMarkEnd().GetContentIndex());
1522 CPPUNIT_ASSERT_EQUAL(
1523 pBM2->GetMarkStart().GetNodeIndex()+1,
1524 pBM2->GetMarkEnd().GetNodeIndex());
1526 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM3->GetMarkStart().GetContentIndex());
1527 CPPUNIT_ASSERT_EQUAL(sal_Int32(15), pBM3->GetMarkEnd().GetContentIndex());
1528 CPPUNIT_ASSERT_EQUAL(
1529 pBM3->GetMarkStart().GetNodeIndex(),
1530 pBM3->GetMarkEnd().GetNodeIndex());
1532 CPPUNIT_ASSERT_EQUAL(
1533 pBM1->GetMarkStart().GetNodeIndex(),
1534 pBM2->GetMarkStart().GetNodeIndex());
1535 CPPUNIT_ASSERT_EQUAL(
1536 pBM2->GetMarkEnd().GetNodeIndex(),
1537 pBM3->GetMarkEnd().GetNodeIndex());
1540 namespace
1542 struct TestRing : public sw::Ring<TestRing>
1544 TestRing() : sw::Ring<TestRing>() {};
1545 TestRing* GetNext()
1546 { return GetNextInRing(); }
1547 TestRing* GetPrev()
1548 { return GetPrevInRing(); }
1549 bool lonely() const
1550 { return unique(); }
1554 void SwDocTest::testIntrusiveRing()
1556 TestRing aRing1, aRing2, aRing3, aRing4, aRing5;
1557 std::vector<TestRing*> vRings
1559 &aRing1,
1560 &aRing2,
1561 &aRing3,
1562 &aRing4,
1563 &aRing5
1565 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aRing1.GetRingContainer().size());
1566 CPPUNIT_ASSERT(aRing1.lonely());
1567 CPPUNIT_ASSERT(aRing2.lonely());
1568 CPPUNIT_ASSERT(aRing3.lonely());
1569 aRing2.MoveTo(&aRing1);
1570 aRing3.MoveTo(&aRing1);
1571 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing1.GetRingContainer().size());
1572 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing2.GetRingContainer().size());
1573 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing3.GetRingContainer().size());
1574 CPPUNIT_ASSERT(!aRing1.lonely());
1575 CPPUNIT_ASSERT(!aRing2.lonely());
1576 CPPUNIT_ASSERT(!aRing3.lonely());
1577 aRing5.MoveTo(&aRing4);
1578 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), aRing4.GetRingContainer().size());
1579 aRing4.GetRingContainer().merge(aRing1.GetRingContainer());
1580 for(TestRing* pRing : vRings)
1582 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), pRing->GetRingContainer().size());
1584 for(std::vector<TestRing*>::iterator ppRing = vRings.begin(); ppRing != vRings.end(); ++ppRing)
1586 std::vector<TestRing*>::iterator ppNext = ppRing+1;
1587 if(ppNext==vRings.end())
1588 ppNext = vRings.begin();
1589 CPPUNIT_ASSERT_EQUAL((*ppRing)->GetNext(), *ppNext);
1590 CPPUNIT_ASSERT_EQUAL((*ppNext)->GetPrev(), *ppRing);
1592 for(TestRing& r: aRing1.GetRingContainer())
1594 TestRing* pRing = &r;
1595 CPPUNIT_ASSERT(pRing);
1597 const TestRing* pConstRing = &aRing1;
1598 for(const TestRing& r: pConstRing->GetRingContainer()) // this should fail without r being const
1600 const TestRing* pRing = &r;
1601 CPPUNIT_ASSERT(pRing);
1603 TestRing foo, bar;
1604 foo.MoveTo(&bar);
1605 CPPUNIT_ASSERT_EQUAL(&foo, bar.GetNext());
1606 CPPUNIT_ASSERT_EQUAL(&foo, bar.GetPrev());
1607 CPPUNIT_ASSERT_EQUAL(&bar, foo.GetNext());
1608 CPPUNIT_ASSERT_EQUAL(&bar, foo.GetPrev());
1609 foo.MoveTo(&foo);
1610 CPPUNIT_ASSERT_EQUAL(&bar, bar.GetNext());
1611 CPPUNIT_ASSERT_EQUAL(&bar, bar.GetPrev());
1612 CPPUNIT_ASSERT_EQUAL(&foo, foo.GetNext());
1613 CPPUNIT_ASSERT_EQUAL(&foo, foo.GetPrev());
1616 namespace
1618 struct TestHint final : SfxHint {};
1619 struct TestModify : sw::BroadcastingModify
1622 struct TestClient : SwClient
1624 int m_nModifyCount;
1625 int m_nNotifyCount;
1626 int m_nModifyChangedCount;
1627 const SwModify* m_pLastChangedModify;
1628 TestClient() : m_nModifyCount(0), m_nNotifyCount(0), m_nModifyChangedCount(0), m_pLastChangedModify(nullptr) {};
1629 virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override
1631 if(typeid(TestHint) == typeid(rHint))
1632 ++m_nNotifyCount;
1633 else if(dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
1634 ++m_nModifyCount;
1635 else if(auto pModifyChangedHint = dynamic_cast<const sw::ModifyChangedHint*>(&rHint))
1637 ++m_nModifyChangedCount;
1638 m_pLastChangedModify = pModifyChangedHint->m_pNew;
1642 struct OtherTestClient : SwClient
1644 int m_nModifyCount;
1645 OtherTestClient() : m_nModifyCount(0) {};
1646 virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override
1648 if(dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
1649 ++m_nModifyCount;
1652 struct TestListener : SvtListener
1654 int m_nNotifyCount;
1655 TestListener() : m_nNotifyCount(0) {};
1656 virtual void Notify( const SfxHint& ) override
1658 ++m_nNotifyCount;
1662 void SwDocTest::testClientModify()
1664 (void) OtherTestClient(); // avoid loplugin:unreffun
1665 TestModify aMod;
1666 TestClient aClient1, aClient2;
1667 OtherTestClient aOtherClient1;
1668 // test client registration
1669 CPPUNIT_ASSERT(!aMod.HasWriterListeners());
1670 CPPUNIT_ASSERT(!aMod.HasOnlyOneListener());
1671 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aClient1.GetRegisteredIn());
1672 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aClient2.GetRegisteredIn());
1673 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aClient2.GetRegisteredIn());
1674 aMod.Add(&aClient1);
1675 CPPUNIT_ASSERT(aMod.HasWriterListeners());
1676 CPPUNIT_ASSERT(aMod.HasOnlyOneListener());
1677 aMod.Add(&aClient2);
1678 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(&aMod),aClient1.GetRegisteredIn());
1679 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(&aMod), aClient2.GetRegisteredIn());
1680 CPPUNIT_ASSERT(aMod.HasWriterListeners());
1681 CPPUNIT_ASSERT(!aMod.HasOnlyOneListener());
1682 // test broadcast
1683 aMod.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1684 CPPUNIT_ASSERT_EQUAL(1,aClient1.m_nModifyCount);
1685 CPPUNIT_ASSERT_EQUAL(1,aClient2.m_nModifyCount);
1686 CPPUNIT_ASSERT_EQUAL(0,aClient1.m_nNotifyCount);
1687 CPPUNIT_ASSERT_EQUAL(0,aClient2.m_nNotifyCount);
1688 aMod.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1689 CPPUNIT_ASSERT_EQUAL(2,aClient1.m_nModifyCount);
1690 CPPUNIT_ASSERT_EQUAL(2,aClient2.m_nModifyCount);
1691 CPPUNIT_ASSERT_EQUAL(0,aClient1.m_nNotifyCount);
1692 CPPUNIT_ASSERT_EQUAL(0,aClient2.m_nNotifyCount);
1693 // test notify
1695 TestHint aHint;
1696 aMod.CallSwClientNotify(aHint);
1697 CPPUNIT_ASSERT_EQUAL(2,aClient1.m_nModifyCount);
1698 CPPUNIT_ASSERT_EQUAL(2,aClient2.m_nModifyCount);
1699 CPPUNIT_ASSERT_EQUAL(1,aClient1.m_nNotifyCount);
1700 CPPUNIT_ASSERT_EQUAL(1,aClient2.m_nNotifyCount);
1702 // test typed iteration
1703 CPPUNIT_ASSERT(typeid(aClient1) != typeid(OtherTestClient));
1705 SwIterator<OtherTestClient,SwModify> aIter(aMod);
1706 for(OtherTestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1707 CPPUNIT_ASSERT(false);
1710 int nCount = 0;
1711 SwIterator<TestClient,SwModify> aIter(aMod);
1712 for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1714 CPPUNIT_ASSERT_EQUAL(2,pClient->m_nModifyCount);
1715 ++nCount;
1717 CPPUNIT_ASSERT_EQUAL(2,nCount);
1719 aMod.Add(&aOtherClient1);
1720 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1.m_nModifyCount);
1722 int nCount = 0;
1723 SwIterator<TestClient,SwModify> aIter(aMod);
1724 for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1726 CPPUNIT_ASSERT_EQUAL(2,pClient->m_nModifyCount);
1727 ++nCount;
1729 CPPUNIT_ASSERT_EQUAL(2,nCount);
1731 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1.m_nModifyCount);
1732 aMod.Remove(&aOtherClient1);
1733 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(&aMod),aClient1.GetRegisteredIn());
1734 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(&aMod),aClient2.GetRegisteredIn());
1735 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aOtherClient1.GetRegisteredIn());
1736 // test client self-deregistration during iteration
1738 int nCount = 0;
1739 SwIterator<TestClient,SwModify> aIter(aMod);
1740 for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1742 aMod.Remove(pClient);
1743 ++nCount;
1745 CPPUNIT_ASSERT_EQUAL(2,nCount);
1747 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aClient1.GetRegisteredIn());
1748 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify*>(nullptr),aClient2.GetRegisteredIn());
1750 SwIterator<TestClient,SwModify> aIter(aMod);
1751 for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1753 CPPUNIT_ASSERT(false);
1756 aMod.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1757 CPPUNIT_ASSERT_EQUAL(2,aClient1.m_nModifyCount);
1758 CPPUNIT_ASSERT_EQUAL(2,aClient2.m_nModifyCount);
1759 CPPUNIT_ASSERT_EQUAL(1,aClient1.m_nNotifyCount);
1760 CPPUNIT_ASSERT_EQUAL(1,aClient2.m_nNotifyCount);
1762 void SwDocTest::testBroadcastingModify()
1764 sw::BroadcastingModify aMod;
1765 TestClient aClient;
1766 TestListener aListener;
1768 aMod.Add(&aClient);
1769 aListener.StartListening(aMod.GetNotifier());
1771 aMod.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1772 CPPUNIT_ASSERT_EQUAL(1,aClient.m_nModifyCount);
1773 CPPUNIT_ASSERT_EQUAL(1,aClient.m_nModifyCount);
1774 CPPUNIT_ASSERT_EQUAL(1,aListener.m_nNotifyCount);
1776 void SwDocTest::testWriterMultiListener()
1778 TestModify aMod;
1779 TestClient aClient;
1780 sw::WriterMultiListener aMulti(aClient);
1781 CPPUNIT_ASSERT(!aMulti.IsListeningTo(&aMod));
1782 aMulti.StartListening(&aMod);
1783 CPPUNIT_ASSERT(aMulti.IsListeningTo(&aMod));
1784 aMulti.EndListeningAll();
1785 CPPUNIT_ASSERT(!aMulti.IsListeningTo(&aMod));
1786 aMulti.StartListening(&aMod);
1787 aMulti.EndListening(&aMod);
1788 CPPUNIT_ASSERT(!aMulti.IsListeningTo(&aMod));
1789 int nPreDeathChangedCount;
1791 TestModify aTempMod;
1792 aMod.Add(&aTempMod);
1793 aMulti.StartListening(&aTempMod);
1794 nPreDeathChangedCount = aClient.m_nModifyChangedCount;
1796 CPPUNIT_ASSERT(aMulti.IsListeningTo(&aMod));
1797 CPPUNIT_ASSERT_EQUAL(nPreDeathChangedCount+1, aClient.m_nModifyChangedCount);
1798 CPPUNIT_ASSERT_EQUAL(static_cast<const SwModify*>(&aMod),aClient.m_pLastChangedModify);
1801 void SwDocTest::test64kPageDescs()
1803 size_t nPageDescCount = 65536; // USHRT_MAX + 1
1805 for (size_t i = 0; i < nPageDescCount; ++i)
1807 OUString aName = "Page" + OUString::number(i);
1808 m_pDoc->MakePageDesc( aName );
1811 size_t nCount = m_pDoc->GetPageDescCnt();
1812 // +1 because Writer always creates a dummy page desc
1813 // in a new SwDoc
1814 CPPUNIT_ASSERT_EQUAL( nPageDescCount + 1, nCount );
1816 const SwPageDesc &rDesc = m_pDoc->GetPageDesc( nPageDescCount );
1817 SwPageDesc &rZeroDesc = m_pDoc->GetPageDesc( 0 );
1818 CPPUNIT_ASSERT_EQUAL( OUString("Page65535"), rDesc.GetName() );
1820 SwPageDesc aDesc( rDesc );
1821 static const OUStringLiteral aChanged(u"Changed01");
1822 aDesc.SetName( aChanged );
1823 m_pDoc->ChgPageDesc( nPageDescCount, aDesc );
1825 size_t nPos;
1826 SwPageDesc *pDesc = m_pDoc->FindPageDesc( aChanged, &nPos );
1827 CPPUNIT_ASSERT( pDesc != nullptr );
1828 CPPUNIT_ASSERT_EQUAL( nPageDescCount, nPos );
1830 // check if we didn't mess up PageDesc at pos 0
1831 // (happens with 16bit int overflow)
1832 OUString aZeroName = rZeroDesc.GetName();
1833 rZeroDesc = m_pDoc->GetPageDesc( 0 );
1834 CPPUNIT_ASSERT_EQUAL( aZeroName, rZeroDesc.GetName() );
1836 m_pDoc->DelPageDesc( aChanged, /*bBroadcast*/true );
1837 pDesc = m_pDoc->FindPageDesc( aChanged, &nPos );
1838 // not there anymore
1839 CPPUNIT_ASSERT( !pDesc );
1840 CPPUNIT_ASSERT_EQUAL( std::numeric_limits<size_t>::max(), nPos);
1842 // check if PageDesc at pos 0 is still there
1843 pDesc = m_pDoc->FindPageDesc( aZeroName, &nPos );
1844 CPPUNIT_ASSERT( pDesc != nullptr );
1845 CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(0), nPos );
1848 void SwDocTest::testTdf92308()
1850 CPPUNIT_ASSERT_EQUAL(false, m_pDoc->HasInvisibleContent());
1853 void SwDocTest::testTableCellComparison()
1855 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst(u"A1", u"Z1") );
1856 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u"Z1", u"A1") );
1857 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByColFirst(u"A1", u"A1") );
1859 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u"A2", u"A1") );
1860 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u"Z3", u"A2") );
1861 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst(u"A3", u"Z1") );
1863 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByRowFirst(u"A1", u"Z1") );
1864 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u"Z1", u"A1") );
1865 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByRowFirst(u"A1", u"A1") );
1867 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u"A2", u"A1") );
1868 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u"Z3", u"A2") );
1869 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u"A3", u"Z1") );
1871 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u"A1", u"A1", u"A1", u"A1", true) );
1872 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u"A1", u"Z1", u"A1", u"Z1", true) );
1873 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u"A1", u"Z1", u"A1", u"Z1", false) );
1875 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u"A1", u"Z1", u"B1", u"Z1", true) );
1876 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u"A1", u"Z1", u"A2", u"Z2", false) );
1877 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u"A1", u"Z1", u"A2", u"Z2", true) );
1878 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u"A1", u"Z1", u"A6", u"Z2", true) );
1880 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u"B1", u"Z1", u"A1", u"Z1", true) );
1881 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u"A2", u"Z2", u"A1", u"Z1", false) );
1882 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u"A2", u"Z2", u"A1", u"Z1", true) );
1883 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u"A6", u"Z2", u"A1", u"Z1", true) );
1885 OUString rCell1("A1");
1886 OUString rCell2("C5");
1888 sw_NormalizeRange(rCell1, rCell2);
1889 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell1 );
1890 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell2 );
1892 sw_NormalizeRange(rCell2, rCell1);
1893 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell1 );
1894 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell2 );
1896 rCell1 = OUString("A5");
1897 rCell2 = OUString("C1");
1899 sw_NormalizeRange(rCell1, rCell2);
1900 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell1 );
1901 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell2 );
1903 sw_NormalizeRange(rCell2, rCell1);
1904 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell1 );
1905 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell2 );
1907 CPPUNIT_ASSERT_EQUAL( OUString(), sw_GetCellName(-1, -1) );
1910 void SwDocTest::setUp()
1912 BootstrapFixture::setUp();
1914 SwGlobals::ensure();
1915 m_pDoc = new SwDoc;
1916 m_xDocShRef = new SwDocShell(*m_pDoc, SfxObjectCreateMode::EMBEDDED);
1917 m_xDocShRef->DoInitNew();
1920 void SwDocTest::tearDown()
1922 m_pDoc = nullptr; // deleted by DoClose()
1923 m_xDocShRef->DoClose();
1924 m_xDocShRef.clear();
1926 BootstrapFixture::tearDown();
1929 CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);
1931 CPPUNIT_PLUGIN_IMPLEMENT();
1933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */