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
(cherry picked from commit d4fdafa103bfea94a279d7069ddc50ba92f67d01)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167244
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index f0d5004..dee26b5 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 0ee2677..85a18c7 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -1220,7 +1220,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())
@@ -1235,15 +1237,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;
                        }
                    }
                }
            }
        }

@@ -1505,21 +1530,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;
@@ -1528,21 +1553,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;
                }
@@ -1574,7 +1599,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;
@@ -1582,7 +1607,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;
@@ -1590,14 +1615,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;
                }
@@ -1605,13 +1630,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/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx
index f5c348d..6b1a79e 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.cxx
+++ b/writerfilter/source/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))
        {