Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <sal/config.h>
11 : #include <test/bootstrapfixture.hxx>
12 :
13 : #include <rtl/strbuf.hxx>
14 : #include <osl/file.hxx>
15 :
16 : #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
17 :
18 : #include <comphelper/processfactory.hxx>
19 : #include <comphelper/random.hxx>
20 : #include <tools/urlobj.hxx>
21 : #include <unotools/tempfile.hxx>
22 : #include <unotools/transliterationwrapper.hxx>
23 :
24 : #include <editeng/langitem.hxx>
25 : #include <editeng/charhiddenitem.hxx>
26 :
27 : #include <sfx2/app.hxx>
28 : #include <sfx2/docfilt.hxx>
29 : #include <sfx2/docfile.hxx>
30 : #include <sfx2/sfxmodelfactory.hxx>
31 :
32 : #include <xmloff/odffields.hxx>
33 :
34 : #include "breakit.hxx"
35 : #include "doc.hxx"
36 : #include <IDocumentRedlineAccess.hxx>
37 : #include <IDocumentFieldsAccess.hxx>
38 : #include <IDocumentStatistics.hxx>
39 : #include "cellfml.hxx"
40 : #include "docsh.hxx"
41 : #include "docstat.hxx"
42 : #include "docufld.hxx"
43 : #include "fmtanchr.hxx"
44 : #include "init.hxx"
45 : #include "ndtxt.hxx"
46 : #include "shellio.hxx"
47 : #include "shellres.hxx"
48 : #include "swcrsr.hxx"
49 : #include "swscanner.hxx"
50 : #include "swmodule.hxx"
51 : #include <swdll.hxx>
52 : #include "swtypes.hxx"
53 : #include "fmtftn.hxx"
54 : #include "fmtrfmrk.hxx"
55 : #include <fmtinfmt.hxx>
56 : #include <fchrfmt.hxx>
57 : #include "fmtfld.hxx"
58 : #include "redline.hxx"
59 : #include "docary.hxx"
60 : #include "modeltoviewhelper.hxx"
61 : #include "scriptinfo.hxx"
62 : #include "IMark.hxx"
63 : #include "ring.hxx"
64 : #include "calbck.hxx"
65 : #include "pagedesc.hxx"
66 :
67 : typedef tools::SvRef<SwDocShell> SwDocShellRef;
68 :
69 : using namespace ::com::sun::star;
70 :
71 : /* Implementation of Swdoc-Test class */
72 :
73 60 : class SwDocTest : public test::BootstrapFixture
74 : {
75 : public:
76 30 : SwDocTest()
77 30 : : m_pDoc(NULL)
78 : {
79 30 : }
80 :
81 : virtual void setUp() SAL_OVERRIDE;
82 : virtual void tearDown() SAL_OVERRIDE;
83 :
84 : void randomTest();
85 : void testPageDescName();
86 : void testFileNameFields();
87 : void testDocStat();
88 : void testModelToViewHelperPassthrough();
89 : void testModelToViewHelperExpandFieldsExpandFootnote();
90 : void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode();
91 : void testModelToViewHelperExpandFields();
92 : void testModelToViewHelperExpandFieldsReplaceMode();
93 : void testModelToViewHelperExpandFieldsHideInvisible();
94 : void testModelToViewHelperExpandFieldsHideRedlined();
95 : void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote();
96 : void testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode();
97 : void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote();
98 : void testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode();
99 : void testModelToViewHelperHideInvisibleHideRedlined();
100 : void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote();
101 : void testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode();
102 : void testModelToViewHelperExpandFieldsExpandFootnote2();
103 : void testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2();
104 : void testSwScanner();
105 : void testUserPerceivedCharCount();
106 : void testMergePortionsDeleteNotSorted();
107 : void testGraphicAnchorDeletion();
108 : void testTransliterate();
109 : void testMarkMove();
110 : void testFormulas();
111 : void testIntrusiveRing();
112 : void testClientModify();
113 : void test64kPageDescs();
114 :
115 2 : CPPUNIT_TEST_SUITE(SwDocTest);
116 :
117 1 : CPPUNIT_TEST(testTransliterate);
118 1 : CPPUNIT_TEST(randomTest);
119 1 : CPPUNIT_TEST(testPageDescName);
120 1 : CPPUNIT_TEST(testFileNameFields);
121 1 : CPPUNIT_TEST(testDocStat);
122 1 : CPPUNIT_TEST(testModelToViewHelperPassthrough);
123 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote);
124 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode);
125 1 : CPPUNIT_TEST(testModelToViewHelperExpandFields);
126 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsReplaceMode);
127 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisible);
128 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideRedlined);
129 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote);
130 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode);
131 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote);
132 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode);
133 1 : CPPUNIT_TEST(testModelToViewHelperHideInvisibleHideRedlined);
134 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote);
135 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode);
136 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnote2);
137 1 : CPPUNIT_TEST(testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2);
138 1 : CPPUNIT_TEST(testSwScanner);
139 1 : CPPUNIT_TEST(testUserPerceivedCharCount);
140 1 : CPPUNIT_TEST(testMergePortionsDeleteNotSorted);
141 1 : CPPUNIT_TEST(testGraphicAnchorDeletion);
142 1 : CPPUNIT_TEST(testMarkMove);
143 1 : CPPUNIT_TEST(testFormulas);
144 1 : CPPUNIT_TEST(testIntrusiveRing);
145 1 : CPPUNIT_TEST(testClientModify);
146 1 : CPPUNIT_TEST(test64kPageDescs);
147 5 : CPPUNIT_TEST_SUITE_END();
148 :
149 : private:
150 : SwDoc *m_pDoc;
151 : SwDocShellRef m_xDocShRef;
152 : };
153 :
154 1 : void SwDocTest::testPageDescName()
155 : {
156 1 : ShellResource aShellResources;
157 :
158 2 : std::vector<OUString> aResults;
159 :
160 : //These names must be unique for each different combination, otherwise
161 : //duplicate page description names may exist, which will causes lookup
162 : //by name to be incorrect, and so the corresponding export to .odt
163 1 : aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
164 1 : aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
165 1 : aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));
166 :
167 1 : std::sort(aResults.begin(), aResults.end());
168 1 : aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());
169 :
170 2 : CPPUNIT_ASSERT_MESSAGE("GetPageDescName results must be unique", aResults.size() == 3);
171 1 : }
172 :
173 : //See https://bugs.libreoffice.org/show_bug.cgi?id=32463
174 1 : void SwDocTest::testFileNameFields()
175 : {
176 : //Here's a file name with some chars in it that will be %% encoded, when expanding
177 : //SwFileNameFields we want to restore the original readable filename
178 1 : utl::TempFile aTempFile(OUString("demo [name]"));
179 1 : aTempFile.EnableKillingFile();
180 :
181 2 : INetURLObject aTempFileURL(aTempFile.GetURL());
182 2 : OUString sFileURL = aTempFileURL.GetMainURL(INetURLObject::NO_DECODE);
183 2 : SfxMedium aDstMed(sFileURL, STREAM_STD_READWRITE);
184 :
185 : SfxFilter aFilter(
186 : OUString("Text"),
187 : OUString(), SfxFilterFlags::NONE, SotClipboardFormatId::NONE, OUString(), 0, OUString(),
188 2 : OUString("TEXT"), OUString() );
189 1 : aDstMed.SetFilter(&aFilter);
190 :
191 1 : m_xDocShRef->DoSaveAs(aDstMed);
192 1 : m_xDocShRef->DoSaveCompleted(&aDstMed);
193 :
194 1 : const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();
195 :
196 2 : SwFileNameFieldType aNameField(m_pDoc);
197 :
198 : {
199 1 : OUString sResult(aNameField.Expand(FF_NAME));
200 : OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
201 2 : true,INetURLObject::DECODE_WITH_CHARSET));
202 2 : CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
203 : }
204 :
205 : {
206 1 : OUString sResult(aNameField.Expand(FF_PATHNAME));
207 2 : OUString sExpected(rUrlObj.GetFull());
208 2 : CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
209 : }
210 :
211 : {
212 1 : OUString sResult(aNameField.Expand(FF_PATH));
213 2 : INetURLObject aTemp(rUrlObj);
214 1 : aTemp.removeSegment();
215 2 : OUString sExpected(aTemp.PathToFileName());
216 2 : CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
217 : }
218 :
219 : {
220 1 : OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
221 : OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
222 2 : true,INetURLObject::DECODE_WITH_CHARSET));
223 : //Chop off .tmp
224 1 : sExpected = sExpected.copy(0, sExpected.getLength() - 4);
225 2 : CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
226 : }
227 :
228 2 : m_xDocShRef->DoInitNew(0);
229 1 : }
230 :
231 : //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
232 : //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
233 : //motivation
234 1 : void SwDocTest::testDocStat()
235 : {
236 1 : CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->getIDocumentStatistics().GetDocStat().nChar == 0);
237 :
238 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
239 2 : SwPaM aPaM(aIdx);
240 :
241 2 : OUString sText("Hello World");
242 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sText);
243 :
244 1 : CPPUNIT_ASSERT_MESSAGE("Should still be non-updated 0 count", m_pDoc->getIDocumentStatistics().GetDocStat().nChar == 0);
245 :
246 1 : SwDocStat aDocStat = m_pDoc->getIDocumentStatistics().GetUpdatedDocStat( false, true );
247 1 : sal_uLong nLen = static_cast<sal_uLong>(sText.getLength());
248 :
249 1 : CPPUNIT_ASSERT_MESSAGE("Should now have updated count", aDocStat.nChar == nLen);
250 :
251 2 : CPPUNIT_ASSERT_MESSAGE("And cache is updated too", m_pDoc->getIDocumentStatistics().GetDocStat().nChar == nLen);
252 1 : }
253 :
254 : //For UI character counts we should follow UAX#29 and display the user
255 : //perceived characters, not the number of codepoints, nor the number of code
256 : //units http://unicode.org/reports/tr29/
257 1 : void SwDocTest::testUserPerceivedCharCount()
258 : {
259 1 : SwBreakIt *pBreakIter = SwBreakIt::Get();
260 :
261 : //Grapheme example, two different unicode code-points perceived by the user as a single
262 : //glyph
263 1 : const sal_Unicode ALEF_QAMATS [] = { 0x05D0, 0x05B8 };
264 1 : OUString sALEF_QAMATS(ALEF_QAMATS, SAL_N_ELEMENTS(ALEF_QAMATS));
265 1 : sal_Int32 nGraphemeCount = pBreakIter->getGraphemeCount(sALEF_QAMATS);
266 1 : CPPUNIT_ASSERT_MESSAGE("Grapheme Count should be 1", nGraphemeCount == 1);
267 :
268 : //Surrogate pair example, one single unicode code-point (U+1D11E)
269 : //represented as two code units in UTF-16
270 1 : const sal_Unicode GCLEF[] = { 0xD834, 0xDD1E };
271 2 : OUString sGCLEF(GCLEF, SAL_N_ELEMENTS(GCLEF));
272 1 : sal_Int32 nCount = pBreakIter->getGraphemeCount(sGCLEF);
273 2 : CPPUNIT_ASSERT_MESSAGE("Surrogate Pair should be counted as single character", nCount == 1);
274 1 : }
275 :
276 16 : SwTextNode* getModelToViewTestDocument(SwDoc *pDoc)
277 : {
278 16 : SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
279 32 : SwPaM aPaM(aIdx);
280 :
281 32 : SwFormatFootnote aFootnote;
282 16 : aFootnote.SetNumStr(OUString("foo"));
283 :
284 16 : pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
285 16 : pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("AAAAA BBBBB "));
286 16 : SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
287 16 : sal_Int32 nPos = aPaM.GetPoint()->nContent.GetIndex();
288 16 : pTextNode->InsertItem(aFootnote, nPos, nPos);
289 16 : pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(" CCCCC "));
290 16 : nPos = aPaM.GetPoint()->nContent.GetIndex();
291 16 : pTextNode->InsertItem(aFootnote, nPos, nPos);
292 16 : pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(" DDDDD"));
293 16 : CPPUNIT_ASSERT(pTextNode->GetText().getLength() == (4*5) + 5 + 2);
294 :
295 : //set start of selection to first B
296 16 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 6);
297 16 : aPaM.SetMark();
298 : //set end of selection to last C
299 16 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 14);
300 : //set character attribute hidden on range
301 32 : SvxCharHiddenItem aHidden(true, RES_CHRATR_HIDDEN);
302 16 : pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aHidden );
303 16 : aPaM.DeleteMark();
304 :
305 : //turn on red-lining and show changes
306 16 : pDoc->getIDocumentRedlineAccess().SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
307 16 : CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn());
308 16 : CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineMode()));
309 :
310 : //set start of selection to last A
311 16 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 4);
312 16 : aPaM.SetMark();
313 : //set end of selection to second last B
314 16 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 9);
315 16 : pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM); //redline-aware deletion api
316 16 : aPaM.DeleteMark();
317 :
318 32 : return pTextNode;
319 : }
320 :
321 2 : SwTextNode* getModelToViewTestDocument2(SwDoc *pDoc)
322 : {
323 2 : SwTextNode* pTextNode = getModelToViewTestDocument(pDoc);
324 :
325 2 : SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
326 4 : SwPaM aPaM(aIdx);
327 :
328 2 : pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
329 2 : pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("AAAAA"));
330 2 : IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
331 : sw::mark::IFieldmark *pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(
332 2 : pMarksAccess->makeNoTextFieldBookmark(aPaM, "test", ODF_FORMDROPDOWN));
333 2 : CPPUNIT_ASSERT(pFieldmark);
334 4 : uno::Sequence< OUString > vListEntries(1);
335 2 : vListEntries[0] = "BBBBB";
336 2 : (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY] = uno::makeAny(vListEntries);
337 2 : (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] = uno::makeAny(sal_Int32(0));
338 2 : pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("CCCCC"));
339 2 : pTextNode = aPaM.GetNode().GetTextNode();
340 4 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11),
341 2 : pTextNode->GetText().getLength());
342 :
343 4 : return pTextNode;
344 : }
345 :
346 1 : void SwDocTest::testModelToViewHelperPassthrough()
347 : {
348 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
349 :
350 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::PassThrough);
351 2 : OUString sViewText = aModelToViewHelper.getViewText();
352 2 : OUString sModelText = pTextNode->GetText();
353 2 : CPPUNIT_ASSERT_EQUAL(sModelText, sViewText);
354 1 : }
355 :
356 1 : void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote()
357 : {
358 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
359 :
360 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields | ExpandMode::ExpandFootnote);
361 2 : OUString sViewText = aModelToViewHelper.getViewText();
362 2 : CPPUNIT_ASSERT_EQUAL(
363 2 : OUString("AAAAA BBBBB foo CCCCC foo DDDDD"), sViewText);
364 1 : }
365 :
366 1 : void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode()
367 : {
368 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
369 :
370 : ModelToViewHelper aModelToViewHelper(*pTextNode,
371 1 : ExpandMode::ExpandFields | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
372 2 : OUString sViewText = aModelToViewHelper.getViewText();
373 2 : CPPUNIT_ASSERT_EQUAL(
374 : OUString("AAAAA BBBBB " + OUString(CHAR_ZWSP) + " CCCCC " + OUString(CHAR_ZWSP) + " DDDDD"),
375 1 : sViewText);
376 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
377 1 : aModelToViewHelper.getFootnotePositions().size());
378 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12),
379 1 : aModelToViewHelper.getFootnotePositions()[0]);
380 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(20),
381 1 : aModelToViewHelper.getFootnotePositions()[1]);
382 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
383 2 : aModelToViewHelper.getFieldPositions().size());
384 1 : }
385 :
386 1 : void SwDocTest::testModelToViewHelperExpandFields()
387 : {
388 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
389 :
390 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields);
391 2 : OUString sViewText = aModelToViewHelper.getViewText();
392 2 : CPPUNIT_ASSERT_EQUAL(
393 2 : OUString("AAAAA BBBBB CCCCC DDDDD"), sViewText);
394 1 : }
395 :
396 1 : void SwDocTest::testModelToViewHelperExpandFieldsReplaceMode()
397 : {
398 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
399 :
400 : ModelToViewHelper aModelToViewHelper(*pTextNode,
401 1 : ExpandMode::ExpandFields | ExpandMode::ReplaceMode);
402 2 : OUString sViewText = aModelToViewHelper.getViewText();
403 2 : CPPUNIT_ASSERT_EQUAL(OUString("AAAAA BBBBB CCCCC DDDDD"),
404 1 : sViewText);
405 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
406 1 : aModelToViewHelper.getFootnotePositions().size());
407 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
408 2 : aModelToViewHelper.getFieldPositions().size());
409 1 : }
410 :
411 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideInvisible()
412 : {
413 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
414 :
415 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::HideInvisible);
416 2 : OUString sViewText = aModelToViewHelper.getViewText();
417 2 : CPPUNIT_ASSERT_EQUAL(
418 : OUString("AAAAA CCCCC " + OUStringLiteral1<CH_TXTATR_BREAKWORD>() + " DDDDD"),
419 2 : sViewText);
420 1 : }
421 :
422 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideRedlined()
423 : {
424 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
425 :
426 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::HideDeletions);
427 2 : OUString sViewText = aModelToViewHelper.getViewText();
428 2 : CPPUNIT_ASSERT_EQUAL(
429 : OUString("AAAABB " + OUStringLiteral1<CH_TXTATR_BREAKWORD>() + " CCCCC " + OUStringLiteral1<CH_TXTATR_BREAKWORD>() + " DDDDD"),
430 2 : sViewText);
431 1 : }
432 :
433 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnote()
434 : {
435 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
436 :
437 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::ExpandFootnote);
438 2 : OUString sViewText = aModelToViewHelper.getViewText();
439 2 : CPPUNIT_ASSERT_EQUAL(OUString("AAAAA CCCCC foo DDDDD"), sViewText);
440 1 : }
441 :
442 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleExpandFootnoteReplaceMode()
443 : {
444 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
445 :
446 : ModelToViewHelper aModelToViewHelper(*pTextNode,
447 1 : ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
448 2 : OUString sViewText = aModelToViewHelper.getViewText();
449 2 : CPPUNIT_ASSERT_EQUAL(
450 : OUString("AAAAA CCCCC " + OUString(CHAR_ZWSP) + " DDDDD"),
451 1 : sViewText);
452 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
453 1 : aModelToViewHelper.getFootnotePositions().size());
454 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12),
455 1 : aModelToViewHelper.getFootnotePositions()[0]);
456 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
457 2 : aModelToViewHelper.getFieldPositions().size());
458 1 : }
459 :
460 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnote()
461 : {
462 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
463 :
464 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote);
465 2 : OUString sViewText = aModelToViewHelper.getViewText();
466 2 : CPPUNIT_ASSERT_EQUAL(
467 2 : OUString("AAAABB foo CCCCC foo DDDDD"), sViewText);
468 1 : }
469 :
470 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideHideRedlinedExpandFootnoteReplaceMode()
471 : {
472 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
473 :
474 : ModelToViewHelper aModelToViewHelper(*pTextNode,
475 1 : ExpandMode::ExpandFields | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
476 2 : OUString sViewText = aModelToViewHelper.getViewText();
477 2 : CPPUNIT_ASSERT_EQUAL(
478 : OUString("AAAABB " + OUString(CHAR_ZWSP) + " CCCCC " + OUString(CHAR_ZWSP) + " DDDDD"),
479 1 : sViewText);
480 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2),
481 1 : aModelToViewHelper.getFootnotePositions().size());
482 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(7),
483 1 : aModelToViewHelper.getFootnotePositions()[0]);
484 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(15),
485 1 : aModelToViewHelper.getFootnotePositions()[1]);
486 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
487 2 : aModelToViewHelper.getFieldPositions().size());
488 1 : }
489 :
490 1 : void SwDocTest::testModelToViewHelperHideInvisibleHideRedlined()
491 : {
492 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
493 :
494 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::HideInvisible | ExpandMode::HideDeletions);
495 2 : OUString sViewText = aModelToViewHelper.getViewText();
496 2 : OUStringBuffer aBuffer;
497 1 : aBuffer.append("AAAACCCCC ");
498 1 : aBuffer.append(CH_TXTATR_BREAKWORD);
499 1 : aBuffer.append(" DDDDD");
500 2 : CPPUNIT_ASSERT_EQUAL(aBuffer.makeStringAndClear(), sViewText);
501 1 : }
502 :
503 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnote()
504 : {
505 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
506 :
507 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote);
508 2 : OUString sViewText = aModelToViewHelper.getViewText();
509 2 : CPPUNIT_ASSERT_EQUAL(OUString("AAAACCCCC foo DDDDD"), sViewText);
510 1 : }
511 :
512 1 : void SwDocTest::testModelToViewHelperExpandFieldsHideInvisibleHideRedlinedExpandFootnoteReplaceMode()
513 : {
514 1 : SwTextNode* pTextNode = getModelToViewTestDocument(m_pDoc);
515 :
516 : ModelToViewHelper aModelToViewHelper(*pTextNode,
517 1 : ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::HideDeletions | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
518 2 : OUString sViewText = aModelToViewHelper.getViewText();
519 2 : CPPUNIT_ASSERT_EQUAL(sViewText,
520 1 : OUString("AAAACCCCC " + OUString(CHAR_ZWSP) + " DDDDD"));
521 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
522 1 : aModelToViewHelper.getFootnotePositions().size());
523 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(10),
524 1 : aModelToViewHelper.getFootnotePositions()[0]);
525 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
526 2 : aModelToViewHelper.getFieldPositions().size());
527 1 : }
528 :
529 1 : void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnote2()
530 : {
531 1 : SwTextNode* pTextNode = getModelToViewTestDocument2(m_pDoc);
532 :
533 1 : ModelToViewHelper aModelToViewHelper(*pTextNode, ExpandMode::ExpandFields | ExpandMode::ExpandFootnote);
534 2 : OUString sViewText = aModelToViewHelper.getViewText();
535 2 : CPPUNIT_ASSERT_EQUAL(OUString("AAAAABBBBBCCCCC"), sViewText);
536 1 : }
537 :
538 1 : void SwDocTest::testModelToViewHelperExpandFieldsExpandFootnoteReplaceMode2()
539 : {
540 1 : SwTextNode* pTextNode = getModelToViewTestDocument2(m_pDoc);
541 :
542 : ModelToViewHelper aModelToViewHelper(*pTextNode,
543 1 : ExpandMode::ExpandFields | ExpandMode::ExpandFootnote | ExpandMode::ReplaceMode);
544 2 : OUString sViewText = aModelToViewHelper.getViewText();
545 2 : CPPUNIT_ASSERT_EQUAL(
546 : OUString("AAAAA" + OUString(CHAR_ZWSP) + "CCCCC"),
547 1 : sViewText);
548 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0),
549 1 : aModelToViewHelper.getFootnotePositions().size());
550 2 : CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1),
551 1 : aModelToViewHelper.getFieldPositions().size());
552 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5),
553 2 : aModelToViewHelper.getFieldPositions()[0]);
554 1 : }
555 :
556 1 : void SwDocTest::testSwScanner()
557 : {
558 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
559 2 : SwPaM aPaM(aIdx);
560 :
561 1 : SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
562 :
563 1 : CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTextNode);
564 :
565 : //See https://bugs.libreoffice.org/show_bug.cgi?id=40449
566 : //See https://bugs.libreoffice.org/show_bug.cgi?id=39365
567 : //Use a temporary OUString as the arg, as that's the trouble behind
568 : //fdo#40449 and fdo#39365
569 : {
570 : SwScanner aScanner(*pTextNode,
571 : OUString("Hello World"),
572 : 0, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD, 0,
573 1 : RTL_CONSTASCII_LENGTH("Hello World"));
574 :
575 1 : bool bFirstOk = aScanner.NextWord();
576 1 : CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk);
577 1 : const OUString &rHello = aScanner.GetWord();
578 2 : CPPUNIT_ASSERT_MESSAGE("Should be Hello",
579 1 : rHello == "Hello");
580 :
581 1 : bool bSecondOk = aScanner.NextWord();
582 1 : CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk);
583 1 : const OUString &rWorld = aScanner.GetWord();
584 2 : CPPUNIT_ASSERT_MESSAGE("Should be World",
585 2 : rWorld == "World");
586 : }
587 :
588 : //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
589 : {
590 1 : const sal_Unicode IDEOGRAPHICFULLSTOP_D[] = { 0x3002, 'D' };
591 :
592 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(IDEOGRAPHICFULLSTOP_D,
593 1 : SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D)));
594 :
595 1 : SvxLanguageItem aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED, RES_CHRATR_CJK_LANGUAGE );
596 2 : SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
597 1 : m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aCJKLangItem );
598 1 : m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aWestLangItem );
599 :
600 1 : SwDocStat aDocStat;
601 1 : pTextNode = aPaM.GetNode().GetTextNode();
602 1 : pTextNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D));
603 :
604 1 : CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nChar == 2);
605 2 : CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nCharExcludingSpaces == 2);
606 : }
607 : {
608 : const sal_Unicode test[] =
609 : {
610 : 0x3053, 0x306E, 0x65E5, 0x672C, 0x8A9E, 0x306F, 0x6B63, 0x3057,
611 : 0x304F, 0x6570, 0x3048, 0x3089, 0x308C, 0x308B, 0x3067, 0x3057,
612 : 0x3087, 0x3046, 0x304B, 0x3002, 0x0041, 0x006E, 0x0064, 0x0020,
613 : 0x006C, 0x0065, 0x0074, 0x0027, 0x0073, 0x0020, 0x0074, 0x0068,
614 : 0x0072, 0x006F, 0x0077, 0x0020, 0x0073, 0x006F, 0x006D, 0x0065,
615 : 0x0020, 0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068,
616 : 0x0020, 0x0069, 0x006E, 0x0020, 0x0074, 0x006F, 0x0020, 0x006D,
617 : 0x0061, 0x006B, 0x0065, 0x0020, 0x0069, 0x0074, 0x0020, 0x0069,
618 : 0x006E, 0x0074, 0x0065, 0x0072, 0x0065, 0x0073, 0x0074, 0x0069,
619 : 0x006E, 0x0067, 0x002E, 0x0020, 0x0020, 0x305D, 0x3057, 0x3066,
620 : 0x3001, 0x307E, 0x305F, 0x65E5, 0x672C, 0x8A9E, 0x3000, 0x3000,
621 : 0x3067, 0x3082, 0x4ECA, 0x56DE, 0x306F, 0x7A7A, 0x767D, 0x3092,
622 : 0x3000, 0x3000, 0x5165, 0x308C, 0x307E, 0x3057, 0x305F, 0x3002,
623 : 0x0020, 0x0020, 0x0053, 0x006F, 0x0020, 0x0068, 0x006F, 0x0077,
624 : 0x0020, 0x0064, 0x006F, 0x0065, 0x0073, 0x0020, 0x0074, 0x0068,
625 : 0x0069, 0x0073, 0x0020, 0x0064, 0x006F, 0x003F, 0x0020, 0x0020
626 1 : };
627 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
628 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(test,
629 1 : SAL_N_ELEMENTS(test)));
630 :
631 1 : SvxLanguageItem aCJKLangItem( LANGUAGE_JAPANESE, RES_CHRATR_CJK_LANGUAGE );
632 2 : SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
633 1 : m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aCJKLangItem );
634 1 : m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, aWestLangItem );
635 :
636 1 : SwDocStat aDocStat;
637 1 : pTextNode = aPaM.GetNode().GetTextNode();
638 1 : pTextNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(test));
639 1 : CPPUNIT_ASSERT_MESSAGE("58 words", aDocStat.nWord == 58);
640 1 : CPPUNIT_ASSERT_MESSAGE("43 Asian characters and Korean syllables", aDocStat.nAsianWord == 43);
641 1 : CPPUNIT_ASSERT_MESSAGE("105 non-whitespace chars", aDocStat.nCharExcludingSpaces == 105);
642 2 : CPPUNIT_ASSERT_MESSAGE("128 characters", aDocStat.nChar == 128);
643 : }
644 :
645 : //See https://bz.apache.org/ooo/show_bug.cgi?id=89042
646 : //See https://bugs.libreoffice.org/show_bug.cgi?id=53399
647 : {
648 1 : SwDocStat aDocStat;
649 :
650 : const sal_Unicode aShouldBeThree[] = {
651 : 0x0053, 0x0068, 0x006F, 0x0075, 0x006C, 0x0064, 0x0020,
652 : 0x2018, 0x0062, 0x0065, 0x0020, 0x0074, 0x0068, 0x0072,
653 : 0x0065, 0x0065, 0x2019
654 1 : };
655 :
656 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
657 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(aShouldBeThree, SAL_N_ELEMENTS(aShouldBeThree)));
658 1 : pTextNode = aPaM.GetNode().GetTextNode();
659 1 : pTextNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeThree));
660 1 : CPPUNIT_ASSERT_MESSAGE("Should be 3", aDocStat.nWord == 3);
661 :
662 : const sal_Unicode aShouldBeFive[] = {
663 : // f r e n c h space
664 : 0x0046, 0x0072, 0x0065, 0x006E, 0x0063, 0x0068, 0x0020,
665 : // << nbsp s a v o i
666 : 0x00AB, 0x00A0, 0x0073, 0x0061, 0x0076, 0x006F, 0x0069,
667 : // r nnbsp c a l c u
668 : 0x0072, 0x202f, 0x0063, 0x0061, 0x006C, 0x0063, 0x0075,
669 : // l e r idspace >>
670 : 0x006C, 0x0065, 0x0072, 0x3000, 0x00BB
671 1 : };
672 :
673 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
674 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(aShouldBeFive, SAL_N_ELEMENTS(aShouldBeFive)));
675 1 : pTextNode = aPaM.GetNode().GetTextNode();
676 1 : aDocStat.Reset();
677 1 : pTextNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeFive));
678 1 : CPPUNIT_ASSERT_MESSAGE("Should be 5", aDocStat.nWord == 5);
679 : }
680 :
681 : //See https://bugs.libreoffice.org/show_bug.cgi?id=49629
682 : {
683 1 : SwDocStat aDocStat;
684 :
685 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
686 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Apple"));
687 1 : pTextNode = aPaM.GetNode().GetTextNode();
688 1 : sal_Int32 nPos = aPaM.GetPoint()->nContent.GetIndex();
689 1 : SwFormatFootnote aFootnote;
690 1 : aFootnote.SetNumStr(OUString("banana"));
691 1 : SwTextAttr* pTA = pTextNode->InsertItem(aFootnote, nPos, nPos);
692 1 : CPPUNIT_ASSERT(pTA);
693 1 : CPPUNIT_ASSERT(pTextNode->Len() == 6); //Apple + 0x02
694 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
695 1 : CPPUNIT_ASSERT(aDocStat.nWord == 1);
696 1 : CPPUNIT_ASSERT_MESSAGE("footnote should be expanded", aDocStat.nChar == 11);
697 :
698 1 : const sal_Int32 nNextPos = aPaM.GetPoint()->nContent.GetIndex();
699 1 : CPPUNIT_ASSERT(nNextPos == nPos+1);
700 2 : SwFormatRefMark aRef(OUString("refmark"));
701 1 : pTA = pTextNode->InsertItem(aRef, nNextPos, nNextPos);
702 1 : CPPUNIT_ASSERT(pTA);
703 :
704 1 : aDocStat.Reset();
705 1 : pTextNode->SetWordCountDirty(true);
706 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
707 1 : CPPUNIT_ASSERT(aDocStat.nWord == 1);
708 1 : CPPUNIT_ASSERT_MESSAGE("refmark anchor should not be counted", aDocStat.nChar == 11);
709 :
710 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
711 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Apple"));
712 :
713 1 : DateTime aDate(DateTime::SYSTEM);
714 : SwPostItField aPostIt(
715 1 : static_cast<SwPostItFieldType*>(m_pDoc->getIDocumentFieldsAccess().GetSysFieldType(RES_POSTITFLD)), OUString("An Author"),
716 3 : OUString("Some Text"), OUString("Initials"), OUString("Name"), aDate );
717 1 : m_pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, SwFormatField(aPostIt));
718 :
719 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Apple"));
720 1 : pTextNode = aPaM.GetNode().GetTextNode();
721 1 : aDocStat.Reset();
722 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
723 1 : CPPUNIT_ASSERT(aDocStat.nWord == 1);
724 1 : CPPUNIT_ASSERT_MESSAGE("postit anchor should effectively not exist", aDocStat.nChar == 10);
725 1 : CPPUNIT_ASSERT(pTextNode->Len() == 11);
726 :
727 2 : aDocStat.Reset();
728 : }
729 :
730 : //See https://bugs.libreoffice.org/show_bug.cgi?id=46757
731 : {
732 1 : SwDocStat aDocStat;
733 :
734 1 : const char aString[] = "Lorem ipsum";
735 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
736 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(aString));
737 1 : pTextNode = aPaM.GetNode().GetTextNode();
738 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
739 1 : CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(2));
740 :
741 : //turn on red-lining and show changes
742 1 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
743 1 : CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->getIDocumentRedlineAccess().IsRedlineOn());
744 1 : CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->getIDocumentRedlineAccess().GetRedlineMode()));
745 :
746 : //delete everything except the first word
747 1 : aPaM.SetMark(); //set start of selection to current pos
748 1 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 5); //set end of selection to fifth char of current node
749 1 : m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM); //redline-aware deletion api
750 : //"real underlying text should be the same"
751 1 : CPPUNIT_ASSERT_EQUAL(pTextNode->GetText(), OUString(aString));
752 :
753 1 : aDocStat.Reset();
754 1 : pTextNode->SetWordCountDirty(true);
755 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //but word-counting the text should only count the non-deleted text
756 1 : CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(1));
757 :
758 1 : pTextNode->SetWordCountDirty(true);
759 :
760 : //keep red-lining on but hide changes
761 1 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode(nsRedlineMode_t::REDLINE_ON);
762 1 : CPPUNIT_ASSERT_MESSAGE("redlining should be still on", m_pDoc->getIDocumentRedlineAccess().IsRedlineOn());
763 1 : CPPUNIT_ASSERT_MESSAGE("redlines should be invisible", !IDocumentRedlineAccess::IsShowChanges(m_pDoc->getIDocumentRedlineAccess().GetRedlineMode()));
764 :
765 1 : aDocStat.Reset();
766 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //but word-counting the text should only count the non-deleted text
767 1 : CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(1));
768 :
769 1 : OUString sLorem = pTextNode->GetText();
770 1 : CPPUNIT_ASSERT(sLorem == "Lorem");
771 :
772 1 : const SwRedlineTable& rTable = m_pDoc->getIDocumentRedlineAccess().GetRedlineTable();
773 :
774 1 : SwNodes& rNds = m_pDoc->GetNodes();
775 1 : CPPUNIT_ASSERT(rTable.size() == 1);
776 :
777 1 : SwNodeIndex* pNodeIdx = rTable[0]->GetContentIdx();
778 1 : CPPUNIT_ASSERT(pNodeIdx);
779 :
780 1 : pTextNode = rNds[ pNodeIdx->GetIndex() + 1 ]->GetTextNode(); //first deleted txtnode
781 1 : CPPUNIT_ASSERT(pTextNode);
782 :
783 2 : OUString sIpsum = pTextNode->GetText();
784 1 : CPPUNIT_ASSERT(sIpsum == " ipsum");
785 :
786 1 : aDocStat.Reset();
787 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len()); //word-counting the text should only count the non-deleted text, and this whole chunk should be ignored
788 1 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(0), aDocStat.nWord);
789 1 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(0), aDocStat.nChar);
790 :
791 : // https://bugs.libreoffice.org/show_bug.cgi?id=68347 we do want to count
792 : // redline *added* text though
793 1 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
794 1 : aPaM.DeleteMark();
795 1 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 0);
796 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, "redline-new-text ");
797 1 : aDocStat.Reset();
798 1 : pTextNode = aPaM.GetNode().GetTextNode();
799 1 : pTextNode->SetWordCountDirty(true);
800 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
801 1 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(2), aDocStat.nWord);
802 : //redline-new-text Lorem ipsum
803 : //+++++++++++++++++ ------
804 : //select start of original text and part of deleted text
805 1 : aDocStat.Reset();
806 1 : pTextNode->CountWords(aDocStat, 17, 25);
807 2 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(5), aDocStat.nChar);
808 : }
809 :
810 : //See https://bugs.libreoffice.org/show_bug.cgi?id=38983
811 : {
812 1 : SwDocStat aDocStat;
813 :
814 1 : OUString sTemplate("ThisXis a test.");
815 :
816 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
817 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', ' '));
818 1 : pTextNode = aPaM.GetNode().GetTextNode();
819 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
820 2 : CPPUNIT_ASSERT(aDocStat.nWord == 4 &&
821 : aDocStat.nCharExcludingSpaces == 12 &&
822 1 : aDocStat.nChar == 15);
823 1 : aDocStat.Reset();
824 :
825 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
826 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll(OUString('X'), OUString(" = ")));
827 1 : pTextNode = aPaM.GetNode().GetTextNode();
828 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
829 2 : CPPUNIT_ASSERT(aDocStat.nWord == 5 &&
830 : aDocStat.nCharExcludingSpaces == 13 &&
831 1 : aDocStat.nChar == 17);
832 1 : aDocStat.Reset();
833 :
834 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
835 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll(OUString('X'), OUString(" _ ")));
836 1 : pTextNode = aPaM.GetNode().GetTextNode();
837 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
838 2 : CPPUNIT_ASSERT(aDocStat.nWord == 5 &&
839 : aDocStat.nCharExcludingSpaces == 13 &&
840 1 : aDocStat.nChar == 17);
841 1 : aDocStat.Reset();
842 :
843 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
844 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll(OUString('X'), OUString(" -- ")));
845 1 : pTextNode = aPaM.GetNode().GetTextNode();
846 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
847 2 : CPPUNIT_ASSERT(aDocStat.nWord == 5 &&
848 : aDocStat.nCharExcludingSpaces == 14 &&
849 1 : aDocStat.nChar == 18);
850 1 : aDocStat.Reset();
851 :
852 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
853 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', '_'));
854 1 : pTextNode = aPaM.GetNode().GetTextNode();
855 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
856 2 : CPPUNIT_ASSERT(aDocStat.nWord == 3 &&
857 : aDocStat.nCharExcludingSpaces == 13 &&
858 1 : aDocStat.nChar == 15);
859 1 : aDocStat.Reset();
860 :
861 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
862 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', '-'));
863 1 : pTextNode = aPaM.GetNode().GetTextNode();
864 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
865 2 : CPPUNIT_ASSERT(aDocStat.nWord == 3 &&
866 : aDocStat.nCharExcludingSpaces == 13 &&
867 1 : aDocStat.nChar == 15);
868 1 : aDocStat.Reset();
869 :
870 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
871 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2012));
872 1 : pTextNode = aPaM.GetNode().GetTextNode();
873 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
874 2 : CPPUNIT_ASSERT(aDocStat.nWord == 3 &&
875 : aDocStat.nCharExcludingSpaces == 13 &&
876 1 : aDocStat.nChar == 15);
877 1 : aDocStat.Reset();
878 :
879 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
880 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2015));
881 1 : pTextNode = aPaM.GetNode().GetTextNode();
882 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
883 2 : CPPUNIT_ASSERT(aDocStat.nWord == 3 &&
884 : aDocStat.nCharExcludingSpaces == 13 &&
885 1 : aDocStat.nChar == 15);
886 1 : aDocStat.Reset();
887 :
888 : //But default configuration should, msword-alike treak emdash
889 : //and endash as word separators for word-counting
890 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
891 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2013));
892 1 : pTextNode = aPaM.GetNode().GetTextNode();
893 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
894 2 : CPPUNIT_ASSERT(aDocStat.nWord == 4 &&
895 : aDocStat.nCharExcludingSpaces == 13 &&
896 1 : aDocStat.nChar == 15);
897 1 : aDocStat.Reset();
898 :
899 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
900 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replace('X', 0x2014));
901 1 : pTextNode = aPaM.GetNode().GetTextNode();
902 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
903 2 : CPPUNIT_ASSERT(aDocStat.nWord == 4 &&
904 : aDocStat.nCharExcludingSpaces == 13 &&
905 1 : aDocStat.nChar == 15);
906 1 : aDocStat.Reset();
907 :
908 1 : const sal_Unicode aChunk[] = {' ', 0x2013, ' '};
909 2 : OUString sChunk(aChunk, SAL_N_ELEMENTS(aChunk));
910 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
911 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, sTemplate.replaceAll(OUString('X'), sChunk));
912 1 : pTextNode = aPaM.GetNode().GetTextNode();
913 1 : pTextNode->CountWords(aDocStat, 0, pTextNode->Len());
914 2 : CPPUNIT_ASSERT(aDocStat.nWord == 4 &&
915 : aDocStat.nCharExcludingSpaces == 13 &&
916 1 : aDocStat.nChar == 17);
917 2 : aDocStat.Reset();
918 1 : }
919 1 : }
920 :
921 1 : void SwDocTest::testMergePortionsDeleteNotSorted()
922 : {
923 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
924 2 : SwPaM aPaM(aIdx);
925 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(" AABBCC"));
926 :
927 1 : SwCharFormat *const pCharFormat(m_pDoc->MakeCharFormat("foo", 0));
928 2 : SwFormatCharFormat const charFormat(pCharFormat);
929 :
930 2 : SwFormatINetFormat const inetFormat("http://example.com", "");
931 :
932 1 : IDocumentContentOperations & rIDCO(m_pDoc->getIDocumentContentOperations());
933 1 : aPaM.SetMark();
934 1 : aPaM.GetPoint()->nContent = 2;
935 1 : aPaM.GetMark()->nContent = 4;
936 1 : rIDCO.InsertPoolItem(aPaM, charFormat);
937 1 : aPaM.GetPoint()->nContent = 2;
938 1 : aPaM.GetMark()->nContent = 5;
939 1 : rIDCO.InsertPoolItem(aPaM, inetFormat);
940 1 : aPaM.GetPoint()->nContent = 6;
941 1 : aPaM.GetMark()->nContent = 8;
942 1 : rIDCO.InsertPoolItem(aPaM, charFormat);
943 1 : aPaM.GetPoint()->nContent = 4;
944 1 : aPaM.GetMark()->nContent = 6;
945 : // this triggered an STL assert in SwpHints::MergePortions()
946 2 : rIDCO.InsertPoolItem(aPaM, charFormat);
947 1 : }
948 :
949 : //See https://bugs.libreoffice.org/show_bug.cgi?id=40599
950 1 : void SwDocTest::testGraphicAnchorDeletion()
951 : {
952 1 : CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->getIDocumentStatistics().GetDocStat().nChar == 0);
953 :
954 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
955 2 : SwPaM aPaM(aIdx);
956 :
957 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Paragraph 1"));
958 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
959 :
960 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("graphic anchor>><<graphic anchor"));
961 2 : SwNodeIndex nPara2 = aPaM.GetPoint()->nNode;
962 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
963 :
964 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Paragraph 3"));
965 :
966 1 : aPaM.GetPoint()->nNode = nPara2;
967 1 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), RTL_CONSTASCII_LENGTH("graphic anchor>>"));
968 :
969 : //Insert a graphic at X of >>X<< in paragraph 2
970 2 : SfxItemSet aFlySet(m_pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
971 2 : SwFormatAnchor aAnchor(FLY_AS_CHAR);
972 1 : aAnchor.SetAnchor(aPaM.GetPoint());
973 1 : aFlySet.Put(aAnchor);
974 1 : SwFlyFrameFormat *pFrame = m_pDoc->getIDocumentContentOperations().Insert(aPaM, OUString(), OUString(), NULL, &aFlySet, NULL, NULL);
975 1 : CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame != NULL);
976 :
977 1 : CPPUNIT_ASSERT_MESSAGE("Should be 1 graphic", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 1);
978 :
979 : //Delete >X<
980 1 : aPaM.GetPoint()->nNode = nPara2;
981 2 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(),
982 3 : RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
983 1 : aPaM.SetMark();
984 1 : aPaM.GetPoint()->nNode = nPara2;
985 1 : aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), RTL_CONSTASCII_LENGTH("graphic anchor>"));
986 1 : m_pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
987 :
988 : #ifdef DEBUG_AS_HTML
989 : {
990 : SvFileStream aPasteDebug(OUString("cppunitDEBUG.html"), StreamMode::WRITE|StreamMode::TRUNC);
991 : WriterRef xWrt;
992 : GetHTMLWriter( String(), String(), xWrt );
993 : SwWriter aDbgWrt( aPasteDebug, *m_pDoc );
994 : aDbgWrt.Write( xWrt );
995 : }
996 : #endif
997 :
998 2 : CPPUNIT_ASSERT_MESSAGE("Should be 0 graphics", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 0);
999 :
1000 : //Now, if instead we swap FLY_AS_CHAR (inline graphic) to FLY_AT_CHAR (anchored to character)
1001 : //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
1002 : //range to which its anchored, which is annoying.
1003 1 : }
1004 :
1005 : static int
1006 36624 : getRand(int modulus)
1007 : {
1008 36624 : if (modulus <= 0)
1009 0 : return 0;
1010 36624 : return comphelper::rng::uniform_int_distribution(0, modulus-1);
1011 : }
1012 :
1013 : static OUString
1014 4079 : getRandString()
1015 : {
1016 4079 : OUString aText("AAAAA BBBB CCC DD E \n");
1017 4079 : int s = getRand(aText.getLength());
1018 4079 : int j = getRand(aText.getLength() - s);
1019 4079 : OUString aRet(aText.copy(s, j));
1020 4079 : if (!getRand(5))
1021 828 : aRet += OUString('\n');
1022 : // fprintf (stderr, "rand string '%s'\n", OUStringToOString(aRet, RTL_TEXTENCODING_UTF8).getStr());
1023 4079 : return aRet;
1024 : }
1025 :
1026 : static SwPosition
1027 18552 : getRandomPosition(SwDoc *pDoc, int /* nOffset */)
1028 : {
1029 18552 : const SwPosition aPos(pDoc->GetNodes().GetEndOfContent());
1030 18552 : size_t nNodes = aPos.nNode.GetNode().GetIndex() - aPos.nNode.GetNode().StartOfSectionIndex();
1031 18552 : size_t n = comphelper::rng::uniform_size_distribution(0, nNodes);
1032 37104 : SwPaM pam(aPos);
1033 37207 : for (sal_uLong i = 0; i < n; ++i)
1034 : {
1035 18655 : pam.Move(fnMoveBackward, fnGoNode);
1036 : }
1037 37104 : return *pam.GetPoint();
1038 : }
1039 :
1040 1 : void SwDocTest::randomTest()
1041 : {
1042 1 : CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1043 : RedlineMode_t modes[] = {
1044 : nsRedlineMode_t::REDLINE_ON,
1045 : nsRedlineMode_t::REDLINE_SHOW_MASK,
1046 : nsRedlineMode_t::REDLINE_NONE,
1047 : nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_MASK,
1048 : nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE,
1049 : nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE | nsRedlineMode_t::REDLINE_SHOW_MASK,
1050 : nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT,
1051 : nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE
1052 1 : };
1053 : static const char *authors[] = {
1054 : "Jim", "Bob", "JimBobina", "Helga", "Gertrude", "Spagna", "Hurtleweed"
1055 : };
1056 :
1057 9 : for( size_t rlm = 0; rlm < SAL_N_ELEMENTS(modes); rlm++ )
1058 : {
1059 8 : m_pDoc->ClearDoc();
1060 :
1061 : // setup redlining
1062 8 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode(modes[rlm]);
1063 8 : SW_MOD()->SetRedlineAuthor(OUString::createFromAscii(authors[0]));
1064 :
1065 16008 : for( int i = 0; i < 2000; i++ )
1066 : {
1067 16000 : SwPaM aPam(m_pDoc->GetNodes());
1068 32000 : SwCursor aCrs(getRandomPosition(m_pDoc, i/20), 0, false);
1069 16000 : aCrs.SetMark();
1070 :
1071 16000 : switch (getRand (i < 50 ? 3 : 6)) {
1072 : // insert ops first
1073 : case 0: {
1074 2783 : if (!m_pDoc->getIDocumentContentOperations().InsertString(aCrs, getRandString())) {
1075 : // fprintf (stderr, "failed to insert string !\n");
1076 : }
1077 2783 : break;
1078 : }
1079 : case 1:
1080 2709 : break;
1081 : case 2: { // switch author
1082 2799 : int a = getRand(SAL_N_ELEMENTS(authors));
1083 2799 : SW_MOD()->SetRedlineAuthor(OUString::createFromAscii(authors[a]));
1084 2799 : break;
1085 : }
1086 :
1087 : // movement / deletion ops later
1088 : case 3: // deletion
1089 2585 : switch (getRand(6)) {
1090 : case 0:
1091 434 : m_pDoc->getIDocumentContentOperations().DelFullPara(aCrs);
1092 434 : break;
1093 : case 1:
1094 404 : m_pDoc->getIDocumentContentOperations().DeleteRange(aCrs);
1095 404 : break;
1096 : case 2:
1097 451 : m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aCrs, !!getRand(1));
1098 451 : break;
1099 : case 3:
1100 : default:
1101 1296 : m_pDoc->getIDocumentContentOperations().Overwrite(aCrs, getRandString());
1102 1296 : break;
1103 : }
1104 2585 : break;
1105 : case 4: { // movement
1106 : SwMoveFlags nFlags =
1107 2552 : getRand(1) // FIXME: puterb this more ?
1108 : ? SwMoveFlags::DEFAULT
1109 : : SwMoveFlags::ALLFLYS |
1110 : SwMoveFlags::CREATEUNDOOBJ |
1111 7656 : SwMoveFlags::REDLINES |
1112 5104 : SwMoveFlags::NO_DELFRMS;
1113 2552 : SwPosition aTo(getRandomPosition(m_pDoc, i/10));
1114 2552 : m_pDoc->getIDocumentContentOperations().MoveRange(aCrs, aTo, nFlags);
1115 2552 : break;
1116 : }
1117 :
1118 : case 5:
1119 2572 : break;
1120 :
1121 : // undo / redo ?
1122 : default:
1123 0 : break;
1124 : }
1125 16000 : }
1126 :
1127 : // Debug / verify the produced document has real content
1128 : #if 0
1129 : OStringBuffer aBuffer("nodes-");
1130 : aBuffer.append(sal_Int32(rlm));
1131 : aBuffer.append(".xml");
1132 :
1133 : xmlTextWriterPtr writer;
1134 : writer = xmlNewTextWriterFilename( aBuffer.makeStringAndClear().getStr(), 0 );
1135 : xmlTextWriterStartDocument( writer, NULL, NULL, NULL );
1136 : m_pDoc->dumpAsXml(writer);
1137 : xmlTextWriterEndDocument( writer );
1138 : xmlFreeTextWriter( writer );
1139 : #endif
1140 : }
1141 1 : }
1142 :
1143 : static OUString
1144 6 : translitTest(SwDoc & rDoc, SwPaM & rPaM, sal_uInt32 const nType)
1145 : {
1146 : utl::TransliterationWrapper aTrans(
1147 6 : ::comphelper::getProcessComponentContext(), nType);
1148 6 : rDoc.getIDocumentContentOperations().TransliterateText(rPaM, aTrans);
1149 6 : return rPaM.GetText();
1150 : }
1151 :
1152 1 : void SwDocTest::testTransliterate()
1153 : {
1154 : // just some simple test to see if it's totally broken
1155 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1156 2 : SwPaM aPaM(aIdx);
1157 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("foobar"));
1158 1 : aPaM.SetMark();
1159 1 : aPaM.GetPoint()->nContent = 0;
1160 1 : CPPUNIT_ASSERT_EQUAL(OUString("foobar"), aPaM.GetText());
1161 :
1162 2 : CPPUNIT_ASSERT_EQUAL(OUString("FOOBAR"),
1163 : translitTest(*m_pDoc, aPaM,
1164 1 : i18n::TransliterationModules_LOWERCASE_UPPERCASE));
1165 2 : CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1166 : translitTest(*m_pDoc, aPaM,
1167 1 : i18n::TransliterationModulesExtra::TITLE_CASE));
1168 2 : CPPUNIT_ASSERT_EQUAL(OUString("fOOBAR"),
1169 : translitTest(*m_pDoc, aPaM,
1170 1 : i18n::TransliterationModulesExtra::TOGGLE_CASE));
1171 2 : CPPUNIT_ASSERT_EQUAL(OUString("foobar"),
1172 : translitTest(*m_pDoc, aPaM,
1173 1 : i18n::TransliterationModules_UPPERCASE_LOWERCASE));
1174 2 : CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1175 : translitTest(*m_pDoc, aPaM,
1176 1 : i18n::TransliterationModulesExtra::SENTENCE_CASE));
1177 2 : CPPUNIT_ASSERT_EQUAL(OUString("Foobar"),
1178 : translitTest(*m_pDoc, aPaM,
1179 2 : i18n::TransliterationModules_HIRAGANA_KATAKANA));
1180 1 : }
1181 :
1182 : namespace
1183 : {
1184 1 : class SwTableFormulaTest : public SwTableFormula
1185 : {
1186 : SwTableNode *m_pNode;
1187 : public:
1188 1 : SwTableFormulaTest(const OUString &rStr, SwTableNode *pNode)
1189 : : SwTableFormula(rStr)
1190 1 : , m_pNode(pNode)
1191 : {
1192 1 : m_eNmType = INTRNL_NAME;
1193 1 : }
1194 0 : virtual const SwNode* GetNodeOfFormula() const SAL_OVERRIDE
1195 : {
1196 0 : return m_pNode;
1197 : }
1198 : };
1199 : }
1200 :
1201 : //tdf#66353 Expression is faulty
1202 1 : void SwDocTest::testFormulas()
1203 : {
1204 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1205 2 : SwPosition aPos(aIdx);
1206 :
1207 : const SwTable *pTable = m_pDoc->InsertTable(
1208 1 : SwInsertTableOptions(tabopts::HEADLINE_NO_BORDER, 0), aPos, 1, 3, 0);
1209 1 : SwTableNode* pTableNode = pTable->GetTableNode();
1210 2 : SwTableFormulaTest aFormula("<\x12-1,0>+<Table1.A1>", pTableNode);
1211 :
1212 1 : aFormula.PtrToBoxNm(pTable);
1213 :
1214 2 : CPPUNIT_ASSERT_EQUAL(OUString("<?>+<Table1.?>"), aFormula.GetFormula());
1215 1 : }
1216 :
1217 1 : void SwDocTest::testMarkMove()
1218 : {
1219 1 : IDocumentMarkAccess* pMarksAccess = m_pDoc->getIDocumentMarkAccess();
1220 :
1221 : {
1222 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1223 2 : SwPaM aPaM(aIdx);
1224 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Paragraph 1"));
1225 1 : aPaM.SetMark();
1226 1 : aPaM.GetMark()->nContent -= aPaM.GetMark()->nContent.GetIndex();
1227 1 : pMarksAccess->makeMark(aPaM, OUString("Para1"), IDocumentMarkAccess::MarkType::BOOKMARK);
1228 :
1229 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
1230 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Paragraph 2"));
1231 1 : aPaM.SetMark();
1232 1 : aPaM.GetMark()->nContent -= aPaM.GetMark()->nContent.GetIndex();
1233 1 : pMarksAccess->makeMark(aPaM, OUString("Para2"), IDocumentMarkAccess::MarkType::BOOKMARK);
1234 :
1235 1 : m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPaM.GetPoint());
1236 1 : m_pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString("Paragraph 3"));
1237 1 : aPaM.SetMark();
1238 1 : aPaM.GetMark()->nContent -= aPaM.GetMark()->nContent.GetIndex();
1239 2 : pMarksAccess->makeMark(aPaM, OUString("Para3"), IDocumentMarkAccess::MarkType::BOOKMARK);
1240 : }
1241 :
1242 : // join paragraph 2 and 3 and check
1243 : {
1244 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -2);
1245 1 : SwTextNode& rParaNode2 = dynamic_cast<SwTextNode&>(aIdx.GetNode());
1246 1 : rParaNode2.JoinNext();
1247 : }
1248 1 : ::sw::mark::IMark* pBM1 = pMarksAccess->findMark("Para1")->get();
1249 1 : ::sw::mark::IMark* pBM2 = pMarksAccess->findMark("Para2")->get();
1250 1 : ::sw::mark::IMark* pBM3 = pMarksAccess->findMark("Para3")->get();
1251 :
1252 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 0 , pBM1->GetMarkStart().nContent.GetIndex());
1253 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 11, pBM1->GetMarkEnd().nContent.GetIndex());
1254 2 : CPPUNIT_ASSERT_EQUAL(
1255 : pBM1->GetMarkStart().nNode.GetIndex(),
1256 1 : pBM1->GetMarkEnd().nNode.GetIndex());
1257 :
1258 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 0 , pBM2->GetMarkStart().nContent.GetIndex());
1259 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 11, pBM2->GetMarkEnd().nContent.GetIndex());
1260 2 : CPPUNIT_ASSERT_EQUAL(
1261 : pBM2->GetMarkStart().nNode.GetIndex(),
1262 1 : pBM2->GetMarkEnd().nNode.GetIndex());
1263 :
1264 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 11, pBM3->GetMarkStart().nContent.GetIndex());
1265 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 22, pBM3->GetMarkEnd().nContent.GetIndex());
1266 2 : CPPUNIT_ASSERT_EQUAL(
1267 : pBM3->GetMarkStart().nNode.GetIndex(),
1268 1 : pBM3->GetMarkEnd().nNode.GetIndex());
1269 :
1270 2 : CPPUNIT_ASSERT_EQUAL(
1271 : pBM1->GetMarkStart().nNode.GetIndex()+1,
1272 1 : pBM2->GetMarkStart().nNode.GetIndex());
1273 2 : CPPUNIT_ASSERT_EQUAL(
1274 : pBM2->GetMarkStart().nNode.GetIndex(),
1275 1 : pBM3->GetMarkStart().nNode.GetIndex());
1276 :
1277 : // cut some text
1278 : {
1279 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1280 2 : SwPaM aPaM(aIdx, aIdx, -1);
1281 1 : aPaM.GetPoint()->nContent += 5;
1282 1 : aPaM.GetMark()->nContent += 6;
1283 2 : m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPaM);
1284 : }
1285 1 : pBM1 = pMarksAccess->findMark("Para1")->get();
1286 1 : pBM2 = pMarksAccess->findMark("Para2")->get();
1287 1 : pBM3 = pMarksAccess->findMark("Para3")->get();
1288 :
1289 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 0, pBM1->GetMarkStart().nContent.GetIndex());
1290 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 6, pBM1->GetMarkEnd().nContent.GetIndex());
1291 2 : CPPUNIT_ASSERT_EQUAL(
1292 : pBM1->GetMarkStart().nNode.GetIndex(),
1293 1 : pBM1->GetMarkEnd().nNode.GetIndex());
1294 :
1295 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 6, pBM2->GetMarkStart().nContent.GetIndex());
1296 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 12, pBM2->GetMarkEnd().nContent.GetIndex());
1297 2 : CPPUNIT_ASSERT_EQUAL(
1298 : pBM2->GetMarkStart().nNode.GetIndex(),
1299 1 : pBM2->GetMarkEnd().nNode.GetIndex());
1300 :
1301 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 12, pBM3->GetMarkStart().nContent.GetIndex());
1302 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 23, pBM3->GetMarkEnd().nContent.GetIndex());
1303 2 : CPPUNIT_ASSERT_EQUAL(
1304 : pBM3->GetMarkStart().nNode.GetIndex(),
1305 1 : pBM3->GetMarkEnd().nNode.GetIndex());
1306 :
1307 2 : CPPUNIT_ASSERT_EQUAL(
1308 : pBM1->GetMarkStart().nNode.GetIndex(),
1309 1 : pBM2->GetMarkStart().nNode.GetIndex());
1310 2 : CPPUNIT_ASSERT_EQUAL(
1311 : pBM2->GetMarkStart().nNode.GetIndex(),
1312 1 : pBM3->GetMarkStart().nNode.GetIndex());
1313 :
1314 : // split the paragraph
1315 : {
1316 1 : SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
1317 2 : SwPosition aPos(aIdx);
1318 1 : aPos.nContent += 8;
1319 2 : m_pDoc->getIDocumentContentOperations().SplitNode(aPos, false);
1320 : }
1321 1 : pBM1 = pMarksAccess->findMark("Para1")->get();
1322 1 : pBM2 = pMarksAccess->findMark("Para2")->get();
1323 1 : pBM3 = pMarksAccess->findMark("Para3")->get();
1324 :
1325 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 0, pBM1->GetMarkStart().nContent.GetIndex());
1326 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 6, pBM1->GetMarkEnd().nContent.GetIndex());
1327 2 : CPPUNIT_ASSERT_EQUAL(
1328 : pBM1->GetMarkStart().nNode.GetIndex(),
1329 1 : pBM1->GetMarkEnd().nNode.GetIndex());
1330 :
1331 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 6, pBM2->GetMarkStart().nContent.GetIndex());
1332 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 4, pBM2->GetMarkEnd().nContent.GetIndex());
1333 2 : CPPUNIT_ASSERT_EQUAL(
1334 : pBM2->GetMarkStart().nNode.GetIndex()+1,
1335 1 : pBM2->GetMarkEnd().nNode.GetIndex());
1336 :
1337 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 4, pBM3->GetMarkStart().nContent.GetIndex());
1338 1 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 15, pBM3->GetMarkEnd().nContent.GetIndex());
1339 2 : CPPUNIT_ASSERT_EQUAL(
1340 : pBM3->GetMarkStart().nNode.GetIndex(),
1341 1 : pBM3->GetMarkEnd().nNode.GetIndex());
1342 :
1343 2 : CPPUNIT_ASSERT_EQUAL(
1344 : pBM1->GetMarkStart().nNode.GetIndex(),
1345 1 : pBM2->GetMarkStart().nNode.GetIndex());
1346 2 : CPPUNIT_ASSERT_EQUAL(
1347 : pBM2->GetMarkEnd().nNode.GetIndex(),
1348 1 : pBM3->GetMarkEnd().nNode.GetIndex());
1349 1 : }
1350 :
1351 : namespace
1352 : {
1353 7 : struct TestRing : public sw::Ring<TestRing>
1354 : {
1355 7 : TestRing() : sw::Ring<TestRing>() {};
1356 9 : TestRing* GetNext()
1357 9 : { return GetNextInRing(); }
1358 9 : TestRing* GetPrev()
1359 9 : { return GetPrevInRing(); }
1360 6 : bool lonely() const
1361 6 : { return unique(); }
1362 : #if 0
1363 : void debug()
1364 : {
1365 : SAL_DEBUG("TestRing at: " << this << " prev: " << GetPrev() << " next: " << GetNext());
1366 : }
1367 : #endif
1368 : };
1369 : }
1370 :
1371 1 : void SwDocTest::testIntrusiveRing()
1372 : {
1373 2 : TestRing aRing1, aRing2, aRing3, aRing4, aRing5;
1374 2 : std::vector<TestRing*> vRings;
1375 1 : vRings.push_back(&aRing1);
1376 1 : vRings.push_back(&aRing2);
1377 1 : vRings.push_back(&aRing3);
1378 1 : vRings.push_back(&aRing4);
1379 1 : vRings.push_back(&aRing5);
1380 1 : CPPUNIT_ASSERT_EQUAL(aRing1.GetRingContainer().size(), static_cast<size_t>(1));
1381 1 : CPPUNIT_ASSERT(aRing1.lonely());
1382 1 : CPPUNIT_ASSERT(aRing2.lonely());
1383 1 : CPPUNIT_ASSERT(aRing3.lonely());
1384 1 : aRing2.MoveTo(&aRing1);
1385 1 : aRing3.MoveTo(&aRing1);
1386 1 : CPPUNIT_ASSERT_EQUAL(aRing1.GetRingContainer().size(), static_cast<size_t>(3));
1387 1 : CPPUNIT_ASSERT_EQUAL(aRing2.GetRingContainer().size(), static_cast<size_t>(3));
1388 1 : CPPUNIT_ASSERT_EQUAL(aRing3.GetRingContainer().size(), static_cast<size_t>(3));
1389 1 : CPPUNIT_ASSERT(!aRing1.lonely());
1390 1 : CPPUNIT_ASSERT(!aRing2.lonely());
1391 1 : CPPUNIT_ASSERT(!aRing3.lonely());
1392 1 : aRing5.MoveTo(&aRing4);
1393 1 : CPPUNIT_ASSERT_EQUAL(aRing4.GetRingContainer().size(), static_cast<size_t>(2));
1394 1 : aRing4.GetRingContainer().merge(aRing1.GetRingContainer());
1395 6 : for(TestRing* pRing : vRings)
1396 : {
1397 5 : CPPUNIT_ASSERT_EQUAL(pRing->GetRingContainer().size(), static_cast<size_t>(5));
1398 : }
1399 6 : for(std::vector<TestRing*>::iterator ppRing = vRings.begin(); ppRing != vRings.end(); ++ppRing)
1400 : {
1401 5 : std::vector<TestRing*>::iterator ppNext = ppRing+1;
1402 5 : if(ppNext==vRings.end())
1403 1 : ppNext = vRings.begin();
1404 5 : CPPUNIT_ASSERT_EQUAL((*ppRing)->GetNext(), *ppNext);
1405 5 : CPPUNIT_ASSERT_EQUAL((*ppNext)->GetPrev(), *ppRing);
1406 : }
1407 6 : for(TestRing& r: aRing1.GetRingContainer())
1408 : {
1409 5 : TestRing* pRing = &r;
1410 5 : CPPUNIT_ASSERT(pRing);
1411 : //pRing->debug();
1412 : }
1413 1 : const TestRing* pConstRing = &aRing1;
1414 6 : for(const TestRing& r: pConstRing->GetRingContainer()) // this should fail without r being const
1415 : {
1416 5 : const TestRing* pRing = &r;
1417 5 : CPPUNIT_ASSERT(pRing);
1418 : }
1419 2 : TestRing foo, bar;
1420 1 : foo.MoveTo(&bar);
1421 1 : CPPUNIT_ASSERT_EQUAL(&foo, bar.GetNext());
1422 1 : CPPUNIT_ASSERT_EQUAL(&foo, bar.GetPrev());
1423 1 : CPPUNIT_ASSERT_EQUAL(&bar, foo.GetNext());
1424 1 : CPPUNIT_ASSERT_EQUAL(&bar, foo.GetPrev());
1425 1 : foo.MoveTo(&foo);
1426 1 : CPPUNIT_ASSERT_EQUAL(&bar, bar.GetNext());
1427 1 : CPPUNIT_ASSERT_EQUAL(&bar, bar.GetPrev());
1428 1 : CPPUNIT_ASSERT_EQUAL(&foo, foo.GetNext());
1429 2 : CPPUNIT_ASSERT_EQUAL(&foo, foo.GetPrev());
1430 1 : }
1431 :
1432 : namespace
1433 : {
1434 1 : struct TestHint SAL_FINAL : SfxHint {};
1435 2 : struct TestModify : SwModify
1436 : {
1437 : TYPEINFO_OVERRIDE();
1438 : };
1439 0 : TYPEINIT1( TestModify, SwModify );
1440 2 : struct TestClient : SwClient
1441 : {
1442 : TYPEINFO_OVERRIDE();
1443 : int m_nModifyCount;
1444 : int m_nNotifyCount;
1445 2 : TestClient() : m_nModifyCount(0), m_nNotifyCount(0) {};
1446 4 : virtual void Modify( const SfxPoolItem*, const SfxPoolItem*) SAL_OVERRIDE
1447 4 : { ++m_nModifyCount; }
1448 6 : virtual void SwClientNotify(const SwModify& rModify, const SfxHint& rHint) SAL_OVERRIDE
1449 : {
1450 6 : if(typeid(TestHint) == typeid(rHint))
1451 2 : ++m_nNotifyCount;
1452 : else
1453 4 : SwClient::SwClientNotify(rModify, rHint);
1454 6 : }
1455 : };
1456 34 : TYPEINIT1( TestClient, SwClient );
1457 : // sad copypasta as tools/rtti.hxxs little brain cant cope with templates
1458 2 : struct OtherTestClient : SwClient
1459 : {
1460 : TYPEINFO_OVERRIDE();
1461 : int m_nModifyCount;
1462 2 : OtherTestClient() : m_nModifyCount(0) {};
1463 0 : virtual void Modify( const SfxPoolItem*, const SfxPoolItem*) SAL_OVERRIDE
1464 0 : { ++m_nModifyCount; }
1465 : };
1466 6 : TYPEINIT1( OtherTestClient, SwClient );
1467 : }
1468 1 : void SwDocTest::testClientModify()
1469 : {
1470 1 : (void) OtherTestClient(); // avoid loplugin:unreffun
1471 1 : TestModify aMod;
1472 2 : TestClient aClient1, aClient2;
1473 2 : OtherTestClient aOtherClient1;
1474 : // test client registration
1475 1 : CPPUNIT_ASSERT(!aMod.HasWriterListeners());
1476 1 : CPPUNIT_ASSERT(!aMod.HasOnlyOneListener());
1477 1 : CPPUNIT_ASSERT_EQUAL(aClient1.GetRegisteredIn(),static_cast<SwModify*>(nullptr));
1478 1 : CPPUNIT_ASSERT_EQUAL(aClient2.GetRegisteredIn(),static_cast<SwModify*>(nullptr));
1479 1 : CPPUNIT_ASSERT_EQUAL(aClient2.GetRegisteredIn(),static_cast<SwModify*>(nullptr));
1480 1 : aMod.Add(&aClient1);
1481 1 : CPPUNIT_ASSERT(aMod.HasWriterListeners());
1482 1 : CPPUNIT_ASSERT(aMod.HasOnlyOneListener());
1483 1 : aMod.Add(&aClient2);
1484 1 : CPPUNIT_ASSERT_EQUAL(aClient1.GetRegisteredIn(),static_cast<SwModify*>(&aMod));
1485 1 : CPPUNIT_ASSERT_EQUAL(aClient2.GetRegisteredIn(),static_cast<SwModify*>(&aMod));
1486 1 : CPPUNIT_ASSERT(aMod.HasWriterListeners());
1487 1 : CPPUNIT_ASSERT(!aMod.HasOnlyOneListener());
1488 : // test broadcast
1489 1 : aMod.ModifyBroadcast(nullptr, nullptr);
1490 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nModifyCount,1);
1491 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nModifyCount,1);
1492 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nNotifyCount,0);
1493 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nNotifyCount,0);
1494 1 : aMod.ModifyBroadcast(nullptr, nullptr);
1495 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nModifyCount,2);
1496 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nModifyCount,2);
1497 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nNotifyCount,0);
1498 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nNotifyCount,0);
1499 : // test notify
1500 : {
1501 1 : TestHint aHint;
1502 1 : aMod.CallSwClientNotify(aHint);
1503 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nModifyCount,2);
1504 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nModifyCount,2);
1505 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nNotifyCount,1);
1506 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nNotifyCount,1);
1507 : }
1508 : // test typed iteration
1509 1 : CPPUNIT_ASSERT(!aClient1.IsA(TYPE(OtherTestClient)));
1510 : {
1511 1 : SwIterator<OtherTestClient,SwModify> aIter(aMod);
1512 1 : for(OtherTestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1513 1 : CPPUNIT_ASSERT(false);
1514 : }
1515 : {
1516 1 : int nCount = 0;
1517 1 : SwIterator<TestClient,SwModify> aIter(aMod);
1518 3 : for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1519 : {
1520 2 : CPPUNIT_ASSERT_EQUAL(pClient->m_nModifyCount,2);
1521 2 : ++nCount;
1522 : }
1523 1 : CPPUNIT_ASSERT_EQUAL(nCount,2);
1524 : }
1525 1 : aMod.Add(&aOtherClient1);
1526 1 : CPPUNIT_ASSERT_EQUAL(aOtherClient1.m_nModifyCount,0);
1527 : {
1528 1 : int nCount = 0;
1529 1 : SwIterator<TestClient,SwModify> aIter(aMod);
1530 3 : for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1531 : {
1532 2 : CPPUNIT_ASSERT_EQUAL(pClient->m_nModifyCount,2);
1533 2 : ++nCount;
1534 : }
1535 1 : CPPUNIT_ASSERT_EQUAL(nCount,2);
1536 : }
1537 1 : CPPUNIT_ASSERT_EQUAL(aOtherClient1.m_nModifyCount,0);
1538 1 : aMod.Remove(&aOtherClient1);
1539 1 : CPPUNIT_ASSERT_EQUAL(aClient1.GetRegisteredIn(),static_cast<SwModify*>(&aMod));
1540 1 : CPPUNIT_ASSERT_EQUAL(aClient2.GetRegisteredIn(),static_cast<SwModify*>(&aMod));
1541 1 : CPPUNIT_ASSERT_EQUAL(aOtherClient1.GetRegisteredIn(),static_cast<SwModify*>(nullptr));
1542 : // test client self-deregistration during iteration
1543 : {
1544 1 : int nCount = 0;
1545 1 : SwIterator<TestClient,SwModify> aIter(aMod);
1546 3 : for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1547 : {
1548 2 : aMod.Remove(pClient);
1549 2 : ++nCount;
1550 : }
1551 1 : CPPUNIT_ASSERT_EQUAL(nCount,2);
1552 : }
1553 1 : CPPUNIT_ASSERT_EQUAL(aClient1.GetRegisteredIn(), static_cast<SwModify*>(nullptr));
1554 1 : CPPUNIT_ASSERT_EQUAL(aClient2.GetRegisteredIn(), static_cast<SwModify*>(nullptr));
1555 : {
1556 1 : int nCount = 0;
1557 1 : SwIterator<TestClient,SwModify> aIter(aMod);
1558 1 : for(TestClient* pClient = aIter.First(); pClient ; pClient = aIter.Next())
1559 : {
1560 0 : CPPUNIT_ASSERT(false);
1561 : }
1562 1 : CPPUNIT_ASSERT_EQUAL(nCount,0);
1563 : }
1564 1 : aMod.ModifyBroadcast(nullptr, nullptr);
1565 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nModifyCount,2);
1566 1 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nModifyCount,2);
1567 1 : CPPUNIT_ASSERT_EQUAL(aClient1.m_nNotifyCount,1);
1568 2 : CPPUNIT_ASSERT_EQUAL(aClient2.m_nNotifyCount,1);
1569 1 : }
1570 :
1571 1 : void SwDocTest::test64kPageDescs()
1572 : {
1573 1 : size_t nPageDescCount = 65536; // USHRT_MAX + 1
1574 :
1575 65537 : for (size_t i = 0; i < nPageDescCount; ++i)
1576 : {
1577 65536 : OUString aName = "Page" + OUString::number(i);
1578 65536 : m_pDoc->MakePageDesc( aName );
1579 65536 : }
1580 :
1581 1 : size_t nCount = m_pDoc->GetPageDescCnt();
1582 : // +1 because Writer always creates a dummy page desc
1583 : // in a new SwDoc
1584 1 : CPPUNIT_ASSERT_EQUAL( nPageDescCount + 1, nCount );
1585 :
1586 1 : const SwPageDesc &rDesc = m_pDoc->GetPageDesc( nPageDescCount );
1587 1 : SwPageDesc &rZeroDesc = m_pDoc->GetPageDesc( 0 );
1588 1 : CPPUNIT_ASSERT_EQUAL( OUString("Page65535"), rDesc.GetName() );
1589 :
1590 1 : SwPageDesc aDesc( rDesc );
1591 2 : const OUString aChanged("Changed01");
1592 1 : aDesc.SetName( aChanged );
1593 1 : m_pDoc->ChgPageDesc( nPageDescCount, aDesc );
1594 :
1595 : size_t nPos;
1596 1 : SwPageDesc *pDesc = m_pDoc->FindPageDesc( aChanged, &nPos );
1597 1 : CPPUNIT_ASSERT( pDesc != NULL );
1598 1 : CPPUNIT_ASSERT( nPos == nPageDescCount );
1599 :
1600 : // check if we didn't mess up PageDesc at pos 0
1601 : // (happens with 16bit int overflow)
1602 2 : OUString aZeroName = rZeroDesc.GetName();
1603 1 : rZeroDesc = m_pDoc->GetPageDesc( 0 );
1604 1 : CPPUNIT_ASSERT_EQUAL( aZeroName, rZeroDesc.GetName() );
1605 :
1606 1 : m_pDoc->DelPageDesc( aChanged, nPos );
1607 1 : pDesc = m_pDoc->FindPageDesc( aChanged, &nPos );
1608 : // not there anymore
1609 1 : CPPUNIT_ASSERT( pDesc == NULL );
1610 1 : CPPUNIT_ASSERT( nPos == SIZE_MAX );
1611 :
1612 : // check if PageDesc at pos 0 is still there
1613 1 : pDesc = m_pDoc->FindPageDesc( aZeroName, &nPos );
1614 1 : CPPUNIT_ASSERT( pDesc != NULL );
1615 2 : CPPUNIT_ASSERT( nPos == 0 );
1616 1 : }
1617 :
1618 30 : void SwDocTest::setUp()
1619 : {
1620 30 : BootstrapFixture::setUp();
1621 :
1622 30 : SwGlobals::ensure();
1623 30 : m_pDoc = new SwDoc;
1624 30 : m_xDocShRef = new SwDocShell(m_pDoc, SfxObjectCreateMode::EMBEDDED);
1625 30 : m_xDocShRef->DoInitNew(0);
1626 30 : }
1627 :
1628 30 : void SwDocTest::tearDown()
1629 : {
1630 30 : m_pDoc = 0; // deleted by DoClose()
1631 30 : m_xDocShRef->DoClose();
1632 30 : m_xDocShRef.Clear();
1633 :
1634 30 : BootstrapFixture::tearDown();
1635 30 : }
1636 :
1637 1 : CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);
1638 :
1639 4 : CPPUNIT_PLUGIN_IMPLEMENT();
1640 :
1641 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|