Kaydet (Commit) 03cee024 authored tarafından Miklos Vajna's avatar Miklos Vajna

tdf#115242 RTF import: order numPr before other paragraph properties

So that paragraph properties inherited from numbering properties can be
properly overwritten with direct formatting, even when we have to take
style deduplication into account.

The OOXML tokenizer already did this,
writerfilter::dmapper::DomainMapper::sprmWithProps()'s
NS_ooxml::LN_CT_NumPr_numId depends on this, so adapt the RTF tokenizer
accordingly.

Change-Id: Iec6026d146f08a9d06266763d01ed626a2d1f3d1
Reviewed-on: https://gerrit.libreoffice.org/49247Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarJenkins <ci@libreoffice.org>
üst 03458f8e
{\rtf1\adeflang1037\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch0\stshfloch1\stshfhich1\stshfbi1\deflang1033\deflangfe1033\themelang1033\themelangfe2052\themelangcs1025
{\*\listtable
{\list\listtemplateid-454920584
{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'02\'00.;}
{\levelnumbers\'01;}
\rtlch\fcs1 \af0\afs26 \ltrch\fcs0 \fs26 }
{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'02\'01.;}
{\levelnumbers\'01;}
\rtlch\fcs1 \af0\afs26 \ltrch\fcs0 \fs26 }
{\listname ;}
\listid1}
}
{\*\listoverridetable
{\listoverride\listid1\listoverridecount0\ls1}
}
\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\noxlattoyen
\noultrlspc\dntblnsbdb\nospaceforul\horzdoc\dgmargin\dghspace120\dgvspace181\dghorigin1440\dgvorigin1440\dghshow2\dgvshow1
\jcompress\viewkind1\viewscale100\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot5451531
\newtblstyruls\nogrowautofit\viewbksp1\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
{\*\wgrffmtfilter 2450}
\nofeaturethrottle1\ilfomacatclnup0
\ltrpar \sectd \ltrsect\linex0\headery735\footery893\sectlinegrid360\sectdefaultcl\sectrsid1254981\sftnbj
\pard\plain \ltrpar\s57\ql \fi-720\li1580\ri0\sl-421\slmult0\widctlpar
\tx2264\wrapdefault\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin1580\itap0\pararsid1254981 \rtlch\fcs1 \af1\afs26\alang1025 \ltrch\fcs0 \f1\fs26\lang1033\langfe2052\cgrid\langnp1033\langfenp2052
{\rtlch\fcs1 \af1 \ltrch\fcs0
\lang1033\langfe1033\langfenp1033\insrsid10637256 This is \'931\'94}
{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid4026340
\par
{\listtext\pard\plain\ltrpar \s56 \rtlch\fcs1 \af0\afs26\alang1025 \ltrch\fcs0 \f1\fs26\insrsid10637256 \hich\af1\dbch\af0\loch\f1 a.\tab}
}
\pard\plain \ltrpar\s56\ql \li1580\ri0\sl-421\slmult0\widctlpar
\tx2293\wrapdefault\aspalpha\aspnum\faauto\ls1\ilvl1\adjustright\rin0\lin1580\itap0\pararsid10637256 \rtlch\fcs1 \af1\afs26\alang1025 \ltrch\fcs0 \f1\fs26\lang1033\langfe2052\cgrid\langnp1033\langfenp2052
{\rtlch\fcs1 \af1 \ltrch\fcs0
\lang1033\langfe1033\langfenp1033\insrsid10637256 This is \'93a\'94, \'93a\'94 starts at the above \'93This\'94}
{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid4026340
\par }
}
......@@ -1390,6 +1390,14 @@ DECLARE_RTFIMPORT_TEST(testTdf104016, "tdf104016.rtf")
xParagraph->getPropertyState("ParaLeftMargin"));
}
DECLARE_RTFIMPORT_TEST(testTdf115242, "tdf115242.rtf")
{
// This was 0, overriden left margin was lost by too aggressive style
// deduplication.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2787),
getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
}
DECLARE_RTFIMPORT_TEST(testDefaultValues, "default-values.rtf")
{
// tdf#105910: control words without values must be treated as having default values,
......
......@@ -510,12 +510,19 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
// Word inherits FirstLineIndent property of the numbering, even if ParaLeftMargin is set, Writer does not.
// So copy it explicitly, if necessary.
sal_Int32 nFirstLineIndent = m_pImpl->getCurrentNumberingProperty("FirstLineIndent");
sal_Int32 nIndentAt = m_pImpl->getCurrentNumberingProperty("IndentAt");
sal_Int32 nParaLeftMargin = ConversionHelper::convertTwipToMM100(nIntValue);
if (nParaLeftMargin != 0 && nIndentAt == nParaLeftMargin)
// Avoid direct left margin when it's the same as from the
// numbering.
break;
if (nFirstLineIndent != 0)
m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::makeAny(nFirstLineIndent), /*bOverwrite=*/false);
m_pImpl->GetTopContext()->Insert(
PROP_PARA_LEFT_MARGIN, uno::makeAny( ConversionHelper::convertTwipToMM100(nIntValue ) ));
m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN,
uno::makeAny(nParaLeftMargin));
}
break;
case NS_ooxml::LN_CT_Ind_end:
......@@ -552,8 +559,17 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
break;
case NS_ooxml::LN_CT_Ind_firstLine:
if (m_pImpl->GetTopContext())
m_pImpl->GetTopContext()->Insert(
PROP_PARA_FIRST_LINE_INDENT, uno::makeAny( ConversionHelper::convertTwipToMM100(nIntValue ) ));
{
sal_Int32 nFirstLineIndent
= m_pImpl->getCurrentNumberingProperty("FirstLineIndent");
sal_Int32 nParaFirstLineIndent = ConversionHelper::convertTwipToMM100(nIntValue);
if (nParaFirstLineIndent != 0 && nFirstLineIndent == nParaFirstLineIndent)
// Avoid direct first margin when it's the same as from the
// numbering.
break;
m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT,
uno::makeAny(nParaFirstLineIndent));
}
break;
case NS_ooxml::LN_CT_Ind_rightChars:
m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "rightChars", OUString::number(nIntValue));
......
......@@ -5661,10 +5661,11 @@ sal_Int32 DomainMapper_Impl::getCurrentNumberingProperty(const OUString& aProp)
if (pProp)
xNumberingRules.set(pProp->second, uno::UNO_QUERY);
pProp = m_pTopContext->getProperty(PROP_NUMBERING_LEVEL);
sal_Int32 nNumberingLevel = -1;
// Default numbering level is the first one.
sal_Int32 nNumberingLevel = 0;
if (pProp)
pProp->second >>= nNumberingLevel;
if (xNumberingRules.is() && nNumberingLevel != -1)
if (xNumberingRules.is())
{
uno::Sequence<beans::PropertyValue> aProps;
xNumberingRules->getByIndex(nNumberingLevel) >>= aProps;
......
......@@ -671,8 +671,14 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIntValue);
else
{
// Insert at the start, so properties inherited from the list
// can be overriden by direct formatting. But still allow the
// case when old-style paragraph numbering is already
// tokenized.
putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr,
NS_ooxml::LN_CT_NumPr_numId, pIntValue);
NS_ooxml::LN_CT_NumPr_numId, pIntValue, RTFOverwrite::YES_PREPEND);
}
}
break;
case RTF_UC:
......
......@@ -97,9 +97,10 @@ void putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Po
rAttributes.set(nId, pValue, eOverwrite);
}
void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue)
void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue,
RTFOverwrite eOverwrite)
{
putNestedAttribute(rSprms, nParent, nId, pValue, RTFOverwrite::NO_APPEND, false);
putNestedAttribute(rSprms, nParent, nId, pValue, eOverwrite, false);
}
static RTFValue::Pointer_t lcl_getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
......
......@@ -387,7 +387,8 @@ public:
};
void putBorderProperty(RTFStack& aStates, Id nId, const RTFValue::Pointer_t& pValue);
void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue);
void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue,
RTFOverwrite eOverwrite = RTFOverwrite::NO_APPEND);
Id getParagraphBorder(sal_uInt32 nIndex);
void putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue,
RTFOverwrite eOverwrite = RTFOverwrite::YES, bool bAttribute = true);
......
......@@ -78,6 +78,17 @@ RTFValue::Pointer_t RTFSprms::find(Id nKeyword, bool bFirst, bool bForWrite)
void RTFSprms::set(Id nKeyword, RTFValue::Pointer_t pValue, RTFOverwrite eOverwrite)
{
ensureCopyBeforeWrite();
if (eOverwrite == RTFOverwrite::YES_PREPEND)
{
auto it = std::remove_if(
m_pSprms->begin(), m_pSprms->end(),
[nKeyword](const RTFSprms::Entry_t& rSprm) { return rSprm.first == nKeyword; });
m_pSprms->erase(it, m_pSprms->end());
m_pSprms->insert(m_pSprms->begin(), std::make_pair(nKeyword, pValue));
return;
}
bool bFound = false;
if (eOverwrite == RTFOverwrite::YES || eOverwrite == RTFOverwrite::NO_IGNORE)
{
......
......@@ -41,7 +41,8 @@ enum class RTFOverwrite
{
YES, ///< Yes, if an existing key is found, overwrite it.
NO_APPEND, ///< No, always append the value to the end of the list.
NO_IGNORE ///< No, if the key is already in the list, then ignore, otherwise append.
NO_IGNORE, ///< No, if the key is already in the list, then ignore, otherwise append.
YES_PREPEND ///< Yes, always prepend the value to the start of the list and remove existing entries.
};
/// A list of RTFSprm with a copy constructor that performs a deep copy.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment