summaryrefslogtreecommitdiffstats
path: root/editeng/qa
diff options
context:
space:
mode:
Diffstat (limited to 'editeng/qa')
-rw-r--r--editeng/qa/items/borderline_test.cxx164
-rw-r--r--editeng/qa/lookuptree/lookuptree_test.cxx146
-rw-r--r--editeng/qa/unit/core-test.cxx1766
3 files changed, 2076 insertions, 0 deletions
diff --git a/editeng/qa/items/borderline_test.cxx b/editeng/qa/items/borderline_test.cxx
new file mode 100644
index 000000000..a44c2927d
--- /dev/null
+++ b/editeng/qa/items/borderline_test.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <editeng/borderline.hxx>
+
+using namespace ::com::sun::star::table::BorderLineStyle;
+
+#define TEST_WIDTH long( 40 )
+
+#define THINTHICKSG_IN_WIDTH long( 15 )
+#define THINTHICKSG_OUT_WIDTH long( 40 )
+#define THINTHICKSG_DIST_WIDTH long( 15 )
+
+#define THINTHICKLG_IN_WIDTH long( 15 )
+#define THINTHICKLG_OUT_WIDTH long( 30 )
+#define THINTHICKLG_DIST_WIDTH long( 40 )
+
+using namespace editeng;
+
+CPPUNIT_NS_BEGIN
+
+template<> struct assertion_traits<SvxBorderLineStyle>
+{
+ static bool equal( SvxBorderLineStyle x, SvxBorderLineStyle y )
+ {
+ return x == y;
+ }
+
+ static std::string toString( SvxBorderLineStyle x )
+ {
+ OStringStream ost;
+ ost << static_cast<unsigned int>(x);
+ return ost.str();
+ }
+};
+
+CPPUNIT_NS_END
+
+namespace {
+
+class BorderLineTest : public CppUnit::TestFixture
+{
+ public:
+ void testGuessWidthDouble();
+ void testGuessWidthNoMatch();
+ void testGuessWidthThinthickSmallgap();
+ void testGuessWidthThinthickLargegap();
+ void testGuessWidthNostyleDouble();
+ void testGuessWidthNostyleSingle();
+
+ CPPUNIT_TEST_SUITE(BorderLineTest);
+ CPPUNIT_TEST(testGuessWidthDouble);
+ CPPUNIT_TEST(testGuessWidthNoMatch);
+ CPPUNIT_TEST(testGuessWidthThinthickSmallgap);
+ CPPUNIT_TEST(testGuessWidthThinthickLargegap);
+ CPPUNIT_TEST(testGuessWidthNostyleDouble);
+ CPPUNIT_TEST(testGuessWidthNostyleSingle);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BorderLineTest);
+
+void BorderLineTest::testGuessWidthDouble()
+{
+ // Normal double case
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::DOUBLE, TEST_WIDTH, TEST_WIDTH, TEST_WIDTH );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::DOUBLE, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetOutWidth()) );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetInWidth()) );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetDistance()) );
+ CPPUNIT_ASSERT_EQUAL( 3*TEST_WIDTH, line.GetWidth() );
+}
+
+void BorderLineTest::testGuessWidthNoMatch()
+{
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::DOUBLE,
+ TEST_WIDTH + 1, TEST_WIDTH + 2, TEST_WIDTH + 3 );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::DOUBLE, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+1, static_cast<long>(line.GetOutWidth()) );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+2, static_cast<long>(line.GetInWidth()) );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+3, static_cast<long>(line.GetDistance()));
+ CPPUNIT_ASSERT_EQUAL( long( (3 * TEST_WIDTH) + 6 ), line.GetWidth() );
+}
+
+void BorderLineTest::testGuessWidthThinthickSmallgap()
+{
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::DOUBLE,
+ THINTHICKSG_OUT_WIDTH,
+ THINTHICKSG_IN_WIDTH,
+ THINTHICKSG_DIST_WIDTH );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::THINTHICK_SMALLGAP, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKSG_OUT_WIDTH,
+ static_cast<long>(line.GetOutWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKSG_IN_WIDTH,
+ static_cast<long>(line.GetInWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKSG_DIST_WIDTH,
+ static_cast<long>(line.GetDistance()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKSG_OUT_WIDTH + THINTHICKSG_IN_WIDTH
+ + THINTHICKSG_DIST_WIDTH, line.GetWidth() );
+}
+
+void BorderLineTest::testGuessWidthThinthickLargegap()
+{
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::DOUBLE,
+ THINTHICKLG_OUT_WIDTH,
+ THINTHICKLG_IN_WIDTH,
+ THINTHICKLG_DIST_WIDTH );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::THINTHICK_LARGEGAP, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH,
+ static_cast<long>(line.GetOutWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_IN_WIDTH,
+ static_cast<long>(line.GetInWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_DIST_WIDTH,
+ static_cast<long>(line.GetDistance()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH + THINTHICKLG_IN_WIDTH
+ + THINTHICKLG_DIST_WIDTH, line.GetWidth() );
+}
+
+void BorderLineTest::testGuessWidthNostyleDouble()
+{
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::NONE,
+ THINTHICKLG_OUT_WIDTH,
+ THINTHICKLG_IN_WIDTH,
+ THINTHICKLG_DIST_WIDTH );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::THINTHICK_LARGEGAP, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH,
+ static_cast<long>(line.GetOutWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_IN_WIDTH,
+ static_cast<long>(line.GetInWidth()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_DIST_WIDTH,
+ static_cast<long>(line.GetDistance()) );
+ CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH + THINTHICKLG_IN_WIDTH
+ + THINTHICKLG_DIST_WIDTH, line.GetWidth() );
+}
+
+void BorderLineTest::testGuessWidthNostyleSingle()
+{
+ SvxBorderLine line;
+ line.GuessLinesWidths( SvxBorderLineStyle::NONE, TEST_WIDTH );
+ CPPUNIT_ASSERT_EQUAL( SvxBorderLineStyle::SOLID, line.GetBorderLineStyle() );
+ CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, line.GetWidth() );
+}
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/qa/lookuptree/lookuptree_test.cxx b/editeng/qa/lookuptree/lookuptree_test.cxx
new file mode 100644
index 000000000..7d5e9647b
--- /dev/null
+++ b/editeng/qa/lookuptree/lookuptree_test.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <editeng/Trie.hxx>
+
+namespace {
+
+class LookupTreeTest : public CppUnit::TestFixture
+{
+public:
+ void testTrie();
+ void testTrieGetAllEntries();
+
+ CPPUNIT_TEST_SUITE(LookupTreeTest);
+ CPPUNIT_TEST(testTrie);
+ CPPUNIT_TEST(testTrieGetAllEntries);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LookupTreeTest);
+
+void LookupTreeTest::testTrie()
+{
+ editeng::Trie trie;
+ std::vector<OUString> suggestions;
+
+ trie.findSuggestions( OUString(), suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(0), suggestions.size() );
+
+ trie.insert( OUString() );
+ trie.findSuggestions( OUString(), suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(0), suggestions.size() );
+
+ trie.findSuggestions( "a", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(0), suggestions.size() );
+
+ trie.insert( "abc" );
+ trie.insert( "abcdefghijklmnopqrstuvwxyz" );
+ trie.findSuggestions( "a", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(2), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("abc"), suggestions[0] );
+ CPPUNIT_ASSERT_EQUAL( OUString("abcdefghijklmnopqrstuvwxyz"), suggestions[1] );
+ suggestions.clear();
+
+ trie.findSuggestions( "abc", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(1), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("abcdefghijklmnopqrstuvwxyz"), suggestions[0] );
+ suggestions.clear();
+
+ trie.findSuggestions( "abe", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(0), suggestions.size() );
+ suggestions.clear();
+
+ trie.insert( "abe" );
+ trie.findSuggestions( "", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(3), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("abc"), suggestions[0] );
+ CPPUNIT_ASSERT_EQUAL( OUString("abcdefghijklmnopqrstuvwxyz"), suggestions[1] );
+ CPPUNIT_ASSERT_EQUAL( OUString("abe"), suggestions[2] );
+ suggestions.clear();
+
+ trie.insert( "H31l0" );
+ trie.findSuggestions( "H", suggestions);
+
+ CPPUNIT_ASSERT_EQUAL( size_t(1), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("H31l0"), suggestions[0] );
+ suggestions.clear();
+
+ trie.insert( "H1" );
+ trie.findSuggestions( "H", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(2), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("H31l0"), suggestions[0] );
+ CPPUNIT_ASSERT_EQUAL( OUString("H1"), suggestions[1] );
+ suggestions.clear();
+
+ trie.findSuggestions( "H3", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(1), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("H31l0"), suggestions[0] );
+ suggestions.clear();
+
+ trie.insert( OStringToOUString( "H\xC3\xA4llo", RTL_TEXTENCODING_UTF8 ) );
+ trie.findSuggestions( "H", suggestions );
+ CPPUNIT_ASSERT_EQUAL( size_t(3), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("H31l0"), suggestions[0] );
+ CPPUNIT_ASSERT_EQUAL( OUString("H1"), suggestions[1] );
+ CPPUNIT_ASSERT_EQUAL( OStringToOUString( "H\xC3\xA4llo", RTL_TEXTENCODING_UTF8 ), suggestions[2] );
+ suggestions.clear();
+
+ trie.findSuggestions( "H3", suggestions );
+ CPPUNIT_ASSERT_EQUAL( size_t(1), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OUString("H31l0"), suggestions[0] );
+ suggestions.clear();
+
+ trie.findSuggestions( OStringToOUString("H\xC3\xA4", RTL_TEXTENCODING_UTF8), suggestions );
+ CPPUNIT_ASSERT_EQUAL( size_t(1), suggestions.size() );
+ CPPUNIT_ASSERT_EQUAL( OStringToOUString("H\xC3\xA4llo", RTL_TEXTENCODING_UTF8), suggestions[0] );
+ suggestions.clear();
+
+ trie.findSuggestions( "", suggestions);
+ CPPUNIT_ASSERT_EQUAL( size_t(6), suggestions.size() );
+ suggestions.clear();
+}
+
+void LookupTreeTest::testTrieGetAllEntries()
+{
+ editeng::Trie trie;
+
+ CPPUNIT_ASSERT_EQUAL( size_t(0), trie.size() );
+
+ trie.insert("A");
+ CPPUNIT_ASSERT_EQUAL( size_t(1), trie.size() );
+
+ trie.insert("B");
+ trie.insert("C");
+ CPPUNIT_ASSERT_EQUAL( size_t(3), trie.size() );
+
+ trie.insert("AA");
+ trie.insert("AAA");
+ CPPUNIT_ASSERT_EQUAL( size_t(5), trie.size() );
+}
+
+} // namespace end
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx
new file mode 100644
index 000000000..b98edae2b
--- /dev/null
+++ b/editeng/qa/unit/core-test.cxx
@@ -0,0 +1,1766 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_features.h>
+
+#include <test/bootstrapfixture.hxx>
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <editdoc.hxx>
+
+#include <sfx2/app.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/unofield.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/section.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <svl/srchitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+
+#include <com/sun/star/text/textfield/Type.hpp>
+
+#include <memory>
+#include <editeng/outliner.hxx>
+
+using namespace com::sun::star;
+
+namespace {
+
+class Test : public test::BootstrapFixture
+{
+public:
+ Test();
+
+ virtual void setUp() override;
+ virtual void tearDown() override;
+
+#if HAVE_MORE_FONTS
+ /// Test text portions position when percentage line spacing is set
+ void testLineSpacing();
+#endif
+
+ void testConstruction();
+
+ /// Test UNO service class that implements text field items.
+ void testUnoTextFields();
+
+ /// AutoCorrect tests
+ void testAutocorrect();
+
+ /// Test Copy/Paste with hyperlinks in text using Legacy Format
+ void testHyperlinkCopyPaste();
+
+ /// Test Copy/Paste using Legacy Format
+ void testCopyPaste();
+
+ /// Test Copy/Paste with selective selection over multiple paragraphs
+ void testMultiParaSelCopyPaste();
+
+ /// Test Copy/Paste with Tabs
+ void testTabsCopyPaste();
+
+ /// Test hyperlinks
+ void testHyperlinkSearch();
+
+ /// Test Copy/Paste with Bold/Italic text using Legacy Format
+ void testBoldItalicCopyPaste();
+
+ /// Test Copy/Paste with Underline text using Legacy Format
+ void testUnderlineCopyPaste();
+
+ /// Test Copy/Paste with multiple paragraphs
+ void testMultiParaCopyPaste();
+
+ /// Test Copy/Paste with multiple paragraphs having Bold/Italic text
+ void testParaBoldItalicCopyPaste();
+
+ void testParaStartCopyPaste();
+
+ void testSectionAttributes();
+
+ void testLargeParaCopyPaste();
+
+ void testTransliterate();
+
+ DECL_STATIC_LINK( Test, CalcFieldValueHdl, EditFieldInfo*, void );
+
+ CPPUNIT_TEST_SUITE(Test);
+#if HAVE_MORE_FONTS
+ CPPUNIT_TEST(testLineSpacing);
+#endif
+ CPPUNIT_TEST(testConstruction);
+ CPPUNIT_TEST(testUnoTextFields);
+ CPPUNIT_TEST(testAutocorrect);
+ CPPUNIT_TEST(testHyperlinkCopyPaste);
+ CPPUNIT_TEST(testCopyPaste);
+ CPPUNIT_TEST(testMultiParaSelCopyPaste);
+ CPPUNIT_TEST(testTabsCopyPaste);
+ CPPUNIT_TEST(testHyperlinkSearch);
+ CPPUNIT_TEST(testBoldItalicCopyPaste);
+ CPPUNIT_TEST(testUnderlineCopyPaste);
+ CPPUNIT_TEST(testMultiParaCopyPaste);
+ CPPUNIT_TEST(testParaBoldItalicCopyPaste);
+ CPPUNIT_TEST(testParaStartCopyPaste);
+ CPPUNIT_TEST(testSectionAttributes);
+ CPPUNIT_TEST(testLargeParaCopyPaste);
+ CPPUNIT_TEST(testTransliterate);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ EditEngineItemPool* mpItemPool;
+};
+
+Test::Test() : mpItemPool(nullptr) {}
+
+void Test::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mpItemPool = new EditEngineItemPool();
+
+ SfxApplication::GetOrCreate();
+}
+
+void Test::tearDown()
+{
+ SfxItemPool::Free(mpItemPool);
+ test::BootstrapFixture::tearDown();
+}
+
+#if HAVE_MORE_FONTS
+void Test::testLineSpacing()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine(mpItemPool);
+
+ if(aEditEngine.GetRefDevice()->GetDPIY() != 96
+ || aEditEngine.GetRefDevice()->GetDPIScaleFactor() != 1.0)
+ return;
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(0), rDoc.GetTextLen());
+ CPPUNIT_ASSERT_EQUAL(OUString(), rDoc.GetParaAsString(sal_Int32(0)));
+
+ // Set initial text
+ OUString aText = "This is multi-line paragraph";
+
+ sal_Int32 aTextLen = aText.getLength();
+ aEditEngine.SetText(aText);
+
+ // Assert changes - text insertion
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(aTextLen), rDoc.GetTextLen());
+ CPPUNIT_ASSERT_EQUAL(aText, rDoc.GetParaAsString(sal_Int32(0)));
+
+ // Select all paragraphs
+ ESelection aSelection(0, 0, 0, aTextLen);
+
+ auto doTest = [&](sal_uInt16 nSpace, sal_uInt16 nExpMaxAscent, sal_uInt32 nExpLineHeight)
+ {
+ std::unique_ptr<SfxItemSet> pSet(new SfxItemSet(aEditEngine.GetEmptyItemSet()));
+ SvxLineSpacingItem aLineSpacing(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aLineSpacing.SetPropLineSpace(nSpace);
+ pSet->Put(aLineSpacing);
+
+ // Set font
+ SvxFontItem aFont(EE_CHAR_FONTINFO);
+ aFont.SetFamilyName("Liberation Sans");
+ pSet->Put(aFont);
+ SvxFontHeightItem aFontSize(240, 100, EE_CHAR_FONTHEIGHT);
+ pSet->Put(aFontSize);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(3), pSet->Count());
+
+ aEditEngine.QuickSetAttribs(*pSet, aSelection);
+
+ // Assert changes
+ ParaPortion* pParaPortion = aEditEngine.GetParaPortions()[0];
+ ContentNode* const pNode = pParaPortion->GetNode();
+ const SvxLineSpacingItem& rLSItem = pNode->GetContentAttribs().GetItem(EE_PARA_SBL);
+ CPPUNIT_ASSERT_EQUAL(SvxInterLineSpaceRule::Prop, rLSItem.GetInterLineSpaceRule());
+ CPPUNIT_ASSERT_EQUAL(nSpace, rLSItem.GetPropLineSpace());
+
+ // Check the first line
+ ParagraphInfos aInfo = aEditEngine.GetParagraphInfos(0);
+ CPPUNIT_ASSERT_EQUAL(nExpMaxAscent, aInfo.nFirstLineMaxAscent);
+ CPPUNIT_ASSERT_EQUAL(nExpLineHeight, aEditEngine.GetLineHeight(0));
+ };
+
+ // Test first case - 60%
+ doTest(60, 122, 153);
+
+ // Force multiple lines
+ aEditEngine.SetPaperSize(Size(1000, 6000));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aEditEngine.GetLineCount(0));
+
+ // Test second case - 150%
+ doTest(150, 337, 382);
+
+ // Test lower Word limit - 6% (factor 0.06)
+ doTest(6, 12, 15);
+
+ // Test upper Word limit - 13200% (factor 132)
+ doTest(13200, 33615, 33660);
+}
+#endif
+
+void Test::testConstruction()
+{
+ EditEngine aEngine(mpItemPool);
+
+ OUString aParaText = "I am Edit Engine.";
+ aEngine.SetText(aParaText);
+}
+
+bool includes(const uno::Sequence<OUString>& rSeq, const OUString& rVal)
+{
+ for (OUString const & s : rSeq)
+ if (s == rVal)
+ return true;
+
+ return false;
+}
+
+void Test::testUnoTextFields()
+{
+ {
+ // DATE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::DATE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // URL
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::URL));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.URL");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // PAGE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::PAGE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.PageNumber");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // PAGES
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::PAGES));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.PageCount");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // TIME
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::TIME));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // FILE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::DOCINFO_TITLE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.docinfo.Title");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // TABLE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::TABLE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.SheetName");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // EXTENDED TIME
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::EXTENDED_TIME));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.DateTime");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // EXTENDED FILE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::EXTENDED_FILE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.FileName");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // AUTHOR
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::AUTHOR));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.Author");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // MEASURE
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::MEASURE));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.text.textfield.Measure");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // PRESENTATION HEADER
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::PRESENTATION_HEADER));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.Header");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // PRESENTATION FOOTER
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::PRESENTATION_FOOTER));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.Footer");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+
+ {
+ // PRESENTATION DATE TIME
+ rtl::Reference<SvxUnoTextField> xField(new SvxUnoTextField(text::textfield::Type::PRESENTATION_DATE_TIME));
+ uno::Sequence<OUString> aSvcs = xField->getSupportedServiceNames();
+ bool bGood = includes(aSvcs, "com.sun.star.presentation.textfield.DateTime");
+ CPPUNIT_ASSERT_MESSAGE("expected service is not present.", bGood);
+ }
+}
+
+class TestAutoCorrDoc : public SvxAutoCorrDoc
+{
+public:
+ /// just like the real thing, this dummy modifies the rText parameter :(
+ TestAutoCorrDoc(OUString &rText, LanguageType eLang)
+ : m_rText(rText)
+ , m_eLang(eLang)
+ {
+ }
+ OUString const& getResult() const
+ {
+ return m_rText;
+ }
+private:
+ OUString & m_rText;
+ LanguageType m_eLang;
+ virtual bool Delete( sal_Int32 nStt, sal_Int32 nEnd ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::Delete\n");
+ m_rText = m_rText.replaceAt(nStt, nEnd-nStt, "");
+ return true;
+ }
+ virtual bool Insert( sal_Int32 nPos, const OUString& rTxt ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::Insert\n");
+ m_rText = m_rText.replaceAt(nPos, 0, rTxt);
+ return true;
+ }
+ virtual bool Replace( sal_Int32 nPos, const OUString& rTxt ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::Replace\n");
+ return ReplaceRange( nPos, rTxt.getLength(), rTxt );
+ }
+ virtual bool ReplaceRange( sal_Int32 nPos, sal_Int32 nLen, const OUString& rTxt ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::ReplaceRange %d %d %s\n", nPos, nLen, OUStringToOString(rTxt, RTL_TEXTENCODING_UTF8).getStr());
+ m_rText = m_rText.replaceAt(nPos, nLen, rTxt);
+ return true;
+ }
+ virtual void SetAttr( sal_Int32, sal_Int32, sal_uInt16, SfxPoolItem& ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::SetAttr\n");
+ }
+ virtual bool SetINetAttr( sal_Int32, sal_Int32, const OUString& ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::SetINetAttr\n");
+ return true;
+ }
+ virtual OUString const* GetPrevPara(bool) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::GetPrevPara\n");
+ return nullptr;
+ }
+ virtual bool ChgAutoCorrWord( sal_Int32& rSttPos,
+ sal_Int32 nEndPos, SvxAutoCorrect& rACorrect,
+ OUString* pPara ) override
+ {
+ //fprintf(stderr, "TestAutoCorrDoc::ChgAutoCorrWord\n");
+
+ if (m_rText.isEmpty())
+ return false;
+
+ LanguageTag aLanguageTag( m_eLang);
+ const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList(
+ m_rText, rSttPos, nEndPos, *this, aLanguageTag);
+ if (pFnd && pFnd->IsTextOnly())
+ {
+ m_rText = m_rText.replaceAt(rSttPos, nEndPos, pFnd->GetLong());
+ if( pPara )
+ pPara->clear(); // =&pCurNode->GetString();
+ return true;
+ }
+
+ return false;
+ }
+ virtual bool TransliterateRTLWord( sal_Int32& /*rSttPos*/, sal_Int32 /*nEndPos*/ ) override
+ {
+ return false;
+ }
+};
+
+//https://bugs.libreoffice.org/show_bug.cgi?id=55693
+//Two capitalized letters are not corrected if dash or slash are directly
+//before the two letters
+void Test::testAutocorrect()
+{
+ SvxAutoCorrect aAutoCorrect((OUString()), (OUString()));
+
+ {
+ OUString sInput("TEst-TEst");
+ sal_Unicode const cNextChar(' ');
+ OUString const sExpected("Test-Test ");
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("autocorrect", sExpected, aFoo.getResult());
+ }
+
+ {
+ OUString sInput("TEst/TEst");
+ sal_Unicode const cNextChar(' ');
+ OUString const sExpected("Test/Test ");
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("autocorrect", sExpected, aFoo.getResult());
+ }
+
+ {
+ // test auto-bolding with '*'
+ OUString sInput("*foo");
+ sal_Unicode const cNextChar('*');
+ OUString const sExpected("foo");
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+
+ CPPUNIT_ASSERT_EQUAL(sExpected, aFoo.getResult());
+ }
+
+ {
+ OUString sInput("Test. test");
+ sal_Unicode const cNextChar(' ');
+ OUString const sExpected("Test. Test ");
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("autocorrect", sExpected, aFoo.getResult());
+ }
+
+ // don't autocapitalize after a field mark
+ {
+ OUString sInput("Test. \x01 test");
+ sal_Unicode const cNextChar(' ');
+ OUString const sExpected("Test. \x01 test ");
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("autocorrect", sExpected, aFoo.getResult());
+ }
+
+ // consider field contents as text for auto quotes
+ {
+ OUString sInput("T\x01");
+ sal_Unicode const cNextChar('"');
+ const sal_Unicode EXPECTED[] = { 'T', 0x01, 0x0201d };
+ OUString sExpected(EXPECTED, SAL_N_ELEMENTS(EXPECTED));
+ bool bNbspRunNext = false;
+
+ TestAutoCorrDoc aFoo(sInput, LANGUAGE_ENGLISH_US);
+ aAutoCorrect.SetAutoCorrFlag(ACFlags::ChgQuotes, true);
+ aAutoCorrect.DoAutoCorrect(aFoo, sInput, sInput.getLength(), cNextChar, true, bNbspRunNext);
+ fprintf(stderr, "text is %x\n", aFoo.getResult()[aFoo.getResult().getLength() - 1]);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("autocorrect", sExpected, aFoo.getResult());
+ }
+
+}
+
+IMPL_STATIC_LINK( Test, CalcFieldValueHdl, EditFieldInfo*, pInfo, void )
+{
+ if (!pInfo)
+ return;
+
+ const SvxFieldItem& rField = pInfo->GetField();
+ const SvxFieldData* pField = rField.GetField();
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ // URLField
+ OUString aURL = pURLField->GetURL();
+ switch ( pURLField->GetFormat() )
+ {
+ case SvxURLFormat::AppDefault:
+ case SvxURLFormat::Repr:
+ {
+ pInfo->SetRepresentation( pURLField->GetRepresentation() );
+ }
+ break;
+
+ case SvxURLFormat::Url:
+ {
+ pInfo->SetRepresentation( aURL );
+ }
+ break;
+ }
+ }
+ else
+ {
+ OSL_FAIL("Unknown Field");
+ pInfo->SetRepresentation(OUString('?'));
+ }
+}
+
+void Test::testHyperlinkCopyPaste()
+{
+ // Create Outliner instance
+ Outliner aOutliner(mpItemPool, OutlinerMode
+::TextObject);
+ aOutliner.SetCalcFieldValueHdl( LINK( nullptr, Test, CalcFieldValueHdl ) );
+
+ // Create EditEngine's instance
+ EditEngine& aEditEngine = const_cast<EditEngine&> (aOutliner.GetEditEngine());
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // New instance must be empty - no initial text
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Get corresponding Field Item for inserting URLs in text
+ // URL 1
+ OUString aURL1 = "mailto:///user@example.com";
+ OUString aRepres1 = "user@example.com";
+ SvxURLField aURLField1( aURL1, aRepres1, SvxURLFormat::Repr );
+ SvxFieldItem aField1( aURLField1, EE_FEATURE_FIELD );
+ // URL 2
+ OUString aURL2 = "mailto:///example@domain.com";
+ OUString aRepres2 = "example@domain.com";
+ SvxURLField aURLField2( aURL2, aRepres2, SvxURLFormat::Repr );
+ SvxFieldItem aField2( aURLField2, EE_FEATURE_FIELD );
+
+ // Insert initial text
+ OUString aParaText = "sampletextfortestingfeaturefields";
+ // Positions Ref .............*13....*20..........
+ sal_Int32 aTextLen = aParaText.getLength();
+ aEditEngine.SetText( aParaText );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aParaText, rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert URL 1
+ ContentNode *pNode = rDoc.GetObject(0);
+ EditSelection aSel1( EditPaM(pNode, 13), EditPaM(pNode, 13) );
+ aEditEngine.InsertField( aSel1, aField1 );
+
+ // Assert Field Count
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(1), aEditEngine.GetFieldCount(0) );
+
+ // Insert URL 2
+ EditSelection aSel2( EditPaM(pNode, 20 + 1), EditPaM(pNode, 20 + 1) );
+ aEditEngine.InsertField( aSel2, aField2 );
+
+ // Assert Field Count
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(2), aEditEngine.GetFieldCount(0) );
+
+ // Assert URL Fields and text before copy
+ // Check text
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aRepres1.getLength() + aRepres2.getLength()), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString("sampletextforuser@example.comtestingexample@domain.comfeaturefields"), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Check Field 1
+ EFieldInfo aURLFieldInfo1 = aEditEngine.GetFieldInfo( sal_Int32(0), sal_uInt16(0) );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(13), aURLFieldInfo1.aPosition.nIndex );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(EE_FEATURE_FIELD), aURLFieldInfo1.pFieldItem->Which() );
+ SvxURLField* pURLField1 = dynamic_cast<SvxURLField*> ( const_cast<SvxFieldData*> (aURLFieldInfo1.pFieldItem->GetField()) );
+ CPPUNIT_ASSERT(pURLField1);
+ CPPUNIT_ASSERT_EQUAL( aURL1, pURLField1->GetURL() );
+ CPPUNIT_ASSERT_EQUAL( aRepres1, pURLField1->GetRepresentation() );
+
+ // Check Field 2
+ EFieldInfo aURLFieldInfo2 = aEditEngine.GetFieldInfo( sal_Int32(0), sal_uInt16(1) );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(21), aURLFieldInfo2.aPosition.nIndex );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(EE_FEATURE_FIELD), aURLFieldInfo2.pFieldItem->Which() );
+ SvxURLField* pURLField2 = dynamic_cast<SvxURLField*> ( const_cast<SvxFieldData*> (aURLFieldInfo2.pFieldItem->GetField()) );
+ CPPUNIT_ASSERT(pURLField2);
+ CPPUNIT_ASSERT_EQUAL( aURL2, pURLField2->GetURL() );
+ CPPUNIT_ASSERT_EQUAL( aRepres2, pURLField2->GetRepresentation() );
+
+ // Copy text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,10,0,21) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert Changes ACP, ACP: after Copy/Paste
+
+ // Check the fields count
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(3), aEditEngine.GetFieldCount(0) );
+
+ // Check the updated text length
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + 10 + aRepres1.getLength()*2 + aRepres2.getLength()), rDoc.GetTextLen() );
+
+ // Check the updated text contents
+ CPPUNIT_ASSERT_EQUAL( OUString("sampletextforuser@example.comtestingexample@domain.comfeaturefieldsforuser@example.comtesting"), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Check the Fields and their values
+
+ // Field 1
+ EFieldInfo aACPURLFieldInfo1 = aEditEngine.GetFieldInfo( sal_Int32(0), sal_uInt16(0) );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(13), aACPURLFieldInfo1.aPosition.nIndex );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(EE_FEATURE_FIELD), aACPURLFieldInfo1.pFieldItem->Which() );
+ SvxURLField* pACPURLField1 = dynamic_cast<SvxURLField*> ( const_cast<SvxFieldData*> (aACPURLFieldInfo1.pFieldItem->GetField()) );
+ CPPUNIT_ASSERT(pACPURLField1);
+ CPPUNIT_ASSERT_EQUAL( aURL1, pACPURLField1->GetURL() );
+ CPPUNIT_ASSERT_EQUAL( aRepres1, pACPURLField1->GetRepresentation() );
+
+ // Field 2
+ EFieldInfo aACPURLFieldInfo2 = aEditEngine.GetFieldInfo( sal_Int32(0), sal_uInt16(1) );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(21), aACPURLFieldInfo2.aPosition.nIndex );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(EE_FEATURE_FIELD), aACPURLFieldInfo2.pFieldItem->Which() );
+ SvxURLField* pACPURLField2 = dynamic_cast<SvxURLField*> ( const_cast<SvxFieldData*> (aACPURLFieldInfo2.pFieldItem->GetField()) );
+ CPPUNIT_ASSERT(pACPURLField2);
+ CPPUNIT_ASSERT_EQUAL( aURL2, pACPURLField2->GetURL() );
+ CPPUNIT_ASSERT_EQUAL( aRepres2, pACPURLField2->GetRepresentation() ) ;
+
+ // Field 3
+ EFieldInfo aACPURLFieldInfo3 = aEditEngine.GetFieldInfo( sal_Int32(0), sal_uInt16(2) );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(38), aACPURLFieldInfo3.aPosition.nIndex );
+ CPPUNIT_ASSERT_EQUAL( sal_uInt16(EE_FEATURE_FIELD), aACPURLFieldInfo3.pFieldItem->Which() );
+ SvxURLField* pACPURLField3 = dynamic_cast<SvxURLField*> ( const_cast<SvxFieldData*> (aACPURLFieldInfo3.pFieldItem->GetField()) );
+ CPPUNIT_ASSERT(pACPURLField3);
+ CPPUNIT_ASSERT_EQUAL( aURL1, pACPURLField3->GetURL() );
+ CPPUNIT_ASSERT_EQUAL( aRepres1, pACPURLField3->GetRepresentation() );
+}
+
+void Test::testCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Set initial text
+ OUString aText = "This is custom initial text";
+ sal_Int32 aTextLen = aText.getLength();
+ aEditEngine.SetText( aText );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aText, rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Copy initial text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,0,0,aTextLen) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(aText + aText), rDoc.GetParaAsString(sal_Int32(0)) );
+}
+
+void Test::testMultiParaSelCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert initial text
+ OUString aFirstPara = "This is first paragraph";
+ // Selection Ref ........8..............
+ OUString aSecondPara = "This is second paragraph";
+ // Selection Ref .............14.........
+ OUString aThirdPara = "This is third paragraph";
+ OUString aText = aFirstPara + "\n" + aSecondPara + "\n" + aThirdPara;
+ sal_Int32 aTextLen = aFirstPara.getLength() + aSecondPara.getLength() + aThirdPara.getLength();
+ aEditEngine.SetText( aText );
+ OUString aCopyText = "first paragraphThis is second";
+ sal_Int32 aCopyTextLen = aCopyText.getLength();
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+
+ // Copy initial text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,8,1,14) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ OUString aThirdParaAfterCopyPaste = aThirdPara + "first paragraph";
+ OUString aFourthPara = "This is second";
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aCopyTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aFourthPara, rDoc.GetParaAsString(sal_Int32(3)) );
+}
+
+void Test::testTabsCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // New instance must be empty - no initial text
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Get corresponding Item for inserting tabs in the text
+ SfxVoidItem aTab( EE_FEATURE_TAB );
+
+ // Insert initial text
+ OUString aParaText = "sampletextfortestingtab";
+ // Positions Ref ......*6...............*23
+ sal_Int32 aTextLen = aParaText.getLength();
+ aEditEngine.SetText( aParaText );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aParaText, rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert tab 1 at desired position
+ ContentNode *pNode = rDoc.GetObject(0);
+ EditSelection aSel1( EditPaM(pNode, 6), EditPaM(pNode, 6) );
+ aEditEngine.InsertFeature( aSel1, aTab );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + 1), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString("sample\ttextfortestingtab"), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert tab 2 at desired position
+ EditSelection aSel2( EditPaM(pNode, 23+1), EditPaM(pNode, 23+1) );
+ aEditEngine.InsertFeature( aSel2, aTab );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + 2), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString("sample\ttextfortestingtab\t"), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Copy text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,6,0,aTextLen+2) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aTextLen - 6 + 4 ), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString("sample\ttextfortestingtab\t\ttextfortestingtab\t"), rDoc.GetParaAsString(sal_Int32(0)) );
+}
+
+class UrlEditEngine : public EditEngine
+{
+public:
+ explicit UrlEditEngine(SfxItemPool *pPool) : EditEngine(pPool) {}
+
+ virtual OUString CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>& ) override
+ {
+ return "jim@bob.com"; // a sophisticated view of value:
+ }
+};
+
+// Odd accounting for hyperlink position & size etc.
+// https://bugzilla.novell.com/show_bug.cgi?id=467459
+void Test::testHyperlinkSearch()
+{
+ UrlEditEngine aEngine(mpItemPool);
+ EditDoc &rDoc = aEngine.GetEditDoc();
+
+ OUString aSampleText = "Please write email to . if you find a fish(not a dog).";
+ aEngine.SetText(aSampleText);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("set text", aSampleText, rDoc.GetParaAsString(sal_Int32(0)));
+
+ ContentNode *pNode = rDoc.GetObject(0);
+ EditSelection aSel(EditPaM(pNode, 22), EditPaM(pNode, 22));
+ SvxURLField aURLField("mailto:///jim@bob.com", "jim@bob.com",
+ SvxURLFormat::Repr);
+ SvxFieldItem aField(aURLField, EE_FEATURE_FIELD);
+
+ aEngine.InsertField(aSel, aField);
+
+ OUString aContent = pNode->GetExpandedText();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("get text", OUString("Please write email to jim@bob.com. if you find a fish(not a dog)."),
+ aContent);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong length", static_cast<sal_uLong>(aContent.getLength()), rDoc.GetTextLen());
+
+ // Check expansion and positioning re-work
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong length", static_cast<sal_uLong>(aContent.getLength()),
+ pNode->GetExpandedLen());
+ for (sal_Int32 n = 0; n < aContent.getLength(); n++)
+ {
+ sal_Int32 nStart = n, nEnd = n;
+ pNode->UnExpandPositions(nStart,nEnd);
+ CPPUNIT_ASSERT_MESSAGE("out of bound start", nStart < pNode->Len());
+ CPPUNIT_ASSERT_MESSAGE("out of bound end", nEnd <= pNode->Len());
+ }
+
+ static const struct {
+ sal_Int32 mnStart, mnEnd;
+ sal_Int32 mnNewStart, mnNewEnd;
+ } aTrickyOnes[] = {
+ { 0, 1, /* -> */ 0, 1 },
+ { 21, 25, /* -> */ 21, 23 }, // the field is really just one char
+ { 25, 27, /* -> */ 22, 23 },
+ { 50, 56, /* -> */ 40, 46 }
+ };
+ for (size_t n = 0; n < SAL_N_ELEMENTS(aTrickyOnes); n++)
+ {
+ sal_Int32 nStart = aTrickyOnes[n].mnStart;
+ sal_Int32 nEnd = aTrickyOnes[n].mnEnd;
+ pNode->UnExpandPositions(nStart,nEnd);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in row " + OString::number(n)).getStr(),
+ aTrickyOnes[n].mnNewStart, nStart);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in row " + OString::number(n)).getStr(),
+ aTrickyOnes[n].mnNewEnd, nEnd);
+ }
+
+ SvxSearchItem aItem(1); //SID_SEARCH_ITEM);
+ aItem.SetBackward(false);
+ aItem.SetSelection(false);
+ aItem.SetSearchString("fish");
+ CPPUNIT_ASSERT_MESSAGE("no fish", aEngine.HasText(aItem));
+ aItem.SetSearchString("dog");
+ CPPUNIT_ASSERT_MESSAGE("no dog", aEngine.HasText(aItem));
+}
+
+bool hasBold(const editeng::Section& rSecAttr)
+{
+ return std::any_of(rSecAttr.maAttributes.begin(), rSecAttr.maAttributes.end(),
+ [](const SfxPoolItem* p) {
+ return p->Which() == EE_CHAR_WEIGHT
+ && static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
+ });
+}
+
+bool hasItalic(const editeng::Section& rSecAttr)
+{
+ return std::any_of(rSecAttr.maAttributes.begin(), rSecAttr.maAttributes.end(),
+ [](const SfxPoolItem* p) {
+ return p->Which() == EE_CHAR_ITALIC
+ && static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
+ });
+}
+
+void Test::testBoldItalicCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // New instance must be empty - no initial text
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Get corresponding ItemSet for inserting Bold/Italic text
+ std::unique_ptr<SfxItemSet> pSet( new SfxItemSet(aEditEngine.GetEmptyItemSet()) );
+ SvxWeightItem aBold( WEIGHT_BOLD, EE_CHAR_WEIGHT );
+ SvxPostureItem aItalic( ITALIC_NORMAL, EE_CHAR_ITALIC );
+
+ // Insert initial text
+ OUString aParaText = "boldeditengineitalic";
+ // Positions Ref ..*2....*8...*13.*17
+ // Bold Ref ..[ BOLD ]......
+ // Italic Ref ........[ ITALIC ]..
+ sal_Int32 aTextLen = aParaText.getLength();
+ aEditEngine.SetText( aParaText );
+
+ // Assert changes - text insertion
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aParaText, rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Apply Bold to appropriate selection
+ pSet->Put(aBold);
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1), pSet->Count() );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(0,2,0,14) );
+
+ // Assert changes
+ std::unique_ptr<EditTextObject> pEditText1( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs1;
+ pEditText1->GetAllSections( aAttrs1 );
+ // There should be 3 sections - woBold - wBold - woBold (w - with, wo - without)
+ CPPUNIT_ASSERT_EQUAL( size_t(3), aAttrs1.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs1[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs1[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs1[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs1[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs1[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 20, static_cast<int>(aAttrs1[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].maAttributes.size()) );
+
+ // Apply Italic to appropriate selection
+ pSet.reset( new SfxItemSet(aEditEngine.GetEmptyItemSet()) );
+ pSet->Put(aItalic);
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1), pSet->Count() );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(0,8,0,18) );
+
+ // Assert changes
+ std::unique_ptr<EditTextObject> pEditText2( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs2;
+ pEditText2->GetAllSections( aAttrs2 );
+ // There should be 5 sections - woBold&woItalic - wBold&woItalic - wBold&wItalic - woBold&wItalic - woBold&woItalic (w - with, wo - without)
+ CPPUNIT_ASSERT_EQUAL( size_t(5), aAttrs2.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 8, static_cast<int>(aAttrs2[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs2[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 8, static_cast<int>(aAttrs2[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs2[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[2].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs2[2]) && hasItalic(aAttrs2[2]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs2[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[3].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs2[3]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[4].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[4].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 20, static_cast<int>(aAttrs2[4].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[4].maAttributes.size()) );
+
+ // Copy text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,1,0,aTextLen-1) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aTextLen - 2), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(aParaText + "oldeditengineitali" ), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Check updated text for appropriate Bold/Italics
+ std::unique_ptr<EditTextObject> pEditText3( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs3;
+ pEditText3->GetAllSections( aAttrs3 );
+ // There should be 9 sections - woBold&woItalic - wBold&woItalic - wBold&wItalic - woBold&wItalic - woBold&woItalic - wBold&woItalic
+ // - wBold&wItalic - woBold&wItalic - woBold&woItalic(w - with, wo - without)
+ CPPUNIT_ASSERT_EQUAL( size_t(9), aAttrs3.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 8, static_cast<int>(aAttrs3[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 8, static_cast<int>(aAttrs3[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs3[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[2].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[2]) && hasItalic(aAttrs3[2]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs3[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs3[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[3].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[3]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[4].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs3[4].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 21, static_cast<int>(aAttrs3[4].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[4].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[5].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 21, static_cast<int>(aAttrs3[5].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 27, static_cast<int>(aAttrs3[5].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[5].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[5]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[6].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 27, static_cast<int>(aAttrs3[6].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 33, static_cast<int>(aAttrs3[6].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[6].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[6]) && hasItalic(aAttrs3[6]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[7].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 33, static_cast<int>(aAttrs3[7].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 37, static_cast<int>(aAttrs3[7].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[7].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[7]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[8].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 37, static_cast<int>(aAttrs3[8].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 38, static_cast<int>(aAttrs3[8].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[8].maAttributes.size()) );
+}
+
+// Auxiliary function to test Underline text Copy/Paste using Legacy Format
+bool hasUnderline(const editeng::Section& rSecAttr)
+{
+ return std::any_of(rSecAttr.maAttributes.begin(), rSecAttr.maAttributes.end(),
+ [](const SfxPoolItem* p) {
+ return p->Which() == EE_CHAR_UNDERLINE
+ && static_cast<const SvxUnderlineItem*>(p)->GetLineStyle() == LINESTYLE_SINGLE;
+ });
+}
+
+void Test::testUnderlineCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // New instance must be empty - no initial text
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Get corresponding ItemSet for inserting Underline text
+ std::unique_ptr<SfxItemSet> pSet( new SfxItemSet(aEditEngine.GetEmptyItemSet()) );
+ SvxUnderlineItem aULine( LINESTYLE_SINGLE, EE_CHAR_UNDERLINE );
+
+ // Insert initial text
+ OUString aParaText = "sampletextforunderline";
+ // Positions Ref ......*6.........*17..
+ // Underline Ref ......[UNDERLINE ]....
+ sal_Int32 aTextLen = aParaText.getLength();
+ aEditEngine.SetText( aParaText );
+
+ // Apply Underline style
+ pSet->Put( aULine );
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1), pSet->Count() );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(0,6,0,18) );
+
+ // Assert changes
+ std::unique_ptr<EditTextObject> pEditText1( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs1;
+ pEditText1->GetAllSections( aAttrs1 );
+
+ // There should be 3 sections - woUnderline - wUnderline - woUnderline (w - with, wo - without)
+ CPPUNIT_ASSERT_EQUAL( size_t(3), aAttrs1.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 6, static_cast<int>(aAttrs1[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 6, static_cast<int>(aAttrs1[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs1[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be underlined.", hasUnderline(aAttrs1[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs1[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 22, static_cast<int>(aAttrs1[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].maAttributes.size()) );
+
+ // Copy text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,6,0,aTextLen-4) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + (OUString("textforunder")).getLength()), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(aParaText + "textforunder" ), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Check updated text for appropriate Underline
+ std::unique_ptr<EditTextObject> pEditText2( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs2;
+ pEditText2->GetAllSections( aAttrs2 );
+
+ // There should be 4 sections - woUnderline - wUnderline - woUnderline - wUnderline (w - with, wo - without)
+ CPPUNIT_ASSERT_EQUAL( size_t(4), aAttrs2.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 6, static_cast<int>(aAttrs2[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 6, static_cast<int>(aAttrs2[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be underlined.", hasUnderline(aAttrs2[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 22, static_cast<int>(aAttrs2[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[2].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 22, static_cast<int>(aAttrs2[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 34, static_cast<int>(aAttrs2[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[3].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be underlined.", hasUnderline(aAttrs2[3]) );
+}
+
+void Test::testMultiParaCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert initial text
+ OUString aFirstPara = "This is first paragraph";
+ OUString aSecondPara = "This is second paragraph";
+ OUString aThirdPara = "This is third paragraph";
+ OUString aText = aFirstPara + "\n" + aSecondPara + "\n" + aThirdPara;
+ sal_Int32 aTextLen = aFirstPara.getLength() + aSecondPara.getLength() + aThirdPara.getLength();
+ aEditEngine.SetText( aText );
+ sal_Int32 aCopyTextLen = aFirstPara.getLength() + aSecondPara.getLength();
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+
+ // Copy initial text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,0,1,aSecondPara.getLength()) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ OUString aThirdParaAfterCopyPaste = aThirdPara + aFirstPara;
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aCopyTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(3)) );
+}
+
+void Test::testParaBoldItalicCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Get corresponding ItemSet for inserting Bold/Italic text
+ std::unique_ptr<SfxItemSet> pSet( new SfxItemSet(aEditEngine.GetEmptyItemSet()) );
+ SvxWeightItem aBold( WEIGHT_BOLD, EE_CHAR_WEIGHT );
+ SvxPostureItem aItalic( ITALIC_NORMAL, EE_CHAR_ITALIC );
+
+ // Insert initial text
+ OUString aFirstPara = "This is first paragraph";
+ // Positions Ref .....*5.*8....*14*17...
+ // Bold Ref .....[ BOLD ].....
+ // Italic Ref ..............[ ITA
+ // Copy Ref ........[ Copy Sel
+ OUString aSecondPara = "This is second paragraph";
+ // Positions Ref .....*5.*8...*13..*18...
+ // Bold Ref .....[ BOLD ].....
+ // Italic Ref LIC ]...............
+ // Copy Ref ection ]..........
+ OUString aThirdPara = "This is third paragraph";
+ OUString aText = aFirstPara + "\n" + aSecondPara + "\n" + aThirdPara;
+ sal_Int32 aTextLen = aFirstPara.getLength() + aSecondPara.getLength() + aThirdPara.getLength();
+ aEditEngine.SetText( aText );
+ OUString aCopyText = "first paragraphThis is second";
+ sal_Int32 aCopyTextLen = aCopyText.getLength();
+
+ // Assert changes - text insertion
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+
+ // Apply Bold to appropriate selections
+ pSet->Put(aBold);
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1), pSet->Count() );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(0,5,0,18) );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(1,5,1,19) );
+
+ // Assert changes
+ std::unique_ptr<EditTextObject> pEditText1( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs1;
+ pEditText1->GetAllSections( aAttrs1 );
+ // There should be 7 sections - woB - wB - woB -woB -wB -woB -woB (w - with, wo - without, B - Bold, I - Italic)
+ CPPUNIT_ASSERT_EQUAL( size_t(7), aAttrs1.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs1[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs1[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs1[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs1[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs1[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs1[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[2].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs1[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[3].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[4].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs1[4].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs1[4].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[4].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs1[4]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs1[5].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs1[5].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 24, static_cast<int>(aAttrs1[5].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[5].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs1[6].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[6].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs1[6].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs1[6].maAttributes.size()) );
+
+ // Apply Italic to appropriate selection
+ pSet.reset( new SfxItemSet(aEditEngine.GetEmptyItemSet()) );
+ pSet->Put(aItalic);
+ CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1), pSet->Count() );
+ aEditEngine.QuickSetAttribs( *pSet, ESelection(0,14,1,9) );
+
+ // Assert changes
+ std::unique_ptr<EditTextObject> pEditText2( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs2;
+ pEditText2->GetAllSections( aAttrs2 );
+ // There should be 9 sections - woB&woI - wB&woI - wB&wI -woB&wI - woB&wI - wB&wI - wB&woI - woB&woI - woB&woI (w - with, wo - without, B - Bold, I - Italic)
+ CPPUNIT_ASSERT_EQUAL( size_t(9), aAttrs2.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs2[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs2[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs2[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs2[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs2[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[2].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs2[2]) && hasItalic(aAttrs2[2]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs2[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs2[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[3].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs2[3]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[4].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[4].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs2[4].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[4].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs2[4]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[5].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs2[5].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs2[5].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[5].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs2[5]) && hasItalic(aAttrs2[5]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[6].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs2[6].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs2[6].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[6].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs2[6]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs2[7].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs2[7].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 24, static_cast<int>(aAttrs2[7].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[7].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs2[8].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[8].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs2[8].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs2[8].maAttributes.size()) );
+
+ // Copy text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,8,1,14) );
+
+ // Paste text at the end
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetEndPaM(), true );
+
+ // Assert changes
+ OUString aThirdParaAfterCopyPaste = aThirdPara + "first paragraph";
+ OUString aFourthParaAfterCopyPaste = "This is second";
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aCopyTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aFourthParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(3)) );
+
+ // Check updated text for appropriate Bold/Italics
+ std::unique_ptr<EditTextObject> pEditText3( aEditEngine.CreateTextObject() );
+ std::vector<editeng::Section> aAttrs3;
+ pEditText3->GetAllSections( aAttrs3 );
+ // There should be 15 sections - woB&woI - wB&woI - wB&wI -woB&wI - woB&wI - wB&wI - wB&woI - woB&woI - woB&woI
+ // - wB&woI - wB&wI - woB&wI - -woB&wI - wB&wI - wB&woI (w - with, wo - without, B - Bold, I - Italic)
+ CPPUNIT_ASSERT_EQUAL( size_t(15), aAttrs3.size() );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[0].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[0].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[1].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[1].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs3[1].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[1].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[1]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[2].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs3[2].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs3[2].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[2].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[2]) && hasItalic(aAttrs3[2]) );
+
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[3].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 18, static_cast<int>(aAttrs3[3].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs3[3].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[3].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[3]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[4].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[4].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[4].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[4].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[4]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[5].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[5].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs3[5].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[5].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[5]) && hasItalic(aAttrs3[5]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[6].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs3[6].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs3[6].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[6].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[6]) );
+
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[7].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 19, static_cast<int>(aAttrs3[7].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 24, static_cast<int>(aAttrs3[7].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[7].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[8].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[8].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs3[8].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[8].maAttributes.size()) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[9].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 23, static_cast<int>(aAttrs3[9].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 29, static_cast<int>(aAttrs3[9].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[9].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[9]) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[10].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 29, static_cast<int>(aAttrs3[10].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 33, static_cast<int>(aAttrs3[10].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[10].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[10]) && hasItalic(aAttrs3[10]) );
+
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[11].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 33, static_cast<int>(aAttrs3[11].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 38, static_cast<int>(aAttrs3[11].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[11].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[11]) );
+
+ CPPUNIT_ASSERT_EQUAL( 3, static_cast<int>(aAttrs3[12].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 0, static_cast<int>(aAttrs3[12].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[12].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[12].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be italic.", hasItalic(aAttrs3[12]) );
+
+ CPPUNIT_ASSERT_EQUAL( 3, static_cast<int>(aAttrs3[13].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 5, static_cast<int>(aAttrs3[13].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs3[13].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aAttrs3[13].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold and italic.", hasBold(aAttrs3[13]) && hasItalic(aAttrs3[13]) );
+
+ CPPUNIT_ASSERT_EQUAL( 3, static_cast<int>(aAttrs3[14].mnParagraph) );
+ CPPUNIT_ASSERT_EQUAL( 9, static_cast<int>(aAttrs3[14].mnStart) );
+ CPPUNIT_ASSERT_EQUAL( 14, static_cast<int>(aAttrs3[14].mnEnd) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(aAttrs3[14].maAttributes.size()) );
+ CPPUNIT_ASSERT_MESSAGE( "This section must be bold.", hasBold(aAttrs3[14]) );
+}
+
+void Test::testParaStartCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert initial text
+ OUString aFirstPara = "This is first paragraph";
+ // Selection Ref ........8..............
+ OUString aSecondPara = "This is second paragraph";
+ // Selection Ref .............14.........
+ OUString aThirdPara = "This is third paragraph";
+ OUString aText = aFirstPara + "\n" + aSecondPara + "\n" + aThirdPara;
+ sal_Int32 aTextLen = aFirstPara.getLength() + aSecondPara.getLength() + aThirdPara.getLength();
+ aEditEngine.SetText( aText );
+ OUString aCopyText = "first paragraphThis is second";
+ sal_Int32 aCopyTextLen = aCopyText.getLength();
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+
+ // Copy initial text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(0,8,1,14) );
+
+ // Paste text at the start
+ aEditEngine.InsertText( xData, OUString(), rDoc.GetStartPaM(), true );
+
+ // Assert changes
+ OUString aFirstParaAfterCopyPaste = "first paragraph";
+ OUString aSecondParaAfterCopyPaste = "This is second" + aFirstPara;
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aCopyTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(3)) );
+}
+
+void Test::testSectionAttributes()
+{
+ EditEngine aEngine(mpItemPool);
+
+ std::unique_ptr<SfxItemSet> pSet(new SfxItemSet(aEngine.GetEmptyItemSet()));
+ SvxWeightItem aBold(WEIGHT_BOLD, EE_CHAR_WEIGHT);
+ SvxPostureItem aItalic(ITALIC_NORMAL, EE_CHAR_ITALIC);
+
+ {
+ OUString aParaText = "aaabbbccc";
+ aEngine.SetText(aParaText);
+ pSet->Put(aBold);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be exactly one item.", static_cast<sal_uInt16>(1), pSet->Count());
+ aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,6)); // 'aaabbb' - end point is not inclusive.
+ pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
+ pSet->Put(aItalic);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be exactly one item.", static_cast<sal_uInt16>(1), pSet->Count());
+
+ aEngine.QuickSetAttribs(*pSet, ESelection(0,3,0,9)); // 'bbbccc'
+ std::unique_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
+ CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText);
+ std::vector<editeng::Section> aAttrs;
+ pEditText->GetAllSections(aAttrs);
+
+ // Now, we should have a total of 3 sections.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 3 sections.", static_cast<size_t>(3), aAttrs.size());
+
+ // First section should be 0-3 of paragraph 0, and it should only have boldness applied.
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnStart));
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(aAttrs[0].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[0].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(aAttrs[0]));
+
+ // Second section should be 3-6, and it should be both bold and italic.
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[1].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(aAttrs[1].mnStart));
+ CPPUNIT_ASSERT_EQUAL(6, static_cast<int>(aAttrs[1].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(aAttrs[1].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be bold and italic.", hasBold(aAttrs[1]) && hasItalic(aAttrs[1]));
+
+ // Third section should be 6-9, and it should be only italic.
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[2].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(6, static_cast<int>(aAttrs[2].mnStart));
+ CPPUNIT_ASSERT_EQUAL(9, static_cast<int>(aAttrs[2].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[2].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be italic.", hasItalic(aAttrs[2]));
+ }
+
+ {
+ // Set text consisting of 5 paragraphs with the 2nd and 4th paragraphs
+ // being empty.
+ aEngine.Clear();
+ aEngine.SetText("one\n\ntwo\n\nthree");
+ sal_Int32 nParaCount = aEngine.GetParagraphCount();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), nParaCount);
+
+ // Apply boldness to paragraphs 1, 3, 5 only. Leave 2 and 4 unformatted.
+ pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
+ pSet->Put(aBold);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be exactly one item.", static_cast<sal_uInt16>(1), pSet->Count());
+ aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,3));
+ aEngine.QuickSetAttribs(*pSet, ESelection(2,0,2,3));
+ aEngine.QuickSetAttribs(*pSet, ESelection(4,0,4,5));
+
+ std::unique_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
+ CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText);
+ std::vector<editeng::Section> aAttrs;
+ pEditText->GetAllSections(aAttrs);
+ CPPUNIT_ASSERT_EQUAL(size_t(5), aAttrs.size());
+
+ // 1st, 3rd and 5th sections should correspond with 1st, 3rd and 5th paragraphs.
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnStart));
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(aAttrs[0].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[0].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(aAttrs[0]));
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(aAttrs[2].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[2].mnStart));
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(aAttrs[2].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[2].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(aAttrs[2]));
+
+ CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(aAttrs[4].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[4].mnStart));
+ CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(aAttrs[4].mnEnd));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[4].maAttributes.size()));
+ CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(aAttrs[4]));
+
+ // The 2nd and 4th paragraphs should be empty.
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aAttrs[1].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[1].mnStart));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[1].mnEnd));
+ CPPUNIT_ASSERT_MESSAGE("Attribute array should be empty.", aAttrs[1].maAttributes.empty());
+
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(aAttrs[3].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[3].mnStart));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[3].mnEnd));
+ CPPUNIT_ASSERT_MESSAGE("Attribute array should be empty.", aAttrs[3].maAttributes.empty());
+ }
+
+
+ {
+ aEngine.Clear();
+ aEngine.SetText("one\ntwo");
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aEngine.GetParagraphCount());
+
+ // embolden 2nd paragraph
+ pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet()));
+ pSet->Put(aBold);
+ aEngine.QuickSetAttribs(*pSet, ESelection(1,0,1,3));
+ // disboldify 1st paragraph
+ SvxWeightItem aNotSoBold(WEIGHT_NORMAL, EE_CHAR_WEIGHT);
+ pSet->Put(aNotSoBold);
+ aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,3));
+
+ // now delete & join the paragraphs - this is fdo#85496 scenario
+ aEngine.QuickDelete(ESelection(0,0,1,3));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aEngine.GetParagraphCount());
+
+ std::unique_ptr<EditTextObject> pEditText(aEngine.CreateTextObject());
+ CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText);
+ std::vector<editeng::Section> aAttrs;
+ pEditText->GetAllSections(aAttrs);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aAttrs.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnParagraph));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnStart));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(aAttrs[0].mnEnd));
+ std::set<sal_uInt16> whiches;
+ for (size_t i = 0; i < aAttrs[0].maAttributes.size(); ++i)
+ {
+ sal_uInt16 const nWhich(aAttrs[0].maAttributes[i]->Which());
+ CPPUNIT_ASSERT_MESSAGE("duplicate item in text portion attributes",
+ whiches.insert(nWhich).second);
+ }
+ }
+}
+
+void Test::testLargeParaCopyPaste()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ // Get EditDoc for current EditEngine's instance
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+
+ // Initially no text should be there
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(0), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( OUString(), rDoc.GetParaAsString(sal_Int32(0)) );
+
+ // Insert initial text
+ OUString aFirstPara = "This is first paragraph";
+ OUString aSecondPara = "This is second paragraph";
+ OUString aThirdPara = "This is third paragraph";
+ OUString aFourthPara = "This is fourth paragraph";
+ OUString aFifthPara = "This is fifth paragraph";
+ OUString aSixthPara = "This is sixth paragraph";
+ //Positions Ref: ........*8.............
+ OUString aSeventhPara = "This is seventh paragraph";
+ OUString aEighthPara = "This is eighth paragraph";
+ //Positions Ref: .............*13
+ OUString aNinthPara = "This is ninth paragraph";
+ OUString aTenthPara = "This is tenth paragraph";
+ OUString aText = aFirstPara + "\n" + aSecondPara + "\n" + aThirdPara + "\n" +
+ aFourthPara + "\n" + aFifthPara + "\n" + aSixthPara + "\n" + aSeventhPara + "\n" +
+ aEighthPara + "\n" + aNinthPara + "\n" + aTenthPara;
+ sal_Int32 aTextLen = aFirstPara.getLength() + aSecondPara.getLength() + aThirdPara.getLength() +
+ aFourthPara.getLength() + aFifthPara.getLength() + aSixthPara.getLength() +
+ aSeventhPara.getLength() + aEighthPara.getLength() + aNinthPara.getLength() + aTenthPara.getLength();
+ aEditEngine.SetText( aText );
+ OUString aCopyText = "sixth paragraphThis is seventh paragraphThis is eighth";
+ sal_Int32 aCopyTextLen = aCopyText.getLength();
+
+ // Assert changes
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aFourthPara, rDoc.GetParaAsString(sal_Int32(3)) );
+ CPPUNIT_ASSERT_EQUAL( aFifthPara, rDoc.GetParaAsString(sal_Int32(4)) );
+ CPPUNIT_ASSERT_EQUAL( aSixthPara, rDoc.GetParaAsString(sal_Int32(5)) );
+ CPPUNIT_ASSERT_EQUAL( aSeventhPara, rDoc.GetParaAsString(sal_Int32(6)) );
+ CPPUNIT_ASSERT_EQUAL( aEighthPara, rDoc.GetParaAsString(sal_Int32(7)) );
+ CPPUNIT_ASSERT_EQUAL( aNinthPara, rDoc.GetParaAsString(sal_Int32(8)) );
+ CPPUNIT_ASSERT_EQUAL( aTenthPara, rDoc.GetParaAsString(sal_Int32(9)) );
+
+ // Copy initial text using legacy format
+ uno::Reference< datatransfer::XTransferable > xData = aEditEngine.CreateTransferable( ESelection(5,8,7,14) );
+
+ // Paste text at the end of 4th Para
+ ContentNode* pLastNode = rDoc.GetObject(3);
+ aEditEngine.InsertText( xData, OUString(), EditPaM( pLastNode, pLastNode->Len() ), true );
+
+ // Assert changes
+ OUString aFourthParaAfterCopyPaste = aFourthPara + "sixth paragraph";
+ OUString aSixthParaAfterCopyPaste = "This is eighth";
+ CPPUNIT_ASSERT_EQUAL( sal_uLong(aTextLen + aCopyTextLen), rDoc.GetTextLen() );
+ CPPUNIT_ASSERT_EQUAL( aFirstPara, rDoc.GetParaAsString(sal_Int32(0)) );
+ CPPUNIT_ASSERT_EQUAL( aSecondPara, rDoc.GetParaAsString(sal_Int32(1)) );
+ CPPUNIT_ASSERT_EQUAL( aThirdPara, rDoc.GetParaAsString(sal_Int32(2)) );
+ CPPUNIT_ASSERT_EQUAL( aFourthParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(3)) );
+ CPPUNIT_ASSERT_EQUAL( aSeventhPara, rDoc.GetParaAsString(sal_Int32(4)) );
+ CPPUNIT_ASSERT_EQUAL( aSixthParaAfterCopyPaste, rDoc.GetParaAsString(sal_Int32(5)) );
+ CPPUNIT_ASSERT_EQUAL( aFifthPara, rDoc.GetParaAsString(sal_Int32(6)) );
+ CPPUNIT_ASSERT_EQUAL( aSixthPara, rDoc.GetParaAsString(sal_Int32(7)) );
+ CPPUNIT_ASSERT_EQUAL( aSeventhPara, rDoc.GetParaAsString(sal_Int32(8)) );
+ CPPUNIT_ASSERT_EQUAL( aEighthPara, rDoc.GetParaAsString(sal_Int32(9)) );
+ CPPUNIT_ASSERT_EQUAL( aNinthPara, rDoc.GetParaAsString(sal_Int32(10)) );
+ CPPUNIT_ASSERT_EQUAL( aTenthPara, rDoc.GetParaAsString(sal_Int32(11)) );
+}
+
+void Test::testTransliterate()
+{
+ // Create EditEngine's instance
+ EditEngine aEditEngine( mpItemPool );
+
+ OUString sText("one (two) three");
+ aEditEngine.SetText(sText);
+ aEditEngine.TransliterateText(ESelection(0, 0, 0, sText.getLength()), TransliterationFlags::TITLE_CASE);
+ CPPUNIT_ASSERT_EQUAL(OUString("One (Two) Three"), aEditEngine.GetText());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */