From cf33af732ed0d3d553bb74636e3b14c55d44c153 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Wed, 23 Apr 2014 14:34:54 +0200 Subject: handle w:gridBefore by faking cells (fdo#38414) Docx's w:gridBefore means that there should be this given space in the table grid before any cells come. But writer requires tables to be rectangular, so the space needs to be faked using cells without border. So far so good, but now reality in the form of the retarded overdesigned writerfilter comes. The internal representation of table data (and not just one actually) is pretty non-obvious and hard to modify, seems to be modelled just to follow the parser data the way it comes. Moreover dmapper gets notified of w:gridBefore only after cells in the row have been already processed. So after futile attempts to add the fake cells somehow in dmapper I've eventually given up and hacked up input handling to fake input as if the fake cells were actually there (which was tedious to find out as well, but at least it's reasonably doable). Change-Id: I7107e13f28dd3f7093688782f64238167cead76f --- .../source/ooxml/OOXMLFastContextHandler.cxx | 79 ++++++++++++++++++++++ .../source/ooxml/OOXMLFastContextHandler.hxx | 3 + writerfilter/source/ooxml/factoryimpl_ns.xsl | 4 ++ writerfilter/source/ooxml/model.xml | 12 +++- 4 files changed, 96 insertions(+), 2 deletions(-) (limited to 'writerfilter') diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx index a8ecda389d99..0506136769cf 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx @@ -1966,6 +1966,85 @@ void OOXMLFastContextHandlerTextTableRow::endRow() endParagraphGroup(); } +// Handle w:gridBefore here by faking necessary input that'll fake cells. I'm apparently +// not insane enough to find out how to add cells in dmapper. +void OOXMLFastContextHandlerTextTableRow::handleGridBefore( OOXMLValue::Pointer_t val ) +{ + int count = val->getInt(); + for( int i = 0; + i < count; + ++i ) + { + endOfParagraph(); + + if (isForwardEvents()) + { + // This whole part is OOXMLFastContextHandlerTextTableCell::endCell() . + OOXMLPropertySet * pProps = new OOXMLPropertySetImpl(); + { + OOXMLValue::Pointer_t pVal + (new OOXMLIntegerValue(mnTableDepth)); + OOXMLProperty::Pointer_t pProp + (new OOXMLPropertyImpl(NS_ooxml::LN_tblDepth, pVal, OOXMLPropertyImpl::SPRM)); + pProps->add(pProp); + } + { + OOXMLValue::Pointer_t pVal + (new OOXMLIntegerValue(1)); + OOXMLProperty::Pointer_t pProp + (new OOXMLPropertyImpl(NS_ooxml::LN_inTbl, pVal, OOXMLPropertyImpl::SPRM)); + pProps->add(pProp); + } + { + OOXMLValue::Pointer_t pVal + (new OOXMLBooleanValue(mnTableDepth > 0)); + OOXMLProperty::Pointer_t pProp + (new OOXMLPropertyImpl(NS_ooxml::LN_tblCell, pVal, OOXMLPropertyImpl::SPRM)); + pProps->add(pProp); + } + + #ifdef DEBUG_PROPERTIES + debug_logger->startElement("handlegridbefore"); + debug_logger->propertySet(OOXMLPropertySet::Pointer_t(pProps->clone()), + IdToString::Pointer_t(new OOXMLIdToString())); + debug_logger->endElement(); + #endif + mpStream->props(writerfilter::Reference::Pointer_t(pProps)); + + // fake with no border + OOXMLPropertySet::Pointer_t pCellProps( new OOXMLPropertySetImpl()); + { + OOXMLPropertySet::Pointer_t pBorderProps( new OOXMLPropertySetImpl()); + static Id borders[] = { NS_ooxml::LN_CT_TcBorders_top, NS_ooxml::LN_CT_TcBorders_bottom, + NS_ooxml::LN_CT_TcBorders_start, NS_ooxml::LN_CT_TcBorders_end }; + for( size_t j = 0; j < SAL_N_ELEMENTS( borders ); ++j ) + pBorderProps->add( fakeNoBorder( borders[ j ] )); + OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pBorderProps )); + OOXMLProperty::Pointer_t pProp + (new OOXMLPropertyImpl(NS_ooxml::LN_CT_TcPrBase_tcBorders, pValue, OOXMLPropertyImpl::SPRM)); + pCellProps->add(pProp); + mpParserState->setCellProperties(pCellProps); + } + } + + sendCellProperties(); + endParagraphGroup(); + } +} + +OOXMLProperty::Pointer_t OOXMLFastContextHandlerTextTableRow::fakeNoBorder( Id id ) +{ + OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySetImpl()); + OOXMLValue::Pointer_t pVal(new OOXMLIntegerValue(0)); + OOXMLProperty::Pointer_t pPropVal + (new OOXMLPropertyImpl(NS_ooxml::LN_CT_Border_val, pVal, OOXMLPropertyImpl::ATTRIBUTE)); + pProps->add(pPropVal); + OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pProps )); + OOXMLProperty::Pointer_t pProp + (new OOXMLPropertyImpl(id, pValue, OOXMLPropertyImpl::SPRM)); + return pProp; +} + /* class OOXMLFastContextHandlerTextTable */ diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx index dd8d99766d9b..799395f4be3e 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx @@ -491,6 +491,9 @@ public: void startRow(); void endRow(); + void handleGridBefore( OOXMLValue::Pointer_t val ); +private: + OOXMLProperty::Pointer_t fakeNoBorder( Id id ); }; class OOXMLFastContextHandlerTextTable : public OOXMLFastContextHandler diff --git a/writerfilter/source/ooxml/factoryimpl_ns.xsl b/writerfilter/source/ooxml/factoryimpl_ns.xsl index 9cb8912dc72a..d932008eb5c8 100644 --- a/writerfilter/source/ooxml/factoryimpl_ns.xsl +++ b/writerfilter/source/ooxml/factoryimpl_ns.xsl @@ -476,6 +476,10 @@ CreateElementMapPointer (); + + + dynamic_cast<OOXMLFastContextHandlerTextTableRow*>(pHandler)->handleGridBefore(); + dynamic_cast<OOXMLFastContextHandlerStream*>(pHandler)-> diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 16039bc63898..11ed808c5a8c 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -19563,7 +19563,7 @@ - + @@ -19614,6 +19614,11 @@ + + + + + @@ -24766,7 +24771,7 @@ - + @@ -24777,6 +24782,9 @@ + + + -- cgit