sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 4 - sw/source/core/fields/reffld.cxx | 66 +++++++++++++++--------- writerfilter/source/dmapper/StyleSheetTable.cxx | 14 +++++ 3 files changed, 58 insertions(+), 26 deletions(-)
New commits: commit ec1c8270dd25fee7035e3fec5d22d220c12c7071 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri May 3 19:31:20 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon May 13 11:38:09 2024 +0200 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. (cherry picked from commit 74f859b5525da0760a70ab660bd912dabfd608ca) Change-Id: Iee126eeb4cc2ff1c570941e3beefd93527c56fee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167564 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index f0d5004f73b5..dee26b595c08 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 0ee26771bb2c..85a18c78927f 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 f5c348d64fc3..6b1a79e66c04 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)) {