summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2024-12-18 10:36:48 +0100
committerChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>2024-12-19 22:50:41 +0100
commit8e662d6878a3e38eb79ec01113984cc01df72ea5 (patch)
tree6443962400de6f39ccbb7f038721a8155d237ee0
parent0bf0fdde53555a9e5346be715d7df9c97c875537 (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.cxx33
-rw-r--r--editeng/source/editeng/impedit4.cxx20
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();
}
}
}