1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "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
;
40 class Test
: public test::BootstrapFixture
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();
54 void testAutocorrect();
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();
70 EditEngineItemPool
* mpItemPool
;
73 Test::Test() : mpItemPool(NULL
) {}
77 test::BootstrapFixture::setUp();
79 mpItemPool
= new EditEngineItemPool(true);
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
);
98 bool includes(const uno::Sequence
<OUString
>& rSeq
, const OUString
& rVal
)
100 for (sal_Int32 i
= 0, n
= rSeq
.getLength(); i
< n
; ++i
)
109 void Test::testUnoTextFields()
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
227 /// just like the real thing, this dummy modifies the rText parameter :(
228 TestAutoCorrDoc(OUString
&rText
, LanguageType eLang
)
233 OUString
const& getResult() const
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
, "");
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
);
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
);
263 virtual bool SetAttr( sal_Int32
, sal_Int32
, sal_uInt16
, SfxPoolItem
& ) SAL_OVERRIDE
265 //fprintf(stderr, "TestAutoCorrDoc::SetAttr\n");
268 virtual bool SetINetAttr( sal_Int32
, sal_Int32
, const OUString
& ) SAL_OVERRIDE
270 //fprintf(stderr, "TestAutoCorrDoc::SetINetAttr\n");
273 virtual OUString
const* GetPrevPara(bool) SAL_OVERRIDE
275 //fprintf(stderr, "TestAutoCorrDoc::GetPrevPara\n");
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())
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());
294 pPara
->clear(); // =&pCurNode->GetString();
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());
347 class UrlEditEngine
: public EditEngine
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",
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
;
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
)
440 if (static_cast<const SvxWeightItem
*>(p
)->GetWeight() != WEIGHT_BOLD
)
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
)
457 if (static_cast<const SvxPostureItem
*>(p
)->GetPosture() != ITALIC_NORMAL
)
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
);
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()));
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
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()));
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());
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()));
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: */