summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2020-11-20 17:16:35 +0100
committerMichael Stahl <Michael.Stahl@cib.de>2020-11-24 17:39:07 +0100
commit6471d88cb8b61741c51499ac579dd16cb5b67ebf (patch)
tree7847e05480d21b7319a4ca983b9caa5eb93fc316
parent1fe6d2b4f92ed3504cbe3223cf8bb494b0bfc636 (diff)
sw: fix copying and deleting of section content via API
The problem happens if a section starts or ends with a table: SwXTextSection::getAnchor() may return a SwXTextRange with one position in a table cell and another position in a different table cell, or outside the table, neither of which is valid to set the cursor via SwXTextViewCurosor::gotoRange(). Introduce a new special mode for SwXTextRange, RANGE_IS_SECTION, analogous to RANGE_IS_TABLE but actually working. Only SwXTextView can be used to create XTransferables, and it requires selecting first via either the SwXTextViewCursor or select(). It's currently not possible to select the content of a section in the ViewShell in these problematic cases, and would be some effort to add. So add a new interface XTransferableTextSupplier that can be used to create XTransferable from the SwXTextRange with RANGE_IS_SECTION. The core CopyRange() and DeleteRange() functions can deal with SwPaMs that start or end in non-text-nodes, so pass the whole section content to these in SwXTextRange::setString() and in SwXTextView::getTransferableFromTextRange(). Change-Id: If7e3210e8a26f5618317c294f2b2f3ed5c217f1c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106293 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@cib.de> (cherry picked from commit 7ab349296dac79dad3fec09f60348efcbb9ea17e)
-rw-r--r--offapi/UnoApi_offapi.mk1
-rw-r--r--offapi/com/sun/star/datatransfer/XTransferableTextSupplier.idl44
-rw-r--r--sw/inc/unotextrange.hxx16
-rw-r--r--sw/qa/extras/unowriter/data/tdf134250.fodt86
-rw-r--r--sw/qa/extras/unowriter/data/tdf134252.fodt95
-rw-r--r--sw/qa/extras/unowriter/unowriter.cxx122
-rw-r--r--sw/source/core/unocore/unoobj2.cxx163
-rw-r--r--sw/source/core/unocore/unosect.cxx25
-rw-r--r--sw/source/core/unocore/unotbl.cxx3
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx91
-rw-r--r--sw/source/uibase/inc/swdtflvr.hxx2
-rw-r--r--sw/source/uibase/inc/unotxvw.hxx5
-rw-r--r--sw/source/uibase/uno/unotxvw.cxx29
13 files changed, 645 insertions, 37 deletions
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 12ab8e2057e9..5e8834e79a91 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2129,6 +2129,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/datatransfer,\
XTransferableEx \
XTransferableSource \
XTransferableSupplier \
+ XTransferableTextSupplier \
))
$(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/datatransfer/clipboard,\
ClipboardEvent \
diff --git a/offapi/com/sun/star/datatransfer/XTransferableTextSupplier.idl b/offapi/com/sun/star/datatransfer/XTransferableTextSupplier.idl
new file mode 100644
index 000000000000..7d91ec9f0c41
--- /dev/null
+++ b/offapi/com/sun/star/datatransfer/XTransferableTextSupplier.idl
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef __com_sun_star_datatransfer_XTransferableTextSupplier_idl__
+#define __com_sun_star_datatransfer_XTransferableTextSupplier_idl__
+
+#include <com/sun/star/datatransfer/XTransferable.idl>
+#include <com/sun/star/text/XTextRange.idl>
+
+
+module com { module sun { module star { module datatransfer {
+
+/** @since LO 7.2
+ */
+interface XTransferableTextSupplier
+{
+ /** Provide access to a transferable representation of a given text
+ range.
+
+ @param xRange a text range known to the supplier.
+
+ @returns
+ a transferable object representing the given text range.
+
+ @see com::sun::star::datatransfer::XTransferable
+ */
+ XTransferable getTransferableForTextRange(
+ [in] com::sun::star::text::XTextRange xRange);
+
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/unotextrange.hxx b/sw/inc/unotextrange.hxx
index 41a69049fc5e..471a9ae8bc3e 100644
--- a/sw/inc/unotextrange.hxx
+++ b/sw/inc/unotextrange.hxx
@@ -55,10 +55,16 @@ public:
namespace sw {
+ enum class TextRangeMode {
+ RequireTextNode,
+ AllowNonTextNode
+ };
+
void DeepCopyPaM(SwPaM const & rSource, SwPaM & rTarget);
SW_DLLPUBLIC bool XTextRangeToSwPaM(SwUnoInternalPaM& rToFill,
- const css::uno::Reference< css::text::XTextRange > & xTextRange);
+ const css::uno::Reference<css::text::XTextRange> & xTextRange,
+ TextRangeMode eMode = TextRangeMode::RequireTextNode);
css::uno::Reference< css::text::XText >
CreateParentXText(SwDoc & rDoc, const SwPosition& rPos);
@@ -95,6 +101,7 @@ private:
RANGE_IN_TEXT, // "ordinary" css::text::TextRange
RANGE_IN_CELL, // position created with a cell that has no uno object
RANGE_IS_TABLE, // anchor of a table
+ RANGE_IS_SECTION, // anchor of a section
};
void SetPositions(SwPaM const& rPam);
@@ -112,11 +119,14 @@ public:
const css::uno::Reference< css::text::XText > & xParent,
const enum RangePosition eRange = RANGE_IN_TEXT);
// only for RANGE_IS_TABLE
- SwXTextRange(SwFrameFormat& rTableFormat);
+ SwXTextRange(SwTableFormat& rTableFormat);
+ // only for RANGE_IS_SECTION
+ SwXTextRange(SwSectionFormat& rSectionFormat);
const SwDoc& GetDoc() const;
SwDoc& GetDoc();
- bool GetPositions(SwPaM & rToFill) const;
+ bool GetPositions(SwPaM & rToFill,
+ ::sw::TextRangeMode eMode = ::sw::TextRangeMode::RequireTextNode) const;
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(
SwDoc & rDoc,
diff --git a/sw/qa/extras/unowriter/data/tdf134250.fodt b/sw/qa/extras/unowriter/data/tdf134250.fodt
new file mode 100644
index 000000000000..86aaa140c9e7
--- /dev/null
+++ b/sw/qa/extras/unowriter/data/tdf134250.fodt
@@ -0,0 +1,86 @@
+<?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="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.2" 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"/>
+ <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+ <style:paragraph-properties fo:orphans="0" fo:widows="0" text:number-lines="false" text:line-number="0"/>
+ </style: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="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="001fe5a9" officeooo:paragraph-rsid="001fe5a9"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Table_20_Contents">
+ <style:text-properties officeooo:rsid="001fe5a9" officeooo:paragraph-rsid="001fe5a9"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
+ </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: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">
+ <text:p text:style-name="P2">foo</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ <text:p text:style-name="P1">b<text:span text:style-name="T1">a</text:span><text:bookmark text:name="Bookmark 1"/>r</text:p>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/unowriter/data/tdf134252.fodt b/sw/qa/extras/unowriter/data/tdf134252.fodt
new file mode 100644
index 000000000000..6e19ac847dd8
--- /dev/null
+++ b/sw/qa/extras/unowriter/data/tdf134252.fodt
@@ -0,0 +1,95 @@
+<?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="urn: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:style style:name="Sect2" 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: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">
+ <text:p text:style-name="P1">bar</text:p>
+ <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">
+ <text:p text:style-name="P3">baz</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ </text:section>
+ <text:section text:style-name="Sect2" text:name="Section2">
+ <text:p text:style-name="P1">foo</text:p>
+ </text:section>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx
index a265bb29e728..4a23082ccc74 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -9,6 +9,8 @@
#include <swmodeltestbase.hxx>
#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/datatransfer/XTransferableSupplier.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 +360,126 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testXAutoTextGroup)
xAutoTextContainer->removeByName(sGroupName);
}
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testSectionAnchorCopyTableAtStart)
+{
+ // this contains a section that starts with a table
+ load(DATA_DIRECTORY, "tdf134250.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("foo" SAL_NEWLINE_STRING "bar"), 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 "bar"),
+ xCursor->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testSectionAnchorCopyTableAtEnd)
+{
+ // this contains a section that ends with a table (plus another section)
+ load(DATA_DIRECTORY, "tdf134252.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(2), 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("bar" SAL_NEWLINE_STRING "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(2), 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(2), xSections->getCount());
+ // note: this selects the 2nd section because it calls StartOfSection()
+ // not SttEndDoc() like it should?
+ xCursor->gotoStart(true);
+ CPPUNIT_ASSERT_EQUAL(OUString(/*"quux" SAL_NEWLINE_STRING */
+ "foobar" SAL_NEWLINE_STRING "baz" SAL_NEWLINE_STRING),
+ xCursor->getString());
+}
+
CPPUNIT_TEST_FIXTURE(SwUnoWriter, testXURI)
{
uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx
index a425f8a30670..718f977b5345 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -687,20 +687,23 @@ public:
const enum RangePosition m_eRangePosition;
SwDoc& m_rDoc;
uno::Reference<text::XText> m_xParentText;
- const SwFrameFormat* m_pTableFormat;
+ const SwFrameFormat* m_pTableOrSectionFormat;
const ::sw::mark::IMark* m_pMark;
Impl(SwDoc& rDoc, const enum RangePosition eRange,
- SwFrameFormat* const pTableFormat,
+ SwFrameFormat* const pTableOrSectionFormat,
const uno::Reference<text::XText>& xParent = nullptr)
: m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
, m_eRangePosition(eRange)
, m_rDoc(rDoc)
, m_xParentText(xParent)
- , m_pTableFormat(pTableFormat)
+ , m_pTableOrSectionFormat(pTableOrSectionFormat)
, m_pMark(nullptr)
{
- m_pTableFormat && StartListening(pTableFormat->GetNotifier());
+ if (m_pTableOrSectionFormat)
+ {
+ StartListening(pTableOrSectionFormat->GetNotifier());
+ }
}
virtual ~Impl() override
@@ -716,7 +719,7 @@ public:
m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
m_pMark = nullptr;
}
- m_pTableFormat = nullptr;
+ m_pTableOrSectionFormat = nullptr;
EndListeningAll();
}
@@ -724,7 +727,7 @@ public:
void SetMark(::sw::mark::IMark& rMark)
{
EndListeningAll();
- m_pTableFormat = nullptr;
+ m_pTableOrSectionFormat = nullptr;
m_pMark = &rMark;
StartListening(rMark.GetNotifier());
}
@@ -738,7 +741,7 @@ void SwXTextRange::Impl::Notify(const SfxHint& rHint)
if(rHint.GetId() == SfxHintId::Dying)
{
EndListeningAll();
- m_pTableFormat = nullptr;
+ m_pTableOrSectionFormat = nullptr;
m_pMark = nullptr;
}
}
@@ -751,7 +754,7 @@ SwXTextRange::SwXTextRange(SwPaM const & rPam,
SetPositions(rPam);
}
-SwXTextRange::SwXTextRange(SwFrameFormat& rTableFormat)
+SwXTextRange::SwXTextRange(SwTableFormat& rTableFormat)
: m_pImpl(
new SwXTextRange::Impl(*rTableFormat.GetDoc(), RANGE_IS_TABLE, &rTableFormat) )
{
@@ -763,6 +766,13 @@ SwXTextRange::SwXTextRange(SwFrameFormat& rTableFormat)
SetPositions( aPam );
}
+SwXTextRange::SwXTextRange(SwSectionFormat& rSectionFormat)
+ : m_pImpl(
+ new SwXTextRange::Impl(*rSectionFormat.GetDoc(), RANGE_IS_SECTION, &rSectionFormat) )
+{
+ // no SetPositions here for now
+}
+
SwXTextRange::~SwXTextRange()
{
}
@@ -790,6 +800,18 @@ void SwXTextRange::SetPositions(const SwPaM& rPam)
m_pImpl->SetMark(*pMark);
}
+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);
+}
+
void SwXTextRange::DeleteAndInsert(
const OUString& rText, const bool bForceExpandHints)
{
@@ -801,10 +823,81 @@ void SwXTextRange::DeleteAndInsert(
const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
SwCursor aCursor(aPos, nullptr);
- if (GetPositions(aCursor))
+
+ UnoActionContext aAction(& m_pImpl->m_rDoc);
+
+ if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition)
{
- UnoActionContext aAction(& m_pImpl->m_rDoc);
+ if (!m_pImpl->m_pTableOrSectionFormat)
+ {
+ throw uno::RuntimeException("disposed?");
+ }
m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
+ SwSectionFormat const& rFormat(
+ *static_cast<SwSectionFormat const*>(m_pImpl->m_pTableOrSectionFormat));
+ SwNodeIndex const start(*rFormat.GetSectionNode());
+ SwNodeIndex const end(*start.GetNode().EndOfSectionNode());
+
+ // delete tables at start
+ for (SwNodeIndex i = start; i < end; )
+ {
+ SwNode & rNode(i.GetNode());
+ if (rNode.IsSectionNode())
+ {
+ ++i;
+ continue;
+ }
+ else if (SwTableNode *const pTableNode = rNode.GetTableNode())
+ {
+ DeleteTable(m_pImpl->m_rDoc, pTableNode->GetTable());
+ // where does that leave index? presumably behind?
+ }
+ else
+ {
+ assert(rNode.IsTextNode());
+ break;
+ }
+ }
+ // delete tables at end
+ for (SwNodeIndex i = end; start <= i; )
+ {
+ --i;
+ SwNode & rNode(i.GetNode());
+ if (rNode.IsEndNode())
+ {
+ if (SwTableNode *const pTableNode = rNode.StartOfSectionNode()->GetTableNode())
+ {
+ DeleteTable(m_pImpl->m_rDoc, pTableNode->GetTable());
+ }
+ else
+ {
+ assert(rNode.StartOfSectionNode()->IsSectionNode());
+ continue;
+ }
+ }
+ else
+ {
+ assert(rNode.IsTextNode());
+ break;
+ }
+ }
+ // now there should be a text node at the start and end of it!
+ *aCursor.GetPoint() = SwPosition(start);
+ aCursor.Move( fnMoveForward, GoInContent );
+ assert(aCursor.GetPoint()->nNode <= end);
+ aCursor.SetMark();
+ *aCursor.GetPoint() = SwPosition(end);
+ aCursor.Move( fnMoveBackward, GoInContent );
+ assert(start <= aCursor.GetPoint()->nNode);
+ }
+ else
+ {
+ if (!GetPositions(aCursor))
+ return;
+ m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
+ }
+
+ {
if (aCursor.HasMark())
{
m_pImpl->m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor);
@@ -873,9 +966,9 @@ SwXTextRange::getText()
if (!m_pImpl->m_xParentText.is())
{
if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE &&
- m_pImpl->m_pTableFormat)
+ m_pImpl->m_pTableOrSectionFormat)
{
- SwTable const*const pTable = SwTable::FindTable( m_pImpl->m_pTableFormat );
+ SwTable const*const pTable = SwTable::FindTable( m_pImpl->m_pTableOrSectionFormat );
SwTableNode const*const pTableNode = pTable->GetTableNode();
const SwPosition aPosition( *pTableNode );
m_pImpl->m_xParentText =
@@ -907,6 +1000,15 @@ SwXTextRange::getStart()
// start and end are this, if it's a table
xRet = this;
}
+ else if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
+ && m_pImpl->m_pTableOrSectionFormat)
+ {
+ auto const pSectFormat(static_cast<SwSectionFormat const*>(m_pImpl->m_pTableOrSectionFormat));
+ SwPaM aPaM(*pSectFormat->GetContent().GetContentIdx());
+ aPaM.Move( fnMoveForward, GoInContent );
+ assert(aPaM.GetPoint()->nNode < *pSectFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionNode());
+ xRet = new SwXTextRange(aPaM, m_pImpl->m_xParentText);
+ }
else
{
throw uno::RuntimeException("disposed?");
@@ -935,6 +1037,15 @@ SwXTextRange::getEnd()
// start and end are this, if it's a table
xRet = this;
}
+ else if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
+ && m_pImpl->m_pTableOrSectionFormat)
+ {
+ auto const pSectFormat(static_cast<SwSectionFormat const*>(m_pImpl->m_pTableOrSectionFormat));
+ SwPaM aPaM(*pSectFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionNode());
+ aPaM.Move( fnMoveBackward, GoInContent );
+ assert(*pSectFormat->GetContent().GetContentIdx() < aPaM.GetPoint()->nNode);
+ xRet = new SwXTextRange(aPaM, m_pImpl->m_xParentText);
+ }
else
{
throw uno::RuntimeException("disposed?");
@@ -950,7 +1061,7 @@ OUString SAL_CALL SwXTextRange::getString()
// for tables there is no bookmark, thus also no text
// one could export the table as ASCII here maybe?
SwPaM aPaM(GetDoc().GetNodes());
- if (GetPositions(aPaM) && aPaM.HasMark())
+ if (GetPositions(aPaM, sw::TextRangeMode::AllowNonTextNode) && aPaM.HasMark())
{
SwUnoCursorHelper::GetTextFromPam(aPaM, sRet);
}
@@ -964,8 +1075,27 @@ void SAL_CALL SwXTextRange::setString(const OUString& rString)
DeleteAndInsert(rString, false);
}
-bool SwXTextRange::GetPositions(SwPaM& rToFill) const
+bool SwXTextRange::GetPositions(SwPaM& rToFill, ::sw::TextRangeMode const eMode) const
{
+ if (RANGE_IS_SECTION == m_pImpl->m_eRangePosition
+ && eMode == ::sw::TextRangeMode::AllowNonTextNode)
+ {
+ if (auto const pSectFormat = static_cast<SwSectionFormat const*>(m_pImpl->m_pTableOrSectionFormat))
+ {
+ SwNodeIndex const*const pSectionNode(pSectFormat->GetContent().GetContentIdx());
+ assert(pSectionNode);
+ assert(pSectionNode->GetNodes().IsDocNodes());
+ rToFill.GetPoint()->nNode = *pSectionNode;
+ ++rToFill.GetPoint()->nNode;
+ rToFill.GetPoint()->nContent.Assign(rToFill.GetPoint()->nNode.GetNode().GetContentNode(), 0);
+ rToFill.SetMark();
+ rToFill.GetMark()->nNode = *pSectionNode->GetNode().EndOfSectionNode();
+ --rToFill.GetMark()->nNode;
+ rToFill.GetMark()->nContent.Assign(rToFill.GetMark()->nNode.GetNode().GetContentNode(),
+ rToFill.GetMark()->nNode.GetNode().GetContentNode() ? rToFill.GetMark()->nNode.GetNode().GetContentNode()->Len() : 0);
+ return true;
+ }
+ }
::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
if(pBkmk)
{
@@ -987,7 +1117,8 @@ bool SwXTextRange::GetPositions(SwPaM& rToFill) const
namespace sw {
bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
- const uno::Reference< text::XTextRange > & xTextRange)
+ const uno::Reference<text::XTextRange> & xTextRange,
+ ::sw::TextRangeMode const eMode)
{
bool bRet = false;
@@ -1021,7 +1152,7 @@ bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
}
if(pRange && &pRange->GetDoc() == rToFill.GetDoc())
{
- bRet = pRange->GetPositions(rToFill);
+ bRet = pRange->GetPositions(rToFill, eMode);
}
else
{
diff --git a/sw/source/core/unocore/unosect.cxx b/sw/source/core/unocore/unosect.cxx
index 05c4ba13275a..8ffb3e081bd3 100644
--- a/sw/source/core/unocore/unosect.cxx
+++ b/sw/source/core/unocore/unosect.cxx
@@ -455,14 +455,35 @@ SwXTextSection::getAnchor()
nullptr != ( pIdx = pSectFormat->GetContent().GetContentIdx() ) &&
pIdx->GetNode().GetNodes().IsDocNodes() )
{
+ bool isMoveIntoTable(false);
SwPaM aPaM(*pIdx);
aPaM.Move( fnMoveForward, GoInContent );
+ assert(pIdx->GetNode().IsSectionNode());
+ if (aPaM.GetPoint()->nNode.GetNode().FindTableNode() != pIdx->GetNode().FindTableNode()
+ || aPaM.GetPoint()->nNode.GetNode().FindSectionNode() != &pIdx->GetNode())
+ {
+ isMoveIntoTable = true;
+ }
const SwEndNode* pEndNode = pIdx->GetNode().EndOfSectionNode();
SwPaM aEnd(*pEndNode);
aEnd.Move( fnMoveBackward, GoInContent );
- xRet = SwXTextRange::CreateXTextRange(*pSectFormat->GetDoc(),
- *aPaM.Start(), aEnd.Start());
+ if (aEnd.GetPoint()->nNode.GetNode().FindTableNode() != pIdx->GetNode().FindTableNode()
+ || aEnd.GetPoint()->nNode.GetNode().FindSectionNode() != &pIdx->GetNode())
+ {
+ isMoveIntoTable = true;
+ }
+ if (isMoveIntoTable)
+ {
+ uno::Reference<text::XText> const xParentText(
+ ::sw::CreateParentXText(*pSectFormat->GetDoc(), SwPosition(*pIdx)));
+ xRet = new SwXTextRange(*pSectFormat);
+ }
+ else // for compatibility, keep the old way in this case
+ {
+ xRet = SwXTextRange::CreateXTextRange(*pSectFormat->GetDoc(),
+ *aPaM.Start(), aEnd.Start());
+ }
}
}
return xRet;
diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx
index fa378c7e8ae1..fbce960453b6 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -2215,7 +2215,8 @@ SwXTextTable::attach(const uno::Reference<text::XTextRange> & xTextRange)
uno::Reference<text::XTextRange> SwXTextTable::getAnchor()
{
SolarMutexGuard aGuard;
- SwFrameFormat* pFormat = lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
+ SwTableFormat *const pFormat = static_cast<SwTableFormat*>(
+ lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this)));
return new SwXTextRange(*pFormat);
}
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index f6e5990b1b3d..c287f87e3f4c 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -92,6 +92,7 @@
#include <IDocumentDeviceAccess.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
#include <IDocumentState.hxx>
#include <pagedesc.hxx>
#include <IMark.hxx>
@@ -876,6 +877,80 @@ void SwTransferable::DeleteSelection()
m_pWrtShell->EndUndo( SwUndoId::END );
}
+static void DeleteDDEMarks(SwDoc & rDest)
+{
+ IDocumentMarkAccess* const pMarkAccess = rDest.getIDocumentMarkAccess();
+ std::vector< ::sw::mark::IMark* > vDdeMarks;
+ // find all DDE-Bookmarks
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
+ ppMark != pMarkAccess->getAllMarksEnd();
+ ++ppMark)
+ {
+ if(IDocumentMarkAccess::MarkType::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark))
+ vDdeMarks.push_back(*ppMark);
+ }
+ // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
+ for(const auto& rpMark : vDdeMarks)
+ pMarkAccess->deleteMark(rpMark);
+}
+
+void SwTransferable::PrepareForCopyTextRange(SwPaM & rPaM)
+{
+ std::unique_ptr<SwWait> pWait;
+ if (m_pWrtShell->ShouldWait())
+ {
+ pWait.reset(new SwWait( *m_pWrtShell->GetView().GetDocShell(), true ));
+ }
+
+ m_pClpDocFac.reset(new SwDocFac);
+
+ SwDoc& rDest(*lcl_GetDoc(*m_pClpDocFac));
+ rDest.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
+ {
+ SwDoc const& rSrc(*m_pWrtShell->GetDoc());
+ assert(&rSrc == rPaM.GetDoc());
+
+ rDest.ReplaceCompatibilityOptions(rSrc);
+ rDest.ReplaceDefaults(rSrc);
+
+ //It would probably make most sense here to only insert the styles used
+ //by the selection, e.g. apply SwDoc::IsUsed on styles ?
+ rDest.ReplaceStyles(rSrc, false);
+
+ // relevant bits of rSrcWrtShell.Copy(rDest);
+ rDest.GetIDocumentUndoRedo().DoUndo(false); // always false!
+ rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+
+ SwNodeIndex const aIdx(rDest.GetNodes().GetEndOfContent(), -1);
+ SwContentNode *const pContentNode(aIdx.GetNode().GetContentNode());
+ SwPosition aPos(aIdx,
+ SwIndex(pContentNode, pContentNode ? pContentNode->Len() : 0));
+
+ rSrc.getIDocumentContentOperations().CopyRange(rPaM, aPos, /*bCopyAll=*/false, /*bCheckPos=*/true, /*bCopyText=*/false);
+
+ rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
+
+ rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
+ }
+
+ DeleteDDEMarks(rDest);
+
+ // a new one was created in core (OLE objects copied!)
+ m_aDocShellRef = rDest.GetTmpDocShell();
+ if (m_aDocShellRef.Is())
+ SwTransferable::InitOle( m_aDocShellRef );
+ rDest.SetTmpDocShell( nullptr );
+
+ // let's add some formats
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+ AddFormat( SotClipboardFormatId::RTF );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::RICHTEXT );
+ AddFormat( SotClipboardFormatId::HTML );
+#endif
+ AddFormat( SotClipboardFormatId::STRING );
+}
+
int SwTransferable::PrepareForCopy( bool bIsCut )
{
int nRet = 1;
@@ -983,21 +1058,7 @@ int SwTransferable::PrepareForCopy( bool bIsCut )
pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
lclOverWriteDoc(*m_pWrtShell, *pTmpDoc);
- {
- IDocumentMarkAccess* const pMarkAccess = pTmpDoc->getIDocumentMarkAccess();
- std::vector< ::sw::mark::IMark* > vDdeMarks;
- // find all DDE-Bookmarks
- for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
- ppMark != pMarkAccess->getAllMarksEnd();
- ++ppMark)
- {
- if(IDocumentMarkAccess::MarkType::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark))
- vDdeMarks.push_back(*ppMark);
- }
- // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
- for(const auto& rpMark : vDdeMarks)
- pMarkAccess->deleteMark(rpMark);
- }
+ DeleteDDEMarks(*pTmpDoc);
// a new one was created in CORE (OLE objects copied!)
m_aDocShellRef = pTmpDoc->GetTmpDocShell();
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
index fdb545311351..664282b8389b 100644
--- a/sw/source/uibase/inc/swdtflvr.hxx
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -40,6 +40,7 @@ class INetImage;
class SfxAbstractPasteDialog;
class SwDoc;
class SwDocFac;
+class SwPaM;
class SwTextBlocks;
class SwWrtShell;
class SvxClipboardFormatItem;
@@ -181,6 +182,7 @@ public:
int Cut();
int Copy( bool bIsCut = false );
int PrepareForCopy( bool bIsCut = false );
+ void PrepareForCopyTextRange(SwPaM & rPaM);
void CalculateAndCopy(); // special for Calculator
bool CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr );
diff --git a/sw/source/uibase/inc/unotxvw.hxx b/sw/source/uibase/inc/unotxvw.hxx
index db2f6eae398f..b31760d8f9fe 100644
--- a/sw/source/uibase/inc/unotxvw.hxx
+++ b/sw/source/uibase/inc/unotxvw.hxx
@@ -36,6 +36,7 @@
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/datatransfer/XTransferableSupplier.hpp>
+#include <com/sun/star/datatransfer/XTransferableTextSupplier.hpp>
#include <cppuhelper/implbase.hxx>
#include <svl/itemprop.hxx>
#include <TextCursorHelper.hxx>
@@ -55,6 +56,7 @@ class SwXTextView :
public css::view::XViewSettingsSupplier,
public css::beans::XPropertySet,
public css::datatransfer::XTransferableSupplier,
+ public css::datatransfer::XTransferableTextSupplier,
public SfxBaseController
{
::comphelper::OInterfaceContainerHelper2 m_SelChangedListeners;
@@ -129,6 +131,9 @@ public:
virtual css::uno::Reference< css::datatransfer::XTransferable > SAL_CALL getTransferable( ) override;
virtual void SAL_CALL insertTransferable( const css::uno::Reference< css::datatransfer::XTransferable >& xTrans ) override;
+ // XTransferableTextSupplier
+ virtual css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getTransferableForTextRange(css::uno::Reference<css::text::XTextRange> const& xTextRange) override;
+
void NotifySelChanged();
void NotifyDBChanged();
diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx
index 7dbdb7574bc9..42ae9a02634b 100644
--- a/sw/source/uibase/uno/unotxvw.cxx
+++ b/sw/source/uibase/uno/unotxvw.cxx
@@ -143,6 +143,7 @@ Sequence< uno::Type > SAL_CALL SwXTextView::getTypes( )
cppu::UnoType<XRubySelection>::get(),
cppu::UnoType<XPropertySet>::get(),
cppu::UnoType<datatransfer::XTransferableSupplier>::get(),
+ cppu::UnoType<datatransfer::XTransferableTextSupplier>::get(),
SfxBaseController::getTypes()
).getTypes();
}
@@ -210,6 +211,11 @@ uno::Any SAL_CALL SwXTextView::queryInterface( const uno::Type& aType )
uno::Reference<datatransfer::XTransferableSupplier> xRet = this;
aRet <<= xRet;
}
+ else if(aType == cppu::UnoType<datatransfer::XTransferableTextSupplier>::get())
+ {
+ uno::Reference<datatransfer::XTransferableTextSupplier> xRet = this;
+ aRet <<= xRet;
+ }
else
aRet = SfxBaseController::queryInterface(aType);
return aRet;
@@ -1710,6 +1716,29 @@ SwPaM* SwXTextViewCursor::GetPaM()
return rSh.GetCursor();
}
+uno::Reference<datatransfer::XTransferable> SAL_CALL
+SwXTextView::getTransferableForTextRange(uno::Reference<text::XTextRange> const& xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ // the point is we can copy PaM that wouldn't be legal as shell cursor
+ SwUnoInternalPaM aPam(*m_pView->GetDocShell()->GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xTextRange, ::sw::TextRangeMode::AllowNonTextNode))
+ {
+ throw uno::RuntimeException("invalid text range");
+ }
+
+ //force immediate shell update
+ GetView()->StopShellTimer();
+ SwWrtShell& rSh = GetView()->GetWrtShell();
+ SwTransferable *const pTransfer = new SwTransferable(rSh);
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true );
+ pTransfer->PrepareForCopyTextRange(aPam);
+ rSh.LockView( bLockedView );
+ return uno::Reference<datatransfer::XTransferable>(pTransfer);
+}
+
uno::Reference< datatransfer::XTransferable > SAL_CALL SwXTextView::getTransferable()
{
SolarMutexGuard aGuard;