1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
11 #include <test/bootstrapfixture.hxx>
13 #include <com/sun/star/i18n/WordType.hpp>
15 #include <rtl/strbuf.hxx>
16 #include <osl/file.hxx>
18 #include <comphelper/processfactory.hxx>
19 #include <comphelper/random.hxx>
20 #include <i18nutil/transliteration.hxx>
21 #include <tools/urlobj.hxx>
22 #include <unotools/tempfile.hxx>
23 #include <unotools/transliterationwrapper.hxx>
25 #include <editeng/langitem.hxx>
26 #include <editeng/charhiddenitem.hxx>
28 #include <sfx2/app.hxx>
29 #include <sfx2/docfilt.hxx>
30 #include <sfx2/docfile.hxx>
31 #include <sfx2/sfxmodelfactory.hxx>
33 #include <xmloff/odffields.hxx>
35 #include <breakit.hxx>
37 #include <IDocumentRedlineAccess.hxx>
38 #include <IDocumentFieldsAccess.hxx>
39 #include <IDocumentStatistics.hxx>
40 #include <cellfml.hxx>
42 #include <docstat.hxx>
43 #include <docufld.hxx>
44 #include <fmtanchr.hxx>
47 #include <shellio.hxx>
48 #include <shellres.hxx>
50 #include <swscanner.hxx>
51 #include <swmodule.hxx>
53 #include <swtypes.hxx>
55 #include <fmtrfmrk.hxx>
56 #include <fmtinfmt.hxx>
57 #include <fchrfmt.hxx>
59 #include <redline.hxx>
61 #include <modeltoviewhelper.hxx>
62 #include <scriptinfo.hxx>
66 #include <pagedesc.hxx>
69 #include <tblafmt.hxx>
71 #include <IDocumentMarkAccess.hxx>
72 #include <itabenum.hxx>
74 typedef tools::SvRef
<SwDocShell
> SwDocShellRef
;
76 using namespace ::com::sun::star
;
78 /* Implementation of Swdoc-Test class */
80 class SwDocTest
: public test::BootstrapFixture
88 virtual void setUp() override
;
89 virtual void tearDown() override
;
92 void testTableAutoFormats();
93 void testPageDescName();
94 void testFileNameFields();
96 void testModelToViewHelperPassthrough();
97 void testModelToViewHelperExpandFieldsExpandFootnote();
98 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode();
99 void testModelToViewHelperExpandFields();
100 void testModelToViewHelperExpandFieldsReplaceMode();
101 void testModelToViewHelperExpandFieldsHideInvisible();
102 void testModelToViewHelperExpandFieldsHideRedlined();
103 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote();
104 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode();
105 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote();
106 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode();
107 void testModelToViewHelperHideInvisibleHideRedlined();
108 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote();
109 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode();
110 void testModelToViewHelperExpandFieldsExpandFootnote2();
111 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2();
112 void testSwScanner();
113 void testUserPerceivedCharCount();
114 void testMergePortionsDeleteNotSorted();
115 void testGraphicAnchorDeletion();
116 void testTransliterate();
119 void testIntrusiveRing();
120 void testClientModify();
121 void testWriterMultiListener();
122 void test64kPageDescs();
124 void testTableCellComparison();
126 CPPUNIT_TEST_SUITE(SwDocTest
);
128 CPPUNIT_TEST(testTransliterate
);
129 CPPUNIT_TEST(randomTest
);
130 CPPUNIT_TEST(testTableAutoFormats
);
131 CPPUNIT_TEST(testPageDescName
);
132 CPPUNIT_TEST(testFileNameFields
);
133 CPPUNIT_TEST(testDocStat
);
134 CPPUNIT_TEST(testModelToViewHelperPassthrough
);
135 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote
);
136 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode
);
137 CPPUNIT_TEST(testModelToViewHelperExpandFields
);
138 CPPUNIT_TEST(testModelToViewHelperExpandFieldsReplaceMode
);
139 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisible
);
140 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideRedlined
);
141 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote
);
142 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode
);
143 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote
);
144 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode
);
145 CPPUNIT_TEST(testModelToViewHelperHideInvisibleHideRedlined
);
146 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote
);
147 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode
);
148 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote2
);
149 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2
);
150 CPPUNIT_TEST(testSwScanner
);
151 CPPUNIT_TEST(testUserPerceivedCharCount
);
152 CPPUNIT_TEST(testMergePortionsDeleteNotSorted
);
153 CPPUNIT_TEST(testGraphicAnchorDeletion
);
154 CPPUNIT_TEST(testMarkMove
);
155 CPPUNIT_TEST(testFormulas
);
156 CPPUNIT_TEST(testIntrusiveRing
);
157 CPPUNIT_TEST(testClientModify
);
158 CPPUNIT_TEST(testWriterMultiListener
);
159 CPPUNIT_TEST(test64kPageDescs
);
160 CPPUNIT_TEST(testTdf92308
);
161 CPPUNIT_TEST(testTableCellComparison
);
162 CPPUNIT_TEST_SUITE_END();
166 SwDocShellRef m_xDocShRef
;
169 void SwDocTest::testPageDescName()
171 ShellResource aShellResources
;
173 std::vector
<OUString
> aResults
;
175 //These names must be unique for each different combination, otherwise
176 //duplicate page description names may exist, which will causes lookup
177 //by name to be incorrect, and so the corresponding export to .odt
178 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::NORMAL_PAGE
));
179 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::FIRST_PAGE
));
180 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::FOLLOW_PAGE
));
182 std::sort(aResults
.begin(), aResults
.end());
183 aResults
.erase(std::unique(aResults
.begin(), aResults
.end()), aResults
.end());
185 CPPUNIT_ASSERT_EQUAL_MESSAGE("GetPageDescName results must be unique", static_cast<size_t>(3), aResults
.size());
188 //See https://bugs.libreoffice.org/show_bug.cgi?id=32463
189 void SwDocTest::testFileNameFields()
191 //Here's a file name with some chars in it that will be %% encoded, when expanding
192 //SwFileNameFields we want to restore the original readable filename
193 utl::TempFile
aTempFile("demo [name]");
194 aTempFile
.EnableKillingFile();
196 INetURLObject
aTempFileURL(aTempFile
.GetURL());
197 OUString sFileURL
= aTempFileURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
198 SfxMedium
aDstMed(sFileURL
, StreamMode::STD_READWRITE
);
200 std::shared_ptr
<SfxFilter
> pFilter(new SfxFilter(
202 OUString(), SfxFilterFlags::NONE
, SotClipboardFormatId::NONE
, OUString(), OUString(),
203 "TEXT", OUString() ));
204 aDstMed
.SetFilter(pFilter
);
206 m_xDocShRef
->DoSaveAs(aDstMed
);
207 m_xDocShRef
->DoSaveCompleted(&aDstMed
);
209 const INetURLObject
&rUrlObj
= m_xDocShRef
->GetMedium()->GetURLObject();
211 SwFileNameFieldType
aNameField(m_pDoc
);
214 OUString
sResult(aNameField
.Expand(FF_NAME
));
215 OUString
sExpected(rUrlObj
.getName(INetURLObject::LAST_SEGMENT
,
216 true,INetURLObject::DecodeMechanism::WithCharset
));
217 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
221 OUString
sResult(aNameField
.Expand(FF_PATHNAME
));
222 OUString
sExpected(rUrlObj
.GetFull());
223 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
227 OUString
sResult(aNameField
.Expand(FF_PATH
));
228 INetURLObject
aTemp(rUrlObj
);
229 aTemp
.removeSegment();
230 OUString
sExpected(aTemp
.PathToFileName());
231 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
235 OUString
sResult(aNameField
.Expand(FF_NAME_NOEXT
));
236 OUString
sExpected(rUrlObj
.getName(INetURLObject::LAST_SEGMENT
,
237 true,INetURLObject::DecodeMechanism::WithCharset
));
239 sExpected
= sExpected
.copy(0, sExpected
.getLength() - 4);
240 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
243 m_xDocShRef
->DoInitNew();
246 //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
247 //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
249 void SwDocTest::testDocStat()
251 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
253 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
256 OUString
sText("Hello World");
257 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sText
);
259 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should still be non-updated 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
261 SwDocStat aDocStat
= m_pDoc
->getIDocumentStatistics().GetUpdatedDocStat( false, true );
262 sal_uLong nLen
= static_cast<sal_uLong
>(sText
.getLength());
264 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should now have updated count", nLen
, aDocStat
.nChar
);
266 CPPUNIT_ASSERT_EQUAL_MESSAGE("And cache is updated too", nLen
, m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
269 //For UI character counts we should follow UAX#29 and display the user
270 //perceived characters, not the number of codepoints, nor the number of code
271 //units http://unicode.org/reports/tr29/
272 void SwDocTest::testUserPerceivedCharCount()
274 SwBreakIt
*pBreakIter
= SwBreakIt::Get();
276 //Grapheme example, two different unicode code-points perceived by the user as a single
278 const sal_Unicode ALEF_QAMATS
[] = { 0x05D0, 0x05B8 };
279 OUString
sALEF_QAMATS(ALEF_QAMATS
, SAL_N_ELEMENTS(ALEF_QAMATS
));
280 sal_Int32 nGraphemeCount
= pBreakIter
->getGraphemeCount(sALEF_QAMATS
);
281 CPPUNIT_ASSERT_EQUAL_MESSAGE("Grapheme Count should be 1", static_cast<sal_Int32
>(1), nGraphemeCount
);
283 //Surrogate pair example, one single unicode code-point (U+1D11E)
284 //represented as two code units in UTF-16
285 const sal_Unicode GCLEF
[] = { 0xD834, 0xDD1E };
286 OUString
sGCLEF(GCLEF
, SAL_N_ELEMENTS(GCLEF
));
287 sal_Int32 nCount
= pBreakIter
->getGraphemeCount(sGCLEF
);
288 CPPUNIT_ASSERT_EQUAL_MESSAGE("Surrogate Pair should be counted as single character", static_cast<sal_Int32
>(1), nCount
);
291 SwTextNode
* getModelToViewTestDocument(SwDoc
*pDoc
)
293 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
296 SwFormatFootnote aFootnote
;
297 aFootnote
.SetNumStr("foo");
299 pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
300 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "AAAAA BBBBB ");
301 SwTextNode
* pTextNode
= aPaM
.GetNode().GetTextNode();
302 sal_Int32 nPos
= aPaM
.GetPoint()->nContent
.GetIndex();
303 pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
304 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, " CCCCC ");
305 nPos
= aPaM
.GetPoint()->nContent
.GetIndex();
306 pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
307 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, " DDDDD");
308 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>((4*5) + 5 + 2), pTextNode
->GetText().getLength());
310 //set start of selection to first B
311 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 6);
313 //set end of selection to last C
314 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 14);
315 //set character attribute hidden on range
316 SvxCharHiddenItem
aHidden(true, RES_CHRATR_HIDDEN
);
317 pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aHidden
);
320 //turn on red-lining and show changes
321 pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
322 CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
323 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
325 //set start of selection to last A
326 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 4);
328 //set end of selection to second last B
329 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 9);
330 pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
); //redline-aware deletion api
336 SwTextNode
* getModelToViewTestDocument2(SwDoc
*pDoc
)
338 getModelToViewTestDocument(pDoc
);
340 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
343 pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
344 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "AAAAA");
345 IDocumentMarkAccess
* pMarksAccess
= pDoc
->getIDocumentMarkAccess();
346 sw::mark::IFieldmark
*pFieldmark
=
347 pMarksAccess
->makeNoTextFieldBookmark(aPaM
, "test", ODF_FORMDROPDOWN
);
348 CPPUNIT_ASSERT(pFieldmark
);
349 uno::Sequence
< OUString
> vListEntries
{ "BBBBB" };
350 (*pFieldmark
->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY
] <<= vListEntries
;
351 (*pFieldmark
->GetParameters())[ODF_FORMDROPDOWN_RESULT
] <<= sal_Int32(0);
352 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "CCCCC");
353 SwTextNode
* pTextNode
= aPaM
.GetNode().GetTextNode();
354 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(11),
355 pTextNode
->GetText().getLength());
360 void SwDocTest::testModelToViewHelperPassthrough()
362 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
364 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::PassThrough
);
365 OUString sViewText
= aModelToViewHelper
.getViewText();
366 OUString sModelText
= pTextNode
->GetText();
367 CPPUNIT_ASSERT_EQUAL(sModelText
, sViewText
);
370 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote()
372 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
374 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
);
375 OUString sViewText
= aModelToViewHelper
.getViewText();
376 CPPUNIT_ASSERT_EQUAL(
377 OUString("AAAAA BBBBB foo CCCCC foo DDDDD"), sViewText
);
380 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode()
382 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
384 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
385 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
386 OUString sViewText
= aModelToViewHelper
.getViewText();
387 CPPUNIT_ASSERT_EQUAL(
388 OUString("AAAAA BBBBB " + OUStringLiteral1(CHAR_ZWSP
) + " CCCCC " + OUStringLiteral1(CHAR_ZWSP
) + " DDDDD"),
390 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
391 aModelToViewHelper
.getFootnotePositions().size());
392 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(12),
393 aModelToViewHelper
.getFootnotePositions()[0]);
394 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(20),
395 aModelToViewHelper
.getFootnotePositions()[1]);
396 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
397 aModelToViewHelper
.getFieldPositions().size());
400 void SwDocTest::testModelToViewHelperExpandFields()
402 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
404 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
);
405 OUString sViewText
= aModelToViewHelper
.getViewText();
406 CPPUNIT_ASSERT_EQUAL(
407 OUString("AAAAA BBBBB CCCCC DDDDD"), sViewText
);
410 void SwDocTest::testModelToViewHelperExpandFieldsReplaceMode()
412 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
414 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
415 ExpandMode::ExpandFields
| ExpandMode::ReplaceMode
);
416 OUString sViewText
= aModelToViewHelper
.getViewText();
417 CPPUNIT_ASSERT_EQUAL(OUString("AAAAA BBBBB CCCCC DDDDD"),
419 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
420 aModelToViewHelper
.getFootnotePositions().size());
421 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
422 aModelToViewHelper
.getFieldPositions().size());
425 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisible()
427 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
429 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::HideInvisible
);
430 OUString sViewText
= aModelToViewHelper
.getViewText();
431 CPPUNIT_ASSERT_EQUAL(
432 OUString("AAAAA CCCCC " + OUStringLiteral1(CH_TXTATR_BREAKWORD
) + " DDDDD"),
436 void SwDocTest::testModelToViewHelperExpandFieldsHideRedlined()
438 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
440 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::HideDeletions
);
441 OUString sViewText
= aModelToViewHelper
.getViewText();
442 CPPUNIT_ASSERT_EQUAL(
443 OUString("AAAABB " + OUStringLiteral1(CH_TXTATR_BREAKWORD
) + " CCCCC " + OUStringLiteral1(CH_TXTATR_BREAKWORD
) + " DDDDD"),
447 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote()
449 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
451 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::ExpandFootnote
);
452 OUString sViewText
= aModelToViewHelper
.getViewText();
453 CPPUNIT_ASSERT_EQUAL(OUString("AAAAA CCCCC foo DDDDD"), sViewText
);
456 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode()
458 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
460 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
461 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
462 OUString sViewText
= aModelToViewHelper
.getViewText();
463 CPPUNIT_ASSERT_EQUAL(
464 OUString("AAAAA CCCCC " + OUStringLiteral1(CHAR_ZWSP
) + " DDDDD"),
466 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
467 aModelToViewHelper
.getFootnotePositions().size());
468 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(12),
469 aModelToViewHelper
.getFootnotePositions()[0]);
470 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
471 aModelToViewHelper
.getFieldPositions().size());
474 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote()
476 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
478 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
);
479 OUString sViewText
= aModelToViewHelper
.getViewText();
480 CPPUNIT_ASSERT_EQUAL(
481 OUString("AAAABB foo CCCCC foo DDDDD"), sViewText
);
484 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode()
486 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
488 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
489 ExpandMode::ExpandFields
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
490 OUString sViewText
= aModelToViewHelper
.getViewText();
491 CPPUNIT_ASSERT_EQUAL(
492 OUString("AAAABB " + OUStringLiteral1(CHAR_ZWSP
) + " CCCCC " + OUStringLiteral1(CHAR_ZWSP
) + " DDDDD"),
494 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
495 aModelToViewHelper
.getFootnotePositions().size());
496 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(7),
497 aModelToViewHelper
.getFootnotePositions()[0]);
498 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(15),
499 aModelToViewHelper
.getFootnotePositions()[1]);
500 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
501 aModelToViewHelper
.getFieldPositions().size());
504 void SwDocTest::testModelToViewHelperHideInvisibleHideRedlined()
506 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
508 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::HideInvisible
| ExpandMode::HideDeletions
);
509 OUString sViewText
= aModelToViewHelper
.getViewText();
510 OUStringBuffer aBuffer
;
511 aBuffer
.append("AAAACCCCC ");
512 aBuffer
.append(CH_TXTATR_BREAKWORD
);
513 aBuffer
.append(" DDDDD");
514 CPPUNIT_ASSERT_EQUAL(aBuffer
.makeStringAndClear(), sViewText
);
517 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote()
519 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
521 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
);
522 OUString sViewText
= aModelToViewHelper
.getViewText();
523 CPPUNIT_ASSERT_EQUAL(OUString("AAAACCCCC foo DDDDD"), sViewText
);
526 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode()
528 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
530 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
531 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
532 OUString sViewText
= aModelToViewHelper
.getViewText();
533 CPPUNIT_ASSERT_EQUAL(sViewText
,
534 OUString("AAAACCCCC " + OUStringLiteral1(CHAR_ZWSP
) + " DDDDD"));
535 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
536 aModelToViewHelper
.getFootnotePositions().size());
537 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(10),
538 aModelToViewHelper
.getFootnotePositions()[0]);
539 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
540 aModelToViewHelper
.getFieldPositions().size());
543 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote2()
545 SwTextNode
* pTextNode
= getModelToViewTestDocument2(m_pDoc
);
547 ModelToViewHelper
aModelToViewHelper(*pTextNode
, ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
);
548 OUString sViewText
= aModelToViewHelper
.getViewText();
549 CPPUNIT_ASSERT_EQUAL(OUString("AAAAABBBBBCCCCC"), sViewText
);
552 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2()
554 SwTextNode
* pTextNode
= getModelToViewTestDocument2(m_pDoc
);
556 ModelToViewHelper
aModelToViewHelper(*pTextNode
,
557 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
558 OUString sViewText
= aModelToViewHelper
.getViewText();
559 CPPUNIT_ASSERT_EQUAL(
560 OUString("AAAAA" + OUStringLiteral1(CHAR_ZWSP
) + "CCCCC"),
562 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
563 aModelToViewHelper
.getFootnotePositions().size());
564 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
565 aModelToViewHelper
.getFieldPositions().size());
566 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(5),
567 aModelToViewHelper
.getFieldPositions()[0]);
570 void SwDocTest::testSwScanner()
572 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
575 SwTextNode
* pTextNode
= aPaM
.GetNode().GetTextNode();
577 CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTextNode
);
579 //See https://bugs.libreoffice.org/show_bug.cgi?id=40449
580 //See https://bugs.libreoffice.org/show_bug.cgi?id=39365
581 //Use a temporary OUString as the arg, as that's the trouble behind
582 //fdo#40449 and fdo#39365
584 SwScanner
aScanner(*pTextNode
,
586 nullptr, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD
, 0,
587 RTL_CONSTASCII_LENGTH("Hello World"));
589 bool bFirstOk
= aScanner
.NextWord();
590 CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk
);
591 const OUString
&rHello
= aScanner
.GetWord();
592 CPPUNIT_ASSERT_EQUAL(OUString("Hello"), rHello
);
594 bool bSecondOk
= aScanner
.NextWord();
595 CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk
);
596 const OUString
&rWorld
= aScanner
.GetWord();
597 CPPUNIT_ASSERT_EQUAL(OUString("World"), rWorld
);
600 //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
602 const sal_Unicode IDEOGRAPHICFULLSTOP_D
[] = { 0x3002, 'D' };
604 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, OUString(IDEOGRAPHICFULLSTOP_D
,
605 SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D
)));
607 SvxLanguageItem
aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED
, RES_CHRATR_CJK_LANGUAGE
);
608 SvxLanguageItem
aWestLangItem( LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
609 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aCJKLangItem
);
610 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aWestLangItem
);
613 pTextNode
= aPaM
.GetNode().GetTextNode();
614 pTextNode
->CountWords(aDocStat
, 0, SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D
));
616 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nChar
);
617 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nCharExcludingSpaces
);
620 const sal_Unicode test
[] =
622 0x3053, 0x306E, 0x65E5, 0x672C, 0x8A9E, 0x306F, 0x6B63, 0x3057,
623 0x304F, 0x6570, 0x3048, 0x3089, 0x308C, 0x308B, 0x3067, 0x3057,
624 0x3087, 0x3046, 0x304B, 0x3002, 0x0041, 0x006E, 0x0064, 0x0020,
625 0x006C, 0x0065, 0x0074, 0x0027, 0x0073, 0x0020, 0x0074, 0x0068,
626 0x0072, 0x006F, 0x0077, 0x0020, 0x0073, 0x006F, 0x006D, 0x0065,
627 0x0020, 0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068,
628 0x0020, 0x0069, 0x006E, 0x0020, 0x0074, 0x006F, 0x0020, 0x006D,
629 0x0061, 0x006B, 0x0065, 0x0020, 0x0069, 0x0074, 0x0020, 0x0069,
630 0x006E, 0x0074, 0x0065, 0x0072, 0x0065, 0x0073, 0x0074, 0x0069,
631 0x006E, 0x0067, 0x002E, 0x0020, 0x0020, 0x305D, 0x3057, 0x3066,
632 0x3001, 0x307E, 0x305F, 0x65E5, 0x672C, 0x8A9E, 0x3000, 0x3000,
633 0x3067, 0x3082, 0x4ECA, 0x56DE, 0x306F, 0x7A7A, 0x767D, 0x3092,
634 0x3000, 0x3000, 0x5165, 0x308C, 0x307E, 0x3057, 0x305F, 0x3002,
635 0x0020, 0x0020, 0x0053, 0x006F, 0x0020, 0x0068, 0x006F, 0x0077,
636 0x0020, 0x0064, 0x006F, 0x0065, 0x0073, 0x0020, 0x0074, 0x0068,
637 0x0069, 0x0073, 0x0020, 0x0064, 0x006F, 0x003F, 0x0020, 0x0020
639 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
640 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, OUString(test
,
641 SAL_N_ELEMENTS(test
)));
643 SvxLanguageItem
aCJKLangItem( LANGUAGE_JAPANESE
, RES_CHRATR_CJK_LANGUAGE
);
644 SvxLanguageItem
aWestLangItem( LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
645 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aCJKLangItem
);
646 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aWestLangItem
);
649 pTextNode
= aPaM
.GetNode().GetTextNode();
650 pTextNode
->CountWords(aDocStat
, 0, SAL_N_ELEMENTS(test
));
651 CPPUNIT_ASSERT_EQUAL_MESSAGE("words", static_cast<sal_uLong
>(58), aDocStat
.nWord
);
652 CPPUNIT_ASSERT_EQUAL_MESSAGE("Asian characters and Korean syllables", static_cast<sal_uLong
>(43), aDocStat
.nAsianWord
);
653 CPPUNIT_ASSERT_EQUAL_MESSAGE("non-whitespace chars", static_cast<sal_uLong
>(105), aDocStat
.nCharExcludingSpaces
);
654 CPPUNIT_ASSERT_EQUAL_MESSAGE("characters", static_cast<sal_uLong
>(128), aDocStat
.nChar
);
657 //See https://bz.apache.org/ooo/show_bug.cgi?id=89042
658 //See https://bugs.libreoffice.org/show_bug.cgi?id=53399
662 const sal_Unicode aShouldBeThree
[] = {
663 0x0053, 0x0068, 0x006F, 0x0075, 0x006C, 0x0064, 0x0020,
664 0x2018, 0x0062, 0x0065, 0x0020, 0x0074, 0x0068, 0x0072,
665 0x0065, 0x0065, 0x2019
668 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
669 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, OUString(aShouldBeThree
, SAL_N_ELEMENTS(aShouldBeThree
)));
670 pTextNode
= aPaM
.GetNode().GetTextNode();
671 pTextNode
->CountWords(aDocStat
, 0, SAL_N_ELEMENTS(aShouldBeThree
));
672 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(3), aDocStat
.nWord
);
674 const sal_Unicode aShouldBeFive
[] = {
676 0x0046, 0x0072, 0x0065, 0x006E, 0x0063, 0x0068, 0x0020,
678 0x00AB, 0x00A0, 0x0073, 0x0061, 0x0076, 0x006F, 0x0069,
680 0x0072, 0x202f, 0x0063, 0x0061, 0x006C, 0x0063, 0x0075,
682 0x006C, 0x0065, 0x0072, 0x3000, 0x00BB
685 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
686 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, OUString(aShouldBeFive
, SAL_N_ELEMENTS(aShouldBeFive
)));
687 pTextNode
= aPaM
.GetNode().GetTextNode();
689 pTextNode
->CountWords(aDocStat
, 0, SAL_N_ELEMENTS(aShouldBeFive
));
690 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(5), aDocStat
.nWord
);
693 //See https://bugs.libreoffice.org/show_bug.cgi?id=49629
697 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
698 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Apple");
699 pTextNode
= aPaM
.GetNode().GetTextNode();
700 sal_Int32 nPos
= aPaM
.GetPoint()->nContent
.GetIndex();
701 SwFormatFootnote aFootnote
;
702 aFootnote
.SetNumStr("banana");
703 SwTextAttr
* pTA
= pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
705 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(6), pTextNode
->Len()); //Apple + 0x02
706 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
707 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
708 CPPUNIT_ASSERT_EQUAL_MESSAGE("footnote should be expanded", static_cast<sal_uLong
>(11), aDocStat
.nChar
);
710 const sal_Int32 nNextPos
= aPaM
.GetPoint()->nContent
.GetIndex();
711 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(nPos
+1), nNextPos
);
712 SwFormatRefMark
aRef("refmark");
713 pTA
= pTextNode
->InsertItem(aRef
, nNextPos
, nNextPos
);
717 pTextNode
->SetWordCountDirty(true);
718 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
719 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
720 CPPUNIT_ASSERT_EQUAL_MESSAGE("refmark anchor should not be counted", static_cast<sal_uLong
>(11), aDocStat
.nChar
);
722 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
723 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Apple");
725 DateTime
aDate(DateTime::SYSTEM
);
726 SwPostItField
aPostIt(
727 static_cast<SwPostItFieldType
*>(m_pDoc
->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit
)), "An Author",
728 "Some Text", "Initials", "Name", aDate
);
729 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, SwFormatField(aPostIt
));
731 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Apple");
732 pTextNode
= aPaM
.GetNode().GetTextNode();
734 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
735 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
736 CPPUNIT_ASSERT_EQUAL_MESSAGE("postit anchor should effectively not exist", static_cast<sal_uLong
>(10), aDocStat
.nChar
);
737 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(11), pTextNode
->Len());
742 //See https://bugs.libreoffice.org/show_bug.cgi?id=46757
746 const char aString
[] = "Lorem ipsum";
747 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
748 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, aString
);
749 pTextNode
= aPaM
.GetNode().GetTextNode();
750 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
751 CPPUNIT_ASSERT_EQUAL(aDocStat
.nWord
, static_cast<sal_uLong
>(2));
753 //turn on red-lining and show changes
754 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
755 CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
756 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
758 //delete everything except the first word
759 aPaM
.SetMark(); //set start of selection to current pos
760 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 5); //set end of selection to fifth char of current node
761 m_pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
); //redline-aware deletion api
762 //"real underlying text should be the same"
763 CPPUNIT_ASSERT_EQUAL(pTextNode
->GetText(), OUString(aString
));
766 pTextNode
->SetWordCountDirty(true);
767 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len()); //but word-counting the text should only count the non-deleted text
768 CPPUNIT_ASSERT_EQUAL(aDocStat
.nWord
, static_cast<sal_uLong
>(1));
770 pTextNode
->SetWordCountDirty(true);
772 //keep red-lining on but hide changes
773 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
);
774 CPPUNIT_ASSERT_MESSAGE("redlining should be still on", m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
775 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible", !IDocumentRedlineAccess::IsShowChanges(m_pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
778 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len()); //but word-counting the text should only count the non-deleted text
779 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
781 OUString sLorem
= pTextNode
->GetText();
782 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), sLorem
);
784 const SwRedlineTable
& rTable
= m_pDoc
->getIDocumentRedlineAccess().GetRedlineTable();
786 SwNodes
& rNds
= m_pDoc
->GetNodes();
787 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(1), rTable
.size());
789 SwNodeIndex
* pNodeIdx
= rTable
[0]->GetContentIdx();
790 CPPUNIT_ASSERT(pNodeIdx
);
792 pTextNode
= rNds
[ pNodeIdx
->GetIndex() + 1 ]->GetTextNode(); //first deleted txtnode
793 CPPUNIT_ASSERT(pTextNode
);
795 OUString sIpsum
= pTextNode
->GetText();
796 CPPUNIT_ASSERT_EQUAL(OUString(" ipsum"), sIpsum
);
799 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len()); //word-counting the text should only count the non-deleted text, and this whole chunk should be ignored
800 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(0), aDocStat
.nWord
);
801 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(0), aDocStat
.nChar
);
803 // https://bugs.libreoffice.org/show_bug.cgi?id=68347 we do want to count
804 // redline *added* text though
805 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
807 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), 0);
808 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "redline-new-text ");
810 pTextNode
= aPaM
.GetNode().GetTextNode();
811 pTextNode
->SetWordCountDirty(true);
812 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
813 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nWord
);
814 //redline-new-text Lorem ipsum
815 //+++++++++++++++++ ------
816 //select start of original text and part of deleted text
818 pTextNode
->CountWords(aDocStat
, 17, 25);
819 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(5), aDocStat
.nChar
);
822 //See https://bugs.libreoffice.org/show_bug.cgi?id=38983
826 OUString
sTemplate("ThisXis a test.");
828 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
829 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', ' '));
830 pTextNode
= aPaM
.GetNode().GetTextNode();
831 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
832 CPPUNIT_ASSERT(aDocStat
.nWord
== 4 &&
833 aDocStat
.nCharExcludingSpaces
== 12 &&
834 aDocStat
.nChar
== 15);
837 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
838 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", " = "));
839 pTextNode
= aPaM
.GetNode().GetTextNode();
840 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
841 CPPUNIT_ASSERT(aDocStat
.nWord
== 5 &&
842 aDocStat
.nCharExcludingSpaces
== 13 &&
843 aDocStat
.nChar
== 17);
846 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
847 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", " _ "));
848 pTextNode
= aPaM
.GetNode().GetTextNode();
849 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
850 CPPUNIT_ASSERT(aDocStat
.nWord
== 5 &&
851 aDocStat
.nCharExcludingSpaces
== 13 &&
852 aDocStat
.nChar
== 17);
855 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
856 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", " -- "));
857 pTextNode
= aPaM
.GetNode().GetTextNode();
858 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
859 CPPUNIT_ASSERT(aDocStat
.nWord
== 5 &&
860 aDocStat
.nCharExcludingSpaces
== 14 &&
861 aDocStat
.nChar
== 18);
864 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
865 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', '_'));
866 pTextNode
= aPaM
.GetNode().GetTextNode();
867 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
868 CPPUNIT_ASSERT(aDocStat
.nWord
== 3 &&
869 aDocStat
.nCharExcludingSpaces
== 13 &&
870 aDocStat
.nChar
== 15);
873 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
874 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', '-'));
875 pTextNode
= aPaM
.GetNode().GetTextNode();
876 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
877 CPPUNIT_ASSERT(aDocStat
.nWord
== 3 &&
878 aDocStat
.nCharExcludingSpaces
== 13 &&
879 aDocStat
.nChar
== 15);
882 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
883 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2012));
884 pTextNode
= aPaM
.GetNode().GetTextNode();
885 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
886 CPPUNIT_ASSERT(aDocStat
.nWord
== 3 &&
887 aDocStat
.nCharExcludingSpaces
== 13 &&
888 aDocStat
.nChar
== 15);
891 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
892 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2015));
893 pTextNode
= aPaM
.GetNode().GetTextNode();
894 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
895 CPPUNIT_ASSERT(aDocStat
.nWord
== 3 &&
896 aDocStat
.nCharExcludingSpaces
== 13 &&
897 aDocStat
.nChar
== 15);
900 //But default configuration should, msword-alike treat emdash
901 //and endash as word separators for word-counting
902 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
903 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2013));
904 pTextNode
= aPaM
.GetNode().GetTextNode();
905 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
906 CPPUNIT_ASSERT(aDocStat
.nWord
== 4 &&
907 aDocStat
.nCharExcludingSpaces
== 13 &&
908 aDocStat
.nChar
== 15);
911 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
912 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2014));
913 pTextNode
= aPaM
.GetNode().GetTextNode();
914 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
915 CPPUNIT_ASSERT(aDocStat
.nWord
== 4 &&
916 aDocStat
.nCharExcludingSpaces
== 13 &&
917 aDocStat
.nChar
== 15);
920 const sal_Unicode aChunk
[] = {' ', 0x2013, ' '};
921 OUString
sChunk(aChunk
, SAL_N_ELEMENTS(aChunk
));
922 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
923 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", sChunk
));
924 pTextNode
= aPaM
.GetNode().GetTextNode();
925 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
926 CPPUNIT_ASSERT(aDocStat
.nWord
== 4 &&
927 aDocStat
.nCharExcludingSpaces
== 13 &&
928 aDocStat
.nChar
== 17);
933 void SwDocTest::testMergePortionsDeleteNotSorted()
935 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
937 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, " AABBCC");
939 SwCharFormat
*const pCharFormat(m_pDoc
->MakeCharFormat("foo", nullptr));
940 SwFormatCharFormat
const charFormat(pCharFormat
);
942 SwFormatINetFormat
const inetFormat("http://example.com", "");
944 IDocumentContentOperations
& rIDCO(m_pDoc
->getIDocumentContentOperations());
946 aPaM
.GetPoint()->nContent
= 2;
947 aPaM
.GetMark()->nContent
= 4;
948 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
949 aPaM
.GetPoint()->nContent
= 2;
950 aPaM
.GetMark()->nContent
= 5;
951 rIDCO
.InsertPoolItem(aPaM
, inetFormat
);
952 aPaM
.GetPoint()->nContent
= 6;
953 aPaM
.GetMark()->nContent
= 8;
954 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
955 aPaM
.GetPoint()->nContent
= 4;
956 aPaM
.GetMark()->nContent
= 6;
957 // this triggered an STL assert in SwpHints::MergePortions()
958 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
961 //See https://bugs.libreoffice.org/show_bug.cgi?id=40599
962 void SwDocTest::testGraphicAnchorDeletion()
964 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
966 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
969 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Paragraph 1");
970 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
972 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "graphic anchor>><<graphic anchor");
973 SwNodeIndex nPara2
= aPaM
.GetPoint()->nNode
;
974 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
976 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Paragraph 3");
978 aPaM
.GetPoint()->nNode
= nPara2
;
979 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), RTL_CONSTASCII_LENGTH("graphic anchor>>"));
981 //Insert a graphic at X of >>X<< in paragraph 2
982 SfxItemSet
aFlySet(m_pDoc
->GetAttrPool(), svl::Items
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1>{});
983 SwFormatAnchor
aAnchor(RndStdIds::FLY_AS_CHAR
);
984 aAnchor
.SetAnchor(aPaM
.GetPoint());
985 aFlySet
.Put(aAnchor
);
986 SwFlyFrameFormat
*pFrame
= m_pDoc
->getIDocumentContentOperations().InsertGraphic(aPaM
, OUString(), OUString(), nullptr, &aFlySet
, nullptr, nullptr);
987 CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame
!= nullptr);
989 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 1 graphic", static_cast<size_t>(1), m_pDoc
->GetFlyCount(FLYCNTTYPE_GRF
));
992 aPaM
.GetPoint()->nNode
= nPara2
;
993 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(),
994 RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
996 aPaM
.GetPoint()->nNode
= nPara2
;
997 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetContentNode(), RTL_CONSTASCII_LENGTH("graphic anchor>"));
998 m_pDoc
->getIDocumentContentOperations().DeleteRange(aPaM
);
1000 #ifdef DEBUG_AS_HTML
1002 SvFileStream
aPasteDebug(OUString("cppunitDEBUG.html"), StreamMode::WRITE
|StreamMode::TRUNC
);
1004 GetHTMLWriter( String(), String(), xWrt
);
1005 SwWriter
aDbgWrt( aPasteDebug
, *m_pDoc
);
1006 aDbgWrt
.Write( xWrt
);
1010 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 0 graphics", static_cast<size_t>(0), m_pDoc
->GetFlyCount(FLYCNTTYPE_GRF
));
1012 //Now, if instead we swap RndStdIds::FLY_AS_CHAR (inline graphic) to RndStdIds::FLY_AT_CHAR (anchored to character)
1013 //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
1014 //range to which its anchored, which is annoying.
1018 getRand(int modulus
)
1022 return comphelper::rng::uniform_int_distribution(0, modulus
-1);
1028 OUString
aText("AAAAA BBBB CCC DD E \n");
1029 int s
= getRand(aText
.getLength());
1030 int j
= getRand(aText
.getLength() - s
);
1031 OUString
aRet(aText
.copy(s
, j
));
1034 // fprintf (stderr, "rand string '%s'\n", OUStringToOString(aRet, RTL_TEXTENCODING_UTF8).getStr());
1039 getRandomPosition(SwDoc
*pDoc
, int /* nOffset */)
1041 const SwPosition
aPos(pDoc
->GetNodes().GetEndOfContent());
1042 size_t nNodes
= aPos
.nNode
.GetNode().GetIndex() - aPos
.nNode
.GetNode().StartOfSectionIndex();
1043 size_t n
= comphelper::rng::uniform_size_distribution(0, nNodes
);
1045 for (sal_uLong i
= 0; i
< n
; ++i
)
1047 pam
.Move(fnMoveBackward
, GoInNode
);
1049 return *pam
.GetPoint();
1052 void SwDocTest::randomTest()
1054 CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1055 RedlineFlags modes
[] = {
1057 RedlineFlags::ShowMask
,
1059 RedlineFlags::On
| RedlineFlags::ShowMask
,
1060 RedlineFlags::On
| RedlineFlags::Ignore
,
1061 RedlineFlags::On
| RedlineFlags::Ignore
| RedlineFlags::ShowMask
,
1062 RedlineFlags::On
| RedlineFlags::ShowInsert
,
1063 RedlineFlags::On
| RedlineFlags::ShowDelete
1065 static const char *authors
[] = {
1066 "Jim", "Bob", "JimBobina", "Helga", "Gertrude", "Spagna", "Hurtleweed"
1069 for( size_t rlm
= 0; rlm
< SAL_N_ELEMENTS(modes
); rlm
++ )
1074 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(modes
[rlm
]);
1075 SW_MOD()->SetRedlineAuthor(OUString::createFromAscii(authors
[0]));
1077 for( int i
= 0; i
< 2000; i
++ )
1079 SwCursor
aCrs(getRandomPosition(m_pDoc
, i
/20), nullptr);
1082 switch (getRand (i
< 50 ? 3 : 6)) {
1085 if (!m_pDoc
->getIDocumentContentOperations().InsertString(aCrs
, getRandString())) {
1086 // fprintf (stderr, "failed to insert string !\n");
1092 case 2: { // switch author
1093 int a
= getRand(SAL_N_ELEMENTS(authors
));
1094 SW_MOD()->SetRedlineAuthor(OUString::createFromAscii(authors
[a
]));
1098 // movement / deletion ops later
1100 switch (getRand(6)) {
1102 m_pDoc
->getIDocumentContentOperations().DelFullPara(aCrs
);
1105 m_pDoc
->getIDocumentContentOperations().DeleteRange(aCrs
);
1108 m_pDoc
->getIDocumentContentOperations().DeleteAndJoin(aCrs
, !!getRand(1));
1112 m_pDoc
->getIDocumentContentOperations().Overwrite(aCrs
, getRandString());
1116 case 4: { // movement
1117 SwMoveFlags nFlags
=
1118 getRand(1) // FIXME: puterb this more ?
1119 ? SwMoveFlags::DEFAULT
1120 : SwMoveFlags::ALLFLYS
|
1121 SwMoveFlags::CREATEUNDOOBJ
|
1122 SwMoveFlags::REDLINES
|
1123 SwMoveFlags::NO_DELFRMS
;
1124 SwPosition
aTo(getRandomPosition(m_pDoc
, i
/10));
1125 m_pDoc
->getIDocumentContentOperations().MoveRange(aCrs
, aTo
, nFlags
);
1138 // Debug / verify the produced document has real content
1140 OStringBuffer
aBuffer("nodes-");
1141 aBuffer
.append(sal_Int32(rlm
));
1142 aBuffer
.append(".xml");
1144 xmlTextWriterPtr writer
;
1145 writer
= xmlNewTextWriterFilename( aBuffer
.makeStringAndClear().getStr(), 0 );
1146 xmlTextWriterStartDocument( writer
, NULL
, NULL
, NULL
);
1147 m_pDoc
->dumpAsXml(writer
);
1148 xmlTextWriterEndDocument( writer
);
1149 xmlFreeTextWriter( writer
);
1154 void SwDocTest::testTableAutoFormats()
1156 SwGlobals::ensure();
1158 //create new AutoFormatTable
1159 SwTableAutoFormatTable aTableAFT
;
1161 //check the style size - default is expected
1162 CPPUNIT_ASSERT_EQUAL( size_t(1), aTableAFT
.size() );
1165 SwTableAutoFormat
aTableAF( "TestItemStyle" );
1167 //create new AutoFormat
1168 SwBoxAutoFormat aBoxAF
;
1171 SvxFontItem
aFont( RES_CHRATR_FONT
);
1172 aFont
.SetFamily( FontFamily::FAMILY_DECORATIVE
);
1173 aFont
.SetPitch( FontPitch::PITCH_VARIABLE
);
1174 aFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1175 aBoxAF
.SetFont( aFont
);
1177 SvxFontHeightItem
aHeight( 280, 120, RES_CHRATR_FONTSIZE
);
1178 aBoxAF
.SetHeight( aHeight
);
1180 SvxWeightItem
aWeight( FontWeight::WEIGHT_BOLD
, RES_CHRATR_WEIGHT
);
1181 aBoxAF
.SetWeight( aWeight
);
1183 SvxPostureItem
aPosture( FontItalic::ITALIC_NORMAL
, RES_CHRATR_POSTURE
);
1184 aBoxAF
.SetPosture( aPosture
);
1186 SvxFontItem
aCJKFont( RES_CHRATR_FONT
);
1187 aCJKFont
.SetFamily( FontFamily::FAMILY_MODERN
);
1188 aCJKFont
.SetPitch( FontPitch::PITCH_FIXED
);
1189 aCJKFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1190 aBoxAF
.SetCJKFont( aCJKFont
);
1192 SvxFontHeightItem
aCJKHeight( 230, 110, RES_CHRATR_FONTSIZE
);
1193 aBoxAF
.SetCJKHeight( aCJKHeight
);
1195 SvxWeightItem
aCJKWeight( FontWeight::WEIGHT_SEMIBOLD
, RES_CHRATR_WEIGHT
);
1196 aBoxAF
.SetCJKWeight( aCJKWeight
);
1198 SvxPostureItem
aCJKPosture( FontItalic::ITALIC_OBLIQUE
, RES_CHRATR_POSTURE
);
1199 aBoxAF
.SetCJKPosture( aCJKPosture
);
1201 SvxFontItem
aCTLFont( RES_CHRATR_FONT
);
1202 aCTLFont
.SetFamily( FontFamily::FAMILY_ROMAN
);
1203 aCTLFont
.SetPitch( FontPitch::PITCH_FIXED
);
1204 aCTLFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1205 aBoxAF
.SetCTLFont( aCTLFont
);
1207 SvxFontHeightItem
aCTLHeight( 215, 105, RES_CHRATR_FONTSIZE
);
1208 aBoxAF
.SetCTLHeight( aCTLHeight
);
1210 SvxWeightItem
aCTLWeight( FontWeight::WEIGHT_ULTRABOLD
, RES_CHRATR_WEIGHT
);
1211 aBoxAF
.SetCTLWeight( aCTLWeight
);
1213 SvxPostureItem
aCTLPosture( FontItalic::ITALIC_OBLIQUE
, RES_CHRATR_POSTURE
);
1214 aBoxAF
.SetCTLPosture( aCTLPosture
);
1216 SvxUnderlineItem
aUnderline( FontLineStyle::LINESTYLE_DOTTED
, RES_CHRATR_UNDERLINE
);
1217 aBoxAF
.SetUnderline( aUnderline
);
1219 SvxOverlineItem
aOverline( FontLineStyle::LINESTYLE_DASH
, RES_CHRATR_OVERLINE
);
1220 aBoxAF
.SetOverline( aOverline
);
1222 SvxCrossedOutItem
aCrossedOut( FontStrikeout::STRIKEOUT_BOLD
, RES_CHRATR_CROSSEDOUT
);
1223 aBoxAF
.SetCrossedOut( aCrossedOut
);
1225 SvxContourItem
aContour( true, RES_CHRATR_CONTOUR
);
1226 aBoxAF
.SetContour( aContour
);
1228 SvxShadowedItem
aShadowed( false, RES_CHRATR_SHADOWED
);
1229 aBoxAF
.SetShadowed( aShadowed
);
1231 SvxColorItem
aColor( Color(0xFF23FF), RES_CHRATR_COLOR
);
1232 aBoxAF
.SetColor( aColor
);
1234 SvxAdjustItem
aAdjust( SvxAdjust::Center
, RES_PARATR_ADJUST
);
1235 aBoxAF
.SetAdjust( aAdjust
);
1236 //SetTextOrientation
1237 SvxFrameDirectionItem
aTOrientation( SvxFrameDirection::Vertical_RL_TB
, RES_FRAMEDIR
);
1238 aBoxAF
.SetTextOrientation( aTOrientation
);
1239 //SetVerticalAlignment
1240 SwFormatVertOrient
aVAlignment( 3, css::text::VertOrientation::CENTER
, css::text::RelOrientation::PAGE_LEFT
);
1241 aBoxAF
.SetVerticalAlignment( aVAlignment
);
1243 SvxBoxItem
aBox( RES_BOX
);
1244 aBox
.SetAllDistances( 5 );
1245 aBoxAF
.SetBox( aBox
);
1247 SvxBrushItem
aBackground( Color(0xFF11FF), RES_BACKGROUND
);
1248 aBoxAF
.SetBackground( aBackground
);
1250 aBoxAF
.m_aTLBR
.ScaleMetrics( 11,12 );
1251 SvxLineItem aTLBRLine
= aBoxAF
.m_aTLBR
;
1253 aBoxAF
.m_aBLTR
.ScaleMetrics( 13,14 );
1254 SvxLineItem aBLTRLine
= aBoxAF
.m_aBLTR
;
1256 SvxHorJustifyItem
aHJustify( SvxCellHorJustify::Center
, 0 );
1257 aBoxAF
.m_aHorJustify
= aHJustify
;
1259 SvxVerJustifyItem
aVJustify( SvxCellVerJustify::Center
, 0 );
1260 aBoxAF
.m_aVerJustify
= aVJustify
;
1262 aBoxAF
.m_aStacked
.SetValue( true );
1263 SfxBoolItem aStacked
= aBoxAF
.m_aStacked
;
1265 aBoxAF
.m_aMargin
.SetLeftMargin( sal_Int16(4) );
1266 aBoxAF
.m_aMargin
.SetRightMargin( sal_Int16(3) );
1267 aBoxAF
.m_aMargin
.SetTopMargin( sal_Int16(2) );
1268 aBoxAF
.m_aMargin
.SetBottomMargin( sal_Int16(3) );
1269 SvxMarginItem aMargin
= aBoxAF
.m_aMargin
;
1271 aBoxAF
.m_aLinebreak
.SetValue( true );
1272 SfxBoolItem aLBreak
= aBoxAF
.m_aLinebreak
;
1273 //Set m_aRotateAngle
1274 aBoxAF
.m_aRotateAngle
.SetValue( sal_Int32(5) );
1275 SfxInt32Item aRAngle
= aBoxAF
.m_aRotateAngle
;
1277 aBoxAF
.m_aRotateMode
.SetValue( SVX_ROTATE_MODE_CENTER
);
1278 //Set m_sNumFormatString
1279 OUString aNFString
= "UnitTestFormat";
1280 aBoxAF
.m_sNumFormatString
= aNFString
;
1281 //Set m_eSysLanguage
1282 LanguageType
aSLang( LANGUAGE_ENGLISH_INDIA
);
1283 aBoxAF
.m_eSysLanguage
= aSLang
;
1284 //Set m_eNumFormatLanguage
1285 LanguageType
aNFLang( LANGUAGE_GERMAN
);
1286 aBoxAF
.m_eNumFormatLanguage
= aNFLang
;
1288 SvxFormatBreakItem
aBreak( SvxBreak::PageBefore
, 0 );
1289 aTableAF
.m_aBreak
= aBreak
;
1290 //Set m_aKeepWithNextPara
1291 SvxFormatKeepItem
aKWNPara( true, 0 );
1292 aTableAF
.m_aKeepWithNextPara
= aKWNPara
;
1294 SwFormatPageDesc aPDesc
;
1295 uno::Any
aPDAny( sal_uInt16(3) );
1296 aPDesc
.PutValue( aPDAny
, 0 );
1297 aTableAF
.m_aPageDesc
= aPDesc
;
1298 //Set m_aRepeatHeading
1299 sal_uInt16 aRHeading
= 3;
1300 aTableAF
.m_aRepeatHeading
= aRHeading
;
1301 //Set m_bLayoutSplit
1302 bool aLSplit
= false;
1303 aTableAF
.m_bLayoutSplit
= aLSplit
;
1305 bool aRSplit
= false;
1306 aTableAF
.m_bRowSplit
= aRSplit
;
1307 //Set m_bCollapsingBorders
1308 bool aCBorders
= false;
1309 aTableAF
.m_bCollapsingBorders
= aCBorders
;
1311 SvxShadowItem
aShadow( 0, nullptr, 103, SvxShadowLocation::BottomLeft
);
1312 aTableAF
.m_aShadow
= aShadow
;
1314 bool aIFont
= false;
1315 aTableAF
.bInclFont
= aIFont
;
1317 bool aIJustify
= false;
1318 aTableAF
.bInclJustify
= aIJustify
;
1320 bool aIFrame
= false;
1321 aTableAF
.bInclFrame
= aIFrame
;
1322 //Set bInclBackground
1323 bool aIBackground
= false;
1324 aTableAF
.bInclBackground
= aIBackground
;
1325 //Set bInclValueFormat
1326 bool aIVFormat
= false;
1327 aTableAF
.bInclValueFormat
= aIVFormat
;
1329 //set the box format to AutoFormat
1330 aTableAF
.SetBoxFormat( aBoxAF
, sal_uInt8(0) );
1331 //add AutoFormat to AutoFormatTable
1332 aTableAFT
.AddAutoFormat( aTableAF
);
1334 //check the style size
1335 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT
.size() );
1337 //save the bInclFontstyles
1340 //check the style size after save
1341 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT
.size() );
1343 //create new AutoFormatTable
1344 SwTableAutoFormatTable aLoadTAFT
;
1346 //check the style size
1347 CPPUNIT_ASSERT_EQUAL( size_t(1), aLoadTAFT
.size() );
1349 //load the saved styles
1352 //check the style size after load
1353 CPPUNIT_ASSERT_EQUAL( size_t(2), aLoadTAFT
.size() );
1356 SwTableAutoFormat
* pLoadAF
= aLoadTAFT
.FindAutoFormat( "TestItemStyle" );
1357 CPPUNIT_ASSERT( pLoadAF
);
1359 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetFont() == aFont
) );
1361 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetHeight() == aHeight
) );
1363 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetWeight() == aWeight
) );
1365 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetPosture() == aPosture
) );
1367 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKFont() == aCJKFont
) );
1369 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKHeight() == aCJKHeight
) );
1371 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKWeight() == aCJKWeight
) );
1373 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKPosture() == aCJKPosture
) );
1375 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLFont() == aCTLFont
) );
1377 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLHeight() == aCTLHeight
) );
1379 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLWeight() == aCTLWeight
) );
1381 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLPosture() == aCTLPosture
) );
1383 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetUnderline() == aUnderline
) );
1385 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetOverline() == aOverline
) );
1387 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCrossedOut() == aCrossedOut
) );
1389 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetContour() == aContour
) );
1391 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetShadowed() == aShadowed
) );
1393 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetColor() == aColor
) );
1395 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetAdjust() == aAdjust
) );
1396 //GetTextOrientation
1397 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetTextOrientation() == aTOrientation
) );
1398 //GetVerticalAlignment
1399 CPPUNIT_ASSERT (bool( pLoadAF
->GetBoxFormat(0).GetVerticalAlignment() == aVAlignment
) );
1401 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetBox() == aBox
) );
1403 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetBackground() == aBackground
) );
1405 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aTLBR
== aTLBRLine
) );
1407 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aBLTR
== aBLTRLine
) );
1409 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aHorJustify
== aHJustify
) );
1411 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aVerJustify
== aVJustify
) );
1413 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aStacked
== aStacked
) );
1415 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aMargin
== aMargin
) );
1417 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aLinebreak
== aLBreak
) );
1418 //Get m_aRotateAngle
1419 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aRotateAngle
== aRAngle
) );
1420 #if !((defined(__clang__) && __clang_major__ == 4 && __clang_minor__ == 0) \
1421 || (defined __APPLE__ && defined __clang__ \
1422 && defined __apple_build_version__ \
1423 && __apple_build_version__ >= 9000000 \
1424 && __apple_build_version__ <= 9000099))
1425 // Temporary fix for mysterious problem with Clang in F26 and Xcode 9
1427 SvxRotateModeItem aRMode
= aBoxAF
.m_aRotateMode
;
1428 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_aRotateMode
== aRMode
) );
1430 //Get m_sNumFormatString
1431 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_sNumFormatString
== aNFString
) );
1432 //Get m_eSysLanguage
1433 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_eSysLanguage
== aSLang
) );
1434 //Get m_eNumFormatLanguage
1435 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).m_eNumFormatLanguage
== aNFLang
) );
1437 CPPUNIT_ASSERT( bool( pLoadAF
->m_aBreak
== aBreak
) );
1438 //Get m_aKeepWithNextPara
1439 CPPUNIT_ASSERT( bool( pLoadAF
->m_aKeepWithNextPara
== aKWNPara
) );
1441 CPPUNIT_ASSERT( bool( pLoadAF
->m_aPageDesc
== aPDesc
) );
1442 //Get m_aRepeatHeading
1443 CPPUNIT_ASSERT( bool( pLoadAF
->m_aRepeatHeading
== aRHeading
) );
1444 //Get m_bLayoutSplit
1445 CPPUNIT_ASSERT( bool( pLoadAF
->m_bLayoutSplit
== aLSplit
) );
1447 CPPUNIT_ASSERT( bool( pLoadAF
->m_bRowSplit
== aRSplit
) );
1448 //Get m_bCollapsingBorders
1449 CPPUNIT_ASSERT( bool( pLoadAF
->m_bCollapsingBorders
== aCBorders
) );
1451 CPPUNIT_ASSERT( bool( pLoadAF
->m_aShadow
== aShadow
) );
1453 CPPUNIT_ASSERT( bool( pLoadAF
->bInclFont
== aIFont
) );
1455 CPPUNIT_ASSERT( bool( pLoadAF
->bInclJustify
== aIJustify
) );
1457 CPPUNIT_ASSERT( bool( pLoadAF
->bInclFrame
== aIFrame
) );
1458 //Get bInclBackground
1459 CPPUNIT_ASSERT( bool( pLoadAF
->bInclBackground
== aIBackground
) );
1460 //Get bInclValueFormat
1461 CPPUNIT_ASSERT( bool( pLoadAF
->bInclValueFormat
== aIVFormat
) );
1465 translitTest(SwDoc
& rDoc
, const SwPaM
& rPaM
, TransliterationFlags
const nType
)
1467 utl::TransliterationWrapper
aTrans(
1468 ::comphelper::getProcessComponentContext(), nType
);
1469 rDoc
.getIDocumentContentOperations().TransliterateText(rPaM
, aTrans
);
1470 return rPaM
.GetText();
1473 void SwDocTest::testTransliterate()
1475 // just some simple test to see if it's totally broken
1476 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1478 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "foobar");
1480 aPaM
.GetPoint()->nContent
= 0;
1481 CPPUNIT_ASSERT_EQUAL(OUString("foobar"), aPaM
.GetText());
1483 CPPUNIT_ASSERT_EQUAL(OUString("FOOBAR"),
1484 translitTest(*m_pDoc
, aPaM
,
1485 TransliterationFlags::LOWERCASE_UPPERCASE
));
1486 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1487 translitTest(*m_pDoc
, aPaM
,
1488 TransliterationFlags::TITLE_CASE
));
1489 CPPUNIT_ASSERT_EQUAL(OUString("fOOBAR"),
1490 translitTest(*m_pDoc
, aPaM
,
1491 TransliterationFlags::TOGGLE_CASE
));
1492 CPPUNIT_ASSERT_EQUAL(OUString("foobar"),
1493 translitTest(*m_pDoc
, aPaM
,
1494 TransliterationFlags::UPPERCASE_LOWERCASE
));
1495 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1496 translitTest(*m_pDoc
, aPaM
,
1497 TransliterationFlags::SENTENCE_CASE
));
1498 CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1499 translitTest(*m_pDoc
, aPaM
,
1500 TransliterationFlags::HIRAGANA_KATAKANA
));
1502 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1503 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "one (two) three");
1504 CPPUNIT_ASSERT_EQUAL(OUString("One (Two) Three"),
1505 translitTest(*m_pDoc
, aPaM
,
1506 TransliterationFlags::TITLE_CASE
));
1511 class SwTableFormulaTest
: public SwTableFormula
1513 SwTableNode
*m_pNode
;
1515 SwTableFormulaTest(const OUString
&rStr
, SwTableNode
*pNode
)
1516 : SwTableFormula(rStr
)
1519 m_eNmType
= INTRNL_NAME
;
1521 virtual const SwNode
* GetNodeOfFormula() const override
1528 //tdf#66353 Expression is faulty
1529 void SwDocTest::testFormulas()
1531 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1532 SwPosition
aPos(aIdx
);
1534 const SwTable
*pTable
= m_pDoc
->InsertTable(
1535 SwInsertTableOptions(SwInsertTableFlags::HeadlineNoBorder
, 0), aPos
, 1, 3, 0);
1536 SwTableNode
* pTableNode
= pTable
->GetTableNode();
1537 SwTableFormulaTest
aFormula("<\x12-1,0>+<Table1.A1>", pTableNode
);
1539 aFormula
.PtrToBoxNm(pTable
);
1541 CPPUNIT_ASSERT_EQUAL(OUString("<?>+<Table1.?>"), aFormula
.GetFormula());
1543 // tdf#61228: Evaluating non-defined function should return an error
1544 SwCalc
aCalc(*m_pDoc
);
1545 SwSbxValue val
= aCalc
.Calculate("foobar()");
1546 CPPUNIT_ASSERT(aCalc
.IsCalcError() && val
.IsVoidValue() && val
.IsDouble());
1547 CPPUNIT_ASSERT_EQUAL(DBL_MAX
, val
.GetDouble());
1548 // Evaluating non-defined variable should return 0 without an error
1549 val
= aCalc
.Calculate("foobar");
1550 CPPUNIT_ASSERT(!aCalc
.IsCalcError() && val
.IsVoidValue() && val
.IsLong());
1551 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), val
.GetLong());
1554 void SwDocTest::testMarkMove()
1556 IDocumentMarkAccess
* pMarksAccess
= m_pDoc
->getIDocumentMarkAccess();
1559 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1561 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Paragraph 1");
1563 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->nContent
.GetIndex();
1564 pMarksAccess
->makeMark(aPaM
, "Para1",
1565 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1567 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1568 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Paragraph 2");
1570 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->nContent
.GetIndex();
1571 pMarksAccess
->makeMark(aPaM
, "Para2",
1572 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1574 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1575 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, "Paragraph 3");
1577 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->nContent
.GetIndex();
1578 pMarksAccess
->makeMark(aPaM
, "Para3",
1579 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1582 // join paragraph 2 and 3 and check
1584 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -2);
1585 SwTextNode
& rParaNode2
= dynamic_cast<SwTextNode
&>(aIdx
.GetNode());
1586 rParaNode2
.JoinNext();
1588 ::sw::mark::IMark
* pBM1
= pMarksAccess
->findMark("Para1")->get();
1589 ::sw::mark::IMark
* pBM2
= pMarksAccess
->findMark("Para2")->get();
1590 ::sw::mark::IMark
* pBM3
= pMarksAccess
->findMark("Para3")->get();
1592 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM1
->GetMarkStart().nContent
.GetIndex());
1593 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM1
->GetMarkEnd().nContent
.GetIndex());
1594 CPPUNIT_ASSERT_EQUAL(
1595 pBM1
->GetMarkStart().nNode
.GetIndex(),
1596 pBM1
->GetMarkEnd().nNode
.GetIndex());
1598 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM2
->GetMarkStart().nContent
.GetIndex());
1599 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM2
->GetMarkEnd().nContent
.GetIndex());
1600 CPPUNIT_ASSERT_EQUAL(
1601 pBM2
->GetMarkStart().nNode
.GetIndex(),
1602 pBM2
->GetMarkEnd().nNode
.GetIndex());
1604 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM3
->GetMarkStart().nContent
.GetIndex());
1605 CPPUNIT_ASSERT_EQUAL(sal_Int32(22), pBM3
->GetMarkEnd().nContent
.GetIndex());
1606 CPPUNIT_ASSERT_EQUAL(
1607 pBM3
->GetMarkStart().nNode
.GetIndex(),
1608 pBM3
->GetMarkEnd().nNode
.GetIndex());
1610 CPPUNIT_ASSERT_EQUAL(
1611 pBM1
->GetMarkStart().nNode
.GetIndex()+1,
1612 pBM2
->GetMarkStart().nNode
.GetIndex());
1613 CPPUNIT_ASSERT_EQUAL(
1614 pBM2
->GetMarkStart().nNode
.GetIndex(),
1615 pBM3
->GetMarkStart().nNode
.GetIndex());
1619 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1620 SwPaM
aPaM(aIdx
, aIdx
, -1);
1621 aPaM
.GetPoint()->nContent
+= 5;
1622 aPaM
.GetMark()->nContent
+= 6;
1623 m_pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
);
1625 pBM1
= pMarksAccess
->findMark("Para1")->get();
1626 pBM2
= pMarksAccess
->findMark("Para2")->get();
1627 pBM3
= pMarksAccess
->findMark("Para3")->get();
1629 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1
->GetMarkStart().nContent
.GetIndex());
1630 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1
->GetMarkEnd().nContent
.GetIndex());
1631 CPPUNIT_ASSERT_EQUAL(
1632 pBM1
->GetMarkStart().nNode
.GetIndex(),
1633 pBM1
->GetMarkEnd().nNode
.GetIndex());
1635 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2
->GetMarkStart().nContent
.GetIndex());
1636 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM2
->GetMarkEnd().nContent
.GetIndex());
1637 CPPUNIT_ASSERT_EQUAL(
1638 pBM2
->GetMarkStart().nNode
.GetIndex(),
1639 pBM2
->GetMarkEnd().nNode
.GetIndex());
1641 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM3
->GetMarkStart().nContent
.GetIndex());
1642 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), pBM3
->GetMarkEnd().nContent
.GetIndex());
1643 CPPUNIT_ASSERT_EQUAL(
1644 pBM3
->GetMarkStart().nNode
.GetIndex(),
1645 pBM3
->GetMarkEnd().nNode
.GetIndex());
1647 CPPUNIT_ASSERT_EQUAL(
1648 pBM1
->GetMarkStart().nNode
.GetIndex(),
1649 pBM2
->GetMarkStart().nNode
.GetIndex());
1650 CPPUNIT_ASSERT_EQUAL(
1651 pBM2
->GetMarkStart().nNode
.GetIndex(),
1652 pBM3
->GetMarkStart().nNode
.GetIndex());
1654 // split the paragraph
1656 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1657 SwPosition
aPos(aIdx
);
1659 m_pDoc
->getIDocumentContentOperations().SplitNode(aPos
, false);
1661 pBM1
= pMarksAccess
->findMark("Para1")->get();
1662 pBM2
= pMarksAccess
->findMark("Para2")->get();
1663 pBM3
= pMarksAccess
->findMark("Para3")->get();
1665 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1
->GetMarkStart().nContent
.GetIndex());
1666 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1
->GetMarkEnd().nContent
.GetIndex());
1667 CPPUNIT_ASSERT_EQUAL(
1668 pBM1
->GetMarkStart().nNode
.GetIndex(),
1669 pBM1
->GetMarkEnd().nNode
.GetIndex());
1671 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2
->GetMarkStart().nContent
.GetIndex());
1672 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM2
->GetMarkEnd().nContent
.GetIndex());
1673 CPPUNIT_ASSERT_EQUAL(
1674 pBM2
->GetMarkStart().nNode
.GetIndex()+1,
1675 pBM2
->GetMarkEnd().nNode
.GetIndex());
1677 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM3
->GetMarkStart().nContent
.GetIndex());
1678 CPPUNIT_ASSERT_EQUAL(sal_Int32(15), pBM3
->GetMarkEnd().nContent
.GetIndex());
1679 CPPUNIT_ASSERT_EQUAL(
1680 pBM3
->GetMarkStart().nNode
.GetIndex(),
1681 pBM3
->GetMarkEnd().nNode
.GetIndex());
1683 CPPUNIT_ASSERT_EQUAL(
1684 pBM1
->GetMarkStart().nNode
.GetIndex(),
1685 pBM2
->GetMarkStart().nNode
.GetIndex());
1686 CPPUNIT_ASSERT_EQUAL(
1687 pBM2
->GetMarkEnd().nNode
.GetIndex(),
1688 pBM3
->GetMarkEnd().nNode
.GetIndex());
1693 struct TestRing
: public sw::Ring
<TestRing
>
1695 TestRing() : sw::Ring
<TestRing
>() {};
1697 { return GetNextInRing(); }
1699 { return GetPrevInRing(); }
1701 { return unique(); }
1705 SAL_DEBUG("TestRing at: " << this << " prev: " << GetPrev() << " next: " << GetNext());
1711 void SwDocTest::testIntrusiveRing()
1713 TestRing aRing1
, aRing2
, aRing3
, aRing4
, aRing5
;
1714 std::vector
<TestRing
*> vRings
;
1715 vRings
.push_back(&aRing1
);
1716 vRings
.push_back(&aRing2
);
1717 vRings
.push_back(&aRing3
);
1718 vRings
.push_back(&aRing4
);
1719 vRings
.push_back(&aRing5
);
1720 CPPUNIT_ASSERT_EQUAL(aRing1
.GetRingContainer().size(), static_cast<size_t>(1));
1721 CPPUNIT_ASSERT(aRing1
.lonely());
1722 CPPUNIT_ASSERT(aRing2
.lonely());
1723 CPPUNIT_ASSERT(aRing3
.lonely());
1724 aRing2
.MoveTo(&aRing1
);
1725 aRing3
.MoveTo(&aRing1
);
1726 CPPUNIT_ASSERT_EQUAL(aRing1
.GetRingContainer().size(), static_cast<size_t>(3));
1727 CPPUNIT_ASSERT_EQUAL(aRing2
.GetRingContainer().size(), static_cast<size_t>(3));
1728 CPPUNIT_ASSERT_EQUAL(aRing3
.GetRingContainer().size(), static_cast<size_t>(3));
1729 CPPUNIT_ASSERT(!aRing1
.lonely());
1730 CPPUNIT_ASSERT(!aRing2
.lonely());
1731 CPPUNIT_ASSERT(!aRing3
.lonely());
1732 aRing5
.MoveTo(&aRing4
);
1733 CPPUNIT_ASSERT_EQUAL(aRing4
.GetRingContainer().size(), static_cast<size_t>(2));
1734 aRing4
.GetRingContainer().merge(aRing1
.GetRingContainer());
1735 for(TestRing
* pRing
: vRings
)
1737 CPPUNIT_ASSERT_EQUAL(pRing
->GetRingContainer().size(), static_cast<size_t>(5));
1739 for(std::vector
<TestRing
*>::iterator ppRing
= vRings
.begin(); ppRing
!= vRings
.end(); ++ppRing
)
1741 std::vector
<TestRing
*>::iterator ppNext
= ppRing
+1;
1742 if(ppNext
==vRings
.end())
1743 ppNext
= vRings
.begin();
1744 CPPUNIT_ASSERT_EQUAL((*ppRing
)->GetNext(), *ppNext
);
1745 CPPUNIT_ASSERT_EQUAL((*ppNext
)->GetPrev(), *ppRing
);
1747 for(TestRing
& r
: aRing1
.GetRingContainer())
1749 TestRing
* pRing
= &r
;
1750 CPPUNIT_ASSERT(pRing
);
1753 const TestRing
* pConstRing
= &aRing1
;
1754 for(const TestRing
& r
: pConstRing
->GetRingContainer()) // this should fail without r being const
1756 const TestRing
* pRing
= &r
;
1757 CPPUNIT_ASSERT(pRing
);
1761 CPPUNIT_ASSERT_EQUAL(&foo
, bar
.GetNext());
1762 CPPUNIT_ASSERT_EQUAL(&foo
, bar
.GetPrev());
1763 CPPUNIT_ASSERT_EQUAL(&bar
, foo
.GetNext());
1764 CPPUNIT_ASSERT_EQUAL(&bar
, foo
.GetPrev());
1766 CPPUNIT_ASSERT_EQUAL(&bar
, bar
.GetNext());
1767 CPPUNIT_ASSERT_EQUAL(&bar
, bar
.GetPrev());
1768 CPPUNIT_ASSERT_EQUAL(&foo
, foo
.GetNext());
1769 CPPUNIT_ASSERT_EQUAL(&foo
, foo
.GetPrev());
1774 struct TestHint final
: SfxHint
{};
1775 struct TestModify
: SwModify
1778 struct TestClient
: SwClient
1782 int m_nModifyChangedCount
;
1783 const SwModify
* m_pLastChangedModify
;
1784 TestClient() : m_nModifyCount(0), m_nNotifyCount(0), m_nModifyChangedCount(0), m_pLastChangedModify(nullptr) {};
1785 virtual void Modify( const SfxPoolItem
*, const SfxPoolItem
*) override
1787 virtual void SwClientNotify(const SwModify
&, const SfxHint
& rHint
) override
1789 if(typeid(TestHint
) == typeid(rHint
))
1791 else if(dynamic_cast<const sw::LegacyModifyHint
*>(&rHint
))
1793 else if(auto pModifyChangedHint
= dynamic_cast<const sw::ModifyChangedHint
*>(&rHint
))
1795 ++m_nModifyChangedCount
;
1796 m_pLastChangedModify
= pModifyChangedHint
->m_pNew
;
1800 struct OtherTestClient
: SwClient
1803 OtherTestClient() : m_nModifyCount(0) {};
1804 virtual void Modify( const SfxPoolItem
*, const SfxPoolItem
*) override
1805 { ++m_nModifyCount
; }
1808 void SwDocTest::testClientModify()
1810 (void) OtherTestClient(); // avoid loplugin:unreffun
1812 TestClient aClient1
, aClient2
;
1813 OtherTestClient aOtherClient1
;
1814 // test client registration
1815 CPPUNIT_ASSERT(!aMod
.HasWriterListeners());
1816 CPPUNIT_ASSERT(!aMod
.HasOnlyOneListener());
1817 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient1
.GetRegisteredIn());
1818 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1819 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1820 aMod
.Add(&aClient1
);
1821 CPPUNIT_ASSERT(aMod
.HasWriterListeners());
1822 CPPUNIT_ASSERT(aMod
.HasOnlyOneListener());
1823 aMod
.Add(&aClient2
);
1824 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient1
.GetRegisteredIn());
1825 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
), aClient2
.GetRegisteredIn());
1826 CPPUNIT_ASSERT(aMod
.HasWriterListeners());
1827 CPPUNIT_ASSERT(!aMod
.HasOnlyOneListener());
1829 aMod
.ModifyBroadcast(nullptr, nullptr);
1830 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nModifyCount
);
1831 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nModifyCount
);
1832 CPPUNIT_ASSERT_EQUAL(0,aClient1
.m_nNotifyCount
);
1833 CPPUNIT_ASSERT_EQUAL(0,aClient2
.m_nNotifyCount
);
1834 aMod
.ModifyBroadcast(nullptr, nullptr);
1835 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1836 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1837 CPPUNIT_ASSERT_EQUAL(0,aClient1
.m_nNotifyCount
);
1838 CPPUNIT_ASSERT_EQUAL(0,aClient2
.m_nNotifyCount
);
1842 aMod
.CallSwClientNotify(aHint
);
1843 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1844 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1845 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nNotifyCount
);
1846 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nNotifyCount
);
1848 // test typed iteration
1849 CPPUNIT_ASSERT(typeid(aClient1
) != typeid(OtherTestClient
));
1851 SwIterator
<OtherTestClient
,SwModify
> aIter(aMod
);
1852 for(OtherTestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1853 CPPUNIT_ASSERT(false);
1857 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1858 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1860 CPPUNIT_ASSERT_EQUAL(2,pClient
->m_nModifyCount
);
1863 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1865 aMod
.Add(&aOtherClient1
);
1866 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1
.m_nModifyCount
);
1869 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1870 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1872 CPPUNIT_ASSERT_EQUAL(2,pClient
->m_nModifyCount
);
1875 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1877 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1
.m_nModifyCount
);
1878 aMod
.Remove(&aOtherClient1
);
1879 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient1
.GetRegisteredIn());
1880 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient2
.GetRegisteredIn());
1881 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aOtherClient1
.GetRegisteredIn());
1882 // test client self-deregistration during iteration
1885 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1886 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1888 aMod
.Remove(pClient
);
1891 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1893 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient1
.GetRegisteredIn());
1894 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1896 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1897 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1899 CPPUNIT_ASSERT(false);
1902 aMod
.ModifyBroadcast(nullptr, nullptr);
1903 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1904 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1905 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nNotifyCount
);
1906 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nNotifyCount
);
1908 void SwDocTest::testWriterMultiListener()
1912 sw::WriterMultiListener
aMulti(aClient
);
1913 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1914 aMulti
.StartListening(&aMod
);
1915 CPPUNIT_ASSERT(aMulti
.IsListeningTo(&aMod
));
1916 aMulti
.EndListeningAll();
1917 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1918 aMulti
.StartListening(&aMod
);
1919 aMulti
.EndListening(&aMod
);
1920 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1921 int nPreDeathChangedCount
;
1923 TestModify aTempMod
;
1924 aMod
.Add(&aTempMod
);
1925 aMulti
.StartListening(&aTempMod
);
1926 nPreDeathChangedCount
= aClient
.m_nModifyChangedCount
;
1928 CPPUNIT_ASSERT(aMulti
.IsListeningTo(&aMod
));
1929 CPPUNIT_ASSERT_EQUAL(nPreDeathChangedCount
+1, aClient
.m_nModifyChangedCount
);
1930 CPPUNIT_ASSERT_EQUAL(static_cast<const SwModify
*>(&aMod
),aClient
.m_pLastChangedModify
);
1933 void SwDocTest::test64kPageDescs()
1935 size_t nPageDescCount
= 65536; // USHRT_MAX + 1
1937 for (size_t i
= 0; i
< nPageDescCount
; ++i
)
1939 OUString aName
= "Page" + OUString::number(i
);
1940 m_pDoc
->MakePageDesc( aName
);
1943 size_t nCount
= m_pDoc
->GetPageDescCnt();
1944 // +1 because Writer always creates a dummy page desc
1946 CPPUNIT_ASSERT_EQUAL( nPageDescCount
+ 1, nCount
);
1948 const SwPageDesc
&rDesc
= m_pDoc
->GetPageDesc( nPageDescCount
);
1949 SwPageDesc
&rZeroDesc
= m_pDoc
->GetPageDesc( 0 );
1950 CPPUNIT_ASSERT_EQUAL( OUString("Page65535"), rDesc
.GetName() );
1952 SwPageDesc
aDesc( rDesc
);
1953 const OUString
aChanged("Changed01");
1954 aDesc
.SetName( aChanged
);
1955 m_pDoc
->ChgPageDesc( nPageDescCount
, aDesc
);
1958 SwPageDesc
*pDesc
= m_pDoc
->FindPageDesc( aChanged
, &nPos
);
1959 CPPUNIT_ASSERT( pDesc
!= nullptr );
1960 CPPUNIT_ASSERT_EQUAL( nPageDescCount
, nPos
);
1962 // check if we didn't mess up PageDesc at pos 0
1963 // (happens with 16bit int overflow)
1964 OUString aZeroName
= rZeroDesc
.GetName();
1965 rZeroDesc
= m_pDoc
->GetPageDesc( 0 );
1966 CPPUNIT_ASSERT_EQUAL( aZeroName
, rZeroDesc
.GetName() );
1968 m_pDoc
->DelPageDesc( aChanged
, /*bBroadcast*/true );
1969 pDesc
= m_pDoc
->FindPageDesc( aChanged
, &nPos
);
1970 // not there anymore
1971 CPPUNIT_ASSERT( !pDesc
);
1972 CPPUNIT_ASSERT_EQUAL( std::numeric_limits
<size_t>::max(), nPos
);
1974 // check if PageDesc at pos 0 is still there
1975 pDesc
= m_pDoc
->FindPageDesc( aZeroName
, &nPos
);
1976 CPPUNIT_ASSERT( pDesc
!= nullptr );
1977 CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(0), nPos
);
1980 void SwDocTest::testTdf92308()
1982 CPPUNIT_ASSERT_EQUAL(m_pDoc
->HasInvisibleContent(), false);
1985 void SwDocTest::testTableCellComparison()
1987 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst("A1", "Z1") );
1988 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst("Z1", "A1") );
1989 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByColFirst("A1", "A1") );
1991 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst("A2", "A1") );
1992 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst("Z3", "A2") );
1993 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst("A3", "Z1") );
1995 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByRowFirst("A1", "Z1") );
1996 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst("Z1", "A1") );
1997 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByRowFirst("A1", "A1") );
1999 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst("A2", "A1") );
2000 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst("Z3", "A2") );
2001 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst("A3", "Z1") );
2003 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges("A1", "A1", "A1", "A1", true) );
2004 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges("A1", "Z1", "A1", "Z1", true) );
2005 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges("A1", "Z1", "A1", "Z1", false) );
2007 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges("A1", "Z1", "B1", "Z1", true) );
2008 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges("A1", "Z1", "A2", "Z2", false) );
2009 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges("A1", "Z1", "A2", "Z2", true) );
2010 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges("A1", "Z1", "A6", "Z2", true) );
2012 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges("B1", "Z1", "A1", "Z1", true) );
2013 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges("A2", "Z2", "A1", "Z1", false) );
2014 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges("A2", "Z2", "A1", "Z1", true) );
2015 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges("A6", "Z2", "A1", "Z1", true) );
2017 OUString rCell1
= OUString("A1");
2018 OUString rCell2
= OUString("C5");
2020 sw_NormalizeRange(rCell1
, rCell2
);
2021 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell1
);
2022 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell2
);
2024 sw_NormalizeRange(rCell2
, rCell1
);
2025 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell1
);
2026 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell2
);
2028 rCell1
= OUString("A5");
2029 rCell2
= OUString("C1");
2031 sw_NormalizeRange(rCell1
, rCell2
);
2032 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell1
);
2033 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell2
);
2035 sw_NormalizeRange(rCell2
, rCell1
);
2036 CPPUNIT_ASSERT_EQUAL( OUString("C5"), rCell1
);
2037 CPPUNIT_ASSERT_EQUAL( OUString("A1"), rCell2
);
2039 CPPUNIT_ASSERT_EQUAL( OUString(), sw_GetCellName(-1, -1) );
2042 void SwDocTest::setUp()
2044 BootstrapFixture::setUp();
2046 SwGlobals::ensure();
2048 m_xDocShRef
= new SwDocShell(m_pDoc
, SfxObjectCreateMode::EMBEDDED
);
2049 m_xDocShRef
->DoInitNew();
2052 void SwDocTest::tearDown()
2054 m_pDoc
= nullptr; // deleted by DoClose()
2055 m_xDocShRef
->DoClose();
2056 m_xDocShRef
.clear();
2058 BootstrapFixture::tearDown();
2061 CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest
);
2063 CPPUNIT_PLUGIN_IMPLEMENT();
2065 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */