editeng/qa/editeng/editeng.cxx | 33 +++++++++++++++++++++++++++++++++ editeng/source/editeng/impedit4.cxx | 20 +++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-)
New commits: commit 65e3b433b3e53e3fa308b0ba66eb8c38670eda8f Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Dec 18 10:36:48 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Mon Jan 6 10:16:24 2025 +0100 Related: tdf#164359 editeng RTF export: track unused follow styles recursively Similar to commit a7a81b6fbe37af938ce461e790fac517be032317 (tdf#164359 editeng RTF export: track unused parent styles recursively, 2024-12-18), the follows of a style has to be tracked recursively as well, to avoid a crash. The Impress UI doesn't seem to have a way to specify the parent/next name of a style, but you can definitely create such a follow chain from test code and probably this is also possible via macros. Fix this similar to the parent case, except here handle when a style sets itself as a follow: that's what the default Outline N styles do in Impress. Change-Id: If3847add02061fdb9ba1e3fbf7c1fc42e3866209 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178786 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 65043a50adf8d56e1f965ec48b9609ca836ccced) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178816 Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> (cherry picked from commit 8e662d6878a3e38eb79ec01113984cc01df72ea5) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179815 Reviewed-by: Aron Budea <aron.bu...@collabora.com> diff --git a/editeng/qa/editeng/editeng.cxx b/editeng/qa/editeng/editeng.cxx index 7358bca5dd59..f3df37592f14 100644 --- a/editeng/qa/editeng/editeng.cxx +++ b/editeng/qa/editeng/editeng.cxx @@ -157,6 +157,39 @@ CPPUNIT_TEST_FIXTURE(Test, testRTFStyleExportParentRecursive) SvMemoryStream& rStream = pData->GetRTFStream(); CPPUNIT_ASSERT_GREATER(static_cast<sal_uInt64>(0), rStream.remainingSize()); } + +CPPUNIT_TEST_FIXTURE(Test, testRTFStyleExportFollowRecursive) +{ + // Given a document with text that has a paragraph style with a follow that itself has a follow: + EditEngine aEditEngine(mpItemPool.get()); + rtl::Reference<SfxStyleSheetPool> xStyles(new SfxStyleSheetPool(*mpItemPool)); + xStyles->Make("mystyle1", SfxStyleFamily::Para); + xStyles->Make("mystyle2", SfxStyleFamily::Para); + xStyles->Make("mystyle3", SfxStyleFamily::Para); + auto pStyle1 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle1", SfxStyleFamily::Para)); + auto pStyle2 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle2", SfxStyleFamily::Para)); + auto pStyle3 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle3", SfxStyleFamily::Para)); + pStyle1->SetFollow(pStyle2->GetName()); + pStyle2->SetFollow(pStyle3->GetName()); + pStyle3->SetFollow(pStyle3->GetName()); + pStyle1->GetItemSet().SetRanges(svl::Items<WEIGHT_BOLD, EE_CHAR_WEIGHT>); + SvxWeightItem aItem(WEIGHT_BOLD, EE_CHAR_WEIGHT); + pStyle1->GetItemSet().Put(aItem); + aEditEngine.SetStyleSheetPool(xStyles.get()); + OUString aText = u"mytest"_ustr; + aEditEngine.SetText(aText); + aEditEngine.SetStyleSheet(0, pStyle1); + + // When copying to the clipboard as RTF: + // Without the accompanying fix in place, this test would have crashed here: + uno::Reference<datatransfer::XTransferable> xData + = aEditEngine.CreateTransferable(ESelection(0, 0, 0, aText.getLength())); + + // Then make sure we produce RTF and not crash: + auto pData = dynamic_cast<EditDataObject*>(xData.get()); + SvMemoryStream& rStream = pData->GetRTFStream(); + CPPUNIT_ASSERT_GREATER(static_cast<sal_uInt64>(0), rStream.remainingSize()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index 6f1cf6abeb2b..cf49099bd6e0 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -468,15 +468,25 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel, bool bCl aParent = pParent->GetParent(); } - const OUString& rFollow = pParaStyle->GetFollow(); - if (!rFollow.isEmpty()) + // Collect follows of the style recursively. + OUString aFollow = pParaStyle->GetFollow(); + while (!aFollow.isEmpty()) { auto pFollow = static_cast<SfxStyleSheet*>( - GetStyleSheetPool()->Find(rFollow, pParaStyle->GetFamily())); - if (pFollow) + GetStyleSheetPool()->Find(aFollow, pParaStyle->GetFamily())); + if (!pFollow) { - aUsedParagraphStyles.insert(pFollow); + break; + } + + auto it = aUsedParagraphStyles.insert(pFollow); + // A style is fine to have itself as a follow. + if (!it.second) + { + // No insertion happened, so this is visited already. + break; } + aFollow = pFollow->GetFollow(); } } }