1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <sal/config.h>
27 #include <svl/svldllapi.h>
28 #include <svl/poolitem.hxx>
29 #include <svl/typedwhich.hxx>
30 #include <svl/whichranges.hxx>
35 SVL_DLLPUBLIC
size_t getAllocatedSfxItemSetCount();
36 SVL_DLLPUBLIC
size_t getUsedSfxItemSetCount();
37 SVL_DLLPUBLIC
size_t getAllocatedSfxPoolItemHolderCount();
38 SVL_DLLPUBLIC
size_t getUsedSfxPoolItemHolderCount();
41 // ItemSet/ItemPool helpers
42 SfxPoolItem
const* implCreateItemEntry(SfxItemPool
& rPool
, SfxPoolItem
const* pSource
, sal_uInt16 nWhich
, bool bPassingOwnership
);
43 void implCleanupItemEntry(SfxItemPool
& rPool
, SfxPoolItem
const* pSource
);
45 class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxPoolItemHolder
48 const SfxPoolItem
* m_pItem
;
54 SfxPoolItemHolder(SfxItemPool
&, const SfxPoolItem
*, bool bPassingOwnership
= false);
55 SfxPoolItemHolder(const SfxPoolItemHolder
&);
59 bool isDeleted() const { return m_bDeleted
; }
62 const SfxPoolItemHolder
& operator=(const SfxPoolItemHolder
&);
63 bool operator==(const SfxPoolItemHolder
&) const;
64 SfxItemPool
& getPool() const { assert(!isDeleted() && "Destructed instance used (!)"); return *m_pPool
; }
65 const SfxPoolItem
* getItem() const { assert(!isDeleted() && "Destructed instance used (!)"); return m_pItem
; }
66 sal_uInt16
Which() const { if(nullptr != m_pItem
) return m_pItem
->Which(); return 0; }
69 class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
71 friend class SfxItemIter
;
72 friend class SfxWhichIter
;
74 // allow ItemSetTooling to access
75 friend SfxPoolItem
const* implCreateItemEntry(SfxItemPool
&, SfxPoolItem
const*, sal_uInt16
, bool);
76 friend void implCleanupItemEntry(SfxItemPool
&, SfxPoolItem
const*);
78 SfxItemPool
* m_pPool
; ///< pool that stores the items
79 const SfxItemSet
* m_pParent
; ///< derivation
80 sal_uInt16 m_nCount
; ///< number of items
81 sal_uInt16 m_nTotalCount
; ///< number of WhichIDs, also size of m_ppItems array
83 // bitfield (better packaging if a bool needs to be added)
84 bool m_bItemsFixed
: 1; ///< true if this is a SfxItemSetFixed object, so does not *own* m_ppItems
86 SfxPoolItem
const** m_ppItems
; ///< pointer to array of items, we allocate and free this unless m_bItemsFixed==true
87 WhichRangesContainer m_pWhichRanges
; ///< array of Which Ranges
89 // Notification-Callback mechanism for SwAttrSet in SW, functionPtr for callback
90 std::function
<void(const SfxPoolItem
*, const SfxPoolItem
*)> m_aCallback
;
93 // Notification-Callback mechanism for SwAttrSet in SW
94 void setCallback(const std::function
<void(const SfxPoolItem
*, const SfxPoolItem
*)> &func
) { m_aCallback
= func
; }
95 void clearCallback() { m_aCallback
= nullptr; }
97 // container library interface support
98 // only for internal use (for now), thus protected
99 using const_iterator
= SfxPoolItem
const**;
101 const_iterator
begin() const noexcept
{ return m_ppItems
; }
102 const_iterator
end() const noexcept
{ return begin() + m_nTotalCount
; }
104 bool empty() const noexcept
{ return 0 == m_nTotalCount
; }
105 sal_Int32
size() const noexcept
{ return m_nTotalCount
; }
106 SfxPoolItem
const* operator[](sal_Int32 idx
) const noexcept
108 assert(idx
>= 0 && idx
< m_nTotalCount
&& "index out of range");
109 return m_ppItems
[idx
];
112 friend class SfxAllItemSet
;
115 SVL_DLLPRIVATE
void RecreateRanges_Impl(const WhichRangesContainer
& pNewRanges
);
118 SfxPoolItem
const** GetItems_Impl() const { return m_ppItems
; }
121 const SfxItemSet
& operator=(const SfxItemSet
&) = delete;
124 virtual const SfxPoolItem
* PutImpl( const SfxPoolItem
&, sal_uInt16 nWhich
, bool bPassingOwnership
);
126 /** special constructor for SfxAllItemSet */
127 enum class SfxAllItemSetFlag
{ Flag
};
128 SfxItemSet( SfxItemPool
&, SfxAllItemSetFlag
);
129 /** special constructor for SfxItemSetFixed */
130 SfxItemSet( SfxItemPool
&, WhichRangesContainer
&& ranges
, SfxPoolItem
const ** ppItems
, sal_uInt16 nTotalCount
);
133 SfxItemSet( const SfxItemSet
& );
134 SfxItemSet( SfxItemSet
&& ) noexcept
;
135 SfxItemSet( SfxItemPool
& );
136 SfxItemSet( SfxItemPool
&, WhichRangesContainer ranges
);
138 SfxItemSet( SfxItemPool
& rPool
, sal_uInt16 nWhichStart
, sal_uInt16 nWhichEnd
)
139 : SfxItemSet(rPool
, WhichRangesContainer(nWhichStart
, nWhichEnd
)) {}
141 template<sal_uInt16
... WIDs
>
142 SfxItemSet(SfxItemPool
& pool
, svl::Items_t
<WIDs
...> wids
)
143 : SfxItemSet(pool
, WhichRangesContainer(wids
)) {}
145 virtual ~SfxItemSet();
147 virtual std::unique_ptr
<SfxItemSet
> Clone(bool bItems
= true, SfxItemPool
*pToPool
= nullptr) const;
148 /** note that this only works if you know for sure that you are dealing with an SfxItemSet
149 and not one of it's subclasses. */
150 SfxItemSet
CloneAsValue(bool bItems
= true, SfxItemPool
*pToPool
= nullptr) const;
152 // Get number of items
153 sal_uInt16
Count() const { return m_nCount
; }
154 sal_uInt16
TotalCount() const { return m_nTotalCount
; }
156 const SfxPoolItem
& Get( sal_uInt16 nWhich
, bool bSrchInParent
= true ) const;
158 const T
& Get( TypedWhichId
<T
> nWhich
, bool bSrchInParent
= true ) const
160 return static_cast<const T
&>(Get(sal_uInt16(nWhich
), bSrchInParent
));
163 /** This method eases accessing single Items in the SfxItemSet.
165 @param nId SlotId or the Item's WhichId
166 @param bSearchInParent also search in parent ItemSets
167 @returns 0 if the ItemSet does not contain an Item with the Id 'nWhich'
169 const SfxPoolItem
* GetItem(sal_uInt16 nWhich
, bool bSearchInParent
= true) const;
171 /// Templatized version of GetItem() to directly return the correct type.
172 template<class T
> const T
* GetItem(sal_uInt16 nWhich
, bool bSearchInParent
= true) const
174 const SfxPoolItem
* pItem
= GetItem(nWhich
, bSearchInParent
);
175 const T
* pCastedItem
= dynamic_cast<const T
*>(pItem
);
177 assert(!pItem
|| pCastedItem
); // if it exists, must have the correct type
180 template<class T
> const T
* GetItem( TypedWhichId
<T
> nWhich
, bool bSearchInParent
= true ) const
182 return GetItem
<T
>(sal_uInt16(nWhich
), bSearchInParent
);
186 /// Templatized static version of GetItem() to directly return the correct type if the SfxItemSet is available.
187 template<class T
> static const T
* GetItem(const SfxItemSet
* pItemSet
, sal_uInt16 nWhich
, bool bSearchInParent
)
190 return pItemSet
->GetItem
<T
>(nWhich
, bSearchInParent
);
195 static const T
* GetItem(const SfxItemSet
* pItemSet
, TypedWhichId
<T
> nWhich
,
196 bool bSearchInParent
)
198 return GetItem
<T
>(pItemSet
, static_cast<sal_uInt16
>(nWhich
), bSearchInParent
);
201 sal_uInt16
GetWhichByOffset(sal_uInt16 nOffset
) const;
203 SfxItemState
GetItemState(sal_uInt16 nWhich
, bool bSrchInParent
= true, const SfxPoolItem
**ppItem
= nullptr) const
205 // use local helper, start value for looped-through SfxItemState value is SfxItemState::UNKNOWN
206 return GetItemState_ForWhichID(SfxItemState::UNKNOWN
, nWhich
, bSrchInParent
, ppItem
);
209 template <class T
> SfxItemState
GetItemState(TypedWhichId
<T
> nWhich
, bool bSrchInParent
= true, const T
**ppItem
= nullptr ) const
211 // use local helper, start value for looped-through SfxItemState value is SfxItemState::UNKNOWN
212 return GetItemState_ForWhichID(SfxItemState::UNKNOWN
, sal_uInt16(nWhich
), bSrchInParent
, reinterpret_cast<SfxPoolItem
const**>(ppItem
));
215 /// Templatized version of GetItemState() to directly return the correct type.
217 const T
* GetItemIfSet( TypedWhichId
<T
> nWhich
,
218 bool bSrchInParent
= true ) const
220 const SfxPoolItem
* pItem
= nullptr;
221 if (SfxItemState::SET
== GetItemState_ForWhichID(SfxItemState::UNKNOWN
, sal_uInt16(nWhich
), bSrchInParent
, &pItem
))
222 return static_cast<const T
*>(pItem
);
226 bool HasItem(sal_uInt16 nWhich
, const SfxPoolItem
** ppItem
= nullptr) const;
228 bool HasItem(TypedWhichId
<T
> nWhich
, const T
** ppItem
= nullptr) const
229 { return HasItem(sal_uInt16(nWhich
), reinterpret_cast<const SfxPoolItem
**>(ppItem
)); }
231 void DisableItem(sal_uInt16 nWhich
);
232 void InvalidateItem(sal_uInt16 nWhich
)
233 { InvalidateItem_ForWhichID(nWhich
); }
234 sal_uInt16
ClearItem( sal_uInt16 nWhich
= 0);
235 void ClearInvalidItems();
236 void InvalidateAllItems(); // HACK(via nWhich = 0) ???
238 inline void SetParent( const SfxItemSet
* pNew
);
240 // add, delete items, work on items
242 const SfxPoolItem
* Put( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
)
243 { return PutImpl(rItem
, nWhich
, /*bPassingOwnership*/false); }
244 const SfxPoolItem
* Put( std::unique_ptr
<SfxPoolItem
> xItem
, sal_uInt16 nWhich
)
245 { return PutImpl(*xItem
.release(), nWhich
, /*bPassingOwnership*/true); }
246 const SfxPoolItem
* Put( const SfxPoolItem
& rItem
)
247 { return Put(rItem
, rItem
.Which()); }
248 const SfxPoolItem
* Put( std::unique_ptr
<SfxPoolItem
> xItem
)
249 { auto nWhich
= xItem
->Which(); return Put(std::move(xItem
), nWhich
); }
250 bool Put( const SfxItemSet
&,
251 bool bInvalidAsDefault
= true );
252 void PutExtended( const SfxItemSet
&,
253 SfxItemState eDontCareAs
,
254 SfxItemState eDefaultAs
);
256 bool Set( const SfxItemSet
&, bool bDeep
= true );
258 void Intersect( const SfxItemSet
& rSet
);
259 void MergeValues( const SfxItemSet
& rSet
);
260 void Differentiate( const SfxItemSet
& rSet
);
261 void MergeValue( const SfxPoolItem
& rItem
, bool bOverwriteDefaults
= false );
263 SfxItemPool
* GetPool() const { return m_pPool
; }
264 const WhichRangesContainer
& GetRanges() const { return m_pWhichRanges
; }
265 void SetRanges( const WhichRangesContainer
& );
266 void SetRanges( WhichRangesContainer
&& );
267 void MergeRange( sal_uInt16 nFrom
, sal_uInt16 nTo
);
268 const SfxItemSet
* GetParent() const { return m_pParent
; }
270 bool operator==(const SfxItemSet
&) const;
272 /** Compare possibly ignoring SfxItemPool pointer.
274 This can be used to compare the content of two SfxItemSet even if they
275 don't share the same pool. EditTextObject::Equals(...,false) uses this
276 which is needed in ScGlobal::EETextObjEqual() for
277 ScPageHFItem::operator==()
280 if <FALSE/> ignore SfxItemPool pointer,
281 if <TRUE/> compare also SfxItemPool pointer (identical to operator==())
283 bool Equals(const SfxItemSet
&, bool bComparePool
) const;
285 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
288 // split version(s) of ClearSingleItemImpl for input types WhichID and Offset
289 sal_uInt16
ClearSingleItem_ForWhichID( sal_uInt16 nWhich
);
290 sal_uInt16
ClearSingleItem_ForOffset( sal_uInt16 nOffset
);
292 // cleanup all Items, but do not reset/change m_ppItems array. That is
293 // responsibility of the caller & allows specific resets
294 sal_uInt16
ClearAllItemsImpl();
296 // Merge two given Item(entries)
297 void MergeItem_Impl(const SfxPoolItem
**ppFnd1
, const SfxPoolItem
*pFnd2
, bool bIgnoreDefaults
);
299 // split version(s) of InvalidateItem for input types WhichID and Offset
300 void InvalidateItem_ForWhichID(sal_uInt16 nWhich
);
301 void InvalidateItem_ForOffset(sal_uInt16 nOffset
);
303 // split version(s) of GetItemStateImpl for input types WhichID and Offset
304 SfxItemState
GetItemState_ForWhichID( SfxItemState eState
, sal_uInt16 nWhich
, bool bSrchInParent
, const SfxPoolItem
**ppItem
) const;
305 SfxItemState
GetItemState_ForOffset( sal_uInt16 nOffset
, const SfxPoolItem
**ppItem
) const;
308 inline void SfxItemSet::SetParent( const SfxItemSet
* pNew
)
313 class SVL_DLLPUBLIC SfxAllItemSet final
: public SfxItemSet
315 // Handles all Ranges. Ranges are automatically modified by putting items.
319 SfxAllItemSet( SfxItemPool
&rPool
);
320 SfxAllItemSet( const SfxItemSet
& );
321 SfxAllItemSet( const SfxAllItemSet
& );
323 virtual std::unique_ptr
<SfxItemSet
> Clone( bool bItems
= true, SfxItemPool
*pToPool
= nullptr ) const override
;
325 virtual const SfxPoolItem
* PutImpl( const SfxPoolItem
&, sal_uInt16 nWhich
, bool bPassingOwnership
) override
;
329 namespace svl::detail
332 * Determines the number of sal_uInt16s in a container of pairs of
333 * sal_uInt16s, each representing a range of sal_uInt16s, and total capacity of the ranges.
335 template <sal_uInt16 WID1
, sal_uInt16 WID2
, sal_uInt16
... Rest
>
336 static constexpr sal_uInt16
CountRanges1()
338 sal_uInt16 nCapacity
= rangeSize(WID1
, WID2
);
339 if constexpr (sizeof...(Rest
) > 0)
340 nCapacity
+= CountRanges1
<Rest
...>();
344 // Allocate the items array inside the object, to reduce allocation cost.
346 template<sal_uInt16
... WIDs
>
347 class SfxItemSetFixed
: public SfxItemSet
350 SfxItemSetFixed( SfxItemPool
& rPool
)
351 : SfxItemSet(rPool
, WhichRangesContainer(svl::Items_t
<WIDs
...>{}), m_aItems
, NITEMS
) {}
353 static constexpr sal_uInt16 NITEMS
= svl::detail::CountRanges1
<WIDs
...>();
354 const SfxPoolItem
* m_aItems
[NITEMS
] = {};
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */