sw/inc/crsrsh.hxx                                                 |   18 
 sw/inc/doc.hxx                                                    |    9 
 sw/inc/ndarr.hxx                                                  |    7 
 sw/inc/node.hxx                                                   |    2 
 sw/inc/undobj.hxx                                                 |   12 
 sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt |   15 
 sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt            |   90 ++
 sw/qa/extras/layout/layout.cxx                                    |   66 +
 sw/qa/extras/odfimport/odfimport.cxx                              |    4 
 sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt              |   20 
 sw/qa/extras/uiwriter/data/hiddenSectionsAroundPageBreak.fodt     |   21 
 sw/qa/extras/uiwriter/data/pagebreak-source.fodt                  |  123 +++
 sw/qa/extras/uiwriter/data/pagebreak-target.fodt                  |  129 +++
 sw/qa/extras/uiwriter/data/table-at-end-of-cell.fodt              |  219 ++++++
 sw/qa/extras/uiwriter/uiwriter.cxx                                |  177 ++++
 sw/qa/extras/uiwriter/uiwriter2.cxx                               |   23 
 sw/qa/extras/unowriter/data/tdf134252_onlytable_protected.fodt    |   87 ++
 sw/qa/extras/unowriter/unowriter.cxx                              |   62 +
 sw/source/core/crsr/crsrsh.cxx                                    |  358 
+++++++++-
 sw/source/core/crsr/pam.cxx                                       |    5 
 sw/source/core/crsr/swcrsr.cxx                                    |   17 
 sw/source/core/doc/DocumentContentOperationsManager.cxx           |   97 +-
 sw/source/core/doc/doccorr.cxx                                    |    7 
 sw/source/core/doc/docedt.cxx                                     |    4 
 sw/source/core/docnode/ndsect.cxx                                 |    4 
 sw/source/core/docnode/ndtbl.cxx                                  |  299 
++++----
 sw/source/core/docnode/nodes.cxx                                  |   49 +
 sw/source/core/docnode/section.cxx                                |    7 
 sw/source/core/edit/eddel.cxx                                     |   36 -
 sw/source/core/edit/edglss.cxx                                    |   19 
 sw/source/core/edit/editsh.cxx                                    |    2 
 sw/source/core/frmedt/fecopy.cxx                                  |   35 
 sw/source/core/frmedt/fetab.cxx                                   |    3 
 sw/source/core/inc/UndoTable.hxx                                  |    2 
 sw/source/core/inc/frame.hxx                                      |    2 
 sw/source/core/inc/layfrm.hxx                                     |    1 
 sw/source/core/inc/sectfrm.hxx                                    |    2 
 sw/source/core/inc/txtfrm.hxx                                     |    2 
 sw/source/core/layout/calcmove.cxx                                |   13 
 sw/source/core/layout/findfrm.cxx                                 |    8 
 sw/source/core/layout/flowfrm.cxx                                 |  120 +--
 sw/source/core/layout/frmtool.cxx                                 |   23 
 sw/source/core/layout/ftnfrm.cxx                                  |   10 
 sw/source/core/layout/pagechg.cxx                                 |    5 
 sw/source/core/layout/sectfrm.cxx                                 |   38 +
 sw/source/core/layout/tabfrm.cxx                                  |    6 
 sw/source/core/layout/trvlfrm.cxx                                 |   25 
 sw/source/core/layout/wsfrm.cxx                                   |   12 
 sw/source/core/text/txtfrm.cxx                                    |   15 
 sw/source/core/text/xmldump.cxx                                   |    9 
 sw/source/core/undo/undobj.cxx                                    |   22 
 sw/source/core/undo/unins.cxx                                     |    4 
 sw/source/core/undo/untbl.cxx                                     |    8 
 sw/source/core/undo/untblk.cxx                                    |   12 
 sw/source/core/unocore/unoobj2.cxx                                |   14 
 sw/source/core/unocore/unotbl.cxx                                 |    2 
 sw/source/core/unocore/unotext.cxx                                |    6 
 sw/source/filter/xml/XMLRedlineImportHelper.cxx                   |    5 
 sw/source/uibase/wrtsh/move.cxx                                   |   46 +
 sw/source/uibase/wrtsh/select.cxx                                 |   36 -
 60 files changed, 1993 insertions(+), 481 deletions(-)

New commits:
commit 0a0196bc0fe18449debae5f6353c1ddb312df916
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Mar 4 15:45:07 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu Mar 7 15:14:42 2024 +0100

    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.st...@allotropia.de>
    (cherry picked from commit fcd4222d36e1864452163e5c94976eea353bbaf0)

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/eleme
 nts/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/eleme
 nts/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
     {
commit fa7cdf1777aa063d3b1cf89a75a66e2ed319c4a9
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Mar 18 20:59:36 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu Mar 7 12:57:42 2024 +0100

    Related: tdf#133933 sw: fix assertion failure in the SwIndexReg dtor
    
    Make sure that by the time we delete a text node, no SwIndexes point to
    us.
    
    Change-Id: I9248a2ebe529e5a0aab0e37bf676e669b9bddb1d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112698
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit e782937228479054336b564a4c34697a12530469)

diff --git a/sw/source/core/inc/UndoTable.hxx b/sw/source/core/inc/UndoTable.hxx
index 2b51dbdbb111..8815cb0881c7 100644
--- a/sw/source/core/inc/UndoTable.hxx
+++ b/sw/source/core/inc/UndoTable.hxx
@@ -280,7 +280,7 @@ class SwUndoTableCpyTable : public SwUndo
     //b6341295: When redlining is active, PrepareRedline has to create the
     //redlining attributes for the new and the old table cell content
     static std::unique_ptr<SwUndo> PrepareRedline( SwDoc* pDoc, const 
SwTableBox& rBox,
-                const SwPosition& rPos, bool& rJoin, bool bRedo );
+                SwPosition& rPos, bool& rJoin, bool bRedo );
 
 public:
     SwUndoTableCpyTable(const SwDoc* pDoc);
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 14cc8de03a84..a07d951dc288 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -2517,7 +2517,7 @@ void SwUndoTableCpyTable::RedoImpl(::sw::UndoRedoContext 
& rContext)
                 // Otherwise aInsIdx has been moved during the Undo operation
                 if( pEntry->bJoin )
                 {
-                    SwPaM const& rLastPam =
+                    SwPaM& rLastPam =
                         rContext.GetCursorSupplier().GetCurrentShellCursor();
                     pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(),
                                             pEntry->bJoin, true );
@@ -2632,7 +2632,7 @@ void SwUndoTableCpyTable::AddBoxAfter( const SwTableBox& 
rBox, const SwNodeIndex
 // rJoin is true if Redo() is calling and the content has already been merged
 
 std::unique_ptr<SwUndo> SwUndoTableCpyTable::PrepareRedline( SwDoc* pDoc, 
const SwTableBox& rBox,
-    const SwPosition& rPos, bool& rJoin, bool bRedo )
+    SwPosition& rPos, bool& rJoin, bool bRedo )
 {
     std::unique_ptr<SwUndo> pUndo;
     // b62341295: Redline for copying tables
@@ -2656,6 +2656,10 @@ std::unique_ptr<SwUndo> 
SwUndoTableCpyTable::PrepareRedline( SwDoc* pDoc, const
             if( !bRedo && rPos.nNode.GetNode().GetTextNode() )
             {   // Try to merge, if not called by Redo()
                 rJoin = true;
+
+                // Park this somewhere else so nothing points to the 
to-be-deleted node.
+                rPos.nContent.Assign(pText, 0);
+
                 pText->JoinNext();
             }
         }
commit 126dd55667826f5d1268a570f7e2930b1b78fc43
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Jan 5 12:32:09 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Mar 6 20:39:47 2024 +0100

    tdf#152710 fixes squashed required by testTdf134250
    
    tdf#152710 sw: invalidate SwUnoCursors properly in DeleteRangeImpl()
    
    This crashes with:
    
     list.cxx:44: corrupt document structure, bailing out of infinite loop
     ndtxt.cxx:5437: void SwTextNode::TriggerNodeUpdate(const 
sw::LegacyModifyHint&): Assertion `dynamic_cast<SwTextFormatColl 
const*>(static_cast<const SwFormatChg*>(pOldValue)->pChangedFormat)' failed.
    
    Because the redline from 7 to 9 is deleted, but then some cursor ends up
    on node 10 which is invalid as it is an end node.
    
    [   6] 0x60666a0            StartNode ,
    [   7]  0x61195e0           StartNode ,
    [   8]   0x61197a8           TextNode "tainment",
    [   9]  0x6119670             EndNode ,
    [  10] 0x6066730              EndNode ,
    
    The first problem is that DeleteRangeImpl() uses the point node as the
    target position for PaMCorrAbs(), but in this case the point node will
    be deleted.
    
    PaMCorrAbs() has a check to invalidate SwUnoCursors that would be moved
    out of their parent sections, but due to the first problem it can't
    check it, and the second problem is that lcl_FindUnoCursorSection()
    doesn't work on redline sections, as those have node type
    SwNormalStartNode.
    
    After fixing the invalidation, subsequent access to the SwXTextCursor
    throws exceptions and importing the file fails.
    
    (regression from commit 477e489e71b4a96ff10d9f2d2b802d91dec3e319)
    
    Thanks to Dave Gilbert for identifying the problematic DeleteRange()
    call.
    
    Change-Id: I48a373cc122073b82bc47513fdae684f45b0efb8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145077
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 8e05bdd26f21fc304978ff3b454cf355841ec75f)
    
    tdf#152710 sw: call and fix DeleteSection() instead
    
    Turns out there's a function to delete a complete nodes array section -
    and it has the same problem?  Why does it move indexes only from
    startnode + 1?  Let's try to fix it to be more consistent.
    
    Change-Id: Iedacc10e29c1646c4ccc85e53a479b0351f5cfcc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145078
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 475e59d29b7a6cc7f058af8ff863b3bb1a2a84a5)

diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 1722a52dc312..c6a1dae2a0e2 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -1972,6 +1972,18 @@ DocumentContentOperationsManager::CopyRange( SwPaM& 
rPam, SwPosition& rPos, cons
     return bRet;
 }
 
+static auto GetCorrPosition(SwPaM const& rPam) -> SwPosition
+{
+    // tdf#152710 target position must be on node that survives deletion
+    // so that PaMCorrAbs can invalidate SwUnoCursors properly
+    return rPam.GetPoint()->nNode.GetNode().IsContentNode()
+            ? *rPam.GetPoint()
+            : rPam.GetMark()->nNode.GetNode().IsContentNode()
+                ? *rPam.GetMark()
+                // this would be the result in SwNodes::RemoveNode()
+                : SwPosition(SwNodeIndex(rPam.End()->nNode.GetNode(), +1));
+}
+
 /// Delete a full Section of the NodeArray.
 /// The passed Node is located somewhere in the designated Section.
 void DocumentContentOperationsManager::DeleteSection( SwNode *pNode )
@@ -1989,8 +2001,9 @@ void DocumentContentOperationsManager::DeleteSection( 
SwNode *pNode )
 
     {
         // move all Cursor/StackCursor/UnoCursor out of the to-be-deleted area
-        SwNodeIndex aMvStt( aSttIdx, 1 );
-        SwDoc::CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), true );
+        SwPaM const range(aSttIdx, aEndIdx);
+        SwPosition const pos(GetCorrPosition(range));
+        ::PaMCorrAbs(range, pos);
     }
 
     m_rDoc.GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - 
aSttIdx.GetIndex() + 1 );
@@ -4098,7 +4111,10 @@ bool 
DocumentContentOperationsManager::DeleteRangeImpl(SwPaM & rPam, SwDeleteFla
     // Move all cursors out of the deleted range, but first copy the
     // passed PaM, because it could be a cursor that would be moved!
     SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
-    ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+    {
+        SwPosition const pos(GetCorrPosition(aDelPam));
+        ::PaMCorrAbs(aDelPam, pos);
+    }
 
     bool const bSuccess( DeleteRangeImplImpl(aDelPam, flags) );
     if (bSuccess)
diff --git a/sw/source/core/doc/doccorr.cxx b/sw/source/core/doc/doccorr.cxx
index 8e2769b353e5..a2564119ce06 100644
--- a/sw/source/core/doc/doccorr.cxx
+++ b/sw/source/core/doc/doccorr.cxx
@@ -33,11 +33,14 @@ namespace
     /// returns NULL if no restrictions apply
     const SwStartNode* lcl_FindUnoCursorSection( const SwNode& rNode )
     {
-        const SwStartNode* pStartNode = rNode.StartOfSectionNode();
+        const SwStartNode* pStartNode = rNode.IsStartNode() ? 
rNode.GetStartNode() : rNode.StartOfSectionNode();
         while( ( pStartNode != nullptr ) &&
                ( pStartNode->StartOfSectionNode() != pStartNode ) &&
-               ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
+               // section node is only start node allowing overlapped delete
+               pStartNode->IsSectionNode() )
+        {
             pStartNode = pStartNode->StartOfSectionNode();
+        }
 
         return pStartNode;
     }
diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx 
b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
index 0a0c75bc9816..b42a28eeacb7 100644
--- a/sw/source/filter/xml/XMLRedlineImportHelper.cxx
+++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
@@ -726,9 +726,8 @@ void 
XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo)
         SAL_WARN("sw.xml", "Recursive change tracking, removing");
         // reuse aPaM to remove it from nodes that will be deleted
         *aPaM.GetPoint() = SwPosition(pRedlineInfo->pContentIndex->GetNode());
-        aPaM.SetMark();
-        *aPaM.GetMark() = 
SwPosition(*pRedlineInfo->pContentIndex->GetNode().EndOfSectionNode());
-        pDoc->getIDocumentContentOperations().DeleteRange(aPaM);
+        aPaM.DeleteMark();
+        
pDoc->getIDocumentContentOperations().DeleteSection(&aPaM.GetPoint()->nNode.GetNode());
     }
     else
     {
commit 67679b3c8a1c550dbcc1f9d80b6b3e77a256ff10
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Jan 18 12:35:12 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Mar 6 20:39:47 2024 +0100

    sw: fix ASAN use-after-free in testTdf39721
    
    The problem is that the cursor is positioned somehow on an SwEndNode.
    Then lcl_CursorOk(pNew) is false and it gets deleted immediately.
    
    Change-Id: I1789280a5116da4e5b7739e311b18c5c54074b1f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109541
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit 43fbe2fbd6a65fa63fa819c6778c3378c2ff6e1f)

diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 3814b3175738..85e9eb837017 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -120,6 +120,10 @@ SwPaM * SwCursorShell::CreateCursor()
     // don't create new Cursor with active table Selection
     assert(!IsTableMode());
 
+    // ensure that m_pCurrentCursor is valid; if it's invalid it would be
+    // copied to pNew and then pNew would be deleted in UpdateCursor() below
+    ClearUpCursors();
+
     // New cursor as copy of current one. Add to the ring.
     // Links point to previously created one, ie forward.
     SwShellCursor* pNew = new SwShellCursor( *m_pCurrentCursor );
commit beba56614ddc53d193647c7403be05ff88c50e8c
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Feb 4 12:36:41 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Mar 6 16:06:41 2024 +0100

    sw: fix copying and deleting of table in section via API
    
    This is a follow-up to 7ab349296dac79dad3fec09f60348efcbb9ea17e.
    
    The first problem was that tables that contain protected cells refused
    to be deleted, which caused an infinite loop in
    SwXTextRange::DeleteAndInsert().
    
    This also affected SwXTextTable::dispose(), and DDE tables.
    
    Fix this by forcibly deleting even protected cells from UNO APIs;
    protection is an UI feature.
    
    The second problem was that pasting the table SwFEShell::Paste() would
    set up aCpyPam so that it selects from the start node of the table to
    the last text node in the table, excluding the table cell and table end
    nodes, which caused:
    
    DocumentContentOperationsManager.cxx:3548: An insufficient number of nodes 
were copied!
    
    Fix this by setting up aCpyPam over the entire body section of the
    clipboard document.
    
    Change-Id: I8c6caee5e75260dff79f106efc11f9669feddc0c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110411
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit c598e0accf24e149520a22a8c062249f147844c7)

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 66ec563e7a14..241ae3b656be 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -21,6 +21,7 @@
 
 // SwDoc interfaces
 #include <o3tl/deleter.hxx>
+#include <o3tl/typed_flags_set.hxx>
 #include <vcl/idle.hxx>
 #include "swdllapi.h"
 #include "swtypes.hxx"
@@ -1190,7 +1191,8 @@ public:
 
     // Delete Columns/Rows in table.
     void DelTable(SwTableNode * pTable);
-    bool DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn = false );
+    enum class RowColMode { DeleteRow = 0, DeleteColumn = 1, DeleteProtected = 
2 };
+    bool DeleteRowCol(const SwSelBoxes& rBoxes, RowColMode eMode = 
RowColMode::DeleteRow);
     void DeleteRow( const SwCursor& rCursor );
     void DeleteCol( const SwCursor& rCursor );
 
@@ -1659,6 +1661,10 @@ private:
 
 };
 
+namespace o3tl {
+    template<> struct typed_flags<SwDoc::RowColMode> : 
is_typed_flags<SwDoc::RowColMode, 3> {};
+}
+
 // This method is called in Dtor of SwDoc and deletes cache of ContourObjects.
 void ClrContourCache();
 
diff --git a/sw/qa/extras/unowriter/data/tdf134252_onlytable_protected.fodt 
b/sw/qa/extras/unowriter/data/tdf134252_onlytable_protected.fodt
new file mode 100644
index 000000000000..f588fdba0515
--- /dev/null
+++ b/sw/qa/extras/unowriter/data/tdf134252_onlytable_protected.fodt
@@ -0,0 +1,87 @@
+<?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:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 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:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing: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:ooo="http://openoffice.org/2004/office"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d: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:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
 xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur
 n:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:xforms="http://www.w3.org/2002/xforms"; 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"/>
+  <style:font-face style:name="Lohit Devanagari" svg:font-family="&apos;Lohit 
Devanagari&apos;" style:font-family-generic="system" 
style:font-pitch="variable"/>
+  <style:font-face style:name="Source Han Serif CN" 
svg:font-family="&apos;Source Han Serif CN&apos;" 
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" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="de" fo:country="DE" style:letter-kerning="true" 
style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Lohit 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" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="de" fo:country="DE" style:letter-kerning="true" 
style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Lohit 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: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="Table1" style:family="table">
+   <style:table-properties style:width="17cm" table:align="margins"/>
+  </style:style>
+  <style:style style:name="Table1.A" style:family="table-column">
+   <style:table-column-properties style:column-width="17cm" 
style:rel-column-width="65535*"/>
+  </style:style>
+  <style:style style:name="Table1.A1" style:family="table-cell">
+   <style:table-cell-properties fo:padding="0.097cm" fo:border="0.05pt solid 
#000000"/>
+  </style:style>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties officeooo:rsid="00078615" 
officeooo:paragraph-rsid="00078615"/>
+  </style:style>
+  <style:style style:name="P3" style:family="paragraph" 
style:parent-style-name="Table_20_Contents">
+   <style:text-properties officeooo:rsid="00095b34" 
officeooo:paragraph-rsid="00095b34"/>
+  </style:style>
+  <style:style style:name="Sect1" style:family="section">
+   <style:section-properties fo:background-color="#81d41a" 
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="Section1">
+    <table:table table:name="Table1" table:style-name="Table1">
+     <table:table-column table:style-name="Table1.A"/>
+     <table:table-row>
+      <table:table-cell table:style-name="Table1.A1" 
office:value-type="string" table:protected="true">
+       <text:p text:style-name="P3">baz</text:p>
+      </table:table-cell>
+     </table:table-row>
+    </table:table>
+   </text:section>
+   <text:p text:style-name="P1">foo</text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/unowriter/unowriter.cxx 
b/sw/qa/extras/unowriter/unowriter.cxx
index 985d1171ac4d..a935128bac23 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -9,6 +9,7 @@
 
 #include <swmodeltestbase.hxx>
 #include <com/sun/star/awt/FontSlant.hpp>
+//#include <com/sun/star/datatransfer/XTransferableTextSupplier.hpp>
 #include <com/sun/star/table/XCellRange.hpp>
 #include <com/sun/star/text/TextContentAnchorType.hpp>
 #include <com/sun/star/text/AutoTextContainer.hpp>
@@ -358,6 +359,67 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testXAutoTextGroup)
     xAutoTextContainer->removeByName(sGroupName);
 }
 
+#if 0
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testSectionAnchorCopyTable)
+{
+    // this contains a section that ends with a table (plus another section)
+    load(DATA_DIRECTORY, "tdf134252_onlytable_protected.fodt");
+
+    uno::Reference<text::XTextTablesSupplier> const 
xTextTablesSupplier(mxComponent,
+                                                                        
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> const 
xTables(xTextTablesSupplier->getTextTables(),
+                                                          uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    uno::Reference<text::XTextSectionsSupplier> const 
xTextSectionsSupplier(mxComponent,
+                                                                            
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> const xSections(
+        xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+
+    uno::Reference<text::XTextContent> const 
xSection(xSections->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> const xAnchor(xSection->getAnchor());
+    CPPUNIT_ASSERT_EQUAL(OUString("baz" SAL_NEWLINE_STRING), 
xAnchor->getString());
+
+    // copy the content of the section to a clipboard document
+    uno::Reference<datatransfer::XTransferableSupplier> const xTS(
+        uno::Reference<frame::XModel>(mxComponent, 
uno::UNO_QUERY_THROW)->getCurrentController(),
+        uno::UNO_QUERY);
+    uno::Reference<datatransfer::XTransferableTextSupplier> const xTTS(xTS, 
uno::UNO_QUERY);
+    uno::Reference<datatransfer::XTransferable> const xTransferable(
+        xTTS->getTransferableForTextRange(xAnchor));
+
+    // check this doesn't throw
+    CPPUNIT_ASSERT(xAnchor->getStart().is());
+    CPPUNIT_ASSERT(xAnchor->getEnd().is());
+
+    // replace section content
+    xAnchor->setString("quux");
+
+    // table in section was deleted, but not section itself
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("\""
+                                  "quux" /*SAL_NEWLINE_STRING*/ "\""),
+                         OUString("\"" + xAnchor->getString() + "\""));
+
+    // now paste it
+    uno::Reference<text::XTextViewCursorSupplier> const xTVCS(xTS, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextViewCursor> const 
xCursor(xTVCS->getViewCursor());
+    xCursor->gotoEnd(false);
+    xTS->insertTransferable(xTransferable);
+
+    // table in section was pasted, but not section itself
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
+    xCursor->gotoStart(true);
+    CPPUNIT_ASSERT_EQUAL(
+        OUString("quux" SAL_NEWLINE_STRING "foo" SAL_NEWLINE_STRING "baz" 
SAL_NEWLINE_STRING),
+        xCursor->getString());
+}
+#endif
+
 CPPUNIT_TEST_FIXTURE(SwUnoWriter, testXURI)
 {
     uno::Reference<uno::XComponentContext> 
xContext(::comphelper::getProcessComponentContext());
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 379c0a7666be..71874cd24a0d 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -1929,7 +1929,7 @@ void SwDoc::DeleteCol( const SwCursor& rCursor )
 
     // Thus delete the Columns
     GetIDocumentUndoRedo().StartUndo(SwUndoId::COL_DELETE, nullptr);
-    DeleteRowCol( aBoxes, true );
+    DeleteRowCol(aBoxes, SwDoc::RowColMode::DeleteColumn);
     GetIDocumentUndoRedo().EndUndo(SwUndoId::COL_DELETE, nullptr);
 }
 
@@ -2093,18 +2093,24 @@ void SwDoc::DelTable(SwTableNode *const pTableNd)
     getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
 }
 
-bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
+bool SwDoc::DeleteRowCol(const SwSelBoxes& rBoxes, RowColMode const eMode)
 {
-    if( ::HasProtectedCells( rBoxes ))
+    if (!(eMode & SwDoc::RowColMode::DeleteProtected)
+        && ::HasProtectedCells(rBoxes))
+    {
         return false;
+    }
 
     OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
     SwTableNode* pTableNd = 
const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
     if( !pTableNd )
         return false;
 
-    if( dynamic_cast<const SwDDETable*>( &pTableNd->GetTable() ) !=  nullptr)
+    if (!(eMode & SwDoc::RowColMode::DeleteProtected)
+        && dynamic_cast<const SwDDETable*>(&pTableNd->GetTable()) != nullptr)
+    {
         return false;
+    }
 
     ::ClearFEShellTabCols(*this, nullptr);
     SwSelBoxes aSelBoxes( rBoxes );
@@ -2113,7 +2119,7 @@ bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool 
bColumn )
     long nMax = 0;
     if( rTable.IsNewModel() )
     {
-        if( bColumn )
+        if (eMode & SwDoc::RowColMode::DeleteColumn)
             rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax );
         else
             rTable.FindSuperfluousRows( aSelBoxes );
@@ -2147,7 +2153,7 @@ bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool 
bColumn )
 
         if (rTable.IsNewModel())
         {
-            if (bColumn)
+            if (eMode & SwDoc::RowColMode::DeleteColumn)
                 rTable.PrepareDeleteCol( nMin, nMax );
             rTable.FindSuperfluousRows( aSelBoxes );
             if (pUndo)
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 8589b8eed579..ccbe00c35ca6 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -686,25 +686,19 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bNestedTable )
     OSL_ENSURE( pClpDoc, "no clipboard document"  );
     // then till end of the nodes array
     SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
-    SwPaM aCpyPam( aIdx ); //DocStart
+    // select content section, whatever it may contain
+    SwPaM aCpyPam(aIdx, SwNodeIndex(pClpDoc->GetNodes().GetEndOfContent(), 
-1));
+    if (SwContentNode *const pAtEnd = aCpyPam.GetNode(true).GetContentNode())
+    {
+        pAtEnd->MakeEndIndex(&aCpyPam.GetPoint()->nContent);
+    }
 
     // If there are table formulas in the area, then display the table first
     // so that the table formula can calculate a new value first
     // (individual boxes in the area are retrieved via the layout)
     SwFieldType* pTableFieldTyp = 
GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table );
 
-    SwTableNode *const pSrcNd = aCpyPam.GetNode().GetTableNode();
-    if( !pSrcNd )                               // table node ?
-    {                                           // don't skip !!
-        SwContentNode* pCNd = aCpyPam.GetNode().GetContentNode();
-        if( pCNd )
-            aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 );
-        else if( !aCpyPam.Move( fnMoveForward, GoInNode ))
-            aCpyPam.Move( fnMoveBackward, GoInNode );
-    }
-
-    aCpyPam.SetMark();
-    aCpyPam.Move( fnMoveForward, GoInDoc );
+    SwTableNode *const pSrcNd = aCpyPam.GetNode(false).GetTableNode();
 
     bool bRet = true;
     StartAllAction();
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
index 1dec2e3102a6..936ababfaea4 100644
--- a/sw/source/core/frmedt/fetab.cxx
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -296,9 +296,8 @@ bool SwFEShell::DeleteCol()
 
         // then delete the column
         StartUndo(SwUndoId::COL_DELETE);
-        bRet = GetDoc()->DeleteRowCol( aBoxes, true );
+        bRet = GetDoc()->DeleteRowCol(aBoxes, SwDoc::RowColMode::DeleteColumn);
         EndUndo(SwUndoId::COL_DELETE);
-
     }
     else
         bRet = false;
diff --git a/sw/source/core/unocore/unoobj2.cxx 
b/sw/source/core/unocore/unoobj2.cxx
index 62180c0bc230..53c881a8400a 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -790,6 +790,20 @@ void SwXTextRange::SetPositions(const SwPaM& rPam)
     m_pImpl->SetMark(*pMark);
 }
 
+#if 0
+static void DeleteTable(SwDoc & rDoc, SwTable& rTable)
+{
+    SwSelBoxes aSelBoxes;
+    for (auto& rBox : rTable.GetTabSortBoxes())
+    {
+        aSelBoxes.insert(rBox);
+    }
+    // note: if the table is the content in the section, this will create
+    // a new text node - that's desirable here
+    rDoc.DeleteRowCol(aSelBoxes, SwDoc::RowColMode::DeleteProtected);
+}
+#endif
+
 void SwXTextRange::DeleteAndInsert(
         const OUString& rText, ::sw::DeleteAndInsertMode const eMode)
 {
diff --git a/sw/source/core/unocore/unotbl.cxx 
b/sw/source/core/unocore/unotbl.cxx
index fa378c7e8ae1..f149c3a4ce16 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -2227,7 +2227,7 @@ void SwXTextTable::dispose()
     SwSelBoxes aSelBoxes;
     for(auto& rBox : pTable->GetTabSortBoxes() )
         aSelBoxes.insert(rBox);
-    pFormat->GetDoc()->DeleteRowCol(aSelBoxes);
+    pFormat->GetDoc()->DeleteRowCol(aSelBoxes, 
SwDoc::RowColMode::DeleteProtected);
 }
 
 void SAL_CALL SwXTextTable::addEventListener(
commit daeb75e6e3f5a3534665ac2cc15f6bcc12bc9fdb
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Feb 14 19:22:42 2024 +0600
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Mar 4 11:04:22 2024 +0100

    tdf#159565: make sure to handle leading hidden section correctly
    
    Change-Id: I41c7d2b6e765f03c72a968fd05e8de7047f1ce41
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163371
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163478
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit a0485be018a68c96329a2fd30d59cdf07cb36363)

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 52f82a6b9caf..cfeac8305f82 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -327,7 +327,7 @@ public:
     void ExtendedSelectAll(bool bFootnotes = true);
     /// If ExtendedSelectAll() was called and selection didn't change since 
then.
     ::std::optional<::std::pair<SwNode const*, ::std::vector<SwTableNode*>>> 
ExtendedSelectedAll() const;
-    enum class StartsWith { None, Table, HiddenPara };
+    enum class StartsWith { None, Table, HiddenPara, HiddenSection };
     /// If document body starts with a table or starts/ends with hidden 
paragraph.
     StartsWith StartsWith_();
 
diff --git a/sw/inc/ndarr.hxx b/sw/inc/ndarr.hxx
index 7504a283fdf3..8b635f9f4778 100644
--- a/sw/inc/ndarr.hxx
+++ b/sw/inc/ndarr.hxx
@@ -133,6 +133,11 @@ class SW_DLLPUBLIC SwNodes final
 
     SwNodes( SwDoc* pDoc );
 
+    // Returns start of the document section 
(PostIts/Inserts/Autotext/Redlines/Content),
+    // or of a specific fly / header / footer / footnote, where this node is, 
which must not
+    // be crossed when moving backwards
+    sal_uLong StartOfGlobalSection(const SwNode& node) const;
+
 public:
     ~SwNodes();
 
@@ -188,7 +193,7 @@ public:
     static void GoEndOfSection(SwNodeIndex *);
 
     SwContentNode* GoNext(SwNodeIndex *) const;
-    static SwContentNode* GoPrevious(SwNodeIndex *);
+    static SwContentNode* GoPrevious(SwNodeIndex *, bool canCrossBoundary = 
false);
 
     /** Go to next content-node that is not protected or hidden
        (Both set FALSE ==> GoNext/GoPrevious!!!). */
diff --git a/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt 
b/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt
new file mode 100644
index 000000000000..2095c7173046
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/FrameInHiddenSection.fodt
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:section text:name="Section1">
+    <text:section text:name="Section2Hidden" text:display="none">
+     <text:p><draw:frame text:anchor-type="paragraph" svg:x="1cm" svg:y="1cm" 
svg:width="1cm">
+      <draw:text-box/>
+     </draw:frame>lorem</text:p>
+    </text:section>
+    <text:section text:name="Section3"/>
+    <text:section text:name="Section4"/>
+    <text:section text:name="Section5">
+     <text:p>ipsum</text:p>
+    </text:section>
+   </text:section>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx 
b/sw/qa/extras/uiwriter/uiwriter.cxx
index 23444c5093b3..beb7fc718d80 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -94,11 +94,13 @@
 #include <com/sun/star/util/XPropertyReplace.hpp>
 #include <com/sun/star/beans/PropertyAttribute.hpp>
 #include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
 #include <com/sun/star/text/TextMarkupType.hpp>
 #include <com/sun/star/chart2/data/XDataSource.hpp>
 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
 #include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
 #include <o3tl/cppunittraitshelper.hxx>
 #include <o3tl/deleter.hxx>
 #include <osl/file.hxx>
@@ -8205,6 +8207,25 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest, 
testHiddenSectionsAroundPageBreak)
     CPPUNIT_ASSERT_EQUAL(OUString("Landscape"), getProperty<OUString>(xCursor, 
"PageStyleName"));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf159565)
+{
+    // Given a document with a hidden section in the beginning, additionally 
containing a frame
+    createDoc("FrameInHiddenSection.fodt");
+
+    lcl_dispatchCommand(mxComponent, u".uno:SelectAll", {});
+
+    // Check that the selection covers the whole visible text
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<view::XSelectionSupplier> 
xSelSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xSelections(xSelSupplier->getSelection(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSelections->getCount());
+    uno::Reference<text::XTextRange> xSelection(xSelections->getByIndex(0), 
uno::UNO_QUERY);
+
+    // Without the fix, this would fail - there was no selection
+    CPPUNIT_ASSERT_EQUAL(OUString(u"" SAL_NEWLINE_STRING SAL_NEWLINE_STRING 
"ipsum"),
+                         xSelection->getString());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 4eb56af09887..3814b3175738 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -758,6 +758,8 @@ static typename SwCursorShell::StartsWith 
StartsWith(SwStartNode const& rStart)
         switch (rNode.GetNodeType())
         {
             case SwNodeType::Section:
+                if (rNode.GetSectionNode()->GetSection().IsHidden())
+                    return SwCursorShell::StartsWith::HiddenSection;
                 continue;
             case SwNodeType::Table:
                 return SwCursorShell::StartsWith::Table;
@@ -782,11 +784,16 @@ static typename SwCursorShell::StartsWith 
EndsWith(SwStartNode const& rStart)
         switch (rNode.GetNodeType())
         {
             case SwNodeType::End:
-                if (rNode.StartOfSectionNode()->IsTableNode())
+                if (auto pStartNode = rNode.StartOfSectionNode(); 
pStartNode->IsTableNode())
                 {
                     return SwCursorShell::StartsWith::Table;
                 }
-//TODO buggy SwUndoRedline in testTdf137503?                
assert(rNode.StartOfSectionNode()->IsSectionNode());
+                else if (pStartNode->IsSectionNode())
+                {
+                    if (pStartNode->GetSectionNode()->GetSection().IsHidden())
+                        return SwCursorShell::StartsWith::HiddenSection;
+                }
+                    //TODO buggy SwUndoRedline in testTdf137503?               
 assert(rNode.StartOfSectionNode()->IsSectionNode());
             break;
             case SwNodeType::Text:
                 if (rNode.GetTextNode()->IsHidden())
@@ -3401,7 +3408,7 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
         GetDoc()->GetDocShell()->IsReadOnlyUI() )
         return true;
 
-    if( m_pCurrentCursor->HasMark() )
+    if( m_pCurrentCursor->HasMark() && !mbSelectAll )
         ClearMark();
 
     // first check for frames
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 985b5ffe75a8..f8b0213a67cc 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -888,7 +888,7 @@ static bool lcl_MakeSelFwrd( const SwNode& rSttNd, const 
SwNode& rEndNd,
 
     rPam.SetMark();
     rPam.GetPoint()->nNode = rEndNd;
-    pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode );
+    pCNd = SwNodes::GoPrevious(&rPam.GetPoint()->nNode, true);
     if( !pCNd )
         return false;
     pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
@@ -908,7 +908,7 @@ static bool lcl_MakeSelBkwrd( const SwNode& rSttNd, const 
SwNode& rEndNd,
     if( !bFirst )
     {
         rPam.GetPoint()->nNode = rSttNd;
-        pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode );
+        pCNd = SwNodes::GoPrevious(&rPam.GetPoint()->nNode, true);
         if( !pCNd )
             return false;
         pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index afa730df9a27..3082f4551862 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1295,17 +1295,49 @@ SwContentNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
     return static_cast<SwContentNode*>(pNd);
 }
 
-SwContentNode* SwNodes::GoPrevious(SwNodeIndex *pIdx)
+sal_uLong SwNodes::StartOfGlobalSection(const SwNode& node) const
+{
+    const sal_uLong pos = node.GetIndex();
+    if (GetEndOfExtras().GetIndex() < pos)
+        // Regular ContentSection
+        return GetEndOfExtras().GetIndex() + sal_uLong(1);
+    if (GetEndOfAutotext().GetIndex() < pos)
+        // Redlines
+        return GetEndOfAutotext().GetIndex() + sal_uLong(1);
+    if (GetEndOfInserts().GetIndex() < pos)
+    {
+        // Flys/Headers/Footers
+        if (auto* p = node.FindFlyStartNode())
+            return p->GetIndex();
+        if (auto* p = node.FindHeaderStartNode())
+            return p->GetIndex();
+        if (auto* p = node.FindFooterStartNode())
+            return p->GetIndex();
+        return GetEndOfInserts().GetIndex() + sal_uLong(1);
+    }
+    if (GetEndOfPostIts().GetIndex() < pos)
+    {
+        // Footnotes
+        if (auto* p = node.FindFootnoteStartNode())
+            return p->GetIndex();
+        return GetEndOfPostIts().GetIndex() + sal_uLong(1);
+    }
+    return sal_uLong(0);
+}
+
+SwContentNode* SwNodes::GoPrevious(SwNodeIndex* pIdx, bool canCrossBoundary)
 {
     if( !pIdx->GetIndex() )
         return nullptr;
 
     SwNodeIndex aTmp( *pIdx, -1 );
+    sal_uLong aGlobalStart(
+        canCrossBoundary ? sal_uLong(0) : 
aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
     SwNode* pNd = nullptr;
-    while( aTmp.GetIndex() && !( pNd = &aTmp.GetNode())->IsContentNode() )
+    while (aTmp > aGlobalStart && !(pNd = &aTmp.GetNode())->IsContentNode())
         --aTmp;
 
-    if( !aTmp.GetIndex() )
+    if (aTmp <= aGlobalStart)
         pNd = nullptr;
     else
         (*pIdx) = aTmp;
@@ -1985,8 +2017,9 @@ SwContentNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
 {
     bool bFirst = true;
     SwNodeIndex aTmp( *pIdx );
+    sal_uLong 
aGlobalStart(aTmp.GetNodes().StartOfGlobalSection(pIdx->GetNode()));
     const SwNode* pNd;
-    while( aTmp > 0 )
+    while (aTmp > aGlobalStart)
     {
         pNd = & aTmp.GetNode();
         if (SwNodeType::End == pNd->GetNodeType())
commit f19d133bf4f07e46eb9ae40865cfc9be46af35af
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Feb 9 11:56:19 2024 +0600
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Mar 4 11:04:22 2024 +0100

    tdf#159565 prerequisite: make hidden sections have zero-height frames
    
    As mentioned in commit bb733957dd39e6f0b9d80bb59eb0177188794797 (tdf#114973
    sw: enable SelectAll with hidden para at start/end, 2023-01-27), the hidden
    sections didn't have frames. That prevented correct handling of the case
    when such a frame was in the beginning of the document.
    
    This change re-implements the hidden section to use 0-height frames, like
    hidden paragraphs, as a pre-requisite for a follow-up change.
    
    Some layout breakages noticed while working on this are unit-tested now.
    
    This change needed to handle the case when the first section is hidden, and
    then goes a page break with page style. In this case, the page style must
    apply to the very first page of the document. Implementing this now, when
    the frame that defines the page style is not the first in the document, I
    accidentally fixed also the previously broken case when the first paragraph
    was hidden. Now the page style defined in the second paragraph's page break
    will apply correctly.
    
    This change makes hidden sections break outer section's frames. This means
    that when text borders are shown, there will be an artifact in the place of
    the hidden sections (a horizontal line breaking outer frame). I suppose
    it's not a problem, actually helping to see the layout better, so in line
    with the "show text borders" helper functionality. If this proves to be
    problematic, this can be handled specially in a follow-up.
    
    [backport: move invalidations from SwSectionFrame::SwClientNotify() to
     SwSectionFrame::Modify()]
    
    Change-Id: I14ebf0559b463186aba28902cd10c5cc978ba456
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163151
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163477
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit ff7f1b59e22092d8548459e75fe912db852f056f)

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 26e6895e88cd..52f82a6b9caf 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -260,7 +260,7 @@ private:
     SAL_DLLPRIVATE bool LRMargin( bool, bool bAPI = false );
     SAL_DLLPRIVATE bool IsAtLRMargin( bool, bool bAPI = false ) const;
 
-    SAL_DLLPRIVATE bool isInHiddenTextFrame(SwShellCursor* pShellCursor);
+    SAL_DLLPRIVATE bool isInHiddenFrame(SwShellCursor* pShellCursor);
 
     SAL_DLLPRIVATE bool GoStartWordImpl();
     SAL_DLLPRIVATE bool GoEndWordImpl();
diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index d12e06d3e950..f4067cd57c4b 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -541,7 +541,7 @@ public:
     const SwSection& GetSection() const { return *m_pSection; }
           SwSection& GetSection()       { return *m_pSection; }
 
-    SwFrame *MakeFrame( SwFrame* );
+    SwFrame* MakeFrame(SwFrame* pSib, bool bHidden);
 
     /** Creates the frms for the SectionNode (i.e. the SectionFrames).
        On default the frames are created until the end of the range.
diff --git a/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt 
b/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt
new file mode 100644
index 000000000000..fbefc5c48046
--- /dev/null
+++ b/sw/qa/extras/layout/data/largeTopMarginAndHiddenFirstSection.fodt
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text">
+   <style:paragraph-properties fo:margin-top="1in" fo:margin-bottom="0" 
style:contextual-spacing="false" fo:line-height="12pt"/>
+  </style:style>
+ </office:styles>
+ <office:body>
+  <office:text>
+   <text:section text:name="Hidden" text:display="none"/>
+   <text:section text:name="Shown"/>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt 
b/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt
new file mode 100644
index 000000000000..5fae6a491704
--- /dev/null
+++ b/sw/qa/extras/layout/data/pageBreakInHiddenSection.fodt
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:master-page-name="Landscape">
+   <style:paragraph-properties style:page-number="1"/>
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph" 
style:master-page-name="Landscape">
+   <style:paragraph-properties style:page-number="1"/>
+   <style:text-properties text:display="none"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <text:p>First line</text:p>
+   <text:section text:name="Hidden" text:display="none">
+    <text:p text:style-name="P1"/>
+   </text:section>
+   <text:section text:name="Shown">
+    <text:p>Before break (still first page)</text:p>
+   </text:section>
+   <text:section text:name="HiddenText">
+    <text:p text:style-name="P2"/>
+   </text:section>
+   <text:p>After break</text:p>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
+   <text:p/>
-e 
... etc. - the rest is truncated

Reply via email to