summaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/crsrsh.hxx4
-rw-r--r--sw/inc/ndarr.hxx9
-rw-r--r--sw/inc/node.hxx2
-rw-r--r--sw/inc/pagedesc.hxx6
-rw-r--r--sw/qa/core/layout/data/floattable-wrapped-by-table-nested.docxbin0 -> 28111 bytes
-rw-r--r--sw/qa/core/layout/tabfrm.cxx14
-rw-r--r--sw/qa/core/unocore/unocore.cxx27
-rw-r--r--sw/qa/extras/accessibility/dialogs.cxx2
-rw-r--r--sw/qa/extras/fodfexport/fodfexport.cxx36
-rw-r--r--sw/qa/extras/htmlexport/data/char_border_and_font_color.fodt14
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx21
-rw-r--r--sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt15
-rw-r--r--sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt90
-rw-r--r--sw/qa/extras/layout/layout3.cxx68
-rw-r--r--sw/qa/extras/odfexport/data/bookmark_order.fodt9
-rw-r--r--sw/qa/extras/odfexport/odfexport2.cxx96
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf158597.docxbin0 -> 12719 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport21.cxx258
-rw-r--r--sw/qa/extras/rtfexport/data/fdo55504-1-min.rtf49
-rw-r--r--sw/qa/extras/rtfexport/data/piccrop.rtf74
-rw-r--r--sw/qa/extras/rtfexport/data/tdf159824_axialGradient.odtbin0 -> 11830 bytes
-rw-r--r--sw/qa/extras/rtfexport/rtfexport2.cxx3
-rw-r--r--sw/qa/extras/rtfexport/rtfexport8.cxx84
-rw-r--r--sw/qa/extras/rtfimport/data/tdf153196.rtf114
-rw-r--r--sw/qa/extras/rtfimport/rtfimport.cxx20
-rw-r--r--sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt20
-rw-r--r--sw/qa/extras/uiwriter/data/hiddenSectionsAroundPageBreak.fodt21
-rw-r--r--sw/qa/extras/uiwriter/uiwriter4.cxx15
-rw-r--r--sw/qa/extras/uiwriter/uiwriter9.cxx78
-rw-r--r--sw/qa/extras/ww8export/data/listWithLgl.docbin0 -> 23552 bytes
-rw-r--r--sw/qa/extras/ww8export/ww8export4.cxx24
-rw-r--r--sw/qa/inc/swmodeltestbase.hxx7
-rw-r--r--sw/qa/uitest/data/tdf150443.docxbin27927 -> 27855 bytes
-rw-r--r--sw/qa/uitest/writer_tests7/tdf150443.py4
-rw-r--r--sw/qa/unit/swmodeltestbase.cxx6
-rw-r--r--sw/source/core/crsr/crsrsh.cxx25
-rw-r--r--sw/source/core/crsr/pam.cxx5
-rw-r--r--sw/source/core/crsr/swcrsr.cxx4
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx14
-rw-r--r--sw/source/core/doc/docedt.cxx4
-rw-r--r--sw/source/core/doc/docfmt.cxx12
-rw-r--r--sw/source/core/doc/doctxm.cxx2
-rw-r--r--sw/source/core/docnode/ndsect.cxx4
-rw-r--r--sw/source/core/docnode/ndtbl.cxx43
-rw-r--r--sw/source/core/docnode/nodes.cxx58
-rw-r--r--sw/source/core/docnode/section.cxx7
-rw-r--r--sw/source/core/edit/editsh.cxx2
-rw-r--r--sw/source/core/edit/edsect.cxx154
-rw-r--r--sw/source/core/inc/frame.hxx2
-rw-r--r--sw/source/core/inc/sectfrm.hxx2
-rw-r--r--sw/source/core/inc/txtfrm.hxx2
-rw-r--r--sw/source/core/layout/calcmove.cxx13
-rw-r--r--sw/source/core/layout/findfrm.cxx8
-rw-r--r--sw/source/core/layout/flowfrm.cxx119
-rw-r--r--sw/source/core/layout/frmtool.cxx23
-rw-r--r--sw/source/core/layout/ftnfrm.cxx10
-rw-r--r--sw/source/core/layout/pagechg.cxx5
-rw-r--r--sw/source/core/layout/pagedesc.cxx74
-rw-r--r--sw/source/core/layout/sectfrm.cxx37
-rw-r--r--sw/source/core/layout/tabfrm.cxx18
-rw-r--r--sw/source/core/layout/trvlfrm.cxx25
-rw-r--r--sw/source/core/text/txtfrm.cxx19
-rw-r--r--sw/source/core/tox/tox.cxx8
-rw-r--r--sw/source/core/unocore/unocrsrhelper.cxx2
-rw-r--r--sw/source/core/unocore/unomap1.cxx1
-rw-r--r--sw/source/core/unocore/unoobj.cxx14
-rw-r--r--sw/source/core/unocore/unoportenum.cxx112
-rw-r--r--sw/source/core/unocore/unotext.cxx3
-rw-r--r--sw/source/filter/html/css1atr.cxx6
-rw-r--r--sw/source/filter/html/htmlatr.cxx409
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx40
-rw-r--r--sw/source/filter/ww8/rtfattributeoutput.cxx17
-rw-r--r--sw/source/filter/ww8/wrtw8nds.cxx8
-rw-r--r--sw/source/filter/ww8/wrtw8num.cxx9
-rw-r--r--sw/source/filter/ww8/ww8par3.cxx11
-rw-r--r--sw/source/ui/index/swuiidxmrk.cxx37
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx3
-rw-r--r--sw/source/uibase/docvw/AnnotationWin2.cxx2
-rw-r--r--sw/source/uibase/docvw/SidebarWinAcc.cxx10
-rw-r--r--sw/source/uibase/index/toxmgr.cxx3
-rw-r--r--sw/source/uibase/shells/textsh.cxx15
-rw-r--r--sw/source/uibase/sidebar/PageSizeControl.cxx1
-rw-r--r--sw/source/uibase/uiview/view2.cxx13
-rw-r--r--sw/source/uibase/utlui/uitool.cxx1
-rw-r--r--sw/source/uibase/wrtsh/wrtsh1.cxx5
85 files changed, 1951 insertions, 660 deletions
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 20636648c7..03afe5006a 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -267,7 +267,7 @@ private:
SAL_DLLPRIVATE bool LRMargin( bool, bool bAPI = false );
SAL_DLLPRIVATE bool IsAtLRMargin( bool, bool bAPI = false ) const;
- SAL_DLLPRIVATE bool isInHiddenTextFrame(SwShellCursor* pShellCursor);
+ SAL_DLLPRIVATE bool isInHiddenFrame(SwShellCursor* pShellCursor);
SAL_DLLPRIVATE bool GoStartWordImpl();
SAL_DLLPRIVATE bool GoEndWordImpl();
@@ -334,7 +334,7 @@ public:
void ExtendedSelectAll(bool bFootnotes = true);
/// If ExtendedSelectAll() was called and selection didn't change since then.
::std::optional<::std::pair<SwNode const*, ::std::vector<SwTableNode*>>> ExtendedSelectedAll() const;
- enum class StartsWith { None, Table, HiddenPara };
+ enum class StartsWith { None, Table, HiddenPara, HiddenSection };
/// If document body starts with a table or starts/ends with hidden paragraph.
StartsWith StartsWith_();
diff --git a/sw/inc/ndarr.hxx b/sw/inc/ndarr.hxx
index 7afe8d2bce..7383c253a2 100644
--- a/sw/inc/ndarr.hxx
+++ b/sw/inc/ndarr.hxx
@@ -131,6 +131,11 @@ class SW_DLLPUBLIC SwNodes final
SwNodes(SwDoc& rDoc);
+ // Returns start of the document section (PostIts/Inserts/Autotext/Redlines/Content),
+ // or of a specific fly / header / footer / footnote, where this node is, which must not
+ // be crossed when moving backwards
+ SwNodeOffset StartOfGlobalSection(const SwNode& node) const;
+
public:
~SwNodes();
@@ -188,8 +193,8 @@ public:
SwContentNode* GoNext(SwNodeIndex *) const;
SwContentNode* GoNext(SwPosition *) const;
- static SwContentNode* GoPrevious(SwNodeIndex *);
- static SwContentNode* GoPrevious(SwPosition *);
+ static SwContentNode* GoPrevious(SwNodeIndex *, bool canCrossBoundary = false);
+ static SwContentNode* GoPrevious(SwPosition *, bool canCrossBoundary = false);
/** Go to next content-node that is not protected or hidden
(Both set FALSE ==> GoNext/GoPrevious!!!). */
diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index de7e24a0b1..b1e3309d59 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -590,7 +590,7 @@ public:
const SwSection& GetSection() const { return *m_pSection; }
SwSection& GetSection() { return *m_pSection; }
- SwFrame *MakeFrame( SwFrame* );
+ SwFrame* MakeFrame(SwFrame* pSib, bool bHidden);
/** Creates the frms for the SectionNode (i.e. the SectionFrames).
On default the frames are created until the end of the range.
diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx
index 11bb347aa1..ddc7e659a5 100644
--- a/sw/inc/pagedesc.hxx
+++ b/sw/inc/pagedesc.hxx
@@ -151,9 +151,9 @@ class SW_DLLPUBLIC SwPageDesc final
struct StashedPageDesc
{
- std::shared_ptr<SwFrameFormat> m_pStashedFirst;
- std::shared_ptr<SwFrameFormat> m_pStashedLeft;
- std::shared_ptr<SwFrameFormat> m_pStashedFirstLeft;
+ std::optional<SwFrameFormat> m_oStashedFirst;
+ std::optional<SwFrameFormat> m_oStashedLeft;
+ std::optional<SwFrameFormat> m_oStashedFirstLeft;
};
mutable StashedPageDesc m_aStashedHeader;
diff --git a/sw/qa/core/layout/data/floattable-wrapped-by-table-nested.docx b/sw/qa/core/layout/data/floattable-wrapped-by-table-nested.docx
new file mode 100644
index 0000000000..d6950a6c8e
--- /dev/null
+++ b/sw/qa/core/layout/data/floattable-wrapped-by-table-nested.docx
Binary files differ
diff --git a/sw/qa/core/layout/tabfrm.cxx b/sw/qa/core/layout/tabfrm.cxx
index 61b1a25109..e0d099c771 100644
--- a/sw/qa/core/layout/tabfrm.cxx
+++ b/sw/qa/core/layout/tabfrm.cxx
@@ -221,6 +221,20 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineTableThenSplitFly)
// large positive one.
CPPUNIT_ASSERT_LESS(static_cast<SwTwips>(0), nInlineLeft);
}
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyWrappedByTableNested)
+{
+ // Given a document with 3 tables, one inline toplevel and two inner ones (one inline, one
+ // floating):
+ // When laying out that document:
+ // Without the accompanying fix in place, this test would have failed here with a layout loop.
+ createSwDoc("floattable-wrapped-by-table-nested.docx");
+
+ // Than make sure we have 3 tables, but only one of them is floating:
+ SwDoc* pDoc = getSwDoc();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc->GetTableFrameFormats()->GetFormatCount());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pDoc->GetSpzFrameFormats()->GetFormatCount());
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index 381fe0dab3..3e52b12a36 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -78,6 +78,33 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testTdf119081)
CPPUNIT_ASSERT_EQUAL(OUString("x"), pWrtShell->GetCurrentShellCursor().GetText());
}
+CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, selectTextRange)
+{
+ createSwDoc();
+ uno::Reference<text::XTextDocument> const xTD(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<text::XText> const xText(xTD->getText());
+ uno::Reference<text::XTextCursor> const xCursor(xText->createTextCursor());
+ xText->insertString(xCursor, "test", /*bAbsorb=*/false);
+ xCursor->gotoStart(false);
+ xCursor->gotoEnd(true);
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), xCursor->getString());
+ uno::Reference<lang::XMultiServiceFactory> const xMSF(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextSection> const xSection(
+ xMSF->createInstance("com.sun.star.text.TextSection"), uno::UNO_QUERY_THROW);
+ xText->insertTextContent(xCursor, xSection, true);
+ uno::Reference<text::XTextRange> const xAnchor(xSection->getAnchor());
+ uno::Reference<view::XSelectionSupplier> const xView(xTD->getCurrentController(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), xAnchor->getString());
+ CPPUNIT_ASSERT(xView->select(uno::Any(xAnchor)));
+ uno::Reference<container::XIndexAccess> xSel;
+ CPPUNIT_ASSERT(xView->getSelection() >>= xSel);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSel->getCount());
+ uno::Reference<text::XTextRange> xSelRange;
+ CPPUNIT_ASSERT(xSel->getByIndex(0) >>= xSelRange);
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), xSelRange->getString());
+}
+
CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, flyAtParaAnchor)
{
createSwDoc();
diff --git a/sw/qa/extras/accessibility/dialogs.cxx b/sw/qa/extras/accessibility/dialogs.cxx
index 091e6729c9..665e76c9bc 100644
--- a/sw/qa/extras/accessibility/dialogs.cxx
+++ b/sw/qa/extras/accessibility/dialogs.cxx
@@ -89,6 +89,7 @@ CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, TestSpecialCharactersDialogFocu
CPPUNIT_ASSERT_EQUAL(u"<PARAGRAPH>!</PARAGRAPH>"_ustr, collectText());
}
+#if !defined(_WIN32)
CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, BasicTestHyperlinkDialog)
{
load(u"private:factory/swriter"_ustr);
@@ -112,6 +113,7 @@ CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, BasicTestHyperlinkDialog)
CPPUNIT_ASSERT_EQUAL(rtl::OUString("<PARAGRAPH>https://libreoffice.org/</PARAGRAPH>"),
collectText());
}
+#endif //defined(_WIN32)
CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, BasicTestBookmarkDialog)
{
diff --git a/sw/qa/extras/fodfexport/fodfexport.cxx b/sw/qa/extras/fodfexport/fodfexport.cxx
index 2cf5bf42a7..840b5d47ba 100644
--- a/sw/qa/extras/fodfexport/fodfexport.cxx
+++ b/sw/qa/extras/fodfexport/fodfexport.cxx
@@ -20,34 +20,38 @@ public:
}
};
-DECLARE_FODFEXPORT_TEST(testTdf113696, "tdf113696.odt")
+CPPUNIT_TEST_FIXTURE(Test, testTdf113696)
{
+ loadFromFile(u"tdf113696.odt");
+
CPPUNIT_ASSERT_EQUAL(1, getShapes());
CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+ save("OpenDocument Text Flat XML");
// Test that an image which is written in svm format (image/x-vclgraphic)
// is accompanied by a png fallback graphic.
- if (xmlDocUniquePtr pXmlDoc = parseExportedFile())
- {
- assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
- "draw:image[@draw:mime-type='image/x-vclgraphic']"_ostr);
- assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
- "draw:image[@draw:mime-type='image/png']"_ostr);
- }
+ xmlDocUniquePtr pXmlDoc = parseExportedFile();
+ assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
+ "draw:image[@draw:mime-type='image/x-vclgraphic']"_ostr);
+ assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
+ "draw:image[@draw:mime-type='image/png']"_ostr);
}
-DECLARE_FODFEXPORT_TEST(testTdf113696WriterImage, "tdf113696-writerimage.odt")
+CPPUNIT_TEST_FIXTURE(Test, testTdf113696WriterImage)
{
+ loadFromFile(u"tdf113696-writerimage.odt");
+
CPPUNIT_ASSERT_EQUAL(1, getShapes());
CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+ save("OpenDocument Text Flat XML");
// Same as testTdf113696, but with a writer image instead of a draw image
// (they use different code paths).
- if (xmlDocUniquePtr pXmlDoc = parseExportedFile())
- {
- assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
- "draw:image[@draw:mime-type='image/x-vclgraphic']"_ostr);
- assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
- "draw:image[@draw:mime-type='image/png']"_ostr);
- }
+ xmlDocUniquePtr pXmlDoc = parseExportedFile();
+ assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
+ "draw:image[@draw:mime-type='image/x-vclgraphic']"_ostr);
+ assertXPath(pXmlDoc, "/office:document/office:body/office:text/text:p/draw:frame/"
+ "draw:image[@draw:mime-type='image/png']"_ostr);
}
DECLARE_FODFEXPORT_TEST(testSvgImageRoundtrip, "SvgImageTest.fodt")
diff --git a/sw/qa/extras/htmlexport/data/char_border_and_font_color.fodt b/sw/qa/extras/htmlexport/data/char_border_and_font_color.fodt
new file mode 100644
index 0000000000..bda2ec6313
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/char_border_and_font_color.fodt
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:text-properties fo:color="#000000" loext:border="none"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="P1">foo</text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 1bd883be11..de2e9da4c6 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -3032,6 +3032,27 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoBrClearForImageWrap)
0);
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_Tdf160017_spanClosingOrder)
+{
+ // Given a document with a paragraph having explicit font color and character border properties:
+ createSwDoc("char_border_and_font_color.fodt");
+ // When exporting to reqif:
+ ExportToReqif();
+ // Without the fix, this would fail, because there was an extra closing </reqif-xhtml:span>
+ WrapReqifFromTempFile();
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160017_spanClosingOrder)
+{
+ // Given a document with a paragraph having explicit font color and character border properties:
+ createSwDoc("char_border_and_font_color.fodt");
+ // When exporting to HTML:
+ ExportToHTML();
+ // Parse it as XML (strict!)
+ // Without the fix, this would fail, because span and font elements closed in wrong order
+ CPPUNIT_ASSERT(parseXml(maTempFile));
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt b/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt
new file mode 100644
index 0000000000..fbefc5c480
--- /dev/null
+++ b/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text">
+ <style:paragraph-properties fo:margin-top="1in" fo:margin-bottom="0" style:contextual-spacing="false" fo:line-height="12pt"/>
+ </style:style>
+ </office:styles>
+ <office:body>
+ <office:text>
+ <text:section text:name="Hidden" text:display="none"/>
+ <text:section text:name="Shown"/>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt b/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt
new file mode 100644
index 0000000000..5fae6a4917
--- /dev/null
+++ b/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph" style:master-page-name="Landscape">
+ <style:paragraph-properties style:page-number="1"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph" style:master-page-name="Landscape">
+ <style:paragraph-properties style:page-number="1"/>
+ <style:text-properties text:display="none"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p>First line</text:p>
+ <text:section text:name="Hidden" text:display="none">
+ <text:p text:style-name="P1"/>
+ </text:section>
+ <text:section text:name="Shown">
+ <text:p>Before break (still first page)</text:p>
+ </text:section>
+ <text:section text:name="HiddenText">
+ <text:p text:style-name="P2"/>
+ </text:section>
+ <text:p>After break</text:p>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p/>
+ <text:p>Should be together with next</text:p>
+ <text:section text:name="Hidden2" text:display="none">
+ <text:p text:style-name="P2"/>
+ </text:section>
+ <text:p>Should be together with previous</text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 9c46d8395a..a074a35dc6 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -94,15 +94,25 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119875)
{
createSwDoc("tdf119875.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
- sal_Int32 nFirstTop
- = getXPath(pXmlDoc, "/root/page[2]/body/section[1]/infos/bounds"_ostr, "top"_ostr)
- .toInt32();
- sal_Int32 nSecondTop
- = getXPath(pXmlDoc, "/root/page[2]/body/section[2]/infos/bounds"_ostr, "top"_ostr)
- .toInt32();
- // The first section had the same top value as the second one, so they
- // overlapped.
- CPPUNIT_ASSERT_LESS(nSecondTop, nFirstTop);
+
+ assertXPath(pXmlDoc, "//page[2]/body/section[1]"_ostr, "formatName"_ostr, u"S10"_ustr);
+ assertXPath(pXmlDoc, "//page[2]/body/section[2]"_ostr, "formatName"_ostr, u"S11"_ustr);
+ assertXPath(pXmlDoc, "//page[2]/body/section[3]"_ostr, "formatName"_ostr, u"S13"_ustr);
+ assertXPath(pXmlDoc, "//page[2]/body/section[4]"_ostr, "formatName"_ostr, u"S14"_ustr);
+ // Sections "S10" and "S13" are hidden -> their frames are zero-height
+ assertXPath(pXmlDoc, "//page[2]/body/section[1]/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+ assertXPath(pXmlDoc, "//page[2]/body/section[3]/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+
+ OUString S10Top = getXPath(pXmlDoc, "//page[2]/body/section[1]/infos/bounds"_ostr, "top"_ostr);
+ OUString S11Top = getXPath(pXmlDoc, "//page[2]/body/section[2]/infos/bounds"_ostr, "top"_ostr);
+ OUString S13Top = getXPath(pXmlDoc, "//page[2]/body/section[3]/infos/bounds"_ostr, "top"_ostr);
+ OUString S14Top = getXPath(pXmlDoc, "//page[2]/body/section[4]/infos/bounds"_ostr, "top"_ostr);
+
+ CPPUNIT_ASSERT_EQUAL(S10Top, S11Top);
+ CPPUNIT_ASSERT_EQUAL(S13Top, S14Top);
+
+ // Section "S11" had the same top value as section "S14", so they overlapped.
+ CPPUNIT_ASSERT_LESS(S14Top.toInt32(), S11Top.toInt32());
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf137523)
@@ -2303,6 +2313,46 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf159259)
CPPUNIT_ASSERT_EQUAL(paraHeight, flyHeight);
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testLargeTopParaMarginAfterHiddenSection)
+{
+ // Given a large top margin in Standard paragraph style, and the first section hidden
+ createSwDoc("largeTopMarginAndHiddenFirstSection.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ // Make sure there is only one page and two sections, first hidden (zero-height)
+ assertXPath(pXmlDoc, "//page"_ostr, 1);
+ assertXPath(pXmlDoc, "//page/body/section"_ostr, 2);
+ assertXPath(pXmlDoc, "//page/body/section[1]/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+ // Check that the top margin (1 in = 1440 twip) is added to line height (12 pt = 240 twip)
+ assertXPath(pXmlDoc, "//page/body/section[2]/infos/bounds"_ostr, "height"_ostr, u"1680"_ustr);
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testPageBreakInHiddenSection)
+{
+ // Given a paragraph with page-break-before with page style and page number
+ createSwDoc("pageBreakInHiddenSection.fodt");
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "//page"_ostr, 4);
+ assertXPath(pXmlDoc, "//section"_ostr, 4);
+ assertXPath(pXmlDoc, "//page[1]/body/txt"_ostr, 1);
+ // The page break inside the hidden section is ignored (otherwise, there would be one section
+ // on the first page)
+ assertXPath(pXmlDoc, "//page[1]/body/section"_ostr, 2);
+ // The first section is hidden
+ assertXPath(pXmlDoc, "//page[1]/body/section[1]/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+
+ // Page 2 is empty even page (generated by the next page's section with page-break-before)
+ assertXPath(pXmlDoc, "//page[2]/body"_ostr, 0);
+
+ // The section on page 3 is not hidden, only text in it is, therefore its page break works
+ assertXPath(pXmlDoc, "//page[3]/body/section"_ostr, 1);
+ assertXPath(pXmlDoc, "//page[3]/body/section/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+
+ // The section on page 4 is hidden, thus page break in it is ignored (no further pages, where
+ // the section would be moved to otherwise)
+ assertXPath(pXmlDoc, "//page[4]/body/section"_ostr, 1);
+ assertXPath(pXmlDoc, "//page[4]/body/section/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/odfexport/data/bookmark_order.fodt b/sw/qa/extras/odfexport/data/bookmark_order.fodt
new file mode 100644
index 0000000000..c7eac58758
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/bookmark_order.fodt
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+ <office:text>
+ <text:p><text:bookmark-start text:name="bookmark1"/>foo<text:bookmark-end text:name="bookmark1"/><text:bookmark text:name="bookmark2"/><text:bookmark-start text:name="bookmark3"/>bar<text:bookmark-end text:name="bookmark3"/></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx
index 37e744e9c8..4983608290 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -1247,6 +1247,102 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf159382)
}
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf159438)
+{
+ // Given a text with bookmarks, where an end of one bookmark is the position of another,
+ // and the start of a third
+ loadAndReload("bookmark_order.fodt");
+ auto xPara = getParagraph(1);
+
+ // Check that the order of runs is correct (bookmarks don't overlap)
+
+ {
+ auto run = getRun(xPara, 1);
+ CPPUNIT_ASSERT_EQUAL(u"Bookmark"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(run, "IsStart"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsCollapsed"));
+ auto named = getProperty<uno::Reference<container::XNamed>>(run, "Bookmark");
+ CPPUNIT_ASSERT_EQUAL(u"bookmark1"_ustr, named->getName());
+ }
+
+ {
+ auto run = getRun(xPara, 2);
+ CPPUNIT_ASSERT_EQUAL(u"Text"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, run->getString());
+ }
+
+ {
+ auto run = getRun(xPara, 3);
+ CPPUNIT_ASSERT_EQUAL(u"Bookmark"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsStart"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsCollapsed"));
+ auto named = getProperty<uno::Reference<container::XNamed>>(run, "Bookmark");
+ CPPUNIT_ASSERT_EQUAL(u"bookmark1"_ustr, named->getName());
+ }
+
+ {
+ auto run = getRun(xPara, 4);
+ CPPUNIT_ASSERT_EQUAL(u"Bookmark"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(run, "IsStart"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(run, "IsCollapsed"));
+ auto named = getProperty<uno::Reference<container::XNamed>>(run, "Bookmark");
+ CPPUNIT_ASSERT_EQUAL(u"bookmark2"_ustr, named->getName());
+ }
+
+ {
+ auto run = getRun(xPara, 5);
+ CPPUNIT_ASSERT_EQUAL(u"Bookmark"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(run, "IsStart"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsCollapsed"));
+ auto named = getProperty<uno::Reference<container::XNamed>>(run, "Bookmark");
+ CPPUNIT_ASSERT_EQUAL(u"bookmark3"_ustr, named->getName());
+ }
+
+ {
+ auto run = getRun(xPara, 6);
+ CPPUNIT_ASSERT_EQUAL(u"Text"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, run->getString());
+ }
+
+ {
+ auto run = getRun(xPara, 7);
+ CPPUNIT_ASSERT_EQUAL(u"Bookmark"_ustr, getProperty<OUString>(run, "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsStart"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(run, "IsCollapsed"));
+ auto named = getProperty<uno::Reference<container::XNamed>>(run, "Bookmark");
+ CPPUNIT_ASSERT_EQUAL(u"bookmark3"_ustr, named->getName());
+ }
+
+ // Test that the markup stays at save-and-reload
+ xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+
+ assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[1]"_ostr,
+ "bookmark-start"_ostr);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/*[1]"_ostr, "name"_ostr,
+ u"bookmark1"_ustr);
+
+ // Without the fix in place, this would fail with
+ // - Expected: bookmark-end
+ // - Actual : bookmark-start
+ // - In XPath '//office:body/office:text/text:p/*[2]' name of node is incorrect
+ assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[2]"_ostr, "bookmark-end"_ostr);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/*[2]"_ostr, "name"_ostr,
+ u"bookmark1"_ustr);
+
+ assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[3]"_ostr, "bookmark"_ostr);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/*[3]"_ostr, "name"_ostr,
+ u"bookmark2"_ustr);
+
+ assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[4]"_ostr,
+ "bookmark-start"_ostr);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/*[4]"_ostr, "name"_ostr,
+ u"bookmark3"_ustr);
+
+ assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[5]"_ostr, "bookmark-end"_ostr);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/*[5]"_ostr, "name"_ostr,
+ u"bookmark3"_ustr);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/data/tdf158597.docx b/sw/qa/extras/ooxmlexport/data/tdf158597.docx
new file mode 100644
index 0000000000..ad7924ce71
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf158597.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
index cdcdfe7785..e902f7a7b8 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
@@ -9,12 +9,15 @@
#include <swmodeltestbase.hxx>
+#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <comphelper/sequenceashashmap.hxx>
+
#include <pam.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
@@ -30,6 +33,261 @@ public:
}
};
+DECLARE_OOXMLEXPORT_TEST(testTdf158597, "tdf158597.docx")
+{
+ // test with 2 properties: font size, italic (toggle)
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(1));
+ CPPUNIT_ASSERT_EQUAL(OUString("No style"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(11.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(2));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style mark"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(11.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT(!listAutoFormat["CharHeight"].hasValue());
+ CPPUNIT_ASSERT(!listAutoFormat["CharPosture"].hasValue());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(3));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style mark and text"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT(!listAutoFormat["CharHeight"].hasValue());
+ CPPUNIT_ASSERT(!listAutoFormat["CharPosture"].hasValue());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(4));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style text"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(5));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(6));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style mark"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT(!listAutoFormat["CharHeight"].hasValue());
+ // bug was that here the toggle property was not overwritten
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(7));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style mark and text"),
+ xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT(!listAutoFormat["CharHeight"].hasValue());
+ // bug was that here the toggle property was not overwritten
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(8));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style text"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(9));
+ CPPUNIT_ASSERT_EQUAL(OUString("No style + direct mark"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(11.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT(!listAutoFormat["CharStyleName"].hasValue());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(10));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style + direct mark"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(11.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(11));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style + direct mark and text"),
+ xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(12));
+ CPPUNIT_ASSERT_EQUAL(OUString("Char style + direct text"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(13));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + direct mark"), xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT(!listAutoFormat["CharStyleName"].hasValue());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(14));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style + direct mark"),
+ xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(15));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style + direct mark and text"),
+ xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ comphelper::SequenceAsHashMap listAutoFormat(xProps->getPropertyValue("ListAutoFormat"));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), listAutoFormat["CharStyleName"].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(16.f, listAutoFormat["CharHeight"].get<float>());
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ listAutoFormat["CharPosture"].get<awt::FontSlant>());
+ }
+ {
+ uno::Reference<text::XTextRange> xParagraph(getParagraph(16));
+ CPPUNIT_ASSERT_EQUAL(OUString("Para style + Char style + direct text"),
+ xParagraph->getString());
+ uno::Reference<beans::XPropertySet> xProps(xParagraph, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph E"),
+ getProperty<OUString>(xProps, "ParaStyleName"));
+ uno::Reference<text::XTextRange> xRun(getRun(xParagraph, 1));
+ CPPUNIT_ASSERT_EQUAL(OUString("Emphasis"), getProperty<OUString>(xRun, "CharStyleName"));
+ CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(xRun, "CharHeight"));
+ CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
+ getProperty<awt::FontSlant>(xRun, "CharPosture"));
+ CPPUNIT_ASSERT(!xProps->getPropertyValue("ListAutoFormat").hasValue());
+ }
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf153909_followTextFlow, "tdf153909_followTextFlow.docx")
{
// Although MSO's UI reports "layoutInCell" for the rectangle, it isn't specified or honored
diff --git a/sw/qa/extras/rtfexport/data/fdo55504-1-min.rtf b/sw/qa/extras/rtfexport/data/fdo55504-1-min.rtf
new file mode 100644
index 0000000000..6e76676299
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/fdo55504-1-min.rtf
@@ -0,0 +1,49 @@
+{\rtf1\adeflang1025\ansi\ansicpg1251\uc1\adeff0\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1049\deflangfe1049{\fonttbl{\f0\froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset204\fprq2{\*\panose 020b0604020202020204}Arial;}{\f39\froman\fcharset0\fprq2 Times New Roman;}
+{\f37\froman\fcharset238\fprq2 Times New Roman CE;}{\f40\froman\fcharset161\fprq2 Times New Roman Greek;}{\f41\froman\fcharset162\fprq2 Times New Roman Tur;}{\f42\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\f43\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f44\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f45\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fswiss\fcharset0\fprq2 Arial;}
+{\f47\fswiss\fcharset238\fprq2 Arial CE;}{\f50\fswiss\fcharset161\fprq2 Arial Greek;}{\f51\fswiss\fcharset162\fprq2 Arial Tur;}{\f52\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f53\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}
+{\f54\fswiss\fcharset186\fprq2 Arial Baltic;}{\f55\fswiss\fcharset163\fprq2 Arial (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
+\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 \snext0 Normal;}{\*\cs10 \additive \ssemihidden
+Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}}
+{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid3757467}{\*\generator Microsoft Word 11.0.0000;}{\info{\title \'d1\'cf\'d0\'c0\'c2\'ca\'c0 \'b9 6785}{\author Crystal Reports}{\doccomm Powered By Crystal}
+{\operator \'cf\'f0\'ee\'e3\'f0\'e0\'ec\'ec\'e8\'f1\'f2}{\creatim\yr2012\mo9\dy26\hr11\min39}{\revtim\yr2012\mo9\dy26\hr11\min39}{\version2}{\edmins0}{\nofpages2}{\nofwords529}{\nofchars3021}{\*\company Crystal Decisions}{\nofcharsws3543}
+{\vern24611}{\*\password 00000000}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw16836\paperh11904\margl567\margr397\margt567\margb284\gutter0\ltrsect
+\widowctrl\ftnbj\aenddoc\donotembedsysfont0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3
+\jcompress\viewkind1\viewscale100\rsidroot3757467 \fet0{\*\wgrffmtfilter 013f}\ilfomacatclnup0\ltrpar \sectd \ltrsect\lndscpsxn\sbknone\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
+\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
+\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li0\ri0\nowidctlpar
+\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760\tx6120\tx6480\tx6840\tx7200\tx7560\tx7920\tx8280\tx8640\tx9000\tx9360\tx9720\tx10080\tx10440\tx10800\tx11160\tx11520\tx11880
+\tx12240\tx12600\pvpg\phpg\posx2007\posy597\absh-900\absw12870\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 {\rtlch\fcs1 \af0 \ltrch\fcs0
+\lang1024\langfe1024\noproof\insrsid3757467 {\shp{\*\shpinst\shpleft6567\shptop3832\shpright8713\shpbottom3832\shpfhdr0\shpbxpage\shpbxignore\shpbypage\shpbyignore\shpwr3\shpwrk0\shpfblwtxt1\shpz0\shplid1026
+{\sp{\sn shapeType}{\sv 20}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn lineWidth}{\sv 12700}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn posrelh}{\sv 1}}{\sp{\sn posrelv}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}{\sp{\sn fBehindDocument}{\sv 1}}
+{\sp{\sn fLayoutInCell}{\sv 0}}}{\shprslt{\*\do\dobxpage\dobypage\dodhgt0\dpline\dpptx0\dppty0\dpptx2146\dppty0\dpx6567\dpy3832\dpxsize2146\dpysize0\dplinew20\dplinecor0\dplinecog0\dplinecob0}}}
+{\shp{\*\shpinst\shpleft9912\shptop3862\shpright12073\shpbottom3862\shpfhdr0\shpbxpage\shpbxignore\shpbypage\shpbyignore\shpwr3\shpwrk0\shpfblwtxt1\shpz1\shplid1027{\sp{\sn shapeType}{\sv 20}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}
+{\sp{\sn lineWidth}{\sv 12700}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn posrelh}{\sv 1}}{\sp{\sn posrelv}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}{\sp{\sn fBehindDocument}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}}{\shprslt{\*\do\dobxpage\dobypage\dodhgt1
+\dpline\dpptx0\dppty0\dpptx2161\dppty0\dpx9912\dpy3862\dpxsize2161\dpysize0\dplinew20\dplinecor0\dplinecog0\dplinecob0}}}
+}
+{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f1\fs17\cf1\insrsid3757467 \'d1\'cf\'d0\'c0\'c2\'ca\'c0 \'b9 6785}{\rtlch\fcs1 \af1 \ltrch\fcs0
+\f1\insrsid3757467
+\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f1\fs17\cf1\insrsid3757467 \'ce \'d1\'ce\'d1\'d2\'ce\'df\'cd\'c8\'c8 \'d0\'c0\'d1\'d7\'c5\'d2\'ce\'c2 \'cf\'ce \'cd\'c0\'cb\'ce\'c3\'c0\'cc, \'d1\'c1\'ce\'d0\'c0\'cc, \'cf\'c5\'cd\'df\'cc \'c8 \'d8\'d2\'d0\'c0\'d4\'c0\'cc
+}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\insrsid3757467
+\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f1\fs17\cf1\insrsid3757467 \'ee\'f0\'e3\'e0\'ed\'e8\'e7\'e0\'f6\'e8\'e9 \'e8 \'e8\'ed\'e4\'e8\'e2\'e8\'e4\'f3\'e0\'eb\'fc\'ed\'fb\'f5 \'ef\'f0\'e5\'e4\'ef\'f0\'e8\'ed\'e8\'ec\'e0\'f2\'e5\'eb\'e5\'e9}{\rtlch\fcs1 \af1
+\ltrch\fcs0 \f1\insrsid3757467
+\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f1\fs17\cf1\insrsid3757467 \'ef\'ee \'f1\'ee\'f1\'f2\'ee\'ff\'ed\'e8\'fe \'ed\'e0 << 26 >> \'d1\'e5\'ed\'f2\'ff\'e1\'f0\'fc 2012\'e3.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\insrsid3757467
+\par }
+\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\insrsid3757467 \page \sect }\sectd \ltrsect\lndscpsxn\sbknone\linex0\sectdefaultcl\sftnbj \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar
+\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760\tx6120\tx6480\tx6840\tx7200\tx7560\tx7920\tx8280\tx8640\tx9000\tx9360\tx9720\tx10080\tx10440\tx10800\tx11160\tx11520\tx11880
+\tx12240\pvpg\phpg\posx612\posy627\absh-225\absw12480\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 {\rtlch\fcs1 \af0 \ltrch\fcs0
+\lang1024\langfe1024\noproof\insrsid3757467 {\shp{\*\shpinst\shpleft567\shptop867\shpright16423\shpbottom867\shpfhdr0\shpbxpage\shpbxignore\shpbypage\shpbyignore\shpwr3\shpwrk0\shpfblwtxt1\shpz29\shplid1055
+{\sp{\sn shapeType}{\sv 20}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn lineWidth}{\sv 12700}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn posrelh}{\sv 1}}{\sp{\sn posrelv}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}{\sp{\sn fBehindDocument}{\sv 1}}
+{\sp{\sn fLayoutInCell}{\sv 0}}}{\shprslt{\*\do\dobxpage\dobypage\dodhgt29\dpline\dpptx0\dppty0\dpptx15856\dppty0\dpx567\dpy867\dpxsize15856\dpysize0\dplinew20\dplinecor0\dplinecog0\dplinecob0}}}
+{\shp{\*\shpinst\shpleft567\shptop1167\shpright16439\shpbottom1167\shpfhdr0\shpbxpage\shpbxignore\shpbypage\shpbyignore\shpwr3\shpwrk0\shpfblwtxt1\shpz30\shplid1056{\sp{\sn shapeType}{\sv 20}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}
+{\sp{\sn lineWidth}{\sv 12700}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn posrelh}{\sv 1}}{\sp{\sn posrelv}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}{\sp{\sn fBehindDocument}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 0}}}{\shprslt{\*\do\dobxpage\dobypage\dodhgt30
+\dpline\dpptx0\dppty0\dpptx15872\dppty0\dpx567\dpy1167\dpxsize15872\dpysize0\dplinew20\dplinecor0\dplinecog0\dplinecob0}}}
+}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\fs17\cf1\insrsid3757467 \'cc\'f3\'ed\'e8\'f6\'e8\'ef\'e0\'eb\'fc\'ed\'ee\'e5 \'e4\'ee\'f8\'ea\'ee
+\'eb\'fc\'ed\'ee\'e5 \'ee\'e1\'f0\'e0\'e7\'ee\'e2\'e0\'f2\'e5\'eb\'fc\'ed\'ee\'e5 \'f3\'f7\'f0\'e5\'e6\'e4\'e5\'ed\'e8\'e5 \'e4\'e5\'f2\'f1\'ea\'e8\'e9 \'f1\'e0\'e4 \'b99 "\'d0\'ee\'ec\'e0\'f8\'ea\'e0" \'ca\'f3\'f0\'f1\'ea\'ee\'e3\'ee \'ec\'f3\'ed\'e8\'f6
+\'e8\'ef\'e0\'eb\'fc\'ed\'ee\'e3\'ee \'f0\'e0\'e9\'ee\'ed\'e0 \'d1\'f2\'e0\'e2\'f0\'ee\'ef\'ee\'eb\'fc\'f1\'ea\'ee\'e3\'ee \'ea\'f0\'e0\'ff}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\insrsid3757467
+\par }
+\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\insrsid3757467
+\par }}
diff --git a/sw/qa/extras/rtfexport/data/piccrop.rtf b/sw/qa/extras/rtfexport/data/piccrop.rtf
new file mode 100644
index 0000000000..4e8a704205
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/piccrop.rtf
@@ -0,0 +1,74 @@
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1028\themelang1033\themelangfe1028\themelangcs1025{\fonttbl{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial{\*\falt Arial};}
+{\f14\fbidi \fnil\fcharset136\fprq2{\*\panose 02010601000101010101}PMingLiU{\*\falt Arial Unicode MS};}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
+{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f291\fbidi \fnil\fcharset136\fprq2{\*\panose 00000000000000000000}@PMingLiU;}
+{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Arial};}{\fdbmajor\f31501\fbidi \fnil\fcharset136\fprq2{\*\panose 02010601000101010101}PMingLiU{\*\falt Arial Unicode MS};}
+{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Arial};}
+{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Arial};}{\fdbminor\f31505\fbidi \fnil\fcharset136\fprq2{\*\panose 02010601000101010101}PMingLiU{\*\falt Arial Unicode MS};}
+{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial{\*\falt Arial};}{\f302\fbidi \fswiss\fcharset238\fprq2 Arial CE{\*\falt Arial};}
+{\f303\fbidi \fswiss\fcharset204\fprq2 Arial Cyr{\*\falt Arial};}{\f305\fbidi \fswiss\fcharset161\fprq2 Arial Greek{\*\falt Arial};}{\f306\fbidi \fswiss\fcharset162\fprq2 Arial Tur{\*\falt Arial};}
+{\f307\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew){\*\falt Arial};}{\f308\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic){\*\falt Arial};}{\f309\fbidi \fswiss\fcharset186\fprq2 Arial Baltic{\*\falt Arial};}
+{\f310\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese){\*\falt Arial};}{\f632\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f633\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f635\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}
+{\f636\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f639\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f640\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f662\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
+{\f663\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f665\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f666\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f667\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
+{\f668\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f669\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f670\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
+{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Arial};}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Arial};}
+{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Arial};}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Arial};}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Arial};}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Arial};}
+{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Arial};}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Arial};}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}
+{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}
+{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}
+{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Arial};}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Arial};}
+{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Arial};}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Arial};}
+{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Arial};}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Arial};}
+{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Arial};}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Arial};}
+{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Arial};}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Arial};}
+{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Arial};}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Arial};}
+{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Arial};}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Arial};}
+{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Arial};}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Arial};}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
+{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
+{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fswiss\fcharset238\fprq2 Arial CE{\*\falt Arial};}{\fbiminor\f31579\fbidi \fswiss\fcharset204\fprq2 Arial Cyr{\*\falt Arial};}
+{\fbiminor\f31581\fbidi \fswiss\fcharset161\fprq2 Arial Greek{\*\falt Arial};}{\fbiminor\f31582\fbidi \fswiss\fcharset162\fprq2 Arial Tur{\*\falt Arial};}{\fbiminor\f31583\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew){\*\falt Arial};}
+{\fbiminor\f31584\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic){\*\falt Arial};}{\fbiminor\f31585\fbidi \fswiss\fcharset186\fprq2 Arial Baltic{\*\falt Arial};}{\fbiminor\f31586\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese){\*\falt Arial};}
+{\f292\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Arial};}{\f293\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Arial};}{\f295\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Arial};}
+{\f296\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Arial};}{\f297\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Arial};}{\f298\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Arial};}
+{\f299\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Arial};}{\f300\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Arial};}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;
+\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;
+\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{
+\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1028\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1028
+\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1028\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1028 \snext11 \ssemihidden \sunhideused
+Normal Table;}}{\*\rsidtbl \rsid1539605\rsid6818220\rsid9513591}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author ms}{\operator ms}
+{\creatim\yr2024\mo2\dy13\hr14\min53}{\revtim\yr2024\mo2\dy13\hr14\min57}{\version1}{\edmins4}{\nofpages1}{\nofwords0}{\nofchars1}{\nofcharsws1}{\vern57435}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
+\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
+\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen
+\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1
+\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
+\asianbrkrule\rsidroot1539605\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
+{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj
+\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1033\langfe1028\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1028 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid9513591\charrsid4597901 {\*\shppict
+{\pict{\*\picprop\shplid1025{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLockAspectRatio}{\sv 1}}{\sp{\sn fLockPosition}{\sv 0}}{\sp{\sn fLockAgainstSelect}{\sv 0}}{\sp{\sn fLockAgainstGrouping}{\sv 0}}
+{\sp{\sn pictureGray}{\sv 0}}{\sp{\sn pictureBiLevel}{\sv 0}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn wzName}{\sv Picture 1}}{\sp{\sn dhgt}{\sv 251658240}}{\sp{\sn fHidden}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}}
+\picscalex780\picscaley780\piccropl70\piccropr70\piccropt70\piccropb70\picw503\pich503\picwgoal285\pichgoal285\pngblip\bliptag-2138324634{\*\blipuid 808bc16643ef1085bdc9d6183a9f49dc}
+89504e470d0a1a0a0000000d4948445200000013000000130806000000725036cc0000000467414d410000d6d8d44f58320000001974455874536f6674776172
+650041646f626520496d616765526561647971c9653c000001694944415478da62fcffff3f03b50040003111a3e8e3646ba26c04082026620ce2bf720cc5c049
+eb57fe076174b50001c4448c41479f3232201bd83b733356f50001c4448c4120806e20360010404cc418c4d1b81dc5c04bdef7192e5d7a8da10f208098883148
+53d312c3c05ea1e518860104101331067171f1613510ddcb0001c4448c4120408c810001c4084ab4f80cfaf6ed13dc6618fffaf5e30c3fea3dc162d6d240fd3a
+560cfcb9471901028809dda0a83f5128068134e6752f02d3203ecc852075e82e040820963b56750c0c5640d700258c8ddd195d1ba7fc87790d64c0f42db71926
+95c6810dcc84a8011be86a69c1605dbf84f1ecd99dffcf425d0e10400c206f22e3e486c9ff41e0ebd78fff416c108d8d0f5587a2172080f0e680ddc74fa04400
+888f0f000410130315014000b160130405f48f1f5fb16ac0250e02000184d53050c0e302f7ef5fc229071040580d03c5200cc87bc4e09443070001c448cd921620c000313009ee012707180000000049454e44ae426082}}{\nonshppict
+{\pict\picscalex781\picscaley790\piccropl70\piccropr70\piccropt70\piccropb70\picw503\pich503\picwgoal285\pichgoal285\wmetafile8\bliptag-2138324634{\*\blipuid 808bc16643ef1085bdc9d6183a9f49dc}
+010009000003370100000000b300000000000400000003010800050000000b0200000000050000000c0214001400030000001e00040000000701040004000000
+070104000800000026060f000600544e505006014b000000410b8600ee0013001300000000001300130000000000280000001300000013000000010001000000
+0000000000000000000000000000000000000000000000000000ffffff000000000c0ffe000c0ffe00000ffe00000ffe00000ffe00000ffe0000effee000ffff
+e0007fffc0003fff80001fff00000ffe000507fe000003fe000c01f6000c00e600000040000000000000b3000000410bc6008800130013000000000013001300
+000000002800000013000000130000000100040000000000000000000000000000000000000000000000000000000000ffffff004ba1f3000078ff00b5baa000
+035dcd006d592c00c3d4d400a2907500f3f7f700eaf0f00000000000000000000000000000000000000000001111111111111111111001011111888666668881
+11100101111187761116778111100801111189a61116a98111100706111181961116918111100100111181961116918111100106111181989198918111100101
+77718117898711817770080123556919787919655320090612355791999197553210010011235579111975532110090811123557919755321110070111112355
+797553211110080111111235575532811110010911111123555326411110024c1111111235321641111009011111111123211441111002031111111112111111111005031111111111111111111005070800000026060f000600544e50500701040000002701ffff030000000000}}}{\rtlch\fcs1 \af31507
+\ltrch\fcs0 \insrsid6818220
+\par }
+}
diff --git a/sw/qa/extras/rtfexport/data/tdf159824_axialGradient.odt b/sw/qa/extras/rtfexport/data/tdf159824_axialGradient.odt
new file mode 100644
index 0000000000..c1ce5cd31d
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf159824_axialGradient.odt
Binary files differ
diff --git a/sw/qa/extras/rtfexport/rtfexport2.cxx b/sw/qa/extras/rtfexport/rtfexport2.cxx
index c718dfffd7..e194db83e4 100644
--- a/sw/qa/extras/rtfexport/rtfexport2.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport2.cxx
@@ -523,7 +523,8 @@ DECLARE_RTFEXPORT_TEST(testFdo48446, "fdo48446.rtf")
DECLARE_RTFEXPORT_TEST(testFdo47495, "fdo47495.rtf")
{
// Used to have 4 paragraphs, as a result the original bugdoc had 2 pages instead of 1.
- CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
+ // Word 2013 shows 1 paragraph
+ CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
}
DECLARE_RTFEXPORT_TEST(testAllGapsWord, "all_gaps_word.rtf")
diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx b/sw/qa/extras/rtfexport/rtfexport8.cxx
index 08ca8452f9..ab787919df 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -9,9 +9,12 @@
#include <swmodeltestbase.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
#include <com/sun/star/text/XFootnote.hpp>
#include <com/sun/star/text/XFootnotesSupplier.hpp>
-#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/text/XEndnotesSupplier.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
@@ -20,7 +23,9 @@
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/style/TabStop.hpp>
+#include <basegfx/utils/gradienttools.hxx>
#include <comphelper/sequenceashashmap.hxx>
+#include <docmodel/uno/UnoGradientTools.hxx>
#include <tools/UnitConversion.hxx>
#include <comphelper/propertyvalue.hxx>
@@ -48,6 +53,28 @@ public:
}
};
+DECLARE_RTFEXPORT_TEST(testTdf155663, "piccrop.rtf")
+{
+ auto const xShape(getShape(1));
+ if (!isExported())
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2004), xShape->getSize().Height);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2004), xShape->getSize().Width);
+ }
+ else // bit of rounding loss?
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2013), xShape->getSize().Height);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2013), xShape->getSize().Width);
+ }
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(123), getProperty<text::GraphicCrop>(xShape, "GraphicCrop").Top);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(123),
+ getProperty<text::GraphicCrop>(xShape, "GraphicCrop").Bottom);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(123),
+ getProperty<text::GraphicCrop>(xShape, "GraphicCrop").Left);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(123),
+ getProperty<text::GraphicCrop>(xShape, "GraphicCrop").Right);
+}
+
DECLARE_RTFEXPORT_TEST(testTdf158586_0, "tdf158586_pageBreak0.rtf")
{
// The specified page break must be lost because it is in a text frame
@@ -109,6 +136,27 @@ DECLARE_RTFEXPORT_TEST(testTdf158586_lostFrame, "tdf158586_lostFrame.rtf")
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
+DECLARE_RTFEXPORT_TEST(testTdf158983, "fdo55504-1-min.rtf")
+{
+ // the problem was that the page break was missing and the shapes were
+ // all anchored to the same node
+
+ const auto& pLayout = parseLayoutDump();
+ assertXPath(pLayout, "/root/page[1]/body/section/txt"_ostr, 1);
+ assertXPath(pLayout, "/root/page[1]/body/section/txt/anchored/fly"_ostr, 1);
+ // Word shows these shapes anchored in the fly, not body, but at least they are not lost
+ assertXPath(pLayout, "/root/page[1]/body/section/txt/anchored/SwAnchoredDrawObject"_ostr, 2);
+ // page break, paragraph break, section break.
+ assertXPath(pLayout, "/root/page[2]/body/section[1]/txt"_ostr, 1);
+ assertXPath(pLayout, "/root/page[2]/body/section[1]/txt/anchored"_ostr, 0);
+ assertXPath(pLayout, "/root/page[2]/body/section[2]/txt"_ostr, 1);
+ assertXPath(pLayout, "/root/page[2]/body/section[2]/txt/anchored/fly"_ostr, 1);
+ // Word shows these shapes anchored in the fly, not body, but at least they are not lost
+ assertXPath(pLayout, "/root/page[2]/body/section[2]/txt/anchored/SwAnchoredDrawObject"_ostr, 2);
+
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
+}
+
DECLARE_RTFEXPORT_TEST(testAnnotationPar, "tdf136445-1-min.rtf")
{
// the problem was that the paragraph break following annotation was missing
@@ -130,8 +178,38 @@ DECLARE_RTFEXPORT_TEST(testTdf158826_extraCR, "tdf158826_extraCR.rtf")
// The page break defined before the document content should not cause a page break
CPPUNIT_ASSERT_EQUAL(1, getPages());
- // There is a two-column floating table [that SHOULD be getParagraphOrTable(1)]
- uno::Reference<text::XTextTable> xTable(getParagraphOrTable(2), uno::UNO_QUERY_THROW);
+ // There is a two-column floating table
+ uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY_THROW);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf159824_axialGradient)
+{
+ // given a frame with an axial gradient (white - green - white)
+ loadAndReload("tdf159824_axialGradient.odt");
+
+ uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT,
+ getProperty<drawing::FillStyle>(xFrame, "FillStyle"));
+ awt::Gradient2 aGradient = getProperty<awt::Gradient2>(xFrame, "FillGradient");
+
+ //const Color aColA(0x127622); // green
+ //const Color aColB(0xffffff); // white
+
+ // MCGR: Use the completely imported transparency gradient to check for correctness
+ basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops);
+
+ // expected: a 3-color linear gradient (or better yet a 2-color AXIAL gradient)
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size());
+ CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style);
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0));
+ //CPPUNIT_ASSERT_EQUAL(aColB, Color(aColorStops[0].getStopColor()));
+ // CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 0.5));
+ // CPPUNIT_ASSERT_EQUAL(aColA, Color(aColorStops[1].getStopColor()));
+ // CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[2].getStopOffset(), 1.0));
+ // CPPUNIT_ASSERT_EQUAL(aColB, Color(aColorStops[2].getStopColor()));
}
DECLARE_RTFEXPORT_TEST(testTdf158830, "tdf158830.rtf")
diff --git a/sw/qa/extras/rtfimport/data/tdf153196.rtf b/sw/qa/extras/rtfimport/data/tdf153196.rtf
new file mode 100644
index 0000000000..835cdeeb41
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/tdf153196.rtf
@@ -0,0 +1,114 @@
+{\rtf1\adeflang1025\ansi\ansicpg1250\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1038\deflangfe1038\themelang1038\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\f364\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\f365\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\f367\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\f368\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\f369\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\f370\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\f371\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\f372\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}
+{\f364\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\f365\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\f367\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\f368\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\f369\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\f370\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\f371\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\f372\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\f754\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
+{\f755\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f757\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f758\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f759\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
+{\f760\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f761\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f762\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
+{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}
+{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}
+{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}
+{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}
+{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}
+{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
+{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
+{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}}{\colortbl;\red0\green0\blue0;
+\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
+\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs22\lang1038\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025
+\ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{
+\s15\ql \li0\ri0\widctlpar\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033
+\sbasedon0 \snext15 \slink16 \sunhideused \styrsid13502046 header;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink15 \slocked \styrsid13502046 Header Char;}{\s17\ql \li0\ri0\widctlpar
+\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033
+\sbasedon0 \snext17 \slink18 \sunhideused \styrsid13502046 footer;}{\*\cs18 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink17 \slocked \styrsid13502046 Footer Char;}}{\*\rsidtbl \rsid4006494\rsid12983264\rsid13502046\rsid16343444}
+\paperw11906\paperh16838\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
+\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml1\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
+\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1
+\jexpand\viewkind1\viewscale70\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
+\asianbrkrule\rsidroot13502046\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
+\nofeaturethrottle1\ilfomacatclnup0
+\ltrpar \sectd \ltrsect\psz9\sbkeven\linex0\headery0\footery397\colsx708\endnhere\titlepg\sectlinegrid360\sectdefaultcl\sectrsid13502046\sftnbj {\footerf \ltrpar \pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar
+\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid13502046
+Hello world!
+\par }}{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}
+{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8
+\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0
+\lang1024\langfe1024\noproof\insrsid13502046 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
+
+\par Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.
+\par Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.
+\par Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.
+\par Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy.
+\par Fusce aliquet pede non pede. Suspendisse dapibus lorem pellentesque magna. Integer nulla.
+\par Donec blandit feugiat ligula. Donec hendrerit, felis et imperdiet euismod, purus ipsum pretium metus, in lacinia nulla nisl eget sapien. Donec ut est in lectus consequat consequat.
+\par Etiam eget dui. Aliquam erat volutpat. Sed at lorem in nunc porta tristique.
+\par Proin nec augue. Quisque aliquam tempor magna. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+\par Nunc ac magna. Maecenas odio dolor, vulputate vel, auctor ac, accumsan id, felis. Pellentesque cursus sagittis felis.
+\par Pellentesque porttitor, velit lacinia egestas auctor, diam eros tempus arcu, nec vulputate augue magna vel risus. Cras non magna vel ante adipiscing rhoncus. Vivamus a mi.
+\par Morbi neque. Aliquam erat volutpat. Integer ultrices lobortis eros.
+\par Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egest
+as. Proin semper, ante vitae sollicitudin posuere, metus quam iaculis nibh, vitae scelerisque nunc massa eget pede. Sed velit urna, interdum vel, ultricies vel, faucibus at, quam.
+\par Donec elit est, consectetuer eget, consequat quis, tempus quis, wisi. In in nunc. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
+\par Donec ullamcorper fringilla eros. Fusce in sapien eu purus dapibus commodo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+\par Cras faucibus condimentum odio. Sed ac ligula. Aliquam at eros.
+\par Etiam at ligula et tellus ullamcorper ultrices. In fermentum, lorem non cursus porttitor, diam urna accumsan lacus, sed interdum wisi nibh nec nisl. Ut tincidunt volutpat urna.
+\par Mauris eleifend nulla eget mauris. Sed cursus quam id felis. Curabitur posuere quam vel nibh.
+\par Cras dapibus dapibus nisl. Vestibulum quis dolor a felis congue vehicula. Maecenas pede purus, tristique ac, tempus eget, egestas quis, mauris.
+\par Curabitur non eros. Nullam hendrerit bibendum justo. Fusce iaculis, est quis lacinia pretium, pede metus molestie lacus, at gravida wisi ante at libero.
+\par Quisque ornare placerat risus. Ut molestie magna at mi. Integer aliquet mauris et nibh.
+\par Ut mattis ligula posuere velit. Nunc sagittis. Curabitur varius fringilla nisl.
+\par Duis pretium mi euismod erat. Maecenas id augue. Nam vulputate.
+\par Duis a quam non neque lobortis malesuada. Praesent euismod. Donec nulla augue, venenatis scelerisque, dapibus a, consequat at, leo.
+\par Pellentesque libero lectus, tristique ac, consectetuer sit amet, imperdiet ut, justo. Sed aliquam odio vitae tortor. Proin hendrerit tempus arcu.
+\par In hac habitasse platea dictumst. Suspendisse potenti. Vivamus vitae massa adipiscing est lacinia sodales.
+\par Donec metus massa, mollis vel, tempus placerat, vestibulum condimentum, ligula. Nunc lacus metus, posuere eget, lacinia eu, varius quis, libero. Aliquam nonummy adipiscing augue.
+\par Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
+\par Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.
+\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13502046 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid13502046
+Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.
+\par }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid13502046
+\par }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid13502046\charrsid13502046 \sect }\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\footerr \ltrpar \pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar
+\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13502046 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0
+\insrsid13502046 Other footer}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid13502046\charrsid13502046
+\par }}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1038\langfe1033\cgrid\langnp1038\langfenp1033 {\rtlch\fcs1
+\af31507 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid13502046
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
+\par Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.
+\par Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.
+\par Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.
+\par Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy.}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid12983264
+\par }
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 1a6d1c9772..58a6857cff 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -1602,6 +1602,26 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf115242)
getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf153196)
+{
+ createSwDoc("tdf153196.rtf");
+
+ const auto& pLayout = parseLayoutDump();
+
+ CPPUNIT_ASSERT_EQUAL(4, getPages());
+
+ // TODO: Writer creates an empty page 1 here, which Word does not
+ assertXPath(pLayout, "/root/page[1]/footer"_ostr, 0);
+ assertXPath(pLayout, "/root/page[2]/footer"_ostr, 1);
+ // the first page (2) has a page style applied, which has a follow page
+ // style; the problem was that the follow page style had a footer.
+ assertXPath(pLayout, "/root/page[3]/footer"_ostr, 0);
+ assertXPath(pLayout, "/root/page[4]/footer"_ostr, 1);
+
+ // TODO exporting this, wrongly produces "even" footer from stashed one
+ // TODO importing that, wrongly creates a footer even without evenAndOddHeaders
+}
+
CPPUNIT_TEST_FIXTURE(Test, testDefaultValues)
{
createSwDoc("default-values.rtf");
diff --git a/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt b/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt
new file mode 100644
index 0000000000..2095c71730
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+ <office:text>
+ <text:section text:name="Section1">
+ <text:section text:name="Section2Hidden" text:display="none">
+ <text:p><draw:frame text:anchor-type="paragraph" svg:x="1cm" svg:y="1cm" svg:width="1cm">
+ <draw:text-box/>
+ </draw:frame>lorem</text:p>
+ </text:section>
+ <text:section text:name="Section3"/>
+ <text:section text:name="Section4"/>
+ <text:section text:name="Section5">
+ <text:p>ipsum</text:p>
+ </text:section>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/data/hiddenSectionsAroundPageBreak.fodt b/sw/qa/extras/uiwriter/data/hiddenSectionsAroundPageBreak.fodt
new file mode 100644
index 0000000000..12761847ed
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/hiddenSectionsAroundPageBreak.fodt
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph" style:master-page-name="Landscape">
+ <style:paragraph-properties style:page-number="auto" fo:break-before="page"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:section text:name="Section 1" text:display="none"/>
+ <text:section text:name="Section 2">
+ <text:p text:style-name="P1">A paragraph with a page-break-before</text:p>
+ </text:section>
+ <text:section text:name="Section 3" text:display="none"/>
+ <text:section text:name="Section 4">
+ <text:p>Lorem</text:p>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/uiwriter4.cxx b/sw/qa/extras/uiwriter/uiwriter4.cxx
index c1f0be1757..98fcbcae22 100644
--- a/sw/qa/extras/uiwriter/uiwriter4.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter4.cxx
@@ -682,8 +682,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testBookmarkCollapsed)
// 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there).
// 7. Save the document:
// <text:p text:style-name="Standard">
-// <text:bookmark-start text:name="test"/>
-// <text:bookmark-end text:name="test"/>
+// <text:bookmark text:name="test"/>
// def
// </text:p>
//
@@ -737,14 +736,10 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkText)
// load only content.xml from the resaved document
xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
- constexpr OString aPath("/office:document-content/office:body/office:text/text:p"_ostr);
-
- CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark")); // not found
- const int pos2 = getXPathPosition(pXmlDoc, aPath, "bookmark-start");
- const int pos3 = getXPathPosition(pXmlDoc, aPath, "bookmark-end");
-
- CPPUNIT_ASSERT_EQUAL(0, pos2); // found, and it is first
- CPPUNIT_ASSERT_EQUAL(1, pos3); // found, and it is second
+ // Bookmark without text becomes collapsed
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark"_ostr, 1);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark-start"_ostr, 0);
+ assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark-end"_ostr, 0);
}
// 1. Open a new writer document
diff --git a/sw/qa/extras/uiwriter/uiwriter9.cxx b/sw/qa/extras/uiwriter/uiwriter9.cxx
index 1a3e49c257..3772955dd9 100644
--- a/sw/qa/extras/uiwriter/uiwriter9.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter9.cxx
@@ -16,6 +16,8 @@
#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/view/XSelectionSupplier.hpp>
+
#include <comphelper/propertysequence.hxx>
#include <swdtflvr.hxx>
#include <o3tl/string_view.hxx>
@@ -26,8 +28,10 @@
#include <ndtxt.hxx>
#include <toxmgr.hxx>
#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <fmtinfmt.hxx>
+#include <rootfrm.hxx>
namespace
{
@@ -122,6 +126,80 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf135083)
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, "PageStyleName"));
+}
+
+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();
+ CPPUNIT_ASSERT(pDoc);
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->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(), "Mark", 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);
+}
+
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/extras/ww8export/data/listWithLgl.doc b/sw/qa/extras/ww8export/data/listWithLgl.doc
new file mode 100644
index 0000000000..94de2967fe
--- /dev/null
+++ b/sw/qa/extras/ww8export/data/listWithLgl.doc
Binary files differ
diff --git a/sw/qa/extras/ww8export/ww8export4.cxx b/sw/qa/extras/ww8export/ww8export4.cxx
index d47c934d9d..d31bf17a31 100644
--- a/sw/qa/extras/ww8export/ww8export4.cxx
+++ b/sw/qa/extras/ww8export/ww8export4.cxx
@@ -228,6 +228,30 @@ DECLARE_WW8EXPORT_TEST(testInlinePageBreakFirstLine, "inlinePageBreakFirstLine.d
CPPUNIT_ASSERT(IsFirstLine(aTextNodes[2]));
}
+CPPUNIT_TEST_FIXTURE(Test, testLegalNumbering)
+{
+ auto verify = [this]() {
+ // Second level's numbering should use Arabic numbers for first level reference
+ auto xPara = getParagraph(1);
+ CPPUNIT_ASSERT_EQUAL(OUString("CH I"), getProperty<OUString>(xPara, "ListLabelString"));
+ xPara = getParagraph(2);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: Sect 1.01
+ // - Actual : Sect I.01
+ // i.e. fLegal was ignored on import/export.
+ CPPUNIT_ASSERT_EQUAL(OUString("Sect 1.01"), getProperty<OUString>(xPara, "ListLabelString"));
+ xPara = getParagraph(3);
+ CPPUNIT_ASSERT_EQUAL(OUString("CH II"), getProperty<OUString>(xPara, "ListLabelString"));
+ xPara = getParagraph(4);
+ CPPUNIT_ASSERT_EQUAL(OUString("Sect 2.01"), getProperty<OUString>(xPara, "ListLabelString"));
+ };
+
+ createSwDoc("listWithLgl.doc");
+ verify();
+ saveAndReload(mpFilter);
+ verify();
+}
+
DECLARE_WW8EXPORT_TEST(testNonInlinePageBreakFirstLine, "nonInlinePageBreakFirstLine.doc")
{
SwDoc* pDoc = getSwDoc();
diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx
index 950136e66e..669fd6dea4 100644
--- a/sw/qa/inc/swmodeltestbase.hxx
+++ b/sw/qa/inc/swmodeltestbase.hxx
@@ -273,13 +273,6 @@ protected:
int getShapes() const;
/**
- * Returns an xml stream of an exported file.
- * To be used when the exporter doesn't create zip archives, but single files
- * (like Flat ODF Export)
- */
- xmlDocUniquePtr parseExportedFile();
-
- /**
* Creates a new document to be used with the internal sw/ API.
*
* Examples:
diff --git a/sw/qa/uitest/data/tdf150443.docx b/sw/qa/uitest/data/tdf150443.docx
index 162aec01f9..f1897c4712 100644
--- a/sw/qa/uitest/data/tdf150443.docx
+++ b/sw/qa/uitest/data/tdf150443.docx
Binary files differ
diff --git a/sw/qa/uitest/writer_tests7/tdf150443.py b/sw/qa/uitest/writer_tests7/tdf150443.py
index fb39bd8a03..91937551a4 100644
--- a/sw/qa/uitest/writer_tests7/tdf150443.py
+++ b/sw/qa/uitest/writer_tests7/tdf150443.py
@@ -26,7 +26,9 @@ class tdf150443(UITestCase):
xsearch = xDialog.getChild("search")
xsearch.executeAction("CLICK", tuple()) #first search
xToolkit.processEventsToIdle()
- self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "4")
+ page = get_state_as_dict(xWriterEdit)["CurrentPage"]
+ # page may depend on font subsitution, just check it moved
+ self.assertTrue(page == "4" or page == "5")
# reject the tracked table row in Manage Changes dialog window
with self.ui_test.execute_modeless_dialog_through_command(".uno:AcceptTrackedChanges", close_button="close") as xTrackDlg:
diff --git a/sw/qa/unit/swmodeltestbase.cxx b/sw/qa/unit/swmodeltestbase.cxx
index d5248bd414..730ece0596 100644
--- a/sw/qa/unit/swmodeltestbase.cxx
+++ b/sw/qa/unit/swmodeltestbase.cxx
@@ -517,12 +517,6 @@ int SwModelTestBase::getShapes() const
return xDraws->getCount();
}
-xmlDocUniquePtr SwModelTestBase::parseExportedFile()
-{
- auto stream(SvFileStream(maTempFile.GetURL(), StreamMode::READ | StreamMode::TEMPORARY));
- return parseXmlStream(&stream);
-}
-
void SwModelTestBase::createSwDoc(const char* pName, const char* pPassword)
{
if (!pName)
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 173414ed4d..b7f6962982 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -775,6 +775,8 @@ static typename SwCursorShell::StartsWith StartsWith(SwStartNode const& rStart)
switch (rNode.GetNodeType())
{
case SwNodeType::Section:
+ if (rNode.GetSectionNode()->GetSection().IsHidden())
+ return SwCursorShell::StartsWith::HiddenSection;
continue;
case SwNodeType::Table:
return SwCursorShell::StartsWith::Table;
@@ -799,11 +801,16 @@ static typename SwCursorShell::StartsWith EndsWith(SwStartNode const& rStart)
switch (rNode.GetNodeType())
{
case SwNodeType::End:
- if (rNode.StartOfSectionNode()->IsTableNode())
+ if (auto pStartNode = rNode.StartOfSectionNode(); pStartNode->IsTableNode())
{
return SwCursorShell::StartsWith::Table;
}
-//TODO buggy SwUndoRedline in testTdf137503? assert(rNode.StartOfSectionNode()->IsSectionNode());
+ else if (pStartNode->IsSectionNode())
+ {
+ if (pStartNode->GetSectionNode()->GetSection().IsHidden())
+ return SwCursorShell::StartsWith::HiddenSection;
+ }
+ //TODO buggy SwUndoRedline in testTdf137503? assert(rNode.StartOfSectionNode()->IsSectionNode());
break;
case SwNodeType::Text:
if (rNode.GetTextNode()->IsHidden())
@@ -944,14 +951,14 @@ bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
return bRet;
}
-bool SwCursorShell::isInHiddenTextFrame(SwShellCursor* pShellCursor)
+bool SwCursorShell::isInHiddenFrame(SwShellCursor* pShellCursor)
{
SwContentNode *pCNode = pShellCursor->GetPointContentNode();
std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false);
SwContentFrame *const pFrame = pCNode
? pCNode->getLayoutFrame(GetLayout(), pShellCursor->GetPoint(), &tmp)
: nullptr;
- return !pFrame || (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow());
+ return !pFrame || pFrame->IsHiddenNow();
}
// sw_redlinehide: this should work for all cases: GoCurrPara, GoNextPara, GoPrevPara
@@ -992,7 +999,7 @@ bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const &
//which is what SwCursorShell::UpdateCursorPos will reset
//the position to if we pass it a position in an
//invisible hidden paragraph field
- while (isInHiddenTextFrame(pTmpCursor)
+ while (isInHiddenFrame(pTmpCursor)
|| !IsAtStartOrEndOfFrame(this, pTmpCursor, fnPosPara))
{
if (!pTmpCursor->MovePara(fnWhichPara, fnPosPara))
@@ -1796,7 +1803,7 @@ void SwCursorShell::UpdateCursorPos()
SwShellCursor* pShellCursor = getShellCursor( true );
Size aOldSz( GetDocSize() );
- if (isInHiddenTextFrame(pShellCursor) && !ExtendedSelectedAll())
+ if (isInHiddenFrame(pShellCursor) && !ExtendedSelectedAll())
{
SwCursorMoveState aTmpState(CursorMoveState::SetOnlyText);
aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
@@ -1805,14 +1812,14 @@ void SwCursorShell::UpdateCursorPos()
pShellCursor->DeleteMark();
// kde45196-1.html: try to get to a non-hidden paragraph, there must
// be one in the document body
- while (isInHiddenTextFrame(pShellCursor))
+ while (isInHiddenFrame(pShellCursor))
{
if (!pShellCursor->MovePara(GoNextPara, fnParaStart))
{
break;
}
}
- while (isInHiddenTextFrame(pShellCursor))
+ while (isInHiddenFrame(pShellCursor))
{
if (!pShellCursor->MovePara(GoPrevPara, fnParaStart))
{
@@ -3470,7 +3477,7 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
GetDoc()->GetDocShell()->IsReadOnlyUI() )
return true;
- if( m_pCurrentCursor->HasMark() )
+ if( m_pCurrentCursor->HasMark() && !mbSelectAll )
ClearMark();
// first check for frames
diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx
index 25bf8d0ef6..4f2ceb0a84 100644
--- a/sw/source/core/crsr/pam.cxx
+++ b/sw/source/core/crsr/pam.cxx
@@ -1060,7 +1060,7 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const &
(
nullptr == pFrame ||
( !bInReadOnly && pFrame->IsProtected() ) ||
- (pFrame->IsTextFrame() && static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
+ pFrame->IsHiddenNow()
) ||
( !bInReadOnly && pNd->FindSectionNode() &&
pNd->FindSectionNode()->GetSection().IsProtect()
@@ -1101,8 +1101,7 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const &
SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout));
if (nullptr == pFrame ||
( !bInReadOnly && pFrame->IsProtected() ) ||
- ( pFrame->IsTextFrame() &&
- static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow()))
+ pFrame->IsHiddenNow())
{
pNd = nullptr;
continue;
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 8d0246bed1..5a2f9afead 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -913,7 +913,7 @@ static bool lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
rPam.SetMark();
rPam.GetPoint()->Assign(rEndNd);
- pCNd = SwNodes::GoPrevious( rPam.GetPoint() );
+ pCNd = SwNodes::GoPrevious(rPam.GetPoint(), true);
if( !pCNd )
return false;
rPam.GetPoint()->AssignEndIndex(*pCNd);
@@ -933,7 +933,7 @@ static bool lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
if( !bFirst )
{
rPam.GetPoint()->Assign(rSttNd);
- pCNd = SwNodes::GoPrevious( rPam.GetPoint() );
+ pCNd = SwNodes::GoPrevious(rPam.GetPoint(), true);
if( !pCNd )
return false;
rPam.GetPoint()->AssignEndIndex(*pCNd);
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 09e0a1233e..57b8e58310 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3788,11 +3788,16 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
SwDoc& rDest = rInsPos.GetDoc();
SwNodeIndex aSavePos( rInsPos );
+ SwPaM aCopiedPaM(rRg.aStart, rRg.aEnd);
+ if (pCopiedPaM)
+ aCopiedPaM = pCopiedPaM->first;
+
if (rRg.aStart != rRg.aEnd)
{
bool bEndIsEqualEndPos = rInsPos == rRg.aEnd.GetNode();
--aSavePos;
SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
+ auto savedEndContentIndex = aCopiedPaM.End()->GetContentIndex();
// insert behind the already copied start node
m_rDoc.GetNodes().CopyNodes( rRg, rInsPos, false, true );
@@ -3801,6 +3806,10 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
if (bEndIsEqualEndPos)
{
const_cast<SwNodeIndex&>(rRg.aEnd).Assign(aSavePos.GetNode(), +1);
+ // pCopiedPaM->first now spans a range from the start of the original selection
+ // to the end of newly added text, and the insertion point is in the middle of
+ // that range. Adjust the local copy to cover the original copied PaM.
+ aCopiedPaM.End()->Assign(rRg.aEnd, savedEndContentIndex);
}
}
@@ -3810,7 +3819,6 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
// sw_fieldmarkhide: also needs to be done before making frames
if (m_rDoc.getIDocumentMarkAccess()->getAllMarksCount())
{
- SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
SwPosition targetPos(aSavePos, SwNodeOffset(rRg.aStart != rRg.aEnd ? +1 : 0));
if (pCopiedPaM && rRg.aStart != pCopiedPaM->first.Start()->GetNode())
{
@@ -3823,7 +3831,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
targetPos = pCopiedPaM->second;
}
- sw::CopyBookmarks(pCopiedPaM ? pCopiedPaM->first : aRgTmp, targetPos, flags);
+ sw::CopyBookmarks(aCopiedPaM, targetPos, flags);
}
if (rRg.aStart != rRg.aEnd)
@@ -3914,7 +3922,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
{
::sw::UndoGuard const undoGuard(rDest.GetIDocumentUndoRedo());
- CopyFlyInFlyImpl(rRg, pCopiedPaM ? &pCopiedPaM->first : nullptr,
+ CopyFlyInFlyImpl(rRg, pCopiedPaM ? &aCopiedPaM : nullptr,
// see comment below regarding use of pCopiedPaM->second
(pCopiedPaM && rRg.aStart != pCopiedPaM->first.Start()->GetNode())
? pCopiedPaM->second.GetNode()
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index c78d8e18b6..2a5aad64de 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -553,7 +553,7 @@ uno::Any SwDoc::Spell( SwPaM& rPaM,
{
nCurrNd = pNd->EndOfSectionIndex();
}
- else if( !static_cast<SwTextFrame*>(pContentFrame)->IsHiddenNow() )
+ else if( !pContentFrame->IsHiddenNow() )
{
if( pPageCnt && *pPageCnt && pPageSt )
{
@@ -766,7 +766,7 @@ static bool lcl_HyphenateNode( SwNode* pNd, void* pArgs )
// sw_redlinehide: this will be called once per node for merged nodes;
// the fully deleted ones won't have frames so are skipped.
SwContentFrame* pContentFrame = pNode->getLayoutFrame( pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
- if( pContentFrame && !static_cast<SwTextFrame*>(pContentFrame)->IsHiddenNow() )
+ if( pContentFrame && !pContentFrame->IsHiddenNow() )
{
sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index d6c943dbcd..1c696bebb6 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -1553,21 +1553,21 @@ void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
{
if (pStashedFormatSrc->GetDoc() != this)
{
- SwFrameFormat* pNewFormat = new SwFrameFormat(GetAttrPool(), "CopyDesc", GetDfltFrameFormat());
+ SwFrameFormat newFormat(GetAttrPool(), "CopyDesc", GetDfltFrameFormat());
SfxItemSet aAttrSet(pStashedFormatSrc->GetAttrSet());
aAttrSet.ClearItem(RES_HEADER);
aAttrSet.ClearItem(RES_FOOTER);
- pNewFormat->DelDiffs( aAttrSet );
- pNewFormat->SetFormatAttr( aAttrSet );
+ newFormat.DelDiffs(aAttrSet);
+ newFormat.SetFormatAttr(aAttrSet);
if (bHeader)
- CopyHeader(*pStashedFormatSrc, *pNewFormat);
+ CopyHeader(*pStashedFormatSrc, newFormat);
else
- CopyFooter(*pStashedFormatSrc, *pNewFormat);
+ CopyFooter(*pStashedFormatSrc, newFormat);
- rDstDesc.StashFrameFormat(*pNewFormat, bHeader, bLeft, bFirst);
+ rDstDesc.StashFrameFormat(newFormat, bHeader, bLeft, bFirst);
}
else
{
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index f03687d810..d29223050b 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -1057,7 +1057,7 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
SwSectionFormat* pSectFormat = rDoc.MakeSectionFormat();
rDoc.GetNodes().InsertTextSection(
*pHeadNd, *pSectFormat, headerData, nullptr, &aIdx.GetNode(), true, false);
-
+ pSectFormat->GetSection()->SetProtect(SwTOXBase::IsProtected());
if (pUndo)
{
pUndo->TitleSectionInserted(*pSectFormat);
diff --git a/sw/source/core/docnode/ndsect.cxx b/sw/source/core/docnode/ndsect.cxx
index cf96e1d509..1da9ecb43e 100644
--- a/sw/source/core/docnode/ndsect.cxx
+++ b/sw/source/core/docnode/ndsect.cxx
@@ -1022,9 +1022,9 @@ SwSectionNode::~SwSectionNode()
}
}
-SwFrame *SwSectionNode::MakeFrame( SwFrame *pSib )
+SwFrame* SwSectionNode::MakeFrame(SwFrame* pSib, bool bHidden)
{
- m_pSection->m_Data.SetHiddenFlag(false);
+ m_pSection->m_Data.SetHiddenFlag(bHidden);
return new SwSectionFrame( *m_pSection, pSib );
}
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index a7a2bee478..f3b3a07d63 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -888,6 +888,34 @@ const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTableOpts,
return &rNdTable;
}
+static void lcl_RemoveBreaksTable(SwTableNode & rNode, SwTableFormat *const pTableFormat)
+{
+ // delete old layout frames, new ones need to be created...
+ rNode.DelFrames(nullptr);
+
+ // remove PageBreaks/PageDesc/ColBreak
+ SwFrameFormat & rFormat(*rNode.GetTable().GetFrameFormat());
+
+ if (const SvxFormatBreakItem* pItem = rFormat.GetItemIfSet(RES_BREAK, false))
+ {
+ if (pTableFormat)
+ {
+ pTableFormat->SetFormatAttr(*pItem);
+ }
+ rFormat.ResetFormatAttr(RES_BREAK);
+ }
+
+ SwFormatPageDesc const*const pPageDescItem(rFormat.GetItemIfSet(RES_PAGEDESC, false));
+ if (pPageDescItem && pPageDescItem->GetPageDesc())
+ {
+ if (pTableFormat)
+ {
+ pTableFormat->SetFormatAttr(*pPageDescItem);
+ }
+ rFormat.ResetFormatAttr(RES_PAGEDESC);
+ }
+}
+
static void lcl_RemoveBreaks(SwContentNode & rNode, SwTableFormat *const pTableFormat)
{
// delete old layout frames, new ones need to be created...
@@ -1385,10 +1413,19 @@ SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes,
// delete frames of all contained content nodes
for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines )
{
- SwNode& rNode = aNodeIndex.GetNode();
- if( rNode.IsContentNode() )
+ SwNode* pNode(&aNodeIndex.GetNode());
+ while (pNode->IsSectionNode()) // could be ToX field in table
+ {
+ pNode = pNode->GetNodes()[pNode->GetIndex()+1];
+ }
+ if (pNode->IsTableNode())
+ {
+ lcl_RemoveBreaksTable(static_cast<SwTableNode&>(*pNode),
+ (0 == nLines) ? pTableFormat : nullptr);
+ }
+ else if (pNode->IsContentNode())
{
- lcl_RemoveBreaks(static_cast<SwContentNode&>(rNode),
+ lcl_RemoveBreaks(static_cast<SwContentNode&>(*pNode),
(0 == nLines) ? pTableFormat : nullptr);
}
}
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index c6ecb9ccf9..3506dff230 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1336,34 +1336,68 @@ SwContentNode* SwNodes::GoNext(SwPosition *pIdx) const
return static_cast<SwContentNode*>(pNd);
}
-SwContentNode* SwNodes::GoPrevious(SwNodeIndex *pIdx)
+SwNodeOffset SwNodes::StartOfGlobalSection(const SwNode& node) const
+{
+ const SwNodeOffset pos = node.GetIndex();
+ if (GetEndOfExtras().GetIndex() < pos)
+ // Regular ContentSection
+ return GetEndOfExtras().GetIndex() + SwNodeOffset(1);
+ if (GetEndOfAutotext().GetIndex() < pos)
+ // Redlines
+ return GetEndOfAutotext().GetIndex() + SwNodeOffset(1);
+ if (GetEndOfInserts().GetIndex() < pos)
+ {
+ // Flys/Headers/Footers
+ if (auto* p = node.FindFlyStartNode())
+ return p->GetIndex();
+ if (auto* p = node.FindHeaderStartNode())
+ return p->GetIndex();
+ if (auto* p = node.FindFooterStartNode())
+ return p->GetIndex();
+ return GetEndOfInserts().GetIndex() + SwNodeOffset(1);
+ }
+ if (GetEndOfPostIts().GetIndex() < pos)
+ {
+ // Footnotes
+ if (auto* p = node.FindFootnoteStartNode())
+ return p->GetIndex();
+ return GetEndOfPostIts().GetIndex() + SwNodeOffset(1);
+ }
+ return SwNodeOffset(0);
+}
+
+SwContentNode* SwNodes::GoPrevious(SwNodeIndex* pIdx, bool canCrossBoundary)
{
if( !pIdx->GetIndex() )
return nullptr;
SwNodeIndex aTmp( *pIdx, -1 );
+ SwNodeOffset aGlobalStart(
+ canCrossBoundary ? SwNodeOffset(0) : aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
SwNode* pNd = nullptr;
- while( aTmp.GetIndex() && !( pNd = &aTmp.GetNode())->IsContentNode() )
+ while (aTmp > aGlobalStart && !(pNd = &aTmp.GetNode())->IsContentNode())
--aTmp;
- if( !aTmp.GetIndex() )
+ if (aTmp <= aGlobalStart)
pNd = nullptr;
else
(*pIdx) = aTmp;
return static_cast<SwContentNode*>(pNd);
}
-SwContentNode* SwNodes::GoPrevious(SwPosition *pIdx)
+SwContentNode* SwNodes::GoPrevious(SwPosition* pIdx, bool canCrossBoundary)
{
if( !pIdx->GetNodeIndex() )
return nullptr;
SwNodeIndex aTmp( pIdx->GetNode(), -1 );
+ SwNodeOffset aGlobalStart(
+ canCrossBoundary ? SwNodeOffset(0) : aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
SwNode* pNd = nullptr;
- while( aTmp.GetIndex() && !( pNd = &aTmp.GetNode())->IsContentNode() )
+ while( aTmp > aGlobalStart && !( pNd = &aTmp.GetNode())->IsContentNode() )
--aTmp;
- if( !aTmp.GetIndex() )
+ if (aTmp <= aGlobalStart)
pNd = nullptr;
else
pIdx->Assign(aTmp);
@@ -1963,7 +1997,7 @@ SwContentNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
if (SwNodeType::Section == pNd->GetNodeType())
{
const SwSection& rSect = static_cast<const SwSectionNode*>(pNd)->GetSection();
- if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ if( (bSkipHidden && rSect.CalcHiddenFlag()) ||
(bSkipProtect && rSect.IsProtectFlag()) )
// than skip the section
aTmp = *pNd->EndOfSectionNode();
@@ -1974,7 +2008,7 @@ SwContentNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
{
const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
m_pStartOfSection)->GetSection();
- if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ if( (bSkipHidden && rSect.CalcHiddenFlag()) ||
(bSkipProtect && rSect.IsProtectFlag()) )
// than skip the section
aTmp = *pNd->EndOfSectionNode();
@@ -1985,7 +2019,7 @@ SwContentNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
const SwSectionNode* pSectNd;
if( ( bSkipHidden || bSkipProtect ) &&
nullptr != (pSectNd = pNd->FindSectionNode() ) &&
- ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
+ ( ( bSkipHidden && pSectNd->GetSection().CalcHiddenFlag() ) ||
( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
{
aTmp = *pSectNd->EndOfSectionNode();
@@ -2072,8 +2106,9 @@ SwContentNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
{
bool bFirst = true;
SwNodeIndex aTmp( *pIdx );
+ SwNodeOffset aGlobalStart(aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
const SwNode* pNd;
- while( aTmp > SwNodeOffset(0) )
+ while (aTmp > aGlobalStart)
{
pNd = & aTmp.GetNode();
if (SwNodeType::End == pNd->GetNodeType())
@@ -2129,8 +2164,9 @@ SwContentNode* SwNodes::GoPrevSection( SwPosition * pIdx,
{
bool bFirst = true;
SwNodeIndex aTmp( pIdx->GetNode() );
+ SwNodeOffset aGlobalStart(aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
const SwNode* pNd;
- while( aTmp > SwNodeOffset(0) )
+ while (aTmp > aGlobalStart)
{
pNd = & aTmp.GetNode();
if (SwNodeType::End == pNd->GetNodeType())
diff --git a/sw/source/core/docnode/section.cxx b/sw/source/core/docnode/section.cxx
index 12d9e281c2..53418541eb 100644
--- a/sw/source/core/docnode/section.cxx
+++ b/sw/source/core/docnode/section.cxx
@@ -299,14 +299,11 @@ void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
// Tell all Children that they are hidden
const sw::SectionHidden aHint;
pFormat->CallSwClientNotify(aHint);
-
- // Delete all Frames
- pFormat->DelFrames();
}
}
else if (m_Data.IsHiddenFlag()) // show Nodes again
{
- // Show all Frames (Child Sections are accounted for by MakeFrames)
+ // Show all Frames
// Only if the Parent Section is not restricting us!
SwSection* pParentSect = pFormat->GetParentSection();
if( !pParentSect || !pParentSect->IsHiddenFlag() )
@@ -314,8 +311,6 @@ void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
// Tell all Children that the Parent is not hidden anymore
const sw::SectionHidden aHint(false);
pFormat->CallSwClientNotify(aHint);
-
- pFormat->MakeFrames();
}
}
}
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index 333eecd352..0400dc8871 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -796,7 +796,7 @@ void SwEditShell::SetNumberingRestart()
if( nullptr != pContentFrame )
{
// skip hidden frames - ignore protection!
- if( !static_cast<SwTextFrame*>(pContentFrame)->IsHiddenNow() )
+ if( !pContentFrame->IsHiddenNow() )
{
// if the node is numbered and the starting value of the numbering equals the
// start value of the numbering rule then set this value as hard starting value
diff --git a/sw/source/core/edit/edsect.cxx b/sw/source/core/edit/edsect.cxx
index a7e652aea9..070a37a90d 100644
--- a/sw/source/core/edit/edsect.cxx
+++ b/sw/source/core/edit/edsect.cxx
@@ -308,89 +308,121 @@ static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
// pInnermostNode contains the section/table before/after which we should
// insert our empty paragraph, or it will be NULL if none is found.
const SwNode* pInnermostNode = nullptr;
+ const SwSection* pSection = nullptr;
{
const SwNode* pTableNode = rCurrentNode.FindTableNode();
const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
// find the table/section which is close
if( pTableNode == nullptr )
+ {
+ if( pSectionNode == nullptr )
+ return nullptr;
+
pInnermostNode = pSectionNode;
+ pSection = &static_cast<const SwSectionNode*>(pSectionNode)->GetSection();
+ }
else if ( pSectionNode == nullptr )
pInnermostNode = pTableNode;
else
{
// compare and choose the larger one
- pInnermostNode =
- ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
- ? pSectionNode : pTableNode;
+ if (pSectionNode->GetIndex() > pTableNode->GetIndex())
+ {
+ pInnermostNode = pSectionNode;
+ pSection = &static_cast<const SwSectionNode*>(pSectionNode)->GetSection();
+ }
+ else
+ pInnermostNode = pTableNode;
}
}
-
- // The previous version had a check to skip empty read-only sections. Those
- // shouldn't occur, so we only need to check whether our pInnermostNode is
- // inside a protected area.
-
- // Now, pInnermostNode is NULL or the innermost section or table node.
- if( (pInnermostNode != nullptr) && !pInnermostNode->IsProtect() )
+ if(pInnermostNode != nullptr)
{
- OSL_ENSURE( pInnermostNode->IsTableNode() ||
- pInnermostNode->IsSectionNode(), "wrong node found" );
- OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
- ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
- rCurrentNode.GetIndex() ), "wrong node found" );
-
- // we now need to find the possible start/end positions
-
- // we found a start if
- // - we're at or just before a start node
- // - there are only start nodes between the current and pInnermostNode
- SwNodeIndex aBegin( pCurrentPos->GetNode() );
- if( rCurrentNode.IsContentNode() &&
- (pCurrentPos->GetContentIndex() == 0))
- --aBegin;
- while( (aBegin != pInnermostNode->GetIndex()) &&
- aBegin.GetNode().IsStartNode() )
- --aBegin;
- bool bStart = ( aBegin == pInnermostNode->GetIndex() );
-
- // we found an end if
- // - we're at or just before an end node
- // - there are only end nodes between the current node and
- // pInnermostNode's end node or
- // - there are only end nodes between the last table cell merged with
- // the current cell and pInnermostNode's end node
- SwNodeIndex aEnd( pCurrentPos->GetNode() );
- if( rCurrentNode.IsContentNode() &&
- ( pCurrentPos->GetContentIndex() ==
- rCurrentNode.GetContentNode()->Len() ) )
+ bool bIsProtected = pInnermostNode->IsProtect();
+
+ //special case - ToxSection
+ // - in this case the inner section could be tox header
+ // section but the new node should be before the content section
+ // protection of the tox should not prevent the insertion
+ // only protection outside needs to be checked
+ if( pSection &&
+ (SectionType::ToxHeader == pSection->GetType() ||
+ SectionType::ToxContent == pSection->GetType()))
{
- ++aEnd;
+ if (SectionType::ToxHeader == pSection->GetType())
+ {
+ if (const SwSection* pSectionParent = pSection->GetParent())
+ pInnermostNode = pSectionParent->GetFormat()->GetSectionNode();
+ }
+ bIsProtected = static_cast<const SwSectionNode*>(pInnermostNode)->IsInProtectSect();
+ }
- // tdf#156492 handle cells merged vertically in the bottom right corner
- if ( pInnermostNode->IsTableNode() )
+ // The previous version had a check to skip empty read-only sections. Those
+ // shouldn't occur, so we only need to check whether our pInnermostNode is
+ // inside a protected area.
+
+ // Now, pInnermostNode is NULL or the innermost section or table node.
+ if(!bIsProtected)
+ {
+ OSL_ENSURE( pInnermostNode->IsTableNode() ||
+ pInnermostNode->IsSectionNode(), "wrong node found" );
+ OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
+ ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
+ rCurrentNode.GetIndex() ), "wrong node found" );
+
+ // we now need to find the possible start/end positions
+
+ // we found a start if
+ // - we're at or just before a start node
+ // - there are only start nodes between the current and pInnermostNode
+ SwNodeIndex aBegin( pCurrentPos->GetNode() );
+ if( rCurrentNode.IsContentNode() &&
+ (pCurrentPos->GetContentIndex() == 0))
+ --aBegin;
+ while( (aBegin != pInnermostNode->GetIndex()) &&
+ aBegin.GetNode().IsStartNode() )
+ --aBegin;
+ bool bStart = ( aBegin == pInnermostNode->GetIndex() );
+
+ // we found an end if
+ // - we're at or just before an end node
+ // - there are only end nodes between the current node and
+ // pInnermostNode's end node or
+ // - there are only end nodes between the last table cell merged with
+ // the current cell and pInnermostNode's end node
+ SwNodeIndex aEnd( pCurrentPos->GetNode() );
+ if( rCurrentNode.IsContentNode() &&
+ ( pCurrentPos->GetContentIndex() ==
+ rCurrentNode.GetContentNode()->Len() ) )
{
- const SwNode* pTableBoxStartNode = pCurrentPos->GetNode().FindTableBoxStartNode();
- const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
- if ( pTableBox && pTableBox->getRowSpan() > 1 )
+ ++aEnd;
+
+ // tdf#156492 handle cells merged vertically in the bottom right corner
+ if ( pInnermostNode->IsTableNode() )
{
- const SwTableNode* pTableNd = pInnermostNode->FindTableNode();
- pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
- pTableBox->getRowSpan() );
- pTableBoxStartNode = pTableBox->GetSttNd();
- aEnd = pTableBoxStartNode->GetIndex() + 2;
+ const SwNode* pTableBoxStartNode = pCurrentPos->GetNode().FindTableBoxStartNode();
+ const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
+ if ( pTableBox && pTableBox->getRowSpan() > 1 )
+ {
+ const SwTableNode* pTableNd = pInnermostNode->FindTableNode();
+ pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
+ pTableBox->getRowSpan() );
+ pTableBoxStartNode = pTableBox->GetSttNd();
+ aEnd = pTableBoxStartNode->GetIndex() + 2;
+ }
}
}
+ while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
+ aEnd.GetNode().IsEndNode() )
+ ++aEnd;
+ bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
+
+ // evaluate result: if both start + end, end is preferred
+ if( bEnd )
+ pReturn = pInnermostNode->EndOfSectionNode();
+ else if ( bStart )
+ pReturn = pInnermostNode;
}
- while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
- aEnd.GetNode().IsEndNode() )
- ++aEnd;
- bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
-
- // evaluate result: if both start + end, end is preferred
- if( bEnd )
- pReturn = pInnermostNode->EndOfSectionNode();
- else if ( bStart )
- pReturn = pInnermostNode;
}
OSL_ENSURE( ( pReturn == nullptr ) || pReturn->IsStartNode() ||
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index d57654f6a9..604488a18c 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -891,6 +891,8 @@ public:
// Fly in ... and footnotes
bool IsProtected() const;
+ virtual bool IsHiddenNow() const;
+
bool IsColLocked() const { return mbColLocked; }
virtual bool IsDeleteForbidden() const { return mnForbidDelete > 0; }
diff --git a/sw/source/core/inc/sectfrm.hxx b/sw/source/core/inc/sectfrm.hxx
index c07d78b12b..69158b3358 100644
--- a/sw/source/core/inc/sectfrm.hxx
+++ b/sw/source/core/inc/sectfrm.hxx
@@ -88,6 +88,8 @@ public:
virtual void Cut() override;
virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) override;
+ virtual bool IsHiddenNow() const override;
+
inline const SwSectionFrame *GetFollow() const;
inline SwSectionFrame *GetFollow();
SwSectionFrame* FindMaster() const;
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index e60dbd20fb..df11ca589b 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -559,7 +559,7 @@ public:
#endif
/// Hidden
- bool IsHiddenNow() const; // bHidden && pOut == pPrt
+ virtual bool IsHiddenNow() const override; // bHidden && pOut == pPrt
void HideHidden(); // Remove appendage if Hidden
void HideFootnotes(TextFrameIndex nStart, TextFrameIndex nEnd);
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index c2bbdd8904..e13fdf0121 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -177,7 +177,7 @@ bool SwContentFrame::ShouldBwdMoved( SwLayoutFrame *pNewUpper, bool & )
if ( nMoveAnyway < 3 )
{
- if ( nSpace )
+ if (nSpace || IsHiddenNow())
{
// Do not notify footnotes which are stuck to the paragraph:
// This would require extremely confusing code, taking into
@@ -209,7 +209,7 @@ bool SwContentFrame::ShouldBwdMoved( SwLayoutFrame *pNewUpper, bool & )
}
// Check for space left in new upper
- return nSpace != 0;
+ return nSpace != 0 || IsHiddenNow();
}
}
return false;
@@ -532,7 +532,7 @@ static SwFrame* lcl_NotHiddenPrev( SwFrame* pFrame )
do
{
pRet = lcl_Prev( pRet );
- } while ( pRet && pRet->IsTextFrame() && static_cast<SwTextFrame*>(pRet)->IsHiddenNow() );
+ } while ( pRet && pRet->IsHiddenNow() );
return pRet;
}
@@ -1083,9 +1083,8 @@ void SwContentFrame::MakePrtArea( const SwBorderAttrs &rAttrs )
setFramePrintAreaValid(true);
SwRectFnSet aRectFnSet(this);
- const bool bTextFrame = IsTextFrame();
SwTwips nUpper = 0;
- if ( bTextFrame && static_cast<SwTextFrame*>(this)->IsHiddenNow() )
+ if (IsTextFrame() && IsHiddenNow())
{
if ( static_cast<SwTextFrame*>(this)->HasFollow() )
static_cast<SwTextFrame*>(this)->JoinFrame();
@@ -1715,7 +1714,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
const bool bMoveFwdInvalid = nullptr != GetIndNext();
const bool bNxtNew =
( 0 == aRectFnSet.GetHeight(pNxt->getFramePrintArea()) ) &&
- (!pNxt->IsTextFrame() ||!static_cast<SwTextFrame*>(pNxt)->IsHiddenNow());
+ !pNxt->IsHiddenNow();
pNxt->Calc(getRootFrame()->GetCurrShell()->GetOut());
@@ -2217,7 +2216,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
pTmpPrev = nullptr;
else
{
- if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow() )
+ if (pFrame->IsHiddenNow())
pTmpPrev = lcl_NotHiddenPrev( pFrame );
else
pTmpPrev = pFrame;
diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx
index 5331baacd9..0dd64c6aec 100644
--- a/sw/source/core/layout/findfrm.cxx
+++ b/sw/source/core/layout/findfrm.cxx
@@ -994,7 +994,7 @@ SwFrame *SwFrame::FindNext_()
(!bFootnote || pSct->IsInFootnote() ) )
return pSct;
}
- return pRet;
+ return pRet == this ? nullptr : pRet;
}
// #i27138# - add parameter <_bInSameFootnote>
@@ -1380,11 +1380,7 @@ void SwFrame::InvalidateNextPrtArea()
SwFrame* pNextFrame = FindNext();
// skip empty section frames and hidden text frames
{
- while ( pNextFrame &&
- ( ( pNextFrame->IsSctFrame() &&
- !static_cast<SwSectionFrame*>(pNextFrame)->GetSection() ) ||
- ( pNextFrame->IsTextFrame() &&
- static_cast<SwTextFrame*>(pNextFrame)->IsHiddenNow() ) ) )
+ while (pNextFrame && pNextFrame->IsHiddenNow())
{
pNextFrame = pNextFrame->FindNext();
}
diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx
index da509e2a6b..88158161c5 100644
--- a/sw/source/core/layout/flowfrm.cxx
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -1271,8 +1271,7 @@ bool SwFlowFrame::IsPageBreak( bool bAct ) const
// Determine predecessor
const SwFrame *pPrev = m_rThis.FindPrev();
- while ( pPrev && ( !pPrev->IsInDocBody() ||
- ( pPrev->IsTextFrame() && static_cast<const SwTextFrame*>(pPrev)->IsHiddenNow() ) ) )
+ while (pPrev && (!pPrev->IsInDocBody() || pPrev->IsHiddenNow()))
pPrev = pPrev->FindPrev();
if ( pPrev )
@@ -1333,7 +1332,7 @@ bool SwFlowFrame::IsColBreak( bool bAct ) const
// Determine predecessor
const SwFrame *pPrev = m_rThis.FindPrev();
while( pPrev && ( ( !pPrev->IsInDocBody() && !m_rThis.IsInFly() && !m_rThis.FindFooterOrHeader() ) ||
- ( pPrev->IsTextFrame() && static_cast<const SwTextFrame*>(pPrev)->IsHiddenNow() ) ) )
+ pPrev->IsHiddenNow() ) )
pPrev = pPrev->FindPrev();
if ( pPrev )
@@ -1364,6 +1363,14 @@ bool SwFlowFrame::IsColBreak( bool bAct ) const
return false;
}
+// Skip hidden paragraphs and empty sections on the same level
+static const SwFrame* skipHiddenSiblingFrames_(const SwFrame* pFrame)
+{
+ while (pFrame && pFrame->IsHiddenNow())
+ pFrame = pFrame->GetPrev();
+ return pFrame;
+}
+
bool SwFlowFrame::HasParaSpaceAtPages( bool bSct ) const
{
if( m_rThis.IsInSct() )
@@ -1379,7 +1386,7 @@ bool SwFlowFrame::HasParaSpaceAtPages( bool bSct ) const
return !pTmp->GetPrev() || IsPageBreak(true);
if( pTmp->IsColumnFrame() && pTmp->GetPrev() )
return IsColBreak( true );
- if( pTmp->IsSctFrame() && ( !bSct || pTmp->GetPrev() ) )
+ if (pTmp->IsSctFrame() && (!bSct || skipHiddenSiblingFrames_(pTmp->GetPrev())))
return false;
pTmp = pTmp->GetUpper();
}
@@ -1401,6 +1408,31 @@ bool SwFlowFrame::HasParaSpaceAtPages( bool bSct ) const
return pTmp && !pTmp->GetPrev();
}
+// Skip hidden paragraphs and empty sections
+static const SwFrame* skipHiddenFrames_(const SwFrame* pFrame)
+{
+ do
+ {
+ pFrame = skipHiddenSiblingFrames_(pFrame);
+ if (!pFrame || !pFrame->IsSctFrame())
+ return pFrame;
+ // Special case: found previous frame is a section
+ // Search for the last content in the section
+ auto pSectFrame = static_cast<const SwSectionFrame*>(pFrame);
+ pFrame = pSectFrame->FindLastContent();
+ // If the last content is in a table _inside_ the section,
+ // take the table herself.
+ // Correction: Check directly, if table is inside table, instead of indirectly
+ // by checking, if section isn't inside a table
+ if (pFrame && pFrame->IsInTab())
+ {
+ const SwTabFrame* pTableFrame = pFrame->FindTabFrame();
+ if (pSectFrame->IsAnLower(pTableFrame))
+ return pTableFrame;
+ }
+ } while (true);
+}
+
/** helper method to determine previous frame for calculation of the
upper space
@@ -1408,73 +1440,21 @@ bool SwFlowFrame::HasParaSpaceAtPages( bool bSct ) const
*/
const SwFrame* SwFlowFrame::GetPrevFrameForUpperSpaceCalc_( const SwFrame* _pProposedPrevFrame ) const
{
- const SwFrame* pPrevFrame = _pProposedPrevFrame
- ? _pProposedPrevFrame
- : m_rThis.GetPrev();
-
- // Skip hidden paragraphs and empty sections
- while ( pPrevFrame &&
- ( ( pPrevFrame->IsTextFrame() &&
- static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ||
- ( pPrevFrame->IsSctFrame() &&
- !static_cast<const SwSectionFrame*>(pPrevFrame)->GetSection() ) ) )
- {
- pPrevFrame = pPrevFrame->GetPrev();
- }
+ const SwFrame* pPrevFrame
+ = skipHiddenFrames_(_pProposedPrevFrame ? _pProposedPrevFrame : m_rThis.GetPrev());
+ if (pPrevFrame || !m_rThis.IsInFootnote()
+ || !(m_rThis.IsSctFrame() || !m_rThis.IsInSct() || !m_rThis.FindSctFrame()->IsInFootnote()))
+ return pPrevFrame;
// Special case: no direct previous frame is found but frame is in footnote
// Search for a previous frame in previous footnote,
// if frame isn't in a section, which is also in the footnote
- if ( !pPrevFrame && m_rThis.IsInFootnote() &&
- ( m_rThis.IsSctFrame() ||
- !m_rThis.IsInSct() || !m_rThis.FindSctFrame()->IsInFootnote() ) )
- {
- const SwFootnoteFrame* pPrevFootnoteFrame =
- static_cast<const SwFootnoteFrame*>(m_rThis.FindFootnoteFrame()->GetPrev());
- if ( pPrevFootnoteFrame )
- {
- pPrevFrame = pPrevFootnoteFrame->GetLastLower();
-
- // Skip hidden paragraphs and empty sections
- while ( pPrevFrame &&
- ( ( pPrevFrame->IsTextFrame() &&
- static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ||
- ( pPrevFrame->IsSctFrame() &&
- !static_cast<const SwSectionFrame*>(pPrevFrame)->GetSection() ) ) )
- {
- pPrevFrame = pPrevFrame->GetPrev();
- }
- }
- }
- // Special case: found previous frame is a section
- // Search for the last content in the section
- if( pPrevFrame && pPrevFrame->IsSctFrame() )
- {
- const SwSectionFrame* pPrevSectFrame =
- static_cast<const SwSectionFrame*>(pPrevFrame);
- pPrevFrame = pPrevSectFrame->FindLastContent();
- // If the last content is in a table _inside_ the section,
- // take the table herself.
- // Correction: Check directly, if table is inside table, instead of indirectly
- // by checking, if section isn't inside a table
- if ( pPrevFrame && pPrevFrame->IsInTab() )
- {
- const SwTabFrame* pTableFrame = pPrevFrame->FindTabFrame();
- if ( pPrevSectFrame->IsAnLower( pTableFrame ) )
- {
- pPrevFrame = pTableFrame;
- }
- }
- // Correction: skip hidden text frames
- while ( pPrevFrame &&
- pPrevFrame->IsTextFrame() &&
- static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() )
- {
- pPrevFrame = pPrevFrame->GetPrev();
- }
- }
+ const SwFootnoteFrame* pPrevFootnoteFrame =
+ static_cast<const SwFootnoteFrame*>(m_rThis.FindFootnoteFrame()->GetPrev());
+ if ( pPrevFootnoteFrame )
+ return skipHiddenFrames_(pPrevFootnoteFrame->GetLastLower());
- return pPrevFrame;
+ return nullptr;
}
// This should be renamed to something like lcl_UseULSpacing
@@ -1912,6 +1892,8 @@ SwTwips SwFlowFrame::CalcAddLowerSpaceAsLastInTableCell(
/// Moves the Frame forward if it seems necessary regarding the current conditions and attributes.
bool SwFlowFrame::CheckMoveFwd( bool& rbMakePage, bool bKeep, bool bIgnoreMyOwnKeepValue )
{
+ if (m_rThis.IsHiddenNow())
+ return false;
const SwFrame* pNxt = m_rThis.GetIndNext();
if ( bKeep && //!bMovedBwd &&
@@ -2299,7 +2281,8 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat )
)
pNewUpper = m_rThis.GetLeaf( MAKEPAGE_FTN, false );
}
- else if ( IsPageBreak( true ) ) // Do we have to respect a PageBreak?
+ // Do we have to respect a PageBreak?
+ else if (IsPageBreak(true) && (!m_rThis.IsInSct() || !m_rThis.FindSctFrame()->IsHiddenNow()))
{
// If the previous page doesn't have a Frame in the body,
// flowing back makes sense despite the PageBreak (otherwise,
@@ -2366,7 +2349,7 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat )
}
}
}
- else if ( IsColBreak( true ) )
+ else if (IsColBreak(true))
{
// If the previous column doesn't contain a ContentFrame, flowing back
// makes sense despite the ColumnBreak, as otherwise we'd get
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index eeab5c60c1..baf632d6eb 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -844,11 +844,7 @@ void SwContentNotify::ImplDestroy()
SwFrame* pPrevFrame = pCnt->FindPrev();
// skip empty section frames and hidden text frames
{
- while ( pPrevFrame &&
- ( ( pPrevFrame->IsSctFrame() &&
- !static_cast<SwSectionFrame*>(pPrevFrame)->GetSection() ) ||
- ( pPrevFrame->IsTextFrame() &&
- static_cast<SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ) )
+ while (pPrevFrame && pPrevFrame->IsHiddenNow())
{
pPrevFrame = pPrevFrame->FindPrev();
}
@@ -1608,7 +1604,7 @@ void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc,
pFrame = pNode->IsTextNode()
? sw::MakeTextFrame(*pNode->GetTextNode(), pLay, eMode)
: pNode->MakeFrame(pLay);
- if( pPageMaker )
+ if (pPageMaker && !pLay->IsHiddenNow())
pPageMaker->CheckInsert( nIndex );
pFrame->InsertBehind( pLay, pPrv );
@@ -1766,15 +1762,11 @@ void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc,
continue; // skip it
}
SwSectionNode *pNode = static_cast<SwSectionNode*>(pNd);
- if( pNode->GetSection().CalcHiddenFlag() )
- // is hidden, skip the area
- nIndex = pNode->EndOfSectionIndex();
- else
{
if (pActualSection)
pActualSection->SetLastPos(pPrv);
- pFrame = pNode->MakeFrame( pLay );
+ pFrame = pNode->MakeFrame(pLay, pNode->GetSection().CalcHiddenFlag());
pActualSection.reset( new SwActualSection( pActualSection.release(),
static_cast<SwSectionFrame*>(pFrame), pNode ) );
if ( pActualSection->GetUpper() )
@@ -1945,7 +1937,8 @@ void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc,
}
else
{
- pFrame = pActualSection->GetSectionNode()->MakeFrame( pLay );
+ pFrame = pActualSection->GetSectionNode()->MakeFrame(
+ pLay, pActualSection->GetSectionNode()->GetSection().IsHiddenFlag());
pFrame->InsertBehind( pLay, pPrv );
static_cast<SwSectionFrame*>(pFrame)->Init();
@@ -2523,8 +2516,7 @@ void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame& _rFrame,
// one as previous frame.
const SwFrame* pPrevFrame = _pPrevFrame ? _pPrevFrame : _rFrame.GetPrev();
// OD 2004-02-13 #i25029# - skip hidden text frames.
- while ( pPrevFrame && pPrevFrame->IsTextFrame() &&
- static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() )
+ while (pPrevFrame && pPrevFrame->IsHiddenNow())
{
pPrevFrame = pPrevFrame->GetPrev();
}
@@ -2555,8 +2547,7 @@ void SwBorderAttrs::CalcJoinedWithNext( const SwFrame& _rFrame )
// corresponding attribute set is set at current text frame.
// OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
const SwFrame* pNextFrame = _rFrame.GetNext();
- while ( pNextFrame && pNextFrame->IsTextFrame() &&
- static_cast<const SwTextFrame*>(pNextFrame)->IsHiddenNow() )
+ while (pNextFrame && pNextFrame->IsHiddenNow())
{
pNextFrame = pNextFrame->GetNext();
}
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index 70453c5727..f4e6072498 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -2965,13 +2965,9 @@ SwContentFrame* SwFootnoteFrame::FindLastContent()
while ( pTmpLastLower && pTmpLastLower->GetNext() )
{
pTmpLastLower = pTmpLastLower->GetNext();
- if ( ( pTmpLastLower->IsTextFrame() &&
- !static_cast<SwTextFrame*>(pTmpLastLower)->IsHiddenNow() ) ||
- ( pTmpLastLower->IsSctFrame() &&
- static_cast<SwSectionFrame*>(pTmpLastLower)->GetSection() &&
- static_cast<SwSectionFrame*>(pTmpLastLower)->ContainsContent() ) ||
- ( pTmpLastLower->IsTabFrame() &&
- static_cast<SwTabFrame*>(pTmpLastLower)->ContainsContent() ) )
+ if (!pTmpLastLower->IsHiddenNow()
+ && (!pTmpLastLower->IsLayoutFrame()
+ || static_cast<SwLayoutFrame*>(pTmpLastLower)->ContainsContent()))
{
pLastLowerOfFootnote = pTmpLastLower;
}
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index bf4bcc45ea..f8c029ea12 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -789,7 +789,10 @@ SwPageDesc *SwPageFrame::FindPageDesc()
return pRet;
}
- SwFrame *pFlow = FindFirstBodyContent();
+ SwContentFrame* pFirstContent = FindFirstBodyContent();
+ while (pFirstContent && pFirstContent->IsHiddenNow())
+ pFirstContent = pFirstContent->GetNextContentFrame();
+ SwFrame* pFlow = pFirstContent;
if ( pFlow && pFlow->IsInTab() )
pFlow = pFlow->FindTabFrame();
diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx
index 2b78823327..f9679bb2a8 100644
--- a/sw/source/core/layout/pagedesc.cxx
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -83,13 +83,13 @@ SwPageDesc::SwPageDesc( const SwPageDesc &rCpy )
, m_FootnoteInfo( rCpy.GetFootnoteInfo() )
, m_pdList( nullptr )
{
- m_aStashedHeader.m_pStashedFirst = rCpy.m_aStashedHeader.m_pStashedFirst;
- m_aStashedHeader.m_pStashedLeft = rCpy.m_aStashedHeader.m_pStashedLeft;
- m_aStashedHeader.m_pStashedFirstLeft = rCpy.m_aStashedHeader.m_pStashedFirstLeft;
+ m_aStashedHeader.m_oStashedFirst = rCpy.m_aStashedHeader.m_oStashedFirst;
+ m_aStashedHeader.m_oStashedLeft = rCpy.m_aStashedHeader.m_oStashedLeft;
+ m_aStashedHeader.m_oStashedFirstLeft = rCpy.m_aStashedHeader.m_oStashedFirstLeft;
- m_aStashedFooter.m_pStashedFirst = rCpy.m_aStashedFooter.m_pStashedFirst;
- m_aStashedFooter.m_pStashedLeft = rCpy.m_aStashedFooter.m_pStashedLeft;
- m_aStashedFooter.m_pStashedFirstLeft = rCpy.m_aStashedFooter.m_pStashedFirstLeft;
+ m_aStashedFooter.m_oStashedFirst = rCpy.m_aStashedFooter.m_oStashedFirst;
+ m_aStashedFooter.m_oStashedLeft = rCpy.m_aStashedFooter.m_oStashedLeft;
+ m_aStashedFooter.m_oStashedFirstLeft = rCpy.m_aStashedFooter.m_oStashedFirstLeft;
if (rCpy.m_pTextFormatColl && rCpy.m_aDepends.IsListeningTo(rCpy.m_pTextFormatColl))
{
@@ -110,13 +110,13 @@ SwPageDesc & SwPageDesc::operator = (const SwPageDesc & rSrc)
m_FirstMaster = rSrc.m_FirstMaster;
m_FirstLeft = rSrc.m_FirstLeft;
- m_aStashedHeader.m_pStashedFirst = rSrc.m_aStashedHeader.m_pStashedFirst;
- m_aStashedHeader.m_pStashedLeft = rSrc.m_aStashedHeader.m_pStashedLeft;
- m_aStashedHeader.m_pStashedFirstLeft = rSrc.m_aStashedHeader.m_pStashedFirstLeft;
+ m_aStashedHeader.m_oStashedFirst = rSrc.m_aStashedHeader.m_oStashedFirst;
+ m_aStashedHeader.m_oStashedLeft = rSrc.m_aStashedHeader.m_oStashedLeft;
+ m_aStashedHeader.m_oStashedFirstLeft = rSrc.m_aStashedHeader.m_oStashedFirstLeft;
- m_aStashedFooter.m_pStashedFirst = rSrc.m_aStashedFooter.m_pStashedFirst;
- m_aStashedFooter.m_pStashedLeft = rSrc.m_aStashedFooter.m_pStashedLeft;
- m_aStashedFooter.m_pStashedFirstLeft = rSrc.m_aStashedFooter.m_pStashedFirstLeft;
+ m_aStashedFooter.m_oStashedFirst = rSrc.m_aStashedFooter.m_oStashedFirst;
+ m_aStashedFooter.m_oStashedLeft = rSrc.m_aStashedFooter.m_oStashedLeft;
+ m_aStashedFooter.m_oStashedFirstLeft = rSrc.m_aStashedFooter.m_oStashedFirstLeft;
m_aDepends.EndListeningAll();
if (rSrc.m_pTextFormatColl && rSrc.m_aDepends.IsListeningTo(rSrc.m_pTextFormatColl))
@@ -416,30 +416,30 @@ void SwPageDesc::ChgFirstShare( bool bNew )
void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bool bLeft, bool bFirst)
{
assert(rFormat.GetRegisteredIn());
- std::shared_ptr<SwFrameFormat>* pFormat = nullptr;
+ std::optional<SwFrameFormat>* pFormat = nullptr;
if (bHeader)
{
if (bLeft && !bFirst)
- pFormat = &m_aStashedHeader.m_pStashedLeft;
+ pFormat = &m_aStashedHeader.m_oStashedLeft;
else if (!bLeft && bFirst)
- pFormat = &m_aStashedHeader.m_pStashedFirst;
+ pFormat = &m_aStashedHeader.m_oStashedFirst;
else if (bLeft && bFirst)
- pFormat = &m_aStashedHeader.m_pStashedFirstLeft;
+ pFormat = &m_aStashedHeader.m_oStashedFirstLeft;
}
else
{
if (bLeft && !bFirst)
- pFormat = &m_aStashedFooter.m_pStashedLeft;
+ pFormat = &m_aStashedFooter.m_oStashedLeft;
else if (!bLeft && bFirst)
- pFormat = &m_aStashedFooter.m_pStashedFirst;
+ pFormat = &m_aStashedFooter.m_oStashedFirst;
else if (bLeft && bFirst)
- pFormat = &m_aStashedFooter.m_pStashedFirstLeft;
+ pFormat = &m_aStashedFooter.m_oStashedFirstLeft;
}
if (pFormat)
{
- *pFormat = std::make_shared<SwFrameFormat>(rFormat);
+ pFormat->emplace(rFormat);
}
else
{
@@ -451,24 +451,24 @@ void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bo
const SwFrameFormat* SwPageDesc::GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const
{
- std::shared_ptr<SwFrameFormat>* pFormat = nullptr;
+ std::optional<SwFrameFormat>* pFormat = nullptr;
if (bLeft && !bFirst)
{
- pFormat = bHeader ? &m_aStashedHeader.m_pStashedLeft : &m_aStashedFooter.m_pStashedLeft;
+ pFormat = bHeader ? &m_aStashedHeader.m_oStashedLeft : &m_aStashedFooter.m_oStashedLeft;
}
else if (!bLeft && bFirst)
{
- pFormat = bHeader ? &m_aStashedHeader.m_pStashedFirst : &m_aStashedFooter.m_pStashedFirst;
+ pFormat = bHeader ? &m_aStashedHeader.m_oStashedFirst : &m_aStashedFooter.m_oStashedFirst;
}
else if (bLeft && bFirst)
{
- pFormat = bHeader ? &m_aStashedHeader.m_pStashedFirstLeft : &m_aStashedFooter.m_pStashedFirstLeft;
+ pFormat = bHeader ? &m_aStashedHeader.m_oStashedFirstLeft : &m_aStashedFooter.m_oStashedFirstLeft;
}
if (pFormat)
{
- return pFormat->get();
+ return pFormat->has_value() ? &**pFormat : nullptr;
}
else
{
@@ -483,15 +483,15 @@ bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) const
{
if (bLeft && !bFirst)
{
- return m_aStashedHeader.m_pStashedLeft != nullptr;
+ return m_aStashedHeader.m_oStashedLeft.has_value();
}
else if (!bLeft && bFirst)
{
- return m_aStashedHeader.m_pStashedFirst != nullptr;
+ return m_aStashedHeader.m_oStashedFirst.has_value();
}
else if (bLeft && bFirst)
{
- return m_aStashedHeader.m_pStashedFirstLeft != nullptr;
+ return m_aStashedHeader.m_oStashedFirstLeft.has_value();
}
else
{
@@ -503,15 +503,15 @@ bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) const
{
if (bLeft && !bFirst)
{
- return m_aStashedFooter.m_pStashedLeft != nullptr;
+ return m_aStashedFooter.m_oStashedLeft.has_value();
}
else if (!bLeft && bFirst)
{
- return m_aStashedFooter.m_pStashedFirst != nullptr;
+ return m_aStashedFooter.m_oStashedFirst.has_value();
}
else if (bLeft && bFirst)
{
- return m_aStashedFooter.m_pStashedFirstLeft != nullptr;
+ return m_aStashedFooter.m_oStashedFirstLeft.has_value();
}
else
{
@@ -527,15 +527,15 @@ void SwPageDesc::RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst)
{
if (bLeft && !bFirst)
{
- m_aStashedHeader.m_pStashedLeft.reset();
+ m_aStashedHeader.m_oStashedLeft.reset();
}
else if (!bLeft && bFirst)
{
- m_aStashedHeader.m_pStashedFirst.reset();
+ m_aStashedHeader.m_oStashedFirst.reset();
}
else if (bLeft && bFirst)
{
- m_aStashedHeader.m_pStashedFirstLeft.reset();
+ m_aStashedHeader.m_oStashedFirstLeft.reset();
}
else
{
@@ -546,15 +546,15 @@ void SwPageDesc::RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst)
{
if (bLeft && !bFirst)
{
- m_aStashedFooter.m_pStashedLeft.reset();
+ m_aStashedFooter.m_oStashedLeft.reset();
}
else if (!bLeft && bFirst)
{
- m_aStashedFooter.m_pStashedFirst.reset();
+ m_aStashedFooter.m_oStashedFirst.reset();
}
else if (bLeft && bFirst)
{
- m_aStashedFooter.m_pStashedFirstLeft.reset();
+ m_aStashedFooter.m_oStashedFirstLeft.reset();
}
else
{
diff --git a/sw/source/core/layout/sectfrm.cxx b/sw/source/core/layout/sectfrm.cxx
index a1fd849ec4..3967a1f564 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -189,6 +189,13 @@ SwSectionFrame::~SwSectionFrame()
{
}
+//virtual
+bool SwSectionFrame::IsHiddenNow() const
+{
+ const auto* pSection = GetSection();
+ return !pSection || pSection->CalcHiddenFlag();
+}
+
void SwSectionFrame::DelEmpty( bool bRemove )
{
if( IsColLocked() )
@@ -1371,6 +1378,20 @@ void SwSectionFrame::Format( vcl::RenderContext* pRenderContext, const SwBorderA
SwRectFnSet aRectFnSet(this);
+ if (GetSection()->CalcHiddenFlag())
+ {
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aRectFnSet.SetHeight(aFrm, 0);
+ }
+ {
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aRectFnSet.SetHeight(aPrt, 0);
+ }
+ setFrameAreaSizeValid(true);
+ setFramePrintAreaValid(true);
+ }
+
if ( !isFramePrintAreaValid() )
{
PROTOCOL( this, PROT::PrintArea, DbgAction::NONE, nullptr )
@@ -2182,6 +2203,11 @@ bool SwSectionFrame::Growable() const
SwTwips SwSectionFrame::Grow_( SwTwips nDist, bool bTst )
{
+ if (GetSection()->CalcHiddenFlag())
+ {
+ return 0;
+ }
+
if ( !IsColLocked() && !HasFixSize() )
{
SwRectFnSet aRectFnSet(this);
@@ -2646,6 +2672,17 @@ void SwSectionFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
return;
SwSectionFrame::MoveContentAndDelete(this, pHint->IsSaveContent());
}
+ else if (rHint.GetId() == SfxHintId::SwSectionHidden)
+ {
+ InvalidateAll();
+ InvalidateObjs(false);
+
+ for (SwFrame* pLowerFrame = Lower(); pLowerFrame; pLowerFrame = pLowerFrame->GetNext())
+ {
+ pLowerFrame->InvalidateAll();
+ pLowerFrame->InvalidateObjs(false);
+ }
+ }
else
SwFrame::SwClientNotify(rMod, rHint);
}
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index f757824561..c4a742c037 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -667,7 +667,7 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& rFollowLine,
{
SwContentFrame const*const pAnchor = pFootnote->GetRef();
SwTabFrame const* pTab = pAnchor->FindTabFrame();
- if (pTab == &rTab)
+ if (pTab)
{
while (pTab->GetUpper()->IsInTab())
{
@@ -1454,6 +1454,8 @@ namespace
auto IsAllHiddenSection(SwSectionFrame const& rSection) -> bool
{
+ if (rSection.IsHiddenNow())
+ return true;
for (SwFrame const* pFrame = rSection.Lower(); pFrame; pFrame = pFrame->GetNext())
{
if (pFrame->IsColumnFrame())
@@ -1474,7 +1476,7 @@ namespace
}
else if (pFrame->IsTextFrame())
{
- if (!static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
+ if (!pFrame->IsHiddenNow())
{
return false;
}
@@ -1509,7 +1511,7 @@ namespace
}
else if (pFrame->IsTextFrame())
{
- if (!static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
+ if (!pFrame->IsHiddenNow())
{
return false;
}
@@ -3371,7 +3373,15 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
}
bool bFlyHoriOrientLeft = text::HoriOrientation::LEFT == rHori.GetHoriOrient();
- if (bSplitFly && !bFlyHoriOrientLeft)
+
+ bool bToplevelSplitFly = false;
+ if (bSplitFly)
+ {
+ // Floating table wrapped by table: avoid this in the nested case.
+ bToplevelSplitFly = !pFly->GetAnchorFrame()->IsInTab();
+ }
+
+ if (bToplevelSplitFly && !bFlyHoriOrientLeft)
{
// Only shift to the right if we don't have enough space on the left.
SwTwips nTabWidth = getFramePrintArea().Width();
diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx
index a8445e90dd..89a5f03302 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -52,6 +52,7 @@
#include <ndtxt.hxx>
#include <undobj.hxx>
#include <flyfrms.hxx>
+#include <sectfrm.hxx>
#include <swselectionlist.hxx>
#include <comphelper/lok.hxx>
@@ -828,8 +829,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
//If I'm in the DocumentBody, I want to stay there.
if ( pStart->IsInDocBody() )
{
- while ( pCnt && (!pCnt->IsInDocBody() ||
- (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
+ while (pCnt && (!pCnt->IsInDocBody() || pCnt->IsHiddenNow()))
{
pCnt = (*fnNxtPrv)( pCnt );
pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
@@ -840,8 +840,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
//case of necessity.
else if ( pStart->IsInFootnote() )
{
- while ( pCnt && (!pCnt->IsInFootnote() ||
- (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
+ while (pCnt && (!pCnt->IsInFootnote() || pCnt->IsHiddenNow()))
{
pCnt = (*fnNxtPrv)( pCnt );
pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
@@ -851,7 +850,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
//In Flys we can go ahead blindly as long as we find a Content.
else if ( pStart->IsInFly() )
{
- if ( pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow() )
+ if (pCnt && pCnt->IsHiddenNow())
{
pCnt = (*fnNxtPrv)( pCnt );
pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
@@ -875,7 +874,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
}
if ( !bSame )
pCnt = nullptr;
- else if (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()) // i73332
+ else if (pCnt->IsHiddenNow()) // i73332
{
pCnt = (*fnNxtPrv)( pCnt );
pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
@@ -958,8 +957,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
}
}
- } while ( !bEnd ||
- (pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()));
+ } while (!bEnd || (pCnt && pCnt->IsHiddenNow()));
if (pCnt == nullptr)
{
@@ -1246,7 +1244,7 @@ const SwContentFrame *SwLayoutFrame::GetContentPos( Point& rPoint,
if ( pComp != pContent )
continue;
- if ( !pContent->IsTextFrame() || !static_cast<const SwTextFrame*>(pContent)->IsHiddenNow() )
+ if (!pContent->IsHiddenNow())
{
SwRect aContentFrame( pContent->UnionFrame() );
if ( aContentFrame.Contains( rPoint ) )
@@ -1727,6 +1725,15 @@ bool SwFrame::IsProtected() const
return false;
}
+// virtual
+bool SwFrame::IsHiddenNow() const
+{
+ if (const auto* pSectFrame = FindSctFrame())
+ return pSectFrame->IsHiddenNow();
+
+ return false;
+}
+
/** @return the physical page number */
sal_uInt16 SwFrame::GetPhyPageNum() const
{
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 302302a9a2..52a51ff1a5 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1485,6 +1485,9 @@ bool SwTextFrame::IsHiddenNow() const
return true;
}
+ if (SwContentFrame::IsHiddenNow())
+ return true;
+
bool bHiddenCharsHidePara(false);
bool bHiddenParaField(false);
if (m_pMergedPara)
@@ -1554,22 +1557,14 @@ bool SwTextFrame::IsHiddenNow() const
// be visible - check this for the 1st body paragraph
if (IsInDocBody() && FindPrevCnt() == nullptr)
{
- bool isAllHidden(true);
for (SwContentFrame const* pNext = FindNextCnt(true);
pNext != nullptr; pNext = pNext->FindNextCnt(true))
{
- if (!pNext->IsTextFrame()
- || !static_cast<SwTextFrame const*>(pNext)->IsHiddenNow())
- {
- isAllHidden = false;
- break;
- }
- }
- if (isAllHidden)
- {
- SAL_INFO("sw.core", "unhiding one body paragraph");
- return false;
+ if (!pNext->IsHiddenNow())
+ return true;
}
+ SAL_INFO("sw.core", "unhiding one body paragraph");
+ return false;
}
return true;
}
diff --git a/sw/source/core/tox/tox.cxx b/sw/source/core/tox/tox.cxx
index 04f43e5d41..b29bafde11 100644
--- a/sw/source/core/tox/tox.cxx
+++ b/sw/source/core/tox/tox.cxx
@@ -148,7 +148,13 @@ void SwTOXMark::RegisterToTOXType(SwTOXType& rType)
bool SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
{
assert(SfxPoolItem::operator==(rAttr));
- return m_pType == static_cast<const SwTOXMark&>(rAttr).m_pType;
+ // tdf#158783 this item was never 'pooled', so operator== was not really
+ // ever used. We discussed to implement it (there is quite some
+ // content), but we came to the point that it's only safe to say
+ // instances are equal when same instance -> fallback to ptr compare.
+ // NOTE: Do *not* use areSfxPoolItemPtrsEqual here, with DBG_UTIL
+ // active the contol/test code there would again call operator==
+ return this == &rAttr;
}
SwTOXMark* SwTOXMark::Clone( SfxItemPool* ) const
diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx
index 70a724814c..30f6d6e619 100644
--- a/sw/source/core/unocore/unocrsrhelper.cxx
+++ b/sw/source/core/unocore/unocrsrhelper.cxx
@@ -225,7 +225,7 @@ void GetSelectableFromAny(uno::Reference<uno::XInterface> const& xIfc,
return;
}
- uno::Reference<text::XTextRange> const xTextRange(xTunnel, UNO_QUERY);
+ uno::Reference<text::XTextRange> const xTextRange(xIfc, UNO_QUERY);
if (xTextRange.is())
{
SwUnoInternalPaM aPam(rTargetDoc);
diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx
index 12db464a87..f9e16b1f42 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -307,6 +307,7 @@ std::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetAutoCharS
{ UNO_NAME_CHAR_BORDER_TOP_COMPLEX_COLOR, RES_CHRATR_BOX, cppu::UnoType<css::util::XComplexColor>::get(), PropertyAttribute::MAYBEVOID, MID_BORDER_TOP_COLOR },
{ UNO_NAME_CHAR_BORDER_BOTTOM_COMPLEX_COLOR, RES_CHRATR_BOX, cppu::UnoType<css::util::XComplexColor>::get(), PropertyAttribute::MAYBEVOID, MID_BORDER_BOTTOM_COLOR },
{ UNO_NAME_CHAR_SHADOW_FORMAT, RES_CHRATR_SHADOW, cppu::UnoType<css::table::ShadowFormat>::get(), PROPERTY_NONE, CONVERT_TWIPS},
+ { UNO_NAME_CHAR_STYLE_NAME, RES_TXTATR_CHARFMT, cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID, 0 },
};
return aAutoCharStyleMap;
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index b2f83fee30..49562c1d02 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -539,11 +539,6 @@ SwUnoCursorHelper::SetCursorPropertyValue(
rMap.getByName(prop.Name);
if (!pEntry)
{
- if (prop.Name == "CharStyleName")
- {
- lcl_setCharStyle(rPam.GetDoc(), prop.Value, items);
- continue;
- }
throw beans::UnknownPropertyException(
"Unknown property: " + prop.Name);
}
@@ -552,7 +547,14 @@ SwUnoCursorHelper::SetCursorPropertyValue(
throw beans::PropertyVetoException(
"Property is read-only: " + prop.Name);
}
- rPropSet.setPropertyValue(*pEntry, prop.Value, items);
+ if (prop.Name == "CharStyleName")
+ {
+ lcl_setCharStyle(rPam.GetDoc(), prop.Value, items);
+ }
+ else
+ {
+ rPropSet.setPropertyValue(*pEntry, prop.Value, items);
+ }
}
IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess();
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 186b5c5b23..494cec7468 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -84,7 +84,17 @@ static void lcl_CreatePortions(
namespace
{
enum class BkmType {
- Start, End, StartEnd
+ // The order is important: BookmarkCompareStruct::operator () depends on it.
+ // When different bookmarks' starts/ends appear at one position, by default (when there's no
+ // frames at the position - see lcl_ExportBookmark), first previous bookmarks close, then
+ // collapsed ones appear, then new bookmarks open.
+ End, StartEnd, Start
+ };
+
+ enum class ExportBookmarkPass
+ {
+ before_frames,
+ after_frames,
};
struct SwXBookmarkPortion_Impl
@@ -124,7 +134,8 @@ namespace
// start of the 2nd bookmark BEFORE the end of the first bookmark
// See bug #i58438# for more details. The below code is correct and
// fixes both #i58438 and #i16896#
- return r1->aPosition < r2->aPosition;
+ return std::make_pair(r1->aPosition, r1->nBkmType)
+ < std::make_pair(r2->aPosition, r2->nBkmType);
}
};
typedef std::multiset < SwXBookmarkPortion_ImplSharedPtr, BookmarkCompareStruct > SwXBookmarkPortion_ImplList;
@@ -132,13 +143,15 @@ namespace
/// Inserts pBkmk to rBkmArr in case it starts or ends at rOwnNode
void lcl_FillBookmark(sw::mark::IMark* const pBkmk, const SwNode& rOwnNode, SwDoc& rDoc, SwXBookmarkPortion_ImplList& rBkmArr)
{
- bool const hasOther = pBkmk->IsExpanded();
+ bool const isExpanded = pBkmk->IsExpanded();
const SwPosition& rStartPos = pBkmk->GetMarkStart();
const SwPosition& rEndPos = pBkmk->GetMarkEnd();
+ // A bookmark where the text was deleted becomes collapsed
+ bool const hasOther = isExpanded && rStartPos != rEndPos;
bool const bStartPosInNode = rStartPos.GetNode() == rOwnNode;
bool const bEndPosInNode = rEndPos.GetNode() == rOwnNode;
sw::mark::CrossRefBookmark* const pCrossRefMark
- = !hasOther && (bStartPosInNode || bEndPosInNode)
+ = !isExpanded && bStartPosInNode
? dynamic_cast<sw::mark::CrossRefBookmark*>(pBkmk)
: nullptr;
@@ -560,15 +573,23 @@ lcl_CreateContentControlPortion(const css::uno::Reference<SwXText>& xParent,
* Exports all bookmarks from rBkmArr into rPortions that have the same start
* or end position as nIndex.
*
- * @param rBkmArr the array of bookmarks. If bOnlyFrameStarts is true, then
- * this is only read, otherwise consumed entries are removed.
+ * @param rBkmArr the array of bookmarks.
*
* @param rFramePositions the list of positions where there is an at-char /
* anchored frame.
+ * Collapsed (BkmType::StartEnd) bookmarks, as well as bookmarks that start/end
+ * at the frame anchor position, are considered as wrapping the frames, if any
+ * (i.e., starts are output before the frames; ends are output after frames).
+ * When there's no frame here, bookmarks are expected to not overlap (#i58438):
+ * first, non-collapsed bookmarks' ends are output; then collapsed bookmarks;
+ * then non-collapsed bookmarks' starts.
*
- * @param bOnlyFrameStarts If true: export only the start of the bookmarks
- * which cover an at-char anchored frame. If false: export the end of the same
- * bookmarks and everything else.
+ * @param stage Case before_frames: if there is a frame at this index, output
+ * starts of both collapsed and non-collapsed bookmarks (remove non-collapsed
+ * starts from rBkmArr, convert collapsed ones to ends); if there's no frame,
+ * doesn't output anything.
+ * Case after_frames: outputs (and removes from rBkmArr) everything (left) at
+ * this index, in the order of occurrence in rBkmArr (see #i58438).
*/
static void lcl_ExportBookmark(
TextRangeList_t & rPortions,
@@ -577,54 +598,56 @@ static void lcl_ExportBookmark(
SwXBookmarkPortion_ImplList& rBkmArr,
const sal_Int32 nIndex,
const o3tl::sorted_vector<sal_Int32>& rFramePositions,
- bool bOnlyFrameStarts)
+ ExportBookmarkPass stage)
{
for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end(); aIter != aEnd; )
{
const SwXBookmarkPortion_ImplSharedPtr& pPtr = *aIter;
if ( nIndex > pPtr->getIndex() )
{
- if (bOnlyFrameStarts)
- ++aIter;
- else
- aIter = rBkmArr.erase(aIter);
+ assert(!"Some bookmarks were not consumed earlier");
continue;
}
if ( nIndex < pPtr->getIndex() )
break;
- if ((BkmType::Start == pPtr->nBkmType && bOnlyFrameStarts) ||
- (BkmType::StartEnd == pPtr->nBkmType))
+ if (stage == ExportBookmarkPass::before_frames)
{
- bool bFrameStart = rFramePositions.find(nIndex) != rFramePositions.end();
- bool bEnd = pPtr->nBkmType == BkmType::StartEnd && bFrameStart && !bOnlyFrameStarts;
- if (pPtr->nBkmType == BkmType::Start || bFrameStart || !bOnlyFrameStarts)
+ if (rFramePositions.find(nIndex) == rFramePositions.end()) // No frames at this index
+ break; // Do nothing; everything will be output at after_frames pass
+
+ if (pPtr->nBkmType == BkmType::End)
{
- // At this we create a text portion, due to one of these
- // reasons:
- // - this is the real start of a non-collapsed bookmark
- // - this is the real position of a collapsed bookmark
- // - this is the start or end (depending on bOnlyFrameStarts)
- // of a collapsed bookmark at the same position as an at-char
- // anchored frame
- rtl::Reference<SwXTextPortion> pPortion =
- new SwXTextPortion(pUnoCursor, xParent, bEnd ? PORTION_BOOKMARK_END : PORTION_BOOKMARK_START);
- rPortions.emplace_back(pPortion);
- pPortion->SetBookmark(pPtr->xBookmark);
- pPortion->SetCollapsed( BkmType::StartEnd == pPtr->nBkmType && !bFrameStart );
+ ++aIter;
+ continue; // Only consider BkmType::Start and BkmType::StartEnd in this pass
}
}
- else if (BkmType::End == pPtr->nBkmType && !bOnlyFrameStarts)
- {
- rtl::Reference<SwXTextPortion> pPortion =
- new SwXTextPortion(pUnoCursor, xParent, PORTION_BOOKMARK_END);
- rPortions.emplace_back(pPortion);
- pPortion->SetBookmark(pPtr->xBookmark);
- }
+
+ // At this we create a text portion, due to one of these
+ // reasons:
+ // - this is the real start of a non-collapsed bookmark
+ // - this is the real end of a non-collapsed bookmark
+ // - this is the real position of a collapsed bookmark
+ // - this is the start or end of a collapsed bookmark at the same position as an at-char
+ // anchored frame
+ const SwTextPortionType portionType
+ = pPtr->nBkmType == BkmType::End ? PORTION_BOOKMARK_END : PORTION_BOOKMARK_START;
+ const bool collapsed
+ = pPtr->nBkmType == BkmType::StartEnd && stage == ExportBookmarkPass::after_frames;
+
+ rtl::Reference<SwXTextPortion> pPortion = new SwXTextPortion(pUnoCursor, xParent, portionType);
+ rPortions.emplace_back(pPortion);
+ pPortion->SetBookmark(pPtr->xBookmark);
+ pPortion->SetCollapsed(collapsed);
// next bookmark
- if (bOnlyFrameStarts)
+ if (pPtr->nBkmType == BkmType::StartEnd && stage == ExportBookmarkPass::before_frames)
+ {
+ // This is a collapsed bookmark around a frame, and its start portion was just emitted;
+ // turn it into an end bookmark to process after_frames
+ pPtr->nBkmType = BkmType::End;
++aIter;
+ }
else
aIter = rBkmArr.erase(aIter);
}
@@ -1168,13 +1191,12 @@ static void lcl_ExportBkmAndRedline(
SwSoftPageBreakList& rBreakArr,
const sal_Int32 nIndex,
const o3tl::sorted_vector<sal_Int32>& rFramePositions,
- bool bOnlyFrameBookmarkStarts)
+ ExportBookmarkPass stage)
{
if (!rBkmArr.empty())
- lcl_ExportBookmark(rPortions, xParent, pUnoCursor, rBkmArr, nIndex, rFramePositions,
- bOnlyFrameBookmarkStarts);
+ lcl_ExportBookmark(rPortions, xParent, pUnoCursor, rBkmArr, nIndex, rFramePositions, stage);
- if (bOnlyFrameBookmarkStarts)
+ if (stage == ExportBookmarkPass::before_frames)
// Only exporting the start of some collapsed bookmarks: no export of
// other arrays.
return;
@@ -1401,7 +1423,7 @@ static void lcl_CreatePortions(
// Then export start of collapsed bookmarks which "cover" at-char
// anchored frames.
lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
- pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, /*bOnlyFrameBookmarkStarts=*/true );
+ pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, ExportBookmarkPass::before_frames );
lcl_ExportAnnotationStarts(
*PortionStack.top().first,
@@ -1419,7 +1441,7 @@ static void lcl_CreatePortions(
// Export ends of the previously started collapsed bookmarks + all
// other bookmarks, redlines, etc.
lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
- pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, /*bOnlyFrameBookmarkStarts=*/false );
+ pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, ExportBookmarkPass::after_frames );
lcl_ExportAnnotationStarts(
*PortionStack.top().first,
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx
index f959d6a610..93603d6d40 100644
--- a/sw/source/core/unocore/unotext.cxx
+++ b/sw/source/core/unocore/unotext.cxx
@@ -1634,6 +1634,9 @@ SwXText::convertToTextFrame(
// see testFlyInFly for why this checks only the edges of the selection,
// and testFloatingTablesAnchor for why it excludes pre/post table
// added nodes
+ // TODO: isGraphicNode here looks dubious; see also tdf#47036 fix;
+ // this needs more investigation when exactly Word considers something
+ // anchored in text frame vs. anchored in body.
if (!isGraphicNode(pFrameFormat)
&& (IsAtParaMatch(*oAnchorCheckPam, rAnchor)
|| (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()
diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx
index 30ba8d3c0a..2587edfaf2 100644
--- a/sw/source/filter/html/css1atr.cxx
+++ b/sw/source/filter/html/css1atr.cxx
@@ -3301,14 +3301,16 @@ SwHTMLWriter& OutCSS1_SvxBox( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
if( rHt.Which() == RES_CHRATR_BOX )
{
+ constexpr std::string_view inline_block("inline-block");
if( rWrt.m_bTagOn )
{
// Inline-block to make the line height changing correspond to the character border
- rWrt.OutCSS1_PropertyAscii(sCSS1_P_display, "inline-block");
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_display, inline_block);
}
else
{
- HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
+ if (!IgnorePropertyForReqIF(rWrt.mbReqIF, sCSS1_P_display, inline_block))
+ HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
return rWrt;
}
}
diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx
index 9f67d1ee03..c880082018 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -1058,7 +1058,7 @@ public:
HTMLStartEndPos( const SfxPoolItem& rItem, sal_Int32 nStt, sal_Int32 nE );
- const SfxPoolItem* GetItem() const { return m_pItem.get(); }
+ const SfxPoolItem& GetItem() const { return *m_pItem; }
void SetStart(sal_Int32 nStt) { m_nStart = nStt; }
sal_Int32 GetStart() const { return m_nStart; }
@@ -1075,7 +1075,7 @@ HTMLStartEndPos::HTMLStartEndPos(const SfxPoolItem& rItem, sal_Int32 nStt, sal_I
, m_pItem(rItem.Clone())
{}
-typedef std::vector<HTMLStartEndPos *> HTMLStartEndPositions;
+typedef std::map<sal_Int32, std::vector<HTMLStartEndPos*>> HTMLStartEndPositions;
namespace {
@@ -1091,8 +1091,8 @@ enum HTMLOnOffState { HTML_NOT_SUPPORTED, // unsupported Attribute
class HTMLEndPosLst
{
- HTMLStartEndPositions m_aStartLst; // list, sorted for start positions
- HTMLStartEndPositions m_aEndLst; // list, sorted for end positions
+ HTMLStartEndPositions m_aStartLst; // list, each position's elements sorted by appearance order
+ HTMLStartEndPositions m_aEndLst; // list, no sort of elements in position
std::deque<sal_Int32> m_aScriptChgLst; // positions where script changes
// 0 is not contained in this list,
// but the text length
@@ -1110,8 +1110,7 @@ class HTMLEndPosLst
// Insert/remove a SttEndPos in/from the Start and End lists.
// The end position is known.
- void InsertItem_( HTMLStartEndPos *pPos, HTMLStartEndPositions::size_type nEndPos );
- void RemoveItem_( HTMLStartEndPositions::size_type nEndPos );
+ void InsertItem_(HTMLStartEndPos* pPos);
// determine the 'type' of the attribute
HTMLOnOffState GetHTMLItemState( const SfxPoolItem& rItem );
@@ -1125,8 +1124,7 @@ class HTMLEndPosLst
sal_Int32 nEndPos );
// adapt the end of a split item
- void FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd,
- HTMLStartEndPositions::size_type nStartPos );
+ void FixSplittedItem(HTMLStartEndPos* pPos, sal_Int32 nNewEnd);
// insert an attribute in the lists and, if necessary, split it
void InsertItem( const SfxPoolItem& rItem, sal_Int32 nStart,
@@ -1144,6 +1142,8 @@ class HTMLEndPosLst
const SwHTMLFormatInfo *GetFormatInfo( const SwFormat& rFormat,
SwHTMLFormatInfos& rFormatInfos );
+ void OutEndAttrs(SwHTMLWriter& rWrt, std::vector<HTMLStartEndPos*>& posItems);
+
public:
HTMLEndPosLst( SwDoc *pDoc, SwDoc* pTemplate, std::optional<Color> xDfltColor,
@@ -1169,36 +1169,46 @@ public:
bool IsHTMLMode(sal_uLong nMode) const { return (m_nHTMLMode & nMode) != 0; }
};
-}
-
-void HTMLEndPosLst::InsertItem_( HTMLStartEndPos *pPos, HTMLStartEndPositions::size_type nEndPos )
+struct SortEnds
{
- // Insert the attribute in the Start list behind all attributes that
- // were started before, or at the same position.
- sal_Int32 nStart = pPos->GetStart();
- HTMLStartEndPositions::size_type i {0};
+ HTMLStartEndPositions& m_startList;
+ SortEnds(HTMLStartEndPositions& startList) : m_startList(startList) {}
+ bool operator()(const HTMLStartEndPos* p1, const HTMLStartEndPos* p2)
+ {
+ // if p1 start after p2, then it ends before
+ if (p1->GetStart() > p2->GetStart())
+ return true;
+ if (p1->GetStart() < p2->GetStart())
+ return false;
+ for (const auto p : m_startList[p1->GetStart()])
+ {
+ if (p == p1)
+ return false;
+ if (p == p2)
+ return true;
+ }
+ assert(!"Neither p1 nor p2 found in their start list");
+ return false;
+ }
+};
- while (i < m_aStartLst.size() && m_aStartLst[i]->GetStart() <= nStart)
- ++i;
- m_aStartLst.insert(m_aStartLst.begin() + i, pPos);
+#ifndef NDEBUG
+bool IsEmpty(const HTMLStartEndPositions& l)
+{
+ return std::find_if(l.begin(), l.end(), [](auto& i) { return !i.second.empty(); }) == l.end();
+}
+#endif
- // the position in the End list was supplied
- m_aEndLst.insert(m_aEndLst.begin() + nEndPos, pPos);
}
-void HTMLEndPosLst::RemoveItem_( HTMLStartEndPositions::size_type nEndPos )
+void HTMLEndPosLst::InsertItem_(HTMLStartEndPos* pPos)
{
- HTMLStartEndPos* pPos = m_aEndLst[nEndPos];
+ // Character border attribute must be the first which is written out because of border merge.
+ auto& posItems1 = m_aStartLst[pPos->GetStart()];
+ auto it = pPos->GetItem().Which() == RES_CHRATR_BOX ? posItems1.begin() : posItems1.end();
+ posItems1.insert(it, pPos);
- // now, we are looking for it in the Start list
- HTMLStartEndPositions::iterator it = std::find(m_aStartLst.begin(), m_aStartLst.end(), pPos);
- OSL_ENSURE(it != m_aStartLst.end(), "Item not found in Start List!");
- if (it != m_aStartLst.end())
- m_aStartLst.erase(it);
-
- m_aEndLst.erase(m_aEndLst.begin() + nEndPos);
-
- delete pPos;
+ m_aEndLst[pPos->GetEnd()].push_back(pPos);
}
HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem )
@@ -1352,23 +1362,25 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem )
bool HTMLEndPosLst::ExistsOnTagItem( sal_uInt16 nWhich, sal_Int32 nPos )
{
- for (auto pTest : m_aStartLst)
+ for (const auto& [startPos, items] : m_aStartLst)
{
- if( pTest->GetStart() > nPos )
+ if (startPos > nPos)
{
// this attribute, and all attributes that follow, start later
break;
}
- else if( pTest->GetEnd() > nPos )
+
+ for (const auto* pTest : items)
{
- // the attribute starts before, or at, the current position and
- // ends after it
- const SfxPoolItem *pItem = pTest->GetItem();
- if( pItem->Which() == nWhich &&
- HTML_ON_VALUE == GetHTMLItemState(*pItem) )
+ if (pTest->GetEnd() > nPos)
{
- // an OnTag attribute was found
- return true;
+ // the attribute starts before, or at, the current position and ends after it
+ const SfxPoolItem& rItem = pTest->GetItem();
+ if (rItem.Which() == nWhich && HTML_ON_VALUE == GetHTMLItemState(rItem))
+ {
+ // an OnTag attribute was found
+ return true;
+ }
}
}
}
@@ -1386,24 +1398,17 @@ bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, sal_Int32 nStartPos,
return false;
}
- for (auto pTest : m_aStartLst)
+ for (const auto* pTest : m_aStartLst[nStartPos])
{
- if( pTest->GetStart() > nStartPos )
- {
- // this attribute, and all attributes that follow, start later
- break;
- }
- else if( pTest->GetStart()==nStartPos &&
- pTest->GetEnd()==nEndPos )
+ if (pTest->GetEnd() == nEndPos)
{
- // the attribute starts before or at the current position and
- // ends after it
- const SfxPoolItem *pItem = pTest->GetItem();
- sal_uInt16 nTstWhich = pItem->Which();
+ // the attribute starts before or at the current position and ends after it
+ const SfxPoolItem& rItem = pTest->GetItem();
+ sal_uInt16 nTstWhich = rItem.Which();
if( (nTstWhich == RES_CHRATR_CROSSEDOUT ||
nTstWhich == RES_CHRATR_UNDERLINE ||
nTstWhich == RES_CHRATR_BLINK) &&
- HTML_OFF_VALUE == GetHTMLItemState(*pItem) )
+ HTML_OFF_VALUE == GetHTMLItemState(rItem) )
{
// an OffTag attribute was found that is exported the same
// way as the current item
@@ -1415,55 +1420,51 @@ bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, sal_Int32 nStartPos,
return false;
}
-void HTMLEndPosLst::FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd,
- HTMLStartEndPositions::size_type nStartPos )
+void HTMLEndPosLst::FixSplittedItem(HTMLStartEndPos* pPos, sal_Int32 nNewEnd)
{
+ // remove the item from the End list
+ std::erase(m_aEndLst[pPos->GetEnd()], pPos);
// fix the end position accordingly
pPos->SetEnd( nNewEnd );
-
- // remove the item from the End list
- HTMLStartEndPositions::iterator it = std::find(m_aEndLst.begin(), m_aEndLst.end(), pPos);
- OSL_ENSURE(it != m_aEndLst.end(), "Item not found in End List!");
- if (it != m_aEndLst.end())
- m_aEndLst.erase(it);
-
- // from now on, it is closed as the last one at the corresponding position
- HTMLStartEndPositions::size_type nEndPos {0};
- while (nEndPos < m_aEndLst.size() && m_aEndLst[nEndPos]->GetEnd() <= nNewEnd)
- ++nEndPos;
- m_aEndLst.insert(m_aEndLst.begin() + nEndPos, pPos);
+ // from now on, it is closed at the corresponding position
+ m_aEndLst[nNewEnd].push_back(pPos);
// now, adjust the attributes that got started afterwards
- for (HTMLStartEndPositions::size_type i = nStartPos + 1; i < m_aStartLst.size(); ++i)
+ const sal_Int32 nPos = pPos->GetStart();
+ for (const auto& [startPos, items] : m_aStartLst)
{
- HTMLStartEndPos* pTest = m_aStartLst[i];
- sal_Int32 nTestEnd = pTest->GetEnd();
- if( pTest->GetStart() >= nNewEnd )
- {
- // the Test attribute and all the following ones start, after the
- // split attribute ends
+ if (startPos < nPos)
+ continue;
+
+ if (startPos >= nNewEnd)
break;
+
+ auto it = items.begin();
+ if (startPos == nPos)
+ {
+ it = std::find(items.begin(), items.end(), pPos);
+ if (it != items.end())
+ ++it;
}
- else if( nTestEnd > nNewEnd )
+ for (; it != items.end(); ++it)
{
+ HTMLStartEndPos* pTest = *it;
+ const sal_Int32 nTestEnd = pTest->GetEnd();
+ if (nTestEnd <= nNewEnd)
+ continue;
+
// the Test attribute starts before the split attribute
// ends, and ends afterwards, i.e., it must be split, as well
+ // remove the attribute from the End list
+ std::erase(m_aEndLst[pTest->GetEnd()], pTest);
// set the new end
pTest->SetEnd( nNewEnd );
-
- // remove the attribute from the End list
- it = std::find(m_aEndLst.begin(), m_aEndLst.end(), pTest);
- OSL_ENSURE(it != m_aEndLst.end(), "Item not found in End List!");
- if (it != m_aEndLst.end())
- m_aEndLst.erase(it);
-
- // it now ends as the first attribute in the respective position.
- // We already know this position in the End list.
- m_aEndLst.insert(m_aEndLst.begin() + nEndPos, pTest);
+ // it now ends in the respective position.
+ m_aEndLst[nNewEnd].push_back(pTest);
// insert the 'rest' of the attribute
- InsertItem( *pTest->GetItem(), nNewEnd, nTestEnd );
+ InsertItem( pTest->GetItem(), nNewEnd, nTestEnd );
}
}
}
@@ -1471,36 +1472,38 @@ void HTMLEndPosLst::FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd,
void HTMLEndPosLst::InsertItem( const SfxPoolItem& rItem, sal_Int32 nStart,
sal_Int32 nEnd )
{
- HTMLStartEndPositions::size_type i;
- for (i = 0; i < m_aEndLst.size(); i++)
+ assert(nStart < nEnd);
+
+ for (auto& [endPos, items] : m_aEndLst)
{
- HTMLStartEndPos* pTest = m_aEndLst[i];
- sal_Int32 nTestEnd = pTest->GetEnd();
- if( nTestEnd <= nStart )
+ if (endPos <= nStart)
{
// the Test attribute ends, before the new one starts
continue;
}
- else if( nTestEnd < nEnd )
+ if (endPos >= nEnd)
+ {
+ // the Test attribute (and all that follow) ends, before the new
+ // one ends
+ break;
+ }
+
+ std::sort(items.begin(), items.end(), SortEnds(m_aStartLst));
+
+ for (HTMLStartEndPos* pTest : items)
{
if( pTest->GetStart() < nStart )
{
// the Test attribute ends, before the new one ends. Thus, the
// new attribute must be split.
- InsertItem_( new HTMLStartEndPos( rItem, nStart, nTestEnd ), i );
- nStart = nTestEnd;
+ InsertItem_(new HTMLStartEndPos(rItem, nStart, endPos));
+ nStart = endPos;
}
}
- else
- {
- // the Test attribute (and all that follow) ends, before the new
- // one ends
- break;
- }
}
// one attribute must still be inserted
- InsertItem_( new HTMLStartEndPos( rItem, nStart, nEnd ), i );
+ InsertItem_(new HTMLStartEndPos(rItem, nStart, nEnd));
}
void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart,
@@ -1511,59 +1514,47 @@ void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart,
// first, we must search for the old items by using the start list and
// determine the new item range
- for (HTMLStartEndPositions::size_type i = 0; i < m_aStartLst.size(); ++i)
+ for (auto& [nTestStart, items] : m_aStartLst)
{
- HTMLStartEndPos* pTest = m_aStartLst[i];
- sal_Int32 nTestStart = pTest->GetStart();
- sal_Int32 nTestEnd = pTest->GetEnd();
-
if( nTestStart >= nEnd )
{
// this attribute, and all that follow, start later
break;
}
- else if( nTestEnd > nStart )
+
+ for (auto it = items.begin(); it != items.end();)
{
+ HTMLStartEndPos* pTest = *it;
+ sal_Int32 nTestEnd = pTest->GetEnd();
+ if (nTestEnd <= nStart)
+ continue;
+
// the Test attribute ends in the range that must be deleted
- const SfxPoolItem *pItem = pTest->GetItem();
+ const SfxPoolItem& rTestItem = pTest->GetItem();
// only the corresponding OnTag attributes have to be considered
- if( pItem->Which() == nWhich &&
- HTML_ON_VALUE == GetHTMLItemState( *pItem ) )
+ if (rTestItem.Which() == nWhich && HTML_ON_VALUE == GetHTMLItemState(rTestItem))
{
- bool bDelete = true;
+ // if necessary, insert the second part of the split
+ // attribute
+ if (nTestEnd > nEnd)
+ InsertItem(pTest->GetItem(), nEnd, nTestEnd);
- if( nTestStart < nStart )
- {
- // the start of the new attribute corresponds to the new
- // end of the attribute
- FixSplittedItem( pTest, nStart, i );
- bDelete = false;
- }
- else
+ if (nTestStart >= nStart)
{
// the Test item only starts after the new end of the
// attribute. Therefore, it can be completely erased.
- m_aStartLst.erase(m_aStartLst.begin() + i);
- i--;
-
- HTMLStartEndPositions::iterator it
- = std::find(m_aEndLst.begin(), m_aEndLst.end(), pTest);
- OSL_ENSURE(it != m_aEndLst.end(), "Item not found in End List!");
- if (it != m_aEndLst.end())
- m_aEndLst.erase(it);
- }
-
- // if necessary, insert the second part of the split
- // attribute
- if( nTestEnd > nEnd )
- {
- InsertItem( *pTest->GetItem(), nEnd, nTestEnd );
+ it = items.erase(it);
+ std::erase(m_aEndLst[pTest->GetEnd()], pTest);
+ delete pTest;
+ continue;
}
- if( bDelete )
- delete pTest;
+ // the start of the new attribute corresponds to the new
+ // end of the attribute
+ FixSplittedItem(pTest, nStart);
}
+ ++it;
}
}
}
@@ -1611,8 +1602,8 @@ HTMLEndPosLst::HTMLEndPosLst(SwDoc* pD, SwDoc* pTempl, std::optional<Color> xDfl
HTMLEndPosLst::~HTMLEndPosLst()
{
- OSL_ENSURE(m_aStartLst.empty(), "Start List not empty in destructor");
- OSL_ENSURE(m_aEndLst.empty(), "End List not empty in destructor");
+ assert(IsEmpty(m_aStartLst) && "Start List not empty in destructor");
+ assert(IsEmpty(m_aEndLst) && "End List not empty in destructor");
}
void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem,
@@ -1900,53 +1891,25 @@ void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos )
{
rWrt.m_bTagOn = true;
- // Character border attribute must be the first which is written out
- // because of border merge.
- HTMLStartEndPositions::size_type nCharBoxIndex = 0;
- while (nCharBoxIndex < m_aStartLst.size()
- && m_aStartLst[nCharBoxIndex]->GetItem()->Which() != RES_CHRATR_BOX)
- {
- ++nCharBoxIndex;
- }
-
+ auto it = m_aStartLst.find(nPos);
+ if (it == m_aStartLst.end())
+ return;
// the attributes of the start list are sorted in ascending order
- for (HTMLStartEndPositions::size_type i = 0; i < m_aStartLst.size(); ++i)
+ for (HTMLStartEndPos* pPos : it->second)
{
- HTMLStartEndPos *pPos = nullptr;
- if (nCharBoxIndex < m_aStartLst.size())
- {
- if( i == 0 )
- pPos = m_aStartLst[nCharBoxIndex];
- else if( i == nCharBoxIndex )
- pPos = m_aStartLst[0];
- else
- pPos = m_aStartLst[i];
- }
- else
- pPos = m_aStartLst[i];
-
- sal_Int32 nStart = pPos->GetStart();
- if( nStart > nPos )
- {
- // this attribute, and all that follow, will be opened later on
- break;
- }
- else if( nStart == nPos )
+ // output the attribute
+ sal_uInt16 nCSS1Script = rWrt.m_nCSS1Script;
+ sal_uInt16 nWhich = pPos->GetItem().Which();
+ if( RES_TXTATR_CHARFMT == nWhich ||
+ RES_TXTATR_INETFMT == nWhich ||
+ RES_PARATR_DROP == nWhich )
{
- // output the attribute
- sal_uInt16 nCSS1Script = rWrt.m_nCSS1Script;
- sal_uInt16 nWhich = pPos->GetItem()->Which();
- if( RES_TXTATR_CHARFMT == nWhich ||
- RES_TXTATR_INETFMT == nWhich ||
- RES_PARATR_DROP == nWhich )
- {
- rWrt.m_nCSS1Script = GetScriptAtPos( nPos, nCSS1Script );
- }
- HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it?
- Out( aHTMLAttrFnTab, *pPos->GetItem(), rWrt );
- rWrt.maStartedAttributes[pPos->GetItem()->Which()]++;
- rWrt.m_nCSS1Script = nCSS1Script;
+ rWrt.m_nCSS1Script = GetScriptAtPos( nPos, nCSS1Script );
}
+ HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it?
+ Out( aHTMLAttrFnTab, pPos->GetItem(), rWrt );
+ rWrt.maStartedAttributes[pPos->GetItem().Which()]++;
+ rWrt.m_nCSS1Script = nCSS1Script;
}
}
@@ -1954,59 +1917,55 @@ void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos )
{
rWrt.m_bTagOn = false;
- // the attributes in the End list are sorted in ascending order
- HTMLStartEndPositions::size_type i {0};
- while (i < m_aEndLst.size())
+ if (nPos == SAL_MAX_INT32)
+ {
+ for (auto& element : m_aEndLst)
+ OutEndAttrs(rWrt, element.second);
+ }
+ else
{
- HTMLStartEndPos* pPos = m_aEndLst[i];
- sal_Int32 nEnd = pPos->GetEnd();
+ auto it = m_aEndLst.find(nPos);
+ if (it != m_aEndLst.end())
+ OutEndAttrs(rWrt, it->second);
+ }
+}
- if( SAL_MAX_INT32 == nPos || nEnd == nPos )
+void HTMLEndPosLst::OutEndAttrs(SwHTMLWriter& rWrt, std::vector<HTMLStartEndPos*>& posItems)
+{
+ std::sort(posItems.begin(), posItems.end(), SortEnds(m_aStartLst));
+ for (auto it = posItems.begin(); it != posItems.end(); it = posItems.erase(it))
+ {
+ HTMLStartEndPos* pPos = *it;
+ HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it?
+ // Skip closing span if next character span has the same border (border merge)
+ bool bSkipOut = false;
+ if( pPos->GetItem().Which() == RES_CHRATR_BOX )
{
- HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it?
- // Skip closing span if next character span has the same border (border merge)
- bool bSkipOut = false;
- if( pPos->GetItem()->Which() == RES_CHRATR_BOX )
+ auto& startPosItems = m_aStartLst[pPos->GetEnd()];
+ for (auto it2 = startPosItems.begin(); it2 != startPosItems.end(); ++it2)
{
- HTMLStartEndPositions::iterator it
- = std::find(m_aStartLst.begin(), m_aStartLst.end(), pPos);
- OSL_ENSURE(it != m_aStartLst.end(), "Item not found in Start List!");
- if (it != m_aStartLst.end())
- ++it;
- while (it != m_aStartLst.end())
+ HTMLStartEndPos* pEndPos = *it2;
+ if( pEndPos->GetItem().Which() == RES_CHRATR_BOX &&
+ static_cast<const SvxBoxItem&>(pEndPos->GetItem()) ==
+ static_cast<const SvxBoxItem&>(pPos->GetItem()) )
{
- HTMLStartEndPos *pEndPos = *it;
- if( pEndPos->GetItem()->Which() == RES_CHRATR_BOX &&
- *static_cast<const SvxBoxItem*>(pEndPos->GetItem()) ==
- *static_cast<const SvxBoxItem*>(pPos->GetItem()) )
- {
- pEndPos->SetStart(pPos->GetStart());
- bSkipOut = true;
- break;
- }
- ++it;
+ startPosItems.erase(it2);
+ pEndPos->SetStart(pPos->GetStart());
+ auto& oldStartPosItems = m_aStartLst[pEndPos->GetStart()];
+ oldStartPosItems.insert(oldStartPosItems.begin(), pEndPos);
+ bSkipOut = true;
+ break;
}
}
- if( !bSkipOut )
- {
- Out( aHTMLAttrFnTab, *pPos->GetItem(), rWrt );
- rWrt.maStartedAttributes[pPos->GetItem()->Which()]--;
- }
- RemoveItem_( i );
- }
- else if( nEnd > nPos )
- {
- // this attribute, and all that follow, are closed later on
- break;
}
- else
+ if( !bSkipOut )
{
- // The attribute is closed before the current position. This
- // is not allowed, but we can handle it anyway.
- OSL_ENSURE( nEnd >= nPos,
- "The attribute should've been closed a long time ago" );
- i++;
+ Out( aHTMLAttrFnTab, pPos->GetItem(), rWrt );
+ rWrt.maStartedAttributes[pPos->GetItem().Which()]--;
}
+
+ std::erase(m_aStartLst[pPos->GetStart()], pPos);
+ delete pPos;
}
}
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index d84549d430..28da6d2883 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -161,6 +161,8 @@
#include <frozen/bits/defines.h>
#include <frozen/bits/elsa_std.h>
#include <frozen/unordered_map.h>
+#include <IDocumentDeviceAccess.hxx>
+#include <sfx2/printer.hxx>
using ::editeng::SvxBorderLine;
@@ -1965,7 +1967,22 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, sal_In
}
// if there is some redlining in the document, output it
- StartRedline( m_pRedlineData, bLastRun );
+ bool bSkipRedline = false;
+ if (nLen == 1)
+ {
+ // Don't redline content-controls--Word doesn't do them.
+ SwTextAttr* pAttr
+ = pNode->GetTextAttrAt(nPos, RES_TXTATR_CONTENTCONTROL, sw::GetTextAttrMode::Default);
+ if (pAttr && pAttr->GetStart() == nPos)
+ {
+ bSkipRedline = true;
+ }
+ }
+
+ if (!bSkipRedline)
+ {
+ StartRedline(m_pRedlineData, bLastRun);
+ }
// XML_r node should be surrounded with bookmark-begin and bookmark-end nodes if it has bookmarks.
// The same is applied for permission ranges.
@@ -2042,6 +2059,13 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, sal_In
// append the actual run end
m_pSerializer->endElementNS( XML_w, XML_r );
+ // if there is some redlining in the document, output it
+ // (except in the case of fields with multiple runs)
+ if (!bSkipRedline)
+ {
+ EndRedline(m_pRedlineData, bLastRun);
+ }
+
if (nLen != -1)
{
sal_Int32 nEnd = nPos + nLen;
@@ -2052,10 +2076,6 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, sal_In
}
}
- // if there is some redlining in the document, output it
- // (except in the case of fields with multiple runs)
- EndRedline( m_pRedlineData, bLastRun );
-
// enclose in a sdt block, if necessary: if one is already started, then don't do it for now
// (so on export sdt blocks are never nested ATM)
if ( !m_bAnchorLinkedToNode && !m_aRunSdt.m_bStartedSdt)
@@ -9118,9 +9138,15 @@ void DocxAttributeOutput::FormatFrameSize( const SwFormatFrameSize& rSize )
}
}
-void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
+void DocxAttributeOutput::FormatPaperBin(const SvxPaperBinItem& rPaperBin)
{
- SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::FormatPaperBin()" );
+ sal_Int8 nPaperBin = rPaperBin.GetValue();
+ rtl::Reference<FastAttributeList> attrList = FastSerializerHelper::createAttrList( );
+ SfxPrinter* pPrinter = m_rExport.m_rDoc.getIDocumentDeviceAccess().getPrinter(true);
+ sal_Int16 nPaperSource = pPrinter->GetSourceIndexByPaperBin(nPaperBin);
+ attrList->add( FSNS( XML_w, XML_first ), OString::number(nPaperSource) );
+ attrList->add( FSNS( XML_w, XML_other ), OString::number(nPaperSource) );
+ m_pSerializer->singleElementNS( XML_w, XML_paperSrc, attrList );
}
void DocxAttributeOutput::FormatFirstLineIndent(SvxFirstLineIndentItem const& rFirstLine)
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 2d68556e8a..7dcda8f73f 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -94,6 +94,8 @@
#include <formatflysplit.hxx>
#include <fmtwrapinfluenceonobjpos.hxx>
#include "rtfexport.hxx"
+#include <IDocumentDeviceAccess.hxx>
+#include <sfx2/printer.hxx>
using namespace ::com::sun::star;
using namespace sw::util;
@@ -3324,9 +3326,14 @@ void RtfAttributeOutput::FormatFrameSize(const SwFormatFrameSize& rSize)
}
}
-void RtfAttributeOutput::FormatPaperBin(const SvxPaperBinItem& /*rItem*/)
+void RtfAttributeOutput::FormatPaperBin(const SvxPaperBinItem& rItem)
{
- SAL_INFO("sw.rtf", "TODO: " << __func__);
+ SfxPrinter* pPrinter = m_rExport.m_rDoc.getIDocumentDeviceAccess().getPrinter(true);
+ sal_Int16 nPaperSource = pPrinter->GetSourceIndexByPaperBin(rItem.GetValue());
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_BINFSXN);
+ m_aSectionBreaks.append(static_cast<sal_Int32>(nPaperSource));
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_BINSXN);
+ m_aSectionBreaks.append(static_cast<sal_Int32>(nPaperSource));
}
void RtfAttributeOutput::FormatFirstLineIndent(SvxFirstLineIndentItem const& rFirstLine)
@@ -3747,6 +3754,12 @@ void RtfAttributeOutput::FormatFillGradient(const XFillGradientItem& rFillGradie
const Color aEndColor(rColorStops.back().getStopColor());
m_aFlyProperties.push_back(std::make_pair<OString, OString>(
"fillBackColor"_ostr, OString::number(wwUtility::RGBToBGR(aEndColor))));
+
+ if (rGradient.GetGradientStyle() == awt::GradientStyle_AXIAL)
+ {
+ m_aFlyProperties.push_back(
+ std::make_pair<OString, OString>("fillFocus"_ostr, OString::number(50)));
+ }
}
else
{
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 39e2f88523..68437c9529 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2478,6 +2478,14 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
bool bStartedPostponedRunProperties = false;
OUString aSavedSnippet ;
+ // Don't redline content-controls--Word doesn't do them.
+ SwTextAttr* pAttr = rNode.GetTextAttrAt(nCurrentPos, RES_TXTATR_CONTENTCONTROL,
+ sw::GetTextAttrMode::Default);
+ if (pAttr && pAttr->GetStart() == nCurrentPos)
+ {
+ pRedlineData = nullptr;
+ }
+
sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nCurrentPos );
// Skip un-exportable attributes.
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index 8d59434db6..681961a377 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -279,7 +279,7 @@ void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
sal_Int16 nListTabPos,
const OUString &rNumberingString,
const SvxBrushItem* pBrush, //For i120928,to transfer graphic of bullet
- bool /*isLegal*/
+ bool isLegal
)
{
// Start value
@@ -303,6 +303,13 @@ void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
nAlign = 0;
break;
}
+
+ if (isLegal)
+ {
+ // 3rd bit.
+ nAlign |= 0x04;
+ }
+
m_rWW8Export.m_pTableStrm->WriteUChar( nAlign );
// Write the rgbxchNums[9], positions of placeholders for paragraph
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
index d0a294b144..41b203f924 100644
--- a/sw/source/filter/ww8/ww8par3.cxx
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -368,6 +368,8 @@ struct WW8LVL // only THE entries, WE need!
short nDxaLeft1; // first line indent
sal_uInt8 nNFC; // number format code
+ /// Legal numbering: whether this level overrides the nfc of all inherited level numbers.
+ bool fLegal;
// Offset of fieldcodes in Num-X-String
sal_uInt8 aOfsNumsXCH[WW8ListManager::nMaxLevel];
sal_uInt8 nLenGrpprlChpx; // length, in bytes, of the LVL's grpprlChpx
@@ -662,7 +664,15 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
m_rSt.ReadUChar( aLVL.nNFC );
m_rSt.ReadUChar( aBits1 );
if( ERRCODE_NONE != m_rSt.GetError() ) return false;
+ // 1st..2nd bits.
aLVL.nAlign = (aBits1 & 0x03);
+
+ if (aBits1 & 0x04)
+ {
+ // 3rd bit.
+ aLVL.fLegal = true;
+ }
+
if( aBits1 & 0x10 ) aLVL.bV6Prev = true;
if( aBits1 & 0x20 ) aLVL.bV6PrSp = true;
if( aBits1 & 0x40 ) aLVL.bV6 = true;
@@ -898,6 +908,7 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
if( bSetStartNo && 0 <= aLVL.nStartAt)
rNumFormat.SetStart(o3tl::narrowing<sal_uInt16>(aLVL.nStartAt));
rNumFormat.SetNumberingType( nType );
+ rNumFormat.SetIsLegal(aLVL.fLegal);
rNumFormat.SetNumAdjust( eAdj );
if( style::NumberingType::CHAR_SPECIAL == nType )
diff --git a/sw/source/ui/index/swuiidxmrk.cxx b/sw/source/ui/index/swuiidxmrk.cxx
index 39443f7e7b..8a6f74b86e 100644
--- a/sw/source/ui/index/swuiidxmrk.cxx
+++ b/sw/source/ui/index/swuiidxmrk.cxx
@@ -287,19 +287,20 @@ void SwIndexMarkPane::InitControls()
bool bShow = false;
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ // tdf#158783 ptr compare OK for SwTOXMark (more below)
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
{
m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
bShow = true;
}
- m_xPrevBT->set_sensitive(!SfxPoolItem::areSame(pMoveMark, pMark));
+ m_xPrevBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
{
m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
bShow = true;
}
- m_xNextBT->set_sensitive(!SfxPoolItem::areSame(pMoveMark, pMark));
+ m_xNextBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
if( bShow )
{
m_xPrevBT->show();
@@ -308,19 +309,19 @@ void SwIndexMarkPane::InitControls()
}
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
{
m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
bShow = true;
}
- m_xPrevSameBT->set_sensitive(!SfxPoolItem::areSame(pMoveMark, pMark));
+ m_xPrevSameBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
{
m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
bShow = true;
}
- m_xNextSameBT->set_sensitive(!SfxPoolItem::areSame(pMoveMark, pMark));
+ m_xNextSameBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
if( bShow )
{
m_xNextSameBT->show();
@@ -894,25 +895,26 @@ void SwIndexMarkPane::UpdateDialog()
if( m_xPrevBT->get_visible() )
{
const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ // tdf#158783 ptr compare OK for SwTOXMark (more below)
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
- m_xPrevBT->set_sensitive( !SfxPoolItem::areSame(pMoveMark, pMark) );
+ m_xPrevBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
- m_xNextBT->set_sensitive( !SfxPoolItem::areSame(pMoveMark, pMark) );
+ m_xNextBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
}
if (m_xPrevSameBT->get_visible())
{
const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
- m_xPrevSameBT->set_sensitive( !SfxPoolItem::areSame(pMoveMark, pMark) );
+ m_xPrevSameBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
- if (!SfxPoolItem::areSame( pMoveMark, pMark ))
+ if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
- m_xNextSameBT->set_sensitive( !SfxPoolItem::areSame(pMoveMark, pMark) );
+ m_xNextSameBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
}
const bool bEnable = !m_pSh->HasReadonlySel();
@@ -1013,7 +1015,8 @@ void SwIndexMarkPane::ReInitDlg(SwWrtShell& rWrtShell, SwTOXMark const * pCurTOX
if(pCurTOXMark)
{
for(sal_uInt16 i = 0; i < m_pTOXMgr->GetTOXMarkCount(); i++)
- if (SfxPoolItem::areSame(m_pTOXMgr->GetTOXMark(i), pCurTOXMark))
+ // tdf#158783 ptr compare OK for SwTOXMark (more below)
+ if (areSfxPoolItemPtrsEqual(m_pTOXMgr->GetTOXMark(i), pCurTOXMark))
{
m_pTOXMgr->SetCurTOXMark(i);
break;
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index cb96c08527..ea419d2326 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -382,7 +382,8 @@ const Graphic* SwTransferable::FindOLEReplacementGraphic() const
void SwTransferable::RemoveDDELinkFormat(vcl::Window& rWin)
{
RemoveFormat( SotClipboardFormatId::LINK );
- CopyToClipboard(&rWin);
+ if (rWin.GetClipboard()->getContents().get() == this)
+ CopyToClipboard(&rWin);
}
void SwTransferable::DisconnectDDE()
diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx
index a1780f9132..6b8895f1d9 100644
--- a/sw/source/uibase/docvw/AnnotationWin2.cxx
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -504,7 +504,7 @@ void SwAnnotationWin::SetMenuButtonColors()
const tools::Long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 150) + 500) / 1000;
aSymbolRect.AdjustBottom( -nBorderDistanceBottom );
DecorationView aDecoView(xVirDev.get());
- aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(),
+ aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, COL_BLACK,
DrawSymbolFlags::NONE);
mxMenuButton->set_image(xVirDev);
mxMenuButton->set_size_request(aSize.Width() + 4, aSize.Height() + 4);
diff --git a/sw/source/uibase/docvw/SidebarWinAcc.cxx b/sw/source/uibase/docvw/SidebarWinAcc.cxx
index f489bc140b..3b2b4c758e 100644
--- a/sw/source/uibase/docvw/SidebarWinAcc.cxx
+++ b/sw/source/uibase/docvw/SidebarWinAcc.cxx
@@ -23,9 +23,9 @@
#include <viewsh.hxx>
#include <accmap.hxx>
#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <vcl/svapp.hxx>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
-#include <mutex>
namespace sw::sidebarwindows {
@@ -47,7 +47,7 @@ class SidebarWinAccessibleContext : public VCLXAccessibleComponent
void ChangeAnchor( const SwFrame* pAnchorFrame )
{
- std::scoped_lock aGuard(maMutex);
+ SolarMutexGuard aGuard;
mpAnchorFrame = pAnchorFrame;
}
@@ -55,7 +55,7 @@ class SidebarWinAccessibleContext : public VCLXAccessibleComponent
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
getAccessibleParent() override
{
- std::scoped_lock aGuard(maMutex);
+ SolarMutexGuard aGuard;
css::uno::Reference< css::accessibility::XAccessible > xAccParent;
@@ -70,7 +70,7 @@ class SidebarWinAccessibleContext : public VCLXAccessibleComponent
virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
{
- std::scoped_lock aGuard(maMutex);
+ SolarMutexGuard aGuard;
sal_Int64 nIndex( -1 );
@@ -87,8 +87,6 @@ class SidebarWinAccessibleContext : public VCLXAccessibleComponent
private:
SwViewShell& mrViewShell;
const SwFrame* mpAnchorFrame;
-
- std::mutex maMutex;
};
}
diff --git a/sw/source/uibase/index/toxmgr.cxx b/sw/source/uibase/index/toxmgr.cxx
index 8b8ff6dbd8..c7cd813eb4 100644
--- a/sw/source/uibase/index/toxmgr.cxx
+++ b/sw/source/uibase/index/toxmgr.cxx
@@ -47,7 +47,8 @@ void SwTOXMgr::DeleteTOXMark()
if( m_pCurTOXMark )
{
pNext = const_cast<SwTOXMark*>(&m_pSh->GotoTOXMark( *m_pCurTOXMark, TOX_NXT ));
- if (SfxPoolItem::areSame( pNext, m_pCurTOXMark ))
+ // tdf#158783 ptr compare OK for SwTOXMark (more below)
+ if (areSfxPoolItemPtrsEqual( pNext, m_pCurTOXMark ))
pNext = nullptr;
m_pSh->DeleteTOXMark( m_pCurTOXMark );
diff --git a/sw/source/uibase/shells/textsh.cxx b/sw/source/uibase/shells/textsh.cxx
index 0924935b3d..97de985401 100644
--- a/sw/source/uibase/shells/textsh.cxx
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -877,7 +877,20 @@ void SwTextShell::ExecTransliteration( SfxRequest const & rReq )
void SwTextShell::ExecRotateTransliteration( SfxRequest const & rReq )
{
if( rReq.GetSlot() == SID_TRANSLITERATE_ROTATE_CASE )
- GetShell().TransliterateText( m_aRotateCase.getNextMode() );
+ {
+ SwWrtShell& rSh = GetShell();
+ if (rSh.HasSelection())
+ {
+ rSh.TransliterateText(m_aRotateCase.getNextMode());
+ }
+ else
+ {
+ rSh.Push(); // save cur cursor
+ if ((rSh.IsEndWrd() || rSh.IsStartWord() || rSh.IsInWord()) && rSh.SelWrd())
+ rSh.TransliterateText(m_aRotateCase.getNextMode());
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ }
}
SwTextShell::SwTextShell(SwView &_rView) :
diff --git a/sw/source/uibase/sidebar/PageSizeControl.cxx b/sw/source/uibase/sidebar/PageSizeControl.cxx
index 4ea5995c09..a2dbe406f3 100644
--- a/sw/source/uibase/sidebar/PageSizeControl.cxx
+++ b/sw/source/uibase/sidebar/PageSizeControl.cxx
@@ -168,7 +168,6 @@ PageSizeControl::PageSizeControl(PageSizePopup* pControl, weld::Widget* pParent)
}
mxSizeValueSet->SetNoSelection();
mxSizeValueSet->SetSelectHdl( LINK(this, PageSizeControl, ImplSizeHdl ) );
- mxSizeValueSet->SetOptimalDrawingAreaHeight();
mxSizeValueSet->Show();
mxSizeValueSet->Resize();
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index cc6faf78a3..f7a10a49f7 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -286,14 +286,21 @@ OUString SwView::GetPageStr(sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, const OUStr
? SwResId(STR_PAGE_COUNT_PRINTED)
: (extra.isEmpty() ? SwResId(STR_PAGE_COUNT) : SwResId(STR_PAGE_COUNT_CUSTOM)));
aStr = aStr.replaceFirst("%1", OUString::number(nPhyNum));
- aStr = aStr.replaceFirst("%2", OUString::number(nPageCount));
if (nPageCount != nPrintedPageCount)
{
+ aStr = aStr.replaceFirst("%2", OUString::number(nPageCount));
aStr = aStr.replaceFirst("%3", OUString::number(nPrintedPhyNum));
aStr = aStr.replaceFirst("%4", OUString::number(nPrintedPageCount));
}
- else
- aStr = aStr.replaceFirst("%3", extra);
+ else {
+ if (extra.isEmpty())
+ aStr = aStr.replaceFirst("%2", OUString::number(nPageCount));
+ else
+ {
+ aStr = aStr.replaceFirst("%2", extra);
+ aStr = aStr.replaceFirst("%3", OUString::number(nPageCount));
+ }
+ }
return aStr;
}
diff --git a/sw/source/uibase/utlui/uitool.cxx b/sw/source/uibase/utlui/uitool.cxx
index fd50bf6678..dfaffe3480 100644
--- a/sw/source/uibase/utlui/uitool.cxx
+++ b/sw/source/uibase/utlui/uitool.cxx
@@ -392,6 +392,7 @@ void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc )
if(rMaster.GetFooter().IsActive())
{
rMaster.SetFormatAttr(SwFormatFooter(false));
+ // why reset this? but not doing it causes testTdf112694 to fail
rPageDesc.ChgFooterShare(false);
}
}
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx
index 4b2402fc93..0054eca4cb 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -115,6 +115,7 @@
#include <frmtool.hxx>
#include <viewopt.hxx>
+#include <IDocumentRedlineAccess.hxx>
#include <IDocumentUndoRedo.hxx>
#include <UndoInsert.hxx>
#include <UndoCore.hxx>
@@ -1177,8 +1178,12 @@ void SwWrtShell::InsertContentControl(SwContentControlType eType)
Left(SwCursorSkipMode::Chars, /*bSelect=*/true, aPlaceholder.getLength(),
/*bBasicCall=*/false);
}
+
+ const RedlineFlags oldRedlineFlags = getIDocumentRedlineAccess().GetRedlineFlags();
+ getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::Ignore);
SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL);
SetAttrItem(aContentControl);
+ getIDocumentRedlineAccess().SetRedlineFlags(oldRedlineFlags);
}
// Insert footnote