resolves tdf#164985 Incorrect bookmarks list in bookmark dialog after
[LibreOffice.git] / sw / source / core / unocore / unoidx.cxx
blobaa4f2d171c937966381cd4a77a06be0fc0d96094
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>
64 #include <unotxdoc.hxx>
65 #include <names.hxx>
67 using namespace ::com::sun::star;
69 /// @throws lang::IllegalArgumentException
70 template<typename T>
71 static T
72 lcl_AnyToType(uno::Any const& rVal)
74 T aRet{};
75 if(!(rVal >>= aRet))
77 throw lang::IllegalArgumentException();
79 return aRet;
82 /// @throws lang::IllegalArgumentException
83 template<typename T>
84 static void lcl_AnyToBitMask(uno::Any const& rValue,
85 T & rBitMask, const T nBit)
87 rBitMask = lcl_AnyToType<bool>(rValue)
88 ? (rBitMask | nBit)
89 : (rBitMask & ~nBit);
92 template<typename T>
93 static void lcl_BitMaskToAny(uno::Any & o_rValue,
94 const T nBitMask, const T nBit)
96 const bool bRet(nBitMask & nBit);
97 o_rValue <<= bRet;
100 static void
101 lcl_ReAssignTOXType(SwDoc& rDoc, SwTOXBase& rTOXBase, const OUString& rNewName)
103 const sal_uInt16 nUserCount = rDoc.GetTOXTypeCount( TOX_USER );
104 const SwTOXType* pNewType = nullptr;
105 for(sal_uInt16 nUser = 0; nUser < nUserCount; nUser++)
107 const SwTOXType* pType = rDoc.GetTOXType( TOX_USER, nUser );
108 if (pType->GetTypeName()==rNewName)
110 pNewType = pType;
111 break;
114 if(!pNewType)
116 SwTOXType aNewType(rDoc, TOX_USER, rNewName);
117 pNewType = rDoc.InsertTOXType( aNewType );
120 rTOXBase.RegisterToTOXType( *const_cast<SwTOXType*>(pNewType) );
123 constexpr OUString cUserDefined = u"User-Defined"_ustr;
124 const char cUserSuffix[] = " (user)";
125 #define USER_LEN 12
126 #define USER_AND_SUFFIXLEN 19
128 static void lcl_ConvertTOUNameToProgrammaticName(OUString& rTmp)
130 ShellResource* pShellRes = SwViewShell::GetShellRes();
132 if(rTmp==pShellRes->aTOXUserName)
134 rTmp = cUserDefined;
136 // if the version is not English but the alternative index's name is
137 // "User-Defined" a " (user)" is appended
138 else if(rTmp == cUserDefined)
140 rTmp += cUserSuffix;
144 static void
145 lcl_ConvertTOUNameToUserName(OUString& rTmp)
147 ShellResource* pShellRes = SwViewShell::GetShellRes();
148 if (rTmp == cUserDefined)
150 rTmp = pShellRes->aTOXUserName;
152 else if (pShellRes->aTOXUserName != cUserDefined &&
153 USER_AND_SUFFIXLEN == rTmp.getLength())
155 //make sure that in non-English versions the " (user)" suffix is removed
156 if (rTmp.startsWith(cUserDefined) &&
157 rTmp.match(cUserSuffix, USER_LEN))
159 rTmp = cUserDefined;
164 typedef ::cppu::WeakImplHelper
165 < lang::XServiceInfo
166 , container::XIndexReplace
167 > SwXDocumentIndexStyleAccess_Base;
169 class SwXDocumentIndex::StyleAccess_Impl
170 : public SwXDocumentIndexStyleAccess_Base
173 private:
174 /// can be destroyed threadsafely, so no UnoImplPtr here
175 ::rtl::Reference<SwXDocumentIndex> m_xParent;
177 virtual ~StyleAccess_Impl() override;
179 public:
180 explicit StyleAccess_Impl(SwXDocumentIndex& rParentIdx);
182 // XServiceInfo
183 virtual OUString SAL_CALL getImplementationName() override;
184 virtual sal_Bool SAL_CALL
185 supportsService(const OUString& rServiceName) override;
186 virtual uno::Sequence< OUString > SAL_CALL
187 getSupportedServiceNames() override;
189 // XElementAccess
190 virtual uno::Type SAL_CALL getElementType() override;
191 virtual sal_Bool SAL_CALL hasElements() override;
193 // XIndexAccess
194 virtual sal_Int32 SAL_CALL getCount() override;
195 virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
197 // XIndexReplace
198 virtual void SAL_CALL
199 replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
203 typedef ::cppu::WeakImplHelper
204 < lang::XServiceInfo
205 , container::XIndexReplace
206 > SwXDocumentIndexTokenAccess_Base;
208 class SwXDocumentIndex::TokenAccess_Impl
209 : public SwXDocumentIndexTokenAccess_Base
212 private:
213 /// can be destroyed threadsafely, so no UnoImplPtr here
214 ::rtl::Reference<SwXDocumentIndex> m_xParent;
216 virtual ~TokenAccess_Impl() override;
218 public:
220 explicit TokenAccess_Impl(SwXDocumentIndex& rParentIdx);
222 // XServiceInfo
223 virtual OUString SAL_CALL getImplementationName() override;
224 virtual sal_Bool SAL_CALL
225 supportsService(const OUString& rServiceName) override;
226 virtual uno::Sequence< OUString > SAL_CALL
227 getSupportedServiceNames() override;
229 // XElementAccess
230 virtual uno::Type SAL_CALL getElementType() override;
231 virtual sal_Bool SAL_CALL hasElements() override;
233 // XIndexAccess
234 virtual sal_Int32 SAL_CALL getCount() override;
235 virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
237 // XIndexReplace
238 virtual void SAL_CALL
239 replaceByIndex(sal_Int32 Index, const uno::Any& rElement) override;
243 namespace {
245 class SwDocIndexDescriptorProperties_Impl
247 private:
248 std::unique_ptr<SwTOXBase> m_pTOXBase;
249 OUString m_sUserTOXTypeName;
251 public:
252 explicit SwDocIndexDescriptorProperties_Impl(SwTOXType const*const pType);
254 SwTOXBase & GetTOXBase() { return *m_pTOXBase; }
255 const OUString& GetTypeName() const { return m_sUserTOXTypeName; }
256 void SetTypeName(const OUString& rSet) { m_sUserTOXTypeName = rSet; }
261 SwDocIndexDescriptorProperties_Impl::SwDocIndexDescriptorProperties_Impl(
262 SwTOXType const*const pType)
264 SwForm aForm(pType->GetType());
265 m_pTOXBase.reset(new SwTOXBase(pType, aForm,
266 SwTOXElement::Mark, pType->GetTypeName()));
267 if(pType->GetType() == TOX_CONTENT || pType->GetType() == TOX_USER)
269 m_pTOXBase->SetLevel(MAXLEVEL);
271 m_sUserTOXTypeName = pType->GetTypeName();
274 static sal_uInt16
275 lcl_TypeToPropertyMap_Index(const TOXTypes eType)
277 switch (eType)
279 case TOX_INDEX: return PROPERTY_MAP_INDEX_IDX;
280 case TOX_CONTENT: return PROPERTY_MAP_INDEX_CNTNT;
281 case TOX_TABLES: return PROPERTY_MAP_INDEX_TABLES;
282 case TOX_ILLUSTRATIONS: return PROPERTY_MAP_INDEX_ILLUSTRATIONS;
283 case TOX_OBJECTS: return PROPERTY_MAP_INDEX_OBJECTS;
284 case TOX_AUTHORITIES: return PROPERTY_MAP_BIBLIOGRAPHY;
285 //case TOX_USER:
286 default:
287 return PROPERTY_MAP_INDEX_USER;
291 class SwXDocumentIndex::Impl final: public SvtListener
293 private:
294 SwSectionFormat* m_pFormat;
296 public:
297 unotools::WeakReference<SwXDocumentIndex> m_wThis;
298 std::mutex m_Mutex; // just for OInterfaceContainerHelper4
299 ::comphelper::OInterfaceContainerHelper4<util::XRefreshListener> m_RefreshListeners;
300 ::comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_EventListeners;
301 SfxItemPropertySet const& m_rPropSet;
302 const TOXTypes m_eTOXType;
303 bool m_bIsDescriptor;
304 SwDoc* m_pDoc;
305 std::optional<SwDocIndexDescriptorProperties_Impl> m_oProps;
306 unotools::WeakReference<StyleAccess_Impl> m_wStyleAccess;
307 unotools::WeakReference<TokenAccess_Impl> m_wTokenAccess;
309 Impl(SwDoc& rDoc, const TOXTypes eType, SwTOXBaseSection *const pBaseSection)
310 : m_pFormat(pBaseSection ? pBaseSection->GetFormat() : nullptr)
311 , m_rPropSet(*aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Index(eType)))
312 , m_eTOXType(eType)
313 , m_bIsDescriptor(nullptr == pBaseSection)
314 , m_pDoc(&rDoc)
315 , m_oProps(m_bIsDescriptor
316 ? std::optional<SwDocIndexDescriptorProperties_Impl>(rDoc.GetTOXType(eType, 0))
317 : std::nullopt)
319 if(m_pFormat)
320 StartListening(m_pFormat->GetNotifier());
323 void SetSectionFormat(SwSectionFormat& rFormat)
325 EndListeningAll();
326 m_pFormat = &rFormat;
327 StartListening(rFormat.GetNotifier());
330 SwSectionFormat* GetSectionFormat() const {
331 return m_pFormat;
334 SwTOXBase & GetTOXSectionOrThrow() const
336 SwSectionFormat *const pSectionFormat(GetSectionFormat());
337 SwTOXBase *const pTOXSection( m_bIsDescriptor
338 ? &const_cast<SwDocIndexDescriptorProperties_Impl&>(*m_oProps).GetTOXBase()
339 : (pSectionFormat
340 ? static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection())
341 : nullptr));
342 if (!pTOXSection)
344 throw uno::RuntimeException(
345 u"SwXDocumentIndex: disposed or invalid"_ustr, nullptr);
347 return *pTOXSection;
350 sal_Int32 GetFormMax() const
352 SwTOXBase & rSection( GetTOXSectionOrThrow() );
353 return m_bIsDescriptor
354 ? SwForm::GetFormMaxLevel(m_eTOXType)
355 : rSection.GetTOXForm().GetFormMax();
357 virtual void Notify(const SfxHint&) override;
361 void SwXDocumentIndex::Impl::Notify(const SfxHint& rHint)
363 if(SfxHintId::SwRemoveUnoObject == rHint.GetId())
364 m_pFormat = nullptr;
365 else if(rHint.GetId() == SfxHintId::Dying)
366 m_pFormat = nullptr;
367 if(!m_pFormat)
369 EndListeningAll();
370 rtl::Reference<SwXDocumentIndex> const xThis(m_wThis);
371 if (!xThis.is())
372 { // fdo#72695: if UNO object is already dead, don't revive it with event
373 return;
375 std::unique_lock g(m_Mutex);
376 lang::EventObject const ev(xThis->getXWeak());
377 m_RefreshListeners.disposeAndClear(g, ev);
378 m_EventListeners.disposeAndClear(g, ev);
382 SwXDocumentIndex::SwXDocumentIndex(
383 SwTOXBaseSection & rBaseSection, SwDoc & rDoc)
384 : m_pImpl( new SwXDocumentIndex::Impl(
385 rDoc, rBaseSection.SwTOXBase::GetType(), & rBaseSection) )
389 SwXDocumentIndex::SwXDocumentIndex(const TOXTypes eType, SwDoc& rDoc)
390 : m_pImpl( new SwXDocumentIndex::Impl(rDoc, eType, nullptr) )
394 SwXDocumentIndex::~SwXDocumentIndex()
398 rtl::Reference<SwXDocumentIndex>
399 SwXDocumentIndex::CreateXDocumentIndex(
400 SwDoc & rDoc, SwTOXBaseSection * pSection, TOXTypes const eTypes)
402 // re-use existing SwXDocumentIndex
403 // #i105557#: do not iterate over the registered clients: race condition
404 rtl::Reference<SwXDocumentIndex> xIndex;
405 if (pSection)
407 SwSectionFormat const *const pFormat = pSection->GetFormat();
408 xIndex = dynamic_cast<SwXDocumentIndex*>(pFormat->GetXObject().get().get());
410 if (!xIndex.is())
412 if (pSection)
414 xIndex = new SwXDocumentIndex(*pSection, rDoc);
415 pSection->GetFormat()->SetXObject(xIndex->getXWeak());
417 else
418 xIndex = new SwXDocumentIndex(eTypes, rDoc);
420 // need a permanent Reference to initialize m_wThis
421 xIndex->m_pImpl->m_wThis = xIndex.get();
423 return xIndex;
426 OUString SAL_CALL
427 SwXDocumentIndex::getImplementationName()
429 return u"SwXDocumentIndex"_ustr;
432 sal_Bool SAL_CALL
433 SwXDocumentIndex::supportsService(const OUString& rServiceName)
435 return cppu::supportsService(this, rServiceName);
438 uno::Sequence< OUString > SAL_CALL
439 SwXDocumentIndex::getSupportedServiceNames()
441 SolarMutexGuard g;
443 uno::Sequence< OUString > aRet(2);
444 OUString* pArray = aRet.getArray();
445 pArray[0] = "com.sun.star.text.BaseIndex";
446 switch (m_pImpl->m_eTOXType)
448 case TOX_INDEX:
449 pArray[1] = "com.sun.star.text.DocumentIndex";
450 break;
451 case TOX_CONTENT:
452 pArray[1] = "com.sun.star.text.ContentIndex";
453 break;
454 case TOX_TABLES:
455 pArray[1] = "com.sun.star.text.TableIndex";
456 break;
457 case TOX_ILLUSTRATIONS:
458 pArray[1] = "com.sun.star.text.IllustrationsIndex";
459 break;
460 case TOX_OBJECTS:
461 pArray[1] = "com.sun.star.text.ObjectIndex";
462 break;
463 case TOX_AUTHORITIES:
464 pArray[1] = "com.sun.star.text.Bibliography";
465 break;
466 //case TOX_USER:
467 default:
468 pArray[1] = "com.sun.star.text.UserDefinedIndex";
470 return aRet;
473 OUString SAL_CALL SwXDocumentIndex::getServiceName()
475 SolarMutexGuard g;
477 SwServiceType nObjectType = SwServiceType::TypeIndex;
478 switch (m_pImpl->m_eTOXType)
480 case TOX_USER: nObjectType = SwServiceType::UserIndex;
481 break;
482 case TOX_CONTENT: nObjectType = SwServiceType::ContentIndex;
483 break;
484 case TOX_ILLUSTRATIONS: nObjectType = SwServiceType::IndexIllustrations;
485 break;
486 case TOX_OBJECTS: nObjectType = SwServiceType::IndexObjects;
487 break;
488 case TOX_TABLES: nObjectType = SwServiceType::IndexTables;
489 break;
490 case TOX_AUTHORITIES: nObjectType = SwServiceType::IndexBibliography;
491 break;
492 default:
493 break;
495 return SwXServiceProvider::GetProviderName(nObjectType);
498 void SAL_CALL SwXDocumentIndex::update()
500 return refresh(); // update is from deprecated XDocumentIndex
503 uno::Reference< beans::XPropertySetInfo > SAL_CALL
504 SwXDocumentIndex::getPropertySetInfo()
506 SolarMutexGuard g;
508 const uno::Reference< beans::XPropertySetInfo > xRef =
509 m_pImpl->m_rPropSet.getPropertySetInfo();
510 return xRef;
513 void SAL_CALL
514 SwXDocumentIndex::setPropertyValue(
515 const OUString& rPropertyName, const uno::Any& rValue)
517 SolarMutexGuard aGuard;
519 SfxItemPropertyMapEntry const*const pEntry =
520 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
521 if (!pEntry)
523 throw beans::UnknownPropertyException(
524 "Unknown property: " + rPropertyName,
525 getXWeak());
527 if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
529 throw beans::PropertyVetoException(
530 "Property is read-only: " + rPropertyName,
531 getXWeak());
534 SwSectionFormat *const pSectionFormat(m_pImpl->GetSectionFormat());
535 SwTOXBase & rTOXBase( m_pImpl->GetTOXSectionOrThrow() );
537 SwTOXElement nCreate = rTOXBase.GetCreateType();
538 SwTOOElements nOLEOptions = rTOXBase.GetOLEOptions();
539 const TOXTypes eTxBaseType = rTOXBase.GetTOXType()->GetType();
540 SwTOIOptions nTOIOptions = (eTxBaseType == TOX_INDEX)
541 ? rTOXBase.GetOptions() : SwTOIOptions::NONE;
542 SwForm aForm(rTOXBase.GetTOXForm());
543 bool bForm = false;
544 switch (pEntry->nWID)
546 case WID_IDX_TITLE:
548 OUString sNewName;
549 if (!(rValue >>= sNewName))
551 throw lang::IllegalArgumentException();
553 rTOXBase.SetTitle(sNewName);
555 break;
556 case WID_IDX_NAME:
558 OUString sNewName;
559 if (!(rValue >>= sNewName))
561 throw lang::IllegalArgumentException();
563 rTOXBase.SetTOXName(sNewName);
565 break;
566 case WID_USER_IDX_NAME:
568 OUString sNewName;
569 if (!(rValue >>= sNewName))
571 throw lang::IllegalArgumentException();
573 lcl_ConvertTOUNameToUserName(sNewName);
574 OSL_ENSURE(TOX_USER == eTxBaseType,
575 "tox type name can only be changed for user indexes");
576 if (pSectionFormat)
578 if (rTOXBase.GetTOXType()->GetTypeName() != sNewName)
580 lcl_ReAssignTOXType(*pSectionFormat->GetDoc(),
581 rTOXBase, sNewName);
584 else
586 m_pImpl->m_oProps->SetTypeName(sNewName);
589 break;
590 case WID_IDX_LOCALE:
592 lang::Locale aLocale;
593 if (!(rValue>>= aLocale))
595 throw lang::IllegalArgumentException();
597 rTOXBase.SetLanguage( LanguageTag::convertToLanguageType(aLocale));
599 break;
600 case WID_IDX_SORT_ALGORITHM:
602 OUString sTmp;
603 if (!(rValue >>= sTmp))
605 throw lang::IllegalArgumentException();
607 rTOXBase.SetSortAlgorithm(sTmp);
609 break;
610 case WID_LEVEL:
612 rTOXBase.SetLevel(lcl_AnyToType<sal_Int16>(rValue));
614 break;
615 case WID_TOC_BOOKMARK:
617 rTOXBase.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
618 nCreate = SwTOXElement::Bookmark;
619 rTOXBase.SetCreate(nCreate);
621 break;
622 case WID_CREATE_FROM_MARKS:
623 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Mark);
624 break;
625 case WID_CREATE_FROM_OUTLINE:
626 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::OutlineLevel);
627 break;
628 case WID_TOC_PARAGRAPH_OUTLINE_LEVEL:
629 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::ParagraphOutlineLevel);
630 break;
631 case WID_TAB_IN_TOC:
632 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableInToc);
633 break;
634 case WID_TOC_NEWLINE:
635 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Newline);
636 break;
637 // case WID_PARAGRAPH_STYLE_NAMES :OSL_FAIL("not implemented")
638 // break;
639 case WID_HIDE_TABLEADER_PAGENUMBERS:
640 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::TableLeader);
641 break ;
642 case WID_CREATE_FROM_CHAPTER:
643 rTOXBase.SetFromChapter(lcl_AnyToType<bool>(rValue));
644 break;
645 case WID_CREATE_FROM_LABELS:
646 rTOXBase.SetFromObjectNames(! lcl_AnyToType<bool>(rValue));
647 break;
648 case WID_PROTECTED:
650 bool bSet = lcl_AnyToType<bool>(rValue);
651 rTOXBase.SetProtected(bSet);
652 if (pSectionFormat)
654 static_cast<SwTOXBaseSection &>(rTOXBase).SetProtect(bSet);
657 break;
658 case WID_USE_ALPHABETICAL_SEPARATORS:
659 lcl_AnyToBitMask(rValue, nTOIOptions,
660 SwTOIOptions::AlphaDelimiter);
661 break;
662 case WID_USE_KEY_AS_ENTRY:
663 lcl_AnyToBitMask(rValue, nTOIOptions,
664 SwTOIOptions::KeyAsEntry);
665 break;
666 case WID_USE_COMBINED_ENTRIES:
667 lcl_AnyToBitMask(rValue, nTOIOptions,
668 SwTOIOptions::SameEntry);
669 break;
670 case WID_IS_CASE_SENSITIVE:
671 lcl_AnyToBitMask(rValue, nTOIOptions,
672 SwTOIOptions::CaseSensitive);
673 break;
674 case WID_USE_P_P:
675 lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::FF);
676 break;
677 case WID_USE_DASH:
678 lcl_AnyToBitMask(rValue, nTOIOptions, SwTOIOptions::Dash);
679 break;
680 case WID_USE_UPPER_CASE:
681 lcl_AnyToBitMask(rValue, nTOIOptions,
682 SwTOIOptions::InitialCaps);
683 break;
684 case WID_IS_COMMA_SEPARATED:
685 bForm = true;
686 aForm.SetCommaSeparated(lcl_AnyToType<bool>(rValue));
687 break;
688 case WID_LABEL_CATEGORY:
690 // convert file-format/API/external programmatic english name
691 // to internal UI name before usage
692 rTOXBase.SetSequenceName( SwStyleNameMapper::GetSpecialExtraUIName(
693 ProgName(lcl_AnyToType<OUString>(rValue)) ) );
695 break;
696 case WID_LABEL_DISPLAY_TYPE:
698 const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
699 sal_uInt16 nSet = CAPTION_COMPLETE;
700 switch (nVal)
702 case text::ReferenceFieldPart::TEXT:
703 nSet = CAPTION_COMPLETE;
704 break;
705 case text::ReferenceFieldPart::CATEGORY_AND_NUMBER:
706 nSet = CAPTION_NUMBER;
707 break;
708 case text::ReferenceFieldPart::ONLY_CAPTION:
709 nSet = CAPTION_TEXT;
710 break;
711 default:
712 throw lang::IllegalArgumentException();
714 rTOXBase.SetCaptionDisplay(static_cast<SwCaptionDisplay>(nSet));
716 break;
717 case WID_USE_LEVEL_FROM_SOURCE:
718 rTOXBase.SetLevelFromChapter(lcl_AnyToType<bool>(rValue));
719 break;
720 case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
722 OUString aString;
723 SwStyleNameMapper::FillUIName(ProgName(lcl_AnyToType<OUString>(rValue)),
724 aString, SwGetPoolIdFromName::ChrFmt);
725 rTOXBase.SetMainEntryCharStyle( aString );
727 break;
728 case WID_CREATE_FROM_TABLES:
729 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Table);
730 break;
731 case WID_CREATE_FROM_TEXT_FRAMES:
732 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Frame);
733 break;
734 case WID_CREATE_FROM_GRAPHIC_OBJECTS:
735 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Graphic);
736 break;
737 case WID_CREATE_FROM_EMBEDDED_OBJECTS:
738 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Ole);
739 break;
740 case WID_CREATE_FROM_STAR_MATH:
741 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Math);
742 break;
743 case WID_CREATE_FROM_STAR_CHART:
744 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Chart);
745 break;
746 case WID_CREATE_FROM_STAR_CALC:
747 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Calc);
748 break;
749 case WID_CREATE_FROM_STAR_DRAW:
750 lcl_AnyToBitMask(rValue, nOLEOptions,
751 SwTOOElements::DrawImpress);
752 break;
753 case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
754 lcl_AnyToBitMask(rValue, nOLEOptions, SwTOOElements::Other);
755 break;
756 case WID_PARA_HEAD:
758 OUString aString;
759 SwStyleNameMapper::FillUIName( ProgName(lcl_AnyToType<OUString>(rValue)),
760 aString, SwGetPoolIdFromName::TxtColl);
761 bForm = true;
762 // Header is on Pos 0
763 aForm.SetTemplate( 0, aString );
765 break;
766 case WID_IS_RELATIVE_TABSTOPS:
767 bForm = true;
768 aForm.SetRelTabPos(lcl_AnyToType<bool>(rValue));
769 break;
770 case WID_PARA_SEP:
772 OUString aString;
773 bForm = true;
774 SwStyleNameMapper::FillUIName( ProgName(lcl_AnyToType<OUString>(rValue)),
775 aString, SwGetPoolIdFromName::TxtColl);
776 aForm.SetTemplate( 1, aString );
778 break;
779 case WID_CREATE_FROM_PARAGRAPH_STYLES:
780 lcl_AnyToBitMask(rValue, nCreate, SwTOXElement::Template);
781 break;
782 case WID_CREATE_FROM_PARAGRAPH_STYLE:
784 OUString style;
785 if (rValue >>= style)
787 if (style.indexOf(TOX_STYLE_DELIMITER) != -1)
789 throw lang::IllegalArgumentException();
791 lcl_AnyToBitMask(uno::Any(true), nCreate, SwTOXElement::Template);
792 OUString uiStyle;
793 SwStyleNameMapper::FillUIName(ProgName(style), uiStyle, SwGetPoolIdFromName::TxtColl);
794 rTOXBase.SetStyleNames(uiStyle, 0);
796 else if (!rValue.hasValue())
798 lcl_AnyToBitMask(uno::Any(false), nCreate, SwTOXElement::Template);
800 else
802 throw lang::IllegalArgumentException();
805 break;
807 case WID_PARA_LEV1:
808 case WID_PARA_LEV2:
809 case WID_PARA_LEV3:
810 case WID_PARA_LEV4:
811 case WID_PARA_LEV5:
812 case WID_PARA_LEV6:
813 case WID_PARA_LEV7:
814 case WID_PARA_LEV8:
815 case WID_PARA_LEV9:
816 case WID_PARA_LEV10:
818 bForm = true;
819 // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
820 const sal_uInt16 nLPos = rTOXBase.GetType() == TOX_INDEX ? 2 : 1;
821 OUString aString;
822 SwStyleNameMapper::FillUIName( ProgName(lcl_AnyToType<OUString>(rValue)),
823 aString, SwGetPoolIdFromName::TxtColl);
824 aForm.SetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1, aString );
826 break;
827 default:
828 //this is for items only
829 if (WID_PRIMARY_KEY > pEntry->nWID)
831 const SwAttrSet& rSet =
832 SwDoc::GetTOXBaseAttrSet(rTOXBase);
833 SfxItemSet aAttrSet(rSet);
834 m_pImpl->m_rPropSet.setPropertyValue(
835 rPropertyName, rValue, aAttrSet);
837 const SwSectionFormats& rSects = m_pImpl->m_pDoc->GetSections();
838 for (size_t i = 0; i < rSects.size(); ++i)
840 const SwSectionFormat* pTmpFormat = rSects[ i ];
841 if (pTmpFormat == pSectionFormat)
843 SwSectionData tmpData(
844 static_cast<SwTOXBaseSection&>(rTOXBase));
845 m_pImpl->m_pDoc->UpdateSection(i, tmpData, & aAttrSet);
846 break;
851 rTOXBase.SetCreate(nCreate);
852 rTOXBase.SetOLEOptions(nOLEOptions);
853 if (rTOXBase.GetTOXType()->GetType() == TOX_INDEX)
855 rTOXBase.SetOptions(nTOIOptions);
857 if (bForm)
859 rTOXBase.SetTOXForm(aForm);
863 uno::Any SAL_CALL
864 SwXDocumentIndex::getPropertyValue(const OUString& rPropertyName)
866 SolarMutexGuard aGuard;
868 uno::Any aRet;
869 SfxItemPropertyMapEntry const*const pEntry =
870 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
871 if (!pEntry)
873 throw beans::UnknownPropertyException(
874 "Unknown property: " + rPropertyName,
875 getXWeak());
877 // TODO: is this the best approach to tell API clients about the change?
878 if (pEntry->nWID == RES_BACKGROUND && pEntry->nMemberId == MID_GRAPHIC_URL)
880 throw uno::RuntimeException(u"Getting GraphicURL property is not supported"_ustr);
883 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
884 SwTOXBase* pTOXBase = nullptr;
885 if (pSectionFormat)
887 pTOXBase = static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection());
889 else if (m_pImpl->m_bIsDescriptor)
891 pTOXBase = &m_pImpl->m_oProps->GetTOXBase();
893 if(pTOXBase)
895 const SwTOXElement nCreate = pTOXBase->GetCreateType();
896 const SwTOOElements nOLEOptions = pTOXBase->GetOLEOptions();
897 const SwTOIOptions nTOIOptions =
898 (pTOXBase->GetTOXType()->GetType() == TOX_INDEX)
899 ? pTOXBase->GetOptions()
900 : SwTOIOptions::NONE;
901 const SwForm& rForm = pTOXBase->GetTOXForm();
902 switch(pEntry->nWID)
904 case WID_IDX_CONTENT_SECTION:
905 case WID_IDX_HEADER_SECTION :
906 if(WID_IDX_CONTENT_SECTION == pEntry->nWID)
908 const uno::Reference <text::XTextSection> xContentSect =
909 SwXTextSection::CreateXTextSection( pSectionFormat );
910 aRet <<= xContentSect;
912 else if (pSectionFormat)
914 SwSections aSectArr;
915 pSectionFormat->GetChildSections(aSectArr,
916 SectionSort::Not, false);
917 for(SwSection* pSect : aSectArr)
919 if(pSect->GetType() == SectionType::ToxHeader)
921 const uno::Reference <text::XTextSection> xHeader =
922 SwXTextSection::CreateXTextSection(
923 pSect->GetFormat() );
924 aRet <<= xHeader;
925 break;
929 break;
930 case WID_IDX_TITLE :
932 aRet <<= pTOXBase->GetTitle();
933 break;
935 case WID_IDX_NAME:
936 aRet <<= pTOXBase->GetTOXName();
937 break;
938 case WID_USER_IDX_NAME:
940 OUString sTmp((!m_pImpl->m_bIsDescriptor)
941 ? pTOXBase->GetTOXType()->GetTypeName()
942 : m_pImpl->m_oProps->GetTypeName());
943 //I18N
944 lcl_ConvertTOUNameToProgrammaticName(sTmp);
945 aRet <<= sTmp;
947 break;
948 case WID_IDX_LOCALE:
949 aRet <<= LanguageTag(pTOXBase->GetLanguage()).getLocale();
950 break;
951 case WID_IDX_SORT_ALGORITHM:
952 aRet <<= pTOXBase->GetSortAlgorithm();
953 break;
954 case WID_LEVEL :
955 aRet <<= static_cast<sal_Int16>(pTOXBase->GetLevel());
956 break;
957 case WID_TOC_BOOKMARK :
958 aRet <<= pTOXBase->GetBookmarkName();
959 break;
960 case WID_CREATE_FROM_MARKS:
961 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Mark);
962 break;
963 case WID_CREATE_FROM_OUTLINE:
964 lcl_BitMaskToAny(aRet, nCreate,
965 SwTOXElement::OutlineLevel);
966 break;
967 case WID_CREATE_FROM_CHAPTER:
969 const bool bRet = pTOXBase->IsFromChapter();
970 aRet <<= bRet;
972 break;
973 case WID_CREATE_FROM_LABELS:
975 const bool bRet = ! pTOXBase->IsFromObjectNames();
976 aRet <<= bRet;
978 break;
979 case WID_PROTECTED:
981 const bool bRet = pTOXBase->IsProtected();
982 aRet <<= bRet;
984 break;
985 case WID_USE_ALPHABETICAL_SEPARATORS:
986 lcl_BitMaskToAny(aRet, nTOIOptions,
987 SwTOIOptions::AlphaDelimiter);
988 break;
989 case WID_USE_KEY_AS_ENTRY:
990 lcl_BitMaskToAny(aRet, nTOIOptions,
991 SwTOIOptions::KeyAsEntry);
992 break;
993 case WID_USE_COMBINED_ENTRIES:
994 lcl_BitMaskToAny(aRet, nTOIOptions,
995 SwTOIOptions::SameEntry);
996 break;
997 case WID_IS_CASE_SENSITIVE:
998 lcl_BitMaskToAny(aRet, nTOIOptions,
999 SwTOIOptions::CaseSensitive);
1000 break;
1001 case WID_USE_P_P:
1002 lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::FF);
1003 break;
1004 case WID_USE_DASH:
1005 lcl_BitMaskToAny(aRet, nTOIOptions, SwTOIOptions::Dash);
1006 break;
1007 case WID_USE_UPPER_CASE:
1008 lcl_BitMaskToAny(aRet, nTOIOptions,
1009 SwTOIOptions::InitialCaps);
1010 break;
1011 case WID_IS_COMMA_SEPARATED:
1013 const bool bRet = rForm.IsCommaSeparated();
1014 aRet <<= bRet;
1016 break;
1017 case WID_LABEL_CATEGORY:
1019 // convert internal UI name to
1020 // file-format/API/external programmatic english name
1021 // before usage
1022 aRet <<= SwStyleNameMapper::GetSpecialExtraProgName(
1023 pTOXBase->GetSequenceName() ).toString();
1025 break;
1026 case WID_LABEL_DISPLAY_TYPE:
1028 sal_Int16 nSet = text::ReferenceFieldPart::TEXT;
1029 switch (pTOXBase->GetCaptionDisplay())
1031 case CAPTION_COMPLETE:
1032 nSet = text::ReferenceFieldPart::TEXT;
1033 break;
1034 case CAPTION_NUMBER:
1035 nSet = text::ReferenceFieldPart::CATEGORY_AND_NUMBER;
1036 break;
1037 case CAPTION_TEXT:
1038 nSet = text::ReferenceFieldPart::ONLY_CAPTION;
1039 break;
1041 aRet <<= nSet;
1043 break;
1044 case WID_USE_LEVEL_FROM_SOURCE:
1046 const bool bRet = pTOXBase->IsLevelFromChapter();
1047 aRet <<= bRet;
1049 break;
1050 case WID_LEVEL_FORMAT:
1052 rtl::Reference< TokenAccess_Impl > xTokenAccess(
1053 m_pImpl->m_wTokenAccess.get());
1054 if (!xTokenAccess.is())
1056 xTokenAccess = new TokenAccess_Impl(*this);
1057 m_pImpl->m_wTokenAccess = xTokenAccess.get();
1059 aRet <<= uno::Reference< container::XIndexReplace >(xTokenAccess);
1061 break;
1062 case WID_LEVEL_PARAGRAPH_STYLES:
1064 rtl::Reference< StyleAccess_Impl > xStyleAccess(
1065 m_pImpl->m_wStyleAccess.get());
1066 if (!xStyleAccess.is())
1068 xStyleAccess = new StyleAccess_Impl(*this);
1069 m_pImpl->m_wStyleAccess = xStyleAccess.get();
1071 aRet <<= uno::Reference< container::XIndexReplace >(xStyleAccess);
1073 break;
1074 case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
1076 ProgName aString;
1077 SwStyleNameMapper::FillProgName(
1078 pTOXBase->GetMainEntryCharStyle(),
1079 aString,
1080 SwGetPoolIdFromName::ChrFmt);
1081 aRet <<= aString.toString();
1083 break;
1084 case WID_CREATE_FROM_TABLES:
1085 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Table);
1086 break;
1087 case WID_CREATE_FROM_TEXT_FRAMES:
1088 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Frame);
1089 break;
1090 case WID_CREATE_FROM_GRAPHIC_OBJECTS:
1091 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Graphic);
1092 break;
1093 case WID_CREATE_FROM_EMBEDDED_OBJECTS:
1094 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Ole);
1095 break;
1096 case WID_CREATE_FROM_STAR_MATH:
1097 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Math);
1098 break;
1099 case WID_CREATE_FROM_STAR_CHART:
1100 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Chart);
1101 break;
1102 case WID_CREATE_FROM_STAR_CALC:
1103 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Calc);
1104 break;
1105 case WID_CREATE_FROM_STAR_DRAW:
1106 lcl_BitMaskToAny(aRet, nOLEOptions,
1107 SwTOOElements::DrawImpress);
1108 break;
1109 case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
1110 lcl_BitMaskToAny(aRet, nOLEOptions, SwTOOElements::Other);
1111 break;
1112 case WID_CREATE_FROM_PARAGRAPH_STYLES:
1113 lcl_BitMaskToAny(aRet, nCreate, SwTOXElement::Template);
1114 break;
1115 case WID_CREATE_FROM_PARAGRAPH_STYLE:
1117 if (nCreate & SwTOXElement::Template)
1118 { // there is only one style, at top level
1119 OUString const& rStyle(pTOXBase->GetStyleNames(0));
1120 if (!rStyle.isEmpty())
1122 assert(rStyle.indexOf(TOX_STYLE_DELIMITER) == -1);
1123 ProgName ret;
1124 SwStyleNameMapper::FillProgName(rStyle, ret,
1125 SwGetPoolIdFromName::TxtColl);
1126 aRet <<= ret.toString();
1130 break;
1132 case WID_PARA_HEAD:
1134 //Header is at position 0
1135 ProgName aString;
1136 SwStyleNameMapper::FillProgName(rForm.GetTemplate( 0 ), aString,
1137 SwGetPoolIdFromName::TxtColl );
1138 aRet <<= aString.toString();
1140 break;
1141 case WID_PARA_SEP:
1143 ProgName aString;
1144 SwStyleNameMapper::FillProgName(
1145 rForm.GetTemplate( 1 ),
1146 aString,
1147 SwGetPoolIdFromName::TxtColl);
1148 aRet <<= aString.toString();
1150 break;
1151 case WID_PARA_LEV1:
1152 case WID_PARA_LEV2:
1153 case WID_PARA_LEV3:
1154 case WID_PARA_LEV4:
1155 case WID_PARA_LEV5:
1156 case WID_PARA_LEV6:
1157 case WID_PARA_LEV7:
1158 case WID_PARA_LEV8:
1159 case WID_PARA_LEV9:
1160 case WID_PARA_LEV10:
1162 // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
1163 const sal_uInt16 nLPos = pTOXBase->GetType() == TOX_INDEX ? 2 : 1;
1164 ProgName aString;
1165 SwStyleNameMapper::FillProgName(
1166 rForm.GetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1),
1167 aString,
1168 SwGetPoolIdFromName::TxtColl);
1169 aRet <<= aString.toString();
1171 break;
1172 case WID_IS_RELATIVE_TABSTOPS:
1174 const bool bRet = rForm.IsRelTabPos();
1175 aRet <<= bRet;
1177 break;
1178 case WID_INDEX_MARKS:
1180 SwTOXMarks aMarks;
1181 const SwTOXType* pType = pTOXBase->GetTOXType();
1182 pType->CollectTextMarks(aMarks);
1183 uno::Sequence< uno::Reference<text::XDocumentIndexMark> > aXMarks(aMarks.size());
1184 uno::Reference<text::XDocumentIndexMark>* pxMarks = aXMarks.getArray();
1185 for(size_t i = 0; i < aMarks.size(); ++i)
1187 SwTOXMark* pMark = aMarks[i];
1188 pxMarks[i] = SwXDocumentIndexMark::CreateXDocumentIndexMark(
1189 *m_pImpl->m_pDoc, pMark);
1191 aRet <<= aXMarks;
1193 break;
1194 default:
1195 //this is for items only
1196 if(WID_PRIMARY_KEY > pEntry->nWID)
1198 const SwAttrSet& rSet =
1199 SwDoc::GetTOXBaseAttrSet(*pTOXBase);
1200 aRet = m_pImpl->m_rPropSet.getPropertyValue(
1201 rPropertyName, rSet);
1205 return aRet;
1208 void SAL_CALL
1209 SwXDocumentIndex::addPropertyChangeListener(
1210 const OUString& /*rPropertyName*/,
1211 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1213 OSL_FAIL("SwXDocumentIndex::addPropertyChangeListener(): not implemented");
1216 void SAL_CALL
1217 SwXDocumentIndex::removePropertyChangeListener(
1218 const OUString& /*rPropertyName*/,
1219 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1221 OSL_FAIL("SwXDocumentIndex::removePropertyChangeListener(): not implemented");
1224 void SAL_CALL
1225 SwXDocumentIndex::addVetoableChangeListener(
1226 const OUString& /*rPropertyName*/,
1227 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1229 OSL_FAIL("SwXDocumentIndex::addVetoableChangeListener(): not implemented");
1232 void SAL_CALL
1233 SwXDocumentIndex::removeVetoableChangeListener(
1234 const OUString& /*rPropertyName*/,
1235 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1237 OSL_FAIL("SwXDocumentIndex::removeVetoableChangeListener(): not implemented");
1240 static void lcl_CalcLayout(SwDoc *pDoc)
1242 SwViewShell *pViewShell = nullptr;
1243 SwEditShell* pEditShell = nullptr;
1244 if( pDoc )
1246 pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
1247 pEditShell = pDoc->GetEditShell();
1250 if (pEditShell)
1252 pEditShell->CalcLayout();
1254 else if (pViewShell)
1256 pViewShell->CalcLayout();
1260 // XRefreshable
1261 void SAL_CALL SwXDocumentIndex::refresh()
1264 SolarMutexGuard g;
1266 SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1267 SwTOXBaseSection *const pTOXBase = pFormat ?
1268 static_cast<SwTOXBaseSection*>(pFormat->GetSection()) : nullptr;
1269 if (!pTOXBase)
1271 throw uno::RuntimeException(
1272 u"SwXDocumentIndex::refresh: must be in attached state"_ustr,
1273 getXWeak());
1275 pTOXBase->Update(nullptr, m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
1277 // the insertion of TOC will affect the document layout
1278 lcl_CalcLayout(m_pImpl->m_pDoc);
1280 // page numbers
1281 pTOXBase->UpdatePageNum();
1284 std::unique_lock g(m_pImpl->m_Mutex);
1285 if (m_pImpl->m_RefreshListeners.getLength(g))
1287 lang::EventObject const event(getXWeak());
1288 m_pImpl->m_RefreshListeners.notifyEach(g, & util::XRefreshListener::refreshed, event);
1292 void SAL_CALL SwXDocumentIndex::addRefreshListener(
1293 const uno::Reference<util::XRefreshListener>& xListener)
1295 // no need to lock here as m_pImpl is const and container threadsafe
1296 std::unique_lock g(m_pImpl->m_Mutex);
1297 m_pImpl->m_RefreshListeners.addInterface(g, xListener);
1300 void SAL_CALL SwXDocumentIndex::removeRefreshListener(
1301 const uno::Reference<util::XRefreshListener>& xListener)
1303 // no need to lock here as m_pImpl is const and container threadsafe
1304 std::unique_lock g(m_pImpl->m_Mutex);
1305 m_pImpl->m_RefreshListeners.removeInterface(g, xListener);
1308 void SAL_CALL
1309 SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange)
1311 SolarMutexGuard aGuard;
1313 if (!m_pImpl->m_bIsDescriptor)
1315 throw uno::RuntimeException();
1317 SwXTextRange *const pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
1318 OTextCursorHelper *const pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
1320 SwDoc *const pDoc =
1321 pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
1322 if (!pDoc)
1324 throw lang::IllegalArgumentException();
1327 SwUnoInternalPaM aPam(*pDoc);
1328 // this now needs to return TRUE
1329 ::sw::XTextRangeToSwPaM(aPam, xTextRange);
1331 const SwTOXBase* pOld = SwDoc::GetCurTOX( *aPam.Start() );
1332 if (pOld)
1334 throw lang::IllegalArgumentException();
1337 UnoActionContext aAction(pDoc);
1339 SwTOXBase & rTOXBase = m_pImpl->m_oProps->GetTOXBase();
1340 SwTOXType const*const pTOXType = rTOXBase.GetTOXType();
1341 if ((TOX_USER == pTOXType->GetType()) &&
1342 m_pImpl->m_oProps->GetTypeName() != pTOXType->GetTypeName())
1344 lcl_ReAssignTOXType(*pDoc, rTOXBase, m_pImpl->m_oProps->GetTypeName());
1346 //TODO: apply Section attributes (columns and background)
1347 SwTOXBaseSection *const pTOX =
1348 pDoc->InsertTableOf( aPam, rTOXBase, nullptr, false,
1349 m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
1351 pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_oProps->GetTOXBase().GetTOXName());
1353 // update page numbers
1354 m_pImpl->SetSectionFormat(*pTOX->GetFormat());
1355 pTOX->GetFormat()->SetXObject(getXWeak());
1356 pTOX->UpdatePageNum();
1358 m_pImpl->m_oProps.reset();
1359 m_pImpl->m_pDoc = pDoc;
1360 m_pImpl->m_bIsDescriptor = false;
1363 uno::Reference< text::XTextRange > SAL_CALL
1364 SwXDocumentIndex::getAnchor()
1366 SolarMutexGuard aGuard;
1368 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1369 if (!pSectionFormat)
1371 throw uno::RuntimeException();
1374 rtl::Reference<SwXTextRange> xRet;
1375 SwNodeIndex const*const pIdx( pSectionFormat->GetContent().GetContentIdx() );
1376 if (pIdx && pIdx->GetNode().GetNodes().IsDocNodes())
1378 SwPaM aPaM(*pIdx);
1379 aPaM.Move( fnMoveForward, GoInContent );
1380 aPaM.SetMark();
1381 aPaM.GetPoint()->Assign( *pIdx->GetNode().EndOfSectionNode() );
1382 aPaM.Move( fnMoveBackward, GoInContent );
1383 xRet = SwXTextRange::CreateXTextRange(*pSectionFormat->GetDoc(),
1384 *aPaM.GetMark(), aPaM.GetPoint());
1386 return xRet;
1389 void SAL_CALL SwXDocumentIndex::dispose()
1391 SolarMutexGuard aGuard;
1393 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1394 if (pSectionFormat)
1396 pSectionFormat->GetDoc()->DeleteTOX(
1397 *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()),
1398 true);
1402 void SAL_CALL
1403 SwXDocumentIndex::addEventListener(
1404 const uno::Reference< lang::XEventListener > & xListener)
1406 // no need to lock here as m_pImpl is const and container threadsafe
1407 std::unique_lock g(m_pImpl->m_Mutex);
1408 m_pImpl->m_EventListeners.addInterface(g, xListener);
1411 void SAL_CALL
1412 SwXDocumentIndex::removeEventListener(
1413 const uno::Reference< lang::XEventListener > & xListener)
1415 // no need to lock here as m_pImpl is const and container threadsafe
1416 std::unique_lock g(m_pImpl->m_Mutex);
1417 m_pImpl->m_EventListeners.removeInterface(g, xListener);
1420 OUString SAL_CALL SwXDocumentIndex::getName()
1422 SolarMutexGuard g;
1424 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1425 if (m_pImpl->m_bIsDescriptor)
1427 return m_pImpl->m_oProps->GetTOXBase().GetTOXName();
1430 if(!pSectionFormat)
1432 throw uno::RuntimeException();
1435 return pSectionFormat->GetSection()->GetSectionName();
1438 void SAL_CALL
1439 SwXDocumentIndex::setName(const OUString& rName)
1441 SolarMutexGuard g;
1443 if (rName.isEmpty())
1445 throw uno::RuntimeException();
1448 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1449 if (m_pImpl->m_bIsDescriptor)
1451 m_pImpl->m_oProps->GetTOXBase().SetTOXName(rName);
1453 else if (pSectionFormat)
1455 const bool bSuccess = pSectionFormat->GetDoc()->SetTOXBaseName(
1456 *static_cast<SwTOXBaseSection*>(pSectionFormat->GetSection()), rName);
1457 if (!bSuccess)
1459 throw uno::RuntimeException();
1462 else
1464 throw uno::RuntimeException();
1468 // MetadatableMixin
1469 ::sfx2::Metadatable* SwXDocumentIndex::GetCoreObject()
1471 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1472 return pSectionFormat;
1475 uno::Reference<frame::XModel> SwXDocumentIndex::GetModel()
1477 SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1478 if (pSectionFormat)
1480 SwDocShell const*const pShell( pSectionFormat->GetDoc()->GetDocShell() );
1481 return pShell ? pShell->GetModel() : nullptr;
1483 return nullptr;
1486 static sal_uInt16
1487 lcl_TypeToPropertyMap_Mark(const TOXTypes eType)
1489 switch (eType)
1491 case TOX_INDEX: return PROPERTY_MAP_INDEX_MARK;
1492 case TOX_CONTENT: return PROPERTY_MAP_CNTIDX_MARK;
1493 case TOX_CITATION : return PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY;
1494 //case TOX_USER:
1495 default:
1496 return PROPERTY_MAP_USER_MARK;
1500 class SwXDocumentIndexMark::Impl final: public SvtListener
1502 private:
1503 SwXDocumentIndexMark & m_rThis;
1504 bool m_bInReplaceMark;
1506 public:
1508 unotools::WeakReference<SwXDocumentIndexMark> m_wThis;
1509 SfxItemPropertySet const& m_rPropSet;
1510 const TOXTypes m_eTOXType;
1511 std::mutex m_Mutex; // just for OInterfaceContainerHelper4
1512 ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners;
1513 bool m_bIsDescriptor;
1514 const SwTOXType* m_pTOXType;
1515 const SwTOXMark* m_pTOXMark;
1516 SwDoc* m_pDoc;
1518 bool m_bMainEntry;
1519 sal_uInt16 m_nLevel;
1520 OUString m_aBookmarkName;
1521 OUString m_sAltText;
1522 OUString m_sPrimaryKey;
1523 OUString m_sSecondaryKey;
1524 OUString m_sTextReading;
1525 OUString m_sPrimaryKeyReading;
1526 OUString m_sSecondaryKeyReading;
1527 OUString m_sUserIndexName;
1529 Impl(SwXDocumentIndexMark& rThis,
1530 SwDoc* const pDoc,
1531 const enum TOXTypes eType,
1532 const SwTOXType* pType,
1533 SwTOXMark const* pMark)
1534 : m_rThis(rThis)
1535 , m_bInReplaceMark(false)
1536 , m_rPropSet(
1537 *aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Mark(eType)))
1538 , m_eTOXType(eType)
1539 , m_bIsDescriptor(nullptr == pMark)
1540 , m_pTOXType(pType)
1541 , m_pTOXMark(pMark)
1542 , m_pDoc(pDoc)
1543 , m_bMainEntry(false)
1544 , m_nLevel(0)
1546 auto pTypeNonConst = const_cast<SwTOXType*>(m_pTOXType);
1548 if(pTypeNonConst)
1549 StartListening(pTypeNonConst->GetNotifier());
1552 SwTOXType* GetTOXType() const {
1553 return const_cast<SwTOXType*>(m_pTOXType);
1556 void DeleteTOXMark()
1558 m_pDoc->DeleteTOXMark(m_pTOXMark);
1559 Invalidate();
1562 void InsertTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
1563 SwXTextCursor const*const pTextCursor);
1565 void ReplaceTOXMark(const SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam)
1567 m_bInReplaceMark = true;
1568 DeleteTOXMark();
1569 m_bInReplaceMark = false;
1570 try {
1571 InsertTOXMark(rTOXType, rMark, rPam, nullptr);
1572 } catch (...) {
1573 OSL_FAIL("ReplaceTOXMark() failed!");
1574 lang::EventObject const ev(m_rThis.getXWeak());
1575 std::unique_lock aGuard(m_Mutex);
1576 m_EventListeners.disposeAndClear(aGuard, ev);
1577 throw;
1581 void Invalidate();
1582 virtual void Notify(const SfxHint&) override;
1585 void SwXDocumentIndexMark::Impl::Invalidate()
1587 if (!m_bInReplaceMark) // #i109983# only dispose on delete, not on replace!
1589 rtl::Reference<SwXDocumentIndexMark> const xThis(m_wThis);
1590 // fdo#72695: if UNO object is already dead, don't revive it with event
1591 if (xThis.is())
1593 lang::EventObject const ev(xThis->getXWeak());
1594 std::unique_lock aGuard(m_Mutex);
1595 m_EventListeners.disposeAndClear(aGuard, ev);
1598 EndListeningAll();
1599 m_pDoc = nullptr;
1600 m_pTOXMark = nullptr;
1601 m_pTOXType = nullptr;
1604 void SwXDocumentIndexMark::Impl::Notify(const SfxHint& rHint)
1606 if(rHint.GetId() == SfxHintId::SwModifyChanged)
1608 auto pModifyChangedHint = static_cast<const sw::ModifyChangedHint*>(&rHint);
1609 if(auto pNewType = dynamic_cast<const SwTOXType*>(pModifyChangedHint->m_pNew))
1610 m_pTOXType = pNewType;
1614 SwXDocumentIndexMark::SwXDocumentIndexMark(const TOXTypes eToxType)
1615 : m_pImpl( new SwXDocumentIndexMark::Impl(*this, nullptr, eToxType, nullptr, nullptr) )
1619 SwXDocumentIndexMark::SwXDocumentIndexMark(SwDoc & rDoc,
1620 const SwTOXType & rType, const SwTOXMark & rMark)
1621 : m_pImpl( new SwXDocumentIndexMark::Impl(*this, &rDoc, rType.GetType(),
1622 &rType, &rMark) )
1626 SwXDocumentIndexMark::~SwXDocumentIndexMark()
1630 // called when the associated SwTOXMark is deleted
1631 void SwXDocumentIndexMark::OnSwTOXMarkDeleted()
1633 m_pImpl->Invalidate();
1636 rtl::Reference<SwXDocumentIndexMark>
1637 SwXDocumentIndexMark::CreateXDocumentIndexMark(
1638 SwDoc & rDoc, SwTOXMark *const pMark, TOXTypes const eType)
1640 // re-use existing SwXDocumentIndexMark
1641 // NB: xmloff depends on this caching to generate ID from the address!
1642 // #i105557#: do not iterate over the registered clients: race condition
1643 rtl::Reference<SwXDocumentIndexMark> xTOXMark;
1644 if (pMark)
1646 xTOXMark = pMark->GetXTOXMark();
1648 if (!xTOXMark.is())
1650 if (pMark)
1652 xTOXMark = new SwXDocumentIndexMark(rDoc,
1653 *const_cast<SwTOXType*>(pMark->GetTOXType()), *pMark);
1654 pMark->SetXTOXMark(xTOXMark);
1656 else
1657 xTOXMark = new SwXDocumentIndexMark(eType);
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 u"SwXDocumentIndexMark"_ustr;
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( u" "_ustr );
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 u"SwXDocumentIndexMark::InsertTOXMark(): cannot insert attribute"_ustr,
1938 nullptr);
1941 m_pDoc = &rDoc;
1942 m_pTOXMark = &pNewTextAttr->GetTOXMark();
1943 m_pTOXType = &rTOXType;
1944 EndListeningAll();
1945 StartListening(const_cast<SwTOXType*>(m_pTOXType)->GetNotifier());
1948 uno::Reference< text::XTextRange > SAL_CALL
1949 SwXDocumentIndexMark::getAnchor()
1951 SolarMutexGuard aGuard;
1953 SwTOXType *const pType = m_pImpl->GetTOXType();
1954 if (!pType || !m_pImpl->m_pTOXMark)
1956 throw uno::RuntimeException();
1958 if (!m_pImpl->m_pTOXMark->GetTextTOXMark())
1960 throw uno::RuntimeException();
1962 const SwTextTOXMark* pTextMark = m_pImpl->m_pTOXMark->GetTextTOXMark();
1963 SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
1964 aPam.SetMark();
1965 if(pTextMark->End())
1967 aPam.GetPoint()->SetContent( *pTextMark->End() );
1969 else
1971 aPam.GetPoint()->AdjustContent(1);
1973 uno::Reference< text::XTextRange > xRet;
1974 if(SwDocShell* pShell = m_pImpl->m_pDoc->GetDocShell())
1976 const rtl::Reference< SwXTextDocument > xModel =
1977 pShell->GetBaseModel();
1978 xRet = new SwXTextRange(aPam, xModel->getText());
1981 return xRet;
1984 void SAL_CALL
1985 SwXDocumentIndexMark::dispose()
1987 SolarMutexGuard aGuard;
1989 SwTOXType *const pType = m_pImpl->GetTOXType();
1990 if (pType && m_pImpl->m_pTOXMark)
1992 m_pImpl->DeleteTOXMark(); // call Invalidate() via modify!
1996 void SAL_CALL
1997 SwXDocumentIndexMark::addEventListener(
1998 const uno::Reference< lang::XEventListener > & xListener)
2000 // no need to lock here as m_pImpl is const and container threadsafe
2001 std::unique_lock aGuard(m_pImpl->m_Mutex);
2002 m_pImpl->m_EventListeners.addInterface(aGuard, xListener);
2005 void SAL_CALL
2006 SwXDocumentIndexMark::removeEventListener(
2007 const uno::Reference< lang::XEventListener > & xListener)
2009 // no need to lock here as m_pImpl is const and container threadsafe
2010 std::unique_lock aGuard(m_pImpl->m_Mutex);
2011 m_pImpl->m_EventListeners.removeInterface(aGuard, xListener);
2014 uno::Reference< beans::XPropertySetInfo > SAL_CALL
2015 SwXDocumentIndexMark::getPropertySetInfo()
2017 SolarMutexGuard g;
2019 static uno::Reference< beans::XPropertySetInfo > xInfos[3];
2020 int nPos = 0;
2021 switch (m_pImpl->m_eTOXType)
2023 case TOX_INDEX: nPos = 0; break;
2024 case TOX_CONTENT: nPos = 1; break;
2025 case TOX_USER: nPos = 2; break;
2026 default:
2029 if(!xInfos[nPos].is())
2031 const uno::Reference< beans::XPropertySetInfo > xInfo =
2032 m_pImpl->m_rPropSet.getPropertySetInfo();
2033 // extend PropertySetInfo!
2034 const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
2035 xInfos[nPos] = new SfxExtItemPropertySetInfo(
2036 aSwMapProvider.GetPropertyMapEntries(
2037 PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
2038 aPropSeq );
2040 return xInfos[nPos];
2043 void SAL_CALL
2044 SwXDocumentIndexMark::setPropertyValue(
2045 const OUString& rPropertyName, const uno::Any& rValue)
2047 SolarMutexGuard aGuard;
2049 SfxItemPropertyMapEntry const*const pEntry =
2050 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
2051 if (!pEntry)
2053 throw beans::UnknownPropertyException(
2054 "Unknown property: " + rPropertyName,
2055 getXWeak());
2057 if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
2059 throw beans::PropertyVetoException(
2060 "Property is read-only: " + rPropertyName,
2061 getXWeak());
2064 SwTOXType *const pType = m_pImpl->GetTOXType();
2065 if (pType && m_pImpl->m_pTOXMark)
2067 SwTOXMark aMark(*m_pImpl->m_pTOXMark);
2068 switch(pEntry->nWID)
2070 case WID_ALT_TEXT:
2071 aMark.SetAlternativeText(lcl_AnyToType<OUString>(rValue));
2072 break;
2073 case WID_LEVEL:
2074 aMark.SetLevel(std::min( static_cast<sal_Int8>( MAXLEVEL ),
2075 static_cast<sal_Int8>(lcl_AnyToType<sal_Int16>(rValue)+1)));
2076 break;
2077 case WID_TOC_BOOKMARK :
2078 aMark.SetBookmarkName(lcl_AnyToType<OUString>(rValue));
2079 break;
2080 case WID_PRIMARY_KEY :
2081 aMark.SetPrimaryKey(lcl_AnyToType<OUString>(rValue));
2082 break;
2083 case WID_SECONDARY_KEY:
2084 aMark.SetSecondaryKey(lcl_AnyToType<OUString>(rValue));
2085 break;
2086 case WID_MAIN_ENTRY:
2087 aMark.SetMainEntry(lcl_AnyToType<bool>(rValue));
2088 break;
2089 case WID_TEXT_READING:
2090 aMark.SetTextReading(lcl_AnyToType<OUString>(rValue));
2091 break;
2092 case WID_PRIMARY_KEY_READING:
2093 aMark.SetPrimaryKeyReading(lcl_AnyToType<OUString>(rValue));
2094 break;
2095 case WID_SECONDARY_KEY_READING:
2096 aMark.SetSecondaryKeyReading(lcl_AnyToType<OUString>(rValue));
2097 break;
2099 SwTextTOXMark const*const pTextMark =
2100 m_pImpl->m_pTOXMark->GetTextTOXMark();
2101 SwPaM aPam(pTextMark->GetTextNode(), pTextMark->GetStart());
2102 aPam.SetMark();
2103 if(pTextMark->End())
2105 aPam.GetPoint()->SetContent(*pTextMark->End());
2107 else
2109 aPam.GetPoint()->AdjustContent(1);
2112 m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
2114 else if (m_pImpl->m_bIsDescriptor)
2116 switch(pEntry->nWID)
2118 case WID_ALT_TEXT:
2119 m_pImpl->m_sAltText = lcl_AnyToType<OUString>(rValue);
2120 break;
2121 case WID_LEVEL:
2123 const sal_Int16 nVal = lcl_AnyToType<sal_Int16>(rValue);
2124 if(nVal < 0 || nVal >= MAXLEVEL)
2126 throw lang::IllegalArgumentException();
2128 m_pImpl->m_nLevel = nVal;
2130 break;
2131 case WID_TOC_BOOKMARK :
2133 m_pImpl->m_aBookmarkName = lcl_AnyToType<OUString>(rValue);
2135 break;
2136 case WID_PRIMARY_KEY:
2137 m_pImpl->m_sPrimaryKey = lcl_AnyToType<OUString>(rValue);
2138 break;
2139 case WID_SECONDARY_KEY:
2140 m_pImpl->m_sSecondaryKey = lcl_AnyToType<OUString>(rValue);
2141 break;
2142 case WID_TEXT_READING:
2143 m_pImpl->m_sTextReading = lcl_AnyToType<OUString>(rValue);
2144 break;
2145 case WID_PRIMARY_KEY_READING:
2146 m_pImpl->m_sPrimaryKeyReading = lcl_AnyToType<OUString>(rValue);
2147 break;
2148 case WID_SECONDARY_KEY_READING:
2149 m_pImpl->m_sSecondaryKeyReading = lcl_AnyToType<OUString>(rValue);
2150 break;
2151 case WID_USER_IDX_NAME:
2153 OUString sTmp(lcl_AnyToType<OUString>(rValue));
2154 lcl_ConvertTOUNameToUserName(sTmp);
2155 m_pImpl->m_sUserIndexName = sTmp;
2157 break;
2158 case WID_MAIN_ENTRY:
2159 m_pImpl->m_bMainEntry = lcl_AnyToType<bool>(rValue);
2160 break;
2161 case PROPERTY_MAP_INDEX_OBJECTS:
2162 // unsupported
2163 break;
2166 else
2168 throw uno::RuntimeException();
2172 uno::Any SAL_CALL
2173 SwXDocumentIndexMark::getPropertyValue(const OUString& rPropertyName)
2175 SolarMutexGuard aGuard;
2177 uno::Any aRet;
2178 SfxItemPropertyMapEntry const*const pEntry =
2179 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
2180 if (!pEntry)
2182 throw beans::UnknownPropertyException(
2183 "Unknown property: " + rPropertyName,
2184 getXWeak());
2186 if (::sw::GetDefaultTextContentValue(aRet, rPropertyName, pEntry->nWID))
2188 return aRet;
2191 SwTOXType *const pType = m_pImpl->GetTOXType();
2192 if (pType && m_pImpl->m_pTOXMark)
2194 switch(pEntry->nWID)
2196 case WID_ALT_TEXT:
2197 aRet <<= m_pImpl->m_pTOXMark->GetAlternativeText();
2198 break;
2199 case WID_LEVEL:
2200 aRet <<= static_cast<sal_Int16>(
2201 m_pImpl->m_pTOXMark->GetLevel() - 1);
2202 break;
2203 case WID_TOC_BOOKMARK :
2204 aRet <<= m_pImpl->m_pTOXMark->GetBookmarkName();
2205 break;
2206 case WID_PRIMARY_KEY :
2207 aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKey();
2208 break;
2209 case WID_SECONDARY_KEY:
2210 aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKey();
2211 break;
2212 case WID_TEXT_READING:
2213 aRet <<= m_pImpl->m_pTOXMark->GetTextReading();
2214 break;
2215 case WID_PRIMARY_KEY_READING:
2216 aRet <<= m_pImpl->m_pTOXMark->GetPrimaryKeyReading();
2217 break;
2218 case WID_SECONDARY_KEY_READING:
2219 aRet <<= m_pImpl->m_pTOXMark->GetSecondaryKeyReading();
2220 break;
2221 case WID_USER_IDX_NAME :
2223 OUString sTmp(pType->GetTypeName());
2224 lcl_ConvertTOUNameToProgrammaticName(sTmp);
2225 aRet <<= sTmp;
2227 break;
2228 case WID_MAIN_ENTRY:
2230 const bool bTemp = m_pImpl->m_pTOXMark->IsMainEntry();
2231 aRet <<= bTemp;
2233 break;
2236 else if (m_pImpl->m_bIsDescriptor)
2238 switch(pEntry->nWID)
2240 case WID_ALT_TEXT:
2241 aRet <<= m_pImpl->m_sAltText;
2242 break;
2243 case WID_LEVEL:
2244 aRet <<= static_cast<sal_Int16>(m_pImpl->m_nLevel);
2245 break;
2246 case WID_TOC_BOOKMARK :
2247 aRet <<= m_pImpl->m_aBookmarkName;
2248 break;
2249 case WID_PRIMARY_KEY:
2250 aRet <<= m_pImpl->m_sPrimaryKey;
2251 break;
2252 case WID_SECONDARY_KEY:
2253 aRet <<= m_pImpl->m_sSecondaryKey;
2254 break;
2255 case WID_TEXT_READING:
2256 aRet <<= m_pImpl->m_sTextReading;
2257 break;
2258 case WID_PRIMARY_KEY_READING:
2259 aRet <<= m_pImpl->m_sPrimaryKeyReading;
2260 break;
2261 case WID_SECONDARY_KEY_READING:
2262 aRet <<= m_pImpl->m_sSecondaryKeyReading;
2263 break;
2264 case WID_USER_IDX_NAME :
2265 aRet <<= m_pImpl->m_sUserIndexName;
2266 break;
2267 case WID_MAIN_ENTRY:
2268 aRet <<= m_pImpl->m_bMainEntry;
2269 break;
2272 else
2274 throw uno::RuntimeException();
2276 return aRet;
2279 void SAL_CALL
2280 SwXDocumentIndexMark::addPropertyChangeListener(
2281 const OUString& /*rPropertyName*/,
2282 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
2284 OSL_FAIL("SwXDocumentIndexMark::addPropertyChangeListener(): not implemented");
2287 void SAL_CALL
2288 SwXDocumentIndexMark::removePropertyChangeListener(
2289 const OUString& /*rPropertyName*/,
2290 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
2292 OSL_FAIL("SwXDocumentIndexMark::removePropertyChangeListener(): not implemented");
2295 void SAL_CALL
2296 SwXDocumentIndexMark::addVetoableChangeListener(
2297 const OUString& /*rPropertyName*/,
2298 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
2300 OSL_FAIL("SwXDocumentIndexMark::addVetoableChangeListener(): not implemented");
2303 void SAL_CALL
2304 SwXDocumentIndexMark::removeVetoableChangeListener(
2305 const OUString& /*rPropertyName*/,
2306 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
2308 OSL_FAIL("SwXDocumentIndexMark::removeVetoableChangeListener(): not implemented");
2311 SwXDocumentIndexes::SwXDocumentIndexes(SwDoc *const _pDoc)
2312 : SwUnoCollection(_pDoc)
2316 SwXDocumentIndexes::~SwXDocumentIndexes()
2320 OUString SAL_CALL
2321 SwXDocumentIndexes::getImplementationName()
2323 return u"SwXDocumentIndexes"_ustr;
2326 sal_Bool SAL_CALL SwXDocumentIndexes::supportsService(const OUString& rServiceName)
2328 return cppu::supportsService(this, rServiceName);
2331 uno::Sequence< OUString > SAL_CALL
2332 SwXDocumentIndexes::getSupportedServiceNames()
2334 return { u"com.sun.star.text.DocumentIndexes"_ustr };
2337 sal_Int32 SAL_CALL
2338 SwXDocumentIndexes::getCount()
2340 SolarMutexGuard aGuard;
2342 sal_uInt32 nRet = 0;
2343 const SwSectionFormats& rFormats = GetDoc().GetSections();
2344 for( size_t n = 0; n < rFormats.size(); ++n )
2346 const SwSection* pSect = rFormats[ n ]->GetSection();
2347 if( SectionType::ToxContent == pSect->GetType() &&
2348 pSect->GetFormat()->GetSectionNode() )
2350 ++nRet;
2353 return nRet;
2356 uno::Any SAL_CALL
2357 SwXDocumentIndexes::getByIndex(sal_Int32 nIndex)
2359 SolarMutexGuard aGuard;
2361 sal_Int32 nIdx = 0;
2363 auto& rDoc = GetDoc();
2364 const SwSectionFormats& rFormats = rDoc.GetSections();
2365 for( size_t n = 0; n < rFormats.size(); ++n )
2367 SwSection* pSect = rFormats[ n ]->GetSection();
2368 if( SectionType::ToxContent == pSect->GetType() &&
2369 pSect->GetFormat()->GetSectionNode() &&
2370 nIdx++ == nIndex )
2372 const uno::Reference< text::XDocumentIndex > xTmp =
2373 SwXDocumentIndex::CreateXDocumentIndex(
2374 rDoc, static_cast<SwTOXBaseSection *>(pSect));
2375 uno::Any aRet;
2376 aRet <<= xTmp;
2377 return aRet;
2381 throw lang::IndexOutOfBoundsException();
2384 uno::Any SAL_CALL
2385 SwXDocumentIndexes::getByName(const OUString& rName)
2387 SolarMutexGuard aGuard;
2389 auto& rDoc = GetDoc();
2390 const SwSectionFormats& rFormats = rDoc.GetSections();
2391 for( size_t n = 0; n < rFormats.size(); ++n )
2393 SwSection* pSect = rFormats[ n ]->GetSection();
2394 if( SectionType::ToxContent == pSect->GetType() &&
2395 pSect->GetFormat()->GetSectionNode() &&
2396 (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
2397 == rName))
2399 const uno::Reference< text::XDocumentIndex > xTmp =
2400 SwXDocumentIndex::CreateXDocumentIndex(
2401 rDoc, static_cast<SwTOXBaseSection *>(pSect));
2402 uno::Any aRet;
2403 aRet <<= xTmp;
2404 return aRet;
2407 throw container::NoSuchElementException();
2410 uno::Sequence< OUString > SAL_CALL
2411 SwXDocumentIndexes::getElementNames()
2413 SolarMutexGuard aGuard;
2415 const SwSectionFormats& rFormats = GetDoc().GetSections();
2416 sal_Int32 nCount = 0;
2417 for( size_t n = 0; n < rFormats.size(); ++n )
2419 SwSection const*const pSect = rFormats[ n ]->GetSection();
2420 if( SectionType::ToxContent == pSect->GetType() &&
2421 pSect->GetFormat()->GetSectionNode() )
2423 ++nCount;
2427 uno::Sequence< OUString > aRet(nCount);
2428 OUString* pArray = aRet.getArray();
2429 sal_Int32 nCnt = 0;
2430 for( size_t n = 0; n < rFormats.size(); ++n )
2432 SwSection const*const pSect = rFormats[ n ]->GetSection();
2433 if( SectionType::ToxContent == pSect->GetType() &&
2434 pSect->GetFormat()->GetSectionNode())
2436 pArray[nCnt++] = static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName();
2439 return aRet;
2442 sal_Bool SAL_CALL
2443 SwXDocumentIndexes::hasByName(const OUString& rName)
2445 SolarMutexGuard aGuard;
2447 const SwSectionFormats& rFormats = GetDoc().GetSections();
2448 for( size_t n = 0; n < rFormats.size(); ++n )
2450 SwSection const*const pSect = rFormats[ n ]->GetSection();
2451 if( SectionType::ToxContent == pSect->GetType() &&
2452 pSect->GetFormat()->GetSectionNode())
2454 if (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
2455 == rName)
2457 return true;
2461 return false;
2464 uno::Type SAL_CALL
2465 SwXDocumentIndexes::getElementType()
2467 return cppu::UnoType<text::XDocumentIndex>::get();
2470 sal_Bool SAL_CALL
2471 SwXDocumentIndexes::hasElements()
2473 return 0 != getCount();
2476 SwXDocumentIndex::StyleAccess_Impl::StyleAccess_Impl(
2477 SwXDocumentIndex& rParentIdx)
2478 : m_xParent(&rParentIdx)
2482 SwXDocumentIndex::StyleAccess_Impl::~StyleAccess_Impl()
2486 OUString SAL_CALL
2487 SwXDocumentIndex::StyleAccess_Impl::getImplementationName()
2489 return u"SwXDocumentIndex::StyleAccess_Impl"_ustr;
2492 sal_Bool SAL_CALL
2493 SwXDocumentIndex::StyleAccess_Impl::supportsService(const OUString& rServiceName)
2495 return cppu::supportsService(this, rServiceName);
2498 uno::Sequence< OUString > SAL_CALL
2499 SwXDocumentIndex::StyleAccess_Impl::getSupportedServiceNames()
2501 return { u"com.sun.star.text.DocumentIndexParagraphStyles"_ustr };
2504 void SAL_CALL
2505 SwXDocumentIndex::StyleAccess_Impl::replaceByIndex(
2506 sal_Int32 nIndex, const uno::Any& rElement)
2508 SolarMutexGuard aGuard;
2510 if(nIndex < 0 || nIndex >= MAXLEVEL)
2512 throw lang::IndexOutOfBoundsException();
2515 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2517 uno::Sequence<OUString> aSeq;
2518 if(!(rElement >>= aSeq))
2520 throw lang::IllegalArgumentException();
2523 const sal_Int32 nStyles = aSeq.getLength();
2524 const OUString* pStyles = aSeq.getConstArray();
2525 OUStringBuffer sSetStyles;
2526 OUString aString;
2527 for(sal_Int32 i = 0; i < nStyles; i++)
2529 if(i)
2531 sSetStyles.append(TOX_STYLE_DELIMITER);
2533 SwStyleNameMapper::FillUIName(ProgName(pStyles[i]), aString,
2534 SwGetPoolIdFromName::TxtColl);
2535 sSetStyles.append(aString);
2537 rTOXBase.SetStyleNames(sSetStyles.makeStringAndClear(), o3tl::narrowing<sal_uInt16>(nIndex));
2540 sal_Int32 SAL_CALL
2541 SwXDocumentIndex::StyleAccess_Impl::getCount()
2543 return MAXLEVEL;
2546 uno::Any SAL_CALL
2547 SwXDocumentIndex::StyleAccess_Impl::getByIndex(sal_Int32 nIndex)
2549 SolarMutexGuard aGuard;
2551 if(nIndex < 0 || nIndex >= MAXLEVEL)
2553 throw lang::IndexOutOfBoundsException();
2556 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2558 const OUString& rStyles =
2559 rTOXBase.GetStyleNames(o3tl::narrowing<sal_uInt16>(nIndex));
2560 const sal_Int32 nStyles = comphelper::string::getTokenCount(rStyles, TOX_STYLE_DELIMITER);
2561 uno::Sequence<OUString> aStyles(nStyles);
2562 OUString* pStyles = aStyles.getArray();
2563 ProgName aString;
2564 sal_Int32 nPos = 0;
2565 for(sal_Int32 i = 0; i < nStyles; ++i)
2567 SwStyleNameMapper::FillProgName(
2568 rStyles.getToken(0, TOX_STYLE_DELIMITER, nPos),
2569 aString,
2570 SwGetPoolIdFromName::TxtColl);
2571 pStyles[i] = aString.toString();
2573 uno::Any aRet(&aStyles, cppu::UnoType<uno::Sequence<OUString>>::get());
2574 return aRet;
2577 uno::Type SAL_CALL
2578 SwXDocumentIndex::StyleAccess_Impl::getElementType()
2580 return cppu::UnoType<uno::Sequence<OUString>>::get();
2583 sal_Bool SAL_CALL
2584 SwXDocumentIndex::StyleAccess_Impl::hasElements()
2586 return true;
2589 SwXDocumentIndex::TokenAccess_Impl::TokenAccess_Impl(
2590 SwXDocumentIndex& rParentIdx)
2591 : m_xParent(&rParentIdx)
2595 SwXDocumentIndex::TokenAccess_Impl::~TokenAccess_Impl()
2599 OUString SAL_CALL
2600 SwXDocumentIndex::TokenAccess_Impl::getImplementationName()
2602 return u"SwXDocumentIndex::TokenAccess_Impl"_ustr;
2605 sal_Bool SAL_CALL SwXDocumentIndex::TokenAccess_Impl::supportsService(
2606 const OUString& rServiceName)
2608 return cppu::supportsService(this, rServiceName);
2611 uno::Sequence< OUString > SAL_CALL
2612 SwXDocumentIndex::TokenAccess_Impl::getSupportedServiceNames()
2614 return { u"com.sun.star.text.DocumentIndexLevelFormat"_ustr };
2617 namespace {
2619 struct TokenType_ {
2620 const char *pName;
2621 enum FormTokenType eTokenType;
2626 const struct TokenType_ g_TokenTypes[] =
2628 { "TokenEntryNumber", TOKEN_ENTRY_NO },
2629 { "TokenEntryText", TOKEN_ENTRY_TEXT },
2630 { "TokenTabStop", TOKEN_TAB_STOP },
2631 { "TokenText", TOKEN_TEXT },
2632 { "TokenPageNumber", TOKEN_PAGE_NUMS },
2633 { "TokenChapterInfo", TOKEN_CHAPTER_INFO },
2634 { "TokenHyperlinkStart", TOKEN_LINK_START },
2635 { "TokenHyperlinkEnd", TOKEN_LINK_END },
2636 { "TokenBibliographyDataField", TOKEN_AUTHORITY },
2637 { nullptr, static_cast<enum FormTokenType>(0) }
2640 void SAL_CALL
2641 SwXDocumentIndex::TokenAccess_Impl::replaceByIndex(
2642 sal_Int32 nIndex, const uno::Any& rElement)
2644 SolarMutexGuard aGuard;
2646 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2648 if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
2650 throw lang::IndexOutOfBoundsException();
2653 uno::Sequence<beans::PropertyValues> aSeq;
2654 if(!(rElement >>= aSeq))
2656 throw lang::IllegalArgumentException();
2659 OUStringBuffer sPattern;
2660 for (const beans::PropertyValues& rToken : aSeq)
2662 const beans::PropertyValue* pProperties = rToken.getConstArray();
2663 const sal_Int32 nProperties = rToken.getLength();
2664 //create an invalid token
2665 SwFormToken aToken(TOKEN_END);
2666 for(sal_Int32 j = 0; j < nProperties; j++)
2668 if ( pProperties[j].Name == "TokenType" )
2670 const OUString sTokenType =
2671 lcl_AnyToType<OUString>(pProperties[j].Value);
2672 for (TokenType_ const* pTokenType = g_TokenTypes;
2673 pTokenType->pName; ++pTokenType)
2675 if (sTokenType.equalsAscii(pTokenType->pName))
2677 aToken.eTokenType = pTokenType->eTokenType;
2678 break;
2682 else if ( pProperties[j].Name == "CharacterStyleName" )
2684 OUString sCharStyleName;
2685 SwStyleNameMapper::FillUIName(
2686 ProgName(lcl_AnyToType<OUString>(pProperties[j].Value)),
2687 sCharStyleName,
2688 SwGetPoolIdFromName::ChrFmt);
2689 aToken.sCharStyleName = sCharStyleName;
2690 aToken.nPoolId = SwStyleNameMapper::GetPoolIdFromUIName (
2691 sCharStyleName, SwGetPoolIdFromName::ChrFmt );
2693 else if ( pProperties[j].Name == "TabStopRightAligned" )
2695 const bool bRight = lcl_AnyToType<bool>(pProperties[j].Value);
2696 aToken.eTabAlign = bRight ?
2697 SvxTabAdjust::End : SvxTabAdjust::Left;
2699 else if ( pProperties[j].Name == "TabStopPosition" )
2701 sal_Int32 nPosition = 0;
2702 if (!(pProperties[j].Value >>= nPosition))
2704 throw lang::IllegalArgumentException();
2706 nPosition = o3tl::toTwips(nPosition, o3tl::Length::mm100);
2707 if(nPosition < 0)
2709 throw lang::IllegalArgumentException();
2711 aToken.nTabStopPosition = nPosition;
2713 else if ( pProperties[j].Name == "TabStopFillCharacter" )
2715 const OUString sFillChar =
2716 lcl_AnyToType<OUString>(pProperties[j].Value);
2717 if (sFillChar.getLength() > 1)
2719 throw lang::IllegalArgumentException();
2721 aToken.cTabFillChar =
2722 sFillChar.isEmpty() ? ' ' : sFillChar[0];
2724 else if ( pProperties[j].Name == "Text" )
2726 aToken.sText = lcl_AnyToType<OUString>(pProperties[j].Value);
2728 else if ( pProperties[j].Name == "ChapterFormat" )
2730 sal_Int16 nFormat = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
2731 switch(nFormat)
2733 case text::ChapterFormat::NUMBER:
2734 nFormat = CF_NUMBER;
2735 break;
2736 case text::ChapterFormat::NAME:
2737 nFormat = CF_TITLE;
2738 break;
2739 case text::ChapterFormat::NAME_NUMBER:
2740 nFormat = CF_NUM_TITLE;
2741 break;
2742 case text::ChapterFormat::NO_PREFIX_SUFFIX:
2743 nFormat = CF_NUMBER_NOPREPST;
2744 break;
2745 case text::ChapterFormat::DIGIT:
2746 nFormat = CF_NUM_NOPREPST_TITLE;
2747 break;
2748 default:
2749 throw lang::IllegalArgumentException();
2751 aToken.nChapterFormat = nFormat;
2753 // #i53420#
2754 else if ( pProperties[j].Name == "ChapterLevel" )
2756 const sal_Int16 nLevel = lcl_AnyToType<sal_Int16>(pProperties[j].Value);
2757 if( nLevel < 1 || nLevel > MAXLEVEL )
2759 throw lang::IllegalArgumentException();
2761 aToken.nOutlineLevel = nLevel;
2763 else if ( pProperties[j].Name == "BibliographyDataField" )
2765 sal_Int16 nType = 0;
2766 pProperties[j].Value >>= nType;
2767 if(nType < 0 || nType > text::BibliographyDataField::LOCAL_URL)
2769 throw lang::IllegalArgumentException(u"BibliographyDataField - wrong value"_ustr, nullptr, j);
2771 aToken.nAuthorityField = nType;
2773 // #i21237#
2774 else if ( pProperties[j].Name == "WithTab" )
2776 aToken.bWithTab = lcl_AnyToType<bool>(pProperties[j].Value);
2780 //exception if wrong TokenType
2781 if(TOKEN_END <= aToken.eTokenType )
2783 throw lang::IllegalArgumentException();
2785 // set TokenType from TOKEN_ENTRY_TEXT to TOKEN_ENTRY if it is
2786 // not a content index
2787 if(TOKEN_ENTRY_TEXT == aToken.eTokenType &&
2788 (TOX_CONTENT != rTOXBase.GetType()))
2790 aToken.eTokenType = TOKEN_ENTRY;
2792 // #i53420#
2793 // check for chapter format allowed values if it was TOKEN_ENTRY_NO type
2794 // only allowed value are CF_NUMBER and CF_NUM_NOPREPST_TITLE
2795 // reading from file
2796 if( TOKEN_ENTRY_NO == aToken.eTokenType )
2798 switch(aToken.nChapterFormat)
2800 case CF_NUMBER:
2801 case CF_NUM_NOPREPST_TITLE:
2802 break;
2803 default:
2804 throw lang::IllegalArgumentException();
2808 if (rTOXBase.GetType() == TOX_CONTENT)
2810 if (aToken.eTokenType == TOKEN_LINK_START && aToken.sCharStyleName.isEmpty())
2812 aToken.sCharStyleName = SwResId(STR_POOLCHR_TOXJUMP);
2816 sPattern.append(aToken.GetString());
2818 SwForm aForm(rTOXBase.GetTOXForm());
2819 aForm.SetPattern(o3tl::narrowing<sal_uInt16>(nIndex), sPattern.makeStringAndClear());
2820 rTOXBase.SetTOXForm(aForm);
2823 sal_Int32 SAL_CALL
2824 SwXDocumentIndex::TokenAccess_Impl::getCount()
2826 SolarMutexGuard aGuard;
2828 const sal_Int32 nRet = m_xParent->m_pImpl->GetFormMax();
2829 return nRet;
2832 uno::Any SAL_CALL
2833 SwXDocumentIndex::TokenAccess_Impl::getByIndex(sal_Int32 nIndex)
2835 SolarMutexGuard aGuard;
2837 SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
2839 if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
2841 throw lang::IndexOutOfBoundsException();
2844 // #i21237#
2845 SwFormTokens aPattern = rTOXBase.GetTOXForm().
2846 GetPattern(o3tl::narrowing<sal_uInt16>(nIndex));
2848 sal_Int32 nTokenCount = 0;
2849 uno::Sequence< beans::PropertyValues > aRetSeq;
2850 ProgName aProgCharStyle;
2851 for(const SwFormToken& aToken : aPattern) // #i21237#
2853 nTokenCount++;
2854 aRetSeq.realloc(nTokenCount);
2855 beans::PropertyValues* pTokenProps = aRetSeq.getArray();
2857 uno::Sequence< beans::PropertyValue >& rCurTokenSeq =
2858 pTokenProps[nTokenCount-1];
2859 SwStyleNameMapper::FillProgName(
2860 aToken.sCharStyleName,
2861 aProgCharStyle,
2862 SwGetPoolIdFromName::ChrFmt);
2863 switch(aToken.eTokenType)
2865 case TOKEN_ENTRY_NO:
2867 // #i53420#
2868 // writing to file (from doc to properties)
2869 sal_Int32 nElements = 2;
2870 sal_Int32 nCurrentElement = 0;
2872 // check for default value
2873 if (aToken.nChapterFormat != CF_NUMBER)
2875 nElements++;//we need the element
2877 if( aToken.nOutlineLevel != MAXLEVEL )
2879 nElements++;
2882 rCurTokenSeq.realloc( nElements );
2884 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2886 pArr[nCurrentElement].Name = "TokenType";
2887 pArr[nCurrentElement++].Value <<=
2888 u"TokenEntryNumber"_ustr;
2890 pArr[nCurrentElement].Name = "CharacterStyleName";
2891 pArr[nCurrentElement++].Value <<= aProgCharStyle.toString();
2892 if( aToken.nChapterFormat != CF_NUMBER )
2894 pArr[nCurrentElement].Name = "ChapterFormat";
2895 sal_Int16 nVal;
2896 // the allowed values for chapter format, when used as entry number,
2897 // are CF_NUMBER and CF_NUM_NOPREPST_TITLE only, all else forced to
2898 //CF_NUMBER
2899 switch(aToken.nChapterFormat)
2901 default:
2902 case CF_NUMBER:
2903 nVal = text::ChapterFormat::NUMBER;
2904 break;
2905 case CF_NUM_NOPREPST_TITLE:
2906 nVal = text::ChapterFormat::DIGIT;
2907 break;
2909 pArr[nCurrentElement++].Value <<= nVal;
2912 // only a ChapterLevel != MAXLEVEL is registered
2913 if (aToken.nOutlineLevel != MAXLEVEL)
2915 pArr[nCurrentElement].Name = "ChapterLevel";
2916 pArr[nCurrentElement].Value <<= aToken.nOutlineLevel;
2919 break;
2920 case TOKEN_ENTRY: // no difference between Entry and Entry Text
2921 case TOKEN_ENTRY_TEXT:
2923 rCurTokenSeq.realloc( 2 );
2924 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2926 pArr[0].Name = "TokenType";
2927 pArr[0].Value <<= u"TokenEntryText"_ustr;
2929 pArr[1].Name = "CharacterStyleName";
2930 pArr[1].Value <<= aProgCharStyle.toString();
2932 break;
2933 case TOKEN_TAB_STOP:
2935 rCurTokenSeq.realloc(5); // #i21237#
2936 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2938 pArr[0].Name = "TokenType";
2939 pArr[0].Value <<= u"TokenTabStop"_ustr;
2941 if(SvxTabAdjust::End == aToken.eTabAlign)
2943 pArr[1].Name = "TabStopRightAligned";
2944 pArr[1].Value <<= true;
2946 else
2948 pArr[1].Name = "TabStopPosition";
2949 sal_Int32 nPos = convertTwipToMm100(aToken.nTabStopPosition);
2950 if(nPos < 0)
2951 nPos = 0;
2952 pArr[1].Value <<= nPos;
2954 pArr[2].Name = "TabStopFillCharacter";
2955 pArr[2].Value <<= OUString(aToken.cTabFillChar);
2956 pArr[3].Name = "CharacterStyleName";
2957 pArr[3].Value <<= aProgCharStyle.toString();
2958 // #i21237#
2959 pArr[4].Name = "WithTab";
2960 pArr[4].Value <<= aToken.bWithTab;
2962 break;
2963 case TOKEN_TEXT:
2965 rCurTokenSeq.realloc( 3 );
2966 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2968 pArr[0].Name = "TokenType";
2969 pArr[0].Value <<= u"TokenText"_ustr;
2971 pArr[1].Name = "CharacterStyleName";
2972 pArr[1].Value <<= aProgCharStyle.toString();
2974 pArr[2].Name = "Text";
2975 pArr[2].Value <<= aToken.sText;
2977 break;
2978 case TOKEN_PAGE_NUMS:
2980 rCurTokenSeq.realloc( 2 );
2981 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2983 pArr[0].Name = "TokenType";
2984 pArr[0].Value <<= u"TokenPageNumber"_ustr;
2986 pArr[1].Name = "CharacterStyleName";
2987 pArr[1].Value <<= aProgCharStyle.toString();
2989 break;
2990 case TOKEN_CHAPTER_INFO:
2992 rCurTokenSeq.realloc( 4 );
2993 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
2995 pArr[0].Name = "TokenType";
2996 pArr[0].Value <<= u"TokenChapterInfo"_ustr;
2998 pArr[1].Name = "CharacterStyleName";
2999 pArr[1].Value <<= aProgCharStyle.toString();
3001 pArr[2].Name = "ChapterFormat";
3002 sal_Int16 nVal = text::ChapterFormat::NUMBER;
3003 switch(aToken.nChapterFormat)
3005 case CF_NUMBER:
3006 nVal = text::ChapterFormat::NUMBER;
3007 break;
3008 case CF_TITLE:
3009 nVal = text::ChapterFormat::NAME;
3010 break;
3011 case CF_NUM_TITLE:
3012 nVal = text::ChapterFormat::NAME_NUMBER;
3013 break;
3014 case CF_NUMBER_NOPREPST:
3015 nVal = text::ChapterFormat::NO_PREFIX_SUFFIX;
3016 break;
3017 case CF_NUM_NOPREPST_TITLE:
3018 nVal = text::ChapterFormat::DIGIT;
3019 break;
3021 pArr[2].Value <<= nVal;
3022 // #i53420#
3023 pArr[3].Name = "ChapterLevel";
3024 pArr[3].Value <<= aToken.nOutlineLevel;
3026 break;
3027 case TOKEN_LINK_START:
3029 rCurTokenSeq.realloc( 2 );
3030 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3032 pArr[0].Name = "TokenType";
3033 pArr[0].Value <<=
3034 u"TokenHyperlinkStart"_ustr;
3035 pArr[1].Name = "CharacterStyleName";
3036 pArr[1].Value <<= aProgCharStyle.toString();
3038 break;
3039 case TOKEN_LINK_END:
3041 rCurTokenSeq.realloc( 1 );
3042 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3044 pArr[0].Name = "TokenType";
3045 pArr[0].Value <<=
3046 u"TokenHyperlinkEnd"_ustr;
3048 break;
3049 case TOKEN_AUTHORITY:
3051 rCurTokenSeq.realloc( 3 );
3052 beans::PropertyValue* pArr = rCurTokenSeq.getArray();
3054 pArr[0].Name = "TokenType";
3055 pArr[0].Value <<=
3056 u"TokenBibliographyDataField"_ustr;
3058 pArr[1].Name = "CharacterStyleName";
3059 pArr[1].Value <<= aProgCharStyle.toString();
3061 pArr[2].Name = "BibliographyDataField";
3062 pArr[2].Value <<= sal_Int16(aToken.nAuthorityField);
3064 break;
3066 default:
3071 uno::Any aRet;
3072 aRet <<= aRetSeq;
3073 return aRet;
3076 uno::Type SAL_CALL
3077 SwXDocumentIndex::TokenAccess_Impl::getElementType()
3079 return cppu::UnoType<uno::Sequence< beans::PropertyValues >>::get();
3082 sal_Bool SAL_CALL
3083 SwXDocumentIndex::TokenAccess_Impl::hasElements()
3085 return true;
3088 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */