summaryrefslogtreecommitdiffstats
path: root/sw/source/core/unocore/unoidx.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/core/unocore/unoidx.cxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/unocore/unoidx.cxx')
-rw-r--r--sw/source/core/unocore/unoidx.cxx3086
1 files changed, 3086 insertions, 0 deletions
diff --git a/sw/source/core/unocore/unoidx.cxx b/sw/source/core/unocore/unoidx.cxx
new file mode 100644
index 0000000000..3617c22b8d
--- /dev/null
+++ b/sw/source/core/unocore/unoidx.cxx
@@ -0,0 +1,3086 @@
+/* -*- 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 <memory>
+#include <unoidx.hxx>
+#include <unoidxcoll.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/BibliographyDataField.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+
+#include <comphelper/interfacecontainer4.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/UnitConversion.hxx>
+#include <vcl/svapp.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <editeng/memberids.h>
+#include <swtypes.hxx>
+#include <shellres.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <unomap.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unosection.hxx>
+#include <doctxm.hxx>
+#include <txttxmrk.hxx>
+#include <ndtxt.hxx>
+#include <docsh.hxx>
+#include <chpfld.hxx>
+#include <editsh.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <strings.hrc>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/string.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <svl/itemprop.hxx>
+#include <svl/listener.hxx>
+#include <mutex>
+
+using namespace ::com::sun::star;
+
+/// @throws lang::IllegalArgumentException
+template<typename T>
+static T
+lcl_AnyToType(uno::Any const& rVal)
+{
+ T aRet{};
+ if(!(rVal >>= aRet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ return aRet;
+}
+
+/// @throws lang::IllegalArgumentException
+template<typename T>
+static void lcl_AnyToBitMask(uno::Any const& rValue,
+ T & rBitMask, const T nBit)
+{
+ rBitMask = lcl_AnyToType<bool>(rValue)
+ ? (rBitMask | nBit)
+ : (rBitMask & ~nBit);
+}
+
+template<typename T>
+static void lcl_BitMaskToAny(uno::Any & o_rValue,
+ const T nBitMask, const T nBit)
+{
+ const bool bRet(nBitMask & nBit);
+ o_rValue <<= bRet;
+}
+
+static void
+lcl_ReAssignTOXType(SwDoc& rDoc, SwTOXBase& rTOXBase, const OUString& rNewName)
+{
+ const sal_uInt16 nUserCount = rDoc.GetTOXTypeCount( TOX_USER );
+ const SwTOXType* pNewType = nullptr;
+ for(sal_uInt16 nUser = 0; nUser < nUserCount; nUser++)
+ {
+ const SwTOXType* pType = rDoc.GetTOXType( TOX_USER, nUser );
+ if (pType->GetTypeName()==rNewName)
+ {
+ pNewType = pType;
+ break;
+ }
+ }
+ if(!pNewType)
+ {
+ SwTOXType aNewType(rDoc, TOX_USER, rNewName);
+ pNewType = rDoc.InsertTOXType( aNewType );
+ }
+
+ rTOXBase.RegisterToTOXType( *const_cast<SwTOXType*>(pNewType) );
+}
+
+constexpr OUString cUserDefined = u"User-Defined"_ustr;
+const char cUserSuffix[] = " (user)";
+#define USER_LEN 12
+#define USER_AND_SUFFIXLEN 19
+
+static void lcl_ConvertTOUNameToProgrammaticName(OUString& rTmp)
+{
+ ShellResource* pShellRes = SwViewShell::GetShellRes();
+
+ if(rTmp==pShellRes->aTOXUserName)
+ {
+ rTmp = cUserDefined;
+ }
+ // if the version is not English but the alternative index's name is
+ // "User-Defined" a " (user)" is appended
+ else if(rTmp == cUserDefined)
+ {
+ rTmp += cUserSuffix;
+ }
+}
+
+static void
+lcl_ConvertTOUNameToUserName(OUString& rTmp)
+{
+ ShellResource* pShellRes = SwViewShell::GetShellRes();
+ if (rTmp == cUserDefined)
+ {
+ rTmp = pShellRes->aTOXUserName;
+ }
+ else if (pShellRes->aTOXUserName != cUserDefined &&
+ USER_AND_SUFFIXLEN == rTmp.getLength())
+ {
+ //make sure that in non-English versions the " (user)" suffix is removed
+ if (rTmp.startsWith(cUserDefined) &&
+ rTmp.match(cUserSuffix, USER_LEN))
+ {
+ rTmp = cUserDefined;
+ }
+ }
+}
+
+typedef ::cppu::WeakImplHelper
+< lang::XServiceInfo
+, container::XIndexReplace
+> SwXDocumentIndexStyleAccess_Base;
+
+class SwXDocumentIndex::StyleAccess_Impl
+ : public SwXDocumentIndexStyleAccess_Base
+{
+
+private:
+ /// can be destroyed threadsafely, so no UnoImplPtr here
+ ::rtl::Reference<SwXDocumentIndex> m_xParent;
+
+ virtual ~StyleAccess_Impl() override;
+
+public:
+ explicit StyleAccess_Impl(SwXDocumentIndex& rParentIdx);
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService(const OUString& rServiceName) override;
+ virtual uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() override;
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override;
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
+
+ // XIndexReplace
+ virtual void SAL_CALL
+ replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
+
+};
+
+typedef ::cppu::WeakImplHelper
+< lang::XServiceInfo
+, container::XIndexReplace
+> SwXDocumentIndexTokenAccess_Base;
+
+class SwXDocumentIndex::TokenAccess_Impl
+ : public SwXDocumentIndexTokenAccess_Base
+{
+
+private:
+ /// can be destroyed threadsafely, so no UnoImplPtr here
+ ::rtl::Reference<SwXDocumentIndex> m_xParent;
+
+ virtual ~TokenAccess_Impl() override;
+
+public:
+
+ explicit TokenAccess_Impl(SwXDocumentIndex& rParentIdx);
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService(const OUString& rServiceName) override;
+ virtual uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() override;
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override;
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
+
+ // XIndexReplace
+ virtual void SAL_CALL
+ replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
+
+};
+
+namespace {
+
+class SwDocIndexDescriptorProperties_Impl
+{
+private:
+ std::unique_ptr<SwTOXBase> m_pTOXBase;
+ OUString m_sUserTOXTypeName;
+
+public:
+ explicit SwDocIndexDescriptorProperties_Impl(SwTOXType const*const pType);
+
+ SwTOXBase & GetTOXBase() { return *m_pTOXBase; }
+ const OUString& GetTypeName() const { return m_sUserTOXTypeName; }
+ void SetTypeName(const OUString& rSet) { m_sUserTOXTypeName = rSet; }
+};
+
+}
+
+SwDocIndexDescriptorProperties_Impl::SwDocIndexDescriptorProperties_Impl(
+ SwTOXType const*const pType)
+{
+ SwForm aForm(pType->GetType());
+ m_pTOXBase.reset(new SwTOXBase(pType, aForm,
+ SwTOXElement::Mark, pType->GetTypeName()));
+ if(pType->GetType() == TOX_CONTENT || pType->GetType() == TOX_USER)
+ {
+ m_pTOXBase->SetLevel(MAXLEVEL);
+ }
+ m_sUserTOXTypeName = pType->GetTypeName();
+}
+
+static sal_uInt16
+lcl_TypeToPropertyMap_Index(const TOXTypes eType)
+{
+ switch (eType)
+ {
+ case TOX_INDEX: return PROPERTY_MAP_INDEX_IDX;
+ case TOX_CONTENT: return PROPERTY_MAP_INDEX_CNTNT;
+ case TOX_TABLES: return PROPERTY_MAP_INDEX_TABLES;
+ case TOX_ILLUSTRATIONS: return PROPERTY_MAP_INDEX_ILLUSTRATIONS;
+ case TOX_OBJECTS: return PROPERTY_MAP_INDEX_OBJECTS;
+ case TOX_AUTHORITIES: return PROPERTY_MAP_BIBLIOGRAPHY;
+ //case TOX_USER:
+ default:
+ return PROPERTY_MAP_INDEX_USER;
+ }
+}
+
+class SwXDocumentIndex::Impl final: public SvtListener
+{
+private:
+ SwSectionFormat* m_pFormat;
+
+public:
+ unotools::WeakReference<SwXDocumentIndex> m_wThis;
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper4
+ ::comphelper::OInterfaceContainerHelper4<util::XRefreshListener> m_RefreshListeners;
+ ::comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_EventListeners;
+ SfxItemPropertySet const& m_rPropSet;
+ const TOXTypes m_eTOXType;
+ bool m_bIsDescriptor;
+ SwDoc* m_pDoc;
+ std::optional<SwDocIndexDescriptorProperties_Impl> m_oProps;
+ uno::WeakReference<container::XIndexReplace> m_wStyleAccess;
+ uno::WeakReference<container::XIndexReplace> m_wTokenAccess;
+
+ Impl(SwDoc& rDoc, const TOXTypes eType, SwTOXBaseSection *const pBaseSection)
+ : m_pFormat(pBaseSection ? pBaseSection->GetFormat() : nullptr)
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Index(eType)))
+ , m_eTOXType(eType)
+ , m_bIsDescriptor(nullptr == pBaseSection)
+ , m_pDoc(&rDoc)
+ , m_oProps(m_bIsDescriptor
+ ? std::optional<SwDocIndexDescriptorProperties_Impl>(rDoc.GetTOXType(eType, 0))
+ : std::nullopt)
+ {
+ if(m_pFormat)
+ StartListening(m_pFormat->GetNotifier());
+ }
+
+ void SetSectionFormat(SwSectionFormat& rFormat)
+ {
+ EndListeningAll();
+ m_pFormat = &rFormat;
+ StartListening(rFormat.GetNotifier());
+ }
+
+ SwSectionFormat* GetSectionFormat() const {
+ return m_pFormat;
+ }
+
+ SwTOXBase & GetTOXSectionOrThrow() const
+ {
+ SwSectionFormat *const pSectionFormat(GetSectionFormat());
+ SwTOXBase *const pTOXSection( m_bIsDescriptor
+ ? &const_cast<SwDocIndexDescriptorProperties_Impl&>(*m_oProps).GetTOXBase()
+ : (pSectionFormat
+ ? static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection())
+ : nullptr));
+ if (!pTOXSection)
+ {
+ throw uno::RuntimeException(
+ "SwXDocumentIndex: disposed or invalid", nullptr);
+ }
+ return *pTOXSection;
+ }
+
+ sal_Int32 GetFormMax() const
+ {
+ SwTOXBase & rSection( GetTOXSectionOrThrow() );
+ return m_bIsDescriptor
+ ? SwForm::GetFormMaxLevel(m_eTOXType)
+ : rSection.GetTOXForm().GetFormMax();
+ }
+ virtual void Notify(const SfxHint&) override;
+
+};
+
+void SwXDocumentIndex::Impl::Notify(const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::SwLegacyModify)
+ {
+ auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ if(pLegacy->m_pOld && pLegacy->m_pOld->Which() == RES_REMOVE_UNO_OBJECT)
+ m_pFormat = nullptr;
+ }
+ else if(rHint.GetId() == SfxHintId::Dying)
+ m_pFormat = nullptr;
+ if(!m_pFormat)
+ {
+ EndListeningAll();
+ rtl::Reference<SwXDocumentIndex> const xThis(m_wThis);
+ if (!xThis.is())
+ { // fdo#72695: if UNO object is already dead, don't revive it with event
+ return;
+ }
+ std::unique_lock g(m_Mutex);
+ lang::EventObject const ev(xThis->getXWeak());
+ m_RefreshListeners.disposeAndClear(g, ev);
+ m_EventListeners.disposeAndClear(g, ev);
+ }
+}
+
+SwXDocumentIndex::SwXDocumentIndex(
+ SwTOXBaseSection & rBaseSection, SwDoc & rDoc)
+ : m_pImpl( new SwXDocumentIndex::Impl(
+ rDoc, rBaseSection.SwTOXBase::GetType(), & rBaseSection) )
+{
+}
+
+SwXDocumentIndex::SwXDocumentIndex(const TOXTypes eType, SwDoc& rDoc)
+ : m_pImpl( new SwXDocumentIndex::Impl(rDoc, eType, nullptr) )
+{
+}
+
+SwXDocumentIndex::~SwXDocumentIndex()
+{
+}
+
+rtl::Reference<SwXDocumentIndex>
+SwXDocumentIndex::CreateXDocumentIndex(
+ SwDoc & rDoc, SwTOXBaseSection * pSection, TOXTypes const eTypes)
+{
+ // re-use existing SwXDocumentIndex
+ // #i105557#: do not iterate over the registered clients: race condition
+ rtl::Reference<SwXDocumentIndex> xIndex;
+ if (pSection)
+ {
+ SwSectionFormat const *const pFormat = pSection->GetFormat();
+ xIndex = dynamic_cast<SwXDocumentIndex*>(pFormat->GetXObject().get().get());
+ }
+ if (!xIndex.is())
+ {
+ xIndex = pSection
+ ? new SwXDocumentIndex(*pSection, rDoc)
+ : new SwXDocumentIndex(eTypes, rDoc);
+ if (pSection)
+ {
+ pSection->GetFormat()->SetXObject(xIndex->getXWeak());
+ }
+ // need a permanent Reference to initialize m_wThis
+ xIndex->m_pImpl->m_wThis = xIndex.get();
+ }
+ return xIndex;
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::getImplementationName()
+{
+ return "SwXDocumentIndex";
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::getSupportedServiceNames()
+{
+ SolarMutexGuard g;
+
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = "com.sun.star.text.BaseIndex";
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ pArray[1] = "com.sun.star.text.DocumentIndex";
+ break;
+ case TOX_CONTENT:
+ pArray[1] = "com.sun.star.text.ContentIndex";
+ break;
+ case TOX_TABLES:
+ pArray[1] = "com.sun.star.text.TableIndex";
+ break;
+ case TOX_ILLUSTRATIONS:
+ pArray[1] = "com.sun.star.text.IllustrationsIndex";
+ break;
+ case TOX_OBJECTS:
+ pArray[1] = "com.sun.star.text.ObjectIndex";
+ break;
+ case TOX_AUTHORITIES:
+ pArray[1] = "com.sun.star.text.Bibliography";
+ break;
+ //case TOX_USER:
+ default:
+ pArray[1] = "com.sun.star.text.UserDefinedIndex";
+ }
+ return aRet;
+}
+
+OUString SAL_CALL SwXDocumentIndex::getServiceName()
+{
+ SolarMutexGuard g;
+
+ SwServiceType nObjectType = SwServiceType::TypeIndex;
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_USER: nObjectType = SwServiceType::UserIndex;
+ break;
+ case TOX_CONTENT: nObjectType = SwServiceType::ContentIndex;
+ break;
+ case TOX_ILLUSTRATIONS: nObjectType = SwServiceType::IndexIllustrations;
+ break;
+ case TOX_OBJECTS: nObjectType = SwServiceType::IndexObjects;
+ break;
+ case TOX_TABLES: nObjectType = SwServiceType::IndexTables;
+ break;
+ case TOX_AUTHORITIES: nObjectType = SwServiceType::IndexBibliography;
+ break;
+ default:
+ break;
+ }
+ return SwXServiceProvider::GetProviderName(nObjectType);
+}
+
+void SAL_CALL SwXDocumentIndex::update()
+{
+ return refresh(); // update is from deprecated XDocumentIndex
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXDocumentIndex::getPropertySetInfo()
+{
+ SolarMutexGuard g;
+
+ const uno::Reference< beans::XPropertySetInfo > xRef =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return xRef;
+}
+
+void SAL_CALL
+SwXDocumentIndex::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+{
+ SolarMutexGuard aGuard;
+
+ SfxItemPropertyMapEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak());
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ "Property is read-only: " + rPropertyName,
+ getXWeak());
+ }
+
+ SwSectionFormat *const pSectionFormat(m_pImpl->GetSectionFormat());
+ SwTOXBase & rTOXBase( m_pImpl->GetTOXSectionOrThrow() );
+
+ SwTOXElement nCreate = rTOXBase.GetCreateType();
+ SwTOOElements nOLEOptions = rTOXBase.GetOLEOptions();
+ const TOXTypes eTxBaseType = rTOXBase.GetTOXType()->GetType();
+ SwTOIOptions nTOIOptions = (eTxBaseType == TOX_INDEX)
+ ? rTOXBase.GetOptions() : SwTOIOptions::NONE;
+ SwForm aForm(rTOXBase.GetTOXForm());
+ bool bForm = false;
+ switch (pEntry->nWID)
+ {
+ case WID_IDX_TITLE:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetTitle(sNewName);
+ }
+ break;
+ case WID_IDX_NAME:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetTOXName(sNewName);
+ }
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ lcl_ConvertTOUNameToUserName(sNewName);
+ OSL_ENSURE(TOX_USER == eTxBaseType,
+ "tox type name can only be changed for user indexes");
+ if (pSectionFormat)
+ {
+ if (rTOXBase.GetTOXType()->GetTypeName() != sNewName)
+ {
+ lcl_ReAssignTOXType(*pSectionFormat->GetDoc(),
+ rTOXBase, sNewName);
+ }
+ }
+ else
+ {
+ m_pImpl->m_oProps->SetTypeName(sNewName);
+ }
+ }
+ break;
+ case WID_IDX_LOCALE:
+ {
+ lang::Locale aLocale;
+ if (!(rValue>>= aLocale))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetLanguage( LanguageTag::convertToLanguageType(aLocale));
+ }
+ break;
+ case WID_IDX_SORT_ALGORITHM:
+ {
+ OUString sTmp;
+ if (!(rValue >>= sTmp))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetSortAlgorithm(sTmp);
+ }
+ break;
+ case WID_LEVEL:
+ {
+ rTOXBase.SetLevel(lcl_AnyToType<sal_Int16>(rValue));
+ }
+ break;
+ case WID_TOC_BOOKMARK:
+ {
+ rTOXBase.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
+ nCreate = SwTOXElement::Bookmark;
+ rTOXBase.SetCreate(nCreate);
+ }
+ break;
+ case WID_CREATE_FROM_MARKS:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Mark);
+ break;
+ case WID_CREATE_FROM_OUTLINE:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::OutlineLevel);
+ break;
+ case WID_TOC_PARAGRAPH_OUTLINE_LEVEL:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::ParagraphOutlineLevel);
+ break;
+ case WID_TAB_IN_TOC:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableInToc);
+ break;
+ case WID_TOC_NEWLINE:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Newline);
+ break;
+// case WID_PARAGRAPH_STYLE_NAMES :OSL_FAIL("not implemented")
+// break;
+ case WID_HIDE_TABLEADER_PAGENUMBERS:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableLeader);
+ break ;
+ case WID_CREATE_FROM_CHAPTER:
+ rTOXBase.SetFromChapter(lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_CREATE_FROM_LABELS:
+ rTOXBase.SetFromObjectNames(! lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_PROTECTED:
+ {
+ bool bSet = lcl_AnyToType<bool>(rValue);
+ rTOXBase.SetProtected(bSet);
+ if (pSectionFormat)
+ {
+ static_cast<SwTOXBaseSection &>(rTOXBase).SetProtect(bSet);
+ }
+ }
+ break;
+ case WID_USE_ALPHABETICAL_SEPARATORS:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ SwTOIOptions::AlphaDelimiter);
+ break;
+ case WID_USE_KEY_AS_ENTRY:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ SwTOIOptions::KeyAsEntry);
+ break;
+ case WID_USE_COMBINED_ENTRIES:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ SwTOIOptions::SameEntry);
+ break;
+ case WID_IS_CASE_SENSITIVE:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ SwTOIOptions::CaseSensitive);
+ break;
+ case WID_USE_P_P:
+ lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::FF);
+ break;
+ case WID_USE_DASH:
+ lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::Dash);
+ break;
+ case WID_USE_UPPER_CASE:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ SwTOIOptions::InitialCaps);
+ break;
+ case WID_IS_COMMA_SEPARATED:
+ bForm = true;
+ aForm.SetCommaSeparated(lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_LABEL_CATEGORY:
+ {
+ // convert file-format/API/external programmatic english name
+ // to internal UI name before usage
+ rTOXBase.SetSequenceName( SwStyleNameMapper::GetSpecialExtraUIName(
+ lcl_AnyToType<OUString>(rValue) ) );
+ }
+ break;
+ case WID_LABEL_DISPLAY_TYPE:
+ {
+ const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
+ sal_uInt16 nSet = CAPTION_COMPLETE;
+ switch (nVal)
+ {
+ case text::ReferenceFieldPart::TEXT:
+ nSet = CAPTION_COMPLETE;
+ break;
+ case text::ReferenceFieldPart::CATEGORY_AND_NUMBER:
+ nSet = CAPTION_NUMBER;
+ break;
+ case text::ReferenceFieldPart::ONLY_CAPTION:
+ nSet = CAPTION_TEXT;
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetCaptionDisplay(static_cast<SwCaptionDisplay>(nSet));
+ }
+ break;
+ case WID_USE_LEVEL_FROM_SOURCE:
+ rTOXBase.SetLevelFromChapter(lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
+ {
+ OUString aString;
+ SwStyleNameMapper::FillUIName(lcl_AnyToType<OUString>(rValue),
+ aString, SwGetPoolIdFromName::ChrFmt);
+ rTOXBase.SetMainEntryCharStyle( aString );
+ }
+ break;
+ case WID_CREATE_FROM_TABLES:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Table);
+ break;
+ case WID_CREATE_FROM_TEXT_FRAMES:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Frame);
+ break;
+ case WID_CREATE_FROM_GRAPHIC_OBJECTS:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Graphic);
+ break;
+ case WID_CREATE_FROM_EMBEDDED_OBJECTS:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Ole);
+ break;
+ case WID_CREATE_FROM_STAR_MATH:
+ lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Math);
+ break;
+ case WID_CREATE_FROM_STAR_CHART:
+ lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Chart);
+ break;
+ case WID_CREATE_FROM_STAR_CALC:
+ lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Calc);
+ break;
+ case WID_CREATE_FROM_STAR_DRAW:
+ lcl_AnyToBitMask(rValue, nOLEOptions,
+ SwTOOElements::DrawImpress);
+ break;
+ case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
+ lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Other);
+ break;
+ case WID_PARA_HEAD:
+ {
+ OUString aString;
+ SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
+ aString, SwGetPoolIdFromName::TxtColl);
+ bForm = true;
+ // Header is on Pos 0
+ aForm.SetTemplate( 0, aString );
+ }
+ break;
+ case WID_IS_RELATIVE_TABSTOPS:
+ bForm = true;
+ aForm.SetRelTabPos(lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_PARA_SEP:
+ {
+ OUString aString;
+ bForm = true;
+ SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
+ aString, SwGetPoolIdFromName::TxtColl);
+ aForm.SetTemplate( 1, aString );
+ }
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLES:
+ lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Template);
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLE:
+ {
+ OUString style;
+ if (rValue >>= style)
+ {
+ if (style.indexOf(TOX_STYLE_DELIMITER) != -1)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ lcl_AnyToBitMask(uno::Any(true), nCreate, SwTOXElement::Template);
+ OUString uiStyle;
+ SwStyleNameMapper::FillUIName(style, uiStyle, SwGetPoolIdFromName::TxtColl);
+ rTOXBase.SetStyleNames(uiStyle, 0);
+ }
+ else if (!rValue.hasValue())
+ {
+ lcl_AnyToBitMask(uno::Any(false), nCreate, SwTOXElement::Template);
+ }
+ else
+ {
+ throw lang::IllegalArgumentException();
+ }
+ }
+ break;
+
+ case WID_PARA_LEV1:
+ case WID_PARA_LEV2:
+ case WID_PARA_LEV3:
+ case WID_PARA_LEV4:
+ case WID_PARA_LEV5:
+ case WID_PARA_LEV6:
+ case WID_PARA_LEV7:
+ case WID_PARA_LEV8:
+ case WID_PARA_LEV9:
+ case WID_PARA_LEV10:
+ {
+ bForm = true;
+ // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
+ const sal_uInt16 nLPos = rTOXBase.GetType() == TOX_INDEX ? 2 : 1;
+ OUString aString;
+ SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
+ aString, SwGetPoolIdFromName::TxtColl);
+ aForm.SetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1, aString );
+ }
+ break;
+ default:
+ //this is for items only
+ if (WID_PRIMARY_KEY > pEntry->nWID)
+ {
+ const SwAttrSet& rSet =
+ SwDoc::GetTOXBaseAttrSet(rTOXBase);
+ SfxItemSet aAttrSet(rSet);
+ m_pImpl->m_rPropSet.setPropertyValue(
+ rPropertyName, rValue, aAttrSet);
+
+ const SwSectionFormats& rSects = m_pImpl->m_pDoc->GetSections();
+ for (size_t i = 0; i < rSects.size(); ++i)
+ {
+ const SwSectionFormat* pTmpFormat = rSects[ i ];
+ if (pTmpFormat == pSectionFormat)
+ {
+ SwSectionData tmpData(
+ static_cast<SwTOXBaseSection&>(rTOXBase));
+ m_pImpl->m_pDoc->UpdateSection(i, tmpData, & aAttrSet);
+ break;
+ }
+ }
+ }
+ }
+ rTOXBase.SetCreate(nCreate);
+ rTOXBase.SetOLEOptions(nOLEOptions);
+ if (rTOXBase.GetTOXType()->GetType() == TOX_INDEX)
+ {
+ rTOXBase.SetOptions(nTOIOptions);
+ }
+ if (bForm)
+ {
+ rTOXBase.SetTOXForm(aForm);
+ }
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ SfxItemPropertyMapEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak());
+ }
+ // TODO: is this the best approach to tell API clients about the change?
+ if (pEntry->nWID == RES_BACKGROUND && pEntry->nMemberId == MID_GRAPHIC_URL)
+ {
+ throw uno::RuntimeException("Getting GraphicURL property is not supported");
+ }
+
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ SwTOXBase* pTOXBase = nullptr;
+ if (pSectionFormat)
+ {
+ pTOXBase = static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection());
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ pTOXBase = &m_pImpl->m_oProps->GetTOXBase();
+ }
+ if(pTOXBase)
+ {
+ const SwTOXElement nCreate = pTOXBase->GetCreateType();
+ const SwTOOElements nOLEOptions = pTOXBase->GetOLEOptions();
+ const SwTOIOptions nTOIOptions =
+ (pTOXBase->GetTOXType()->GetType() == TOX_INDEX)
+ ? pTOXBase->GetOptions()
+ : SwTOIOptions::NONE;
+ const SwForm& rForm = pTOXBase->GetTOXForm();
+ switch(pEntry->nWID)
+ {
+ case WID_IDX_CONTENT_SECTION:
+ case WID_IDX_HEADER_SECTION :
+ if(WID_IDX_CONTENT_SECTION == pEntry->nWID)
+ {
+ const uno::Reference <text::XTextSection> xContentSect =
+ SwXTextSection::CreateXTextSection( pSectionFormat );
+ aRet <<= xContentSect;
+ }
+ else if (pSectionFormat)
+ {
+ SwSections aSectArr;
+ pSectionFormat->GetChildSections(aSectArr,
+ SectionSort::Not, false);
+ for(SwSection* pSect : aSectArr)
+ {
+ if(pSect->GetType() == SectionType::ToxHeader)
+ {
+ const uno::Reference <text::XTextSection> xHeader =
+ SwXTextSection::CreateXTextSection(
+ pSect->GetFormat() );
+ aRet <<= xHeader;
+ break;
+ }
+ }
+ }
+ break;
+ case WID_IDX_TITLE :
+ {
+ aRet <<= pTOXBase->GetTitle();
+ break;
+ }
+ case WID_IDX_NAME:
+ aRet <<= pTOXBase->GetTOXName();
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sTmp((!m_pImpl->m_bIsDescriptor)
+ ? pTOXBase->GetTOXType()->GetTypeName()
+ : m_pImpl->m_oProps->GetTypeName());
+ //I18N
+ lcl_ConvertTOUNameToProgrammaticName(sTmp);
+ aRet <<= sTmp;
+ }
+ break;
+ case WID_IDX_LOCALE:
+ aRet <<= LanguageTag(pTOXBase->GetLanguage()).getLocale();
+ break;
+ case WID_IDX_SORT_ALGORITHM:
+ aRet <<= pTOXBase->GetSortAlgorithm();
+ break;
+ case WID_LEVEL :
+ aRet <<= static_cast<sal_Int16>(pTOXBase->GetLevel());
+ break;
+ case WID_TOC_BOOKMARK :
+ aRet <<= pTOXBase->GetBookmarkName();
+ break;
+ case WID_CREATE_FROM_MARKS:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Mark);
+ break;
+ case WID_CREATE_FROM_OUTLINE:
+ lcl_BitMaskToAny(aRet, nCreate,
+ SwTOXElement::OutlineLevel);
+ break;
+ case WID_CREATE_FROM_CHAPTER:
+ {
+ const bool bRet = pTOXBase->IsFromChapter();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_CREATE_FROM_LABELS:
+ {
+ const bool bRet = ! pTOXBase->IsFromObjectNames();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_PROTECTED:
+ {
+ const bool bRet = pTOXBase->IsProtected();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_USE_ALPHABETICAL_SEPARATORS:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ SwTOIOptions::AlphaDelimiter);
+ break;
+ case WID_USE_KEY_AS_ENTRY:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ SwTOIOptions::KeyAsEntry);
+ break;
+ case WID_USE_COMBINED_ENTRIES:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ SwTOIOptions::SameEntry);
+ break;
+ case WID_IS_CASE_SENSITIVE:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ SwTOIOptions::CaseSensitive);
+ break;
+ case WID_USE_P_P:
+ lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::FF);
+ break;
+ case WID_USE_DASH:
+ lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::Dash);
+ break;
+ case WID_USE_UPPER_CASE:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ SwTOIOptions::InitialCaps);
+ break;
+ case WID_IS_COMMA_SEPARATED:
+ {
+ const bool bRet = rForm.IsCommaSeparated();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_LABEL_CATEGORY:
+ {
+ // convert internal UI name to
+ // file-format/API/external programmatic english name
+ // before usage
+ aRet <<= SwStyleNameMapper::GetSpecialExtraProgName(
+ pTOXBase->GetSequenceName() );
+ }
+ break;
+ case WID_LABEL_DISPLAY_TYPE:
+ {
+ sal_Int16 nSet = text::ReferenceFieldPart::TEXT;
+ switch (pTOXBase->GetCaptionDisplay())
+ {
+ case CAPTION_COMPLETE:
+ nSet = text::ReferenceFieldPart::TEXT;
+ break;
+ case CAPTION_NUMBER:
+ nSet = text::ReferenceFieldPart::CATEGORY_AND_NUMBER;
+ break;
+ case CAPTION_TEXT:
+ nSet = text::ReferenceFieldPart::ONLY_CAPTION;
+ break;
+ }
+ aRet <<= nSet;
+ }
+ break;
+ case WID_USE_LEVEL_FROM_SOURCE:
+ {
+ const bool bRet = pTOXBase->IsLevelFromChapter();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_LEVEL_FORMAT:
+ {
+ uno::Reference< container::XIndexReplace > xTokenAccess(
+ m_pImpl->m_wTokenAccess);
+ if (!xTokenAccess.is())
+ {
+ xTokenAccess = new TokenAccess_Impl(*this);
+ m_pImpl->m_wTokenAccess = xTokenAccess;
+ }
+ aRet <<= xTokenAccess;
+ }
+ break;
+ case WID_LEVEL_PARAGRAPH_STYLES:
+ {
+ uno::Reference< container::XIndexReplace > xStyleAccess(
+ m_pImpl->m_wStyleAccess);
+ if (!xStyleAccess.is())
+ {
+ xStyleAccess = new StyleAccess_Impl(*this);
+ m_pImpl->m_wStyleAccess = xStyleAccess;
+ }
+ aRet <<= xStyleAccess;
+ }
+ break;
+ case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
+ {
+ OUString aString;
+ SwStyleNameMapper::FillProgName(
+ pTOXBase->GetMainEntryCharStyle(),
+ aString,
+ SwGetPoolIdFromName::ChrFmt);
+ aRet <<= aString;
+ }
+ break;
+ case WID_CREATE_FROM_TABLES:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Table);
+ break;
+ case WID_CREATE_FROM_TEXT_FRAMES:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Frame);
+ break;
+ case WID_CREATE_FROM_GRAPHIC_OBJECTS:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Graphic);
+ break;
+ case WID_CREATE_FROM_EMBEDDED_OBJECTS:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Ole);
+ break;
+ case WID_CREATE_FROM_STAR_MATH:
+ lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Math);
+ break;
+ case WID_CREATE_FROM_STAR_CHART:
+ lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Chart);
+ break;
+ case WID_CREATE_FROM_STAR_CALC:
+ lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Calc);
+ break;
+ case WID_CREATE_FROM_STAR_DRAW:
+ lcl_BitMaskToAny(aRet, nOLEOptions,
+ SwTOOElements::DrawImpress);
+ break;
+ case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
+ lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Other);
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLES:
+ lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Template);
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLE:
+ {
+ if (nCreate & SwTOXElement::Template)
+ { // there is only one style, at top level
+ OUString const& rStyle(pTOXBase->GetStyleNames(0));
+ if (!rStyle.isEmpty())
+ {
+ assert(rStyle.indexOf(TOX_STYLE_DELIMITER) == -1);
+ OUString ret;
+ SwStyleNameMapper::FillProgName(rStyle, ret,
+ SwGetPoolIdFromName::TxtColl);
+ aRet <<= ret;
+ }
+ }
+ }
+ break;
+
+ case WID_PARA_HEAD:
+ {
+ //Header is at position 0
+ OUString aString;
+ SwStyleNameMapper::FillProgName(rForm.GetTemplate( 0 ), aString,
+ SwGetPoolIdFromName::TxtColl );
+ aRet <<= aString;
+ }
+ break;
+ case WID_PARA_SEP:
+ {
+ OUString aString;
+ SwStyleNameMapper::FillProgName(
+ rForm.GetTemplate( 1 ),
+ aString,
+ SwGetPoolIdFromName::TxtColl);
+ aRet <<= aString;
+ }
+ break;
+ case WID_PARA_LEV1:
+ case WID_PARA_LEV2:
+ case WID_PARA_LEV3:
+ case WID_PARA_LEV4:
+ case WID_PARA_LEV5:
+ case WID_PARA_LEV6:
+ case WID_PARA_LEV7:
+ case WID_PARA_LEV8:
+ case WID_PARA_LEV9:
+ case WID_PARA_LEV10:
+ {
+ // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
+ const sal_uInt16 nLPos = pTOXBase->GetType() == TOX_INDEX ? 2 : 1;
+ OUString aString;
+ SwStyleNameMapper::FillProgName(
+ rForm.GetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1),
+ aString,
+ SwGetPoolIdFromName::TxtColl);
+ aRet <<= aString;
+ }
+ break;
+ case WID_IS_RELATIVE_TABSTOPS:
+ {
+ const bool bRet = rForm.IsRelTabPos();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_INDEX_MARKS:
+ {
+ SwTOXMarks aMarks;
+ const SwTOXType* pType = pTOXBase->GetTOXType();
+ pType->CollectTextMarks(aMarks);
+ uno::Sequence< uno::Reference<text::XDocumentIndexMark> > aXMarks(aMarks.size());
+ uno::Reference<text::XDocumentIndexMark>* pxMarks = aXMarks.getArray();
+ for(size_t i = 0; i < aMarks.size(); ++i)
+ {
+ SwTOXMark* pMark = aMarks[i];
+ pxMarks[i] = SwXDocumentIndexMark::CreateXDocumentIndexMark(
+ *m_pImpl->m_pDoc, pMark);
+ }
+ aRet <<= aXMarks;
+ }
+ break;
+ default:
+ //this is for items only
+ if(WID_PRIMARY_KEY > pEntry->nWID)
+ {
+ const SwAttrSet& rSet =
+ SwDoc::GetTOXBaseAttrSet(*pTOXBase);
+ aRet = m_pImpl->m_rPropSet.getPropertyValue(
+ rPropertyName, rSet);
+ }
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXDocumentIndex::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndex::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndex::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndex::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndex::removeVetoableChangeListener(): not implemented");
+}
+
+static void lcl_CalcLayout(SwDoc *pDoc)
+{
+ SwViewShell *pViewShell = nullptr;
+ SwEditShell* pEditShell = nullptr;
+ if( pDoc )
+ {
+ pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
+ pEditShell = pDoc->GetEditShell();
+ }
+
+ if (pEditShell)
+ {
+ pEditShell->CalcLayout();
+ }
+ else if (pViewShell)
+ {
+ pViewShell->CalcLayout();
+ }
+}
+
+// XRefreshable
+void SAL_CALL SwXDocumentIndex::refresh()
+{
+ {
+ SolarMutexGuard g;
+
+ SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
+ SwTOXBaseSection *const pTOXBase = pFormat ?
+ static_cast<SwTOXBaseSection*>(pFormat->GetSection()) : nullptr;
+ if (!pTOXBase)
+ {
+ throw uno::RuntimeException(
+ "SwXDocumentIndex::refresh: must be in attached state",
+ getXWeak());
+ }
+ pTOXBase->Update(nullptr, m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+
+ // the insertion of TOC will affect the document layout
+ lcl_CalcLayout(m_pImpl->m_pDoc);
+
+ // page numbers
+ pTOXBase->UpdatePageNum();
+ }
+
+ std::unique_lock g(m_pImpl->m_Mutex);
+ if (m_pImpl->m_RefreshListeners.getLength(g))
+ {
+ lang::EventObject const event(getXWeak());
+ m_pImpl->m_RefreshListeners.notifyEach(g, & util::XRefreshListener::refreshed, event);
+ }
+}
+
+void SAL_CALL SwXDocumentIndex::addRefreshListener(
+ const uno::Reference<util::XRefreshListener>& xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock g(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.addInterface(g, xListener);
+}
+
+void SAL_CALL SwXDocumentIndex::removeRefreshListener(
+ const uno::Reference<util::XRefreshListener>& xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock g(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.removeInterface(g, xListener);
+}
+
+void SAL_CALL
+SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+ SwXTextRange *const pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper *const pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+
+ SwDoc *const pDoc =
+ pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ // this now needs to return TRUE
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+
+ const SwTOXBase* pOld = SwDoc::GetCurTOX( *aPam.Start() );
+ if (pOld)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ UnoActionContext aAction(pDoc);
+
+ SwTOXBase & rTOXBase = m_pImpl->m_oProps->GetTOXBase();
+ SwTOXType const*const pTOXType = rTOXBase.GetTOXType();
+ if ((TOX_USER == pTOXType->GetType()) &&
+ m_pImpl->m_oProps->GetTypeName() != pTOXType->GetTypeName())
+ {
+ lcl_ReAssignTOXType(*pDoc, rTOXBase, m_pImpl->m_oProps->GetTypeName());
+ }
+ //TODO: apply Section attributes (columns and background)
+ SwTOXBaseSection *const pTOX =
+ pDoc->InsertTableOf( aPam, rTOXBase, nullptr, false,
+ m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+
+ pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_oProps->GetTOXBase().GetTOXName());
+
+ // update page numbers
+ m_pImpl->SetSectionFormat(*pTOX->GetFormat());
+ pTOX->GetFormat()->SetXObject(getXWeak());
+ pTOX->UpdatePageNum();
+
+ m_pImpl->m_oProps.reset();
+ m_pImpl->m_pDoc = pDoc;
+ m_pImpl->m_bIsDescriptor = false;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXDocumentIndex::getAnchor()
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ if (!pSectionFormat)
+ {
+ throw uno::RuntimeException();
+ }
+
+ rtl::Reference<SwXTextRange> xRet;
+ SwNodeIndex const*const pIdx( pSectionFormat->GetContent().GetContentIdx() );
+ if (pIdx && pIdx->GetNode().GetNodes().IsDocNodes())
+ {
+ SwPaM aPaM(*pIdx);
+ aPaM.Move( fnMoveForward, GoInContent );
+ aPaM.SetMark();
+ aPaM.GetPoint()->Assign( *pIdx->GetNode().EndOfSectionNode() );
+ aPaM.Move( fnMoveBackward, GoInContent );
+ xRet = SwXTextRange::CreateXTextRange(*pSectionFormat->GetDoc(),
+ *aPaM.GetMark(), aPaM.GetPoint());
+ }
+ return xRet;
+}
+
+void SAL_CALL SwXDocumentIndex::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ if (pSectionFormat)
+ {
+ pSectionFormat->GetDoc()->DeleteTOX(
+ *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()),
+ true);
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndex::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock g(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.addInterface(g, xListener);
+}
+
+void SAL_CALL
+SwXDocumentIndex::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock g(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.removeInterface(g, xListener);
+}
+
+OUString SAL_CALL SwXDocumentIndex::getName()
+{
+ SolarMutexGuard g;
+
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ return m_pImpl->m_oProps->GetTOXBase().GetTOXName();
+ }
+
+ if(!pSectionFormat)
+ {
+ throw uno::RuntimeException();
+ }
+
+ return pSectionFormat->GetSection()->GetSectionName();
+}
+
+void SAL_CALL
+SwXDocumentIndex::setName(const OUString& rName)
+{
+ SolarMutexGuard g;
+
+ if (rName.isEmpty())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_oProps->GetTOXBase().SetTOXName(rName);
+ }
+ else if (pSectionFormat)
+ {
+ const bool bSuccess = pSectionFormat->GetDoc()->SetTOXBaseName(
+ *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()), rName);
+ if (!bSuccess)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXDocumentIndex::GetCoreObject()
+{
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ return pSectionFormat;
+}
+
+uno::Reference<frame::XModel> SwXDocumentIndex::GetModel()
+{
+ SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
+ if (pSectionFormat)
+ {
+ SwDocShell const*const pShell( pSectionFormat->GetDoc()->GetDocShell() );
+ return pShell ? pShell->GetModel() : nullptr;
+ }
+ return nullptr;
+}
+
+static sal_uInt16
+lcl_TypeToPropertyMap_Mark(const TOXTypes eType)
+{
+ switch (eType)
+ {
+ case TOX_INDEX: return PROPERTY_MAP_INDEX_MARK;
+ case TOX_CONTENT: return PROPERTY_MAP_CNTIDX_MARK;
+ case TOX_CITATION : return PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY;
+ //case TOX_USER:
+ default:
+ return PROPERTY_MAP_USER_MARK;
+ }
+}
+
+class SwXDocumentIndexMark::Impl final: public SvtListener
+{
+private:
+ SwXDocumentIndexMark & m_rThis;
+ bool m_bInReplaceMark;
+
+public:
+
+ unotools::WeakReference<SwXDocumentIndexMark> m_wThis;
+ SfxItemPropertySet const& m_rPropSet;
+ const TOXTypes m_eTOXType;
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper4
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners;
+ bool m_bIsDescriptor;
+ const SwTOXType* m_pTOXType;
+ const SwTOXMark* m_pTOXMark;
+ SwDoc* m_pDoc;
+
+ bool m_bMainEntry;
+ sal_uInt16 m_nLevel;
+ OUString m_aBookmarkName;
+ OUString m_sAltText;
+ OUString m_sPrimaryKey;
+ OUString m_sSecondaryKey;
+ OUString m_sTextReading;
+ OUString m_sPrimaryKeyReading;
+ OUString m_sSecondaryKeyReading;
+ OUString m_sUserIndexName;
+
+ Impl(SwXDocumentIndexMark& rThis,
+ SwDoc* const pDoc,
+ const enum TOXTypes eType,
+ const SwTOXType* pType,
+ SwTOXMark const* pMark)
+ : m_rThis(rThis)
+ , m_bInReplaceMark(false)
+ , m_rPropSet(
+ *aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Mark(eType)))
+ , m_eTOXType(eType)
+ , m_bIsDescriptor(nullptr == pMark)
+ , m_pTOXType(pType)
+ , m_pTOXMark(pMark)
+ , m_pDoc(pDoc)
+ , m_bMainEntry(false)
+ , m_nLevel(0)
+ {
+ auto pMarkNonConst = const_cast<SwTOXMark*>(m_pTOXMark);
+ auto pTypeNonConst = const_cast<SwTOXType*>(m_pTOXType);
+
+ if(pMarkNonConst)
+ StartListening(pMarkNonConst->GetNotifier());
+ if(pTypeNonConst)
+ StartListening(pTypeNonConst->GetNotifier());
+ }
+
+ SwTOXType* GetTOXType() const {
+ return const_cast<SwTOXType*>(m_pTOXType);
+ }
+
+ void DeleteTOXMark()
+ {
+ m_pDoc->DeleteTOXMark(m_pTOXMark);
+ Invalidate();
+ }
+
+ void InsertTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
+ SwXTextCursor const*const pTextCursor);
+
+ void ReplaceTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam)
+ {
+ m_bInReplaceMark = true;
+ DeleteTOXMark();
+ m_bInReplaceMark = false;
+ try {
+ InsertTOXMark(rTOXType, rMark, rPam, nullptr);
+ } catch (...) {
+ OSL_FAIL("ReplaceTOXMark() failed!");
+ lang::EventObject const ev(m_rThis.getXWeak());
+ std::unique_lock aGuard(m_Mutex);
+ m_EventListeners.disposeAndClear(aGuard, ev);
+ throw;
+ }
+ }
+
+ void Invalidate();
+ virtual void Notify(const SfxHint&) override;
+};
+
+void SwXDocumentIndexMark::Impl::Invalidate()
+{
+ if (!m_bInReplaceMark) // #i109983# only dispose on delete, not on replace!
+ {
+ rtl::Reference<SwXDocumentIndexMark> const xThis(m_wThis);
+ // fdo#72695: if UNO object is already dead, don't revive it with event
+ if (xThis.is())
+ {
+ lang::EventObject const ev(xThis->getXWeak());
+ std::unique_lock aGuard(m_Mutex);
+ m_EventListeners.disposeAndClear(aGuard, ev);
+ }
+ }
+ EndListeningAll();
+ m_pDoc = nullptr;
+ m_pTOXMark = nullptr;
+ m_pTOXType = nullptr;
+}
+
+void SwXDocumentIndexMark::Impl::Notify(const SfxHint& rHint)
+{
+ if(auto pModifyChangedHint = dynamic_cast<const sw::ModifyChangedHint*>(&rHint))
+ {
+ if(auto pNewType = dynamic_cast<const SwTOXType*>(pModifyChangedHint->m_pNew))
+ m_pTOXType = pNewType;
+
+ else
+ Invalidate();
+ }
+}
+
+SwXDocumentIndexMark::SwXDocumentIndexMark(const TOXTypes eToxType)
+ : m_pImpl( new SwXDocumentIndexMark::Impl(*this, nullptr, eToxType, nullptr, nullptr) )
+{
+}
+
+SwXDocumentIndexMark::SwXDocumentIndexMark(SwDoc & rDoc,
+ const SwTOXType & rType, const SwTOXMark & rMark)
+ : m_pImpl( new SwXDocumentIndexMark::Impl(*this, &rDoc, rType.GetType(),
+ &rType, &rMark) )
+{
+}
+
+SwXDocumentIndexMark::~SwXDocumentIndexMark()
+{
+}
+
+rtl::Reference<SwXDocumentIndexMark>
+SwXDocumentIndexMark::CreateXDocumentIndexMark(
+ SwDoc & rDoc, SwTOXMark *const pMark, TOXTypes const eType)
+{
+ // re-use existing SwXDocumentIndexMark
+ // NB: xmloff depends on this caching to generate ID from the address!
+ // #i105557#: do not iterate over the registered clients: race condition
+ rtl::Reference<SwXDocumentIndexMark> xTOXMark;
+ if (pMark)
+ {
+ xTOXMark = pMark->GetXTOXMark();
+ }
+ if (!xTOXMark.is())
+ {
+ xTOXMark = pMark
+ ? new SwXDocumentIndexMark(rDoc,
+ *const_cast<SwTOXType*>(pMark->GetTOXType()), *pMark)
+ : new SwXDocumentIndexMark(eType);
+ if (pMark)
+ {
+ pMark->SetXTOXMark(xTOXMark);
+ }
+ // need a permanent Reference to initialize m_wThis
+ xTOXMark->m_pImpl->m_wThis = xTOXMark.get();
+ }
+ return xTOXMark;
+}
+
+namespace
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndexMark::getImplementationName()
+{
+ return "SwXDocumentIndexMark";
+}
+
+sal_Bool SAL_CALL SwXDocumentIndexMark::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexMark::getSupportedServiceNames()
+{
+ SolarMutexGuard g;
+
+ const sal_Int32 nCnt = (m_pImpl->m_eTOXType == TOX_INDEX) ? 4 : 3;
+ uno::Sequence< OUString > aRet(nCnt);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = "com.sun.star.text.BaseIndexMark";
+ pArray[1] = "com.sun.star.text.TextContent";
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_USER:
+ pArray[2] = "com.sun.star.text.UserIndexMark";
+ break;
+ case TOX_CONTENT:
+ pArray[2] = "com.sun.star.text.ContentIndexMark";
+ break;
+ case TOX_INDEX:
+ pArray[2] = "com.sun.star.text.DocumentIndexMark";
+ pArray[3] = "com.sun.star.text.DocumentIndexMarkAsian";
+ break;
+
+ default:
+ ;
+ }
+ return aRet;
+}
+
+OUString SAL_CALL
+SwXDocumentIndexMark::getMarkEntry()
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ return m_pImpl->m_pTOXMark->GetAlternativeText();
+ }
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ return m_pImpl->m_sAltText;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::setMarkEntry(const OUString& rIndexEntry)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ SwTOXMark aMark(*m_pImpl->m_pTOXMark);
+ aMark.SetAlternativeText(rIndexEntry);
+ SwTextTOXMark const*const pTextMark =
+ m_pImpl->m_pTOXMark->GetTextTOXMark();
+ SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
+ aPam.SetMark();
+ if(pTextMark->End())
+ {
+ aPam.GetPoint()->SetContent( *pTextMark->End() );
+ }
+ else
+ aPam.GetPoint()->AdjustContent(1);
+
+ m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_sAltText = rIndexEntry;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::attach(
+ const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwXTextRange *const pRange =
+ dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper *const pCursor =
+ dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+ SwDoc *const pDoc =
+ pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const SwTOXType* pTOXType = nullptr;
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ case TOX_CONTENT:
+ case TOX_CITATION:
+ pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
+ break;
+ case TOX_USER:
+ {
+ if (m_pImpl->m_sUserIndexName.isEmpty())
+ {
+ pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
+ }
+ else
+ {
+ const sal_uInt16 nCount =
+ pDoc->GetTOXTypeCount(m_pImpl->m_eTOXType);
+ for (sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwTOXType const*const pTemp =
+ pDoc->GetTOXType( m_pImpl->m_eTOXType, i );
+ if (m_pImpl->m_sUserIndexName == pTemp->GetTypeName())
+ {
+ pTOXType = pTemp;
+ break;
+ }
+ }
+ if (!pTOXType)
+ {
+ SwTOXType aUserType(*pDoc, TOX_USER, m_pImpl->m_sUserIndexName);
+ pTOXType = pDoc->InsertTOXType(aUserType);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (!pTOXType)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ // this now needs to return TRUE
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ SwTOXMark aMark (pTOXType);
+ if (!m_pImpl->m_sAltText.isEmpty())
+ {
+ aMark.SetAlternativeText(m_pImpl->m_sAltText);
+ }
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ if (!m_pImpl->m_sPrimaryKey.isEmpty())
+ {
+ aMark.SetPrimaryKey(m_pImpl->m_sPrimaryKey);
+ }
+ if (!m_pImpl->m_sSecondaryKey.isEmpty())
+ {
+ aMark.SetSecondaryKey(m_pImpl->m_sSecondaryKey);
+ }
+ if (!m_pImpl->m_sTextReading.isEmpty())
+ {
+ aMark.SetTextReading(m_pImpl->m_sTextReading);
+ }
+ if (!m_pImpl->m_sPrimaryKeyReading.isEmpty())
+ {
+ aMark.SetPrimaryKeyReading(m_pImpl->m_sPrimaryKeyReading);
+ }
+ if (!m_pImpl->m_sSecondaryKeyReading.isEmpty())
+ {
+ aMark.SetSecondaryKeyReading(m_pImpl->m_sSecondaryKeyReading);
+ }
+ aMark.SetMainEntry(m_pImpl->m_bMainEntry);
+ break;
+ case TOX_CITATION:
+ aMark.SetMainEntry(m_pImpl->m_bMainEntry);
+ break;
+ case TOX_USER:
+ case TOX_CONTENT:
+ if (USHRT_MAX != m_pImpl->m_nLevel)
+ {
+ aMark.SetLevel(m_pImpl->m_nLevel+1);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ m_pImpl->InsertTOXMark(*const_cast<SwTOXType *>(pTOXType), aMark, aPam,
+ dynamic_cast<SwXTextCursor const*>(pCursor));
+
+ m_pImpl->m_bIsDescriptor = false;
+}
+
+namespace {
+
+template<typename T> struct NotContainedIn
+{
+ std::vector<T> const& m_rVector;
+ explicit NotContainedIn(std::vector<T> const& rVector)
+ : m_rVector(rVector) { }
+ bool operator() (T const& rT) {
+ return std::find(m_rVector.begin(), m_rVector.end(), rT)
+ == m_rVector.end();
+ }
+};
+
+}
+
+void SwXDocumentIndexMark::Impl::InsertTOXMark(
+ const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
+ SwXTextCursor const*const pTextCursor)
+{
+ SwDoc& rDoc(rPam.GetDoc());
+ UnoActionContext aAction(&rDoc);
+ bool bMark = *rPam.GetPoint() != *rPam.GetMark();
+ // n.b.: toxmarks must have either alternative text or an extent
+ if (bMark && !rMark.GetAlternativeText().isEmpty())
+ {
+ rPam.Normalize();
+ rPam.DeleteMark();
+ bMark = false;
+ }
+ // Marks without alternative text and without selected text cannot be inserted,
+ // thus use a space - is this really the ideal solution?
+ if (!bMark && rMark.GetAlternativeText().isEmpty())
+ {
+ rMark.SetAlternativeText( " " );
+ }
+
+ const bool bForceExpandHints( !bMark && pTextCursor && pTextCursor->IsAtEndOfMeta() );
+ const SetAttrMode nInsertFlags = bForceExpandHints
+ ? ( SetAttrMode::FORCEHINTEXPAND
+ | SetAttrMode::DONTEXPAND)
+ : SetAttrMode::DONTEXPAND;
+
+ // rMark gets copied into the document pool;
+ // pNewTextAttr comes back with the real format
+ SwTextAttr *pNewTextAttr = nullptr;
+ rDoc.getIDocumentContentOperations().InsertPoolItem(rPam, rMark, nInsertFlags,
+ /*pLayout*/nullptr, &pNewTextAttr);
+ if (bMark && *rPam.GetPoint() > *rPam.GetMark())
+ {
+ rPam.Exchange();
+ }
+
+ if (!pNewTextAttr)
+ {
+ throw uno::RuntimeException(
+ "SwXDocumentIndexMark::InsertTOXMark(): cannot insert attribute",
+ nullptr);
+ }
+
+ m_pDoc = &rDoc;
+ m_pTOXMark = &pNewTextAttr->GetTOXMark();
+ m_pTOXType = &rTOXType;
+ EndListeningAll();
+ StartListening(const_cast<SwTOXMark*>(m_pTOXMark)->GetNotifier());
+ StartListening(const_cast<SwTOXType*>(m_pTOXType)->GetNotifier());
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXDocumentIndexMark::getAnchor()
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (!pType || !m_pImpl->m_pTOXMark)
+ {
+ throw uno::RuntimeException();
+ }
+ if (!m_pImpl->m_pTOXMark->GetTextTOXMark())
+ {
+ throw uno::RuntimeException();
+ }
+ const SwTextTOXMark* pTextMark = m_pImpl->m_pTOXMark->GetTextTOXMark();
+ SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
+ aPam.SetMark();
+ if(pTextMark->End())
+ {
+ aPam.GetPoint()->SetContent( *pTextMark->End() );
+ }
+ else
+ {
+ aPam.GetPoint()->AdjustContent(1);
+ }
+ const uno::Reference< frame::XModel > xModel =
+ m_pImpl->m_pDoc->GetDocShell()->GetBaseModel();
+ const uno::Reference< text::XTextDocument > xTDoc(xModel, uno::UNO_QUERY);
+ const uno::Reference< text::XTextRange > xRet =
+ new SwXTextRange(aPam, xTDoc->getText());
+
+ return xRet;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ m_pImpl->DeleteTOXMark(); // call Invalidate() via modify!
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.addInterface(aGuard, xListener);
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+{
+ // no need to lock here as m_pImpl is const and container threadsafe
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.removeInterface(aGuard, xListener);
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXDocumentIndexMark::getPropertySetInfo()
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xInfos[3];
+ int nPos = 0;
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX: nPos = 0; break;
+ case TOX_CONTENT: nPos = 1; break;
+ case TOX_USER: nPos = 2; break;
+ default:
+ ;
+ }
+ if(!xInfos[nPos].is())
+ {
+ const uno::Reference< beans::XPropertySetInfo > xInfo =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ // extend PropertySetInfo!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ xInfos[nPos] = new SfxExtItemPropertySetInfo(
+ aSwMapProvider.GetPropertyMapEntries(
+ PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
+ aPropSeq );
+ }
+ return xInfos[nPos];
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+{
+ SolarMutexGuard aGuard;
+
+ SfxItemPropertyMapEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak());
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ "Property is read-only: " + rPropertyName,
+ getXWeak());
+ }
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ SwTOXMark aMark(*m_pImpl->m_pTOXMark);
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aMark.SetAlternativeText(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_LEVEL:
+ aMark.SetLevel(std::min( static_cast<sal_Int8>( MAXLEVEL ),
+ static_cast<sal_Int8>(lcl_AnyToType<sal_Int16>(rValue)+1)));
+ break;
+ case WID_TOC_BOOKMARK :
+ aMark.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_PRIMARY_KEY :
+ aMark.SetPrimaryKey(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_SECONDARY_KEY:
+ aMark.SetSecondaryKey(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_MAIN_ENTRY:
+ aMark.SetMainEntry(lcl_AnyToType<bool>(rValue));
+ break;
+ case WID_TEXT_READING:
+ aMark.SetTextReading(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aMark.SetPrimaryKeyReading(lcl_AnyToType<OUString>(rValue));
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aMark.SetSecondaryKeyReading(lcl_AnyToType<OUString>(rValue));
+ break;
+ }
+ SwTextTOXMark const*const pTextMark =
+ m_pImpl->m_pTOXMark->GetTextTOXMark();
+ SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
+ aPam.SetMark();
+ if(pTextMark->End())
+ {
+ aPam.GetPoint()->SetContent(*pTextMark->End());
+ }
+ else
+ {
+ aPam.GetPoint()->AdjustContent(1);
+ }
+
+ m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ m_pImpl->m_sAltText = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_LEVEL:
+ {
+ const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
+ if(nVal < 0 || nVal >= MAXLEVEL)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ m_pImpl->m_nLevel = nVal;
+ }
+ break;
+ case WID_TOC_BOOKMARK :
+ {
+ m_pImpl->m_aBookmarkName = lcl_AnyToType<OUString>(rValue);
+ }
+ break;
+ case WID_PRIMARY_KEY:
+ m_pImpl->m_sPrimaryKey = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_SECONDARY_KEY:
+ m_pImpl->m_sSecondaryKey = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_TEXT_READING:
+ m_pImpl->m_sTextReading = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_PRIMARY_KEY_READING:
+ m_pImpl->m_sPrimaryKeyReading = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_SECONDARY_KEY_READING:
+ m_pImpl->m_sSecondaryKeyReading = lcl_AnyToType<OUString>(rValue);
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sTmp(lcl_AnyToType<OUString>(rValue));
+ lcl_ConvertTOUNameToUserName(sTmp);
+ m_pImpl->m_sUserIndexName = sTmp;
+ }
+ break;
+ case WID_MAIN_ENTRY:
+ m_pImpl->m_bMainEntry = lcl_AnyToType<bool>(rValue);
+ break;
+ case PROPERTY_MAP_INDEX_OBJECTS:
+ // unsupported
+ break;
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexMark::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ SfxItemPropertyMapEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak());
+ }
+ if (::sw::GetDefaultTextContentValue(aRet, rPropertyName, pEntry->nWID))
+ {
+ return aRet;
+ }
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aRet <<= m_pImpl->m_pTOXMark->GetAlternativeText();
+ break;
+ case WID_LEVEL:
+ aRet <<= static_cast<sal_Int16>(
+ m_pImpl->m_pTOXMark->GetLevel() - 1);
+ break;
+ case WID_TOC_BOOKMARK :
+ aRet <<= m_pImpl->m_pTOXMark->GetBookmarkName();
+ break;
+ case WID_PRIMARY_KEY :
+ aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKey();
+ break;
+ case WID_SECONDARY_KEY:
+ aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKey();
+ break;
+ case WID_TEXT_READING:
+ aRet <<= m_pImpl->m_pTOXMark->GetTextReading();
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKeyReading();
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKeyReading();
+ break;
+ case WID_USER_IDX_NAME :
+ {
+ OUString sTmp(pType->GetTypeName());
+ lcl_ConvertTOUNameToProgrammaticName(sTmp);
+ aRet <<= sTmp;
+ }
+ break;
+ case WID_MAIN_ENTRY:
+ {
+ const bool bTemp = m_pImpl->m_pTOXMark->IsMainEntry();
+ aRet <<= bTemp;
+ }
+ break;
+ }
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aRet <<= m_pImpl->m_sAltText;
+ break;
+ case WID_LEVEL:
+ aRet <<= static_cast<sal_Int16>(m_pImpl->m_nLevel);
+ break;
+ case WID_TOC_BOOKMARK :
+ aRet <<= m_pImpl->m_aBookmarkName;
+ break;
+ case WID_PRIMARY_KEY:
+ aRet <<= m_pImpl->m_sPrimaryKey;
+ break;
+ case WID_SECONDARY_KEY:
+ aRet <<= m_pImpl->m_sSecondaryKey;
+ break;
+ case WID_TEXT_READING:
+ aRet <<= m_pImpl->m_sTextReading;
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aRet <<= m_pImpl->m_sPrimaryKeyReading;
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aRet <<= m_pImpl->m_sSecondaryKeyReading;
+ break;
+ case WID_USER_IDX_NAME :
+ aRet <<= m_pImpl->m_sUserIndexName;
+ break;
+ case WID_MAIN_ENTRY:
+ aRet <<= m_pImpl->m_bMainEntry;
+ break;
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndexMark::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndexMark::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndexMark::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+{
+ OSL_FAIL("SwXDocumentIndexMark::removeVetoableChangeListener(): not implemented");
+}
+
+SwXDocumentIndexes::SwXDocumentIndexes(SwDoc *const _pDoc)
+ : SwUnoCollection(_pDoc)
+{
+}
+
+SwXDocumentIndexes::~SwXDocumentIndexes()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndexes::getImplementationName()
+{
+ return "SwXDocumentIndexes";
+}
+
+sal_Bool SAL_CALL SwXDocumentIndexes::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexes::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.DocumentIndexes" };
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndexes::getCount()
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt32 nRet = 0;
+ const SwSectionFormats& rFormats = GetDoc().GetSections();
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ const SwSection* pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode() )
+ {
+ ++nRet;
+ }
+ }
+ return nRet;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexes::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nIdx = 0;
+
+ auto& rDoc = GetDoc();
+ const SwSectionFormats& rFormats = rDoc.GetSections();
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ SwSection* pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode() &&
+ nIdx++ == nIndex )
+ {
+ const uno::Reference< text::XDocumentIndex > xTmp =
+ SwXDocumentIndex::CreateXDocumentIndex(
+ rDoc, static_cast<SwTOXBaseSection *>(pSect));
+ uno::Any aRet;
+ aRet <<= xTmp;
+ return aRet;
+ }
+ }
+
+ throw lang::IndexOutOfBoundsException();
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexes::getByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+
+ auto& rDoc = GetDoc();
+ const SwSectionFormats& rFormats = rDoc.GetSections();
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ SwSection* pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode() &&
+ (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
+ == rName))
+ {
+ const uno::Reference< text::XDocumentIndex > xTmp =
+ SwXDocumentIndex::CreateXDocumentIndex(
+ rDoc, static_cast<SwTOXBaseSection *>(pSect));
+ uno::Any aRet;
+ aRet <<= xTmp;
+ return aRet;
+ }
+ }
+ throw container::NoSuchElementException();
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexes::getElementNames()
+{
+ SolarMutexGuard aGuard;
+
+ const SwSectionFormats& rFormats = GetDoc().GetSections();
+ sal_Int32 nCount = 0;
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ SwSection const*const pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode() )
+ {
+ ++nCount;
+ }
+ }
+
+ uno::Sequence< OUString > aRet(nCount);
+ OUString* pArray = aRet.getArray();
+ sal_Int32 nCnt = 0;
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ SwSection const*const pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode())
+ {
+ pArray[nCnt++] = static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName();
+ }
+ }
+ return aRet;
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndexes::hasByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+
+ const SwSectionFormats& rFormats = GetDoc().GetSections();
+ for( size_t n = 0; n < rFormats.size(); ++n )
+ {
+ SwSection const*const pSect = rFormats[ n ]->GetSection();
+ if( SectionType::ToxContent == pSect->GetType() &&
+ pSect->GetFormat()->GetSectionNode())
+ {
+ if (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
+ == rName)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndexes::getElementType()
+{
+ return cppu::UnoType<text::XDocumentIndex>::get();
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndexes::hasElements()
+{
+ return 0 != getCount();
+}
+
+SwXDocumentIndex::StyleAccess_Impl::StyleAccess_Impl(
+ SwXDocumentIndex& rParentIdx)
+ : m_xParent(&rParentIdx)
+{
+}
+
+SwXDocumentIndex::StyleAccess_Impl::~StyleAccess_Impl()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getImplementationName()
+{
+ return "SwXDocumentIndex::StyleAccess_Impl";
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.DocumentIndexParagraphStyles" };
+}
+
+void SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::replaceByIndex(
+ sal_Int32 nIndex, const uno::Any& rElement)
+{
+ SolarMutexGuard aGuard;
+
+ if(nIndex < 0 || nIndex >= MAXLEVEL)
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ uno::Sequence<OUString> aSeq;
+ if(!(rElement >>= aSeq))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const sal_Int32 nStyles = aSeq.getLength();
+ const OUString* pStyles = aSeq.getConstArray();
+ OUStringBuffer sSetStyles;
+ OUString aString;
+ for(sal_Int32 i = 0; i < nStyles; i++)
+ {
+ if(i)
+ {
+ sSetStyles.append(TOX_STYLE_DELIMITER);
+ }
+ SwStyleNameMapper::FillUIName(pStyles[i], aString,
+ SwGetPoolIdFromName::TxtColl);
+ sSetStyles.append(aString);
+ }
+ rTOXBase.SetStyleNames(sSetStyles.makeStringAndClear(), o3tl::narrowing<sal_uInt16>(nIndex));
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getCount()
+{
+ return MAXLEVEL;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+
+ if(nIndex < 0 || nIndex >= MAXLEVEL)
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ const OUString& rStyles =
+ rTOXBase.GetStyleNames(o3tl::narrowing<sal_uInt16>(nIndex));
+ const sal_Int32 nStyles = comphelper::string::getTokenCount(rStyles, TOX_STYLE_DELIMITER);
+ uno::Sequence<OUString> aStyles(nStyles);
+ OUString* pStyles = aStyles.getArray();
+ OUString aString;
+ sal_Int32 nPos = 0;
+ for(sal_Int32 i = 0; i < nStyles; ++i)
+ {
+ SwStyleNameMapper::FillProgName(
+ rStyles.getToken(0, TOX_STYLE_DELIMITER, nPos),
+ aString,
+ SwGetPoolIdFromName::TxtColl);
+ pStyles[i] = aString;
+ }
+ uno::Any aRet(&aStyles, cppu::UnoType<uno::Sequence<OUString>>::get());
+ return aRet;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getElementType()
+{
+ return cppu::UnoType<uno::Sequence<OUString>>::get();
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::hasElements()
+{
+ return true;
+}
+
+SwXDocumentIndex::TokenAccess_Impl::TokenAccess_Impl(
+ SwXDocumentIndex& rParentIdx)
+ : m_xParent(&rParentIdx)
+{
+}
+
+SwXDocumentIndex::TokenAccess_Impl::~TokenAccess_Impl()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getImplementationName()
+{
+ return "SwXDocumentIndex::TokenAccess_Impl";
+}
+
+sal_Bool SAL_CALL SwXDocumentIndex::TokenAccess_Impl::supportsService(
+ const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.DocumentIndexLevelFormat" };
+}
+
+namespace {
+
+struct TokenType_ {
+ const char *pName;
+ enum FormTokenType eTokenType;
+};
+
+}
+
+const struct TokenType_ g_TokenTypes[] =
+{
+ { "TokenEntryNumber", TOKEN_ENTRY_NO },
+ { "TokenEntryText", TOKEN_ENTRY_TEXT },
+ { "TokenTabStop", TOKEN_TAB_STOP },
+ { "TokenText", TOKEN_TEXT },
+ { "TokenPageNumber", TOKEN_PAGE_NUMS },
+ { "TokenChapterInfo", TOKEN_CHAPTER_INFO },
+ { "TokenHyperlinkStart", TOKEN_LINK_START },
+ { "TokenHyperlinkEnd", TOKEN_LINK_END },
+ { "TokenBibliographyDataField", TOKEN_AUTHORITY },
+ { nullptr, static_cast<enum FormTokenType>(0) }
+};
+
+void SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::replaceByIndex(
+ sal_Int32 nIndex, const uno::Any& rElement)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ uno::Sequence<beans::PropertyValues> aSeq;
+ if(!(rElement >>= aSeq))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ OUStringBuffer sPattern;
+ for(const beans::PropertyValues& rToken : std::as_const(aSeq))
+ {
+ const beans::PropertyValue* pProperties = rToken.getConstArray();
+ const sal_Int32 nProperties = rToken.getLength();
+ //create an invalid token
+ SwFormToken aToken(TOKEN_END);
+ for(sal_Int32 j = 0; j < nProperties; j++)
+ {
+ if ( pProperties[j].Name == "TokenType" )
+ {
+ const OUString sTokenType =
+ lcl_AnyToType<OUString>(pProperties[j].Value);
+ for (TokenType_ const* pTokenType = g_TokenTypes;
+ pTokenType->pName; ++pTokenType)
+ {
+ if (sTokenType.equalsAscii(pTokenType->pName))
+ {
+ aToken.eTokenType = pTokenType->eTokenType;
+ break;
+ }
+ }
+ }
+ else if ( pProperties[j].Name == "CharacterStyleName" )
+ {
+ OUString sCharStyleName;
+ SwStyleNameMapper::FillUIName(
+ lcl_AnyToType<OUString>(pProperties[j].Value),
+ sCharStyleName,
+ SwGetPoolIdFromName::ChrFmt);
+ aToken.sCharStyleName = sCharStyleName;
+ aToken.nPoolId = SwStyleNameMapper::GetPoolIdFromUIName (
+ sCharStyleName, SwGetPoolIdFromName::ChrFmt );
+ }
+ else if ( pProperties[j].Name == "TabStopRightAligned" )
+ {
+ const bool bRight = lcl_AnyToType<bool>(pProperties[j].Value);
+ aToken.eTabAlign = bRight ?
+ SvxTabAdjust::End : SvxTabAdjust::Left;
+ }
+ else if ( pProperties[j].Name == "TabStopPosition" )
+ {
+ sal_Int32 nPosition = 0;
+ if (!(pProperties[j].Value >>= nPosition))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ nPosition = o3tl::toTwips(nPosition, o3tl::Length::mm100);
+ if(nPosition < 0)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nTabStopPosition = nPosition;
+ }
+ else if ( pProperties[j].Name == "TabStopFillCharacter" )
+ {
+ const OUString sFillChar =
+ lcl_AnyToType<OUString>(pProperties[j].Value);
+ if (sFillChar.getLength() > 1)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.cTabFillChar =
+ sFillChar.isEmpty() ? ' ' : sFillChar[0];
+ }
+ else if ( pProperties[j].Name == "Text" )
+ {
+ aToken.sText = lcl_AnyToType<OUString>(pProperties[j].Value);
+ }
+ else if ( pProperties[j].Name == "ChapterFormat" )
+ {
+ sal_Int16 nFormat = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
+ switch(nFormat)
+ {
+ case text::ChapterFormat::NUMBER:
+ nFormat = CF_NUMBER;
+ break;
+ case text::ChapterFormat::NAME:
+ nFormat = CF_TITLE;
+ break;
+ case text::ChapterFormat::NAME_NUMBER:
+ nFormat = CF_NUM_TITLE;
+ break;
+ case text::ChapterFormat::NO_PREFIX_SUFFIX:
+ nFormat = CF_NUMBER_NOPREPST;
+ break;
+ case text::ChapterFormat::DIGIT:
+ nFormat = CF_NUM_NOPREPST_TITLE;
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nChapterFormat = nFormat;
+ }
+// #i53420#
+ else if ( pProperties[j].Name == "ChapterLevel" )
+ {
+ const sal_Int16 nLevel = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
+ if( nLevel < 1 || nLevel > MAXLEVEL )
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nOutlineLevel = nLevel;
+ }
+ else if ( pProperties[j].Name == "BibliographyDataField" )
+ {
+ sal_Int16 nType = 0;
+ pProperties[j].Value >>= nType;
+ if(nType < 0 || nType > text::BibliographyDataField::LOCAL_URL)
+ {
+ throw lang::IllegalArgumentException("BibliographyDataField - wrong value", nullptr, j);
+ }
+ aToken.nAuthorityField = nType;
+ }
+ // #i21237#
+ else if ( pProperties[j].Name == "WithTab" )
+ {
+ aToken.bWithTab = lcl_AnyToType<bool>(pProperties[j].Value);
+ }
+
+ }
+ //exception if wrong TokenType
+ if(TOKEN_END <= aToken.eTokenType )
+ {
+ throw lang::IllegalArgumentException();
+ }
+ // set TokenType from TOKEN_ENTRY_TEXT to TOKEN_ENTRY if it is
+ // not a content index
+ if(TOKEN_ENTRY_TEXT == aToken.eTokenType &&
+ (TOX_CONTENT != rTOXBase.GetType()))
+ {
+ aToken.eTokenType = TOKEN_ENTRY;
+ }
+// #i53420#
+// check for chapter format allowed values if it was TOKEN_ENTRY_NO type
+// only allowed value are CF_NUMBER and CF_NUM_NOPREPST_TITLE
+// reading from file
+ if( TOKEN_ENTRY_NO == aToken.eTokenType )
+ {
+ switch(aToken.nChapterFormat)
+ {
+ case CF_NUMBER:
+ case CF_NUM_NOPREPST_TITLE:
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ }
+
+ if (rTOXBase.GetType() == TOX_CONTENT)
+ {
+ if (aToken.eTokenType == TOKEN_LINK_START && aToken.sCharStyleName.isEmpty())
+ {
+ aToken.sCharStyleName = SwResId(STR_POOLCHR_TOXJUMP);
+ }
+ }
+
+ sPattern.append(aToken.GetString());
+ }
+ SwForm aForm(rTOXBase.GetTOXForm());
+ aForm.SetPattern(o3tl::narrowing<sal_uInt16>(nIndex), sPattern.makeStringAndClear());
+ rTOXBase.SetTOXForm(aForm);
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getCount()
+{
+ SolarMutexGuard aGuard;
+
+ const sal_Int32 nRet = m_xParent->m_pImpl->GetFormMax();
+ return nRet;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ // #i21237#
+ SwFormTokens aPattern = rTOXBase.GetTOXForm().
+ GetPattern(o3tl::narrowing<sal_uInt16>(nIndex));
+
+ sal_Int32 nTokenCount = 0;
+ uno::Sequence< beans::PropertyValues > aRetSeq;
+ OUString aProgCharStyle;
+ for(const SwFormToken& aToken : aPattern) // #i21237#
+ {
+ nTokenCount++;
+ aRetSeq.realloc(nTokenCount);
+ beans::PropertyValues* pTokenProps = aRetSeq.getArray();
+
+ uno::Sequence< beans::PropertyValue >& rCurTokenSeq =
+ pTokenProps[nTokenCount-1];
+ SwStyleNameMapper::FillProgName(
+ aToken.sCharStyleName,
+ aProgCharStyle,
+ SwGetPoolIdFromName::ChrFmt);
+ switch(aToken.eTokenType)
+ {
+ case TOKEN_ENTRY_NO:
+ {
+// #i53420#
+// writing to file (from doc to properties)
+ sal_Int32 nElements = 2;
+ sal_Int32 nCurrentElement = 0;
+
+ // check for default value
+ if (aToken.nChapterFormat != CF_NUMBER)
+ {
+ nElements++;//we need the element
+ }
+ if( aToken.nOutlineLevel != MAXLEVEL )
+ {
+ nElements++;
+ }
+
+ rCurTokenSeq.realloc( nElements );
+
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[nCurrentElement].Name = "TokenType";
+ pArr[nCurrentElement++].Value <<=
+ OUString("TokenEntryNumber");
+
+ pArr[nCurrentElement].Name = "CharacterStyleName";
+ pArr[nCurrentElement++].Value <<= aProgCharStyle;
+ if( aToken.nChapterFormat != CF_NUMBER )
+ {
+ pArr[nCurrentElement].Name = "ChapterFormat";
+ sal_Int16 nVal;
+// the allowed values for chapter format, when used as entry number,
+// are CF_NUMBER and CF_NUM_NOPREPST_TITLE only, all else forced to
+//CF_NUMBER
+ switch(aToken.nChapterFormat)
+ {
+ default:
+ case CF_NUMBER:
+ nVal = text::ChapterFormat::NUMBER;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nVal = text::ChapterFormat::DIGIT;
+ break;
+ }
+ pArr[nCurrentElement++].Value <<= nVal;
+ }
+
+ // only a ChapterLevel != MAXLEVEL is registered
+ if (aToken.nOutlineLevel != MAXLEVEL)
+ {
+ pArr[nCurrentElement].Name = "ChapterLevel";
+ pArr[nCurrentElement].Value <<= aToken.nOutlineLevel;
+ }
+ }
+ break;
+ case TOKEN_ENTRY: // no difference between Entry and Entry Text
+ case TOKEN_ENTRY_TEXT:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<= OUString("TokenEntryText");
+
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_TAB_STOP:
+ {
+ rCurTokenSeq.realloc(5); // #i21237#
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<= OUString("TokenTabStop");
+
+ if(SvxTabAdjust::End == aToken.eTabAlign)
+ {
+ pArr[1].Name = "TabStopRightAligned";
+ pArr[1].Value <<= true;
+ }
+ else
+ {
+ pArr[1].Name = "TabStopPosition";
+ sal_Int32 nPos = convertTwipToMm100(aToken.nTabStopPosition);
+ if(nPos < 0)
+ nPos = 0;
+ pArr[1].Value <<= nPos;
+ }
+ pArr[2].Name = "TabStopFillCharacter";
+ pArr[2].Value <<= OUString(aToken.cTabFillChar);
+ pArr[3].Name = "CharacterStyleName";
+ pArr[3].Value <<= aProgCharStyle;
+ // #i21237#
+ pArr[4].Name = "WithTab";
+ pArr[4].Value <<= aToken.bWithTab;
+ }
+ break;
+ case TOKEN_TEXT:
+ {
+ rCurTokenSeq.realloc( 3 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<= OUString("TokenText");
+
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = "Text";
+ pArr[2].Value <<= aToken.sText;
+ }
+ break;
+ case TOKEN_PAGE_NUMS:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<= OUString("TokenPageNumber");
+
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_CHAPTER_INFO:
+ {
+ rCurTokenSeq.realloc( 4 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<= OUString("TokenChapterInfo");
+
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = "ChapterFormat";
+ sal_Int16 nVal = text::ChapterFormat::NUMBER;
+ switch(aToken.nChapterFormat)
+ {
+ case CF_NUMBER:
+ nVal = text::ChapterFormat::NUMBER;
+ break;
+ case CF_TITLE:
+ nVal = text::ChapterFormat::NAME;
+ break;
+ case CF_NUM_TITLE:
+ nVal = text::ChapterFormat::NAME_NUMBER;
+ break;
+ case CF_NUMBER_NOPREPST:
+ nVal = text::ChapterFormat::NO_PREFIX_SUFFIX;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nVal = text::ChapterFormat::DIGIT;
+ break;
+ }
+ pArr[2].Value <<= nVal;
+// #i53420#
+ pArr[3].Name = "ChapterLevel";
+ pArr[3].Value <<= aToken.nOutlineLevel;
+ }
+ break;
+ case TOKEN_LINK_START:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<=
+ OUString("TokenHyperlinkStart");
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_LINK_END:
+ {
+ rCurTokenSeq.realloc( 1 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<=
+ OUString("TokenHyperlinkEnd");
+ }
+ break;
+ case TOKEN_AUTHORITY:
+ {
+ rCurTokenSeq.realloc( 3 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = "TokenType";
+ pArr[0].Value <<=
+ OUString("TokenBibliographyDataField");
+
+ pArr[1].Name = "CharacterStyleName";
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = "BibliographyDataField";
+ pArr[2].Value <<= sal_Int16(aToken.nAuthorityField);
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+
+ uno::Any aRet;
+ aRet <<= aRetSeq;
+ return aRet;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getElementType()
+{
+ return cppu::UnoType<uno::Sequence< beans::PropertyValues >>::get();
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::hasElements()
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */