summaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/doc.hxx1
-rw-r--r--sw/inc/editsh.hxx4
-rw-r--r--sw/inc/usrfld.hxx2
-rw-r--r--sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx11
-rw-r--r--sw/qa/core/accessibilitycheck/data/Tabs-in-TOC.odtbin0 -> 15284 bytes
-rw-r--r--sw/qa/core/layout/data/floattable-header.docxbin0 -> 31604 bytes
-rw-r--r--sw/qa/core/layout/data/floattable-in-section.docxbin14024 -> 16073 bytes
-rw-r--r--sw/qa/core/layout/layact.cxx22
-rw-r--r--sw/qa/core/layout/tabfrm.cxx21
-rw-r--r--sw/qa/extras/htmlexport/data/tdf160390.fodt17
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx7
-rw-r--r--sw/qa/extras/layout/data/tdf160526.fodt47
-rw-r--r--sw/qa/extras/layout/data/tdf160549.fodt60
-rw-r--r--sw/qa/extras/layout/layout3.cxx21
-rw-r--r--sw/qa/extras/odfexport/data/tdf160700.odtbin0 -> 10398 bytes
-rw-r--r--sw/qa/extras/odfexport/odfexport2.cxx30
-rw-r--r--sw/qa/extras/uiwriter/uiwriter5.cxx2
-rw-r--r--sw/qa/extras/unowriter/unowriter.cxx21
-rw-r--r--sw/qa/uitest/writer_tests2/formatParagraph.py2
-rw-r--r--sw/source/core/access/AccessibilityCheck.cxx5
-rw-r--r--sw/source/core/doc/docfly.cxx19
-rw-r--r--sw/source/core/edit/eddel.cxx8
-rw-r--r--sw/source/core/fields/expfld.cxx2
-rw-r--r--sw/source/core/layout/layact.cxx12
-rw-r--r--sw/source/core/layout/paintfrm.cxx3
-rw-r--r--sw/source/core/layout/tabfrm.cxx15
-rw-r--r--sw/source/core/text/frmform.cxx101
-rw-r--r--sw/source/core/undo/untbl.cxx15
-rw-r--r--sw/source/core/unocore/unoframe.cxx13
-rw-r--r--sw/source/core/unocore/unoobj.cxx12
-rw-r--r--sw/source/core/unocore/unoportenum.cxx3
-rw-r--r--sw/source/filter/html/htmlatr.cxx40
-rw-r--r--sw/source/filter/html/htmlctxt.cxx3
-rw-r--r--sw/source/filter/ww8/wrtw8nds.cxx41
-rw-r--r--sw/source/filter/ww8/ww8par.cxx43
-rw-r--r--sw/source/filter/ww8/ww8par5.cxx30
-rw-r--r--sw/source/ui/fldui/fldref.cxx2
-rw-r--r--sw/source/ui/index/cnttab.cxx4
-rw-r--r--sw/source/ui/index/swuiidxmrk.cxx1
-rw-r--r--sw/source/uibase/shells/textsh.cxx9
-rw-r--r--sw/source/uibase/wrtsh/delete.cxx4
41 files changed, 538 insertions, 115 deletions
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index ea95cef856..99cb33c758 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -838,6 +838,7 @@ public:
std::vector<SwFrameFormat const*> GetFlyFrameFormats(
FlyCntType eType,
bool bIgnoreTextBoxes);
+ SwFrameFormat* GetFlyFrameFormatByName( const OUString& sFrameFormatName );
// Copy formats in own arrays and return them.
SwFrameFormat *CopyFrameFormat ( const SwFrameFormat& );
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 1fb9ff3a5b..2b75353015 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -152,7 +152,7 @@ class SW_DLLPUBLIC SwEditShell : public SwCursorShell
that will be used by GetGraphic() and GetGraphicSize(). */
SAL_DLLPRIVATE SwGrfNode *GetGrfNode_() const ;
- SAL_DLLPRIVATE void DeleteSel(SwPaM& rPam, bool isArtificialSelection, bool* pUndo = nullptr);
+ SAL_DLLPRIVATE void DeleteSel(SwPaM& rPam, bool isArtificialSelection, bool goLeft = false, bool* pUndo = nullptr);
SAL_DLLPRIVATE void SetSectionAttr_( SwSectionFormat& rSectFormat, const SfxItemSet& rSet );
@@ -178,7 +178,7 @@ public:
/** Delete content of all ranges.
If whole nodes are selected, these nodes get deleted. */
- bool Delete(bool isArtificialSelection = false);
+ bool Delete(bool isArtificialSelection = false, bool goLeft = false);
/// Remove a complete paragraph.
bool DelFullPara();
diff --git a/sw/inc/usrfld.hxx b/sw/inc/usrfld.hxx
index 28d582c4c5..f7371ef52c 100644
--- a/sw/inc/usrfld.hxx
+++ b/sw/inc/usrfld.hxx
@@ -102,7 +102,7 @@ inline void SwUserFieldType::SetType(sal_uInt16 nSub)
* Tracks the number format and the language, conversion between the float and
* string representation is independent from the system locale.
*/
-class SwUserField final : public SwValueField
+class SW_DLLPUBLIC SwUserField final : public SwValueField
{
sal_uInt16 m_nSubType;
diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
index 117b48d016..bfe2e08d85 100644
--- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
+++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
@@ -251,6 +251,17 @@ scanAccessibilityIssuesOnNodes(SwDoc* pDocument)
return aIssues;
}
+CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTabsinTOC)
+{
+ createSwDoc("Tabs-in-TOC.odt");
+ SwDoc* pDoc = getSwDoc();
+ CPPUNIT_ASSERT(pDoc);
+ sw::AccessibilityCheck aCheck(pDoc);
+ aCheck.check();
+ auto& aIssues = aCheck.getIssueCollection().getIssues();
+ CPPUNIT_ASSERT_EQUAL(size_t(0), aIssues.size());
+}
+
void checkIssuePosition(std::shared_ptr<sfx::AccessibilityIssue> const& pIssue, int nLine,
sal_Int32 nStart, sal_Int32 nEnd, SwNodeOffset nIndex)
{
diff --git a/sw/qa/core/accessibilitycheck/data/Tabs-in-TOC.odt b/sw/qa/core/accessibilitycheck/data/Tabs-in-TOC.odt
new file mode 100644
index 0000000000..2b3ce54cc5
--- /dev/null
+++ b/sw/qa/core/accessibilitycheck/data/Tabs-in-TOC.odt
Binary files differ
diff --git a/sw/qa/core/layout/data/floattable-header.docx b/sw/qa/core/layout/data/floattable-header.docx
new file mode 100644
index 0000000000..baddd365ce
--- /dev/null
+++ b/sw/qa/core/layout/data/floattable-header.docx
Binary files differ
diff --git a/sw/qa/core/layout/data/floattable-in-section.docx b/sw/qa/core/layout/data/floattable-in-section.docx
index a0e9090bcc..9aab264867 100644
--- a/sw/qa/core/layout/data/floattable-in-section.docx
+++ b/sw/qa/core/layout/data/floattable-in-section.docx
Binary files differ
diff --git a/sw/qa/core/layout/layact.cxx b/sw/qa/core/layout/layact.cxx
index d432ae52b7..8923d6b0e8 100644
--- a/sw/qa/core/layout/layact.cxx
+++ b/sw/qa/core/layout/layact.cxx
@@ -86,6 +86,28 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf157096)
CPPUNIT_ASSERT_EQUAL(1, getPages());
}
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInSection)
+{
+ // Given a document with multiple sections, the 2nd section on page 1 has a one-page floating
+ // table:
+ createSwDoc("floattable-in-section.docx");
+
+ // When laying out that document:
+ SwDoc* pDoc = getSwDoc();
+ SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+
+ // Then make sure the table is on page 1, not on page 2:
+ auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+ CPPUNIT_ASSERT(pPage1);
+ // Without the fix in place, it would have failed, the table was on page 2, not on page 1.
+ CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+ SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+ auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+ CPPUNIT_ASSERT(pPage2);
+ CPPUNIT_ASSERT(!pPage2->GetSortedObjs());
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/layout/tabfrm.cxx b/sw/qa/core/layout/tabfrm.cxx
index e0d099c771..9bfbd1b82e 100644
--- a/sw/qa/core/layout/tabfrm.cxx
+++ b/sw/qa/core/layout/tabfrm.cxx
@@ -17,6 +17,8 @@
#include <anchoredobject.hxx>
#include <flyfrm.hxx>
#include <flyfrms.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
namespace
{
@@ -235,6 +237,25 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyWrappedByTableNested)
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc->GetTableFrameFormats()->GetFormatCount());
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pDoc->GetSpzFrameFormats()->GetFormatCount());
}
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyHeader)
+{
+ // Given a document with 8 pages: a first page ending in a manual page break, then a multi-page
+ // floating table on pages 2..8:
+ createSwDoc("floattable-header.docx");
+ CPPUNIT_ASSERT_EQUAL(8, getPages());
+
+ // When creating a new paragraph at doc start:
+ SwDocShell* pDocShell = getSwDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->SplitNode();
+ // Without the accompanying fix in place, this test would have crashed here.
+ pWrtShell->CalcLayout();
+
+ // Then make sure we get one more page, since the first page is now 2 pages:
+ CPPUNIT_ASSERT_EQUAL(9, getPages());
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/htmlexport/data/tdf160390.fodt b/sw/qa/extras/htmlexport/data/tdf160390.fodt
new file mode 100644
index 0000000000..53d6144ff1
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/tdf160390.fodt
@@ -0,0 +1,17 @@
+<?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:text-properties style:text-underline-style="solid" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties style:text-underline-style="none" fo:font-weight="normal"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="P1">foo<text:span text:style-name="T1"> </text:span></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 de2e9da4c6..42099f3bc4 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -3053,6 +3053,13 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160017_spanClosingOrder)
CPPUNIT_ASSERT(parseXml(maTempFile));
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160390)
+{
+ // This document must not hang infinitely on HTML export
+ createSwDoc("tdf160390.fodt");
+ ExportToHTML();
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/layout/data/tdf160526.fodt b/sw/qa/extras/layout/data/tdf160526.fodt
new file mode 100644
index 0000000000..37cf73fb8e
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160526.fodt
@@ -0,0 +1,47 @@
+<?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: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:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:writing-mode="lr-tb" style:flow-with-text="false"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties style:punctuation-wrap="hanging" style:line-break="strict" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true" fo:hyphenate="false"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic">
+ <style:graphic-properties draw:fill-color="#81d41a" draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="3cm" fo:min-width="12cm" style:run-through="foreground" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="25cm" fo:min-width="7cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="top" style:vertical-rel="baseline" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="20pt" style:layout-grid-ruby-height="10pt" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0"/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page"/>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="1" draw:name="Shape 1" draw:style-name="gr1" svg:width="12cm" svg:height="3cm" svg:x="4cm" svg:y="0cm">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>Foo</text:p>
+ <text:p><draw:custom-shape text:anchor-type="as-char" draw:z-index="0" draw:name="Shape 2" draw:style-name="gr2" svg:width="7cm" svg:height="25cm">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/layout/data/tdf160549.fodt b/sw/qa/extras/layout/data/tdf160549.fodt
new file mode 100644
index 0000000000..fd8425eedd
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160549.fodt
@@ -0,0 +1,60 @@
+<?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: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:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="36pt" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Graphics" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" fo:margin-left="2mm" fo:margin-right="2mm" fo:margin-top="2mm" fo:margin-bottom="2mm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" draw:fill="none" fo:padding="1.5mm" fo:border="0.06pt solid #000000"/>
+ </style:style>
+ <style:default-page-layout>
+ <style:page-layout-properties style:layout-grid-standard-mode="true"/>
+ </style:default-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:wrap="none" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="right" style:horizontal-rel="page-content" fo:background-color="#ffffff" style:background-transparency="100%" draw:fill="solid" draw:fill-color="#ffffff" draw:opacity="0%" fo:padding="0pt" fo:border="none" style:writing-mode="lr-tb" draw:wrap-influence-on-position="once-successive"/>
+ </style:style>
+ <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Graphics">
+ <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:vertical-pos="top" style:vertical-rel="baseline" fo:border="none" style:mirror="none" fo:clip="rect(0pt, 0pt, 0pt, 0pt)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
+ </style:style>
+ <style:page-layout style:name="pm1" style:page-usage="mirrored">
+ <style:page-layout-properties fo:page-width="148mm" fo:page-height="210mm" style:num-format="1" style:print-orientation="landscape" fo:margin-top="15mm" fo:margin-bottom="15mm" fo:margin-left="15mm" fo:margin-right="15mm" style:writing-mode="lr-tb"/>
+ <style:header-style>
+ <style:header-footer-properties fo:min-height="5mm" fo:margin-bottom="1mm" style:dynamic-spacing="true"/>
+ </style:header-style>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1">
+ <style:header>
+ <text:p><draw:frame draw:style-name="fr1" draw:name="Frame1" text:anchor-type="paragraph" svg:y="1mm" draw:z-index="0">
+ <draw:text-box fo:min-height="5mm" fo:min-width="4cm">
+ <text:p>foobar</text:p>
+ </draw:text-box>
+ </draw:frame></text:p>
+ </style:header>
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p><draw:custom-shape draw:style-name="fr2" draw:name="Image2" text:anchor-type="as-char" svg:width="8cm" svg:height="19cm" draw:z-index="1">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape><text:s/></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 a074a35dc6..98c77b18ec 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -2353,6 +2353,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testPageBreakInHiddenSection)
assertXPath(pXmlDoc, "//page[4]/body/section/infos/bounds"_ostr, "height"_ostr, u"0"_ustr);
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf160549)
+{
+ // Given a document with a large as-char object, alone in its paragraph, shifted down by a
+ // header object: it must not hang in a layout loop on import (similar to i84870, but not
+ // fixed by its fix)
+ createSwDoc("tdf160549.fodt");
+ // The object is the first in the document; it must not move to the next page
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf160526)
+{
+ // Given a document with a large as-char object, alone in its paragraph, shifted down by
+ // another body object
+ createSwDoc("tdf160526.fodt");
+ // It must move to the next page
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
+ auto pExportDump = parseLayoutDump();
+ assertXPath(pExportDump, "//page[2]/body/txt/anchored/SwAnchoredDrawObject"_ostr);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/odfexport/data/tdf160700.odt b/sw/qa/extras/odfexport/data/tdf160700.odt
new file mode 100644
index 0000000000..bc1515da3f
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf160700.odt
Binary files differ
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx
index 4983608290..f654821acf 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -21,6 +21,7 @@
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
@@ -1343,6 +1344,35 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf159438)
u"bookmark3"_ustr);
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf160700)
+{
+ // Given a document with an empty numbered paragraph, and a cross-reference to it
+ loadAndReload("tdf160700.odt");
+
+ // Refresh fields and ensure cross-reference to numbered para is okay
+ auto xTextFieldsSupplier(mxComponent.queryThrow<text::XTextFieldsSupplier>());
+ auto xFieldsAccess(xTextFieldsSupplier->getTextFields());
+
+ xFieldsAccess.queryThrow<util::XRefreshable>()->refresh();
+
+ auto xFields(xFieldsAccess->createEnumeration());
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+ auto xTextField(xFields->nextElement().queryThrow<text::XTextField>());
+ // Save must not create markup with text:bookmark-end element before text:bookmark-start
+ // Withoud the fix, this would fail with
+ // - Expected: 1
+ // - Actual : Error: Reference source not found
+ // i.e., the bookmark wasn't imported, and the field had no proper source
+ CPPUNIT_ASSERT_EQUAL(u"1"_ustr, xTextField->getPresentation(false));
+
+ xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+ // Check that we export the bookmark in the empty paragraph as a single text:bookmark
+ // element. Another walid markup is text:bookmark-start followed by text:bookmark-end
+ // (in that order). The problem was, that text:bookmark-end was before text:bookmark-start.
+ assertXPathChildren(pXmlDoc, "//office:text/text:list/text:list-item/text:p"_ostr, 1);
+ assertXPath(pXmlDoc, "//office:text/text:list/text:list-item/text:p/text:bookmark"_ostr);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx b/sw/qa/extras/uiwriter/uiwriter5.cxx
index c6353f980d..702f6d7dd3 100644
--- a/sw/qa/extras/uiwriter/uiwriter5.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter5.cxx
@@ -3007,7 +3007,6 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156487)
assertXPath(pXmlDoc, "/metafile/push/push/push/textarray/text"_ostr, 1);
}
-#ifndef DBG_UTIL
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
{
// load a table, and delete the first column with enabled change tracking:
@@ -3023,7 +3022,6 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
// this would crash due to bookmark over cell boundary
dispatchCommand(mxComponent, ".uno:Undo", {});
}
-#endif
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150673_RedlineTableColumnDeletionWithExport)
{
diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx
index 8bcadbaf42..80b9e556f7 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -1201,6 +1201,27 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf129841)
CPPUNIT_ASSERT_EQUAL(aRefColor, aColor);
}
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf160278)
+{
+ createSwDoc();
+ auto xTextDocument(mxComponent.queryThrow<css::text::XTextDocument>());
+ auto xText(xTextDocument->getText());
+ xText->setString(u"123"_ustr);
+ CPPUNIT_ASSERT_EQUAL(u"123"_ustr, xText->getString());
+ auto xCursor = xText->createTextCursorByRange(xText->getEnd());
+ xCursor->goLeft(1, true);
+ CPPUNIT_ASSERT_EQUAL(u"3"_ustr, xCursor->getString());
+ // Insert an SMP character U+1f702 (so it's two UTF-16 code units, 0xd83d 0xdf02):
+ xCursor->setString(u"🜂"_ustr);
+ // Without the fix, the replacement would expand the cursor one too many characters to the left,
+ // and the cursor text would become "2🜂", failing the next test:
+ CPPUNIT_ASSERT_EQUAL(u"🜂"_ustr, xCursor->getString());
+ xCursor->setString(u"test"_ustr);
+ CPPUNIT_ASSERT_EQUAL(u"test"_ustr, xCursor->getString());
+ // This test would fail, too; the text would be "1test":
+ CPPUNIT_ASSERT_EQUAL(u"12test"_ustr, xText->getString());
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/uitest/writer_tests2/formatParagraph.py b/sw/qa/uitest/writer_tests2/formatParagraph.py
index e90d0fd7f9..bfa6eff48d 100644
--- a/sw/qa/uitest/writer_tests2/formatParagraph.py
+++ b/sw/qa/uitest/writer_tests2/formatParagraph.py
@@ -177,7 +177,7 @@ class formatParagraph(UITestCase):
self.assertEqual(get_state_as_dict(xspinWidow)["Text"], "2")
self.assertEqual(get_state_as_dict(xcheckWidow)["Selected"], "false")
self.assertEqual(get_state_as_dict(xcheckOrphan)["Selected"], "false")
- self.assertEqual(get_state_as_dict(xcheckSplitPara)["Selected"], "true")
+ self.assertEqual(get_state_as_dict(xcheckSplitPara)["Selected"], "false")
self.assertEqual(get_state_as_dict(xcheckKeepPara)["Selected"], "true")
diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx
index e515b5cae7..dfa94c3ed9 100644
--- a/sw/source/core/access/AccessibilityCheck.cxx
+++ b/sw/source/core/access/AccessibilityCheck.cxx
@@ -901,6 +901,11 @@ public:
}
case '\t':
{
+ // Don't warn about tabs in ToC
+ auto pSection = SwDoc::GetCurrSection(SwPosition(*pTextNode, 0));
+ if (pSection && pSection->GetTOXBase())
+ continue;
+
if (bPreviousWasChar)
{
++nTabCount;
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index c492212487..2038941230 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -149,6 +149,25 @@ SwFrameFormat* SwDoc::GetFlyNum( size_t nIdx, FlyCntType eType, bool bIgnoreText
return pRetFormat;
}
+SwFrameFormat* SwDoc::GetFlyFrameFormatByName( const OUString& rFrameFormatName )
+{
+ auto pFrameFormats = GetSpzFrameFormats();
+ auto it = pFrameFormats->findByTypeAndName( RES_FLYFRMFMT, rFrameFormatName );
+ auto endIt = pFrameFormats->typeAndNameEnd();
+ for ( ; it != endIt; ++it)
+ {
+ sw::SpzFrameFormat* pFlyFormat = *it;
+ const SwNodeIndex* pIdx = pFlyFormat->GetContent().GetContentIdx();
+ if( !pIdx || !pIdx->GetNodes().IsDocNodes() )
+ continue;
+
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+ if( !pNd->IsNoTextNode())
+ return pFlyFormat;
+ }
+ return nullptr;
+}
+
std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats(
FlyCntType const eType, bool const bIgnoreTextBoxes)
{
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 9eb51da617..b8d6b0e395 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -33,7 +33,8 @@
#include <strings.hrc>
#include <vector>
-void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool *const pUndo)
+void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool goLeft,
+ bool* const pUndo)
{
auto const oSelectAll(StartsWith_() != SwCursorShell::StartsWith::None
? ExtendedSelectedAll()
@@ -127,11 +128,12 @@ void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool
}
}
+ rPam.Normalize(goLeft); // change tracking case: will make sure to end up in the correct point
// Selection is not needed anymore
rPam.DeleteMark();
}
-bool SwEditShell::Delete(bool const isArtificialSelection)
+bool SwEditShell::Delete(bool const isArtificialSelection, bool goLeft)
{
CurrShell aCurr( this );
bool bRet = false;
@@ -159,7 +161,7 @@ bool SwEditShell::Delete(bool const isArtificialSelection)
for(SwPaM& rPaM : GetCursor()->GetRingContainer())
{
- DeleteSel(rPaM, isArtificialSelection, &bUndo);
+ DeleteSel(rPaM, isArtificialSelection, goLeft, &bUndo);
}
// If undo container then close here
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx
index 6ed4cdb7c1..47c675cc42 100644
--- a/sw/source/core/fields/expfld.cxx
+++ b/sw/source/core/fields/expfld.cxx
@@ -233,7 +233,7 @@ const SwTextNode* GetBodyTextNode( const SwDoc& rDoc, SwPosition& rPos,
else
pContentFrame = pPgFrame->FindLastBodyContent();
- if( pContentFrame )
+ if( pContentFrame && !pContentFrame->IsInFootnote() )
{
assert(pContentFrame->IsTextFrame());
SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pContentFrame));
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index a705ef2511..1a0a1260a1 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -809,6 +809,12 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext)
unlockPositionOfObjects( pPg );
pPg = static_cast<SwPageFrame*>(pPg->GetNext());
}
+ if (m_pRoot->IsSuperfluous()) // could be newly set now!
+ {
+ bool bOld = IsAgain();
+ m_pRoot->RemoveSuperfluous();
+ SetAgain(bOld);
+ }
// reset flag for special interrupt content formatting.
mbFormatContentOnInterrupt = false;
}
@@ -1433,7 +1439,11 @@ bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLa
PopFormatLayout();
}
}
- // else: don't calc content frames any more
+ else if (pLay->IsSctFrame() && pLow->IsTextFrame() && pLow == pLay->GetLastLower())
+ {
+ // else: only calc the last text lower of sections
+ pLow->OptCalc();
+ }
if ( IsAgain() )
return false;
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 0f048c4e80..5472695e97 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -7012,7 +7012,8 @@ void SwPageFrame::RefreshSubsidiary( const SwRect &rRect ) const
void SwLayoutFrame::RefreshLaySubsidiary( const SwPageFrame *pPage,
const SwRect &rRect ) const
{
- const bool bSubsOpt = isSubsidiaryLinesEnabled() || isSubsidiaryLinesForSectionsEnabled();
+ const bool bSubsOpt
+ = isSubsidiaryLinesEnabled() || (IsSctFrame() && isSubsidiaryLinesForSectionsEnabled());
if ( bSubsOpt )
PaintSubsidiaryLines( pPage, rRect );
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index c4a742c037..adffbba177 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -1165,7 +1165,13 @@ bool SwTabFrame::Split(const SwTwips nCutPos, bool bTryToSplit,
OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
if ( !IsInSct() )
{
- m_pTable->SetRowsToRepeat(0);
+ // This would mean the layout modifies the doc model, so RowsToRepeat drops to 0 while
+ // there are existing row frames with RepeatedHeadline == true. Avoid this at least
+ // inside split flys, it would lead to a crash in SwTabFrame::MakeAll().
+ if (!pFly || !pFly->IsFlySplitAllowed())
+ {
+ m_pTable->SetRowsToRepeat(0);
+ }
return false;
}
else
@@ -1517,7 +1523,8 @@ namespace
}
}
}
- if (rTab.IsCollapsingBorders() && !rCell.Lower()->IsRowFrame())
+ assert(rCell.Lower());
+ if (rTab.IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrame())
{
if (rRow.GetTopMarginForLowers() != 0
|| rRow.GetBottomMarginForLowers() != 0)
@@ -6371,6 +6378,10 @@ void SwTabFrame::dumpAsXml(xmlTextWriterPtr writer) const
{
(void)xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("tab"));
SwFrame::dumpAsXmlAttributes( writer );
+
+ (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("has-follow-flow-line"),
+ BAD_CAST(OString::boolean(m_bHasFollowFlowLine).getStr()));
+
if ( HasFollow() )
(void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() );
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index e19b834a56..97eff3e607 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1081,6 +1081,54 @@ void SwTextFrame::ChangeOffset( SwTextFrame* pFrame, TextFrameIndex nNew )
MoveFlyInCnt( pFrame, nNew, TextFrameIndex(COMPLETE_STRING) );
}
+static bool isFirstVisibleFrameInBody(const SwTextFrame* pFrame)
+{
+ const SwFrame* pBodyFrame = pFrame->FindBodyFrame();
+ if (!pBodyFrame)
+ return false;
+ for (const SwFrame* pCur = pFrame;;)
+ {
+ for (const SwFrame* pPrev = pCur->GetPrev(); pPrev; pPrev = pPrev->GetPrev())
+ if (!pPrev->IsHiddenNow())
+ return false;
+ pCur = pCur->GetUpper();
+ assert(pCur); // We found pBodyFrame, right?
+ if (pCur->IsBodyFrame())
+ return true;
+ }
+}
+
+static bool hasFly(const SwTextFrame* pFrame)
+{
+ if (auto pDrawObjs = pFrame->GetDrawObjs(); pDrawObjs && pDrawObjs->size())
+ {
+ auto anchorId = (*pDrawObjs)[0]->GetFrameFormat()->GetAnchor().GetAnchorId();
+ if (anchorId == RndStdIds::FLY_AT_PARA || anchorId == RndStdIds::FLY_AT_CHAR)
+ return true;
+ }
+ return false;
+}
+
+static bool hasAtPageFly(const SwFrame* pFrame)
+{
+ auto pPageFrame = pFrame->FindPageFrame();
+ if (!pPageFrame)
+ return false;
+ auto pPageDrawObjs = pPageFrame->GetDrawObjs();
+ if (pPageDrawObjs)
+ {
+ for (const auto pObject : *pPageDrawObjs)
+ if (pObject->GetFrameFormat()->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ return true;
+ }
+ return false;
+}
+
+static bool isReallyEmptyMaster(const SwTextFrame* pFrame)
+{
+ return pFrame->IsEmptyMaster() && (!pFrame->GetDrawObjs() || !pFrame->GetDrawObjs()->size());
+}
+
void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
WidowsAndOrphans &rFrameBreak,
TextFrameIndex const nStrLen,
@@ -1108,27 +1156,55 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
? 1 : 0;
SwTextFormatInfo& rInf = rLine.GetInfo();
+ bool bEmptyWithSplitFly = false;
if (nNew == 0 && !nStrLen && !rInf.GetTextFly().IsOn() && IsEmptyWithSplitFly())
{
// Empty paragraph, so IsBreakNow() is not called, but we should split the fly portion and
// the paragraph marker.
nNew = 1;
+ bEmptyWithSplitFly = true;
}
+ const SwFrame *pBodyFrame = FindBodyFrame();
+
// i#84870
// no split of text frame, which only contains an as-character anchored object
- bool bOnlyContainsAsCharAnchoredObj =
+ bool bLoneAsCharAnchoredObj =
+ pBodyFrame &&
!IsFollow() && nStrLen == TextFrameIndex(1) &&
GetDrawObjs() && GetDrawObjs()->size() == 1 &&
(*GetDrawObjs())[0]->GetFrameFormat()->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR;
- // Still try split text frame if we have columns.
- if (FindColFrame())
- bOnlyContainsAsCharAnchoredObj = false;
-
- if ( nNew && bOnlyContainsAsCharAnchoredObj )
+ if (bLoneAsCharAnchoredObj)
{
- nNew = 0;
+ // Still try split text frame if we have columns.
+ if (FindColFrame())
+ bLoneAsCharAnchoredObj = false;
+ // tdf#160526: only no split if there is no preceding frames on same page
+ else if (!isFirstVisibleFrameInBody(this))
+ bLoneAsCharAnchoredObj = false;
+ else
+ nNew = 0;
+ }
+ else if (nNew)
+ {
+ if (IsFollow())
+ {
+ // tdf#160549: do not split the frame at the very beginning again, if its master was empty
+ auto precede = static_cast<SwTextFrame*>(GetPrecede());
+ assert(precede);
+ auto precedeText = precede->DynCastTextFrame();
+ assert(precedeText);
+ if (isReallyEmptyMaster(precedeText))
+ nNew = 0;
+ }
+ else if (!bEmptyWithSplitFly)
+ {
+ // Do not split immediately in the beginning of page (unless there is an at-para or
+ // at-char or at-page fly, which pushes the rest down)
+ if (isFirstVisibleFrameInBody(this) && !hasFly(this) && !hasAtPageFly(pBodyFrame))
+ nNew = 0;
+ }
}
if ( nNew )
@@ -1136,8 +1212,6 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SplitFrame( nEnd );
}
- const SwFrame *pBodyFrame = FindBodyFrame();
-
const tools::Long nBodyHeight = pBodyFrame ? ( IsVertical() ?
pBodyFrame->getFrameArea().Width() :
pBodyFrame->getFrameArea().Height() ) : 0;
@@ -1239,9 +1313,10 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
// content or contains no content, but has a numbering.
// i#84870 - No split, if text frame only contains one
// as-character anchored object.
- if ( !bOnlyContainsAsCharAnchoredObj &&
- (nStrLen > TextFrameIndex(0) ||
- bHasVisibleNumRule )
+ if (!bLoneAsCharAnchoredObj
+ && (bHasVisibleNumRule
+ || (nStrLen > TextFrameIndex(0)
+ && (nEnd != rLine.GetStart() || rInf.GetRest())))
)
{
SplitFrame( nEnd );
@@ -1265,7 +1340,7 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight;
//#i84870# - no shrink of text frame, if it only contains one as-character anchored object.
- if ( nChg < 0 && !bDelta && bOnlyContainsAsCharAnchoredObj )
+ if (nChg < 0 && !bDelta && bLoneAsCharAnchoredObj)
{
nChg = 0;
}
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 72f1c809e2..52157df0ca 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -2599,11 +2599,17 @@ void SwUndoTableCpyTable::AddBoxBefore( const SwTableBox& rBox, bool bDelContent
if( bDelContent )
{
SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
- pDoc->GetNodes().MakeTextNode( aInsIdx.GetNode(), pDoc->GetDfltTextFormatColl() );
+ SwTextNode *const pNewNode(pDoc->GetNodes().MakeTextNode(aInsIdx.GetNode(), pDoc->GetDfltTextFormatColl()));
SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
if( !pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
+ {
+ { // move cursors to new node which precedes aPam
+ SwPosition const pos(*pNewNode, 0);
+ ::PaMCorrAbs(aPam, pos);
+ }
pEntry->pUndo = std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, true);
+ }
}
pEntry->pBoxNumAttr = std::make_unique<SfxItemSetFixed<
@@ -2627,6 +2633,13 @@ void SwUndoTableCpyTable::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex
SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
DEBUG_REDLINE( pDoc )
+ { // move cursors to first node which was inserted
+ SwPaM pam(SwNodeIndex(*rBox.GetSttNd(), 1));
+ assert(pam.GetPoint()->GetNode().IsTextNode());
+ pam.SetMark();
+ pam.Move(fnMoveForward, GoInContent);
+ ::PaMCorrAbs(pam, *pam.GetPoint());
+ }
if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
{
SwPosition aTmpPos( rIdx );
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 7880a749b9..62c4c76ac3 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1713,18 +1713,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any&
}
else
{
- const size_t nCount = pDoc->GetFlyCount(FLYCNTTYPE_FRM);
-
- SwFrameFormat* pChain = nullptr;
- for( size_t i = 0; i < nCount; ++i )
- {
- SwFrameFormat* pFormat2 = pDoc->GetFlyNum(i, FLYCNTTYPE_FRM);
- if(sChainName == pFormat2->GetName() )
- {
- pChain = pFormat2;
- break;
- }
- }
+ SwFrameFormat* pChain = pDoc->GetFlyFrameFormatByName(sChainName);
if(pChain)
{
SwFrameFormat* pSource = bNextFrame ? pFormat : pChain;
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index 49562c1d02..df02c4773a 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -752,13 +752,19 @@ void SwXTextCursor::DeleteAndInsert(std::u16string_view aText,
}
if(nTextLen)
{
+ // Store node and content indexes prior to insertion: to select the inserted text,
+ // we need to account for possible surrogate pairs, combining characters, etc.; it
+ // is easier to just restore the correct position from the indexes.
+ const auto start = pCurrent->Start();
+ const auto nodeIndex = start->GetNodeIndex();
+ const auto contentIndex = start->GetContentIndex();
const bool bSuccess(
SwUnoCursorHelper::DocInsertStringSplitCR(
- rDoc, *pCurrent, aText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints)));
+ rDoc, SwPaM(*start, pCurrent), aText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints)));
OSL_ENSURE( bSuccess, "Doc->Insert(Str) failed." );
- SwUnoCursorHelper::SelectPam(*pUnoCursor, true);
- pCurrent->Left(aText.size());
+ pCurrent->SetMark();
+ pCurrent->GetPoint()->Assign(nodeIndex, contentIndex);
}
pCurrent = pCurrent->GetNext();
} while (pCurrent != pUnoCursor);
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 494cec7468..709d79ef4d 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -150,8 +150,11 @@ namespace
bool const hasOther = isExpanded && rStartPos != rEndPos;
bool const bStartPosInNode = rStartPos.GetNode() == rOwnNode;
bool const bEndPosInNode = rEndPos.GetNode() == rOwnNode;
+ // tdf#160700: Crossrefbookmarks only need separate start and end, when the start
+ // isn't in the end position (so in empty nodes, no need to handle them specially)
sw::mark::CrossRefBookmark* const pCrossRefMark
= !isExpanded && bStartPosInNode
+ && rStartPos.GetContentIndex() < rStartPos.GetContentNode()->Len()
? dynamic_cast<sw::mark::CrossRefBookmark*>(pBkmk)
: nullptr;
diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx
index c880082018..f298f93dc5 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -1524,8 +1524,9 @@ void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart,
for (auto it = items.begin(); it != items.end();)
{
- HTMLStartEndPos* pTest = *it;
- sal_Int32 nTestEnd = pTest->GetEnd();
+ auto itTest = it++; // forward early, allow 'continue', and keep a copy for 'erase'
+ HTMLStartEndPos* pTest = *itTest;
+ const sal_Int32 nTestEnd = pTest->GetEnd();
if (nTestEnd <= nStart)
continue;
@@ -1533,28 +1534,25 @@ void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart,
const SfxPoolItem& rTestItem = pTest->GetItem();
// only the corresponding OnTag attributes have to be considered
- if (rTestItem.Which() == nWhich && HTML_ON_VALUE == GetHTMLItemState(rTestItem))
- {
- // if necessary, insert the second part of the split
- // attribute
- if (nTestEnd > nEnd)
- InsertItem(pTest->GetItem(), nEnd, nTestEnd);
+ if (rTestItem.Which() != nWhich || HTML_ON_VALUE != GetHTMLItemState(rTestItem))
+ continue;
- if (nTestStart >= nStart)
- {
- // the Test item only starts after the new end of the
- // attribute. Therefore, it can be completely erased.
- it = items.erase(it);
- std::erase(m_aEndLst[pTest->GetEnd()], pTest);
- delete pTest;
- continue;
- }
+ // if necessary, insert the second part of the split attribute
+ if (nTestEnd > nEnd)
+ InsertItem(rTestItem, nEnd, nTestEnd);
- // the start of the new attribute corresponds to the new
- // end of the attribute
- FixSplittedItem(pTest, nStart);
+ if (nTestStart >= nStart)
+ {
+ // the Test item only starts after the new end of the
+ // attribute. Therefore, it can be completely erased.
+ it = items.erase(itTest);
+ std::erase(m_aEndLst[nTestEnd], pTest);
+ delete pTest;
+ continue;
}
- ++it;
+
+ // the start of the new attribute corresponds to the new end of the attribute
+ FixSplittedItem(pTest, nStart);
}
}
}
diff --git a/sw/source/filter/html/htmlctxt.cxx b/sw/source/filter/html/htmlctxt.cxx
index 80245ba2ea..0e87b83644 100644
--- a/sw/source/filter/html/htmlctxt.cxx
+++ b/sw/source/filter/html/htmlctxt.cxx
@@ -656,7 +656,8 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet,
}
#endif
- for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ SfxItemIter aIter2(rItemSet);
+ for (const SfxPoolItem* pItem = aIter2.GetCurItem(); pItem; pItem = aIter2.NextItem())
{
HTMLAttr **ppAttr = nullptr;
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 68437c9529..e33e8708f4 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2658,33 +2658,36 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
assert(pFieldmark);
- if (pFieldmark->GetFieldname() == ODF_FORMDATE)
+ if (pFieldmark)
{
- if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
+ if (pFieldmark->GetFieldname() == ODF_FORMDATE)
{
- OutputField( nullptr, ww::eFORMDATE, OUString(), FieldFlags::Close );
+ if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
+ {
+ OutputField( nullptr, ww::eFORMDATE, OUString(), FieldFlags::Close );
+ }
}
- }
- else
- {
- ww::eField eFieldId = lcl_getFieldId( pFieldmark );
- if (pFieldmark->GetFieldname() == ODF_UNHANDLED)
+ else
{
- IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
- if ( it != pFieldmark->GetParameters()->end() )
+ ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+ if (pFieldmark->GetFieldname() == ODF_UNHANDLED)
{
- OUString sFieldId;
- it->second >>= sFieldId;
- eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
+ IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
+ if ( it != pFieldmark->GetParameters()->end() )
+ {
+ OUString sFieldId;
+ it->second >>= sFieldId;
+ eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
+ }
}
- }
- OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
+ OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
- if (pFieldmark->GetFieldname() == ODF_FORMTEXT
- && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
- {
- AppendBookmark( pFieldmark->GetName() );
+ if (pFieldmark->GetFieldname() == ODF_FORMTEXT
+ && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
+ {
+ AppendBookmark( pFieldmark->GetName() );
+ }
}
}
}
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 10ccaa4878..976a68b88a 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -27,6 +27,7 @@
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/packages/XPackageEncryption.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <i18nlangtag/languagetag.hxx>
@@ -4808,27 +4809,35 @@ void SwWW8ImplReader::ReadDocVars()
aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
if (m_bVer67) return;
- uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
- m_pDocShell->GetModel(), uno::UNO_QUERY_THROW);
- uno::Reference<document::XDocumentProperties> xDocProps(
- xDPS->getDocumentProperties());
- OSL_ENSURE(xDocProps.is(), "DocumentProperties is null");
- uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
- xDocProps->getUserDefinedProperties();
- OSL_ENSURE(xUserDefinedProps.is(), "UserDefinedProperties is null");
-
- for(size_t i=0; i<aDocVarStrings.size(); i++)
+ uno::Reference< text::XTextFieldsSupplier > xFieldsSupplier(m_pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<css::lang::XMultiServiceFactory> xTextFactory(m_pDocShell->GetModel(), uno::UNO_QUERY);
+ uno::Reference< container::XNameAccess > xFieldMasterAccess = xFieldsSupplier->getTextFieldMasters();
+ for(size_t i = 0; i < aDocVarStrings.size(); i++)
{
const OUString &rName = aDocVarStrings[i];
uno::Any aValue;
- aValue <<= rName;
- try {
- xUserDefinedProps->addProperty( rName,
- beans::PropertyAttribute::REMOVABLE,
- aValue );
- } catch (const uno::Exception &) {
- // ignore
+ if (aDocValueStrings.size() > i)
+ {
+ OUString value = aDocValueStrings[i];
+ value = value.replaceAll("\r\n", "\n");
+ value = value.replaceAll("\r", "\n");
+ aValue <<= value;
+ }
+
+ uno::Reference< beans::XPropertySet > xMaster;
+ OUString sFieldMasterService("com.sun.star.text.FieldMaster.User." + rName);
+
+ // Find or create Field Master
+ if (xFieldMasterAccess->hasByName(sFieldMasterService))
+ {
+ xMaster.set(xFieldMasterAccess->getByName(sFieldMasterService), uno::UNO_QUERY_THROW);
+ }
+ else
+ {
+ xMaster.set(xTextFactory->createInstance("com.sun.star.text.FieldMaster.User"), uno::UNO_QUERY_THROW);
+ xMaster->setPropertyValue("Name", uno::Any(rName));
}
+ xMaster->setPropertyValue("Content", aValue);
}
}
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index c87c33dde0..6750fa21ae 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -58,6 +58,7 @@
#include <IDocumentState.hxx>
#include <flddat.hxx>
#include <docufld.hxx>
+#include <usrfld.hxx>
#include <reffld.hxx>
#include <IMark.hxx>
#include <expfld.hxx>
@@ -1831,12 +1832,29 @@ eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, OUString& rStr )
aData = aData.replaceAll("\"", "");
}
- const auto pType(static_cast<SwDocInfoFieldType*>(
- m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocInfo)));
- SwDocInfoField aField(pType, nSub|nReg, aData, GetFieldResult(pF), nFormat);
- if (bDateTime)
- ForceFieldLanguage(aField, nLang);
- m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM, SwFormatField(aField));
+ bool bDone = false;
+ if (DI_CUSTOM == nSub)
+ {
+ const auto pType(static_cast<SwUserFieldType*>(
+ m_rDoc.getIDocumentFieldsAccess().GetFieldType(SwFieldIds::User, aData, false)));
+ if (pType)
+ {
+ SwUserField aField(pType, 0, nFormat);
+ if (bDateTime)
+ ForceFieldLanguage(aField, nLang);
+ m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM, SwFormatField(aField));
+ bDone = true;
+ }
+ }
+ if (!bDone)
+ {
+ const auto pType(static_cast<SwDocInfoFieldType*>(
+ m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocInfo)));
+ SwDocInfoField aField(pType, nSub|nReg, aData, GetFieldResult(pF), nFormat);
+ if (bDateTime)
+ ForceFieldLanguage(aField, nLang);
+ m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM, SwFormatField(aField));
+ }
return eF_ResT::OK;
}
diff --git a/sw/source/ui/fldui/fldref.cxx b/sw/source/ui/fldui/fldref.cxx
index a08715c8ca..434e10a6a2 100644
--- a/sw/source/ui/fldui/fldref.cxx
+++ b/sw/source/ui/fldui/fldref.cxx
@@ -268,7 +268,7 @@ void SwFieldRefPage::Reset(const SfxItemSet* )
nFieldDlgFormatSel = 0;
sal_uInt16 nFormatBoxPosition = USHRT_MAX;
- if( !IsRefresh() )
+ if( !IsFieldEdit() )
{
sal_Int32 nIdx{ 0 };
const OUString sUserData = GetUserData();
diff --git a/sw/source/ui/index/cnttab.cxx b/sw/source/ui/index/cnttab.cxx
index a5d3bf92dd..535dc298dd 100644
--- a/sw/source/ui/index/cnttab.cxx
+++ b/sw/source/ui/index/cnttab.cxx
@@ -2933,7 +2933,7 @@ SwTOXWidget* SwTokenWindow::InsertItem(const OUString& rText, const SwFormToken&
//use the first two chars as symbol
OUString sTmp(SwAuthorityFieldType::GetAuthFieldName(
static_cast<ToxAuthorityField>(rToken.nAuthorityField)));
- pButton->SetText(sTmp.copy(0, 2));
+ pButton->SetText(sTmp.copy(0, std::min(sTmp.getLength(), sal_Int32(2))));
}
sal_uInt32 nIndex = GetControlIndex( rToken.eTokenType );
@@ -3140,7 +3140,7 @@ void SwTokenWindow::InsertAtSelection(const SwFormToken& rToken)
//use the first two chars as symbol
OUString sTmp(SwAuthorityFieldType::GetAuthFieldName(
static_cast<ToxAuthorityField>(aToInsertToken.nAuthorityField)));
- pButton->SetText(sTmp.copy(0, 2));
+ pButton->SetText(sTmp.copy(0, std::min(sTmp.getLength(), sal_Int32(2))));
}
pButton->Check();
diff --git a/sw/source/ui/index/swuiidxmrk.cxx b/sw/source/ui/index/swuiidxmrk.cxx
index 8a6f74b86e..03d5733a87 100644
--- a/sw/source/ui/index/swuiidxmrk.cxx
+++ b/sw/source/ui/index/swuiidxmrk.cxx
@@ -441,6 +441,7 @@ IMPL_LINK_NOARG(SwIndexMarkPane, SyncSelectionHdl, weld::Button&, void)
m_xApplyToAllCB->show();
m_xSearchCaseSensitiveCB->show();
m_xSearchCaseWordOnlyCB->show();
+ m_xDialog->resize_to_request();
m_xApplyToAllCB->set_sensitive(!m_aOrgStr.isEmpty() &&
!(nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FLY_ANY )));
SearchTypeHdl(*m_xApplyToAllCB);
diff --git a/sw/source/uibase/shells/textsh.cxx b/sw/source/uibase/shells/textsh.cxx
index 97de985401..29242d9946 100644
--- a/sw/source/uibase/shells/textsh.cxx
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -885,10 +885,13 @@ void SwTextShell::ExecRotateTransliteration( SfxRequest const & rReq )
}
else
{
- rSh.Push(); // save cur cursor
- if ((rSh.IsEndWrd() || rSh.IsStartWord() || rSh.IsInWord()) && rSh.SelWrd())
+ if (rSh.IsEndSentence())
+ {
+ rSh.BwdSentence(true);
+ rSh.TransliterateText(m_aRotateCase.getNextMode());
+ }
+ else if ((rSh.IsEndWrd() || rSh.IsStartWord() || rSh.IsInWord()) && rSh.SelWrd())
rSh.TransliterateText(m_aRotateCase.getNextMode());
- rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
}
}
}
diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx
index e7a09d0165..46b0a40cca 100644
--- a/sw/source/uibase/wrtsh/delete.cxx
+++ b/sw/source/uibase/wrtsh/delete.cxx
@@ -171,7 +171,7 @@ bool SwWrtShell::DelLeft()
{
SwActContext aActContext(this);
ResetCursorStack();
- Delete(false);
+ Delete(false, true);
UpdateAttr();
}
if( IsBlockMode() )
@@ -274,7 +274,7 @@ bool SwWrtShell::DelLeft()
SwCursorShell::Pop( SwCursorShell::PopMode::DeleteStack );
}
}
- bool bRet = Delete(true);
+ bool bRet = Delete(true, true);
if( !bRet && bSwap )
SwCursorShell::SwapPam();
CloseMark( bRet );