tdf#95377 ooxmlimport: treat default style like named styles
The default style was missing out on all of the fixes made
by LN_CT_PPrBase_pStyle. That included right margins, and
numbering styles.
Essentially, this change is just copy and paste from one function
to another. I tried to make all of the logic changes
separately in previous commits. So the adjustments here are simply
to accommodate different variable/function names. So if this
causes any regressions, it ought to just be related to either
applying later on (at finishparagraph instead of
LN_CT_PPrBase_pStyle or because it includes the default style.
One important note regards the preparatory
commit 254c80037a3939c110d5c66fef6c28caf47625e5.
If this commit is reverted, make sure to check that commit
to add a conditional wrappers around GetCurrentNumberingRules().
Change-Id: I9827b2cd1a74a13cf18ada9baa221c5c567a7391
Reviewed-on: https://gerrit.libreoffice.org/48458
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index 9128303..4451e06 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -921,6 +921,14 @@ DECLARE_OOXMLEXPORT_TEST(testTdf95377, "tdf95377.docx")
CPPUNIT_ASSERT_EQUAL(sal_Int32(-250), getProperty<sal_Int32>(xParagraph, "ParaFirstLineIndent"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(250), getProperty<sal_Int32>(xParagraph, "ParaLeftMargin"));
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent"));
//default style has numbering enabled. Styles inherit numbering unless specifically disabled
xmlDocPtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "//body/txt/Special", 3); //first three paragraphs have numbering
assertXPath(pXmlDoc, "//body/txt[1]/Special", "rText", "a.");
assertXPath(pXmlDoc, "//body/txt[2]/Special", "rText", "b.");
assertXPath(pXmlDoc, "//body/txt[3]/Special", "rText", "c.");
assertXPath(pXmlDoc, "/root/page/body/txt[4]/Special", 0); //last paragraph style disables numbering
}
DECLARE_OOXMLEXPORT_TEST(testTdf95376, "tdf95376.docx")
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 9acb00f..a573275 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1194,30 +1194,6 @@ static bool ExchangeLeftRight(const PropertyMapPtr& rContext, DomainMapper_Impl&
return bExchangeLeftRight;
}
/// Check if the style or its parent has a list id, recursively.
static sal_Int32 lcl_getListId(const StyleSheetEntryPtr& rEntry, const StyleSheetTablePtr& rStyleTable)
{
const StyleSheetPropertyMap* pEntryProperties = dynamic_cast<const StyleSheetPropertyMap*>(rEntry->pProperties.get());
if (!pEntryProperties)
return -1;
sal_Int32 nListId = pEntryProperties->GetListId();
// The style itself has a list id.
if (nListId >= 0)
return nListId;
// The style has no parent.
if (rEntry->sBaseStyleIdentifier.isEmpty())
return -1;
const StyleSheetEntryPtr pParent = rStyleTable->FindStyleSheetByISTD(rEntry->sBaseStyleIdentifier);
// No such parent style or loop in the style hierarchy.
if (!pParent || pParent == rEntry)
return -1;
return lcl_getListId(pParent, rStyleTable);
}
void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
{
// These SPRM's are not specific to any section, so it's expected that there is no context yet.
@@ -2121,57 +2097,6 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
const OUString sConvertedStyleName = pStyleTable->ConvertStyleName( sStringValue, true );
if (m_pImpl->GetTopContext() && m_pImpl->GetTopContextType() != CONTEXT_SECTION)
m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::makeAny( sConvertedStyleName ));
//apply numbering to paragraph if it was set at the style, but only if the paragraph itself
//does not specify the numbering
if( !rContext->isSet(PROP_NUMBERING_RULES) ) // !contains
{
const StyleSheetEntryPtr pEntry = pStyleTable->FindStyleSheetByISTD(sStringValue);
OSL_ENSURE( pEntry.get(), "no style sheet found" );
const StyleSheetPropertyMap* pStyleSheetProperties = dynamic_cast<const StyleSheetPropertyMap*>(pEntry ? pEntry->pProperties.get() : nullptr);
sal_Int32 nListId = pEntry ? lcl_getListId(pEntry, pStyleTable) : -1;
if( pStyleSheetProperties && nListId >= 0 )
{
if ( !pEntry->bIsChapterNumbering )
rContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( ListDef::GetStyleName( nListId ) ), false);
// Indent properties from the paragraph style have priority
// over the ones from the numbering styles in Word
// but in Writer numbering styles have priority,
// so insert directly into the paragraph properties to compensate.
boost::optional<PropertyMap::Property> oProperty;
if ( (oProperty = pStyleSheetProperties->getProperty(PROP_PARA_FIRST_LINE_INDENT)) )
rContext->Insert(PROP_PARA_FIRST_LINE_INDENT, oProperty->second, /*bOverwrite=*/false);
if ( (oProperty = pStyleSheetProperties->getProperty(PROP_PARA_LEFT_MARGIN)) )
rContext->Insert(PROP_PARA_LEFT_MARGIN, oProperty->second, /*bOverwrite=*/false);
// We're inheriting properties from a numbering style. Make sure a possible right margin is inherited from the base style.
sal_Int32 nParaRightMargin = 0;
if (!pEntry->sBaseStyleIdentifier.isEmpty())
{
const StyleSheetEntryPtr pParent = pStyleTable->FindStyleSheetByISTD(pEntry->sBaseStyleIdentifier);
const StyleSheetPropertyMap* pParentProperties = dynamic_cast<const StyleSheetPropertyMap*>(pParent ? pParent->pProperties.get() : nullptr);
boost::optional<PropertyMap::Property> pPropMargin;
if (pParentProperties && (pPropMargin = pParentProperties->getProperty(PROP_PARA_RIGHT_MARGIN)) )
nParaRightMargin = pPropMargin->second.get<sal_Int32>();
}
if (nParaRightMargin != 0)
{
// If we're setting the right margin, we should set the first / left margin as well from the numbering style.
const sal_Int32 nFirstLineIndent = m_pImpl->getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "FirstLineIndent");
const sal_Int32 nParaLeftMargin = m_pImpl->getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "IndentAt");
if (nFirstLineIndent != 0)
rContext->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::makeAny(nFirstLineIndent), /*bOverwrite=*/false);
if (nParaLeftMargin != 0)
rContext->Insert(PROP_PARA_LEFT_MARGIN, uno::makeAny(nParaLeftMargin), /*bOverwrite=*/false);
rContext->Insert(PROP_PARA_RIGHT_MARGIN, uno::makeAny(nParaRightMargin), /*bOverwrite=*/false);
}
}
if( pStyleSheetProperties && pStyleSheetProperties->GetListLevel() >= 0 )
rContext->Insert( PROP_NUMBERING_LEVEL, uno::makeAny(pStyleSheetProperties->GetListLevel()), false);
}
}
break;
case NS_ooxml::LN_EG_RPrBase_rStyle:
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 823fc60..69147cd 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1056,6 +1056,30 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( )
}
}
/// Check if the style or its parent has a list id, recursively.
static sal_Int32 lcl_getListId(const StyleSheetEntryPtr& rEntry, const StyleSheetTablePtr& rStyleTable)
{
const StyleSheetPropertyMap* pEntryProperties = dynamic_cast<const StyleSheetPropertyMap*>(rEntry->pProperties.get());
if (!pEntryProperties)
return -1;
sal_Int32 nListId = pEntryProperties->GetListId();
// The style itself has a list id.
if (nListId >= 0)
return nListId;
// The style has no parent.
if (rEntry->sBaseStyleIdentifier.isEmpty())
return -1;
const StyleSheetEntryPtr pParent = rStyleTable->FindStyleSheetByISTD(rEntry->sBaseStyleIdentifier);
// No such parent style or loop in the style hierarchy.
if (!pParent || pParent == rEntry)
return -1;
return lcl_getListId(pParent, rStyleTable);
}
void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap )
{
#ifdef DEBUG_WRITERFILTER
@@ -1073,6 +1097,59 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap )
TagLogger::getInstance().attribute("isTextAppend", sal_uInt32(xTextAppend.is()));
#endif
//apply numbering to paragraph if it was set at the style, but only if the paragraph itself
//does not specify the numbering
if( pParaContext && !pParaContext->isSet(PROP_NUMBERING_RULES) )
{
const StyleSheetEntryPtr pEntry = GetStyleSheetTable()->FindStyleSheetByISTD( GetCurrentParaStyleId() );
OSL_ENSURE( pEntry.get(), "no style sheet found" );
const StyleSheetPropertyMap* pStyleSheetProperties = dynamic_cast<const StyleSheetPropertyMap*>(pEntry ? pEntry->pProperties.get() : nullptr);
sal_Int32 nListId = pEntry ? lcl_getListId(pEntry, GetStyleSheetTable()) : -1;
if( pStyleSheetProperties && nListId >= 0 )
{
if ( !pEntry->bIsChapterNumbering )
pParaContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( ListDef::GetStyleName( nListId ) ), false);
// Indent properties from the paragraph style have priority
// over the ones from the numbering styles in Word
// but in Writer numbering styles have priority,
// so insert directly into the paragraph properties to compensate.
boost::optional<PropertyMap::Property> oProperty;
if ( (oProperty = pStyleSheetProperties->getProperty(PROP_PARA_FIRST_LINE_INDENT)) )
pParaContext->Insert(PROP_PARA_FIRST_LINE_INDENT, oProperty->second, /*bOverwrite=*/false);
if ( (oProperty = pStyleSheetProperties->getProperty(PROP_PARA_LEFT_MARGIN)) )
pParaContext->Insert(PROP_PARA_LEFT_MARGIN, oProperty->second, /*bOverwrite=*/false);
// We're inheriting properties from a numbering style. Make sure a possible right margin is inherited from the base style.
sal_Int32 nParaRightMargin = 0;
if (!pEntry->sBaseStyleIdentifier.isEmpty())
{
const StyleSheetEntryPtr pParent = GetStyleSheetTable()->FindStyleSheetByISTD(pEntry->sBaseStyleIdentifier);
const StyleSheetPropertyMap* pParentProperties = dynamic_cast<const StyleSheetPropertyMap*>(pParent ? pParent->pProperties.get() : nullptr);
boost::optional<PropertyMap::Property> pPropMargin;
if (pParentProperties && (pPropMargin = pParentProperties->getProperty(PROP_PARA_RIGHT_MARGIN)) )
nParaRightMargin = pPropMargin->second.get<sal_Int32>();
}
if (nParaRightMargin != 0)
{
// If we're setting the right margin, we should set the first / left margin as well from the numbering style.
const sal_Int32 nFirstLineIndent = getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "FirstLineIndent");
const sal_Int32 nParaLeftMargin = getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "IndentAt");
if (nFirstLineIndent != 0)
pParaContext->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::makeAny(nFirstLineIndent), /*bOverwrite=*/false);
if (nParaLeftMargin != 0)
pParaContext->Insert(PROP_PARA_LEFT_MARGIN, uno::makeAny(nParaLeftMargin), /*bOverwrite=*/false);
pParaContext->Insert(PROP_PARA_RIGHT_MARGIN, uno::makeAny(nParaRightMargin), /*bOverwrite=*/false);
}
}
if( pStyleSheetProperties && pStyleSheetProperties->GetListLevel() >= 0 )
pParaContext->Insert( PROP_NUMBERING_LEVEL, uno::makeAny(pStyleSheetProperties->GetListLevel()), false);
}
if (xTextAppend.is() && pParaContext && hasTableManager() && !getTableManager().isIgnore())
{
try