sw/Library_sw.mk                         |    1 
 sw/inc/unocoll.hxx                       |    1 
 sw/qa/core/unocore/unocore.cxx           |   32 ++++
 sw/source/core/bastyp/init.cxx           |    2 
 sw/source/core/inc/unolinebreak.hxx      |   91 +++++++++++
 sw/source/core/txtnode/attrlinebreak.cxx |    1 
 sw/source/core/txtnode/thints.cxx        |    5 
 sw/source/core/unocore/unocoll.cxx       |    7 
 sw/source/core/unocore/unolinebreak.cxx  |  236 +++++++++++++++++++++++++++++++
 9 files changed, 374 insertions(+), 2 deletions(-)

New commits:
commit 461de6f712ebdc5a5a3f0e0563c50d92614f0760
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Mar 1 16:44:03 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Mar 25 13:41:59 2022 +0100

    sw clearing breaks: add UNO API to insert this
    
    This only allows the clear=all break type, the others are not yet
    handled.
    
    (cherry picked from commit 5028e5670da25ec1e8eeee62789b744c32e6108b)
    
    Conflicts:
            sw/qa/core/unocore/unocore.cxx
    
    Change-Id: Id4981b3cc0a8faca2166ad93827ae547f5539095
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132106
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 0f594e203f59..ef3a27b74458 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -482,6 +482,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/core/unocore/unoframe \
     sw/source/core/unocore/unoftn \
     sw/source/core/unocore/unoidx \
+    sw/source/core/unocore/unolinebreak \
     sw/source/core/unocore/unomap \
     sw/source/core/unocore/unomap1 \
     sw/source/core/unocore/unoobj \
diff --git a/sw/inc/unocoll.hxx b/sw/inc/unocoll.hxx
index ae16ab4ab7bc..821d50ab4a2c 100644
--- a/sw/inc/unocoll.hxx
+++ b/sw/inc/unocoll.hxx
@@ -176,6 +176,7 @@ enum class SwServiceType {
     VbaGlobals                      = 113,
     StyleTable                      = 114,
     StyleCell                       = 115,
+    LineBreak                       = 116,
 
     Invalid                         = USHRT_MAX
 };
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index a480a082f975..ddf8d4bb5362 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -23,6 +23,8 @@
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
 #include <view.hxx>
+#include <ndtxt.hxx>
+#include <textlinebreak.hxx>
 
 using namespace ::com::sun::star;
 
@@ -215,6 +217,36 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testBrokenEmbeddedObject)
         
xEmbeddedObject->supportsService("com.sun.star.comp.embed.OCommonEmbeddedObject"));
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testLineBreakInsert)
+{
+    // Given an empty document:
+    SwDoc* pDoc = createSwDoc();
+
+    // When inserting a line-break with properties:
+    uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextContent> xLineBreak(
+        xMSF->createInstance("com.sun.star.text.LineBreak"), uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+    xText->insertTextContent(xCursor, xLineBreak, /*bAbsorb=*/false);
+
+    // Then make sure that both the line break and its matching text attribute 
is inserted:
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    SwNodeOffset nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+    SwTextNode* pTextNode = pDoc->GetNodes()[nIndex]->GetTextNode();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: "\n" (newline)
+    // - Actual  : "" (empty string)
+    // i.e. SwXLineBreak::attach() did not insert the newline + its text 
attribute.
+    CPPUNIT_ASSERT_EQUAL(OUString("\n"), pTextNode->GetText());
+    SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, 
RES_TXTATR_LINEBREAK);
+    CPPUNIT_ASSERT(pAttr);
+    auto pTextLineBreak = static_cast<SwTextLineBreak*>(pAttr);
+    auto& rFormatLineBreak = 
static_cast<SwFormatLineBreak&>(pTextLineBreak->GetAttr());
+    CPPUNIT_ASSERT_EQUAL(SwLineBreakClear::ALL, rFormatLineBreak.GetValue());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index b6703dcd1d0d..87cb7dfa3127 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -319,7 +319,7 @@ SfxItemInfo aSlotTab[] =
     { 0, false },                               // RES_TXTATR_FLYCNT
     { 0, false },                               // RES_TXTATR_FTN
     { 0, false },                               // RES_TXTATR_ANNOTATION
-    { 0, true },                           // RES_TXTATR_LINEBREAK
+    { 0, false },                               // RES_TXTATR_LINEBREAK
     { 0, true },                           // RES_TXTATR_DUMMY1
     { 0, true },                           // RES_TXTATR_DUMMY2
 
diff --git a/sw/source/core/inc/unolinebreak.hxx 
b/sw/source/core/inc/unolinebreak.hxx
new file mode 100644
index 000000000000..1eb939e24b68
--- /dev/null
+++ b/sw/source/core/inc/unolinebreak.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_CORE_INC_UNOLINEBREAK_HXX
+#define INCLUDED_SW_SOURCE_CORE_INC_UNOLINEBREAK_HXX
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+
+#include <unobaseclass.hxx>
+
+class SwDoc;
+class SwFormatLineBreak;
+
+/// UNO API wrapper around an SwFormatLineBreak, exposed as the 
com.sun.star.text.LineBreak service.
+class SwXLineBreak final
+    : public cppu::WeakImplHelper<css::beans::XPropertySet, 
css::lang::XServiceInfo,
+                                  css::text::XTextContent, 
css::lang::XUnoTunnel>
+{
+    class Impl;
+    ::sw::UnoImplPtr<Impl> m_pImpl;
+
+    SwXLineBreak(SwFormatLineBreak& rFormat);
+    SwXLineBreak();
+
+    ~SwXLineBreak() override;
+
+public:
+    static css::uno::Reference<css::text::XTextContent> CreateXLineBreak();
+
+    // XPropertySet
+    css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL 
getPropertySetInfo() override;
+    void SAL_CALL setPropertyValue(const OUString& rPropertyName,
+                                   const css::uno::Any& rValue) override;
+    css::uno::Any SAL_CALL getPropertyValue(const OUString& rPropertyName) 
override;
+    void SAL_CALL addPropertyChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XPropertyChangeListener>& 
xListener) override;
+    void SAL_CALL removePropertyChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XPropertyChangeListener>& 
xListener) override;
+    void SAL_CALL addVetoableChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XVetoableChangeListener>& 
xListener) override;
+    void SAL_CALL removeVetoableChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XVetoableChangeListener>& 
xListener) override;
+
+    // XServiceInfo
+    OUString SAL_CALL getImplementationName() override;
+    sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
+    css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+    // XTextContent
+    void SAL_CALL attach(const css::uno::Reference<css::text::XTextRange>& 
xTextRange) override;
+    css::uno::Reference<css::text::XTextRange> SAL_CALL getAnchor() override;
+
+    // XComponent, via XTextContent
+    void SAL_CALL dispose() override;
+    void SAL_CALL
+    addEventListener(const css::uno::Reference<css::lang::XEventListener>& 
xListener) override;
+    void SAL_CALL
+    removeEventListener(const css::uno::Reference<css::lang::XEventListener>& 
xListener) override;
+
+    // XUnoTunnel
+    sal_Int64 SAL_CALL getSomething(const css::uno::Sequence<sal_Int8>& 
rIdentifier) override;
+
+    static const css::uno::Sequence<sal_Int8>& getUnoTunnelId();
+};
+
+#endif // INCLUDED_SW_SOURCE_CORE_INC_UNOLINEBREAK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/attrlinebreak.cxx 
b/sw/source/core/txtnode/attrlinebreak.cxx
index 64aedd9d2be1..f0f583ecc2df 100644
--- a/sw/source/core/txtnode/attrlinebreak.cxx
+++ b/sw/source/core/txtnode/attrlinebreak.cxx
@@ -104,6 +104,7 @@ SwTextLineBreak::SwTextLineBreak(SwFormatLineBreak& rAttr, 
sal_Int32 nStartPos)
     : SwTextAttr(rAttr, nStartPos)
 {
     rAttr.SetTextLineBreak(this);
+    SetHasDummyChar(true);
 }
 
 SwTextLineBreak::~SwTextLineBreak() {}
diff --git a/sw/source/core/txtnode/thints.cxx 
b/sw/source/core/txtnode/thints.cxx
index bdf954d27e40..7a31b1061333 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -3476,6 +3476,11 @@ sal_Unicode GetCharOfTextAttr( const SwTextAttr& rAttr )
             cRet = CH_TXTATR_BREAKWORD;
         }
         break;
+        case RES_TXTATR_LINEBREAK:
+        {
+            cRet = CH_TXTATR_NEWLINE;
+        }
+        break;
 
         default:
             assert(!"GetCharOfTextAttr: unknown attr");
diff --git a/sw/source/core/unocore/unocoll.cxx 
b/sw/source/core/unocore/unocoll.cxx
index 5edf059d4885..cb7a0bbb390f 100644
--- a/sw/source/core/unocore/unocoll.cxx
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -43,6 +43,7 @@
 #include <unoframe.hxx>
 #include <textboxhelper.hxx>
 #include <unofootnote.hxx>
+#include <unolinebreak.hxx>
 #include <vcl/svapp.hxx>
 #include <fmtcntnt.hxx>
 #include <authfld.hxx>
@@ -453,7 +454,8 @@ const ProvNamesId_Type aProvNamesId[] =
     { CSS_TEXT_FIELDMASTER_DATABASE,                  
SwServiceType::FieldMasterDatabase },
     { CSS_TEXT_FIELDMASTER_BIBLIOGRAPHY,              
SwServiceType::FieldMasterBibliography },
     { "com.sun.star.style.TableStyle",                
SwServiceType::StyleTable },
-    { "com.sun.star.style.CellStyle",                 SwServiceType::StyleCell 
}
+    { "com.sun.star.style.CellStyle",                 SwServiceType::StyleCell 
},
+    { "com.sun.star.text.LineBreak",                  SwServiceType::LineBreak 
}
 };
 
 const SvEventDescription* sw_GetSupportedMacroItems()
@@ -823,6 +825,9 @@ SwXServiceProvider::MakeInstance(SwServiceType nObjectType, 
SwDoc & rDoc)
         case SwServiceType::FieldTypeMetafield:
             xRet = SwXMeta::CreateXMeta(rDoc, true);
         break;
+        case SwServiceType::LineBreak:
+            xRet = SwXLineBreak::CreateXLineBreak();
+        break;
         default:
             throw uno::RuntimeException();
     }
diff --git a/sw/source/core/unocore/unolinebreak.cxx 
b/sw/source/core/unocore/unolinebreak.cxx
new file mode 100644
index 000000000000..1d44a273df5d
--- /dev/null
+++ b/sw/source/core/unocore/unolinebreak.cxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <unolinebreak.hxx>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <sal/log.hxx>
+#include <svl/listener.hxx>
+
+#include <IDocumentContentOperations.hxx>
+#include <doc.hxx>
+#include <formatlinebreak.hxx>
+#include <unotextrange.hxx>
+#include <ndtxt.hxx>
+#include <textlinebreak.hxx>
+
+using namespace com::sun::star;
+
+class SwXLineBreak::Impl : public SvtListener
+{
+public:
+    SwXLineBreak& m_rThis;
+    uno::WeakReference<uno::XInterface> m_wThis;
+    bool m_bIsDescriptor;
+    SwFormatLineBreak* m_pFormatLineBreak;
+
+    Impl(SwXLineBreak& rThis, SwFormatLineBreak* const pLineBreak)
+        : m_rThis(rThis)
+        , m_bIsDescriptor(pLineBreak == nullptr)
+        , m_pFormatLineBreak(pLineBreak)
+    {
+        if (m_pFormatLineBreak)
+        {
+            StartListening(m_pFormatLineBreak->GetNotifier());
+        }
+    }
+
+    void Invalidate();
+
+protected:
+    void Notify(const SfxHint& rHint) override;
+};
+
+void SwXLineBreak::Impl::Invalidate()
+{
+    EndListeningAll();
+    m_pFormatLineBreak = nullptr;
+}
+
+void SwXLineBreak::Impl::Notify(const SfxHint& rHint)
+{
+    if (rHint.GetId() == SfxHintId::Dying)
+    {
+        Invalidate();
+    }
+}
+
+SwXLineBreak::SwXLineBreak(SwFormatLineBreak& rFormat)
+    : m_pImpl(new SwXLineBreak::Impl(*this, &rFormat))
+{
+}
+
+SwXLineBreak::SwXLineBreak()
+    : m_pImpl(new SwXLineBreak::Impl(*this, nullptr))
+{
+}
+
+SwXLineBreak::~SwXLineBreak() {}
+
+uno::Reference<text::XTextContent> SwXLineBreak::CreateXLineBreak()
+{
+    uno::Reference<text::XTextContent> xLineBreak;
+
+    rtl::Reference<SwXLineBreak> pLineBreak(new SwXLineBreak);
+    xLineBreak.set(pLineBreak);
+    pLineBreak->m_pImpl->m_wThis = xLineBreak;
+
+    return xLineBreak;
+}
+
+OUString SAL_CALL SwXLineBreak::getImplementationName() { return 
"SwXLineBreak"; }
+
+sal_Bool SAL_CALL SwXLineBreak::supportsService(const OUString& rServiceName)
+{
+    return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL SwXLineBreak::getSupportedServiceNames()
+{
+    return { "com.sun.star.text.LineBreak" };
+}
+
+void SAL_CALL SwXLineBreak::attach(const uno::Reference<text::XTextRange>& 
xTextRange)
+{
+    SolarMutexGuard aGuard;
+    if (!m_pImpl->m_bIsDescriptor)
+    {
+        throw uno::RuntimeException();
+    }
+
+    uno::Reference<lang::XUnoTunnel> xRangeTunnel(xTextRange, uno::UNO_QUERY);
+    auto pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+    if (!pRange)
+    {
+        throw lang::IllegalArgumentException();
+    }
+
+    SwDoc& rNewDoc = pRange->GetDoc();
+    SwUnoInternalPaM aPam(rNewDoc);
+    sw::XTextRangeToSwPaM(aPam, xTextRange);
+    UnoActionContext aContext(&rNewDoc);
+    SwFormatLineBreak aLineBreak(SwLineBreakClear::ALL);
+    SetAttrMode nInsertFlags = SetAttrMode::DEFAULT;
+    rNewDoc.getIDocumentContentOperations().InsertPoolItem(aPam, aLineBreak, 
nInsertFlags);
+    auto pTextAttr
+        = 
static_cast<SwTextLineBreak*>(aPam.GetNode().GetTextNode()->GetTextAttrForCharAt(
+            aPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_LINEBREAK));
+    if (pTextAttr)
+    {
+        m_pImpl->EndListeningAll();
+        auto pLineBreak = 
const_cast<SwFormatLineBreak*>(&pTextAttr->GetLineBreak());
+        m_pImpl->m_pFormatLineBreak = pLineBreak;
+        m_pImpl->StartListening(pLineBreak->GetNotifier());
+    }
+    m_pImpl->m_bIsDescriptor = false;
+}
+
+uno::Reference<text::XTextRange> SAL_CALL SwXLineBreak::getAnchor()
+{
+    SolarMutexGuard aGuard;
+
+    SAL_WARN("sw.uno", "SwXLineBreak::getAnnchor: not implemented");
+
+    return {};
+}
+
+void SAL_CALL SwXLineBreak::dispose()
+{
+    SolarMutexGuard aGuard;
+
+    SAL_WARN("sw.uno", "SwXLineBreak::dispose: not implemented");
+}
+
+void SAL_CALL
+SwXLineBreak::addEventListener(const uno::Reference<lang::XEventListener>& 
/*xListener*/)
+{
+}
+
+void SAL_CALL
+SwXLineBreak::removeEventListener(const uno::Reference<lang::XEventListener>& 
/*xListener*/)
+{
+}
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL 
SwXLineBreak::getPropertySetInfo()
+{
+    SolarMutexGuard aGuard;
+
+    SAL_WARN("sw.uno", "SwXLineBreak::getPropertySetInfo: not implemented");
+
+    return {};
+}
+
+void SAL_CALL SwXLineBreak::setPropertyValue(const OUString& /*rPropertyName*/,
+                                             const css::uno::Any& /*rValue*/)
+{
+    SolarMutexGuard aGuard;
+
+    SAL_WARN("sw.uno", "SwXLineBreak::setPropertySetInfo: not implemented");
+}
+
+uno::Any SAL_CALL SwXLineBreak::getPropertyValue(const OUString& 
/*rPropertyName*/)
+{
+    SolarMutexGuard aGuard;
+
+    SAL_WARN("sw.uno", "SwXLineBreak::getPropertyValue: not implemented");
+
+    return {};
+}
+
+void SAL_CALL SwXLineBreak::addPropertyChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XPropertyChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXLineBreak::addPropertyChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXLineBreak::removePropertyChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XPropertyChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXLineBreak::removePropertyChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXLineBreak::addVetoableChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XVetoableChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXLineBreak::addVetoableChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXLineBreak::removeVetoableChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XVetoableChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXLineBreak::removeVetoableChangeListener: not 
implemented");
+}
+
+sal_Int64 SAL_CALL SwXLineBreak::getSomething(const 
css::uno::Sequence<sal_Int8>& rIdentifier)
+{
+    return comphelper::getSomethingImpl<SwXLineBreak>(rIdentifier, this);
+}
+
+const uno::Sequence<sal_Int8>& SwXLineBreak::getUnoTunnelId()
+{
+    static const comphelper::UnoIdInit theSwXLineBreakUnoTunnelId;
+    return theSwXLineBreakUnoTunnelId.getSeq();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to