diff options
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/unotextrange.hxx | 16 | ||||
-rw-r--r-- | sw/qa/extras/unowriter/data/tdf134250.fodt | 86 | ||||
-rw-r--r-- | sw/qa/extras/unowriter/data/tdf134252.fodt | 95 | ||||
-rw-r--r-- | sw/qa/extras/unowriter/unowriter.cxx | 122 | ||||
-rw-r--r-- | sw/source/core/unocore/unoobj2.cxx | 163 | ||||
-rw-r--r-- | sw/source/core/unocore/unosect.cxx | 25 | ||||
-rw-r--r-- | sw/source/core/unocore/unotbl.cxx | 3 | ||||
-rw-r--r-- | sw/source/uibase/dochdl/swdtflvr.cxx | 91 | ||||
-rw-r--r-- | sw/source/uibase/inc/swdtflvr.hxx | 2 | ||||
-rw-r--r-- | sw/source/uibase/inc/unotxvw.hxx | 5 | ||||
-rw-r--r-- | sw/source/uibase/uno/unotxvw.cxx | 29 |
11 files changed, 600 insertions, 37 deletions
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="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Lohit Devanagari" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Source Han Serif CN" svg:font-family="'Source Han Serif CN'" 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="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Lohit Devanagari" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Source Han Serif CN" svg:font-family="'Source Han Serif CN'" 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; |