From 9c0049cfae49c8e4ddef9125a69db2ad134c10c6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 13:48:25 +0200 Subject: Merging upstream version 4:24.2.4. Signed-off-by: Daniel Baumann --- sw/qa/core/frmedt/frmedt.cxx | 35 +++ sw/qa/core/layout/calcmove.cxx | 87 +++++++ sw/qa/core/layout/data/bad-split-section.odt | Bin 0 -> 29305 bytes sw/qa/core/layout/data/ignore-top-margin-fly.odt | Bin 0 -> 11395 bytes .../core/layout/data/ignore-top-margin-table.docx | Bin 0 -> 12465 bytes sw/qa/core/layout/data/ignore-top-margin.docx | Bin 0 -> 14904 bytes sw/qa/core/layout/layact.cxx | 22 ++ sw/qa/core/objectpositioning/objectpositioning.cxx | 48 ++++ sw/qa/core/text/data/A011-charheight.rtf | 27 ++ sw/qa/core/text/data/Broken indent demo.odt | Bin 0 -> 9970 bytes sw/qa/core/text/data/tdf156146.fodt | 281 +++++++++++++++++++++ sw/qa/core/text/itrform2.cxx | 18 ++ sw/qa/core/text/text.cxx | 62 +++++ .../txtnode/data/plain-content-control-copy.docx | Bin 0 -> 12178 bytes sw/qa/core/txtnode/txtnode.cxx | 23 ++ sw/qa/extras/odfexport/odfexport2.cxx | 6 +- sw/qa/extras/ooxmlexport/data/StyleRef-DE.docx | Bin 0 -> 19230 bytes sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 12 +- sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 4 +- sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 2 + sw/qa/extras/uiwriter/data/pagebreak-source.fodt | 131 ++++++++++ sw/qa/extras/uiwriter/data/pagebreak-target.fodt | 137 ++++++++++ .../uiwriter/data/stylewithlistandindents.fodt | 182 +++++++++++++ sw/qa/extras/uiwriter/data/table-in-table.fodt | 29 +++ sw/qa/extras/uiwriter/data/tdf160842.fodt | 75 ++++++ sw/qa/extras/uiwriter/data/tdf161172.fodt | 35 +++ sw/qa/extras/uiwriter/uiwriter.cxx | 121 +++++++++ sw/qa/extras/uiwriter/uiwriter2.cxx | 6 +- sw/qa/extras/uiwriter/uiwriter3.cxx | 7 +- sw/qa/extras/uiwriter/uiwriter6.cxx | 157 ++++++++++++ sw/qa/extras/uiwriter/uiwriter8.cxx | 121 +++++++++ sw/qa/extras/uiwriter/uiwriter9.cxx | 56 ++++ sw/qa/extras/unowriter/data/tdf161035.fodt | 9 + sw/qa/extras/unowriter/unowriter.cxx | 27 ++ .../ww8export/data/draw-obj-rtl-no-mirror-vml.docx | Bin 0 -> 14534 bytes sw/qa/extras/ww8export/ww8export4.cxx | 24 ++ sw/qa/uibase/uno/uno.cxx | 24 ++ .../cppunittests/filter/WriterFilter.cxx | 57 +++++ .../filter/data/draw-obj-rtl-no-mirror.docx | Bin 0 -> 12859 bytes 39 files changed, 1813 insertions(+), 12 deletions(-) create mode 100644 sw/qa/core/layout/calcmove.cxx create mode 100644 sw/qa/core/layout/data/bad-split-section.odt create mode 100644 sw/qa/core/layout/data/ignore-top-margin-fly.odt create mode 100644 sw/qa/core/layout/data/ignore-top-margin-table.docx create mode 100644 sw/qa/core/layout/data/ignore-top-margin.docx create mode 100644 sw/qa/core/text/data/A011-charheight.rtf create mode 100644 sw/qa/core/text/data/Broken indent demo.odt create mode 100644 sw/qa/core/text/data/tdf156146.fodt create mode 100644 sw/qa/core/txtnode/data/plain-content-control-copy.docx create mode 100644 sw/qa/extras/ooxmlexport/data/StyleRef-DE.docx create mode 100644 sw/qa/extras/uiwriter/data/pagebreak-source.fodt create mode 100644 sw/qa/extras/uiwriter/data/pagebreak-target.fodt create mode 100644 sw/qa/extras/uiwriter/data/stylewithlistandindents.fodt create mode 100644 sw/qa/extras/uiwriter/data/table-in-table.fodt create mode 100644 sw/qa/extras/uiwriter/data/tdf160842.fodt create mode 100644 sw/qa/extras/uiwriter/data/tdf161172.fodt create mode 100644 sw/qa/extras/unowriter/data/tdf161035.fodt create mode 100644 sw/qa/extras/ww8export/data/draw-obj-rtl-no-mirror-vml.docx create mode 100644 sw/qa/writerfilter/cppunittests/filter/WriterFilter.cxx create mode 100644 sw/qa/writerfilter/cppunittests/filter/data/draw-obj-rtl-no-mirror.docx (limited to 'sw/qa') diff --git a/sw/qa/core/frmedt/frmedt.cxx b/sw/qa/core/frmedt/frmedt.cxx index b2a53e60db..37425c1306 100644 --- a/sw/qa/core/frmedt/frmedt.cxx +++ b/sw/qa/core/frmedt/frmedt.cxx @@ -250,6 +250,41 @@ CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testSplitFlyUnfloat) CPPUNIT_ASSERT_EQUAL(static_cast(1), pDoc->GetTableFrameFormatCount(/*bUsed=*/true)); } +CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testInsertOnGrfNodeAsChar) +{ + // Given a selected as-char image: + createSwDoc(); + SwDoc* pDoc = getSwDocShell()->GetDoc(); + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + { + SfxItemSet aFrameSet(pDoc->GetAttrPool(), svl::Items); + SwFormatAnchor aAnchor(RndStdIds::FLY_AS_CHAR); + aFrameSet.Put(aAnchor); + Graphic aGrf; + pWrtShell->SwFEShell::Insert(OUString(), OUString(), &aGrf, &aFrameSet); + } + + // When inserting another as-char image: + SfxItemSet aFrameSet(pDoc->GetAttrPool(), svl::Items); + SwFormatAnchor aAnchor(RndStdIds::FLY_AS_CHAR); + aFrameSet.Put(aAnchor); + Graphic aGrf; + // Without the accompanying fix in place, this call crashed, we try to set a graphic node as an + // anchor of an as-char image (which should be a text node). + pWrtShell->SwFEShell::Insert(OUString(), OUString(), &aGrf, &aFrameSet); + + // Then make sure that the anchor of the second image is next to the first anchor: + CPPUNIT_ASSERT(pDoc->GetSpzFrameFormats()); + sw::FrameFormats& rFormats = *pDoc->GetSpzFrameFormats(); + CPPUNIT_ASSERT_EQUAL(static_cast(2), rFormats.size()); + const sw::SpzFrameFormat& rFormat1 = *rFormats[0]; + const SwPosition* pAnchor1 = rFormat1.GetAnchor().GetContentAnchor(); + const sw::SpzFrameFormat& rFormat2 = *rFormats[1]; + const SwPosition* pAnchor2 = rFormat2.GetAnchor().GetContentAnchor(); + CPPUNIT_ASSERT_EQUAL(pAnchor1->nNode, pAnchor2->nNode); + CPPUNIT_ASSERT_EQUAL(pAnchor1->GetContentIndex() + 1, pAnchor2->GetContentIndex()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/layout/calcmove.cxx b/sw/qa/core/layout/calcmove.cxx new file mode 100644 index 0000000000..ad53df9bd0 --- /dev/null +++ b/sw/qa/core/layout/calcmove.cxx @@ -0,0 +1,87 @@ +/* -*- 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 + +#include + +namespace +{ +/// Covers sw/source/core/layout/calcmove.cxx fixes. +class Test : public SwModelTestBase +{ +public: + Test() + : SwModelTestBase("/sw/qa/core/layout/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testIgnoreTopMargin) +{ + // Given a DOCX (>= Word 2013) file, with 2 pages: + // When loading that document: + createSwDoc("ignore-top-margin.docx"); + + // Then make sure that the paragraph on the 2nd page has no top margin: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + sal_Int32 nParaTopMargin + = getXPath(pXmlDoc, "/root/page[2]/body/txt/infos/prtBounds"_ostr, "top"_ostr).toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 2400 + // i.e. the top margin in the first para of a non-first page wasn't ignored, like in Word. + CPPUNIT_ASSERT_EQUAL(static_cast(0), nParaTopMargin); +} + +CPPUNIT_TEST_FIXTURE(Test, testIgnoreTopMarginTable) +{ + // Given a DOCX (>= Word 2013) file, with 2 pages: + // When loading that document: + createSwDoc("ignore-top-margin-table.docx"); + + // Then make sure that the paragraph on the 2nd page in B1 has a top margin: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + sal_Int32 nParaTopMargin + = getXPath(pXmlDoc, "/root/page[2]/body/tab/row/cell[2]/txt/infos/prtBounds"_ostr, + "top"_ostr) + .toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2000 + // - Actual : 0 + // i.e. the top margin in B1's first paragraph was ignored, but not in Word. + CPPUNIT_ASSERT_EQUAL(static_cast(2000), nParaTopMargin); +} + +CPPUNIT_TEST_FIXTURE(Test, testIgnoreTopMarginFly) +{ + // Given a document with compat flags like DOCX (>= Word 2013), 2 pages, multi-col fly frame on + // page 2: + createSwDoc("ignore-top-margin-fly.odt"); + + // When laying out that document: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + // Then make sure that the top margin is not ignored inside shape text: + sal_Int32 nParaTopMargin + = getXPath( + pXmlDoc, + "/root/page[2]/body/section/column[2]/body/txt/anchored/fly/column/body/txt/infos/prtBounds"_ostr, + "top"_ostr) + .toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 4000 + // - Actual : 0 + // i.e. the top margin was ignored inside shape text for Word compat, while multi-col shape text + // is a Writer feature. + CPPUNIT_ASSERT_EQUAL(static_cast(4000), nParaTopMargin); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/layout/data/bad-split-section.odt b/sw/qa/core/layout/data/bad-split-section.odt new file mode 100644 index 0000000000..6dbd07802d Binary files /dev/null and b/sw/qa/core/layout/data/bad-split-section.odt differ diff --git a/sw/qa/core/layout/data/ignore-top-margin-fly.odt b/sw/qa/core/layout/data/ignore-top-margin-fly.odt new file mode 100644 index 0000000000..51bda8fe40 Binary files /dev/null and b/sw/qa/core/layout/data/ignore-top-margin-fly.odt differ diff --git a/sw/qa/core/layout/data/ignore-top-margin-table.docx b/sw/qa/core/layout/data/ignore-top-margin-table.docx new file mode 100644 index 0000000000..c82f6d63c1 Binary files /dev/null and b/sw/qa/core/layout/data/ignore-top-margin-table.docx differ diff --git a/sw/qa/core/layout/data/ignore-top-margin.docx b/sw/qa/core/layout/data/ignore-top-margin.docx new file mode 100644 index 0000000000..d05a1358db Binary files /dev/null and b/sw/qa/core/layout/data/ignore-top-margin.docx differ diff --git a/sw/qa/core/layout/layact.cxx b/sw/qa/core/layout/layact.cxx index 8923d6b0e8..9de0c9ebfa 100644 --- a/sw/qa/core/layout/layact.cxx +++ b/sw/qa/core/layout/layact.cxx @@ -21,6 +21,7 @@ #include #include #include +#include namespace { @@ -108,6 +109,27 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInSection) CPPUNIT_ASSERT(pPage2); CPPUNIT_ASSERT(!pPage2->GetSortedObjs()); } + +CPPUNIT_TEST_FIXTURE(Test, testBadSplitSection) +{ + // Given a document with a section, containing 5 paragraphs: + createSwDoc("bad-split-section.odt"); + + // When laying out that document: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + + // Then make sure the entire section is on page 1: + auto pPage = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage); + auto pBody = pPage->FindBodyCont(); + CPPUNIT_ASSERT(pBody); + auto pSection = dynamic_cast(pBody->GetLastLower()); + CPPUNIT_ASSERT(pSection); + // Without the fix in place, it would have failed, the section was split between page 1 and page + // 2. + CPPUNIT_ASSERT(!pSection->GetFollow()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx b/sw/qa/core/objectpositioning/objectpositioning.cxx index bf560cbdaf..a1805bf450 100644 --- a/sw/qa/core/objectpositioning/objectpositioning.cxx +++ b/sw/qa/core/objectpositioning/objectpositioning.cxx @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include namespace { @@ -404,6 +408,50 @@ CPPUNIT_TEST_FIXTURE(Test, testFloatingTableOverlapCell) CPPUNIT_ASSERT(pPage1); CPPUNIT_ASSERT(!pPage1->GetNext()); } + +CPPUNIT_TEST_FIXTURE(Test, testDoNotMirrorRtlDrawObjsLayout) +{ + // Given a document with an RTL paragraph, Word-style compat flag is enabled: + createSwDoc(); + SwDoc* pDoc = getSwDoc(); + auto& rIDSA = pDoc->getIDocumentSettingAccess(); + rIDSA.set(DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS, true); + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + SwView& rView = pWrtShell->GetView(); + SfxItemSetFixed aSet(rView.GetPool()); + SvxFrameDirectionItem aDirection(SvxFrameDirection::Horizontal_RL_TB, RES_FRAMEDIR); + aSet.Put(aDirection); + pWrtShell->SetAttrSet(aSet, SetAttrMode::DEFAULT, nullptr, /*bParagraphSetting=*/true); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPageFrame = pLayout->Lower()->DynCastPageFrame(); + SwFrame* pBodyFrame = pPageFrame->GetLower(); + + // When inserting a graphic on the middle of the right margin: + SfxItemSet aFrameSet(pDoc->GetAttrPool(), svl::Items); + SwFormatAnchor aAnchor(RndStdIds::FLY_AT_CHAR); + aFrameSet.Put(aAnchor); + // Default margin is 1440, this is 1440/2. + SwFormatFrameSize aSize(SwFrameSize::Fixed, 720, 720); + aFrameSet.Put(aSize); + // This is 1440/4. + SwFormatHoriOrient aOrient(pBodyFrame->getFrameArea().Right() + 360); + aFrameSet.Put(aOrient); + Graphic aGrf; + pWrtShell->SwFEShell::Insert(OUString(), OUString(), &aGrf, &aFrameSet); + + // Then make sure that the image is on the right margin: + SwTwips nBodyRight = pBodyFrame->getFrameArea().Right(); + CPPUNIT_ASSERT(pPageFrame->GetSortedObjs()); + const SwSortedObjs& rPageObjs = *pPageFrame->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rPageObjs.size()); + const SwAnchoredObject* pAnchored = rPageObjs[0]; + Point aAnchoredCenter = pAnchored->GetDrawObj()->GetLastBoundRect().Center(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 11389 + // - Actual : 643 + // i.e. the graphic was on the left margin, not on the right margin. + CPPUNIT_ASSERT_GREATER(nBodyRight, aAnchoredCenter.getX()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/core/text/data/A011-charheight.rtf b/sw/qa/core/text/data/A011-charheight.rtf new file mode 100644 index 0000000000..4b56ecdd6a --- /dev/null +++ b/sw/qa/core/text/data/A011-charheight.rtf @@ -0,0 +1,27 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang3079\deflangfe3079\themelang3079\themelangfe0\themelangcs0 +{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2Times New Roman{\*\falt Arial};} +} +{\*\defchp \f0\fs22\lang3079\langfe1033\langfenp1033 } +{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 } +\noqfpromote +{\stylesheet +{\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\f0\fs23\lang3079\langfe1033\cgrid\langnp3079\langfenp1033 \snext0 \sqformat \spriority0 Normal;} +{\s15\ql \li0\ri0\widctlpar\tqc\tx4536\tqr\tx9072\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f0\fs23\lang3079\langfe1033\cgrid\langnp3079\langfenp1033 +\sbasedon0 \snext15 \slink16 \sunhideused header;} +{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink15 \slocked Kopfzeile Zchn;} +} +\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect +\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0 +\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1 +\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct +\asianbrkrule\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0 +{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0 + +\ltrpar \pard\plain \ltrpar\s15\qc \li0\ri0\widctlpar +\tqc\tx4536\tqr\tx9072\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f0\fs23\lang3079\langfe1033\cgrid\langnp3079\langfenp1033 {\rtlch\fcs1 \af0\afs16 \ltrch\fcs0 +\fs16 \line \line \line +\par \line +\par } +} diff --git a/sw/qa/core/text/data/Broken indent demo.odt b/sw/qa/core/text/data/Broken indent demo.odt new file mode 100644 index 0000000000..af5928bfa5 Binary files /dev/null and b/sw/qa/core/text/data/Broken indent demo.odt differ diff --git a/sw/qa/core/text/data/tdf156146.fodt b/sw/qa/core/text/data/tdf156146.fodt new file mode 100644 index 0000000000..1587cd945e --- /dev/null +++ b/sw/qa/core/text/data/tdf156146.fodt @@ -0,0 +1,281 @@ + + + 2023-06-14T01:10:01.4975110772024-04-18T18:00:26.359273842PT14M47S2ZetaOffice/7.4.8.0.0$Linux_X86_64 LibreOffice_project/b82f1163cc2fc696cf86209d94d838d04998350f + + + false + false + false + true + true + true + true + true + false + 0 + false + false + false + true + false + false + true + false + false + false + false + true + true + true + false + false + false + false + false + false + false + false + true + false + false + true + false + false + false + true + 0 + 1 + true + false + + high-resolution + true + + + false + false + true + false + true + true + true + false + true + + true + 910346 + + true + false + true + true + 0 + + false + false + false + true + false + true + 0 + false + false + false + false + true + false + false + false + + false + false + true + false + false + false + false + false + false + false + false + false + 811422 + false + false + false + false + false + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + He heard quiet steps behind him. That didn't bode well. Who could be following him this late at night and in this deadbeat part of town? And at this particular moment, just after he pulled off the big time and was making off with the greenbacks. Was there another crook who'd had the same idea, and was now watching him and waiting for a chance to grab the fruit of his labor? Or did the steps behind him mean that one of many law officers in town was on to him and just waiting to pounce and snap those cuffs on his wrists? He nervously looked all around. Suddenly he saw the alley. Like lightning he darted off to the left and disappeared between the two warehouses almost falling over the trash can lying in the middle of the sidewalk. He tried to nervously tap his way along in the inky darkness and + + + + + diff --git a/sw/qa/core/text/itrform2.cxx b/sw/qa/core/text/itrform2.cxx index 6d59140f97..860b2197f7 100644 --- a/sw/qa/core/text/itrform2.cxx +++ b/sw/qa/core/text/itrform2.cxx @@ -88,6 +88,24 @@ CPPUNIT_TEST_FIXTURE(Test, testFloattableLegacyWrapEmptyParagraph) CPPUNIT_ASSERT_EQUAL(static_cast(1), rPageObjs2.size()); } +CPPUNIT_TEST_FIXTURE(Test, testApplyTextAttrToEmptyLineAtEndOfParagraph) +{ + createSwDoc("A011-charheight.rtf"); + + calcLayout(); + + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage = dynamic_cast(pLayout->Lower()); + + SwContentFrame* pLastPara = pPage->FindLastBodyContent(); + // wrong was 449 (11.5pt) + CPPUNIT_ASSERT_EQUAL(static_cast(368), pLastPara->getFrameArea().Height()); + SwContentFrame* pFirstPara = pPage->FindFirstBodyContent(); + // wrong was 817 (11.5pt) + CPPUNIT_ASSERT_EQUAL(static_cast(736), pFirstPara->getFrameArea().Height()); +} + CPPUNIT_TEST_FIXTURE(Test, testFlyMinimalWrap) { // Given a document with a first page that has a shape and a table in it (not floating table), diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx index 690fc333af..f18c4fd531 100644 --- a/sw/qa/core/text/text.cxx +++ b/sw/qa/core/text/text.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,8 @@ #include #include #include +#include +#include /// Covers sw/source/core/text/ fixes. class SwCoreTextTest : public SwModelTestBase @@ -116,6 +119,65 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testLastBibliographyPdfExport) CPPUNIT_ASSERT(true); } +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf156146) +{ + createSwDoc("tdf156146.fodt"); + + uno::Reference const xLevels1( + getProperty>(getParagraph(1), "NumberingRules")); + uno::Reference const xNum1(xLevels1, uno::UNO_QUERY); + ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-700), props1["FirstLineIndent"].get()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1330), props1["IndentAt"].get()); + + // common style applies list-style-name and margin-left + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), + getProperty(getParagraph(1), "ParaFirstLineIndent")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaLeftMargin")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaRightMargin")); + + SwTextFrame* const pFrame(dynamic_cast( + static_cast(getSwDoc()->GetDocShell()->GetWrtShell()->GetLayout()->GetLower()) + ->FindFirstBodyContent())); + CPPUNIT_ASSERT(pFrame); + // this appears to be the only way to get the actual computed margins + SwTextSizeInfo info(pFrame); + SwTextMargin tm(pFrame, &info); + // this was wrong, 357 + CPPUNIT_ASSERT_EQUAL(SwTwips(0), tm.FirstLeft() - pFrame->getFrameArea().Left()); + // this was wrong, 754 + CPPUNIT_ASSERT_EQUAL(SwTwips(0), tm.Left() - pFrame->getFrameArea().Left()); +} + +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf159903) +{ + createSwDoc("Broken indent demo.odt"); + + uno::Reference const xLevels1( + getProperty>(getParagraph(1), "NumberingRules")); + uno::Reference const xNum1(xLevels1, uno::UNO_QUERY); + ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-4001), props1["FirstLineIndent"].get()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4001), props1["IndentAt"].get()); + + // common style applies list-style-name, parent style margin-left + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), + getProperty(getParagraph(1), "ParaFirstLineIndent")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaLeftMargin")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaRightMargin")); + + SwTextFrame* const pFrame(dynamic_cast( + static_cast(getSwDoc()->GetDocShell()->GetWrtShell()->GetLayout()->GetLower()) + ->FindFirstBodyContent())); + CPPUNIT_ASSERT(pFrame); + // this appears to be the only way to get the actual computed margins + SwTextSizeInfo info(pFrame); + SwTextMargin tm(pFrame, &info); + CPPUNIT_ASSERT_EQUAL(SwTwips(0), tm.FirstLeft() - pFrame->getFrameArea().Left()); + // left was wrong, was same as first + CPPUNIT_ASSERT_EQUAL(SwTwips(2268), tm.Left() - pFrame->getFrameArea().Left()); +} + CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf159336) { createSwDoc("tdf159336.odt"); diff --git a/sw/qa/core/txtnode/data/plain-content-control-copy.docx b/sw/qa/core/txtnode/data/plain-content-control-copy.docx new file mode 100644 index 0000000000..80fecae26d Binary files /dev/null and b/sw/qa/core/txtnode/data/plain-content-control-copy.docx differ diff --git a/sw/qa/core/txtnode/txtnode.cxx b/sw/qa/core/txtnode/txtnode.cxx index c2df8a407e..be4d971902 100644 --- a/sw/qa/core/txtnode/txtnode.cxx +++ b/sw/qa/core/txtnode/txtnode.cxx @@ -539,6 +539,29 @@ CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testSplitFlyAnchorSplit) CPPUNIT_ASSERT_EQUAL(OUString("PortionType::Fly"), aPortionType); } +CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testPlainContentControlCopy) +{ + // Given a document with a plain text content control, all text selected and copied to the + // clipboard: + createSwDoc("plain-content-control-copy.docx"); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->SelAll(); + { + rtl::Reference xTransfer = new SwTransferable(*pWrtShell); + xTransfer->Copy(); + } + + // When closing that document, then make sure we don't crash on shutdown: + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + uno::Reference xFrame(xModel->getCurrentController()->getFrame(), + uno::UNO_QUERY); + // Without the accompanying fix in place, this resulted in an assertion failure, a char style + // still had clients by the time it was deleted. + xFrame->close(false); + mxComponent.clear(); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx index f654821acf..fb45d5c8e9 100644 --- a/sw/qa/extras/odfexport/odfexport2.cxx +++ b/sw/qa/extras/odfexport/odfexport2.cxx @@ -885,9 +885,9 @@ DECLARE_ODFEXPORT_TEST(testTdf114287, "tdf114287.odt") xmlDocUniquePtr pXmlDoc = parseLayoutDump(); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "left"_ostr, "2268"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "right"_ostr, "11339"); - // the problem was that the list style name of the list must override the - // paragraph style even though it's the same list style - assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "left"_ostr, "357"); + // the list style name of the list is the same as the list style name of the + // paragraph, but in any case the margins of the paragraph take precedence + assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "left"_ostr, "2268"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "right"_ostr, "11339"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds"_ostr, "left"_ostr, "357"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds"_ostr, "right"_ostr, "11339"); diff --git a/sw/qa/extras/ooxmlexport/data/StyleRef-DE.docx b/sw/qa/extras/ooxmlexport/data/StyleRef-DE.docx new file mode 100644 index 0000000000..800ef6413f Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/StyleRef-DE.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 49d974b011..dee26b595c 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -229,7 +229,7 @@ CPPUNIT_TEST_FIXTURE(Test, testParaStyleNumLevel) // - Expected: 1 // - Actual : 0 // i.e. a custom list level in a para style was lost on import+export. - assertXPath(pXmlDoc, "/w:styles/w:style[@w:styleId='Mystyle']/w:pPr/w:numPr/w:ilvl"_ostr, "val"_ostr, "1"); + assertXPath(pXmlDoc, "/w:styles/w:style[@w:styleId='mystyle']/w:pPr/w:numPr/w:ilvl"_ostr, "val"_ostr, "1"); } CPPUNIT_TEST_FIXTURE(Test, testClearingBreak) @@ -741,6 +741,16 @@ DECLARE_OOXMLEXPORT_TEST(testTdf153082_comma, "custom-styles-TOC-comma.docx") CPPUNIT_ASSERT(tocContent.indexOf("Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.") != -1); } +DECLARE_OOXMLEXPORT_TEST(testTdf160402, "StyleRef-DE.docx") +{ + xmlDocUniquePtr pLayout = parseLayoutDump(); + assertXPath(pLayout, "/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Heading 1"); + assertXPath(pLayout, "/root/page[2]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."); + assertXPath(pLayout, "/root/page[3]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Cras faucibus condimentum odio. Sed ac ligula. Aliquam at eros."); + assertXPath(pLayout, "/root/page[4]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."); + assertXPath(pLayout, "/root/page[5]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Aenean nec lorem. In porttitor. Donec laoreet nonummy augue."); +} + DECLARE_OOXMLEXPORT_TEST(testTdf142407, "tdf142407.docx") { uno::Reference xPageStyles = getStyles("PageStyles"); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index ad3bba49df..91f0deb4bb 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -563,7 +563,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf104061_tableSectionColumns,"tdf104061_tableSecti //tdf#95114 - follow style is Text Body - DOCX test uno::Reference< beans::XPropertySet > properties(getStyles("ParagraphStyles")->getByName("annotation subject"), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(OUString("annotation text"), getProperty(properties, "FollowStyle")); + CPPUNIT_ASSERT_EQUAL(OUString("Marginalia"), getProperty(properties, "FollowStyle")); } DECLARE_OOXMLEXPORT_TEST(testTdf46940_dontEquallyDistributeColumns, "tdf46940_dontEquallyDistributeColumns.docx") @@ -690,7 +690,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf109310_endnoteStyleForMSO) xmlDocUniquePtr pXmlDoc = parseExport("word/endnotes.xml"); // Check w:rStyle element has w:val attribute - note that w: is not specified for attribute assertXPath(pXmlDoc, "/w:endnotes/w:endnote[@w:id='2']/w:p/w:r[1]/w:rPr/w:rStyle"_ostr, "val"_ostr, - "EndnoteCharacters"); + "EndnoteCharacters1"); } CPPUNIT_TEST_FIXTURE(Test, testTdf103389) diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index a97d8e8b84..66faba5f3e 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -177,6 +177,8 @@ CPPUNIT_TEST_FIXTURE(Test, testFDO77715) xTOC->update(); OUString const tocContent(xTOC->getAnchor()->getString()); CPPUNIT_ASSERT(tocContent.startsWith("National Infrastructure Bank Aff/Neg Index")); + // check that 1st paragraph has outline level 1 + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty(getParagraph(1), "OutlineLevel")); } CPPUNIT_TEST_FIXTURE(Test, testTOCFlag_u) diff --git a/sw/qa/extras/uiwriter/data/pagebreak-source.fodt b/sw/qa/extras/uiwriter/data/pagebreak-source.fodt new file mode 100644 index 0000000000..cb72fea62a --- /dev/null +++ b/sw/qa/extras/uiwriter/data/pagebreak-source.fodt @@ -0,0 +1,131 @@ + + + 2024-03-05T16:51:41.5265948182024-03-05T17:24:50.151189313PT24M14S5CIB_OfficeDev/6.4.0.24$Linux_X86_64 LibreOffice_project/2b8ce275a2d1aae9319dfc266e677412b611101d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sw/qa/extras/uiwriter/data/pagebreak-target.fodt b/sw/qa/extras/uiwriter/data/pagebreak-target.fodt new file mode 100644 index 0000000000..1219cdd95e --- /dev/null +++ b/sw/qa/extras/uiwriter/data/pagebreak-target.fodt @@ -0,0 +1,137 @@ + + + 2024-03-05T16:57:01.1791494012024-03-05T16:58:35.972978544PT1M35S2CIB_OfficeDev/6.4.0.24$Linux_X86_64 LibreOffice_project/2b8ce275a2d1aae9319dfc266e677412b611101d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sw/qa/extras/uiwriter/data/stylewithlistandindents.fodt b/sw/qa/extras/uiwriter/data/stylewithlistandindents.fodt new file mode 100644 index 0000000000..afb7ae06aa --- /dev/null +++ b/sw/qa/extras/uiwriter/data/stylewithlistandindents.fodt @@ -0,0 +1,182 @@ + + + 2024-05-16T18:27:43.9131312122024-05-16T18:30:43.721654337PT3M1LibreOfficeDev/24.8.0.0.alpha0$Linux_X86_64 LibreOffice_project/a2e7a65b22857abc945af33c7673d9d8b50688d5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Item + + + more + + + + + + \ No newline at end of file diff --git a/sw/qa/extras/uiwriter/data/table-in-table.fodt b/sw/qa/extras/uiwriter/data/table-in-table.fodt new file mode 100644 index 0000000000..e055d343b8 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/table-in-table.fodt @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sw/qa/extras/uiwriter/data/tdf160842.fodt b/sw/qa/extras/uiwriter/data/tdf160842.fodt new file mode 100644 index 0000000000..217b9c1a95 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/tdf160842.fodt @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQI12P2Ytilf46NeWX3 + a804HgAg7QTAqXPBTwAAAABJRU5ErkJggg== + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing. + + + + + + + + diff --git a/sw/qa/extras/uiwriter/data/tdf161172.fodt b/sw/qa/extras/uiwriter/data/tdf161172.fodt new file mode 100644 index 0000000000..08cea575cc --- /dev/null +++ b/sw/qa/extras/uiwriter/data/tdf161172.fodt @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + foo + + + + + \ No newline at end of file diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index 21b7358c3d..b6913d4f6b 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -318,6 +318,127 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf149548) dispatchCommand(mxComponent, ".uno:Paste", {}); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testPasteTableAtFlyAnchor) +{ + createSwDoc(); + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR); + anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint()); + SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items); + flySet.Put(anchor); + SwFlyFrameFormat const* pFly = dynamic_cast( + pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true)); + CPPUNIT_ASSERT(pFly != nullptr); + CPPUNIT_ASSERT(pFly->GetFrame() != nullptr); + pWrtShell->SelFlyGrabCursor(); + pWrtShell->GetDrawView()->UnmarkAll(); + CPPUNIT_ASSERT(pWrtShell->GetCurrFlyFrame() != nullptr); + + // insert table in fly + SwInsertTableOptions tableOpt(SwInsertTableFlags::DefaultBorder, 0); + pWrtShell->InsertTable(tableOpt, 2, 2); + + // select table + pWrtShell->SelAll(); + + dispatchCommand(mxComponent, ".uno:Copy", {}); + + // move cursor back to body + pWrtShell->ClearMark(); + pWrtShell->SttEndDoc(/*bStt=*/true); + CPPUNIT_ASSERT(!pWrtShell->GetCurrFlyFrame()); + + dispatchCommand(mxComponent, ".uno:Paste", {}); + + pWrtShell->SttEndDoc(/*bStt=*/true); + CPPUNIT_ASSERT(pWrtShell->IsCursorInTable()); + CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->GetNode().FindTableNode()); + + pWrtShell->Undo(); + + pWrtShell->SttEndDoc(/*bStt=*/true); + CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable()); + CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->GetNode().FindTableNode()); + + // the problem was that Redo moved the fly anchor into the first table cell + pWrtShell->Redo(); + + pWrtShell->SttEndDoc(/*bStt=*/true); + CPPUNIT_ASSERT(pWrtShell->IsCursorInTable()); + CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->GetNode().FindTableNode()); + + pWrtShell->Undo(); + + pWrtShell->SttEndDoc(/*bStt=*/true); + CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable()); + CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->GetNode().FindTableNode()); +} + +CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCopyPastePageBreak) +{ + { + createSwDoc("pagebreak-source.fodt"); + SwDoc* pDoc = getSwDoc(); + + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); + + pWrtShell->SelAll(); + dispatchCommand(mxComponent, ".uno:Copy", {}); + + mxComponent->dispose(); + mxComponent.clear(); + } + + createSwDoc("pagebreak-target.fodt"); + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + CPPUNIT_ASSERT_EQUAL(1, getParagraphs()); + CPPUNIT_ASSERT_EQUAL(OUString("WithMargin"), getProperty(getParagraph(1), "PageDescName")); + CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName()); + // page style WithMargin is used + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); + + dispatchCommand(mxComponent, ".uno:Paste", {}); + + CPPUNIT_ASSERT_EQUAL(2, getParagraphs()); + CPPUNIT_ASSERT_EQUAL(OUString("WithMargin"), getProperty(getParagraph(1), "PageDescName")); + CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetSections().size()); + CPPUNIT_ASSERT_EQUAL(OUString("SourceSection"), pWrtShell->GetCurrSection()->GetSectionName()); + // the problem was that there was a page break now + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // page style WithMargin is used + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); + + pWrtShell->Undo(); + CPPUNIT_ASSERT_EQUAL(1, getParagraphs()); + CPPUNIT_ASSERT_EQUAL(OUString("WithMargin"), getProperty(getParagraph(1), "PageDescName")); + CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName()); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // page style WithMargin is used + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); + + pWrtShell->Redo(); + CPPUNIT_ASSERT_EQUAL(2, getParagraphs()); + CPPUNIT_ASSERT_EQUAL(OUString("WithMargin"), getProperty(getParagraph(1), "PageDescName")); + CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetSections().size()); + CPPUNIT_ASSERT_EQUAL(OUString("SourceSection"), pWrtShell->GetCurrSection()->GetSectionName()); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // page style WithMargin is used + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); + + pWrtShell->Undo(); + CPPUNIT_ASSERT_EQUAL(1, getParagraphs()); + CPPUNIT_ASSERT_EQUAL(OUString("WithMargin"), getProperty(getParagraph(1), "PageDescName")); + CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName()); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + // page style WithMargin is used + CPPUNIT_ASSERT_EQUAL(tools::Long(5669), pWrtShell->GetLayout()->GetLower()->getFramePrintArea().Top()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testBookmarkCopy) { createSwDoc(); diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index af51954487..15852718f4 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -459,7 +459,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf134250) dispatchCommand(mxComponent, ".uno:Paste", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount()); // this would crash in 2 different ways dispatchCommand(mxComponent, ".uno:Undo", {}); @@ -474,7 +474,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf134250) dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount()); dispatchCommand(mxComponent, ".uno:Undo", {}); @@ -486,7 +486,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf134250) dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf134436) diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 3027c65855..ba8d03ae7e 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -1333,7 +1333,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf131963) { createSwDoc("tdf131963.docx"); - CPPUNIT_ASSERT_EQUAL(11, getPages()); + CPPUNIT_ASSERT(11 == getPages() || 12 == getPages()); dispatchCommand(mxComponent, ".uno:SelectAll", {}); @@ -1348,7 +1348,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf131963) // Without the fix in place, this test would have crashed here // tdf#133169: without the fix in place, it would have been 2 instead of 11 - CPPUNIT_ASSERT_EQUAL(11, getPages()); + CPPUNIT_ASSERT(11 == getPages() || 12 == getPages()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf132596) @@ -1516,7 +1516,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135733) dispatchCommand(mxComponent, ".uno:Paste", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount()); - CPPUNIT_ASSERT_EQUAL(1, getPages()); + // the table is inserted before the first paragraph, which has a pagedesc + CPPUNIT_ASSERT_EQUAL(2, getPages()); CPPUNIT_ASSERT_EQUAL(2, getShapes()); dispatchCommand(mxComponent, ".uno:Undo", {}); diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx index 5b4140e029..8e67d26e46 100644 --- a/sw/qa/extras/uiwriter/uiwriter6.cxx +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -1406,6 +1411,158 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf154771_MovingMultipleColumns) CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1->getColumns()->getCount()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf44773) +{ + // allow resizing table rows, if cursor outside the table + createSwDoc(); + SwDoc* pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + // insert an empty paragraph + pWrtShell->SplitNode(); + + // create a table + SwInsertTableOptions TableOpt(SwInsertTableFlags::DefaultBorder, 0); + (void)&pWrtShell->InsertTable(TableOpt, 2, 1); + + // the cursor is not inside the table + CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable()); + + uno::Reference xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xTableNames = xTablesSupplier->getTextTables(); + CPPUNIT_ASSERT(xTableNames->hasByName("Table1")); + uno::Reference xTable1(xTableNames->getByName("Table1"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1->getRows()->getCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable1->getColumns()->getCount()); + + Scheduler::ProcessEventsToIdle(); + + // set table row height by drag & drop + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + + SwFrame* pPage = pLayout->Lower(); + SwFrame* pBody = pPage->GetLower(); + SwFrame* pTable = pBody->GetLower()->GetNext(); + SwFrame* pRow1 = pTable->GetLower(); + CPPUNIT_ASSERT(pRow1->IsRowFrame()); + SwFrame* pCellA1 = pRow1->GetLower(); + const SwRect& rCellA1Rect = pCellA1->getFrameArea(); + auto nRowHeight = rCellA1Rect.Height(); + // select center of the bottom border of the first table cell + Point ptFrom(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, rCellA1Rect.Top() + nRowHeight); + // double the row height + Point ptTo(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, rCellA1Rect.Top() + 2 * nRowHeight); + vcl::Window& rEditWin = pDoc->GetDocShell()->GetView()->GetEditWin(); + Point aFrom = rEditWin.LogicToPixel(ptFrom); + MouseEvent aClickEvent(aFrom, 1, MouseEventModifiers::SIMPLECLICK | MouseEventModifiers::SELECT, + MOUSE_LEFT); + rEditWin.MouseButtonDown(aClickEvent); + Point aTo = rEditWin.LogicToPixel(ptTo); + MouseEvent aMoveEvent(aTo, 1, MouseEventModifiers::SIMPLECLICK | MouseEventModifiers::SELECT, + MOUSE_LEFT); + TrackingEvent aTEvt(aMoveEvent, TrackingEventFlags::Repeat); + // drag & drop of cell border inside the document (and outside the table) + // still based on the ruler code, use that to simulate dragging + pDoc->GetDocShell()->GetView()->GetVRuler().Tracking(aTEvt); + TrackingEvent aTEvt2(aMoveEvent, TrackingEventFlags::End); + pDoc->GetDocShell()->GetView()->GetVRuler().Tracking(aTEvt2); + Scheduler::ProcessEventsToIdle(); + rEditWin.CaptureMouse(); + rEditWin.ReleaseMouse(); + + // this was 396 (not modified row height previously) + CPPUNIT_ASSERT_EQUAL(tools::Long(810), pCellA1->getFrameArea().Height()); +} + +CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf160842) +{ + createSwDoc("tdf160842.fodt"); + SwDoc* pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + // the cursor is not in the table + CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable()); + + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage = dynamic_cast(pLayout->Lower()); + CPPUNIT_ASSERT(pPage); + const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rPageObjs.size()); + auto pPageFly = dynamic_cast(rPageObjs[0]); + CPPUNIT_ASSERT(pPageFly); + auto pTable = dynamic_cast(pPageFly->GetLower()); + CPPUNIT_ASSERT(pTable); + auto pRow2 = pTable->GetLower()->GetNext(); + CPPUNIT_ASSERT(pRow2->IsRowFrame()); + auto pCellA2 = pRow2->GetLower(); + CPPUNIT_ASSERT(pCellA2); + const SwRect& rCellA2Rect = pCellA2->getFrameArea(); + auto nRowHeight = rCellA2Rect.Height(); + // select center of the bottom cell + Point ptFrom(rCellA2Rect.Left() + rCellA2Rect.Width() / 2, rCellA2Rect.Top() + nRowHeight / 2); + vcl::Window& rEditWin = pDoc->GetDocShell()->GetView()->GetEditWin(); + Point aFrom = rEditWin.LogicToPixel(ptFrom); + MouseEvent aClickEvent(aFrom, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT); + rEditWin.MouseButtonDown(aClickEvent); + rEditWin.MouseButtonUp(aClickEvent); + + // the cursor is in the table + CPPUNIT_ASSERT(pWrtShell->IsCursorInTable()); +} + +CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf160836) +{ + createSwDoc("tdf160842.fodt"); + SwDoc* pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + // set table row height by drag & drop at images cropped by the fixed row height + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage = dynamic_cast(pLayout->Lower()); + CPPUNIT_ASSERT(pPage); + const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rPageObjs.size()); + auto pPageFly = dynamic_cast(rPageObjs[0]); + CPPUNIT_ASSERT(pPageFly); + auto pTable = dynamic_cast(pPageFly->GetLower()); + CPPUNIT_ASSERT(pTable); + auto pRow1 = pTable->GetLower(); + CPPUNIT_ASSERT(pRow1->IsRowFrame()); + auto pCellA1 = pRow1->GetLower(); + CPPUNIT_ASSERT(pCellA1); + const SwRect& rCellA1Rect = pCellA1->getFrameArea(); + auto nRowHeight = rCellA1Rect.Height(); + // select center of the bottom border of the first table cell + Point ptFrom(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, rCellA1Rect.Top() + nRowHeight); + // halve the row height + Point ptTo(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, rCellA1Rect.Top() + 0.5 * nRowHeight); + vcl::Window& rEditWin = pDoc->GetDocShell()->GetView()->GetEditWin(); + Point aFrom = rEditWin.LogicToPixel(ptFrom); + MouseEvent aClickEvent(aFrom, 1, MouseEventModifiers::SIMPLECLICK | MouseEventModifiers::SELECT, + MOUSE_LEFT); + rEditWin.MouseButtonDown(aClickEvent); + Point aTo = rEditWin.LogicToPixel(ptTo); + MouseEvent aMoveEvent(aTo, 1, MouseEventModifiers::SIMPLECLICK | MouseEventModifiers::SELECT, + MOUSE_LEFT); + TrackingEvent aTEvt(aMoveEvent, TrackingEventFlags::Repeat); + // drag & drop of cell border inside the document (and outside the table) + // still based on the ruler code, use that to simulate dragging + pDoc->GetDocShell()->GetView()->GetVRuler().Tracking(aTEvt); + TrackingEvent aTEvt2(aMoveEvent, TrackingEventFlags::End); + pDoc->GetDocShell()->GetView()->GetVRuler().Tracking(aTEvt2); + Scheduler::ProcessEventsToIdle(); + rEditWin.CaptureMouse(); + rEditWin.ReleaseMouse(); + + // this was 3910 (not modified row height previously) + CPPUNIT_ASSERT_EQUAL(tools::Long(1980), pCellA1->getFrameArea().Height()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf115132) { createSwDoc(); diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx b/sw/qa/extras/uiwriter/uiwriter8.cxx index 4fa027b051..60b1bd8e9c 100644 --- a/sw/qa/extras/uiwriter/uiwriter8.cxx +++ b/sw/qa/extras/uiwriter/uiwriter8.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -870,6 +871,126 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf116315) } } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testInsertAutoTextIntoListFromParaStyle) +{ + createSwDoc("stylewithlistandindents.fodt"); + SwDoc* const pDoc = getSwDoc(); + SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + pWrtShell->FwdPara(); + pWrtShell->EndPara(/*bSelect=*/false); + // expands autotext (via F3) + pWrtShell->Insert(" jacr"); + + SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); + pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F3); + Scheduler::ProcessEventsToIdle(); + + pWrtShell->SttEndDoc(/*bStt=*/true); + pWrtShell->FwdPara(); + + SwNumRule* pNumRule; + SvxTextLeftMarginItem const* pTextLeftMargin; + SvxFirstLineIndentItem const* pFirstLineIndent; + + { + SwTextNode& rNode{ *pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() }; + // numrule from paragraph style, but not from direct formatting + auto pSet{ rNode.GetpSwAttrSet() }; + CPPUNIT_ASSERT(pSet); + // list id was set + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_LIST_ID, false)); + // the numrule is set on the paragraph style, not on the paragraph + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_PARATR_NUMRULE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_NUMRULE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, + pSet->GetItemState(RES_MARGIN_FIRSTLINE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_FIRSTLINE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_MARGIN_TEXTLEFT, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_TEXTLEFT, true)); + CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, rNode.GetTextColl()->GetName()); + CPPUNIT_ASSERT_EQUAL(u"Item We confirm receipt of your application material."_ustr, + rNode.GetText()); + pNumRule = rNode.GetNumRule(); + pTextLeftMargin = &rNode.GetAttr(RES_MARGIN_TEXTLEFT); + pFirstLineIndent = &rNode.GetAttr(RES_MARGIN_FIRSTLINE); + } + + pWrtShell->FwdPara(); + + { + SwTextNode& rNode{ *pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() }; + auto pSet{ rNode.GetpSwAttrSet() }; + CPPUNIT_ASSERT(pSet); + // list id was set + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_LIST_ID, false)); + // middle paragraph was pasted - has numrule and indents applied directly + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_NUMRULE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_FIRSTLINE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_TEXTLEFT, false)); + CPPUNIT_ASSERT_EQUAL(u"Default Paragraph Style"_ustr, rNode.GetTextColl()->GetName()); + CPPUNIT_ASSERT(rNode.GetText().startsWith("As more applicants applied")); + CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule()); + CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(), + rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft()); + CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(), + rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset()); + } + + pWrtShell->FwdPara(); + + { + SwTextNode& rNode{ *pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() }; + // numrule from paragraph style, but not from direct formatting + auto pSet{ rNode.GetpSwAttrSet() }; + CPPUNIT_ASSERT(pSet); + // list id was set + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_LIST_ID, false)); + // the numrule is set on the paragraph style, not on the paragraph + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_PARATR_NUMRULE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_NUMRULE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, + pSet->GetItemState(RES_MARGIN_FIRSTLINE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_FIRSTLINE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_MARGIN_TEXTLEFT, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_TEXTLEFT, true)); + CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, rNode.GetTextColl()->GetName()); + CPPUNIT_ASSERT(rNode.GetText().endsWith("as soon as we have come to a decision.")); + CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule()); + CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(), + rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft()); + CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(), + rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset()); + } + + pWrtShell->FwdPara(); + + { + SwTextNode& rNode{ *pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() }; + // numrule from paragraph style, but not from direct formatting + auto pSet{ rNode.GetpSwAttrSet() }; + CPPUNIT_ASSERT(pSet); + // list id was set + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_LIST_ID, false)); + // the numrule is set on the paragraph style, not on the paragraph + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_PARATR_NUMRULE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_PARATR_NUMRULE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, + pSet->GetItemState(RES_MARGIN_FIRSTLINE, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_FIRSTLINE, true)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, pSet->GetItemState(RES_MARGIN_TEXTLEFT, false)); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, pSet->GetItemState(RES_MARGIN_TEXTLEFT, true)); + CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, rNode.GetTextColl()->GetName()); + CPPUNIT_ASSERT_EQUAL(u"more"_ustr, rNode.GetText()); // pre-exising list item + CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule()); + CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(), + rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft()); + CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(), + rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset()); + } +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf144364) { createSwDoc(); diff --git a/sw/qa/extras/uiwriter/uiwriter9.cxx b/sw/qa/extras/uiwriter/uiwriter9.cxx index 3772955dd9..2389aa6371 100644 --- a/sw/qa/extras/uiwriter/uiwriter9.cxx +++ b/sw/qa/extras/uiwriter/uiwriter9.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -200,6 +201,61 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf159816) xTransfer->PrivateDrop(*pWrtShell, ptTo, /*bMove=*/true, /*bXSelection=*/true); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf160898) +{ + // Given a document with a 1-cell table in another 1-cell table: + createSwDoc("table-in-table.fodt"); + SwXTextDocument* pXTextDocument = dynamic_cast(mxComponent.get()); + SwDocShell* pDocShell = pXTextDocument->GetDocShell(); + 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, 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(para, u"ParaStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty(para, u"NumberingStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Num1_lvl1_1"_ustr, getProperty(para, u"ListLabelString"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty(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(para, u"ParaStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty(para, u"NumberingStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Num1_lvl2_1"_ustr, getProperty(para, u"ListLabelString"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty(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(para, u"ParaStyleName"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Num_1"_ustr, getProperty(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(para, u"ListLabelString"_ustr)); + // Without the fix, this would fail with + // - Expected: 0 + // - Actual : 1 + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty(para, u"NumberingLevel"_ustr)); +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/extras/unowriter/data/tdf161035.fodt b/sw/qa/extras/unowriter/data/tdf161035.fodt new file mode 100644 index 0000000000..8f1d53b083 --- /dev/null +++ b/sw/qa/extras/unowriter/data/tdf161035.fodt @@ -0,0 +1,9 @@ + + + + + + Lorem ipsum. + + + \ No newline at end of file diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx index 80b9e556f7..7175e702d7 100644 --- a/sw/qa/extras/unowriter/unowriter.cxx +++ b/sw/qa/extras/unowriter/unowriter.cxx @@ -1222,6 +1222,33 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf160278) CPPUNIT_ASSERT_EQUAL(u"12test"_ustr, xText->getString()); } +CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf161035) +{ + // Given a paragraph with a bookmark: + createSwDoc("tdf161035.fodt"); + auto xModel = mxComponent.queryThrow(); + + // Create a text view cursor in the paragraph. + auto xController = xModel->getCurrentController().queryThrow(); + auto xViewCursor = xController->getViewCursor(); + CPPUNIT_ASSERT(xViewCursor); + auto xText = xViewCursor->getText(); + CPPUNIT_ASSERT(xText); + // Create a text cursor from the text view cursor, and move it to the end of the paragraph + auto xTextCursor = xText->createTextCursorByRange(xViewCursor); + CPPUNIT_ASSERT(xTextCursor); + xTextCursor->gotoEnd(false); + // Get the first paragraph portion from the text cursor + auto xParaEnum = xTextCursor.queryThrow()->createEnumeration(); + CPPUNIT_ASSERT(xParaEnum); + auto xPara = xParaEnum->nextElement().queryThrow(); + // Try to enumerate text portions. Without the fix, it would fail an assertion in debug builds, + // and hang in release builds, because the paragraph portion started after the bookmark, and + // so the bookmark wasn't processed (expectedly): + auto xRunEnum = xPara->createEnumeration(); + CPPUNIT_ASSERT(!xRunEnum->hasMoreElements()); // Empty enumeration for empty selection +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/ww8export/data/draw-obj-rtl-no-mirror-vml.docx b/sw/qa/extras/ww8export/data/draw-obj-rtl-no-mirror-vml.docx new file mode 100644 index 0000000000..3b291901f7 Binary files /dev/null and b/sw/qa/extras/ww8export/data/draw-obj-rtl-no-mirror-vml.docx differ diff --git a/sw/qa/extras/ww8export/ww8export4.cxx b/sw/qa/extras/ww8export/ww8export4.cxx index d31bf17a31..3fb0ae7b03 100644 --- a/sw/qa/extras/ww8export/ww8export4.cxx +++ b/sw/qa/extras/ww8export/ww8export4.cxx @@ -252,6 +252,30 @@ CPPUNIT_TEST_FIXTURE(Test, testLegalNumbering) verify(); } +CPPUNIT_TEST_FIXTURE(Test, testDOCExportDoNotMirrorRtlDrawObjs) +{ + // Given a document with a shape, anchored in an RTL paragraph, loaded from DOCX: + createSwDoc("draw-obj-rtl-no-mirror-vml.docx"); + + // When saving that to DOC: + saveAndReload(mpFilter); + + // Then make sure the shape is on the right margin: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + sal_Int32 nPageRight = getXPath(pXmlDoc, "//page/infos/bounds"_ostr, "right"_ostr).toInt32(); + sal_Int32 nBodyRight = getXPath(pXmlDoc, "//body/infos/bounds"_ostr, "right"_ostr).toInt32(); + sal_Int32 nShapeLeft + = getXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds"_ostr, "left"_ostr).toInt32(); + CPPUNIT_ASSERT_GREATER(nBodyRight, nShapeLeft); + sal_Int32 nShapeRight + = getXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds"_ostr, "right"_ostr).toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected less than: 12523 + // - Actual : 12536 + // i.e. the shape was outside of the page right margin area, due to an unwanted mapping. + CPPUNIT_ASSERT_LESS(nPageRight, nShapeRight); +} + DECLARE_WW8EXPORT_TEST(testNonInlinePageBreakFirstLine, "nonInlinePageBreakFirstLine.doc") { SwDoc* pDoc = getSwDoc(); diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index d38d0bbfc9..3e6d9c93d5 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -560,6 +560,30 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testAllowTextAfterFloatingTableBreak) CPPUNIT_ASSERT(bAllowTextAfterFloatingTableBreak); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testDoNotMirrorRtlDrawObjs) +{ + // Given an empty document: + createSwDoc(); + + // When checking the state of the DoNotMirrorRtlDrawObjs compat flag: + uno::Reference xDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xSettings( + xDocument->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY); + bool bDoNotMirrorRtlDrawObjs{}; + // Without the accompanying fix in place, this test would have failed with: + // An uncaught exception of type com.sun.star.beans.UnknownPropertyException + // i.e. the compat flag was not recognized. + xSettings->getPropertyValue("DoNotMirrorRtlDrawObjs") >>= bDoNotMirrorRtlDrawObjs; + // Then make sure it's false by default: + CPPUNIT_ASSERT(!bDoNotMirrorRtlDrawObjs); + + // And when setting DoNotMirrorRtlDrawObjs=true: + xSettings->setPropertyValue("DoNotMirrorRtlDrawObjs", uno::Any(true)); + // Then make sure it gets enabled: + xSettings->getPropertyValue("DoNotMirrorRtlDrawObjs") >>= bDoNotMirrorRtlDrawObjs; + CPPUNIT_ASSERT(bDoNotMirrorRtlDrawObjs); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/writerfilter/cppunittests/filter/WriterFilter.cxx b/sw/qa/writerfilter/cppunittests/filter/WriterFilter.cxx new file mode 100644 index 0000000000..10b8cab57a --- /dev/null +++ b/sw/qa/writerfilter/cppunittests/filter/WriterFilter.cxx @@ -0,0 +1,57 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Tests for sw/source/writerfilter/filter/WriterFilter.cxx. +class Test : public UnoApiXmlTest +{ +public: + Test() + : UnoApiXmlTest("/sw/qa/writerfilter/cppunittests/filter/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testDoNotMirrorRtlDrawObjs) +{ + // Given a document with a shape, anchored in an RTL paragraph: + // When loading that document: + loadFromFile(u"draw-obj-rtl-no-mirror.docx"); + + // Then make sure the shape is on the right margin: + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + css::uno::Reference xDumper(xModel->getCurrentController(), uno::UNO_QUERY); + OString aDump = xDumper->dump("layout").toUtf8(); + auto pCharBuffer = reinterpret_cast(aDump.getStr()); + xmlDocUniquePtr pXmlDoc(xmlParseDoc(pCharBuffer)); + sal_Int32 nBodyRight = getXPath(pXmlDoc, "//body/infos/bounds"_ostr, "right"_ostr).toInt32(); + sal_Int32 nShapeLeft + = getXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds"_ostr, "left"_ostr).toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 11083 + // - Actual : 722 + // i.e. the shape was on the left margin. + CPPUNIT_ASSERT_GREATER(nBodyRight, nShapeLeft); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/writerfilter/cppunittests/filter/data/draw-obj-rtl-no-mirror.docx b/sw/qa/writerfilter/cppunittests/filter/data/draw-obj-rtl-no-mirror.docx new file mode 100644 index 0000000000..7988384b2c Binary files /dev/null and b/sw/qa/writerfilter/cppunittests/filter/data/draw-obj-rtl-no-mirror.docx differ -- cgit v1.2.3