diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2024-12-18 10:36:48 +0100 |
---|---|---|
committer | Christian Lohmaier <lohmaier+LibreOffice@googlemail.com> | 2024-12-19 22:50:41 +0100 |
commit | 8e662d6878a3e38eb79ec01113984cc01df72ea5 (patch) | |
tree | 6443962400de6f39ccbb7f038721a8155d237ee0 | |
parent | 0bf0fdde53555a9e5346be715d7df9c97c875537 (diff) |
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 <vmiklos@collabora.com>
(cherry picked from commit 65043a50adf8d56e1f965ec48b9609ca836ccced)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178816
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
-rw-r--r-- | editeng/qa/editeng/editeng.cxx | 33 | ||||
-rw-r--r-- | editeng/source/editeng/impedit4.cxx | 20 |
2 files changed, 48 insertions, 5 deletions
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 6c83f2a4e5e2..de167e657690 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -479,15 +479,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(); } } } |