writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx    |   34 ++++++++
 writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx |binary
 writerfilter/source/dmapper/DomainMapper.cxx                  |   18 +++-
 writerfilter/source/dmapper/DomainMapper_Impl.cxx             |   38 ++++++++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx             |    8 ++
 writerfilter/source/ooxml/Handler.cxx                         |    9 ++
 writerfilter/source/ooxml/Handler.hxx                         |    3 
 writerfilter/source/ooxml/OOXMLFastContextHandler.cxx         |    2 
 writerfilter/source/ooxml/OOXMLParserState.cxx                |    2 
 9 files changed, 106 insertions(+), 8 deletions(-)

New commits:
commit f86d1482bef285f90079b5130e410646db96cf58
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Mar 8 08:42:44 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Mar 8 12:25:55 2022 +0100

    sw clearing breaks: add DOCX import
    
    Map <w:br w:clear="..."> to the com.sun.star.text.LineBreak UNO service,
    but keep the default clear=none case unchanged.
    
    Change-Id: I145e891c1df0bbd0fdac2c62463dc801bca827fb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131167
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
index a161c3514a17..16039f98370a 100644
--- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
@@ -284,6 +284,40 @@ CPPUNIT_TEST_FIXTURE(Test, testPasteOle)
     uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), 
uno::UNO_QUERY);
     CPPUNIT_ASSERT_EQUAL(OUString("hello"), xPara->getString());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testClearingBreak)
+{
+    // Given a document with a clearing break:
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"clearing-break.docx";
+
+    // When loading that file:
+    getComponent() = loadFromDesktop(aURL);
+
+    // Then make sure that the clear property of the break is not ignored:
+    uno::Reference<text::XTextDocument> xTextDocument(getComponent(), 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextDocument->getText();
+    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xText, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParagraphs = 
xParaEnumAccess->createEnumeration();
+    uno::Reference<container::XEnumerationAccess> 
xParagraph(xParagraphs->nextElement(),
+                                                             uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xPortions = 
xParagraph->createEnumeration();
+    xPortions->nextElement();
+    xPortions->nextElement();
+    // Without the accompanying fix in place, this test would have failed with:
+    // An uncaught exception of type 
com.sun.star.container.NoSuchElementException
+    // i.e. the first para was just a fly + text portion, the clearing break 
was lost.
+    uno::Reference<beans::XPropertySet> xPortion(xPortions->nextElement(), 
uno::UNO_QUERY);
+    OUString aPortionType;
+    xPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+    CPPUNIT_ASSERT_EQUAL(OUString("LineBreak"), aPortionType);
+    uno::Reference<text::XTextContent> xLineBreak;
+    xPortion->getPropertyValue("LineBreak") >>= xLineBreak;
+    sal_Int16 eClear{};
+    uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, 
uno::UNO_QUERY);
+    xLineBreakProps->getPropertyValue("Clear") >>= eClear;
+    // SwLineBreakClear::ALL
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3), eClear);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx 
b/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx
new file mode 100644
index 000000000000..453a4c2b83d1
Binary files /dev/null and 
b/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index eed7ab8d45b0..f261538a0f19 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -749,9 +749,12 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
         case NS_ooxml::LN_CT_SmartTagRun_element:
             m_pImpl->getSmartTagHandler().setElement(val.getString());
         break;
-        case NS_ooxml::LN_CT_Br_type :
-            //TODO: attributes for break (0x12) are not supported
-        break;
+        case NS_ooxml::LN_CT_Br_type:
+            // Handled in the OOXMLBreakHandler dtor.
+            break;
+        case NS_ooxml::LN_CT_Br_clear:
+            m_pImpl->HandleLineBreakClear(val.getInt());
+            break;
         case NS_ooxml::LN_CT_Fonts_hint :
             /*  assigns script type to ambiguous characters, values can be:
                 NS_ooxml::LN_Value_ST_Hint_default
@@ -3471,7 +3474,14 @@ void DomainMapper::lcl_text(const sal_uInt8 * data_, 
size_t len)
             if (pContext == nullptr)
                 pContext = new PropertyMap();
 
-            m_pImpl->appendTextPortion( sText, pContext );
+            if (sText == "\n")
+            {
+                m_pImpl->HandleLineBreak(pContext);
+            }
+            else
+            {
+                m_pImpl->appendTextPortion(sText, pContext);
+            }
         }
     }
     catch( const uno::RuntimeException& )
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 882bd28086a6..bbbe68a01700 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -4004,6 +4004,44 @@ void DomainMapper_Impl::HandlePTab(sal_Int32 nAlignment)
     xTextAppend->insertControlCharacter(xCursor, 
text::ControlCharacter::LINE_BREAK, true);
 }
 
+void DomainMapper_Impl::HandleLineBreakClear(sal_Int32 nClear)
+{
+    switch (nClear)
+    {
+        case NS_ooxml::LN_Value_ST_BrClear_left:
+            // SwLineBreakClear::LEFT
+            m_oLineBreakClear = 1;
+            break;
+        case NS_ooxml::LN_Value_ST_BrClear_right:
+            // SwLineBreakClear::RIGHT
+            m_oLineBreakClear = 2;
+            break;
+        case NS_ooxml::LN_Value_ST_BrClear_all:
+            // SwLineBreakClear::ALL
+            m_oLineBreakClear = 3;
+            break;
+    }
+}
+
+void DomainMapper_Impl::HandleLineBreak(const PropertyMapPtr& pPropertyMap)
+{
+    if (!m_oLineBreakClear.has_value())
+    {
+        appendTextPortion("\n", pPropertyMap);
+        return;
+    }
+
+    if (GetTextFactory().is())
+    {
+        uno::Reference<text::XTextContent> xLineBreak(
+            GetTextFactory()->createInstance("com.sun.star.text.LineBreak"), 
uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, 
uno::UNO_QUERY);
+        xLineBreakProps->setPropertyValue("Clear", 
uno::makeAny(*m_oLineBreakClear));
+        appendTextContent(xLineBreak, pPropertyMap->GetPropertyValues());
+    }
+    m_oLineBreakClear.reset();
+}
+
 static sal_Int16 lcl_ParseNumberingType( const OUString& rCommand )
 {
     sal_Int16 nRet = style::NumberingType::PAGE_DESCRIPTOR;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index bbd5d566367e..869d0cdf1ece 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -633,6 +633,8 @@ private:
     bool m_bIsNewDoc;
     bool m_bIsAltChunk = false;
     bool m_bIsReadGlossaries;
+    std::optional<sal_Int16> m_oLineBreakClear;
+
 public:
     DomainMapper_Impl(
             DomainMapper& rDMapper,
@@ -1169,6 +1171,12 @@ public:
     /// Handles <w:ptab>.
     void HandlePTab(sal_Int32 nAlignment);
 
+    /// Handles <w:br w:clear="...">.
+    void HandleLineBreakClear(sal_Int32 nClear);
+
+    /// Handles <w:br>.
+    void HandleLineBreak(const PropertyMapPtr& pPropertyMap);
+
     void commentProps(const OUString& sId, const CommentProperties& rProps);
 
 private:
diff --git a/writerfilter/source/ooxml/Handler.cxx 
b/writerfilter/source/ooxml/Handler.cxx
index d58453c8ee32..7cbd9b6bfdc3 100644
--- a/writerfilter/source/ooxml/Handler.cxx
+++ b/writerfilter/source/ooxml/Handler.cxx
@@ -236,14 +236,21 @@ void OOXMLHeaderHandler::sprm(Sprm & /*sprm*/)
 /*
   class OOXMLBreakHandler
  */
-OOXMLBreakHandler::OOXMLBreakHandler(Stream &rStream)
+OOXMLBreakHandler::OOXMLBreakHandler(OOXMLFastContextHandler* pContext, Stream 
&rStream)
 : mnType(0),
+  mpFastContext(pContext),
   mrStream(rStream)
 {
 }
 
 OOXMLBreakHandler::~OOXMLBreakHandler()
 {
+    if (mpFastContext)
+    {
+        mrStream.props(mpFastContext->getPropertySet().get());
+        mpFastContext->clearProps();
+    }
+
     sal_uInt8 tmpBreak[1];
     switch (mnType)
     {
diff --git a/writerfilter/source/ooxml/Handler.hxx 
b/writerfilter/source/ooxml/Handler.hxx
index 42ea025538f0..df6673d44318 100644
--- a/writerfilter/source/ooxml/Handler.hxx
+++ b/writerfilter/source/ooxml/Handler.hxx
@@ -111,10 +111,11 @@ public:
 class OOXMLBreakHandler : public Properties
 {
     sal_Int32 mnType;
+    OOXMLFastContextHandler* mpFastContext;
     Stream& mrStream;
 
 public:
-    explicit OOXMLBreakHandler(Stream& rStream);
+    explicit OOXMLBreakHandler(OOXMLFastContextHandler* pContext, Stream& 
rStream);
     virtual ~OOXMLBreakHandler() override;
     virtual void attribute(Id name, Value& val) override;
     virtual void sprm(Sprm& sprm) override;
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx 
b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index aa9de6408202..e6aa15298c05 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -1117,7 +1117,7 @@ void OOXMLFastContextHandlerProperties::handleBreak()
 {
     if(isForwardEvents())
     {
-        OOXMLBreakHandler aBreakHandler(*mpStream);
+        OOXMLBreakHandler aBreakHandler(this, *mpStream);
         getPropertySet()->resolve(aBreakHandler);
     }
 }
diff --git a/writerfilter/source/ooxml/OOXMLParserState.cxx 
b/writerfilter/source/ooxml/OOXMLParserState.cxx
index 3d35cbb9deac..a11afde8fb37 100644
--- a/writerfilter/source/ooxml/OOXMLParserState.cxx
+++ b/writerfilter/source/ooxml/OOXMLParserState.cxx
@@ -212,7 +212,7 @@ void OOXMLParserState::resolvePostponedBreak(Stream & 
rStream)
 {
     for (const auto & rBreak: mvPostponedBreaks)
     {
-        OOXMLBreakHandler aBreakHandler(rStream);
+        OOXMLBreakHandler aBreakHandler(nullptr, rStream);
         rBreak->resolve(aBreakHandler);
     }
     mvPostponedBreaks.clear();

Reply via email to