tdf#160402 writerfilter,sw: STYLEREF field can refer to character style
Adapt SwGetRefFieldType::FindAnchor() to search for SwTextCharFormat,
and ApplyClonedTOCStylesToXText() to replace "CharStyleName".
Works for the "Intensive Hervorhebung" field in bugdoc.
Change-Id: Iee126eeb4cc2ff1c570941e3beefd93527c56fee
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167098
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Jenkins
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index e84bb35..74f83e1 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -746,9 +746,9 @@ DECLARE_OOXMLEXPORT_TEST(testTdf160402, "StyleRef-DE.docx")
xmlDocUniquePtr pLayout = parseLayoutDump();
assertXPath(pLayout, "/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Heading 1");
assertXPath(pLayout, "/root/page[2]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
assertXPath(pLayout, "/root/page[3]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Error: Reference source not found"); // TODO
assertXPath(pLayout, "/root/page[3]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Cras faucibus condimentum odio. Sed ac ligula. Aliquam at eros.");
assertXPath(pLayout, "/root/page[4]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
assertXPath(pLayout, "/root/page[5]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Error: Reference source not found"); // TODO
assertXPath(pLayout, "/root/page[5]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion"_ostr, "expand"_ostr, "Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.");
}
DECLARE_OOXMLEXPORT_TEST(testTdf142407, "tdf142407.docx")
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
index 3d592f5..4c03b26 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -1219,7 +1219,9 @@ namespace
/// Picks the first text node with a matching style from a double ended queue, starting at the front
/// This allows us to use the deque either as a stack or as a queue depending on whether we want to search up or down
SwTextNode* SearchForStyleAnchor(SwTextNode* pSelf, const std::deque<SwNode*>& pToSearch,
std::u16string_view rStyleName, bool bCaseSensitive = true)
std::u16string_view rStyleName,
sal_Int32 *const pStart, sal_Int32 *const pEnd,
bool bCaseSensitive = true)
{
std::deque<SwNode*> pSearching(pToSearch);
while (!pSearching.empty())
@@ -1234,15 +1236,38 @@ namespace
if (!pTextNode)
continue;
if (bCaseSensitive)
if (bCaseSensitive
? pTextNode->GetFormatColl()->GetName() == rStyleName
: pTextNode->GetFormatColl()->GetName().equalsIgnoreAsciiCase(rStyleName))
{
if (pTextNode->GetFormatColl()->GetName() == rStyleName)
return pTextNode;
*pStart = 0;
if (pEnd)
{
*pEnd = pTextNode->GetText().getLength();
}
return pTextNode;
}
else
if (auto const pHints = pTextNode->GetpSwpHints())
{
if (pTextNode->GetFormatColl()->GetName().equalsIgnoreAsciiCase(rStyleName))
return pTextNode;
for (size_t i = 0; i < pHints->Count(); ++i)
{
auto const*const pHint(pHints->Get(i));
if (pHint->Which() == RES_TXTATR_CHARFMT)
{
if (bCaseSensitive
? pHint->GetCharFormat().GetCharFormat()->HasName(rStyleName)
: pHint->GetCharFormat().GetCharFormat()->GetName().equalsIgnoreAsciiCase(rStyleName))
{
*pStart = pHint->GetStart();
if (pEnd)
{
*pEnd = *pHint->End();
}
return pTextNode;
}
}
}
}
}
@@ -1503,21 +1528,21 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
pSearchThird.push_back(nodes[n]);
}
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark);
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark, pStt, pEnd);
if (pTextNd)
{
break;
}
// 2. Search up from the top of the page
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark);
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark, pStt, pEnd);
if (pTextNd)
{
break;
}
// 3. Search down from the bottom of the page
pTextNd = SearchForStyleAnchor(pSelf, pSearchThird, rRefMark);
pTextNd = SearchForStyleAnchor(pSelf, pSearchThird, rRefMark, pStt, pEnd);
if (pTextNd)
{
break;
@@ -1526,21 +1551,21 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
// Word has case insensitive styles. LO has case sensitive styles. If we didn't find
// it yet, maybe we could with a case insensitive search. Let's do that
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark,
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark, pStt, pEnd,
false /* bCaseSensitive */);
if (pTextNd)
{
break;
}
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark,
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark, pStt, pEnd,
false /* bCaseSensitive */);
if (pTextNd)
{
break;
}
pTextNd = SearchForStyleAnchor(pSelf, pSearchThird, rRefMark,
pTextNd = SearchForStyleAnchor(pSelf, pSearchThird, rRefMark, pStt, pEnd,
false /* bCaseSensitive */);
break;
}
@@ -1572,7 +1597,7 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
// 1. Search up until we hit the top of the document
pTextNd = SearchForStyleAnchor(pSelf, pSearchFirst, rRefMark);
pTextNd = SearchForStyleAnchor(pSelf, pSearchFirst, rRefMark, pStt, pEnd);
if (pTextNd)
{
break;
@@ -1580,7 +1605,7 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
// 2. Search down until we hit the bottom of the document
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark);
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark, pStt, pEnd);
if (pTextNd)
{
break;
@@ -1588,14 +1613,14 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
// Again, we need to remember that Word styles are not case sensitive
pTextNd = SearchForStyleAnchor(pSelf, pSearchFirst, rRefMark,
pTextNd = SearchForStyleAnchor(pSelf, pSearchFirst, rRefMark, pStt, pEnd,
false /* bCaseSensitive */);
if (pTextNd)
{
break;
}
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark,
pTextNd = SearchForStyleAnchor(pSelf, pSearchSecond, rRefMark, pStt, pEnd,
false /* bCaseSensitive */);
break;
}
@@ -1603,13 +1628,6 @@ SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
OSL_FAIL("<SwGetRefFieldType::FindAnchor(..)> - unknown getref element type");
}
if (pTextNd)
{
*pStt = 0;
if (pEnd)
*pEnd = pTextNd->GetText().getLength();
}
break;
}
diff --git a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
index 2d8ff27..eac2585 100644
--- a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
+++ b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
@@ -1030,6 +1030,20 @@ void StyleSheetTable_Impl::ApplyClonedTOCStylesToXText(uno::Reference<text::XTex
xPara->setPropertyValue(u"ParaStyleName"_ustr, uno::Any(it->second));
}
}
uno::Reference<container::XEnumerationAccess> const xParaEA{xPara, uno::UNO_QUERY_THROW};
uno::Reference<container::XEnumeration> const xEnum{xParaEA->createEnumeration()};
while (xEnum->hasMoreElements())
{
uno::Reference<beans::XPropertySet> const xPortion{xEnum->nextElement(), uno::UNO_QUERY_THROW};
if (xPortion->getPropertyValue(u"CharStyleName"_ustr) >>= styleName)
{
auto const it{m_ClonedTOCStylesMap.find(styleName)};
if (it != m_ClonedTOCStylesMap.end())
{
xPortion->setPropertyValue(u"CharStyleName"_ustr, uno::Any(it->second));
}
}
}
}
else if (xElem->supportsService(u"com.sun.star.text.TextTable"_ustr))
{