Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / unocore / unoidx.cxx
blob2b6afa848414df1644313ffe67108e7e815819e2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <unoidx.hxx>
22 #include <unoidxcoll.hxx>
24 #include <com/sun/star/beans/PropertyAttribute.hpp>
25 #include <com/sun/star/container/XIndexReplace.hpp>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <com/sun/star/text/ChapterFormat.hpp>
29 #include <com/sun/star/text/ReferenceFieldPart.hpp>
30 #include <com/sun/star/text/BibliographyDataField.hpp>
31 #include <com/sun/star/text/XTextDocument.hpp>
33 #include <comphelper/interfacecontainer4.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <tools/UnitConversion.hxx>
36 #include <vcl/svapp.hxx>
37 #include <i18nlangtag/languagetag.hxx>
38 #include <editeng/memberids.h>
39 #include <swtypes.hxx>
40 #include <shellres.hxx>
41 #include <viewsh.hxx>
42 #include <doc.hxx>
43 #include <IDocumentLayoutAccess.hxx>
44 #include <docary.hxx>
45 #include <fmtcntnt.hxx>
46 #include <unomap.hxx>
47 #include <unotextrange.hxx>
48 #include <unotextcursor.hxx>
49 #include <unosection.hxx>
50 #include <doctxm.hxx>
51 #include <txttxmrk.hxx>
52 #include <ndtxt.hxx>
53 #include <docsh.hxx>
54 #include <chpfld.hxx>
55 #include <editsh.hxx>
56 #include <SwStyleNameMapper.hxx>
57 #include <strings.hrc>
58 #include <comphelper/servicehelper.hxx>
59 #include <comphelper/string.hxx>
60 #include <cppuhelper/implbase.hxx>
61 #include <svl/itemprop.hxx>
62 #include <svl/listener.hxx>
63 #include <mutex>
65 using namespace ::com::sun::star;
67 /// @throws lang::IllegalArgumentException
68 template<typename T>
69 static T
70 lcl_AnyToType(uno::Any const& rVal)
72 T aRet{};
73 if(!(rVal >>= aRet))
75 throw lang::IllegalArgumentException();
77 return aRet;
80 /// @throws lang::IllegalArgumentException
81 template<typename T>
82 static void lcl_AnyToBitMask(uno::Any const& rValue,
83 T & rBitMask, const T nBit)
85 rBitMask = lcl_AnyToType<bool>(rValue)
86 ? (rBitMask | nBit)
87 : (rBitMask & ~nBit);
90 template<typename T>
91 static void lcl_BitMaskToAny(uno::Any & o_rValue,
92 const T nBitMask, const T nBit)
94 const bool bRet(nBitMask & nBit);
95 o_rValue <<= bRet;
98 static void
99 lcl_ReAssignTOXType(SwDoc& rDoc, SwTOXBase& rTOXBase, const OUString& rNewName)
101 const sal_uInt16 nUserCount = rDoc.GetTOXTypeCount( TOX_USER );
102 const SwTOXType* pNewType = nullptr;
103 for(sal_uInt16 nUser = 0; nUser < nUserCount; nUser++)
105 const SwTOXType* pType = rDoc.GetTOXType( TOX_USER, nUser );
106 if (pType->GetTypeName()==rNewName)
108 pNewType = pType;
109 break;
112 if(!pNewType)
114 SwTOXType aNewType(rDoc, TOX_USER, rNewName);
115 pNewType = rDoc.InsertTOXType( aNewType );
118 rTOXBase.RegisterToTOXType( *const_cast<SwTOXType*>(pNewType) );
121 constexpr OUStringLiteral cUserDefined = u"User-Defined";
122 const char cUserSuffix[] = " (user)";
123 #define USER_LEN 12
124 #define USER_AND_SUFFIXLEN 19
126 static void lcl_ConvertTOUNameToProgrammaticName(OUString& rTmp)
128 ShellResource* pShellRes = SwViewShell::GetShellRes();
130 if(rTmp==pShellRes->aTOXUserName)
132 rTmp = cUserDefined;
134 // if the version is not English but the alternative index's name is
135 // "User-Defined" a " (user)" is appended
136 else if(rTmp == cUserDefined)
138 rTmp += cUserSuffix;
142 static void
143 lcl_ConvertTOUNameToUserName(OUString& rTmp)
145 ShellResource* pShellRes = SwViewShell::GetShellRes();
146 if (rTmp == cUserDefined)
148 rTmp = pShellRes->aTOXUserName;
150 else if (pShellRes->aTOXUserName != cUserDefined &&
151 USER_AND_SUFFIXLEN == rTmp.getLength())
153 //make sure that in non-English versions the " (user)" suffix is removed
154 if (rTmp.startsWith(cUserDefined) &&
155 rTmp.match(cUserSuffix, USER_LEN))
157 rTmp = cUserDefined;
162 typedef ::cppu::WeakImplHelper
163 < lang::XServiceInfo
164 , container::XIndexReplace
165 > SwXDocumentIndexStyleAccess_Base;
167 class SwXDocumentIndex::StyleAccess_Impl
168 : public SwXDocumentIndexStyleAccess_Base
171 private:
172 /// can be destroyed threadsafely, so no UnoImplPtr here
173 ::rtl::Reference<SwXDocumentIndex> m_xParent;
175 virtual ~StyleAccess_Impl() override;
177 public:
178 explicit StyleAccess_Impl(SwXDocumentIndex& rParentIdx);
180 // XServiceInfo
181 virtual OUString SAL_CALL getImplementationName() override;
182 virtual sal_Bool SAL_CALL
183 supportsService(const OUString& rServiceName) override;
184 virtual uno::Sequence< OUString > SAL_CALL
185 getSupportedServiceNames() override;
187 // XElementAccess
188 virtual uno::Type SAL_CALL getElementType() override;
189 virtual sal_Bool SAL_CALL hasElements() override;
191 // XIndexAccess
192 virtual sal_Int32 SAL_CALL getCount() override;
193 virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
195 // XIndexReplace
196 virtual void SAL_CALL
197 replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
201 typedef ::cppu::WeakImplHelper
202 < lang::XServiceInfo
203 , container::XIndexReplace
204 > SwXDocumentIndexTokenAccess_Base;
206 class SwXDocumentIndex::TokenAccess_Impl
207 : public SwXDocumentIndexTokenAccess_Base
210 private:
211 /// can be destroyed threadsafely, so no UnoImplPtr here
212 ::rtl::Reference<SwXDocumentIndex> m_xParent;
214 virtual ~TokenAccess_Impl() override;
216 public:
218 explicit TokenAccess_Impl(SwXDocumentIndex& rParentIdx);
220 // XServiceInfo
221 virtual OUString SAL_CALL getImplementationName() override;
222 virtual sal_Bool SAL_CALL
223 supportsService(const OUString& rServiceName) override;
224 virtual uno::Sequence< OUString > SAL_CALL
225 getSupportedServiceNames() override;
227 // XElementAccess
228 virtual uno::Type SAL_CALL getElementType() override;
229 virtual sal_Bool SAL_CALL hasElements() override;
231 // XIndexAccess
232 virtual sal_Int32 SAL_CALL getCount() override;
233 virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
235 // XIndexReplace
236 virtual void SAL_CALL
237 replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
241 namespace {
243 class SwDocIndexDescriptorProperties_Impl
245 private:
246 std::unique_ptr<SwTOXBase> m_pTOXBase;
247 OUString m_sUserTOXTypeName;
249 public:
250 explicit SwDocIndexDescriptorProperties_Impl(SwTOXType const*const pType);
252 SwTOXBase & GetTOXBase() { return *m_pTOXBase; }
253 const OUString& GetTypeName() const { return m_sUserTOXTypeName; }
254 void SetTypeName(const OUString& rSet) { m_sUserTOXTypeName = rSet; }
259 SwDocIndexDescriptorProperties_Impl::SwDocIndexDescriptorProperties_Impl(
260 SwTOXType const*const pType)
262 SwForm aForm(pType->GetType());
263 m_pTOXBase.reset(new SwTOXBase(pType, aForm,
264 SwTOXElement::Mark, pType->GetTypeName()));
265 if(pType->GetType() == TOX_CONTENT || pType->GetType() == TOX_USER)
267 m_pTOXBase->SetLevel(MAXLEVEL);
269 m_sUserTOXTypeName = pType->GetTypeName();
272 static sal_uInt16
273 lcl_TypeToPropertyMap_Index(const TOXTypes eType)
275 switch (eType)
277 case TOX_INDEX: return PROPERTY_MAP_INDEX_IDX;
278 case TOX_CONTENT: return PROPERTY_MAP_INDEX_CNTNT;
279 case TOX_TABLES: return PROPERTY_MAP_INDEX_TABLES;
280 case TOX_ILLUSTRATIONS: return PROPERTY_MAP_INDEX_ILLUSTRATIONS;
281 case TOX_OBJECTS: return PROPERTY_MAP_INDEX_OBJECTS;
282 case TOX_AUTHORITIES: return PROPERTY_MAP_BIBLIOGRAPHY;
283 //case TOX_USER:
284 default:
285 return PROPERTY_MAP_INDEX_USER;
289 class SwXDocumentIndex::Impl final: public SvtListener
291 private:
292 SwSectionFormat* m_pFormat;
294 public:
295 unotools::WeakReference<SwXDocumentIndex> m_wThis;
296 std::mutex m_Mutex; // just for OInterfaceContainerHelper4
297 ::comphelper::OInterfaceContainerHelper4<util::XRefreshListener> m_RefreshListeners;
298 ::comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_EventListeners;
299 SfxItemPropertySet const& m_rPropSet;
300 const TOXTypes m_eTOXType;
301 bool m_bIsDescriptor;
302 SwDoc* m_pDoc;
303 std::optional<SwDocIndexDescriptorProperties_Impl> m_oProps;
304 uno::WeakReference<container::XIndexReplace> m_wStyleAccess;
305 uno::WeakReference<container::XIndexReplace> m_wTokenAccess;
307 Impl(SwDoc& rDoc, const TOXTypes eType, SwTOXBaseSection *const pBaseSection)
308 : m_pFormat(pBaseSection ? pBaseSection->GetFormat() : nullptr)
309 , m_rPropSet(*aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Index(eType)))
310 , m_eTOXType(eType)
311 , m_bIsDescriptor(nullptr == pBaseSection)
312 , m_pDoc(&rDoc)
313 , m_oProps(m_bIsDescriptor
314 ? std::optional<SwDocIndexDescriptorProperties_Impl>(rDoc.GetTOXType(eType, 0))
315 : std::nullopt)
317 if(m_pFormat)
318 StartListening(m_pFormat->GetNotifier());
321 void SetSectionFormat(SwSectionFormat& rFormat)
323 EndListeningAll();
324 m_pFormat = &rFormat;
325 StartListening(rFormat.GetNotifier());
328 SwSectionFormat* GetSectionFormat() const {
329 return m_pFormat;
332 SwTOXBase & GetTOXSectionOrThrow() const
334 SwSectionFormat *const pSectionFormat(GetSectionFormat());
335 SwTOXBase *const pTOXSection( m_bIsDescriptor
336 ? &const_cast<SwDocIndexDescriptorProperties_Impl&>(*m_oProps).GetTOXBase()
337 : (pSectionFormat
338 ? static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection())
339 : nullptr));
340 if (!pTOXSection)
342 throw uno::RuntimeException(
343 "SwXDocumentIndex: disposed or invalid", nullptr);
345 return *pTOXSection;
348 sal_Int32 GetFormMax() const
350 SwTOXBase & rSection( GetTOXSectionOrThrow() );
351 return m_bIsDescriptor
352 ? SwForm::GetFormMaxLevel(m_eTOXType)
353 : rSection.GetTOXForm().GetFormMax();
355 virtual void Notify(const SfxHint&) override;
359 void SwXDocumentIndex::Impl::Notify(const SfxHint& rHint)
361 if (rHint.GetId() == SfxHintId::SwLegacyModify)
363 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
364 if(pLegacy->m_pOld && pLegacy->m_pOld->Which() == RES_REMOVE_UNO_OBJECT)
365 m_pFormat = nullptr;
367 else if(rHint.GetId() == SfxHintId::Dying)
368 m_pFormat = nullptr;
369 if(!m_pFormat)
371 EndListeningAll();
372 rtl::Reference<SwXDocumentIndex> const xThis(m_wThis);
373 if (!xThis.is())
374 { // fdo#72695: if UNO object is already dead, don't revive it with event
375 return;
377 std::unique_lock g(m_Mutex);
378 lang::EventObject const ev(static_cast<cppu::OWeakObject*>(xThis.get()));
379 m_RefreshListeners.disposeAndClear(g, ev);
380 m_EventListeners.disposeAndClear(g, ev);
384 SwXDocumentIndex::SwXDocumentIndex(
385 SwTOXBaseSection & rBaseSection, SwDoc & rDoc)
386 : m_pImpl( new SwXDocumentIndex::Impl(
387 rDoc, rBaseSection.SwTOXBase::GetType(), & rBaseSection) )
391 SwXDocumentIndex::SwXDocumentIndex(const TOXTypes eType, SwDoc& rDoc)
392 : m_pImpl( new SwXDocumentIndex::Impl(rDoc, eType, nullptr) )
396 SwXDocumentIndex::~SwXDocumentIndex()
400 rtl::Reference<SwXDocumentIndex>
401 SwXDocumentIndex::CreateXDocumentIndex(
402 SwDoc & rDoc, SwTOXBaseSection * pSection, TOXTypes const eTypes)
404 // re-use existing SwXDocumentIndex
405 // #i105557#: do not iterate over the registered clients: race condition
406 rtl::Reference<SwXDocumentIndex> xIndex;
407 if (pSection)
409 SwSectionFormat const *const pFormat = pSection->GetFormat();
410 xIndex = dynamic_cast<SwXDocumentIndex*>(pFormat->GetXObject().get().get());
412 if (!xIndex.is())
414 xIndex = pSection
415 ? new SwXDocumentIndex(*pSection, rDoc)
416 : new SwXDocumentIndex(eTypes, rDoc);
417 if (pSection)
419 pSection->GetFormat()->SetXObject(static_cast<cppu::OWeakObject*>(xIndex.get()));
421 // need a permanent Reference to initialize m_wThis
422 xIndex->m_pImpl->m_wThis = xIndex.get();
424 return xIndex;
427 OUString SAL_CALL
428 SwXDocumentIndex::getImplementationName()
430 return "SwXDocumentIndex";
433 sal_Bool SAL_CALL
434 SwXDocumentIndex::supportsService(const OUString& rServiceName)
436 return cppu::supportsService(this, rServiceName);
439 uno::Sequence< OUString > SAL_CALL
440 SwXDocumentIndex::getSupportedServiceNames()
442 SolarMutexGuard g;
444 uno::Sequence< OUString > aRet(2);
445 OUString* pArray = aRet.getArray();
446 pArray[0] = "com.sun.star.text.BaseIndex";
447 switch (m_pImpl->m_eTOXType)
449 case TOX_INDEX:
450 pArray[1] = "com.sun.star.text.DocumentIndex";
451 break;
452 case TOX_CONTENT:
453 pArray[1] = "com.sun.star.text.ContentIndex";
454 break;
455 case TOX_TABLES:
456 pArray[1] = "com.sun.star.text.TableIndex";
457 break;
458 case TOX_ILLUSTRATIONS:
459 pArray[1] = "com.sun.star.text.IllustrationsIndex";
460 break;
461 case TOX_OBJECTS:
462 pArray[1] = "com.sun.star.text.ObjectIndex";
463 break;
464 case TOX_AUTHORITIES:
465 pArray[1] = "com.sun.star.text.Bibliography";
466 break;
467 //case TOX_USER:
468 default:
469 pArray[1] = "com.sun.star.text.UserDefinedIndex";
471 return aRet;
474 OUString SAL_CALL SwXDocumentIndex::getServiceName()
476 SolarMutexGuard g;
478 SwServiceType nObjectType = SwServiceType::TypeIndex;
479 switch (m_pImpl->m_eTOXType)
481 case TOX_USER: nObjectType = SwServiceType::UserIndex;
482 break;
483 case TOX_CONTENT: nObjectType = SwServiceType::ContentIndex;
484 break;
485 case TOX_ILLUSTRATIONS: nObjectType = SwServiceType::IndexIllustrations;
486 break;
487 case TOX_OBJECTS: nObjectType = SwServiceType::IndexObjects;
488 break;
489 case TOX_TABLES: nObjectType = SwServiceType::IndexTables;
490 break;
491 case TOX_AUTHORITIES: nObjectType = SwServiceType::IndexBibliography;
492 break;
493 default:
494 break;
496 return SwXServiceProvider::GetProviderName(nObjectType);
499 void SAL_CALL SwXDocumentIndex::update()
501 return refresh(); // update is from deprecated XDocumentIndex
504 uno::Reference< beans::XPropertySetInfo > SAL_CALL
505 SwXDocumentIndex::getPropertySetInfo()
507 SolarMutexGuard g;
509 const uno::Reference< beans::XPropertySetInfo > xRef =
510 m_pImpl->m_rPropSet.getPropertySetInfo();
511 return xRef;
514 void SAL_CALL
515 SwXDocumentIndex::setPropertyValue(
516 const OUString& rPropertyName, const uno::Any& rValue)
518 SolarMutexGuard aGuard;
520 SfxItemPropertyMapEntry const*const pEntry =
521 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
522 if (!pEntry)
524 throw beans::UnknownPropertyException(
525 "Unknown property: " + rPropertyName,
526 static_cast<cppu::OWeakObject *>(this));
528 if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
530 throw beans::PropertyVetoException(
531 "Property is read-only: " + rPropertyName,
532 static_cast<cppu::OWeakObject *>(this));
535 SwSectionFormat *const pSectionFormat(m_pImpl->GetSectionFormat());
536 SwTOXBase & rTOXBase( m_pImpl->GetTOXSectionOrThrow() );
538 SwTOXElement nCreate = rTOXBase.GetCreateType();
539 SwTOOElements nOLEOptions = rTOXBase.GetOLEOptions();
540 const TOXTypes eTxBaseType = rTOXBase.GetTOXType()->GetType();
541 SwTOIOptions nTOIOptions = (eTxBaseType == TOX_INDEX)
542 ? rTOXBase.GetOptions() : SwTOIOptions::NONE;
543 SwForm aForm(rTOXBase.GetTOXForm());
544 bool bForm = false;
545 switch (pEntry->nWID)
547 case WID_IDX_TITLE:
549 OUString sNewName;
550 if (!(rValue >>= sNewName))
552 throw lang::IllegalArgumentException();
554 rTOXBase.SetTitle(sNewName);
556 break;
557 case WID_IDX_NAME:
559 OUString sNewName;
560 if (!(rValue >>= sNewName))
562 throw lang::IllegalArgumentException();
564 rTOXBase.SetTOXName(sNewName);
566 break;
567 case WID_USER_IDX_NAME:
569 OUString sNewName;
570 if (!(rValue >>= sNewName))
572 throw lang::IllegalArgumentException();
574 lcl_ConvertTOUNameToUserName(sNewName);
575 OSL_ENSURE(TOX_USER == eTxBaseType,
576 "tox type name can only be changed for user indexes");
577 if (pSectionFormat)
579 if (rTOXBase.GetTOXType()->GetTypeName() != sNewName)
581 lcl_ReAssignTOXType(*pSectionFormat->GetDoc(),
582 rTOXBase, sNewName);
585 else
587 m_pImpl->m_oProps->SetTypeName(sNewName);
590 break;
591 case WID_IDX_LOCALE:
593 lang::Locale aLocale;
594 if (!(rValue>>= aLocale))
596 throw lang::IllegalArgumentException();
598 rTOXBase.SetLanguage( LanguageTag::convertToLanguageType(aLocale));
600 break;
601 case WID_IDX_SORT_ALGORITHM:
603 OUString sTmp;
604 if (!(rValue >>= sTmp))
606 throw lang::IllegalArgumentException();
608 rTOXBase.SetSortAlgorithm(sTmp);
610 break;
611 case WID_LEVEL:
613 rTOXBase.SetLevel(lcl_AnyToType<sal_Int16>(rValue));
615 break;
616 case WID_TOC_BOOKMARK:
618 rTOXBase.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
619 nCreate = SwTOXElement::Bookmark;
620 rTOXBase.SetCreate(nCreate);
622 break;
623 case WID_CREATE_FROM_MARKS:
624 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Mark);
625 break;
626 case WID_CREATE_FROM_OUTLINE:
627 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::OutlineLevel);
628 break;
629 case WID_TOC_PARAGRAPH_OUTLINE_LEVEL:
630 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::ParagraphOutlineLevel);
631 break;
632 case WID_TAB_IN_TOC:
633 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableInToc);
634 break;
635 case WID_TOC_NEWLINE:
636 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Newline);
637 break;
638 // case WID_PARAGRAPH_STYLE_NAMES :OSL_FAIL("not implemented")
639 // break;
640 case WID_HIDE_TABLEADER_PAGENUMBERS:
641 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableLeader);
642 break ;
643 case WID_CREATE_FROM_CHAPTER:
644 rTOXBase.SetFromChapter(lcl_AnyToType<bool>(rValue));
645 break;
646 case WID_CREATE_FROM_LABELS:
647 rTOXBase.SetFromObjectNames(! lcl_AnyToType<bool>(rValue));
648 break;
649 case WID_PROTECTED:
651 bool bSet = lcl_AnyToType<bool>(rValue);
652 rTOXBase.SetProtected(bSet);
653 if (pSectionFormat)
655 static_cast<SwTOXBaseSection &>(rTOXBase).SetProtect(bSet);
658 break;
659 case WID_USE_ALPHABETICAL_SEPARATORS:
660 lcl_AnyToBitMask(rValue, nTOIOptions,
661 SwTOIOptions::AlphaDelimiter);
662 break;
663 case WID_USE_KEY_AS_ENTRY:
664 lcl_AnyToBitMask(rValue, nTOIOptions,
665 SwTOIOptions::KeyAsEntry);
666 break;
667 case WID_USE_COMBINED_ENTRIES:
668 lcl_AnyToBitMask(rValue, nTOIOptions,
669 SwTOIOptions::SameEntry);
670 break;
671 case WID_IS_CASE_SENSITIVE:
672 lcl_AnyToBitMask(rValue, nTOIOptions,
673 SwTOIOptions::CaseSensitive);
674 break;
675 case WID_USE_P_P:
676 lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::FF);
677 break;
678 case WID_USE_DASH:
679 lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::Dash);
680 break;
681 case WID_USE_UPPER_CASE:
682 lcl_AnyToBitMask(rValue, nTOIOptions,
683 SwTOIOptions::InitialCaps);
684 break;
685 case WID_IS_COMMA_SEPARATED:
686 bForm = true;
687 aForm.SetCommaSeparated(lcl_AnyToType<bool>(rValue));
688 break;
689 case WID_LABEL_CATEGORY:
691 // convert file-format/API/external programmatic english name
692 // to internal UI name before usage
693 rTOXBase.SetSequenceName( SwStyleNameMapper::GetSpecialExtraUIName(
694 lcl_AnyToType<OUString>(rValue) ) );
696 break;
697 case WID_LABEL_DISPLAY_TYPE:
699 const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
700 sal_uInt16 nSet = CAPTION_COMPLETE;
701 switch (nVal)
703 case text::ReferenceFieldPart::TEXT:
704 nSet = CAPTION_COMPLETE;
705 break;
706 case text::ReferenceFieldPart::CATEGORY_AND_NUMBER:
707 nSet = CAPTION_NUMBER;
708 break;
709 case text::ReferenceFieldPart::ONLY_CAPTION:
710 nSet = CAPTION_TEXT;
711 break;
712 default:
713 throw lang::IllegalArgumentException();
715 rTOXBase.SetCaptionDisplay(static_cast<SwCaptionDisplay>(nSet));
717 break;
718 case WID_USE_LEVEL_FROM_SOURCE:
719 rTOXBase.SetLevelFromChapter(lcl_AnyToType<bool>(rValue));
720 break;
721 case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
723 OUString aString;
724 SwStyleNameMapper::FillUIName(lcl_AnyToType<OUString>(rValue),
725 aString, SwGetPoolIdFromName::ChrFmt);
726 rTOXBase.SetMainEntryCharStyle( aString );
728 break;
729 case WID_CREATE_FROM_TABLES:
730 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Table);
731 break;
732 case WID_CREATE_FROM_TEXT_FRAMES:
733 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Frame);
734 break;
735 case WID_CREATE_FROM_GRAPHIC_OBJECTS:
736 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Graphic);
737 break;
738 case WID_CREATE_FROM_EMBEDDED_OBJECTS:
739 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Ole);
740 break;
741 case WID_CREATE_FROM_STAR_MATH:
742 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Math);
743 break;
744 case WID_CREATE_FROM_STAR_CHART:
745 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Chart);
746 break;
747 case WID_CREATE_FROM_STAR_CALC:
748 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Calc);
749 break;
750 case WID_CREATE_FROM_STAR_DRAW:
751 lcl_AnyToBitMask(rValue, nOLEOptions,
752 SwTOOElements::DrawImpress);
753 break;
754 case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
755 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Other);
756 break;
757 case WID_PARA_HEAD:
759 OUString aString;
760 SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
761 aString, SwGetPoolIdFromName::TxtColl);
762 bForm = true;
763 // Header is on Pos 0
764 aForm.SetTemplate( 0, aString );
766 break;
767 case WID_IS_RELATIVE_TABSTOPS:
768 bForm = true;
769 aForm.SetRelTabPos(lcl_AnyToType<bool>(rValue));
770 break;
771 case WID_PARA_SEP:
773 OUString aString;
774 bForm = true;
775 SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
776 aString, SwGetPoolIdFromName::TxtColl);
777 aForm.SetTemplate( 1, aString );
779 break;
780 case WID_CREATE_FROM_PARAGRAPH_STYLES:
781 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Template);
782 break;
783 case WID_CREATE_FROM_PARAGRAPH_STYLE:
785 OUString style;
786 if (rValue >>= style)
788 if (style.indexOf(TOX_STYLE_DELIMITER) != -1)
790 throw lang::IllegalArgumentException();
792 lcl_AnyToBitMask(uno::Any(true), nCreate, SwTOXElement::Template);
793 OUString uiStyle;
794 SwStyleNameMapper::FillUIName(style, uiStyle, SwGetPoolIdFromName::TxtColl);
795 rTOXBase.SetStyleNames(uiStyle, 0);
797 else if (!rValue.hasValue())
799 lcl_AnyToBitMask(uno::Any(false), nCreate, SwTOXElement::Template);
801 else
803 throw lang::IllegalArgumentException();
806 break;
808 case WID_PARA_LEV1:
809 case WID_PARA_LEV2:
810 case WID_PARA_LEV3:
811 case WID_PARA_LEV4:
812 case WID_PARA_LEV5:
813 case WID_PARA_LEV6:
814 case WID_PARA_LEV7:
815 case WID_PARA_LEV8:
816 case WID_PARA_LEV9:
817 case WID_PARA_LEV10:
819 bForm = true;
820 // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
821 const sal_uInt16 nLPos = rTOXBase.GetType() == TOX_INDEX ? 2 : 1;
822 OUString aString;
823 SwStyleNameMapper::FillUIName( lcl_AnyToType<OUString>(rValue),
824 aString, SwGetPoolIdFromName::TxtColl);
825 aForm.SetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1, aString );
827 break;
828 default:
829 //this is for items only
830 if (WID_PRIMARY_KEY > pEntry->nWID)
832 const SwAttrSet& rSet =
833 SwDoc::GetTOXBaseAttrSet(rTOXBase);
834 SfxItemSet aAttrSet(rSet);
835 m_pImpl->m_rPropSet.setPropertyValue(
836 rPropertyName, rValue, aAttrSet);
838 const SwSectionFormats& rSects = m_pImpl->m_pDoc->GetSections();
839 for (size_t i = 0; i < rSects.size(); ++i)
841 const SwSectionFormat* pTmpFormat = rSects[ i ];
842 if (pTmpFormat == pSectionFormat)
844 SwSectionData tmpData(
845 static_cast<SwTOXBaseSection&>(rTOXBase));
846 m_pImpl->m_pDoc->UpdateSection(i, tmpData, & aAttrSet);
847 break;
852 rTOXBase.SetCreate(nCreate);
853 rTOXBase.SetOLEOptions(nOLEOptions);
854 if (rTOXBase.GetTOXType()->GetType() == TOX_INDEX)
856 rTOXBase.SetOptions(nTOIOptions);
858 if (bForm)
860 rTOXBase.SetTOXForm(aForm);
864 uno::Any SAL_CALL
865 SwXDocumentIndex::getPropertyValue(const OUString& rPropertyName)
867 SolarMutexGuard aGuard;
869 uno::Any aRet;
870 SfxItemPropertyMapEntry const*const pEntry =
871 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
872 if (!pEntry)
874 throw beans::UnknownPropertyException(
875 "Unknown property: " + rPropertyName,
876 static_cast< cppu::OWeakObject * >(this));
878 // TODO: is this the best approach to tell API clients about the change?
879 if (pEntry->nWID == RES_BACKGROUND && pEntry->nMemberId == MID_GRAPHIC_URL)
881 throw uno::RuntimeException("Getting GraphicURL property is not supported");
884 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
885 SwTOXBase* pTOXBase = nullptr;
886 if (pSectionFormat)
888 pTOXBase = static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection());
890 else if (m_pImpl->m_bIsDescriptor)
892 pTOXBase = &m_pImpl->m_oProps->GetTOXBase();
894 if(pTOXBase)
896 const SwTOXElement nCreate = pTOXBase->GetCreateType();
897 const SwTOOElements nOLEOptions = pTOXBase->GetOLEOptions();
898 const SwTOIOptions nTOIOptions =
899 (pTOXBase->GetTOXType()->GetType() == TOX_INDEX)
900 ? pTOXBase->GetOptions()
901 : SwTOIOptions::NONE;
902 const SwForm& rForm = pTOXBase->GetTOXForm();
903 switch(pEntry->nWID)
905 case WID_IDX_CONTENT_SECTION:
906 case WID_IDX_HEADER_SECTION :
907 if(WID_IDX_CONTENT_SECTION == pEntry->nWID)
909 const uno::Reference <text::XTextSection> xContentSect =
910 SwXTextSection::CreateXTextSection( pSectionFormat );
911 aRet <<= xContentSect;
913 else if (pSectionFormat)
915 SwSections aSectArr;
916 pSectionFormat->GetChildSections(aSectArr,
917 SectionSort::Not, false);
918 for(SwSection* pSect : aSectArr)
920 if(pSect->GetType() == SectionType::ToxHeader)
922 const uno::Reference <text::XTextSection> xHeader =
923 SwXTextSection::CreateXTextSection(
924 pSect->GetFormat() );
925 aRet <<= xHeader;
926 break;
930 break;
931 case WID_IDX_TITLE :
933 aRet <<= pTOXBase->GetTitle();
934 break;
936 case WID_IDX_NAME:
937 aRet <<= pTOXBase->GetTOXName();
938 break;
939 case WID_USER_IDX_NAME:
941 OUString sTmp((!m_pImpl->m_bIsDescriptor)
942 ? pTOXBase->GetTOXType()->GetTypeName()
943 : m_pImpl->m_oProps->GetTypeName());
944 //I18N
945 lcl_ConvertTOUNameToProgrammaticName(sTmp);
946 aRet <<= sTmp;
948 break;
949 case WID_IDX_LOCALE:
950 aRet <<= LanguageTag(pTOXBase->GetLanguage()).getLocale();
951 break;
952 case WID_IDX_SORT_ALGORITHM:
953 aRet <<= pTOXBase->GetSortAlgorithm();
954 break;
955 case WID_LEVEL :
956 aRet <<= static_cast<sal_Int16>(pTOXBase->GetLevel());
957 break;
958 case WID_TOC_BOOKMARK :
959 aRet <<= pTOXBase->GetBookmarkName();
960 break;
961 case WID_CREATE_FROM_MARKS:
962 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Mark);
963 break;
964 case WID_CREATE_FROM_OUTLINE:
965 lcl_BitMaskToAny(aRet, nCreate,
966 SwTOXElement::OutlineLevel);
967 break;
968 case WID_CREATE_FROM_CHAPTER:
970 const bool bRet = pTOXBase->IsFromChapter();
971 aRet <<= bRet;
973 break;
974 case WID_CREATE_FROM_LABELS:
976 const bool bRet = ! pTOXBase->IsFromObjectNames();
977 aRet <<= bRet;
979 break;
980 case WID_PROTECTED:
982 const bool bRet = pTOXBase->IsProtected();
983 aRet <<= bRet;
985 break;
986 case WID_USE_ALPHABETICAL_SEPARATORS:
987 lcl_BitMaskToAny(aRet, nTOIOptions,
988 SwTOIOptions::AlphaDelimiter);
989 break;
990 case WID_USE_KEY_AS_ENTRY:
991 lcl_BitMaskToAny(aRet, nTOIOptions,
992 SwTOIOptions::KeyAsEntry);
993 break;
994 case WID_USE_COMBINED_ENTRIES:
995 lcl_BitMaskToAny(aRet, nTOIOptions,
996 SwTOIOptions::SameEntry);
997 break;
998 case WID_IS_CASE_SENSITIVE:
999 lcl_BitMaskToAny(aRet, nTOIOptions,
1000 SwTOIOptions::CaseSensitive);
1001 break;
1002 case WID_USE_P_P:
1003 lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::FF);
1004 break;
1005 case WID_USE_DASH:
1006 lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::Dash);
1007 break;
1008 case WID_USE_UPPER_CASE:
1009 lcl_BitMaskToAny(aRet, nTOIOptions,
1010 SwTOIOptions::InitialCaps);
1011 break;
1012 case WID_IS_COMMA_SEPARATED:
1014 const bool bRet = rForm.IsCommaSeparated();
1015 aRet <<= bRet;
1017 break;
1018 case WID_LABEL_CATEGORY:
1020 // convert internal UI name to
1021 // file-format/API/external programmatic english name
1022 // before usage
1023 aRet <<= SwStyleNameMapper::GetSpecialExtraProgName(
1024 pTOXBase->GetSequenceName() );
1026 break;
1027 case WID_LABEL_DISPLAY_TYPE:
1029 sal_Int16 nSet = text::ReferenceFieldPart::TEXT;
1030 switch (pTOXBase->GetCaptionDisplay())
1032 case CAPTION_COMPLETE:
1033 nSet = text::ReferenceFieldPart::TEXT;
1034 break;
1035 case CAPTION_NUMBER:
1036 nSet = text::ReferenceFieldPart::CATEGORY_AND_NUMBER;
1037 break;
1038 case CAPTION_TEXT:
1039 nSet = text::ReferenceFieldPart::ONLY_CAPTION;
1040 break;
1042 aRet <<= nSet;
1044 break;
1045 case WID_USE_LEVEL_FROM_SOURCE:
1047 const bool bRet = pTOXBase->IsLevelFromChapter();
1048 aRet <<= bRet;
1050 break;
1051 case WID_LEVEL_FORMAT:
1053 uno::Reference< container::XIndexReplace > xTokenAccess(
1054 m_pImpl->m_wTokenAccess);
1055 if (!xTokenAccess.is())
1057 xTokenAccess = new TokenAccess_Impl(*this);
1058 m_pImpl->m_wTokenAccess = xTokenAccess;
1060 aRet <<= xTokenAccess;
1062 break;
1063 case WID_LEVEL_PARAGRAPH_STYLES:
1065 uno::Reference< container::XIndexReplace > xStyleAccess(
1066 m_pImpl->m_wStyleAccess);
1067 if (!xStyleAccess.is())
1069 xStyleAccess = new StyleAccess_Impl(*this);
1070 m_pImpl->m_wStyleAccess = xStyleAccess;
1072 aRet <<= xStyleAccess;
1074 break;
1075 case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
1077 OUString aString;
1078 SwStyleNameMapper::FillProgName(
1079 pTOXBase->GetMainEntryCharStyle(),
1080 aString,
1081 SwGetPoolIdFromName::ChrFmt);
1082 aRet <<= aString;
1084 break;
1085 case WID_CREATE_FROM_TABLES:
1086 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Table);
1087 break;
1088 case WID_CREATE_FROM_TEXT_FRAMES:
1089 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Frame);
1090 break;
1091 case WID_CREATE_FROM_GRAPHIC_OBJECTS:
1092 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Graphic);
1093 break;
1094 case WID_CREATE_FROM_EMBEDDED_OBJECTS:
1095 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Ole);
1096 break;
1097 case WID_CREATE_FROM_STAR_MATH:
1098 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Math);
1099 break;
1100 case WID_CREATE_FROM_STAR_CHART:
1101 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Chart);
1102 break;
1103 case WID_CREATE_FROM_STAR_CALC:
1104 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Calc);
1105 break;
1106 case WID_CREATE_FROM_STAR_DRAW:
1107 lcl_BitMaskToAny(aRet, nOLEOptions,
1108 SwTOOElements::DrawImpress);
1109 break;
1110 case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
1111 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Other);
1112 break;
1113 case WID_CREATE_FROM_PARAGRAPH_STYLES:
1114 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Template);
1115 break;
1116 case WID_CREATE_FROM_PARAGRAPH_STYLE:
1118 if (nCreate & SwTOXElement::Template)
1119 { // there is only one style, at top level
1120 OUString const& rStyle(pTOXBase->GetStyleNames(0));
1121 if (!rStyle.isEmpty())
1123 assert(rStyle.indexOf(TOX_STYLE_DELIMITER) == -1);
1124 OUString ret;
1125 SwStyleNameMapper::FillProgName(rStyle, ret,
1126 SwGetPoolIdFromName::TxtColl);
1127 aRet <<= ret;
1131 break;
1133 case WID_PARA_HEAD:
1135 //Header is at position 0
1136 OUString aString;
1137 SwStyleNameMapper::FillProgName(rForm.GetTemplate( 0 ), aString,
1138 SwGetPoolIdFromName::TxtColl );
1139 aRet <<= aString;
1141 break;
1142 case WID_PARA_SEP:
1144 OUString aString;
1145 SwStyleNameMapper::FillProgName(
1146 rForm.GetTemplate( 1 ),
1147 aString,
1148 SwGetPoolIdFromName::TxtColl);
1149 aRet <<= aString;
1151 break;
1152 case WID_PARA_LEV1:
1153 case WID_PARA_LEV2:
1154 case WID_PARA_LEV3:
1155 case WID_PARA_LEV4:
1156 case WID_PARA_LEV5:
1157 case WID_PARA_LEV6:
1158 case WID_PARA_LEV7:
1159 case WID_PARA_LEV8:
1160 case WID_PARA_LEV9:
1161 case WID_PARA_LEV10:
1163 // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
1164 const sal_uInt16 nLPos = pTOXBase->GetType() == TOX_INDEX ? 2 : 1;
1165 OUString aString;
1166 SwStyleNameMapper::FillProgName(
1167 rForm.GetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1),
1168 aString,
1169 SwGetPoolIdFromName::TxtColl);
1170 aRet <<= aString;
1172 break;
1173 case WID_IS_RELATIVE_TABSTOPS:
1175 const bool bRet = rForm.IsRelTabPos();
1176 aRet <<= bRet;
1178 break;
1179 case WID_INDEX_MARKS:
1181 SwTOXMarks aMarks;
1182 const SwTOXType* pType = pTOXBase->GetTOXType();
1183 pType->CollectTextMarks(aMarks);
1184 uno::Sequence< uno::Reference<text::XDocumentIndexMark> > aXMarks(aMarks.size());
1185 uno::Reference<text::XDocumentIndexMark>* pxMarks = aXMarks.getArray();
1186 for(size_t i = 0; i < aMarks.size(); ++i)
1188 SwTOXMark* pMark = aMarks[i];
1189 pxMarks[i] = SwXDocumentIndexMark::CreateXDocumentIndexMark(
1190 *m_pImpl->m_pDoc, pMark);
1192 aRet <<= aXMarks;
1194 break;
1195 default:
1196 //this is for items only
1197 if(WID_PRIMARY_KEY > pEntry->nWID)
1199 const SwAttrSet& rSet =
1200 SwDoc::GetTOXBaseAttrSet(*pTOXBase);
1201 aRet = m_pImpl->m_rPropSet.getPropertyValue(
1202 rPropertyName, rSet);
1206 return aRet;
1209 void SAL_CALL
1210 SwXDocumentIndex::addPropertyChangeListener(
1211 const OUString& /*rPropertyName*/,
1212 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1214 OSL_FAIL("SwXDocumentIndex::addPropertyChangeListener(): not implemented");
1217 void SAL_CALL
1218 SwXDocumentIndex::removePropertyChangeListener(
1219 const OUString& /*rPropertyName*/,
1220 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1222 OSL_FAIL("SwXDocumentIndex::removePropertyChangeListener(): not implemented");
1225 void SAL_CALL
1226 SwXDocumentIndex::addVetoableChangeListener(
1227 const OUString& /*rPropertyName*/,
1228 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1230 OSL_FAIL("SwXDocumentIndex::addVetoableChangeListener(): not implemented");
1233 void SAL_CALL
1234 SwXDocumentIndex::removeVetoableChangeListener(
1235 const OUString& /*rPropertyName*/,
1236 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1238 OSL_FAIL("SwXDocumentIndex::removeVetoableChangeListener(): not implemented");
1241 static void lcl_CalcLayout(SwDoc *pDoc)
1243 SwViewShell *pViewShell = nullptr;
1244 SwEditShell* pEditShell = nullptr;
1245 if( pDoc )
1247 pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
1248 pEditShell = pDoc->GetEditShell();
1251 if (pEditShell)
1253 pEditShell->CalcLayout();
1255 else if (pViewShell)
1257 pViewShell->CalcLayout();
1261 // XRefreshable
1262 void SAL_CALL SwXDocumentIndex::refresh()
1265 SolarMutexGuard g;
1267 SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1268 SwTOXBaseSection *const pTOXBase = pFormat ?
1269 static_cast<SwTOXBaseSection*>(pFormat->GetSection()) : nullptr;
1270 if (!pTOXBase)
1272 throw uno::RuntimeException(
1273 "SwXDocumentIndex::refresh: must be in attached state",
1274 static_cast< ::cppu::OWeakObject*>(this));
1276 pTOXBase->Update(nullptr, m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
1278 // the insertion of TOC will affect the document layout
1279 lcl_CalcLayout(m_pImpl->m_pDoc);
1281 // page numbers
1282 pTOXBase->UpdatePageNum();
1285 std::unique_lock g(m_pImpl->m_Mutex);
1286 if (m_pImpl->m_RefreshListeners.getLength(g))
1288 lang::EventObject const event(static_cast< ::cppu::OWeakObject*>(this));
1289 m_pImpl->m_RefreshListeners.notifyEach(g, & util::XRefreshListener::refreshed, event);
1293 void SAL_CALL SwXDocumentIndex::addRefreshListener(
1294 const uno::Reference<util::XRefreshListener>& xListener)
1296 // no need to lock here as m_pImpl is const and container threadsafe
1297 std::unique_lock g(m_pImpl->m_Mutex);
1298 m_pImpl->m_RefreshListeners.addInterface(g, xListener);
1301 void SAL_CALL SwXDocumentIndex::removeRefreshListener(
1302 const uno::Reference<util::XRefreshListener>& xListener)
1304 // no need to lock here as m_pImpl is const and container threadsafe
1305 std::unique_lock g(m_pImpl->m_Mutex);
1306 m_pImpl->m_RefreshListeners.removeInterface(g, xListener);
1309 void SAL_CALL
1310 SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange)
1312 SolarMutexGuard aGuard;
1314 if (!m_pImpl->m_bIsDescriptor)
1316 throw uno::RuntimeException();
1318 SwXTextRange *const pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
1319 OTextCursorHelper *const pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
1321 SwDoc *const pDoc =
1322 pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
1323 if (!pDoc)
1325 throw lang::IllegalArgumentException();
1328 SwUnoInternalPaM aPam(*pDoc);
1329 // this now needs to return TRUE
1330 ::sw::XTextRangeToSwPaM(aPam, xTextRange);
1332 const SwTOXBase* pOld = SwDoc::GetCurTOX( *aPam.Start() );
1333 if (pOld)
1335 throw lang::IllegalArgumentException();
1338 UnoActionContext aAction(pDoc);
1340 SwTOXBase & rTOXBase = m_pImpl->m_oProps->GetTOXBase();
1341 SwTOXType const*const pTOXType = rTOXBase.GetTOXType();
1342 if ((TOX_USER == pTOXType->GetType()) &&
1343 m_pImpl->m_oProps->GetTypeName() != pTOXType->GetTypeName())
1345 lcl_ReAssignTOXType(*pDoc, rTOXBase, m_pImpl->m_oProps->GetTypeName());
1347 //TODO: apply Section attributes (columns and background)
1348 SwTOXBaseSection *const pTOX =
1349 pDoc->InsertTableOf( aPam, rTOXBase, nullptr, false,
1350 m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
1352 pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_oProps->GetTOXBase().GetTOXName());
1354 // update page numbers
1355 m_pImpl->SetSectionFormat(*pTOX->GetFormat());
1356 pTOX->GetFormat()->SetXObject(static_cast< ::cppu::OWeakObject*>(this));
1357 pTOX->UpdatePageNum();
1359 m_pImpl->m_oProps.reset();
1360 m_pImpl->m_pDoc = pDoc;
1361 m_pImpl->m_bIsDescriptor = false;
1364 uno::Reference< text::XTextRange > SAL_CALL
1365 SwXDocumentIndex::getAnchor()
1367 SolarMutexGuard aGuard;
1369 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1370 if (!pSectionFormat)
1372 throw uno::RuntimeException();
1375 rtl::Reference<SwXTextRange> xRet;
1376 SwNodeIndex const*const pIdx( pSectionFormat->GetContent().GetContentIdx() );
1377 if (pIdx && pIdx->GetNode().GetNodes().IsDocNodes())
1379 SwPaM aPaM(*pIdx);
1380 aPaM.Move( fnMoveForward, GoInContent );
1381 aPaM.SetMark();
1382 aPaM.GetPoint()->Assign( *pIdx->GetNode().EndOfSectionNode() );
1383 aPaM.Move( fnMoveBackward, GoInContent );
1384 xRet = SwXTextRange::CreateXTextRange(*pSectionFormat->GetDoc(),
1385 *aPaM.GetMark(), aPaM.GetPoint());
1387 return xRet;
1390 void SAL_CALL SwXDocumentIndex::dispose()
1392 SolarMutexGuard aGuard;
1394 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1395 if (pSectionFormat)
1397 pSectionFormat->GetDoc()->DeleteTOX(
1398 *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()),
1399 true);
1403 void SAL_CALL
1404 SwXDocumentIndex::addEventListener(
1405 const uno::Reference< lang::XEventListener > & xListener)
1407 // no need to lock here as m_pImpl is const and container threadsafe
1408 std::unique_lock g(m_pImpl->m_Mutex);
1409 m_pImpl->m_EventListeners.addInterface(g, xListener);
1412 void SAL_CALL
1413 SwXDocumentIndex::removeEventListener(
1414 const uno::Reference< lang::XEventListener > & xListener)
1416 // no need to lock here as m_pImpl is const and container threadsafe
1417 std::unique_lock g(m_pImpl->m_Mutex);
1418 m_pImpl->m_EventListeners.removeInterface(g, xListener);
1421 OUString SAL_CALL SwXDocumentIndex::getName()
1423 SolarMutexGuard g;
1425 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1426 if (m_pImpl->m_bIsDescriptor)
1428 return m_pImpl->m_oProps->GetTOXBase().GetTOXName();
1431 if(!pSectionFormat)
1433 throw uno::RuntimeException();
1436 return pSectionFormat->GetSection()->GetSectionName();
1439 void SAL_CALL
1440 SwXDocumentIndex::setName(const OUString& rName)
1442 SolarMutexGuard g;
1444 if (rName.isEmpty())
1446 throw uno::RuntimeException();
1449 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1450 if (m_pImpl->m_bIsDescriptor)
1452 m_pImpl->m_oProps->GetTOXBase().SetTOXName(rName);
1454 else if (pSectionFormat)
1456 const bool bSuccess = pSectionFormat->GetDoc()->SetTOXBaseName(
1457 *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()), rName);
1458 if (!bSuccess)
1460 throw uno::RuntimeException();
1463 else
1465 throw uno::RuntimeException();
1469 // MetadatableMixin
1470 ::sfx2::Metadatable* SwXDocumentIndex::GetCoreObject()
1472 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1473 return pSectionFormat;
1476 uno::Reference<frame::XModel> SwXDocumentIndex::GetModel()
1478 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1479 if (pSectionFormat)
1481 SwDocShell const*const pShell( pSectionFormat->GetDoc()->GetDocShell() );
1482 return pShell ? pShell->GetModel() : nullptr;
1484 return nullptr;
1487 static sal_uInt16
1488 lcl_TypeToPropertyMap_Mark(const TOXTypes eType)
1490 switch (eType)
1492 case TOX_INDEX: return PROPERTY_MAP_INDEX_MARK;
1493 case TOX_CONTENT: return PROPERTY_MAP_CNTIDX_MARK;
1494 case TOX_CITATION : return PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY;
1495 //case TOX_USER:
1496 default:
1497 return PROPERTY_MAP_USER_MARK;
1501 class SwXDocumentIndexMark::Impl final: public SvtListener
1503 private:
1504 SwXDocumentIndexMark & m_rThis;
1505 bool m_bInReplaceMark;
1507 public:
1509 unotools::WeakReference<SwXDocumentIndexMark> m_wThis;
1510 SfxItemPropertySet const& m_rPropSet;
1511 const TOXTypes m_eTOXType;
1512 std::mutex m_Mutex; // just for OInterfaceContainerHelper4
1513 ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners;
1514 bool m_bIsDescriptor;
1515 const SwTOXType* m_pTOXType;
1516 const SwTOXMark* m_pTOXMark;
1517 SwDoc* m_pDoc;
1519 bool m_bMainEntry;
1520 sal_uInt16 m_nLevel;
1521 OUString m_aBookmarkName;
1522 OUString m_sAltText;
1523 OUString m_sPrimaryKey;
1524 OUString m_sSecondaryKey;
1525 OUString m_sTextReading;
1526 OUString m_sPrimaryKeyReading;
1527 OUString m_sSecondaryKeyReading;
1528 OUString m_sUserIndexName;
1530 Impl(SwXDocumentIndexMark& rThis,
1531 SwDoc* const pDoc,
1532 const enum TOXTypes eType,
1533 const SwTOXType* pType,
1534 SwTOXMark const* pMark)
1535 : m_rThis(rThis)
1536 , m_bInReplaceMark(false)
1537 , m_rPropSet(
1538 *aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Mark(eType)))
1539 , m_eTOXType(eType)
1540 , m_bIsDescriptor(nullptr == pMark)
1541 , m_pTOXType(pType)
1542 , m_pTOXMark(pMark)
1543 , m_pDoc(pDoc)
1544 , m_bMainEntry(false)
1545 , m_nLevel(0)
1547 auto pMarkNonConst = const_cast<SwTOXMark*>(m_pTOXMark);
1548 auto pTypeNonConst = const_cast<SwTOXType*>(m_pTOXType);
1550 if(pMarkNonConst)
1551 StartListening(pMarkNonConst->GetNotifier());
1552 if(pTypeNonConst)
1553 StartListening(pTypeNonConst->GetNotifier());
1556 SwTOXType* GetTOXType() const {
1557 return const_cast<SwTOXType*>(m_pTOXType);
1560 void DeleteTOXMark()
1562 m_pDoc->DeleteTOXMark(m_pTOXMark);
1563 Invalidate();
1566 void InsertTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
1567 SwXTextCursor const*const pTextCursor);
1569 void ReplaceTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam)
1571 m_bInReplaceMark = true;
1572 DeleteTOXMark();
1573 m_bInReplaceMark = false;
1574 try {
1575 InsertTOXMark(rTOXType, rMark, rPam, nullptr);
1576 } catch (...) {
1577 OSL_FAIL("ReplaceTOXMark() failed!");
1578 lang::EventObject const ev(
1579 static_cast< ::cppu::OWeakObject&>(m_rThis));
1580 std::unique_lock aGuard(m_Mutex);
1581 m_EventListeners.disposeAndClear(aGuard, ev);
1582 throw;
1586 void Invalidate();
1587 virtual void Notify(const SfxHint&) override;
1590 void SwXDocumentIndexMark::Impl::Invalidate()
1592 if (!m_bInReplaceMark) // #i109983# only dispose on delete, not on replace!
1594 rtl::Reference<SwXDocumentIndexMark> const xThis(m_wThis);
1595 // fdo#72695: if UNO object is already dead, don't revive it with event
1596 if (xThis.is())
1598 lang::EventObject const ev(static_cast<cppu::OWeakObject*>(xThis.get()));
1599 std::unique_lock aGuard(m_Mutex);
1600 m_EventListeners.disposeAndClear(aGuard, ev);
1603 EndListeningAll();
1604 m_pDoc = nullptr;
1605 m_pTOXMark = nullptr;
1606 m_pTOXType = nullptr;
1609 void SwXDocumentIndexMark::Impl::Notify(const SfxHint& rHint)
1611 if(auto pModifyChangedHint = dynamic_cast<const sw::ModifyChangedHint*>(&rHint))
1613 if(auto pNewType = dynamic_cast<const SwTOXType*>(pModifyChangedHint->m_pNew))
1614 m_pTOXType = pNewType;
1616 else
1617 Invalidate();
1621 SwXDocumentIndexMark::SwXDocumentIndexMark(const TOXTypes eToxType)
1622 : m_pImpl( new SwXDocumentIndexMark::Impl(*this, nullptr, eToxType, nullptr, nullptr) )
1626 SwXDocumentIndexMark::SwXDocumentIndexMark(SwDoc & rDoc,
1627 const SwTOXType & rType, const SwTOXMark & rMark)
1628 : m_pImpl( new SwXDocumentIndexMark::Impl(*this, &rDoc, rType.GetType(),
1629 &rType, &rMark) )
1633 SwXDocumentIndexMark::~SwXDocumentIndexMark()
1637 rtl::Reference<SwXDocumentIndexMark>
1638 SwXDocumentIndexMark::CreateXDocumentIndexMark(
1639 SwDoc & rDoc, SwTOXMark *const pMark, TOXTypes const eType)
1641 // re-use existing SwXDocumentIndexMark
1642 // NB: xmloff depends on this caching to generate ID from the address!
1643 // #i105557#: do not iterate over the registered clients: race condition
1644 rtl::Reference<SwXDocumentIndexMark> xTOXMark;
1645 if (pMark)
1647 xTOXMark = pMark->GetXTOXMark();
1649 if (!xTOXMark.is())
1651 xTOXMark = pMark
1652 ? new SwXDocumentIndexMark(rDoc,
1653 *const_cast<SwTOXType*>(pMark->GetTOXType()), *pMark)
1654 : new SwXDocumentIndexMark(eType);
1655 if (pMark)
1657 pMark->SetXTOXMark(xTOXMark);
1659 // need a permanent Reference to initialize m_wThis
1660 xTOXMark->m_pImpl->m_wThis = xTOXMark.get();
1662 return xTOXMark;
1665 namespace
1669 OUString SAL_CALL
1670 SwXDocumentIndexMark::getImplementationName()
1672 return "SwXDocumentIndexMark";
1675 sal_Bool SAL_CALL SwXDocumentIndexMark::supportsService(const OUString& rServiceName)
1677 return cppu::supportsService(this, rServiceName);
1680 uno::Sequence< OUString > SAL_CALL
1681 SwXDocumentIndexMark::getSupportedServiceNames()
1683 SolarMutexGuard g;
1685 const sal_Int32 nCnt = (m_pImpl->m_eTOXType == TOX_INDEX) ? 4 : 3;
1686 uno::Sequence< OUString > aRet(nCnt);
1687 OUString* pArray = aRet.getArray();
1688 pArray[0] = "com.sun.star.text.BaseIndexMark";
1689 pArray[1] = "com.sun.star.text.TextContent";
1690 switch (m_pImpl->m_eTOXType)
1692 case TOX_USER:
1693 pArray[2] = "com.sun.star.text.UserIndexMark";
1694 break;
1695 case TOX_CONTENT:
1696 pArray[2] = "com.sun.star.text.ContentIndexMark";
1697 break;
1698 case TOX_INDEX:
1699 pArray[2] = "com.sun.star.text.DocumentIndexMark";
1700 pArray[3] = "com.sun.star.text.DocumentIndexMarkAsian";
1701 break;
1703 default:
1706 return aRet;
1709 OUString SAL_CALL
1710 SwXDocumentIndexMark::getMarkEntry()
1712 SolarMutexGuard aGuard;
1714 SwTOXType *const pType = m_pImpl->GetTOXType();
1715 if (pType && m_pImpl->m_pTOXMark)
1717 return m_pImpl->m_pTOXMark->GetAlternativeText();
1720 if (!m_pImpl->m_bIsDescriptor)
1722 throw uno::RuntimeException();
1725 return m_pImpl->m_sAltText;
1728 void SAL_CALL
1729 SwXDocumentIndexMark::setMarkEntry(const OUString& rIndexEntry)
1731 SolarMutexGuard aGuard;
1733 SwTOXType *const pType = m_pImpl->GetTOXType();
1734 if (pType && m_pImpl->m_pTOXMark)
1736 SwTOXMark aMark(*m_pImpl->m_pTOXMark);
1737 aMark.SetAlternativeText(rIndexEntry);
1738 SwTextTOXMark const*const pTextMark =
1739 m_pImpl->m_pTOXMark->GetTextTOXMark();
1740 SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
1741 aPam.SetMark();
1742 if(pTextMark->End())
1744 aPam.GetPoint()->SetContent( *pTextMark->End() );
1746 else
1747 aPam.GetPoint()->AdjustContent(1);
1749 m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
1751 else if (m_pImpl->m_bIsDescriptor)
1753 m_pImpl->m_sAltText = rIndexEntry;
1755 else
1757 throw uno::RuntimeException();
1761 void SAL_CALL
1762 SwXDocumentIndexMark::attach(
1763 const uno::Reference< text::XTextRange > & xTextRange)
1765 SolarMutexGuard aGuard;
1767 if (!m_pImpl->m_bIsDescriptor)
1769 throw uno::RuntimeException();
1772 SwXTextRange *const pRange =
1773 dynamic_cast<SwXTextRange*>(xTextRange.get());
1774 OTextCursorHelper *const pCursor =
1775 dynamic_cast<OTextCursorHelper*>(xTextRange.get());
1776 SwDoc *const pDoc =
1777 pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
1778 if (!pDoc)
1780 throw lang::IllegalArgumentException();
1783 const SwTOXType* pTOXType = nullptr;
1784 switch (m_pImpl->m_eTOXType)
1786 case TOX_INDEX:
1787 case TOX_CONTENT:
1788 case TOX_CITATION:
1789 pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
1790 break;
1791 case TOX_USER:
1793 if (m_pImpl->m_sUserIndexName.isEmpty())
1795 pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
1797 else
1799 const sal_uInt16 nCount =
1800 pDoc->GetTOXTypeCount(m_pImpl->m_eTOXType);
1801 for (sal_uInt16 i = 0; i < nCount; i++)
1803 SwTOXType const*const pTemp =
1804 pDoc->GetTOXType( m_pImpl->m_eTOXType, i );
1805 if (m_pImpl->m_sUserIndexName == pTemp->GetTypeName())
1807 pTOXType = pTemp;
1808 break;
1811 if (!pTOXType)
1813 SwTOXType aUserType(*pDoc, TOX_USER, m_pImpl->m_sUserIndexName);
1814 pTOXType = pDoc->InsertTOXType(aUserType);
1818 break;
1820 default:
1821 break;
1823 if (!pTOXType)
1825 throw lang::IllegalArgumentException();
1828 SwUnoInternalPaM aPam(*pDoc);
1829 // this now needs to return TRUE
1830 ::sw::XTextRangeToSwPaM(aPam, xTextRange);
1831 SwTOXMark aMark (pTOXType);
1832 if (!m_pImpl->m_sAltText.isEmpty())
1834 aMark.SetAlternativeText(m_pImpl->m_sAltText);
1836 switch (m_pImpl->m_eTOXType)
1838 case TOX_INDEX:
1839 if (!m_pImpl->m_sPrimaryKey.isEmpty())
1841 aMark.SetPrimaryKey(m_pImpl->m_sPrimaryKey);
1843 if (!m_pImpl->m_sSecondaryKey.isEmpty())
1845 aMark.SetSecondaryKey(m_pImpl->m_sSecondaryKey);
1847 if (!m_pImpl->m_sTextReading.isEmpty())
1849 aMark.SetTextReading(m_pImpl->m_sTextReading);
1851 if (!m_pImpl->m_sPrimaryKeyReading.isEmpty())
1853 aMark.SetPrimaryKeyReading(m_pImpl->m_sPrimaryKeyReading);
1855 if (!m_pImpl->m_sSecondaryKeyReading.isEmpty())
1857 aMark.SetSecondaryKeyReading(m_pImpl->m_sSecondaryKeyReading);
1859 aMark.SetMainEntry(m_pImpl->m_bMainEntry);
1860 break;
1861 case TOX_CITATION:
1862 aMark.SetMainEntry(m_pImpl->m_bMainEntry);
1863 break;
1864 case TOX_USER:
1865 case TOX_CONTENT:
1866 if (USHRT_MAX != m_pImpl->m_nLevel)
1868 aMark.SetLevel(m_pImpl->m_nLevel+1);
1870 break;
1872 default:
1873 break;
1876 m_pImpl->InsertTOXMark(*const_cast<SwTOXType *>(pTOXType), aMark, aPam,
1877 dynamic_cast<SwXTextCursor const*>(pCursor));
1879 m_pImpl->m_bIsDescriptor = false;
1882 namespace {
1884 template<typename T> struct NotContainedIn
1886 std::vector<T> const& m_rVector;
1887 explicit NotContainedIn(std::vector<T> const& rVector)
1888 : m_rVector(rVector) { }
1889 bool operator() (T const& rT) {
1890 return std::find(m_rVector.begin(), m_rVector.end(), rT)
1891 == m_rVector.end();
1897 void SwXDocumentIndexMark::Impl::InsertTOXMark(
1898 const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
1899 SwXTextCursor const*const pTextCursor)
1901 SwDoc& rDoc(rPam.GetDoc());
1902 UnoActionContext aAction(&rDoc);
1903 bool bMark = *rPam.GetPoint() != *rPam.GetMark();
1904 // n.b.: toxmarks must have either alternative text or an extent
1905 if (bMark && !rMark.GetAlternativeText().isEmpty())
1907 rPam.Normalize();
1908 rPam.DeleteMark();
1909 bMark = false;
1911 // Marks without alternative text and without selected text cannot be inserted,
1912 // thus use a space - is this really the ideal solution?
1913 if (!bMark && rMark.GetAlternativeText().isEmpty())
1915 rMark.SetAlternativeText( " " );
1918 const bool bForceExpandHints( !bMark && pTextCursor && pTextCursor->IsAtEndOfMeta() );
1919 const SetAttrMode nInsertFlags = bForceExpandHints
1920 ? ( SetAttrMode::FORCEHINTEXPAND
1921 | SetAttrMode::DONTEXPAND)
1922 : SetAttrMode::DONTEXPAND;
1924 // rMark gets copied into the document pool;
1925 // pNewTextAttr comes back with the real format
1926 SwTextAttr *pNewTextAttr = nullptr;
1927 rDoc.getIDocumentContentOperations().InsertPoolItem(rPam, rMark, nInsertFlags,
1928 /*pLayout*/nullptr, &pNewTextAttr);
1929 if (bMark && *rPam.GetPoint() > *rPam.GetMark())
1931 rPam.Exchange();
1934 if (!pNewTextAttr)
1936 throw uno::RuntimeException(
1937 "SwXDocumentIndexMark::InsertTOXMark(): cannot insert attribute",
1938 nullptr);
1941 m_pDoc = &rDoc;
1942 m_pTOXMark = &pNewTextAttr->GetTOXMark();
1943 m_pTOXType = &rTOXType;
1944 EndListeningAll();
1945 StartListening(const_cast<SwTOXMark*>(m_pTOXMark)->GetNotifier());
1946 StartListening(const_cast<SwTOXType*>(m_pTOXType)->GetNotifier());
1949 uno::Reference< text::XTextRange > SAL_CALL
1950 SwXDocumentIndexMark::getAnchor()
1952 SolarMutexGuard aGuard;
1954 SwTOXType *const pType = m_pImpl->GetTOXType();
1955 if (!pType || !m_pImpl->m_pTOXMark)
1957 throw uno::RuntimeException();
1959 if (!m_pImpl->m_pTOXMark->GetTextTOXMark())
1961 throw uno::RuntimeException();
1963 const SwTextTOXMark* pTextMark = m_pImpl->m_pTOXMark->GetTextTOXMark();
1964 SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
1965 aPam.SetMark();
1966 if(pTextMark->End())
1968 aPam.GetPoint()->SetContent( *pTextMark->End() );
1970 else
1972 aPam.GetPoint()->AdjustContent(1);
1974 const uno::Reference< frame::XModel > xModel =
1975 m_pImpl->m_pDoc->GetDocShell()->GetBaseModel();
1976 const uno::Reference< text::XTextDocument > xTDoc(xModel, uno::UNO_QUERY);
1977 const uno::Reference< text::XTextRange > xRet =
1978 new SwXTextRange(aPam, xTDoc->getText());
1980 return xRet;
1983 void SAL_CALL
1984 SwXDocumentIndexMark::dispose()
1986 SolarMutexGuard aGuard;
1988 SwTOXType *const pType = m_pImpl->GetTOXType();
1989 if (pType && m_pImpl->m_pTOXMark)
1991 m_pImpl->DeleteTOXMark(); // call Invalidate() via modify!
1995 void SAL_CALL
1996 SwXDocumentIndexMark::addEventListener(
1997 const uno::Reference< lang::XEventListener > & xListener)
1999 // no need to lock here as m_pImpl is const and container threadsafe
2000 std::unique_lock aGuard(m_pImpl->m_Mutex);
2001 m_pImpl->m_EventListeners.addInterface(aGuard, xListener);
2004 void SAL_CALL
2005 SwXDocumentIndexMark::removeEventListener(
2006 const uno::Reference< lang::XEventListener > & xListener)
2008 // no need to lock here as m_pImpl is const and container threadsafe
2009 std::unique_lock aGuard(m_pImpl->m_Mutex);
2010 m_pImpl->m_EventListeners.removeInterface(aGuard, xListener);
2013 uno::Reference< beans::XPropertySetInfo > SAL_CALL
2014 SwXDocumentIndexMark::getPropertySetInfo()
2016 SolarMutexGuard g;
2018 static uno::Reference< beans::XPropertySetInfo > xInfos[3];
2019 int nPos = 0;
2020 switch (m_pImpl->m_eTOXType)
2022 case TOX_INDEX: nPos = 0; break;
2023 case TOX_CONTENT: nPos = 1; break;
2024 case TOX_USER: nPos = 2; break;
2025 default:
2028 if(!xInfos[nPos].is())
2030 const uno::Reference< beans::XPropertySetInfo > xInfo =
2031 m_pImpl->m_rPropSet.getPropertySetInfo();
2032 // extend PropertySetInfo!
2033 const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
2034 xInfos[nPos] = new SfxExtItemPropertySetInfo(
2035 aSwMapProvider.GetPropertyMapEntries(
2036 PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
2037 aPropSeq );
2039 return xInfos[nPos];
2042 void SAL_CALL
2043 SwXDocumentIndexMark::setPropertyValue(
2044 const OUString& rPropertyName, const uno::Any& rValue)
2046 SolarMutexGuard aGuard;
2048 SfxItemPropertyMapEntry const*const pEntry =
2049 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
2050 if (!pEntry)
2052 throw beans::UnknownPropertyException(
2053 "Unknown property: " + rPropertyName,
2054 static_cast<cppu::OWeakObject *>(this));
2056 if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
2058 throw beans::PropertyVetoException(
2059 "Property is read-only: " + rPropertyName,
2060 static_cast<cppu::OWeakObject *>(this));
2063 SwTOXType *const pType = m_pImpl->GetTOXType();
2064 if (pType && m_pImpl->m_pTOXMark)
2066 SwTOXMark aMark(*m_pImpl->m_pTOXMark);
2067 switch(pEntry->nWID)
2069 case WID_ALT_TEXT:
2070 aMark.SetAlternativeText(lcl_AnyToType<OUString>(rValue));
2071 break;
2072 case WID_LEVEL:
2073 aMark.SetLevel(std::min( static_cast<sal_Int8>( MAXLEVEL ),
2074 static_cast<sal_Int8>(lcl_AnyToType<sal_Int16>(rValue)+1)));
2075 break;
2076 case WID_TOC_BOOKMARK :
2077 aMark.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
2078 break;
2079 case WID_PRIMARY_KEY :
2080 aMark.SetPrimaryKey(lcl_AnyToType<OUString>(rValue));
2081 break;
2082 case WID_SECONDARY_KEY:
2083 aMark.SetSecondaryKey(lcl_AnyToType<OUString>(rValue));
2084 break;
2085 case WID_MAIN_ENTRY:
2086 aMark.SetMainEntry(lcl_AnyToType<bool>(rValue));
2087 break;
2088 case WID_TEXT_READING:
2089 aMark.SetTextReading(lcl_AnyToType<OUString>(rValue));
2090 break;
2091 case WID_PRIMARY_KEY_READING:
2092 aMark.SetPrimaryKeyReading(lcl_AnyToType<OUString>(rValue));
2093 break;
2094 case WID_SECONDARY_KEY_READING:
2095 aMark.SetSecondaryKeyReading(lcl_AnyToType<OUString>(rValue));
2096 break;
2098 SwTextTOXMark const*const pTextMark =
2099 m_pImpl->m_pTOXMark->GetTextTOXMark();
2100 SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
2101 aPam.SetMark();
2102 if(pTextMark->End())
2104 aPam.GetPoint()->SetContent(*pTextMark->End());
2106 else
2108 aPam.GetPoint()->AdjustContent(1);
2111 m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
2113 else if (m_pImpl->m_bIsDescriptor)
2115 switch(pEntry->nWID)
2117 case WID_ALT_TEXT:
2118 m_pImpl->m_sAltText = lcl_AnyToType<OUString>(rValue);
2119 break;
2120 case WID_LEVEL:
2122 const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
2123 if(nVal < 0 || nVal >= MAXLEVEL)
2125 throw lang::IllegalArgumentException();
2127 m_pImpl->m_nLevel = nVal;
2129 break;
2130 case WID_TOC_BOOKMARK :
2132 m_pImpl->m_aBookmarkName = lcl_AnyToType<OUString>(rValue);
2134 break;
2135 case WID_PRIMARY_KEY:
2136 m_pImpl->m_sPrimaryKey = lcl_AnyToType<OUString>(rValue);
2137 break;
2138 case WID_SECONDARY_KEY:
2139 m_pImpl->m_sSecondaryKey = lcl_AnyToType<OUString>(rValue);
2140 break;
2141 case WID_TEXT_READING:
2142 m_pImpl->m_sTextReading = lcl_AnyToType<OUString>(rValue);
2143 break;
2144 case WID_PRIMARY_KEY_READING:
2145 m_pImpl->m_sPrimaryKeyReading = lcl_AnyToType<OUString>(rValue);
2146 break;
2147 case WID_SECONDARY_KEY_READING:
2148 m_pImpl->m_sSecondaryKeyReading = lcl_AnyToType<OUString>(rValue);
2149 break;
2150 case WID_USER_IDX_NAME:
2152 OUString sTmp(lcl_AnyToType<OUString>(rValue));
2153 lcl_ConvertTOUNameToUserName(sTmp);
2154 m_pImpl->m_sUserIndexName = sTmp;
2156 break;
2157 case WID_MAIN_ENTRY:
2158 m_pImpl->m_bMainEntry = lcl_AnyToType<bool>(rValue);
2159 break;
2160 case PROPERTY_MAP_INDEX_OBJECTS:
2161 // unsupported
2162 break;
2165 else
2167 throw uno::RuntimeException();
2171 uno::Any SAL_CALL
2172 SwXDocumentIndexMark::getPropertyValue(const OUString& rPropertyName)
2174 SolarMutexGuard aGuard;
2176 uno::Any aRet;
2177 SfxItemPropertyMapEntry const*const pEntry =
2178 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
2179 if (!pEntry)
2181 throw beans::UnknownPropertyException(
2182 "Unknown property: " + rPropertyName,
2183 static_cast<cppu::OWeakObject *>(this));
2185 if (::sw::GetDefaultTextContentValue(aRet, rPropertyName, pEntry->nWID))
2187 return aRet;
2190 SwTOXType *const pType = m_pImpl->GetTOXType();
2191 if (pType && m_pImpl->m_pTOXMark)
2193 switch(pEntry->nWID)
2195 case WID_ALT_TEXT:
2196 aRet <<= m_pImpl->m_pTOXMark->GetAlternativeText();
2197 break;
2198 case WID_LEVEL:
2199 aRet <<= static_cast<sal_Int16>(
2200 m_pImpl->m_pTOXMark->GetLevel() - 1);
2201 break;
2202 case WID_TOC_BOOKMARK :
2203 aRet <<= m_pImpl->m_pTOXMark->GetBookmarkName();
2204 break;
2205 case WID_PRIMARY_KEY :
2206 aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKey();
2207 break;
2208 case WID_SECONDARY_KEY:
2209 aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKey();
2210 break;
2211 case WID_TEXT_READING:
2212 aRet <<= m_pImpl->m_pTOXMark->GetTextReading();
2213 break;
2214 case WID_PRIMARY_KEY_READING:
2215 aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKeyReading();
2216 break;
2217 case WID_SECONDARY_KEY_READING:
2218 aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKeyReading();
2219 break;
2220 case WID_USER_IDX_NAME :
2222 OUString sTmp(pType->GetTypeName());
2223 lcl_ConvertTOUNameToProgrammaticName(sTmp);
2224 aRet <<= sTmp;
2226 break;
2227 case WID_MAIN_ENTRY:
2229 const bool bTemp = m_pImpl->m_pTOXMark->IsMainEntry();
2230 aRet <<= bTemp;
2232 break;
2235 else if (m_pImpl->m_bIsDescriptor)
2237 switch(pEntry->nWID)
2239 case WID_ALT_TEXT:
2240 aRet <<= m_pImpl->m_sAltText;
2241 break;
2242 case WID_LEVEL:
2243 aRet <<= static_cast<sal_Int16>(m_pImpl->m_nLevel);
2244 break;
2245 case WID_TOC_BOOKMARK :
2246 aRet <<= m_pImpl->m_aBookmarkName;
2247 break;
2248 case WID_PRIMARY_KEY:
2249 aRet <<= m_pImpl->m_sPrimaryKey;
2250 break;
2251 case WID_SECONDARY_KEY:
2252 aRet <<= m_pImpl->m_sSecondaryKey;
2253 break;
2254 case WID_TEXT_READING:
2255 aRet <<= m_pImpl->m_sTextReading;
2256 break;
2257 case WID_PRIMARY_KEY_READING:
2258 aRet <<= m_pImpl->m_sPrimaryKeyReading;
2259 break;
2260 case WID_SECONDARY_KEY_READING:
2261 aRet <<= m_pImpl->m_sSecondaryKeyReading;
2262 break;
2263 case WID_USER_IDX_NAME :
2264 aRet <<= m_pImpl->m_sUserIndexName;
2265 break;
2266 case WID_MAIN_ENTRY:
2267 aRet <<= m_pImpl->m_bMainEntry;
2268 break;
2271 else
2273 throw uno::RuntimeException();
2275 return aRet;
2278 void SAL_CALL
2279 SwXDocumentIndexMark::addPropertyChangeListener(
2280 const OUString& /*rPropertyName*/,
2281 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
2283 OSL_FAIL("SwXDocumentIndexMark::addPropertyChangeListener(): not implemented");
2286 void SAL_CALL
2287 SwXDocumentIndexMark::removePropertyChangeListener(
2288 const OUString& /*rPropertyName*/,
2289 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
2291 OSL_FAIL("SwXDocumentIndexMark::removePropertyChangeListener(): not implemented");
2294 void SAL_CALL
2295 SwXDocumentIndexMark::addVetoableChangeListener(
2296 const OUString& /*rPropertyName*/,
2297 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
2299 OSL_FAIL("SwXDocumentIndexMark::addVetoableChangeListener(): not implemented");
2302 void SAL_CALL
2303 SwXDocumentIndexMark::removeVetoableChangeListener(
2304 const OUString& /*rPropertyName*/,
2305 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
2307 OSL_FAIL("SwXDocumentIndexMark::removeVetoableChangeListener(): not implemented");
2310 SwXDocumentIndexes::SwXDocumentIndexes(SwDoc *const _pDoc)
2311 : SwUnoCollection(_pDoc)
2315 SwXDocumentIndexes::~SwXDocumentIndexes()
2319 OUString SAL_CALL
2320 SwXDocumentIndexes::getImplementationName()
2322 return "SwXDocumentIndexes";
2325 sal_Bool SAL_CALL SwXDocumentIndexes::supportsService(const OUString& rServiceName)
2327 return cppu::supportsService(this, rServiceName);
2330 uno::Sequence< OUString > SAL_CALL
2331 SwXDocumentIndexes::getSupportedServiceNames()
2333 return { "com.sun.star.text.DocumentIndexes" };
2336 sal_Int32 SAL_CALL
2337 SwXDocumentIndexes::getCount()
2339 SolarMutexGuard aGuard;
2341 if(!IsValid())
2342 throw uno::RuntimeException();
2344 sal_uInt32 nRet = 0;
2345 const SwSectionFormats& rFormats = GetDoc()->GetSections();
2346 for( size_t n = 0; n < rFormats.size(); ++n )
2348 const SwSection* pSect = rFormats[ n ]->GetSection();
2349 if( SectionType::ToxContent == pSect->GetType() &&
2350 pSect->GetFormat()->GetSectionNode() )
2352 ++nRet;
2355 return nRet;
2358 uno::Any SAL_CALL
2359 SwXDocumentIndexes::getByIndex(sal_Int32 nIndex)
2361 SolarMutexGuard aGuard;
2363 if(!IsValid())
2364 throw uno::RuntimeException();
2366 sal_Int32 nIdx = 0;
2368 const SwSectionFormats& rFormats = GetDoc()->GetSections();
2369 for( size_t n = 0; n < rFormats.size(); ++n )
2371 SwSection* pSect = rFormats[ n ]->GetSection();
2372 if( SectionType::ToxContent == pSect->GetType() &&
2373 pSect->GetFormat()->GetSectionNode() &&
2374 nIdx++ == nIndex )
2376 const uno::Reference< text::XDocumentIndex > xTmp =
2377 SwXDocumentIndex::CreateXDocumentIndex(
2378 *GetDoc(), static_cast<SwTOXBaseSection *>(pSect));
2379 uno::Any aRet;
2380 aRet <<= xTmp;
2381 return aRet;
2385 throw lang::IndexOutOfBoundsException();
2388 uno::Any SAL_CALL
2389 SwXDocumentIndexes::getByName(const OUString& rName)
2391 SolarMutexGuard aGuard;
2393 if(!IsValid())
2394 throw uno::RuntimeException();
2396 const SwSectionFormats& rFormats = GetDoc()->GetSections();
2397 for( size_t n = 0; n < rFormats.size(); ++n )
2399 SwSection* pSect = rFormats[ n ]->GetSection();
2400 if( SectionType::ToxContent == pSect->GetType() &&
2401 pSect->GetFormat()->GetSectionNode() &&
2402 (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
2403 == rName))
2405 const uno::Reference< text::XDocumentIndex > xTmp =
2406 SwXDocumentIndex::CreateXDocumentIndex(
2407 *GetDoc(), static_cast<SwTOXBaseSection *>(pSect));
2408 uno::Any aRet;
2409 aRet <<= xTmp;
2410 return aRet;
2413 throw container::NoSuchElementException();
2416 uno::Sequence< OUString > SAL_CALL
2417 SwXDocumentIndexes::getElementNames()
2419 SolarMutexGuard aGuard;
2421 if(!IsValid())
2422 throw uno::RuntimeException();
2424 const SwSectionFormats& rFormats = GetDoc()->GetSections();
2425 sal_Int32 nCount = 0;
2426 for( size_t n = 0; n < rFormats.size(); ++n )
2428 SwSection const*const pSect = rFormats[ n ]->GetSection();
2429 if( SectionType::ToxContent == pSect->GetType() &&
2430 pSect->GetFormat()->GetSectionNode() )
2432 ++nCount;
2436 uno::Sequence< OUString > aRet(nCount);
2437 OUString* pArray = aRet.getArray();
2438 sal_Int32 nCnt = 0;
2439 for( size_t n = 0; n < rFormats.size(); ++n )
2441 SwSection const*const pSect = rFormats[ n ]->GetSection();
2442 if( SectionType::ToxContent == pSect->GetType() &&
2443 pSect->GetFormat()->GetSectionNode())
2445 pArray[nCnt++] = static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName();
2448 return aRet;
2451 sal_Bool SAL_CALL
2452 SwXDocumentIndexes::hasByName(const OUString& rName)
2454 SolarMutexGuard aGuard;
2456 if(!IsValid())
2457 throw uno::RuntimeException();
2459 const SwSectionFormats& rFormats = GetDoc()->GetSections();
2460 for( size_t n = 0; n < rFormats.size(); ++n )
2462 SwSection const*const pSect = rFormats[ n ]->GetSection();
2463 if( SectionType::ToxContent == pSect->GetType() &&
2464 pSect->GetFormat()->GetSectionNode())
2466 if (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
2467 == rName)
2469 return true;
2473 return false;
2476 uno::Type SAL_CALL
2477 SwXDocumentIndexes::getElementType()
2479 return cppu::UnoType<text::XDocumentIndex>::get();
2482 sal_Bool SAL_CALL
2483 SwXDocumentIndexes::hasElements()
2485 return 0 != getCount();
2488 SwXDocumentIndex::StyleAccess_Impl::StyleAccess_Impl(
2489 SwXDocumentIndex& rParentIdx)
2490 : m_xParent(&rParentIdx)
2494 SwXDocumentIndex::StyleAccess_Impl::~StyleAccess_Impl()
2498 OUString SAL_CALL
2499 SwXDocumentIndex::StyleAccess_Impl::getImplementationName()
2501 return "SwXDocumentIndex::StyleAccess_Impl";
2504 sal_Bool SAL_CALL
2505 SwXDocumentIndex::StyleAccess_Impl::supportsService(const OUString& rServiceName)
2507 return cppu::supportsService(this, rServiceName);
2510 uno::Sequence< OUString > SAL_CALL
2511 SwXDocumentIndex::StyleAccess_Impl::getSupportedServiceNames()
2513 return { "com.sun.star.text.DocumentIndexParagraphStyles" };
2516 void SAL_CALL
2517 SwXDocumentIndex::StyleAccess_Impl::replaceByIndex(
2518 sal_Int32 nIndex, const uno::Any& rElement)
2520 SolarMutexGuard aGuard;
2522 if(nIndex < 0 || nIndex >= MAXLEVEL)
2524 throw lang::IndexOutOfBoundsException();
2527 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2529 uno::Sequence<OUString> aSeq;
2530 if(!(rElement >>= aSeq))
2532 throw lang::IllegalArgumentException();
2535 const sal_Int32 nStyles = aSeq.getLength();
2536 const OUString* pStyles = aSeq.getConstArray();
2537 OUStringBuffer sSetStyles;
2538 OUString aString;
2539 for(sal_Int32 i = 0; i < nStyles; i++)
2541 if(i)
2543 sSetStyles.append(TOX_STYLE_DELIMITER);
2545 SwStyleNameMapper::FillUIName(pStyles[i], aString,
2546 SwGetPoolIdFromName::TxtColl);
2547 sSetStyles.append(aString);
2549 rTOXBase.SetStyleNames(sSetStyles.makeStringAndClear(), o3tl::narrowing<sal_uInt16>(nIndex));
2552 sal_Int32 SAL_CALL
2553 SwXDocumentIndex::StyleAccess_Impl::getCount()
2555 return MAXLEVEL;
2558 uno::Any SAL_CALL
2559 SwXDocumentIndex::StyleAccess_Impl::getByIndex(sal_Int32 nIndex)
2561 SolarMutexGuard aGuard;
2563 if(nIndex < 0 || nIndex >= MAXLEVEL)
2565 throw lang::IndexOutOfBoundsException();
2568 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2570 const OUString& rStyles =
2571 rTOXBase.GetStyleNames(o3tl::narrowing<sal_uInt16>(nIndex));
2572 const sal_Int32 nStyles = comphelper::string::getTokenCount(rStyles, TOX_STYLE_DELIMITER);
2573 uno::Sequence<OUString> aStyles(nStyles);
2574 OUString* pStyles = aStyles.getArray();
2575 OUString aString;
2576 sal_Int32 nPos = 0;
2577 for(sal_Int32 i = 0; i < nStyles; ++i)
2579 SwStyleNameMapper::FillProgName(
2580 rStyles.getToken(0, TOX_STYLE_DELIMITER, nPos),
2581 aString,
2582 SwGetPoolIdFromName::TxtColl);
2583 pStyles[i] = aString;
2585 uno::Any aRet(&aStyles, cppu::UnoType<uno::Sequence<OUString>>::get());
2586 return aRet;
2589 uno::Type SAL_CALL
2590 SwXDocumentIndex::StyleAccess_Impl::getElementType()
2592 return cppu::UnoType<uno::Sequence<OUString>>::get();
2595 sal_Bool SAL_CALL
2596 SwXDocumentIndex::StyleAccess_Impl::hasElements()
2598 return true;
2601 SwXDocumentIndex::TokenAccess_Impl::TokenAccess_Impl(
2602 SwXDocumentIndex& rParentIdx)
2603 : m_xParent(&rParentIdx)
2607 SwXDocumentIndex::TokenAccess_Impl::~TokenAccess_Impl()
2611 OUString SAL_CALL
2612 SwXDocumentIndex::TokenAccess_Impl::getImplementationName()
2614 return "SwXDocumentIndex::TokenAccess_Impl";
2617 sal_Bool SAL_CALL SwXDocumentIndex::TokenAccess_Impl::supportsService(
2618 const OUString& rServiceName)
2620 return cppu::supportsService(this, rServiceName);
2623 uno::Sequence< OUString > SAL_CALL
2624 SwXDocumentIndex::TokenAccess_Impl::getSupportedServiceNames()
2626 return { "com.sun.star.text.DocumentIndexLevelFormat" };
2629 namespace {
2631 struct TokenType_ {
2632 const char *pName;
2633 enum FormTokenType eTokenType;
2638 const struct TokenType_ g_TokenTypes[] =
2640 { "TokenEntryNumber", TOKEN_ENTRY_NO },
2641 { "TokenEntryText", TOKEN_ENTRY_TEXT },
2642 { "TokenTabStop", TOKEN_TAB_STOP },
2643 { "TokenText", TOKEN_TEXT },
2644 { "TokenPageNumber", TOKEN_PAGE_NUMS },
2645 { "TokenChapterInfo", TOKEN_CHAPTER_INFO },
2646 { "TokenHyperlinkStart", TOKEN_LINK_START },
2647 { "TokenHyperlinkEnd", TOKEN_LINK_END },
2648 { "TokenBibliographyDataField", TOKEN_AUTHORITY },
2649 { nullptr, static_cast<enum FormTokenType>(0) }
2652 void SAL_CALL
2653 SwXDocumentIndex::TokenAccess_Impl::replaceByIndex(
2654 sal_Int32 nIndex, const uno::Any& rElement)
2656 SolarMutexGuard aGuard;
2658 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2660 if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
2662 throw lang::IndexOutOfBoundsException();
2665 uno::Sequence<beans::PropertyValues> aSeq;
2666 if(!(rElement >>= aSeq))
2668 throw lang::IllegalArgumentException();
2671 OUStringBuffer sPattern;
2672 for(const beans::PropertyValues& rToken : std::as_const(aSeq))
2674 const beans::PropertyValue* pProperties = rToken.getConstArray();
2675 const sal_Int32 nProperties = rToken.getLength();
2676 //create an invalid token
2677 SwFormToken aToken(TOKEN_END);
2678 for(sal_Int32 j = 0; j < nProperties; j++)
2680 if ( pProperties[j].Name == "TokenType" )
2682 const OUString sTokenType =
2683 lcl_AnyToType<OUString>(pProperties[j].Value);
2684 for (TokenType_ const* pTokenType = g_TokenTypes;
2685 pTokenType->pName; ++pTokenType)
2687 if (sTokenType.equalsAscii(pTokenType->pName))
2689 aToken.eTokenType = pTokenType->eTokenType;
2690 break;
2694 else if ( pProperties[j].Name == "CharacterStyleName" )
2696 OUString sCharStyleName;
2697 SwStyleNameMapper::FillUIName(
2698 lcl_AnyToType<OUString>(pProperties[j].Value),
2699 sCharStyleName,
2700 SwGetPoolIdFromName::ChrFmt);
2701 aToken.sCharStyleName = sCharStyleName;
2702 aToken.nPoolId = SwStyleNameMapper::GetPoolIdFromUIName (
2703 sCharStyleName, SwGetPoolIdFromName::ChrFmt );
2705 else if ( pProperties[j].Name == "TabStopRightAligned" )
2707 const bool bRight = lcl_AnyToType<bool>(pProperties[j].Value);
2708 aToken.eTabAlign = bRight ?
2709 SvxTabAdjust::End : SvxTabAdjust::Left;
2711 else if ( pProperties[j].Name == "TabStopPosition" )
2713 sal_Int32 nPosition = 0;
2714 if (!(pProperties[j].Value >>= nPosition))
2716 throw lang::IllegalArgumentException();
2718 nPosition = o3tl::toTwips(nPosition, o3tl::Length::mm100);
2719 if(nPosition < 0)
2721 throw lang::IllegalArgumentException();
2723 aToken.nTabStopPosition = nPosition;
2725 else if ( pProperties[j].Name == "TabStopFillCharacter" )
2727 const OUString sFillChar =
2728 lcl_AnyToType<OUString>(pProperties[j].Value);
2729 if (sFillChar.getLength() > 1)
2731 throw lang::IllegalArgumentException();
2733 aToken.cTabFillChar =
2734 sFillChar.isEmpty() ? ' ' : sFillChar[0];
2736 else if ( pProperties[j].Name == "Text" )
2738 aToken.sText = lcl_AnyToType<OUString>(pProperties[j].Value);
2740 else if ( pProperties[j].Name == "ChapterFormat" )
2742 sal_Int16 nFormat = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
2743 switch(nFormat)
2745 case text::ChapterFormat::NUMBER:
2746 nFormat = CF_NUMBER;
2747 break;
2748 case text::ChapterFormat::NAME:
2749 nFormat = CF_TITLE;
2750 break;
2751 case text::ChapterFormat::NAME_NUMBER:
2752 nFormat = CF_NUM_TITLE;
2753 break;
2754 case text::ChapterFormat::NO_PREFIX_SUFFIX:
2755 nFormat = CF_NUMBER_NOPREPST;
2756 break;
2757 case text::ChapterFormat::DIGIT:
2758 nFormat = CF_NUM_NOPREPST_TITLE;
2759 break;
2760 default:
2761 throw lang::IllegalArgumentException();
2763 aToken.nChapterFormat = nFormat;
2765 // #i53420#
2766 else if ( pProperties[j].Name == "ChapterLevel" )
2768 const sal_Int16 nLevel = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
2769 if( nLevel < 1 || nLevel > MAXLEVEL )
2771 throw lang::IllegalArgumentException();
2773 aToken.nOutlineLevel = nLevel;
2775 else if ( pProperties[j].Name == "BibliographyDataField" )
2777 sal_Int16 nType = 0;
2778 pProperties[j].Value >>= nType;
2779 if(nType < 0 || nType > text::BibliographyDataField::LOCAL_URL)
2781 lang::IllegalArgumentException aExcept;
2782 aExcept.Message = "BibliographyDataField - wrong value";
2783 aExcept.ArgumentPosition = static_cast< sal_Int16 >(j);
2784 throw aExcept;
2786 aToken.nAuthorityField = nType;
2788 // #i21237#
2789 else if ( pProperties[j].Name == "WithTab" )
2791 aToken.bWithTab = lcl_AnyToType<bool>(pProperties[j].Value);
2795 //exception if wrong TokenType
2796 if(TOKEN_END <= aToken.eTokenType )
2798 throw lang::IllegalArgumentException();
2800 // set TokenType from TOKEN_ENTRY_TEXT to TOKEN_ENTRY if it is
2801 // not a content index
2802 if(TOKEN_ENTRY_TEXT == aToken.eTokenType &&
2803 (TOX_CONTENT != rTOXBase.GetType()))
2805 aToken.eTokenType = TOKEN_ENTRY;
2807 // #i53420#
2808 // check for chapter format allowed values if it was TOKEN_ENTRY_NO type
2809 // only allowed value are CF_NUMBER and CF_NUM_NOPREPST_TITLE
2810 // reading from file
2811 if( TOKEN_ENTRY_NO == aToken.eTokenType )
2813 switch(aToken.nChapterFormat)
2815 case CF_NUMBER:
2816 case CF_NUM_NOPREPST_TITLE:
2817 break;
2818 default:
2819 throw lang::IllegalArgumentException();
2823 if (rTOXBase.GetType() == TOX_CONTENT)
2825 if (aToken.eTokenType == TOKEN_LINK_START && aToken.sCharStyleName.isEmpty())
2827 aToken.sCharStyleName = SwResId(STR_POOLCHR_TOXJUMP);
2831 sPattern.append(aToken.GetString());
2833 SwForm aForm(rTOXBase.GetTOXForm());
2834 aForm.SetPattern(o3tl::narrowing<sal_uInt16>(nIndex), sPattern.makeStringAndClear());
2835 rTOXBase.SetTOXForm(aForm);
2838 sal_Int32 SAL_CALL
2839 SwXDocumentIndex::TokenAccess_Impl::getCount()
2841 SolarMutexGuard aGuard;
2843 const sal_Int32 nRet = m_xParent->m_pImpl->GetFormMax();
2844 return nRet;
2847 uno::Any SAL_CALL
2848 SwXDocumentIndex::TokenAccess_Impl::getByIndex(sal_Int32 nIndex)
2850 SolarMutexGuard aGuard;
2852 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2854 if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
2856 throw lang::IndexOutOfBoundsException();
2859 // #i21237#
2860 SwFormTokens aPattern = rTOXBase.GetTOXForm().
2861 GetPattern(o3tl::narrowing<sal_uInt16>(nIndex));
2863 sal_Int32 nTokenCount = 0;
2864 uno::Sequence< beans::PropertyValues > aRetSeq;
2865 OUString aProgCharStyle;
2866 for(const SwFormToken& aToken : aPattern) // #i21237#
2868 nTokenCount++;
2869 aRetSeq.realloc(nTokenCount);
2870 beans::PropertyValues* pTokenProps = aRetSeq.getArray();
2872 uno::Sequence< beans::PropertyValue >& rCurTokenSeq =
2873 pTokenProps[nTokenCount-1];
2874 SwStyleNameMapper::FillProgName(
2875 aToken.sCharStyleName,
2876 aProgCharStyle,
2877 SwGetPoolIdFromName::ChrFmt);
2878 switch(aToken.eTokenType)
2880 case TOKEN_ENTRY_NO:
2882 // #i53420#
2883 // writing to file (from doc to properties)
2884 sal_Int32 nElements = 2;
2885 sal_Int32 nCurrentElement = 0;
2887 // check for default value
2888 if (aToken.nChapterFormat != CF_NUMBER)
2890 nElements++;//we need the element
2892 if( aToken.nOutlineLevel != MAXLEVEL )
2894 nElements++;
2897 rCurTokenSeq.realloc( nElements );
2899 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2901 pArr[nCurrentElement].Name = "TokenType";
2902 pArr[nCurrentElement++].Value <<=
2903 OUString("TokenEntryNumber");
2905 pArr[nCurrentElement].Name = "CharacterStyleName";
2906 pArr[nCurrentElement++].Value <<= aProgCharStyle;
2907 if( aToken.nChapterFormat != CF_NUMBER )
2909 pArr[nCurrentElement].Name = "ChapterFormat";
2910 sal_Int16 nVal;
2911 // the allowed values for chapter format, when used as entry number,
2912 // are CF_NUMBER and CF_NUM_NOPREPST_TITLE only, all else forced to
2913 //CF_NUMBER
2914 switch(aToken.nChapterFormat)
2916 default:
2917 case CF_NUMBER:
2918 nVal = text::ChapterFormat::NUMBER;
2919 break;
2920 case CF_NUM_NOPREPST_TITLE:
2921 nVal = text::ChapterFormat::DIGIT;
2922 break;
2924 pArr[nCurrentElement++].Value <<= nVal;
2927 // only a ChapterLevel != MAXLEVEL is registered
2928 if (aToken.nOutlineLevel != MAXLEVEL)
2930 pArr[nCurrentElement].Name = "ChapterLevel";
2931 pArr[nCurrentElement].Value <<= aToken.nOutlineLevel;
2934 break;
2935 case TOKEN_ENTRY: // no difference between Entry and Entry Text
2936 case TOKEN_ENTRY_TEXT:
2938 rCurTokenSeq.realloc( 2 );
2939 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2941 pArr[0].Name = "TokenType";
2942 pArr[0].Value <<= OUString("TokenEntryText");
2944 pArr[1].Name = "CharacterStyleName";
2945 pArr[1].Value <<= aProgCharStyle;
2947 break;
2948 case TOKEN_TAB_STOP:
2950 rCurTokenSeq.realloc(5); // #i21237#
2951 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2953 pArr[0].Name = "TokenType";
2954 pArr[0].Value <<= OUString("TokenTabStop");
2956 if(SvxTabAdjust::End == aToken.eTabAlign)
2958 pArr[1].Name = "TabStopRightAligned";
2959 pArr[1].Value <<= true;
2961 else
2963 pArr[1].Name = "TabStopPosition";
2964 sal_Int32 nPos = convertTwipToMm100(aToken.nTabStopPosition);
2965 if(nPos < 0)
2966 nPos = 0;
2967 pArr[1].Value <<= nPos;
2969 pArr[2].Name = "TabStopFillCharacter";
2970 pArr[2].Value <<= OUString(aToken.cTabFillChar);
2971 pArr[3].Name = "CharacterStyleName";
2972 pArr[3].Value <<= aProgCharStyle;
2973 // #i21237#
2974 pArr[4].Name = "WithTab";
2975 pArr[4].Value <<= aToken.bWithTab;
2977 break;
2978 case TOKEN_TEXT:
2980 rCurTokenSeq.realloc( 3 );
2981 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2983 pArr[0].Name = "TokenType";
2984 pArr[0].Value <<= OUString("TokenText");
2986 pArr[1].Name = "CharacterStyleName";
2987 pArr[1].Value <<= aProgCharStyle;
2989 pArr[2].Name = "Text";
2990 pArr[2].Value <<= aToken.sText;
2992 break;
2993 case TOKEN_PAGE_NUMS:
2995 rCurTokenSeq.realloc( 2 );
2996 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2998 pArr[0].Name = "TokenType";
2999 pArr[0].Value <<= OUString("TokenPageNumber");
3001 pArr[1].Name = "CharacterStyleName";
3002 pArr[1].Value <<= aProgCharStyle;
3004 break;
3005 case TOKEN_CHAPTER_INFO:
3007 rCurTokenSeq.realloc( 4 );
3008 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3010 pArr[0].Name = "TokenType";
3011 pArr[0].Value <<= OUString("TokenChapterInfo");
3013 pArr[1].Name = "CharacterStyleName";
3014 pArr[1].Value <<= aProgCharStyle;
3016 pArr[2].Name = "ChapterFormat";
3017 sal_Int16 nVal = text::ChapterFormat::NUMBER;
3018 switch(aToken.nChapterFormat)
3020 case CF_NUMBER:
3021 nVal = text::ChapterFormat::NUMBER;
3022 break;
3023 case CF_TITLE:
3024 nVal = text::ChapterFormat::NAME;
3025 break;
3026 case CF_NUM_TITLE:
3027 nVal = text::ChapterFormat::NAME_NUMBER;
3028 break;
3029 case CF_NUMBER_NOPREPST:
3030 nVal = text::ChapterFormat::NO_PREFIX_SUFFIX;
3031 break;
3032 case CF_NUM_NOPREPST_TITLE:
3033 nVal = text::ChapterFormat::DIGIT;
3034 break;
3036 pArr[2].Value <<= nVal;
3037 // #i53420#
3038 pArr[3].Name = "ChapterLevel";
3039 pArr[3].Value <<= aToken.nOutlineLevel;
3041 break;
3042 case TOKEN_LINK_START:
3044 rCurTokenSeq.realloc( 2 );
3045 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3047 pArr[0].Name = "TokenType";
3048 pArr[0].Value <<=
3049 OUString("TokenHyperlinkStart");
3050 pArr[1].Name = "CharacterStyleName";
3051 pArr[1].Value <<= aProgCharStyle;
3053 break;
3054 case TOKEN_LINK_END:
3056 rCurTokenSeq.realloc( 1 );
3057 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3059 pArr[0].Name = "TokenType";
3060 pArr[0].Value <<=
3061 OUString("TokenHyperlinkEnd");
3063 break;
3064 case TOKEN_AUTHORITY:
3066 rCurTokenSeq.realloc( 3 );
3067 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3069 pArr[0].Name = "TokenType";
3070 pArr[0].Value <<=
3071 OUString("TokenBibliographyDataField");
3073 pArr[1].Name = "CharacterStyleName";
3074 pArr[1].Value <<= aProgCharStyle;
3076 pArr[2].Name = "BibliographyDataField";
3077 pArr[2].Value <<= sal_Int16(aToken.nAuthorityField);
3079 break;
3081 default:
3086 uno::Any aRet;
3087 aRet <<= aRetSeq;
3088 return aRet;
3091 uno::Type SAL_CALL
3092 SwXDocumentIndex::TokenAccess_Impl::getElementType()
3094 return cppu::UnoType<uno::Sequence< beans::PropertyValues >>::get();
3097 sal_Bool SAL_CALL
3098 SwXDocumentIndex::TokenAccess_Impl::hasElements()
3100 return true;
3103 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */