summaryrefslogtreecommitdiffstats
path: root/sw/qa/extras/uiwriter/uiwriter.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx1754
1 files changed, 1754 insertions, 0 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
new file mode 100644
index 000000000..ddbe5e009
--- /dev/null
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -0,0 +1,1754 @@
+/* -*- 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 <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/document/XDocumentInsertable.hpp>
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <swmodeltestbase.hxx>
+#include <ndtxt.hxx>
+#include <wrtsh.hxx>
+#include <shellio.hxx>
+#include <expfld.hxx>
+#include <drawdoc.hxx>
+#include <redline.hxx>
+#include <fmtclds.hxx>
+#include <dcontact.hxx>
+#include <view.hxx>
+#include <hhcwrp.hxx>
+#include <swacorr.hxx>
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unocrsrhelper.hxx>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+#include <vcl/TypeSerializer.hxx>
+
+#include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svxids.hrc>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <UndoManager.hxx>
+#include <frmatr.hxx>
+
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <osl/file.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <vcl/scheduler.hxx>
+#include <sfx2/watermarkitem.hxx>
+#include <sfx2/docfile.hxx>
+#include <fmthdft.hxx>
+#include <iodetect.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotxdoc.hxx>
+#include <swdtflvr.hxx>
+#include <sortedobjs.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/extras/uiwriter/data/";
+
+void lcl_selectCharacters(SwPaM& rPaM, sal_Int32 first, sal_Int32 end)
+{
+ rPaM.GetPoint()->nContent.Assign(rPaM.GetContentNode(), first);
+ rPaM.SetMark();
+ rPaM.GetPoint()->nContent.Assign(rPaM.GetContentNode(), end);
+}
+} //namespace
+
+class SwUiWriterTest : public SwModelTestBase
+{
+public:
+ std::unique_ptr<SwTextBlocks> readDOCXAutotext(
+ std::u16string_view sFileName, bool bEmpty = false);
+ void testRedlineFrame(char const*const file);
+};
+
+std::unique_ptr<SwTextBlocks> SwUiWriterTest::readDOCXAutotext(std::u16string_view sFileName, bool bEmpty)
+{
+ utl::TempFile tmp;
+ tmp.EnableKillingFile();
+ OUString rURL = tmp.GetURL();
+ CPPUNIT_ASSERT_EQUAL(
+ osl::FileBase::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + sFileName, rURL));
+
+ SfxMedium aSrcMed(rURL, StreamMode::STD_READ);
+ SwDoc* pDoc = createSwDoc();
+
+ SwReader aReader(aSrcMed, rURL, pDoc);
+ Reader* pDOCXReader = SwReaderWriter::GetDOCXReader();
+ auto pGlossary = std::make_unique<SwTextBlocks>(rURL);
+
+ CPPUNIT_ASSERT(pDOCXReader != nullptr);
+ CPPUNIT_ASSERT_EQUAL(!bEmpty, aReader.ReadGlossaries(*pDOCXReader, *pGlossary, false));
+
+ return pGlossary;
+}
+
+void SwUiWriterTest::testRedlineFrame(char const*const file)
+{
+ SwDoc * pDoc(createSwDoc(DATA_DIRECTORY, file));
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ // there is exactly one frame
+ CPPUNIT_ASSERT_EQUAL(1, getShapes());
+
+ RedlineFlags nMode = pWrtShell->GetRedlineFlags();
+ CPPUNIT_ASSERT(nMode & RedlineFlags::ShowDelete);
+
+ // hide delete redlines
+ pWrtShell->SetRedlineFlags(nMode & ~RedlineFlags::ShowDelete);
+
+ // there is still exactly one frame
+ CPPUNIT_ASSERT_EQUAL(1, getShapes());
+
+ pWrtShell->SetRedlineFlags(nMode); // show again
+
+ // there is still exactly one frame
+ CPPUNIT_ASSERT_EQUAL(1, getShapes());
+}
+
+//Replacement tests
+
+constexpr OUStringLiteral ORIGINAL_REPLACE_CONTENT(u"toto titi tutu");
+constexpr OUStringLiteral EXPECTED_REPLACE_CONTENT(u"toto toto tutu");
+
+// Chinese conversion tests
+
+const sal_Unicode CHINESE_TRADITIONAL_CONTENT(0x9F8D);
+const sal_Unicode CHINESE_SIMPLIFIED_CONTENT(0x9F99);
+constexpr OUStringLiteral NON_CHINESE_CONTENT(u"Hippopotamus");
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testReplaceForward)
+{
+ SwDoc* pDoc = createSwDoc();
+
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, ORIGINAL_REPLACE_CONTENT);
+
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ lcl_selectCharacters(aPaM, 5, 9);
+ pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "toto", false);
+
+ CPPUNIT_ASSERT_EQUAL(OUString(EXPECTED_REPLACE_CONTENT), pTextNode->GetText());
+
+ rUndoManager.Undo();
+
+ CPPUNIT_ASSERT_EQUAL(OUString(ORIGINAL_REPLACE_CONTENT), pTextNode->GetText());
+}
+
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtCharStartOutside0)
+{
+ testRedlineFrame("redlineFrame.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtCharStartOutside)
+{
+ testRedlineFrame("redlineFrame_at_char_start_outside.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtCharStartInside)
+{
+ testRedlineFrame("redlineFrame_at_char_start_inside.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtParaStartOutside)
+{
+ testRedlineFrame("redline_fly_duplication_at_para_start_outside.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtParaEndInside)
+{
+ testRedlineFrame("redline_fly_duplication_at_para_end_inside.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtParaOneParagraph)
+{
+ // test ALLFLYS flag: oddly enough it didn't fail as fodt but failed as odt...
+ testRedlineFrame("redline_fly_at_para_one_paragraph.odt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testRedlineFrameAtPara2ndParagraph)
+{
+ // lost via the buggy increment in Copy
+ testRedlineFrame("redline_fly_duplication_at_para_2nd_paragraph.fodt");
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testThreadedException)
+{
+ SvFileStream aFileStream(m_directories.getURLFromSrc(DATA_DIRECTORY) + "threadedException.fodt", StreamMode::READ);
+
+ //threaded reading only kicks in if there is sufficient buffer to make it worthwhile, so read
+ //from a SvFileStream to ensure that
+ bool bRes = TestImportFODT(aFileStream);
+
+ CPPUNIT_ASSERT(!bRes);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf149595)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "demo91.fodt");
+
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ // all 4 shapes are on the 2nd paragraph
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() == nullptr);
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(4), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+
+ {
+ pWrtShell->Down(false);
+ pWrtShell->EndPara(/*bSelect=*/true);
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+ pTransfer->Cut();
+
+ // one shape is anchored in the middle, others at the start/end/at-para
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() == nullptr);
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+
+ pWrtShell->Up(false);
+ TransferableDataHelper aHelper(pTransfer);
+ SwTransferable::Paste(*pWrtShell, aHelper);
+
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs()->size());
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+
+ pWrtShell->Undo();
+ pWrtShell->Undo();
+
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() == nullptr);
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(4), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+ }
+
+ // now try the same with redlining enabled - should be the same result
+ dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
+ dispatchCommand(mxComponent, ".uno:TrackChanges", {});
+ {
+ pWrtShell->Down(false);
+ pWrtShell->SttPara(/*bSelect=*/false);
+ pWrtShell->EndPara(/*bSelect=*/true);
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+ pTransfer->Cut();
+
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() == nullptr);
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ // problem was that this deleted all at-char flys, even at the start/end
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+
+ pWrtShell->Up(false);
+ TransferableDataHelper aHelper(pTransfer);
+ SwTransferable::Paste(*pWrtShell, aHelper);
+
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs()->size());
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+
+ pWrtShell->Undo();
+ pWrtShell->Undo();
+
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs() == nullptr);
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs() != nullptr);
+ CPPUNIT_ASSERT_EQUAL(size_t(4), pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetNext()->GetDrawObjs()->size());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testBookmarkCopy)
+{
+ SwDoc * pDoc(createSwDoc());
+
+ // add text and bookmark
+ IDocumentMarkAccess & rIDMA(*pDoc->getIDocumentMarkAccess());
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwCursor aPaM(SwPosition(aIdx), nullptr);
+ rIDCO.InsertString(aPaM, "foo");
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ rIDCO.InsertString(aPaM, "bar");
+ aPaM.SetMark();
+ aPaM.MovePara(GoCurrPara, fnParaStart);
+ rIDMA.makeMark(aPaM, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ aPaM.Exchange();
+ aPaM.DeleteMark();
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ rIDCO.InsertString(aPaM, "baz");
+
+ // copy range
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ SwPosition target(*aPaM.GetPoint());
+ aPaM.Move(fnMoveBackward, GoInContent);
+ aPaM.SetMark();
+ aPaM.SttEndDoc(true/*start*/);
+ aPaM.Move(fnMoveForward, GoInContent); // partially select 1st para
+
+ rIDCO.CopyRange(aPaM, target, SwCopyFlags::CheckPosInFly);
+
+ // check bookmark was copied to correct position
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rIDMA.getBookmarksCount());
+ for (auto it(rIDMA.getBookmarksBegin()); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ OUString markText(SwPaM((*it)->GetMarkPos(), (*it)->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), markText);
+ }
+
+ // copy 2nd time, such that bCanMoveBack is false in CopyImpl
+ SwPaM aCopyPaM(*aPaM.GetMark(), *aPaM.GetPoint());
+ aPaM.SttEndDoc(true/*start*/);
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ aPaM.SttEndDoc(true/*start*/);
+
+ rIDCO.CopyRange(aCopyPaM, *aPaM.GetPoint(), SwCopyFlags::CheckPosInFly);
+
+ // check bookmark was copied to correct position
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getBookmarksCount());
+ for (auto it(rIDMA.getBookmarksBegin()); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ OUString markText(SwPaM((*it)->GetMarkPos(), (*it)->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), markText);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testInsertFileInInputFieldException)
+{
+ createSwDoc();
+ uno::Reference<text::XTextDocument> const xTextDoc(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> const xBody(xTextDoc->getText());
+ uno::Reference<lang::XMultiServiceFactory> const xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> const xCursor(xBody->createTextCursor());
+ uno::Reference<document::XDocumentInsertable> const xInsertable(xCursor, uno::UNO_QUERY);
+ uno::Reference<text::XTextContent> const xContent(
+ xFactory->createInstance("com.sun.star.text.textfield.Input"), uno::UNO_QUERY);
+ xBody->insertTextContent(xCursor, xContent, false);
+ xCursor->goLeft(1, false);
+ // try to insert some random file
+ OUString const url(m_directories.getURLFromSrc(DATA_DIRECTORY) + "fdo75110.odt");
+ // inserting even asserts in debug builds - document model goes invalid with input field split across 2 nodes
+ CPPUNIT_ASSERT_THROW(xInsertable->insertDocumentFromURL(url, {}), uno::RuntimeException);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf67238)
+{
+ //create a new writer document
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ //insert a 3X3 table in the newly created document
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ const SwTable& rTable = pWrtShell->InsertTable(TableOpt, 3, 3);
+ //checking for the rows and columns
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getColumns()->getCount());
+ //selecting the table
+ pWrtShell->StartOfSection();
+ pWrtShell->SelTable();
+ //making the table protected
+ pWrtShell->ProtectCells();
+ //checking each cell's protection, it should be protected
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ //undo the changes, make cells [un]protected
+ rUndoManager.Undo();
+ //checking each cell's protection, it should be [un]protected
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ //redo the changes, make cells protected
+ rUndoManager.Redo();
+ //checking each cell's protection, it should be protected
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ //moving the cursor to the starting of the document
+ pWrtShell->StartOfSection();
+ //making the table [un]protected
+ pWrtShell->SelTable();
+ pWrtShell->UnProtectCells();
+ //checking each cell's protection, it should be [un]protected
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ //undo the changes, make cells protected
+ rUndoManager.Undo();
+ //checking each cell's protection, it should be protected
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ //redo the changes, make cells [un]protected
+ rUndoManager.Redo();
+ //checking each cell's protection, it should be [un]protected
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("A3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("B3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C1"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C2"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+ CPPUNIT_ASSERT(!((rTable.GetTableBox("C3"))->GetFrameFormat()->GetProtect()).IsContentProtected());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf147220)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ pWrtShell->Insert(u"él");
+
+ // hide and enable
+ dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
+ dispatchCommand(mxComponent, ".uno:TrackChanges", {});
+ CPPUNIT_ASSERT(pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+ CPPUNIT_ASSERT(
+ IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+
+ pWrtShell->GoStartSentence();
+ pWrtShell->SetMark();
+ pWrtShell->GoEndSentence();
+
+ // this did not remove the original text from the layout
+ pWrtShell->Replace(u"Él", false);
+
+ // currently the deleted text is before the replacement text, not sure if
+ // that is really required
+ CPPUNIT_ASSERT_EQUAL(OUString(u"élÉl"),
+ pWrtShell->GetCursor()->GetPoint()->nNode.GetNode().GetTextNode()->GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Él"),
+ static_cast<SwTextFrame const*>(pWrtShell->GetCursor()->GetPoint()->nNode.GetNode().GetTextNode()->getLayoutFrame(nullptr))->GetText());
+
+ SwRedlineTable const& rRedlines(pDoc->getIDocumentRedlineAccess().GetRedlineTable());
+ CPPUNIT_ASSERT_EQUAL(SwRedlineTable::size_type(2), rRedlines.size());
+ CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlines[0]->GetType());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"él"), rRedlines[0]->GetText());
+ CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[1]->GetType());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Él"), rRedlines[1]->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf135978)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ pWrtShell->Insert("foobar");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("bazquux");
+
+ CPPUNIT_ASSERT(pWrtShell->IsEndOfDoc());
+
+ SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
+ anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint());
+ SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>);
+ flySet.Put(anchor);
+ SwFlyFrameFormat const* pFly = dynamic_cast<SwFlyFrameFormat const*>(
+ pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true));
+ CPPUNIT_ASSERT(pFly != nullptr);
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+ // move cursor back to body
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+
+ // hide and enable
+ dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
+ dispatchCommand(mxComponent, ".uno:TrackChanges", {});
+
+ CPPUNIT_ASSERT(pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+ CPPUNIT_ASSERT(
+ IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, /*bBasicCall=*/false);
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 6, /*bBasicCall=*/false);
+ pWrtShell->Delete();
+
+ // now split
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SplitNode();
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+ // the problem was that undo removed the fly frame from the layout
+ pWrtShell->Undo();
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+ pWrtShell->Redo();
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+
+ pWrtShell->Undo();
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo75110)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "fdo75110.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ pWrtShell->SelAll();
+ // The problem was that SwEditShell::DeleteSel() what this Delete() invokes took the wrong selection...
+ pWrtShell->Delete();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ // ... so this Undo() call resulted in a crash.
+ rUndoManager.Undo();
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo75898)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "fdo75898.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->SelAll();
+ pWrtShell->InsertRow(1, true);
+ pWrtShell->InsertRow(1, true);
+
+ // Now check if the table has 3 lines.
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+ SwTableNode* pTableNode = pShellCursor->Start()->nNode.GetNode().FindTableNode();
+ // This was 1, when doing the same using the UI, Writer even crashed.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pTableNode->GetTable().GetTabLines().size());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testReplaceBackward)
+{
+ //Regression test of fdo#70143
+ //EDITING: undo search&replace corrupt text when searching backward
+ SwDoc* pDoc = createSwDoc();
+
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, "toto titi tutu");
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ lcl_selectCharacters(aPaM, 9, 5);
+
+ pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "toto", false);
+
+ CPPUNIT_ASSERT_EQUAL(OUString(EXPECTED_REPLACE_CONTENT), pTextNode->GetText());
+
+ rUndoManager.Undo();
+
+ CPPUNIT_ASSERT_EQUAL(OUString(ORIGINAL_REPLACE_CONTENT), pTextNode->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo69893)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "fdo69893.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ pWrtShell->SelAll(); // A1 is empty -> selects the whole table.
+ pWrtShell->SelAll(); // Selects the whole document.
+
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+ SwTextNode& rEnd = dynamic_cast<SwTextNode&>(pShellCursor->End()->nNode.GetNode());
+ // Selection did not include the para after table, this was "B1".
+ CPPUNIT_ASSERT_EQUAL(OUString("Para after table."), rEnd.GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo70807)
+{
+ createSwDoc(DATA_DIRECTORY, "fdo70807.odt");
+
+ uno::Reference<container::XIndexAccess> xStylesIter(getStyles("PageStyles"), uno::UNO_QUERY);
+
+ for (sal_Int32 i = 0; i < xStylesIter->getCount(); ++i)
+ {
+ uno::Reference<style::XStyle> xStyle(xStylesIter->getByIndex(i), uno::UNO_QUERY);
+
+ bool expectedUsedStyle = false;
+ bool expectedUserDefined = false;
+
+ OUString styleName(xStyle->getName());
+
+ // just these styles are user defined styles
+ if (styleName == "pagestyle1" || styleName == "pagestyle2")
+ expectedUserDefined = true;
+
+ // just these styles are used in the document
+ if (styleName == "Right Page" || styleName == "pagestyle1" || styleName == "pagestyle2")
+ expectedUsedStyle = true;
+
+ CPPUNIT_ASSERT_EQUAL(expectedUserDefined, bool(xStyle->isUserDefined()));
+ CPPUNIT_ASSERT_EQUAL(expectedUsedStyle, bool(xStyle->isInUse()));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testImportRTF)
+{
+ // Insert "foobar" and position the cursor between "foo" and "bar".
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("foobar");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
+
+ // Insert the RTF at the cursor position.
+ OString aData = "{\\rtf1 Hello world!\\par}";
+ SvMemoryStream aStream(const_cast<char*>(aData.getStr()), aData.getLength(), StreamMode::READ);
+ SwReader aReader(aStream, OUString(), OUString(), *pWrtShell->GetCursor());
+ Reader* pRTFReader = SwReaderWriter::GetRtfReader();
+ CPPUNIT_ASSERT(pRTFReader != nullptr);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, aReader.Read(*pRTFReader));
+
+ SwNodeOffset nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ CPPUNIT_ASSERT_EQUAL(OUString("fooHello world!"), pDoc->GetNodes()[nIndex - 1]->GetTextNode()->GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), pDoc->GetNodes()[nIndex]->GetTextNode()->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testExportRTF)
+{
+ // Insert "aaabbbccc" and select "bbb".
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("aaabbbccc");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, /*bBasicCall=*/false);
+
+ // Create the clipboard document.
+ rtl::Reference<SwDoc> xClpDoc(new SwDoc());
+ xClpDoc->SetClipBoard(true);
+ pWrtShell->Copy(*xClpDoc);
+
+ // And finally export it as RTF.
+ WriterRef xWrt;
+ SwReaderWriter::GetWriter(u"RTF", OUString(), xWrt);
+ SvMemoryStream aStream;
+ SwWriter aWrt(aStream, *xClpDoc);
+ aWrt.Write(xWrt);
+
+ OString aData(static_cast<const char*>(aStream.GetData()), aStream.GetSize());
+
+ //Amusingly eventually there was a commit id with "ccc" in it, and so the rtf contained
+ //{\*\generator LibreOfficeDev/4.4.0.0.alpha0$Linux_X86_64 LibreOffice_project/f70664ccc6837f2cc21a29bb4f44e41e100efe6b}
+ //so the test fell over. so strip the generator tag
+ sal_Int32 nGeneratorStart = aData.indexOf("{\\*\\generator ");
+ CPPUNIT_ASSERT(nGeneratorStart != -1);
+ sal_Int32 nGeneratorEnd = aData.indexOf('}', nGeneratorStart + 1);
+ CPPUNIT_ASSERT(nGeneratorEnd != -1);
+ aData = aData.replaceAt(nGeneratorStart, nGeneratorEnd-nGeneratorStart+1, "");
+
+ CPPUNIT_ASSERT(aData.startsWith("{\\rtf1"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aData.indexOf("aaa"));
+ CPPUNIT_ASSERT(aData.indexOf("bbb") != -1);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aData.indexOf("ccc"));
+ // Ensure there's no extra newline
+ CPPUNIT_ASSERT(aData.endsWith("bbb}" SAL_NEWLINE_STRING "}"));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDOCXAutoTextEmpty)
+{
+ // file contains normal content but no AutoText
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext(u"autotext-empty.dotx", true);
+ CPPUNIT_ASSERT(pGlossary != nullptr);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDOCXAutoTextMultiple)
+{
+ // file contains three AutoText entries
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext(u"autotext-multiple.dotx");
+
+ // check entries count
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pGlossary->GetCount());
+
+ // check names of entries, sorted order
+ CPPUNIT_ASSERT_EQUAL(OUString("Anothercomplex"), pGlossary->GetLongName(0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Multiple"), pGlossary->GetLongName(1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Second Autotext"), pGlossary->GetLongName(2));
+
+ // check if previously loaded content is correct (eg. doesn't contain title)
+ SwDoc* pDoc = pGlossary->GetDoc();
+ CPPUNIT_ASSERT(pDoc != nullptr);
+
+ SwNodeIndex aDocEnd(pDoc->GetNodes().GetEndOfContent());
+ SwNodeIndex aStart(*aDocEnd.GetNode().StartOfSectionNode(), 1);
+
+ CPPUNIT_ASSERT(aStart < aDocEnd);
+
+ // first line
+ SwNode& rNode = aStart.GetNode();
+ CPPUNIT_ASSERT(rNode.IsTextNode());
+ SwTextNode& rTextNode = *rNode.GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString("Another "), rTextNode.GetText());
+
+ // Make sure that autotext does not set a custom page style, leading to an unexpected page break
+ // on insertion.
+ // Without the accompanying fix in place, this test would have failed: the text node had an
+ // attribute set containing a page style item.
+ CPPUNIT_ASSERT(!rTextNode.HasSwAttrSet() || !rTextNode.GetSwAttrSet().HasItem(RES_PAGEDESC));
+
+ // last line
+ SwNodeIndex aLast(*aDocEnd.GetNode().EndOfSectionNode(), -1);
+ SwNode& rLastNode = aLast.GetNode();
+ CPPUNIT_ASSERT_EQUAL(OUString("complex"), rLastNode.GetTextNode()->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDOTMAutoText)
+{
+ // this is dotm file difference is that in the dotm
+ // there are no empty paragraphs at the end of each entry
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext(u"autotext-dotm.dotm");
+
+ SwDoc* pDoc = pGlossary->GetDoc();
+ CPPUNIT_ASSERT(pDoc != nullptr);
+
+ // check if content is correct
+ SwNodeIndex aDocEnd(pDoc->GetNodes().GetEndOfContent());
+ SwNodeIndex aStart(*aDocEnd.GetNode().StartOfSectionNode(), 1);
+ SwNode& rNode = aStart.GetNode();
+ CPPUNIT_ASSERT_EQUAL(OUString("paragraph"), rNode.GetTextNode()->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDOCXAutoTextGallery)
+{
+ // this file contains one AutoText entry and other
+ // entries which are not AutoText (have different "gallery" value)
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext(u"autotext-gallery.dotx");
+
+ SwDoc* pDoc = pGlossary->GetDoc();
+ CPPUNIT_ASSERT(pDoc != nullptr);
+
+ // check entries count
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pGlossary->GetCount());
+
+ // check entry name (if not contains gallery type)
+ CPPUNIT_ASSERT_EQUAL(OUString("Multiple"), pGlossary->GetLongName(0));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testWatermarkDOCX)
+{
+ SwDoc* const pDoc = createSwDoc(DATA_DIRECTORY, "watermark.docx");
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ const SfxWatermarkItem* pWatermark;
+ SfxItemState eState = pDocShell->GetViewShell()->GetViewFrame()->GetDispatcher()->QueryState(SID_WATERMARK, pWatermark);
+
+ CPPUNIT_ASSERT(eState >= SfxItemState::DEFAULT);
+ CPPUNIT_ASSERT(pWatermark);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(SID_WATERMARK), pWatermark->Which());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("CustomWatermark"), pWatermark->GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Sans Light"), pWatermark->GetFont());
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(45), pWatermark->GetAngle());
+ CPPUNIT_ASSERT_EQUAL(Color(0x548dd4), pWatermark->GetColor());
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(50), pWatermark->GetTransparency());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testWatermarkPosition)
+{
+ // tdf#108494 Watermark inserted in the document with page break was outside the first page
+ const int aPagesInDocument = 2;
+ const int aAdditionalPagesCount[] = { 0, 0, 1, 1, 5, 5, 20, 20 };
+ const bool aChangeHeader[] = { true, false, true, false, true, false, true, false };
+
+ for (tools::ULong i = 0; i < sizeof(aAdditionalPagesCount) / sizeof(int); ++i)
+ {
+ int aPages = aPagesInDocument + aAdditionalPagesCount[i];
+
+ // Empty document with one Page Break
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "watermark-position.odt");
+ SwEditShell* pEditShell = pDoc->GetEditShell();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<frame::XModel> xModel = pDoc->GetDocShell()->GetBaseModel();
+ uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xStyleFamilies = xStyleFamiliesSupplier->getStyleFamilies();
+ uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName("Default Page Style"), uno::UNO_QUERY);
+
+ // 1. Add additional page breaks
+ for (int j = 0; j < aAdditionalPagesCount[i]; ++j)
+ pWrtShell->InsertPageBreak();
+
+ // 2. Change header state (On, Off, On)
+ if (aChangeHeader[i])
+ {
+ SwPageDesc aDesc(pDoc->GetPageDesc(0));
+ SwFrameFormat& rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr(SwFormatHeader(true));
+ pDoc->ChgPageDesc(0, aDesc);
+
+ aDesc = pDoc->GetPageDesc(0);
+ SwFrameFormat& rMaster2 = aDesc.GetMaster();
+ rMaster2.SetFormatAttr(SwFormatHeader(false));
+ pDoc->ChgPageDesc(0, aDesc);
+
+ aDesc = pDoc->GetPageDesc(0);
+ SwFrameFormat& rMaster3 = aDesc.GetMaster();
+ rMaster3.SetFormatAttr(SwFormatHeader(true));
+ pDoc->ChgPageDesc(0, aDesc);
+ }
+
+ // 3. Insert Watermark
+ SfxWatermarkItem aWatermark;
+ aWatermark.SetText("Watermark");
+ aWatermark.SetFont("DejaVu Sans");
+
+ pEditShell->SetWatermark(aWatermark);
+
+ uno::Reference<css::drawing::XShape> xShape = getShape(1);
+ CPPUNIT_ASSERT(xShape.is());
+
+ SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+
+ // Get Watermark object
+ SdrObject* pObject = pPage->GetObj(0);
+ pObject->RecalcBoundRect();
+ const tools::Rectangle& rRect = pObject->GetSnapRect();
+ Size rSize = pPage->GetSize();
+
+ // Page break, calculate height of a page
+ const int nPageHeight = rSize.getHeight() / aPages;
+
+ std::stringstream aMessage;
+ aMessage << "Case: " << i << ", nPageHeight = " << nPageHeight << ", rRect.Bottom = " << rRect.Bottom();
+
+ // Check if Watermark is inside a page
+ CPPUNIT_ASSERT_MESSAGE(aMessage.str(), nPageHeight >= rRect.Bottom());
+
+ // Check if Watermark is centered
+ CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::CENTER, getProperty<sal_Int16>(xShape, "HoriOrient"));
+ CPPUNIT_ASSERT_EQUAL(text::VertOrientation::CENTER, getProperty<sal_Int16>(xShape, "VertOrient"));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo74981)
+{
+ // create a document with an input field
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwInputField aField(static_cast<SwInputFieldType*>(pWrtShell->GetFieldType(0, SwFieldIds::Input)), "foo", "bar", 0, 0);
+ pWrtShell->InsertField2(aField);
+
+ {
+ // expect hints
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
+ CPPUNIT_ASSERT(pTextNode->HasHints());
+ }
+
+ // go to the begin of the paragraph and split this node
+ pWrtShell->Left(CRSR_SKIP_CHARS, false, 100, false);
+ pWrtShell->SplitNode();
+
+ {
+ // expect only the second paragraph to have hints
+ SwNodeIndex aIdx(SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1));
+ SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
+ CPPUNIT_ASSERT(pTextNode->HasHints());
+ --aIdx;
+ pTextNode = aIdx.GetNode().GetTextNode();
+ CPPUNIT_ASSERT(!pTextNode->HasHints());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf98512)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwInputFieldType *const pType(static_cast<SwInputFieldType*>(
+ pWrtShell->GetFieldType(0, SwFieldIds::Input)));
+ SwInputField aField1(pType, "foo", "bar", INP_TXT, 0);
+ pWrtShell->InsertField2(aField1);
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ SwInputField aField2(pType, "baz", "quux", INP_TXT, 0);
+ pWrtShell->InsertField2(aField2);
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SetMark();
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ OUString const expected1(
+ OUStringChar(CH_TXT_ATR_INPUTFIELDSTART) + "foo" + OUStringChar(CH_TXT_ATR_INPUTFIELDEND));
+ OUString const expected2(
+ OUStringChar(CH_TXT_ATR_INPUTFIELDSTART) + "baz" + OUStringChar(CH_TXT_ATR_INPUTFIELDEND)
+ + expected1);
+ CPPUNIT_ASSERT_EQUAL(expected2, pWrtShell->getShellCursor(false)->GetText());
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ rUndoManager.Undo();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SetMark();
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ CPPUNIT_ASSERT_EQUAL(expected1, pWrtShell->getShellCursor(false)->GetText());
+ rUndoManager.Redo();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SetMark();
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ CPPUNIT_ASSERT_EQUAL(expected2, pWrtShell->getShellCursor(false)->GetText());
+ rUndoManager.Undo();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SetMark();
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ CPPUNIT_ASSERT_EQUAL(expected1, pWrtShell->getShellCursor(false)->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testShapeTextboxSelect)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "shape-textbox.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(1);
+ SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall());
+ // First, make sure that pTextBox is a fly frame (textbox of a shape).
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());
+
+ // Then select it.
+ pWrtShell->SelectObj(Point(), 0, pObject);
+ const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
+ SwDrawContact* pShape = static_cast<SwDrawContact*>(rMarkList.GetMark(0)->GetMarkedSdrObj()->GetUserCall());
+ // And finally make sure the shape got selected, not just the textbox itself.
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_DRAWFRMFMT), pShape->GetFormat()->Which());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testShapeTextboxDelete)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "shape-textbox.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(0);
+ pWrtShell->SelectObj(Point(), 0, pObject);
+ size_t nActual = pPage->GetObjCount();
+ // Two objects on the draw page: the shape and its textbox.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), nActual);
+
+ pWrtShell->DelSelectedObj();
+ nActual = pPage->GetObjCount();
+ // Both (not only the shape) should be removed by now (the textbox wasn't removed, so this was 1).
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), nActual);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testAnchorChangeSelection)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "test_anchor_as_character.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ // Then select it.
+ pWrtShell->SelectObj(Point(), 0, pObject);
+ const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
+ CPPUNIT_ASSERT_EQUAL(pObject, rMarkList.GetMark(0)->GetMarkedSdrObj());
+
+ pWrtShell->ChgAnchor(RndStdIds::FLY_AS_CHAR);
+
+ // tdf#125039 shape must still be selected, extensions depend on that
+ CPPUNIT_ASSERT_EQUAL(pObject, rMarkList.GetMark(0)->GetMarkedSdrObj());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCp1000071)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "cp1000071.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ CPPUNIT_ASSERT_EQUAL( SwRedlineTable::size_type( 2 ), rTable.size());
+ SwNodeOffset redlineStart0NodeIndex = rTable[ 0 ]->Start()->nNode.GetIndex();
+ sal_Int32 redlineStart0Index = rTable[ 0 ]->Start()->nContent.GetIndex();
+ SwNodeOffset redlineEnd0NodeIndex = rTable[ 0 ]->End()->nNode.GetIndex();
+ sal_Int32 redlineEnd0Index = rTable[ 0 ]->End()->nContent.GetIndex();
+ SwNodeOffset redlineStart1NodeIndex = rTable[ 1 ]->Start()->nNode.GetIndex();
+ sal_Int32 redlineStart1Index = rTable[ 1 ]->Start()->nContent.GetIndex();
+ SwNodeOffset redlineEnd1NodeIndex = rTable[ 1 ]->End()->nNode.GetIndex();
+ sal_Int32 redlineEnd1Index = rTable[ 1 ]->End()->nContent.GetIndex();
+
+ // Change the document layout to be 2 columns, and then undo.
+ pWrtShell->SelAll();
+ SwSectionData section(SectionType::Content, pWrtShell->GetUniqueSectionName());
+ SfxItemSet set( pDoc->GetDocShell()->GetPool(), svl::Items<RES_COL, RES_COL> );
+ SwFormatCol col;
+ col.Init( 2, 0, 10000 );
+ set.Put( col );
+ pWrtShell->InsertSection( section, &set );
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ rUndoManager.Undo();
+
+ // Check that redlines are the same like at the beginning.
+ CPPUNIT_ASSERT_EQUAL( SwRedlineTable::size_type( 2 ), rTable.size());
+ CPPUNIT_ASSERT_EQUAL( redlineStart0NodeIndex, rTable[ 0 ]->Start()->nNode.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineStart0Index, rTable[ 0 ]->Start()->nContent.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineEnd0NodeIndex, rTable[ 0 ]->End()->nNode.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineEnd0Index, rTable[ 0 ]->End()->nContent.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineStart1NodeIndex, rTable[ 1 ]->Start()->nNode.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineStart1Index, rTable[ 1 ]->Start()->nContent.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineEnd1NodeIndex, rTable[ 1 ]->End()->nNode.GetIndex());
+ CPPUNIT_ASSERT_EQUAL( redlineEnd1Index, rTable[ 1 ]->End()->nContent.GetIndex());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testShapeTextboxVertadjust)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "shape-textbox-vertadjust.odt");
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(1);
+ SwFrameFormat* pFormat = static_cast<SwContact*>(pObject->GetUserCall())->GetFormat();
+ // This was SDRTEXTVERTADJUST_TOP.
+ CPPUNIT_ASSERT_EQUAL(SDRTEXTVERTADJUST_CENTER, pFormat->GetTextVertAdjust().GetValue());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testShapeTextboxAutosize)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "shape-textbox-autosize.odt");
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ // 0-1 is the first UI-visible shape+textbox.
+ SdrObject* pFirst = pPage->GetObj(0);
+ CPPUNIT_ASSERT_EQUAL(OUString("1st"), pFirst->GetName());
+
+ // 2-3 is the second UI-visible shape+textbox.
+ SdrObject* pSecond = pPage->GetObj(2);
+ CPPUNIT_ASSERT_EQUAL(OUString("2nd"), pSecond->GetName());
+
+ // Shape -> textbox synchronization was missing, the second shape had the
+ // same height as the first, even though the first contained 1 paragraph
+ // and the other 2 ones.
+ CPPUNIT_ASSERT(pFirst->GetSnapRect().getHeight() < pSecond->GetSnapRect().getHeight());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo82191)
+{
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "fdo82191.odt");
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ // Make sure we have a single draw shape.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), SwTextBoxHelper::getCount(pPage));
+
+ SwDoc aClipboard;
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrObject* pObject = pPage->GetObj(0);
+ // Select it, then copy and paste.
+ pWrtShell->SelectObj(Point(), 0, pObject);
+ pWrtShell->Copy(aClipboard);
+ pWrtShell->Paste(aClipboard);
+
+ // This was one: the textbox of the shape wasn't copied.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), SwTextBoxHelper::getCount(*pDoc));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCommentedWord)
+{
+ // This word is commented. <- string in document
+ // 123456789 <- character positions
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "commented-word.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // Move the cursor into the second word.
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 5, /*bBasicCall=*/false);
+ // Select the word.
+ pWrtShell->SelWrd();
+
+ // Make sure that not only the word, but its comment anchor is also selected.
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+ // This was 9, only "word", not "word<anchor character>" was selected.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(10), pShellCursor->End()->nContent.GetIndex());
+
+ // Test that getAnchor() points to "word", not to an empty string.
+ uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+ uno::Reference<text::XTextContent> xField(xFields->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("word"), xField->getAnchor()->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTextFieldGetAnchorGetTextInFooter)
+{
+ createSwDoc(DATA_DIRECTORY, "textfield-getanchor-gettext-in-footer.odt");
+
+ uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+ uno::Reference<text::XTextContent> xField(xFields->nextElement(), uno::UNO_QUERY);
+
+ OUString value = xField->getAnchor()->getText()->getString();
+ CPPUNIT_ASSERT_EQUAL(OUString("userfield_in_footer"), value );
+}
+
+// Tests that a blank document is still blank after conversion
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testChineseConversionBlank)
+{
+
+ // Given
+ SwDoc* pDoc = createSwDoc();
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ const uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ // When
+ SwHHCWrapper aWrap( pView, xContext, LANGUAGE_CHINESE_TRADITIONAL, LANGUAGE_CHINESE_SIMPLIFIED, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, false,
+ true, false, false );
+ aWrap.Convert();
+
+ // Then
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString(), pTextNode->GetText());
+
+}
+
+// Tests that non Chinese text is unchanged after conversion
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testChineseConversionNonChineseText)
+{
+
+ // Given
+ SwDoc* pDoc = createSwDoc();
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ const uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, NON_CHINESE_CONTENT);
+
+ // When
+ SwHHCWrapper aWrap( pView, xContext, LANGUAGE_CHINESE_TRADITIONAL, LANGUAGE_CHINESE_SIMPLIFIED, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, false,
+ true, false, false );
+ aWrap.Convert();
+
+ // Then
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString(NON_CHINESE_CONTENT), pTextNode->GetText());
+
+}
+
+// Tests conversion of traditional Chinese characters to simplified Chinese
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testChineseConversionTraditionalToSimplified)
+{
+
+ // Given
+ SwDoc* pDoc = createSwDoc();
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ const uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(CHINESE_TRADITIONAL_CONTENT));
+
+ // When
+ SwHHCWrapper aWrap( pView, xContext, LANGUAGE_CHINESE_TRADITIONAL, LANGUAGE_CHINESE_SIMPLIFIED, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, false,
+ true, false, false );
+ aWrap.Convert();
+
+ // Then
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString(CHINESE_SIMPLIFIED_CONTENT), pTextNode->GetText());
+
+}
+
+// Tests conversion of simplified Chinese characters to traditional Chinese
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testChineseConversionSimplifiedToTraditional)
+{
+
+ // Given
+ SwDoc* pDoc = createSwDoc();
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ const uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, OUString(CHINESE_SIMPLIFIED_CONTENT));
+
+ // When
+ SwHHCWrapper aWrap( pView, xContext, LANGUAGE_CHINESE_SIMPLIFIED, LANGUAGE_CHINESE_TRADITIONAL, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, false,
+ true, false, false );
+ aWrap.Convert();
+
+ // Then
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString(CHINESE_TRADITIONAL_CONTENT), pTextNode->GetText());
+
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo85554)
+{
+ // Load the document, it contains one shape with a textbox.
+ createSwDoc(DATA_DIRECTORY, "fdo85554.odt");
+
+ // Add a second shape to the document.
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
+ xShape->setSize(awt::Size(10000, 10000));
+ xShape->setPosition(awt::Point(1000, 1000));
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ xDrawPage->add(xShape);
+
+ // Save it and load it back.
+ reload("writer8", "fdo85554.odt");
+
+ // This was 1, we lost a shape on export.
+ CPPUNIT_ASSERT_EQUAL(2, getShapes());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testMergeDoc)
+{
+ SwDoc* const pDoc1(createSwDoc(DATA_DIRECTORY, "merge-change1.odt"));
+
+ auto xDoc2Component(loadFromDesktop(
+ m_directories.getURLFromSrc(DATA_DIRECTORY) + "merge-change2.odt",
+ "com.sun.star.text.TextDocument"));
+ auto pxDoc2Document(
+ dynamic_cast<SwXTextDocument *>(xDoc2Component.get()));
+ CPPUNIT_ASSERT(pxDoc2Document);
+ SwDoc* const pDoc2(pxDoc2Document->GetDocShell()->GetDoc());
+
+ SwEditShell* const pEditShell(pDoc1->GetEditShell());
+ pEditShell->MergeDoc(*pDoc2);
+
+ // accept all redlines
+ while(pEditShell->GetRedlineCount())
+ pEditShell->AcceptRedline(0);
+
+ CPPUNIT_ASSERT_EQUAL(7, getParagraphs());
+ getParagraph(1, "Para One: Two Three Four Five");
+ getParagraph(2, "Para Two: One Three Four Five");
+ getParagraph(3, "Para Three: One Two Four Five");
+ getParagraph(4, "Para Four: One Two Three Four Five");
+ getParagraph(5, "Para Six: One Three Four Five");
+ getParagraph(6, "");
+ getParagraph(7, "");
+
+ xDoc2Component->dispose();
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCreatePortions)
+{
+ createSwDoc(DATA_DIRECTORY, "uno-cycle.odt");
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextContent> xText(xBookmarksSupplier->getBookmarks()->getByName("Mark"), uno::UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xTextCursor(xText->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextCursor.is());
+
+ uno::Reference<container::XEnumerationAccess> xParagraph(
+ xTextCursor->createEnumeration()->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xParagraph.is());
+ // This looped forever in lcl_CreatePortions
+ xParagraph->createEnumeration();
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testBookmarkUndo)
+{
+ SwDoc* pDoc = createSwDoc();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ SwPaM aPaM( SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1) );
+
+ pMarkAccess->makeMark(aPaM, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark("Mark");
+ CPPUNIT_ASSERT(ppBkmk != pMarkAccess->getAllMarksEnd());
+
+ pMarkAccess->renameMark(*ppBkmk, "Mark_");
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd()));
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark") != pMarkAccess->getAllMarksEnd());
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark_") == pMarkAccess->getAllMarksEnd()));
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd()));
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());
+
+ pMarkAccess->deleteMark(pMarkAccess->findMark("Mark_"), false);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+}
+
+static void lcl_setWeight(SwWrtShell* pWrtShell, FontWeight aWeight)
+{
+ SvxWeightItem aWeightItem(aWeight, EE_CHAR_WEIGHT);
+ SvxScriptSetItem aScriptSetItem(SID_ATTR_CHAR_WEIGHT, pWrtShell->GetAttrPool());
+ aScriptSetItem.PutItemForScriptType(SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX, aWeightItem);
+ pWrtShell->SetAttrSet(aScriptSetItem.GetItemSet());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo85876)
+{
+ SwDoc* const pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ lcl_setWeight(pWrtShell, WEIGHT_BOLD);
+ pWrtShell->Insert("test");
+ lcl_setWeight(pWrtShell, WEIGHT_NORMAL);
+ pWrtShell->SplitNode();
+ pWrtShell->SplitNode();
+ pWrtShell->Up(false);
+ pWrtShell->Insert("test");
+ auto xText = getParagraph(1)->getText();
+ CPPUNIT_ASSERT(xText.is());
+ {
+ auto xCursor(xText->createTextCursorByRange(getParagraph(1)));
+ CPPUNIT_ASSERT(xCursor.is());
+ xCursor->collapseToStart();
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
+ }
+ {
+ auto xCursor(xText->createTextCursorByRange(getParagraph(2)));
+ CPPUNIT_ASSERT(xCursor.is());
+ xCursor->collapseToStart();
+ // this used to be BOLD too with fdo#85876
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCaretPositionMovingUp)
+{
+ SwDoc* const pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("after");
+ pWrtShell->InsertLineBreak();
+ pWrtShell->Up(false);
+ pWrtShell->Insert("before");
+
+ CPPUNIT_ASSERT_EQUAL(OUString(u"beforeAfter" + OUStringChar(CH_TXTATR_NEWLINE)), getParagraph(1)->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf93441)
+{
+ SwDoc* const pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("Hello");
+ pWrtShell->InsertLineBreak();
+ pWrtShell->Insert("Hello World");
+ pWrtShell->Up(false);
+ pWrtShell->Insert(" World");
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: Hello World\nHello World
+ // - Actual : WorldHello\nHello World
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Hello World" + OUStringChar(CH_TXTATR_NEWLINE) + u"Hello World"), getParagraph(1)->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf81226)
+{
+ SwDoc* const pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("before");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, /*bBasicCall=*/false);
+ pWrtShell->Down(false);
+ pWrtShell->Insert("after");
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: beforeafter
+ // - Actual : beafterfore
+ CPPUNIT_ASSERT_EQUAL(OUString("beforeafter"), getParagraph(1)->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf137532)
+{
+ SwDoc* const pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("test");
+
+ //Select the word and change it to bold
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 4, /*bBasicCall=*/false);
+ lcl_setWeight(pWrtShell, WEIGHT_BOLD);
+
+ // Select first character and replace it
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+ pWrtShell->Insert("x");
+
+ auto xText = getParagraph(1)->getText();
+ CPPUNIT_ASSERT(xText.is());
+ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
+
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("xest"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ xCursor.set(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), xCursor->getString());
+
+ // Without the fix in place, this test would have failed in
+ // - Expected: 150
+ // - Actual : 100
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ xCursor.set(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testFdo87448)
+{
+ createSwDoc(DATA_DIRECTORY, "fdo87448.odt");
+
+ // Save the first shape to a metafile.
+ uno::Reference<drawing::XGraphicExportFilter> xGraphicExporter = drawing::GraphicExportFilter::create(comphelper::getProcessComponentContext());
+ uno::Reference<lang::XComponent> xSourceDoc(getShape(1), uno::UNO_QUERY);
+ xGraphicExporter->setSourceDocument(xSourceDoc);
+
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "OutputStream", uno::Any(xOutputStream) },
+ { "FilterName", uno::Any(OUString("SVM")) }
+ }));
+ xGraphicExporter->filter(aDescriptor);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Read it back and dump it as an XML file.
+ Graphic aGraphic;
+ TypeSerializer aSerializer(aStream);
+ aSerializer.readGraphic(aGraphic);
+ const GDIMetaFile& rMetaFile = aGraphic.GetGDIMetaFile();
+ MetafileXmlDump dumper;
+ xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, rMetaFile);
+
+ // The first polyline in the document has a number of points to draw arcs,
+ // the last one jumps back to the start, so we call "end" the last but one.
+ sal_Int32 nFirstEnd = getXPath(pXmlDoc, "(//polyline)[1]/point[last()-1]", "x").toInt32();
+ // The second polyline has a different start point, but the arc it draws
+ // should end at the ~same position as the first polyline.
+ sal_Int32 nSecondEnd = getXPath(pXmlDoc, "(//polyline)[2]/point[last()]", "x").toInt32();
+
+ // nFirstEnd was 6023 and nSecondEnd was 6648, now they should be much closer, e.g. nFirstEnd = 6550, nSecondEnd = 6548
+ OString aMsg = "nFirstEnd is " + OString::number(nFirstEnd) + ", nSecondEnd is " + OString::number(nSecondEnd);
+ // Assert that the difference is less than half point.
+ CPPUNIT_ASSERT_MESSAGE(aMsg.getStr(), abs(nFirstEnd - nSecondEnd) < 10);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTextCursorInvalidation)
+{
+ createSwDoc();
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<beans::XPropertySet> xPageStyle(getStyles("PageStyles")->getByName("Standard"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPageStyle.is());
+ xPageStyle->setPropertyValue("HeaderIsOn", uno::Any(true));
+ uno::Reference<text::XText> xHeader(getProperty<uno::Reference<text::XText>>(xPageStyle, "HeaderText"));
+ CPPUNIT_ASSERT(xHeader.is());
+ // create cursor inside the header text
+ uno::Reference<text::XTextCursor> xCursor(xHeader->createTextCursor());
+ // can't go right in empty header
+ CPPUNIT_ASSERT(!xCursor->goRight(1, false));
+// this does not actually delete the header: xPageStyle->setPropertyValue("HeaderIsOn", uno::makeAny(false));
+ pWrtShell->ChangeHeaderOrFooter(u"Default Page Style", true, false, false);
+ // must be disposed after deleting header
+ // cursor ends up in body
+ // UPDATE: this behaviour has been corrected as a side effect of the fix to tdf#46561:
+ //CPPUNIT_ASSERT_THROW(xCursor->goRight(1, false), uno::RuntimeException);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf68183)
+{
+ // First disable RSID and check if indeed no such attribute is inserted.
+ SwDoc* pDoc = createSwDoc();
+ SW_MOD()->GetModuleConfig()->SetStoreRsid(false);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert2("X");
+
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(false, pTextNode->GetSwAttrSet().HasItem(RES_PARATR_RSID));
+
+ // Then enable storing of RSID and make sure that the attribute is inserted.
+ SW_MOD()->GetModuleConfig()->SetStoreRsid(true);
+
+ pWrtShell->DelToStartOfLine();
+ pWrtShell->Insert2("X");
+
+ CPPUNIT_ASSERT_EQUAL(true, pTextNode->GetSwAttrSet().HasItem(RES_PARATR_RSID));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCp1000115)
+{
+ createSwDoc(DATA_DIRECTORY, "cp1000115.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "/root/page[2]/body/tab/row/cell[2]/txt");
+ xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+ // This was 1: the long paragraph in the B1 cell did flow over to the
+ // second page, so there was only one paragraph in the second cell of the
+ // second page.
+ CPPUNIT_ASSERT_EQUAL(2, xmlXPathNodeSetGetLength(pXmlNodes));
+ xmlXPathFreeObject(pXmlObj);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf63214)
+{
+ //This is a crash test
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ pWrtShell->Insert("V");
+ { //limiting the lifetime of SwPaM with a nested scope
+ //the shell cursor are automatically adjusted when nodes are deleted, but the shell doesn't know about an SwPaM on the stack
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ SwPaM aPaM( SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1) );
+ aPaM.SetMark();
+ aPaM.Move(fnMoveForward, GoInContent);
+ //Inserting a crossRefBookmark
+ pMarkAccess->makeMark(aPaM, "Bookmark",
+ IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ }
+ //moving cursor to the end of paragraph
+ pWrtShell->EndPara();
+ //inserting paragraph break
+ pWrtShell->SplitNode();
+ rUndoManager.Undo();
+ rUndoManager.Redo();
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf90003)
+{
+ createSwDoc(DATA_DIRECTORY, "tdf90003.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ CPPUNIT_ASSERT(pXmlDoc);
+ // This was 1: an unexpected fly portion was created, resulting in too
+ // large x position for the empty paragraph marker.
+ assertXPath(pXmlDoc, "//Special[@nType='PortionType::Fly']", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf51741)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ SwPaM aPaM( SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1) );
+ //Modification 1
+ pMarkAccess->makeMark(aPaM, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ //Modification 2
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+ //Modification 3
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark("Mark");
+ CPPUNIT_ASSERT(ppBkmk != pMarkAccess->getAllMarksEnd());
+ //Modification 4
+ pMarkAccess->renameMark(*ppBkmk, "Mark_");
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd()));
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());
+ //Modification 5
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark") != pMarkAccess->getAllMarksEnd());
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark_") == pMarkAccess->getAllMarksEnd()));
+ //Modification 6
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT(bool(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd()));
+ CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());
+ //Modification 7
+ pMarkAccess->deleteMark(pMarkAccess->findMark("Mark_"), false);
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+ //Modification 8
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ //Modification 9
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(pWrtShell->IsModified());
+ pWrtShell->ResetModified();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDefaultsOfOutlineNumbering)
+{
+ uno::Reference<text::XDefaultNumberingProvider> xDefNum(m_xSFactory->createInstance("com.sun.star.text.DefaultNumberingProvider"), uno::UNO_QUERY);
+ css::lang::Locale alocale;
+ alocale.Language = "en";
+ alocale.Country = "US";
+ const uno::Sequence<beans::PropertyValues> aPropVal(xDefNum->getDefaultContinuousNumberingLevels(alocale));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aPropVal.getLength());
+ for(const auto& rPropValues : aPropVal)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), rPropValues.getLength());
+ for(const auto& rPropVal : rPropValues)
+ {
+ uno::Any aAny = rPropVal.Value;
+ if(rPropVal.Name == "Prefix" || rPropVal.Name == "Suffix" || rPropVal.Name == "Transliteration")
+ CPPUNIT_ASSERT_EQUAL(OUString("string"), aAny.getValueTypeName());
+ else if(rPropVal.Name == "NumberingType")
+ CPPUNIT_ASSERT_EQUAL(OUString("short"), aAny.getValueTypeName());
+ else if(rPropVal.Name == "NatNum")
+ CPPUNIT_ASSERT_EQUAL(OUString("short"), aAny.getValueTypeName());
+ //It is expected to be long but right now its short !error!
+ else
+ CPPUNIT_FAIL("Property Name not matched");
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testDeleteTableRedlines)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ const SwTable& rTable = pWrtShell->InsertTable(TableOpt, 1, 3);
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getColumns()->getCount());
+ uno::Sequence<beans::PropertyValue> aDescriptor;
+ SwUnoCursorHelper::makeTableCellRedline((*const_cast<SwTableBox*>(rTable.GetTableBox("A1"))), u"TableCellInsert", aDescriptor);
+ SwUnoCursorHelper::makeTableCellRedline((*const_cast<SwTableBox*>(rTable.GetTableBox("B1"))), u"TableCellInsert", aDescriptor);
+ SwUnoCursorHelper::makeTableCellRedline((*const_cast<SwTableBox*>(rTable.GetTableBox("C1"))), u"TableCellInsert", aDescriptor);
+ IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+ SwExtraRedlineTable& rExtras = rIDRA.GetExtraRedlineTable();
+ rExtras.DeleteAllTableRedlines(*pDoc, rTable, false, RedlineType::Any);
+ CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(0), rExtras.GetSize());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testXFlatParagraph)
+{
+ SwDoc* pDoc = createSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //Inserting some text in the document
+ pWrtShell->Insert("This is sample text");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("This is another sample text");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("This is yet another sample text");
+ //retrieving the XFlatParagraphs
+ uno::Reference<text::XFlatParagraphIteratorProvider> xFPIP(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XFlatParagraphIterator> xFPIterator(xFPIP->getFlatParagraphIterator(sal_Int32(text::TextMarkupType::SPELLCHECK), true));
+ uno::Reference<text::XFlatParagraph> xFlatPara(xFPIterator->getFirstPara());
+ CPPUNIT_ASSERT_EQUAL(OUString("This is sample text"), xFlatPara->getText());
+ //checking modified status
+ CPPUNIT_ASSERT(!xFlatPara->isModified());
+ //checking "checked" status, modifying it and asserting the changes
+ CPPUNIT_ASSERT(!xFlatPara->isChecked(sal_Int32(text::TextMarkupType::SPELLCHECK)));
+ xFlatPara->setChecked((sal_Int32(text::TextMarkupType::SPELLCHECK)), true);
+ CPPUNIT_ASSERT(xFlatPara->isChecked(sal_Int32(text::TextMarkupType::SPELLCHECK)));
+ //getting other XFlatParagraphs and asserting their contents
+ uno::Reference<text::XFlatParagraph> xFlatPara2(xFPIterator->getParaAfter(xFlatPara));
+ CPPUNIT_ASSERT_EQUAL(OUString("This is another sample text"), xFlatPara2->getText());
+ uno::Reference<text::XFlatParagraph> xFlatPara3(xFPIterator->getParaAfter(xFlatPara2));
+ CPPUNIT_ASSERT_EQUAL(OUString("This is yet another sample text"), xFlatPara3->getText());
+ uno::Reference<text::XFlatParagraph> xFlatPara4(xFPIterator->getParaBefore(xFlatPara3));
+ CPPUNIT_ASSERT_EQUAL(xFlatPara2->getText(), xFlatPara4->getText());
+ //changing the attributes of last para
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "CharWeight", uno::Any(float(css::awt::FontWeight::BOLD)) }
+ }));
+ xFlatPara3->changeAttributes(sal_Int32(0), sal_Int32(5), aDescriptor);
+ //checking Language Portions
+ uno::Sequence<::sal_Int32> aLangPortions(xFlatPara4->getLanguagePortions());
+ CPPUNIT_ASSERT(!aLangPortions.hasElements());
+ //examining Language of text
+ css::lang::Locale alocale = xFlatPara4->getLanguageOfText(sal_Int32(0), sal_Int32(4));
+ CPPUNIT_ASSERT_EQUAL(OUString("en"), alocale.Language);
+ CPPUNIT_ASSERT_EQUAL(OUString("US"), alocale.Country);
+ //examining Primary Language of text
+ css::lang::Locale aprimarylocale = xFlatPara4->getPrimaryLanguageOfText(sal_Int32(0), sal_Int32(20));
+ CPPUNIT_ASSERT_EQUAL(OUString("en"), aprimarylocale.Language);
+ CPPUNIT_ASSERT_EQUAL(OUString("US"), aprimarylocale.Country);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf81995)
+{
+ uno::Reference<text::XDefaultNumberingProvider> xDefNum(m_xSFactory->createInstance("com.sun.star.text.DefaultNumberingProvider"), uno::UNO_QUERY);
+ css::lang::Locale alocale;
+ alocale.Language = "en";
+ alocale.Country = "US";
+ const uno::Sequence<uno::Reference<container::XIndexAccess>> aIndexAccess(xDefNum->getDefaultOutlineNumberings(alocale));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aIndexAccess.getLength());
+ for(const auto& rIndexAccess : aIndexAccess)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), rIndexAccess->getCount());
+ for(int j=0;j<rIndexAccess->getCount();j++)
+ {
+ uno::Sequence<beans::PropertyValue> aProps;
+ rIndexAccess->getByIndex(j) >>= aProps;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(12), aProps.getLength());
+ for(const beans::PropertyValue& rProp : std::as_const(aProps))
+ {
+ uno::Any aAny = rProp.Value;
+ if(rProp.Name == "Prefix" || rProp.Name == "Suffix" || rProp.Name == "BulletChar" || rProp.Name == "BulletFontName" || rProp.Name == "Transliteration")
+ CPPUNIT_ASSERT_EQUAL(OUString("string"), aAny.getValueTypeName());
+ else if(rProp.Name == "NumberingType" || rProp.Name == "ParentNumbering" || rProp.Name == "Adjust")
+ CPPUNIT_ASSERT_EQUAL(OUString("short"), aAny.getValueTypeName());
+ else if(rProp.Name == "LeftMargin" || rProp.Name == "SymbolTextDistance" || rProp.Name == "FirstLineOffset" || rProp.Name == "NatNum")
+ CPPUNIT_ASSERT_EQUAL(OUString("long"), aAny.getValueTypeName());
+ else
+ CPPUNIT_FAIL("Property Name not matched");
+ }
+ }
+ }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */