summaryrefslogtreecommitdiffstats
path: root/sw/qa/extras/uiwriter/uiwriter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/qa/extras/uiwriter/uiwriter.cxx')
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx7783
1 files changed, 7783 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..32788114c
--- /dev/null
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -0,0 +1,7783 @@
+/* -*- 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 <memory>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <com/sun/star/style/CaseMap.hpp>
+#include <vcl/errcode.hxx>
+#include <tools/gen.hxx>
+#include <swmodeltestbase.hxx>
+#include <ndtxt.hxx>
+#include <wrtsh.hxx>
+#include <shellio.hxx>
+#include <expfld.hxx>
+#include <drawdoc.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <section.hxx>
+#include <fmtclds.hxx>
+#include <dcontact.hxx>
+#include <textboxhelper.hxx>
+#include <view.hxx>
+#include <hhcwrp.hxx>
+#include <swacorr.hxx>
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <charatr.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unocrsr.hxx>
+#include <unocrsrhelper.hxx>
+#include <unotbl.hxx>
+#include <IMark.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <pagedesc.hxx>
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <config_libnumbertext.h>
+
+#include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
+#include <svx/xfillit0.hxx>
+#include <svl/itemiter.hxx>
+#include <svx/svxids.hrc>
+#include <unotools/localfilehelper.hxx>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <i18nutil/transliteration.hxx>
+#include <i18nutil/searchopt.hxx>
+#include <reffld.hxx>
+#include <dbfld.hxx>
+#include <txatbase.hxx>
+#include <txtftn.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentState.hxx>
+#include <unofldmid.h>
+#include <UndoManager.hxx>
+#include <textsh.hxx>
+#include <frmatr.hxx>
+#include <frmmgr.hxx>
+#include <tblafmt.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/util/SearchAlgorithms.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/text/XParagraphCursor.hpp>
+#include <com/sun/star/util/XPropertyReplace.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <o3tl/cppunittraitshelper.hxx>
+#include <o3tl/deleter.hxx>
+#include <osl/file.hxx>
+#include <osl/thread.hxx>
+#include <paratr.hxx>
+#include <drawfont.hxx>
+#include <txtfrm.hxx>
+#include <txttypes.hxx>
+#include <SwPortionHandler.hxx>
+#include <hyp.hxx>
+#include <swdtflvr.hxx>
+#include <editeng/svxenum.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <sfx2/classificationhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <comphelper/configurationhelper.hxx>
+#include <editeng/unolingu.hxx>
+#include <vcl/scheduler.hxx>
+#include <config_features.h>
+#include <sfx2/watermarkitem.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/docfile.hxx>
+#include <test/htmltesttools.hxx>
+#include <fmthdft.hxx>
+#include <iodetect.hxx>
+#include <wrthtml.hxx>
+#include <dbmgr.hxx>
+#include <frameformats.hxx>
+
+namespace
+{
+char const DATA_DIRECTORY[] = "/sw/qa/extras/uiwriter/data/";
+
+int CountFilesInDirectory(const OUString &rURL)
+{
+ int nRet = 0;
+
+ osl::Directory aDir(rURL);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aDir.open());
+
+ osl::DirectoryItem aItem;
+ osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type);
+ while (aDir.getNextItem(aItem) == osl::FileBase::E_None)
+ {
+ aItem.getFileStatus(aFileStatus);
+ if (aFileStatus.getFileType() != osl::FileStatus::Directory)
+ ++nRet;
+ }
+
+ return nRet;
+}
+}
+
+class SwUiWriterTest : public SwModelTestBase, public HtmlTestTools
+{
+
+public:
+ void testReplaceForward();
+ //Regression test of fdo#70143
+ //EDITING: undo search&replace corrupt text when searching backward
+ void testReplaceBackward();
+ void testRedlineFrame(char const*const file);
+ void testRedlineFrameAtCharStartOutside0();
+ void testRedlineFrameAtCharStartOutside();
+ void testRedlineFrameAtCharStartInside();
+ void testRedlineFrameAtParaStartOutside();
+ void testRedlineFrameAtParaEndInside();
+ void testRedlineFrameAtParaOneParagraph();
+ void testRedlineFrameAtPara2ndParagraph();
+ void testThreadedException();
+ void testBookmarkCopy();
+ void testFdo69893();
+ void testFdo70807();
+ void testImportRTF();
+ void testExportRTF();
+ void testDOCXAutoTextEmpty();
+ void testDOCXAutoTextMultiple();
+ void testDOTMAutoText();
+ void testDOCXAutoTextGallery();
+ void testWatermarkDOCX();
+ void testWatermarkPosition();
+ void testTdf67238();
+ void testFdo75110();
+ void testFdo75898();
+ void testFdo74981();
+ void testTdf98512();
+ void testShapeTextboxSelect();
+ void testShapeTextboxDelete();
+ void testAnchorChangeSelection();
+ void testCp1000071();
+ void testShapeTextboxVertadjust();
+ void testShapeTextboxAutosize();
+ void testFdo82191();
+ void testCommentedWord();
+ void testTextFieldGetAnchorGetTextInFooter();
+ void testChineseConversionBlank();
+ void testChineseConversionNonChineseText();
+ void testChineseConversionTraditionalToSimplified();
+ void testChineseConversionSimplifiedToTraditional();
+ void testFdo85554();
+ void testAutoCorr();
+ void testTdf83260();
+ void testTdf130274();
+ void testMergeDoc();
+ void testCreatePortions();
+ void testBookmarkUndo();
+ void testFdo85876();
+ void testTdf79717();
+ void testTdf137532();
+ void testFdo87448();
+ void testTextCursorInvalidation();
+ void testTdf68183();
+ void testCp1000115();
+ void testTdf63214();
+ void testTdf90003();
+ void testTdf51741();
+ void testDefaultsOfOutlineNumbering();
+ void testDeleteTableRedlines();
+ void testXFlatParagraph();
+ void testTdf81995();
+ void testForcepoint3();
+ void testForcepoint80();
+ void testExportToPicture();
+ void testTdf77340();
+ void testTdf79236();
+ void testTextSearch();
+ void testTdf69282();
+ void testTdf69282WithMirror();
+ void testTdf78742();
+ void testUnoParagraph();
+ void testTdf72788();
+ void testTdf60967();
+ void testSearchWithTransliterate();
+ void testTdf73660();
+ void testNewDocModifiedState();
+ void testTdf77342();
+ void testTdf63553();
+ void testTdf74230();
+ void testTdf74363();
+ void testTdf80663();
+ void testTdf57197();
+ void testTdf90808();
+ void testTdf97601();
+ void testTdf75137();
+ void testTdf83798();
+ void testTdf89714();
+ void testTdf130287();
+ void testPropertyDefaults();
+ void testTableBackgroundColor();
+ void testTdf88899();
+ void testTdf90362();
+ void testUndoDelAsCharTdf107512();
+ void testUndoCharAttribute();
+ void testUndoDelAsChar();
+ void testTdf86639();
+ void testTdf90883TableBoxGetCoordinates();
+ void testEmbeddedDataSource();
+ void testUnoCursorPointer();
+ void testUnicodeNotationToggle();
+ void testTextTableCellNames();
+ void testShapeAnchorUndo();
+ void testDde();
+ void testDocModState();
+ void testTdf94804();
+ void testTdf34957();
+ void testTdf89954();
+ void testTdf89720();
+ void testTdf88986();
+ void testTdf87922();
+ void testTdf77014();
+ void testTdf92648();
+ void testTdf103978_backgroundTextShape();
+ void testTdf96515();
+ void testTdf96943();
+ void testTdf96536();
+ void testTdf96479();
+ void testBookmarkCollapsed();
+ void testRemoveBookmarkText();
+ void testRemoveBookmarkTextAndAddNew();
+ void testRemoveBookmarkTextAndAddNewAfterReload();
+ void testTdf96961();
+ void testTdf88453();
+ void testTdf88453Table();
+ void testClassificationPaste();
+ void testSmallCaps();
+ void testTdf98987();
+ void testTdf99004();
+ void testTdf84695();
+ void testTdf84695NormalChar();
+ void testTdf84695Tab();
+ void testTableStyleUndo();
+ void testRedlineCopyPaste();
+ void testRedlineParam();
+ void testRedlineViewAuthor();
+ void testTdf91292();
+ void testTdf78727();
+ void testRedlineTimestamp();
+ void testCursorWindows();
+ void testLandscape();
+ void testTdf95699();
+ void testTdf104032();
+ void testTdf104440();
+ void testTdf104425();
+ void testTdf104814();
+ void testTdf66405();
+ void testTdf35021_tabOverMarginDemo();
+ void testTdf106701_tabOverMarginAutotab();
+ void testTdf104492();
+ void testTdf107025();
+ void testTdf107362();
+ void testTdf105417();
+ void testTdf105625();
+ void testTdf125151_protected();
+ void testTdf125151_protectedB();
+ void testTdf106736();
+ void testTdf58604();
+ void testTdf112025();
+ void testTdf72942();
+ void testTdf113877();
+ void testTdf113877NoMerge();
+ void testTdf113877_default_style();
+ void testTdf113877_Standard_style();
+ void testMsWordCompTrailingBlanks();
+ void testCreateDocxAnnotation();
+ void testTdf107976();
+ void testTdf108524();
+ void testRhbz1810732();
+ void testTableInSection();
+ void testTableInNestedSection();
+ void testTableInSectionInTable();
+ void testSectionInTableInTable();
+ void testSectionInTableInTable2();
+ void testSectionInTableInTable3();
+ void testSectionInTableInTable4();
+ void testTdf112160();
+ void testLinesMoveBackwardsInSectionInTable();
+ void testTdf112741();
+ void testTdf112860();
+ void testTdf113287();
+ void testTdf113445();
+ void testTdf113686();
+ void testFontEmbedding();
+ void testLinesInSectionInTable();
+ void testParagraphOfTextRange();
+ void testTdf99689TableOfContents();
+ void testTdf99689TableOfFigures();
+ void testTdf99689TableOfTables();
+ void testTdf112448();
+ void testTdf113790();
+ void testTdf108048();
+ void testTdf114306();
+ void testTdf114306_2();
+ void testTdf113481();
+ void testTdf115013();
+ void testTdf114536();
+ void testTdf115065();
+ void testTdf115132();
+ void testXDrawPagesSupplier();
+ void testTdf116403();
+ void testHtmlCopyImages();
+ void testTdf116789();
+ void testTdf117225();
+ void testTdf91801();
+ void testTdf51223();
+ void testTdf108423();
+ void testTdf106164();
+ void testTdf54409();
+ void testTdf38394();
+ void testTdf59666();
+ void testTdf133524();
+ void testTdf133524_Romanian();
+ void testTdf128860();
+ void testTdf123786();
+#if ENABLE_LIBNUMBERTEXT
+ void testTdf133589();
+#endif
+ void testInconsistentBookmark();
+ void testInsertLongDateFormat();
+#if HAVE_FEATURE_PDFIUM
+ void testInsertPdf();
+#endif
+
+ CPPUNIT_TEST_SUITE(SwUiWriterTest);
+ CPPUNIT_TEST(testReplaceForward);
+ CPPUNIT_TEST(testReplaceBackward);
+ CPPUNIT_TEST(testRedlineFrameAtCharStartOutside0);
+ CPPUNIT_TEST(testRedlineFrameAtCharStartOutside);
+ CPPUNIT_TEST(testRedlineFrameAtCharStartInside);
+ CPPUNIT_TEST(testRedlineFrameAtParaStartOutside);
+ CPPUNIT_TEST(testRedlineFrameAtParaEndInside);
+ CPPUNIT_TEST(testRedlineFrameAtParaOneParagraph);
+ CPPUNIT_TEST(testRedlineFrameAtPara2ndParagraph);
+ CPPUNIT_TEST(testThreadedException);
+ CPPUNIT_TEST(testBookmarkCopy);
+ CPPUNIT_TEST(testFdo69893);
+ CPPUNIT_TEST(testFdo70807);
+ CPPUNIT_TEST(testImportRTF);
+ CPPUNIT_TEST(testExportRTF);
+ CPPUNIT_TEST(testDOCXAutoTextEmpty);
+ CPPUNIT_TEST(testDOCXAutoTextMultiple);
+ CPPUNIT_TEST(testDOTMAutoText);
+ CPPUNIT_TEST(testDOCXAutoTextGallery);
+ CPPUNIT_TEST(testWatermarkDOCX);
+ CPPUNIT_TEST(testWatermarkPosition);
+ CPPUNIT_TEST(testTdf67238);
+ CPPUNIT_TEST(testFdo75110);
+ CPPUNIT_TEST(testFdo75898);
+ CPPUNIT_TEST(testFdo74981);
+ CPPUNIT_TEST(testTdf98512);
+ CPPUNIT_TEST(testShapeTextboxSelect);
+ CPPUNIT_TEST(testShapeTextboxDelete);
+ CPPUNIT_TEST(testAnchorChangeSelection);
+ CPPUNIT_TEST(testCp1000071);
+ CPPUNIT_TEST(testShapeTextboxVertadjust);
+ CPPUNIT_TEST(testShapeTextboxAutosize);
+ CPPUNIT_TEST(testFdo82191);
+ CPPUNIT_TEST(testCommentedWord);
+ CPPUNIT_TEST(testTextFieldGetAnchorGetTextInFooter);
+ CPPUNIT_TEST(testChineseConversionBlank);
+ CPPUNIT_TEST(testChineseConversionNonChineseText);
+ CPPUNIT_TEST(testChineseConversionTraditionalToSimplified);
+ CPPUNIT_TEST(testChineseConversionSimplifiedToTraditional);
+ CPPUNIT_TEST(testFdo85554);
+ CPPUNIT_TEST(testAutoCorr);
+ CPPUNIT_TEST(testTdf83260);
+ CPPUNIT_TEST(testTdf130274);
+ CPPUNIT_TEST(testMergeDoc);
+ CPPUNIT_TEST(testCreatePortions);
+ CPPUNIT_TEST(testBookmarkUndo);
+ CPPUNIT_TEST(testFdo85876);
+ CPPUNIT_TEST(testTdf79717);
+ CPPUNIT_TEST(testTdf137532);
+ CPPUNIT_TEST(testFdo87448);
+ CPPUNIT_TEST(testTextCursorInvalidation);
+ CPPUNIT_TEST(testTdf68183);
+ CPPUNIT_TEST(testCp1000115);
+ CPPUNIT_TEST(testTdf63214);
+ CPPUNIT_TEST(testTdf90003);
+ CPPUNIT_TEST(testTdf51741);
+ CPPUNIT_TEST(testDefaultsOfOutlineNumbering);
+ CPPUNIT_TEST(testDeleteTableRedlines);
+ CPPUNIT_TEST(testXFlatParagraph);
+ CPPUNIT_TEST(testTdf81995);
+ CPPUNIT_TEST(testForcepoint3);
+ CPPUNIT_TEST(testForcepoint80);
+ CPPUNIT_TEST(testExportToPicture);
+ CPPUNIT_TEST(testTdf77340);
+ CPPUNIT_TEST(testTdf79236);
+ CPPUNIT_TEST(testTextSearch);
+ CPPUNIT_TEST(testTdf69282);
+ CPPUNIT_TEST(testTdf69282WithMirror);
+ CPPUNIT_TEST(testTdf78742);
+ CPPUNIT_TEST(testUnoParagraph);
+ CPPUNIT_TEST(testTdf72788);
+ CPPUNIT_TEST(testTdf60967);
+ CPPUNIT_TEST(testSearchWithTransliterate);
+ CPPUNIT_TEST(testTdf73660);
+ CPPUNIT_TEST(testNewDocModifiedState);
+ CPPUNIT_TEST(testTdf77342);
+ CPPUNIT_TEST(testTdf63553);
+ CPPUNIT_TEST(testTdf74230);
+ CPPUNIT_TEST(testTdf74363);
+ CPPUNIT_TEST(testTdf80663);
+ CPPUNIT_TEST(testTdf57197);
+ CPPUNIT_TEST(testTdf90808);
+ CPPUNIT_TEST(testTdf97601);
+ CPPUNIT_TEST(testTdf75137);
+ CPPUNIT_TEST(testTdf83798);
+ CPPUNIT_TEST(testTdf89714);
+ CPPUNIT_TEST(testTdf130287);
+ CPPUNIT_TEST(testPropertyDefaults);
+ CPPUNIT_TEST(testTableBackgroundColor);
+ CPPUNIT_TEST(testTdf88899);
+ CPPUNIT_TEST(testTdf90362);
+ CPPUNIT_TEST(testUndoDelAsCharTdf107512);
+ CPPUNIT_TEST(testUndoCharAttribute);
+ CPPUNIT_TEST(testUndoDelAsChar);
+ CPPUNIT_TEST(testTdf86639);
+ CPPUNIT_TEST(testTdf90883TableBoxGetCoordinates);
+ CPPUNIT_TEST(testEmbeddedDataSource);
+ CPPUNIT_TEST(testUnoCursorPointer);
+ CPPUNIT_TEST(testUnicodeNotationToggle);
+ CPPUNIT_TEST(testTextTableCellNames);
+ CPPUNIT_TEST(testShapeAnchorUndo);
+ CPPUNIT_TEST(testDde);
+ CPPUNIT_TEST(testDocModState);
+ CPPUNIT_TEST(testTdf94804);
+ CPPUNIT_TEST(testTdf34957);
+ CPPUNIT_TEST(testTdf89954);
+ CPPUNIT_TEST(testTdf89720);
+ CPPUNIT_TEST(testTdf88986);
+ CPPUNIT_TEST(testTdf87922);
+ CPPUNIT_TEST(testTdf77014);
+ CPPUNIT_TEST(testTdf92648);
+ CPPUNIT_TEST(testTdf103978_backgroundTextShape);
+ CPPUNIT_TEST(testTdf96515);
+ CPPUNIT_TEST(testTdf96943);
+ CPPUNIT_TEST(testTdf96536);
+ CPPUNIT_TEST(testTdf96479);
+ CPPUNIT_TEST(testBookmarkCollapsed);
+ CPPUNIT_TEST(testRemoveBookmarkText);
+ CPPUNIT_TEST(testRemoveBookmarkTextAndAddNew);
+ CPPUNIT_TEST(testRemoveBookmarkTextAndAddNewAfterReload);
+ CPPUNIT_TEST(testTdf96961);
+ CPPUNIT_TEST(testTdf88453);
+ CPPUNIT_TEST(testTdf88453Table);
+ CPPUNIT_TEST(testClassificationPaste);
+ CPPUNIT_TEST(testSmallCaps);
+ CPPUNIT_TEST(testTdf98987);
+ CPPUNIT_TEST(testTdf99004);
+ CPPUNIT_TEST(testTdf84695);
+ CPPUNIT_TEST(testTdf84695NormalChar);
+ CPPUNIT_TEST(testTdf84695Tab);
+ CPPUNIT_TEST(testTableStyleUndo);
+ CPPUNIT_TEST(testRedlineCopyPaste);
+ CPPUNIT_TEST(testRedlineParam);
+ CPPUNIT_TEST(testRedlineViewAuthor);
+ CPPUNIT_TEST(testTdf91292);
+ CPPUNIT_TEST(testTdf78727);
+ CPPUNIT_TEST(testRedlineTimestamp);
+ CPPUNIT_TEST(testCursorWindows);
+ CPPUNIT_TEST(testLandscape);
+ CPPUNIT_TEST(testTdf95699);
+ CPPUNIT_TEST(testTdf104032);
+ CPPUNIT_TEST(testTdf104440);
+ CPPUNIT_TEST(testTdf104425);
+ CPPUNIT_TEST(testTdf104814);
+ CPPUNIT_TEST(testTdf66405);
+ CPPUNIT_TEST(testTdf35021_tabOverMarginDemo);
+ CPPUNIT_TEST(testTdf106701_tabOverMarginAutotab);
+ CPPUNIT_TEST(testTdf104492);
+ CPPUNIT_TEST(testTdf107025);
+ CPPUNIT_TEST(testTdf107362);
+ CPPUNIT_TEST(testTdf105417);
+ CPPUNIT_TEST(testTdf105625);
+ CPPUNIT_TEST(testTdf125151_protected);
+ CPPUNIT_TEST(testTdf125151_protectedB);
+ CPPUNIT_TEST(testTdf106736);
+ CPPUNIT_TEST(testTdf58604);
+ CPPUNIT_TEST(testTdf112025);
+ CPPUNIT_TEST(testTdf72942);
+ CPPUNIT_TEST(testTdf113877);
+ CPPUNIT_TEST(testTdf113877NoMerge);
+ CPPUNIT_TEST(testTdf113877_default_style);
+ CPPUNIT_TEST(testTdf113877_Standard_style);
+ CPPUNIT_TEST(testMsWordCompTrailingBlanks);
+ CPPUNIT_TEST(testCreateDocxAnnotation);
+ CPPUNIT_TEST(testTdf107976);
+ CPPUNIT_TEST(testTdf108524);
+ CPPUNIT_TEST(testRhbz1810732);
+ CPPUNIT_TEST(testTableInSection);
+ CPPUNIT_TEST(testTableInNestedSection);
+ CPPUNIT_TEST(testTableInSectionInTable);
+ CPPUNIT_TEST(testSectionInTableInTable);
+ CPPUNIT_TEST(testSectionInTableInTable2);
+ CPPUNIT_TEST(testSectionInTableInTable3);
+ CPPUNIT_TEST(testSectionInTableInTable4);
+ CPPUNIT_TEST(testTdf112160);
+ CPPUNIT_TEST(testLinesMoveBackwardsInSectionInTable);
+ CPPUNIT_TEST(testTdf112741);
+ CPPUNIT_TEST(testTdf112860);
+ CPPUNIT_TEST(testTdf113287);
+ CPPUNIT_TEST(testTdf113445);
+ CPPUNIT_TEST(testTdf113686);
+ CPPUNIT_TEST(testFontEmbedding);
+ CPPUNIT_TEST(testLinesInSectionInTable);
+ CPPUNIT_TEST(testParagraphOfTextRange);
+ CPPUNIT_TEST(testTdf99689TableOfContents);
+ CPPUNIT_TEST(testTdf99689TableOfFigures);
+ CPPUNIT_TEST(testTdf99689TableOfTables);
+ CPPUNIT_TEST(testTdf112448);
+ CPPUNIT_TEST(testTdf113790);
+ CPPUNIT_TEST(testTdf108048);
+ CPPUNIT_TEST(testTdf114306);
+ CPPUNIT_TEST(testTdf114306_2);
+ CPPUNIT_TEST(testTdf113481);
+ CPPUNIT_TEST(testTdf115013);
+ CPPUNIT_TEST(testTdf114536);
+ CPPUNIT_TEST(testTdf115065);
+ CPPUNIT_TEST(testTdf115132);
+ CPPUNIT_TEST(testXDrawPagesSupplier);
+ CPPUNIT_TEST(testTdf116403);
+ CPPUNIT_TEST(testHtmlCopyImages);
+ CPPUNIT_TEST(testTdf116789);
+ CPPUNIT_TEST(testTdf117225);
+ CPPUNIT_TEST(testTdf91801);
+ CPPUNIT_TEST(testTdf51223);
+ CPPUNIT_TEST(testInconsistentBookmark);
+ CPPUNIT_TEST(testTdf108423);
+ CPPUNIT_TEST(testTdf106164);
+ CPPUNIT_TEST(testTdf54409);
+ CPPUNIT_TEST(testTdf38394);
+ CPPUNIT_TEST(testTdf59666);
+ CPPUNIT_TEST(testTdf133524);
+ CPPUNIT_TEST(testTdf133524_Romanian);
+ CPPUNIT_TEST(testTdf128860);
+ CPPUNIT_TEST(testTdf123786);
+#if ENABLE_LIBNUMBERTEXT
+ CPPUNIT_TEST(testTdf133589);
+#endif
+ CPPUNIT_TEST(testInsertLongDateFormat);
+#if HAVE_FEATURE_PDFIUM
+ CPPUNIT_TEST(testInsertPdf);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ SwDoc* createDoc(const char* pName = nullptr);
+ std::unique_ptr<SwTextBlocks> readDOCXAutotext(const OUString& sFileName, bool bEmpty = false);
+};
+
+SwDoc* SwUiWriterTest::createDoc(const char* pName)
+{
+ if (!pName)
+ loadURL("private:factory/swriter", nullptr);
+ else
+ load(DATA_DIRECTORY, pName);
+
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ return pTextDoc->GetDocShell()->GetDoc();
+}
+
+std::unique_ptr<SwTextBlocks> SwUiWriterTest::readDOCXAutotext(const OUString& 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 = createDoc();
+
+ 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;
+}
+
+//Replacement tests
+
+static 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);
+}
+
+static const OUString ORIGINAL_REPLACE_CONTENT("toto titi tutu");
+static const OUString EXPECTED_REPLACE_CONTENT("toto toto tutu");
+
+void SwUiWriterTest::testReplaceForward()
+{
+ SwDoc* pDoc = createDoc();
+
+ 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(EXPECTED_REPLACE_CONTENT, pTextNode->GetText());
+
+ rUndoManager.Undo();
+
+ CPPUNIT_ASSERT_EQUAL(ORIGINAL_REPLACE_CONTENT, pTextNode->GetText());
+}
+
+void SwUiWriterTest::testRedlineFrame(char const*const file)
+{
+ SwDoc * pDoc(createDoc(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());
+}
+
+void SwUiWriterTest::testRedlineFrameAtCharStartOutside0()
+{
+ testRedlineFrame("redlineFrame.fodt");
+}
+
+void SwUiWriterTest::testRedlineFrameAtCharStartOutside()
+{
+ testRedlineFrame("redlineFrame_at_char_start_outside.fodt");
+}
+
+void SwUiWriterTest::testRedlineFrameAtCharStartInside()
+{
+ testRedlineFrame("redlineFrame_at_char_start_inside.fodt");
+}
+
+void SwUiWriterTest::testRedlineFrameAtParaStartOutside()
+{
+ testRedlineFrame("redline_fly_duplication_at_para_start_outside.fodt");
+}
+
+void SwUiWriterTest::testRedlineFrameAtParaEndInside()
+{
+ testRedlineFrame("redline_fly_duplication_at_para_end_inside.fodt");
+}
+
+void 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");
+}
+
+void SwUiWriterTest::testRedlineFrameAtPara2ndParagraph()
+{
+ // lost via the buggy increment in Copy
+ testRedlineFrame("redline_fly_duplication_at_para_2nd_paragraph.fodt");
+}
+
+void 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);
+}
+
+void SwUiWriterTest::testBookmarkCopy()
+{
+ SwDoc * pDoc(createDoc());
+
+ // 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);
+ }
+}
+
+void SwUiWriterTest::testTdf67238()
+{
+ //create a new writer document
+ SwDoc* pDoc = createDoc();
+ 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());
+}
+
+void SwUiWriterTest::testFdo75110()
+{
+ SwDoc* pDoc = createDoc("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();
+}
+
+void SwUiWriterTest::testFdo75898()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testReplaceBackward()
+{
+ SwDoc* pDoc = createDoc();
+
+ 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(EXPECTED_REPLACE_CONTENT, pTextNode->GetText());
+
+ rUndoManager.Undo();
+
+ CPPUNIT_ASSERT_EQUAL(ORIGINAL_REPLACE_CONTENT, pTextNode->GetText());
+}
+
+void SwUiWriterTest::testFdo69893()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testFdo70807()
+{
+ load(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()));
+ }
+}
+
+void SwUiWriterTest::testImportRTF()
+{
+ // Insert "foobar" and position the cursor between "foo" and "bar".
+ SwDoc* pDoc = createDoc();
+ 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));
+
+ sal_uLong 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());
+}
+
+void SwUiWriterTest::testExportRTF()
+{
+ // Insert "aaabbbccc" and select "bbb".
+ SwDoc* pDoc = createDoc();
+ 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.get());
+
+ // And finally export it as RTF.
+ WriterRef xWrt;
+ SwReaderWriter::GetWriter("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 "}"));
+}
+
+void SwUiWriterTest::testDOCXAutoTextEmpty()
+{
+ // file contains normal content but no AutoText
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext("autotext-empty.dotx", true);
+ CPPUNIT_ASSERT(pGlossary != nullptr);
+}
+
+void SwUiWriterTest::testDOCXAutoTextMultiple()
+{
+ // file contains three AutoText entries
+ std::unique_ptr<SwTextBlocks> pGlossary = readDOCXAutotext("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());
+}
+
+void 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("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());
+}
+
+void 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("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));
+}
+
+void SwUiWriterTest::testWatermarkDOCX()
+{
+ SwDoc* const pDoc = createDoc("watermark.docx");
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ const SfxPoolItem* pItem;
+ SfxItemState eState = pDocShell->GetViewShell()->GetViewFrame()->GetDispatcher()->QueryState(SID_WATERMARK, pItem);
+
+ CPPUNIT_ASSERT(eState >= SfxItemState::DEFAULT);
+ CPPUNIT_ASSERT(pItem);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(SID_WATERMARK), pItem->Which());
+
+ const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>(pItem);
+ 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, testTdf134252)
+{
+ load(DATA_DIRECTORY, "tdf134252.fodt");
+
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCursor(xTextViewCursorSupplier->getViewCursor());
+ uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
+
+ // select all with section
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar" SAL_NEWLINE_STRING "baz" SAL_NEWLINE_STRING), xCursor->getString());
+
+ dispatchCommand(mxComponent, ".uno:Delete", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xCursor->getString());
+
+ // this would crash
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar" SAL_NEWLINE_STRING "baz" SAL_NEWLINE_STRING), xCursor->getString());
+
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xCursor->getString());
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar" SAL_NEWLINE_STRING "baz" SAL_NEWLINE_STRING), xCursor->getString());
+
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xCursor->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf136453)
+{
+ load(DATA_DIRECTORY, "tdf136453.fodt");
+
+ SwXTextDocument *const pTextDoc(dynamic_cast<SwXTextDocument*>(mxComponent.get()));
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* const pDoc(pTextDoc->GetDocShell()->GetDoc());
+ SwWrtShell *const pWrtShell(pDoc->GetDocShell()->GetWrtShell());
+
+ sal_uLong const nNodes(pDoc->GetNodes().Count());
+
+ pWrtShell->SttEndDoc(false);
+ pWrtShell->SetMark();
+ pWrtShell->Up(true, 1);
+ pWrtShell->SttPara(true);
+ pWrtShell->Delete();
+
+ // one paragraph deleted, section is gone
+ CPPUNIT_ASSERT_EQUAL(nNodes - 3, pDoc->GetNodes().Count());
+
+ pWrtShell->Undo();
+
+ CPPUNIT_ASSERT_EQUAL(nNodes, pDoc->GetNodes().Count());
+
+ // check that every node has 1 frame
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt", 3);
+ assertXPath(pXmlDoc, "/root/page[1]/body/section", 1);
+ assertXPath(pXmlDoc, "/root/page[1]/body/section/txt", 1);
+
+ pWrtShell->Redo();
+
+ // one paragraph deleted, section is gone
+ CPPUNIT_ASSERT_EQUAL(nNodes - 3, pDoc->GetNodes().Count());
+
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt", 3);
+ assertXPath(pXmlDoc, "/root/page[1]/body/section", 0);
+
+ pWrtShell->Undo();
+
+ CPPUNIT_ASSERT_EQUAL(nNodes, pDoc->GetNodes().Count());
+
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt", 3);
+ assertXPath(pXmlDoc, "/root/page[1]/body/section", 1);
+ assertXPath(pXmlDoc, "/root/page[1]/body/section/txt", 1);
+}
+
+void 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 (unsigned long i = 0; i < sizeof(aAdditionalPagesCount) / sizeof(int); ++i)
+ {
+ int aPages = aPagesInDocument + aAdditionalPagesCount[i];
+
+ // Empty document with one Page Break
+ SwDoc* pDoc = createDoc("watermark-position.odt");
+ SwEditShell* pEditShell = pDoc->GetEditShell();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ const OUString rPageStyleName = "Default Page Style";
+ 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(rPageStyleName), 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, testTdf134250)
+{
+ load(DATA_DIRECTORY, "tdf134250.fodt");
+
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+ uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+
+ uno::Reference<text::XTextContent> xTextContent(xSections->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextContent->getAnchor()->getString().endsWith("bar"));
+
+ // select all with table at start -> 3 times
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+
+ // .uno:Copy without touching shared clipboard
+ SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+ rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell);
+ xTransfer->Copy();
+
+ // .uno:Paste without touching shared clipboard
+ TransferableDataHelper aHelper(xTransfer.get());
+ SwTransferable::Paste(*pWrtShell, aHelper);
+
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+
+ // this would crash in 2 different ways
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+
+ // Without the fix in place, section's content would have been gone after undo
+ CPPUNIT_ASSERT(xTextContent->getAnchor()->getString().endsWith("bar"));
+
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT(xTextContent->getAnchor()->getString().endsWith("bar"));
+
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+}
+
+void SwUiWriterTest::testFdo74981()
+{
+ // create a document with an input field
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwInputField aField(static_cast<SwInputFieldType*>(pWrtShell->GetFieldType(0, SwFieldIds::Input)), "foo", "bar", 0, 0);
+ pWrtShell->Insert(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());
+ }
+}
+
+void SwUiWriterTest::testTdf98512()
+{
+ SwDoc* pDoc = createDoc();
+ 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->Insert(aField1);
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ SwInputField aField2(pType, "baz", "quux", INP_TXT, 0);
+ pWrtShell->Insert(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());
+}
+
+void SwUiWriterTest::testShapeTextboxSelect()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testShapeTextboxDelete()
+{
+ SwDoc* pDoc = createDoc("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);
+}
+
+void SwUiWriterTest::testAnchorChangeSelection()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testCp1000071()
+{
+ SwDoc* pDoc = createDoc("cp1000071.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ CPPUNIT_ASSERT_EQUAL( SwRedlineTable::size_type( 2 ), rTable.size());
+ sal_uLong redlineStart0NodeIndex = rTable[ 0 ]->Start()->nNode.GetIndex();
+ sal_Int32 redlineStart0Index = rTable[ 0 ]->Start()->nContent.GetIndex();
+ sal_uLong redlineEnd0NodeIndex = rTable[ 0 ]->End()->nNode.GetIndex();
+ sal_Int32 redlineEnd0Index = rTable[ 0 ]->End()->nContent.GetIndex();
+ sal_uLong redlineStart1NodeIndex = rTable[ 1 ]->Start()->nNode.GetIndex();
+ sal_Int32 redlineStart1Index = rTable[ 1 ]->Start()->nContent.GetIndex();
+ sal_uLong 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());
+}
+
+void SwUiWriterTest::testShapeTextboxVertadjust()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testShapeTextboxAutosize()
+{
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testFdo82191()
+{
+ SwDoc* pDoc = createDoc("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));
+}
+
+void SwUiWriterTest::testCommentedWord()
+{
+ // This word is commented. <- string in document
+ // 123456789 <- character positions
+ SwDoc* pDoc = createDoc("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());
+}
+
+void SwUiWriterTest::testTextFieldGetAnchorGetTextInFooter() {
+ createDoc("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 );
+}
+
+// Chinese conversion tests
+
+static const sal_Unicode CHINESE_TRADITIONAL_CONTENT(0x9F8D);
+static const sal_Unicode CHINESE_SIMPLIFIED_CONTENT(0x9F99);
+static const OUStringLiteral NON_CHINESE_CONTENT("Hippopotamus");
+
+// Tests that a blank document is still blank after conversion
+void SwUiWriterTest::testChineseConversionBlank()
+{
+
+ // Given
+ SwDoc* pDoc = createDoc();
+ 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
+void SwUiWriterTest::testChineseConversionNonChineseText()
+{
+
+ // Given
+ SwDoc* pDoc = createDoc();
+ 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
+void SwUiWriterTest::testChineseConversionTraditionalToSimplified()
+{
+
+ // Given
+ SwDoc* pDoc = createDoc();
+ 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
+void SwUiWriterTest::testChineseConversionSimplifiedToTraditional()
+{
+
+ // Given
+ SwDoc* pDoc = createDoc();
+ 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());
+
+}
+
+void SwUiWriterTest::testFdo85554()
+{
+ // Load the document, it contains one shape with a textbox.
+ load("/sw/qa/extras/uiwriter/data/", "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());
+}
+
+void SwUiWriterTest::testAutoCorr()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ const sal_Unicode cIns = ' ';
+
+ //Normal AutoCorrect
+ pWrtShell->Insert("tset");
+ pWrtShell->AutoCorrect(corr, cIns);
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ CPPUNIT_ASSERT_EQUAL(OUString("Test "), static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+
+ //AutoCorrect with change style to bolt
+ pWrtShell->Insert("Bolt");
+ pWrtShell->AutoCorrect(corr, cIns);
+ const uno::Reference< text::XTextRange > xRun = getRun(getParagraph(1), 2);
+ CPPUNIT_ASSERT_EQUAL(OUString("Bolt"), xRun->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Arial"), getProperty<OUString>(xRun, "CharFontName"));
+
+ //AutoCorrect inserts Table with 2 rows and 3 columns
+ pWrtShell->Insert("4xx");
+ pWrtShell->AutoCorrect(corr, cIns);
+ const uno::Reference< text::XTextTable > xTable(getParagraphOrTable(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getColumns()->getCount());
+}
+
+void SwUiWriterTest::testTdf83260()
+{
+ SwDoc* const pDoc(createDoc("tdf83260-1.odt"));
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+
+ // enabled but not shown
+ CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+#if 0
+ CPPUNIT_ASSERT(IDocumentRedlineAccess::IsHideChanges(
+ pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+#endif
+ CPPUNIT_ASSERT(IDocumentRedlineAccess::IsRedlineOn(
+ pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+ CPPUNIT_ASSERT(!pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty());
+
+ // the document contains redlines that are combined with CompressRedlines()
+ // if that happens during AutoCorrect then indexes in Undo are off -> crash
+ pWrtShell->Insert("tset");
+ pWrtShell->AutoCorrect(corr, u' ');
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ auto const nActions(rUndoManager.GetUndoActionCount());
+ for (auto i = nActions; 0 < i; --i)
+ {
+ rUndoManager.Undo();
+ }
+ for (auto i = nActions; 0 < i; --i)
+ {
+ rUndoManager.Redo();
+ }
+ for (auto i = nActions; 0 < i; --i)
+ {
+ rUndoManager.Undo();
+ }
+}
+
+void SwUiWriterTest::testTdf130274()
+{
+ SwDoc *const pDoc(createDoc());
+ SwWrtShell *const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+
+ CPPUNIT_ASSERT(!pWrtShell->GetLayout()->IsHideRedlines());
+ CPPUNIT_ASSERT(!IDocumentRedlineAccess::IsRedlineOn(
+ pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+
+ // "tset" may be replaced by the AutoCorrect in the test profile
+ pWrtShell->Insert("tset");
+ // select from left to right
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, /*bBasicCall=*/false);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 4, /*bBasicCall=*/false);
+
+ pWrtShell->SetRedlineFlags(pWrtShell->GetRedlineFlags() | RedlineFlags::On);
+ // this would crash in AutoCorrect
+ pWrtShell->AutoCorrect(corr, '.');
+
+ CPPUNIT_ASSERT(!pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty());
+}
+
+void SwUiWriterTest::testMergeDoc()
+{
+ SwDoc* const pDoc1(createDoc("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();
+}
+
+void SwUiWriterTest::testCreatePortions()
+{
+ createDoc("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();
+}
+
+void SwUiWriterTest::testBookmarkUndo()
+{
+ SwDoc* pDoc = createDoc();
+ 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_") );
+ 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());
+}
+
+void SwUiWriterTest::testFdo85876()
+{
+ SwDoc* const pDoc = createDoc();
+ 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"));
+ }
+}
+
+void SwUiWriterTest::testTdf79717()
+{
+ SwDoc* const pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("normal");
+ lcl_setWeight(pWrtShell, WEIGHT_BOLD);
+ pWrtShell->Insert("bold");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ // Select 'bol' and replace it
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, /*bBasicCall=*/false);
+ pWrtShell->Insert("bol");
+
+ // Without the fix in place, 'bol' would have been replaced with normal font weight
+
+ 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("normal"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
+ }
+ {
+ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("bold"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
+ }
+
+ // Now select characters from both runs and replace them
+ pWrtShell->EndPara();
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 5, /*bBasicCall=*/false);
+ pWrtShell->Insert("new");
+ {
+ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("norma"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
+ }
+ {
+ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
+ CPPUNIT_ASSERT(xCursor.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("new"), xCursor->getString());
+ CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
+ }
+}
+
+void SwUiWriterTest::testTdf137532()
+{
+ SwDoc* const pDoc = createDoc();
+ 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"));
+}
+
+void SwUiWriterTest::testFdo87448()
+{
+ createDoc("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::makeAny(xOutputStream) },
+ { "FilterName", uno::makeAny(OUString("SVM")) }
+ }));
+ xGraphicExporter->filter(aDescriptor);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Read it back and dump it as an XML file.
+ Graphic aGraphic;
+ ReadGraphic(aStream, 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);
+}
+
+void SwUiWriterTest::testTextCursorInvalidation()
+{
+ createDoc();
+ SwDoc* pDoc = createDoc();
+ 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::makeAny(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("Default Page Style", true, false, false);
+ // must be disposed after deleting header
+ CPPUNIT_ASSERT_THROW(xCursor->goRight(1, false), uno::RuntimeException);
+}
+
+void SwUiWriterTest::testTdf68183()
+{
+ // First disable RSID and check if indeed no such attribute is inserted.
+ SwDoc* pDoc = createDoc();
+ 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));
+}
+
+void SwUiWriterTest::testCp1000115()
+{
+ createDoc("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);
+}
+
+void SwUiWriterTest::testTdf63214()
+{
+ //This is a crash test
+ SwDoc* pDoc = createDoc();
+ 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();
+}
+
+void SwUiWriterTest::testTdf90003()
+{
+ createDoc("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);
+}
+
+void SwUiWriterTest::testTdf51741()
+{
+ SwDoc* pDoc = createDoc();
+ 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_") );
+ 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());
+}
+
+void 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");
+ }
+ }
+}
+
+void SwUiWriterTest::testDeleteTableRedlines()
+{
+ SwDoc* pDoc = createDoc();
+ 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"))), "TableCellInsert", aDescriptor);
+ SwUnoCursorHelper::makeTableCellRedline((*const_cast<SwTableBox*>(rTable.GetTableBox("B1"))), "TableCellInsert", aDescriptor);
+ SwUnoCursorHelper::makeTableCellRedline((*const_cast<SwTableBox*>(rTable.GetTableBox("C1"))), "TableCellInsert", aDescriptor);
+ IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+ SwExtraRedlineTable& rExtras = rIDRA.GetExtraRedlineTable();
+ rExtras.DeleteAllTableRedlines(pDoc, rTable, false, RedlineType::Any);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(0), rExtras.GetSize());
+}
+
+void SwUiWriterTest::testXFlatParagraph()
+{
+ SwDoc* pDoc = createDoc();
+ 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);
+}
+
+void 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");
+ }
+ }
+ }
+}
+
+void SwUiWriterTest::testForcepoint3()
+{
+ createDoc("flowframe_null_ptr_deref.sample");
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "FilterName", uno::Any(OUString("writer_pdf_Export")) },
+ }));
+ utl::TempFile aTempFile;
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ // printing asserted in SwFrame::GetNextSctLeaf()
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ aTempFile.EnableKillingFile();
+}
+
+void SwUiWriterTest::testForcepoint80()
+{
+ try
+ {
+ createDoc("forcepoint80-1.rtf");
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "FilterName", uno::Any(OUString("writer_pdf_Export")) },
+ }));
+ utl::TempFile aTempFile;
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ // printing asserted in SwCellFrame::FindStartEndOfRowSpanCell
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ aTempFile.EnableKillingFile();
+ }
+ catch(...)
+ {
+ }
+}
+
+void SwUiWriterTest::testExportToPicture()
+{
+ createDoc();
+ uno::Sequence<beans::PropertyValue> aFilterData( comphelper::InitPropertySequence({
+ { "PixelWidth", uno::Any(sal_Int32(610)) },
+ { "PixelHeight", uno::Any(sal_Int32(610)) }
+ }));
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "FilterName", uno::Any(OUString("writer_png_Export")) },
+ { "FilterData", uno::Any(aFilterData) }
+ }));
+ utl::TempFile aTempFile;
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ bool extchk = aTempFile.IsValid();
+ CPPUNIT_ASSERT_EQUAL(true, extchk);
+ osl::File tmpFile(aTempFile.GetURL());
+ tmpFile.open(sal_uInt32(osl_File_OpenFlag_Read));
+ sal_uInt64 val;
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, tmpFile.getSize(val));
+ CPPUNIT_ASSERT(val > 100);
+ aTempFile.EnableKillingFile();
+}
+
+void SwUiWriterTest::testTdf77340()
+{
+ createDoc();
+ //Getting some paragraph style in our document
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<style::XStyle> xStyle(xFactory->createInstance("com.sun.star.style.ParagraphStyle"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropSet(xStyle, uno::UNO_QUERY_THROW);
+ xPropSet->setPropertyValue("ParaBackColor", uno::makeAny(sal_Int32(0xFF00FF)));
+ uno::Reference<style::XStyleFamiliesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xNameAccess(xSupplier->getStyleFamilies());
+ uno::Reference<container::XNameContainer> xNameCont;
+ xNameAccess->getByName("ParagraphStyles") >>= xNameCont;
+ xNameCont->insertByName("myStyle", uno::makeAny(xStyle));
+ CPPUNIT_ASSERT_EQUAL(OUString("myStyle"), xStyle->getName());
+ //Setting the properties with proper values
+ xPropSet->setPropertyValue("PageDescName", uno::makeAny(OUString("First Page")));
+ xPropSet->setPropertyValue("PageNumberOffset", uno::makeAny(sal_Int16(3)));
+ //Getting the properties and checking that they have proper values
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(OUString("First Page")), xPropSet->getPropertyValue("PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_Int16(3)), xPropSet->getPropertyValue("PageNumberOffset"));
+}
+
+void SwUiWriterTest::testTdf79236()
+{
+ SwDoc* pDoc = createDoc();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ //Getting some paragraph style
+ SwTextFormatColl* pTextFormat = pDoc->FindTextFormatCollByName("Text Body");
+ const SwAttrSet& rAttrSet = pTextFormat->GetAttrSet();
+ std::unique_ptr<SfxItemSet> pNewSet = rAttrSet.Clone();
+ sal_uInt16 initialCount = pNewSet->Count();
+ SvxAdjustItem AdjustItem = rAttrSet.GetAdjust();
+ SvxAdjust initialAdjust = AdjustItem.GetAdjust();
+ //By default the adjust is LEFT
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Left, initialAdjust);
+ //Changing the adjust to RIGHT
+ AdjustItem.SetAdjust(SvxAdjust::Right);
+ //Checking whether the change is made or not
+ SvxAdjust modifiedAdjust = AdjustItem.GetAdjust();
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Right, modifiedAdjust);
+ //Modifying the itemset, putting *one* item
+ pNewSet->Put(AdjustItem);
+ //The count should increment by 1
+ sal_uInt16 modifiedCount = pNewSet->Count();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(initialCount + 1), modifiedCount);
+ //Setting the updated item set on the style
+ pDoc->ChgFormat(*pTextFormat, *pNewSet);
+ //Checking the Changes
+ SwTextFormatColl* pTextFormat2 = pDoc->FindTextFormatCollByName("Text Body");
+ const SwAttrSet& rAttrSet2 = pTextFormat2->GetAttrSet();
+ const SvxAdjustItem& rAdjustItem2 = rAttrSet2.GetAdjust();
+ SvxAdjust Adjust2 = rAdjustItem2.GetAdjust();
+ //The adjust should be RIGHT as per the modifications made
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Right, Adjust2);
+ //Undo the changes
+ rUndoManager.Undo();
+ SwTextFormatColl* pTextFormat3 = pDoc->FindTextFormatCollByName("Text Body");
+ const SwAttrSet& rAttrSet3 = pTextFormat3->GetAttrSet();
+ const SvxAdjustItem& rAdjustItem3 = rAttrSet3.GetAdjust();
+ SvxAdjust Adjust3 = rAdjustItem3.GetAdjust();
+ //The adjust should be back to default, LEFT
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Left, Adjust3);
+ //Redo the changes
+ rUndoManager.Redo();
+ SwTextFormatColl* pTextFormat4 = pDoc->FindTextFormatCollByName("Text Body");
+ const SwAttrSet& rAttrSet4 = pTextFormat4->GetAttrSet();
+ const SvxAdjustItem& rAdjustItem4 = rAttrSet4.GetAdjust();
+ SvxAdjust Adjust4 = rAdjustItem4.GetAdjust();
+ //The adjust should be RIGHT as per the modifications made
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Right, Adjust4);
+ //Undo the changes
+ rUndoManager.Undo();
+ SwTextFormatColl* pTextFormat5 = pDoc->FindTextFormatCollByName("Text Body");
+ const SwAttrSet& rAttrSet5 = pTextFormat5->GetAttrSet();
+ const SvxAdjustItem& rAdjustItem5 = rAttrSet5.GetAdjust();
+ SvxAdjust Adjust5 = rAdjustItem5.GetAdjust();
+ //The adjust should be back to default, LEFT
+ CPPUNIT_ASSERT_EQUAL(SvxAdjust::Left, Adjust5);
+}
+
+void SwUiWriterTest::testTextSearch()
+{
+ // Create a new empty Writer document
+ SwDoc* pDoc = createDoc();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ // Insert some text
+ rIDCO.InsertString(*pCursor, "Hello World This is a test");
+ // Use cursor to select part of text
+ for (int i = 0; i < 10; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ pCursor->SetMark();
+ for(int i = 0; i < 4; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ //Checking that the proper selection is made
+ CPPUNIT_ASSERT_EQUAL(OUString("This"), pCursor->GetText());
+ // Apply a "Bold" attribute to selection
+ SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
+ rIDCO.InsertPoolItem(*pCursor, aWeightItem);
+ //making another selection of text
+ for (int i = 0; i < 7; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ pCursor->SetMark();
+ for(int i = 0; i < 5; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ //Checking that the proper selection is made
+ CPPUNIT_ASSERT_EQUAL(OUString("Hello"), pCursor->GetText());
+ // Apply a "Bold" attribute to selection
+ rIDCO.InsertPoolItem(*pCursor, aWeightItem);
+ //Performing Search Operation and also covering the UNO coverage for setProperty
+ uno::Reference<util::XSearchable> xSearch(mxComponent, uno::UNO_QUERY);
+ uno::Reference<util::XSearchDescriptor> xSearchDes = xSearch->createSearchDescriptor();
+ uno::Reference<util::XPropertyReplace> xProp(xSearchDes, uno::UNO_QUERY);
+ //setting some properties
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "CharWeight", uno::Any(float(css::awt::FontWeight::BOLD)) }
+ }));
+ xProp->setSearchAttributes(aDescriptor);
+ //receiving the defined properties and asserting them with expected values, covering UNO
+ uno::Sequence<beans::PropertyValue> aPropVal2(xProp->getSearchAttributes());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aPropVal2.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("CharWeight"), aPropVal2[0].Name);
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(float(css::awt::FontWeight::BOLD)), aPropVal2[0].Value);
+ //specifying the search attributes
+ uno::Reference<beans::XPropertySet> xPropSet(xSearchDes, uno::UNO_QUERY_THROW);
+ xPropSet->setPropertyValue("SearchWords", uno::makeAny(true));
+ xPropSet->setPropertyValue("SearchCaseSensitive", uno::makeAny(true));
+ //this will search all the BOLD words
+ uno::Reference<container::XIndexAccess> xIndex(xSearch->findAll(xSearchDes));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndex->getCount());
+ //Replacing the searched string via XReplaceable
+ uno::Reference<util::XReplaceable> xReplace(mxComponent, uno::UNO_QUERY);
+ uno::Reference<util::XReplaceDescriptor> xReplaceDes = xReplace->createReplaceDescriptor();
+ uno::Reference<util::XPropertyReplace> xProp2(xReplaceDes, uno::UNO_QUERY);
+ xProp2->setReplaceAttributes(aDescriptor);
+ //checking that the proper attributes are there or not
+ uno::Sequence<beans::PropertyValue> aRepProp(xProp2->getReplaceAttributes());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRepProp.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("CharWeight"), aRepProp[0].Name);
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(float(css::awt::FontWeight::BOLD)), aRepProp[0].Value);
+ //setting strings for replacement
+ xReplaceDes->setSearchString("test");
+ xReplaceDes->setReplaceString("task");
+ //checking the replaceString
+ CPPUNIT_ASSERT_EQUAL(OUString("task"), xReplaceDes->getReplaceString());
+ //this will replace *normal*test to *bold*task
+ sal_Int32 ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ //There should be only 1 replacement since there is only one occurrence of "test" in the document
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ReplaceCount);
+ //Now performing search again for BOLD words, count should be 3 due to replacement
+ uno::Reference<container::XIndexAccess> xIndex2(xReplace->findAll(xSearchDes));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xIndex2->getCount());
+ // regex tests
+ xSearchDes->setPropertyValue("SearchRegularExpression", uno::makeAny(true));
+ // regex: test correct matching combined with attributes like BOLD
+ xSearchDes->setSearchString(".*"); // should match all bold words in the text
+ xIndex.set(xReplace->findAll(xSearchDes), uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xIndex->getCount());
+ uno::Reference<text::XTextRange> xFound(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("Hello"), xFound->getString());
+ xFound.set(xIndex->getByIndex(1), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("This"), xFound->getString());
+ xFound.set(xIndex->getByIndex(2), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("task"), xFound->getString());
+ // regex: test anchor combined with attributes like BOLD
+ xSearchDes->setSearchString("^.*|.*$"); // should match first and last words (they are bold)
+ xIndex.set(xReplace->findAll(xSearchDes), uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndex->getCount());
+ xFound.set(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("Hello"), xFound->getString());
+ xFound.set(xIndex->getByIndex(1), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("task"), xFound->getString());
+ // regex: test look-ahead/look-behind assertions outside of the bold text
+ xSearchDes->setSearchString("(?<= ).*(?= )"); // should match second bold word
+ xIndex.set(xReplace->findAll(xSearchDes), uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndex->getCount());
+ xFound.set(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("This"), xFound->getString());
+ xReplaceDes->setPropertyValue("SearchRegularExpression", uno::makeAny(true));
+ // regex: test correct match of paragraph start
+ xReplaceDes->setSearchString("^."); // should only match first character of the paragraph
+ xReplaceDes->setReplaceString("C");
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ReplaceCount);
+ // regex: test correct match of word start
+ xReplaceDes->setSearchString("\\b\\w"); // should match all words' first characters
+ xReplaceDes->setReplaceString("x&");
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), ReplaceCount);
+ // regex: test negative look-behind assertion
+ xReplaceDes->setSearchString("(?<!xCelly xW)o"); // only "o" in "xCello", not in "xWorld"
+ xReplaceDes->setReplaceString("y");
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ReplaceCount);
+ // regex: test positive look-behind assertion
+ xReplaceDes->setSearchString("(?<=xCelly xWorld xTh)i"); // only "i" in "xThis", not in "xis"
+ xReplaceDes->setReplaceString("z");
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ReplaceCount);
+ // regex: use capturing group to test reference
+ xReplaceDes->setSearchString("\\b(\\w\\w\\w\\w)\\w");
+ xReplaceDes->setReplaceString("$1q"); // only fifth characters in words should change
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), ReplaceCount);
+ // check of the end result
+ CPPUNIT_ASSERT_EQUAL(OUString("xCelqy xWorqd xThzq xis xa xtasq"),
+ pCursor->GetNode().GetTextNode()->GetText());
+ // regex: use positive look-ahead assertion
+ xReplaceDes->setSearchString("Wor(?=qd xThzq xis xa xtasq)");
+ xReplaceDes->setReplaceString("&p"); // testing & reference
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ReplaceCount);
+ // regex: use negative look-ahead assertion
+ xReplaceDes->setSearchString("x(?!Worpqd xThzq xis xa xtasq)");
+ xReplaceDes->setReplaceString("m");
+ ReplaceCount = xReplace->replaceAll(xReplaceDes);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ReplaceCount); // one of the 6 "x" must not be replaced
+ // check of the end result
+ CPPUNIT_ASSERT_EQUAL(OUString("mCelqy xWorpqd mThzq mis ma mtasq"),
+ pCursor->GetNode().GetTextNode()->GetText());
+}
+
+void SwUiWriterTest::testTdf69282()
+{
+ mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument");
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* source = pTextDoc->GetDocShell()->GetDoc();
+ uno::Reference<lang::XComponent> xSourceDoc = mxComponent;
+ mxComponent.clear();
+ SwDoc* target = createDoc();
+ SwPageDesc* sPageDesc = source->MakePageDesc("SourceStyle");
+ SwPageDesc* tPageDesc = target->MakePageDesc("TargetStyle");
+ sPageDesc->ChgFirstShare(false);
+ CPPUNIT_ASSERT(!sPageDesc->IsFirstShared());
+ SwFrameFormat& rSourceMasterFormat = sPageDesc->GetMaster();
+ //Setting horizontal spaces on master
+ SvxLRSpaceItem horizontalSpace(RES_LR_SPACE);
+ horizontalSpace.SetLeft(11);
+ horizontalSpace.SetRight(12);
+ rSourceMasterFormat.SetFormatAttr(horizontalSpace);
+ //Setting vertical spaces on master
+ SvxULSpaceItem verticalSpace(RES_UL_SPACE);
+ verticalSpace.SetUpper(13);
+ verticalSpace.SetLower(14);
+ rSourceMasterFormat.SetFormatAttr(verticalSpace);
+ //Changing the style and copying it to target
+ source->ChgPageDesc("SourceStyle", *sPageDesc);
+ target->CopyPageDesc(*sPageDesc, *tPageDesc);
+ //Checking the set values on all Formats in target
+ SwFrameFormat& rTargetMasterFormat = tPageDesc->GetMaster();
+ SwFrameFormat& rTargetLeftFormat = tPageDesc->GetLeft();
+ SwFrameFormat& rTargetFirstMasterFormat = tPageDesc->GetFirstMaster();
+ SwFrameFormat& rTargetFirstLeftFormat = tPageDesc->GetFirstLeft();
+ //Checking horizontal spaces
+ const SvxLRSpaceItem MasterLRSpace = rTargetMasterFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), MasterLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), MasterLRSpace.GetRight());
+ const SvxLRSpaceItem LeftLRSpace = rTargetLeftFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), LeftLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), LeftLRSpace.GetRight());
+ const SvxLRSpaceItem FirstMasterLRSpace = rTargetFirstMasterFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), FirstMasterLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), FirstMasterLRSpace.GetRight());
+ const SvxLRSpaceItem FirstLeftLRSpace = rTargetFirstLeftFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), FirstLeftLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), FirstLeftLRSpace.GetRight());
+ //Checking vertical spaces
+ const SvxULSpaceItem MasterULSpace = rTargetMasterFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), MasterULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), MasterULSpace.GetLower());
+ const SvxULSpaceItem LeftULSpace = rTargetLeftFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), LeftULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), LeftULSpace.GetLower());
+ const SvxULSpaceItem FirstMasterULSpace = rTargetFirstMasterFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), FirstMasterULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), FirstMasterULSpace.GetLower());
+ const SvxULSpaceItem FirstLeftULSpace = rTargetFirstLeftFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), FirstLeftULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), FirstLeftULSpace.GetLower());
+ xSourceDoc->dispose();
+}
+
+void SwUiWriterTest::testTdf69282WithMirror()
+{
+ mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument");
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* source = pTextDoc->GetDocShell()->GetDoc();
+ uno::Reference<lang::XComponent> xSourceDoc = mxComponent;
+ mxComponent.clear();
+ SwDoc* target = createDoc();
+ SwPageDesc* sPageDesc = source->MakePageDesc("SourceStyle");
+ SwPageDesc* tPageDesc = target->MakePageDesc("TargetStyle");
+ //Enabling Mirror
+ sPageDesc->SetUseOn(UseOnPage::Mirror);
+ SwFrameFormat& rSourceMasterFormat = sPageDesc->GetMaster();
+ //Setting horizontal spaces on master
+ SvxLRSpaceItem horizontalSpace(RES_LR_SPACE);
+ horizontalSpace.SetLeft(11);
+ horizontalSpace.SetRight(12);
+ rSourceMasterFormat.SetFormatAttr(horizontalSpace);
+ //Setting vertical spaces on master
+ SvxULSpaceItem verticalSpace(RES_UL_SPACE);
+ verticalSpace.SetUpper(13);
+ verticalSpace.SetLower(14);
+ rSourceMasterFormat.SetFormatAttr(verticalSpace);
+ //Changing the style and copying it to target
+ source->ChgPageDesc("SourceStyle", *sPageDesc);
+ target->CopyPageDesc(*sPageDesc, *tPageDesc);
+ //Checking the set values on all Formats in target
+ SwFrameFormat& rTargetMasterFormat = tPageDesc->GetMaster();
+ SwFrameFormat& rTargetLeftFormat = tPageDesc->GetLeft();
+ SwFrameFormat& rTargetFirstMasterFormat = tPageDesc->GetFirstMaster();
+ SwFrameFormat& rTargetFirstLeftFormat = tPageDesc->GetFirstLeft();
+ //Checking horizontal spaces
+ const SvxLRSpaceItem MasterLRSpace = rTargetMasterFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), MasterLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), MasterLRSpace.GetRight());
+ //mirror effect should be present
+ const SvxLRSpaceItem LeftLRSpace = rTargetLeftFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), LeftLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), LeftLRSpace.GetRight());
+ const SvxLRSpaceItem FirstMasterLRSpace = rTargetFirstMasterFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), FirstMasterLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), FirstMasterLRSpace.GetRight());
+ //mirror effect should be present
+ const SvxLRSpaceItem FirstLeftLRSpace = rTargetFirstLeftFormat.GetLRSpace();
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetRight(), FirstLeftLRSpace.GetLeft());
+ CPPUNIT_ASSERT_EQUAL(horizontalSpace.GetLeft(), FirstLeftLRSpace.GetRight());
+ //Checking vertical spaces
+ const SvxULSpaceItem MasterULSpace = rTargetMasterFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), MasterULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), MasterULSpace.GetLower());
+ const SvxULSpaceItem LeftULSpace = rTargetLeftFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), LeftULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), LeftULSpace.GetLower());
+ const SvxULSpaceItem FirstMasterULSpace = rTargetFirstMasterFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), FirstMasterULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), FirstMasterULSpace.GetLower());
+ const SvxULSpaceItem FirstLeftULSpace = rTargetFirstLeftFormat.GetULSpace();
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetUpper(), FirstLeftULSpace.GetUpper());
+ CPPUNIT_ASSERT_EQUAL(verticalSpace.GetLower(), FirstLeftULSpace.GetLower());
+ xSourceDoc->dispose();
+}
+
+void SwUiWriterTest::testTdf78742()
+{
+ //testing with service type and any .ods file
+ OUString path = m_directories.getURLFromSrc(DATA_DIRECTORY) + "calc-data-source.ods";
+ SfxMedium aMedium(path, StreamMode::READ | StreamMode::SHARE_DENYWRITE);
+ SfxFilterMatcher aMatcher("com.sun.star.text.TextDocument");
+ std::shared_ptr<const SfxFilter> pFilter;
+ ErrCode filter = aMatcher.DetectFilter(aMedium, pFilter);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_IO_ABORT, filter);
+ //it should not return any Filter
+ CPPUNIT_ASSERT(!pFilter);
+ //testing without service type and any .ods file
+ SfxMedium aMedium2(path, StreamMode::READ | StreamMode::SHARE_DENYWRITE);
+ SfxFilterMatcher aMatcher2;
+ std::shared_ptr<const SfxFilter> pFilter2;
+ ErrCode filter2 = aMatcher2.DetectFilter(aMedium2, pFilter2);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, filter2);
+ //Filter should be returned with proper Name
+ CPPUNIT_ASSERT_EQUAL(OUString("calc8"), pFilter2->GetFilterName());
+ //testing with service type and any .odt file
+ OUString path2 = m_directories.getURLFromSrc(DATA_DIRECTORY) + "fdo69893.odt";
+ SfxMedium aMedium3(path2, StreamMode::READ | StreamMode::SHARE_DENYWRITE);
+ SfxFilterMatcher aMatcher3("com.sun.star.text.TextDocument");
+ std::shared_ptr<const SfxFilter> pFilter3;
+ ErrCode filter3 = aMatcher3.DetectFilter(aMedium3, pFilter3);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, filter3);
+ //Filter should be returned with proper Name
+ CPPUNIT_ASSERT_EQUAL(OUString("writer8"), pFilter3->GetFilterName());
+}
+
+void SwUiWriterTest::testUnoParagraph()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //Inserting some text content in the document
+ pWrtShell->Insert("This is initial text in paragraph one");
+ pWrtShell->SplitNode();
+ //Inserting second paragraph
+ pWrtShell->Insert("This is initial text in paragraph two");
+ //now testing the SwXParagraph
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText(xTextDocument->getText());
+ uno::Reference<container::XEnumerationAccess> xParaAccess(xText, uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xPara(xParaAccess->createEnumeration());
+ //getting first paragraph
+ uno::Reference<text::XTextContent> xFirstParaContent(xPara->nextElement(), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xFirstPara(xFirstParaContent, uno::UNO_QUERY);
+ //testing the initial text
+ CPPUNIT_ASSERT_EQUAL(OUString("This is initial text in paragraph one"), xFirstPara->getString());
+ //changing the text content in first paragraph
+ xFirstPara->setString("This is modified text in paragraph one");
+ //testing the changes
+ CPPUNIT_ASSERT_EQUAL(OUString("This is modified text in paragraph one"), xFirstPara->getString());
+ //getting second paragraph
+ uno::Reference<text::XTextContent> xSecondParaContent(xPara->nextElement(), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xSecondPara(xSecondParaContent, uno::UNO_QUERY);
+ //testing the initial text
+ CPPUNIT_ASSERT_EQUAL(OUString("This is initial text in paragraph two"), xSecondPara->getString());
+ //changing the text content in second paragraph
+ xSecondPara->setString("This is modified text in paragraph two");
+ //testing the changes
+ CPPUNIT_ASSERT_EQUAL(OUString("This is modified text in paragraph two"), xSecondPara->getString());
+}
+
+void SwUiWriterTest::testTdf72788()
+{
+ //Create a new empty Writer document
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ //Insert some text - two paragraphs
+ rIDCO.InsertString(*pCursor, "this is text");
+ //Position of word 9876543210
+ //Position of word 0123456789
+ //Change Paragraph
+ pWrtShell->SplitNode();
+ //Insert second paragraph
+ rIDCO.InsertString(*pCursor, "more text");
+ //Position of word 012345678
+ //Make the following selection *bold*
+ //this[is text
+ //more] text
+ //Move cursor back
+ for (int i = 0; i < 5; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ //Start selection
+ pCursor->SetMark();
+ for (int i = 0; i < 12; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ //Check the text selection
+ CPPUNIT_ASSERT_EQUAL(OUString(u"is text" + OUStringChar(CH_TXTATR_NEWLINE) + u"more"), pCursor->GetText());
+ //Apply a *Bold* attribute to selection
+ SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
+ rIDCO.InsertPoolItem(*pCursor, aWeightItem);
+ SfxItemSet aSet( pDoc->GetAttrPool(), svl::Items<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT>{});
+ //Add selected text's attributes to aSet
+ pCursor->GetNode().GetTextNode()->GetParaAttr(aSet, 5, 12);
+ SfxPoolItem const * pPoolItem = aSet.GetItem(RES_CHRATR_WEIGHT);
+ //Check that bold is active on the selection and it's in aSet
+ CPPUNIT_ASSERT_EQUAL(true, (*pPoolItem == aWeightItem));
+ //Make selection to remove formatting in first paragraph
+ //[this is text
+ //]more text
+ pWrtShell->StartOfSection();
+ //Start selection
+ pCursor->SetMark();
+ for (int i = 0; i < 13; i++) {
+ pCursor->Move(fnMoveForward);
+ }
+ //Clear all the Direct Formatting ( Ctrl + M )
+ SwTextNode* pTextNode = pCursor->GetNode().GetTextNode();
+ SwIndex aSt( pTextNode, 0 );
+ sal_Int32 nEnd = pTextNode->Len();
+ pTextNode->RstTextAttr(aSt, nEnd - aSt.GetIndex());
+ //In case of Regression RstTextAttr() call will result to infinite recursion
+ //Check that bold is removed in first paragraph
+ aSet.ClearItem();
+ pTextNode->GetParaAttr(aSet, 5, 12);
+ SfxPoolItem const * pPoolItem2 = aSet.GetItem(RES_CHRATR_WEIGHT);
+ CPPUNIT_ASSERT_EQUAL(true, (*pPoolItem2 != aWeightItem));
+}
+
+void SwUiWriterTest::testTdf60967()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ pWrtShell->ChangeHeaderOrFooter("Default Page Style", true, true, true);
+ //Inserting table
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(TableOpt, 2, 2);
+ //getting the cursor's position just after the table insert
+ SwPosition aPosAfterTable(*(pCursor->GetPoint()));
+ //moving cursor to B2 (bottom right cell)
+ pCursor->Move(fnMoveBackward);
+ SwPosition aPosInTable(*(pCursor->GetPoint()));
+ //deleting paragraph following table with Ctrl+Shift+Del
+ bool val = pWrtShell->DelToEndOfSentence();
+ CPPUNIT_ASSERT_EQUAL(true, val);
+ //getting the cursor's position just after the paragraph deletion
+ SwPosition aPosAfterDel(*(pCursor->GetPoint()));
+ //moving cursor forward to check whether there is any node following the table, BTW there should not be any such node
+ pCursor->Move(fnMoveForward);
+ SwPosition aPosMoveAfterDel(*(pCursor->GetPoint()));
+ //checking the positions to verify that the paragraph is actually deleted
+ CPPUNIT_ASSERT_EQUAL(aPosAfterDel, aPosInTable);
+ CPPUNIT_ASSERT_EQUAL(aPosMoveAfterDel, aPosInTable);
+ //Undo the changes
+ rUndoManager.Undo();
+ {
+ //paragraph *text node* should be back
+ SwPosition aPosAfterUndo(*(pCursor->GetPoint()));
+ //after undo aPosAfterTable increases the node position by one, since this contains the position *text node* so aPosAfterUndo should be less than aPosAfterTable
+ CPPUNIT_ASSERT(aPosAfterTable > aPosAfterUndo);
+ //moving cursor forward to check whether there is any node following the paragraph, BTW there should not be any such node as paragraph node is the last one in header
+ pCursor->Move(fnMoveForward);
+ SwPosition aPosMoveAfterUndo(*(pCursor->GetPoint()));
+ //checking positions to verify that paragraph node is the last one and we are paragraph node only
+ CPPUNIT_ASSERT(aPosAfterTable > aPosMoveAfterUndo);
+ CPPUNIT_ASSERT_EQUAL(aPosAfterUndo, aPosMoveAfterUndo);
+ }
+ //Redo the changes
+ rUndoManager.Redo();
+ //paragraph *text node* should not be there
+ SwPosition aPosAfterRedo(*(pCursor->GetPoint()));
+ //position should be exactly same as it was after deletion of *text node*
+ CPPUNIT_ASSERT_EQUAL(aPosAfterRedo, aPosMoveAfterDel);
+ //moving the cursor forward, but it should not actually move as there is no *text node* after the table due to this same position is expected after move as it was before move
+ pCursor->Move(fnMoveForward);
+ SwPosition aPosAfterUndoMove(*(pCursor->GetPoint()));
+ CPPUNIT_ASSERT_EQUAL(aPosAfterRedo, aPosAfterUndoMove);
+}
+
+void SwUiWriterTest::testSearchWithTransliterate()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM,"This is paragraph one");
+ pWrtShell->SplitNode();
+ }
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM,"This is Other PARAGRAPH");
+ }
+ i18nutil::SearchOptions2 SearchOpt;
+ SearchOpt.algorithmType = css::util::SearchAlgorithms_ABSOLUTE;
+ SearchOpt.searchFlag = css::util::SearchFlags::ALL_IGNORE_CASE;
+ SearchOpt.searchString = "other";
+ SearchOpt.replaceString.clear();
+ SearchOpt.changedChars = 0;
+ SearchOpt.deletedChars = 0;
+ SearchOpt.insertedChars = 0;
+ SearchOpt.transliterateFlags = TransliterationFlags::IGNORE_DIACRITICS_CTL;
+ SearchOpt.AlgorithmType2 = css::util::SearchAlgorithms2::ABSOLUTE;
+ SearchOpt.WildcardEscapeCharacter = 0;
+ //transliteration option set so that at least one of the search strings is not found
+ sal_uLong case1 = pWrtShell->SearchPattern(SearchOpt,true,SwDocPositions::Start,SwDocPositions::End);
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(true);
+ CPPUNIT_ASSERT_EQUAL(OUString(),pShellCursor->GetText());
+ CPPUNIT_ASSERT_EQUAL(0,static_cast<int>(case1));
+ SearchOpt.searchString = "paragraph";
+ SearchOpt.transliterateFlags = TransliterationFlags::IGNORE_KASHIDA_CTL;
+ //transliteration option set so that all search strings are found
+ sal_uLong case2 = pWrtShell->SearchPattern(SearchOpt,true,SwDocPositions::Start,SwDocPositions::End);
+ pShellCursor = pWrtShell->getShellCursor(true);
+ CPPUNIT_ASSERT_EQUAL(OUString("paragraph"),pShellCursor->GetText());
+ CPPUNIT_ASSERT_EQUAL(1,static_cast<int>(case2));
+}
+
+void SwUiWriterTest::testTdf73660()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ OUString aData1 = "First" + OUStringChar(CHAR_SOFTHYPHEN) + "Word";
+ OUString aData2 = "Seco" + OUStringChar(CHAR_SOFTHYPHEN) + "nd";
+ OUString aData3 = OUStringChar(CHAR_SOFTHYPHEN) + "Third";
+ OUString aData4 = "Fourth" + OUStringChar(CHAR_SOFTHYPHEN);
+ OUString aData5 = "Fifth";
+ pWrtShell->Insert("We are inserting some text in the document to check the search feature ");
+ pWrtShell->Insert(aData1 + " ");
+ pWrtShell->Insert(aData2 + " ");
+ pWrtShell->Insert(aData3 + " ");
+ pWrtShell->Insert(aData4 + " ");
+ pWrtShell->Insert(aData5 + " ");
+ pWrtShell->Insert("Now we have enough text let's test search for all the cases");
+ //searching for all 5 strings entered with soft-hyphen, search string contains no soft-hyphen
+ i18nutil::SearchOptions2 searchOpt;
+ searchOpt.algorithmType = css::util::SearchAlgorithms_REGEXP;
+ searchOpt.searchFlag = css::util::SearchFlags::NORM_WORD_ONLY;
+ //case 1
+ searchOpt.searchString = "First";
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(1), pWrtShell->SearchPattern(searchOpt,true,SwDocPositions::Start,SwDocPositions::End));
+ //case 2
+ searchOpt.searchString = "Second";
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(1), pWrtShell->SearchPattern(searchOpt,true,SwDocPositions::Start,SwDocPositions::End));
+ //case 3
+ searchOpt.searchString = "Third";
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(1), pWrtShell->SearchPattern(searchOpt,true,SwDocPositions::Start,SwDocPositions::End));
+ //case 4
+ searchOpt.searchString = "Fourth";
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(1), pWrtShell->SearchPattern(searchOpt,true,SwDocPositions::Start,SwDocPositions::End));
+ //case 5
+ searchOpt.searchString = "Fifth";
+ CPPUNIT_ASSERT_EQUAL(sal_uLong(1), pWrtShell->SearchPattern(searchOpt,true,SwDocPositions::Start,SwDocPositions::End));
+}
+
+void SwUiWriterTest::testNewDocModifiedState()
+{
+ //creating a new doc
+ SwDoc* pDoc = new SwDoc();
+ //getting the state of the document via IDocumentState
+ IDocumentState& rState(pDoc->getIDocumentState());
+ //the state should not be modified, no modifications yet
+ CPPUNIT_ASSERT(!(rState.IsModified()));
+}
+
+void SwUiWriterTest::testTdf77342()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ //inserting first footnote
+ pWrtShell->InsertFootnote("");
+ SwFieldType* pField = pWrtShell->GetFieldType(0, SwFieldIds::GetRef);
+ SwGetRefFieldType* pRefType = static_cast<SwGetRefFieldType*>(pField);
+ //moving cursor to the starting of document
+ pWrtShell->StartOfSection();
+ //inserting reference field 1
+ SwGetRefField aField1(pRefType, "", "", REF_FOOTNOTE, sal_uInt16(0), REF_CONTENT);
+ pWrtShell->Insert(aField1);
+ //inserting second footnote
+ pWrtShell->InsertFootnote("");
+ pWrtShell->StartOfSection();
+ pCursor->Move(fnMoveForward);
+ //inserting reference field 2
+ SwGetRefField aField2(pRefType, "", "", REF_FOOTNOTE, sal_uInt16(1), REF_CONTENT);
+ pWrtShell->Insert(aField2);
+ //inserting third footnote
+ pWrtShell->InsertFootnote("");
+ pWrtShell->StartOfSection();
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ //inserting reference field 3
+ SwGetRefField aField3(pRefType, "", "", REF_FOOTNOTE, sal_uInt16(2), REF_CONTENT);
+ pWrtShell->Insert(aField3);
+ //updating the fields
+ IDocumentFieldsAccess& rField(pDoc->getIDocumentFieldsAccess());
+ rField.UpdateExpFields(nullptr, true);
+ //creating new clipboard doc
+ rtl::Reference<SwDoc> xClpDoc(new SwDoc());
+ xClpDoc->SetClipBoard(true);
+ xClpDoc->getIDocumentFieldsAccess().LockExpFields();
+ //selecting reference field 2 and reference field 3 and footnote 1 and footnote 2
+ //selection is such that more than one and not all footnotes and ref fields are selected
+ pCursor->Move(fnMoveBackward);
+ pCursor->Move(fnMoveBackward);
+ //start marking
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ //copying the selection to clipboard
+ pWrtShell->Copy(xClpDoc.get());
+ //deleting selection mark after copy
+ pCursor->DeleteMark();
+ //checking that the footnotes reference fields have same values after copy operation
+ uno::Any aAny;
+ sal_uInt16 aFormat;
+ //reference field 1
+ pWrtShell->StartOfSection();
+ SwField* pRef1 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef1->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef1->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pRef2 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef2->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef2->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pRef3 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef3->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef3->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //moving cursor to the end of the document
+ pWrtShell->EndOfSection();
+ //pasting the copied selection at current cursor position
+ pWrtShell->Paste(xClpDoc.get());
+ //checking the fields, both new and old, for proper values
+ pWrtShell->StartOfSection();
+ //old reference field 1
+ SwField* pOldRef11 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef11->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef11->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //old reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef12 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef12->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef12->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //old reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef13 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef13->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef13->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //old footnote 1
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd1 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote1 = pTextNd1->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote1(pFootnote1->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnote1.GetNumber());
+ SwTextFootnote* pTFNote1 = static_cast<SwTextFootnote*> (pFootnote1);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pTFNote1->GetSeqRefNo());
+ //old footnote 2
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd2 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote2 = pTextNd2->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote2(pFootnote2->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnote2.GetNumber());
+ SwTextFootnote* pTFNote2 = static_cast<SwTextFootnote*> (pFootnote2);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pTFNote2->GetSeqRefNo());
+ //old footnote 3
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd3 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote3 = pTextNd3->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote3(pFootnote3->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), rFootnote3.GetNumber());
+ SwTextFootnote* pTFNote3 = static_cast<SwTextFootnote*> (pFootnote3);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pTFNote3->GetSeqRefNo());
+ //new reference field 1
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef11 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef11->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef11->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //new reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef12 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef12->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef12->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(3)), aAny);
+ //new footnote 1
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd4 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote4 = pTextNd4->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote4(pFootnote4->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), rFootnote4.GetNumber());
+ SwTextFootnote* pTFNote4 = static_cast<SwTextFootnote*> (pFootnote4);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pTFNote4->GetSeqRefNo());
+ //moving the cursor to the starting of document
+ pWrtShell->StartOfSection();
+ //pasting the selection again at current cursor position
+ pWrtShell->Paste(xClpDoc.get());
+ //checking the fields, both new and old, for proper values
+ pWrtShell->StartOfSection();
+ //new reference field 1
+ SwField* pNewRef21 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef21->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef21->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //new reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef22 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef22->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef22->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(4)), aAny);
+ //new footnote 1
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd11 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote11 = pTextNd11->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote11(pFootnote11->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnote11.GetNumber());
+ SwTextFootnote* pTFNote11 = static_cast<SwTextFootnote*> (pFootnote11);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), pTFNote11->GetSeqRefNo());
+ //old reference field 1
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef21 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef21->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef21->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //old reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef22 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef22->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef22->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //old reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef23 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef23->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef23->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //old footnote 1
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd12 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote12 = pTextNd12->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote12(pFootnote12->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnote12.GetNumber());
+ SwTextFootnote* pTFNote12 = static_cast<SwTextFootnote*> (pFootnote12);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pTFNote12->GetSeqRefNo());
+ //old footnote 2
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd13 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote13 = pTextNd13->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote13(pFootnote13->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), rFootnote13.GetNumber());
+ SwTextFootnote* pTFNote13 = static_cast<SwTextFootnote*> (pFootnote13);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pTFNote13->GetSeqRefNo());
+ //old footnote 3
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd14 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote14 = pTextNd14->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote14(pFootnote14->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), rFootnote14.GetNumber());
+ SwTextFootnote* pTFNote14 = static_cast<SwTextFootnote*> (pFootnote14);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pTFNote14->GetSeqRefNo());
+ //old reference field 4
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef24 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef24->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef24->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //old reference field 5
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef25 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef25->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef25->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(3)), aAny);
+ //old footnote 4
+ pCursor->Move(fnMoveForward);
+ SwTextNode* pTextNd15 = pCursor->GetNode().GetTextNode();
+ SwTextAttr* const pFootnote15 = pTextNd15->GetTextAttrForCharAt(pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ const SwFormatFootnote& rFootnote15(pFootnote15->GetFootnote());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(5), rFootnote15.GetNumber());
+ SwTextFootnote* pTFNote15 = static_cast<SwTextFootnote*> (pFootnote15);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pTFNote15->GetSeqRefNo());
+}
+
+void SwUiWriterTest::testTdf63553()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ //inserting sequence field 1
+ SwSetExpFieldType* pSeqType = static_cast<SwSetExpFieldType*>(pWrtShell->GetFieldType(SwFieldIds::SetExp, "Illustration"));
+ SwSetExpField aSetField1(pSeqType, "", SVX_NUM_ARABIC);
+ pWrtShell->Insert(aSetField1);
+ SwGetRefFieldType* pRefType = static_cast<SwGetRefFieldType*>(pWrtShell->GetFieldType(0, SwFieldIds::GetRef));
+ //moving cursor to the starting of document
+ pWrtShell->StartOfSection();
+ //inserting reference field 1
+ SwGetRefField aGetField1(pRefType, "Illustration", "", REF_SEQUENCEFLD, sal_uInt16(0), REF_CONTENT);
+ pWrtShell->Insert(aGetField1);
+ //now we have ref1-seq1
+ //moving the cursor
+ pCursor->Move(fnMoveForward);
+ //inserting sequence field 2
+ SwSetExpField aSetField2(pSeqType, "", SVX_NUM_ARABIC);
+ pWrtShell->Insert(aSetField2);
+ //moving the cursor
+ pWrtShell->StartOfSection();
+ pCursor->Move(fnMoveForward);
+ //inserting reference field 2
+ SwGetRefField aGetField2(pRefType, "Illustration", "", REF_SEQUENCEFLD, sal_uInt16(1), REF_CONTENT);
+ pWrtShell->Insert(aGetField2);
+ //now we have ref1-ref2-seq1-seq2
+ //moving the cursor
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ //inserting sequence field 3
+ SwSetExpField aSetField3(pSeqType, "", SVX_NUM_ARABIC);
+ pWrtShell->Insert(aSetField3);
+ pWrtShell->StartOfSection();
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ //inserting reference field 3
+ SwGetRefField aGetField3(pRefType, "Illustration", "", REF_SEQUENCEFLD, sal_uInt16(2), REF_CONTENT);
+ pWrtShell->Insert(aGetField3);
+ //now after insertion we have ref1-ref2-ref3-seq1-seq2-seq3
+ //updating the fields
+ IDocumentFieldsAccess& rField(pDoc->getIDocumentFieldsAccess());
+ rField.UpdateExpFields(nullptr, true);
+ //creating new clipboard doc
+ rtl::Reference<SwDoc> xClpDoc( new SwDoc() );
+ xClpDoc->SetClipBoard(true);
+ xClpDoc->getIDocumentFieldsAccess().LockExpFields();
+ //selecting reference field 2 and 3 and sequence field 1 and 2
+ //selection is such that more than one and not all sequence fields and reference fields are selected
+ //ref1-[ref2-ref3-seq1-seq2]-seq3
+ pWrtShell->StartOfSection();
+ pCursor->Move(fnMoveForward);
+ //start marking
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ pCursor->Move(fnMoveForward);
+ //copying the selection to clipboard
+ pWrtShell->Copy(xClpDoc.get());
+ //deleting selection mark after copy
+ pCursor->DeleteMark();
+ //checking whether the sequence and reference fields have same values after copy operation
+ uno::Any aAny;
+ sal_uInt16 aFormat;
+ //reference field 1
+ pWrtShell->StartOfSection();
+ SwField* pRef1 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef1->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef1->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pRef2 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef2->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef2->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pRef3 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pRef3->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pRef3->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //sequence field 1
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeqF1 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pSeqF1->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeqF1->GetFieldName());
+ //sequence field 2
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeqF2 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pSeqF2->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeqF2->GetFieldName());
+ //sequence field 3
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeqF3 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pSeqF3->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeqF3->GetFieldName());
+ //moving cursor to the end of the document
+ pWrtShell->EndOfSection();
+ //pasting the copied selection at current cursor position
+ pWrtShell->Paste(xClpDoc.get());
+ //checking the fields, both new and old, for proper values
+ pWrtShell->StartOfSection();
+ //now we have ref1-ref2-ref3-seq1-seq2-seq3-nref1-nref2-nseq1-nseq2
+ //old reference field 1
+ SwField* pOldRef11 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef11->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef11->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //old reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef12 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef12->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef12->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //old reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef13 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef13->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef13->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //old sequence field 1
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeq1 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pSeq1->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeq1->GetFieldName());
+ //old sequence field 2
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeq2 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pSeq2->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeq2->GetFieldName());
+ //old sequence field 3
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pSeq3 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pSeq3->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pSeq3->GetFieldName());
+ //new reference field 1
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef11 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef11->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef11->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(4)), aAny);
+ //new reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef12 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef12->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef12->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //new sequence field 1
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pNewSeq1 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pNewSeq1->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pNewSeq1->GetFieldName());
+ //new sequence field 2
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pNewSeq2 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), pNewSeq2->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pNewSeq2->GetFieldName());
+ //moving the cursor to the starting of document
+ pWrtShell->StartOfSection();
+ //pasting the selection again at current cursor position
+ pWrtShell->Paste(xClpDoc.get());
+ //checking the fields, both new and old, for proper values
+ pWrtShell->StartOfSection();
+ //now we have [nnref1-nnref2-nnseq1-nnseq2]-ref1-[ref2-ref3-seq1-seq2]-seq3-[nref1-nref2-nseq1-nseq2]
+ //new reference field 1
+ SwField* pNewRef21 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef21->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef21->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(6)), aAny);
+ //new reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pNewRef22 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pNewRef22->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pNewRef22->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //new sequence field 1
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pNewSeq11 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(5), pNewSeq11->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pNewSeq11->GetFieldName());
+ //new sequence field 2
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pNewSeq12 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), pNewSeq12->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pNewSeq12->GetFieldName());
+ //old reference field 1
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef21 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef21->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef21->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(0)), aAny);
+ //old reference field 2
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef22 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef22->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef22->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(1)), aAny);
+ //old reference field 3
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef23 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef23->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef23->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //old sequence field 1
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pOldSeq11 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pOldSeq11->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pOldSeq11->GetFieldName());
+ //old sequence field 2
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pOldSeq12 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pOldSeq12->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pOldSeq12->GetFieldName());
+ //old sequence field 3
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pOldSeq13 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pOldSeq13->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pOldSeq13->GetFieldName());
+ //old reference field 4
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef24 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef24->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef24->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(4)), aAny);
+ //old reference field 5
+ pCursor->Move(fnMoveForward);
+ SwField* pOldRef25 = SwCursorShell::GetFieldAtCursor(pCursor, true);
+ aFormat = pOldRef25->GetFormat();
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_CONTENT), aFormat);
+ pOldRef25->QueryValue(aAny, sal_uInt16(FIELD_PROP_SHORT1));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_uInt16(2)), aAny);
+ //old sequence field 4
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pOldSeq14 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pOldSeq14->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pOldSeq14->GetFieldName());
+ //old sequence field 5
+ pCursor->Move(fnMoveForward);
+ SwSetExpField* pOldSeq15 = static_cast<SwSetExpField*> (SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), pOldSeq15->GetSeqNumber());
+ CPPUNIT_ASSERT_EQUAL(OUString("Number range Illustration"), pOldSeq15->GetFieldName());
+}
+
+void SwUiWriterTest::testTdf74230()
+{
+ createDoc();
+ //exporting the empty document to ODT via TempFile
+ uno::Sequence<beans::PropertyValue> aDescriptor;
+ utl::TempFile aTempFile;
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ CPPUNIT_ASSERT(aTempFile.IsValid());
+ //loading an XML DOM of the "styles.xml" of the TempFile
+ xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(),"styles.xml");
+ //pXmlDoc should not be null
+ CPPUNIT_ASSERT(pXmlDoc);
+ //asserting XPath in loaded XML DOM
+ assertXPath(pXmlDoc, "//office:styles/style:default-style[@style:family='graphic']/style:graphic-properties[@svg:stroke-color='#3465a4']");
+ assertXPath(pXmlDoc, "//office:styles/style:default-style[@style:family='graphic']/style:graphic-properties[@draw:fill-color='#729fcf']");
+ //deleting the TempFile
+ aTempFile.EnableKillingFile();
+}
+
+void SwUiWriterTest::testTdf74363()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //testing autocorrect of initial capitals on start of first paragraph
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ //Inserting one all-lowercase word into the first paragraph
+ pWrtShell->Insert("testing");
+ const sal_Unicode cChar = ' ';
+ pWrtShell->AutoCorrect(corr, cChar);
+ //The word should be capitalized due to autocorrect
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ CPPUNIT_ASSERT_EQUAL(OUString("Testing "), static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf80663()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //Inserting 2x2 Table
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(TableOpt, 2, 2);
+ //Checking for the number of rows and columns
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Deleting the first row
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->SelTableRow(); //selects the first row
+ pWrtShell->DeleteRow();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Deleting the second row
+ pWrtShell->GoNextCell(); //moves the cursor to next cell
+ pWrtShell->SelTableRow(); //selects the second row
+ pWrtShell->DeleteRow();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Deleting the first column
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->SelTableCol(); //selects first column
+ pWrtShell->DeleteCol();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Deleting the second column
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->GoNextCell(); //moves the cursor to next cell
+ pWrtShell->SelTableCol(); //selects second column
+ pWrtShell->DeleteCol();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+}
+
+void SwUiWriterTest::testTdf57197()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //Inserting 1x1 Table
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(TableOpt, 1, 1);
+ //Checking for the number of rows and columns
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Inserting one row before the existing row
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->InsertRow(1, false);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Inserting one row after the existing row
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->InsertRow(1, true);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Inserting one column before the existing column
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->InsertCol(1, false);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Inserting one column after the existing column
+ pWrtShell->StartOfSection(); //moves the cursor to the start of Doc
+ pWrtShell->InsertCol(1, true);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ //Redo changes
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getColumns()->getCount());
+ //Undo changes
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+}
+
+void SwUiWriterTest::testTdf90808()
+{
+ createDoc();
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xTextRange = xTextDocument->getText();
+ uno::Reference<text::XText> xText = xTextRange->getText();
+ uno::Reference<text::XParagraphCursor> xCursor(xText->createTextCursor(), uno::UNO_QUERY);
+ //inserting text into document so that the paragraph is not empty
+ xText->setString("Hello World!");
+ uno::Reference<lang::XMultiServiceFactory> xFact(mxComponent, uno::UNO_QUERY);
+ //creating bookmark 1
+ uno::Reference<text::XTextContent> xHeadingBookmark1(xFact->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xHeadingName1(xHeadingBookmark1, uno::UNO_QUERY);
+ xHeadingName1->setName("__RefHeading__1");
+ //moving cursor to the starting of paragraph
+ xCursor->gotoStartOfParagraph(false);
+ //inserting the bookmark in paragraph
+ xText->insertTextContent(xCursor, xHeadingBookmark1, true);
+ //creating bookmark 2
+ uno::Reference<text::XTextContent> xHeadingBookmark2(xFact->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xHeadingName2(xHeadingBookmark2, uno::UNO_QUERY);
+ xHeadingName2->setName("__RefHeading__2");
+ //inserting the bookmark in same paragraph, at the end
+ //only one bookmark of this type is allowed in each paragraph an exception of com.sun.star.lang.IllegalArgumentException must be thrown when inserting the other bookmark in same paragraph
+ xCursor->gotoEndOfParagraph(true);
+ CPPUNIT_ASSERT_THROW(xText->insertTextContent(xCursor, xHeadingBookmark2, true), css::lang::IllegalArgumentException);
+ //now testing for __RefNumPara__
+ //creating bookmark 1
+ uno::Reference<text::XTextContent> xNumBookmark1(xFact->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xNumName1(xNumBookmark1, uno::UNO_QUERY);
+ xNumName1->setName("__RefNumPara__1");
+ //moving cursor to the starting of paragraph
+ xCursor->gotoStartOfParagraph(false);
+ //inserting the bookmark in paragraph
+ xText->insertTextContent(xCursor, xNumBookmark1, true);
+ //creating bookmark 2
+ uno::Reference<text::XTextContent> xNumBookmark2(xFact->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xNumName2(xNumBookmark2, uno::UNO_QUERY);
+ xNumName2->setName("__RefNumPara__2");
+ //inserting the bookmark in same paragraph, at the end
+ //only one bookmark of this type is allowed in each paragraph an exception of com.sun.star.lang.IllegalArgumentException must be thrown when inserting the other bookmark in same paragraph
+ xCursor->gotoEndOfParagraph(true);
+ CPPUNIT_ASSERT_THROW(xText->insertTextContent(xCursor, xNumBookmark2, true), css::lang::IllegalArgumentException);
+}
+
+void SwUiWriterTest::testTdf97601()
+{
+ // Instructions from the bugreport to trigger an infinite loop.
+ createDoc("tdf97601.odt");
+ uno::Reference<text::XTextEmbeddedObjectsSupplier> xEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xEmbeddedObjects = xEmbeddedObjectsSupplier->getEmbeddedObjects();
+ uno::Reference<beans::XPropertySet> xChart;
+ xEmbeddedObjects->getByName("myChart") >>= xChart;
+ uno::Reference<chart2::data::XDataSource> xChartComponent;
+ xChart->getPropertyValue("Component") >>= xChartComponent;
+ uno::Sequence< uno::Reference<chart2::data::XLabeledDataSequence> > aDataSequences = xChartComponent->getDataSequences();
+ uno::Reference<document::XEmbeddedObjectSupplier2> xChartState(xChart, uno::UNO_QUERY);
+ xChartState->getExtendedControlOverEmbeddedObject()->changeState(1);
+ uno::Reference<util::XModifiable> xDataSequenceModifiable(aDataSequences[2]->getValues(), uno::UNO_QUERY);
+ xDataSequenceModifiable->setModified(true);
+
+ // Make sure that the chart is marked as modified.
+ uno::Reference<util::XModifiable> xModifiable(xChartComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(true, bool(xModifiable->isModified()));
+ calcLayout();
+ // This never returned.
+ Scheduler::ProcessEventsToIdle();
+}
+
+void SwUiWriterTest::testTdf75137()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(true);
+ pWrtShell->InsertFootnote("This is first footnote");
+ sal_uLong firstIndex = pShellCursor->GetNode().GetIndex();
+ pShellCursor->GotoFootnoteAnchor();
+ pWrtShell->InsertFootnote("This is second footnote");
+ pWrtShell->Up(false);
+ sal_uLong secondIndex = pShellCursor->GetNode().GetIndex();
+ pWrtShell->Down(false);
+ sal_uLong thirdIndex = pShellCursor->GetNode().GetIndex();
+ CPPUNIT_ASSERT_EQUAL(firstIndex, thirdIndex);
+ CPPUNIT_ASSERT(firstIndex != secondIndex);
+}
+
+namespace
+{
+ sal_Int32 lcl_getAttributeIDFromHints( const SwpHints& hints )
+ {
+ for (size_t i = 0; i < hints.Count(); ++i)
+ {
+ const SwTextAttr* hint = hints.Get(i);
+ if( hint->Which() == RES_TXTATR_AUTOFMT )
+ {
+ const SwFormatAutoFormat& rFmt = hint->GetAutoFormat();
+ SfxItemIter aIter( *rFmt.GetStyleHandle() );
+ return aIter.GetCurItem()->Which();
+ }
+ }
+ return -1;
+ }
+}
+
+void SwUiWriterTest::testTdf99689TableOfContents()
+{
+ SwDoc* pDoc = createDoc("tdf99689.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->GotoNextTOXBase();
+ const SwTOXBase* pTOXBase = pWrtShell->GetCurTOX();
+ pWrtShell->UpdateTableOf(*pTOXBase);
+ SwCursorShell * pShell(pDoc->GetEditShell());
+ SwTextNode* pTitleNode = pShell->GetCursor()->GetNode().GetTextNode();
+ SwNodeIndex aIdx ( *pTitleNode );
+ // skip the title
+ pDoc->GetNodes().GoNext( &aIdx );
+
+ // skip the first header. No attributes there.
+ // next node should contain superscript
+ SwTextNode* pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ sal_uInt16 nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+
+ // next node should contain subscript
+ pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+}
+
+void SwUiWriterTest::testTdf99689TableOfFigures()
+{
+ SwDoc* pDoc = createDoc("tdf99689_figures.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->GotoNextTOXBase();
+ const SwTOXBase* pTOXBase = pWrtShell->GetCurTOX();
+ pWrtShell->UpdateTableOf(*pTOXBase);
+ SwCursorShell * pShell(pDoc->GetEditShell());
+ SwTextNode* pTitleNode = pShell->GetCursor()->GetNode().GetTextNode();
+ SwNodeIndex aIdx ( *pTitleNode );
+
+ // skip the title
+ // next node should contain subscript
+ SwTextNode* pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ sal_uInt16 nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+
+ // next node should contain superscript
+ pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+}
+
+void SwUiWriterTest::testTdf99689TableOfTables()
+{
+ SwDoc* pDoc = createDoc("tdf99689_tables.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->GotoNextTOXBase();
+ const SwTOXBase* pTOXBase = pWrtShell->GetCurTOX();
+ pWrtShell->UpdateTableOf(*pTOXBase);
+ SwCursorShell * pShell(pDoc->GetEditShell());
+ SwTextNode* pTitleNode = pShell->GetCursor()->GetNode().GetTextNode();
+ SwNodeIndex aIdx ( *pTitleNode );
+
+ // skip the title
+ // next node should contain superscript
+ SwTextNode* pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ sal_uInt16 nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+
+ // next node should contain subscript
+ pNext = static_cast<SwTextNode*> (pDoc->GetNodes().GoNext( &aIdx ));
+ CPPUNIT_ASSERT( pNext->HasHints() );
+ nAttrType = lcl_getAttributeIDFromHints( pNext->GetSwpHints() );
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT), nAttrType );
+}
+
+void SwUiWriterTest::testTdf83798()
+{
+ SwDoc* pDoc = createDoc("tdf83798.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->GotoNextTOXBase();
+ const SwTOXBase* pTOXBase = pWrtShell->GetCurTOX();
+ pWrtShell->UpdateTableOf(*pTOXBase);
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward, GoInNode);
+ pCursor->Move(fnMoveBackward, GoInContent);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table of Contents"), pCursor->GetText());
+ pCursor->Move(fnMoveForward, GoInContent);
+ pCursor->DeleteMark();
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward, GoInContent);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), pCursor->GetText());
+ pCursor->DeleteMark();
+ pCursor->Move(fnMoveForward, GoInNode);
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward, GoInContent);
+ pCursor->Move(fnMoveForward, GoInContent);
+ pCursor->Move(fnMoveForward, GoInContent);
+ CPPUNIT_ASSERT_EQUAL(OUString("1.A"), pCursor->GetText());
+ pCursor->DeleteMark();
+ pCursor->Move(fnMoveForward, GoInNode);
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward, GoInContent);
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), pCursor->GetText());
+ pCursor->DeleteMark();
+ pCursor->Move(fnMoveForward, GoInNode);
+ pCursor->SetMark();
+ pCursor->Move(fnMoveForward, GoInContent);
+ pCursor->Move(fnMoveForward, GoInContent);
+ pCursor->Move(fnMoveForward, GoInContent);
+ CPPUNIT_ASSERT_EQUAL(OUString("2.A"), pCursor->GetText());
+ pCursor->DeleteMark();
+}
+
+void SwUiWriterTest::testTdf89714()
+{
+ createDoc();
+ uno::Reference<lang::XMultiServiceFactory> xFact(mxComponent, uno::UNO_QUERY);
+ uno::Reference<uno::XInterface> xInterface(xFact->createInstance("com.sun.star.text.Defaults"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertyState> xPropState(xInterface, uno::UNO_QUERY);
+ //enabled Paragraph Orphan and Widows by default starting in LO5.1
+ CPPUNIT_ASSERT_EQUAL( uno::makeAny(sal_Int8(2)), xPropState->getPropertyDefault("ParaOrphans") );
+ CPPUNIT_ASSERT_EQUAL( uno::makeAny(sal_Int8(2)), xPropState->getPropertyDefault("ParaWidows") );
+}
+
+void SwUiWriterTest::testTdf130287()
+{
+ //create a new writer document
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ //insert a 1-cell table in the newly created document
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(TableOpt, 1, 1);
+ //checking for the row and column
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumns()->getCount());
+ uno::Reference<table::XCell> xCell = xTable->getCellByName("A1");
+ uno::Reference<text::XText> xCellText(xCell, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xParagraph = getParagraphOfText(1, xCellText);
+ // they were 2 (orphan/widow control enabled unnecessarily in Table Contents paragraph style)
+ CPPUNIT_ASSERT_EQUAL( sal_Int8(0), getProperty<sal_Int8>(xParagraph, "ParaOrphans"));
+ CPPUNIT_ASSERT_EQUAL( sal_Int8(0), getProperty<sal_Int8>(xParagraph, "ParaWidows"));
+}
+
+void SwUiWriterTest::testPropertyDefaults()
+{
+ createDoc();
+ uno::Reference<lang::XMultiServiceFactory> xFact(mxComponent, uno::UNO_QUERY);
+ uno::Reference<uno::XInterface> xInterface(xFact->createInstance("com.sun.star.text.Defaults"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropSet(xInterface, uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertyState> xPropState(xInterface, uno::UNO_QUERY);
+ //testing CharFontName from style::CharacterProperties
+ //getting property default
+ uno::Any aCharFontName = xPropState->getPropertyDefault("CharFontName");
+ //asserting property default and defaults received from "css.text.Defaults" service
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharFontName"), aCharFontName);
+ //changing the default value
+ xPropSet->setPropertyValue("CharFontName", uno::makeAny(OUString("Symbol")));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(OUString("Symbol")), xPropSet->getPropertyValue("CharFontName"));
+ //resetting the value to default
+ xPropState->setPropertyToDefault("CharFontName");
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharFontName"), aCharFontName);
+ //testing CharHeight from style::CharacterProperties
+ //getting property default
+ uno::Any aCharHeight = xPropState->getPropertyDefault("CharHeight");
+ //asserting property default and defaults received from "css.text.Defaults" service
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharHeight"), aCharHeight);
+ //changing the default value
+ xPropSet->setPropertyValue("CharHeight", uno::makeAny(float(14)));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(float(14)), xPropSet->getPropertyValue("CharHeight"));
+ //resetting the value to default
+ xPropState->setPropertyToDefault("CharHeight");
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharHeight"), aCharHeight);
+ //testing CharWeight from style::CharacterProperties
+ uno::Any aCharWeight = xPropSet->getPropertyValue("CharWeight");
+ //changing the default value
+ xPropSet->setPropertyValue("CharWeight", uno::makeAny(float(awt::FontWeight::BOLD)));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(float(awt::FontWeight::BOLD)), xPropSet->getPropertyValue("CharWeight"));
+ //resetting the value to default
+ xPropState->setPropertyToDefault("CharWeight");
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharWeight"), aCharWeight);
+ //testing CharUnderline from style::CharacterProperties
+ uno::Any aCharUnderline = xPropSet->getPropertyValue("CharUnderline");
+ //changing the default value
+ xPropSet->setPropertyValue("CharUnderline", uno::makeAny(sal_Int16(awt::FontUnderline::SINGLE)));
+ CPPUNIT_ASSERT_EQUAL(uno::makeAny(sal_Int16(awt::FontUnderline::SINGLE)), xPropSet->getPropertyValue("CharUnderline"));
+ //resetting the value to default
+ xPropState->setPropertyToDefault("CharUnderline");
+ CPPUNIT_ASSERT_EQUAL(xPropSet->getPropertyValue("CharUnderline"), aCharUnderline);
+}
+
+void SwUiWriterTest::testTableBackgroundColor()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(TableOpt, 3, 3); //Inserting Table
+ //Checking Rows and Columns of Inserted Table
+ 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());
+ pWrtShell->StartOfSection();
+ pWrtShell->SelTableRow(); //Selecting First Row
+ pWrtShell->ClearMark();
+ //Modifying the color of Table Box
+ pWrtShell->SetBoxBackground(SvxBrushItem(Color(sal_Int32(0xFF00FF)), sal_Int16(RES_BACKGROUND)));
+ //Checking cells for background color only A1 should be modified
+ uno::Reference<table::XCell> xCell;
+ xCell = xTable->getCellByName("A1");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0xFF00FF), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("A2");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("A3");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("B1");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("B2");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("B3");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("C1");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("C2");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+ xCell = xTable->getCellByName("C3");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xCell, "BackColor"));
+}
+
+void SwUiWriterTest::testTdf88899()
+{
+ createDoc();
+ uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<document::XDocumentProperties> xProps(xDocumentPropertiesSupplier->getDocumentProperties());
+ uno::Reference<beans::XPropertyContainer> xUserProps = xProps->getUserDefinedProperties();
+ css::util::DateTime aDateTime = {sal_uInt32(1234567), sal_uInt16(3), sal_uInt16(3), sal_uInt16(3), sal_uInt16(10), sal_uInt16(11), sal_uInt16(2014), true};
+ xUserProps->addProperty("dateTime", sal_Int16(beans::PropertyAttribute::OPTIONAL), uno::makeAny(aDateTime));
+ uno::Reference<lang::XMultiServiceFactory> xFact(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextField> xTextField(xFact->createInstance("com.sun.star.text.textfield.docinfo.Custom"), uno::UNO_QUERY);
+ //Setting Name Property
+ uno::Reference<beans::XPropertySet> xPropSet(xTextField, uno::UNO_QUERY_THROW);
+ xPropSet->setPropertyValue("Name", uno::makeAny(OUString("dateTime")));
+ //Setting NumberFormat
+ uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<util::XNumberFormatTypes> xNumFormat(xNumberFormatsSupplier->getNumberFormats(), uno::UNO_QUERY);
+ css::lang::Locale alocale;
+ alocale.Language = "en";
+ alocale.Country = "US";
+ sal_Int16 key = xNumFormat->getStandardFormat(util::NumberFormat::DATETIME, alocale);
+ xPropSet->setPropertyValue("NumberFormat", uno::makeAny(key));
+ //Inserting Text Content
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xTextRange = xTextDocument->getText();
+ uno::Reference<text::XText> xText = xTextRange->getText();
+ xText->insertTextContent(xTextRange, xTextField, true);
+ //Retrieving the contents for verification
+ CPPUNIT_ASSERT_EQUAL(OUString("11/10/14 03:03 AM"), xTextField->getPresentation(false));
+}
+
+void SwUiWriterTest::testTdf90362()
+{
+ SwDoc* pDoc = createDoc("tdf90362.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ // Ensure correct initial setting
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea", css::uno::Any(false), comphelper::EConfigurationModes::Standard);
+ // First check if the end of the second paragraph is indeed protected.
+ pWrtShell->EndPara();
+ pWrtShell->Down(/*bSelect=*/false);
+ CPPUNIT_ASSERT_EQUAL(true, pWrtShell->HasReadonlySel());
+
+ // Then enable ignoring of protected areas and make sure that this time the cursor is read-write.
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea", css::uno::Any(true), comphelper::EConfigurationModes::Standard);
+ CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
+ // Clean up, otherwise following tests will have that option set
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext, "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea", css::uno::Any(false), comphelper::EConfigurationModes::Standard);
+}
+
+void SwUiWriterTest::testUndoDelAsCharTdf107512()
+{
+ SwDoc * pDoc(createDoc());
+ sw::UndoManager & rUndoManager(pDoc->GetUndoManager());
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ SwCursorShell * pShell(pDoc->GetEditShell());
+ SfxItemSet frameSet(pDoc->GetAttrPool(), svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{});
+ SfxItemSet grfSet(pDoc->GetAttrPool(), svl::Items<RES_GRFATR_BEGIN, RES_GRFATR_END-1>{});
+ rIDCO.InsertString(*pShell->GetCursor(), "foo");
+ pShell->ClearMark();
+ SwFormatAnchor anchor(RndStdIds::FLY_AS_CHAR);
+ frameSet.Put(anchor);
+ GraphicObject grf;
+ pShell->SttEndDoc(true);
+ CPPUNIT_ASSERT(rIDCO.InsertGraphicObject(*pShell->GetCursor(), grf, &frameSet, &grfSet));
+ pShell->SttEndDoc(false);
+ CPPUNIT_ASSERT(rIDCO.InsertGraphicObject(*pShell->GetCursor(), grf, &frameSet, &grfSet));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ SvxCharHiddenItem hidden(true, RES_CHRATR_HIDDEN);
+ pShell->SelectText(1, 4);
+ rIDCO.InsertPoolItem(*pShell->GetCursor(), hidden);
+ // now we have "\1foo\1" with the "foo" hidden
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_BREAKWORD) + u"foo" + OUStringChar(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+ SfxPoolItem const* pItem;
+ SfxItemSet query(pDoc->GetAttrPool(), svl::Items<RES_CHRATR_HIDDEN, RES_CHRATR_HIDDEN>{});
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 1, 4);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+ query.ClearItem(RES_CHRATR_HIDDEN);
+
+ // delete from the start
+ pShell->SelectText(0, 4);
+ rIDCO.DeleteAndJoin(*pShell->GetCursor());
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 0, 1);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_BREAKWORD) + u"foo" + OUStringChar(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 0, 1);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 1, 4);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 0, 1);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_BREAKWORD) + u"foo" + OUStringChar(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 0, 1);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 1, 4);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+ query.ClearItem(RES_CHRATR_HIDDEN);
+
+ // delete from the end
+ pShell->SelectText(1, 5);
+ rIDCO.DeleteAndJoin(*pShell->GetCursor());
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 4, 5);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_BREAKWORD) + u"foo" + OUStringChar(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 4, 5);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 1, 4);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 4, 5);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_BREAKWORD) + u"foo" + OUStringChar(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 4, 5);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ query.ClearItem(RES_CHRATR_HIDDEN);
+ pShell->GetCursor()->GetNode().GetTextNode()->GetParaAttr(query, 1, 4);
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+ CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+ query.ClearItem(RES_CHRATR_HIDDEN);
+}
+
+void SwUiWriterTest::testUndoCharAttribute()
+{
+ // Create a new empty Writer document
+ SwDoc* pDoc = createDoc();
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ // Insert some text
+ rIDCO.InsertString(*pCursor, "This will be bolded");
+ // Position of word 9876543210
+ // Use cursor to select part of text
+ pCursor->SetMark();
+ for (int i = 0; i < 9; i++) {
+ pCursor->Move(fnMoveBackward);
+ }
+ // Check that correct text was selected
+ CPPUNIT_ASSERT_EQUAL(OUString("be bolded"), pCursor->GetText());
+ // Apply a "Bold" attribute to selection
+ SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
+ rIDCO.InsertPoolItem(*pCursor, aWeightItem);
+ SfxItemSet aSet( pDoc->GetAttrPool(), svl::Items<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT>{});
+ // Adds selected text's attributes to aSet
+ pCursor->GetNode().GetTextNode()->GetParaAttr(aSet, 10, 19);
+ SfxPoolItem const * pPoolItem = aSet.GetItem(RES_CHRATR_WEIGHT);
+ // Check that bold is active on the selection; checks if it's in aSet
+ CPPUNIT_ASSERT_EQUAL(true, (*pPoolItem == aWeightItem));
+ // Invoke Undo
+ rUndoManager.Undo();
+ // Check that bold is no longer active
+ aSet.ClearItem(RES_CHRATR_WEIGHT);
+ pCursor->GetNode().GetTextNode()->GetParaAttr(aSet, 10, 19);
+ pPoolItem = aSet.GetItem(RES_CHRATR_WEIGHT);
+ CPPUNIT_ASSERT_EQUAL(false, (*pPoolItem == aWeightItem));
+}
+
+void SwUiWriterTest::testUndoDelAsChar()
+{
+ SwDoc * pDoc(createDoc());
+ sw::UndoManager & rUndoManager(pDoc->GetUndoManager());
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ SwCursorShell * pShell(pDoc->GetEditShell());
+ SfxItemSet frameSet(pDoc->GetAttrPool(), svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{});
+ SfxItemSet grfSet(pDoc->GetAttrPool(), svl::Items<RES_GRFATR_BEGIN, RES_GRFATR_END-1>{});
+ SwFormatAnchor anchor(RndStdIds::FLY_AS_CHAR);
+ frameSet.Put(anchor);
+ GraphicObject grf;
+ CPPUNIT_ASSERT(rIDCO.InsertGraphicObject(*pShell->GetCursor(), grf, &frameSet, &grfSet));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ pShell->SetMark();
+ pShell->Left(1, CRSR_SKIP_CHARS);
+ rIDCO.DeleteAndJoin(*pShell->GetCursor());
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT(!pShell->GetCursor()->GetNode().GetTextNode()->HasHints());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->HasHints());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT(!pShell->GetCursor()->GetNode().GetTextNode()->HasHints());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+ CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->HasHints());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+}
+
+void SwUiWriterTest::testTdf86639()
+{
+ SwDoc* pDoc = createDoc("tdf86639.rtf");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwTextFormatColl* pColl = pDoc->FindTextFormatCollByName("Heading");
+ pWrtShell->SetTextFormatColl(pColl);
+ OUString aExpected = pColl->GetAttrSet().GetFont().GetFamilyName();
+ // This was Calibri, should be Liberation Sans.
+ CPPUNIT_ASSERT_EQUAL(aExpected, getProperty<OUString>(getRun(getParagraph(1), 1), "CharFontName"));
+}
+
+void SwUiWriterTest::testTdf90883TableBoxGetCoordinates()
+{
+ SwDoc* pDoc = createDoc("tdf90883.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Down(true);
+ SwSelBoxes aBoxes;
+ ::GetTableSel( *pWrtShell, aBoxes );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(aBoxes.size()) );
+ Point pos ( aBoxes[0]->GetCoordinates() );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(pos.X()) );
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(pos.Y()) );
+ pos = aBoxes[1]->GetCoordinates();
+ CPPUNIT_ASSERT_EQUAL( 1, static_cast<int>(pos.X()) );
+ CPPUNIT_ASSERT_EQUAL( 2, static_cast<int>(pos.Y()) );
+}
+
+void SwUiWriterTest::testEmbeddedDataSource()
+{
+ // Initially no data source.
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ uno::Reference<sdb::XDatabaseContext> xDatabaseContext = sdb::DatabaseContext::create(xComponentContext);
+ CPPUNIT_ASSERT(!xDatabaseContext->hasByName("calc-data-source"));
+
+ // Load: should have a component and a data source, too.
+ // Path with "#" must not cause issues
+ load(DATA_DIRECTORY + OUStringLiteral("hash%23path/"), "embedded-data-source.odt");
+ CPPUNIT_ASSERT(mxComponent.is());
+ CPPUNIT_ASSERT(xDatabaseContext->hasByName("calc-data-source"));
+
+ // Data source has a table named Sheet1.
+ uno::Reference<sdbc::XDataSource> xDataSource(xDatabaseContext->getByName("calc-data-source"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDataSource.is());
+ auto xConnection = xDataSource->getConnection("", "");
+ uno::Reference<container::XNameAccess> xTables =
+ css::uno::Reference<css::sdbcx::XTablesSupplier>(
+ xConnection, uno::UNO_QUERY_THROW)->getTables();
+ CPPUNIT_ASSERT(xTables.is());
+ CPPUNIT_ASSERT(xTables->hasByName("Sheet1"));
+ xConnection->close();
+
+ // Reload: should still have a component and a data source, too.
+ reload("writer8", "embedded-data-source.odt");
+ CPPUNIT_ASSERT(mxComponent.is());
+ CPPUNIT_ASSERT(xDatabaseContext->hasByName("calc-data-source"));
+
+ // Data source has a table named Sheet1 after saving to a different directory.
+ xDataSource.set(xDatabaseContext->getByName("calc-data-source"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDataSource.is());
+ xConnection = xDataSource->getConnection("", "");
+ xTables =
+ css::uno::Reference<css::sdbcx::XTablesSupplier>(
+ xConnection, uno::UNO_QUERY_THROW)->getTables();
+ CPPUNIT_ASSERT(xTables.is());
+ CPPUNIT_ASSERT(xTables->hasByName("Sheet1"));
+ xConnection->close();
+
+ // Close: should not have a data source anymore.
+ mxComponent->dispose();
+ mxComponent.clear();
+ CPPUNIT_ASSERT(!xDatabaseContext->hasByName("calc-data-source"));
+
+ // Now open again the saved result, and instead of 'save as', just 'save'.
+ mxComponent = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument");
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->store();
+}
+
+void SwUiWriterTest::testUnoCursorPointer()
+{
+ auto xDocComponent(loadFromDesktop("private:factory/swriter",
+ "com.sun.star.text.TextDocument"));
+ auto pxDocDocument(
+ dynamic_cast<SwXTextDocument *>(xDocComponent.get()));
+ CPPUNIT_ASSERT(pxDocDocument);
+ SwDoc* const pDoc(pxDocDocument->GetDocShell()->GetDoc());
+ std::unique_ptr<SwNodeIndex> pIdx(new SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1));
+ std::unique_ptr<SwPosition> pPos(new SwPosition(*pIdx));
+ sw::UnoCursorPointer pCursor(pDoc->CreateUnoCursor(*pPos));
+ CPPUNIT_ASSERT(static_cast<bool>(pCursor));
+ pPos.reset(); // we need to kill the SwPosition before disposing
+ pIdx.reset(); // we need to kill the SwNodeIndex before disposing
+ xDocComponent->dispose();
+ CPPUNIT_ASSERT(!static_cast<bool>(pCursor));
+}
+
+void SwUiWriterTest::testTextTableCellNames()
+{
+ sal_Int32 nCol, nRow2;
+ SwXTextTable::GetCellPosition( "z1", nCol, nRow2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(51), nCol);
+ SwXTextTable::GetCellPosition( "AA1", nCol, nRow2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(52), nCol);
+ SwXTextTable::GetCellPosition( "AB1", nCol, nRow2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(53), nCol);
+ SwXTextTable::GetCellPosition( "BB1", nCol, nRow2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(105), nCol);
+}
+
+void SwUiWriterTest::testShapeAnchorUndo()
+{
+ SwDoc* pDoc = createDoc("draw-anchor-undo.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(0);
+ tools::Rectangle aOrigLogicRect(pObject->GetLogicRect());
+
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ rUndoManager.StartUndo(SwUndoId::START, nullptr);
+
+ pWrtShell->SelectObj(Point(), 0, pObject);
+
+ pWrtShell->GetDrawView()->MoveMarkedObj(Size(100, 100));
+ pWrtShell->ChgAnchor(RndStdIds::FLY_AT_PARA, true);
+
+ rUndoManager.EndUndo(SwUndoId::END, nullptr);
+
+ CPPUNIT_ASSERT(aOrigLogicRect != pObject->GetLogicRect());
+
+ rUndoManager.Undo();
+
+ CPPUNIT_ASSERT_EQUAL(pObject->GetLogicRect(), aOrigLogicRect);
+}
+
+void SwUiWriterTest::testDde()
+{
+#if HAVE_FEATURE_UI
+ // Type asdf and copy it.
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("asdf");
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 4, /*bBasicCall=*/false);
+ uno::Sequence<beans::PropertyValue> aPropertyValues;
+ dispatchCommand(mxComponent, ".uno:Copy", aPropertyValues);
+
+ // Go before the selection and paste as a DDE link.
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ aPropertyValues = comphelper::InitPropertySequence(
+ {
+ {"SelectedFormat", uno::makeAny(static_cast<sal_uInt32>(SotClipboardFormatId::LINK))}
+ });
+ dispatchCommand(mxComponent, ".uno:ClipboardFormatItems", aPropertyValues);
+
+ // Make sure that the document starts with a field now, and its expanded string value contains asdf.
+ const uno::Reference< text::XTextRange > xField = getRun(getParagraph(1), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty<OUString>(xField, "TextPortionType"));
+ CPPUNIT_ASSERT(xField->getString().endsWith("asdf"));
+#endif
+}
+
+namespace {
+
+//IdleTask class to add a low priority Idle task
+class IdleTask
+{
+ public:
+ bool GetFlag() const;
+ IdleTask();
+ DECL_LINK( FlipFlag, Timer *, void );
+ private:
+ bool flag;
+ Idle maIdle;
+};
+
+}
+
+//constructor of IdleTask Class
+IdleTask::IdleTask() : flag( false )
+{
+ //setting the Priority of Idle task to LOW, LOWEST
+ maIdle.SetPriority( TaskPriority::LOWEST );
+ //set idle for callback
+ maIdle.SetInvokeHandler( LINK( this, IdleTask, FlipFlag) );
+ //starting the idle
+ maIdle.Start();
+}
+
+//GetFlag() of IdleTask Class
+bool IdleTask::GetFlag() const
+{
+ //returning the status of current flag
+ return flag;
+}
+
+//Callback function of IdleTask Class
+IMPL_LINK(IdleTask, FlipFlag, Timer*, , void)
+{
+ //setting the flag to make sure that low priority idle task has been dispatched
+ flag = true;
+}
+
+void SwUiWriterTest::testDocModState()
+{
+ //creating a new writer document via the XDesktop(to have more shells etc.)
+ SwDoc* pDoc = createDoc();
+ //creating instance of IdleTask Class
+ IdleTask idleTask;
+ //checking the state of the document via IDocumentState
+ IDocumentState& rState(pDoc->getIDocumentState());
+ //the state should not be modified
+ CPPUNIT_ASSERT(!(rState.IsModified()));
+ //checking the state of the document via SfxObjectShell
+ SwDocShell* pShell(pDoc->GetDocShell());
+ CPPUNIT_ASSERT(!(pShell->IsModified()));
+ //looping around yield until low priority idle task is dispatched and flag is flipped
+ while(!idleTask.GetFlag())
+ {
+ //dispatching all the events via VCL main-loop
+ Application::Yield();
+ }
+ //again checking for the state via IDocumentState
+ CPPUNIT_ASSERT(!(rState.IsModified()));
+ //again checking for the state via SfxObjectShell
+ CPPUNIT_ASSERT(!(pShell->IsModified()));
+}
+
+void SwUiWriterTest::testTdf94804()
+{
+ //create new writer document
+ SwDoc* pDoc = createDoc();
+ //get cursor for making bookmark at a particular location
+ SwPaM* pCrsr = pDoc->GetEditShell()->GetCursor();
+ IDocumentMarkAccess* pIDMAccess(pDoc->getIDocumentMarkAccess());
+ //make first bookmark, CROSSREF_HEADING, with *empty* name
+ sw::mark::IMark* pMark1(pIDMAccess->makeMark(*pCrsr, "",
+ IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK,
+ ::sw::mark::InsertMode::New));
+ //get the new(autogenerated) bookmark name
+ OUString bookmark1name = pMark1->GetName();
+ //match the bookmark name, it should be like "__RefHeading__**"
+ CPPUNIT_ASSERT(bookmark1name.match("__RefHeading__"));
+ //make second bookmark, CROSSREF_NUMITEM, with *empty* name
+ sw::mark::IMark* pMark2(pIDMAccess->makeMark(*pCrsr, "",
+ IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK,
+ ::sw::mark::InsertMode::New));
+ //get the new(autogenerated) bookmark name
+ OUString bookmark2name = pMark2->GetName();
+ //match the bookmark name, it should be like "__RefNumPara__**"
+ CPPUNIT_ASSERT(bookmark2name.match("__RefNumPara__"));
+}
+
+void SwUiWriterTest::testUnicodeNotationToggle()
+{
+ SwDoc* pDoc = createDoc("unicodeAltX.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ OUString sOriginalDocString;
+ OUString sDocString;
+ OUString sExpectedString;
+ uno::Sequence<beans::PropertyValue> aPropertyValues;
+
+ pWrtShell->EndPara();
+ sOriginalDocString = pWrtShell->GetCursor()->GetNode().GetTextNode()->GetText();
+ CPPUNIT_ASSERT_EQUAL(OUString("uU+002b"), sOriginalDocString);
+
+ dispatchCommand(mxComponent, ".uno:UnicodeNotationToggle", aPropertyValues);
+ sExpectedString = "u+";
+ sDocString = pWrtShell->GetCursor()->GetNode().GetTextNode()->GetText();
+ CPPUNIT_ASSERT_EQUAL( sDocString, sExpectedString );
+
+ dispatchCommand(mxComponent, ".uno:UnicodeNotationToggle", aPropertyValues);
+ sDocString = pWrtShell->GetCursor()->GetNode().GetTextNode()->GetText();
+ CPPUNIT_ASSERT_EQUAL( sDocString, sOriginalDocString );
+}
+
+void SwUiWriterTest::testTdf34957()
+{
+ load(DATA_DIRECTORY, "tdf34957.odt");
+ // table with "keep with next" always started on a new page if the table was large,
+ // regardless of whether it was already kept with the previous paragraph,
+ // or whether the following paragraph actually fit on the same page (MAB 3.6 - 5.0)
+ CPPUNIT_ASSERT_EQUAL( OUString("Row 1"), parseDump("/root/page[2]/body/tab[1]/row[2]/cell[1]/txt") );
+ CPPUNIT_ASSERT_EQUAL( OUString("Row 1"), parseDump("/root/page[4]/body/tab[1]/row[2]/cell[1]/txt") );
+}
+
+void SwUiWriterTest::testTdf89954()
+{
+ SwDoc* pDoc = createDoc("tdf89954.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->EndPara();
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 't', 0);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'e', 0);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 's', 0);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 't', 0);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, '.', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ SwNodeIndex aNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1);
+ // Placeholder character for the comment anchor was ^A (CH_TXTATR_BREAKWORD), not <fff9> (CH_TXTATR_INWORD).
+ // As a result, autocorrect did not turn the 't' input into 'T'.
+ OUString aExpected(u"Tes\uFFF9t. Test.");
+ CPPUNIT_ASSERT_EQUAL(aExpected, aNodeIndex.GetNode().GetTextNode()->GetText());
+}
+
+void SwUiWriterTest::testTdf89720()
+{
+ SwDoc* pDoc = createDoc("tdf89720.odt");
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ SwPostItMgr* pPostItMgr = pView->GetPostItMgr();
+ for (std::unique_ptr<SwSidebarItem> const & pItem : *pPostItMgr)
+ {
+ if (pItem->pPostIt->IsFollow())
+ // This was non-0: reply comments had a text range overlay,
+ // resulting in unexpected dark color.
+ CPPUNIT_ASSERT(!pItem->pPostIt->TextRange());
+ }
+}
+
+void SwUiWriterTest::testTdf88986()
+{
+ // Create a text shell.
+ SwDoc* pDoc = createDoc();
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ SwTextShell aShell(*pView);
+
+ // Create the item set that is normally passed to the insert frame dialog.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwFlyFrameAttrMgr aMgr(true, pWrtShell, Frmmgr_Type::TEXT, nullptr);
+ SfxItemSet aSet = aShell.CreateInsertFrameItemSet(aMgr);
+
+ // This was missing along with the gradient and other tables.
+ CPPUNIT_ASSERT(aSet.HasItem(SID_COLOR_TABLE));
+}
+
+void SwUiWriterTest::testTdf87922()
+{
+ // Create an SwDrawTextInfo.
+ SwDoc* pDoc = createDoc("tdf87922.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwScriptInfo* pScriptInfo = nullptr;
+ // Get access to the single paragraph in the document.
+ SwNodeIndex aNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1);
+ const OUString& rText = aNodeIndex.GetNode().GetTextNode()->GetText();
+ sal_Int32 nLength = rText.getLength();
+ SwDrawTextInfo aDrawTextInfo(pWrtShell, *pWrtShell->GetOut(), pScriptInfo, rText, TextFrameIndex(0), TextFrameIndex(nLength));
+ // Root -> page -> body -> text.
+ SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower());
+ aDrawTextInfo.SetFrame(pTextFrame);
+
+ // If no color background color is found, assume white.
+ Color* pColor = sw::GetActiveRetoucheColor();
+ *pColor = COL_WHITE;
+
+ // Make sure that automatic color on black background is white, not black.
+ vcl::Font aFont;
+ aDrawTextInfo.ApplyAutoColor(&aFont);
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, aFont.GetColor());
+}
+
+#if HAVE_MORE_FONTS
+namespace {
+
+struct PortionItem
+{
+ PortionItem(OUString const & sItemType, sal_Int32 nLength,
+ PortionType nTextType)
+ : msItemType(sItemType)
+ , mnLength(nLength)
+ , mnTextType(nTextType)
+ {}
+
+ OUString msItemType;
+ sal_Int32 mnLength;
+ PortionType mnTextType;
+};
+
+class PortionHandler : public SwPortionHandler
+{
+ public:
+
+ std::vector<PortionItem> mPortionItems;
+ explicit PortionHandler()
+ : SwPortionHandler()
+ {}
+
+ void clear()
+ {
+ mPortionItems.clear();
+ }
+
+ virtual void Text(TextFrameIndex nLength, PortionType nType,
+ sal_Int32 /*nHeight*/, sal_Int32 /*nWidth*/) override
+ {
+ mPortionItems.emplace_back("text", sal_Int32(nLength), nType);
+ }
+
+ virtual void Special(TextFrameIndex nLength, const OUString & /*rText*/,
+ PortionType nType, sal_Int32 /*nHeight*/,
+ sal_Int32 /*nWidth*/, const SwFont* /*pFont*/) override
+ {
+ mPortionItems.emplace_back("special", sal_Int32(nLength), nType);
+ }
+
+ virtual void LineBreak(sal_Int32 /*nWidth*/) override
+ {
+ mPortionItems.emplace_back("line_break", 0, PortionType::NONE);
+ }
+
+ virtual void Skip(TextFrameIndex nLength) override
+ {
+ mPortionItems.emplace_back("skip", sal_Int32(nLength), PortionType::NONE);
+ }
+
+ virtual void Finish() override
+ {
+ mPortionItems.emplace_back("finish", 0, PortionType::NONE);
+ }
+};
+
+}
+#endif
+
+void SwUiWriterTest::testTdf77014()
+{
+#if HAVE_MORE_FONTS
+ // The problem described in the bug tdf#77014 is that the input
+ // field text ("ThisIsAllOneWord") is broken up on linebreak, but
+ // it should be in one piece (like normal text).
+
+ // This test checks that the input field is in one piece and if the
+ // input field has more words, it is broken up at the correct place.
+
+ SwDoc* pDoc = createDoc("tdf77014.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower());
+
+ PortionHandler aHandler;
+ pTextFrame->VisitPortions(aHandler);
+
+ {
+ // Input Field - "One Two Three Four Five" = 25 chars
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), aHandler.mPortionItems[0].msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(25), aHandler.mPortionItems[0].mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::InputField, aHandler.mPortionItems[0].mnTextType);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), aHandler.mPortionItems[1].msItemType);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("finish"), aHandler.mPortionItems[2].msItemType);
+ }
+
+ aHandler.clear();
+
+ pTextFrame = static_cast<SwTextFrame*>(pTextFrame->GetNext());
+ pTextFrame->VisitPortions(aHandler);
+
+ {
+ // Input Field - "ThisIsAllOneWord" = 18 chars
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), aHandler.mPortionItems[0].msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(18), aHandler.mPortionItems[0].mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::InputField, aHandler.mPortionItems[0].mnTextType);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), aHandler.mPortionItems[1].msItemType);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("finish"), aHandler.mPortionItems[2].msItemType);
+ }
+
+ aHandler.clear();
+
+ // skip empty paragraph
+ pTextFrame = static_cast<SwTextFrame*>(pTextFrame->GetNext());
+
+ pTextFrame = static_cast<SwTextFrame*>(pTextFrame->GetNext());
+ pTextFrame->VisitPortions(aHandler);
+
+ {
+ // Text "The purpose of this report is to summarize the results of the existing bug in the LO suite"
+ // = 91 chars
+ auto& rPortionItem = aHandler.mPortionItems[0];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(91), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::Text, rPortionItem.mnTextType);
+
+ // NEW LINE
+ rPortionItem = aHandler.mPortionItems[1];
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), rPortionItem.msItemType);
+
+ // Input Field: "ThisIsAllOneWord" = 18 chars
+ // which is 16 chars + 2 hidden chars (start & end input field) = 18 chars
+ // If this is correct then the input field is in one piece
+ rPortionItem = aHandler.mPortionItems[2];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(18), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::InputField, rPortionItem.mnTextType);
+
+ // Text "."
+ rPortionItem = aHandler.mPortionItems[3];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::Text, rPortionItem.mnTextType);
+
+ // NEW LINE
+ rPortionItem = aHandler.mPortionItems[4];
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), rPortionItem.msItemType);
+
+ rPortionItem = aHandler.mPortionItems[5];
+ CPPUNIT_ASSERT_EQUAL(OUString("finish"), rPortionItem.msItemType);
+
+ }
+
+ aHandler.clear();
+
+ pTextFrame = static_cast<SwTextFrame*>(pTextFrame->GetNext());
+ pTextFrame->VisitPortions(aHandler);
+ {
+ printf ("Portions:\n");
+
+ for (const auto& rPortionItem : aHandler.mPortionItems)
+ {
+ printf ("-- Type: %s length: %" SAL_PRIdINT32 " text type: %d\n",
+ rPortionItem.msItemType.toUtf8().getStr(),
+ rPortionItem.mnLength,
+ sal_uInt16(rPortionItem.mnTextType));
+ }
+
+ // Text "The purpose of this report is to summarize the results of the existing bug in the LO suite"
+ // 91 chars
+ auto& rPortionItem = aHandler.mPortionItems[0];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(91), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::Text, rPortionItem.mnTextType);
+
+ // The input field here has more words ("One Two Three Four Five")
+ // and it should break after "Two".
+ // Input Field: "One Two" = 7 chars + 1 start input field hidden character = 8 chars
+ rPortionItem = aHandler.mPortionItems[1];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::InputField, rPortionItem.mnTextType);
+
+ rPortionItem = aHandler.mPortionItems[2];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::Hole, rPortionItem.mnTextType);
+
+ // NEW LINE
+ rPortionItem = aHandler.mPortionItems[3];
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), rPortionItem.msItemType);
+
+ // Input Field: "Three Four Five" = 16 chars + 1 end input field hidden character = 16 chars
+ rPortionItem = aHandler.mPortionItems[4];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::InputField, rPortionItem.mnTextType);
+
+ // Text "."
+ rPortionItem = aHandler.mPortionItems[5];
+ CPPUNIT_ASSERT_EQUAL(OUString("text"), rPortionItem.msItemType);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rPortionItem.mnLength);
+ CPPUNIT_ASSERT_EQUAL(PortionType::Text, rPortionItem.mnTextType);
+
+ // NEW LINE
+ rPortionItem = aHandler.mPortionItems[6];
+ CPPUNIT_ASSERT_EQUAL(OUString("line_break"), rPortionItem.msItemType);
+
+ rPortionItem = aHandler.mPortionItems[7];
+ CPPUNIT_ASSERT_EQUAL(OUString("finish"), rPortionItem.msItemType);
+ }
+#endif
+}
+
+void SwUiWriterTest::testTdf92648()
+{
+ SwDoc* pDoc = createDoc("tdf92648.docx");
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ // Make sure we have ten draw shapes.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage));
+ // and the text boxes haven't got zero height
+ sal_Int32 nCount = 0;
+ for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats())
+ {
+ if (!SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT))
+ continue;
+ SwFormatFrameSize aSize(pFormat->GetFrameSize());
+ CPPUNIT_ASSERT(aSize.GetHeight() != 0);
+ ++nCount;
+ }
+ // and we have had five of them.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), nCount);
+}
+
+void SwUiWriterTest::testTdf103978_backgroundTextShape()
+{
+ SwDoc* pDoc = createDoc("tdf103978_backgroundTextShape.docx");
+
+ // there is only one shape. It has an attached textbox
+ bool bShapeIsOpaque = getProperty<bool>(getShape(1), "Opaque");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Shape is in the foreground", false, bShapeIsOpaque );
+ sal_Int32 nCount = 0;
+ for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats())
+ {
+ if (!SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT))
+ continue;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Textbox syncs the shape's transparency", bShapeIsOpaque, pFormat->GetOpaque().GetValue() );
+ ++nCount;
+ }
+ //ensure that we don't skip the for loop without an error
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of TextBoxes", sal_Int32(1), nCount);
+}
+
+void SwUiWriterTest::testTdf96515()
+{
+ // Enable hide whitespace mode.
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
+ aViewOptions.SetHideWhitespaceMode(true);
+ pWrtShell->ApplyViewOptions(aViewOptions);
+ CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsWhitespaceHidden());
+
+ // Insert a new paragraph at the end of the document.
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(), uno::UNO_QUERY);
+ xParagraphAppend->finishParagraph(uno::Sequence<beans::PropertyValue>());
+ calcLayout();
+
+ // This was 2, a new page was created for the new paragraph.
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+}
+
+void SwUiWriterTest::testTdf96943()
+{
+ // Enable hide whitespace mode.
+ SwDoc* pDoc = createDoc("tdf96943.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
+ aViewOptions.SetHideWhitespaceMode(true);
+ pWrtShell->ApplyViewOptions(aViewOptions);
+
+ // Insert a new character at the end of the document.
+ pWrtShell->SttEndDoc(/*bStt=*/false);
+ pWrtShell->Insert("d");
+
+ // This was 2, a new page was created for the new layout line.
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+}
+
+void SwUiWriterTest::testTdf96536()
+{
+ // Enable hide whitespace mode.
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
+ aViewOptions.SetHideWhitespaceMode(true);
+ pWrtShell->ApplyViewOptions(aViewOptions);
+ CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsWhitespaceHidden());
+
+ // Insert a page break and go back to the first page.
+ pWrtShell->InsertPageBreak();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ calcLayout();
+ sal_Int32 nSingleParaPageHeight = parseDump("/root/page[1]/infos/bounds", "height").toInt32();
+ discardDumpedLayout();
+
+ // Insert a 2nd paragraph at the end of the first page, so the page height grows at least twice...
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(), uno::UNO_QUERY);
+ const uno::Reference< text::XTextRange > xInsertPos = getRun(getParagraph(1), 1);
+ xParagraphAppend->finishParagraphInsert(uno::Sequence<beans::PropertyValue>(), xInsertPos);
+ calcLayout();
+ CPPUNIT_ASSERT(parseDump("/root/page[1]/infos/bounds", "height").toInt32() >= 2 * nSingleParaPageHeight);
+ discardDumpedLayout();
+
+ // ... and then delete the 2nd paragraph, which shrinks the page to the previous size.
+ uno::Reference<lang::XComponent> xParagraph(getParagraph(2), uno::UNO_QUERY);
+ xParagraph->dispose();
+ calcLayout();
+ CPPUNIT_ASSERT_EQUAL(nSingleParaPageHeight, parseDump("/root/page[1]/infos/bounds", "height").toInt32());
+}
+
+void SwUiWriterTest::testTdf96479()
+{
+ // We want to verify the empty input text field in the bookmark
+ static const OUString emptyInputTextField =
+ OUStringChar(CH_TXT_ATR_INPUTFIELDSTART) + OUStringChar(CH_TXT_ATR_INPUTFIELDEND);
+
+ SwDoc* pDoc = createDoc();
+ SwXTextDocument *pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ // So we can clean up all references for reload
+ {
+ // Append bookmark
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ sw::mark::IMark *pMark =
+ rIDMA.makeMark(aPaM, "original",
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ CPPUNIT_ASSERT(!pMark->IsExpanded());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+
+ // Get helper objects
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+
+ // Create cursor from bookmark
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("original"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
+ uno::Reference<text::XTextCursor> xCursor = xRange->getText()->createTextCursorByRange(xRange);
+ CPPUNIT_ASSERT(xCursor->isCollapsed());
+
+ // Remove bookmark
+ xRange->getText()->removeTextContent(xTextContent);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getBookmarksCount());
+
+ // Insert replacement bookmark
+ uno::Reference<text::XTextContent> xBookmarkNew(xFactory->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xBookmarkName(xBookmarkNew, uno::UNO_QUERY);
+ xBookmarkName->setName("replacement");
+ CPPUNIT_ASSERT(xCursor->isCollapsed());
+ // Force bookmark expansion
+ xCursor->getText()->insertString(xCursor, ".", true);
+ xCursor->getText()->insertTextContent(xCursor, xBookmarkNew, true);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ auto mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+
+ // Create and insert input textfield with some content
+ uno::Reference<text::XTextField> xTextField(xFactory->createInstance("com.sun.star.text.TextField.Input"), uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> xCursorNew(xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(xBookmarkNew->getAnchor()));
+ CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
+ xCursorNew->getText()->insertTextContent(xCursorNew, xTextField, true);
+ xBookmarkNew = uno::Reference<text::XTextContent>(xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
+ xCursorNew = xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(xBookmarkNew->getAnchor());
+ CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
+
+ // Can't check the actual content of the text node via UNO
+ mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+ SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
+ // Check for the actual bug, which didn't include CH_TXT_ATR_INPUTFIELDEND in the bookmark
+ CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
+ }
+
+ {
+ // Save and load cycle
+ // Actually not needed, but the bug symptom of a missing bookmark
+ // occurred because a broken bookmark was saved and loading silently
+ // dropped the broken bookmark!
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+ loadURL(aTempFile.GetURL(), nullptr);
+ pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ pDoc = pTextDoc->GetDocShell()->GetDoc();
+
+ // Lookup "replacement" bookmark
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xBookmarksSupplier->getBookmarks()->hasByName("replacement"));
+
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
+ uno::Reference<text::XTextCursor> xCursor = xRange->getText()->createTextCursorByRange(xRange);
+ CPPUNIT_ASSERT(!xCursor->isCollapsed());
+
+ // Verify bookmark content via text node / PaM
+ auto mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+ SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
+ CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
+ }
+}
+
+// If you resave original document the bookmark will be changed from
+//
+// <text:p text:style-name="Standard">
+// <text:bookmark-start text:name="test"/>
+// <text:bookmark-end text:name="test"/>
+// def
+// </text:p>
+//
+// to
+//
+// <text:p text:style-name="Standard">
+// <text:bookmark text:name="test"/>
+// def
+// </text:p>
+//
+void SwUiWriterTest::testBookmarkCollapsed()
+{
+ // load document
+ SwDoc* pDoc = createDoc("collapsed_bookmark.odt");
+ CPPUNIT_ASSERT(pDoc);
+
+ // save original document
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+
+ // load only content.xml from the resaved document
+ if (xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(), "content.xml"))
+ {
+ const OString aPath("/office:document-content/office:body/office:text/text:p");
+
+ const int pos1 = getXPathPosition(pXmlDoc, aPath, "bookmark");
+ CPPUNIT_ASSERT_EQUAL(0, pos1); // found, and it is first
+
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
+ }
+}
+
+// 1. Open a new writer document
+// 2. Enter the text "abcdef"
+// 3. Select "abc"
+// 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
+// 5. Open the navigator (F5)
+// Select the bookmark "test" using the navigator.
+// 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
+// 7. Save the document:
+// <text:p text:style-name="Standard">
+// <text:bookmark-start text:name="test"/>
+// <text:bookmark-end text:name="test"/>
+// def
+// </text:p>
+//
+void SwUiWriterTest::testRemoveBookmarkText()
+{
+ // create document
+ {
+ // create a text document with "abcdef"
+ SwDoc* pDoc = createDoc();
+ SwXTextDocument *pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, "abcdef");
+ }
+
+ // mark "abc" with "testBookmark" bookmark
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ lcl_selectCharacters(aPaM, 0, 3);
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ sw::mark::IMark *pMark =
+ rIDMA.makeMark(aPaM, "testBookmark",
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+
+ // verify
+ CPPUNIT_ASSERT(pMark->IsExpanded());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+
+ // remove text marked with bookmark
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ lcl_selectCharacters(aPaM, 0, 3);
+ pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
+
+ // verify: bookmark is still exist
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+ }
+
+ // save document
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+
+ // load only content.xml from the resaved document
+ if (xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(), "content.xml"))
+ {
+ const OString aPath("/office:document-content/office:body/office:text/text:p");
+
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark")); // not found
+ const int pos2 = getXPathPosition(pXmlDoc, aPath, "bookmark-start");
+ const int pos3 = getXPathPosition(pXmlDoc, aPath, "bookmark-end");
+
+ CPPUNIT_ASSERT_EQUAL(0, pos2); // found, and it is first
+ CPPUNIT_ASSERT_EQUAL(1, pos3); // found, and it is second
+ }
+}
+
+// 1. Open a new writer document
+// 2. Enter the text "abcdef"
+// 3. Select "abc"
+// 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test".
+// 5. Open the navigator (F5)
+// Select the bookmark "test" using the navigator.
+// 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
+// 7. Call our macro
+//
+// Sub Main
+// bookmark = ThisComponent.getBookmarks().getByName("test")
+// bookmark.getAnchor().setString("abc")
+// End Sub
+//
+// The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
+// 7. Save the document:
+// <text:p text:style-name="Standard">
+// <text:bookmark-start text:name="test"/>
+// abc
+// <text:bookmark-end text:name="test"/>
+// def
+// </text:p>
+//
+void SwUiWriterTest::testRemoveBookmarkTextAndAddNew()
+{
+ // create document
+ {
+ // create a text document with "abcdef"
+ SwDoc* pDoc = createDoc();
+ SwXTextDocument *pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, "abcdef");
+ }
+
+ // mark "abc" with "testBookmark" bookmark
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ lcl_selectCharacters(aPaM, 0, 3);
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ sw::mark::IMark *pMark =
+ rIDMA.makeMark(aPaM, "testBookmark",
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+
+ // verify
+ CPPUNIT_ASSERT(pMark->IsExpanded());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+
+ // remove text marked with bookmark
+ {
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ lcl_selectCharacters(aPaM, 0, 3);
+ pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
+
+ // verify: bookmark is still exist
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+
+ // write "abc" to area marked with "testBookmark" bookmark
+ {
+ // Get helper objects
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+
+ // Create cursor from bookmark
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("testBookmark"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xRange->getString());
+
+ // write "abc"
+ xRange->setString("abc");
+
+ // verify: bookmark is still exist
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+ }
+
+ // save document
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+
+ // load only content.xml from the resaved document
+ if (xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(), "content.xml"))
+ {
+ const OString aPath("/office:document-content/office:body/office:text/text:p");
+
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark")); // not found
+ const int pos2 = getXPathPosition(pXmlDoc, aPath, "bookmark-start");
+ const int pos3 = getXPathPosition(pXmlDoc, aPath, "text");
+ const int pos4 = getXPathPosition(pXmlDoc, aPath, "bookmark-end");
+
+ CPPUNIT_ASSERT_EQUAL(0, pos2);
+ CPPUNIT_ASSERT_EQUAL(1, pos3);
+ CPPUNIT_ASSERT_EQUAL(2, pos4);
+ }
+}
+
+// 1. Load document:
+// <text:p text:style-name="Standard">
+// <text:bookmark-start text:name="test"/>
+// <text:bookmark-end text:name="test"/>
+// def
+// </text:p>
+//
+// 2. Call our macro
+//
+// Sub Main
+// bookmark = ThisComponent.getBookmarks().getByName("test")
+// bookmark.getAnchor().setString("abc")
+// End Sub
+//
+// The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef".
+// 3. Save the document:
+// <text:p text:style-name="Standard">
+// <text:bookmark text:name="test"/>
+// abcdef
+// </text:p>
+//
+void SwUiWriterTest::testRemoveBookmarkTextAndAddNewAfterReload()
+{
+ // load document
+ SwDoc* pDoc = createDoc("collapsed_bookmark.odt");
+ CPPUNIT_ASSERT(pDoc);
+
+ // write "abc" to area marked with "testBookmark" bookmark
+ {
+ // Get helper objects
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+
+ // Create cursor from bookmark
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("test"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xRange->getString());
+
+ // write "abc"
+ xRange->setString("abc");
+
+ // verify: bookmark is still exist
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ }
+
+ // save original document
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+
+ // load only content.xml from the resaved document
+ if (xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(), "content.xml"))
+ {
+ const OString aPath("/office:document-content/office:body/office:text/text:p");
+
+ const int pos1 = getXPathPosition(pXmlDoc, aPath, "bookmark");
+ const int pos2 = getXPathPosition(pXmlDoc, aPath, "text");
+
+ CPPUNIT_ASSERT_EQUAL(0, pos1);
+ CPPUNIT_ASSERT_EQUAL(1, pos2);
+
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
+ CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
+ }
+}
+
+void SwUiWriterTest::testTdf96961()
+{
+ // Insert a page break.
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->InsertPageBreak();
+
+ // Enable hide whitespace mode.
+ SwViewOption aViewOptions(*pWrtShell->GetViewOptions());
+ aViewOptions.SetHideWhitespaceMode(true);
+ pWrtShell->ApplyViewOptions(aViewOptions);
+
+ calcLayout();
+
+ // Assert that the height of the last page is larger than the height of other pages.
+ sal_Int32 nOther = parseDump("/root/page[1]/infos/bounds", "height").toInt32();
+ sal_Int32 nLast = parseDump("/root/page[2]/infos/bounds", "height").toInt32();
+ CPPUNIT_ASSERT(nLast > nOther);
+}
+
+void SwUiWriterTest::testTdf88453()
+{
+ createDoc("tdf88453.odt");
+ calcLayout();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // This was 0: the table does not fit the first page, but it wasn't split
+ // to continue on the second page.
+ assertXPath(pXmlDoc, "/root/page[2]/body/tab", 1);
+}
+
+void SwUiWriterTest::testTdf88453Table()
+{
+ createDoc("tdf88453-table.odt");
+ calcLayout();
+ // This was 2: layout could not split the large outer table in the document
+ // into 3 pages.
+ CPPUNIT_ASSERT_EQUAL(3, getPages());
+}
+
+namespace
+{
+
+int checkShells(const SwDocShell* pSource, const SwDocShell* pDestination)
+{
+ return int(SfxClassificationHelper::CheckPaste(pSource->getDocProperties(), pDestination->getDocProperties()));
+}
+
+}
+
+void SwUiWriterTest::testClassificationPaste()
+{
+ SwDocShell* pSourceShell = createDoc()->GetDocShell();
+ uno::Reference<lang::XComponent> xSourceComponent = mxComponent;
+ mxComponent.clear();
+
+ SwDocShell* pDestinationShell = createDoc()->GetDocShell();
+
+ // Not classified source, not classified destination.
+ CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None), checkShells(pSourceShell, pDestinationShell));
+
+ // Classified source, not classified destination.
+ uno::Sequence<beans::PropertyValue> aInternalOnly = comphelper::InitPropertySequence({{"Name", uno::makeAny(OUString("Internal Only"))}});
+ dispatchCommand(xSourceComponent, ".uno:ClassificationApply", aInternalOnly);
+ CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::TargetDocNotClassified), checkShells(pSourceShell, pDestinationShell));
+
+ // Classified source and classified destination -- internal only has a higher level than confidential.
+ uno::Sequence<beans::PropertyValue> aConfidential = comphelper::InitPropertySequence({{"Name", uno::makeAny(OUString("Confidential"))}});
+ dispatchCommand(mxComponent, ".uno:ClassificationApply", aConfidential);
+ CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow), checkShells(pSourceShell, pDestinationShell));
+
+ xSourceComponent->dispose();
+}
+
+void SwUiWriterTest::testSmallCaps()
+{
+ // Create a document, add some characters and select them.
+ createDoc();
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ pWrtShell->Insert("text");
+ pWrtShell->SelAll();
+
+ // Dispatch the command to make them formatted small capitals.
+ dispatchCommand(mxComponent, ".uno:SmallCaps", {});
+
+ // This was css::style::CaseMap::NONE as the shell didn't handle the command.
+ CPPUNIT_ASSERT_EQUAL(css::style::CaseMap::SMALLCAPS, getProperty<sal_Int16>(getRun(getParagraph(1), 1), "CharCaseMap"));
+}
+
+void SwUiWriterTest::testTdf98987()
+{
+ createDoc("tdf98987.docx");
+ calcLayout();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/SdrObject", "name", "Rectangle 1");
+ sal_Int32 nRectangle1 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[2]/bounds", "top").toInt32();
+ assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name", "Rectangle 2");
+ sal_Int32 nRectangle2 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top").toInt32();
+ CPPUNIT_ASSERT_GREATER(nRectangle1, nRectangle2);
+
+ assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/SdrObject", "name", "Rectangle 3");
+ sal_Int32 nRectangle3 = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/bounds", "top").toInt32();
+ // This failed: the 3rd rectangle had a smaller "top" value than the 2nd one, it even overlapped with the 1st one.
+ CPPUNIT_ASSERT_GREATER(nRectangle2, nRectangle3);
+}
+
+void SwUiWriterTest::testTdf99004()
+{
+ createDoc("tdf99004.docx");
+ calcLayout();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_Int32 nTextbox1Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "top").toInt32();
+ sal_Int32 nTextBox1Height = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32();
+ sal_Int32 nTextBox1Bottom = nTextbox1Top + nTextBox1Height;
+
+ assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name", "Rectangle 2");
+ sal_Int32 nRectangle2Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top").toInt32();
+ // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
+ CPPUNIT_ASSERT(nTextBox1Bottom < nRectangle2Top);
+}
+
+void SwUiWriterTest::testTdf84695()
+{
+ SwDoc* pDoc = createDoc("tdf84695.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);
+
+ // Now Enter + a key should add some text.
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'a', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
+ // This was empty, Enter did not start the fly frame edit mode.
+ CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape->getString());
+}
+
+void SwUiWriterTest::testTdf84695NormalChar()
+{
+ SwDoc* pDoc = createDoc("tdf84695.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);
+
+ // Now pressing 'a' should add a character.
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'a', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
+ // This was empty, pressing a normal character did not start the fly frame edit mode.
+ CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape->getString());
+}
+
+void SwUiWriterTest::testTdf84695Tab()
+{
+ SwDoc* pDoc = createDoc("tdf84695-tab.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ SdrObject* pObject = pPage->GetObj(0);
+ SwContact* pShape = static_cast<SwContact*>(pObject->GetUserCall());
+ // First, make sure that pShape is a draw shape.
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_DRAWFRMFMT), pShape->GetFormat()->Which());
+
+ // Then select it.
+ pWrtShell->SelectObj(Point(), 0, pObject);
+
+ // Now pressing 'tab' should jump to the other shape.
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
+ Scheduler::ProcessEventsToIdle();
+
+ // And finally make sure the selection has changed.
+ const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
+ SwContact* pOtherShape = static_cast<SwContact*>(rMarkList.GetMark(0)->GetMarkedSdrObj()->GetUserCall());
+ // This failed, 'tab' didn't do anything -> the selected shape was the same.
+ CPPUNIT_ASSERT(pOtherShape != pShape);
+}
+
+void SwUiWriterTest::testTableStyleUndo()
+{
+ SwDoc* pDoc = createDoc();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+
+ sal_Int32 nStyleCount = pDoc->GetTableStyles().size();
+ SwTableAutoFormat* pStyle = pDoc->MakeTableStyle("Test Style");
+ SvxBrushItem aBackground(Color(0xFF00FF), RES_BACKGROUND );
+ pStyle->GetBoxFormat(0).SetBackground(aBackground);
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
+ // check if attributes are preserved
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
+
+ pDoc->DelTableStyle("Test Style");
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ // check if attributes are preserved
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
+
+ // undo delete so we can replace the style
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount +1 );
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
+
+ SwTableAutoFormat aNewStyle("Test Style2");
+ SvxBrushItem aBackground2(Color(0x00FF00), RES_BACKGROUND);
+ aNewStyle.GetBoxFormat(0).SetBackground(aBackground2);
+
+ pDoc->ChgTableStyle("Test Style", aNewStyle);
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground2));
+ rUndoManager.Undo();
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground));
+ rUndoManager.Redo();
+ pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
+ CPPUNIT_ASSERT(pStyle);
+ CPPUNIT_ASSERT(bool(pStyle->GetBoxFormat(0).GetBackground() == aBackground2));
+}
+
+void SwUiWriterTest::testRedlineCopyPaste()
+{
+ // regressed in tdf#106746
+ SwDoc* pDoc = createDoc();
+
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ pDoc->getIDocumentContentOperations().InsertString(aPaM, "abzdezgh");
+ SwTextNode* pTextNode = aPaM.GetNode().GetTextNode();
+
+ // Turn on track changes, make changes, turn off track changes
+ uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true));
+ lcl_selectCharacters(aPaM, 2, 3);
+ pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "c", false);
+ lcl_selectCharacters(aPaM, 6, 7);
+ pDoc->getIDocumentContentOperations().ReplaceRange(aPaM, "f", false);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(false));
+
+ // Create the clipboard document.
+ SwDoc aClipboard;
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ // Select the whole content, copy, delete the original and paste the copied content
+ pWrtShell->SelAll();
+ pWrtShell->Copy(&aClipboard);
+ pWrtShell->Delete();
+ pWrtShell->Paste(&aClipboard);
+
+ // With the bug this is "abzcdefgh", ie. contains the first deleted piece, too
+ CPPUNIT_ASSERT_EQUAL(OUString("abcdefgh"), pTextNode->GetText());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf134436)
+{
+ load(DATA_DIRECTORY, "tdf134436.fodt");
+
+ SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ SwDoc * pDoc = pXTextDocument->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell * pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
+
+ // select all 3 times, table at the start
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ // the stupid SwXTextView::getString doesn't work "for symmetry" so use CursorShell
+ CPPUNIT_ASSERT_EQUAL(OUString("a\nb\n"), pWrtShell->GetCursor()->GetText());
+
+ // first, the section doesn't get deleted
+ dispatchCommand(mxComponent, ".uno:Delete", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), pWrtShell->GetCursor()->GetText());
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("a\nb\n"), pWrtShell->GetCursor()->GetText());
+
+ // second, the section does get deleted because point is at the end
+ dispatchCommand(mxComponent, ".uno:Delete", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), pWrtShell->GetCursor()->GetText());
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("a\nb\n"), pWrtShell->GetCursor()->GetText());
+
+ // the problem was that the section was not deleted on Redo
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), pWrtShell->GetCursor()->GetText());
+
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString("a\nb\n"), pWrtShell->GetCursor()->GetText());
+
+ dispatchCommand(mxComponent, ".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(OUString(""), pWrtShell->GetCursor()->GetText());
+}
+
+void SwUiWriterTest::testRedlineParam()
+{
+ // Create a document with minimal content.
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ pWrtShell->Insert("middle");
+
+ // Turn on track changes, and add changes to the start and end of the document.
+ uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true));
+ pWrtShell->StartOfSection();
+ pWrtShell->Insert("aaa");
+ pWrtShell->EndOfSection();
+ pWrtShell->Insert("zzz");
+
+ const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size());
+
+ // Select the first redline.
+ pWrtShell->StartOfSection();
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"NextTrackedChange", uno::makeAny(static_cast<sal_uInt16>(rTable[0]->GetId()))}
+ }));
+ dispatchCommand(mxComponent, ".uno:NextTrackedChange", aPropertyValues);
+ Scheduler::ProcessEventsToIdle();
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+ // This failed: the parameter wasn't handled so the next change (zzz) was
+ // selected, not the first one (aaa).
+ CPPUNIT_ASSERT_EQUAL(OUString("aaa"), pShellCursor->GetText());
+
+ // Select the second redline.
+ pWrtShell->StartOfSection();
+ aPropertyValues = comphelper::InitPropertySequence(
+ {
+ {"NextTrackedChange", uno::makeAny(static_cast<sal_uInt16>(rTable[1]->GetId()))}
+ });
+ dispatchCommand(mxComponent, ".uno:NextTrackedChange", aPropertyValues);
+ Scheduler::ProcessEventsToIdle();
+ pShellCursor = pWrtShell->getShellCursor(false);
+ CPPUNIT_ASSERT_EQUAL(OUString("zzz"), pShellCursor->GetText());
+
+ // Move the cursor to the start again, and reject the second change.
+ pWrtShell->StartOfSection();
+ aPropertyValues = comphelper::InitPropertySequence(
+ {
+ {"RejectTrackedChange", uno::makeAny(static_cast<sal_uInt16>(rTable[1]->GetId()))}
+ });
+ dispatchCommand(mxComponent, ".uno:RejectTrackedChange", aPropertyValues);
+ Scheduler::ProcessEventsToIdle();
+ pShellCursor = pWrtShell->getShellCursor(false);
+
+ // This was 'middlezzz', the uno command rejected the redline under the
+ // cursor, instead of the requested one.
+ CPPUNIT_ASSERT_EQUAL(OUString("aaamiddle"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText());
+}
+
+void SwUiWriterTest::testRedlineViewAuthor()
+{
+ // Test that setting an author at an SwView level has effect.
+
+ // Create a document with minimal content.
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ pWrtShell->Insert("middle");
+ SwView* pView = pDocShell->GetView();
+ const OUString aAuthor("A U. Thor");
+ pView->SetRedlineAuthor(aAuthor);
+ pDocShell->SetView(pView);
+
+ // Turn on track changes, and add changes to the start of the document.
+ uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true));
+ pWrtShell->StartOfSection();
+ pWrtShell->Insert("aaa");
+
+ // Now assert that SwView::SetRedlineAuthor() had an effect.
+ const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
+ SwRangeRedline* pRedline = rTable[0];
+ // This was 'Unknown Author' instead of 'A U. Thor'.
+ CPPUNIT_ASSERT_EQUAL(aAuthor, pRedline->GetAuthorString());
+
+ // Insert a comment and assert that SwView::SetRedlineAuthor() affects this as well.
+ dispatchCommand(mxComponent, ".uno:.uno:InsertAnnotation", {});
+ 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<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY);
+ // This was 'Unknown Author' instead of 'A U. Thor'.
+ CPPUNIT_ASSERT_EQUAL(aAuthor, xField->getPropertyValue("Author").get<OUString>());
+
+ //Reset the redline author after using it, otherwise, it might interfere with other unittests
+ pView->SetRedlineAuthor("Unknown Author");
+ pDocShell->SetView(pView);
+}
+
+void SwUiWriterTest::testTdf91292()
+{
+ createDoc("tdf91292_paraBackground.docx");
+ uno::Reference<beans::XPropertySet> xPropertySet(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Solid background color", drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xPropertySet, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Background Color", static_cast<sal_Int32>(0x5C2D91), getProperty<sal_Int32>(xPropertySet, "FillColor"));
+
+ // remove background color
+ xPropertySet->setPropertyValue("FillStyle", uno::makeAny( drawing::FillStyle_NONE));
+
+ // Save it and load it back.
+ reload("Office Open XML Text", "tdf91292_paraBackground.docx");
+
+ xPropertySet.set( getParagraph(1), uno::UNO_QUERY );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("No background color", drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xPropertySet, "FillStyle"));
+}
+
+void SwUiWriterTest::testTdf78727()
+{
+ SwDoc* pDoc = createDoc("tdf78727.docx");
+ SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ // This was 1: make sure we don't loose the TextBox anchored inside the
+ // table that is moved inside a text frame.
+ CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage) > 1);
+}
+
+void SwUiWriterTest::testRedlineTimestamp()
+{
+ // Test that a redline timestamp's second is not always 0.
+
+ // Create a document with minimal content.
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ pWrtShell->Insert("middle");
+
+ // Turn on track changes, and add changes to the start and to the end of
+ // the document.
+ uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true));
+ pWrtShell->StartOfSection();
+ pWrtShell->Insert("aaa");
+ osl::Thread::wait(std::chrono::seconds(1));
+ pWrtShell->EndOfSection();
+ pWrtShell->Insert("zzz");
+
+ // Inserting additional characters at the start changed the table size to
+ // 3, i.e. the first and the second "aaa" wasn't combined.
+ pWrtShell->StartOfSection();
+ pWrtShell->Insert("aaa");
+
+ // Now assert that at least one of the seconds are not 0.
+ const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ if (rTable.size() >= 2 && rTable[0]->GetRedlineData().GetTimeStamp().GetMin() != rTable[1]->GetRedlineData().GetTimeStamp().GetMin())
+ // The relatively rare case when waiting for a second also changes the minute.
+ return;
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size());
+ sal_uInt16 nSec1 = rTable[0]->GetRedlineData().GetTimeStamp().GetSec();
+ sal_uInt16 nSec2 = rTable[1]->GetRedlineData().GetTimeStamp().GetSec();
+ // This failed, seconds was always 0.
+ CPPUNIT_ASSERT(nSec1 != 0 || nSec2 != 0);
+}
+
+void SwUiWriterTest::testCursorWindows()
+{
+ // Create a new document with one window.
+ SwDoc* pDoc = createDoc();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell1 = pDocShell->GetWrtShell();
+
+ // Create a second view and type something.
+ pDocShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_NEWWINDOW, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
+ SwWrtShell* pWrtShell2 = pDocShell->GetWrtShell();
+ OUString aText("foo");
+ pWrtShell2->Insert(aText);
+
+ // Assert that only the cursor of the actual window move, not other cursors.
+ SwShellCursor* pShellCursor1 = pWrtShell1->getShellCursor(false);
+ SwShellCursor* pShellCursor2 = pWrtShell2->getShellCursor(false);
+ // This was 3, not 0 -- cursor of the other window moved.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), pShellCursor1->Start()->nContent.GetIndex());
+ CPPUNIT_ASSERT_EQUAL(aText.getLength(), pShellCursor2->Start()->nContent.GetIndex());
+}
+
+void SwUiWriterTest::testLandscape()
+{
+ // Set page orientation to landscape.
+ SwDoc* pDoc = createDoc();
+ uno::Sequence<beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence({
+ { "AttributePage.Landscape", uno::Any(true) }
+ }));
+ dispatchCommand(mxComponent, ".uno:AttributePage", aPropertyValues);
+ Scheduler::ProcessEventsToIdle();
+
+ // Assert that the document model was modified.
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ size_t nPageDesc = pWrtShell->GetCurPageDesc();
+ // This failed, page was still portrait.
+ CPPUNIT_ASSERT(pWrtShell->GetPageDesc(nPageDesc).GetLandscape());
+}
+
+void SwUiWriterTest::testTdf95699()
+{
+ // Open the document with single FORMCHECKBOX field, select all and copy to clipboard
+ // then check that clipboard contains the FORMCHECKBOX in text body.
+ // Previously that failed.
+ SwDoc* pDoc = createDoc("tdf95699.odt");
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ SwDoc aClipboard;
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->SelAll();
+ pWrtShell->Copy(&aClipboard);
+ pMarkAccess = aClipboard.getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ ::sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkAfter(SwPosition(pDoc->GetNodes().GetEndOfExtras()));
+ CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"), pFieldMark->GetFieldname());
+}
+
+void SwUiWriterTest::testTdf104032()
+{
+ // Open the document with FORMCHECKBOX field, select it and copy to clipboard
+ // Go to end of document and paste it, then undo
+ // Previously that asserted in debug build.
+ SwDoc* pDoc = createDoc("tdf104032.odt");
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ SwDoc aClipboard;
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->StartOfSection();
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+ pWrtShell->Copy(&aClipboard);
+ pWrtShell->EndOfSection();
+ pWrtShell->Paste(&aClipboard);
+ rUndoManager.Undo();
+}
+
+void SwUiWriterTest::testTdf104440()
+{
+ createDoc("tdf104440.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "//page[2]/body/txt/anchored");
+ xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+ // This was 0: both Text Frames in the document were anchored to a
+ // paragraph on page 1, while we expect that the second Text Frame is
+ // anchored to a paragraph on page 2.
+ CPPUNIT_ASSERT_EQUAL(1, xmlXPathNodeSetGetLength(pXmlNodes));
+ xmlXPathFreeObject(pXmlObj);
+}
+
+void SwUiWriterTest::testTdf104425()
+{
+ createDoc("tdf104425.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // The document contains one top-level 1-cell table with minimum row height set to 70 cm,
+ // and the cell contents does not exceed the minimum row height.
+ // It should span over 3 pages.
+ assertXPath(pXmlDoc, "//page", 3);
+ sal_Int32 nHeight1 = getXPath(pXmlDoc, "//page[1]/body/tab/row/infos/bounds", "height").toInt32();
+ sal_Int32 nHeight2 = getXPath(pXmlDoc, "//page[2]/body/tab/row/infos/bounds", "height").toInt32();
+ sal_Int32 nHeight3 = getXPath(pXmlDoc, "//page[3]/body/tab/row/infos/bounds", "height").toInt32();
+ double fSumHeight_mm = (nHeight1 + nHeight2 + nHeight3) * 25.4 / 1440.0;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(700.0, fSumHeight_mm, 0.05);
+}
+
+// accepting change tracking gets stuck on change
+void SwUiWriterTest::testTdf104814()
+{
+ SwDoc* const pDoc1(createDoc("tdf104814.docx"));
+
+ SwEditShell* const pEditShell(pDoc1->GetEditShell());
+
+ // accept all redlines
+ while(pEditShell->GetRedlineCount())
+ pEditShell->AcceptRedline(0);
+}
+
+void SwUiWriterTest::testTdf66405()
+{
+ // Imported formula should have zero margins
+ createDoc("tdf66405.docx");
+ uno::Reference<text::XTextEmbeddedObjectsSupplier> xEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xEmbeddedObjects = xEmbeddedObjectsSupplier->getEmbeddedObjects();
+ uno::Reference<beans::XPropertySet> xFormula;
+ xEmbeddedObjects->getByName(xEmbeddedObjects->getElementNames()[0]) >>= xFormula;
+ uno::Reference<beans::XPropertySet> xComponent;
+ xFormula->getPropertyValue("Component") >>= xComponent;
+
+ // Test embedded object's margins
+ sal_Int32 nLeftMargin, nRightMargin, nTopMargin, nBottomMargin;
+ xFormula->getPropertyValue("LeftMargin") >>= nLeftMargin;
+ xFormula->getPropertyValue("RightMargin") >>= nRightMargin;
+ xFormula->getPropertyValue("TopMargin") >>= nTopMargin;
+ xFormula->getPropertyValue("BottomMargin") >>= nBottomMargin;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin);
+
+ // Test embedded object component's margins
+ xComponent->getPropertyValue("LeftMargin") >>= nLeftMargin;
+ xComponent->getPropertyValue("RightMargin") >>= nRightMargin;
+ xComponent->getPropertyValue("TopMargin") >>= nTopMargin;
+ xComponent->getPropertyValue("BottomMargin") >>= nBottomMargin;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRightMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nTopMargin);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nBottomMargin);
+}
+
+void SwUiWriterTest::testTdf35021_tabOverMarginDemo()
+{
+#if HAVE_MORE_FONTS
+ createDoc("tdf35021_tabOverMarginDemo.doc");
+ calcLayout();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // Tabs should go past the margin @ ~3381
+ sal_Int32 nMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32();
+ // left tab was 3381 because it got its own full line
+ sal_Int32 nWidth = getXPath(pXmlDoc, "//Text[@nType='PortionType::TabLeft']", "nWidth").toInt32();
+ CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~4479", nMargin < nWidth);
+ // center tab was 842
+ nWidth = getXPath(pXmlDoc, "//Text[@nType='PortionType::TabCenter']", "nWidth").toInt32();
+ CPPUNIT_ASSERT_MESSAGE("Center Tab width is ~3521", nMargin < nWidth);
+ // right tab was probably the same as center tab.
+ nWidth = getXPath(pXmlDoc, "//Text[@nType='PortionType::TabRight']", "nWidth").toInt32();
+ CPPUNIT_ASSERT_MESSAGE("Right Tab width is ~2907", sal_Int32(2500) < nWidth);
+ // decimal tab was 266
+ nWidth = getXPath(pXmlDoc, "//Text[@nType='PortionType::TabDecimal']", "nWidth").toInt32();
+ CPPUNIT_ASSERT_MESSAGE("Decimal Tab width is ~4096", nMargin < nWidth);
+#endif
+}
+
+void SwUiWriterTest::testTdf106701_tabOverMarginAutotab()
+{
+ createDoc("tdf106701_tabOverMarginAutotab.doc");
+ calcLayout();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // The right margin is ~3378
+ sal_Int32 nRightMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32();
+ // Automatic tabstops should never be affected by tabOverMargin compatibility
+ // The 1st line's width previously was ~9506
+ sal_Int32 nWidth = getXPath(pXmlDoc, "//LineBreak[1]", "nWidth").toInt32();
+ CPPUNIT_ASSERT_MESSAGE("1st line's width is less than the right margin", nWidth < nRightMargin);
+}
+
+void SwUiWriterTest::testTdf104492()
+{
+ createDoc("tdf104492.docx");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // The document should split table over 3 pages.
+ assertXPath(pXmlDoc, "//page", 3);
+}
+
+void SwUiWriterTest::testTdf107025()
+{
+ // Tdf107025 - characters advance with wrong distance, so that
+ // they are cluttered because of negative value or
+ // break into multiple lines because of overflow.
+ // The test document uses DFKAI-SB shipped with Windows.
+ createDoc("tdf107025.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // Verify the number of characters in each line.
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(1), getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[1]", "nLength").toInt32());
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(9), getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[2]", "nLength").toInt32());
+
+ // Do the subsequent test only if the first line can be displayed,
+ // in case that the required font does not exist.
+ sal_Int32 nWidth1 = getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[1]", "nWidth").toInt32();
+ if (!nWidth1)
+ return;
+
+ CPPUNIT_ASSERT(!parseDump("(//Text[@nType='PortionType::Text'])[2]", "nWidth").isEmpty());
+ // Width of the second line is expected to be 9 times of the first.
+ sal_Int32 nWidth2 = getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[2]", "nWidth").toInt32();
+
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(9), nWidth2 / nWidth1 );
+}
+
+void SwUiWriterTest::testTdf107362()
+{
+ createDoc("tdf107362.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_Int32 nHeight = getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[1]" , "nHeight").toInt32();
+ sal_Int32 nWidth1 = getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[1]" , "nWidth").toInt32();
+ sal_Int32 nWidth2 = getXPath(pXmlDoc, "(//Text[@nType='PortionType::Text'])[2]" , "nWidth").toInt32();
+ sal_Int32 nLineWidth = getXPath(pXmlDoc, "//LineBreak" , "nWidth").toInt32();
+ sal_Int32 nKernWidth = nLineWidth - nWidth1 - nWidth2;
+ // Test only if fonts are available
+ if ( nWidth1 > 500 && nWidth2 > 200 )
+ {
+ // Kern width should be smaller than 1/3 of the CJK font height.
+ CPPUNIT_ASSERT( nKernWidth * 3 < nHeight );
+ }
+}
+
+void SwUiWriterTest::testTdf105417()
+{
+ SwDoc* pDoc = createDoc("tdf105417.odt");
+ CPPUNIT_ASSERT(pDoc);
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ CPPUNIT_ASSERT(pView);
+ uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
+ CPPUNIT_ASSERT(xHyphenator.is());
+ // If there are no English hyphenation rules installed, we can't test
+ // hyphenation.
+ if (!xHyphenator->hasLocale(lang::Locale("en", "US", OUString())))
+ return;
+
+ uno::Reference<linguistic2::XLinguProperties> xLinguProperties(LinguMgr::GetLinguPropertySet());
+ // Automatic hyphenation means not opening a dialog, but going ahead
+ // non-interactively.
+ xLinguProperties->setIsHyphAuto(true);
+ SwHyphWrapper aWrap(pView, xHyphenator, /*bStart=*/false, /*bOther=*/true, /*bSelection=*/false);
+ // This never returned, it kept trying to hyphenate the last word
+ // (greenbacks) again and again.
+ aWrap.SpellDocument();
+}
+
+void SwUiWriterTest::testTdf105625()
+{
+ SwDoc* pDoc = createDoc("tdf105625.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ // Ensure correct initial setting
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext,
+ "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
+ css::uno::Any(false), comphelper::EConfigurationModes::Standard);
+ // We should be able to edit at positions adjacent to fields.
+ // Check if the start and the end of the 1st paragraph are not protected
+ // (they are adjacent to FORMCHECKBOX)
+ pWrtShell->SttPara();
+ CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
+ pWrtShell->EndPara();
+ CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
+ // 2nd paragraph - FORMTEXT
+ pWrtShell->Down(/*bSelect=*/false);
+ // Check selection across FORMTEXT field boundary - must be read-only
+ pWrtShell->SttPara();
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+ CPPUNIT_ASSERT_EQUAL(true, pWrtShell->HasReadonlySel());
+ // Test deletion of whole field with single backspace
+ // Previously it only removed right boundary of FORMTEXT, or failed removal at all
+ const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
+ sal_Int32 nMarksBefore = pMarksAccess->getAllMarksCount();
+ pWrtShell->EndPara();
+ pWrtShell->DelLeft();
+ sal_Int32 nMarksAfter = pMarksAccess->getAllMarksCount();
+ CPPUNIT_ASSERT_EQUAL(nMarksBefore, nMarksAfter + 1);
+}
+
+void SwUiWriterTest::testTdf125151_protected()
+{
+ // Similar to testTdf105625 except this is in a protected section,
+ // so read-only is already true when fieldmarks are considered.
+ SwDoc* pDoc = createDoc("tdf125151_protected.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ // Ensure correct initial setting
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext,
+ "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
+ css::uno::Any(false), comphelper::EConfigurationModes::Standard);
+ pWrtShell->Down(/*bSelect=*/false);
+ // The cursor moved inside of the FieldMark textbox.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel());
+ // Move left to the start/definition of the textbox
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
+}
+
+void SwUiWriterTest::testTdf125151_protectedB()
+{
+ // Similar to testTdf105625 except this is protected with the Protect_Form compat setting
+ SwDoc* pDoc = createDoc("tdf125151_protectedB.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ // Ensure correct initial setting
+ comphelper::ConfigurationHelper::writeDirectKey(xComponentContext,
+ "org.openoffice.Office.Writer/", "Cursor/Option", "IgnoreProtectedArea",
+ css::uno::Any(false), comphelper::EConfigurationModes::Standard);
+ // The cursor starts inside of the FieldMark textbox.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel());
+ // Move left to the start/definition of the textbox
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
+}
+
+void SwUiWriterTest::testTdf106736()
+{
+ createDoc("tdf106736-grid.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_Int32 nWidth = getXPath(pXmlDoc, "(//Text[@nType='PortionType::TabLeft'])[1]", "nWidth").toInt32();
+ // In tdf106736, width of tab overflow so that it got
+ // width value around 9200, expected value is around 103
+ CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~103", nWidth < 150);
+}
+
+void SwUiWriterTest::testMsWordCompTrailingBlanks()
+{
+ // The option is true in settings.xml
+ SwDoc* pDoc = createDoc( "MsWordCompTrailingBlanksTrue.odt" );
+ CPPUNIT_ASSERT_EQUAL( true, pDoc->getIDocumentSettingAccess().get( DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS ) );
+ calcLayout();
+ // Check that trailing spaces spans have no width if option is enabled
+
+ CPPUNIT_ASSERT_EQUAL( OUString(), parseDump( "/root/page/body/txt[2]/Text[4]", "nWidth" ) );
+ CPPUNIT_ASSERT_EQUAL( OUString(), parseDump( "/root/page/body/txt[2]/Text[5]", "nWidth" ) );
+ CPPUNIT_ASSERT_EQUAL( OUString(), parseDump( "/root/page/body/txt[3]/Text[4]", "nWidth" ) );
+ CPPUNIT_ASSERT_EQUAL( OUString(), parseDump( "/root/page/body/txt[3]/Text[5]", "nWidth" ) );
+
+ // The option is false in settings.xml
+ pDoc = createDoc( "MsWordCompTrailingBlanksFalse.odt" );
+ CPPUNIT_ASSERT_EQUAL( false, pDoc->getIDocumentSettingAccess().get( DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS ) );
+ calcLayout();
+ // Check that trailing spaces spans have width if option is disabled
+ CPPUNIT_ASSERT( !parseDump( "/root/page/body/txt[2]/Text[4]", "nWidth" ).isEmpty() );
+ CPPUNIT_ASSERT( !parseDump( "/root/page/body/txt[2]/Text[5]", "nWidth" ).isEmpty() );
+ CPPUNIT_ASSERT( !parseDump( "/root/page/body/txt[3]/Text[4]", "nWidth" ).isEmpty() );
+ CPPUNIT_ASSERT( !parseDump( "/root/page/body/txt[3]/Text[5]", "nWidth" ).isEmpty() );
+
+ // MsWordCompTrailingBlanks option should be false by default in new documents
+ pDoc = createDoc();
+ CPPUNIT_ASSERT_EQUAL( false, pDoc->getIDocumentSettingAccess().get( DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS ) );
+
+ // The option should be true if a .docx, .doc or .rtf document is opened
+ pDoc = createDoc( "MsWordCompTrailingBlanks.docx" );
+ CPPUNIT_ASSERT_EQUAL( true, pDoc->getIDocumentSettingAccess().get( DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS ) );
+}
+
+void SwUiWriterTest::testCreateDocxAnnotation()
+{
+ createDoc();
+
+ // insert an annotation with a text
+ const OUString aSomeText("some text");
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
+ {
+ {"Text", uno::makeAny(aSomeText)},
+ {"Author", uno::makeAny(OUString("me"))},
+ });
+ dispatchCommand(mxComponent, ".uno:InsertAnnotation", aPropertyValues);
+
+ // Save it as DOCX & load it again
+ reload("Office Open XML Text", "create-docx-annotation.docx");
+
+ // get the annotation
+ 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<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY);
+
+ // this was empty instead of "some text"
+ CPPUNIT_ASSERT_EQUAL(aSomeText, xField->getPropertyValue("Content").get<OUString>());
+}
+
+void SwUiWriterTest::testTdf107976()
+{
+ // Create a document and create two transferables.
+ SwDoc* pDoc = createDoc();
+ SwWrtShell& rShell = *pDoc->GetDocShell()->GetWrtShell();
+ rtl::Reference<SwTransferable> pTransferable(new SwTransferable(rShell));
+ rtl::Reference<SwTransferable> pTransferable2(new SwTransferable(rShell));
+ // Now close the document.
+ mxComponent->dispose();
+ mxComponent.clear();
+ // This failed: the first shell had a pointer to the deleted shell.
+ CPPUNIT_ASSERT(!pTransferable->GetShell());
+ CPPUNIT_ASSERT(!pTransferable2->GetShell());
+}
+
+void SwUiWriterTest::testTdf58604()
+{
+#ifdef _WIN32
+ // Allow linebreak character follows hanging punctuation immediately instead of
+ // breaking at the start of the next line.
+ load(DATA_DIRECTORY, "tdf58604.odt");
+ CPPUNIT_ASSERT_EQUAL( OUString("PortionType::Break"), parseDump( "(/root/page/body/txt/LineBreak[1]/preceding::Text)[last()]", "nType" ) );
+#endif
+}
+
+void SwUiWriterTest::testTdf112025()
+{
+ load(DATA_DIRECTORY, "fdo112025.odt");
+ const int numberOfParagraphs = getParagraphs();
+ CPPUNIT_ASSERT_EQUAL(1, numberOfParagraphs);
+
+ // get a page cursor
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "fdo112025-insert.docx";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({{ "Name", uno::makeAny(insertFileid) }}));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ // something has been inserted + an additional paragraph
+ CPPUNIT_ASSERT_GREATER(numberOfParagraphs, getParagraphs());
+
+ uno::Reference<beans::XPropertySet> xStyle(getStyles("PageStyles")->getByName("Standard"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xStyle, "IsLandscape"));
+}
+
+void SwUiWriterTest::testTdf72942()
+{
+ load(DATA_DIRECTORY, "fdo72942.docx");
+
+ // get a page cursor
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "fdo72942-insert.docx";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({{ "Name", uno::makeAny(insertFileid) }}));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+
+ // check styles of paragraphs added from [fdo72942.docx]
+ const uno::Reference< text::XTextRange > xRun1 = getRun(getParagraph(1), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("Default English (Liberation serif) text with "), xRun1->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"), getProperty<OUString>(xRun1, "CharFontName"));
+
+ const uno::Reference< text::XTextRange > xRun2 = getRun(getParagraph(2), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("Header 1 English text (Liberation sans) with "), xRun2->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty<OUString>(xRun2, "CharFontName"));
+
+ // check styles of paragraphs added from [fdo72942-insert.docx]
+ const uno::Reference< text::XTextRange > xRun3 = getRun(getParagraph(4), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("Default German text (Calibri) with "), xRun3->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"), getProperty<OUString>(xRun3, "CharFontName"));
+
+ const uno::Reference< text::XTextRange > xRun4 = getRun(getParagraph(5), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("Header 1 German text (Calibri Light) with "), xRun4->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Liberation Sans"), getProperty<OUString>(xRun4, "CharFontName"));
+}
+
+void SwUiWriterTest::testTdf114306()
+{
+ load(DATA_DIRECTORY, "fdo114306.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+ // There are 2 long paragraphs in cell A1.
+ // A part of paragraph 2 should flow over to the second page but
+ // *not* the whole paragraph. There should be 2 paragraphs on
+ // page 1 and 1 paragraph on page 2.
+ assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row[1]/cell[1]/txt", 2);
+ assertXPath(pXmlDoc, "/root/page[2]/body/tab[1]/row[1]/cell[1]/txt", 1);
+}
+
+void SwUiWriterTest::testTdf114306_2()
+{
+ // tdf#114306 fix unexpected page break in row-spanned table
+ // load regression document without writer crash
+ load(DATA_DIRECTORY, "fdo114306_2.odt");
+
+ // correct number of pages
+ CPPUNIT_ASSERT_EQUAL(4, getPages());
+}
+
+
+// During insert of the document with list inside into the main document inside the list
+// we should merge both lists into one, when they have the same list properties
+void SwUiWriterTest::testTdf113877()
+{
+ load(DATA_DIRECTORY, "tdf113877_insert_numbered_list.odt");
+
+ // set a page cursor into the end of the document
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ // insert the same document at current cursor position
+ {
+ const OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf113877_insert_numbered_list.odt";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid) } }));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ }
+
+ const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+ const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
+ const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
+ const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
+ const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
+
+ // the initial list with 4 list items
+ CPPUNIT_ASSERT_EQUAL(listId1, listId4);
+
+ // the last of the first list, and the first of the inserted list
+ CPPUNIT_ASSERT_EQUAL(listId4, listId5);
+ CPPUNIT_ASSERT_EQUAL(listId5, listId6);
+ CPPUNIT_ASSERT_EQUAL(listId6, listId7);
+}
+
+// The same test as testTdf113877() but merging of two list should not be performed.
+void SwUiWriterTest::testTdf113877NoMerge()
+{
+ load(DATA_DIRECTORY, "tdf113877_insert_numbered_list.odt");
+
+ // set a page cursor into the end of the document
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ // insert the same document at current cursor position
+ {
+ const OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf113877_insert_numbered_list_abcd.odt";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid) } }));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ }
+
+ const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+ const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
+ const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
+ const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
+ const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
+
+ // the initial list with 4 list items
+ CPPUNIT_ASSERT_EQUAL(listId1, listId4);
+
+ // the last of the first list, and the first of the inserted list
+ CPPUNIT_ASSERT(listId4 != listId5);
+ CPPUNIT_ASSERT_EQUAL(listId5, listId6);
+ CPPUNIT_ASSERT(listId6 != listId7);
+}
+
+// Related test to testTdf113877(): Inserting into empty document a new document with list.
+// Insert position has NO its own paragraph style ("Standard" will be used).
+//
+// Resulting document should be the same for following tests:
+// - testTdf113877_default_style()
+// - testTdf113877_Standard_style()
+//
+void SwUiWriterTest::testTdf113877_default_style()
+{
+ load(DATA_DIRECTORY, "tdf113877_blank.odt");
+
+ // set a page cursor into the end of the document
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ // insert the same document at current cursor position
+ {
+ const OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf113877_insert_numbered_list_abcd.odt";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid) } }));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ }
+
+ const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+ const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
+ const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
+
+ CPPUNIT_ASSERT_EQUAL(listId1, listId2);
+ CPPUNIT_ASSERT_EQUAL(listId1, listId3);
+}
+
+// Related test to testTdf113877(): Inserting into empty document a new document with list.
+// Insert position has its own paragraph style derived from "Standard", but this style is the same as "Standard".
+//
+// Resulting document should be the same for following tests:
+// - testTdf113877_default_style()
+// - testTdf113877_Standard_style()
+//
+void SwUiWriterTest::testTdf113877_Standard_style()
+{
+ load(DATA_DIRECTORY, "tdf113877_blank_ownStandard.odt");
+
+ // set a page cursor into the end of the document
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ // insert the same document at current cursor position
+ {
+ const OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf113877_insert_numbered_list_abcd.odt";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid) } }));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ }
+
+ const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+ const OUString listId2 = getProperty<OUString>(getParagraph(2), "ListId");
+ const OUString listId3 = getProperty<OUString>(getParagraph(3), "ListId");
+
+ CPPUNIT_ASSERT_EQUAL(listId1, listId2);
+ CPPUNIT_ASSERT_EQUAL(listId1, listId3);
+}
+
+// just care that this does crash/assert
+void SwUiWriterTest::testRhbz1810732()
+{
+ load(DATA_DIRECTORY, "tdf113877_blank.odt");
+
+ // set a page cursor into the end of the document
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+ xCursor->jumpToEndOfPage();
+
+ // insert the same document at current cursor position
+ {
+ const OUString insertFileid = m_directories.getURLFromSrc(DATA_DIRECTORY) + "rhbz1810732.docx";
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({ { "Name", uno::makeAny(insertFileid) } }));
+ dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+ }
+}
+
+void SwUiWriterTest::testTdf108524()
+{
+ createDoc("tdf108524.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // In total we expect two cells containing a section.
+ assertXPath(pXmlDoc, "/root/page/body/tab/row/cell/section", 2);
+
+ assertXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell/section", 1);
+ // This was 0, section wasn't split, instead it was only on the first page
+ // and it was cut off.
+ assertXPath(pXmlDoc, "/root/page[2]/body/tab/row/cell/section", 1);
+}
+
+void SwUiWriterTest::testLinesInSectionInTable()
+{
+ // This is similar to testTdf108524(), but the page boundary now is not in
+ // the middle of a multi-line paragraph: the section only contains oneliner
+ // paragraphs instead.
+ createDoc("lines-in-section-in-table.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // In total we expect two cells containing a section.
+ assertXPath(pXmlDoc, "/root/page/body/tab/row/cell/section", 2);
+
+ assertXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell/section", 1);
+ // This was 0, section wasn't split, instead it was only on the first page
+ // and it was cut off.
+ assertXPath(pXmlDoc, "/root/page[2]/body/tab/row/cell/section", 1);
+}
+
+void SwUiWriterTest::testLinesMoveBackwardsInSectionInTable()
+{
+#if HAVE_MORE_FONTS
+ // Assert that paragraph "4" is on page 1 and "5" is on page 2.
+ SwDoc* pDoc = createDoc("lines-in-section-in-table.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page", 2);
+ sal_uInt32 nPara4Node = getXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("4"), pDoc->GetNodes()[nPara4Node]->GetTextNode()->GetText());
+ sal_uInt32 nPara5Node = getXPath(pXmlDoc, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc->GetNodes()[nPara5Node]->GetTextNode()->GetText());
+
+ // Remove paragraph "4".
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ while (pWrtShell->GetCursor()->GetNode().GetIndex() < nPara4Node)
+ pWrtShell->Down(/*bSelect=*/false);
+ pWrtShell->EndPara();
+ pWrtShell->Up(/*bSelect=*/true);
+ pWrtShell->DelLeft();
+
+ // Assert that paragraph "5" is now moved back to page 1 and is the last paragraph there.
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ sal_uInt32 nPage1LastNode = getXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex").toUInt32();
+ // This was "3", paragraph "4" was deleted, but "5" was not moved backwards from page 2.
+ CPPUNIT_ASSERT_EQUAL(OUString("5"), pDoc->GetNodes()[nPage1LastNode]->GetTextNode()->GetText());
+#endif
+}
+
+void SwUiWriterTest::testTableInSection()
+{
+#if HAVE_MORE_FONTS
+ // The document has a section, containing a table that spans over 2 pages.
+ createDoc("table-in-sect.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // In total we expect 4 cells.
+ assertXPath(pXmlDoc, "/root/page/body/section/tab/row/cell", 4);
+
+ // Assert that on both pages the section contains 2 cells.
+ assertXPath(pXmlDoc, "/root/page[1]/body/section/tab/row/cell", 2);
+ assertXPath(pXmlDoc, "/root/page[2]/body/section/tab/row/cell", 2);
+#endif
+}
+
+void SwUiWriterTest::testTableInNestedSection()
+{
+#if HAVE_MORE_FONTS
+ // The document has a nested section, containing a table that spans over 2 pages.
+ // This crashed the layout.
+ createDoc("rhbz739252-3.odt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // Make sure the table is inside a section and spans over 2 pages.
+ assertXPath(pXmlDoc, "//page[1]//section/tab", 1);
+ assertXPath(pXmlDoc, "//page[2]//section/tab", 1);
+#endif
+}
+
+void SwUiWriterTest::testTdf112741()
+{
+#if HAVE_MORE_FONTS
+ createDoc("tdf112741.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // This was 5 pages.
+ assertXPath(pXmlDoc, "//page", 4);
+ assertXPath(pXmlDoc, "//page[1]/body/tab/row/cell/tab/row/cell/section", 1);
+ assertXPath(pXmlDoc, "//page[2]/body/tab/row/cell/tab/row/cell/section", 1);
+ // This failed, 3rd page contained no sections.
+ assertXPath(pXmlDoc, "//page[3]/body/tab/row/cell/tab/row/cell/section", 1);
+ assertXPath(pXmlDoc, "//page[4]/body/tab/row/cell/tab/row/cell/section", 1);
+#endif
+}
+
+void SwUiWriterTest::testTdf112860()
+{
+#if HAVE_MORE_FONTS
+ // The document has a split section inside a nested table, and also a table
+ // in the footer.
+ // This crashed the layout.
+ createDoc("tdf112860.fodt");
+#endif
+}
+
+void SwUiWriterTest::testTdf113287()
+{
+#if HAVE_MORE_FONTS
+ createDoc("tdf113287.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "//page", 2);
+ sal_uInt32 nCellTop = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell[1]/infos/bounds", "top").toUInt32();
+ sal_uInt32 nSectionTop = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell[1]/section/infos/bounds", "top").toUInt32();
+ // Make sure section frame is inside the cell frame.
+ // Expected greater than 4593, was only 3714.
+ CPPUNIT_ASSERT_GREATER(nCellTop, nSectionTop);
+#endif
+}
+
+void SwUiWriterTest::testTdf113445()
+{
+#if HAVE_MORE_FONTS
+ // Force multiple-page view.
+ SwDoc* pDoc = createDoc("tdf113445.fodt");
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwView* pView = pDocShell->GetView();
+ pView->SetViewLayout(/*nColumns=*/2, /*bBookMode=*/false);
+ calcLayout();
+
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "//page", 2);
+ sal_uInt32 nPage1Left = getXPath(pXmlDoc, "//page[1]/infos/bounds", "left").toUInt32();
+ sal_uInt32 nPage2Left = getXPath(pXmlDoc, "//page[2]/infos/bounds", "left").toUInt32();
+ // Make sure that page 2 is on the right hand side of page 1, not below it.
+ CPPUNIT_ASSERT_GREATER(nPage1Left, nPage2Left);
+
+ // Insert a new paragraph at the start of the document.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->StartOfSection();
+ pWrtShell->SplitNode();
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+
+ // Make sure that Table2:C5 and Table2:D5 has its section frame inside the cell frame.
+ sal_uInt32 nCell3Top = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/infos/bounds", "top").toUInt32();
+ sal_uInt32 nSection3Top = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/section/infos/bounds", "top").toUInt32();
+ CPPUNIT_ASSERT_GREATER(nCell3Top, nSection3Top);
+ sal_uInt32 nCell4Top = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/infos/bounds", "top").toUInt32();
+ sal_uInt32 nSection4Top = getXPath(pXmlDoc, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/section/infos/bounds", "top").toUInt32();
+ CPPUNIT_ASSERT_GREATER(nCell4Top, nSection4Top);
+ // Also check if the two cells in the same row have the same top position.
+ // This was 4818, expected only 1672.
+ CPPUNIT_ASSERT_EQUAL(nCell3Top, nCell4Top);
+#endif
+}
+
+void SwUiWriterTest::testTdf113686()
+{
+#if HAVE_MORE_FONTS
+ SwDoc* pDoc = createDoc("tdf113686.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page", 2);
+ sal_uInt32 nPage1LastNode = getXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/txt[last()]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("Table2:A1-P10"), pDoc->GetNodes()[nPage1LastNode]->GetTextNode()->GetText());
+ sal_uInt32 nPage2FirstNode = getXPath(pXmlDoc, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("Table1:A1"), pDoc->GetNodes()[nPage2FirstNode]->GetTextNode()->GetText());
+
+ // Remove page 2.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ while (pWrtShell->GetCursor()->Start()->nNode.GetIndex() < nPage1LastNode)
+ pWrtShell->Down(/*bSelect=*/false);
+ pWrtShell->EndPara();
+ for (int i = 0; i < 3; ++i)
+ pWrtShell->Up(/*bSelect=*/true);
+ pWrtShell->DelLeft();
+
+ // Assert that the second page is removed.
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ // This was still 2, content from 2nd page was not moved.
+ assertXPath(pXmlDoc, "/root/page", 1);
+#endif
+}
+
+void SwUiWriterTest::testTableInSectionInTable()
+{
+#if HAVE_MORE_FONTS
+ // The document has a table, containing a section, containing a nested
+ // table.
+ // This crashed the layout.
+ createDoc("i95698.odt");
+#endif
+}
+
+void SwUiWriterTest::testSectionInTableInTable()
+{
+#if HAVE_MORE_FONTS
+ // The document has a nested table, containing a multi-line section at a
+ // page boundary.
+ // This crashed the layout later in SwFrame::IsFootnoteAllowed().
+ createDoc("tdf112109.fodt");
+#endif
+}
+
+void SwUiWriterTest::testSectionInTableInTable2()
+{
+#if HAVE_MORE_FONTS
+ createDoc("split-section-in-nested-table.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_uInt32 nSection1 = getXPath(pXmlDoc, "//page[1]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
+ sal_uInt32 nSection1Follow = getXPath(pXmlDoc, "//page[1]//body/tab/row/cell/tab/row/cell/section", "follow").toUInt32();
+ // This failed, the section wasn't split inside a nested table.
+ sal_uInt32 nSection2 = getXPath(pXmlDoc, "//page[2]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
+ sal_uInt32 nSection2Precede = getXPath(pXmlDoc, "//page[2]//body/tab/row/cell/tab/row/cell/section", "precede").toUInt32();
+
+ // Make sure that the first's follow and the second's precede is correct.
+ CPPUNIT_ASSERT_EQUAL(nSection2, nSection1Follow);
+ CPPUNIT_ASSERT_EQUAL(nSection1, nSection2Precede);
+#endif
+}
+
+void SwUiWriterTest::testSectionInTableInTable3()
+{
+#if HAVE_MORE_FONTS
+ createDoc("tdf113153.fodt");
+
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xTable(xTables->getByIndex(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table16"), xTable->getName());
+
+ uno::Reference<text::XTextTable> xRowSupplier(xTable, uno::UNO_QUERY);
+ uno::Reference<table::XTableRows> xRows = xRowSupplier->getRows();
+ uno::Reference<beans::XPropertySet> xRow(xRows->getByIndex(1), uno::UNO_QUERY);
+ xRow->setPropertyValue("IsSplitAllowed", uno::makeAny(true));
+ // This never returned.
+ calcLayout();
+
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_uInt32 nTable1 = getXPath(pXmlDoc, "//page[1]//body/tab", "id").toUInt32();
+ sal_uInt32 nTable1Follow = getXPath(pXmlDoc, "//page[1]//body/tab", "follow").toUInt32();
+ sal_uInt32 nTable2 = getXPath(pXmlDoc, "//page[2]//body/tab", "id").toUInt32();
+ sal_uInt32 nTable2Precede = getXPath(pXmlDoc, "//page[2]//body/tab", "precede").toUInt32();
+ sal_uInt32 nTable2Follow = getXPath(pXmlDoc, "//page[2]//body/tab", "follow").toUInt32();
+ sal_uInt32 nTable3 = getXPath(pXmlDoc, "//page[3]//body/tab", "id").toUInt32();
+ sal_uInt32 nTable3Precede = getXPath(pXmlDoc, "//page[3]//body/tab", "precede").toUInt32();
+
+ // Make sure the outer table frames are linked together properly.
+ CPPUNIT_ASSERT_EQUAL(nTable2, nTable1Follow);
+ CPPUNIT_ASSERT_EQUAL(nTable1, nTable2Precede);
+ CPPUNIT_ASSERT_EQUAL(nTable3, nTable2Follow);
+ CPPUNIT_ASSERT_EQUAL(nTable2, nTable3Precede);
+#endif
+}
+
+void SwUiWriterTest::testSectionInTableInTable4()
+{
+#if HAVE_MORE_FONTS
+ SwDoc* pDoc = createDoc("tdf113520.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page", 3);
+ sal_uInt32 nPage1LastNode = getXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("Section1:P10"), pDoc->GetNodes()[nPage1LastNode]->GetTextNode()->GetText());
+ sal_uInt32 nPage3FirstNode = getXPath(pXmlDoc, "/root/page[3]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[1]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("Section1:P23"), pDoc->GetNodes()[nPage3FirstNode]->GetTextNode()->GetText());
+
+ // Remove page 2.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ while (pWrtShell->GetCursor()->Start()->nNode.GetIndex() < nPage1LastNode)
+ pWrtShell->Down(/*bSelect=*/false);
+ pWrtShell->EndPara();
+ while (pWrtShell->GetCursor()->End()->nNode.GetIndex() < nPage3FirstNode)
+ pWrtShell->Down(/*bSelect=*/true);
+ pWrtShell->EndPara(/*bSelect=*/true);
+ pWrtShell->DelLeft();
+
+ // Assert that the page is removed.
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ // This was 3, page 2 was emptied, but it wasn't removed.
+ assertXPath(pXmlDoc, "/root/page", 2);
+
+ // Make sure the outer table frames are linked together properly.
+ sal_uInt32 nTable1 = getXPath(pXmlDoc, "//page[1]//body/tab", "id").toUInt32();
+ sal_uInt32 nTable1Follow = getXPath(pXmlDoc, "//page[1]//body/tab", "follow").toUInt32();
+ sal_uInt32 nTable2 = getXPath(pXmlDoc, "//page[2]//body/tab", "id").toUInt32();
+ sal_uInt32 nTable2Precede = getXPath(pXmlDoc, "//page[2]//body/tab", "precede").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(nTable2, nTable1Follow);
+ CPPUNIT_ASSERT_EQUAL(nTable1, nTable2Precede);
+#endif
+}
+
+void SwUiWriterTest::testTdf112160()
+{
+#if HAVE_MORE_FONTS
+ // Assert that the A2 cell is on page 1.
+ SwDoc* pDoc = createDoc("tdf112160.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ sal_uInt32 nA2CellNode = getXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/section/txt[last()]", "txtNodeIndex").toUInt32();
+ CPPUNIT_ASSERT_EQUAL(OUString("Table1.A2"), pDoc->GetNodes()[nA2CellNode]->GetTextNode()->GetText());
+
+ // Append a new paragraph to the end of the A2 cell.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ while (pWrtShell->GetCursor()->GetNode().GetIndex() < nA2CellNode)
+ pWrtShell->Down(/*bSelect=*/false);
+ pWrtShell->EndPara();
+ pWrtShell->SplitNode();
+
+ // Assert that after A2 got extended, D2 stays on page 1.
+ discardDumpedLayout();
+ pXmlDoc = parseLayoutDump();
+ sal_uInt32 nD2CellNode = getXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[last()]/section/txt[last()]", "txtNodeIndex").toUInt32();
+ // This was Table1.C2, Table1.D2 was moved to the next page, unexpected.
+ CPPUNIT_ASSERT_EQUAL(OUString("Table1.D2"), pDoc->GetNodes()[nD2CellNode]->GetTextNode()->GetText());
+#endif
+}
+
+void SwUiWriterTest::testTdf114536()
+{
+ // This crashed in SwTextFormatter::MergeCharacterBorder() due to a
+ // use after free.
+ createDoc("tdf114536.odt");
+}
+
+void SwUiWriterTest::testParagraphOfTextRange()
+{
+ SwDoc* pDoc = createDoc("paragraph-of-text-range.odt");
+
+ // Enter the table.
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Down(/*bSelect=*/false);
+ CPPUNIT_ASSERT(pWrtShell->IsCursorInTable());
+ // Enter the section.
+ pWrtShell->Down(/*bSelect=*/false);
+ CPPUNIT_ASSERT(pWrtShell->IsDirectlyInSection());
+
+ // Assert that we get the right paragraph object.
+ uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XTextViewCursorSupplier> xController(xModel->getCurrentController(), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xViewCursor = xController->getViewCursor();
+ // This failed as there were no TextParagraph property.
+ auto xParagraph = getProperty< uno::Reference<text::XTextRange> >(xViewCursor->getStart(), "TextParagraph");
+ CPPUNIT_ASSERT_EQUAL(OUString("In section"), xParagraph->getString());
+}
+
+// tdf#112448: Fix: take correct line height
+//
+// When line metrics is not calculated we need to call CalcRealHeight()
+// before usage of the Height() and GetRealHeight().
+void SwUiWriterTest::testTdf112448()
+{
+ createDoc("tdf112448.odt");
+
+ // check actual number of line breaks in the paragraph
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page/body/txt/LineBreak", 2);
+}
+
+void SwUiWriterTest::testTdf113790()
+{
+ SwDoc* pDoc = createDoc("tdf113790.docx");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // Create the clipboard document.
+ SwDoc aClipboard;
+ aClipboard.SetClipBoard(true);
+
+ // Go to fourth line - to "ABCD" bulleted list item
+ pWrtShell->Down(/*bSelect=*/false, 4);
+ pWrtShell->SelPara(nullptr);
+ CPPUNIT_ASSERT_EQUAL(OUString("ABCD"), pWrtShell->GetSelText());
+ pWrtShell->Copy(&aClipboard);
+
+ // Go down to next-to-last (empty) line above "Title3"
+ pWrtShell->Down(/*bSelect=*/false, 4);
+ pWrtShell->Paste(&aClipboard);
+
+ // Save it as DOCX & load it again
+ reload("Office Open XML Text", "tdf113790.docx");
+ CPPUNIT_ASSERT(dynamic_cast<SwXTextDocument *>(mxComponent.get()));
+}
+
+void SwUiWriterTest::testTdf108048()
+{
+ createDoc();
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
+ { "Kind", uno::makeAny(sal_Int16(3)) },
+ { "TemplateName", uno::makeAny(OUString("Default Page Style")) },
+ { "PageNumber", uno::makeAny(sal_uInt16(6)) }, // Even number to avoid auto-inserted blank page
+ { "PageNumberFilled", uno::makeAny(true) },
+ });
+ dispatchCommand(mxComponent, ".uno:InsertBreak", aPropertyValues);
+ CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
+
+ // The inserted page must have page number set to 6
+ uno::Reference<text::XTextRange> xPara = getParagraph(2);
+ sal_uInt16 nPageNumber = getProperty< sal_uInt16 >(xPara, "PageNumberOffset");
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), nPageNumber);
+}
+
+void SwUiWriterTest::testTdf113481()
+{
+ SwDoc* pDoc = createDoc("tdf113481-IVS.odt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ // One backspace should completely remove the CJK ideograph variation sequence
+ pWrtShell->EndPara();
+ // Before: U+8FBA U+E0102. After: empty
+ pWrtShell->DelLeft();
+ const uno::Reference< text::XTextRange > xPara1 = getParagraph(1);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara1->getString().getLength());
+
+ // In case that weak script is treated as CJK script, remove one character.
+ pWrtShell->Down(false);
+ pWrtShell->EndPara();
+ // Before: U+4E2D U+2205 U+FE00. After: U+4E2D U+2205
+ if ( pWrtShell->GetScriptType() == SvtScriptType::ASIAN )
+ {
+ pWrtShell->DelLeft();
+ const uno::Reference< text::XTextRange > xPara2 = getParagraph(2);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xPara2->getString().getLength());
+ CPPUNIT_ASSERT_EQUAL(u'\x2205', xPara2->getString()[1]);
+ }
+
+ // Characters of other scripts, remove one character.
+ pWrtShell->Down(false);
+ pWrtShell->EndPara();
+ // Before: U+1820 U+180B. After: U+1820
+ pWrtShell->DelLeft();
+ const uno::Reference< text::XTextRange > xPara3 = getParagraph(3);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPara3->getString().getLength());
+ CPPUNIT_ASSERT_EQUAL(u'\x1820', xPara3->getString()[0]);
+}
+
+void SwUiWriterTest::testTdf115013()
+{
+ const OUString sColumnName("Name with spaces, \"quotes\" and \\backslashes");
+
+ utl::TempFile aTempDir(nullptr, true);
+ const OUString aWorkDir = aTempDir.GetURL();
+
+ //create new writer document
+ SwDoc* pDoc = createDoc();
+
+ {
+ // Load and register data source
+ const OUString aDataSourceURI(m_directories.getURLFromSrc(DATA_DIRECTORY) + "datasource.ods");
+ OUString sDataSource = SwDBManager::LoadAndRegisterDataSource(aDataSourceURI, &aWorkDir);
+ CPPUNIT_ASSERT(!sDataSource.isEmpty());
+
+ // Insert a new field type for the mailmerge field
+ SwDBData aDBData;
+ aDBData.sDataSource = sDataSource;
+ aDBData.sCommand = "Sheet1";
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+ SwDBFieldType* pFieldType = static_cast<SwDBFieldType*>(pWrtShell->InsertFieldType(
+ SwDBFieldType(pDoc, sColumnName, aDBData)));
+ CPPUNIT_ASSERT(pFieldType);
+
+ // Insert the field into document
+ SwDBField aField(pFieldType);
+ pWrtShell->Insert(aField);
+ }
+ // Save it as DOCX & load it again
+ reload("Office Open XML Text", "mm-field.docx");
+
+ auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pXTextDocument);
+ pDoc = pXTextDocument->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+ SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
+ CPPUNIT_ASSERT(pCursor);
+
+ // Get the field at the beginning of the document
+ SwDBField* pField = dynamic_cast<SwDBField*>(SwCursorShell::GetFieldAtCursor(pCursor, true));
+ CPPUNIT_ASSERT(pField);
+ OUString sColumn = static_cast<SwDBFieldType*>(pField->GetTyp())->GetColumnName();
+ // The column name must come correct after round trip
+ CPPUNIT_ASSERT_EQUAL(sColumnName, sColumn);
+
+ utl::removeTree(aWorkDir);
+}
+
+void SwUiWriterTest::testTdf115065()
+{
+ // In the document, the tables have table style assigned
+ // Source table (first one) has two rows;
+ // destination (second one) has only one row
+ SwDoc* pDoc = createDoc("tdf115065.odt");
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ pWrtShell->GotoTable("Table2");
+ SwRect aRect = pWrtShell->GetCurrFrame()->getFrameArea();
+ // Destination point is the middle of the first cell of second table
+ Point ptTo(aRect.Left() + aRect.Width() / 2, aRect.Top() + aRect.Height() / 2);
+
+ pWrtShell->GotoTable("Table1");
+ aRect = pWrtShell->GetCurrFrame()->getFrameArea();
+ // Source point is the middle of the first cell of first table
+ Point ptFrom(aRect.Left() + aRect.Width() / 2, aRect.Top() + aRect.Height() / 2);
+
+ pWrtShell->SelTableCol();
+ // The copy operation (or closing document after that) segfaulted
+ pWrtShell->Copy(pWrtShell, ptFrom, ptTo);
+}
+
+void SwUiWriterTest::testTdf115132()
+{
+ SwDoc* pDoc = createDoc();
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ std::vector<OUString> vTestTableNames;
+
+ // Create an empty paragraph that will separate first table from the rest
+ pWrtShell->SplitNode();
+ pWrtShell->StartOfSection();
+ // Create a table at the start of document body
+ SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ const SwTable* pTable = &pWrtShell->InsertTable(TableOpt, 2, 3);
+ const SwTableFormat* pFormat = pTable->GetFrameFormat();
+ CPPUNIT_ASSERT(pFormat);
+ vTestTableNames.push_back(pFormat->GetName());
+ pWrtShell->EndOfSection();
+ // Create a table after a paragraph
+ pTable = &pWrtShell->InsertTable(TableOpt, 2, 3);
+ pFormat = pTable->GetFrameFormat();
+ CPPUNIT_ASSERT(pFormat);
+ vTestTableNames.push_back(pFormat->GetName());
+ // Create a table immediately after the previous
+ pTable = &pWrtShell->InsertTable(TableOpt, 2, 3);
+ pFormat = pTable->GetFrameFormat();
+ CPPUNIT_ASSERT(pFormat);
+ vTestTableNames.push_back(pFormat->GetName());
+ // Create a nested table in the middle of last row
+ pWrtShell->GotoTable(vTestTableNames.back());
+ for (int i = 0; i < 4; ++i)
+ pWrtShell->GoNextCell(false);
+ pTable = &pWrtShell->InsertTable(TableOpt, 2, 3);
+ pFormat = pTable->GetFrameFormat();
+ CPPUNIT_ASSERT(pFormat);
+ vTestTableNames.push_back(pFormat->GetName());
+
+ // Now check that in any cell in all tables we don't go out of a cell
+ // using Delete or Backspace. We test cases when a table is the first node;
+ // when we are in a first/middle/last cell in a row; when there's a paragraph
+ // before/after this cell; when there's another table before/after this cell;
+ // in nested table.
+ for (const auto& rTableName : vTestTableNames)
+ {
+ pWrtShell->GotoTable(rTableName);
+ do {
+ const SwStartNode* pNd = pWrtShell->GetSwCursor()->GetNode().FindTableBoxStartNode();
+ pWrtShell->DelRight();
+ CPPUNIT_ASSERT_EQUAL(pNd, pWrtShell->GetSwCursor()->GetNode().FindTableBoxStartNode());
+ pWrtShell->DelLeft();
+ CPPUNIT_ASSERT_EQUAL(pNd, pWrtShell->GetSwCursor()->GetNode().FindTableBoxStartNode());
+ } while (pWrtShell->GoNextCell(false));
+ }
+}
+
+void SwUiWriterTest::testXDrawPagesSupplier()
+{
+ createDoc();
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("XDrawPagesSupplier interface is unavailable", xDrawPagesSupplier.is());
+ uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages();
+ CPPUNIT_ASSERT(xDrawPages.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be only a single DrawPage in Writer documents",
+ sal_Int32(1), xDrawPages->getCount());
+ uno::Any aDrawPage = xDrawPages->getByIndex(0);
+ uno::Reference<drawing::XDrawPage> xDrawPageFromXDrawPages(aDrawPage, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDrawPageFromXDrawPages.is());
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("The DrawPage accessed using XDrawPages must be the same as using XDrawPageSupplier",
+ xDrawPage.get(), xDrawPageFromXDrawPages.get());
+}
+
+void SwUiWriterTest::testTdf116403()
+{
+ createDoc("tdf116403-considerborders.odt");
+ // Check that before ToX update, the tab stop position is the old one
+ uno::Reference<text::XTextRange> xParagraph = getParagraph(2, "1\t1");
+ auto aTabs = getProperty<uno::Sequence<style::TabStop>>(xParagraph, "ParaTabStops");
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aTabs.getLength());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(17000), aTabs[0].Position);
+
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+ const SwTOXBase* pTOX = pWrtShell->GetTOX(0);
+ CPPUNIT_ASSERT(pTOX);
+ pWrtShell->UpdateTableOf(*pTOX);
+
+ xParagraph = getParagraph(2, "1\t1");
+ aTabs = getProperty<uno::Sequence<style::TabStop>>(xParagraph, "ParaTabStops");
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aTabs.getLength());
+ // This was still 17000, refreshing ToX didn't take borders spacings and widths into account
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Page borders must be considered for right-aligned tabstop",
+ static_cast<sal_Int32>(17000 - 2 * 500 - 2 * 1), aTabs[0].Position);
+}
+
+void SwUiWriterTest::testHtmlCopyImages()
+{
+ // Load a document with an image.
+ SwDoc* pDoc = createDoc("image.odt");
+
+ // Trigger the copy part of HTML copy&paste.
+ WriterRef xWrt = new SwHTMLWriter( /*rBaseURL=*/OUString() );
+ CPPUNIT_ASSERT(xWrt.is());
+
+ xWrt->m_bWriteClipboardDoc = true;
+ xWrt->m_bWriteOnlyFirstTable = false;
+ xWrt->SetShowProgress(false);
+ {
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::WRITE|StreamMode::TRUNC);
+ SwWriter aWrt(aStream, *pDoc);
+ aWrt.Write(xWrt);
+ }
+ htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
+ CPPUNIT_ASSERT(pHtmlDoc);
+
+ // This failed, image was lost during HTML copy.
+ OUString aImage = getXPath(pHtmlDoc, "/html/body/p/img", "src");
+ // Also make sure that the image is not embedded (e.g. Word doesn't handle
+ // embedded images).
+ CPPUNIT_ASSERT(aImage.startsWith("file:///"));
+}
+
+void SwUiWriterTest::testTdf116789()
+{
+ createDoc("tdf116789.fodt");
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XText> xText1;
+ uno::Reference<text::XText> xText2;
+ {
+ uno::Reference<text::XTextContent> xBookmark(
+ xBookmarksSupplier->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY);
+ xText1 = xBookmark->getAnchor()->getText();
+ }
+ {
+ uno::Reference<text::XTextContent> xBookmark(
+ xBookmarksSupplier->getBookmarks()->getByName("Bookmark 1"), uno::UNO_QUERY);
+ xText2 = xBookmark->getAnchor()->getText();
+ }
+ // This failed, we got two different SwXCell for the same bookmark anchor text.
+ CPPUNIT_ASSERT_EQUAL(xText1, xText2);
+}
+
+void SwUiWriterTest::testTdf117225()
+{
+ // Test that saving a document with an embedded object does not leak
+ // tempfiles in the directory of the target file.
+ OUString aTargetDirectory = m_directories.getURLFromWorkdir("/CppunitTest/sw_uiwriter.test.user/");
+ OUString aTargetFile = aTargetDirectory + "tdf117225.odt";
+ OUString aSourceFile = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf117225.odt";
+ osl::File::copy(aSourceFile, aTargetFile);
+ mxComponent = loadFromDesktop(aTargetFile);
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ int nExpected = CountFilesInDirectory(aTargetDirectory);
+ xStorable->store();
+ int nActual = CountFilesInDirectory(aTargetDirectory);
+ // nActual was nExpected + 1, i.e. we leaked a tempfile.
+ CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
+
+ OUString aTargetFileSaveAs = aTargetDirectory + "tdf117225-save-as.odt";
+ xStorable->storeAsURL(aTargetFileSaveAs, {});
+ ++nExpected;
+ nActual = CountFilesInDirectory(aTargetDirectory);
+ // nActual was nExpected + 1, i.e. we leaked a tempfile.
+ CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
+}
+
+void SwUiWriterTest::testTdf91801()
+{
+ // Tests calculation with several user field variables without prior user fields
+ createDoc("tdf91801.fodt");
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
+ uno::Reference<table::XCell> xCell(xTable->getCellByName("A1"));
+ CPPUNIT_ASSERT_EQUAL(555.0, xCell->getValue());
+}
+
+void SwUiWriterTest::testTdf51223()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ pWrtShell->Insert("i");
+ pWrtShell->SplitNode(true);
+ CPPUNIT_ASSERT_EQUAL(OUString("I"), static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(OUString("i"), static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+
+}
+
+void SwUiWriterTest::testFontEmbedding()
+{
+#if HAVE_MORE_FONTS && !defined(MACOSX)
+ createDoc("testFontEmbedding.odt");
+
+ OString aContentBaseXpath("/office:document-content/office:font-face-decls");
+ OString aSettingsBaseXpath("/office:document-settings/office:settings/config:config-item-set");
+
+ xmlDocUniquePtr pXmlDoc;
+ uno::Sequence<beans::PropertyValue> aDescriptor;
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+
+ // Get document settings
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xProps(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW);
+
+ // Check font embedding state
+ CPPUNIT_ASSERT_EQUAL(false, xProps->getPropertyValue("EmbedFonts").get<bool>());
+ CPPUNIT_ASSERT_EQUAL(false, xProps->getPropertyValue("EmbedOnlyUsedFonts").get<bool>());
+ // Font scripts should be enabled by default, however this has no effect unless "EmbedOnlyUsedFonts" is enabled
+ CPPUNIT_ASSERT_EQUAL(true, xProps->getPropertyValue("EmbedLatinScriptFonts").get<bool>());
+ CPPUNIT_ASSERT_EQUAL(true, xProps->getPropertyValue("EmbedAsianScriptFonts").get<bool>());
+ CPPUNIT_ASSERT_EQUAL(true, xProps->getPropertyValue("EmbedComplexScriptFonts").get<bool>());
+
+ // CASE 1 - no font embedding enabled
+
+ // Save the document
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ CPPUNIT_ASSERT(aTempFile.IsValid());
+
+ // Check setting - No font embedding should be enabled
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"settings.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedFonts']", "false");
+
+ // Check content - No font-face-src nodes should be present
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face", 6);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
+
+ // CASE 2 - font embedding enabled, but embed used fonts disabled
+
+ // Enable font embedding, disable embedding used font only
+ xProps->setPropertyValue("EmbedFonts", uno::makeAny(true));
+ xProps->setPropertyValue("EmbedOnlyUsedFonts", uno::makeAny(false));
+
+ // Save the document again
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ CPPUNIT_ASSERT(aTempFile.IsValid());
+
+ // Check setting - font embedding should be enabled + embed only used fonts and scripts
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"settings.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedOnlyUsedFonts']", "false");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedLatinScriptFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedAsianScriptFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedComplexScriptFonts']", "true");
+
+ // Check content - font-face-src should be present only for "Liberation Sans" fonts
+
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face", 6);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']/svg:font-face-src", 1);
+
+ // CASE 3 - font embedding enabled, embed only used fonts enabled
+
+ // Enable font embedding and setting to embed used fonts only
+ xProps->setPropertyValue("EmbedFonts", uno::makeAny(true));
+ xProps->setPropertyValue("EmbedOnlyUsedFonts", uno::makeAny(true));
+ xProps->setPropertyValue("EmbedLatinScriptFonts", uno::makeAny(true));
+ xProps->setPropertyValue("EmbedAsianScriptFonts", uno::makeAny(true));
+ xProps->setPropertyValue("EmbedComplexScriptFonts", uno::makeAny(true));
+
+ // Save the document again
+ xStorable->storeToURL(aTempFile.GetURL(), aDescriptor);
+ CPPUNIT_ASSERT(aTempFile.IsValid());
+
+ // Check setting - font embedding should be enabled + embed only used fonts and scripts
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"settings.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedOnlyUsedFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedLatinScriptFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedAsianScriptFonts']", "true");
+ assertXPathContent(pXmlDoc, aSettingsBaseXpath + "/config:config-item[@config:name='EmbedComplexScriptFonts']", "true");
+
+ // Check content - font-face-src should be present only for "Liberation Sans" fonts
+
+ pXmlDoc = parseExportInternal(aTempFile.GetURL(),"content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face", 6);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src", 0);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']");
+ assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
+#endif
+}
+
+// Unit test for fix inconsistent bookmark behavior around at-char/as-char anchored frames
+//
+// We have a placeholder character in the sw doc model for as-char anchored frames,
+// so it's possible to have a bookmark before/after the frame or a non-collapsed bookmark
+// which covers the frame. The same is not true for at-char anchored frames,
+// where the anchor points to a doc model position, but there is no placeholder character.
+// If a bookmark is created covering the start and end of the anchor of the frame,
+// internally we create a collapsed bookmark which has the same position as the anchor of the frame.
+// When this doc model is handled by SwXParagraph::createEnumeration(),
+// first the frame and then the bookmark is appended to the text portion enumeration,
+// so your bookmark around the frame is turned into a collapsed bookmark after the frame.
+// (The same happens when we roundtrip an ODT document representing this doc model.)
+//
+// Fix the problem by inserting collapsed bookmarks with affected anchor positions
+// (same position is the anchor for an at-char frame) into the enumeration in two stages:
+// first the start of them before frames and then the end of them + other bookmarks.
+// This way UNO API users get their non-collapsed bookmarks around at-char anchored frames,
+// similar to as-char ones.
+void SwUiWriterTest::testInconsistentBookmark()
+{
+ // create test document with text and bookmark
+ {
+ SwDoc* pDoc(createDoc("testInconsistentBookmark.ott"));
+ IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwCursor aPaM(SwPosition(aIdx), nullptr);
+ aPaM.SetMark();
+ aPaM.MovePara(GoCurrPara, fnParaStart);
+ aPaM.MovePara(GoCurrPara, fnParaEnd);
+ rIDMA.makeMark(aPaM, "Mark", IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ aPaM.Exchange();
+ aPaM.DeleteMark();
+ }
+
+ // save document and verify the bookmark scoup
+ {
+ // save document
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+
+ // load only content.xml
+ if (xmlDocUniquePtr pXmlDoc = parseExportInternal(aTempFile.GetURL(), "content.xml"))
+ {
+ const OString aPath("/office:document-content/office:body/office:text/text:p");
+
+ const OString aTagBookmarkStart("bookmark-start");
+ const OString aTagControl("control");
+ const OString aTagBookmarkEnd("bookmark-end");
+
+ const int pos1 = getXPathPosition(pXmlDoc, aPath, aTagBookmarkStart);
+ const int pos2 = getXPathPosition(pXmlDoc, aPath, aTagControl);
+ const int pos3 = getXPathPosition(pXmlDoc, aPath, aTagBookmarkEnd);
+
+ CPPUNIT_ASSERT_GREATER(pos1, pos2);
+ CPPUNIT_ASSERT_GREATER(pos2, pos3);
+ }
+ }
+}
+
+void SwUiWriterTest::testTdf108423()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // testing autocorrect of i' -> I' on start of first paragraph
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert("i");
+ const sal_Unicode cChar = '\'';
+ pWrtShell->AutoCorrect(corr, cChar);
+ // The word "i" should be capitalized due to autocorrect, followed by a typographical apostrophe
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sIApostrophe(u"I\u2019");
+ CPPUNIT_ASSERT_EQUAL(sIApostrophe, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ pWrtShell->Insert(" i");
+ pWrtShell->AutoCorrect(corr, cChar);
+ OUString sText(sIApostrophe + u" " + sIApostrophe);
+ CPPUNIT_ASSERT_EQUAL(sText, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf106164()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // testing autocorrect of we're -> We're on start of first paragraph
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"we\u2019re");
+ const sal_Unicode cChar = ' ';
+ pWrtShell->AutoCorrect(corr, cChar);
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"We\u2019re ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf54409()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // testing autocorrect of "tset -> "test with typographical double quotation mark U+201C
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"\u201Ctset");
+ const sal_Unicode cChar = ' ';
+ pWrtShell->AutoCorrect(corr, cChar);
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"\u201Ctest ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // testing autocorrect of test" -> test" with typographical double quotation mark U+201D
+ pWrtShell->Insert(u"and tset\u201D");
+ pWrtShell->AutoCorrect(corr, cChar);
+ OUString sReplaced2(sReplaced + u"and test\u201D ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced2, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // testing autocorrect of "tset" -> "test" with typographical double quotation mark U+201C and U+201D
+ pWrtShell->Insert(u"\u201Ctset\u201D");
+ pWrtShell->AutoCorrect(corr, cChar);
+ OUString sReplaced3(sReplaced2 + u"\u201Ctest\u201D ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced3, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf38394()
+{
+ SwDoc* pDoc = createDoc("tdf38394.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // testing autocorrect of French l'" -> l'« (instead of l'»)
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"l\u2019");
+ const sal_Unicode cChar = '"';
+ pWrtShell->AutoCorrect(corr, cChar);
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"l\u2019« ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // tdf#132301 autocorrect of qu'«
+ pWrtShell->Insert(u" qu\u2019");
+ pWrtShell->AutoCorrect(corr, cChar);
+ sReplaced += u" qu\u2019« ";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf59666()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // testing missing autocorrect of single Greek letters
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"\u03C0");
+ const sal_Unicode cChar = ' ';
+ pWrtShell->AutoCorrect(corr, cChar);
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"\u03C0 ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf133524()
+{
+ SwDoc* pDoc = createDoc("tdf133524.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // 1. Testing autocorrect of >> and <<
+ // Example: »word«
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ // >>
+ pWrtShell->Insert(u">");
+ pWrtShell->AutoCorrect(corr, '>');
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"»");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // <<
+ pWrtShell->Insert(u"word<");
+ pWrtShell->AutoCorrect(corr, '<');
+ sReplaced += u"word«";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // 2. Testing autocorrect of " to >> and << inside „...”
+ // Example: „Sentence and »word«.”
+ // opening primary level quote
+ pWrtShell->Insert(u" ");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u" „";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // opening second level quote
+ pWrtShell->Insert(u"Sentence and ");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u"Sentence and »";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // closing second level quote
+ pWrtShell->Insert(u"word");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u"word«";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // closing primary level quote
+ pWrtShell->Insert(u".");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u".”";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf133524_Romanian()
+{
+ SwDoc* pDoc = createDoc("tdf133524_ro.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ // 1. Testing autocorrect of " to << and >> inside „...”
+ // Example: „Sentence and «word».”
+ // opening primary level quote
+ pWrtShell->AutoCorrect(corr, '"');
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"„");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // opening second level quote
+ pWrtShell->Insert(u"Sentence and ");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u"Sentence and «";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // closing second level quote
+ pWrtShell->Insert(u"word");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u"word»";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // closing primary level quote
+ pWrtShell->Insert(u".");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u".”";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // 2. Testing recognition of closing double quotation mark ”
+ pWrtShell->Insert(u" ");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u" „";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // 3. Testing recognition of alternative closing double quotation mark “
+ pWrtShell->Insert(u"Alternative.“ ");
+ pWrtShell->AutoCorrect(corr, '"');
+ sReplaced += u"Alternative.“ „";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf128860()
+{
+ SwDoc* pDoc = createDoc("tdf128860.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // Second level ending quote: ‚word' -> ,word‘
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"‚word");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"‚word‘");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // Us apostrophe without preceding starting quote: word' -> word’
+ pWrtShell->Insert(u" word");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sReplaced += u" word’";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // But only after letters: word.' -> word.‘
+ pWrtShell->Insert(u" word.");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sReplaced += u" word.‘";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+void SwUiWriterTest::testTdf123786()
+{
+ SwDoc* pDoc = createDoc("tdf123786.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // Second level ending quote: „word' -> „word“
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"„слово");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"„слово“");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // Us apostrophe without preceding starting quote: word' -> word’
+ pWrtShell->Insert(u" слово");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sReplaced += u" слово’";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // But only after letters: word.' -> word.“
+ pWrtShell->Insert(u" слово.");
+ pWrtShell->AutoCorrect(corr, '\'');
+ sReplaced += u" слово.“";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+
+#if ENABLE_LIBNUMBERTEXT
+void SwUiWriterTest::testTdf133589()
+{
+ // Hungarian test document with right-to-left paragraph setting
+ SwDoc* pDoc = createDoc("tdf133589.fodt");
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ // translitere words to Old Hungarian
+ SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
+ pWrtShell->Insert(u"székely");
+ pWrtShell->AutoCorrect(corr, ' ');
+ sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ OUString sReplaced(u"𐳥𐳋𐳓𐳉𐳗 ");
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // disambiguate consonants: asszony -> asz|szony
+ pWrtShell->Insert(u"asszony");
+ pWrtShell->AutoCorrect(corr, ' ');
+ sReplaced += u"𐳀𐳥𐳥𐳛𐳚 ";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // disambiguate consonants: kosszarv -> kos|szarv
+ // (add explicite ZWSP temporarily for consonant disambiguation, because the requested
+ // hu_HU hyphenation dictionary isn't installed on all testing platform)
+ // pWrtShell->Insert(u"kosszarv");
+ pWrtShell->Insert(u"kos​szarv");
+ pWrtShell->AutoCorrect(corr, ' ');
+ sReplaced += u"𐳓𐳛𐳤𐳥𐳀𐳢𐳮 ";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+ // transliterate numbers to Old Hungarian
+ pWrtShell->Insert(u"2020");
+ pWrtShell->AutoCorrect(corr, ' ');
+ sReplaced += u"𐳺𐳺𐳿𐳼𐳼 ";
+ CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
+}
+#endif
+
+void SwUiWriterTest::testInsertLongDateFormat()
+{
+ // only for Hungarian, yet
+ createDoc("tdf133524.fodt");
+ dispatchCommand(mxComponent, ".uno:InsertDateField", {});
+ // Make sure that the document starts with a field now, and its expanded string value contains space
+ const uno::Reference< text::XTextRange > xField = getRun(getParagraph(1), 1);
+ CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty<OUString>(xField, "TextPortionType"));
+ // the date format was "YYYY-MM-DD", but now "YYYY. MMM DD."
+ CPPUNIT_ASSERT(xField->getString().indexOf(" ") > -1);
+}
+
+#if HAVE_FEATURE_PDFIUM
+void SwUiWriterTest::testInsertPdf()
+{
+ createDoc();
+ SwXTextDocument *pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ // insert the PDF into the document
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence({
+ {"FileName", uno::Any(m_directories.getURLFromSrc(DATA_DIRECTORY) + "hello-world.pdf")}
+ }));
+ dispatchCommand(mxComponent, ".uno:InsertGraphic", aArgs);
+
+ // Save and load cycle
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+ loadURL(aTempFile.GetURL(), nullptr);
+ pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+
+ uno::Reference<drawing::XShape> xShape = getShape(1);
+ // Assert that we have a replacement graphics
+ auto xReplacementGraphic = getProperty<uno::Reference<graphic::XGraphic>>(xShape, "ReplacementGraphic");
+ CPPUNIT_ASSERT(xReplacementGraphic.is());
+
+ auto xGraphic = getProperty<uno::Reference<graphic::XGraphic>>(xShape, "Graphic");
+ CPPUNIT_ASSERT(xGraphic.is());
+ // Assert that the graphic is a PDF
+ CPPUNIT_ASSERT_EQUAL(OUString("application/pdf"), getProperty<OUString>(xGraphic, "MimeType"));
+}
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */