diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-03-01 20:57:38 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2021-03-03 12:16:24 +0100 |
commit | a4bdd833a252ed4d942e4478fc820f9f2ee725fe (patch) | |
tree | babfa9bb0b27a22f2a0aedba0bf09160039fbc72 | |
parent | 4ddde32ea6807eaa686ad25aa18ea24a8b834df8 (diff) |
tdf#140552 RTF export: fix hyperlink, in footnote, in hyperlink
Regression from commit 7d42346ba77c9c4df241ea40eaf550993ca18783
(tdf#90421 RTF export: ignore hyperlinks without an URL, 2015-04-21),
URLs can be nested in the footnote case, which requires a stack.
Otherwise the inner URL clears "the" URL and we don't close the outer
field as we believe it's empty, so it was not started.
Change-Id: I9f87ddbb7e597c413bf836eb9b58beb76722361f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111794
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 5a74baa4f033f84c4bbcec869a68eef149f77161)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111778
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111823
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r-- | sw/qa/extras/rtfexport/rtfexport3.cxx | 47 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfattributeoutput.cxx | 12 | ||||
-rw-r--r-- | sw/source/filter/ww8/rtfattributeoutput.hxx | 2 |
3 files changed, 57 insertions, 4 deletions
diff --git a/sw/qa/extras/rtfexport/rtfexport3.cxx b/sw/qa/extras/rtfexport/rtfexport3.cxx index 7bb20cbb410e..45f84f5c5089 100644 --- a/sw/qa/extras/rtfexport/rtfexport3.cxx +++ b/sw/qa/extras/rtfexport/rtfexport3.cxx @@ -13,6 +13,7 @@ #include <com/sun/star/text/XFootnotesSupplier.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp> #include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/text/XTextDocument.hpp> class Test : public SwModelTestBase { @@ -236,6 +237,52 @@ DECLARE_RTFEXPORT_TEST(testTdf112520, "tdf112520.docx") getProperty<text::TextContentAnchorType>(getShape(3), "AnchorType")); } +CPPUNIT_TEST_FIXTURE(Test, testNestedHyperlink) +{ + // Given a hyperlink contains a footnote which contains a hyperlink: + { + createSwDoc(); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextContent> xFootnote( + xFactory->createInstance("com.sun.star.text.Footnote"), uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertString(xCursor, "a", /*bAbsorb=*/false); + xText->insertTextContent(xCursor, xFootnote, /*bAbsorb=*/false); + xText->insertString(xCursor, "b", /*bAbsorb=*/false); + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + uno::Reference<beans::XPropertySet> xCursorProps(xCursor, uno::UNO_QUERY); + xCursorProps->setPropertyValue("HyperLinkURL", uno::makeAny(OUString("http://body.com/"))); + uno::Reference<text::XText> xFootnoteText(xFootnote, uno::UNO_QUERY); + xCursor = xFootnoteText->createTextCursor(); + xFootnoteText->insertString(xCursor, "x", /*bAbsorb=*/false); + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + xCursorProps.set(xCursor, uno::UNO_QUERY); + xCursorProps->setPropertyValue("HyperLinkURL", + uno::makeAny(OUString("http://footnote.com/"))); + } + + // When exporting to RTF: + // Without the accompanying fix in place, this test would have failed with: + // assertion failed + // - Expression: xComponent.is() + // i.e. the RTF output was not well-formed, loading failed. + reload(mpFilter, "nested-hyperlink.rtf"); + + // Then make sure both hyperlinks are have the correct URLs. + uno::Reference<text::XTextRange> xParagraph = getParagraph(1); + uno::Reference<text::XTextRange> xPortion = getRun(xParagraph, 1); + CPPUNIT_ASSERT_EQUAL(OUString("http://body.com/"), + getProperty<OUString>(xPortion, "HyperLinkURL")); + auto xFootnote = getProperty<uno::Reference<text::XText>>(getRun(xParagraph, 2), "Footnote"); + uno::Reference<text::XTextRange> xFootnotePortion = getRun(getParagraphOfText(1, xFootnote), 1); + CPPUNIT_ASSERT_EQUAL(OUString("http://footnote.com/"), + getProperty<OUString>(xFootnotePortion, "HyperLinkURL")); +} + DECLARE_RTFEXPORT_TEST(testTdf121623, "tdf121623.rtf") { // This was 2, multicolumn section was ignored at the table. diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 10d38a569e92..fe7f24e474be 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -530,7 +530,7 @@ void RtfAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos) bool RtfAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget) { - m_sURL = rUrl; + m_aURLs.push(rUrl); // Ignore hyperlink without a URL. if (!rUrl.isEmpty()) { @@ -560,7 +560,13 @@ bool RtfAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget) bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph) { - if (!m_sURL.isEmpty()) + if (m_aURLs.empty()) + { + return true; + } + + const OUString& rURL = m_aURLs.top(); + if (!rURL.isEmpty()) { // UGLY: usually EndRun is called earlier, but there is an extra // call to OutAttrWithRange() when at the end of the paragraph, @@ -580,8 +586,8 @@ bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph) // close the field group m_aRun->append('}'); } - m_sURL.clear(); } + m_aURLs.pop(); return true; } diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index 2493ce38fbb0..2a739a330f1e 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -617,7 +617,7 @@ private: std::optional<css::drawing::FillStyle> m_oFillStyle; /// If we're in the process of exporting a hyperlink, then its URL. - OUString m_sURL; + std::stack<OUString> m_aURLs; /// If original file had \sbauto. bool m_bParaBeforeAutoSpacing; |