1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <swmodeltestbase.hxx>
12 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
13 #include <comphelper/lok.hxx>
14 #include <sfx2/viewsh.hxx>
15 #include <sfx2/lokcallback.hxx>
16 #include <vcl/gdimtf.hxx>
17 #include <vcl/scheduler.hxx>
19 #include <IDocumentStatistics.hxx>
20 #include <fmtanchr.hxx>
21 #include <frameformats.hxx>
23 #include <unotxdoc.hxx>
26 constexpr OUStringLiteral DATA_DIRECTORY
= u
"/sw/qa/core/txtnode/data/";
28 /// Covers sw/source/core/txtnode/ fixes.
29 class SwCoreTxtnodeTest
: public SwModelTestBase
33 CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest
, testBtlrCellChinese
)
35 // Load a document with a table cell, with btlr cell direction. The cell has text which is
36 // classified as vertical, i.e. the glyph has the same direction in both the lrtb ("Latin") and
37 // tbrl ("Chinese") directions. Make sure that Chinese text is handled the same way in the btlr
38 // case as it's handled in the Latin case.
39 load(DATA_DIRECTORY
, "btlr-cell-chinese.doc");
40 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
41 SwDocShell
* pShell
= pTextDoc
->GetDocShell();
42 std::shared_ptr
<GDIMetaFile
> xMetaFile
= pShell
->GetPreviewMetaFile();
43 MetafileXmlDump dumper
;
44 xmlDocUniquePtr pXmlDoc
= dumpAndParse(dumper
, *xMetaFile
);
45 assertXPath(pXmlDoc
, "//font[1]", "orientation", "900");
46 // Without the accompanying fix in place, this test would have failed with:
49 // i.e. the glyph was rotated further, so it was upside down.
50 assertXPath(pXmlDoc
, "//font[1]", "vertical", "false");
53 CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest
, testTextBoxCopyAnchor
)
55 load(DATA_DIRECTORY
, "textbox-copy-anchor.docx");
56 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
57 SwDocShell
* pShell
= pTextDoc
->GetDocShell();
58 SwWrtShell
* pWrtShell
= pShell
->GetWrtShell();
61 pWrtShell
->Copy(aClipboard
);
62 pWrtShell
->SttEndDoc(/*bStart=*/false);
63 pWrtShell
->Paste(aClipboard
);
65 const SwFrameFormats
& rFormats
= *pShell
->GetDoc()->GetSpzFrameFormats();
66 // Without the accompanying fix in place, this test would have failed with:
69 // i.e. 2 fly frames were copied twice.
70 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rFormats
.size());
72 SwPosition aDrawAnchor1
= *rFormats
[0]->GetAnchor().GetContentAnchor();
73 SwPosition aFlyAnchor1
= *rFormats
[1]->GetAnchor().GetContentAnchor();
74 CPPUNIT_ASSERT_EQUAL(aFlyAnchor1
.nNode
, aDrawAnchor1
.nNode
);
75 SwPosition aDrawAnchor2
= *rFormats
[2]->GetAnchor().GetContentAnchor();
76 SwPosition aFlyAnchor2
= *rFormats
[3]->GetAnchor().GetContentAnchor();
77 // This also failed, aFlyAnchor2 was wrong, as it got out of sync with aDrawAnchor2.
78 CPPUNIT_ASSERT_EQUAL(aFlyAnchor2
.nNode
, aDrawAnchor2
.nNode
);
81 CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest
, testTextBoxNodeSplit
)
83 load(DATA_DIRECTORY
, "textbox-node-split.docx");
84 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
85 SwDocShell
* pShell
= pTextDoc
->GetDocShell();
86 SwWrtShell
* pWrtShell
= pShell
->GetWrtShell();
87 pWrtShell
->SttEndDoc(/*bStart=*/false);
88 // Without the accompanying fix in place, this would have crashed in
89 // SwFlyAtContentFrame::SwClientNotify().
90 pWrtShell
->SplitNode();
95 struct ViewCallback
: public SfxLokCallbackInterface
97 int m_nInvalidations
= 0;
99 virtual void libreOfficeKitViewCallback(int, const char*) override
{}
100 virtual void libreOfficeKitViewCallback(int, const char*, int) override
{}
101 virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle
*, int) override
108 CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest
, testTitleFieldInvalidate
)
110 // Set up LOK to track invalidations.
111 comphelper::LibreOfficeKit::setActive(true);
113 // Given a document with a title field:
114 load(DATA_DIRECTORY
, "title-field-invalidate.fodt");
115 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
116 pTextDoc
->initializeForTiledRendering({});
117 SwDocShell
* pShell
= pTextDoc
->GetDocShell();
118 SwDoc
* pDoc
= pShell
->GetDoc();
119 SwWrtShell
* pWrtShell
= pShell
->GetWrtShell();
120 pWrtShell
->SttEndDoc(/*bStt=*/false);
121 ViewCallback aCallback
;
122 pWrtShell
->GetSfxViewShell()->setLibreOfficeKitViewCallback(&aCallback
);
123 Scheduler::ProcessEventsToIdle();
124 aCallback
.m_nInvalidations
= 0;
126 // When typing to the document:
127 pWrtShell
->Insert("x");
128 pWrtShell
->GetSfxViewShell()->flushPendingLOKInvalidateTiles();
130 // Then make sure that only the text frame at the cursor is invalidated:
131 pDoc
->getIDocumentStatistics().GetUpdatedDocStat(/*bCompleteAsync=*/true, /*bFields=*/false);
132 // Without the accompanying fix in place, this test would have failed with:
135 // i.e. the footer was also invalidated on each keypress.
136 CPPUNIT_ASSERT_EQUAL(1, aCallback
.m_nInvalidations
);
139 pWrtShell
->GetSfxViewShell()->setLibreOfficeKitViewCallback(nullptr);
140 mxComponent
->dispose();
142 comphelper::LibreOfficeKit::setActive(false);
145 CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest
, testFlyAnchorUndo
)
147 // Given a document with a fly frame, anchored after the last char of the document:
148 load(DATA_DIRECTORY
, "fly-anchor-undo.odt");
149 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
150 SwDocShell
* pShell
= pTextDoc
->GetDocShell();
151 SwDoc
* pDoc
= pShell
->GetDoc();
152 const SwFrameFormats
& rSpz
= *pDoc
->GetSpzFrameFormats();
153 sal_Int32 nExpected
= rSpz
[0]->GetAnchor().GetContentAnchor()->nContent
.GetIndex();
155 // When deleting that last character and undoing it:
156 SwWrtShell
* pWrtShell
= pShell
->GetWrtShell();
157 pWrtShell
->SttEndDoc(/*bStt=*/false);
158 pWrtShell
->DelLeft();
161 // Then make sure the anchor position after the undo is the same as the original:
162 sal_Int32 nActual
= rSpz
[0]->GetAnchor().GetContentAnchor()->nContent
.GetIndex();
163 // Without the accompanying fix in place, this test would have failed with:
166 // i.e. the anchor position was left unchanged by the undo.
167 CPPUNIT_ASSERT_EQUAL(nExpected
, nActual
);
170 CPPUNIT_PLUGIN_IMPLEMENT();
172 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */