tdf#79329 DOCX import: fix missing outer table with floattable at cell start
The bug document has a normal table, then its C1 cell starts with a nested table, which is floating. The problem is that converting the nested table to a textframe invalidates the start text range of the C1 cell in the outer table we store, so the conversion of the outer table from text to table fails. This never worked, so to avoid the regression just don't convert inner floating tables to textframes when they're anchored at the cell start. A more general fix in the future can be addressing the actual invalidation of the cell start/end text ranges, and then this specific fix will not be necessary anymore. Change-Id: I12cefa41977cf719b07b0fb3ef9ec423c17ef3b1 Reviewed-on: https://gerrit.libreoffice.org/30685 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
This commit is contained in:
parent
bbf6c51717
commit
c1eebcdac9
BIN
sw/qa/extras/ooxmlexport/data/tdf79329.docx
Normal file
BIN
sw/qa/extras/ooxmlexport/data/tdf79329.docx
Normal file
Binary file not shown.
@ -110,6 +110,14 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx")
|
|||||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not centered horizontally relatively to right page border", text::RelOrientation::PAGE_RIGHT, nValue);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not centered horizontally relatively to right page border", text::RelOrientation::PAGE_RIGHT, nValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_OOXMLEXPORT_TEST(testTdf79329, "tdf79329.docx")
|
||||||
|
{
|
||||||
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||||||
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
|
||||||
|
// This was 1: only the inner, not the outer table was created.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xTables->getCount());
|
||||||
|
}
|
||||||
|
|
||||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
@ -2535,6 +2535,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
|
|||||||
break;
|
break;
|
||||||
case NS_ooxml::LN_tblStart:
|
case NS_ooxml::LN_tblStart:
|
||||||
{
|
{
|
||||||
|
if (m_pImpl->hasTableManager())
|
||||||
|
{
|
||||||
|
bool bTableStartsAtCellStart = m_pImpl->m_nTableDepth > 0 && m_pImpl->m_nTableCellDepth > m_pImpl->m_nLastTableCellParagraphDepth + 1;
|
||||||
|
m_pImpl->getTableManager().setTableStartsAtCellStart(bTableStartsAtCellStart);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Hack for Importing Section Properties
|
* Hack for Importing Section Properties
|
||||||
* LO is not able to import section properties if first element in the
|
* LO is not able to import section properties if first element in the
|
||||||
@ -2575,6 +2580,13 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
|
|||||||
case NS_ooxml::LN_tblEnd:
|
case NS_ooxml::LN_tblEnd:
|
||||||
m_pImpl->m_nTableDepth--;
|
m_pImpl->m_nTableDepth--;
|
||||||
break;
|
break;
|
||||||
|
case NS_ooxml::LN_tcStart:
|
||||||
|
m_pImpl->m_nTableCellDepth++;
|
||||||
|
break;
|
||||||
|
case NS_ooxml::LN_tcEnd:
|
||||||
|
m_pImpl->m_nTableCellDepth--;
|
||||||
|
m_pImpl->m_nLastTableCellParagraphDepth = 0;
|
||||||
|
break;
|
||||||
case NS_ooxml::LN_glow_glow:
|
case NS_ooxml::LN_glow_glow:
|
||||||
case NS_ooxml::LN_shadow_shadow:
|
case NS_ooxml::LN_shadow_shadow:
|
||||||
case NS_ooxml::LN_reflection_reflection:
|
case NS_ooxml::LN_reflection_reflection:
|
||||||
|
@ -982,7 +982,7 @@ static void lcl_ApplyCellParaProps(uno::Reference<table::XCell> const& xCell,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
|
void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_WRITERFILTER
|
#ifdef DEBUG_WRITERFILTER
|
||||||
TagLogger::getInstance().startElement("tablehandler.endTable");
|
TagLogger::getInstance().startElement("tablehandler.endTable");
|
||||||
@ -1127,7 +1127,10 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
|
|||||||
{
|
{
|
||||||
// m_xText points to the body text, get the current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
|
// m_xText points to the body text, get the current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
|
||||||
uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY);
|
uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY);
|
||||||
if (xTextAppendAndConvert.is())
|
// Only execute the conversion if the table is not anchored at
|
||||||
|
// the start of an outer table cell, that's not yet
|
||||||
|
// implemented.
|
||||||
|
if (xTextAppendAndConvert.is() && !bTableStartsAtCellStart)
|
||||||
xTextAppendAndConvert->convertToTextFrame(xStart, xEnd, comphelper::containerToSequence(aFrameProperties));
|
xTextAppendAndConvert->convertToTextFrame(xStart, xEnd, comphelper::containerToSequence(aFrameProperties));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void startTable(unsigned int nDepth, const TablePropertyMapPtr& pProps);
|
void startTable(unsigned int nDepth, const TablePropertyMapPtr& pProps);
|
||||||
/// Handle end of table.
|
/// Handle end of table.
|
||||||
void endTable(unsigned int nestedTableLevel);
|
void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);
|
||||||
/**
|
/**
|
||||||
Handle start of row.
|
Handle start of row.
|
||||||
|
|
||||||
|
@ -233,6 +233,8 @@ DomainMapper_Impl::DomainMapper_Impl(
|
|||||||
m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
|
m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
|
||||||
m_bInTableStyleRunProps(false),
|
m_bInTableStyleRunProps(false),
|
||||||
m_nTableDepth(0),
|
m_nTableDepth(0),
|
||||||
|
m_nTableCellDepth(0),
|
||||||
|
m_nLastTableCellParagraphDepth(0),
|
||||||
m_bHasFtnSep(false),
|
m_bHasFtnSep(false),
|
||||||
m_bIgnoreNextPara(false),
|
m_bIgnoreNextPara(false),
|
||||||
m_bIgnoreNextTab(false),
|
m_bIgnoreNextTab(false),
|
||||||
@ -1034,6 +1036,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap )
|
|||||||
TagLogger::getInstance().startElement("finishParagraph");
|
TagLogger::getInstance().startElement("finishParagraph");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_nLastTableCellParagraphDepth = m_nTableCellDepth;
|
||||||
ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pPropertyMap.get() );
|
ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pPropertyMap.get() );
|
||||||
if (m_aTextAppendStack.empty())
|
if (m_aTextAppendStack.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -820,6 +820,10 @@ public:
|
|||||||
* inTbl SPRM or not).
|
* inTbl SPRM or not).
|
||||||
*/
|
*/
|
||||||
sal_Int32 m_nTableDepth;
|
sal_Int32 m_nTableDepth;
|
||||||
|
/// Raw table cell depth.
|
||||||
|
sal_Int32 m_nTableCellDepth;
|
||||||
|
/// Table cell depth of the last finished paragraph.
|
||||||
|
sal_Int32 m_nLastTableCellParagraphDepth;
|
||||||
|
|
||||||
/// If the document has a footnote separator.
|
/// If the document has a footnote separator.
|
||||||
bool m_bHasFtnSep;
|
bool m_bHasFtnSep;
|
||||||
|
@ -314,7 +314,7 @@ void TableManager::resolveCurrentTable()
|
|||||||
mpTableDataHandler->endRow();
|
mpTableDataHandler->endRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
mpTableDataHandler->endTable(mTableDataStack.size() - 1);
|
mpTableDataHandler->endTable(mTableDataStack.size() - 1, m_bTableStartsAtCellStart);
|
||||||
}
|
}
|
||||||
catch (css::uno::Exception const& e)
|
catch (css::uno::Exception const& e)
|
||||||
{
|
{
|
||||||
@ -454,8 +454,14 @@ void TableManager::cellDepth(sal_uInt32 nDepth)
|
|||||||
mnTableDepthNew = nDepth;
|
mnTableDepthNew = nDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TableManager::setTableStartsAtCellStart(bool bTableStartsAtCellStart)
|
||||||
|
{
|
||||||
|
m_bTableStartsAtCellStart = bTableStartsAtCellStart;
|
||||||
|
}
|
||||||
|
|
||||||
TableManager::TableManager()
|
TableManager::TableManager()
|
||||||
: mnTableDepthNew(0), mnTableDepth(0), mbKeepUnfinishedRow(false)
|
: mnTableDepthNew(0), mnTableDepth(0), mbKeepUnfinishedRow(false),
|
||||||
|
m_bTableStartsAtCellStart(false)
|
||||||
{
|
{
|
||||||
setRowEnd(false);
|
setRowEnd(false);
|
||||||
setInCell(false);
|
setInCell(false);
|
||||||
|
@ -275,6 +275,8 @@ private:
|
|||||||
std::stack<TableData::Pointer_t> mTableDataStack;
|
std::stack<TableData::Pointer_t> mTableDataStack;
|
||||||
RowData::Pointer_t mpUnfinishedRow;
|
RowData::Pointer_t mpUnfinishedRow;
|
||||||
bool mbKeepUnfinishedRow;
|
bool mbKeepUnfinishedRow;
|
||||||
|
/// If this is a nested table, does it start at cell start?
|
||||||
|
bool m_bTableStartsAtCellStart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
handler for resolveCurrentTable
|
handler for resolveCurrentTable
|
||||||
@ -476,6 +478,7 @@ public:
|
|||||||
bool isIgnore() const;
|
bool isIgnore() const;
|
||||||
|
|
||||||
|
|
||||||
|
void setTableStartsAtCellStart(bool bTableStartsAtCellStart);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1306,6 +1306,17 @@ OOXMLFastContextHandlerTextTableCell::~OOXMLFastContextHandlerTextTableCell()
|
|||||||
|
|
||||||
void OOXMLFastContextHandlerTextTableCell::startCell()
|
void OOXMLFastContextHandlerTextTableCell::startCell()
|
||||||
{
|
{
|
||||||
|
if (isForwardEvents())
|
||||||
|
{
|
||||||
|
OOXMLPropertySet * pProps = new OOXMLPropertySet;
|
||||||
|
{
|
||||||
|
OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
|
||||||
|
OOXMLProperty::Pointer_t pProp(new OOXMLProperty(NS_ooxml::LN_tcStart, pVal, OOXMLProperty::SPRM));
|
||||||
|
pProps->add(pProp);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpStream->props(writerfilter::Reference<Properties>::Pointer_t(pProps));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OOXMLFastContextHandlerTextTableCell::endCell()
|
void OOXMLFastContextHandlerTextTableCell::endCell()
|
||||||
@ -1328,6 +1339,11 @@ void OOXMLFastContextHandlerTextTableCell::endCell()
|
|||||||
OOXMLProperty::Pointer_t pProp(new OOXMLProperty(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM));
|
OOXMLProperty::Pointer_t pProp(new OOXMLProperty(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM));
|
||||||
pProps->add(pProp);
|
pProps->add(pProp);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
|
||||||
|
OOXMLProperty::Pointer_t pProp(new OOXMLProperty(NS_ooxml::LN_tcEnd, pVal, OOXMLProperty::SPRM));
|
||||||
|
pProps->add(pProp);
|
||||||
|
}
|
||||||
|
|
||||||
mpStream->props(writerfilter::Reference<Properties>::Pointer_t(pProps));
|
mpStream->props(writerfilter::Reference<Properties>::Pointer_t(pProps));
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ public:
|
|||||||
|
|
||||||
virtual std::string getType() const override { return "TextTableCell"; }
|
virtual std::string getType() const override { return "TextTableCell"; }
|
||||||
|
|
||||||
static void startCell();
|
void startCell();
|
||||||
void endCell();
|
void endCell();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
<token tokenid="ooxml:object"/>
|
<token tokenid="ooxml:object"/>
|
||||||
<token tokenid="ooxml:tblStart"/>
|
<token tokenid="ooxml:tblStart"/>
|
||||||
<token tokenid="ooxml:tblEnd"/>
|
<token tokenid="ooxml:tblEnd"/>
|
||||||
|
<token tokenid="ooxml:tcStart"/>
|
||||||
|
<token tokenid="ooxml:tcEnd"/>
|
||||||
|
|
||||||
<!-- These are not directly generated from OOXML XML elements / attributes, need to clean them up in the future. -->
|
<!-- These are not directly generated from OOXML XML elements / attributes, need to clean them up in the future. -->
|
||||||
<token tokenid="ooxml:tblDepth"/>
|
<token tokenid="ooxml:tblDepth"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user