summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2024-03-04 15:45:07 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2024-03-07 15:14:42 +0100
commit0a0196bc0fe18449debae5f6353c1ddb312df916 (patch)
tree8eea7fc790bdc08d83cc471aa8a563c111f67751
parentfa7cdf1777aa063d3b1cf89a75a66e2ed319c4a9 (diff)
sw: SelectAll of section with RES_PAGEDESC corner-case
The main problem here is that if a document has a RES_PAGEDESC on its first body text node, and you paste a section whose first text node also has a RES_PAGEDESC, the result inevitably has a page break that wasn't there before, and which is unwanted. SwEditShell::CopySelToDoc() needs a change to include the end node of a section at the start, so it is copied. Change CopyImplImpl() to insert a non-textnode *before* a text node at the insert position, instead of after it. This simplifies the implementation: only SwFEShell::Paste() needs to care about removing an empty trailing paragraph, but SwEditShell::CopySelToDoc() needs no changes; both functions would need to delete the empty paragraph when inserting after. Several tests such as CppunitTest_sw_ooxmlexport3 testCrashWhileSave fail because of this, which can be solved by removing the DelFullPara() call in SwXText::copyText() that is now unnecessary. Generalise and simplify the "bAfterTable" code in CopyImplImpl(): it doesn't really matter what is before the insert position, what matters is if the pasted text starts with a table or section. Also, the fly-anchor-correction code (both here and in SwUndoInserts::RedoImpl()) needs to move to the first text node also in case a section was inserted (but the equal-looking code *before* inserting remains as is!), in the situation where the last node will be deleted. Now there are some test failures: unowriter.cxx:430:Assertion Test name: (anonymous namespace)::testSectionAnchorCopyTableAtStart::TestBody equality assertion failed - Expected: quux foo bar - Actual : quux foo This is because the end position was created from SwNodeIndex aInsPos only, it needs to take also the aDestIdx from the "if (pEndTextNd)" branch. testTdf134250::TestBody finished in: 867ms uiwriter2.cxx:462:Assertion Test name: testTdf134250::TestBody equality assertion failed - Expected: 1 - Actual : 2 The section is pasted now, so there are 2. uiwriter3.cxx:1519:Assertion Test name: testTdf135733::TestBody equality assertion failed - Expected: 1 - Actual : 2 Table is now inserted before the first paragraph, which has a RES_PAGEDESC. (presumably regression from commit 9667e5ffd18d6167344e102b89a393bc981644ec) For the backport, this also fails: uiwriter2.cxx:1220:testTdf141175::TestBody equality assertion failed - Expected: 2 - Actual : 1 Because the clipboard doc starts with a table node, it takes different path in Paste and merges the source table cells into target table cells. Probably users don't care about this corner case, and it doesn't do anything obviously wrong. On master it does yet different things because Cut creates table delete redlines. Change-Id: I820e381113fee90a81249afbc2280bfc3ddb7647 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164401 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit fcd4222d36e1864452163e5c94976eea353bbaf0)
-rw-r--r--sw/qa/extras/uiwriter/data/pagebreak-source.fodt123
-rw-r--r--sw/qa/extras/uiwriter/data/pagebreak-target.fodt129
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx119
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx4
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx75
-rw-r--r--sw/source/core/docnode/nodes.cxx2
-rw-r--r--sw/source/core/edit/edglss.cxx9
-rw-r--r--sw/source/core/frmedt/fecopy.cxx15
-rw-r--r--sw/source/core/undo/untblk.cxx6
-rw-r--r--sw/source/core/unocore/unotext.cxx6
10 files changed, 441 insertions, 47 deletions
diff --git a/sw/qa/extras/uiwriter/data/pagebreak-source.fodt b/sw/qa/extras/uiwriter/data/pagebreak-source.fodt
new file mode 100644
index 000000000000..e09c1b447cfd
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/pagebreak-source.fodt
@@ -0,0 +1,123 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooo="http://openoffice.org/2004/office" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2024-03-05T16:51:41.526594818</meta:creation-date><dc:date>2024-03-05T17:24:50.151189313</dc:date><meta:editing-duration>PT24M14S</meta:editing-duration><meta:editing-cycles>5</meta:editing-cycles><meta:generator>CIB_OfficeDev/6.4.0.24$Linux_X86_64 LibreOffice_project/2b8ce275a2d1aae9319dfc266e677412b611101d</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="0" meta:word-count="0" meta:character-count="0" meta:non-whitespace-character-count="0"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans Devanagari" svg:font-family="'Noto Sans Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" 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:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
+ <style:text-properties/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="Standard">
+ <style:paragraph-properties style:page-number="auto"/>
+ </style:style>
+ <style:style style:name="Sect1" style:family="section">
+ <style:section-properties fo:background-color="transparent" style:editable="false">
+ <style:columns fo:column-count="1" fo:column-gap="0cm"/>
+ <style:background-image/>
+ </style:section-properties>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" 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="0.706cm" style:layout-grid-ruby-height="0.353cm" 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="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:section text:style-name="Sect1" text:name="SourceSection">
+ <text:p text:style-name="P3"><text:hidden-paragraph text:condition="ooow:TRUE" text:is-hidden="true"/></text:p>
+ <text:p text:style-name="P2"/>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/data/pagebreak-target.fodt b/sw/qa/extras/uiwriter/data/pagebreak-target.fodt
new file mode 100644
index 000000000000..f059e33f1514
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/pagebreak-target.fodt
@@ -0,0 +1,129 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooo="http://openoffice.org/2004/office" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2024-03-05T16:57:01.179149401</meta:creation-date><dc:date>2024-03-05T16:58:35.972978544</dc:date><meta:editing-duration>PT1M35S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>CIB_OfficeDev/6.4.0.24$Linux_X86_64 LibreOffice_project/2b8ce275a2d1aae9319dfc266e677412b611101d</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="0" meta:word-count="0" meta:character-count="0" meta:non-whitespace-character-count="0"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans Devanagari" svg:font-family="'Noto Sans Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" 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:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" 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:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" 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" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
+ </style:style>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="Standard">
+ <style:paragraph-properties style:page-number="auto"/>
+ </style:style>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties style:vertical-pos="top" style:vertical-rel="page-content" style:horizontal-pos="center" style:horizontal-rel="page"/>
+ </style:style>
+ <style:style style:name="Sect1" style:family="section">
+ <style:section-properties style:editable="false">
+ <style:columns fo:column-count="1" fo:column-gap="0cm"/>
+ </style:section-properties>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" 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:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls><draw:frame draw:style-name="fr1" draw:name="Frame1" text:anchor-type="page" text:anchor-page-number="1" svg:width="2cm" draw:z-index="0">
+ <draw:text-box fo:min-height="0.499cm">
+ <text:p text:style-name="Frame_20_contents"/>
+ </draw:text-box>
+ </draw:frame>
+ <text:section text:style-name="Sect1" text:name="TargetSection">
+ <text:p text:style-name="P1"/>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index beb7fc718d80..9e1a8c4c3b50 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -749,6 +749,119 @@ void SwUiWriterTest::testThreadedException()
CPPUNIT_ASSERT(!bRes);
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testPasteTableAtFlyAnchor)
+{
+ SwDoc * pDoc(createDoc());
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
+ anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint());
+ SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>{});
+ flySet.Put(anchor);
+ SwFlyFrameFormat const* pFly = dynamic_cast<SwFlyFrameFormat const*>(
+ pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true));
+ CPPUNIT_ASSERT(pFly != nullptr);
+ CPPUNIT_ASSERT(pFly->GetFrame() != nullptr);
+ pWrtShell->SelFlyGrabCursor();
+ pWrtShell->GetDrawView()->UnmarkAll();
+ CPPUNIT_ASSERT(pWrtShell->GetCurrFlyFrame() != nullptr);
+
+ // insert table in fly
+ SwInsertTableOptions tableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ pWrtShell->InsertTable(tableOpt, 2, 2);
+
+ // select table
+ pWrtShell->SelAll();
+
+ lcl_dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ // move cursor back to body
+ pWrtShell->ClearMark();
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ CPPUNIT_ASSERT(!pWrtShell->GetCurrFlyFrame());
+
+ lcl_dispatchCommand(mxComponent, ".uno:Paste", {});
+
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ CPPUNIT_ASSERT(pWrtShell->IsCursorInTable());
+ CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->nNode.GetNode().FindTableNode());
+
+ pWrtShell->Undo();
+
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable());
+ CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->nNode.GetNode().FindTableNode());
+
+ // the problem was that Redo moved the fly anchor into the first table cell
+ pWrtShell->Redo();
+
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ CPPUNIT_ASSERT(pWrtShell->IsCursorInTable());
+ CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->nNode.GetNode().FindTableNode());
+
+ pWrtShell->Undo();
+
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable());
+ CPPUNIT_ASSERT(!pFly->GetAnchor().GetContentAnchor()->nNode.GetNode().FindTableNode());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testCopyPastePageBreak)
+{
+ rtl::Reference<SwTransferable> pTransfer;
+ {
+ SwDoc * pDoc(createDoc("pagebreak-source.fodt"));
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ pWrtShell->SelAll();
+
+ pTransfer = new SwTransferable(*pWrtShell);
+ pTransfer->Copy();
+
+ //lcl_dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ mxComponent->dispose();
+ mxComponent.clear();
+ }
+
+ SwDoc * pDoc(createDoc("pagebreak-target.fodt"));
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty<OUString>(getParagraph(1), "PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName());
+
+ //paste not working in this branch? lcl_dispatchCommand(mxComponent, ".uno:Paste", {});
+ TransferableDataHelper aHelper(pTransfer.get());
+ SwTransferable::Paste(*pWrtShell, aHelper);
+
+ CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty<OUString>(getParagraph(1), "PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetSections().size());
+ CPPUNIT_ASSERT_EQUAL(OUString("SourceSection"), pWrtShell->GetCurrSection()->GetSectionName());
+ // the problem was that there was a page break now
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+ pWrtShell->Undo();
+ CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty<OUString>(getParagraph(1), "PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName());
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+ pWrtShell->Redo();
+ CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty<OUString>(getParagraph(1), "PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetSections().size());
+ CPPUNIT_ASSERT_EQUAL(OUString("SourceSection"), pWrtShell->GetCurrSection()->GetSectionName());
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+ pWrtShell->Undo();
+ CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty<OUString>(getParagraph(1), "PageDescName"));
+ CPPUNIT_ASSERT_EQUAL(OUString("TargetSection"), pWrtShell->GetCurrSection()->GetSectionName());
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+}
+
void SwUiWriterTest::testBookmarkCopy()
{
SwDoc * pDoc(createDoc());
@@ -4622,7 +4735,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf134250)
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
- CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
// this would crash in 2 different ways
lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
@@ -4638,7 +4751,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf134250)
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
- CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
Scheduler::ProcessEventsToIdle();
@@ -4651,7 +4764,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf134250)
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
- CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xSections->getCount());
}
void SwUiWriterTest::testDde()
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index f37f96a8a1fb..f6748fc1200b 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1217,7 +1217,9 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf141175)
lcl_dispatchCommand(mxComponent, ".uno:Paste", {});
Scheduler::ProcessEventsToIdle();
- CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
+ // the paste now takes a different path, where it doesn't insert a neseted
+ // table but instead merges the source table cells into the target table cells
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
CPPUNIT_ASSERT_EQUAL(1, getPages());
}
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index c6a1dae2a0e2..8318cc5d5ba8 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -26,6 +26,7 @@
#include <IDocumentSettingAccess.hxx>
#include <UndoManager.hxx>
#include <docary.hxx>
+#include <pamtyp.hxx>
#include <textboxhelper.hxx>
#include <dcontact.hxx>
#include <grfatr.hxx>
@@ -4784,26 +4785,25 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
// Move the PaM one node back from the insert position, so that
// the position doesn't get moved
pCopyPam->SetMark();
- bool bCanMoveBack = pCopyPam->Move(fnMoveBackward, GoInContent);
- // If the position was shifted from more than one node, an end node has been skipped
- bool bAfterTable = false;
- if ((rPos.nNode.GetIndex() - pCopyPam->GetPoint()->nNode.GetIndex()) > 1)
+ bool bCanMoveBack = false;
+ // First check if it will be able to move *to* first copied node.
+ // Note this doesn't just check IsStartNode() because SwDoc::AppendDoc()
+ // intentionally sets it to the body start node, perhaps it should just
+ // call SplitNode instead?
+ if (!pStt->nNode.GetNode().IsSectionNode() && !pStt->nNode.GetNode().IsTableNode())
{
- // First go back to the original place
- pCopyPam->GetPoint()->nNode = rPos.nNode;
- pCopyPam->GetPoint()->nContent = rPos.nContent;
-
- bCanMoveBack = false;
- bAfterTable = true;
+ bCanMoveBack = pCopyPam->Move(fnMoveBackward, GoInContent);
}
if( !bCanMoveBack )
{
pCopyPam->GetPoint()->nNode--;
+ pCopyPam->GetPoint()->nContent.Assign(pCopyPam->GetPoint()->nNode.GetNode().GetContentNode(), 0);
assert(pCopyPam->GetPoint()->nContent.GetIndex() == 0);
}
SwNodeRange aRg( pStt->nNode, pEnd->nNode );
SwNodeIndex aInsPos( rPos.nNode );
+ ::std::optional<SwIndex> oInsContentIndex;
const bool bOneNode = pStt->nNode == pEnd->nNode;
SwTextNode* pSttTextNd = pStt->nNode.GetNode().GetTextNode();
SwTextNode* pEndTextNd = pEnd->nNode.GetNode().GetTextNode();
@@ -4953,8 +4953,8 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
// We have to set the correct PaM for Undo, if this PaM starts in a textnode,
// the undo operation will try to merge this node after removing the table.
// If we didn't split a textnode, the PaM should start at the inserted table node
- if( rPos.nContent.GetIndex() == pDestTextNd->Len() )
- { // Insertion at the last position of a textnode (empty or not)
+ if (pDestTextNd->Len() && rPos.nContent.GetIndex() == pDestTextNd->Len())
+ { // Insertion at the last position of a textnode
++aInsPos; // The table will be inserted behind the text node
}
else if( rPos.nContent.GetIndex() )
@@ -4988,27 +4988,18 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
aRg.aEnd--;
}
}
- else if( bCanMoveBack )
- { // Insertion at the first position of a text node. It will not be split, the table
- // will be inserted before the text node.
- // See below, before the SetInsertRange function of the undo object will be called,
- // the CpyPam would be moved to the next content position. This has to be avoided
- // We want to be moved to the table node itself thus we have to set bCanMoveBack
- // and to manipulate pCopyPam.
- bCanMoveBack = false;
- pCopyPam->GetPoint()->nNode--;
- }
+ assert(!bCanMoveBack);
}
pDestTextNd = aInsPos.GetNode().GetTextNode();
if (pEndTextNd)
{
- SwIndex aDestIdx( rPos.nContent );
+ oInsContentIndex.emplace(rPos.nContent);
if( !pDestTextNd )
{
pDestTextNd = pDoc->GetNodes().MakeTextNode( aInsPos,
pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD));
- aDestIdx.Assign( pDestTextNd, 0 );
+ oInsContentIndex->Assign(pDestTextNd, 0);
aInsPos--;
// if we have to insert an extra text node
@@ -5026,7 +5017,7 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
PUSH_NUMRULE_STATE
}
- pEndTextNd->CopyText( pDestTextNd, aDestIdx, SwIndex( pEndTextNd ),
+ pEndTextNd->CopyText(pDestTextNd, *oInsContentIndex, SwIndex(pEndTextNd),
pEnd->nContent.GetIndex() );
// Also copy all format templates
@@ -5080,21 +5071,30 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
bCopyBookmarks = false;
}
+ // init *again* - because CopyWithFlyInFly moved startPos
+ SwPosition startPos(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1),
+ SwIndex(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1).GetNode().GetContentNode()));
// at-char anchors post SplitNode are on index 0 of 2nd node and will
// remain there - move them back to the start (end would also work?)
// ... also for at-para anchors; here start is preferable because
// it's consistent with SplitNode from SwUndoInserts::RedoImpl()
- if (pFlysAtInsPos)
+ if (pFlysAtInsPos
+ && (bCanMoveBack
+ || startPos.nNode.GetNode().IsTextNode()
+ || (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode()
+ && startPos.nNode.GetNode().IsSectionNode()))) // not into table
{
- // init *again* - because CopyWithFlyInFly moved startPos
- SwPosition startPos(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1),
- SwIndex(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1).GetNode().GetContentNode()));
if (bCanMoveBack)
{ // pCopyPam is actually 1 before the copy range so move it fwd
SwPaM temp(*pCopyPam->GetPoint());
temp.Move(fnMoveForward, GoInContent);
startPos = *temp.GetPoint();
}
+ else if (startPos.nNode.GetNode().IsSectionNode())
+ { // probably on top-level start node, so no CheckNodesRange here;
+ GoNextNds(&startPos.nNode, false); // SwFEShell::Paste() deletes node
+ startPos.nContent.Assign(startPos.nNode.GetNode().GetContentNode(), 0);
+ }
assert(startPos.nNode.GetNode().IsContentNode());
SwPosition startPosAtPara(startPos);
startPosAtPara.nContent.Assign(nullptr, 0);
@@ -5155,27 +5155,32 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
}
else // incremented in (!pSttTextNd && pDestTextNd) above
{
- pCopyPam->GetMark()->nContent.Assign(pCopyPam->GetContentNode(false), 0);
+ // assign also content index in this case, see testSectionAnchorCopyTableAtStart
+ assert(oInsContentIndex);
+ assert(oInsContentIndex->GetIdxReg() == aInsPos.GetNode().GetContentNode());
+ pCopyPam->GetMark()->nContent = (*oInsContentIndex);
}
rPos = *pCopyPam->GetMark();
}
else
*pCopyPam->GetMark() = rPos;
- if ( !bAfterTable )
- pCopyPam->Move( fnMoveForward, bCanMoveBack ? GoInContent : GoInNode );
+ if (bCanMoveBack)
+ {
+ pCopyPam->Move(fnMoveForward, GoInContent);
+ }
else
{
pCopyPam->GetPoint()->nNode++;
// Reset the offset to 0 as it was before the insertion
pCopyPam->GetPoint()->nContent.Assign(pCopyPam->GetPoint()->nNode.GetNode().GetContentNode(), 0);
- // If the next node is a start node, then step back: the start node
- // has been copied and needs to be in the selection for the undo
+ // If the next node is a start node, then step back: SetInsertRange()
+ // will add 1 in this case, but that is too much...
if (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode())
pCopyPam->GetPoint()->nNode--;
-
}
+ oInsContentIndex.reset();
pCopyPam->Exchange();
// Also copy all bookmarks
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 3082f4551862..8e8587994c88 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1837,7 +1837,7 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
// If the end of the section is outside the copy range,
// the section node will skipped, not copied!
// If someone want to change this behaviour, he has to adjust the function
- // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
+ // lcl_NonCopyCount() which relies on it.
if( pCurrentNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
{
// copy of the whole section, so create a new SectionNode
diff --git a/sw/source/core/edit/edglss.cxx b/sw/source/core/edit/edglss.cxx
index bad2bb719a86..49683c682371 100644
--- a/sw/source/core/edit/edglss.cxx
+++ b/sw/source/core/edit/edglss.cxx
@@ -235,6 +235,15 @@ bool SwEditShell::CopySelToDoc( SwDoc* pInsDoc )
// but we want to copy the table and the start node before
// the first cell as well.
*aPaM.Start() = SwPosition(*oSelectAll->first);
+ if (SwSectionNode const* pSection = oSelectAll->first->GetSectionNode())
+ {
+ if (aPaM.End()->nNode.GetIndex() < pSection->EndOfSectionIndex())
+ {
+ // include section end so that section is copied
+ aPaM.End()->nNode = *oSelectAll->first->GetNodes()[pSection->EndOfSectionIndex() + 1];
+ aPaM.End()->nContent.Assign(aPaM.End()->nNode.GetNode().GetContentNode(), 0);
+ }
+ }
}
bRet = GetDoc()->getIDocumentContentOperations().CopyRange( aPaM, aPos, /*bCopyAll=*/false, /*bCheckPos=*/true, /*bCopyText=*/false ) || bRet;
}
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index ccbe00c35ca6..a39b7479e669 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1039,9 +1039,24 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bNestedTable )
--aIndexBefore;
+ // copying to the clipboard, the section is inserted
+ // at the start of the nodes, followed by empty text node
+ bool const isSourceSection(aCpyPam.Start()->nNode.GetNode().IsSectionNode()
+ && aCpyPam.End()->nNode.GetIndex() == aCpyPam.Start()->nNode.GetNode().EndOfSectionIndex() + 1
+ && aCpyPam.End()->nNode.GetNode().IsTextNode()
+ && aCpyPam.End()->nNode.GetNode().GetTextNode()->Len() == 0);
+
pClpDoc->getIDocumentContentOperations().CopyRange( aCpyPam, rInsPos, /*bCopyAll=*/false, /*bCheckPos=*/true, /*bCopyText=*/false );
// Note: aCpyPam is invalid now
+ if (isSourceSection
+ && aIndexBefore.GetNode().IsStartNode()
+ && rInsPos.nNode.GetNode().GetTextNode()->Len() == 0)
+ { // if there is an empty text node at the start, it
+ // should be *replaced* by the section, so delete it
+ GetDoc()->getIDocumentContentOperations().DelFullPara(rPaM);
+ }
+
++aIndexBefore;
SwPaM aPaM(SwPosition(aIndexBefore),
SwPosition(rInsPos.nNode));
diff --git a/sw/source/core/undo/untblk.cxx b/sw/source/core/undo/untblk.cxx
index 01561018ec56..8258498b9181 100644
--- a/sw/source/core/undo/untblk.cxx
+++ b/sw/source/core/undo/untblk.cxx
@@ -358,6 +358,10 @@ void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
rPam.GetPoint()->nNode.GetIndex()));
::std::optional<SwNodeIndex> oMvBkwrd = MovePtBackward(rPam);
+ bool const isMoveFlyAnchors(!oMvBkwrd // equivalent to bCanMoveBack
+ || m_pUndoNodeIndex->GetNode().IsTextNode()
+ || (oMvBkwrd->GetNode().IsStartNode()
+ && m_pUndoNodeIndex->GetNode().IsSectionNode()));
// re-insert content again (first detach m_pUndoNodeIndex!)
sal_uLong const nMvNd = m_pUndoNodeIndex->GetIndex();
@@ -371,7 +375,7 @@ void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
// at-char anchors post SplitNode are on index 0 of 2nd node and will
// remain there - move them back to the start (end would also work?)
- if (pFlysAtInsPos)
+ if (pFlysAtInsPos && isMoveFlyAnchors)
{
for (SwFrameFormat * pFly : *pFlysAtInsPos)
{
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx
index a8f91620622c..4b5e16c028e2 100644
--- a/sw/source/core/unocore/unotext.cxx
+++ b/sw/source/core/unocore/unotext.cxx
@@ -2286,12 +2286,6 @@ SwXText::copyText(
// us, even if we have only a single paragraph.
m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, /*bCopyAll=*/false, /*bCheckPos=*/true, /*bCopyText=*/false);
}
- if (!pFirstNode)
- { // the node at rPos was split; get rid of the first empty one so
- // that the pasted table is first
- auto pDelCursor(m_pImpl->m_pDoc->CreateUnoCursor(SwPosition(SwNodeIndex(*GetStartNode(), 1))));
- m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pDelCursor);
- }
}
else
{