From 304dcd15d5ea5bac750249d5688372123565f9df Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Fri, 23 Jun 2017 14:48:03 +0300 Subject: tdf#108714: allow as direct child of MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LibreOffice doesn't accept element as a child of . ECMA-376-1:2016 17.3.3.1 describes br as element of a run content, and points to CT_Br in §A.1. CT_Br may appear only as part of EG_RunInnerContent. In turn, EG_RunInnerContent may appear only inside CT_R. So, using outside of produces ill-formed OOXML. Open XML SDK 2.5 Productivity Tool for Microsoft Office confirms that, showing OpenXmlUnknownElement error. However, Word accepts it as direct child of . It behaves as if the were used as first element in first run of the following (thus creating page break after next paragraph). Another Word bug that provokes third-parties to create ill-formed documents, and requires LibreOffice to be bug-to-bug compatible. This commit makes the following changes: 1. Registers a dedicated complex type CT_Br_OutOfOrder to handle those unusual breaks, with corresponding handler function. 2. In the handler function, saves the gathered property set to parser state to use later in next paragraph group handler. This reproduces Word behaviour. Change-Id: I5df6927e2de9266b58f87807319ad1c4977e45a7 Reviewed-on: https://gerrit.libreoffice.org/39168 Tested-by: Jenkins Reviewed-by: Mike Kaganski (cherry picked from commit a4a1467bc47b81ad68ecad0d5e2e163670582919) Reviewed-on: https://gerrit.libreoffice.org/39303 Tested-by: Mike Kaganski --- writerfilter/source/ooxml/OOXMLFastContextHandler.cxx | 13 +++++++++++++ writerfilter/source/ooxml/OOXMLFastContextHandler.hxx | 1 + writerfilter/source/ooxml/OOXMLParserState.cxx | 17 +++++++++++++++++ writerfilter/source/ooxml/OOXMLParserState.hxx | 4 ++++ writerfilter/source/ooxml/factoryimpl_ns.py | 2 +- writerfilter/source/ooxml/model.xml | 18 ++++++++++++++++++ 6 files changed, 54 insertions(+), 1 deletion(-) (limited to 'writerfilter/source') diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx index bb5ff5fa98fb..cd79f2c0454b 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx @@ -397,6 +397,10 @@ void OOXMLFastContextHandler::startParagraphGroup() { mpStream->startParagraphGroup(); mpParserState->setInParagraphGroup(true); + + // tdf#108714 : if we have a postponed break information, + // then apply it now, before any other paragraph content. + mpParserState->resolvePostponedBreak(*mpStream); } } } @@ -1061,6 +1065,15 @@ void OOXMLFastContextHandlerProperties::handleBreak() } } +// tdf#108714 : allow at block level (despite this is illegal according to ECMA-376-1:2016) +void OOXMLFastContextHandlerProperties::handleOutOfOrderBreak() +{ + if(isForwardEvents()) + { + mpParserState->setPostponedBreak(getPropertySet()); + } +} + void OOXMLFastContextHandlerProperties::handleOLE() { OOXMLOLEHandler aOLEHandler(this); diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx index f986c76029ae..e4e3e563fad5 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx @@ -278,6 +278,7 @@ public: void handleComment(); void handlePicture(); void handleBreak(); + void handleOutOfOrderBreak(); void handleOLE(); void handleFontRel(); void handleHyperlinkURL(); diff --git a/writerfilter/source/ooxml/OOXMLParserState.cxx b/writerfilter/source/ooxml/OOXMLParserState.cxx index 71d0290b707a..a655488e3194 100644 --- a/writerfilter/source/ooxml/OOXMLParserState.cxx +++ b/writerfilter/source/ooxml/OOXMLParserState.cxx @@ -20,6 +20,7 @@ #include #include #include "OOXMLParserState.hxx" +#include "Handler.hxx" namespace writerfilter { namespace ooxml @@ -210,6 +211,22 @@ void OOXMLParserState::setTableProperties(const OOXMLPropertySet::Pointer_t& pPr } } +// tdf#108714 +void OOXMLParserState::resolvePostponedBreak(Stream & rStream) +{ + if (mpPostponedBreak) + { + OOXMLBreakHandler aBreakHandler(rStream); + mpPostponedBreak->resolve(aBreakHandler); + mpPostponedBreak.reset(); + } +} + +void OOXMLParserState::setPostponedBreak(const OOXMLPropertySet::Pointer_t & pProps) +{ + mpPostponedBreak = pProps; +} + void OOXMLParserState::startTable() { OOXMLPropertySet::Pointer_t pCellProps; diff --git a/writerfilter/source/ooxml/OOXMLParserState.hxx b/writerfilter/source/ooxml/OOXMLParserState.hxx index 0ba0079d1653..d328b07b2835 100644 --- a/writerfilter/source/ooxml/OOXMLParserState.hxx +++ b/writerfilter/source/ooxml/OOXMLParserState.hxx @@ -59,6 +59,7 @@ class OOXMLParserState final bool savedInCharacterGroup; bool savedLastParagraphInSection; std::vector maSavedAlternateStates; + OOXMLPropertySet::Pointer_t mpPostponedBreak; public: typedef std::shared_ptr Pointer_t; @@ -102,6 +103,9 @@ public: void setRowProperties(const OOXMLPropertySet::Pointer_t& pProps); void resolveTableProperties(Stream & rStream); void setTableProperties(const OOXMLPropertySet::Pointer_t& pProps); + // tdf#108714 + void resolvePostponedBreak(Stream & rStream); + void setPostponedBreak(const OOXMLPropertySet::Pointer_t& pProps); void startTable(); void endTable(); diff --git a/writerfilter/source/ooxml/factoryimpl_ns.py b/writerfilter/source/ooxml/factoryimpl_ns.py index cee40a75bd45..74ee6e8e3d25 100644 --- a/writerfilter/source/ooxml/factoryimpl_ns.py +++ b/writerfilter/source/ooxml/factoryimpl_ns.py @@ -428,7 +428,7 @@ def factoryChooseAction(actionNode): ret.append(" {") extra_space = " " - if actionNode.getAttribute("action") in ("handleXNotes", "handleHdrFtr", "handleComment", "handlePicture", "handleBreak", "handleOLE", "handleFontRel", "handleHyperlinkURL"): + if actionNode.getAttribute("action") in ("handleXNotes", "handleHdrFtr", "handleComment", "handlePicture", "handleBreak", "handleOutOfOrderBreak", "handleOLE", "handleFontRel", "handleHyperlinkURL"): ret.append(" %sif (OOXMLFastContextHandlerProperties* pProperties = dynamic_cast(pHandler))" % extra_space) ret.append(" %s pProperties->%s();" % (extra_space, actionNode.getAttribute("action"))) elif actionNode.getAttribute("action") == "propagateCharacterPropertiesAsSet": diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index d132f03ed72f..5318d7d3c819 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -13224,6 +13224,14 @@ + + + + + + + + @@ -13963,6 +13971,11 @@ + + + + + @@ -17842,6 +17855,11 @@ + + + + + left center -- cgit