cool#16219 engine sd, RTF export: fix lost bullets of paragraphs
Add a few bulleted lines to a text frame in an Impress document, copy
them, paste in Writer: the paragraphs are imported with no bullet marks.
ImpEditEngine::WriteRTF() emits a bare \level<n> for the paragraph's
outline level, which editeng's own RTF importer reads back as a
bulleted item, but sw's RTF import ignores. The PowerPoint RTF clipboard
markup for the same thing is the RTF 1.0 old-style numbering pair: a
{\pntext <bullet>\tab} fallback and a {\*\pn\pnlvlblt{\pntxtb <bullet>}}
destination that contains the bullet character.
Fix the problem by emitting that pair alongside \level<n>, from the
paragraph loop in WriteRTF(), when the paragraph's EE_PARA_NUMBULLET
at that outline level is of type SVX_NUM_CHAR_SPECIAL.
Signed-off-by: Miklos Vajna <vmiklos@collabora.com>
Change-Id: I18a022ac28d50a8b7557ee2282cd3fd8e7c37299
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/14439
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
(cherry picked from commit b7002f07f475ce4eb5cf7309dfe8e59ba21ecd7a)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211942
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
09d3cc2c14
commit
1886cb2ee3
@@ -11,8 +11,10 @@
|
||||
|
||||
#include <editeng/eeitem.hxx>
|
||||
#include <editeng/editeng.hxx>
|
||||
#include <editeng/numitem.hxx>
|
||||
#include <editeng/wghtitem.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <svl/intitem.hxx>
|
||||
#include <svtools/parrtf.hxx>
|
||||
#include <svtools/rtftoken.h>
|
||||
|
||||
@@ -213,6 +215,35 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf119192RTFFontAttributesInParagraphScope)
|
||||
bool bContains = (aCnt.find("{mytest}") != std::string::npos);
|
||||
CPPUNIT_ASSERT(bContains);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(Test, testRTFBullet)
|
||||
{
|
||||
// Given a document with a paragraph that is a bulleted item:
|
||||
EditEngine aEditEngine(mpItemPool.get());
|
||||
OUString aText = u"mytest"_ustr;
|
||||
aEditEngine.SetText(aText);
|
||||
SfxItemSet aItems(aEditEngine.GetParaAttribs(0));
|
||||
aItems.Put(SfxInt16Item(EE_PARA_OUTLLEVEL, 0));
|
||||
SvxNumRule aRule(SvxNumRuleFlags::BULLET_REL_SIZE, 10, false);
|
||||
SvxNumberFormat aFmt(SVX_NUM_CHAR_SPECIAL);
|
||||
aFmt.SetBulletChar(0x2022); // bullet
|
||||
aRule.SetLevel(0, aFmt);
|
||||
aItems.Put(SvxNumBulletItem(std::move(aRule), EE_PARA_NUMBULLET));
|
||||
aEditEngine.SetParaAttribs(0, aItems);
|
||||
|
||||
// When copying to the clipboard as RTF:
|
||||
uno::Reference<datatransfer::XTransferable> xData
|
||||
= aEditEngine.CreateTransferable(ESelection(0, 0, 0, aText.getLength()));
|
||||
|
||||
// Then make sure the RTF carries the bullet so a non-editeng reader sees it:
|
||||
auto pData = dynamic_cast<EditDataObject*>(xData.get());
|
||||
SvMemoryStream& rStream = pData->GetRTFStream();
|
||||
std::string aCnt{ static_cast<const char*>(rStream.GetData()),
|
||||
static_cast<size_t>(rStream.GetSize()) };
|
||||
// Without the accompanying fix in place, this failed, the export wrote
|
||||
// only editeng's own \level0 and \pnlvlblt.
|
||||
CPPUNIT_ASSERT(aCnt.find("\\pnlvlblt") != std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <editeng/adjustitem.hxx>
|
||||
#include <editeng/cmapitem.hxx>
|
||||
#include <editeng/lspcitem.hxx>
|
||||
#include <editeng/numitem.hxx>
|
||||
#include <editeng/tstpitem.hxx>
|
||||
|
||||
#include "eertfpar.hxx"
|
||||
@@ -644,6 +645,32 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel, bool bCl
|
||||
if ( bAttr )
|
||||
rOutput.WriteChar( ' ' ); // Separator
|
||||
|
||||
const SfxInt16Item& rOutlLevelItem = GetParaAttrib(nNode, EE_PARA_OUTLLEVEL);
|
||||
sal_Int16 nOutlLevel = rOutlLevelItem.GetValue();
|
||||
if (nOutlLevel >= 0)
|
||||
{
|
||||
// The paragraph has an outline level, check if that is a bullet.
|
||||
const SvxNumBulletItem& rNumBullet = GetParaAttrib(nNode, EE_PARA_NUMBULLET);
|
||||
const SvxNumberFormat* pFmt = rNumBullet.GetNumRule().Get(nOutlLevel);
|
||||
if (pFmt && pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
|
||||
{
|
||||
sal_Unicode cBullet = static_cast<sal_Unicode>(pFmt->GetBulletChar());
|
||||
OUString aBullet(&cBullet, 1);
|
||||
rOutput.WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_PNTEXT).WriteChar(' ');
|
||||
RTFOutFuncs::Out_String(rOutput, aBullet, eDestEnc);
|
||||
rOutput.WriteOString("\\tab}");
|
||||
rOutput.WriteChar('{')
|
||||
.WriteOString(OOO_STRING_SVTOOLS_RTF_IGNORE)
|
||||
.WriteOString(OOO_STRING_SVTOOLS_RTF_PN)
|
||||
.WriteOString(OOO_STRING_SVTOOLS_RTF_PNLVLBLT)
|
||||
.WriteChar('{')
|
||||
.WriteOString(OOO_STRING_SVTOOLS_RTF_PNTXTB)
|
||||
.WriteChar(' ');
|
||||
RTFOutFuncs::Out_String(rOutput, aBullet, eDestEnc);
|
||||
rOutput.WriteOString("}}");
|
||||
}
|
||||
}
|
||||
|
||||
ItemList aAttribItems;
|
||||
ParaPortion* pParaPortion = FindParaPortion( pNode );
|
||||
DBG_ASSERT( pParaPortion, "Portion not found: WriteRTF" );
|
||||
|
||||
Reference in New Issue
Block a user