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 <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>
48 #include <IDocumentRedlineAccess.hxx>
49 #include <IDocumentFieldsAccess.hxx>
50 #include <IDocumentStatistics.hxx>
51 #include <cellfml.hxx>
53 #include <docstat.hxx>
54 #include <docufld.hxx>
55 #include <fmtanchr.hxx>
57 #include <shellres.hxx>
58 #include <swscanner.hxx>
60 #include <swtypes.hxx>
62 #include <fmtrfmrk.hxx>
63 #include <fmtinfmt.hxx>
64 #include <fchrfmt.hxx>
66 #include <redline.hxx>
68 #include <modeltoviewhelper.hxx>
72 #include <pagedesc.hxx>
74 #include <scriptinfo.hxx>
75 #include <rubylist.hxx>
76 #include <txatbase.hxx>
78 #include <tblafmt.hxx>
80 #include <IDocumentMarkAccess.hxx>
81 #include <itabenum.hxx>
83 typedef rtl::Reference
<SwDocShell
> SwDocShellRef
;
85 using namespace ::com::sun::star
;
87 /* Implementation of Swdoc-Test class */
89 class SwDocTest
: public test::BootstrapFixture
97 virtual void setUp() override
;
98 virtual void tearDown() override
;
100 void testTableAutoFormats();
101 void testPageDescName();
102 void testFileNameFields();
104 void testModelToViewHelperPassthrough();
105 void testModelToViewHelperExpandFieldsExpandFootnote();
106 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode();
107 void testModelToViewHelperExpandFields();
108 void testModelToViewHelperExpandFieldsReplaceMode();
109 void testModelToViewHelperExpandFieldsHideInvisible();
110 void testModelToViewHelperExpandFieldsHideRedlined();
111 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote();
112 void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode();
113 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote();
114 void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode();
115 void testModelToViewHelperHideInvisibleHideRedlined();
116 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote();
117 void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode();
118 void testModelToViewHelperExpandFieldsExpandFootnote2();
119 void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2();
120 void testSwScanner();
121 void testUserPerceivedCharCount();
122 void testMergePortionsDeleteNotSorted();
123 void testGraphicAnchorDeletion();
124 void testTransliterate();
127 void testIntrusiveRing();
128 void testClientModify();
129 void testBroadcastingModify();
130 void testWriterMultiListener();
131 void test64kPageDescs();
133 void testTableCellComparison();
134 void testTdf156211();
135 void testFillRubyList();
136 void testSetRubyList();
138 CPPUNIT_TEST_SUITE(SwDocTest
);
140 CPPUNIT_TEST(testTransliterate
);
141 CPPUNIT_TEST(testTableAutoFormats
);
142 CPPUNIT_TEST(testPageDescName
);
143 CPPUNIT_TEST(testFileNameFields
);
144 CPPUNIT_TEST(testDocStat
);
145 CPPUNIT_TEST(testModelToViewHelperPassthrough
);
146 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote
);
147 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode
);
148 CPPUNIT_TEST(testModelToViewHelperExpandFields
);
149 CPPUNIT_TEST(testModelToViewHelperExpandFieldsReplaceMode
);
150 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisible
);
151 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideRedlined
);
152 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote
);
153 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode
);
154 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote
);
155 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode
);
156 CPPUNIT_TEST(testModelToViewHelperHideInvisibleHideRedlined
);
157 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote
);
158 CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode
);
159 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote2
);
160 CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2
);
161 CPPUNIT_TEST(testSwScanner
);
162 CPPUNIT_TEST(testUserPerceivedCharCount
);
163 CPPUNIT_TEST(testMergePortionsDeleteNotSorted
);
164 CPPUNIT_TEST(testGraphicAnchorDeletion
);
165 CPPUNIT_TEST(testMarkMove
);
166 CPPUNIT_TEST(testFormulas
);
167 CPPUNIT_TEST(testIntrusiveRing
);
168 CPPUNIT_TEST(testClientModify
);
169 CPPUNIT_TEST(testBroadcastingModify
);
170 CPPUNIT_TEST(testWriterMultiListener
);
171 CPPUNIT_TEST(test64kPageDescs
);
172 CPPUNIT_TEST(testTdf92308
);
173 CPPUNIT_TEST(testTableCellComparison
);
174 CPPUNIT_TEST(testTdf156211
);
175 CPPUNIT_TEST(testFillRubyList
);
176 CPPUNIT_TEST(testSetRubyList
);
177 CPPUNIT_TEST_SUITE_END();
181 SwDocShellRef m_xDocShRef
;
184 void SwDocTest::testPageDescName()
186 ShellResource aShellResources
;
188 std::vector
<OUString
> aResults
;
190 //These names must be unique for each different combination, otherwise
191 //duplicate page description names may exist, which will causes lookup
192 //by name to be incorrect, and so the corresponding export to .odt
193 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::NORMAL_PAGE
));
194 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::FIRST_PAGE
));
195 aResults
.push_back(aShellResources
.GetPageDescName(1, ShellResource::FOLLOW_PAGE
));
197 std::sort(aResults
.begin(), aResults
.end());
198 aResults
.erase(std::unique(aResults
.begin(), aResults
.end()), aResults
.end());
200 CPPUNIT_ASSERT_EQUAL_MESSAGE("GetPageDescName results must be unique", static_cast<size_t>(3), aResults
.size());
203 //See https://bugs.libreoffice.org/show_bug.cgi?id=32463
204 void SwDocTest::testFileNameFields()
206 //Here's a file name with some chars in it that will be %% encoded, when expanding
207 //SwFileNameFields we want to restore the original readable filename
208 utl::TempFileNamed
aTempFile(u
"demo [name]");
209 aTempFile
.EnableKillingFile();
211 INetURLObject
aTempFileURL(aTempFile
.GetURL());
212 OUString sFileURL
= aTempFileURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
213 SfxMedium
aDstMed(sFileURL
, StreamMode::STD_READWRITE
);
215 auto pFilter
= std::make_shared
<SfxFilter
>(
217 OUString(), SfxFilterFlags::NONE
, SotClipboardFormatId::NONE
, OUString(), OUString(),
218 "TEXT", OUString() );
219 aDstMed
.SetFilter(pFilter
);
221 m_xDocShRef
->DoSaveAs(aDstMed
);
222 m_xDocShRef
->DoSaveCompleted(&aDstMed
);
224 const INetURLObject
&rUrlObj
= m_xDocShRef
->GetMedium()->GetURLObject();
226 SwFileNameFieldType
aNameField(*m_pDoc
);
229 OUString
sResult(aNameField
.Expand(FF_NAME
));
230 OUString
sExpected(rUrlObj
.getName(INetURLObject::LAST_SEGMENT
,
231 true,INetURLObject::DecodeMechanism::WithCharset
));
232 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
236 OUString
sResult(aNameField
.Expand(FF_PATHNAME
));
237 OUString
sExpected(rUrlObj
.GetFull());
238 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
242 OUString
sResult(aNameField
.Expand(FF_PATH
));
243 INetURLObject
aTemp(rUrlObj
);
244 aTemp
.removeSegment();
245 OUString
sExpected(aTemp
.PathToFileName());
246 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
250 OUString
sResult(aNameField
.Expand(FF_NAME_NOEXT
));
251 OUString
sExpected(rUrlObj
.getName(INetURLObject::LAST_SEGMENT
,
252 true,INetURLObject::DecodeMechanism::WithCharset
));
254 sExpected
= sExpected
.copy(0, sExpected
.getLength() - 4);
255 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected Readable FileName", sExpected
, sResult
);
258 m_xDocShRef
->DoInitNew();
261 //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
262 //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
264 void SwDocTest::testDocStat()
266 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
268 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
271 OUString
sText(u
"Hello World"_ustr
);
272 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sText
);
274 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should still be non-updated 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
276 SwDocStat aDocStat
= m_pDoc
->getIDocumentStatistics().GetUpdatedDocStat( false, true );
277 sal_uLong nLen
= static_cast<sal_uLong
>(sText
.getLength());
279 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should now have updated count", nLen
, aDocStat
.nChar
);
281 CPPUNIT_ASSERT_EQUAL_MESSAGE("And cache is updated too", nLen
, m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
284 //For UI character counts we should follow UAX#29 and display the user
285 //perceived characters, not the number of codepoints, nor the number of code
286 //units http://unicode.org/reports/tr29/
287 void SwDocTest::testUserPerceivedCharCount()
289 SwBreakIt
*pBreakIter
= SwBreakIt::Get();
291 //Grapheme example, two different unicode code-points perceived by the user as a single
293 static constexpr OUStringLiteral sALEF_QAMATS
= u
"\u05D0\u05B8";
294 sal_Int32 nGraphemeCount
= pBreakIter
->getGraphemeCount(sALEF_QAMATS
);
295 CPPUNIT_ASSERT_EQUAL_MESSAGE("Grapheme Count should be 1", static_cast<sal_Int32
>(1), nGraphemeCount
);
297 //Surrogate pair example, one single unicode code-point (U+1D11E)
298 //represented as two code units in UTF-16
299 static constexpr OUStringLiteral sGCLEF
= u
"\U0001D11E";
300 sal_Int32 nCount
= pBreakIter
->getGraphemeCount(sGCLEF
);
301 CPPUNIT_ASSERT_EQUAL_MESSAGE("Surrogate Pair should be counted as single character", static_cast<sal_Int32
>(1), nCount
);
304 static SwTextNode
* getModelToViewTestDocument(SwDoc
*pDoc
)
306 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
309 SwFormatFootnote aFootnote
;
310 aFootnote
.SetNumStr(u
"foo"_ustr
);
312 pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
313 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"AAAAA BBBBB "_ustr
);
314 SwTextNode
* pTextNode
= aPaM
.GetPointNode().GetTextNode();
315 sal_Int32 nPos
= aPaM
.GetPoint()->GetContentIndex();
316 pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
317 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
" CCCCC "_ustr
);
318 nPos
= aPaM
.GetPoint()->GetContentIndex();
319 pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
320 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
" DDDDD"_ustr
);
321 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>((4*5) + 5 + 2), pTextNode
->GetText().getLength());
323 //set start of selection to first B
324 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 6);
326 //set end of selection to last C
327 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 14);
328 //set character attribute hidden on range
329 SvxCharHiddenItem
aHidden(true, RES_CHRATR_HIDDEN
);
330 pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aHidden
);
333 //turn on red-lining and show changes
334 pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
335 CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
336 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
338 //set start of selection to last A
339 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 4);
341 //set end of selection to second last B
342 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 9);
343 pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
); //redline-aware deletion api
349 static SwTextNode
* getModelToViewTestDocument2(SwDoc
*pDoc
)
351 getModelToViewTestDocument(pDoc
);
353 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
356 pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
357 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"AAAAA"_ustr
);
358 IDocumentMarkAccess
* pMarksAccess
= pDoc
->getIDocumentMarkAccess();
359 sw::mark::Fieldmark
*pFieldmark
=
360 pMarksAccess
->makeNoTextFieldBookmark(aPaM
, u
"test"_ustr
, ODF_FORMDROPDOWN
);
361 CPPUNIT_ASSERT(pFieldmark
);
362 uno::Sequence
< OUString
> vListEntries
{ u
"BBBBB"_ustr
};
363 (*pFieldmark
->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY
] <<= vListEntries
;
364 (*pFieldmark
->GetParameters())[ODF_FORMDROPDOWN_RESULT
] <<= sal_Int32(0);
365 pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"CCCCC"_ustr
);
366 SwTextNode
* pTextNode
= aPaM
.GetPointNode().GetTextNode();
367 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(11),
368 pTextNode
->GetText().getLength());
373 void SwDocTest::testModelToViewHelperPassthrough()
375 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
377 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr, ExpandMode::PassThrough
);
378 OUString sViewText
= aModelToViewHelper
.getViewText();
379 OUString sModelText
= pTextNode
->GetText();
380 CPPUNIT_ASSERT_EQUAL(sModelText
, sViewText
);
383 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote()
385 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
387 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
388 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
);
389 OUString sViewText
= aModelToViewHelper
.getViewText();
390 CPPUNIT_ASSERT_EQUAL(
391 u
"AAAAA BBBBB foo CCCCC foo DDDDD"_ustr
, sViewText
);
394 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode()
396 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
398 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
399 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
400 OUString sViewText
= aModelToViewHelper
.getViewText();
401 CPPUNIT_ASSERT_EQUAL(
402 OUString("AAAAA BBBBB " + OUStringChar(CHAR_ZWSP
) + " CCCCC " + OUStringChar(CHAR_ZWSP
) + " DDDDD"),
404 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
405 aModelToViewHelper
.getFootnotePositions().size());
406 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(12),
407 aModelToViewHelper
.getFootnotePositions()[0]);
408 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(20),
409 aModelToViewHelper
.getFootnotePositions()[1]);
410 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
411 aModelToViewHelper
.getFieldPositions().size());
414 void SwDocTest::testModelToViewHelperExpandFields()
416 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
418 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr, ExpandMode::ExpandFields
);
419 OUString sViewText
= aModelToViewHelper
.getViewText();
420 CPPUNIT_ASSERT_EQUAL(
421 u
"AAAAA BBBBB CCCCC DDDDD"_ustr
, sViewText
);
424 void SwDocTest::testModelToViewHelperExpandFieldsReplaceMode()
426 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
428 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
429 ExpandMode::ExpandFields
| ExpandMode::ReplaceMode
);
430 OUString sViewText
= aModelToViewHelper
.getViewText();
431 CPPUNIT_ASSERT_EQUAL(u
"AAAAA BBBBB CCCCC DDDDD"_ustr
,
433 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
434 aModelToViewHelper
.getFootnotePositions().size());
435 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
436 aModelToViewHelper
.getFieldPositions().size());
439 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisible()
441 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
443 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr, ExpandMode::HideInvisible
);
444 OUString sViewText
= aModelToViewHelper
.getViewText();
445 CPPUNIT_ASSERT_EQUAL(
446 OUString("AAAAA CCCCC " + OUStringChar(CH_TXTATR_BREAKWORD
) + " DDDDD"),
450 void SwDocTest::testModelToViewHelperExpandFieldsHideRedlined()
452 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
454 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr, ExpandMode::HideDeletions
);
455 OUString sViewText
= aModelToViewHelper
.getViewText();
456 CPPUNIT_ASSERT_EQUAL(
457 OUString("AAAABB " + OUStringChar(CH_TXTATR_BREAKWORD
) + " CCCCC " + OUStringChar(CH_TXTATR_BREAKWORD
) + " DDDDD"),
461 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote()
463 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
465 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
466 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::ExpandFootnote
);
467 OUString sViewText
= aModelToViewHelper
.getViewText();
468 CPPUNIT_ASSERT_EQUAL(u
"AAAAA CCCCC foo DDDDD"_ustr
, sViewText
);
471 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode()
473 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
475 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
476 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
477 OUString sViewText
= aModelToViewHelper
.getViewText();
478 CPPUNIT_ASSERT_EQUAL(
479 OUString("AAAAA CCCCC " + OUStringChar(CHAR_ZWSP
) + " DDDDD"),
481 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
482 aModelToViewHelper
.getFootnotePositions().size());
483 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(12),
484 aModelToViewHelper
.getFootnotePositions()[0]);
485 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
486 aModelToViewHelper
.getFieldPositions().size());
489 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote()
491 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
493 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
494 ExpandMode::ExpandFields
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
);
495 OUString sViewText
= aModelToViewHelper
.getViewText();
496 CPPUNIT_ASSERT_EQUAL(
497 u
"AAAABB foo CCCCC foo DDDDD"_ustr
, sViewText
);
500 void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode()
502 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
504 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
505 ExpandMode::ExpandFields
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
506 OUString sViewText
= aModelToViewHelper
.getViewText();
507 CPPUNIT_ASSERT_EQUAL(
508 OUString("AAAABB " + OUStringChar(CHAR_ZWSP
) + " CCCCC " + OUStringChar(CHAR_ZWSP
) + " DDDDD"),
510 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
511 aModelToViewHelper
.getFootnotePositions().size());
512 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(7),
513 aModelToViewHelper
.getFootnotePositions()[0]);
514 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(15),
515 aModelToViewHelper
.getFootnotePositions()[1]);
516 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
517 aModelToViewHelper
.getFieldPositions().size());
520 void SwDocTest::testModelToViewHelperHideInvisibleHideRedlined()
522 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
524 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
525 ExpandMode::HideInvisible
| ExpandMode::HideDeletions
);
526 OUString sViewText
= aModelToViewHelper
.getViewText();
527 OUString aBuffer
= "AAAACCCCC " +
528 OUStringChar(CH_TXTATR_BREAKWORD
) +
530 CPPUNIT_ASSERT_EQUAL(aBuffer
, sViewText
);
533 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote()
535 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
537 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
538 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
);
539 OUString sViewText
= aModelToViewHelper
.getViewText();
540 CPPUNIT_ASSERT_EQUAL(u
"AAAACCCCC foo DDDDD"_ustr
, sViewText
);
543 void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode()
545 SwTextNode
* pTextNode
= getModelToViewTestDocument(m_pDoc
);
547 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
548 ExpandMode::ExpandFields
| ExpandMode::HideInvisible
| ExpandMode::HideDeletions
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
549 OUString sViewText
= aModelToViewHelper
.getViewText();
550 CPPUNIT_ASSERT_EQUAL(sViewText
,
551 OUString("AAAACCCCC " + OUStringChar(CHAR_ZWSP
) + " DDDDD"));
552 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
553 aModelToViewHelper
.getFootnotePositions().size());
554 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(10),
555 aModelToViewHelper
.getFootnotePositions()[0]);
556 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
557 aModelToViewHelper
.getFieldPositions().size());
560 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote2()
562 SwTextNode
* pTextNode
= getModelToViewTestDocument2(m_pDoc
);
564 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
565 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
);
566 OUString sViewText
= aModelToViewHelper
.getViewText();
567 CPPUNIT_ASSERT_EQUAL(u
"AAAAABBBBBCCCCC"_ustr
, sViewText
);
570 void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2()
572 SwTextNode
* pTextNode
= getModelToViewTestDocument2(m_pDoc
);
574 ModelToViewHelper
aModelToViewHelper(*pTextNode
, nullptr,
575 ExpandMode::ExpandFields
| ExpandMode::ExpandFootnote
| ExpandMode::ReplaceMode
);
576 OUString sViewText
= aModelToViewHelper
.getViewText();
577 CPPUNIT_ASSERT_EQUAL(
578 OUString("AAAAA" + OUStringChar(CHAR_ZWSP
) + "CCCCC"),
580 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
581 aModelToViewHelper
.getFootnotePositions().size());
582 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
583 aModelToViewHelper
.getFieldPositions().size());
584 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(5),
585 aModelToViewHelper
.getFieldPositions()[0]);
588 void SwDocTest::testSwScanner()
590 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
593 SwTextNode
* pTextNode
= aPaM
.GetPointNode().GetTextNode();
595 CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTextNode
);
597 //See https://bugs.libreoffice.org/show_bug.cgi?id=40449
598 //See https://bugs.libreoffice.org/show_bug.cgi?id=39365
599 //Use a temporary OUString as the arg, as that's the trouble behind
600 //fdo#40449 and fdo#39365
602 SwScanner
aScanner(*pTextNode
,
604 nullptr, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD
, 0,
605 RTL_CONSTASCII_LENGTH("Hello World"));
607 bool bFirstOk
= aScanner
.NextWord();
608 CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk
);
609 const OUString
&rHello
= aScanner
.GetWord();
610 CPPUNIT_ASSERT_EQUAL(u
"Hello"_ustr
, rHello
);
612 bool bSecondOk
= aScanner
.NextWord();
613 CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk
);
614 const OUString
&rWorld
= aScanner
.GetWord();
615 CPPUNIT_ASSERT_EQUAL(u
"World"_ustr
, rWorld
);
618 //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
620 static constexpr OUString IDEOGRAPHICFULLSTOP_D
= u
"\u3002D"_ustr
;
622 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, IDEOGRAPHICFULLSTOP_D
);
624 SvxLanguageItem
aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED
, RES_CHRATR_CJK_LANGUAGE
);
625 SvxLanguageItem
aWestLangItem( LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
626 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aCJKLangItem
);
627 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aWestLangItem
);
630 pTextNode
= aPaM
.GetPointNode().GetTextNode();
631 pTextNode
->CountWords(aDocStat
, 0, IDEOGRAPHICFULLSTOP_D
.getLength());
633 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nChar
);
634 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nCharExcludingSpaces
);
637 static constexpr OUString test
=
638 u
"\u3053\u306E\u65E5\u672C\u8A9E\u306F\u6B63\u3057"
639 "\u304F\u6570\u3048\u3089\u308C\u308B\u3067\u3057"
640 "\u3087\u3046\u304B\u3002And "
647 "ng. \u305D\u3057\u3066"
648 "\u3001\u307E\u305F\u65E5\u672C\u8A9E\u3000\u3000"
649 "\u3067\u3082\u4ECA\u56DE\u306F\u7A7A\u767D\u3092"
650 "\u3000\u3000\u5165\u308C\u307E\u3057\u305F\u3002"
654 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
655 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, test
);
657 SvxLanguageItem
aCJKLangItem( LANGUAGE_JAPANESE
, RES_CHRATR_CJK_LANGUAGE
);
658 SvxLanguageItem
aWestLangItem( LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
659 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aCJKLangItem
);
660 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aWestLangItem
);
663 pTextNode
= aPaM
.GetPointNode().GetTextNode();
664 pTextNode
->CountWords(aDocStat
, 0, test
.getLength());
665 CPPUNIT_ASSERT_EQUAL_MESSAGE("words", static_cast<sal_uLong
>(58), aDocStat
.nWord
);
666 CPPUNIT_ASSERT_EQUAL_MESSAGE("Asian characters and Korean words", static_cast<sal_uLong
>(43), aDocStat
.nAsianWord
);
667 CPPUNIT_ASSERT_EQUAL_MESSAGE("non-whitespace chars", static_cast<sal_uLong
>(105), aDocStat
.nCharExcludingSpaces
);
668 CPPUNIT_ASSERT_EQUAL_MESSAGE("characters", static_cast<sal_uLong
>(128), aDocStat
.nChar
);
671 //See https://bz.apache.org/ooo/show_bug.cgi?id=89042
672 //See https://bugs.libreoffice.org/show_bug.cgi?id=53399
676 static constexpr OUString aShouldBeThree
=
681 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
682 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, aShouldBeThree
);
683 pTextNode
= aPaM
.GetPointNode().GetTextNode();
684 pTextNode
->CountWords(aDocStat
, 0, aShouldBeThree
.getLength());
685 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(3), aDocStat
.nWord
);
687 static constexpr OUString aShouldBeFive
=
694 "ler\u3000\u00BB"_ustr
;
696 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
697 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, aShouldBeFive
);
698 pTextNode
= aPaM
.GetPointNode().GetTextNode();
700 pTextNode
->CountWords(aDocStat
, 0, aShouldBeFive
.getLength());
701 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(5), aDocStat
.nWord
);
704 //See https://bugs.libreoffice.org/show_bug.cgi?id=49629
708 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
709 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Apple"_ustr
);
710 pTextNode
= aPaM
.GetPointNode().GetTextNode();
711 sal_Int32 nPos
= aPaM
.GetPoint()->GetContentIndex();
712 SwFormatFootnote aFootnote
;
713 aFootnote
.SetNumStr(u
"banana"_ustr
);
714 SwTextAttr
* pTA
= pTextNode
->InsertItem(aFootnote
, nPos
, nPos
);
716 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(6), pTextNode
->Len()); //Apple + 0x02
717 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
718 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
719 CPPUNIT_ASSERT_EQUAL_MESSAGE("footnote should be expanded", static_cast<sal_uLong
>(11), aDocStat
.nChar
);
721 const sal_Int32 nNextPos
= aPaM
.GetPoint()->GetContentIndex();
722 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(nPos
+1), nNextPos
);
723 SwFormatRefMark
aRef(u
"refmark"_ustr
);
724 pTA
= pTextNode
->InsertItem(aRef
, nNextPos
, nNextPos
);
728 pTextNode
->SetWordCountDirty(true);
729 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
730 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
731 CPPUNIT_ASSERT_EQUAL_MESSAGE("refmark anchor should not be counted", static_cast<sal_uLong
>(11), aDocStat
.nChar
);
733 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
734 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Apple"_ustr
);
736 DateTime
aDate(DateTime::SYSTEM
);
737 SwPostItField
aPostIt(
738 static_cast<SwPostItFieldType
*>(m_pDoc
->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit
)), u
"An Author"_ustr
,
739 u
"Some Text"_ustr
, u
"Initials"_ustr
, u
"Name"_ustr
, aDate
);
740 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, SwFormatField(aPostIt
));
742 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Apple"_ustr
);
743 pTextNode
= aPaM
.GetPointNode().GetTextNode();
745 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
746 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
747 CPPUNIT_ASSERT_EQUAL_MESSAGE("postit anchor should effectively not exist", static_cast<sal_uLong
>(10), aDocStat
.nChar
);
748 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(11), pTextNode
->Len());
753 //See https://bugs.libreoffice.org/show_bug.cgi?id=46757
757 static constexpr OUString aString
= u
"Lorem ipsum"_ustr
;
758 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
759 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, aString
);
760 pTextNode
= aPaM
.GetPointNode().GetTextNode();
761 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
762 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nWord
);
764 //turn on red-lining and show changes
765 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
766 CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
767 CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
769 //delete everything except the first word
770 aPaM
.SetMark(); //set start of selection to current pos
771 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 5); //set end of selection to fifth char of current node
772 m_pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
); //redline-aware deletion api
773 //"real underlying text should be the same"
774 CPPUNIT_ASSERT_EQUAL(aString
, pTextNode
->GetText());
777 pTextNode
->SetWordCountDirty(true);
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 pTextNode
->SetWordCountDirty(true);
783 //keep red-lining on but hide changes
784 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
);
785 CPPUNIT_ASSERT_MESSAGE("redlining should be still on", m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
786 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible", !IDocumentRedlineAccess::IsShowChanges(m_pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
789 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len()); //but word-counting the text should only count the non-deleted text
790 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), aDocStat
.nWord
);
792 OUString sLorem
= pTextNode
->GetText();
793 CPPUNIT_ASSERT_EQUAL(u
"Lorem"_ustr
, sLorem
);
795 const SwRedlineTable
& rTable
= m_pDoc
->getIDocumentRedlineAccess().GetRedlineTable();
797 SwNodes
& rNds
= m_pDoc
->GetNodes();
798 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(1), rTable
.size());
800 const SwNodeIndex
* pNodeIdx
= rTable
[0]->GetContentIdx();
801 CPPUNIT_ASSERT(pNodeIdx
);
803 pTextNode
= rNds
[ pNodeIdx
->GetIndex() + 1 ]->GetTextNode(); //first deleted txtnode
804 CPPUNIT_ASSERT(pTextNode
);
806 OUString sIpsum
= pTextNode
->GetText();
807 CPPUNIT_ASSERT_EQUAL(u
" ipsum"_ustr
, sIpsum
);
810 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len()); //word-counting the text should only count the non-deleted text, and this whole chunk should be ignored
811 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(0), aDocStat
.nWord
);
812 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(0), aDocStat
.nChar
);
814 // https://bugs.libreoffice.org/show_bug.cgi?id=68347 we do want to count
815 // redline *added* text though
816 m_pDoc
->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On
| RedlineFlags::ShowDelete
|RedlineFlags::ShowInsert
);
818 aPaM
.GetPoint()->nContent
.Assign(aPaM
.GetPointContentNode(), 0);
819 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"redline-new-text "_ustr
);
821 pTextNode
= aPaM
.GetPointNode().GetTextNode();
822 pTextNode
->SetWordCountDirty(true);
823 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
824 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), aDocStat
.nWord
);
825 //redline-new-text Lorem ipsum
826 //+++++++++++++++++ ------
827 //select start of original text and part of deleted text
829 pTextNode
->CountWords(aDocStat
, 17, 25);
830 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(5), aDocStat
.nChar
);
833 //See https://bugs.libreoffice.org/show_bug.cgi?id=38983
837 OUString
sTemplate(u
"ThisXis a test."_ustr
);
839 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
840 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', ' '));
841 pTextNode
= aPaM
.GetPointNode().GetTextNode();
842 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
843 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat
.nWord
);
844 CPPUNIT_ASSERT_EQUAL(sal_uLong(12), aDocStat
.nCharExcludingSpaces
);
845 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat
.nChar
);
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
);
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(13), aDocStat
.nCharExcludingSpaces
);
863 CPPUNIT_ASSERT_EQUAL(sal_uLong(17), aDocStat
.nChar
);
866 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
867 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", " -- "));
868 pTextNode
= aPaM
.GetPointNode().GetTextNode();
869 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
870 CPPUNIT_ASSERT_EQUAL(sal_uLong(5), aDocStat
.nWord
);
871 CPPUNIT_ASSERT_EQUAL(sal_uLong(14), aDocStat
.nCharExcludingSpaces
);
872 CPPUNIT_ASSERT_EQUAL(sal_uLong(18), aDocStat
.nChar
);
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
);
884 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
885 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', '-'));
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
);
893 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
894 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2012));
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
);
902 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
903 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2015));
904 pTextNode
= aPaM
.GetPointNode().GetTextNode();
905 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
906 CPPUNIT_ASSERT_EQUAL(sal_uLong(3), aDocStat
.nWord
);
907 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat
.nCharExcludingSpaces
);
908 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat
.nChar
);
911 //But default configuration should, msword-alike treat emdash
912 //and endash as word separators for word-counting
913 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
914 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2013));
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
);
922 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
923 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replace('X', 0x2014));
924 pTextNode
= aPaM
.GetPointNode().GetTextNode();
925 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
926 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat
.nWord
);
927 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat
.nCharExcludingSpaces
);
928 CPPUNIT_ASSERT_EQUAL(sal_uLong(15), aDocStat
.nChar
);
931 static constexpr OUStringLiteral sChunk
= u
" \u2013 ";
932 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
933 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, sTemplate
.replaceAll("X", sChunk
));
934 pTextNode
= aPaM
.GetPointNode().GetTextNode();
935 pTextNode
->CountWords(aDocStat
, 0, pTextNode
->Len());
936 CPPUNIT_ASSERT_EQUAL(sal_uLong(4), aDocStat
.nWord
);
937 CPPUNIT_ASSERT_EQUAL(sal_uLong(13), aDocStat
.nCharExcludingSpaces
);
938 CPPUNIT_ASSERT_EQUAL(sal_uLong(17), aDocStat
.nChar
);
942 // tdf#150621 Korean words should be counted individually, rather than by syllable.
944 // Per i#80815, the intention for the word count feature is to emulate the behavior of MS Word.
946 auto fnAssertWords
= [&](const OUString
& aStr
, sal_uLong nWords
, sal_uLong nAsianWords
)
948 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
950 SvxLanguageItem
aCJKLangItem(LANGUAGE_KOREAN
, RES_CHRATR_CJK_LANGUAGE
);
951 SvxLanguageItem
aWestLangItem(LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
952 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aCJKLangItem
);
953 m_pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, aWestLangItem
);
955 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, aStr
);
958 pTextNode
= aPaM
.GetPointNode().GetTextNode();
959 pTextNode
->CountWords(aDocStat
, 0, aStr
.getLength());
960 CPPUNIT_ASSERT_EQUAL_MESSAGE("words", nWords
, aDocStat
.nWord
);
961 CPPUNIT_ASSERT_EQUAL_MESSAGE("Asian characters and Korean words", nAsianWords
,
962 aDocStat
.nAsianWord
);
965 // Basic case: Korean words are counted as space-delimited. In particular, grammatical
966 // particles are treated as part of the previous word.
967 fnAssertWords(u
"저는 영화를 봤어요"_ustr
, 3, 3);
969 // Mixed script: Korean is mostly written in hangul, but hanja are still used in certain
970 // situations (e.g. abbreviations in newspaper articles). For Chinese and Japanese, such
971 // ideographs would be counted individually as words. In Korean, however, they are treated
972 // no differently than hangul characters.
973 fnAssertWords(u
"尹탄핵"_ustr
, 1, 1);
974 fnAssertWords(u
"尹 탄핵"_ustr
, 2, 2);
976 // These mixed-script results are anomalous, but reflect the behavior of MSW.
977 fnAssertWords(u
"불렀다...與"_ustr
, 1, 1);
978 fnAssertWords(u
"불렀다 ...與"_ustr
, 2, 1);
979 fnAssertWords(u
"불렀다 ... 與"_ustr
, 3, 2);
983 void SwDocTest::testMergePortionsDeleteNotSorted()
985 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
987 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
" AABBCC"_ustr
);
989 SwCharFormat
*const pCharFormat(m_pDoc
->MakeCharFormat(u
"foo"_ustr
, nullptr));
990 SwFormatCharFormat
const charFormat(pCharFormat
);
992 SwFormatINetFormat
const inetFormat(u
"http://example.com"_ustr
, u
""_ustr
);
994 IDocumentContentOperations
& rIDCO(m_pDoc
->getIDocumentContentOperations());
996 aPaM
.GetPoint()->nContent
= 2;
997 aPaM
.GetMark()->nContent
= 4;
998 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
999 aPaM
.GetPoint()->nContent
= 2;
1000 aPaM
.GetMark()->nContent
= 5;
1001 rIDCO
.InsertPoolItem(aPaM
, inetFormat
);
1002 aPaM
.GetPoint()->nContent
= 6;
1003 aPaM
.GetMark()->nContent
= 8;
1004 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
1005 aPaM
.GetPoint()->nContent
= 4;
1006 aPaM
.GetMark()->nContent
= 6;
1007 // this triggered an STL assert in SwpHints::MergePortions()
1008 rIDCO
.InsertPoolItem(aPaM
, charFormat
);
1011 //See https://bugs.libreoffice.org/show_bug.cgi?id=40599
1012 void SwDocTest::testGraphicAnchorDeletion()
1014 CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected initial 0 count", static_cast<sal_uLong
>(0), m_pDoc
->getIDocumentStatistics().GetDocStat().nChar
);
1016 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1019 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Paragraph 1"_ustr
);
1020 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1022 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"graphic anchor>><<graphic anchor"_ustr
);
1023 SwNodeIndex
nPara2(aPaM
.GetPoint()->GetNode());
1024 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1026 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Paragraph 3"_ustr
);
1028 aPaM
.GetPoint()->Assign(nPara2
);
1029 aPaM
.GetPoint()->SetContent(RTL_CONSTASCII_LENGTH("graphic anchor>>"));
1031 //Insert a graphic at X of >>X<< in paragraph 2
1032 SfxItemSet
aFlySet(m_pDoc
->GetAttrPool(), svl::Items
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1>);
1033 SwFormatAnchor
aAnchor(RndStdIds::FLY_AS_CHAR
);
1034 aAnchor
.SetAnchor(aPaM
.GetPoint());
1035 aFlySet
.Put(aAnchor
);
1036 SwFlyFrameFormat
*pFrame
= m_pDoc
->getIDocumentContentOperations().InsertGraphic(aPaM
, OUString(), OUString(), nullptr, &aFlySet
, nullptr, nullptr);
1037 CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame
!= nullptr);
1039 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 1 graphic", static_cast<size_t>(1), m_pDoc
->GetFlyCount(FLYCNTTYPE_GRF
));
1042 aPaM
.GetPoint()->Assign(nPara2
);
1043 aPaM
.GetPoint()->SetContent(
1044 RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
1046 aPaM
.GetPoint()->Assign(nPara2
);
1047 aPaM
.GetPoint()->SetContent(RTL_CONSTASCII_LENGTH("graphic anchor>"));
1048 m_pDoc
->getIDocumentContentOperations().DeleteRange(aPaM
);
1050 #ifdef DEBUG_AS_HTML
1052 SvFileStream
aPasteDebug(OUString("cppunitDEBUG.html"), StreamMode::WRITE
|StreamMode::TRUNC
);
1054 GetHTMLWriter( String(), String(), xWrt
);
1055 SwWriter
aDbgWrt( aPasteDebug
, *m_pDoc
);
1056 aDbgWrt
.Write( xWrt
);
1060 CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be 0 graphics", static_cast<size_t>(0), m_pDoc
->GetFlyCount(FLYCNTTYPE_GRF
));
1062 //Now, if instead we swap RndStdIds::FLY_AS_CHAR (inline graphic) to RndStdIds::FLY_AT_CHAR (anchored to character)
1063 //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
1064 //range to which its anchored, which is annoying.
1067 void SwDocTest::testTableAutoFormats()
1069 SwGlobals::ensure();
1071 //create new AutoFormatTable
1072 SwTableAutoFormatTable aTableAFT
;
1074 //check the style size - default is expected
1075 CPPUNIT_ASSERT_EQUAL( size_t(1), aTableAFT
.size() );
1078 SwTableAutoFormat
aTableAF( u
"TestItemStyle"_ustr
);
1080 //create new AutoFormat
1081 SwBoxAutoFormat aBoxAF
;
1084 SvxFontItem
aFont( RES_CHRATR_FONT
);
1085 aFont
.SetFamily( FontFamily::FAMILY_DECORATIVE
);
1086 aFont
.SetPitch( FontPitch::PITCH_VARIABLE
);
1087 aFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1088 aBoxAF
.SetFont( aFont
);
1090 SvxFontHeightItem
aHeight( 280, 120, RES_CHRATR_FONTSIZE
);
1091 aBoxAF
.SetHeight( aHeight
);
1093 SvxWeightItem
aWeight( FontWeight::WEIGHT_BOLD
, RES_CHRATR_WEIGHT
);
1094 aBoxAF
.SetWeight( aWeight
);
1096 SvxPostureItem
aPosture( FontItalic::ITALIC_NORMAL
, RES_CHRATR_POSTURE
);
1097 aBoxAF
.SetPosture( aPosture
);
1099 SvxFontItem
aCJKFont( RES_CHRATR_FONT
);
1100 aCJKFont
.SetFamily( FontFamily::FAMILY_MODERN
);
1101 aCJKFont
.SetPitch( FontPitch::PITCH_FIXED
);
1102 aCJKFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1103 aBoxAF
.SetCJKFont( aCJKFont
);
1105 SvxFontHeightItem
aCJKHeight( 230, 110, RES_CHRATR_FONTSIZE
);
1106 aBoxAF
.SetCJKHeight( aCJKHeight
);
1108 SvxWeightItem
aCJKWeight( FontWeight::WEIGHT_SEMIBOLD
, RES_CHRATR_WEIGHT
);
1109 aBoxAF
.SetCJKWeight( aCJKWeight
);
1111 SvxPostureItem
aCJKPosture( FontItalic::ITALIC_OBLIQUE
, RES_CHRATR_POSTURE
);
1112 aBoxAF
.SetCJKPosture( aCJKPosture
);
1114 SvxFontItem
aCTLFont( RES_CHRATR_FONT
);
1115 aCTLFont
.SetFamily( FontFamily::FAMILY_ROMAN
);
1116 aCTLFont
.SetPitch( FontPitch::PITCH_FIXED
);
1117 aCTLFont
.SetCharSet( RTL_TEXTENCODING_MS_1251
);
1118 aBoxAF
.SetCTLFont( aCTLFont
);
1120 SvxFontHeightItem
aCTLHeight( 215, 105, RES_CHRATR_FONTSIZE
);
1121 aBoxAF
.SetCTLHeight( aCTLHeight
);
1123 SvxWeightItem
aCTLWeight( FontWeight::WEIGHT_ULTRABOLD
, RES_CHRATR_WEIGHT
);
1124 aBoxAF
.SetCTLWeight( aCTLWeight
);
1126 SvxPostureItem
aCTLPosture( FontItalic::ITALIC_OBLIQUE
, RES_CHRATR_POSTURE
);
1127 aBoxAF
.SetCTLPosture( aCTLPosture
);
1129 SvxUnderlineItem
aUnderline( FontLineStyle::LINESTYLE_DOTTED
, RES_CHRATR_UNDERLINE
);
1130 aBoxAF
.SetUnderline( aUnderline
);
1132 SvxOverlineItem
aOverline( FontLineStyle::LINESTYLE_DASH
, RES_CHRATR_OVERLINE
);
1133 aBoxAF
.SetOverline( aOverline
);
1135 SvxCrossedOutItem
aCrossedOut( FontStrikeout::STRIKEOUT_BOLD
, RES_CHRATR_CROSSEDOUT
);
1136 aBoxAF
.SetCrossedOut( aCrossedOut
);
1138 SvxContourItem
aContour( true, RES_CHRATR_CONTOUR
);
1139 aBoxAF
.SetContour( aContour
);
1141 SvxShadowedItem
aShadowed( false, RES_CHRATR_SHADOWED
);
1142 aBoxAF
.SetShadowed( aShadowed
);
1144 SvxColorItem
aColor( Color(0xFF23FF), RES_CHRATR_COLOR
);
1145 aBoxAF
.SetColor( aColor
);
1147 SvxAdjustItem
aAdjust( SvxAdjust::Center
, RES_PARATR_ADJUST
);
1148 aBoxAF
.SetAdjust( aAdjust
);
1149 //SetTextOrientation
1150 SvxFrameDirectionItem
aTOrientation( SvxFrameDirection::Vertical_RL_TB
, RES_FRAMEDIR
);
1151 aBoxAF
.SetTextOrientation( aTOrientation
);
1152 //SetVerticalAlignment
1153 SwFormatVertOrient
aVAlignment( 3, css::text::VertOrientation::CENTER
, css::text::RelOrientation::PAGE_LEFT
);
1154 aBoxAF
.SetVerticalAlignment( aVAlignment
);
1156 SvxBoxItem
aBox( RES_BOX
);
1157 aBox
.SetAllDistances( 5 );
1158 aBoxAF
.SetBox( aBox
);
1160 SvxBrushItem
aBackground( Color(0xFF11FF), RES_BACKGROUND
);
1161 aBoxAF
.SetBackground( aBackground
);
1163 SvxLineItem
aTLBRLine(0); aTLBRLine
.ScaleMetrics( 11,12 );
1164 aBoxAF
.SetTLBR(aTLBRLine
);
1166 SvxLineItem
aBLTRLine(0); aBLTRLine
.ScaleMetrics( 13,14 );
1167 aBoxAF
.SetBLTR(aBLTRLine
);
1169 SvxHorJustifyItem
aHJustify( SvxCellHorJustify::Center
, 0 );
1170 aBoxAF
.SetHorJustify(aHJustify
);
1172 SvxVerJustifyItem
aVJustify( SvxCellVerJustify::Center
, 0 );
1173 aBoxAF
.SetVerJustify(aVJustify
);
1175 SfxBoolItem
aStacked(0, true);
1176 aBoxAF
.SetStacked(aStacked
);
1178 SvxMarginItem
aSvxMarginItem(sal_Int16(4), sal_Int16(2), sal_Int16(3), sal_Int16(3), TypedWhichId
<SvxMarginItem
>(0));
1179 aBoxAF
.SetMargin(aSvxMarginItem
);
1181 SfxBoolItem
aLBreak(0, true);
1182 aBoxAF
.SetLinebreak(aLBreak
);
1183 //Set m_aRotateAngle
1184 SfxInt32Item
aRAngle(sal_Int32(5));
1185 aBoxAF
.SetRotateAngle(aRAngle
);
1187 SvxRotateModeItem
aSvxRotateModeItem(SVX_ROTATE_MODE_CENTER
, TypedWhichId
<SvxRotateModeItem
>(0));
1188 aBoxAF
.SetRotateMode(aSvxRotateModeItem
);
1189 //Set m_sNumFormatString
1190 OUString aNFString
= u
"UnitTestFormat"_ustr
;
1191 aBoxAF
.SetNumFormatString(aNFString
);
1192 //Set m_eSysLanguage
1193 LanguageType
aSLang( LANGUAGE_ENGLISH_INDIA
);
1194 aBoxAF
.SetSysLanguage(aSLang
);
1195 //Set m_eNumFormatLanguage
1196 LanguageType
aNFLang( LANGUAGE_GERMAN
);
1197 aBoxAF
.SetNumFormatLanguage(aNFLang
);
1198 //Set m_aKeepWithNextPara
1199 SvxFormatKeepItem
aKWNPara( true, 0 );
1200 aTableAF
.SetKeepWithNextPara(aKWNPara
);
1201 //Set m_aRepeatHeading
1202 sal_uInt16 aRHeading
= 3;
1203 aTableAF
.m_aRepeatHeading
= aRHeading
;
1204 //Set m_bLayoutSplit
1205 bool aLSplit
= false;
1206 aTableAF
.m_bLayoutSplit
= aLSplit
;
1208 bool aRSplit
= false;
1209 aTableAF
.m_bRowSplit
= aRSplit
;
1210 //Set m_bCollapsingBorders
1211 bool aCBorders
= false;
1212 aTableAF
.m_bCollapsingBorders
= aCBorders
;
1214 SvxShadowItem
aShadow( 0, nullptr, 103, SvxShadowLocation::BottomLeft
);
1215 aTableAF
.SetShadow(aShadow
);
1217 bool aIFont
= false;
1218 aTableAF
.m_bInclFont
= aIFont
;
1220 bool aIJustify
= false;
1221 aTableAF
.m_bInclJustify
= aIJustify
;
1223 bool aIFrame
= false;
1224 aTableAF
.m_bInclFrame
= aIFrame
;
1225 //Set bInclBackground
1226 bool aIBackground
= false;
1227 aTableAF
.m_bInclBackground
= aIBackground
;
1228 //Set bInclValueFormat
1229 bool aIVFormat
= false;
1230 aTableAF
.m_bInclValueFormat
= aIVFormat
;
1232 //set the box format to AutoFormat
1233 aTableAF
.SetBoxFormat( aBoxAF
, sal_uInt8(0) );
1234 //add AutoFormat to AutoFormatTable
1235 aTableAFT
.AddAutoFormat( aTableAF
);
1237 //check the style size
1238 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT
.size() );
1240 //save the bInclFontstyles
1243 //check the style size after save
1244 CPPUNIT_ASSERT_EQUAL( size_t(2), aTableAFT
.size() );
1246 //create new AutoFormatTable
1247 SwTableAutoFormatTable aLoadTAFT
;
1249 //check the style size
1250 CPPUNIT_ASSERT_EQUAL( size_t(1), aLoadTAFT
.size() );
1252 //load the saved styles
1255 //check the style size after load
1256 CPPUNIT_ASSERT_EQUAL( size_t(2), aLoadTAFT
.size() );
1259 SwTableAutoFormat
* pLoadAF
= aLoadTAFT
.FindAutoFormat( u
"TestItemStyle" );
1260 CPPUNIT_ASSERT( pLoadAF
);
1262 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetFont() == aFont
) );
1264 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetHeight() == aHeight
) );
1266 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetWeight() == aWeight
) );
1268 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetPosture() == aPosture
) );
1270 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKFont() == aCJKFont
) );
1272 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKHeight() == aCJKHeight
) );
1274 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKWeight() == aCJKWeight
) );
1276 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCJKPosture() == aCJKPosture
) );
1278 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLFont() == aCTLFont
) );
1280 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLHeight() == aCTLHeight
) );
1282 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLWeight() == aCTLWeight
) );
1284 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCTLPosture() == aCTLPosture
) );
1286 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetUnderline() == aUnderline
) );
1288 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetOverline() == aOverline
) );
1290 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetCrossedOut() == aCrossedOut
) );
1292 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetContour() == aContour
) );
1294 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetShadowed() == aShadowed
) );
1296 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetColor() == aColor
) );
1298 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetAdjust() == aAdjust
) );
1299 //GetTextOrientation
1300 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetTextOrientation() == aTOrientation
) );
1301 //GetVerticalAlignment
1302 CPPUNIT_ASSERT (bool( pLoadAF
->GetBoxFormat(0).GetVerticalAlignment() == aVAlignment
) );
1304 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetBox() == aBox
) );
1306 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetBackground() == aBackground
) );
1308 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetTLBR() == aTLBRLine
) );
1310 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetBLTR() == aBLTRLine
) );
1312 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetHorJustify() == aHJustify
) );
1314 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetVerJustify() == aVJustify
) );
1316 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetStacked() == aStacked
) );
1318 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetMargin() == aSvxMarginItem
) );
1320 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetLinebreak() == aLBreak
) );
1321 //Get m_aRotateAngle
1322 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetRotateAngle() == aRAngle
) );
1324 //SvxRotateModeItem aRMode = aBoxAF.m_aRotateMode;GetRotateMode
1325 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetRotateMode() == aSvxRotateModeItem
) );
1326 //Get m_sNumFormatString
1327 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetNumFormatString() == aNFString
) );
1328 //Get m_eSysLanguage
1329 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetSysLanguage() == aSLang
) );
1330 //Get m_eNumFormatLanguage
1331 CPPUNIT_ASSERT( bool( pLoadAF
->GetBoxFormat(0).GetNumFormatLanguage() == aNFLang
) );
1332 //Get m_aKeepWithNextPara
1333 CPPUNIT_ASSERT( bool( pLoadAF
->GetKeepWithNextPara() == aKWNPara
) );
1334 //Get m_aRepeatHeading
1335 CPPUNIT_ASSERT( bool( pLoadAF
->m_aRepeatHeading
== aRHeading
) );
1336 //Get m_bLayoutSplit
1337 CPPUNIT_ASSERT( bool( pLoadAF
->m_bLayoutSplit
== aLSplit
) );
1339 CPPUNIT_ASSERT( bool( pLoadAF
->m_bRowSplit
== aRSplit
) );
1340 //Get m_bCollapsingBorders
1341 CPPUNIT_ASSERT( bool( pLoadAF
->m_bCollapsingBorders
== aCBorders
) );
1343 CPPUNIT_ASSERT( bool( pLoadAF
->GetShadow() == aShadow
) );
1345 CPPUNIT_ASSERT( bool( pLoadAF
->m_bInclFont
== aIFont
) );
1347 CPPUNIT_ASSERT( bool( pLoadAF
->m_bInclJustify
== aIJustify
) );
1349 CPPUNIT_ASSERT( bool( pLoadAF
->m_bInclFrame
== aIFrame
) );
1350 //Get bInclBackground
1351 CPPUNIT_ASSERT( bool( pLoadAF
->m_bInclBackground
== aIBackground
) );
1352 //Get bInclValueFormat
1353 CPPUNIT_ASSERT( bool( pLoadAF
->m_bInclValueFormat
== aIVFormat
) );
1357 translitTest(SwDoc
& rDoc
, const SwPaM
& rPaM
, TransliterationFlags
const nType
)
1359 utl::TransliterationWrapper
aTrans(
1360 ::comphelper::getProcessComponentContext(), nType
);
1361 rDoc
.getIDocumentContentOperations().TransliterateText(rPaM
, aTrans
);
1362 return rPaM
.GetText();
1365 void SwDocTest::testTransliterate()
1367 // just some simple test to see if it's totally broken
1368 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1370 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"foobar"_ustr
);
1372 aPaM
.GetPoint()->nContent
= 0;
1373 CPPUNIT_ASSERT_EQUAL(u
"foobar"_ustr
, aPaM
.GetText());
1375 CPPUNIT_ASSERT_EQUAL(u
"FOOBAR"_ustr
,
1376 translitTest(*m_pDoc
, aPaM
,
1377 TransliterationFlags::LOWERCASE_UPPERCASE
));
1378 CPPUNIT_ASSERT_EQUAL(u
"Foobar"_ustr
,
1379 translitTest(*m_pDoc
, aPaM
,
1380 TransliterationFlags::TITLE_CASE
));
1381 CPPUNIT_ASSERT_EQUAL(u
"fOOBAR"_ustr
,
1382 translitTest(*m_pDoc
, aPaM
,
1383 TransliterationFlags::TOGGLE_CASE
));
1384 CPPUNIT_ASSERT_EQUAL(u
"foobar"_ustr
,
1385 translitTest(*m_pDoc
, aPaM
,
1386 TransliterationFlags::UPPERCASE_LOWERCASE
));
1387 CPPUNIT_ASSERT_EQUAL(u
"Foobar"_ustr
,
1388 translitTest(*m_pDoc
, aPaM
,
1389 TransliterationFlags::SENTENCE_CASE
));
1390 CPPUNIT_ASSERT_EQUAL(u
"Foobar"_ustr
,
1391 translitTest(*m_pDoc
, aPaM
,
1392 TransliterationFlags::HIRAGANA_KATAKANA
));
1394 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1395 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"one (two) three"_ustr
);
1397 aPaM
.GetMark()->nContent
= 0;
1398 CPPUNIT_ASSERT_EQUAL(u
"One (Two) Three"_ustr
,
1399 translitTest(*m_pDoc
, aPaM
,
1400 TransliterationFlags::TITLE_CASE
));
1405 class SwTableFormulaTest
: public SwTableFormula
1407 SwTableNode
*m_pNode
;
1409 SwTableFormulaTest(const OUString
&rStr
, SwTableNode
*pNode
)
1410 : SwTableFormula(rStr
)
1413 m_eNmType
= INTRNL_NAME
;
1415 virtual const SwNode
* GetNodeOfFormula() const override
1422 //tdf#66353 Expression is faulty
1423 void SwDocTest::testFormulas()
1425 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1426 SwPosition
aPos(aIdx
);
1428 const SwTable
*pTable
= m_pDoc
->InsertTable(
1429 SwInsertTableOptions(SwInsertTableFlags::HeadlineNoBorder
, 0), aPos
, 1, 3, 0);
1430 SwTableNode
* pTableNode
= pTable
->GetTableNode();
1431 SwTableFormulaTest
aFormula(u
"<\x12-1,0>+<Table1.A1>"_ustr
, pTableNode
);
1433 aFormula
.PtrToBoxNm(pTable
);
1435 CPPUNIT_ASSERT_EQUAL(u
"<?>+<Table1.?>"_ustr
, aFormula
.GetFormula());
1437 // tdf#61228: Evaluating non-defined function should return an error
1438 SwCalc
aCalc(*m_pDoc
);
1439 SwSbxValue val
= aCalc
.Calculate(u
"foobar()"_ustr
);
1440 CPPUNIT_ASSERT(aCalc
.IsCalcError());
1441 CPPUNIT_ASSERT(val
.IsVoidValue());
1442 CPPUNIT_ASSERT(val
.IsDouble());
1443 CPPUNIT_ASSERT_EQUAL(DBL_MAX
, val
.GetDouble());
1444 // Evaluating non-defined variable should return 0 without an error
1445 val
= aCalc
.Calculate(u
"foobar"_ustr
);
1446 CPPUNIT_ASSERT(!aCalc
.IsCalcError());
1447 CPPUNIT_ASSERT(val
.IsVoidValue());
1448 CPPUNIT_ASSERT(val
.IsLong());
1449 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), val
.GetLong());
1452 void SwDocTest::testMarkMove()
1454 IDocumentMarkAccess
* pMarksAccess
= m_pDoc
->getIDocumentMarkAccess();
1457 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1459 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Paragraph 1"_ustr
);
1461 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->GetContentIndex();
1462 pMarksAccess
->makeMark(aPaM
, u
"Para1"_ustr
,
1463 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1465 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1466 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Paragraph 2"_ustr
);
1468 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->GetContentIndex();
1469 pMarksAccess
->makeMark(aPaM
, u
"Para2"_ustr
,
1470 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1472 m_pDoc
->getIDocumentContentOperations().AppendTextNode(*aPaM
.GetPoint());
1473 m_pDoc
->getIDocumentContentOperations().InsertString(aPaM
, u
"Paragraph 3"_ustr
);
1475 aPaM
.GetMark()->nContent
-= aPaM
.GetMark()->GetContentIndex();
1476 pMarksAccess
->makeMark(aPaM
, u
"Para3"_ustr
,
1477 IDocumentMarkAccess::MarkType::BOOKMARK
, sw::mark::InsertMode::New
);
1480 // join paragraph 2 and 3 and check
1482 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -2);
1483 SwTextNode
& rParaNode2
= dynamic_cast<SwTextNode
&>(aIdx
.GetNode());
1484 rParaNode2
.JoinNext();
1486 ::sw::mark::MarkBase
* pBM1
= *pMarksAccess
->findMark(u
"Para1"_ustr
);
1487 ::sw::mark::MarkBase
* pBM2
= *pMarksAccess
->findMark(u
"Para2"_ustr
);
1488 ::sw::mark::MarkBase
* pBM3
= *pMarksAccess
->findMark(u
"Para3"_ustr
);
1490 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM1
->GetMarkStart().GetContentIndex());
1491 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM1
->GetMarkEnd().GetContentIndex());
1492 CPPUNIT_ASSERT_EQUAL(
1493 pBM1
->GetMarkStart().GetNodeIndex(),
1494 pBM1
->GetMarkEnd().GetNodeIndex());
1496 CPPUNIT_ASSERT_EQUAL(sal_Int32(0) , pBM2
->GetMarkStart().GetContentIndex());
1497 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM2
->GetMarkEnd().GetContentIndex());
1498 CPPUNIT_ASSERT_EQUAL(
1499 pBM2
->GetMarkStart().GetNodeIndex(),
1500 pBM2
->GetMarkEnd().GetNodeIndex());
1502 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), pBM3
->GetMarkStart().GetContentIndex());
1503 CPPUNIT_ASSERT_EQUAL(sal_Int32(22), pBM3
->GetMarkEnd().GetContentIndex());
1504 CPPUNIT_ASSERT_EQUAL(
1505 pBM3
->GetMarkStart().GetNodeIndex(),
1506 pBM3
->GetMarkEnd().GetNodeIndex());
1508 CPPUNIT_ASSERT_EQUAL(
1509 pBM1
->GetMarkStart().GetNodeIndex()+1,
1510 pBM2
->GetMarkStart().GetNodeIndex());
1511 CPPUNIT_ASSERT_EQUAL(
1512 pBM2
->GetMarkStart().GetNodeIndex(),
1513 pBM3
->GetMarkStart().GetNodeIndex());
1517 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1518 SwPaM
aPaM(aIdx
, aIdx
, SwNodeOffset(-1));
1519 aPaM
.GetPoint()->nContent
+= 5;
1520 aPaM
.GetMark()->nContent
+= 6;
1521 m_pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPaM
);
1523 pBM1
= *pMarksAccess
->findMark(u
"Para1"_ustr
);
1524 pBM2
= *pMarksAccess
->findMark(u
"Para2"_ustr
);
1525 pBM3
= *pMarksAccess
->findMark(u
"Para3"_ustr
);
1527 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1
->GetMarkStart().GetContentIndex());
1528 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1
->GetMarkEnd().GetContentIndex());
1529 CPPUNIT_ASSERT_EQUAL(
1530 pBM1
->GetMarkStart().GetNodeIndex(),
1531 pBM1
->GetMarkEnd().GetNodeIndex());
1533 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2
->GetMarkStart().GetContentIndex());
1534 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM2
->GetMarkEnd().GetContentIndex());
1535 CPPUNIT_ASSERT_EQUAL(
1536 pBM2
->GetMarkStart().GetNodeIndex(),
1537 pBM2
->GetMarkEnd().GetNodeIndex());
1539 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), pBM3
->GetMarkStart().GetContentIndex());
1540 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), pBM3
->GetMarkEnd().GetContentIndex());
1541 CPPUNIT_ASSERT_EQUAL(
1542 pBM3
->GetMarkStart().GetNodeIndex(),
1543 pBM3
->GetMarkEnd().GetNodeIndex());
1545 CPPUNIT_ASSERT_EQUAL(
1546 pBM1
->GetMarkStart().GetNodeIndex(),
1547 pBM2
->GetMarkStart().GetNodeIndex());
1548 CPPUNIT_ASSERT_EQUAL(
1549 pBM2
->GetMarkStart().GetNodeIndex(),
1550 pBM3
->GetMarkStart().GetNodeIndex());
1552 // split the paragraph
1554 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1555 SwPosition
aPos(aIdx
);
1557 m_pDoc
->getIDocumentContentOperations().SplitNode(aPos
, false);
1559 pBM1
= *pMarksAccess
->findMark(u
"Para1"_ustr
);
1560 pBM2
= *pMarksAccess
->findMark(u
"Para2"_ustr
);
1561 pBM3
= *pMarksAccess
->findMark(u
"Para3"_ustr
);
1563 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pBM1
->GetMarkStart().GetContentIndex());
1564 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM1
->GetMarkEnd().GetContentIndex());
1565 CPPUNIT_ASSERT_EQUAL(
1566 pBM1
->GetMarkStart().GetNodeIndex(),
1567 pBM1
->GetMarkEnd().GetNodeIndex());
1569 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pBM2
->GetMarkStart().GetContentIndex());
1570 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM2
->GetMarkEnd().GetContentIndex());
1571 CPPUNIT_ASSERT_EQUAL(
1572 pBM2
->GetMarkStart().GetNodeIndex()+1,
1573 pBM2
->GetMarkEnd().GetNodeIndex());
1575 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pBM3
->GetMarkStart().GetContentIndex());
1576 CPPUNIT_ASSERT_EQUAL(sal_Int32(15), pBM3
->GetMarkEnd().GetContentIndex());
1577 CPPUNIT_ASSERT_EQUAL(
1578 pBM3
->GetMarkStart().GetNodeIndex(),
1579 pBM3
->GetMarkEnd().GetNodeIndex());
1581 CPPUNIT_ASSERT_EQUAL(
1582 pBM1
->GetMarkStart().GetNodeIndex(),
1583 pBM2
->GetMarkStart().GetNodeIndex());
1584 CPPUNIT_ASSERT_EQUAL(
1585 pBM2
->GetMarkEnd().GetNodeIndex(),
1586 pBM3
->GetMarkEnd().GetNodeIndex());
1591 struct TestRing
: public sw::Ring
<TestRing
>
1593 TestRing() : sw::Ring
<TestRing
>() {};
1595 { return GetNextInRing(); }
1597 { return GetPrevInRing(); }
1599 { return unique(); }
1603 void SwDocTest::testIntrusiveRing()
1605 TestRing aRing1
, aRing2
, aRing3
, aRing4
, aRing5
;
1606 std::vector
<TestRing
*> vRings
1614 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aRing1
.GetRingContainer().size());
1615 CPPUNIT_ASSERT(aRing1
.lonely());
1616 CPPUNIT_ASSERT(aRing2
.lonely());
1617 CPPUNIT_ASSERT(aRing3
.lonely());
1618 aRing2
.MoveTo(&aRing1
);
1619 aRing3
.MoveTo(&aRing1
);
1620 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing1
.GetRingContainer().size());
1621 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing2
.GetRingContainer().size());
1622 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRing3
.GetRingContainer().size());
1623 CPPUNIT_ASSERT(!aRing1
.lonely());
1624 CPPUNIT_ASSERT(!aRing2
.lonely());
1625 CPPUNIT_ASSERT(!aRing3
.lonely());
1626 aRing5
.MoveTo(&aRing4
);
1627 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), aRing4
.GetRingContainer().size());
1628 aRing4
.GetRingContainer().merge(aRing1
.GetRingContainer());
1629 for(TestRing
* pRing
: vRings
)
1631 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), pRing
->GetRingContainer().size());
1633 for(std::vector
<TestRing
*>::iterator ppRing
= vRings
.begin(); ppRing
!= vRings
.end(); ++ppRing
)
1635 std::vector
<TestRing
*>::iterator ppNext
= ppRing
+1;
1636 if(ppNext
==vRings
.end())
1637 ppNext
= vRings
.begin();
1638 CPPUNIT_ASSERT_EQUAL((*ppRing
)->GetNext(), *ppNext
);
1639 CPPUNIT_ASSERT_EQUAL((*ppNext
)->GetPrev(), *ppRing
);
1641 for(TestRing
& r
: aRing1
.GetRingContainer())
1643 TestRing
* pRing
= &r
;
1644 CPPUNIT_ASSERT(pRing
);
1646 const TestRing
* pConstRing
= &aRing1
;
1647 for(const TestRing
& r
: pConstRing
->GetRingContainer()) // this should fail without r being const
1649 const TestRing
* pRing
= &r
;
1650 CPPUNIT_ASSERT(pRing
);
1654 CPPUNIT_ASSERT_EQUAL(&foo
, bar
.GetNext());
1655 CPPUNIT_ASSERT_EQUAL(&foo
, bar
.GetPrev());
1656 CPPUNIT_ASSERT_EQUAL(&bar
, foo
.GetNext());
1657 CPPUNIT_ASSERT_EQUAL(&bar
, foo
.GetPrev());
1659 CPPUNIT_ASSERT_EQUAL(&bar
, bar
.GetNext());
1660 CPPUNIT_ASSERT_EQUAL(&bar
, bar
.GetPrev());
1661 CPPUNIT_ASSERT_EQUAL(&foo
, foo
.GetNext());
1662 CPPUNIT_ASSERT_EQUAL(&foo
, foo
.GetPrev());
1667 struct TestHint final
: SfxHint
{};
1668 struct TestModify
: sw::BroadcastingModify
1671 struct TestClient
: SwClient
1675 int m_nModifyChangedCount
;
1676 const SwModify
* m_pLastChangedModify
;
1677 TestClient() : m_nModifyCount(0), m_nNotifyCount(0), m_nModifyChangedCount(0), m_pLastChangedModify(nullptr) {};
1678 virtual void SwClientNotify(const SwModify
&, const SfxHint
& rHint
) override
1680 if(typeid(TestHint
) == typeid(rHint
))
1682 else if(dynamic_cast<const sw::LegacyModifyHint
*>(&rHint
))
1684 else if(dynamic_cast<const sw::AttrSetChangeHint
*>(&rHint
))
1686 else if(auto pModifyChangedHint
= dynamic_cast<const sw::ModifyChangedHint
*>(&rHint
))
1688 ++m_nModifyChangedCount
;
1689 m_pLastChangedModify
= pModifyChangedHint
->m_pNew
;
1693 struct OtherTestClient
: SwClient
1696 OtherTestClient() : m_nModifyCount(0) {};
1697 virtual void SwClientNotify(const SwModify
&, const SfxHint
& rHint
) override
1699 if(dynamic_cast<const sw::LegacyModifyHint
*>(&rHint
))
1701 else if(dynamic_cast<const sw::AttrSetChangeHint
*>(&rHint
))
1705 struct TestListener
: SvtListener
1708 TestListener() : m_nNotifyCount(0) {};
1709 virtual void Notify( const SfxHint
& ) override
1715 void SwDocTest::testClientModify()
1717 (void) OtherTestClient(); // avoid loplugin:unreffun
1719 TestClient aClient1
, aClient2
;
1720 OtherTestClient aOtherClient1
;
1721 // test client registration
1722 CPPUNIT_ASSERT(!aMod
.HasWriterListeners());
1723 CPPUNIT_ASSERT(!aMod
.HasOnlyOneListener());
1724 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient1
.GetRegisteredIn());
1725 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1726 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1728 CPPUNIT_ASSERT(aMod
.HasWriterListeners());
1729 CPPUNIT_ASSERT(aMod
.HasOnlyOneListener());
1731 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient1
.GetRegisteredIn());
1732 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
), aClient2
.GetRegisteredIn());
1733 CPPUNIT_ASSERT(aMod
.HasWriterListeners());
1734 CPPUNIT_ASSERT(!aMod
.HasOnlyOneListener());
1736 aMod
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1737 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nModifyCount
);
1738 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nModifyCount
);
1739 CPPUNIT_ASSERT_EQUAL(0,aClient1
.m_nNotifyCount
);
1740 CPPUNIT_ASSERT_EQUAL(0,aClient2
.m_nNotifyCount
);
1741 aMod
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1742 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1743 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1744 CPPUNIT_ASSERT_EQUAL(0,aClient1
.m_nNotifyCount
);
1745 CPPUNIT_ASSERT_EQUAL(0,aClient2
.m_nNotifyCount
);
1749 aMod
.CallSwClientNotify(aHint
);
1750 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1751 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1752 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nNotifyCount
);
1753 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nNotifyCount
);
1755 // test typed iteration
1756 CPPUNIT_ASSERT(typeid(aClient1
) != typeid(OtherTestClient
));
1758 SwIterator
<OtherTestClient
,SwModify
> aIter(aMod
);
1759 for(OtherTestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1760 CPPUNIT_ASSERT(false);
1764 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1765 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1767 CPPUNIT_ASSERT_EQUAL(2,pClient
->m_nModifyCount
);
1770 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1772 aMod
.Add(aOtherClient1
);
1773 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1
.m_nModifyCount
);
1776 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1777 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1779 CPPUNIT_ASSERT_EQUAL(2,pClient
->m_nModifyCount
);
1782 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1784 CPPUNIT_ASSERT_EQUAL(0,aOtherClient1
.m_nModifyCount
);
1785 aMod
.Remove(aOtherClient1
);
1786 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient1
.GetRegisteredIn());
1787 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(&aMod
),aClient2
.GetRegisteredIn());
1788 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aOtherClient1
.GetRegisteredIn());
1789 // test client self-deregistration during iteration
1792 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1793 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1795 aMod
.Remove(*pClient
);
1798 CPPUNIT_ASSERT_EQUAL(2,nCount
);
1800 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient1
.GetRegisteredIn());
1801 CPPUNIT_ASSERT_EQUAL(static_cast<SwModify
*>(nullptr),aClient2
.GetRegisteredIn());
1803 SwIterator
<TestClient
,SwModify
> aIter(aMod
);
1804 for(TestClient
* pClient
= aIter
.First(); pClient
; pClient
= aIter
.Next())
1806 CPPUNIT_ASSERT(false);
1809 aMod
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1810 CPPUNIT_ASSERT_EQUAL(2,aClient1
.m_nModifyCount
);
1811 CPPUNIT_ASSERT_EQUAL(2,aClient2
.m_nModifyCount
);
1812 CPPUNIT_ASSERT_EQUAL(1,aClient1
.m_nNotifyCount
);
1813 CPPUNIT_ASSERT_EQUAL(1,aClient2
.m_nNotifyCount
);
1815 void SwDocTest::testBroadcastingModify()
1817 sw::BroadcastingModify aMod
;
1819 TestListener aListener
;
1822 aListener
.StartListening(aMod
.GetNotifier());
1824 aMod
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
1825 CPPUNIT_ASSERT_EQUAL(1,aClient
.m_nModifyCount
);
1826 CPPUNIT_ASSERT_EQUAL(1,aClient
.m_nModifyCount
);
1827 CPPUNIT_ASSERT_EQUAL(1,aListener
.m_nNotifyCount
);
1829 void SwDocTest::testWriterMultiListener()
1833 sw::WriterMultiListener
aMulti(aClient
);
1834 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1835 aMulti
.StartListening(&aMod
);
1836 CPPUNIT_ASSERT(aMulti
.IsListeningTo(&aMod
));
1837 aMulti
.EndListeningAll();
1838 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1839 aMulti
.StartListening(&aMod
);
1840 aMulti
.EndListening(&aMod
);
1841 CPPUNIT_ASSERT(!aMulti
.IsListeningTo(&aMod
));
1842 int nPreDeathChangedCount
;
1844 TestModify aTempMod
;
1846 aMulti
.StartListening(&aTempMod
);
1847 nPreDeathChangedCount
= aClient
.m_nModifyChangedCount
;
1849 CPPUNIT_ASSERT(aMulti
.IsListeningTo(&aMod
));
1850 CPPUNIT_ASSERT_EQUAL(nPreDeathChangedCount
+1, aClient
.m_nModifyChangedCount
);
1851 CPPUNIT_ASSERT_EQUAL(static_cast<const SwModify
*>(&aMod
),aClient
.m_pLastChangedModify
);
1854 void SwDocTest::test64kPageDescs()
1856 size_t nPageDescCount
= 65536; // USHRT_MAX + 1
1858 for (size_t i
= 0; i
< nPageDescCount
; ++i
)
1860 OUString aName
= "Page" + OUString::number(i
);
1861 m_pDoc
->MakePageDesc( aName
);
1864 size_t nCount
= m_pDoc
->GetPageDescCnt();
1865 // +1 because Writer always creates a dummy page desc
1867 CPPUNIT_ASSERT_EQUAL( nPageDescCount
+ 1, nCount
);
1869 const SwPageDesc
&rDesc
= m_pDoc
->GetPageDesc( nPageDescCount
);
1870 SwPageDesc
&rZeroDesc
= m_pDoc
->GetPageDesc( 0 );
1871 CPPUNIT_ASSERT_EQUAL( u
"Page65535"_ustr
, rDesc
.GetName() );
1873 SwPageDesc
aDesc( rDesc
);
1874 static constexpr OUString
aChanged(u
"Changed01"_ustr
);
1875 aDesc
.SetName( aChanged
);
1876 m_pDoc
->ChgPageDesc( nPageDescCount
, aDesc
);
1879 SwPageDesc
*pDesc
= m_pDoc
->FindPageDesc( aChanged
, &nPos
);
1880 CPPUNIT_ASSERT( pDesc
!= nullptr );
1881 CPPUNIT_ASSERT_EQUAL( nPageDescCount
, nPos
);
1883 // check if we didn't mess up PageDesc at pos 0
1884 // (happens with 16bit int overflow)
1885 OUString aZeroName
= rZeroDesc
.GetName();
1886 rZeroDesc
= m_pDoc
->GetPageDesc( 0 );
1887 CPPUNIT_ASSERT_EQUAL( aZeroName
, rZeroDesc
.GetName() );
1889 m_pDoc
->DelPageDesc( aChanged
, /*bBroadcast*/true );
1890 pDesc
= m_pDoc
->FindPageDesc( aChanged
, &nPos
);
1891 // not there anymore
1892 CPPUNIT_ASSERT( !pDesc
);
1893 CPPUNIT_ASSERT_EQUAL( std::numeric_limits
<size_t>::max(), nPos
);
1895 // check if PageDesc at pos 0 is still there
1896 pDesc
= m_pDoc
->FindPageDesc( aZeroName
, &nPos
);
1897 CPPUNIT_ASSERT( pDesc
!= nullptr );
1898 CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(0), nPos
);
1901 void SwDocTest::testTdf92308()
1903 CPPUNIT_ASSERT_EQUAL(false, m_pDoc
->HasInvisibleContent());
1906 void SwDocTest::testTableCellComparison()
1908 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst(u
"A1", u
"Z1") );
1909 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u
"Z1", u
"A1") );
1910 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByColFirst(u
"A1", u
"A1") );
1912 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u
"A2", u
"A1") );
1913 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByColFirst(u
"Z3", u
"A2") );
1914 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByColFirst(u
"A3", u
"Z1") );
1916 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellsByRowFirst(u
"A1", u
"Z1") );
1917 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u
"Z1", u
"A1") );
1918 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellsByRowFirst(u
"A1", u
"A1") );
1920 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u
"A2", u
"A1") );
1921 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u
"Z3", u
"A2") );
1922 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellsByRowFirst(u
"A3", u
"Z1") );
1924 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u
"A1", u
"A1", u
"A1", u
"A1", true) );
1925 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u
"A1", u
"Z1", u
"A1", u
"Z1", true) );
1926 CPPUNIT_ASSERT_EQUAL( 0, sw_CompareCellRanges(u
"A1", u
"Z1", u
"A1", u
"Z1", false) );
1928 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u
"A1", u
"Z1", u
"B1", u
"Z1", true) );
1929 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u
"A1", u
"Z1", u
"A2", u
"Z2", false) );
1930 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u
"A1", u
"Z1", u
"A2", u
"Z2", true) );
1931 CPPUNIT_ASSERT_EQUAL( -1, sw_CompareCellRanges(u
"A1", u
"Z1", u
"A6", u
"Z2", true) );
1933 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u
"B1", u
"Z1", u
"A1", u
"Z1", true) );
1934 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u
"A2", u
"Z2", u
"A1", u
"Z1", false) );
1935 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u
"A2", u
"Z2", u
"A1", u
"Z1", true) );
1936 CPPUNIT_ASSERT_EQUAL( +1, sw_CompareCellRanges(u
"A6", u
"Z2", u
"A1", u
"Z1", true) );
1938 OUString
rCell1(u
"A1"_ustr
);
1939 OUString
rCell2(u
"C5"_ustr
);
1941 sw_NormalizeRange(rCell1
, rCell2
);
1942 CPPUNIT_ASSERT_EQUAL( u
"A1"_ustr
, rCell1
);
1943 CPPUNIT_ASSERT_EQUAL( u
"C5"_ustr
, rCell2
);
1945 sw_NormalizeRange(rCell2
, rCell1
);
1946 CPPUNIT_ASSERT_EQUAL( u
"C5"_ustr
, rCell1
);
1947 CPPUNIT_ASSERT_EQUAL( u
"A1"_ustr
, rCell2
);
1949 rCell1
= u
"A5"_ustr
;
1950 rCell2
= u
"C1"_ustr
;
1952 sw_NormalizeRange(rCell1
, rCell2
);
1953 CPPUNIT_ASSERT_EQUAL( u
"A1"_ustr
, rCell1
);
1954 CPPUNIT_ASSERT_EQUAL( u
"C5"_ustr
, rCell2
);
1956 sw_NormalizeRange(rCell2
, rCell1
);
1957 CPPUNIT_ASSERT_EQUAL( u
"C5"_ustr
, rCell1
);
1958 CPPUNIT_ASSERT_EQUAL( u
"A1"_ustr
, rCell2
);
1960 CPPUNIT_ASSERT_EQUAL( OUString(), sw_GetCellName(-1, -1) );
1963 void SwDocTest::setUp()
1965 BootstrapFixture::setUp();
1967 SwGlobals::ensure();
1969 m_xDocShRef
= new SwDocShell(*m_pDoc
, SfxObjectCreateMode::EMBEDDED
);
1970 m_xDocShRef
->DoInitNew();
1973 void SwDocTest::tearDown()
1975 m_pDoc
= nullptr; // deleted by DoClose()
1976 m_xDocShRef
->DoClose();
1977 m_xDocShRef
.clear();
1979 BootstrapFixture::tearDown();
1982 void SwDocTest::testTdf156211()
1985 oSI
.SetNoKashidaLine(TextFrameIndex
{ 89 }, TextFrameIndex
{ 95 });
1987 CPPUNIT_ASSERT(!oSI
.IsKashidaLine(TextFrameIndex
{ 95 }));
1989 oSI
.ClearNoKashidaLine(TextFrameIndex
{ 0 }, TextFrameIndex
{ 89 });
1991 CPPUNIT_ASSERT(!oSI
.IsKashidaLine(TextFrameIndex
{ 95 }));
1994 void SwDocTest::testFillRubyList()
1996 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
1999 SwTextNode
* pTextNode
= aPaM
.GetPointNode().GetTextNode();
2000 CPPUNIT_ASSERT(pTextNode
);
2002 auto& rOps
= m_pDoc
->getIDocumentContentOperations();
2004 auto fnAppendJapanese
= [&](const OUString
& rText
)
2006 rOps
.AppendTextNode(*aPaM
.GetPoint());
2008 SvxLanguageItem
aCJKLangItem(LANGUAGE_JAPANESE
, RES_CHRATR_CJK_LANGUAGE
);
2009 SvxLanguageItem
aWestLangItem(LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
2010 rOps
.InsertPoolItem(aPaM
, aCJKLangItem
);
2011 rOps
.InsertPoolItem(aPaM
, aWestLangItem
);
2013 rOps
.InsertString(aPaM
, rText
);
2016 aPaM
.GetPoint()->nContent
= 0;
2018 CPPUNIT_ASSERT_EQUAL(rText
, aPaM
.GetText());
2021 auto fnAppendRuby
= [](SwRubyList
* rList
, OUString aBase
, OUString aRuby
)
2023 auto pEnt
= std::make_unique
<SwRubyListEntry
>();
2024 pEnt
->SetText(std::move(aBase
));
2025 pEnt
->SetRubyAttr(SwFormatRuby
{ std::move(aRuby
) });
2027 rList
->push_back(std::move(pEnt
));
2030 auto fnGetCombinedString
= [](SwPaM
& rPaM
)
2033 SwDoc::FillRubyList(rPaM
, aRubies
);
2035 OUStringBuffer aTemp
;
2037 for (auto const& rRuby
: aRubies
)
2039 aTemp
.append(rRuby
->GetText() + u
"["_ustr
+ rRuby
->GetRubyAttr().GetText() + u
"]"_ustr
);
2042 return aTemp
.toString();
2045 // Single word without existing rubies
2047 fnAppendJapanese(u
"学校"_ustr
);
2048 CPPUNIT_ASSERT_EQUAL(u
"学校[]"_ustr
, fnGetCombinedString(aPaM
));
2051 // Compound word without existing rubies
2053 fnAppendJapanese(u
"自動販売機"_ustr
);
2054 CPPUNIT_ASSERT_EQUAL(u
"自動[]販売[]機[]"_ustr
, fnGetCombinedString(aPaM
));
2057 // Single word with existing rubies
2059 fnAppendJapanese(u
"学校"_ustr
);
2062 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2064 m_pDoc
->SetRubyList(aPaM
, rList
);
2066 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]"_ustr
, fnGetCombinedString(aPaM
));
2069 // Compound word with existing rubies
2071 fnAppendJapanese(u
"自動販売機"_ustr
);
2074 fnAppendRuby(&rList
, u
"自動"_ustr
, u
"じどう"_ustr
);
2075 fnAppendRuby(&rList
, u
"販売"_ustr
, u
"はんばい"_ustr
);
2076 fnAppendRuby(&rList
, u
"機"_ustr
, u
"き"_ustr
);
2078 m_pDoc
->SetRubyList(aPaM
, rList
);
2080 CPPUNIT_ASSERT_EQUAL(u
"自動[じどう]販売[はんばい]機[き]"_ustr
, fnGetCombinedString(aPaM
));
2083 // Compound word with existing rubies treated as a single word
2085 fnAppendJapanese(u
"自動販売機"_ustr
);
2088 fnAppendRuby(&rList
, u
"自動販売機"_ustr
, u
"じどうはんばいき"_ustr
);
2089 fnAppendRuby(&rList
, u
""_ustr
, u
""_ustr
);
2090 fnAppendRuby(&rList
, u
""_ustr
, u
""_ustr
);
2092 m_pDoc
->SetRubyList(aPaM
, rList
);
2094 CPPUNIT_ASSERT_EQUAL(u
"自動販売機[じどうはんばいき]"_ustr
, fnGetCombinedString(aPaM
));
2097 // tdf#141466: Characteristic test from bug
2099 fnAppendJapanese(u
"学校に行きます。"_ustr
);
2102 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2103 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2104 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2105 fnAppendRuby(&rList
, u
"きます"_ustr
, u
""_ustr
);
2106 fnAppendRuby(&rList
, u
"。"_ustr
, u
""_ustr
);
2108 m_pDoc
->SetRubyList(aPaM
, rList
);
2110 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に[]行[い]き[]ます[]。[]"_ustr
,
2111 fnGetCombinedString(aPaM
));
2114 // tdf#107184: Characteristic test for ruby group mode editing
2116 fnAppendJapanese(u
"学校に行きます"_ustr
);
2119 fnAppendRuby(&rList
, u
"学校に行きます"_ustr
, u
"がっこうにいきます"_ustr
);
2121 m_pDoc
->SetRubyList(aPaM
, rList
);
2123 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます[がっこうにいきます]"_ustr
, fnGetCombinedString(aPaM
));
2126 // tdf#156543: Characteristic test for ruby mono mode editing
2128 fnAppendJapanese(u
"学校に行きます"_ustr
);
2131 fnAppendRuby(&rList
, u
"学"_ustr
, u
"がっ"_ustr
);
2132 fnAppendRuby(&rList
, u
"校"_ustr
, u
"こう"_ustr
);
2133 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2134 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2135 fnAppendRuby(&rList
, u
"き"_ustr
, u
""_ustr
);
2136 fnAppendRuby(&rList
, u
"ま"_ustr
, u
""_ustr
);
2137 fnAppendRuby(&rList
, u
"す"_ustr
, u
""_ustr
);
2139 m_pDoc
->SetRubyList(aPaM
, rList
);
2141 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に[]行[い]き[]ます[]"_ustr
,
2142 fnGetCombinedString(aPaM
));
2145 // tdf#156543: Characteristic test for ruby mono mode editing
2147 fnAppendJapanese(u
"学校に行きます"_ustr
);
2150 fnAppendRuby(&rList
, u
"学"_ustr
, u
"がっ"_ustr
);
2151 fnAppendRuby(&rList
, u
"校"_ustr
, u
"こう"_ustr
);
2152 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2153 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2154 fnAppendRuby(&rList
, u
"き"_ustr
, u
""_ustr
);
2155 fnAppendRuby(&rList
, u
"ま"_ustr
, u
""_ustr
);
2156 fnAppendRuby(&rList
, u
"す"_ustr
, u
""_ustr
);
2158 m_pDoc
->SetRubyList(aPaM
, rList
);
2160 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に[]行[い]き[]ます[]"_ustr
,
2161 fnGetCombinedString(aPaM
));
2166 fnAppendJapanese(u
"学校に行こう。"_ustr
);
2168 SwPaM aAdjPaM
{ *aPaM
.GetPoint(), *aPaM
.GetMark() };
2169 aAdjPaM
.Normalize();
2170 aAdjPaM
.GetMark()->AdjustContent(-1);
2172 CPPUNIT_ASSERT_EQUAL(u
"学校[]に[]行[]こう[]"_ustr
, fnGetCombinedString(aAdjPaM
));
2177 fnAppendJapanese(u
"学校"_ustr
);
2181 CPPUNIT_ASSERT_EQUAL(u
"学校[]"_ustr
, fnGetCombinedString(aPaM
));
2185 void SwDocTest::testSetRubyList()
2187 SwNodeIndex
aIdx(m_pDoc
->GetNodes().GetEndOfContent(), -1);
2190 SwTextNode
* pTextNode
= aPaM
.GetPointNode().GetTextNode();
2191 CPPUNIT_ASSERT(pTextNode
);
2193 auto& rOps
= m_pDoc
->getIDocumentContentOperations();
2195 auto fnAppendJapanese
= [&](const OUString
& rText
)
2197 rOps
.AppendTextNode(*aPaM
.GetPoint());
2199 SvxLanguageItem
aCJKLangItem(LANGUAGE_JAPANESE
, RES_CHRATR_CJK_LANGUAGE
);
2200 SvxLanguageItem
aWestLangItem(LANGUAGE_ENGLISH_US
, RES_CHRATR_LANGUAGE
);
2201 rOps
.InsertPoolItem(aPaM
, aCJKLangItem
);
2202 rOps
.InsertPoolItem(aPaM
, aWestLangItem
);
2204 rOps
.InsertString(aPaM
, rText
);
2207 aPaM
.GetPoint()->nContent
= 0;
2209 CPPUNIT_ASSERT_EQUAL(rText
, aPaM
.GetText());
2212 auto fnAppendRuby
= [](SwRubyList
* rList
, OUString aBase
, OUString aRuby
)
2214 auto pEnt
= std::make_unique
<SwRubyListEntry
>();
2215 pEnt
->SetText(std::move(aBase
));
2216 pEnt
->SetRubyAttr(SwFormatRuby
{ std::move(aRuby
) });
2218 rList
->push_back(std::move(pEnt
));
2221 auto fnGetCombinedString
= [&]
2223 OUStringBuffer aTemp
;
2225 auto* pPos
= aPaM
.GetPoint();
2226 const auto* pTNd
= pPos
->GetNode().GetTextNode();
2227 const auto& rText
= pTNd
->GetText();
2228 const auto* pHts
= pTNd
->GetpSwpHints();
2230 for (sal_Int32 i
= 0; i
< rText
.getLength(); ++i
)
2232 aTemp
.append(rText
[i
]);
2236 for (size_t j
= 0; j
< pHts
->Count(); ++j
)
2238 const auto* pHt
= pHts
->Get(j
);
2239 if (pHt
->Which() == RES_TXTATR_CJK_RUBY
&& pHt
->GetAnyEnd() == (i
+ 1))
2241 aTemp
.append(u
"["_ustr
+ pHt
->GetRuby().GetText() + u
"]"_ustr
);
2247 return aTemp
.toString();
2250 // Trivial characteristic test
2252 fnAppendJapanese(u
"学校"_ustr
);
2255 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2257 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2258 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aPaM
.GetMark()->GetContentIndex());
2259 m_pDoc
->SetRubyList(aPaM
, rList
);
2260 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2261 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aPaM
.GetMark()->GetContentIndex());
2263 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]"_ustr
, fnGetCombinedString());
2265 // Operation should be idempotent
2266 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2267 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aPaM
.GetMark()->GetContentIndex());
2268 m_pDoc
->SetRubyList(aPaM
, rList
);
2269 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2270 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aPaM
.GetMark()->GetContentIndex());
2272 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]"_ustr
, fnGetCombinedString());
2275 // tdf#141466: Characteristic test from bug
2277 fnAppendJapanese(u
"学校に行きます。"_ustr
);
2280 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2281 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2282 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2283 fnAppendRuby(&rList
, u
"きます"_ustr
, u
""_ustr
);
2284 fnAppendRuby(&rList
, u
"。"_ustr
, u
""_ustr
);
2286 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2287 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2288 m_pDoc
->SetRubyList(aPaM
, rList
);
2289 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2290 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2292 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に行[い]きます。"_ustr
, fnGetCombinedString());
2294 // Operation should be idempotent
2295 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2296 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2297 m_pDoc
->SetRubyList(aPaM
, rList
);
2298 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2299 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2301 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に行[い]きます。"_ustr
, fnGetCombinedString());
2304 // Base text merging/deletion at end of selection
2306 fnAppendJapanese(u
"学校に行こう。"_ustr
);
2308 SwPaM aAdjPaM
{ *aPaM
.GetPoint(), *aPaM
.GetMark() };
2309 aAdjPaM
.GetPoint()->AdjustContent(-1);
2312 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2313 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2314 fnAppendRuby(&rList
, u
"行こう"_ustr
, u
"いこう"_ustr
);
2315 fnAppendRuby(&rList
, u
""_ustr
, u
""_ustr
);
2316 fnAppendRuby(&rList
, u
""_ustr
, u
"this ruby should not appear"_ustr
);
2317 fnAppendRuby(&rList
, u
""_ustr
, u
""_ustr
);
2319 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetPoint()->GetContentIndex());
2320 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetMark()->GetContentIndex());
2321 m_pDoc
->SetRubyList(aAdjPaM
, rList
);
2322 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2323 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2325 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に行こう[いこう]。"_ustr
, fnGetCombinedString());
2327 // Operation should be idempotent
2328 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2329 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2330 m_pDoc
->SetRubyList(aAdjPaM
, rList
);
2331 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2332 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2334 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に行こう[いこう]。"_ustr
, fnGetCombinedString());
2337 // Base text deletion
2339 fnAppendJapanese(u
"学校に行きます。"_ustr
);
2342 fnAppendRuby(&rList
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2343 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2344 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2345 fnAppendRuby(&rList
, u
"きます"_ustr
, u
""_ustr
);
2346 fnAppendRuby(&rList
, u
"。"_ustr
, u
""_ustr
);
2348 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2349 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2350 m_pDoc
->SetRubyList(aPaM
, rList
);
2351 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2352 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2354 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に行[い]きます。"_ustr
, fnGetCombinedString());
2357 fnAppendRuby(&rList2
, u
"学校"_ustr
, u
"がっこう"_ustr
);
2358 fnAppendRuby(&rList2
, u
"に"_ustr
, u
""_ustr
);
2359 fnAppendRuby(&rList2
, u
""_ustr
, u
"い"_ustr
);
2360 fnAppendRuby(&rList2
, u
"来"_ustr
, u
"き"_ustr
);
2361 fnAppendRuby(&rList2
, u
"ます"_ustr
, u
""_ustr
);
2362 fnAppendRuby(&rList2
, u
"。"_ustr
, u
""_ustr
);
2364 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2365 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPaM
.GetMark()->GetContentIndex());
2366 m_pDoc
->SetRubyList(aPaM
, rList2
);
2367 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2368 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2370 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に来[き]ます。"_ustr
, fnGetCombinedString());
2372 // Operation should be idempotent
2373 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2374 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2375 m_pDoc
->SetRubyList(aPaM
, rList2
);
2376 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2377 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2379 CPPUNIT_ASSERT_EQUAL(u
"学校[がっこう]に来[き]ます。"_ustr
, fnGetCombinedString());
2382 // tdf#107184: Characteristic test for ruby group mode editing
2384 fnAppendJapanese(u
"学校に行きます"_ustr
);
2387 fnAppendRuby(&rList
, u
"学校に行きます"_ustr
, u
"がっこうにいきます"_ustr
);
2389 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2390 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2391 m_pDoc
->SetRubyList(aPaM
, rList
);
2392 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2393 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2395 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます[がっこうにいきます]"_ustr
, fnGetCombinedString());
2397 // Operation should be idempotent
2398 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2399 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2400 m_pDoc
->SetRubyList(aPaM
, rList
);
2401 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2402 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2404 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます[がっこうにいきます]"_ustr
, fnGetCombinedString());
2407 // tdf#107184: Delete ruby in group mode after populating
2409 fnAppendJapanese(u
"学校に行きます"_ustr
);
2412 fnAppendRuby(&rList
, u
"学校に行きます"_ustr
, u
"がっこうにいきます"_ustr
);
2414 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2415 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2416 m_pDoc
->SetRubyList(aPaM
, rList
);
2417 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2418 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2420 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます[がっこうにいきます]"_ustr
, fnGetCombinedString());
2423 fnAppendRuby(&rList2
, u
"学校に行きます"_ustr
, u
""_ustr
);
2425 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2426 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2427 m_pDoc
->SetRubyList(aPaM
, rList2
);
2428 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2429 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2431 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます"_ustr
, fnGetCombinedString());
2433 // Operation should be idempotent
2434 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2435 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2436 m_pDoc
->SetRubyList(aPaM
, rList2
);
2437 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2438 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2440 CPPUNIT_ASSERT_EQUAL(u
"学校に行きます"_ustr
, fnGetCombinedString());
2443 // tdf#156543: Characteristic test for ruby mono mode editing
2445 fnAppendJapanese(u
"学校に行きます"_ustr
);
2448 fnAppendRuby(&rList
, u
"学"_ustr
, u
"がっ"_ustr
);
2449 fnAppendRuby(&rList
, u
"校"_ustr
, u
"こう"_ustr
);
2450 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2451 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2452 fnAppendRuby(&rList
, u
"き"_ustr
, u
""_ustr
);
2453 fnAppendRuby(&rList
, u
"ま"_ustr
, u
""_ustr
);
2454 fnAppendRuby(&rList
, u
"す"_ustr
, u
"す"_ustr
);
2456 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2457 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2458 m_pDoc
->SetRubyList(aPaM
, rList
);
2459 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2460 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2462 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に行[い]きます[す]"_ustr
, fnGetCombinedString());
2464 // Operation should be idempotent
2465 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2466 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2467 m_pDoc
->SetRubyList(aPaM
, rList
);
2468 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPaM
.GetPoint()->GetContentIndex());
2469 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aPaM
.GetMark()->GetContentIndex());
2471 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に行[い]きます[す]"_ustr
, fnGetCombinedString());
2474 // Offset PaM - Combination of insert and replace
2476 fnAppendJapanese(u
"学校員"_ustr
);
2478 SwPosition aNewPos
{ aPaM
.GetPoint()->nNode
, aPaM
.GetPoint()->nContent
};
2479 const SwTextNode
* pTNd
= aNewPos
.GetNode().GetTextNode();
2480 pTNd
->GoNext(aNewPos
, SwCursorSkipMode::Chars
);
2482 SwPaM aEmptyPaM
{ aNewPos
};
2483 aEmptyPaM
.SetMark();
2484 aEmptyPaM
.GetMark()->AdjustContent(1);
2487 fnAppendRuby(&rList
, u
"森林"_ustr
, u
"しんりん"_ustr
);
2488 fnAppendRuby(&rList
, u
"海上"_ustr
, u
"かいじょう"_ustr
);
2489 fnAppendRuby(&rList
, u
"地面"_ustr
, u
"じめん"_ustr
);
2491 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2492 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aEmptyPaM
.GetMark()->GetContentIndex());
2493 m_pDoc
->SetRubyList(aEmptyPaM
, rList
);
2494 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2495 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2497 CPPUNIT_ASSERT_EQUAL(u
"学森林[しんりん]海上[かいじょう]地面[じめん]員"_ustr
,
2498 fnGetCombinedString());
2500 // Operation should be idempotent
2501 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2502 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2503 m_pDoc
->SetRubyList(aEmptyPaM
, rList
);
2504 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2505 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2507 CPPUNIT_ASSERT_EQUAL(u
"学森林[しんりん]海上[かいじょう]地面[じめん]員"_ustr
,
2508 fnGetCombinedString());
2511 // Partial PaM with mono replacement
2513 fnAppendJapanese(u
"学校に行こう。"_ustr
);
2515 SwPaM aAdjPaM
{ *aPaM
.GetPoint(), *aPaM
.GetMark() };
2516 aAdjPaM
.Normalize();
2517 aAdjPaM
.GetMark()->AdjustContent(-1);
2520 fnAppendRuby(&rList
, u
"学"_ustr
, u
"がっ"_ustr
);
2521 fnAppendRuby(&rList
, u
"校"_ustr
, u
"こう"_ustr
);
2522 fnAppendRuby(&rList
, u
"に"_ustr
, u
""_ustr
);
2523 fnAppendRuby(&rList
, u
"行"_ustr
, u
"い"_ustr
);
2524 fnAppendRuby(&rList
, u
"こ"_ustr
, u
""_ustr
);
2525 fnAppendRuby(&rList
, u
"う"_ustr
, u
""_ustr
);
2527 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2528 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2529 m_pDoc
->SetRubyList(aAdjPaM
, rList
);
2530 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2531 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2533 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に行[い]こう。"_ustr
, fnGetCombinedString());
2535 // Operation should be idempotent
2536 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2537 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2538 m_pDoc
->SetRubyList(aAdjPaM
, rList
);
2539 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aAdjPaM
.GetPoint()->GetContentIndex());
2540 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aAdjPaM
.GetMark()->GetContentIndex());
2542 CPPUNIT_ASSERT_EQUAL(u
"学[がっ]校[こう]に行[い]こう。"_ustr
, fnGetCombinedString());
2545 // Empty PaM - Should insert
2547 fnAppendJapanese(u
"学校"_ustr
);
2549 SwPosition aNewPos
{ aPaM
.GetPoint()->nNode
, aPaM
.GetPoint()->nContent
};
2550 const SwTextNode
* pTNd
= aNewPos
.GetNode().GetTextNode();
2551 pTNd
->GoNext(aNewPos
, SwCursorSkipMode::Chars
);
2553 SwPaM aEmptyPaM
{ aNewPos
};
2554 aEmptyPaM
.SetMark();
2557 fnAppendRuby(&rList
, u
"森林"_ustr
, u
"しんりん"_ustr
);
2558 fnAppendRuby(&rList
, u
"海上"_ustr
, u
"かいじょう"_ustr
);
2559 fnAppendRuby(&rList
, u
"地面"_ustr
, u
"じめん"_ustr
);
2561 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2562 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetMark()->GetContentIndex());
2563 m_pDoc
->SetRubyList(aEmptyPaM
, rList
);
2564 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2565 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2567 CPPUNIT_ASSERT_EQUAL(u
"学森林[しんりん]海上[かいじょう]地面[じめん]校"_ustr
,
2568 fnGetCombinedString());
2570 // Operation should be idempotent
2571 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2572 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2573 m_pDoc
->SetRubyList(aEmptyPaM
, rList
);
2574 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEmptyPaM
.GetPoint()->GetContentIndex());
2575 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), aEmptyPaM
.GetMark()->GetContentIndex());
2577 CPPUNIT_ASSERT_EQUAL(u
"学森林[しんりん]海上[かいじょう]地面[じめん]校"_ustr
,
2578 fnGetCombinedString());
2582 CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest
);
2584 CPPUNIT_PLUGIN_IMPLEMENT();
2586 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */