tdf#126426: support for hyperlinks in TextParagraphContext
Usually hyperlinks are processed by TextBodyContext, but
for grouped shape we accidentaly gone into TextParagraphContext
It has almost all possibilities to process txbxContent,
but not hyperlinks.
Additionally some hyperlink char attributes (color and underline)
can expand to follow up ordinal text. Additional small hack applied
to avoid this.
Unfortunately this is not a final solution: such document fails
roundtrip and hyperlinks are lost after saving to DOCX.
Change-Id: Ie954f53696bd872cb1f59cb586fb55f6cd7c73bc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121172
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx
index 0492ac2..b1e5241 100644
--- a/oox/source/drawingml/textbodycontext.cxx
+++ b/oox/source/drawingml/textbodycontext.cxx
@@ -29,6 +29,7 @@
#include <oox/token/namespaces.hxx>
#include <oox/helper/attributelist.hxx>
#include <sax/fastattribs.hxx>
#include "hyperlinkcontext.hxx"
#include <oox/mathml/import.hxx>
@@ -104,6 +105,16 @@ ContextHandlerRef TextParagraphContext::onCreateContext( sal_Int32 aElementToken
return this;
case OOX_TOKEN(a14, m):
return CreateLazyMathBufferingContext(*this, mrParagraph);
case W_TOKEN( hyperlink ):
{
TextRunPtr pRun = std::make_shared<TextRun>();
mrParagraph.addRun(pRun);
// parse hyperlink attributes: use HyperLinkContext for that
rtl::Reference<HyperLinkContext> pContext(new HyperLinkContext(
*this, rAttribs, pRun->getTextCharacterProperties().maHyperlinkPropertyMap));
// but create text run context because HyperLinkContext can't process internal w:r, w:t, etc
return new RegularTextRunContext(*this, pRun);
}
default:
SAL_WARN("oox", "TextParagraphContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
}
diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx
index ab87fb7..e3bcecb 100644
--- a/oox/source/drawingml/textrun.cxx
+++ b/oox/source/drawingml/textrun.cxx
@@ -69,7 +69,13 @@ sal_Int32 TextRun::insertAt(
Any aOldFontFamily = xState->getPropertyDefault("CharFontFamily");
TextCharacterProperties aTextCharacterProps( rTextCharacterStyle );
aTextCharacterProps.assignUsed( maTextCharacterProperties );
// If no text color specified lets anyway initialize it as default:
// this will help to recover after hyperlink
if (!aTextCharacterProps.maFillProperties.maFillColor.isUsed())
aTextCharacterProps.maFillProperties.moFillType = XML_solidFill;
aTextCharacterProps.assignUsed(maTextCharacterProperties);
if ( aTextCharacterProps.moHeight.has() )
nCharHeight = aTextCharacterProps.moHeight.get();
else
diff --git a/sw/qa/extras/ooxmlimport/data/tdf126426.docx b/sw/qa/extras/ooxmlimport/data/tdf126426.docx
new file mode 100644
index 0000000..d770513
--- /dev/null
+++ b/sw/qa/extras/ooxmlimport/data/tdf126426.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index e132bef..03f6b21 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -23,6 +23,7 @@
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <xmloff/odffields.hxx>
@@ -903,6 +904,43 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf129912)
}
}
CPPUNIT_TEST_FIXTURE(Test, testTdf126426)
{
load(mpTestDocumentPath, "tdf126426.docx");
uno::Reference<container::XIndexAccess> xGroup(getShape(1), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xGroup->getCount());
// get second shape in group
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xGroup->getByIndex(1),
uno::UNO_QUERY_THROW);
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xPara, uno::UNO_QUERY_THROW);
uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
{
// Text before: was before this bugfix
uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(OUString("Some text "), xRun->getString());
}
{
// Link and this content was completely missong before
uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(OUString("Link"), xRun->getString());
auto xURLField = getProperty<uno::Reference<text::XTextField>>(xRun, "TextField");
auto aURL = getProperty<OUString>(xURLField, "URL");
CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice.org/"), aURL);
}
{
// Need to ensure that text following hyperlink is still default color (-1)
uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(OUString(" and something more."), xRun->getString());
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty<sal_Int32>(xRun, "CharColor"));
}
}
// tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT
CPPUNIT_PLUGIN_IMPLEMENT();