sw/qa/extras/ooxmlexport/data/tdf159897.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport21.cxx | 11 +++++++++++ sw/source/filter/ww8/attributeoutputbase.hxx | 2 +- sw/source/filter/ww8/docxattributeoutput.cxx | 6 +++++- sw/source/filter/ww8/docxattributeoutput.hxx | 2 +- sw/source/filter/ww8/rtfattributeoutput.cxx | 3 ++- sw/source/filter/ww8/rtfattributeoutput.hxx | 3 ++- sw/source/filter/ww8/wrtw8nds.cxx | 4 ++-- sw/source/filter/ww8/ww8attributeoutput.hxx | 2 +- sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx | 16 +++++++++++++++- sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx | 3 +++ 11 files changed, 43 insertions(+), 9 deletions(-)
New commits: commit 6c583b38bc96b397f1a742127ea7ac99cadd024f Author: Tibor Nagy <tibor.nagy.ext...@allotropia.de> AuthorDate: Mon May 27 14:56:37 2024 +0200 Commit: Nagy Tibor <tibor.nagy.ext...@allotropia.de> CommitDate: Sat Jun 1 13:50:26 2024 +0200 tdf#159897 docx import: fix ScreenTip of hyperlink Note: if the ScreenTip contains double quote marks, the link will be broken after the import Change-Id: I4ed3e4e9e87335407e01d50cc5c440d04598a33f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168105 Tested-by: Jenkins Reviewed-by: Nagy Tibor <tibor.nagy.ext...@allotropia.de> diff --git a/sw/qa/extras/ooxmlexport/data/tdf159897.docx b/sw/qa/extras/ooxmlexport/data/tdf159897.docx new file mode 100644 index 000000000000..7b3d5c228105 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf159897.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx index e487bbf00015..3e1ebb45e24b 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx @@ -572,6 +572,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf154369, "tdf154369.docx") "color"_ostr, "00527d55"); } +CPPUNIT_TEST_FIXTURE(Test, testScreenTip) +{ + loadAndSave("tdf159897.docx"); + + xmlDocUniquePtr pXmlDocument = parseExport("word/document.xml"); + + // Hyperlink with ScreenTip + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:hyperlink"_ostr, "tooltip"_ostr, + "This is a hyperlink"); +} + CPPUNIT_TEST_FIXTURE(Test, testEmptyObjectRange) { // Before the fix, this failed an assertion like this: diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 4ce7f495cc3b..a6845c56b633 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -203,7 +203,7 @@ public: virtual void EndRuby( const SwTextNode& rNode, sal_Int32 nPos ) = 0; /// Output URL start. - virtual bool StartURL( const OUString& rUrl, const OUString& rTarget ) = 0; + virtual bool StartURL(const OUString& rUrl, const OUString& rTarget, const OUString& rName = OUString()) = 0; /// Output URL end. virtual bool EndURL(bool isAtEndOfParagraph) = 0; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 827d037b274c..97a4c038c736 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3911,7 +3911,7 @@ void DocxAttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sa m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName)); } -bool DocxAttributeOutput::StartURL( const OUString& rUrl, const OUString& rTarget ) +bool DocxAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget, const OUString& rName) { OUString sMark; OUString sUrl; @@ -3983,6 +3983,10 @@ bool DocxAttributeOutput::StartURL( const OUString& rUrl, const OUString& rTarge { m_pHyperlinkAttrList->add(FSNS(XML_w, XML_tgtFrame), rTarget); } + else if (!rName.isEmpty()) + { + m_pHyperlinkAttrList->add(FSNS(XML_w, XML_tooltip), rName); + } } return true; diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 063cb02bbc69..d9cddce059c7 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -253,7 +253,7 @@ public: virtual void EndRuby(const SwTextNode& rNode, sal_Int32 nPos) override; /// Output URL start. - virtual bool StartURL( const OUString& rUrl, const OUString& rTarget ) override; + virtual bool StartURL( const OUString& rUrl, const OUString& rTarget, const OUString& rName = OUString() ) override; /// Output URL end. virtual bool EndURL(bool) override; diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 5b0e89de1e73..2c9f92aaa245 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -547,7 +547,8 @@ void RtfAttributeOutput::StartRuby(const SwTextNode& rNode, sal_Int32 /*nPos*/, void RtfAttributeOutput::EndRuby(const SwTextNode& /*rNode*/, sal_Int32 /*nPos*/) {} -bool RtfAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget) +bool RtfAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget, + const OUString& /*rName*/) { m_aURLs.push(rUrl); // Ignore hyperlink without a URL. diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index 50ca3c0899b2..4309e1f213f3 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -102,7 +102,8 @@ public: void EndRuby(const SwTextNode& rNode, sal_Int32 nPos) override; /// Output URL start. - bool StartURL(const OUString& rUrl, const OUString& rTarget) override; + bool StartURL(const OUString& rUrl, const OUString& rTarget, + const OUString& rName = OUString()) override; /// Output URL end. bool EndURL(bool isAtEndOfParagraph) override; diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index ee561dc129b6..a42fc133ebb3 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -1146,7 +1146,7 @@ void WW8AttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName)); } -bool WW8AttributeOutput::StartURL( const OUString &rUrl, const OUString &rTarget ) +bool WW8AttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget, const OUString& /*rName*/) { INetURLObject aURL( rUrl ); OUString sURL; @@ -1489,7 +1489,7 @@ int SwWW8AttrIter::OutAttrWithRange(const SwTextNode& rNode, sal_Int32 nPos) if ( nPos == pHt->GetStart() ) { const SwFormatINetFormat *rINet = static_cast< const SwFormatINetFormat* >( pItem ); - if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) ) + if (m_rExport.AttrOutput().StartURL(rINet->GetValue(), rINet->GetTargetFrame(), rINet->GetName())) ++nRet; } pEnd = pHt->End(); diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index 7a0d13a2bc62..a103cc4c11ce 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -79,7 +79,7 @@ public: virtual void EndRuby(const SwTextNode& rNode, sal_Int32 nPos) override; /// Output URL start. - virtual bool StartURL( const OUString &rUrl, const OUString &rTarget ) override; + virtual bool StartURL(const OUString& rUrl, const OUString& rTarget, const OUString& rName = OUString()) override; /// Output URL end. virtual bool EndURL(bool) override; diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx index 32d26b03d5bb..25f9e0630083 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx @@ -7842,6 +7842,7 @@ void DomainMapper_Impl::CloseFieldCommand() OUString sURL; OUString sTarget; + OUString sName; while (aPartIt != aItEnd) { @@ -7857,7 +7858,7 @@ void DomainMapper_Impl::CloseFieldCommand() else if (*aPartIt == "\m" || *aPartIt == "\n" || *aPartIt == "\h") { } - else if ( *aPartIt == "\o" || *aPartIt == "\t" ) + else if (*aPartIt == "\t") { ++aPartIt; @@ -7866,6 +7867,15 @@ void DomainMapper_Impl::CloseFieldCommand() sTarget = *aPartIt; } + else if (*aPartIt == "\o") + { + ++aPartIt; + + if (aPartIt == aItEnd) + break; + + sName = *aPartIt; + } else { sURL = *aPartIt; @@ -7905,6 +7915,8 @@ void DomainMapper_Impl::CloseFieldCommand() if (!sTarget.isEmpty()) pContext->SetHyperlinkTarget(sTarget); + else if (!sName.isEmpty()) + pContext->SetHyperlinkName(sName); } break; case FIELD_IF: @@ -8798,6 +8810,8 @@ void DomainMapper_Impl::PopFieldContext() if (!pContext->GetHyperlinkTarget().isEmpty()) xCrsrProperties->setPropertyValue(u"HyperLinkTarget"_ustr, uno::Any(pContext->GetHyperlinkTarget())); + else if (!pContext->GetHyperlinkName().isEmpty()) + xCrsrProperties->setPropertyValue(u"HyperLinkName"_ustr, uno::Any(pContext->GetHyperlinkName())); if (IsInTOC()) { diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx index 7962facc5252..f60411128bcf 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx +++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx @@ -307,6 +307,7 @@ private: OUString m_sHyperlinkURL; /// A frame for the hyperlink when one exists. OUString m_sHyperlinkTarget; + OUString m_sHyperlinkName; OUString m_sHyperlinkStyle; FFDataHandler::Pointer_t m_pFFDataHandler; @@ -359,6 +360,8 @@ public: const OUString& GetHyperlinkURL() const { return m_sHyperlinkURL; } void SetHyperlinkTarget(const OUString& rTarget) { m_sHyperlinkTarget = rTarget; } const OUString& GetHyperlinkTarget() const { return m_sHyperlinkTarget; } + void SetHyperlinkName(const OUString& rName) { m_sHyperlinkName = rName; } + const OUString& GetHyperlinkName() const { return m_sHyperlinkName; } void SetHyperlinkStyle(const OUString& rStyle) { m_sHyperlinkStyle = rStyle; } const OUString& GetHyperlinkStyle() const { return m_sHyperlinkStyle; }