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 5028e5670da25ec1e8eeee62789b744c32e6108b Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Mar 1 16:44:03 2022 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Mar 1 19:52:31 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. Change-Id: Id4981b3cc0a8faca2166ad93827ae547f5539095 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130741 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index 401ac0d307fd..30c53b6131b1 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -489,6 +489,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 55bfa1425528..b7d92d8485ac 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -22,6 +22,8 @@ #include <unotextrange.hxx> #include <unotxdoc.hxx> #include <docsh.hxx> +#include <ndtxt.hxx> +#include <textlinebreak.hxx> using namespace ::com::sun::star; @@ -214,6 +216,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 9bbe888ba3b9..f7ad215602bf 100644 --- a/sw/source/core/bastyp/init.cxx +++ b/sw/source/core/bastyp/init.cxx @@ -320,7 +320,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 4ca96f593cb4..a04a427826fa 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: */