bump product version to 5.0.4.1
[LibreOffice.git] / editeng / qa / unit / core-test.cxx
blobefb82d83ad4e908266e75ec2c5464f46f4a5e0e0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "test/bootstrapfixture.hxx"
12 #include <cppunit/TestFixture.h>
13 #include <cppunit/extensions/HelperMacros.h>
15 #include "svl/itempool.hxx"
16 #include "editeng/eerdll.hxx"
17 #include "editeng/eerdll2.hxx"
18 #include "editeng/editeng.hxx"
19 #include "editeng/eeitem.hxx"
20 #include "editeng/editids.hrc"
21 #include "editeng/editdoc.hxx"
22 #include "editeng/svxacorr.hxx"
23 #include "editeng/unofield.hxx"
24 #include "editeng/wghtitem.hxx"
25 #include "editeng/postitem.hxx"
26 #include "editeng/section.hxx"
27 #include "editeng/editobj.hxx"
28 #include "editeng/flditem.hxx"
29 #include "svl/srchitem.hxx"
30 #include "rtl/strbuf.hxx"
32 #include <com/sun/star/text/textfield/Type.hpp>
34 #include <boost/scoped_ptr.hpp>
36 using namespace com::sun::star;
38 namespace {
40 class Test : public test::BootstrapFixture
42 public:
43 Test();
45 virtual void setUp() SAL_OVERRIDE;
46 virtual void tearDown() SAL_OVERRIDE;
48 void testConstruction();
50 /// Test UNO service class that implements text field items.
51 void testUnoTextFields();
53 /// AutoCorrect tests
54 void testAutocorrect();
56 /// Test hyperlinks
57 void testHyperlinkSearch();
59 void testSectionAttributes();
61 CPPUNIT_TEST_SUITE(Test);
62 CPPUNIT_TEST(testConstruction);
63 CPPUNIT_TEST(testUnoTextFields);
64 CPPUNIT_TEST(testAutocorrect);
65 CPPUNIT_TEST(testHyperlinkSearch);
66 CPPUNIT_TEST(testSectionAttributes);
67 CPPUNIT_TEST_SUITE_END();
69 private:
70 EditEngineItemPool* mpItemPool;
73 Test::Test() : mpItemPool(NULL) {}
75 void Test::setUp()
77 test::BootstrapFixture::setUp();
79 mpItemPool = new EditEngineItemPool(true);
82 void Test::tearDown()
84 SfxItemPool::Free(mpItemPool);
85 test::BootstrapFixture::tearDown();
88 void Test::testConstruction()
90 EditEngine aEngine(mpItemPool);
92 OUString aParaText = "I am Edit Engine.";
93 aEngine.SetText(aParaText);
96 namespace {
98 bool includes(const uno::Sequence<OUString>& rSeq, const OUString& rVal)
100 for (sal_Int32 i = 0, n = rSeq.getLength(); i < n; ++i)
101 if (rSeq[i] == rVal)
102 return true;
104 return false;
109 void Test::testUnoTextFields()
112 // DATE
113 SvxUnoTextField aField(text::textfield::Type::DATE);
114 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
115 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
116 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
120 // URL
121 SvxUnoTextField aField(text::textfield::Type::URL);
122 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
123 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.URL");
124 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
128 // PAGE
129 SvxUnoTextField aField(text::textfield::Type::PAGE);
130 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
131 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.PageNumber");
132 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
136 // PAGES
137 SvxUnoTextField aField(text::textfield::Type::PAGES);
138 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
139 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.PageCount");
140 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
144 // TIME
145 SvxUnoTextField aField(text::textfield::Type::TIME);
146 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
147 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
148 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
152 // FILE
153 SvxUnoTextField aField(text::textfield::Type::DOCINFO_TITLE);
154 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
155 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.docinfo.Title");
156 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
160 // TABLE
161 SvxUnoTextField aField(text::textfield::Type::TABLE);
162 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
163 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.SheetName");
164 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
168 // EXTENDED TIME
169 SvxUnoTextField aField(text::textfield::Type::EXTENDED_TIME);
170 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
171 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
172 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
176 // EXTENDED FILE
177 SvxUnoTextField aField(text::textfield::Type::EXTENDED_FILE);
178 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
179 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.FileName");
180 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
184 // AUTHOR
185 SvxUnoTextField aField(text::textfield::Type::AUTHOR);
186 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
187 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.Author");
188 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
192 // MEASURE
193 SvxUnoTextField aField(text::textfield::Type::MEASURE);
194 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
195 bool bGood = includes(aSvcs, "com.sun.star.text.textfield.Measure");
196 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
200 // PRESENTATION HEADER
201 SvxUnoTextField aField(text::textfield::Type::PRESENTATION_HEADER);
202 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
203 bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.Header");
204 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
208 // PRESENTATION FOOTER
209 SvxUnoTextField aField(text::textfield::Type::PRESENTATION_FOOTER);
210 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
211 bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.Footer");
212 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
216 // PRESENTATION DATE TIME
217 SvxUnoTextField aField(text::textfield::Type::PRESENTATION_DATE_TIME);
218 uno::Sequence<OUString> aSvcs = aField.getSupportedServiceNames();
219 bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.DateTime");
220 CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
224 class TestAutoCorrDoc : public SvxAutoCorrDoc
226 public:
227 /// just like the real thing, this dummy modifies the rText parameter :(
228 TestAutoCorrDoc(OUString &rText, LanguageType eLang)
229 : m_rText(rText)
230 , m_eLang(eLang)
233 OUString const& getResult() const
235 return m_rText;
237 private:
238 OUString & m_rText;
239 LanguageType m_eLang;
240 virtual bool Delete( sal_Int32 nStt, sal_Int32 nEnd ) SAL_OVERRIDE
242 //fprintf(stderr, "TestAutoCorrDoc::Delete\n");
243 m_rText = m_rText.replaceAt(nStt, nEnd-nStt, "");
244 return true;
246 virtual bool Insert( sal_Int32 nPos, const OUString& rTxt ) SAL_OVERRIDE
248 //fprintf(stderr, "TestAutoCorrDoc::Insert\n");
249 m_rText = m_rText.replaceAt(nPos, 0, rTxt);
250 return true;
252 virtual bool Replace( sal_Int32 nPos, const OUString& rTxt ) SAL_OVERRIDE
254 //fprintf(stderr, "TestAutoCorrDoc::Replace\n");
255 return ReplaceRange( nPos, rTxt.getLength(), rTxt );
257 virtual bool ReplaceRange( sal_Int32 nPos, sal_Int32 nLen, const OUString& rTxt ) SAL_OVERRIDE
259 //fprintf(stderr, "TestAutoCorrDoc::ReplaceRange %d %d %s\n", nPos, nLen, OUStringToOString(rTxt, RTL_TEXTENCODING_UTF8).getStr());
260 m_rText = m_rText.replaceAt(nPos, nLen, rTxt);
261 return true;
263 virtual bool SetAttr( sal_Int32, sal_Int32, sal_uInt16, SfxPoolItem& ) SAL_OVERRIDE
265 //fprintf(stderr, "TestAutoCorrDoc::SetAttr\n");
266 return true;
268 virtual bool SetINetAttr( sal_Int32, sal_Int32, const OUString& ) SAL_OVERRIDE
270 //fprintf(stderr, "TestAutoCorrDoc::SetINetAttr\n");
271 return true;
273 virtual OUString const* GetPrevPara(bool) SAL_OVERRIDE
275 //fprintf(stderr, "TestAutoCorrDoc::GetPrevPara\n");
276 return 0;
278 virtual bool ChgAutoCorrWord( sal_Int32& rSttPos,
279 sal_Int32 nEndPos, SvxAutoCorrect& rACorrect,
280 OUString* pPara ) SAL_OVERRIDE
282 //fprintf(stderr, "TestAutoCorrDoc::ChgAutoCorrWord\n");
284 if (m_rText.isEmpty())
285 return false;
287 LanguageTag aLanguageTag( m_eLang);
288 const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList(
289 m_rText, rSttPos, nEndPos, *this, aLanguageTag);
290 if (pFnd && pFnd->IsTextOnly())
292 m_rText = m_rText.replaceAt(rSttPos, nEndPos, pFnd->GetLong());
293 if( pPara )
294 pPara->clear(); // =&pCurNode->GetString();
295 return true;
298 return false;
302 //https://bugs.libreoffice.org/show_bug.cgi?id=55693
303 //Two capitalized letters are not corrected if dash or slash are directly
304 //before the two letters
305 void Test::testAutocorrect()
307 OUString sShareAutocorrFile;
308 OUString sUserAutocorrFile;
309 SvxAutoCorrect aAutoCorrect(sShareAutocorrFile, sUserAutocorrFile);
312 OUString sInput("TEst-TEst");
313 sal_Unicode cNextChar(' ');
314 OUString sExpected("Test-Test ");
316 TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
317 aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true);
319 CPPUNIT_ASSERT_MESSAGE("autocorrect", aFoo.getResult() == sExpected);
323 OUString sInput("TEst/TEst");
324 sal_Unicode cNextChar(' ');
325 OUString sExpected("Test/Test ");
327 TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
328 aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true);
330 CPPUNIT_ASSERT_MESSAGE("autocorrect", aFoo.getResult() == sExpected);
334 // test auto-bolding with '*'
335 OUString sInput("*foo");
336 sal_Unicode cNextChar('*');
337 OUString sExpected("foo");
339 TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
340 aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true);
342 CPPUNIT_ASSERT_EQUAL(sExpected, aFoo.getResult());
346 namespace {
347 class UrlEditEngine : public EditEngine
349 public:
350 UrlEditEngine(SfxItemPool *pPool) : EditEngine(pPool) {}
352 virtual OUString CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, Color*&, Color*& ) SAL_OVERRIDE
354 return OUString("jim@bob.com"); // a sophisticated view of value:
359 // Odd accounting for hyperlink position & size etc.
360 // https://bugzilla.novell.com/show_bug.cgi?id=467459
361 void Test::testHyperlinkSearch()
363 UrlEditEngine aEngine(mpItemPool);
364 EditDoc &rDoc = aEngine.GetEditDoc();
366 OUString aSampleText = "Please write email to . if you find a fish(not a dog).";
367 aEngine.SetText(aSampleText);
369 CPPUNIT_ASSERT_MESSAGE("set text", rDoc.GetParaAsString(sal_Int32(0)) == aSampleText);
371 ContentNode *pNode = rDoc.GetObject(0);
372 EditSelection aSel(EditPaM(pNode, 22), EditPaM(pNode, 22));
373 SvxURLField aURLField("mailto:///jim@bob.com", "jim@bob.com",
374 SVXURLFORMAT_REPR);
375 SvxFieldItem aField(aURLField, EE_FEATURE_FIELD);
377 aEngine.InsertField(aSel, aField);
378 aEngine.UpdateFields();
380 OUString aContent = pNode->GetExpandedText();
381 CPPUNIT_ASSERT_MESSAGE("get text", aContent ==
382 "Please write email to jim@bob.com. if you find a fish(not a dog).");
383 CPPUNIT_ASSERT_MESSAGE("wrong length", rDoc.GetTextLen() == (sal_uLong)aContent.getLength());
385 // Check expansion and positioning re-work
386 CPPUNIT_ASSERT_MESSAGE("wrong length", pNode->GetExpandedLen() ==
387 (sal_uLong)aContent.getLength());
388 for (sal_Int32 n = 0; n < aContent.getLength(); n++)
390 sal_Int32 nStart = n, nEnd = n;
391 pNode->UnExpandPositions(nStart,nEnd);
392 CPPUNIT_ASSERT_MESSAGE("out of bound start", nStart < pNode->Len());
393 CPPUNIT_ASSERT_MESSAGE("out of bound end", nEnd <= pNode->Len());
396 static const struct {
397 sal_Int32 mnStart, mnEnd;
398 sal_Int32 mnNewStart, mnNewEnd;
399 } aTrickyOnes[] = {
400 { 0, 1, /* -> */ 0, 1 },
401 { 21, 25, /* -> */ 21, 23 }, // the field is really just one char
402 { 25, 27, /* -> */ 22, 23 },
403 { 50, 56, /* -> */ 40, 46 }
405 for (size_t n = 0; n < SAL_N_ELEMENTS(aTrickyOnes); n++)
407 sal_Int32 nStart = aTrickyOnes[n].mnStart;
408 sal_Int32 nEnd = aTrickyOnes[n].mnEnd;
409 pNode->UnExpandPositions(nStart,nEnd);
411 rtl::OStringBuffer aBuf;
412 aBuf = "bound check start is ";
413 aBuf.append(nStart).append(" but should be ").append(aTrickyOnes[n].mnNewStart);
414 aBuf.append(" in row ").append((sal_Int32)n);
415 CPPUNIT_ASSERT_MESSAGE(aBuf.getStr(), nStart == aTrickyOnes[n].mnNewStart);
416 aBuf = "bound check end is ";
417 aBuf.append(nEnd).append(" but should be ").append(aTrickyOnes[n].mnNewEnd);
418 aBuf.append(" in row ").append((sal_Int32)n);
419 CPPUNIT_ASSERT_MESSAGE(aBuf.getStr(), nEnd == aTrickyOnes[n].mnNewEnd);
422 SvxSearchItem aItem(1); //SID_SEARCH_ITEM);
423 aItem.SetBackward(false);
424 aItem.SetSelection(false);
425 aItem.SetSearchString("fish");
426 CPPUNIT_ASSERT_MESSAGE("no fish", aEngine.HasText(aItem));
427 aItem.SetSearchString("dog");
428 CPPUNIT_ASSERT_MESSAGE("no dog", aEngine.HasText(aItem));
431 bool hasBold(const editeng::Section& rSecAttr)
433 std::vector<const SfxPoolItem*>::const_iterator it = rSecAttr.maAttributes.begin(), itEnd = rSecAttr.maAttributes.end();
434 for (; it != itEnd; ++it)
436 const SfxPoolItem* p = *it;
437 if (p->Which() != EE_CHAR_WEIGHT)
438 continue;
440 if (static_cast<const SvxWeightItem*>(p)->GetWeight() != WEIGHT_BOLD)
441 continue;
443 return true;
445 return false;
448 bool hasItalic(const editeng::Section& rSecAttr)
450 std::vector<const SfxPoolItem*>::const_iterator it = rSecAttr.maAttributes.begin(), itEnd = rSecAttr.maAttributes.end();
451 for (; it != itEnd; ++it)
453 const SfxPoolItem* p = *it;
454 if (p->Which() != EE_CHAR_ITALIC)
455 continue;
457 if (static_cast<const SvxPostureItem*>(p)->GetPosture() != ITALIC_NORMAL)
458 continue;
460 return true;
462 return false;
465 void Test::testSectionAttributes()
467 EditEngine aEngine(mpItemPool);
469 boost::scoped_ptr<SfxItemSet> pSet(new SfxItemSet(aEngine.GetEmptyItemSet()));
470 SvxWeightItem aBold(WEIGHT_BOLD, EE_CHAR_WEIGHT);
471 SvxPostureItem aItalic(ITALIC_NORMAL, EE_CHAR_ITALIC);
474 OUString aParaText = "aaabbbccc";
475 aEngine.SetText(aParaText);
476 pSet->Put(aBold);
477 CPPUNIT_ASSERT_MESSAGE("There should be exactly one item.", pSet->Count() == 1);
478 aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,6)); // 'aaabbb' - end point is not inclusive.
479 pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
480 pSet->Put(aItalic);
481 CPPUNIT_ASSERT_MESSAGE("There should be exactly one item.", pSet->Count() == 1);
483 aEngine.QuickSetAttribs(*pSet, ESelection(0,3,0,9)); // 'bbbccc'
484 boost::scoped_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
485 CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText.get());
486 std::vector<editeng::Section> aAttrs;
487 pEditText->GetAllSections(aAttrs);
489 // Now, we should have a total of 3 sections.
490 CPPUNIT_ASSERT_MESSAGE("There should be 3 sections.", aAttrs.size() == 3);
492 // First section should be 0-3 of paragraph 0, and it should only have boldness applied.
493 const editeng::Section* pSecAttr = &aAttrs[0];
494 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnParagraph);
495 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
496 CPPUNIT_ASSERT_EQUAL(3, (int)pSecAttr->mnEnd);
497 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->maAttributes.size());
498 CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(*pSecAttr));
500 // Second section should be 3-6, and it should be both bold and italic.
501 pSecAttr = &aAttrs[1];
502 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnParagraph);
503 CPPUNIT_ASSERT_EQUAL(3, (int)pSecAttr->mnStart);
504 CPPUNIT_ASSERT_EQUAL(6, (int)pSecAttr->mnEnd);
505 CPPUNIT_ASSERT_EQUAL(2, (int)pSecAttr->maAttributes.size());
506 CPPUNIT_ASSERT_MESSAGE("This section must be bold and italic.", hasBold(*pSecAttr) && hasItalic(*pSecAttr));
508 // Third section should be 6-9, and it should be only italic.
509 pSecAttr = &aAttrs[2];
510 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnParagraph);
511 CPPUNIT_ASSERT_EQUAL(6, (int)pSecAttr->mnStart);
512 CPPUNIT_ASSERT_EQUAL(9, (int)pSecAttr->mnEnd);
513 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->maAttributes.size());
514 CPPUNIT_ASSERT_MESSAGE("This section must be italic.", hasItalic(*pSecAttr));
518 // Set text consisting of 5 paragraphs with the 2nd and 4th paragraphs
519 // being empty.
520 aEngine.Clear();
521 aEngine.SetText("one\n\ntwo\n\nthree");
522 sal_Int32 nParaCount = aEngine.GetParagraphCount();
523 sal_Int32 nCheck = 5;
524 CPPUNIT_ASSERT_EQUAL(nCheck, nParaCount);
526 // Apply boldness to paragraphs 1, 3, 5 only. Leave 2 and 4 unformatted.
527 pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
528 pSet->Put(aBold);
529 CPPUNIT_ASSERT_MESSAGE("There should be exactly one item.", pSet->Count() == 1);
530 aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,3));
531 aEngine.QuickSetAttribs(*pSet, ESelection(2,0,2,3));
532 aEngine.QuickSetAttribs(*pSet, ESelection(4,0,4,5));
534 boost::scoped_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
535 CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText.get());
536 std::vector<editeng::Section> aAttrs;
537 pEditText->GetAllSections(aAttrs);
538 size_t nSecCountCheck = 5;
539 CPPUNIT_ASSERT_EQUAL(nSecCountCheck, aAttrs.size());
541 // 1st, 3rd and 5th sections should correspond with 1st, 3rd and 5th paragraphs.
542 const editeng::Section* pSecAttr = &aAttrs[0];
543 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnParagraph);
544 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
545 CPPUNIT_ASSERT_EQUAL(3, (int)pSecAttr->mnEnd);
546 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->maAttributes.size());
547 CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(*pSecAttr));
549 pSecAttr = &aAttrs[2];
550 CPPUNIT_ASSERT_EQUAL(2, (int)pSecAttr->mnParagraph);
551 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
552 CPPUNIT_ASSERT_EQUAL(3, (int)pSecAttr->mnEnd);
553 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->maAttributes.size());
554 CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(*pSecAttr));
556 pSecAttr = &aAttrs[4];
557 CPPUNIT_ASSERT_EQUAL(4, (int)pSecAttr->mnParagraph);
558 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
559 CPPUNIT_ASSERT_EQUAL(5, (int)pSecAttr->mnEnd);
560 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->maAttributes.size());
561 CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(*pSecAttr));
563 // The 2nd and 4th paragraphs should be empty.
564 pSecAttr = &aAttrs[1];
565 CPPUNIT_ASSERT_EQUAL(1, (int)pSecAttr->mnParagraph);
566 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
567 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnEnd);
568 CPPUNIT_ASSERT_MESSAGE("Attribute array should be empty.", pSecAttr->maAttributes.empty());
570 pSecAttr = &aAttrs[3];
571 CPPUNIT_ASSERT_EQUAL(3, (int)pSecAttr->mnParagraph);
572 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
573 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnEnd);
574 CPPUNIT_ASSERT_MESSAGE("Attribute array should be empty.", pSecAttr->maAttributes.empty());
579 aEngine.Clear();
580 aEngine.SetText("one\ntwo");
581 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aEngine.GetParagraphCount());
583 // embolden 2nd paragraph
584 pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
585 pSet->Put(aBold);
586 aEngine.QuickSetAttribs(*pSet, ESelection(1,0,1,3));
587 // disboldify 1st paragraph
588 SvxWeightItem aNotSoBold(WEIGHT_NORMAL, EE_CHAR_WEIGHT);
589 pSet->Put(aNotSoBold);
590 aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,3));
592 // now delete & join the paragraphs - this is fdo#85496 scenario
593 aEngine.QuickDelete(ESelection(0,0,1,3));
594 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aEngine.GetParagraphCount());
596 boost::scoped_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
597 CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText.get());
598 std::vector<editeng::Section> aAttrs;
599 pEditText->GetAllSections(aAttrs);
601 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aAttrs.size());
603 const editeng::Section* pSecAttr = &aAttrs[0];
604 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnParagraph);
605 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnStart);
606 CPPUNIT_ASSERT_EQUAL(0, (int)pSecAttr->mnEnd);
607 std::set<sal_uInt16> whiches;
608 for (size_t i = 0; i < pSecAttr->maAttributes.size(); ++i)
610 sal_uInt16 const nWhich(pSecAttr->maAttributes[i]->Which());
611 CPPUNIT_ASSERT_MESSAGE("duplicate item in text portion attributes",
612 whiches.insert(nWhich).second);
617 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
621 CPPUNIT_PLUGIN_IMPLEMENT();
623 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */