blob: f3b3299d645cb07ff889ee853dafbc82bce5ea13 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the Collabora Office project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <config_poppler.h>
#include <swmodeltestbase.hxx>
#include <officecfg/Office/Common.hxx>
#include <officecfg/Office/Writer.hxx>
#include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <COKit/COKitEnums.h>
#include <vcl/scheduler.hxx>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/table/TableBorder2.hpp>
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/text/XPageCursor.hpp>
#include <com/sun/star/text/XParagraphCursor.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <comphelper/lok.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/configuration.hxx>
#include <swdtflvr.hxx>
#include <o3tl/string_view.hxx>
#include <editeng/acorrcfg.hxx>
#include <swacorr.hxx>
#include <sfx2/linkmgr.hxx>
#include <scriptinfo.hxx>
#include <txtfrm.hxx>
#include <edtwin.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <unotxdoc.hxx>
#include <itabenum.hxx>
#include <ndtxt.hxx>
#include <toxmgr.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentLinksAdministration.hxx>
#include <IDocumentUndoRedo.hxx>
#include <fmtanchr.hxx>
#include <fmtfsize.hxx>
#include <fmtinfmt.hxx>
#include <rootfrm.hxx>
#include <dbmgr.hxx>
#include <mmconfigitem.hxx>
#include <svx/svxids.hrc>
#include <pagefrm.hxx>
#include <svx/svdview.hxx>
#include <svx/svdmark.hxx>
namespace
{
class SwUiWriterTest9 : public SwModelTestBase
{
public:
SwUiWriterTest9()
: SwModelTestBase(u"/sw/qa/extras/uiwriter/data/"_ustr)
{
}
};
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf158785)
{
// given a document with a hyperlink surrounded by N-dashes (–www.dordt.edu–)
createSwDoc("tdf158785_hyperlink.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
// go to the end of the hyperlink
pWrtShell->SttEndDoc(/*bStart=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
// get last point that will be part of the hyperlink (current position 1pt wide).
Point aLogicL(pWrtShell->GetCharRect().Center());
Point aLogicR(aLogicL);
// sanity check - we really are right by the hyperlink
aLogicL.AdjustX(-1);
SwContentAtPos aContentAtPos(IsAttrAtPos::InetAttr);
pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::InetAttr, aContentAtPos.eContentAtPos);
// The test: the position of the N-dash should not indicate hyperlink properties
// cursor pos would NOT be considered part of the hyperlink, but increase for good measure...
aLogicR.AdjustX(1);
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
/*
* tdf#111969: the beginning of the hyperlink should allow the right-click menu to remove it
*/
// move cursor (with no selection) to the start of the hyperlink - after the N-dash
pWrtShell->SttEndDoc(/*bStart=*/true);
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
aLogicL = pWrtShell->GetCharRect().Center();
aLogicR = aLogicL;
// sanity check - we really are right in front of the hyperlink
aLogicL.AdjustX(-1);
aContentAtPos = IsAttrAtPos::InetAttr;
pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
aLogicR.AdjustX(1);
aContentAtPos = IsAttrAtPos::InetAttr;
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::InetAttr, aContentAtPos.eContentAtPos);
// Remove the hyperlink
dispatchCommand(mxComponent, u".uno:RemoveHyperlink"_ustr, {});
// The test: was the hyperlink actually removed?
aContentAtPos = IsAttrAtPos::InetAttr;
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testHiddenSectionShape)
{
createSwDoc("section-shape.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
auto xTextSectionsSupplier = mxComponent.queryThrow<css::text::XTextSectionsSupplier>();
auto xSections = xTextSectionsSupplier->getTextSections();
CPPUNIT_ASSERT(xSections);
CPPUNIT_ASSERT(xSections->getByName(u"Section1"_ustr)
.queryThrow<css::beans::XPropertySet>()
->getPropertyValue(u"IsVisible"_ustr)
.get<bool>());
CPPUNIT_ASSERT(!xSections->getByName(u"Section2"_ustr)
.queryThrow<css::beans::XPropertySet>()
->getPropertyValue(u"IsVisible"_ustr)
.get<bool>());
// shape is anchored in hidden section
auto xShape = getShape(1).queryThrow<text::XTextContent>();
CPPUNIT_ASSERT_EQUAL(u"Section2"_ustr, getProperty<uno::Reference<container::XNamed>>(
xShape->getAnchor(), u"TextSection"_ustr)
->getName());
// prevent the warning dialog which is automatically cancelled
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::Content::Display::ShowWarningHiddenSection::set(false, pBatch);
pBatch->commit();
comphelper::ScopeGuard _([&] {
officecfg::Office::Writer::Content::Display::ShowWarningHiddenSection::set(true, pBatch);
pBatch->commit();
});
// backspace should delete the hidden section
pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1);
pWrtShell->DelLeft();
CPPUNIT_ASSERT_THROW(xSections->getByName(u"Section2"_ustr), container::NoSuchElementException);
CPPUNIT_ASSERT_EQUAL(0, getShapes());
// this would assert/crash because the shape was anchored to SwEndNode
save(TestFilter::ODT);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testSetStringDeletesShape)
{
createSwDoc();
SwDoc* const pDoc = getSwDoc();
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
IDocumentUndoRedo& rUndoManager = pDoc->GetIDocumentUndoRedo();
sw::UnoCursorPointer pCursor(
pDoc->CreateUnoCursor(SwPosition(pDoc->GetNodes().GetEndOfContent(), SwNodeOffset(-1))));
pDoc->getIDocumentContentOperations().InsertString(*pCursor, u"foo"_ustr);
pDoc->getIDocumentContentOperations().SplitNode(*pCursor->GetPoint(), false);
pDoc->getIDocumentContentOperations().SplitNode(*pCursor->GetPoint(), false);
pDoc->getIDocumentContentOperations().InsertString(*pCursor, u"end"_ustr);
{
SfxItemSet flySet(pDoc->GetAttrPool(),
svl::Items<RES_FRM_SIZE, RES_FRM_SIZE, RES_ANCHOR, RES_ANCHOR>);
SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
pWrtShell->StartOfSection(false);
pWrtShell->Down(/*bSelect=*/false, 1, /*bBasicCall=*/false);
anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint());
flySet.Put(anchor);
SwFormatFrameSize size(SwFrameSize::Minimum, 1000, 1000);
flySet.Put(size); // set a size, else we get 1 char per line...
SwFrameFormat const* pFly = pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true);
CPPUNIT_ASSERT(pFly != nullptr);
}
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
auto xCursor = mxComponent.queryThrow<text::XTextDocument>()->getText()->createTextCursor();
xCursor->gotoStart(false);
xCursor->goRight(3, false);
xCursor->gotoEnd(true);
xCursor->setString("bar"); // replace multi-paragraph selection
// the problem was that the fly on the middle node was not deleted
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
rUndoManager.Undo();
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
rUndoManager.Redo();
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
rUndoManager.Undo();
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159377)
{
createSwDoc();
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0);
pWrtShell->InsertTable(aTableOptions, /*nRows=*/2, /*nCols=*/2);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
pWrtShell->InsertFootnote(u""_ustr);
CPPUNIT_ASSERT(pWrtShell->IsCursorInFootnote());
CPPUNIT_ASSERT_EQUAL(SwNodeOffset(28), pDoc->GetNodes().Count());
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
// this pasted the 4 text nodes in the table, but no table nodes
// as currently tables aren't allowed in footnotes
CPPUNIT_ASSERT_EQUAL(SwNodeOffset(32), pDoc->GetNodes().Count());
pWrtShell->Undo();
CPPUNIT_ASSERT(pWrtShell->IsCursorInFootnote());
// problem was that this was 29 with an extra text node in the footnote
CPPUNIT_ASSERT_EQUAL(SwNodeOffset(28), pDoc->GetNodes().Count());
pWrtShell->Redo();
CPPUNIT_ASSERT_EQUAL(SwNodeOffset(32), pDoc->GetNodes().Count());
pWrtShell->Undo();
CPPUNIT_ASSERT_EQUAL(SwNodeOffset(28), pDoc->GetNodes().Count());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testSplitFloatingTable)
{
createSwDoc("floattable-split.docx");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
// apparently follow fly is on the text frame of page 1 even though
// positioned on page 2...
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 2);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/txt", 0);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab/row",
5);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab/row",
4);
}
pWrtShell->GotoFly(UIName{ u"Frame1"_ustr });
pWrtShell->Down(/*bSelect=*/false, 3);
pWrtShell->SplitTable(SplitTable_HeadlineOption::BorderCopy);
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/txt", 0);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab/row", 3);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly", 2);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly/txt", 0);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab/row",
2);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab/row",
4);
}
pWrtShell->Do(SwWrtShell::UNDO);
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
// apparently follow fly is on the text frame of page 1 even though
// positioned on page 2...
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 2);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/txt", 0);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab/row",
5);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[2]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab/row",
4);
}
pWrtShell->Do(SwWrtShell::REDO);
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/txt", 0);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab/row", 3);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly", 2);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly/txt", 0);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab/row",
2);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab/row",
4);
}
// now check that these round-trip as floating tables
saveAndReload(TestFilter::DOCX);
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/txt", 0);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab", 1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly/tab/row", 3);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly", 2);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/anchored/fly/txt", 0);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab",
1);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top < "
"/root/page[2]/infos/bounds/@top]/tab/row",
2);
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[3]/anchored/fly[infos/bounds/@top > "
"/root/page[2]/infos/bounds/@top]/tab/row",
4);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testPasteTableInMiddleOfParagraph)
{
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0);
pWrtShell->InsertTable(aTableOptions, /*nRows=*/2, /*nCols=*/2);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
pWrtShell->Undo();
pWrtShell->Insert(u"AB"_ustr);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
pWrtShell->Undo();
// the problem was that the A was missing
CPPUNIT_ASSERT_EQUAL(OUString("AB"),
pWrtShell->GetCursor()->GetPointNode().GetTextNode()->GetText());
pWrtShell->Redo();
pWrtShell->Undo();
CPPUNIT_ASSERT_EQUAL(OUString("AB"),
pWrtShell->GetCursor()->GetPointNode().GetTextNode()->GetText());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testHiddenSectionPDFExport)
{
// this uses biblio.odb
createSwDoc("database-display-hidden-section.fodt");
uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(),
uno::UNO_QUERY);
uno::Reference<text::XTextSection> xSection(xSections->getByIndex(0), uno::UNO_QUERY);
// apparently without a record it evaluates to hidden?
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsVisible"));
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
// somehow a timer that constructs toolbars isn't run in unit tests -
// it would query state of .uno:MailMergeEmailDocuments which as a side
// effect (!) calls this:
getSwDocShell()->GetView()->EnsureMailMergeConfigItem();
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "English ");
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "English ");
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
uno::Sequence<css::beans::PropertyValue> args{
comphelper::makePropertyValue(u"SynchronMode"_ustr, true),
comphelper::makePropertyValue(u"URL"_ustr, maTempFile.GetURL())
};
dispatchCommand(mxComponent, u".uno:ExportDirectToPDF"_ustr, args);
// fetch again in case it was deleted and undo
xSection.set(xSections->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
int nObjectsHidden;
if (pPDFium)
{
SvFileStream aPDFFile(maTempFile.GetURL(), StreamMode::READ);
SvMemoryStream aMemory;
aMemory.WriteStream(aPDFFile);
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
= pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
CPPUNIT_ASSERT(pPdfDocument);
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(0);
CPPUNIT_ASSERT(pPdfPage);
nObjectsHidden = pPdfPage->getObjectCount();
}
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "Deutsch ");
CPPUNIT_ASSERT(getProperty<bool>(xSection, "IsCurrentlyVisible"));
dispatchCommand(mxComponent, u".uno:ExportDirectToPDF"_ustr, args);
// fetch again in case it was deleted and undo
xSection.set(xSections->getByIndex(0), uno::UNO_QUERY);
// the problem was that PDF export hid the section
CPPUNIT_ASSERT(getProperty<bool>(xSection, "IsCurrentlyVisible"));
if (pPDFium)
{
SvFileStream aPDFFile(maTempFile.GetURL(), StreamMode::READ);
SvMemoryStream aMemory;
aMemory.WriteStream(aPDFFile);
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
= pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
CPPUNIT_ASSERT(pPdfDocument);
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(0);
CPPUNIT_ASSERT(pPdfPage);
// there must be more objects on the page now (currently goes 2->3)
CPPUNIT_ASSERT_LESS(pPdfPage->getObjectCount(), nObjectsHidden);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testHiddenSectionPDFExport2)
{
// this uses biblio.odb
createSwDoc("database-display-hidden-section2.fodt");
uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(),
uno::UNO_QUERY);
uno::Reference<text::XTextSection> xSection(xSections->getByIndex(0), uno::UNO_QUERY);
// apparently without a record it evaluates to hidden?
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsVisible"));
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
// somehow a timer that constructs toolbars isn't run in unit tests -
// it would query state of .uno:MailMergeEmailDocuments which as a side
// effect (!) calls this:
auto pMMConfig = getSwDocShell()->GetView()->EnsureMailMergeConfigItem();
// ... but the file has wrong DB name so we first have to fix it
// in the same way as SwChangeDBDlg
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->GetDBManager()->RegisterConnection("Bibliography");
SwDBData data;
data.sDataSource = "Bibliography";
data.sCommand = "biblio";
pWrtShell->ChgDBData(data);
// this would be called via a SwXTextView listener
pMMConfig->updateCurrentDBDataFromDocument();
pWrtShell->ChangeDBFields({ u"Bibliography2ÿbiblioÿ0"_ustr }, u"Bibliographyÿbiblioÿ0"_ustr);
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "English ");
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "English ");
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
uno::Sequence<css::beans::PropertyValue> args{
comphelper::makePropertyValue(u"SynchronMode"_ustr, true),
comphelper::makePropertyValue(u"URL"_ustr, maTempFile.GetURL())
};
dispatchCommand(mxComponent, u".uno:ExportDirectToPDF"_ustr, args);
// fetch again in case it was deleted and undo
xSection.set(xSections->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(!getProperty<bool>(xSection, "IsCurrentlyVisible"));
std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
int nObjectsHidden;
if (pPDFium)
{
SvFileStream aPDFFile(maTempFile.GetURL(), StreamMode::READ);
SvMemoryStream aMemory;
aMemory.WriteStream(aPDFFile);
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
= pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
CPPUNIT_ASSERT(pPdfDocument);
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(0);
CPPUNIT_ASSERT(pPdfPage);
nObjectsHidden = pPdfPage->getObjectCount();
}
dispatchCommand(mxComponent, u".uno:MailMergeNextEntry"_ustr, {});
getParagraph(1, "Deutsch ");
CPPUNIT_ASSERT(getProperty<bool>(xSection, "IsCurrentlyVisible"));
dispatchCommand(mxComponent, u".uno:ExportDirectToPDF"_ustr, args);
// fetch again in case it was deleted and undo
xSection.set(xSections->getByIndex(0), uno::UNO_QUERY);
// the problem was that PDF export hid the section
CPPUNIT_ASSERT(getProperty<bool>(xSection, "IsCurrentlyVisible"));
if (pPDFium)
{
SvFileStream aPDFFile(maTempFile.GetURL(), StreamMode::READ);
SvMemoryStream aMemory;
aMemory.WriteStream(aPDFFile);
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
= pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
CPPUNIT_ASSERT(pPdfDocument);
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(0);
CPPUNIT_ASSERT(pPdfPage);
// there must be more objects on the page now (currently goes 2->3)
CPPUNIT_ASSERT_LESS(pPdfPage->getObjectCount(), nObjectsHidden);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testHiddenTextFieldPDFExport)
{
createSwDoc("set-variable-hidden-text.fodt");
getParagraph(1, "2");
getParagraph(2, "Expected");
uno::Sequence<css::beans::PropertyValue> args{
comphelper::makePropertyValue(u"SynchronMode"_ustr, true),
comphelper::makePropertyValue(u"URL"_ustr, maTempFile.GetURL())
};
dispatchCommand(mxComponent, u".uno:ExportDirectToPDF"_ustr, args);
getParagraph(1, "2");
// the problem was that this changed to Wrong
getParagraph(2, "Expected");
std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
if (pPDFium)
{
SvFileStream aPDFFile(maTempFile.GetURL(), StreamMode::READ);
SvMemoryStream aMemory;
aMemory.WriteStream(aPDFFile);
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
= pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
CPPUNIT_ASSERT(pPdfDocument);
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(0);
CPPUNIT_ASSERT(pPdfPage);
std::unique_ptr<vcl::pdf::PDFiumTextPage> pPdfTextPage = pPdfPage->getTextPage();
CPPUNIT_ASSERT(pPdfTextPage);
std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
OUString sText = pPageObject->getText(pPdfTextPage);
// the problem was that this changed to Wrong
CPPUNIT_ASSERT_EQUAL(u"Expected"_ustr, sText);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf111969)
{
// given a document with a field surrounded by N-dashes (–date–)
createSwDoc("tdf111969_field.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
// go to the end of the field
pWrtShell->SttEndDoc(/*bStart=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
// get last point that will be part of the field (current position 1pt wide).
Point aLogicL(pWrtShell->GetCharRect().Center());
Point aLogicR(aLogicL);
// sanity check - we really are at the right edge of the field
aLogicR.AdjustX(1);
SwContentAtPos aContentAtPos(IsAttrAtPos::Field);
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
aLogicL.AdjustX(-1);
aContentAtPos = IsAttrAtPos::Field;
pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
// the test: simulate a right-click of a mouse which sets the cursor and then acts on that pos.
pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
CPPUNIT_ASSERT(pWrtShell->GetCurField(true));
/*
* An edge case at the start of a field - don't start the field menu on the first N-dash
*/
// go to the start of the field
pWrtShell->SttEndDoc(/*bStart=*/true);
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
// get first point that will be part of the field (current position 1pt wide).
aLogicL = pWrtShell->GetCharRect().Center();
aLogicR = aLogicL;
// sanity check - we really are at the left edge of the field
aLogicR.AdjustX(1);
aContentAtPos = IsAttrAtPos::Field;
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
aLogicL.AdjustX(-1);
aContentAtPos = IsAttrAtPos::Field;
pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
// the test: simulate a right-click of a mouse (at the end-edge of the N-dash)
// which sets the cursor and then acts on that pos.
pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
CPPUNIT_ASSERT(!pWrtShell->GetCurField(true));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf111969B)
{
// given a document with a field surrounded by two N-dashes (––date––)
createSwDoc("tdf111969_fieldB.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
// go to the start of the field
pWrtShell->SttEndDoc(/*bStart=*/true);
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2, /*bBasicCall=*/false);
// get first point that will be part of the field (current position 1pt wide).
Point aLogicL(pWrtShell->GetCharRect().Center());
Point aLogicR(aLogicL);
// sanity check - we really are at the left edge of the field
aLogicR.AdjustX(1);
SwContentAtPos aContentAtPos(IsAttrAtPos::Field);
pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
aLogicL.AdjustX(-1);
aContentAtPos = IsAttrAtPos::Field;
pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
// the test: simulate a right-click of a mouse (at the end-edge of the second N-dash)
// which sets the cursor and then acts on that pos.
pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
//CPPUNIT_ASSERT(!pWrtShell->GetCurField(true));
}
#if ENABLE_PDFIMPORT
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testPDFExportCrash)
{
createSwDoc("section-table-section.fodt");
uno::Sequence<beans::PropertyValue> aFilterData(
comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
uno::Sequence<beans::PropertyValue> aDescriptor(
comphelper::InitPropertySequence({ { "FilterName", uno::Any(u"writer_pdf_Export"_ustr) },
{ "FilterData", uno::Any(aFilterData) },
{ "URL", uno::Any(maTempFile.GetURL()) } }));
// Without the fix in place, this test would have crashed here
dispatchCommand(mxComponent, u".uno:ExportToPDF"_ustr, aDescriptor);
}
#endif
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159049)
{
// The document contains a shape which has a text with a line break. When copying the text to
// clipboard the line break was missing in the RTF flavor of the clipboard.
createSwDoc("tdf159049_LineBreakRTFClipboard.fodt");
CPPUNIT_ASSERT_EQUAL(1, getShapes());
selectShape(1);
// Bring shape into text edit mode
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYUP, 0, KEY_RETURN);
Scheduler::ProcessEventsToIdle();
// Copy text
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
// Deactivate text edit mode ...
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_ESCAPE);
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYUP, 0, KEY_ESCAPE);
Scheduler::ProcessEventsToIdle();
// ... and deselect shape.
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_ESCAPE);
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYUP, 0, KEY_ESCAPE);
Scheduler::ProcessEventsToIdle();
// Paste special as RTF
uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
{ { "SelectedFormat", uno::Any(static_cast<sal_uInt32>(SotClipboardFormatId::RTF)) } }));
dispatchCommand(mxComponent, u".uno:ClipboardFormatItems"_ustr, aArgs);
// Without fix Actual was "Abreakhere", the line break \n was missing.
CPPUNIT_ASSERT_EQUAL(u"Abreak\nhere"_ustr, getParagraph(1)->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf135083)
{
createSwDoc("tdf135083-simple-text-plus-list.fodt");
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
// Paste special as RTF
uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
{ { u"SelectedFormat"_ustr,
uno::Any(static_cast<sal_uInt32>(SotClipboardFormatId::RTF)) } }));
dispatchCommand(mxComponent, u".uno:ClipboardFormatItems"_ustr, aArgs);
auto xLastPara = getParagraph(3);
CPPUNIT_ASSERT_EQUAL(u"dolor"_ustr, xLastPara->getString());
// Without the fix in place, the last paragraph would loose its settings. ListId would be empty.
CPPUNIT_ASSERT(!getProperty<OUString>(xLastPara, u"ListId"_ustr).isEmpty());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testHiddenSectionsAroundPageBreak)
{
createSwDoc("hiddenSectionsAroundPageBreak.fodt");
CPPUNIT_ASSERT_EQUAL(1, getPages());
auto xModel(mxComponent.queryThrow<frame::XModel>());
auto xTextViewCursorSupplier(
xModel->getCurrentController().queryThrow<text::XTextViewCursorSupplier>());
auto xCursor(xTextViewCursorSupplier->getViewCursor().queryThrow<text::XPageCursor>());
// Make sure that the page style is set correctly
xCursor->jumpToFirstPage();
CPPUNIT_ASSERT_EQUAL(u"Landscape"_ustr, getProperty<OUString>(xCursor, u"PageStyleName"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159565)
{
// Given a document with a hidden section in the beginning, additionally containing a frame
createSwDoc("FrameInHiddenSection.fodt");
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
// Check that the selection covers the whole visible text
auto xModel(mxComponent.queryThrow<css::frame::XModel>());
auto xSelSupplier(xModel->getCurrentController().queryThrow<css::view::XSelectionSupplier>());
auto xSelections(xSelSupplier->getSelection().queryThrow<css::container::XIndexAccess>());
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSelections->getCount());
auto xSelection(xSelections->getByIndex(0).queryThrow<css::text::XTextRange>());
// Without the fix, this would fail - there was no selection
CPPUNIT_ASSERT_EQUAL(u"" SAL_NEWLINE_STRING SAL_NEWLINE_STRING "ipsum"_ustr,
xSelection->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159816)
{
createSwDoc();
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
// Add 5 empty paragraphs
pWrtShell->SplitNode();
pWrtShell->SplitNode();
pWrtShell->SplitNode();
pWrtShell->SplitNode();
pWrtShell->SplitNode();
// Add a bookmark at the very end
IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
rIDMA.makeMark(*pWrtShell->GetCursor(), SwMarkName(u"Mark"_ustr),
IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
// Get coordinates of the end point in the document
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
SwFrame* pPage = pLayout->Lower();
SwFrame* pBody = pPage->GetLower();
SwFrame* pLastPara = pBody->GetLower()->GetNext()->GetNext()->GetNext()->GetNext()->GetNext();
Point ptTo = pLastPara->getFrameArea().BottomRight();
pWrtShell->SelAll();
// Drag-n-drop to its own end
rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell);
// Without the fix, this would crash: either in CopyFlyInFlyImpl (tdf#159813):
// Assertion failed: !pCopiedPaM || pCopiedPaM->End()->GetNode() == rRg.aEnd.GetNode()
// or in BigPtrArray::operator[] (tdf#159816):
// Assertion failed: idx < m_nSize
xTransfer->PrivateDrop(*pWrtShell, ptTo, /*bMove=*/true, /*bXSelection=*/true);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf34804)
{
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
// Simulate a keyboard shortcut to SID_ATTR_CHAR_COLOR2 (which must use the shared button color)
dispatchCommand(mxComponent, u".uno:FontColor"_ustr, {});
pWrtShell->Insert(u"New World!"_ustr);
const uno::Reference<text::XTextRange> xRun = getRun(getParagraph(1, "New World!"), 1);
// (This test assumes that nothing in the unit tests has modified the app's recent font color)
// COL_DEFAULT_FONT is the default red color for the fontColor button on the toolbar.
CPPUNIT_ASSERT_EQUAL(COL_DEFAULT_FONT, getProperty<Color>(xRun, u"CharColor"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf139631)
{
// Unit test for tdf#139631
// Test to see if preceding space is cut when cutting a word with track changes (redline) on
createSwDoc();
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"New World!\""_ustr);
// Assert that the string, New World!", is inserted correctly into the document
CPPUNIT_ASSERT_EQUAL(u"New World!\""_ustr, getParagraph(1)->getString());
// Enable redline
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
CPPUNIT_ASSERT(pDoc->getIDocumentRedlineAccess().IsRedlineOn());
// Hide redline changes
dispatchCommand(mxComponent, u".uno:ShowTrackedChanges"_ustr, {});
CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
pWrtShell->Left(SwCursorSkipMode::Chars, false, 2, false);
// Select and cut "World" from string
pWrtShell->Left(SwCursorSkipMode::Chars, true, 5, false);
dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
pXmlDoc = parseLayoutDump();
// Verifies that the leading space before "World" was also cut
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion",
"portion", u"New!\"");
// Reset to initial string
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion",
"portion", u"New World!\"");
pWrtShell->EndPara(false);
pWrtShell->Left(SwCursorSkipMode::Chars, false, 1, false);
// Replace ! with .
pWrtShell->Left(SwCursorSkipMode::Chars, true, 1, false);
pWrtShell->Delete();
pWrtShell->Insert(u"."_ustr);
pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion",
"portion", u"New World.\"");
pWrtShell->Left(SwCursorSkipMode::Chars, false, 1, false);
// Select and cut "World" from string
pWrtShell->Left(SwCursorSkipMode::Chars, true, 5, false);
dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
pXmlDoc = parseLayoutDump();
// Without the test in place, the leading space before "World" is not also cut.
// Expected: New."
// Actual: New ."
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion",
"portion", u"New.\"");
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf165351)
{
createSwDoc("tdf165351.fodt");
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
// Move the cursor into the fly frame
pWrtShell->GotoFly(UIName(u"Frame1"_ustr), FLYCNTTYPE_FRM, false);
pWrtShell->EndOfSection();
pWrtShell->GoNextCell(/*bAppendLine=*/true);
pWrtShell->Undo();
// getting this item crashed
SfxItemSet temp{ pDoc->GetAttrPool(), svl::Items<SID_RULER_LR_MIN_MAX, SID_RULER_LR_MIN_MAX> };
pWrtShell->GetView().StateTabWin(temp);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf151710)
{
// Turn "Enclose with characters" on temporarily
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(true, pBatch);
pBatch->commit();
comphelper::ScopeGuard _([&] {
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(false, pBatch);
pBatch->commit();
});
createSwDoc();
const SwViewOption* pVwOpt = getSwDocShell()->GetWrtShell()->GetViewOptions();
CPPUNIT_ASSERT(pVwOpt);
CPPUNIT_ASSERT(pVwOpt->IsEncloseWithCharactersOn());
// Localized quotation marks
SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
CPPUNIT_ASSERT(pACorr);
LanguageType eLang = Application::GetSettings().GetLanguageTag().getLanguageType();
OUString sStartSingleQuote{ pACorr->GetQuote('\'', true, eLang) };
OUString sEndSingleQuote{ pACorr->GetQuote('\'', false, eLang) };
OUString sStartDoubleQuote{ pACorr->GetQuote('\"', true, eLang) };
OUString sEndDoubleQuote{ pACorr->GetQuote('\"', false, eLang) };
// Insert some text to work with
uno::Sequence<beans::PropertyValue> aArgsInsert(
comphelper::InitPropertySequence({ { "Text", uno::Any(u"abcd"_ustr) } }));
dispatchCommand(mxComponent, u".uno:InsertText"_ustr, aArgsInsert);
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(u"abcd"_ustr, xTextDocument->getText()->getString());
// Successfully enclose the text; afterwards the selection should exist with the new
// enclosed text
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '(', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"(abcd)"_ustr, xTextDocument->getText()->getString());
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '[', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"[(abcd)]"_ustr, xTextDocument->getText()->getString());
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '{', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"{[(abcd)]}"_ustr, xTextDocument->getText()->getString());
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '\'', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(OUString(sStartSingleQuote + "{[(abcd)]}" + sEndSingleQuote),
xTextDocument->getText()->getString());
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '\"', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(OUString(sStartDoubleQuote + sStartSingleQuote + "{[(abcd)]}"
+ sEndSingleQuote + sEndDoubleQuote),
xTextDocument->getText()->getString());
// Disable the setting and check that enclosing doesn't happen anymore
const_cast<SwViewOption*>(pVwOpt)->SetEncloseWithCharactersOn(false);
CPPUNIT_ASSERT(!pVwOpt->IsEncloseWithCharactersOn());
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '(', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"("_ustr, xTextDocument->getText()->getString());
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '[', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"["_ustr, xTextDocument->getText()->getString());
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '{', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"{"_ustr, xTextDocument->getText()->getString());
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '\'', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sStartSingleQuote, xTextDocument->getText()->getString());
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '\"', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sStartDoubleQuote, xTextDocument->getText()->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf167132)
{
// Turn "Enclose with characters" on temporarily
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(true, pBatch);
pBatch->commit();
comphelper::ScopeGuard _([&] {
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(false, pBatch);
pBatch->commit();
});
// Given a document with several paragraphs, and a formula object
createSwDoc("text-with-formula.fodt");
CPPUNIT_ASSERT_EQUAL(3, getParagraphs());
SwXTextDocument* pTextDoc = getSwTextDoc();
auto& rObjectContainer = pTextDoc->GetObjectShell()->GetEmbeddedObjectContainer();
CPPUNIT_ASSERT(rObjectContainer.HasEmbeddedObjects());
auto xMathObject = rObjectContainer.GetEmbeddedObject(rObjectContainer.GetObjectNames()[0]);
CPPUNIT_ASSERT(xMathObject);
auto xSelSupplier = pTextDoc->getCurrentController().queryThrow<view::XSelectionSupplier>();
auto xCursor = pTextDoc->getText()->createTextCursor();
// 1. Select almost whole text, except the first and the last characters (to test the stability
// of the selection boundaries) - meaning that the selection spans across three paragraphs:
xCursor->gotoRange(pTextDoc->getText()->getStart(), false);
xCursor->goRight(1, false);
xCursor->gotoRange(pTextDoc->getText()->getEnd(), true);
xCursor->goLeft(1, true);
xSelSupplier->select(css::uno::Any(xCursor));
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '(', 0);
Scheduler::ProcessEventsToIdle();
// The formula must not be removed from the document
CPPUNIT_ASSERT(rObjectContainer.HasEmbeddedObject(xMathObject));
auto xSelections = xSelSupplier->getSelection().queryThrow<css::container::XIndexAccess>();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSelections->getCount());
auto xSelection = xSelections->getByIndex(0).queryThrow<css::text::XTextRange>();
// Check that selection includes parentheses
CPPUNIT_ASSERT_EQUAL(u"(aragraph one" SAL_NEWLINE_STRING "Paragraph two: " SAL_NEWLINE_STRING
"Paragraph thre)"_ustr,
xSelection->getString());
// Check that the selection includes the formula
auto xContentEnumAccess = xSelection.queryThrow<css::container::XContentEnumerationAccess>();
auto xContentEnum
= xContentEnumAccess->createContentEnumeration(u"com.sun.star.text.TextContent"_ustr);
CPPUNIT_ASSERT(xContentEnum->hasMoreElements());
// 2. Select part of the second paragraph, starting with the bold word, to the end (including
// the formula), to test that the added characters assume the formatting of selection:
auto xPara2 = getParagraph(2);
xCursor->gotoRange(xPara2->getStart(), false);
xCursor->goRight(10, false); // to start of "two", which is bold
xCursor->gotoRange(xPara2->getEnd(), true);
CPPUNIT_ASSERT_EQUAL(u"two: "_ustr, xCursor->getString());
xContentEnumAccess.set(xCursor, css::uno::UNO_QUERY_THROW);
xContentEnum
= xContentEnumAccess->createContentEnumeration(u"com.sun.star.text.TextContent"_ustr);
CPPUNIT_ASSERT(xContentEnum->hasMoreElements()); // The selection contains the formula
xSelSupplier->select(css::uno::Any(xCursor));
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, '[', 0);
Scheduler::ProcessEventsToIdle();
// The formula must not be removed from the document
CPPUNIT_ASSERT(rObjectContainer.HasEmbeddedObject(xMathObject));
// The paragraph now must consist of five runs: first, the non-bold "Paragraph ";
// then bold "[two"; then non-bold ": "; then the formula; and then non-bold "]":
auto xRun = getRun(xPara2, 1, u"Paragraph "_ustr);
CPPUNIT_ASSERT_EQUAL(100.0f, getProperty<float>(xRun, u"CharWeight"_ustr));
xRun = getRun(xPara2, 2, u"[two"_ustr);
CPPUNIT_ASSERT_EQUAL(150.0f, getProperty<float>(xRun, u"CharWeight"_ustr));
xRun = getRun(xPara2, 3, u": "_ustr);
CPPUNIT_ASSERT_EQUAL(100.0f, getProperty<float>(xRun, u"CharWeight"_ustr));
xRun = getRun(xPara2, 4, u""_ustr);
// Check that the run includes the formula
xContentEnumAccess.set(xRun, css::uno::UNO_QUERY_THROW);
xContentEnum
= xContentEnumAccess->createContentEnumeration(u"com.sun.star.text.TextContent"_ustr);
CPPUNIT_ASSERT(xContentEnum->hasMoreElements()); // The selection contains the formula
xRun = getRun(xPara2, 5, u"]"_ustr);
CPPUNIT_ASSERT_EQUAL(100.0f, getProperty<float>(xRun, u"CharWeight"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf167133)
{
// Turn "Enclose with characters" on temporarily
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(true, pBatch);
pBatch->commit();
comphelper::ScopeGuard _([&] {
officecfg::Office::Writer::FmtAidsAutocomplete::EncloseWithCharacters::set(false, pBatch);
pBatch->commit();
});
// Given a document with a single paragraph, having a formula object
createSwDoc("text-with-formula-one-paragraph.fodt");
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
pDoc->getIDocumentContentOperations().ReplaceRange(*pWrtShell->GetCursor(), "", false);
Scheduler::ProcessEventsToIdle();
// This must not crash!
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159054_disableOutlineNumbering)
{
createSwDoc("tdf159054_disableOutlineNumbering.docx");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
const uno::Reference<text::XTextRange> xPara1 = getParagraph(1, u"Heading A"_ustr);
const uno::Reference<text::XTextRange> xPara2 = getParagraph(2, u"Heading B"_ustr);
const uno::Reference<text::XTextRange> xPara3 = getParagraph(3, u"Heading C"_ustr);
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xPara1, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u"B."_ustr, getProperty<OUString>(xPara2, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u"C."_ustr, getProperty<OUString>(xPara3, u"ListLabelString"_ustr));
// select (at least parts) of the first two paragraphs
pWrtShell->Down(/*bSelect=*/true, /*nCount=*/1, /*bBasicCall=*/true);
// on the selection, simulate pressing the toolbar button to toggle OFF numbering
dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
// the selected paragraphs should definitely have the list label removed
CPPUNIT_ASSERT_EQUAL(u""_ustr, getProperty<OUString>(xPara1, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u""_ustr, getProperty<OUString>(xPara2, u"ListLabelString"_ustr));
// the third paragraph must retain the existing numbering format
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xPara3, u"ListLabelString"_ustr));
// on the selection, simulate pressing the toolbar button to toggle ON numbering again
dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
// the outline numbering format must be re-applied to the first two paragraphs
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xPara1, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u"B."_ustr, getProperty<OUString>(xPara2, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u"C."_ustr, getProperty<OUString>(xPara3, u"ListLabelString"_ustr));
// on the selection, simulate a right click - list - No list
dispatchCommand(mxComponent, u".uno:RemoveBullets"_ustr, {});
// the selected paragraphs should definitely have the list label removed
CPPUNIT_ASSERT_EQUAL(u""_ustr, getProperty<OUString>(xPara1, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u""_ustr, getProperty<OUString>(xPara2, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xPara3, u"ListLabelString"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf158375_dde_disable)
{
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Security::Scripting::DisableActiveContent::set(true, pBatch);
pBatch->commit();
comphelper::ScopeGuard g([] {
std::shared_ptr<comphelper::ConfigurationChanges> _pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Security::Scripting::DisableActiveContent::set(false, _pBatch);
_pBatch->commit();
});
createSwDoc();
SwDoc* pDoc = getSwDoc();
// force the AppName to enable DDE, it is not there for test runs
Application::SetAppName(u"soffice"_ustr);
// temp copy for the file that will be used as a reference for DDE link
// this file includes a section named "Section1" with text inside
createTempCopy(u"tdf158375_dde_reference.fodt");
comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer
= getSwDocShell()->getEmbeddedObjectContainer();
rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
// create a section with DDE link
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xTextSectionProps(
xFactory->createInstance(u"com.sun.star.text.TextSection"_ustr), uno::UNO_QUERY);
uno::Sequence<OUString> aNames{ u"DDECommandFile"_ustr, u"DDECommandType"_ustr,
u"DDECommandElement"_ustr, u"IsAutomaticUpdate"_ustr,
u"IsProtected"_ustr };
uno::Sequence<uno::Any> aValues{ uno::Any(u"soffice"_ustr), uno::Any(maTempFile.GetURL()),
uno::Any(u"Section1"_ustr), uno::Any(true), uno::Any(true) };
uno::Reference<beans::XMultiPropertySet> rMultiPropSet(xTextSectionProps, uno::UNO_QUERY);
rMultiPropSet->setPropertyValues(aNames, aValues);
// insert the TextSection with DDE link
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);
xText->insertTextContent(
xCursor, uno::Reference<text::XTextContent>(xTextSectionProps, uno::UNO_QUERY), false);
CPPUNIT_ASSERT_EQUAL(
size_t(1), pDoc->getIDocumentLinksAdministration().GetLinkManager().GetLinks().size());
pDoc->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks(false, false, nullptr,
u""_ustr);
uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(),
uno::UNO_QUERY);
uno::Reference<text::XTextSection> xSection(xSections->getByIndex(0), uno::UNO_QUERY);
// make sure there's no text in the section after UpdateAllLinks, since
// DisableActiveContent disables DDE links.
CPPUNIT_ASSERT_EQUAL(u""_ustr, xSection->getAnchor()->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf158375_ole_object_disable)
{
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Security::Scripting::DisableActiveContent::set(true, pBatch);
pBatch->commit();
comphelper::ScopeGuard g([] {
std::shared_ptr<comphelper::ConfigurationChanges> _pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Security::Scripting::DisableActiveContent::set(false, _pBatch);
_pBatch->commit();
});
// Enable LOK mode, otherwise OCommonEmbeddedObject::SwitchStateTo_Impl() will throw when it
// finds out that the test runs headless.
comphelper::COKit::setActive();
// Load a document with a Draw doc in it.
createSwDoc("ole-save-while-edit.odt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
selectShape(1);
// attempt to edit the OLE object.
pWrtShell->LaunchOLEObj();
// it shouldn't switch because the current configuration
// (DisableActiveContent) prohibits OLE objects changing to states other
// then LOADED
auto xShape = getShape(1);
uno::Reference<document::XEmbeddedObjectSupplier2> xEmbedSupplier(xShape, uno::UNO_QUERY);
auto xEmbeddedObj = xEmbedSupplier->getExtendedControlOverEmbeddedObject();
CPPUNIT_ASSERT_EQUAL(embed::EmbedStates::LOADED, xEmbeddedObj->getCurrentState());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf146190)
{
// Given a document with a number rule at the start of a paragraph and two drawing objects:
createSwDoc("tdf146190.odt");
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
const SdrMarkList& rMrkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
// Assert the current cursor position has a number rule and is at the start of a paragraph:
pWrtShell->SttEndDoc(/*bStt=*/true);
CPPUNIT_ASSERT(pWrtShell->GetNumRuleAtCurrCursorPos());
CPPUNIT_ASSERT(pWrtShell->IsSttOfPara());
// Then go to "Shape 1" drawing object using the GotoDrawingObject function:
pWrtShell->GotoDrawingObject(u"Shape 1");
CPPUNIT_ASSERT_EQUAL(u"Shape 1"_ustr, rMrkList.GetMark(0)->GetMarkedSdrObj()->GetName());
// Move to the next drawing object by Tab key press:
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_TAB);
Scheduler::ProcessEventsToIdle();
// Without the fix in place, this test would have failed with:
// equality assertion failed
// - Expected: Shape 2
// - Actual : Shape 1
// i.e. Tab did not move to the next drawing object
CPPUNIT_ASSERT_EQUAL(u"Shape 2"_ustr, rMrkList.GetMark(0)->GetMarkedSdrObj()->GetName());
// Tab key press should now select 'Shape 1':
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_TAB);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"Shape 1"_ustr, rMrkList.GetMark(0)->GetMarkedSdrObj()->GetName());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf160898)
{
// Given a document with a 1-cell table in another 1-cell table:
createSwDoc("table-in-table.fodt");
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
// Move to the normally hidden paragraph inside the outer table cell, following the inner table
pWrtShell->Down(false, 2);
// Without the fix, this would crash:
pWrtShell->SelAll();
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf164949)
{
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0);
pWrtShell->InsertTable(aTableOptions, /*nRows=*/2, /*nCols=*/2);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
uno::Sequence aArgs{ comphelper::makePropertyValue(u"PersistentCopy"_ustr, uno::Any(false)) };
// Without the fix in place, this test would have crashed here
dispatchCommand(mxComponent, u".uno:FormatPaintbrush"_ustr, aArgs);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testParagraphStyleCloneFormatting)
{
createSwDoc();
emulateTyping(u"First Line");
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
pTextDoc->postKeyEvent(KIT_KEYEVENT_KEYUP, 0, KEY_RETURN);
Scheduler::ProcessEventsToIdle();
emulateTyping(u"Second Line");
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
{ "Style", uno::Any(u"Heading 1"_ustr) },
{ "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
});
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
uno::Sequence aArgs{ comphelper::makePropertyValue(u"PersistentCopy"_ustr, uno::Any(false)) };
dispatchCommand(mxComponent, u".uno:FormatPaintbrush"_ustr, aArgs);
// Disable map mode, so that it's possible to send mouse event coordinates
// directly in twips.
SwEditWin& rEditWin = getSwDocShell()->GetView()->GetEditWin();
rEditWin.EnableMapMode(false);
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
// move to first line
pWrtShell->Up(/*bSelect=*/false, 1);
Point aPoint = pShellCursor->GetSttPos();
// click on first line
pTextDoc->postMouseEvent(KIT_MOUSEEVENT_MOUSEBUTTONDOWN, aPoint.getX(), aPoint.getY(), 1,
MOUSE_LEFT, 0);
pTextDoc->postMouseEvent(KIT_MOUSEEVENT_MOUSEBUTTONUP, aPoint.getX(), aPoint.getY(), 1,
MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf122756)
{
createSwDoc("tdf122756.odt");
uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xCellA1(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(u"€ 100,00"_ustr, xCellA1->getString());
uno::Reference<text::XTextRange> xCellA2(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(u"100"_ustr, xCellA2->getString());
// Cursor is already on cell A1
uno::Sequence aArgs{ comphelper::makePropertyValue(u"PersistentCopy"_ustr, uno::Any(false)) };
dispatchCommand(mxComponent, u".uno:FormatPaintbrush"_ustr, aArgs);
// Disable map mode, so that it's possible to send mouse event coordinates
// directly in twips.
SwEditWin& rEditWin = getSwDocShell()->GetView()->GetEditWin();
rEditWin.EnableMapMode(false);
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
// move to cell A2
pWrtShell->Down(/*bSelect=*/false, 1);
Point aPoint = pShellCursor->GetSttPos();
// click on cell A2
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postMouseEvent(KIT_MOUSEEVENT_MOUSEBUTTONDOWN, aPoint.getX(), aPoint.getY(), 1,
MOUSE_LEFT, 0);
pTextDoc->postMouseEvent(KIT_MOUSEEVENT_MOUSEBUTTONUP, aPoint.getX(), aPoint.getY(), 1,
MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(u"€ 100,00"_ustr, xCellA1->getString());
// Without the fix in place, this test would have failed with
// - Expected: € 100,00
// - Actual : 100
CPPUNIT_ASSERT_EQUAL(u"€ 100,00"_ustr, xCellA2->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf161172)
{
// Given a paragraph manually made a member of a list:
createSwDoc("tdf161172.fodt");
auto para = getParagraph(1);
// Check initial state: the first paragraph has "No_list" para style, "Num_1" numbering style,
// numbering level 0, and "Num1_lvl1_1" numbering label.
CPPUNIT_ASSERT_EQUAL(u"No_list"_ustr, getProperty<OUString>(para, u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty<OUString>(para, u"NumberingStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Num1_lvl1_1"_ustr, getProperty<OUString>(para, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(para, u"NumberingLevel"_ustr));
// Assign "Num_1_lvl2" paragraph style to the first paragraph. The style is associated with
// "Num_1" numbering style, level 1.
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr,
{ comphelper::makePropertyValue(u"FamilyName"_ustr, u"ParagraphStyles"_ustr),
comphelper::makePropertyValue(u"Style"_ustr, u"Num_1_lvl2"_ustr) });
// Check that the respective properties got correctly applied
CPPUNIT_ASSERT_EQUAL(u"Num_1_lvl2"_ustr, getProperty<OUString>(para, u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty<OUString>(para, u"NumberingStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Num1_lvl2_1"_ustr, getProperty<OUString>(para, u"ListLabelString"_ustr));
CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(para, u"NumberingLevel"_ustr));
// Undo
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
// Check that the numbering properties got correctly restored
CPPUNIT_ASSERT_EQUAL(u"No_list"_ustr, getProperty<OUString>(para, u"ParaStyleName"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty<OUString>(para, u"NumberingStyleName"_ustr));
// Without the fix, this would fail with
// - Expected: Num1_lvl1_1
// - Actual : Num1_lvl2_1
CPPUNIT_ASSERT_EQUAL(u"Num1_lvl1_1"_ustr, getProperty<OUString>(para, u"ListLabelString"_ustr));
// Without the fix, this would fail with
// - Expected: 0
// - Actual : 1
CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(para, u"NumberingLevel"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf144752)
{
// Undoing/redoing a replacement must select the new text
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
emulateTyping(u"Some Text");
CPPUNIT_ASSERT(!pWrtShell->HasSelection());
// Select "Text", and replace with "Word"
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect*/ true, 4, /*bBasicCall*/ false);
pWrtShell->Replace(u"Word"_ustr, false);
pWrtShell->EndOfSection();
CPPUNIT_ASSERT(!pWrtShell->HasSelection());
// Undo and check, that the "Text" is selected
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
// Without the fix, this would fail
CPPUNIT_ASSERT(pWrtShell->HasSelection());
CPPUNIT_ASSERT_EQUAL(u"Text"_ustr, pWrtShell->GetSelText());
// Redo and check, that the "Word" is selected
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
CPPUNIT_ASSERT(pWrtShell->HasSelection());
CPPUNIT_ASSERT_EQUAL(u"Word"_ustr, pWrtShell->GetSelText());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf162326_Paragraph)
{
createSwDoc("tdf162326.odt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(getRun(getParagraph(1), 1), u"CharWeight"_ustr));
CPPUNIT_ASSERT_EQUAL(
awt::FontSlant_ITALIC,
getProperty<awt::FontSlant>(getRun(getParagraph(2), 2), u"CharPosture"_ustr));
CPPUNIT_ASSERT_EQUAL(short(1),
getProperty<short>(getRun(getParagraph(3), 2), u"CharUnderline"_ustr));
pWrtShell->Down(/*bSelect=*/true, 3);
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr,
{ comphelper::makePropertyValue(u"FamilyName"_ustr, u"ParagraphStyles"_ustr),
comphelper::makePropertyValue(u"Style"_ustr, u"Footnote"_ustr),
comphelper::makePropertyValue(u"KeyModifier"_ustr, uno::Any(KEY_MOD1)) });
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
getProperty<float>(getRun(getParagraph(1), 1), u"CharWeight"_ustr));
CPPUNIT_ASSERT_THROW(getRun(getParagraph(2), 2), css::container::NoSuchElementException);
CPPUNIT_ASSERT_THROW(getRun(getParagraph(3), 2), css::container::NoSuchElementException);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf162326_Character)
{
createSwDoc("tdf162326.odt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(getRun(getParagraph(1), 1), u"CharWeight"_ustr));
CPPUNIT_ASSERT_EQUAL(
awt::FontSlant_ITALIC,
getProperty<awt::FontSlant>(getRun(getParagraph(2), 2), u"CharPosture"_ustr));
CPPUNIT_ASSERT_EQUAL(short(1),
getProperty<short>(getRun(getParagraph(3), 2), u"CharUnderline"_ustr));
pWrtShell->Down(/*bSelect=*/true, 3);
//add Ctrl/MOD_1
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr,
{ comphelper::makePropertyValue(u"FamilyName"_ustr, u"CharacterStyles"_ustr),
comphelper::makePropertyValue(u"Style"_ustr, u"Definition"_ustr),
comphelper::makePropertyValue(u"KeyModifier"_ustr, uno::Any(KEY_MOD1)) });
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
getProperty<float>(getRun(getParagraph(1), 1), u"CharWeight"_ustr));
CPPUNIT_ASSERT_THROW(getRun(getParagraph(2), 2), css::container::NoSuchElementException);
//last runs are not changed because the selection ends at the beginning of that paragraph
CPPUNIT_ASSERT_EQUAL(short(1),
getProperty<short>(getRun(getParagraph(3), 2), u"CharUnderline"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf162326_List)
{
createSwDoc("tdf162326_list.odt");
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XParagraphCursor> xParaCursor(xTextDocument->getText()->createTextCursor(),
uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(u"A)"_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr,
{ comphelper::makePropertyValue(u"FamilyName"_ustr, u"ParagraphStyles"_ustr),
comphelper::makePropertyValue(u"Style"_ustr, u"Footnote"_ustr) });
//hard list attribute unchanged
CPPUNIT_ASSERT_EQUAL(u"A)"_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr,
{ comphelper::makePropertyValue(u"FamilyName"_ustr, u"ParagraphStyles"_ustr),
comphelper::makePropertyValue(u"Style"_ustr, u"Footnote"_ustr),
comphelper::makePropertyValue(u"KeyModifier"_ustr, uno::Any(KEY_MOD1)) });
//list replaced by para style list setting
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf163340)
{
createSwDoc("tdf163340.odt");
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XText> xText = xTextDocument->getText();
uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
uno::UNO_QUERY_THROW);
uno::Reference<text::XParagraphCursor> xParaCursor(xTextDocument->getText()->createTextCursor(),
uno::UNO_QUERY);
for (int i = 0; i < 14; i++)
xParaCursor->gotoNextParagraph(false);
xParaCursor->gotoEndOfParagraph(true);
xSelSupplier->select(uno::Any(xParaCursor));
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
xParaCursor = uno::Reference<text::XParagraphCursor>(xText->createTextCursor(), uno::UNO_QUERY);
for (int i = 0; i < 3; i++)
xParaCursor->gotoNextParagraph(false);
xParaCursor->gotoEndOfParagraph(true);
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
xSelSupplier->select(uno::Any(xParaCursor));
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
CPPUNIT_ASSERT_EQUAL(u"A."_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf163340_2)
{
//selects and copies a single paragraph with a list (bullets)
//and pastes it into an empty paragraph with a different list (numbers)
//checks that the resulting paragraph keeps that different list
createSwDoc("tdf163340_2.odt");
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XText> xText = xTextDocument->getText();
uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
uno::UNO_QUERY_THROW);
uno::Reference<text::XParagraphCursor> xParaCursor(xTextDocument->getText()->createTextCursor(),
uno::UNO_QUERY);
for (int i = 0; i < 2; i++)
xParaCursor->gotoNextParagraph(false);
xParaCursor->gotoEndOfParagraph(true);
xSelSupplier->select(uno::Any(xParaCursor));
xParaCursor = uno::Reference<text::XParagraphCursor>(xText->createTextCursor(), uno::UNO_QUERY);
for (int i = 0; i < 10; i++)
xParaCursor->gotoNextParagraph(false);
xParaCursor->gotoEndOfParagraph(true);
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
CPPUNIT_ASSERT_EQUAL(u"5."_ustr, getProperty<OUString>(xParaCursor, u"ListLabelString"_ustr));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159023)
{
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0);
pWrtShell->InsertTable(aTableOptions, /*nRows=*/2, /*nCols=*/2);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
pWrtShell->InsertFootnote(u""_ustr);
CPPUNIT_ASSERT(pWrtShell->IsCursorInFootnote());
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
dispatchCommand(mxComponent, u".uno:GoLeft"_ustr, {});
dispatchCommand(mxComponent, u".uno:GoLeft"_ustr, {});
// Without the fix in place, this test would have crashed here
CPPUNIT_ASSERT(pWrtShell->IsCursorInFootnote());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf162195)
{
// Given a document, which has some index entries in a hidden section
createSwDoc("IndexElementsInHiddenSections.fodt");
auto xIndexSupplier(mxComponent.queryThrow<css::text::XDocumentIndexesSupplier>());
auto xIndexes = xIndexSupplier->getDocumentIndexes();
CPPUNIT_ASSERT(xIndexes);
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexes->getCount()); // A ToC and a table index
auto xToC(xIndexes->getByIndex(0).queryThrow<css::text::XDocumentIndex>());
xToC->update();
// Without the fix, all the elements from the hidden section appeared in the index
CPPUNIT_ASSERT_EQUAL(u"Table of Contents" SAL_NEWLINE_STRING "Section Visible\t1"_ustr,
xToC->getAnchor()->getString());
auto xTables(xIndexes->getByIndex(1).queryThrow<css::text::XDocumentIndex>());
xTables->update();
// Without the fix, all the elements from the hidden section appeared in the index
CPPUNIT_ASSERT_EQUAL(u"Index of Tables" SAL_NEWLINE_STRING "Table1\t1"_ustr,
xTables->getAnchor()->getString());
// Show the hidden section
auto xTextSectionsSupplier = mxComponent.queryThrow<css::text::XTextSectionsSupplier>();
auto xSections = xTextSectionsSupplier->getTextSections();
CPPUNIT_ASSERT(xSections);
auto xSection
= xSections->getByName(u"Section Hidden"_ustr).queryThrow<css::beans::XPropertySet>();
xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(true));
xToC->update();
CPPUNIT_ASSERT_EQUAL(u"Table of Contents" SAL_NEWLINE_STRING
"Section Visible\t1" SAL_NEWLINE_STRING
"Section Hidden\t1" SAL_NEWLINE_STRING "entry\t1" SAL_NEWLINE_STRING
"CustomTOCStyle paragraph\t1"_ustr,
xToC->getAnchor()->getString());
xTables->update();
CPPUNIT_ASSERT_EQUAL(u"Index of Tables" SAL_NEWLINE_STRING "Table1\t1" SAL_NEWLINE_STRING
"Table2\t1"_ustr,
xTables->getAnchor()->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf164140)
{
createSwDoc("tdf164140.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwTextFrame& pTextFrame
= dynamic_cast<SwTextFrame&>(*pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower());
const SwScriptInfo* pSI = pTextFrame.GetScriptInfo();
// Prior to editing, there should be no kashida
auto stBeforeKashida = pSI->GetKashidaPositions();
CPPUNIT_ASSERT_EQUAL(size_t(0), stBeforeKashida.size());
// Insert text at the beginning of the document
pWrtShell->Insert(u"A"_ustr);
// After editing, there should still be no room for kashida
// Without the fix, this will be non-zero
auto stAfterKashida = pSI->GetKashidaPositions();
CPPUNIT_ASSERT_EQUAL(size_t(0), stAfterKashida.size());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf71583)
{
//create a document, multiple pages, some restart page counting
// insert page count in section fields and check the calculated
// values
auto insertParagraphAndBreak = [](sal_Int32& nParagraph, SwWrtShell& rWrtSh,
uno::Reference<lang::XComponent> xComponent,
const sal_uInt16 nPages) {
for (sal_uInt16 nPage = 0; nPage < nPages; ++nPage)
{
rWrtSh.Insert(u"Paragraph "_ustr);
rWrtSh.Insert(OUString::number(nParagraph));
++nParagraph;
auto xModel(xComponent.queryThrow<frame::XModel>());
auto xFactory(xComponent.queryThrow<lang::XMultiServiceFactory>());
auto xTextViewCursorSupplier(
xModel->getCurrentController().queryThrow<text::XTextViewCursorSupplier>());
auto xTextRangeCursor(
xTextViewCursorSupplier->getViewCursor().queryThrow<text::XTextRange>());
uno::Reference<text::XTextField> xTextField(
xFactory->createInstance(u"com.sun.star.text.TextField.PageCountRange"_ustr),
uno::UNO_QUERY);
xTextRangeCursor->getText()->insertTextContent(xTextRangeCursor, xTextField, false);
rWrtSh.SttEndDoc(false);
rWrtSh.SplitNode();
if (nPage < nPages - 1)
rWrtSh.InsertPageBreak();
else
{
std::optional<sal_uInt16> oPageNumber = 1;
UIName sPageStyle(u"Default Page Style"_ustr);
rWrtSh.InsertPageBreak(&sPageStyle, oPageNumber);
}
}
};
auto checkDocument = [this]() {
auto checkFieldContent = [this](uno::Reference<text::XText>& xBodyText, sal_uInt16 nPara,
rtl::OUString sSymbol) {
uno::Reference<text::XTextRange> xPara(getParagraphOfText(nPara, xBodyText));
const uno::Reference<text::XTextRange> xRun = getRun(xPara, 2);
uno::Reference<text::XTextField> xTextField
= getProperty<uno::Reference<text::XTextField>>(xRun, u"TextField"_ustr);
OUString sPresentation = xTextField->getPresentation(false);
CPPUNIT_ASSERT_EQUAL(sSymbol, sPresentation);
};
auto xModel(mxComponent.queryThrow<text::XTextDocument>());
uno::Reference<text::XText> xBodyText = xModel->getText();
OUString sCompare = u"B"_ustr;
for (sal_uInt16 nPara = 1; nPara < 25; nPara += 2)
{
if (nPara == 5)
sCompare = u"D"_ustr;
if (nPara == 13)
sCompare = u"F"_ustr;
checkFieldContent(xBodyText, nPara, sCompare);
}
};
createSwDoc();
SwWrtShell* pWrtShell = nullptr;
{
pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
sal_Int32 nParagraph = 0;
for (int i = 1; i <= 3; ++i)
insertParagraphAndBreak(nParagraph, *pWrtShell, mxComponent, i * 2);
checkDocument();
}
{
saveAndReload(TestFilter::ODT);
checkDocument();
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf167006)
{
createSwDoc("embeddedPPTX.docx");
selectShape(1);
// attempt to edit the OLE object. This must not crash.
getSwDocShell()->GetWrtShell()->LaunchOLEObj();
}
// tdf#168355 Page break with page style with page number in table properties is wrong
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf168355)
{
createSwDoc("tdf168355.odt");
SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pTextDoc);
SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
const SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
const SwPageFrame* pPageFrm = static_cast<const SwPageFrame*>(pLayout->Lower());
CPPUNIT_ASSERT(pPageFrm);
CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pPageFrm->GetVirtPageNum());
pPageFrm = static_cast<const SwPageFrame*>(pPageFrm->GetNext());
CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pPageFrm->GetVirtPageNum());
pPageFrm = static_cast<const SwPageFrame*>(pPageFrm->GetNext());
// this used to be page 3
CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pPageFrm->GetVirtPageNum());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testSplitFloattableGetCurWord)
{
// Given a document with a floating table that splits across pages: the anchor paragraph has
// text; it's split together with its floating table; and its first frame has no SwParaPortion
// (only the last follow frame has it).
createSwDoc("floattable-nosection-7in.docx");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
// Go to end (the anchor paragraph for the floating table)
pWrtShell->SttEndDoc(/*bStt=*/false);
// Without the fix this would crash
CPPUNIT_ASSERT_EQUAL(u"End"_ustr, pWrtShell->GetCurWord());
}
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */