summaryrefslogtreecommitdiffstats
path: root/svl/source/items
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /svl/source/items
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svl/source/items')
-rw-r--r--svl/source/items/IndexedStyleSheets.cxx244
-rw-r--r--svl/source/items/cenumitm.cxx148
-rw-r--r--svl/source/items/cintitem.cxx209
-rw-r--r--svl/source/items/custritm.cxx72
-rw-r--r--svl/source/items/flagitem.cxx67
-rw-r--r--svl/source/items/globalnameitem.cxx90
-rw-r--r--svl/source/items/grabbagitem.cxx70
-rw-r--r--svl/source/items/ilstitem.cxx88
-rw-r--r--svl/source/items/imageitm.cxx84
-rw-r--r--svl/source/items/int64item.cxx58
-rw-r--r--svl/source/items/intitem.cxx183
-rw-r--r--svl/source/items/itemiter.cxx84
-rw-r--r--svl/source/items/itempool.cxx1253
-rw-r--r--svl/source/items/itemprop.cxx356
-rw-r--r--svl/source/items/itemset.cxx2068
-rw-r--r--svl/source/items/lckbitem.cxx102
-rw-r--r--svl/source/items/legacyitem.cxx69
-rw-r--r--svl/source/items/macitem.cxx243
-rw-r--r--svl/source/items/poolitem.cxx703
-rw-r--r--svl/source/items/ptitem.cxx136
-rw-r--r--svl/source/items/rectitem.cxx132
-rw-r--r--svl/source/items/rngitem.cxx59
-rw-r--r--svl/source/items/sitem.cxx73
-rw-r--r--svl/source/items/slstitm.cxx166
-rw-r--r--svl/source/items/srchitem.cxx662
-rw-r--r--svl/source/items/stringio.cxx34
-rw-r--r--svl/source/items/stritem.cxx42
-rw-r--r--svl/source/items/style.cxx905
-rw-r--r--svl/source/items/stylepool.cxx468
-rw-r--r--svl/source/items/visitem.cxx71
-rw-r--r--svl/source/items/voiditem.cxx70
-rw-r--r--svl/source/items/whiter.cxx93
32 files changed, 9102 insertions, 0 deletions
diff --git a/svl/source/items/IndexedStyleSheets.cxx b/svl/source/items/IndexedStyleSheets.cxx
new file mode 100644
index 0000000000..57e2dddbf1
--- /dev/null
+++ b/svl/source/items/IndexedStyleSheets.cxx
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+#include <svl/IndexedStyleSheets.hxx>
+#include <svl/style.hxx>
+
+#include <stdexcept>
+#include <algorithm>
+#include <utility>
+
+
+namespace {
+const size_t NUMBER_OF_FAMILIES = 7;
+size_t family_to_index(SfxStyleFamily family)
+{
+ switch (family) {
+ case SfxStyleFamily::Char:
+ return 0;
+ case SfxStyleFamily::Para:
+ return 1;
+ case SfxStyleFamily::Frame:
+ return 2;
+ case SfxStyleFamily::Page:
+ return 3;
+ case SfxStyleFamily::Pseudo:
+ return 4;
+ case SfxStyleFamily::Table:
+ return 5;
+ case SfxStyleFamily::All:
+ return 6;
+ default: break;
+ }
+ assert(false); // only for compiler warning. all cases are handled in the switch
+ return 0;
+}
+}
+
+namespace svl {
+
+IndexedStyleSheets::IndexedStyleSheets()
+{
+ for (size_t i = 0; i < NUMBER_OF_FAMILIES; i++) {
+ mStyleSheetPositionsByFamily.emplace_back();
+ }
+;}
+
+void IndexedStyleSheets::Register(const SfxStyleSheetBase& style, sal_Int32 pos)
+{
+ mPositionsByName.insert(std::make_pair(style.GetName(), pos));
+ size_t position = family_to_index(style.GetFamily());
+ mStyleSheetPositionsByFamily.at(position).push_back(pos);
+ size_t positionForFamilyAll = family_to_index(SfxStyleFamily::All);
+ mStyleSheetPositionsByFamily.at(positionForFamilyAll).push_back(pos);
+}
+
+void
+IndexedStyleSheets::Reindex()
+{
+ mPositionsByName.clear();
+ mStyleSheetPositionsByFamily.clear();
+ for (size_t i = 0; i < NUMBER_OF_FAMILIES; i++) {
+ mStyleSheetPositionsByFamily.emplace_back();
+ }
+
+ sal_Int32 i = 0;
+ for (const auto& rxStyleSheet : mStyleSheets) {
+ SfxStyleSheetBase* p = rxStyleSheet.get();
+ Register(*p, i);
+ ++i;
+ }
+}
+
+sal_Int32 IndexedStyleSheets::GetNumberOfStyleSheets() const
+{
+ return mStyleSheets.size();
+}
+
+void
+IndexedStyleSheets::AddStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style)
+{
+ if (!HasStyleSheet(style)) {
+ mStyleSheets.push_back(style);
+ // since we just added an element to the vector, we can safely do -1 as it will always be >= 1
+ Register(*style, mStyleSheets.size()-1);
+ }
+}
+
+bool
+IndexedStyleSheets::RemoveStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style)
+{
+ std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(style->GetName());
+ for (MapType::const_iterator it = range.first; it != range.second; ++it)
+ {
+ sal_Int32 pos = it->second;
+ if (mStyleSheets.at(pos) == style)
+ {
+ mStyleSheets.erase(mStyleSheets.begin() + pos);
+ Reindex();
+ return true;
+ }
+ }
+ return false;
+}
+
+std::vector<sal_Int32> IndexedStyleSheets::FindPositionsByName(const OUString& name) const
+{
+ std::vector<sal_Int32> r;
+ std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(name);
+ for (MapType::const_iterator it = range.first; it != range.second; ++it) {
+ r.push_back(it->second);
+ }
+ return r;
+}
+
+std::vector<sal_Int32> IndexedStyleSheets::FindPositionsByNameAndPredicate(const OUString& name,
+ StyleSheetPredicate& predicate, SearchBehavior behavior) const
+{
+ std::vector<sal_Int32> r;
+ auto range = mPositionsByName.equal_range(name);
+ for (auto it = range.first; it != range.second; ++it) {
+ sal_Int32 pos = it->second;
+ SfxStyleSheetBase *ssheet = mStyleSheets.at(pos).get();
+ if (predicate.Check(*ssheet)) {
+ r.push_back(pos);
+ if (behavior == SearchBehavior::ReturnFirst) {
+ break;
+ }
+ }
+ }
+ return r;
+}
+
+
+sal_Int32
+IndexedStyleSheets::GetNumberOfStyleSheetsWithPredicate(StyleSheetPredicate& predicate) const
+{
+ return std::count_if(mStyleSheets.begin(), mStyleSheets.end(),
+ [&predicate](const rtl::Reference<SfxStyleSheetBase>& rxStyleSheet) {
+ const SfxStyleSheetBase *ssheet = rxStyleSheet.get();
+ return predicate.Check(*ssheet);
+ });
+}
+
+SfxStyleSheetBase*
+IndexedStyleSheets::GetNthStyleSheetThatMatchesPredicate(
+ sal_Int32 n,
+ StyleSheetPredicate& predicate,
+ sal_Int32 startAt)
+{
+ SfxStyleSheetBase* retval = nullptr;
+ sal_Int32 matching = 0;
+ for (VectorType::const_iterator it = mStyleSheets.begin()+startAt; it != mStyleSheets.end(); ++it) {
+ SfxStyleSheetBase *ssheet = it->get();
+ if (predicate.Check(*ssheet)) {
+ if (matching == n) {
+ retval = it->get();
+ break;
+ }
+ ++matching;
+ }
+ }
+ return retval;
+}
+
+sal_Int32 IndexedStyleSheets::FindStyleSheetPosition(const SfxStyleSheetBase& style) const
+{
+ VectorType::const_iterator it = std::find(mStyleSheets.begin(), mStyleSheets.end(), &style);
+ if (it == mStyleSheets.end()) {
+ throw std::runtime_error("IndexedStyleSheets::FindStylePosition Looked for style not in index");
+ }
+ return std::distance(mStyleSheets.begin(), it);
+}
+
+void
+IndexedStyleSheets::Clear(StyleSheetDisposer& disposer)
+{
+ for (const auto& rxStyleSheet : mStyleSheets) {
+ disposer.Dispose(rxStyleSheet);
+ }
+ mStyleSheets.clear();
+ mPositionsByName.clear();
+}
+
+IndexedStyleSheets::~IndexedStyleSheets()
+{
+}
+
+bool
+IndexedStyleSheets::HasStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style) const
+{
+ std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(style->GetName());
+ for (MapType::const_iterator it = range.first; it != range.second; ++it)
+ {
+ if (mStyleSheets.at(it->second) == style)
+ return true;
+ }
+ return false;
+}
+
+SfxStyleSheetBase*
+IndexedStyleSheets::GetStyleSheetByPosition(sal_Int32 pos)
+{
+ if( pos < static_cast<sal_Int32>(mStyleSheets.size()) )
+ return mStyleSheets.at(pos).get();
+ return nullptr;
+}
+
+void
+IndexedStyleSheets::ApplyToAllStyleSheets(StyleSheetCallback& callback) const
+{
+ for (const auto& rxStyleSheet : mStyleSheets) {
+ callback.DoIt(*rxStyleSheet);
+ }
+}
+
+std::vector<sal_Int32>
+IndexedStyleSheets::FindPositionsByPredicate(StyleSheetPredicate& predicate) const
+{
+ std::vector<sal_Int32> r;
+ for (VectorType::const_iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
+ if (predicate.Check(**it)) {
+ r.push_back(std::distance(mStyleSheets.begin(), it));
+ }
+ }
+ return r;
+}
+
+const std::vector<sal_Int32>&
+IndexedStyleSheets::GetStyleSheetPositionsByFamily(SfxStyleFamily e) const
+{
+ size_t position = family_to_index(e);
+ return mStyleSheetPositionsByFamily.at(position);
+}
+
+} /* namespace svl */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/cenumitm.cxx b/svl/source/items/cenumitm.cxx
new file mode 100644
index 0000000000..713e1608ef
--- /dev/null
+++ b/svl/source/items/cenumitm.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Any.hxx>
+#include <svl/cenumitm.hxx>
+#include <svl/eitem.hxx>
+
+#include <comphelper/extract.hxx>
+#include <libxml/xmlwriter.h>
+#include <sal/log.hxx>
+
+
+// virtual
+bool SfxEnumItemInterface::operator ==(const SfxPoolItem & rItem) const
+{
+ SAL_WARN_IF(!SfxPoolItem::operator ==(rItem), "svl.items", "unequal type, with ID/pos " << Which() );
+ return GetEnumValue()
+ == static_cast< const SfxEnumItemInterface * >(&rItem)->
+ GetEnumValue();
+}
+
+// virtual
+bool SfxEnumItemInterface::GetPresentation(SfxItemPresentation, MapUnit,
+ MapUnit, OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = OUString::number( GetEnumValue() );
+ return true;
+}
+
+// virtual
+bool SfxEnumItemInterface::QueryValue(css::uno::Any& rVal, sal_uInt8)
+ const
+{
+ rVal <<= sal_Int32(GetEnumValue());
+ return true;
+}
+
+// virtual
+bool SfxEnumItemInterface::PutValue(const css::uno::Any& rVal,
+ sal_uInt8)
+{
+ sal_Int32 nTheValue = 0;
+
+ if ( ::cppu::enum2int( nTheValue, rVal ) )
+ {
+ SetEnumValue(sal_uInt16(nTheValue));
+ return true;
+ }
+ SAL_WARN("svl.items", "SfxEnumItemInterface::PutValue(): Wrong type");
+ return false;
+}
+
+// virtual
+bool SfxEnumItemInterface::HasBoolValue() const
+{
+ return false;
+}
+
+// virtual
+bool SfxEnumItemInterface::GetBoolValue() const
+{
+ return false;
+}
+
+// virtual
+void SfxEnumItemInterface::SetBoolValue(bool)
+{}
+
+SfxPoolItem* SfxBoolItem::CreateDefault()
+{
+ return new SfxBoolItem();
+}
+
+// virtual
+bool SfxBoolItem::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_bValue == static_cast< SfxBoolItem const * >(&rItem)->m_bValue;
+}
+
+// virtual
+bool SfxBoolItem::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = GetValueTextByVal(m_bValue);
+ return true;
+}
+
+void SfxBoolItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxBoolItem"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(GetValueTextByVal(m_bValue).toUtf8().getStr()));
+ SfxPoolItem::dumpAsXml(pWriter);
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+// virtual
+bool SfxBoolItem::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ rVal <<= m_bValue;
+ return true;
+}
+
+// virtual
+bool SfxBoolItem::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ bool bTheValue = bool();
+ if (rVal >>= bTheValue)
+ {
+ m_bValue = bTheValue;
+ return true;
+ }
+ SAL_WARN("svl.items", "SfxBoolItem::PutValue(): Wrong type");
+ return false;
+}
+
+// virtual
+SfxBoolItem* SfxBoolItem::Clone(SfxItemPool *) const
+{
+ return new SfxBoolItem(*this);
+}
+
+// virtual
+OUString SfxBoolItem::GetValueTextByVal(bool bTheValue) const
+{
+ return bTheValue ? OUString("TRUE") : OUString("FALSE");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/cintitem.cxx b/svl/source/items/cintitem.cxx
new file mode 100644
index 0000000000..d9a77adc2a
--- /dev/null
+++ b/svl/source/items/cintitem.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Any.hxx>
+#include <svl/cintitem.hxx>
+#include <sal/log.hxx>
+
+
+// virtual
+bool CntByteItem::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue == static_cast< const CntByteItem * >(&rItem)->m_nValue;
+}
+
+// virtual
+bool CntByteItem::GetPresentation(SfxItemPresentation, MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = OUString::number( m_nValue );
+ return true;
+}
+
+// virtual
+bool CntByteItem::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ sal_Int8 nValue = m_nValue;
+ rVal <<= nValue;
+ return true;
+}
+
+// virtual
+bool CntByteItem::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ sal_Int8 nValue = sal_Int8();
+ if (rVal >>= nValue)
+ {
+ m_nValue = nValue;
+ return true;
+ }
+
+ SAL_WARN("svl.items", "CntByteItem::PutValue - Wrong type!");
+ return false;
+}
+
+// virtual
+CntByteItem* CntByteItem::Clone(SfxItemPool *) const
+{
+ return new CntByteItem(*this);
+}
+
+// virtual
+bool CntUInt16Item::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue == static_cast<const CntUInt16Item *>(&rItem)->m_nValue;
+}
+
+// virtual
+bool CntUInt16Item::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&)
+ const
+{
+ rText = OUString::number( m_nValue );
+ return true;
+}
+
+// virtual
+bool CntUInt16Item::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ sal_Int32 nValue = m_nValue;
+ rVal <<= nValue;
+ return true;
+}
+
+// virtual
+bool CntUInt16Item::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ sal_Int32 nValue = 0;
+ if (rVal >>= nValue)
+ {
+ SAL_WARN_IF(nValue < 0 || nValue > SAL_MAX_UINT16, "svl.items", "Overflow in UInt16 value!");
+ m_nValue = static_cast<sal_uInt16>(nValue);
+ return true;
+ }
+
+ SAL_WARN("svl.items", "CntUInt16Item::PutValue - Wrong type!");
+ return false;
+}
+
+// virtual
+CntUInt16Item* CntUInt16Item::Clone(SfxItemPool *) const
+{
+ return new CntUInt16Item(*this);
+}
+
+// virtual
+bool CntInt32Item::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue == static_cast<const CntInt32Item *>(&rItem)->m_nValue;
+}
+
+// virtual
+bool CntInt32Item::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = OUString::number( m_nValue );
+ return true;
+}
+
+// virtual
+bool CntInt32Item::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ sal_Int32 nValue = m_nValue;
+ rVal <<= nValue;
+ return true;
+}
+
+// virtual
+bool CntInt32Item::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ sal_Int32 nValue = 0;
+ if (rVal >>= nValue)
+ {
+ m_nValue = nValue;
+ return true;
+ }
+
+ SAL_WARN("svl.items", "CntInt32Item::PutValue - Wrong type!");
+ return false;
+}
+
+// virtual
+CntInt32Item* CntInt32Item::Clone(SfxItemPool *) const
+{
+ return new CntInt32Item(*this);
+}
+
+// virtual
+bool CntUInt32Item::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue == static_cast<const CntUInt32Item *>(&rItem)->m_nValue;
+}
+
+// virtual
+bool CntUInt32Item::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&)
+ const
+{
+ rText = OUString::number(m_nValue);
+ return true;
+}
+
+// virtual
+bool CntUInt32Item::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ sal_Int32 nValue = m_nValue;
+ SAL_WARN_IF(nValue < 0, "svl.items", "Overflow in UInt32 value!");
+ rVal <<= nValue;
+ return true;
+}
+
+// virtual
+bool CntUInt32Item::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ sal_Int32 nValue = 0;
+ if (rVal >>= nValue)
+ {
+ SAL_WARN_IF(nValue < 0, "svl.items", "Overflow in UInt32 value!");
+ m_nValue = nValue;
+ return true;
+ }
+
+ SAL_WARN("svl.items", "CntUInt32Item::PutValue - Wrong type!");
+ return false;
+}
+
+// virtual
+CntUInt32Item* CntUInt32Item::Clone(SfxItemPool *) const
+{
+ return new CntUInt32Item(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/custritm.cxx b/svl/source/items/custritm.cxx
new file mode 100644
index 0000000000..0d68b6d455
--- /dev/null
+++ b/svl/source/items/custritm.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Any.hxx>
+
+#include <osl/diagnose.h>
+#include <unotools/intlwrapper.hxx>
+#include <svl/custritm.hxx>
+
+
+// virtual
+bool CntUnencodedStringItem::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_aValue
+ == static_cast< const CntUnencodedStringItem * >(&rItem)->
+ m_aValue;
+}
+
+// virtual
+bool CntUnencodedStringItem::GetPresentation(SfxItemPresentation, MapUnit,
+ MapUnit, OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = m_aValue;
+ return true;
+}
+
+// virtual
+bool CntUnencodedStringItem::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ rVal <<= m_aValue;
+ return true;
+}
+
+// virtual
+bool CntUnencodedStringItem::PutValue(const css::uno::Any& rVal,
+ sal_uInt8)
+{
+ OUString aTheValue;
+ if (rVal >>= aTheValue)
+ {
+ m_aValue = aTheValue;
+ return true;
+ }
+ OSL_FAIL("CntUnencodedStringItem::PutValue(): Wrong type");
+ return false;
+}
+
+// virtual
+CntUnencodedStringItem* CntUnencodedStringItem::Clone(SfxItemPool *) const
+{
+ return new CntUnencodedStringItem(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/flagitem.cxx b/svl/source/items/flagitem.cxx
new file mode 100644
index 0000000000..270be1e575
--- /dev/null
+++ b/svl/source/items/flagitem.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <svl/flagitem.hxx>
+#include <svl/poolitem.hxx>
+#include <sal/log.hxx>
+
+
+SfxFlagItem::SfxFlagItem( sal_uInt16 nW, sal_uInt16 nV ) :
+ SfxPoolItem( nW ),
+ nVal(nV)
+{
+}
+
+bool SfxFlagItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+ rText.clear();
+ for ( sal_uInt8 nFlag = 0; nFlag < GetFlagCount(); ++nFlag )
+ rText += GetFlag(nFlag) ? std::u16string_view(u"true") : std::u16string_view(u"false");
+ return true;
+}
+
+sal_uInt8 SfxFlagItem::GetFlagCount() const
+{
+ SAL_INFO("svl", "calling GetValueText(sal_uInt16) on SfxFlagItem -- override!");
+ return 0;
+}
+
+bool SfxFlagItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return static_cast<const SfxFlagItem&>(rItem).nVal == nVal;
+}
+
+SfxFlagItem* SfxFlagItem::Clone(SfxItemPool *) const
+{
+ return new SfxFlagItem( *this );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/globalnameitem.cxx b/svl/source/items/globalnameitem.cxx
new file mode 100644
index 0000000000..3f8d3265d7
--- /dev/null
+++ b/svl/source/items/globalnameitem.cxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/script/Converter.hpp>
+
+#include <osl/diagnose.h>
+
+#include <comphelper/processfactory.hxx>
+
+#include <svl/globalnameitem.hxx>
+
+SfxPoolItem* SfxGlobalNameItem::CreateDefault() { return new SfxGlobalNameItem; }
+
+
+SfxGlobalNameItem::SfxGlobalNameItem()
+{
+}
+
+
+SfxGlobalNameItem::SfxGlobalNameItem( sal_uInt16 nW, const SvGlobalName& rName )
+: SfxPoolItem( nW ),
+ m_aName( rName )
+{
+}
+
+SfxGlobalNameItem::~SfxGlobalNameItem()
+{
+}
+
+bool SfxGlobalNameItem::operator==( const SfxPoolItem& rItem ) const
+{
+ return SfxPoolItem::operator==(rItem) &&
+ static_cast<const SfxGlobalNameItem&>(rItem).m_aName == m_aName;
+}
+
+SfxGlobalNameItem* SfxGlobalNameItem::Clone(SfxItemPool *) const
+{
+ return new SfxGlobalNameItem( *this );
+}
+
+// virtual
+bool SfxGlobalNameItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
+{
+ css::uno::Reference < css::script::XTypeConverter > xConverter
+ ( css::script::Converter::create( ::comphelper::getProcessComponentContext() ));
+ css::uno::Sequence< sal_Int8 > aSeq;
+ css::uno::Any aNew;
+
+ try { aNew = xConverter->convertTo( rVal, cppu::UnoType<css::uno::Sequence < sal_Int8 >>::get() ); }
+ catch (css::uno::Exception&) {}
+ aNew >>= aSeq;
+ if ( aSeq.getLength() == 16 )
+ {
+ m_aName.MakeFromMemory( aSeq.getConstArray() );
+ return true;
+ }
+
+ OSL_FAIL( "SfxGlobalNameItem::PutValue - Wrong type!" );
+ return true;
+}
+
+// virtual
+bool SfxGlobalNameItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
+{
+ css::uno::Sequence< sal_Int8 > aSeq( 16 );
+ void const * pData = &m_aName.GetCLSID();
+ memcpy( aSeq.getArray(), pData, 16 );
+ rVal <<= aSeq;
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/grabbagitem.cxx b/svl/source/items/grabbagitem.cxx
new file mode 100644
index 0000000000..39ee566866
--- /dev/null
+++ b/svl/source/items/grabbagitem.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <svl/grabbagitem.hxx>
+#include <sal/config.h>
+
+#include <sal/log.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using namespace com::sun::star;
+
+SfxGrabBagItem::SfxGrabBagItem() = default;
+
+SfxGrabBagItem::SfxGrabBagItem(sal_uInt16 nWhich)
+ : SfxPoolItem(nWhich)
+{
+}
+
+SfxGrabBagItem::~SfxGrabBagItem() = default;
+
+bool SfxGrabBagItem::operator==(const SfxPoolItem& rItem) const
+{
+ return SfxPoolItem::operator==(rItem)
+ && m_aMap == static_cast<const SfxGrabBagItem*>(&rItem)->m_aMap;
+}
+
+SfxGrabBagItem* SfxGrabBagItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new SfxGrabBagItem(*this);
+}
+
+bool SfxGrabBagItem::PutValue(const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ uno::Sequence<beans::PropertyValue> aValue;
+ if (rVal >>= aValue)
+ {
+ m_aMap.clear();
+ for (beans::PropertyValue const& aPropertyValue : std::as_const(aValue))
+ {
+ m_aMap[aPropertyValue.Name] = aPropertyValue.Value;
+ }
+ return true;
+ }
+
+ SAL_WARN("svl", "SfxGrabBagItem::PutValue: wrong type");
+ return false;
+}
+
+bool SfxGrabBagItem::QueryValue(uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ uno::Sequence<beans::PropertyValue> aValue(m_aMap.size());
+ beans::PropertyValue* pValue = aValue.getArray();
+ for (const auto& i : m_aMap)
+ {
+ pValue[0].Name = i.first;
+ pValue[0].Value = i.second;
+ ++pValue;
+ }
+ rVal <<= aValue;
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/ilstitem.cxx b/svl/source/items/ilstitem.cxx
new file mode 100644
index 0000000000..0cb9ea8e6c
--- /dev/null
+++ b/svl/source/items/ilstitem.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/script/Converter.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <svl/ilstitem.hxx>
+
+
+SfxPoolItem* SfxIntegerListItem::CreateDefault() { return new SfxIntegerListItem; }
+
+SfxIntegerListItem::SfxIntegerListItem()
+{
+}
+
+SfxIntegerListItem::SfxIntegerListItem( sal_uInt16 which, ::std::vector < sal_Int32 >&& rList )
+ : SfxPoolItem( which )
+ , m_aList( std::move(rList) )
+{
+}
+
+SfxIntegerListItem::SfxIntegerListItem( sal_uInt16 which, const css::uno::Sequence < sal_Int32 >& rList )
+ : SfxPoolItem( which )
+{
+ comphelper::sequenceToContainer(m_aList, rList);
+}
+
+SfxIntegerListItem::~SfxIntegerListItem()
+{
+}
+
+bool SfxIntegerListItem::operator==( const SfxPoolItem& rPoolItem ) const
+{
+ if ( !SfxPoolItem::operator==(rPoolItem) )
+ return false;
+
+ const SfxIntegerListItem & rItem = static_cast<const SfxIntegerListItem&>(rPoolItem);
+ return rItem.m_aList == m_aList;
+}
+
+SfxIntegerListItem* SfxIntegerListItem::Clone( SfxItemPool * ) const
+{
+ return new SfxIntegerListItem( *this );
+}
+
+bool SfxIntegerListItem::PutValue ( const css::uno::Any& rVal, sal_uInt8 )
+{
+ css::uno::Reference < css::script::XTypeConverter > xConverter
+ ( css::script::Converter::create(::comphelper::getProcessComponentContext()) );
+ css::uno::Any aNew;
+ try { aNew = xConverter->convertTo( rVal, cppu::UnoType<css::uno::Sequence < sal_Int32 >>::get() ); }
+ catch (css::uno::Exception&)
+ {
+ return true;
+ }
+
+ css::uno::Sequence<sal_Int32> aTempSeq;
+ bool bRet = aNew >>= aTempSeq;
+ if (bRet)
+ m_aList = comphelper::sequenceToContainer<std::vector<sal_Int32>>(aTempSeq);
+ return bRet;
+}
+
+bool SfxIntegerListItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
+{
+ rVal <<= comphelper::containerToSequence(m_aList);
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/imageitm.cxx b/svl/source/items/imageitm.cxx
new file mode 100644
index 0000000000..cba4b7103b
--- /dev/null
+++ b/svl/source/items/imageitm.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svl/imageitm.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+
+SfxPoolItem* SfxImageItem::CreateDefault() { return new SfxImageItem; }
+
+SfxImageItem::SfxImageItem( sal_uInt16 which )
+ : SfxInt16Item( which, 0 ), mnAngle(0), mbMirrored(false)
+{
+}
+
+SfxImageItem::SfxImageItem( const SfxImageItem& rItem )
+ : SfxInt16Item( rItem ),
+ mnAngle(rItem.mnAngle), mbMirrored(rItem.mbMirrored)
+{
+}
+
+SfxImageItem::~SfxImageItem()
+{
+}
+
+SfxImageItem* SfxImageItem::Clone( SfxItemPool* ) const
+{
+ return new SfxImageItem( *this );
+}
+
+bool SfxImageItem::operator==( const SfxPoolItem& rItem ) const
+{
+ if (!SfxInt16Item::operator==(rItem))
+ return false;
+ const SfxImageItem& rOther = static_cast<const SfxImageItem&>(rItem);
+ return mnAngle == rOther.mnAngle && mbMirrored == rOther.mbMirrored;
+}
+
+bool SfxImageItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
+{
+ css::uno::Sequence< css::uno::Any > aSeq{ css::uno::Any(GetValue()),
+ css::uno::Any(sal_Int16(mnAngle)),
+ css::uno::Any(mbMirrored),
+ css::uno::Any(maURL) };
+ rVal <<= aSeq;
+ return true;
+}
+
+bool SfxImageItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
+{
+ css::uno::Sequence< css::uno::Any > aSeq;
+ if (( rVal >>= aSeq ) && ( aSeq.getLength() == 4 ))
+ {
+ sal_Int16 nVal = sal_Int16();
+ if ( aSeq[0] >>= nVal )
+ SetValue( nVal );
+ sal_Int16 nTmp = 0;
+ aSeq[1] >>= nTmp;
+ mnAngle = Degree10(nTmp);
+ aSeq[2] >>= mbMirrored;
+ aSeq[3] >>= maURL;
+ return true;
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/int64item.cxx b/svl/source/items/int64item.cxx
new file mode 100644
index 0000000000..06efd1fc9a
--- /dev/null
+++ b/svl/source/items/int64item.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <svl/int64item.hxx>
+
+SfxInt64Item::SfxInt64Item( sal_uInt16 nWhich, sal_Int64 nVal ) :
+ SfxPoolItem(nWhich), mnValue(nVal)
+{
+}
+
+SfxInt64Item::~SfxInt64Item() {}
+
+bool SfxInt64Item::operator== ( const SfxPoolItem& rItem ) const
+{
+ return SfxPoolItem::operator==(rItem) && mnValue == static_cast<const SfxInt64Item&>(rItem).mnValue;
+}
+
+bool SfxInt64Item::GetPresentation(
+ SfxItemPresentation, MapUnit, MapUnit, OUString& rText,
+ const IntlWrapper& /*rIntlWrapper*/ ) const
+{
+ rText = OUString::number(mnValue);
+ return true;
+}
+
+bool SfxInt64Item::QueryValue(
+ css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
+{
+ rVal <<= mnValue;
+ return true;
+}
+
+bool SfxInt64Item::PutValue(
+ const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
+{
+ sal_Int64 nVal;
+
+ if (rVal >>= nVal)
+ {
+ mnValue = nVal;
+ return true;
+ }
+
+ return false;
+}
+
+SfxInt64Item* SfxInt64Item::Clone( SfxItemPool* /*pOther*/ ) const
+{
+ return new SfxInt64Item(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/intitem.cxx b/svl/source/items/intitem.cxx
new file mode 100644
index 0000000000..0ced3eb201
--- /dev/null
+++ b/svl/source/items/intitem.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svl/intitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <osl/diagnose.h>
+#include <tools/bigint.hxx>
+#include <svl/metitem.hxx>
+#include <libxml/xmlwriter.h>
+#include <boost/property_tree/ptree.hpp>
+
+
+
+
+SfxPoolItem* SfxByteItem::CreateDefault()
+{
+ return new SfxByteItem();
+};
+
+SfxPoolItem* SfxInt16Item::CreateDefault()
+{
+ return new SfxInt16Item();
+};
+
+// virtual
+bool SfxInt16Item::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue == static_cast< const SfxInt16Item * >(&rItem)->
+ m_nValue;
+}
+
+// virtual
+bool SfxInt16Item::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = OUString::number(m_nValue);
+ return true;
+}
+
+
+boost::property_tree::ptree SfxInt16Item::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+ aTree.put("state", GetValue());
+ return aTree;
+}
+
+
+// virtual
+bool SfxInt16Item::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ sal_Int16 nValue = m_nValue;
+ rVal <<= nValue;
+ return true;
+}
+
+// virtual
+bool SfxInt16Item::PutValue(const css::uno::Any& rVal, sal_uInt8 )
+{
+ sal_Int16 nValue = sal_Int16();
+ if (rVal >>= nValue)
+ {
+ m_nValue = nValue;
+ return true;
+ }
+
+ OSL_FAIL( "SfxInt16Item::PutValue - Wrong type!" );
+ return false;
+}
+
+SfxInt16Item* SfxInt16Item::Clone(SfxItemPool *) const
+{
+ return new SfxInt16Item(*this);
+}
+
+SfxPoolItem* SfxUInt16Item::CreateDefault()
+{
+ return new SfxUInt16Item();
+};
+
+void SfxUInt16Item::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxUInt16Item"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree SfxUInt16Item::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+ aTree.put("state", GetValue());
+ return aTree;
+}
+
+
+
+
+SfxPoolItem* SfxInt32Item::CreateDefault()
+{
+ return new SfxInt32Item();
+};
+
+void SfxInt32Item::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxInt32Item"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree SfxInt32Item::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+ aTree.put("state", GetValue());
+ return aTree;
+}
+
+
+
+
+SfxPoolItem* SfxUInt32Item::CreateDefault()
+{
+ return new SfxUInt32Item();
+};
+
+void SfxUInt32Item::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxUInt32Item"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree SfxUInt32Item::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+ aTree.put("state", GetValue());
+ return aTree;
+}
+
+SfxMetricItem::SfxMetricItem(sal_uInt16 which, sal_Int32 nValue):
+ SfxInt32Item(which, nValue)
+{
+}
+
+// virtual
+void SfxMetricItem::ScaleMetrics(tools::Long nMult, tools::Long nDiv)
+{
+ BigInt aTheValue(GetValue());
+ aTheValue *= nMult;
+ aTheValue += nDiv / 2;
+ aTheValue /= nDiv;
+ SetValue(aTheValue);
+}
+
+// virtual
+bool SfxMetricItem::HasMetrics() const
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/itemiter.cxx b/svl/source/items/itemiter.cxx
new file mode 100644
index 0000000000..d8864c387e
--- /dev/null
+++ b/svl/source/items/itemiter.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/itemiter.hxx>
+#include <svl/itemset.hxx>
+
+SfxItemIter::SfxItemIter(const SfxItemSet& rItemSet)
+ : m_rSet(rItemSet)
+{
+ if (!m_rSet.m_nCount)
+ {
+ m_nStart = 0;
+ m_nEnd = 0;
+ }
+ else
+ {
+ SfxPoolItem const** ppFnd = m_rSet.m_ppItems;
+
+ // Find the first Item that is set
+ for (m_nStart = 0; !*(ppFnd + m_nStart); ++m_nStart)
+ ; // empty loop
+ if (1 < m_rSet.Count())
+ for (m_nEnd = m_rSet.TotalCount(); !*(ppFnd + --m_nEnd);)
+ ; // empty loop
+ else
+ m_nEnd = m_nStart;
+ }
+
+ m_nCurrent = m_nStart;
+}
+
+// Precondition : m_nCurrent < m_nEnd
+const SfxPoolItem* SfxItemIter::ImplNextItem()
+{
+ SfxPoolItem const** ppFnd = m_rSet.m_ppItems;
+ do
+ {
+ m_nCurrent++;
+ } while (m_nCurrent < m_nEnd && !*(ppFnd + m_nCurrent));
+ return *(ppFnd + m_nCurrent);
+}
+
+SfxItemState SfxItemIter::GetItemState(bool bSrchInParent, const SfxPoolItem** ppItem) const
+{
+ // we have the offset, so use it to profit. It is always valid, so no need
+ // to check if smaller than TotalCount()
+ SfxItemState eState(m_rSet.GetItemState_ForOffset(m_nCurrent, ppItem));
+
+ // search in parent?
+ if (bSrchInParent && nullptr != m_rSet.GetParent()
+ && (SfxItemState::UNKNOWN == eState || SfxItemState::DEFAULT == eState))
+ {
+ // nOffset was only valid for *local* SfxItemSet, need to continue with WhichID
+ const sal_uInt16 nWhich(m_rSet.GetWhichByOffset(m_nCurrent));
+ eState = m_rSet.GetParent()->GetItemState_ForWhichID(eState, nWhich, true, ppItem);
+ }
+
+ return eState;
+}
+
+void SfxItemIter::ClearItem()
+{
+ // we have the offset, so use it to profit. It is always valid, so no need
+ // to check if smaller than TotalCount()
+ const_cast<SfxItemSet&>(m_rSet).ClearSingleItem_ForOffset(m_nCurrent);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx
new file mode 100644
index 0000000000..faedbd516a
--- /dev/null
+++ b/svl/source/items/itempool.cxx
@@ -0,0 +1,1253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/itempool.hxx>
+#include <svl/setitem.hxx>
+
+#include <string.h>
+#include <libxml/xmlwriter.h>
+
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <svl/SfxBroadcaster.hxx>
+#include <svl/hint.hxx>
+#include <svl/itemset.hxx>
+
+#include <poolio.hxx>
+
+#include <cassert>
+#include <vector>
+
+#ifdef DBG_UTIL
+static size_t nAllDirectlyPooledSfxPoolItemCount(0);
+static size_t nRemainingDirectlyPooledSfxPoolItemCount(0);
+size_t getAllDirectlyPooledSfxPoolItemCount() { return nAllDirectlyPooledSfxPoolItemCount; }
+size_t getRemainingDirectlyPooledSfxPoolItemCount() { return nRemainingDirectlyPooledSfxPoolItemCount; }
+#endif
+
+// WhichIDs that need to set _bNeedsPoolRegistration in SfxItemInfo
+// to true to allow a register of all items of that type/with that WhichID
+// to be accessible using SfxItemPool::GetItemSurrogates. Created by
+// grepping for 'GetItemSurrogates' usages & interpreting. Some
+// are double, more may be necessary. There is a SAL_INFO("svl.items", ...)
+// in SfxItemPool::GetItemSurrogates that will give hints on missing flags.
+//
+// due to SwTable::UpdateFields
+// due to SwCursorShell::GotoNxtPrvTableFormula
+// due to DocumentFieldsManager::UpdateTableFields
+// due to SwTable::GatherFormulas
+// RES_BOXATR_FORMULA ok
+// due to SwContentTree::EditEntry
+// due to SwDoc::FindINetAttr
+// due to SwUndoResetAttr::RedoImpl
+// due to SwContentTree::EditEntry
+// due to SwContentTree::BringEntryToAttention
+// RES_TXTATR_REFMARK ok
+// due to ImpEditEngine::WriteRTF
+// due to ScDocument::UpdateFontCharSet()
+// due to ScXMLFontAutoStylePool_Impl
+// due to SdXImpressDocument::getPropertyValue
+// due to Writer::AddFontItems_
+// EE_CHAR_FONTINFO ok
+// due to ImpEditEngine::WriteRTF
+// due to ScXMLFontAutoStylePool_Impl
+// due to SdXImpressDocument::getPropertyValue
+// due to Writer::AddFontItems_
+// EE_CHAR_FONTINFO_CJK ok
+// due to ImpEditEngine::WriteRTF
+// due to ScXMLFontAutoStylePool_Impl
+// due to SdXImpressDocument::getPropertyValue
+// due to Writer::AddFontItems_
+// EE_CHAR_FONTINFO_CTL ok
+// due to ImpEditEngine::WriteRTF
+// EE_CHAR_COLOR ok
+// due to ScDocumentPool::StyleDeleted
+// ATTR_PATTERN ok
+// due to ScDocument::UpdateFontCharSet()
+// due to ScXMLFontAutoStylePool_Impl
+// ATTR_FONT ok
+// due to OptimizeHasAttrib
+// ATTR_ROTATE_VALUE ok
+// due to ScDocument::GetDocColors()
+// ATTR_BACKGROUND ok
+// ATTR_FONT_COLOR ok
+// due to ScXMLExport::CollectUserDefinedNamespaces
+// ATTR_USERDEF ok
+// due to ScXMLExport::CollectUserDefinedNamespaces
+// due to SwXMLExport::exportDoc
+// EE_PARA_XMLATTRIBS ok
+// due to ScXMLExport::CollectUserDefinedNamespaces
+// due to SwXMLExport::exportDoc
+// EE_CHAR_XMLATTRIBS ok
+// due to ScXMLExport::CollectUserDefinedNamespaces
+// due to SwXMLExport::exportDoc
+// SDRATTR_XMLATTRIBUTES ok
+// due to ScXMLFontAutoStylePool_Impl
+// ATTR_CJK_FONT ok
+// ATTR_CTL_FONT ok
+// ATTR_PAGE_HEADERLEFT ok
+// ATTR_PAGE_FOOTERLEFT ok
+// ATTR_PAGE_HEADERRIGHT ok
+// ATTR_PAGE_FOOTERRIGHT ok
+// ATTR_PAGE_HEADERFIRST ok
+// ATTR_PAGE_FOOTERFIRST ok
+// due to ScCellShell::ExecuteEdit
+// due to ScTabViewShell::CreateRefDialogController
+// SCITEM_CONDFORMATDLGDATA ok
+// due to SdDrawDocument::UpdatePageRelativeURLs
+// EE_FEATURE_FIELD ok
+// due to SvxUnoMarkerTable::replaceByName
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// due to XLineStartItem::checkForUniqueItem
+// XATTR_LINESTART ok
+// due to SvxUnoMarkerTable::replaceByName
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// due to XLineStartItem::checkForUniqueItem
+// XATTR_LINEEND ok
+// due to SvxUnoNameItemTable
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// due to NameOrIndex::CheckNamedItem all derived from NameOrIndex
+// XATTR_FILLBITMAP ok
+// due to SvxUnoNameItemTable
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// XATTR_LINEDASH ok
+// due to SvxUnoNameItemTable
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// due to NameOrIndex::CheckNamedItem all derived from NameOrIndex
+// XATTR_FILLGRADIENT ok
+// due to SvxUnoNameItemTable
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// XATTR_FILLHATCH ok
+// due to SvxUnoNameItemTable
+// due to SvxShape::setPropertyValueImpl/SvxShape::SetFillAttribute
+// XATTR_FILLFLOATTRANSPARENCE ok
+// due to NamespaceIteratorImpl
+// -> needs to be evaluated
+// due to SwCursorShell::GotoNxtPrvTOXMark
+// due to SwDoc::GetTOIKeys
+// RES_TXTATR_TOXMARK ok
+// due to SwDoc::GetRefMark
+// due to SwDoc::CallEvent
+// due to SwURLStateChanged::Notify
+// due to SwHTMLWriter::CollectLinkTargets
+// due to MSWordExportBase::CollectOutlineBookmarks
+// RES_TXTATR_INETFMT ok
+// due to SwDoc::GetAllUsedDB
+// due to lcl_FindInputField
+// due to SwViewShell::IsAnyFieldInDoc
+// RES_TXTATR_FIELD ok
+// due to SwDoc::GetAllUsedDB
+// due to lcl_FindInputField
+// due to SwViewShell::IsAnyFieldInDoc
+// RES_TXTATR_INPUTFIELD ok
+// due to SwDoc::SetDefault
+// RES_PARATR_TABSTOP ok
+// due to SwDoc::GetDocColors()
+// due to RtfExport::OutColorTable
+// RES_CHRATR_COLOR ok
+// due to SwDoc::GetDocColors()
+// RES_CHRATR_HIGHLIGHT ok
+// due to SwDoc::GetDocColors()
+// RES_BACKGROUND ok
+// due to SwNode::FindPageDesc
+// due to SwPageNumberFieldType::ChangeExpansion
+// due to SwFrame::GetVirtPageNum
+// RES_PAGEDESC ok
+// due to SwAutoStylesEnumImpl::
+// RES_TXTATR_CJK_RUBY ok
+// due to SwHTMLWriter::CollectLinkTargets
+// due to MSWordExportBase::CollectOutlineBookmarks
+// RES_URL
+// due to RtfExport::OutColorTable
+// RES_CHRATR_UNDERLINE ok
+// RES_CHRATR_OVERLINE ok
+// RES_CHRATR_BACKGROUND ok
+// RES_SHADOW ok
+// RES_BOX ok
+// RES_CHRATR_BOX ok
+// XATTR_FILLCOLOR ok
+// due to wwFontHelper::InitFontTable
+// due to SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl
+// RES_CHRATR_FONT ok
+// due to wwFontHelper::InitFontTable
+// due to SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl
+// RES_CHRATR_CJK_FONT ok
+// due to wwFontHelper::InitFontTable
+// due to SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl
+// RES_CHRATR_CTL_FONT
+// due to SwXMLExport::exportDoc
+// RES_UNKNOWNATR_CONTAINER ok
+// RES_TXTATR_UNKNOWN_CONTAINER ok
+
+
+
+#if OSL_DEBUG_LEVEL > 0
+#include <map>
+
+static void
+lcl_CheckSlots2(std::map<sal_uInt16, sal_uInt16> & rSlotMap,
+ SfxItemPool const& rPool, SfxItemInfo const* pInfo)
+{
+ if (!pInfo)
+ return; // may not be initialized yet
+ if (rPool.GetName() == "EditEngineItemPool")
+ return; // HACK: this one has loads of duplicates already, ignore it :(
+ sal_uInt16 const nFirst(rPool.GetFirstWhich());
+ sal_uInt16 const nCount(rPool.GetLastWhich() - rPool.GetFirstWhich() + 1);
+ for (sal_uInt16 n = 0; n < nCount; ++n)
+ {
+ sal_uInt16 const nSlotId(pInfo[n]._nSID);
+ if (nSlotId != 0
+ && nSlotId != 10883 // preexisting duplicate SID_ATTR_GRAF_CROP
+ && nSlotId != 10023 // preexisting duplicate SID_ATTR_BORDER_INNER
+ && nSlotId != 10024 // preexisting duplicate SID_ATTR_BORDER_OUTER
+ && nSlotId != 11013 // preexisting duplicate SID_ATTR_BORDER_DIAG_TLBR
+ && nSlotId != 11014) // preexisting duplicate SID_ATTR_BORDER_DIAG_BLTR
+ { // check for duplicate slot-id mapping
+ std::map<sal_uInt16, sal_uInt16>::const_iterator const iter(
+ rSlotMap.find(nSlotId));
+ sal_uInt16 const nWhich(nFirst + n);
+ if (iter != rSlotMap.end())
+ {
+ SAL_WARN("svl", "SfxItemPool: duplicate SlotId " << nSlotId
+ << " mapped to " << iter->second << " and " << nWhich);
+ assert(false);
+ }
+ rSlotMap.insert(std::make_pair(nSlotId, nWhich));
+ }
+ }
+}
+
+#define CHECK_SLOTS() \
+do { \
+ std::map<sal_uInt16, sal_uInt16> slotmap; \
+ for (SfxItemPool * p = pImpl->mpMaster; p; p = p->pImpl->mpSecondary.get()) \
+ { \
+ lcl_CheckSlots2(slotmap, *p, p->pItemInfos); \
+ } \
+} while (false)
+
+#else
+#define CHECK_SLOTS() do {} while (false)
+#endif
+
+sal_uInt16 SfxItemPool::GetFirstWhich() const
+{
+ return pImpl->mnStart;
+}
+
+sal_uInt16 SfxItemPool::GetLastWhich() const
+{
+ return pImpl->mnEnd;
+}
+
+bool SfxItemPool::IsInRange( sal_uInt16 nWhich ) const
+{
+ return nWhich >= pImpl->mnStart && nWhich <= pImpl->mnEnd;
+}
+
+sal_uInt16 SfxItemPool::GetIndex_Impl(sal_uInt16 nWhich) const
+{
+ if (nWhich < pImpl->mnStart || nWhich > pImpl->mnEnd)
+ {
+ assert(false && "missing bounds check before use");
+ return 0;
+ }
+ return nWhich - pImpl->mnStart;
+}
+
+sal_uInt16 SfxItemPool::GetSize_Impl() const
+{
+ return pImpl->mnEnd - pImpl->mnStart + 1;
+}
+
+const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const
+{
+ const SfxPoolItem* pRet;
+ if( IsInRange( nWhich ) )
+ pRet = pImpl->maPoolDefaults[GetIndex_Impl(nWhich)];
+ else if( pImpl->mpSecondary )
+ pRet = pImpl->mpSecondary->GetPoolDefaultItem( nWhich );
+ else
+ {
+ assert(false && "unknown WhichId - cannot get pool default");
+ pRet = nullptr;
+ }
+ return pRet;
+}
+
+
+bool SfxItemPool::NeedsPoolRegistration(sal_uInt16 nWhich) const
+{
+ if (!IsInRange(nWhich))
+ {
+ // get to correct pool
+ if (pImpl->mpSecondary)
+ return pImpl->mpSecondary->NeedsPoolRegistration(nWhich);
+ return false;
+ }
+
+ return NeedsPoolRegistration_Impl(nWhich - pImpl->mnStart);
+}
+
+bool SfxItemPool::Shareable(sal_uInt16 nWhich) const
+{
+ if (!IsInRange(nWhich))
+ {
+ // get to correct pool
+ if (pImpl->mpSecondary)
+ return pImpl->mpSecondary->Shareable(nWhich);
+ return false;
+ }
+
+ return Shareable_Impl(nWhich - pImpl->mnStart);
+}
+
+
+SfxBroadcaster& SfxItemPool::BC()
+{
+ return pImpl->aBC;
+}
+
+
+/**
+ * This is the regular ctor to be used for this class.
+ * An SfxItemPool instance is initialized, which can manage Items in the
+ * range from 'nStartWhich' to 'nEndWhich'.
+ *
+ * For every one of these WhichIds a static Default must be present in the
+ * 'pDefaults' array. They start with an SfxPoolItem (with the WhichId
+ * 'nStartWhich'), are sorted by WhichId and consecutively stored.
+ *
+ * 'pItemInfos' is a USHORT array arranged in the same way, which holds
+ * SlotIds and Flags. These SlotIds can be 0, if the affected Items are
+ * exclusively used in the Core.
+ * The flags allow for e.g. enabling value sharing (poolable).
+ *
+ * If the Pool is supposed to hold SfxSetItems, the ctor cannot yet contain
+ * static Defaults. This needs to be done afterwards, using
+ * @see SfxItemPool::SetDefaults(std::vector<SfxPoolItem*>*).
+ *
+ * @see SfxItemPool::SetDefaults(std::vector<SfxPoolItem*>*)
+ * @see SfxItemPool::ReleaseDefaults(std::vector<SfxPoolItem*>*,bool)
+ * @see SfxItemPool::ReleaseDefaults(bool)
+ */
+SfxItemPool::SfxItemPool
+(
+ const OUString& rName, /* Pool name to identify in the file format */
+ sal_uInt16 nStartWhich, /* First WhichId of the Pool (must be > 0) */
+ sal_uInt16 nEndWhich, /* Last WhichId of the Pool */
+ const SfxItemInfo* pInfo, /* SID Map and Item flags */
+ std::vector<SfxPoolItem*>*
+ pDefaults /* Pointer to static Defaults;
+ is directly referenced by the Pool,
+ but no transfer of ownership */
+) :
+ pItemInfos(pInfo),
+ pImpl( new SfxItemPool_Impl( this, rName, nStartWhich, nEndWhich ) ),
+ ppRegisteredSfxPoolItems(nullptr)
+{
+ pImpl->eDefMetric = MapUnit::MapTwip;
+
+ if ( pDefaults )
+ SetDefaults(pDefaults);
+
+#ifdef DBG_UTIL
+ if (pItemInfos)
+ {
+ auto p = pItemInfos;
+ auto nWhich = nStartWhich;
+ while (nWhich <= nEndWhich)
+ {
+ if (p->_nSID == nWhich)
+ {
+ SAL_WARN("svl.items", "No point mapping a SID to itself, just put a 0 here in the SfxItemInfo array, at index " << (p - pItemInfos));
+ assert(false);
+ }
+ ++p;
+ ++nWhich;
+ }
+ }
+#endif
+}
+
+
+/**
+ * Copy ctor
+ *
+ * @see SfxItemPool::Clone() const
+*/
+SfxItemPool::SfxItemPool
+(
+ const SfxItemPool& rPool, // Copy from this instance
+ bool bCloneStaticDefaults /* true
+ Copy static Defaults
+
+ false
+ Take over static Defaults */
+) :
+ salhelper::SimpleReferenceObject(),
+ pItemInfos(rPool.pItemInfos),
+ pImpl( new SfxItemPool_Impl( this, rPool.pImpl->aName, rPool.pImpl->mnStart, rPool.pImpl->mnEnd ) ),
+ ppRegisteredSfxPoolItems(nullptr)
+{
+ pImpl->eDefMetric = rPool.pImpl->eDefMetric;
+
+ // Take over static Defaults
+ if ( bCloneStaticDefaults )
+ {
+ std::vector<SfxPoolItem *>* ppDefaults = new std::vector<SfxPoolItem*>(pImpl->mnEnd-pImpl->mnStart+1);
+ for ( sal_uInt16 n = 0; n <= pImpl->mnEnd - pImpl->mnStart; ++n )
+ {
+ (*ppDefaults)[n] = (*rPool.pImpl->mpStaticDefaults)[n]->Clone(this);
+ (*ppDefaults)[n]->setStaticDefault();
+ }
+
+ SetDefaults( ppDefaults );
+ }
+ else
+ SetDefaults( rPool.pImpl->mpStaticDefaults );
+
+ // Copy Pool Defaults
+ for (size_t n = 0; n < pImpl->maPoolDefaults.size(); ++n )
+ if (rPool.pImpl->maPoolDefaults[n])
+ {
+ pImpl->maPoolDefaults[n] = rPool.pImpl->maPoolDefaults[n]->Clone(this); //resets kind
+ pImpl->maPoolDefaults[n]->setPoolDefault();
+ }
+
+ // Repair linkage
+ if ( rPool.pImpl->mpSecondary )
+ SetSecondaryPool( rPool.pImpl->mpSecondary->Clone().get() );
+}
+
+void SfxItemPool::SetDefaults( std::vector<SfxPoolItem*>* pDefaults )
+{
+ DBG_ASSERT( pDefaults, "first we ask for it, and then we don't give back..." );
+ DBG_ASSERT( !pImpl->mpStaticDefaults, "already have Defaults" );
+
+ pImpl->mpStaticDefaults = pDefaults;
+ //! if ((*mpStaticDefaults)->GetKind() != SfxItemKind::StaticDefault)
+ //! FIXME: Probably doesn't work with SetItems at the end
+ {
+ DBG_ASSERT( (*pImpl->mpStaticDefaults)[0]->GetRefCount() == 0 ||
+ IsDefaultItem( (*pImpl->mpStaticDefaults)[0] ),
+ "these are not static" );
+ for ( sal_uInt16 n = 0; n <= pImpl->mnEnd - pImpl->mnStart; ++n )
+ {
+ assert( ((*pImpl->mpStaticDefaults)[n]->Which() == n + pImpl->mnStart)
+ && "items ids in pool-ranges and in static-defaults do not match" );
+ (*pImpl->mpStaticDefaults)[n]->setStaticDefault();
+ DBG_ASSERT(nullptr == ppRegisteredSfxPoolItems || nullptr == ppRegisteredSfxPoolItems[n]
+ || ppRegisteredSfxPoolItems[n]->empty(), "defaults with setitems with items?!" );
+ }
+ }
+}
+
+void SfxItemPool::ClearDefaults()
+{
+ pImpl->mpStaticDefaults = nullptr;
+}
+
+/**
+ * Frees the static Defaults of the corresponding SfxItemPool instance
+ * and deletes them if specified.
+ *
+ * The SfxItemPool instance MUST NOT BE USED after this function has
+ * been called; only the dtor must be called.
+ */
+void SfxItemPool::ReleaseDefaults
+(
+ bool bDelete /* true
+ Deletes the array as well as the single static Defaults
+
+ false
+ Neither deletes the array not the single static Defaults */
+)
+
+
+{
+ DBG_ASSERT( pImpl->mpStaticDefaults, "requirements not met" );
+ ReleaseDefaults( pImpl->mpStaticDefaults, bDelete );
+
+ // mpStaticDefaults points to deleted memory if bDelete == true.
+ if ( bDelete )
+ pImpl->mpStaticDefaults = nullptr;
+}
+
+
+/**
+ * Frees the specified static Defaults and also deletes them, if so
+ * specified.
+ *
+ * This method MUST be called AFTER all SfxItemPool instances (which
+ * use the specified static Defaults 'pDefault') have been destroyed.
+ */
+void SfxItemPool::ReleaseDefaults
+(
+ std::vector<SfxPoolItem*>*
+ pDefaults, /* Static Defaults that are to be freed */
+
+ bool bDelete /* true
+ Deletes the array as well as the specified
+ static Defaults
+
+ false
+ Neither deletes the array nor the single
+ static Defaults */
+)
+{
+ DBG_ASSERT( pDefaults, "we first ask for it and the return nothing ..." );
+
+ for ( auto & rpItem : *pDefaults )
+ {
+ assert(IsStaticDefaultItem(rpItem));
+ rpItem->SetRefCount(0);
+ if ( bDelete )
+ {
+ delete rpItem;
+ rpItem = nullptr;
+ }
+ }
+
+ if ( bDelete )
+ {
+ delete pDefaults;
+ pDefaults = nullptr;
+ }
+}
+
+
+SfxItemPool::~SfxItemPool()
+{
+ // Need to be deleted?
+ // Caution: ppRegisteredSfxPoolItems is on-demand created and can be nullptr
+ if ( nullptr != ppRegisteredSfxPoolItems || !pImpl->maPoolDefaults.empty() )
+ Delete();
+
+ if (pImpl->mpMaster != nullptr && pImpl->mpMaster != this)
+ {
+ // This condition indicates an error.
+ // A pImpl->mpMaster->SetSecondaryPool(...) call should have been made
+ // earlier to prevent this. At this point we can only try to
+ // prevent a crash later on.
+ DBG_ASSERT( pImpl->mpMaster == this, "destroying active Secondary-Pool" );
+ if (pImpl->mpMaster->pImpl->mpSecondary == this)
+ pImpl->mpMaster->pImpl->mpSecondary = nullptr;
+ }
+}
+
+void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool )
+{
+ // Reset Master in attached Pools
+ if ( pImpl->mpSecondary )
+ {
+#ifdef DBG_UTIL
+ if (nullptr != pImpl->mpStaticDefaults
+ && nullptr != ppRegisteredSfxPoolItems
+ && nullptr != pImpl->mpSecondary->ppRegisteredSfxPoolItems)
+ // Delete() did not yet run?
+ {
+ // Does the Master have SetItems?
+ bool bHasSetItems(false);
+
+ for (sal_uInt16 i(0); !bHasSetItems && i < pImpl->mnEnd - pImpl->mnStart; ++i)
+ {
+ const SfxPoolItem* pStaticDefaultItem((*pImpl->mpStaticDefaults)[i]);
+ bHasSetItems = pStaticDefaultItem->isSetItem();
+ }
+
+ if (bHasSetItems)
+ {
+ // Detached Pools must be empty
+ registeredSfxPoolItems** ppSet(pImpl->mpSecondary->ppRegisteredSfxPoolItems);
+
+ for (sal_uInt16 a(0); a < pImpl->mpSecondary->GetSize_Impl(); a++, ppSet++)
+ {
+ if (nullptr != *ppSet && (*ppSet)->size() != 0)
+ {
+ SAL_WARN("svl.items", "old secondary pool: " << pImpl->mpSecondary->pImpl->aName
+ << " of pool: " << pImpl->aName << " must be empty.");
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+ pImpl->mpSecondary->pImpl->mpMaster = pImpl->mpSecondary.get();
+ for ( SfxItemPool *p = pImpl->mpSecondary->pImpl->mpSecondary.get(); p; p = p->pImpl->mpSecondary.get() )
+ p->pImpl->mpMaster = pImpl->mpSecondary.get();
+ }
+
+ // Set Master of new Secondary Pools
+ DBG_ASSERT( !pPool || pPool->pImpl->mpMaster == pPool, "Secondary is present in two Pools" );
+ SfxItemPool *pNewMaster = GetMasterPool() ? pImpl->mpMaster : this;
+ for ( SfxItemPool *p = pPool; p; p = p->pImpl->mpSecondary.get() )
+ p->pImpl->mpMaster = pNewMaster;
+
+ // Remember new Secondary Pool
+ pImpl->mpSecondary = pPool;
+
+ CHECK_SLOTS();
+}
+
+void SfxItemPool::SetItemInfos(SfxItemInfo const*const pInfo)
+{
+ pItemInfos = pInfo;
+ CHECK_SLOTS();
+}
+
+
+MapUnit SfxItemPool::GetMetric( sal_uInt16 ) const
+{
+ return pImpl->eDefMetric;
+}
+
+
+void SfxItemPool::SetDefaultMetric( MapUnit eNewMetric )
+{
+// assert((pImpl->eDefMetric == eNewMetric || !pImpl->mpPoolRanges) && "pool already frozen, cannot change metric");
+ pImpl->eDefMetric = eNewMetric;
+}
+
+MapUnit SfxItemPool::GetDefaultMetric() const
+{
+ return pImpl->eDefMetric;
+}
+
+const OUString& SfxItemPool::GetName() const
+{
+ return pImpl->aName;
+}
+
+
+bool SfxItemPool::GetPresentation
+(
+ const SfxPoolItem& rItem,
+ MapUnit eMetric,
+ OUString& rText,
+ const IntlWrapper& rIntlWrapper
+) const
+{
+ return rItem.GetPresentation(
+ SfxItemPresentation::Complete, GetMetric(rItem.Which()), eMetric, rText, rIntlWrapper );
+}
+
+
+rtl::Reference<SfxItemPool> SfxItemPool::Clone() const
+{
+ return new SfxItemPool( *this );
+}
+
+
+void SfxItemPool::Delete()
+{
+ // Already deleted?
+ // Caution: ppRegisteredSfxPoolItems is on-demand created and can be nullptr
+ if (nullptr == ppRegisteredSfxPoolItems && pImpl->maPoolDefaults.empty())
+ return;
+
+ // Inform e.g. running Requests
+ pImpl->aBC.Broadcast( SfxHint( SfxHintId::Dying ) );
+
+ // Iterate through twice: first for the SetItems.
+ if (nullptr != pImpl->mpStaticDefaults && nullptr != ppRegisteredSfxPoolItems)
+ {
+ for (size_t n = 0; n < GetSize_Impl(); ++n)
+ {
+ // *mpStaticDefaultItem could've already been deleted in a class derived
+ // from SfxItemPool
+ // This causes chaos in Itempool!
+ const SfxPoolItem* pStaticDefaultItem((*pImpl->mpStaticDefaults)[n]);
+ if (pStaticDefaultItem->isSetItem() && nullptr != ppRegisteredSfxPoolItems[n])
+ {
+ // SfxSetItem found, remove PoolItems (and defaults) with same ID
+ auto& rArray(*(ppRegisteredSfxPoolItems[n]));
+ for (auto& rItemPtr : rArray)
+ {
+ ReleaseRef(*rItemPtr, rItemPtr->GetRefCount()); // for RefCount check in dtor
+ delete rItemPtr;
+ }
+ rArray.clear();
+ // let pImpl->DeleteItems() delete item arrays in maPoolItems
+ auto& rItemPtr = pImpl->maPoolDefaults[n];
+ if (rItemPtr)
+ {
+#ifdef DBG_UTIL
+ ClearRefCount(*rItemPtr);
+#endif
+ delete rItemPtr;
+ rItemPtr = nullptr;
+ }
+ }
+ }
+ }
+
+ if (nullptr != ppRegisteredSfxPoolItems)
+ {
+ registeredSfxPoolItems** ppSet(ppRegisteredSfxPoolItems);
+
+ for (sal_uInt16 a(0); a < GetSize_Impl(); a++, ppSet++)
+ {
+ if (nullptr != *ppSet)
+ {
+ for (auto& rCandidate : **ppSet)
+ {
+ if (nullptr != rCandidate && !IsDefaultItem(rCandidate))
+ {
+ ReleaseRef(*rCandidate, rCandidate->GetRefCount()); // for RefCount check in dtor
+ delete rCandidate;
+ }
+ }
+
+ delete *ppSet;
+ *ppSet = nullptr;
+ }
+ }
+
+ delete[] ppRegisteredSfxPoolItems;
+ ppRegisteredSfxPoolItems = nullptr;
+ }
+
+ // default items
+ for (auto rItemPtr : pImpl->maPoolDefaults)
+ {
+ if (rItemPtr)
+ {
+#ifdef DBG_UTIL
+ ClearRefCount(*rItemPtr);
+#endif
+ delete rItemPtr;
+ rItemPtr = nullptr;
+ }
+ }
+
+ pImpl->DeleteItems();
+}
+
+
+void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem)
+{
+ if ( IsInRange(rItem.Which()) )
+ {
+ auto& rOldDefault =
+ pImpl->maPoolDefaults[GetIndex_Impl(rItem.Which())];
+ SfxPoolItem *pNewDefault = rItem.Clone(this);
+ pNewDefault->setPoolDefault();
+ if (rOldDefault)
+ {
+ rOldDefault->SetRefCount(0);
+ delete rOldDefault;
+ rOldDefault = nullptr;
+ }
+ rOldDefault = pNewDefault;
+ }
+ else if ( pImpl->mpSecondary )
+ pImpl->mpSecondary->SetPoolDefaultItem(rItem);
+ else
+ {
+ assert(false && "unknown WhichId - cannot set pool default");
+ }
+}
+
+/**
+ * Resets the default of the given WhichId back to the static Default.
+ * If a pool default exists, it is removed.
+ */
+void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId )
+{
+ if ( IsInRange(nWhichId) )
+ {
+ auto& rOldDefault =
+ pImpl->maPoolDefaults[GetIndex_Impl(nWhichId)];
+ if (rOldDefault)
+ {
+ rOldDefault->SetRefCount(0);
+ delete rOldDefault;
+ rOldDefault = nullptr;
+ }
+ }
+ else if ( pImpl->mpSecondary )
+ pImpl->mpSecondary->ResetPoolDefaultItem(nWhichId);
+ else
+ {
+ assert(false && "unknown WhichId - cannot reset pool default");
+ }
+}
+
+const SfxPoolItem& SfxItemPool::DirectPutItemInPoolImpl(const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership)
+{
+ // CAUTION: Do not register the problematic pool default
+ if (rItem.isExceptionalSCItem() && GetMasterPool()->newItem_UseDirect(rItem))
+ return rItem;
+
+#ifdef DBG_UTIL
+ nAllDirectlyPooledSfxPoolItemCount++;
+ nRemainingDirectlyPooledSfxPoolItemCount++;
+#endif
+
+ // make sure to use 'master'-pool, that's the one used by SfxItemSets
+ const SfxPoolItem* pRetval(implCreateItemEntry(*GetMasterPool(), &rItem, nWhich, bPassingOwnership));
+
+ // For the moment, as long as DirectPutItemInPoolImpl is used, make sure that
+ // the changes in implCreateItemEntry do not change anything, that would
+ // risc memory leaks by not (ab)using the garbage collector aspect of the pool.
+ registerSfxPoolItem(*pRetval);
+
+ return *pRetval;
+}
+
+void SfxItemPool::DirectRemoveItemFromPool(const SfxPoolItem& rItem)
+{
+ // CAUTION: Do not remove the problematic pool default
+ if (rItem.isExceptionalSCItem() && GetMasterPool()->newItem_UseDirect(rItem))
+ return;
+
+#ifdef DBG_UTIL
+ nRemainingDirectlyPooledSfxPoolItemCount--;
+#endif
+
+ // make sure to use 'master'-pool, that's the one used by SfxItemSets
+ implCleanupItemEntry(*GetMasterPool(), &rItem);
+}
+
+void SfxItemPool::newItem_Callback(const SfxPoolItem& rItem) const
+{
+ if (!IsInRange(rItem.Which()) && pImpl->mpSecondary)
+ pImpl->mpSecondary->newItem_Callback(rItem);
+}
+
+bool SfxItemPool::newItem_UseDirect(const SfxPoolItem& rItem) const
+{
+ if (!IsInRange(rItem.Which()) && pImpl->mpSecondary)
+ return pImpl->mpSecondary->newItem_UseDirect(rItem);
+ return false;
+}
+
+const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const
+{
+ if ( !IsInRange(nWhich) )
+ {
+ if ( pImpl->mpSecondary )
+ return pImpl->mpSecondary->GetDefaultItem( nWhich );
+ assert(!"unknown which - don't ask me for defaults");
+ }
+
+ DBG_ASSERT( pImpl->mpStaticDefaults, "no defaults known - don't ask me for defaults" );
+ sal_uInt16 nPos = GetIndex_Impl(nWhich);
+ SfxPoolItem* pDefault = pImpl->maPoolDefaults[nPos];
+ if ( pDefault )
+ return *pDefault;
+ return *(*pImpl->mpStaticDefaults)[nPos];
+}
+
+SfxItemPool* SfxItemPool::GetSecondaryPool() const
+{
+ return pImpl->mpSecondary.get();
+}
+
+/* get the last pool by following the GetSecondaryPool chain */
+SfxItemPool* SfxItemPool::GetLastPoolInChain()
+{
+ SfxItemPool* pLast = this;
+ while(pLast->GetSecondaryPool())
+ pLast = pLast->GetSecondaryPool();
+ return pLast;
+}
+
+SfxItemPool* SfxItemPool::GetMasterPool() const
+{
+ return pImpl->mpMaster;
+}
+
+/**
+ * This method should be called at the master pool, when all secondary
+ * pools are appended to it.
+ *
+ * It calculates the ranges of 'which-ids' for fast construction of
+ * item-sets, which contains all 'which-ids'.
+ */
+void SfxItemPool::FreezeIdRanges()
+{
+ assert(pImpl->mpPoolRanges.empty() && "pool already frozen, cannot freeze twice");
+ FillItemIdRanges_Impl( pImpl->mpPoolRanges );
+}
+
+
+void SfxItemPool::FillItemIdRanges_Impl( WhichRangesContainer& pWhichRanges ) const
+{
+ DBG_ASSERT( pImpl->mpPoolRanges.empty(), "GetFrozenRanges() would be faster!" );
+
+ pWhichRanges.reset();
+
+ // Merge all ranges, keeping them sorted
+ for (const SfxItemPool* pPool = this; pPool; pPool = pPool->pImpl->mpSecondary.get())
+ pWhichRanges = pWhichRanges.MergeRange(pPool->pImpl->mnStart, pPool->pImpl->mnEnd);
+}
+
+const WhichRangesContainer& SfxItemPool::GetFrozenIdRanges() const
+{
+ return pImpl->mpPoolRanges;
+}
+
+const SfxPoolItem *SfxItemPool::GetItem2Default(sal_uInt16 nWhich) const
+{
+ if ( !IsInRange(nWhich) )
+ {
+ if ( pImpl->mpSecondary )
+ return pImpl->mpSecondary->GetItem2Default( nWhich );
+ assert(false && "unknown WhichId - cannot resolve surrogate");
+ return nullptr;
+ }
+ return (*pImpl->mpStaticDefaults)[ GetIndex_Impl(nWhich) ];
+}
+
+#ifdef DBG_UTIL
+static void warnForMissingPoolRegistration(const SfxItemPool& rPool, sal_uInt16 nWhich)
+{
+ if (!rPool.NeedsPoolRegistration(nWhich))
+ SAL_INFO("svl.items", "ITEM: ItemSurrogate requested for WhichID " << nWhich <<
+ " class " << typeid(rPool.GetDefaultItem(nWhich)).name() <<
+ ": needs _bNeedsPoolRegistration==true in SfxItemInfo for that slot");
+}
+#endif
+
+const registeredSfxPoolItems& SfxItemPool::GetItemSurrogates(sal_uInt16 nWhich) const
+{
+ static const registeredSfxPoolItems EMPTY;
+
+ if (!IsInRange(nWhich))
+ {
+ if (pImpl->mpSecondary)
+ return pImpl->mpSecondary->GetItemSurrogates(nWhich);
+ return EMPTY;
+ }
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ {
+#ifdef DBG_UTIL
+ warnForMissingPoolRegistration(*this, nWhich);
+#endif
+ return EMPTY;
+ }
+
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nWhich - pImpl->mnStart]);
+
+ if (nullptr == pSet)
+ {
+#ifdef DBG_UTIL
+ warnForMissingPoolRegistration(*this, nWhich);
+#endif
+ return EMPTY;
+ }
+
+ return *pSet;
+}
+
+std::vector<const SfxPoolItem*> SfxItemPool::FindItemSurrogate(sal_uInt16 nWhich, SfxPoolItem const & rSample) const
+{
+ static const std::vector<const SfxPoolItem*> EMPTY;
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ return EMPTY;
+
+ if ( !IsInRange(nWhich) )
+ {
+ if ( pImpl->mpSecondary )
+ return pImpl->mpSecondary->FindItemSurrogate( nWhich, rSample );
+ assert(false && "unknown WhichId - cannot resolve surrogate");
+ return EMPTY;
+ }
+
+ // get index (must exist due to checks above)
+ const sal_uInt16 nIndex(rSample.Which() - pImpl->mnStart);
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ {
+#ifdef DBG_UTIL
+ warnForMissingPoolRegistration(*this, nWhich);
+#endif
+ return EMPTY;
+ }
+
+ // get registeredSfxPoolItems container
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]);
+
+ if (nullptr == pSet)
+ {
+#ifdef DBG_UTIL
+ warnForMissingPoolRegistration(*this, nWhich);
+#endif
+ return EMPTY;
+ }
+
+ std::vector<const SfxPoolItem*> rv;
+
+ for (const SfxPoolItem* p : *pSet)
+ if (rSample == *p)
+ rv.push_back(p);
+
+ return rv;
+}
+
+sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, bool bDeep ) const
+{
+ if ( !IsSlot(nSlotId) )
+ return nSlotId;
+
+ sal_uInt16 nCount = pImpl->mnEnd - pImpl->mnStart + 1;
+ for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
+ if ( pItemInfos[nOfs]._nSID == nSlotId )
+ return nOfs + pImpl->mnStart;
+ if ( pImpl->mpSecondary && bDeep )
+ return pImpl->mpSecondary->GetWhich(nSlotId);
+ return nSlotId;
+}
+
+
+sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich ) const
+{
+ if ( !IsWhich(nWhich) )
+ return nWhich;
+
+ if ( !IsInRange( nWhich ) )
+ {
+ if ( pImpl->mpSecondary )
+ return pImpl->mpSecondary->GetSlotId(nWhich);
+ assert(false && "unknown WhichId - cannot get slot-id");
+ return 0;
+ }
+
+ sal_uInt16 nSID = pItemInfos[nWhich - pImpl->mnStart]._nSID;
+ return nSID ? nSID : nWhich;
+}
+
+
+sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, bool bDeep ) const
+{
+ if ( !IsSlot(nSlotId) )
+ return 0;
+
+ sal_uInt16 nCount = pImpl->mnEnd - pImpl->mnStart + 1;
+ for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
+ if ( pItemInfos[nOfs]._nSID == nSlotId )
+ return nOfs + pImpl->mnStart;
+ if ( pImpl->mpSecondary && bDeep )
+ return pImpl->mpSecondary->GetTrueWhich(nSlotId);
+ return 0;
+}
+
+
+sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich ) const
+{
+ if ( !IsWhich(nWhich) )
+ return 0;
+
+ if ( !IsInRange( nWhich ) )
+ {
+ if ( pImpl->mpSecondary )
+ return pImpl->mpSecondary->GetTrueSlotId(nWhich);
+ assert(false && "unknown WhichId - cannot get slot-id");
+ return 0;
+ }
+ return pItemInfos[nWhich - pImpl->mnStart]._nSID;
+}
+
+void SfxItemPool::registerSfxPoolItem(const SfxPoolItem& rItem)
+{
+ assert(rItem.Which() != 0);
+
+ if (IsSlot(rItem.Which()))
+ // do not register SlotItems
+ return;
+
+ if (rItem.isRegisteredAtPool())
+ // already registered, done
+ return;
+
+ if (!IsInRange(rItem.Which()))
+ {
+ // get to the right pool
+ if (pImpl->mpSecondary)
+ {
+ pImpl->mpSecondary->registerSfxPoolItem(rItem);
+ return;
+ }
+
+ return;
+ }
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ // on-demand allocate array of registeredSfxPoolItems and init to nullptr
+ ppRegisteredSfxPoolItems = new registeredSfxPoolItems*[GetSize_Impl()]{};
+
+ // get correct registeredSfxPoolItems
+ const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart);
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]);
+
+ if (nullptr == pSet)
+ // on-demand allocate
+ ppRegisteredSfxPoolItems[nIndex] = pSet = new registeredSfxPoolItems;
+
+ // insert to registeredSfxPoolItems and set flag at Item
+ pSet->insert(&rItem);
+ const_cast<SfxPoolItem&>(rItem).setRegisteredAtPool(true);
+}
+
+void SfxItemPool::unregisterSfxPoolItem(const SfxPoolItem& rItem)
+{
+ if (!rItem.isRegisteredAtPool())
+ // Item is not registered, done
+ return;
+
+ if (!IsInRange(rItem.Which()))
+ {
+ // get to the right pool
+ if (pImpl->mpSecondary)
+ {
+ pImpl->mpSecondary->unregisterSfxPoolItem(rItem);
+ return;
+ }
+
+ assert(false && "unknown WhichId - cannot execute unregisterSfxPoolItem");
+ return;
+ }
+
+ // we need a valid WhichID and the array of containers has to exist
+ assert(rItem.Which() != 0);
+ assert(nullptr != ppRegisteredSfxPoolItems);
+
+ // get index (must exist due to checks above)
+ const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart);
+
+ // a valid registeredSfxPoolItems container has to exist
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]);
+ assert(nullptr != pSet);
+
+ // remove registered Item and reset flag at Item
+ pSet->erase(&rItem);
+ const_cast<SfxPoolItem&>(rItem).setRegisteredAtPool(false);
+}
+
+bool SfxItemPool::isSfxPoolItemRegisteredAtThisPool(const SfxPoolItem& rItem) const
+{
+ if (!rItem.isRegisteredAtPool())
+ // Item is not registered at all, so also not at this Pool
+ return false;
+
+ if (IsSlot(rItem.Which()))
+ // do not check being registered for SlotItems
+ return false;
+
+ if (!IsInRange(rItem.Which()))
+ {
+ // get to the right pool
+ if (pImpl->mpSecondary)
+ return pImpl->mpSecondary->isSfxPoolItemRegisteredAtThisPool(rItem);
+ return false;
+ }
+
+ // we need a valid WhichID
+ assert(rItem.Which() != 0);
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ // when no array of containers exists the Item is not registered
+ return false;
+
+ // get index (must exist due to checks above)
+ const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart);
+
+ // get registeredSfxPoolItems container
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]);
+
+ if (nullptr == pSet)
+ // when no registeredSfxPoolItems container exists the Item is not registered
+ return false;
+
+ // test if Item is registered
+ return pSet->find(&rItem) != pSet->end();
+}
+
+const SfxPoolItem* SfxItemPool::tryToGetEqualItem(const SfxPoolItem& rItem, sal_uInt16 nWhich) const
+{
+ if (IsSlot(nWhich))
+ // SlotItems are not registered @pool and not in any range
+ return nullptr;
+
+ if (!IsInRange(nWhich))
+ {
+ // get to the right pool
+ if (pImpl->mpSecondary)
+ return pImpl->mpSecondary->tryToGetEqualItem(rItem, nWhich);
+ return nullptr;
+ }
+
+ if (nullptr == ppRegisteredSfxPoolItems)
+ // no Items at all
+ return nullptr;
+
+ // get index (must exist due to checks above)
+ const sal_uInt16 nIndex(nWhich - pImpl->mnStart);
+
+ if (!Shareable_Impl(nIndex))
+ // not shareable
+ return nullptr;
+
+ // get registeredSfxPoolItems container
+ registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]);
+
+ if (nullptr == pSet)
+ // no registeredSfxPoolItems for this WhichID
+ return nullptr;
+
+ for (const auto& rCandidate : *pSet)
+ if (*rCandidate == rItem)
+ return rCandidate;
+
+ return nullptr;
+}
+
+void SfxItemPool::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemPool"));
+
+ if (nullptr != ppRegisteredSfxPoolItems)
+ {
+ registeredSfxPoolItems** ppSet(ppRegisteredSfxPoolItems);
+
+ for (sal_uInt16 a(0); a < GetSize_Impl(); a++, ppSet++)
+ {
+ if (nullptr != *ppSet)
+ {
+ for (auto& rCandidate : **ppSet)
+ {
+ if (nullptr != rCandidate)
+ {
+ rCandidate->dumpAsXml(pWriter);
+ }
+ }
+ }
+ }
+ }
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/itemprop.cxx b/svl/source/items/itemprop.cxx
new file mode 100644
index 0000000000..3885542f89
--- /dev/null
+++ b/svl/source/items/itemprop.cxx
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <svl/itemprop.hxx>
+#include <svl/itempool.hxx>
+#include <svl/itemset.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <memory>
+
+/*
+ * UNO III Implementation
+ */
+using namespace com::sun::star;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+
+SfxItemPropertyMap::SfxItemPropertyMap( std::span<const SfxItemPropertyMapEntry> pEntries )
+{
+ m_aMap.reserve(pEntries.size());
+ for (const auto & pEntry : pEntries)
+ {
+ assert(!pEntry.aName.isEmpty() && "empty name? might be something left an empty entry at the end of this array");
+ m_aMap.insert( &pEntry );
+ }
+}
+
+SfxItemPropertyMap::SfxItemPropertyMap( const SfxItemPropertyMap& rSource ) = default;
+
+SfxItemPropertyMap::~SfxItemPropertyMap()
+{
+}
+
+const SfxItemPropertyMapEntry* SfxItemPropertyMap::getByName( std::u16string_view rName ) const
+{
+ struct Compare
+ {
+ bool operator() ( const SfxItemPropertyMapEntry* lhs, std::u16string_view rhs ) const
+ {
+ return lhs->aName < rhs;
+ }
+ bool operator() ( std::u16string_view lhs, const SfxItemPropertyMapEntry* rhs ) const
+ {
+ return lhs < rhs->aName;
+ }
+ };
+ auto it = std::lower_bound(m_aMap.begin(), m_aMap.end(), rName, Compare());
+ if (it == m_aMap.end() || Compare()(rName, *it))
+ return nullptr;
+ return *it;
+}
+
+uno::Sequence<beans::Property> const & SfxItemPropertyMap::getProperties() const
+{
+ if( !m_aPropSeq.hasElements() )
+ {
+ m_aPropSeq.realloc( m_aMap.size() );
+ beans::Property* pPropArray = m_aPropSeq.getArray();
+ sal_uInt32 n = 0;
+ for( const SfxItemPropertyMapEntry* pEntry : m_aMap )
+ {
+ pPropArray[n].Name = pEntry->aName;
+ pPropArray[n].Handle = pEntry->nWID;
+ pPropArray[n].Type = pEntry->aType;
+ pPropArray[n].Attributes =
+ sal::static_int_cast< sal_Int16 >(pEntry->nFlags);
+ n++;
+ }
+ }
+
+ return m_aPropSeq;
+}
+
+beans::Property SfxItemPropertyMap::getPropertyByName( const OUString& rName ) const
+{
+ const SfxItemPropertyMapEntry* pEntry = getByName(rName);
+ if( !pEntry )
+ throw UnknownPropertyException(rName);
+ beans::Property aProp;
+ aProp.Name = rName;
+ aProp.Handle = pEntry->nWID;
+ aProp.Type = pEntry->aType;
+ aProp.Attributes = sal::static_int_cast< sal_Int16 >(pEntry->nFlags);
+ return aProp;
+}
+
+bool SfxItemPropertyMap::hasPropertyByName( std::u16string_view rName ) const
+{
+ return getByName(rName) != nullptr;
+}
+
+SfxItemPropertySet::~SfxItemPropertySet()
+{
+}
+
+void SfxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry& rEntry,
+ const SfxItemSet& rSet, Any& rAny ) const
+{
+ // get the SfxPoolItem
+ const SfxPoolItem* pItem = nullptr;
+ SfxItemState eState = rSet.GetItemState( rEntry.nWID, true, &pItem );
+ if (SfxItemState::SET != eState && SfxItemPool::IsWhich(rEntry.nWID) )
+ pItem = &rSet.GetPool()->GetDefaultItem(rEntry.nWID);
+ // return item values as uno::Any
+ if(eState >= SfxItemState::DEFAULT && pItem)
+ {
+ pItem->QueryValue( rAny, rEntry.nMemberId );
+ }
+ else if(0 == (rEntry.nFlags & PropertyAttribute::MAYBEVOID))
+ {
+ throw RuntimeException(
+ "Property not found in ItemSet but not MAYBEVOID?", nullptr);
+ }
+
+ // convert general SfxEnumItem values to specific values
+ if( rEntry.aType.getTypeClass() == TypeClass_ENUM &&
+ rAny.getValueTypeClass() == TypeClass_LONG )
+ {
+ sal_Int32 nTmp = *o3tl::forceAccess<sal_Int32>(rAny);
+ rAny.setValue( &nTmp, rEntry.aType );
+ }
+}
+
+void SfxItemPropertySet::getPropertyValue( const OUString &rName,
+ const SfxItemSet& rSet, Any& rAny ) const
+{
+ // detect which-id
+ const SfxItemPropertyMapEntry* pEntry = m_aMap.getByName( rName );
+ if ( !pEntry )
+ throw UnknownPropertyException(rName);
+ getPropertyValue( *pEntry,rSet, rAny );
+}
+
+Any SfxItemPropertySet::getPropertyValue( const OUString &rName,
+ const SfxItemSet& rSet ) const
+{
+ Any aVal;
+ getPropertyValue( rName,rSet, aVal );
+ return aVal;
+}
+
+void SfxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry& rEntry,
+ const Any& aVal,
+ SfxItemSet& rSet ) const
+{
+ // get the SfxPoolItem
+ const SfxPoolItem* pItem = nullptr;
+ std::unique_ptr<SfxPoolItem> pNewItem;
+ SfxItemState eState = rSet.GetItemState( rEntry.nWID, true, &pItem );
+ if (SfxItemState::SET != eState && SfxItemPool::IsWhich(rEntry.nWID))
+ pItem = &rSet.GetPool()->GetDefaultItem(rEntry.nWID);
+ if (pItem)
+ {
+ pNewItem.reset(pItem->Clone());
+ }
+ if(pNewItem)
+ {
+ if( !pNewItem->PutValue( aVal, rEntry.nMemberId ) )
+ {
+ throw IllegalArgumentException();
+ }
+ // apply new item
+ rSet.Put( std::move(pNewItem) );
+ }
+}
+
+void SfxItemPropertySet::setPropertyValue( const OUString &rName,
+ const Any& aVal,
+ SfxItemSet& rSet ) const
+{
+ const SfxItemPropertyMapEntry* pEntry = m_aMap.getByName( rName );
+ if ( !pEntry )
+ {
+ throw UnknownPropertyException(rName);
+ }
+ setPropertyValue(*pEntry, aVal, rSet);
+}
+
+PropertyState SfxItemPropertySet::getPropertyState(const SfxItemPropertyMapEntry& rEntry, const SfxItemSet& rSet) const
+ noexcept
+{
+ PropertyState eRet = PropertyState_DIRECT_VALUE;
+ sal_uInt16 nWhich = rEntry.nWID;
+
+ // Get item state
+ SfxItemState eState = rSet.GetItemState( nWhich, false );
+ // Return item value as UnoAny
+ if(eState == SfxItemState::DEFAULT)
+ eRet = PropertyState_DEFAULT_VALUE;
+ else if(eState < SfxItemState::DEFAULT)
+ eRet = PropertyState_AMBIGUOUS_VALUE;
+ return eRet;
+}
+
+PropertyState SfxItemPropertySet::getPropertyState(const OUString& rName, const SfxItemSet& rSet) const
+{
+ PropertyState eRet = PropertyState_DIRECT_VALUE;
+
+ // Get WhichId
+ const SfxItemPropertyMapEntry* pEntry = m_aMap.getByName( rName );
+ if( !pEntry || !pEntry->nWID )
+ {
+ throw UnknownPropertyException(rName);
+ }
+ sal_uInt16 nWhich = pEntry->nWID;
+
+ // Get item state
+ SfxItemState eState = rSet.GetItemState(nWhich, false);
+ // Return item value as UnoAny
+ if(eState == SfxItemState::DEFAULT)
+ eRet = PropertyState_DEFAULT_VALUE;
+ else if(eState < SfxItemState::DEFAULT)
+ eRet = PropertyState_AMBIGUOUS_VALUE;
+ return eRet;
+}
+
+Reference<XPropertySetInfo> const & SfxItemPropertySet::getPropertySetInfo() const
+{
+ if( !m_xInfo.is() )
+ m_xInfo = new SfxItemPropertySetInfo( m_aMap );
+ return m_xInfo;
+}
+
+SfxItemPropertySetInfo::SfxItemPropertySetInfo(const SfxItemPropertyMap &rMap )
+ : m_aOwnMap( rMap )
+{
+}
+
+SfxItemPropertySetInfo::SfxItemPropertySetInfo(std::span<const SfxItemPropertyMapEntry> pEntries )
+ : m_aOwnMap( pEntries )
+{
+}
+
+Sequence< Property > SAL_CALL SfxItemPropertySetInfo::getProperties( )
+{
+ return m_aOwnMap.getProperties();
+}
+
+SfxItemPropertySetInfo::~SfxItemPropertySetInfo()
+{
+}
+
+Property SAL_CALL SfxItemPropertySetInfo::getPropertyByName( const OUString& rName )
+{
+ return m_aOwnMap.getPropertyByName( rName );
+}
+
+sal_Bool SAL_CALL SfxItemPropertySetInfo::hasPropertyByName( const OUString& rName )
+{
+ return m_aOwnMap.hasPropertyByName( rName );
+}
+
+SfxExtItemPropertySetInfo::SfxExtItemPropertySetInfo( std::span<const SfxItemPropertyMapEntry> pEntries,
+ const Sequence<Property>& rPropSeq )
+{
+ maMap.reserve(pEntries.size() + rPropSeq.getLength());
+ for (const auto & rEntry : pEntries )
+ {
+ assert(!rEntry.aName.isEmpty() && "empty name? might be something left an empty entry at the end of this array");
+ maMap.insert( rEntry );
+ }
+ for( const auto & rProp : rPropSeq )
+ {
+ SfxItemPropertyMapEntry aTemp(
+ rProp.Name,
+ sal::static_int_cast< sal_Int16 >( rProp.Handle ), //nWID
+ rProp.Type, //aType
+ rProp.Attributes,
+ 0); //nFlags
+ maMap.insert( aTemp );
+ }
+}
+
+SfxExtItemPropertySetInfo::~SfxExtItemPropertySetInfo()
+{
+}
+
+Sequence< Property > SAL_CALL SfxExtItemPropertySetInfo::getProperties( )
+{
+ if( !m_aPropSeq.hasElements() )
+ {
+ m_aPropSeq.realloc( maMap.size() );
+ beans::Property* pPropArray = m_aPropSeq.getArray();
+ sal_uInt32 n = 0;
+ for( const SfxItemPropertyMapEntry& rEntry : maMap )
+ {
+ pPropArray[n].Name = rEntry.aName;
+ pPropArray[n].Handle = rEntry.nWID;
+ pPropArray[n].Type = rEntry.aType;
+ pPropArray[n].Attributes =
+ sal::static_int_cast< sal_Int16 >(rEntry.nFlags);
+ n++;
+ }
+ }
+
+ return m_aPropSeq;
+}
+
+Property SAL_CALL SfxExtItemPropertySetInfo::getPropertyByName( const OUString& rPropertyName )
+{
+ const SfxItemPropertyMapEntry* pEntry = getByName(rPropertyName);
+ if( !pEntry )
+ throw UnknownPropertyException(rPropertyName);
+ beans::Property aProp;
+ aProp.Name = rPropertyName;
+ aProp.Handle = pEntry->nWID;
+ aProp.Type = pEntry->aType;
+ aProp.Attributes = sal::static_int_cast< sal_Int16 >(pEntry->nFlags);
+ return aProp;
+}
+
+sal_Bool SAL_CALL SfxExtItemPropertySetInfo::hasPropertyByName( const OUString& rPropertyName )
+{
+ return getByName(rPropertyName) != nullptr;
+}
+
+const SfxItemPropertyMapEntry* SfxExtItemPropertySetInfo::getByName( std::u16string_view rName ) const
+{
+ struct Compare
+ {
+ bool operator() ( const SfxItemPropertyMapEntry& lhs, std::u16string_view rhs ) const
+ {
+ return lhs.aName < rhs;
+ }
+ bool operator() ( std::u16string_view lhs, const SfxItemPropertyMapEntry& rhs ) const
+ {
+ return lhs < rhs.aName;
+ }
+ };
+ auto it = std::lower_bound(maMap.begin(), maMap.end(), rName, Compare());
+ if (it == maMap.end() || Compare()(rName, *it))
+ return nullptr;
+ return &*it;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
new file mode 100644
index 0000000000..66780cb581
--- /dev/null
+++ b/svl/source/items/itemset.cxx
@@ -0,0 +1,2068 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <string.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+
+#include <libxml/xmlwriter.h>
+
+#include <sal/log.hxx>
+#include <svl/itemset.hxx>
+#include <svl/itempool.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/setitem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/voiditem.hxx>
+
+#include <items_helper.hxx>
+
+#ifdef DBG_UTIL
+static size_t nAllocatedSfxItemSetCount(0);
+static size_t nUsedSfxItemSetCount(0);
+static size_t nAllocatedSfxPoolItemHolderCount(0);
+static size_t nUsedSfxPoolItemHolderCount(0);
+size_t getAllocatedSfxItemSetCount() { return nAllocatedSfxItemSetCount; }
+size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
+size_t getAllocatedSfxPoolItemHolderCount() { return nAllocatedSfxPoolItemHolderCount; }
+size_t getUsedSfxPoolItemHolderCount() { return nUsedSfxPoolItemHolderCount; }
+#endif
+// NOTE: Only needed for one Item in SC (see notes below for
+// ScPatternAttr/ATTR_PATTERN). Still keep it so that when errors
+// come up to this change be able to quickly check using the
+// fallback flag 'ITEM_CLASSIC_MODE'
+static bool g_bItemClassicMode(getenv("ITEM_CLASSIC_MODE"));
+
+// I thought about this constructor a while, but when there is no
+// Item we need no cleanup at destruction (what we would need the
+// Pool for), so it is OK and makes default construction easier
+// when no Pool is needed. The other constructors guanantee that
+// there *cannot* be a state with Item set and Pool not set. IF
+// you change this class, ALWAYS ensure that this can not happen (!)
+SfxPoolItemHolder::SfxPoolItemHolder()
+: m_pPool(nullptr)
+, m_pItem(nullptr)
+#ifdef DBG_UTIL
+, m_bDeleted(false)
+#endif
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxPoolItemHolderCount++;
+ nUsedSfxPoolItemHolderCount++;
+#endif
+}
+
+SfxPoolItemHolder::SfxPoolItemHolder(SfxItemPool& rPool, const SfxPoolItem* pItem, bool bPassingOwnership)
+: m_pPool(&rPool)
+, m_pItem(pItem)
+#ifndef NDEBUG
+, m_bDeleted(false)
+#endif
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxPoolItemHolderCount++;
+ nUsedSfxPoolItemHolderCount++;
+#endif
+ if (nullptr != m_pItem)
+ m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), bPassingOwnership);
+}
+
+SfxPoolItemHolder::SfxPoolItemHolder(const SfxPoolItemHolder& rHolder)
+: m_pPool(rHolder.m_pPool)
+, m_pItem(rHolder.m_pItem)
+#ifndef NDEBUG
+, m_bDeleted(false)
+#endif
+{
+#ifdef DBG_UTIL
+ assert(!rHolder.isDeleted() && "Destructed instance used (!)");
+ nAllocatedSfxPoolItemHolderCount++;
+ nUsedSfxPoolItemHolderCount++;
+#endif
+ if (nullptr != m_pItem)
+ m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false);
+}
+
+SfxPoolItemHolder::~SfxPoolItemHolder()
+{
+#ifdef DBG_UTIL
+ assert(!isDeleted() && "Destructed instance used (!)");
+ nAllocatedSfxPoolItemHolderCount--;
+#endif
+ if (nullptr != m_pItem)
+ implCleanupItemEntry(*m_pPool, m_pItem);
+#ifdef DBG_UTIL
+ m_bDeleted = true;
+#endif
+}
+
+const SfxPoolItemHolder& SfxPoolItemHolder::operator=(const SfxPoolItemHolder& rHolder)
+{
+ assert(!isDeleted() && "Destructed instance used (!)");
+ assert(!rHolder.isDeleted() && "Destructed instance used (!)");
+ if (this == &rHolder || *this == rHolder)
+ return *this;
+
+ if (nullptr != m_pItem)
+ implCleanupItemEntry(*m_pPool, m_pItem);
+
+ m_pPool = rHolder.m_pPool;
+ m_pItem = rHolder.m_pItem;
+
+ if (nullptr != m_pItem)
+ m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false);
+
+ return *this;
+}
+
+bool SfxPoolItemHolder::operator==(const SfxPoolItemHolder &rHolder) const
+{
+ assert(!isDeleted() && "Destructed instance used (!)");
+ assert(!rHolder.isDeleted() && "Destructed instance used (!)");
+ return m_pPool == rHolder.m_pPool && areSfxPoolItemPtrsEqual(m_pItem, rHolder.m_pItem);
+}
+
+/**
+ * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
+ * the supplied SfxItemPool.
+ *
+ * For Sfx programmers: an SfxItemSet constructed in this way cannot
+ * contain any Items with SlotIds as Which values.
+ *
+ * Don't create ItemSets with full range before FreezeIdRanges()!
+ */
+SfxItemSet::SfxItemSet(SfxItemPool& rPool)
+ : m_pPool(&rPool)
+ , m_pParent(nullptr)
+ , m_nCount(0)
+ , m_nTotalCount(svl::detail::CountRanges(rPool.GetFrozenIdRanges()))
+ , m_bItemsFixed(false)
+ , m_ppItems(new SfxPoolItem const *[m_nTotalCount]{})
+ , m_pWhichRanges(rPool.GetFrozenIdRanges())
+ , m_aCallback()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+ assert(svl::detail::validRanges2(m_pWhichRanges));
+}
+
+SfxItemSet::SfxItemSet( SfxItemPool& rPool, SfxAllItemSetFlag )
+ : m_pPool(&rPool)
+ , m_pParent(nullptr)
+ , m_nCount(0)
+ , m_nTotalCount(0)
+ , m_bItemsFixed(false)
+ , m_ppItems(nullptr)
+ , m_pWhichRanges()
+ , m_aCallback()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+}
+
+/** special constructor for SfxItemSetFixed */
+SfxItemSet::SfxItemSet( SfxItemPool& rPool, WhichRangesContainer&& ranges, SfxPoolItem const ** ppItems, sal_uInt16 nTotalCount )
+ : m_pPool(&rPool)
+ , m_pParent(nullptr)
+ , m_nCount(0)
+ , m_nTotalCount(nTotalCount)
+ , m_bItemsFixed(true)
+ , m_ppItems(ppItems)
+ , m_pWhichRanges(std::move(ranges))
+ , m_aCallback()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+ assert(ppItems);
+ assert(m_pWhichRanges.size() > 0);
+ assert(svl::detail::validRanges2(m_pWhichRanges));
+}
+
+SfxItemSet::SfxItemSet(SfxItemPool& pool, WhichRangesContainer wids)
+ : m_pPool(&pool)
+ , m_pParent(nullptr)
+ , m_nCount(0)
+ , m_nTotalCount(svl::detail::CountRanges(wids))
+ , m_bItemsFixed(false)
+ , m_ppItems(new SfxPoolItem const *[m_nTotalCount]{})
+ , m_pWhichRanges(std::move(wids))
+ , m_aCallback()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+ assert(svl::detail::CountRanges(m_pWhichRanges) != 0);
+ assert(svl::detail::validRanges2(m_pWhichRanges));
+}
+
+SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource, sal_uInt16 nWhich, bool bPassingOwnership)
+{
+ if (nullptr == pSource)
+ // SfxItemState::UNKNOWN aka current default (nullptr)
+ // just use/return nullptr
+ return nullptr;
+
+ if (IsInvalidItem(pSource))
+ // SfxItemState::DONTCARE aka invalid item
+ // just use pSource which equals INVALID_POOL_ITEM
+ return pSource;
+
+ if (pSource->isExceptionalSCItem() && rPool.GetMasterPool()->newItem_UseDirect(*pSource))
+ // exceptional handling for *some* items, see SC
+ // (do not copy item: use directly, it is a pool default)
+ return pSource;
+
+ // CAUTION: static default items are not *that* static as it seems
+ // (or: should be). If they are freed with the Pool (see
+ // ::ReleaseDefaults) they will be deleted. Same is true for
+ // dynamic defaults. Thus currently no default can be shared
+ // at all since these may be deleted with the pool owning them.
+ // That these are not shared but cloned is ensured by those
+ // having a default RefCount of zero, so these are used merely as
+ // templates.
+ // if (IsStaticDefaultItem(pSource))
+ // return pSource;
+
+ if (0 == pSource->Which())
+ // These *should* be SfxVoidItem(0) the only Items with 0 == WhichID,
+ // these need to be cloned (currently...)
+ return pSource->Clone();
+
+ // get correct target WhichID
+ if (0 == nWhich)
+ nWhich = pSource->Which();
+
+ if (SfxItemPool::IsSlot(nWhich))
+ {
+ // SlotItems were always cloned in original (even when bPassingOwnership),
+ // so do that here, too (but without bPassingOwnership).
+ // They do not need to be registered at pool (actually impossible, pools
+ // do not have entries for SlotItems) so handle here early
+ if (!bPassingOwnership)
+ pSource = pSource->Clone(rPool.GetMasterPool());
+
+ if (pSource->Which() != nWhich)
+ const_cast<SfxPoolItem*>(pSource)->SetWhich(nWhich);
+
+ pSource->AddRef();
+ return pSource;
+ }
+
+ // get the pool with which ItemSets have to work, plus get the
+ // pool at which the WhichID is defined, so calls to it do not
+ // have to do this repeatedly
+ SfxItemPool* pMasterPool(rPool.GetMasterPool());
+ assert(nullptr != pMasterPool);
+ SfxItemPool* pTargetPool(pMasterPool);
+ while (!pTargetPool->IsInRange(nWhich))
+ pTargetPool = pTargetPool->GetSecondaryPool();
+
+ // if this goes wrong, an Item with invalid ID for this pool is
+ // processed. This is not allowed (and should not happen, e.g.
+ // ItemSets already have WhichRanges that are checked against
+ // their Pool)
+ if (nullptr == pTargetPool)
+ {
+ assert(false);
+ return pSource;
+ }
+
+ // CAUTION: Shareable_Impl and NeedsPoolRegistration_Impl
+ // use index, not WhichID (one more reason to change the Pools)
+ const sal_uInt16 nIndex(pTargetPool->GetIndex_Impl(nWhich));
+
+ // the Item itself is shareable when it already is used somewhere
+ // which is equivalent to be referenced already. IsPooledItem also
+ // checked for SFX_ITEMS_MAXREF, that is not needed here. Use a
+ // fake 'while' loop and 'break' to make this better readable
+
+ // only try to share items that are already shared somehow, else
+ // these items are probably not (heap) item-ptr's (but on the
+ // stack or else)
+ while(pSource->GetRefCount() > 0)
+ {
+ if (pSource->Which() != nWhich)
+ // If the target WhichID differs from the WhichID of a shared Item
+ // the item needs to be cloned. This happens, e.g. in
+ // ScPatternAttr::GetFromEditItemSet existing items with WhichIDs
+ // from EditEngine get set at a SetItem's ItemSet with different
+ // target ranges (e.g. look for ATTR_FONT_UNDERLINE)
+ break;
+
+ if (!pTargetPool->Shareable_Impl(nIndex))
+ // not shareable, done
+ break;
+
+ // SfxSetItems cannot be shared if they are in/use another pool
+ if (pSource->isSetItem() && static_cast<const SfxSetItem*>(pSource)->GetItemSet().GetPool() != pMasterPool)
+ break;
+
+ // If the Item is registered it is pool-dependent, so do not share when
+ // it is registered but not at this pool
+ if (pSource->isRegisteredAtPool() && !pTargetPool->isSfxPoolItemRegisteredAtThisPool(*pSource))
+ break;
+
+ // If we get here we can share the Item
+ pSource->AddRef();
+ return pSource;
+ }
+
+ // g_bItemClassicMode: try finding already existing item
+ // NOTE: the UnitTest testIteratorsDefPattern claims that that Item "can be
+ // edited by the user" which explains why it breaks so many rules for Items,
+ // it behaves like an alien. That Item in the SC Pool claims to be a
+ // 'StaticDefault' and gets changed (..?)
+
+ // only do this if classic mode or required (calls from Pool::Direct*)
+ while(g_bItemClassicMode || pSource->isExceptionalSCItem())
+ {
+ if (!pTargetPool->Shareable_Impl(nIndex))
+ // not shareable, so no need to search for identical item
+ break;
+
+ // try to get equal Item. This is the expensive part...
+ const SfxPoolItem* pExisting(pTargetPool->tryToGetEqualItem(*pSource, nWhich));
+
+ if (nullptr == pExisting)
+ // none found, done
+ break;
+
+ if (0 == pExisting->GetRefCount())
+ // do not share not-yet shared Items (should not happen)
+ break;
+
+ if (bPassingOwnership)
+ // need to cleanup if we are offered to own pSource
+ delete pSource;
+
+ // If we get here we can share the found Item
+ pExisting->AddRef();
+ return pExisting;
+ }
+
+ // check if the handed over and to be directly used item is a
+ // SfxSetItem, that would make it pool-dependent. It then must have
+ // the same target-pool, ensure that by the cost of cloning it
+ // (should not happen)
+ if (bPassingOwnership
+ && pSource->isSetItem()
+ && static_cast<const SfxSetItem*>(pSource)->GetItemSet().GetPool() != pMasterPool)
+ {
+ const SfxPoolItem* pOld(pSource);
+ pSource = pSource->Clone(pMasterPool);
+ delete pOld;
+ }
+
+ // when we reach this line we know that we have to add/create a new item. If
+ // bPassingOwnership is given just use the item, else clone it
+ if (!bPassingOwnership)
+ pSource = pSource->Clone(pMasterPool);
+
+ // ensure WhichID @Item
+ if (pSource->Which() != nWhich)
+ const_cast<SfxPoolItem*>(pSource)->SetWhich(nWhich);
+
+ // increase RefCnt 0->1
+ pSource->AddRef();
+
+ // Unfortunately e,g, SC does 'special' things for some new Items,
+ // so we need to give the opportunity for this. To limit this to
+ // the needed cases, use m_bExceptionalSCItem flag at item
+ if (pSource->isExceptionalSCItem())
+ pMasterPool->newItem_Callback(*pSource);
+
+ // try to register @Pool (only needed if not yet registered)
+ if (!pSource->isRegisteredAtPool())
+ {
+ bool bRegisterAtPool(pSource->isExceptionalSCItem());
+
+ if (!bRegisterAtPool)
+ {
+ if (g_bItemClassicMode)
+ {
+ // in classic mode register only/all shareable items
+ bRegisterAtPool = pTargetPool->Shareable_Impl(nIndex);
+ }
+ else
+ {
+ // in new mode register only/all items marked as need to be registered
+ bRegisterAtPool = pTargetPool->NeedsPoolRegistration_Impl(nIndex);
+ }
+ }
+
+ if (bRegisterAtPool)
+ pTargetPool->registerSfxPoolItem(*pSource);
+ }
+
+ return pSource;
+}
+
+void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource)
+{
+ if (nullptr == pSource)
+ // no entry, done
+ return;
+
+ if (IsInvalidItem(pSource))
+ // nothing to do for invalid item entries
+ return;
+
+ if (pSource->isExceptionalSCItem() && rPool.GetMasterPool()->newItem_UseDirect(*pSource))
+ // exceptional handling for *some* items, see SC
+ // do not delete Item, it is a pool default
+ return;
+
+ if (0 == pSource->Which())
+ {
+ // de-register when registered @pool
+ if (pSource->isRegisteredAtPool())
+ rPool.unregisterSfxPoolItem(*pSource);
+
+ // These *should* be SfxVoidItem(0) the only Items with 0 == WhichID
+ // and need to be deleted
+ delete pSource;
+ return;
+ }
+
+ if (1 < pSource->GetRefCount())
+ {
+ // Still multiple references present, so just alter the RefCount
+ pSource->ReleaseRef();
+ return;
+ }
+
+ if (IsDefaultItem(pSource))
+ // default items (static and dynamic) are owned by the pool, do not delete
+ return;
+
+ // decrease RefCnt before deleting (destructor asserts for it and that's
+ // good to find other errors)
+ pSource->ReleaseRef();
+
+ // de-register before deletion when registered @pool
+ if (pSource->isRegisteredAtPool())
+ rPool.unregisterSfxPoolItem(*pSource);
+
+ // delete Item
+ delete pSource;
+}
+
+SfxItemSet::SfxItemSet( const SfxItemSet& rASet )
+ : m_pPool( rASet.m_pPool )
+ , m_pParent( rASet.m_pParent )
+ , m_nCount( rASet.m_nCount )
+ , m_nTotalCount( rASet.m_nTotalCount )
+ , m_bItemsFixed(false)
+ , m_ppItems(nullptr)
+ , m_pWhichRanges( rASet.m_pWhichRanges )
+ , m_aCallback(rASet.m_aCallback)
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+ if (rASet.GetRanges().empty())
+ {
+ return;
+ }
+
+ if (0 == rASet.Count())
+ {
+ // no Items set in source ItemSet, allocate new array
+ // *plus* init to nullptr
+ m_ppItems = new const SfxPoolItem* [TotalCount()]{};
+ return;
+ }
+
+ // allocate new array (no need to initialize, will be done below)
+ m_ppItems = new const SfxPoolItem* [TotalCount()];
+
+ // Copy attributes
+ SfxPoolItem const** ppDst(m_ppItems);
+
+ for (const auto& rSource : rASet)
+ {
+ *ppDst = implCreateItemEntry(*GetPool(), rSource, 0, false);
+ ppDst++;
+ }
+
+ assert(svl::detail::validRanges2(m_pWhichRanges));
+}
+
+SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept
+ : m_pPool( rASet.m_pPool )
+ , m_pParent( rASet.m_pParent )
+ , m_nCount( rASet.m_nCount )
+ , m_nTotalCount( rASet.m_nTotalCount )
+ , m_bItemsFixed(false)
+ , m_ppItems( rASet.m_ppItems )
+ , m_pWhichRanges( std::move(rASet.m_pWhichRanges) )
+ , m_aCallback(rASet.m_aCallback)
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount++;
+ nUsedSfxItemSetCount++;
+#endif
+ if (rASet.m_bItemsFixed)
+ {
+ // have to make a copy
+ m_ppItems = new const SfxPoolItem* [TotalCount()];
+
+ // can just copy the pointers, the ones in the original m_ppItems
+ // array will no longer be used/referenced (unused mem, but not lost,
+ // it's part of the ItemSet-derived object)
+ std::copy(rASet.m_ppItems, rASet.m_ppItems + TotalCount(), m_ppItems);
+ }
+ else
+ {
+ // taking over ownership
+ rASet.m_nTotalCount = 0;
+ rASet.m_ppItems = nullptr;
+ }
+ rASet.m_pPool = nullptr;
+ rASet.m_pParent = nullptr;
+ rASet.m_nCount = 0;
+
+ assert(svl::detail::validRanges2(m_pWhichRanges));
+}
+
+SfxItemSet::~SfxItemSet()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxItemSetCount--;
+#endif
+ // cleanup items. No std::fill needed, we are done with this ItemSet.
+ // the callback is not set in destructor, so no worries about that
+ ClearAllItemsImpl();
+
+ if (!m_bItemsFixed)
+ {
+ // free SfxPoolItem array
+ delete[] m_ppItems;
+ }
+
+ // for invariant-testing
+ m_pWhichRanges.reset();
+}
+
+// Delete single Items or all Items (nWhich == 0)
+sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
+{
+ if( !Count() )
+ return 0;
+
+ if( nWhich )
+ return ClearSingleItem_ForWhichID(nWhich);
+
+ // clear all & reset to nullptr
+ const sal_uInt16 nRetval(ClearAllItemsImpl());
+ std::fill(begin(), begin() + TotalCount(), nullptr);
+ return nRetval;
+}
+
+sal_uInt16 SfxItemSet::ClearSingleItem_ForWhichID( sal_uInt16 nWhich )
+{
+ const sal_uInt16 nOffset(GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ // found, continue with offset
+ return ClearSingleItem_ForOffset(nOffset);
+ }
+
+ // not found, return sal_uInt16 nDel = 0;
+ return 0;
+}
+
+sal_uInt16 SfxItemSet::ClearSingleItem_ForOffset( sal_uInt16 nOffset )
+{
+ assert(nOffset < TotalCount());
+ const_iterator aEntry(begin() + nOffset);
+ assert(nullptr == *aEntry || IsInvalidItem(*aEntry) || (*aEntry)->isVoidItem() || 0 != (*aEntry)->Which());
+
+ if (nullptr == *aEntry)
+ // no entry, done
+ return 0;
+
+ // we reset an entry to nullptr -> decrement count
+ --m_nCount;
+
+ // Notification-Callback
+ if(m_aCallback)
+ {
+ m_aCallback(*aEntry, nullptr);
+ }
+
+ // cleanup item & reset ptr
+ implCleanupItemEntry(*GetPool(), *aEntry);
+ *aEntry = nullptr;
+
+ return 1;
+}
+
+sal_uInt16 SfxItemSet::ClearAllItemsImpl()
+{
+ if (0 == Count())
+ // no items set, done
+ return 0;
+
+ // loop & cleanup items
+ for (auto& rCandidate : *this)
+ {
+ if (nullptr != rCandidate && m_aCallback)
+ {
+ m_aCallback(rCandidate, nullptr);
+ }
+
+ implCleanupItemEntry(*GetPool(), rCandidate);
+ }
+
+ // remember count before resetting it, that is the retval
+ const sal_uInt16 nRetval(Count());
+ m_nCount = 0;
+ return nRetval;
+}
+
+void SfxItemSet::ClearInvalidItems()
+{
+ if (0 == Count())
+ // no items set, done
+ return;
+
+ // loop, here using const_iterator due to need to set ptr in m_ppItems array
+ for (const_iterator candidate(begin()); candidate != end(); candidate++)
+ {
+ if (IsInvalidItem(*candidate))
+ {
+ *candidate = nullptr;
+ --m_nCount;
+ }
+ }
+}
+
+void SfxItemSet::InvalidateAllItems()
+{
+ // instead of just asserting, do the change. Clear all items
+ ClearAllItemsImpl();
+
+ // set all to invalid
+ std::fill(begin(), begin() + TotalCount(), INVALID_POOL_ITEM);
+
+ // ...and correct the count - invalid items get counted
+ m_nCount = m_nTotalCount;
+}
+
+SfxItemState SfxItemSet::GetItemState_ForWhichID( SfxItemState eState, sal_uInt16 nWhich, bool bSrchInParent, const SfxPoolItem **ppItem) const
+{
+ const sal_uInt16 nOffset(GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ // found, continue with offset
+ eState = GetItemState_ForOffset(nOffset, ppItem);
+ }
+
+ // search in parent?
+ if (bSrchInParent && nullptr != GetParent() && (SfxItemState::UNKNOWN == eState || SfxItemState::DEFAULT == eState))
+ {
+ // nOffset was only valid for *local* SfxItemSet, need to continue with WhichID
+ // Use the *highest* SfxItemState as result
+ return GetParent()->GetItemState_ForWhichID( eState, nWhich, true, ppItem);
+ }
+
+ return eState;
+}
+
+SfxItemState SfxItemSet::GetItemState_ForOffset( sal_uInt16 nOffset, const SfxPoolItem **ppItem) const
+{
+ // check and assert from invalid offset. The caller is responsible for
+ // ensuring a valid offset (see callers, all checked & safe)
+ assert(nOffset < TotalCount());
+ SfxPoolItem const* pCandidate(*(begin() + nOffset));
+
+ if (nullptr == pCandidate)
+ // set to Default
+ return SfxItemState::DEFAULT;
+
+ if (IsInvalidItem(pCandidate))
+ // Different ones are present
+ return SfxItemState::DONTCARE;
+
+ if (pCandidate->isVoidItem())
+ // Item is Disabled
+ return SfxItemState::DISABLED;
+
+ if (nullptr != ppItem)
+ // if we have the Item, add it to output an hand back
+ *ppItem = pCandidate;
+
+ // Item is set
+ return SfxItemState::SET;
+}
+
+bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
+{
+ const bool bRet(SfxItemState::SET == GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, true, ppItem));
+
+ // we need to reset ppItem when it was *not* set by GetItemState_ForWhichID
+ // since many usages of that return parameter re-use it, so it might still
+ // be set to 'something'
+ if (!bRet && nullptr != ppItem)
+ {
+ *ppItem = nullptr;
+ }
+
+ return bRet;
+}
+
+const SfxPoolItem* SfxItemSet::PutImpl(const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership)
+{
+ bool bActionNeeded(0 != nWhich);
+ sal_uInt16 nOffset(INVALID_WHICHPAIR_OFFSET);
+
+#ifdef _WIN32
+ // Win build *insists* for initialization, triggers warning C4701:
+ // "potentially uninitialized local variable 'aEntry' used" for
+ // lines below. This is not the case here, but I know of no way
+ // to silence the warning in another way
+ const_iterator aEntry(begin());
+#else
+ const_iterator aEntry;
+#endif
+
+ if (bActionNeeded)
+ {
+ nOffset = GetRanges().getOffsetFromWhich(nWhich);
+ bActionNeeded = (INVALID_WHICHPAIR_OFFSET != nOffset);
+ }
+
+ if (bActionNeeded)
+ {
+ aEntry = begin() + nOffset;
+
+ if (nullptr == *aEntry)
+ {
+ // increase count if there was no entry before
+ ++m_nCount;
+ }
+ else
+ {
+ // compare items, evtl. containing content compare
+ bActionNeeded = !SfxPoolItem::areSame(**aEntry, rItem);
+ }
+ }
+
+ if (!bActionNeeded)
+ {
+ if (bPassingOwnership)
+ {
+ delete &rItem;
+ }
+
+ return nullptr;
+ }
+
+ // prepare new entry
+ SfxPoolItem const* pNew(implCreateItemEntry(*GetPool(), &rItem, nWhich, bPassingOwnership));
+
+ // Notification-Callback
+ if(m_aCallback)
+ {
+ m_aCallback(*aEntry, pNew);
+ }
+
+ // cleanup old entry & set entry at m_ppItems array
+ implCleanupItemEntry(*GetPool(), *aEntry);
+ *aEntry = pNew;
+
+ return pNew;
+}
+
+bool SfxItemSet::Put(const SfxItemSet& rSource, bool bInvalidAsDefault)
+{
+ if (0 == rSource.Count())
+ // no items in source, done
+ return false;
+
+ const_iterator aSource(rSource.begin());
+ sal_uInt16 nNumberToGo(rSource.Count());
+ bool bRetval(false);
+
+ // iterate based on WhichIDs to have it available for evtl. PutImpl calls
+ for (const WhichPair& rPair : rSource.GetRanges())
+ {
+ for (sal_uInt16 nWhich(rPair.first); nWhich <= rPair.second; nWhich++, aSource++)
+ {
+ if (nullptr != *aSource)
+ {
+ nNumberToGo--;
+
+ if (IsInvalidItem(*aSource))
+ {
+ if (bInvalidAsDefault)
+ {
+ bRetval |= 0 != ClearSingleItem_ForWhichID(nWhich);
+ }
+ else
+ {
+ InvalidateItem_ForWhichID(nWhich);
+ }
+ }
+ else
+ {
+ bRetval |= nullptr != PutImpl(**aSource, nWhich, false);
+ }
+ }
+
+ if (0 == nNumberToGo)
+ {
+ // we can return early if all set Items are handled
+ return bRetval;
+ }
+ }
+ }
+
+ return bRetval;
+}
+
+/**
+ * This method takes the Items from the 'rSet' and adds to '*this'.
+ * Which ranges in '*this' that are non-existent in 'rSet' will not
+ * be altered. The Which range of '*this' is also not changed.
+ *
+ * Items set in 'rSet' are also set in '*this'.
+ * Default (0 pointer) and Invalid (-1 pointer) Items are processed
+ * according to their parameter 'eDontCareAs' and 'eDefaultAs':
+ *
+ * SfxItemState::SET: Hard set to the default of the Pool
+ * SfxItemState::DEFAULT: Deleted (0 pointer)
+ * SfxItemState::DONTCARE: Invalid (-1 pointer)
+ *
+ * NB: All other values for 'eDontCareAs' and 'eDefaultAs' are invalid
+ */
+void SfxItemSet::PutExtended
+(
+ const SfxItemSet& rSource, // Source of the Items to be put
+ SfxItemState eDontCareAs, // What will happen to the DontCare Items
+ SfxItemState eDefaultAs // What will happen to the Default Items
+)
+{
+ // don't "optimize" with "if( rSource.Count()" because of dontcare + defaults
+ const_iterator aSource(rSource.begin());
+
+ for (const WhichPair& rPair : rSource.GetRanges())
+ {
+ for (sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; nWhich++, aSource++)
+ {
+ if (nullptr != *aSource)
+ {
+ if (IsInvalidItem(*aSource))
+ {
+ // Item is DontCare:
+ switch (eDontCareAs)
+ {
+ case SfxItemState::SET:
+ PutImpl(rSource.GetPool()->GetDefaultItem(nWhich), nWhich, false);
+ break;
+
+ case SfxItemState::DEFAULT:
+ ClearSingleItem_ForWhichID(nWhich);
+ break;
+
+ case SfxItemState::DONTCARE:
+ InvalidateItem_ForWhichID(nWhich);
+ break;
+
+ default:
+ assert(!"invalid Argument for eDontCareAs");
+ }
+ }
+ else
+ {
+ // Item is set:
+ PutImpl(**aSource, nWhich, false);
+ }
+ }
+ else
+ {
+ // Item is default:
+ switch (eDefaultAs)
+ {
+ case SfxItemState::SET:
+ PutImpl(rSource.GetPool()->GetDefaultItem(nWhich), nWhich, false);
+ break;
+
+ case SfxItemState::DEFAULT:
+ ClearSingleItem_ForWhichID(nWhich);
+ break;
+
+ case SfxItemState::DONTCARE:
+ InvalidateItem_ForWhichID(nWhich);
+ break;
+
+ default:
+ assert(!"invalid Argument for eDefaultAs");
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
+ * items which are new ranges too.
+ */
+void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
+{
+ // check if all from new range are already included. This will
+ // use the cache in WhichRangesContainer since we check linearly.
+ // Start with assuming all are included, but only if not empty.
+ // If empty all included is wrong (and GetRanges().MergeRange
+ // will do the right thing/shortcut)
+ bool bAllIncluded(!GetRanges().empty());
+
+ for (sal_uInt16 a(nFrom); bAllIncluded && a <= nTo; a++)
+ if (INVALID_WHICHPAIR_OFFSET == GetRanges().getOffsetFromWhich(a))
+ bAllIncluded = false;
+
+ // if yes, we are done
+ if (bAllIncluded)
+ return;
+
+ // need to create new WhichRanges
+ auto pNewRanges = m_pWhichRanges.MergeRange(nFrom, nTo);
+ RecreateRanges_Impl(pNewRanges);
+ m_pWhichRanges = std::move(pNewRanges);
+}
+
+/**
+ * Modifies the ranges of settable items. Keeps state of items which
+ * are new ranges too.
+ */
+void SfxItemSet::SetRanges( const WhichRangesContainer& pNewRanges )
+{
+ // Identical Ranges?
+ if (GetRanges() == pNewRanges)
+ return;
+
+ assert(svl::detail::validRanges2(pNewRanges));
+ RecreateRanges_Impl(pNewRanges);
+ m_pWhichRanges = pNewRanges;
+}
+
+void SfxItemSet::SetRanges( WhichRangesContainer&& pNewRanges )
+{
+ // Identical Ranges?
+ if (GetRanges() == pNewRanges)
+ return;
+
+ assert(svl::detail::validRanges2(pNewRanges));
+ RecreateRanges_Impl(pNewRanges);
+ m_pWhichRanges = std::move(pNewRanges);
+}
+
+void SfxItemSet::RecreateRanges_Impl(const WhichRangesContainer& rNewRanges)
+{
+ // create new item-array (by iterating through all new ranges)
+ const sal_uInt16 nNewTotalCount(svl::detail::CountRanges(rNewRanges));
+ SfxPoolItem const** aNewItemArray(new const SfxPoolItem* [nNewTotalCount]);
+ sal_uInt16 nNewCount(0);
+
+ if (0 == Count())
+ {
+ // no Items set, just reset to nullptr (default)
+ std::fill(aNewItemArray, aNewItemArray + nNewTotalCount, nullptr);
+ }
+ else
+ {
+ // iterate over target - all entries there need to be set/initialized. Use
+ // WhichIDs, we need to access two different WhichRanges
+ const_iterator aNewTarget(aNewItemArray);
+
+ for (auto const & rNewRange : rNewRanges)
+ {
+ for (sal_uInt16 nWhich(rNewRange.first); nWhich <= rNewRange.second; nWhich++, aNewTarget++)
+ {
+ // check if we have that WhichID in source ranges
+ const sal_uInt16 nSourceOffset(GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET == nSourceOffset)
+ {
+ // no entry in source, init to nullptr
+ *aNewTarget = nullptr;
+ }
+ else
+ {
+ // we have entry in source, transfer entry - whatever it may be,
+ // also for nullptr (for initialization)
+ const_iterator aSourceEntry(begin() + nSourceOffset);
+ *aNewTarget = *aSourceEntry;
+
+ // take care of new Count
+ if (nullptr != *aNewTarget)
+ {
+ nNewCount++;
+ }
+
+ // reset entry, since it got transferred it should not be cleaned-up
+ *aSourceEntry = nullptr;
+ }
+ }
+ }
+
+ // free old items: only necessary when not all Items were transferred
+ if (nNewCount != Count())
+ {
+ ClearAllItemsImpl();
+ }
+ }
+
+ // replace old items-array and ranges
+ if (m_bItemsFixed)
+ {
+ m_bItemsFixed = false;
+ }
+ else
+ {
+ delete[] m_ppItems;
+ }
+
+ m_nTotalCount = nNewTotalCount;
+ m_ppItems = aNewItemArray;
+ m_nCount = nNewCount;
+}
+
+/**
+ * The SfxItemSet takes over exactly those SfxPoolItems that are
+ * set in rSet and are in their own Which range. All others are removed.
+ * The SfxItemPool is retained, such that SfxPoolItems that have been
+ * taken over, are moved from the rSet's SfxItemPool to the SfxItemPool
+ * of *this.
+ *
+ * SfxPoolItems in rSet, for which holds 'IsInvalidItem() == true' are
+ * taken over as invalid items.
+ *
+ * @return bool true
+ * SfxPoolItems have been taken over
+ *
+ * false
+ * No SfxPoolItems have been taken over, because
+ * e.g. the Which ranges of SfxItemSets are not intersecting
+ * or the intersection does not contain SfxPoolItems that are
+ * set in rSet
+ */
+bool SfxItemSet::Set
+(
+ const SfxItemSet& rSet, /* The SfxItemSet, whose SfxPoolItems are
+ to been taken over */
+
+ bool bDeep /* true (default)
+
+ The SfxPoolItems from the parents that may
+ be present in rSet, are also taken over into
+ this SfxPoolItemSet
+
+ false
+ The SfxPoolItems from the parents of
+ rSet are not taken into account */
+)
+{
+ bool bRet = false;
+ if (Count())
+ ClearItem();
+ if ( bDeep )
+ {
+ SfxWhichIter aIter1(*this);
+ SfxWhichIter aIter2(rSet);
+ sal_uInt16 nWhich1 = aIter1.FirstWhich();
+ sal_uInt16 nWhich2 = aIter2.FirstWhich();
+ for (;;)
+ {
+ if (!nWhich1 || !nWhich2)
+ break;
+ if (nWhich1 > nWhich2)
+ {
+ nWhich2 = aIter2.NextWhich();
+ continue;
+ }
+ if (nWhich1 < nWhich2)
+ {
+ nWhich1 = aIter1.NextWhich();
+ continue;
+ }
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == aIter2.GetItemState( true, &pItem ) )
+ bRet |= nullptr != Put( *pItem, pItem->Which() );
+ nWhich1 = aIter1.NextWhich();
+ nWhich2 = aIter2.NextWhich();
+ }
+ }
+ else
+ bRet = Put(rSet, false);
+
+ return bRet;
+}
+
+const SfxPoolItem* SfxItemSet::GetItem(sal_uInt16 nId, bool bSearchInParent) const
+{
+ // evtl. Convert from SlotID to WhichId
+ const sal_uInt16 nWhich(GetPool()->GetWhich(nId));
+
+ // Is the Item set or 'bDeep == true' available?
+ const SfxPoolItem *pItem(nullptr);
+ const SfxItemState eState(GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, bSearchInParent, &pItem));
+
+ if (bSearchInParent && SfxItemState::DEFAULT == eState && SfxItemPool::IsWhich(nWhich))
+ {
+ pItem = &GetPool()->GetDefaultItem(nWhich);
+ }
+
+ return pItem;
+}
+
+const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) const
+{
+ // Search the Range in which the Which is located in:
+ const sal_uInt16 nOffset(GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ const_iterator aFoundOne(begin() + nOffset);
+
+ if (nullptr != *aFoundOne)
+ {
+ if (IsInvalidItem(*aFoundOne))
+ {
+ //FIXME: The following code is duplicated further down
+ assert(m_pPool);
+ //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
+ //!return aDefault;
+ return GetPool()->GetDefaultItem(nWhich);
+ }
+#ifdef DBG_UTIL
+ const SfxPoolItem *pItem = *aFoundOne;
+ if ( pItem->isVoidItem() || !pItem->Which() )
+ SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
+#endif
+ return **aFoundOne;
+ }
+ }
+
+ if (bSrchInParent && nullptr != GetParent())
+ {
+ return GetParent()->Get(nWhich, bSrchInParent);
+ }
+
+ // Get the Default from the Pool and return
+ assert(m_pPool);
+ return GetPool()->GetDefaultItem(nWhich);
+}
+
+/**
+ * Only retain the Items that are also present in rSet
+ * (nevermind their value).
+ */
+void SfxItemSet::Intersect( const SfxItemSet& rSet )
+{
+ // Delete all Items not contained in rSet
+ assert(m_pPool && "Not implemented without Pool");
+
+ if (!Count() || this == &rSet)
+ // none set -> none to delete
+ // same ItemSet? -> no Items not contained
+ return;
+
+ if (!rSet.Count())
+ {
+ // no Items contained in rSet -> Delete everything
+ ClearItem();
+ return;
+ }
+
+ // CAUTION: In the former impl, the
+ // - version for different ranges checked for SfxItemState::UNKNOWN
+ // in rSet -> this means that the WhichID is *not* defined in
+ // the ranges of rSet *at all* > definitely an *error*
+ // - version for same ranges checked for
+ // nullptr != local && nullptr == rSet.
+ // All together I think also using the text
+ // "Delete all Items not contained in rSet" leads to
+ // locally delete all Items that are *not* set in rSet
+ // -> != SfxItemState::SET
+
+ // same ranges?
+ if (GetRanges() == rSet.GetRanges())
+ {
+ for (sal_uInt16 nOffset(0); nOffset < TotalCount(); nOffset++)
+ {
+ if (SfxItemState::SET != rSet.GetItemState_ForOffset(nOffset, nullptr))
+ {
+ // can use same offset
+ ClearSingleItem_ForOffset(nOffset);
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nOffset(0);
+
+ for (auto const & rRange : GetRanges())
+ {
+ for (sal_uInt16 nWhich(rRange.first); nWhich <= rRange.second; nWhich++, nOffset++)
+ {
+ if (SfxItemState::SET != rSet.GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, false, nullptr))
+ {
+ // can use offset
+ ClearSingleItem_ForOffset(nOffset);
+ }
+ }
+ }
+ }
+}
+
+void SfxItemSet::Differentiate(const SfxItemSet& rSet)
+{
+ assert(m_pPool && "Not implemented without Pool");
+
+ // Delete all Items contained in rSet
+ if (!Count() || !rSet.Count())
+ // None set?
+ return;
+
+ if (this == &rSet)
+ {
+ // same ItemSet, all Items are contained -> Delete everything
+ ClearItem();
+ return;
+ }
+
+ // CAUTION: In the former impl, the
+ // - version for different ranges checked for SfxItemState::SET
+ // in rSet
+ // - version for same ranges checked for
+ // nullptr != local && nullptr != rSet.
+ // All together I think also using the text
+ // "Delete all Items contained in rSet" leads to
+ // locally delete all Items that *are *not* set in rSet
+ // -> ==SfxItemState::SET
+
+ // same ranges?
+ if (GetRanges() == rSet.GetRanges())
+ {
+ for (sal_uInt16 nOffset(0); nOffset < TotalCount(); nOffset++)
+ {
+ if (SfxItemState::SET == rSet.GetItemState_ForOffset(nOffset, nullptr))
+ {
+ // can use same offset
+ ClearSingleItem_ForOffset(nOffset);
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nOffset(0);
+
+ for (auto const & rRange : GetRanges())
+ {
+ for (sal_uInt16 nWhich(rRange.first); nWhich <= rRange.second; nWhich++, nOffset++)
+ {
+ if (SfxItemState::SET == rSet.GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, false, nullptr))
+ {
+ // can use offset
+ ClearSingleItem_ForOffset(nOffset);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Decision table for MergeValue(s)
+ *
+ * Principles:
+ * 1. If the Which value in the 1st set is "unknown", there's never any action
+ * 2. If the Which value in the 2nd set is "unknown", it's made the "default"
+ * 3. For comparisons the values of the "default" Items are take into account
+ *
+ * 1st Item 2nd Item Values bIgnoreDefs Remove Assign Add
+ *
+ * set set == sal_False - - -
+ * default set == sal_False - - -
+ * dontcare set == sal_False - - -
+ * unknown set == sal_False - - -
+ * set default == sal_False - - -
+ * default default == sal_False - - -
+ * dontcare default == sal_False - - -
+ * unknown default == sal_False - - -
+ * set dontcare == sal_False 1st Item -1 -
+ * default dontcare == sal_False - -1 -
+ * dontcare dontcare == sal_False - - -
+ * unknown dontcare == sal_False - - -
+ * set unknown == sal_False 1st Item -1 -
+ * default unknown == sal_False - - -
+ * dontcare unknown == sal_False - - -
+ * unknown unknown == sal_False - - -
+ *
+ * set set != sal_False 1st Item -1 -
+ * default set != sal_False - -1 -
+ * dontcare set != sal_False - - -
+ * unknown set != sal_False - - -
+ * set default != sal_False 1st Item -1 -
+ * default default != sal_False - - -
+ * dontcare default != sal_False - - -
+ * unknown default != sal_False - - -
+ * set dontcare != sal_False 1st Item -1 -
+ * default dontcare != sal_False - -1 -
+ * dontcare dontcare != sal_False - - -
+ * unknown dontcare != sal_False - - -
+ * set unknown != sal_False 1st Item -1 -
+ * default unknown != sal_False - - -
+ * dontcare unknown != sal_False - - -
+ * unknown unknown != sal_False - - -
+ *
+ * set set == sal_True - - -
+ * default set == sal_True - 2nd Item 2nd Item
+ * dontcare set == sal_True - - -
+ * unknown set == sal_True - - -
+ * set default == sal_True - - -
+ * default default == sal_True - - -
+ * dontcare default == sal_True - - -
+ * unknown default == sal_True - - -
+ * set dontcare == sal_True - - -
+ * default dontcare == sal_True - -1 -
+ * dontcare dontcare == sal_True - - -
+ * unknown dontcare == sal_True - - -
+ * set unknown == sal_True - - -
+ * default unknown == sal_True - - -
+ * dontcare unknown == sal_True - - -
+ * unknown unknown == sal_True - - -
+ *
+ * set set != sal_True 1st Item -1 -
+ * default set != sal_True - 2nd Item 2nd Item
+ * dontcare set != sal_True - - -
+ * unknown set != sal_True - - -
+ * set default != sal_True - - -
+ * default default != sal_True - - -
+ * dontcare default != sal_True - - -
+ * unknown default != sal_True - - -
+ * set dontcare != sal_True 1st Item -1 -
+ * default dontcare != sal_True - -1 -
+ * dontcare dontcare != sal_True - - -
+ * unknown dontcare != sal_True - - -
+ * set unknown != sal_True - - -
+ * default unknown != sal_True - - -
+ * dontcare unknown != sal_True - - -
+ * unknown unknown != sal_True - - -
+ */
+void SfxItemSet::MergeItem_Impl(const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2, bool bIgnoreDefaults)
+{
+ assert(ppFnd1 != nullptr && "Merging to 0-Item");
+
+ // 1st Item is Default?
+ if ( !*ppFnd1 )
+ {
+ if ( IsInvalidItem(pFnd2) )
+ // Decision table: default, dontcare, doesn't matter, doesn't matter
+ *ppFnd1 = INVALID_POOL_ITEM;
+
+ else if ( pFnd2 && !bIgnoreDefaults &&
+ GetPool()->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
+ // Decision table: default, set, !=, sal_False
+ *ppFnd1 = INVALID_POOL_ITEM;
+
+ else if ( pFnd2 && bIgnoreDefaults )
+ // Decision table: default, set, doesn't matter, sal_True
+ *ppFnd1 = implCreateItemEntry(*GetPool(), pFnd2, 0, false);
+ // *ppFnd1 = &GetPool()->Put( *pFnd2 );
+
+ if ( *ppFnd1 )
+ ++m_nCount;
+ }
+
+ // 1st Item set?
+ else if ( !IsInvalidItem(*ppFnd1) )
+ {
+ if ( !pFnd2 )
+ {
+ // 2nd Item is Default
+ if ( !bIgnoreDefaults &&
+ **ppFnd1 != GetPool()->GetDefaultItem((*ppFnd1)->Which()) )
+ {
+ // Decision table: set, default, !=, sal_False
+ implCleanupItemEntry(*GetPool(), *ppFnd1);
+ // GetPool()->Remove( **ppFnd1 );
+ *ppFnd1 = INVALID_POOL_ITEM;
+ }
+ }
+ else if ( IsInvalidItem(pFnd2) )
+ {
+ // 2nd Item is dontcare
+ if ( !bIgnoreDefaults ||
+ **ppFnd1 != GetPool()->GetDefaultItem( (*ppFnd1)->Which()) )
+ {
+ // Decision table: set, dontcare, doesn't matter, sal_False
+ // or: set, dontcare, !=, sal_True
+ implCleanupItemEntry(*GetPool(), *ppFnd1);
+ // GetPool()->Remove( **ppFnd1 );
+ *ppFnd1 = INVALID_POOL_ITEM;
+ }
+ }
+ else
+ {
+ // 2nd Item is set
+ if ( **ppFnd1 != *pFnd2 )
+ {
+ // Decision table: set, set, !=, doesn't matter
+ implCleanupItemEntry(*GetPool(), *ppFnd1);
+ // GetPool()->Remove( **ppFnd1 );
+ *ppFnd1 = INVALID_POOL_ITEM;
+ }
+ }
+ }
+}
+
+void SfxItemSet::MergeValues( const SfxItemSet& rSet )
+{
+ // WARNING! When making changes/fixing bugs, always update the table above!!
+ assert( GetPool() == rSet.GetPool() && "MergeValues with different Pools" );
+
+ // CAUTION: Old version did *different* things when the WhichRanges
+ // were the same (true) or different (false) (which is an error/
+ // false optimization):
+ // true: MergeItem_Impl was directly fed with SfxItem*'s
+ // for entry @this & @rSet
+ // false: Looped over rSet WhichID's, fetched defaults from pool,
+ // fed all that to SfxItemSet::MergeValue which then
+ // evtl. could not find that WhichID in local WhichRanges
+ // Better to loop over local WhichRanges (these get changed) and look
+ // for Item with same WhichID in rSet, this is done now.
+ if (GetRanges() == rSet.GetRanges())
+ {
+
+ // loop over both & merge, WhichIDs are identical
+ for (const_iterator dst(begin()), src(rSet.begin()); dst != end(); dst++, src++)
+ {
+ MergeItem_Impl(dst, *src, false/*bIgnoreDefaults*/);
+ }
+ }
+ else
+ {
+ // loop over local which-ranges - the local Items need to be changed
+ const_iterator dst(begin());
+
+ for (auto const & rRange : GetRanges())
+ {
+ for (sal_uInt16 nWhich(rRange.first); nWhich <= rRange.second; nWhich++, dst++)
+ {
+ // try to get offset in rSet for same WhichID
+ const sal_uInt16 nOffset(rSet.GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ // if entry with same WhichID exists in rSet, merge with local entry
+ MergeItem_Impl(dst, *(rSet.begin() + nOffset), false/*bIgnoreDefaults*/);
+ }
+ }
+ }
+ }
+}
+
+void SfxItemSet::MergeValue(const SfxPoolItem& rAttr, bool bIgnoreDefaults)
+{
+ if (0 == rAttr.Which())
+ // seems to be SfxVoidItem(0), nothing to do
+ return;
+
+ const sal_uInt16 nOffset(GetRanges().getOffsetFromWhich(rAttr.Which()));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ MergeItem_Impl(begin() + nOffset, &rAttr, bIgnoreDefaults);
+ }
+}
+
+void SfxItemSet::InvalidateItem_ForWhichID(sal_uInt16 nWhich)
+{
+ const sal_uInt16 nOffset(GetRanges().getOffsetFromWhich(nWhich));
+
+ if (INVALID_WHICHPAIR_OFFSET != nOffset)
+ {
+ InvalidateItem_ForOffset(nOffset);
+ }
+}
+
+void SfxItemSet::InvalidateItem_ForOffset(sal_uInt16 nOffset)
+{
+ // check and assert from invalid offset. The caller is responsible for
+ // ensuring a valid offset (see callers, all checked & safe)
+ assert(nOffset < TotalCount());
+ const_iterator aFoundOne(begin() + nOffset);
+
+ if (nullptr == *aFoundOne)
+ {
+ // entry goes from nullptr -> invalid
+ ++m_nCount;
+ }
+ else
+ {
+ // entry is set
+ if (IsInvalidItem(*aFoundOne))
+ // already invalid item, done
+ return;
+
+ // cleanup entry
+ implCleanupItemEntry(*GetPool(), *aFoundOne);
+ }
+
+ // set new entry
+ *aFoundOne = INVALID_POOL_ITEM;
+}
+
+sal_uInt16 SfxItemSet::GetWhichByOffset( sal_uInt16 nOffset ) const
+{
+ assert(nOffset < TotalCount());
+
+ // 1st try to get a set SfxPoolItem and fetch the WhichID from there.
+ const SfxPoolItem* pItem(nullptr);
+ (void)GetItemState_ForOffset(nOffset, &pItem);
+
+ if (nullptr != pItem && 0 != pItem->Which())
+ return pItem->Which();
+
+ // 2nd have to get from WhichRangesContainer. That might use
+ // the buffering, too. We might assert a return value of zero
+ // (which means invalid WhichID), but we already assert for
+ // a valid offset at the start of this method
+ return GetRanges().getWhichFromOffset(nOffset);
+}
+
+bool SfxItemSet::operator==(const SfxItemSet &rCmp) const
+{
+ return Equals( rCmp, true);
+}
+
+bool SfxItemSet::Equals(const SfxItemSet &rCmp, bool bComparePool) const
+{
+ // check if same incarnation
+ if (this == &rCmp)
+ return true;
+
+ // check parents (if requested, also bComparePool)
+ if (bComparePool && GetParent() != rCmp.GetParent())
+ return false;
+
+ // check pools (if requested)
+ if (bComparePool && GetPool() != rCmp.GetPool())
+ return false;
+
+ // check count of set items
+ if (Count() != rCmp.Count())
+ return false;
+
+ // both have no items, done
+ if (0 == Count())
+ return true;
+
+ // check if ranges are equal
+ if (GetRanges() == rCmp.GetRanges())
+ {
+ // if yes, we can simplify: are all pointers the same?
+ if (0 == memcmp( m_ppItems, rCmp.m_ppItems, TotalCount() * sizeof(m_ppItems[0]) ))
+ return true;
+
+ // compare each one separately
+ const SfxPoolItem **ppItem1(m_ppItems);
+ const SfxPoolItem **ppItem2(rCmp.m_ppItems);
+
+ for (sal_uInt16 nPos(0); nPos < TotalCount(); nPos++)
+ {
+ // do full SfxPoolItem compare
+ if (!SfxPoolItem::areSame(*ppItem1, *ppItem2))
+ return false;
+ ++ppItem1;
+ ++ppItem2;
+ }
+
+ return true;
+ }
+
+ // Not same ranges, need to compare content. Only need to check if
+ // the content of one is inside the other due to already having
+ // compared Count() above.
+ // Iterate over local SfxItemSet by using locval ranges and offset,
+ // so we can access needed data at least for one SfxItemSet more
+ // direct. For the 2nd one we need the WhichID which we have by
+ // iterating over the ranges.
+ sal_uInt16 nOffset(0);
+ sal_uInt16 nNumberToGo(Count());
+
+ for (auto const & rRange : GetRanges())
+ {
+ for (sal_uInt16 nWhich(rRange.first); nWhich <= rRange.second; nWhich++, nOffset++)
+ {
+ const SfxPoolItem *pItem1(nullptr);
+ const SfxPoolItem *pItem2(nullptr);
+ const SfxItemState aStateA(GetItemState_ForOffset(nOffset, &pItem1));
+ const SfxItemState aStateB(rCmp.GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, false, &pItem2));
+
+ if (aStateA != aStateB)
+ return false;
+
+ // only compare items if SfxItemState::SET, else the item ptrs are not set
+ if (SfxItemState::SET == aStateA && !SfxPoolItem::areSame(pItem1, pItem2))
+ return false;
+
+ if (SfxItemState::DEFAULT != aStateA)
+ // if local item is not-nullptr we have compared one more, reduce NumberToGo
+ // NOTE: we could also use 'nullptr != *(begin() + nOffset)' here, but the
+ // entry was already checked by GetItemState_ForOffset above
+ nNumberToGo--;
+
+ if (0 == nNumberToGo)
+ // if we have compared Count() number of items and are still here
+ // (all were equal), we can exit early
+ return true;
+ }
+ }
+
+ return true;
+}
+
+std::unique_ptr<SfxItemSet> SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
+{
+ if (pToPool && pToPool != GetPool())
+ {
+ std::unique_ptr<SfxItemSet> pNewSet(new SfxItemSet(*pToPool, GetRanges()));
+ if ( bItems )
+ {
+ SfxWhichIter aIter(*pNewSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if ( SfxItemState::SET == GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, false, &pItem ) )
+ pNewSet->Put( *pItem, pItem->Which() );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ return pNewSet;
+ }
+ else
+ return std::unique_ptr<SfxItemSet>(bItems
+ ? new SfxItemSet(*this)
+ : new SfxItemSet(*GetPool(), GetRanges()));
+}
+
+SfxItemSet SfxItemSet::CloneAsValue(bool bItems, SfxItemPool *pToPool ) const
+{
+ // if you are trying to clone, then the thing you are cloning is polymorphic, which means
+ // it cannot be cloned as a value
+ assert((typeid(*this) == typeid(SfxItemSet)) && "cannot call this on a subclass of SfxItemSet");
+
+ if (pToPool && pToPool != GetPool())
+ {
+ SfxItemSet aNewSet(*pToPool, GetRanges());
+ if ( bItems )
+ {
+ SfxWhichIter aIter(aNewSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if ( SfxItemState::SET == GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, false, &pItem ) )
+ aNewSet.Put( *pItem, pItem->Which() );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ return aNewSet;
+ }
+ else
+ return bItems
+ ? *this
+ : SfxItemSet(*GetPool(), GetRanges());
+}
+
+void SfxItemSet::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemSet"));
+ SfxItemIter aIter(*this);
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if (IsInvalidItem(pItem))
+ {
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("invalid"));
+ (void)xmlTextWriterEndElement(pWriter);
+ }
+ else
+ {
+ pItem->dumpAsXml(pWriter);
+ }
+ }
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+
+// ----------------------------------------------- class SfxAllItemSet
+
+SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
+: SfxItemSet(rPool, SfxAllItemSetFlag::Flag)
+{
+}
+
+SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
+: SfxItemSet(rCopy)
+{
+}
+
+/**
+ * Explicitly define this ctor to avoid auto-generation by the compiler.
+ * The compiler does not take the ctor with the 'const SfxItemSet&'!
+ */
+SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
+: SfxItemSet(rCopy)
+{
+}
+
+/**
+ * Putting with automatic extension of the WhichId with the ID of the Item.
+ */
+const SfxPoolItem* SfxAllItemSet::PutImpl( const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership )
+{
+ MergeRange(nWhich, nWhich);
+ return SfxItemSet::PutImpl(rItem, nWhich, bPassingOwnership);
+}
+
+/**
+ * Disable Item
+ * Using a VoidItem with Which value 0
+ */
+void SfxItemSet::DisableItem(sal_uInt16 nWhich)
+{
+ Put( SfxVoidItem(0), nWhich );
+}
+
+std::unique_ptr<SfxItemSet> SfxAllItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
+{
+ if (pToPool && pToPool != GetPool())
+ {
+ std::unique_ptr<SfxAllItemSet> pNewSet(new SfxAllItemSet( *pToPool ));
+ if ( bItems )
+ pNewSet->Set( *this );
+ return pNewSet;
+ }
+ else
+ return std::unique_ptr<SfxItemSet>(bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*GetPool()));
+}
+
+
+WhichRangesContainer::WhichRangesContainer( const WhichPair* wids, sal_Int32 nSize )
+{
+ auto p = new WhichPair[nSize];
+ for (int i=0; i<nSize; ++i)
+ p[i] = wids[i];
+ m_pairs = p;
+ m_size = nSize;
+ m_bOwnRanges = true;
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+}
+
+WhichRangesContainer::WhichRangesContainer(sal_uInt16 nWhichStart, sal_uInt16 nWhichEnd)
+ : m_size(1), m_bOwnRanges(true)
+{
+ auto p = new WhichPair[1];
+ p[0] = { nWhichStart, nWhichEnd };
+ m_pairs = p;
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+}
+
+WhichRangesContainer::WhichRangesContainer(WhichRangesContainer && other)
+{
+ std::swap(m_pairs, other.m_pairs);
+ std::swap(m_size, other.m_size);
+ std::swap(m_bOwnRanges, other.m_bOwnRanges);
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+}
+
+WhichRangesContainer& WhichRangesContainer::operator=(WhichRangesContainer && other)
+{
+ std::swap(m_pairs, other.m_pairs);
+ std::swap(m_size, other.m_size);
+ std::swap(m_bOwnRanges, other.m_bOwnRanges);
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+ return *this;
+}
+
+WhichRangesContainer& WhichRangesContainer::operator=(WhichRangesContainer const & other)
+{
+ reset();
+ m_size = other.m_size;
+ m_bOwnRanges = other.m_bOwnRanges;
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+ if (m_bOwnRanges)
+ {
+ auto p = new WhichPair[m_size];
+ for (int i=0; i<m_size; ++i)
+ p[i] = other.m_pairs[i];
+ m_pairs = p;
+ }
+ else
+ m_pairs = other.m_pairs;
+ return *this;
+}
+
+WhichRangesContainer::~WhichRangesContainer()
+{
+ reset();
+}
+
+bool WhichRangesContainer::operator==(WhichRangesContainer const & other) const
+{
+ if (m_size != other.m_size)
+ return false;
+ if (m_pairs == other.m_pairs)
+ return true;
+ return std::equal(m_pairs, m_pairs + m_size, other.m_pairs, other.m_pairs + m_size);
+}
+
+
+void WhichRangesContainer::reset()
+{
+ if (m_bOwnRanges)
+ {
+ delete [] m_pairs;
+ m_bOwnRanges = false;
+ }
+ m_pairs = nullptr;
+ m_size = 0;
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+ m_aLastWhichPairFirst = 0;
+ m_aLastWhichPairSecond = 0;
+}
+
+#ifdef DBG_UTIL
+static size_t g_nHit(0);
+static size_t g_nMiss(1);
+static bool g_bShowWhichRangesHitRate(getenv("SVL_SHOW_WHICHRANGES_HITRATE"));
+static void isHit() { g_nHit++; }
+static void isMiss()
+{
+ g_nMiss++;
+ const double fHitRate(double(g_nHit) /double(g_nMiss));
+ if (0 == g_nMiss % 1000 && g_bShowWhichRangesHitRate)
+ SAL_WARN("svl", "ITEM: hits: " << g_nHit << " misses: " << g_nMiss << " hits/misses(rate): " << fHitRate);
+}
+#endif
+
+sal_uInt16 WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const
+{
+ if (empty())
+ return INVALID_WHICHPAIR_OFFSET;
+
+ // special case for single entry - happens often e.g. UI stuff
+ if (1 == m_size)
+ {
+ if( m_pairs->first <= nWhich && nWhich <= m_pairs->second )
+ return nWhich - m_pairs->first;
+
+ // we have only one WhichPair entry and it's not contained -> failed
+ return INVALID_WHICHPAIR_OFFSET;
+ }
+
+ // check if nWhich is inside last successfully used WhichPair
+ if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset
+ && m_aLastWhichPairFirst <= nWhich
+ && nWhich <= m_aLastWhichPairSecond)
+ {
+#ifdef DBG_UTIL
+ isHit();
+#endif
+ // we can re-use the last found WhichPair
+ return m_aLastWhichPairOffset + (nWhich - m_aLastWhichPairFirst);
+ }
+
+#ifdef DBG_UTIL
+ isMiss();
+#endif
+
+ // we have to find the correct WhichPair, iterate linear. This
+ // also directly updates the buffered m_aLastWhichPair* values
+ m_aLastWhichPairOffset = 0;
+
+ for (const WhichPair& rPair : *this)
+ {
+ // Within this range?
+ if( rPair.first <= nWhich && nWhich <= rPair.second )
+ {
+ // found, remember parameters for buffered hits
+ m_aLastWhichPairFirst = rPair.first;
+ m_aLastWhichPairSecond = rPair.second;
+
+ // ...and return
+ return m_aLastWhichPairOffset + (nWhich - m_aLastWhichPairFirst);
+ }
+
+ m_aLastWhichPairOffset += rPair.second - rPair.first + 1;
+ }
+
+ // *need* to reset: if 1st WhichPair only one entry it could be 1
+ // what could wrongly trigger re-use above for next search
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+
+ return m_aLastWhichPairOffset;
+}
+
+sal_uInt16 WhichRangesContainer::getWhichFromOffset(sal_uInt16 nOffset) const
+{
+ // check for empty, if yes, return null which is an invalid WhichID
+ if (empty())
+ return 0;
+
+ // special case for single entry - happens often e.g. UI stuff
+ if (1 == m_size)
+ {
+ if (nOffset <= m_pairs->second - m_pairs->first)
+ return m_pairs->first + nOffset;
+
+ // we have only one WhichPair entry and it's not contained -> failed
+ return 0;
+ }
+
+ // check if nWhich is inside last successfully used WhichPair
+ if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset)
+ {
+ // only try if we are beyond or at m_aLastWhichPairOffset to
+ // not get numerically negative
+ if (nOffset >= m_aLastWhichPairOffset)
+ {
+ const sal_uInt16 nAdaptedOffset(nOffset - m_aLastWhichPairOffset);
+
+ if (nAdaptedOffset <= m_aLastWhichPairSecond - m_aLastWhichPairFirst)
+ {
+#ifdef DBG_UTIL
+ isHit();
+#endif
+ return m_aLastWhichPairFirst + nAdaptedOffset;
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ isMiss();
+#endif
+
+ // Iterate over WhichPairs in WhichRangesContainer
+ // Do not update buffered last hit (m_aLastWhichPair*), these calls
+ // are potentially more rare than getOffsetFromWhich calls. Still,
+ // it could also be done here
+ for( auto const & pPtr : *this )
+ {
+ const sal_uInt16 nWhichPairRange(pPtr.second - pPtr.first);
+ if( nOffset <= nWhichPairRange )
+ return pPtr.first + nOffset;
+ nOffset -= nWhichPairRange + 1;
+ }
+
+ // no WhichID found, return invalid one
+ return 0;
+}
+
+// Adds a range to which ranges, keeping the ranges in valid state (sorted, non-overlapping)
+WhichRangesContainer WhichRangesContainer::MergeRange(sal_uInt16 nFrom,
+ sal_uInt16 nTo) const
+{
+ assert(svl::detail::validRange(nFrom, nTo));
+
+ if (empty())
+ return WhichRangesContainer(nFrom, nTo);
+
+ // reset buffer
+ m_aLastWhichPairOffset = INVALID_WHICHPAIR_OFFSET;
+
+ // create vector of ranges (sal_uInt16 pairs of lower and upper bound)
+ const size_t nOldCount = size();
+ // Allocate one item more than we already have.
+ // In the worst case scenario we waste a little bit
+ // of memory, but we avoid another allocation, which is more important.
+ std::unique_ptr<WhichPair[]> aRangesTable(new WhichPair[nOldCount+1]);
+ int aRangesTableSize = 0;
+ bool bAdded = false;
+ for (const auto& rPair : *this)
+ {
+ if (!bAdded && rPair.first >= nFrom)
+ { // insert new range, keep ranges sorted
+ aRangesTable[aRangesTableSize++] = { nFrom, nTo };
+ bAdded = true;
+ }
+ // insert current range
+ aRangesTable[aRangesTableSize++] = rPair;
+ }
+ if (!bAdded)
+ aRangesTable[aRangesTableSize++] = { nFrom, nTo };
+
+ // true if ranges overlap or adjoin, false if ranges are separate
+ auto needMerge = [](WhichPair lhs, WhichPair rhs) {
+ return (lhs.first - 1) <= rhs.second && (rhs.first - 1) <= lhs.second;
+ };
+
+ auto it = aRangesTable.get();
+ auto endIt = aRangesTable.get() + aRangesTableSize;
+ // we have at least one range at this point
+ for (;;)
+ {
+ auto itNext = std::next(it);
+ if (itNext == endIt)
+ break;
+ // check if neighbouring ranges overlap or adjoin
+ if (needMerge(*it, *itNext))
+ {
+ // lower bounds are sorted, implies: it->first = min(it[0].first, it[1].first)
+ it->second = std::max(it->second, itNext->second);
+ // remove next element
+ std::move(std::next(itNext), endIt, itNext);
+ --aRangesTableSize;
+ endIt = aRangesTable.get() + aRangesTableSize;
+ }
+ else
+ ++it;
+ }
+
+ return WhichRangesContainer(std::move(aRangesTable), aRangesTableSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/lckbitem.cxx b/svl/source/items/lckbitem.cxx
new file mode 100644
index 0000000000..87165ae507
--- /dev/null
+++ b/svl/source/items/lckbitem.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/lckbitem.hxx>
+#include <tools/stream.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+
+SfxPoolItem* SfxLockBytesItem::CreateDefault() { return new SfxLockBytesItem; }
+
+
+SfxLockBytesItem::SfxLockBytesItem()
+{
+}
+
+
+SfxLockBytesItem::~SfxLockBytesItem()
+{
+}
+
+
+bool SfxLockBytesItem::operator==( const SfxPoolItem& rItem ) const
+{
+ return SfxPoolItem::operator==(rItem) && static_cast<const SfxLockBytesItem&>(rItem)._xVal == _xVal;
+}
+
+SfxLockBytesItem* SfxLockBytesItem::Clone(SfxItemPool *) const
+{
+ return new SfxLockBytesItem( *this );
+}
+
+// virtual
+bool SfxLockBytesItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
+{
+ css::uno::Sequence< sal_Int8 > aSeq;
+ if ( rVal >>= aSeq )
+ {
+ if ( aSeq.hasElements() )
+ {
+ SvMemoryStream* pStream = new SvMemoryStream();
+ pStream->WriteBytes( aSeq.getConstArray(), aSeq.getLength() );
+ pStream->Seek(0);
+
+ _xVal = new SvLockBytes( pStream, true );
+ }
+ else
+ _xVal = nullptr;
+
+ return true;
+ }
+
+ OSL_FAIL( "SfxLockBytesItem::PutValue - Wrong type!" );
+ return true;
+}
+
+// virtual
+bool SfxLockBytesItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
+{
+ if ( _xVal.is() )
+ {
+ sal_uInt32 nLen;
+ SvLockBytesStat aStat;
+
+ if ( _xVal->Stat( &aStat ) == ERRCODE_NONE )
+ nLen = aStat.nSize;
+ else
+ return false;
+
+ std::size_t nRead = 0;
+ css::uno::Sequence< sal_Int8 > aSeq( nLen );
+
+ _xVal->ReadAt( 0, aSeq.getArray(), nLen, &nRead );
+ rVal <<= aSeq;
+ }
+ else
+ {
+ css::uno::Sequence< sal_Int8 > aSeq( 0 );
+ rVal <<= aSeq;
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/legacyitem.cxx b/svl/source/items/legacyitem.cxx
new file mode 100644
index 0000000000..b0daa3b906
--- /dev/null
+++ b/svl/source/items/legacyitem.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/legacyitem.hxx>
+#include <tools/stream.hxx>
+#include <svl/eitem.hxx>
+#include <svl/cintitem.hxx>
+
+namespace legacy
+{
+ namespace SfxBool
+ {
+ sal_uInt16 GetVersion(sal_uInt16)
+ {
+ return 0;
+ }
+
+ void Create(SfxBoolItem& rItem, SvStream& rStrm, sal_uInt16)
+ {
+ bool tmp(false);
+ rStrm.ReadCharAsBool(tmp);
+ rItem.SetValue(tmp);
+ }
+
+ SvStream& Store(const SfxBoolItem& rItem, SvStream& rStrm, sal_uInt16)
+ {
+ rStrm.WriteBool(rItem.GetValue()); // not bool for serialization!
+ return rStrm;
+ }
+ }
+ namespace CntInt32
+ {
+ sal_uInt16 GetVersion(sal_uInt16)
+ {
+ return 0;
+ }
+
+ void Create(CntInt32Item& rItem, SvStream& rStrm, sal_uInt16)
+ {
+ sal_Int32 tmp(0);
+ rStrm.ReadInt32(tmp);
+ rItem.SetValue(tmp);
+ }
+
+ SvStream& Store(const CntInt32Item& rItem, SvStream& rStrm, sal_uInt16)
+ {
+ rStrm.WriteInt32(rItem.GetValue());
+ return rStrm;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/macitem.cxx b/svl/source/items/macitem.cxx
new file mode 100644
index 0000000000..0b242c7cff
--- /dev/null
+++ b/svl/source/items/macitem.cxx
@@ -0,0 +1,243 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+#include <comphelper/fileformat.h>
+#include <tools/stream.hxx>
+
+#include <svl/macitem.hxx>
+#include <stringio.hxx>
+#include <algorithm>
+#include <utility>
+
+SvxMacro::SvxMacro( OUString _aMacName, const OUString &rLanguage)
+ : aMacName(std::move( _aMacName )), aLibName( rLanguage),
+ eType( EXTENDED_STYPE)
+{
+ if ( rLanguage == SVX_MACRO_LANGUAGE_STARBASIC )
+ eType=STARBASIC;
+ else if ( rLanguage == SVX_MACRO_LANGUAGE_JAVASCRIPT )
+ eType=JAVASCRIPT;
+}
+
+OUString SvxMacro::GetLanguage()const
+{
+ if(eType==STARBASIC)
+ {
+ return SVX_MACRO_LANGUAGE_STARBASIC;
+ }
+ else if(eType==JAVASCRIPT)
+ {
+ return SVX_MACRO_LANGUAGE_JAVASCRIPT;
+ }
+ else if(eType==EXTENDED_STYPE)
+ {
+ return SVX_MACRO_LANGUAGE_SF;
+
+ }
+ return aLibName;
+}
+
+SvxMacroTableDtor& SvxMacroTableDtor::operator=( const SvxMacroTableDtor& rTbl )
+{
+ if (this != &rTbl)
+ {
+ aSvxMacroTable.clear();
+ aSvxMacroTable.insert(rTbl.aSvxMacroTable.begin(), rTbl.aSvxMacroTable.end());
+ }
+ return *this;
+}
+
+bool SvxMacroTableDtor::operator==( const SvxMacroTableDtor& rOther ) const
+{
+ // Count different => odd in any case
+ // Compare single ones; the sequence matters due to performance reasons
+ return std::equal(aSvxMacroTable.begin(), aSvxMacroTable.end(),
+ rOther.aSvxMacroTable.begin(), rOther.aSvxMacroTable.end(),
+ [](const SvxMacroTable::value_type& rOwnEntry, const SvxMacroTable::value_type& rOtherEntry) {
+ const SvxMacro& rOwnMac = rOwnEntry.second;
+ const SvxMacro& rOtherMac = rOtherEntry.second;
+ return rOwnEntry.first == rOtherEntry.first
+ && rOwnMac.GetLibName() == rOtherMac.GetLibName()
+ && rOwnMac.GetMacName() == rOtherMac.GetMacName();
+ });
+}
+
+void SvxMacroTableDtor::Read( SvStream& rStrm )
+{
+ sal_uInt16 nVersion;
+ rStrm.ReadUInt16( nVersion );
+
+ short nReadMacro(0);
+ rStrm.ReadInt16(nReadMacro);
+ if (nReadMacro < 0)
+ {
+ SAL_WARN("editeng", "Parsing error: negative value " << nReadMacro);
+ return;
+ }
+
+ auto nMacro = o3tl::make_unsigned(nReadMacro);
+
+ const size_t nMinStringSize = rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE ? 4 : 2;
+ size_t nMinRecordSize = 2 + 2*nMinStringSize;
+ if( SVX_MACROTBL_VERSION40 <= nVersion )
+ nMinRecordSize+=2;
+
+ const size_t nMaxRecords = rStrm.remainingSize() / nMinRecordSize;
+ if (nMacro > nMaxRecords)
+ {
+ SAL_WARN("editeng", "Parsing error: " << nMaxRecords <<
+ " max possible entries, but " << nMacro<< " claimed, truncating");
+ nMacro = nMaxRecords;
+ }
+
+ for (decltype(nMacro) i = 0; i < nMacro; ++i)
+ {
+ sal_uInt16 nCurKey, eType = STARBASIC;
+ OUString aLibName, aMacName;
+ rStrm.ReadUInt16( nCurKey );
+ aLibName = readByteString(rStrm);
+ aMacName = readByteString(rStrm);
+
+ if( SVX_MACROTBL_VERSION40 <= nVersion )
+ rStrm.ReadUInt16( eType );
+
+ aSvxMacroTable.emplace( SvMacroItemId(nCurKey), SvxMacro( aMacName, aLibName, static_cast<ScriptType>(eType) ) );
+ }
+}
+
+SvStream& SvxMacroTableDtor::Write( SvStream& rStream ) const
+{
+ sal_uInt16 nVersion = SOFFICE_FILEFORMAT_31 == rStream.GetVersion()
+ ? SVX_MACROTBL_VERSION31
+ : SVX_MACROTBL_VERSION40;
+
+ if( SVX_MACROTBL_VERSION40 <= nVersion )
+ rStream.WriteUInt16( nVersion );
+
+ rStream.WriteUInt16( aSvxMacroTable.size() );
+
+ for( const auto& rEntry : aSvxMacroTable )
+ {
+ if (rStream.GetError() != ERRCODE_NONE)
+ break;
+ const SvxMacro& rMac = rEntry.second;
+ rStream.WriteUInt16( static_cast<sal_uInt16>(rEntry.first) );
+ writeByteString(rStream, rMac.GetLibName());
+ writeByteString(rStream, rMac.GetMacName());
+
+ if( SVX_MACROTBL_VERSION40 <= nVersion )
+ rStream.WriteUInt16( rMac.GetScriptType() );
+ }
+ return rStream;
+}
+
+// returns NULL if no entry exists, or a pointer to the internal value
+const SvxMacro* SvxMacroTableDtor::Get(SvMacroItemId nEvent) const
+{
+ SvxMacroTable::const_iterator it = aSvxMacroTable.find(nEvent);
+ return it == aSvxMacroTable.end() ? nullptr : &(it->second);
+}
+
+// returns NULL if no entry exists, or a pointer to the internal value
+SvxMacro* SvxMacroTableDtor::Get(SvMacroItemId nEvent)
+{
+ SvxMacroTable::iterator it = aSvxMacroTable.find(nEvent);
+ return it == aSvxMacroTable.end() ? nullptr : &(it->second);
+}
+
+// return true if the key exists
+bool SvxMacroTableDtor::IsKeyValid(SvMacroItemId nEvent) const
+{
+ SvxMacroTable::const_iterator it = aSvxMacroTable.find(nEvent);
+ return it != aSvxMacroTable.end();
+}
+
+// This stores a copy of the rMacro parameter
+SvxMacro& SvxMacroTableDtor::Insert(SvMacroItemId nEvent, const SvxMacro& rMacro)
+{
+ return aSvxMacroTable.emplace( nEvent, rMacro ).first->second;
+}
+
+// If the entry exists, remove it from the map and release it's storage
+void SvxMacroTableDtor::Erase(SvMacroItemId nEvent)
+{
+ SvxMacroTable::iterator it = aSvxMacroTable.find(nEvent);
+ if ( it != aSvxMacroTable.end())
+ {
+ aSvxMacroTable.erase(it);
+ }
+}
+
+bool SvxMacroItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+
+ const SvxMacroTableDtor& rOwn = aMacroTable;
+ const SvxMacroTableDtor& rOther = static_cast<const SvxMacroItem&>(rAttr).aMacroTable;
+
+ return rOwn == rOther;
+}
+
+SvxMacroItem* SvxMacroItem::Clone( SfxItemPool* ) const
+{
+ return new SvxMacroItem( *this );
+}
+
+bool SvxMacroItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+/*!!!
+ SvxMacroTableDtor& rTbl = (SvxMacroTableDtor&)GetMacroTable();
+ SvxMacro* pMac = rTbl.First();
+
+ while ( pMac )
+ {
+ rText += pMac->GetLibName();
+ rText += cpDelim;
+ rText += pMac->GetMacName();
+ pMac = rTbl.Next();
+ if ( pMac )
+ rText += cpDelim;
+ }
+*/
+ rText.clear();
+ return false;
+}
+
+
+void SvxMacroItem::SetMacro( SvMacroItemId nEvent, const SvxMacro& rMacro )
+{
+ // tdf#141123: emplace doesn't replace the element in the map if already exists
+ // see https://en.cppreference.com/w/cpp/container/map/emplace
+ // so first erase the macro if there's one for this event
+ aMacroTable.Erase(nEvent);
+ aMacroTable.Insert( nEvent, rMacro);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/poolitem.cxx b/svl/source/items/poolitem.cxx
new file mode 100644
index 0000000000..ae7c97136c
--- /dev/null
+++ b/svl/source/items/poolitem.cxx
@@ -0,0 +1,703 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/poolitem.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <libxml/xmlwriter.h>
+#include <typeinfo>
+#include <boost/property_tree/ptree.hpp>
+
+#ifdef DBG_UTIL
+#include <unordered_set>
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// list of classes derived from SfxPoolItem
+// will not be kept up-to-date, but give a good overview for right now
+//////////////////////////////////////////////////////////////////////////////
+//
+// class SbxItem : public SfxPoolItem
+// class SvxChartColorTableItem : public SfxPoolItem
+// class DriverPoolingSettingsItem final : public SfxPoolItem
+// class DatabaseMapItem final : public SfxPoolItem
+// class DbuTypeCollectionItem : public SfxPoolItem
+// class OptionalBoolItem : public SfxPoolItem
+// class OStringListItem : public SfxPoolItem
+// class MediaItem : public SfxPoolItem
+// class SvxBoxItem : public SfxPoolItem
+// class SvxBoxInfoItem : public SfxPoolItem
+// class SvxBrushItem : public SfxPoolItem
+// class SvxBulletItem : public SfxPoolItem
+// class SvxColorItem : public SfxPoolItem
+// class SvxFontHeightItem : public SfxPoolItem
+// class SvxFieldItem : public SfxPoolItem
+// class SvxFontListItem : public SfxPoolItem
+// class SvxFontItem : public SfxPoolItem
+// class SvxHyphenZoneItem : public SfxPoolItem
+// class SvxLineItem : public SfxPoolItem
+// class SvxLRSpaceItem : public SfxPoolItem
+// class SvxNumBulletItem : public SfxPoolItem
+// class SfxHyphenRegionItem: public SfxPoolItem
+// class SvxProtectItem : public SfxPoolItem
+// class SvxSizeItem : public SfxPoolItem
+// class SwFormatFrameSize: public SvxSizeItem
+// class SvxTabStopItem : public SfxPoolItem
+// class SvxTwoLinesItem : public SfxPoolItem
+// class SvxULSpaceItem : public SfxPoolItem
+// class SvXMLAttrContainerItem: public SfxPoolItem
+// class SfxLinkItem : public SfxPoolItem
+// class SfxEventNamesItem : public SfxPoolItem
+// class SfxFrameItem: public SfxPoolItem
+// class SfxUnoAnyItem : public SfxPoolItem
+// class SfxUnoFrameItem : public SfxPoolItem
+// class SfxMacroInfoItem: public SfxPoolItem
+// class SfxObjectItem: public SfxPoolItem
+// class SfxObjectShellItem: public SfxPoolItem
+// class SfxViewFrameItem: public SfxPoolItem
+// class SfxWatermarkItem: public SfxPoolItem
+// class SfxEnumItemInterface: public SfxPoolItem
+// class SvxAdjustItem : public SfxEnumItemInterface
+// class SvxEscapementItem : public SfxEnumItemInterface
+// class SvxLineSpacingItem : public SfxEnumItemInterface
+// class SvxShadowItem : public SfxEnumItemInterface
+// class SfxEnumItem : public SfxEnumItemInterface
+// class SvxCharReliefItem : public SfxEnumItem<FontRelief>
+// class SvxCaseMapItem : public SfxEnumItem<SvxCaseMap>
+// class SvxCrossedOutItem : public SfxEnumItem<FontStrikeout>
+// class SvxFormatBreakItem : public SfxEnumItem<SvxBreak>
+// class SvxFrameDirectionItem : public SfxEnumItem<SvxFrameDirection>
+// class SvxHorJustifyItem: public SfxEnumItem<SvxCellHorJustify>
+// class SvxVerJustifyItem: public SfxEnumItem<SvxCellVerJustify>
+// class SvxJustifyMethodItem: public SfxEnumItem<SvxCellJustifyMethod>
+// class SvxLanguageItem_Base: public SfxEnumItem<LanguageType>
+// class SvxLanguageItem : public SvxLanguageItem_Base
+// class SvxPostureItem : public SfxEnumItem<FontItalic>
+// class SvxTextLineItem : public SfxEnumItem<FontLineStyle>
+// class SvxUnderlineItem : public SvxTextLineItem
+// class SvxOverlineItem : public SvxTextLineItem
+// class SvxWeightItem : public SfxEnumItem<FontWeight>
+// class SvxOrientationItem: public SfxEnumItem<SvxCellOrientation>
+// class SvxChartRegressItem : public SfxEnumItem<SvxChartRegress>
+// class SvxChartTextOrderItem : public SfxEnumItem<SvxChartTextOrder>
+// class SvxChartKindErrorItem : public SfxEnumItem<SvxChartKindError>
+// class SvxChartIndicateItem : public SfxEnumItem<SvxChartIndicate>
+// class SvxRotateModeItem: public SfxEnumItem<SvxRotateMode>
+// class SdrGrafModeItem_Base: public SfxEnumItem<GraphicDrawMode>
+// class SdrGrafModeItem : public SdrGrafModeItem_Base
+// class SdrTextAniDirectionItem: public SfxEnumItem<SdrTextAniDirection>
+// class SdrTextVertAdjustItem: public SfxEnumItem<SdrTextVertAdjust>
+// class SdrTextHorzAdjustItem: public SfxEnumItem<SdrTextHorzAdjust>
+// class SdrTextAniKindItem: public SfxEnumItem<SdrTextAniKind>
+// class SdrTextFitToSizeTypeItem : public SfxEnumItem<css::drawing::TextFitToSizeType>
+// class SdrCaptionEscDirItem: public SfxEnumItem<SdrCaptionEscDir>
+// class SdrCaptionTypeItem: public SfxEnumItem<SdrCaptionType>
+// class SdrEdgeKindItem: public SfxEnumItem<SdrEdgeKind>
+// class SdrMeasureTextHPosItem: public SfxEnumItem<css::drawing::MeasureTextHorzPos>
+// class SdrMeasureTextVPosItem: public SfxEnumItem<css::drawing::MeasureTextVertPos>
+// class SdrMeasureUnitItem: public SfxEnumItem<FieldUnit>
+// class XFillStyleItem : public SfxEnumItem<css::drawing::FillStyle>
+// class XFillBmpPosItem : public SfxEnumItem<RectPoint>
+// class XFormTextAdjustItem : public SfxEnumItem<XFormTextAdjust>
+// class XFormTextShadowItem : public SfxEnumItem<XFormTextShadow>
+// class XLineStyleItem : public SfxEnumItem<css::drawing::LineStyle>
+// class XLineJointItem : public SfxEnumItem<css::drawing::LineJoint>
+// class XLineCapItem : public SfxEnumItem<css::drawing::LineCap>
+// class XFormTextStyleItem : public SfxEnumItem<XFormTextStyle>
+// class ScViewObjectModeItem: public SfxEnumItem<ScVObjMode>
+// class SdrCircKindItem: public SfxEnumItem<SdrCircKind>
+// class SdrMeasureKindItem: public SfxEnumItem<SdrMeasureKind>
+// class SwFormatFillOrder: public SfxEnumItem<SwFillOrder>
+// class SwFormatFootnoteEndAtTextEnd : public SfxEnumItem<SwFootnoteEndPosEnum>
+// class SwFormatFootnoteAtTextEnd : public SwFormatFootnoteEndAtTextEnd
+// class SwFormatEndAtTextEnd : public SwFormatFootnoteEndAtTextEnd
+// class SwFormatSurround: public SfxEnumItem<css::text::WrapTextMode>
+// class SwMirrorGrf : public SfxEnumItem<MirrorGraph>
+// class SwDrawModeGrf_Base: public SfxEnumItem<GraphicDrawMode>
+// class SwDrawModeGrf : public SwDrawModeGrf_Base
+//class CntByteItem: public SfxPoolItem
+// class SfxByteItem: public CntByteItem
+// class SvxOrphansItem: public SfxByteItem
+// class SvxPaperBinItem : public SfxByteItem
+// class SvxWidowsItem: public SfxByteItem
+// class SwTransparencyGrf : public SfxByteItem
+//class CntUInt16Item: public SfxPoolItem
+// class SfxUInt16Item: public CntUInt16Item
+// class SvxTextRotateItem : public SfxUInt16Item
+// class SvxCharRotateItem : public SvxTextRotateItem
+// class SvxCharScaleWidthItem : public SfxUInt16Item
+// class SvxEmphasisMarkItem : public SfxUInt16Item
+// class SvxParaVertAlignItem : public SfxUInt16Item
+// class SvxWritingModeItem : public SfxUInt16Item
+// class SvxZoomItem: public SfxUInt16Item
+// class SdrPercentItem : public SfxUInt16Item
+// class SdrGrafTransparenceItem : public SdrPercentItem
+// class SdrTextAniCountItem: public SfxUInt16Item
+// class SdrTextAniDelayItem: public SfxUInt16Item
+// class Svx3DNormalsKindItem : public SfxUInt16Item
+// class Svx3DTextureProjectionXItem : public SfxUInt16Item
+// class Svx3DTextureProjectionYItem : public SfxUInt16Item
+// class Svx3DTextureKindItem : public SfxUInt16Item
+// class Svx3DTextureModeItem : public SfxUInt16Item
+// class Svx3DPerspectiveItem : public SfxUInt16Item
+// class Svx3DShadeModeItem : public SfxUInt16Item
+// class SdrEdgeLineDeltaCountItem: public SfxUInt16Item
+// class SvxViewLayoutItem: public SfxUInt16Item
+// class XFillBmpPosOffsetXItem : public SfxUInt16Item
+// class XFillBmpPosOffsetYItem : public SfxUInt16Item
+// class XFillBmpTileOffsetXItem : public SfxUInt16Item
+// class XFillBmpTileOffsetYItem : public SfxUInt16Item
+// class XFillTransparenceItem: public SfxUInt16Item
+// class XFormTextShadowTranspItem: public SfxUInt16Item
+// class XGradientStepCountItem: public SfxUInt16Item
+// class XLineTransparenceItem: public SfxUInt16Item
+// class SvxZoomSliderItem: public SfxUInt16Item
+// class SdrLayerIdItem: public SfxUInt16Item
+// class SwRotationGrf : public SfxUInt16Item
+//class CntInt32Item: public SfxPoolItem
+// class SfxInt32Item: public CntInt32Item
+// class SfxMetricItem: public SfxInt32Item
+// class XFillBmpSizeXItem : public SfxMetricItem
+// class XFillBmpSizeYItem : public SfxMetricItem
+// class XFormTextDistanceItem : public SfxMetricItem
+// class XFormTextShadowXValItem : public SfxMetricItem
+// class XFormTextShadowYValItem : public SfxMetricItem
+// class XFormTextStartItem : public SfxMetricItem
+// class XLineEndWidthItem : public SfxMetricItem
+// class XLineStartWidthItem : public SfxMetricItem
+// class XLineWidthItem : public SfxMetricItem
+// class SdrAngleItem: public SfxInt32Item
+//
+// class SdrCaptionAngleItem: public SdrAngleItem
+// class SdrMeasureTextFixedAngleItem: public SdrAngleItem
+// class SdrMeasureTextAutoAngleViewItem: public SdrAngleItem
+// class SdrRotateAllItem: public SdrAngleItem
+// class SdrRotateOneItem: public SdrAngleItem
+// class SdrShearAngleItem: public SdrAngleItem
+// class SdrHorzShearAllItem: public SdrAngleItem
+// class SdrVertShearAllItem: public SdrAngleItem
+// class SdrHorzShearOneItem: public SdrAngleItem
+// class SdrVertShearOneItem: public SdrAngleItem
+// class SdrMetricItem: public SfxInt32Item
+// class SdrCaptionEscAbsItem: public SdrMetricItem
+// class SdrCaptionGapItem: public SdrMetricItem
+// class SdrCaptionLineLenItem: public SdrMetricItem
+// class SdrEdgeNode1HorzDistItem: public SdrMetricItem
+// class SdrEdgeNode1VertDistItem: public SdrMetricItem
+// class SdrEdgeNode2HorzDistItem: public SdrMetricItem
+// class SdrEdgeNode2VertDistItem: public SdrMetricItem
+// class SdrEdgeNode1GlueDistItem: public SdrMetricItem
+// class SdrEdgeNode2GlueDistItem: public SdrMetricItem
+// class SdrAllPositionXItem: public SdrMetricItem
+// class SdrAllPositionYItem: public SdrMetricItem
+// class SdrAllSizeWidthItem: public SdrMetricItem
+// class SdrAllSizeHeightItem: public SdrMetricItem
+// class SdrLogicSizeWidthItem: public SdrMetricItem
+// class SdrLogicSizeHeightItem: public SdrMetricItem
+// class SdrMeasureOverhangItem: public SdrMetricItem
+// class SdrMoveXItem: public SdrMetricItem
+// class SdrMoveYItem: public SdrMetricItem
+// class SdrOnePositionXItem: public SdrMetricItem
+// class SdrOnePositionYItem: public SdrMetricItem
+// class SdrOneSizeWidthItem: public SdrMetricItem
+// class SdrOneSizeHeightItem: public SdrMetricItem
+// class SdrTransformRef1XItem: public SdrMetricItem
+// class SdrTransformRef1YItem: public SdrMetricItem
+// class SdrTransformRef2XItem: public SdrMetricItem
+// class SdrTransformRef2YItem: public SdrMetricItem
+// class SdrCaptionEscRelItem: public SfxInt32Item
+//class CntUInt32Item: public SfxPoolItem
+// class SfxUInt32Item: public CntUInt32Item
+// class SvxRsidItem : public SfxUInt32Item
+// class SdrGrafGamma100Item : public SfxUInt32Item
+// class SwTableBoxNumFormat : public SfxUInt32Item
+//class CntUnencodedStringItem: public SfxPoolItem
+// class SfxStringItem: public CntUnencodedStringItem
+// class SvxPageModelItem : public SfxStringItem
+// class SfxDocumentInfoItem : public SfxStringItem
+// class SvxPostItAuthorItem: public SfxStringItem
+// class SvxPostItDateItem: public SfxStringItem
+// class SvxPostItTextItem: public SfxStringItem
+// class SvxPostItIdItem: public SfxStringItem
+// class SdrMeasureFormatStringItem: public SfxStringItem
+// class NameOrIndex : public SfxStringItem
+// class XFillBitmapItem : public NameOrIndex
+// class XColorItem : public NameOrIndex
+// class XFillColorItem : public XColorItem
+// class XFormTextShadowColorItem : public XColorItem
+// class XLineColorItem : public XColorItem
+// class XSecondaryFillColorItem : public XColorItem
+// class XFillGradientItem : public NameOrIndex
+// class XFillFloatTransparenceItem : public XFillGradientItem
+// class XFillHatchItem : public NameOrIndex
+// class XLineDashItem : public NameOrIndex
+// class XLineEndItem : public NameOrIndex
+// class XLineStartItem : public NameOrIndex
+// class SfxScriptOrganizerItem : public SfxStringItem
+// class SdrLayerNameItem: public SfxStringItem
+// class SwNumRuleItem : public SfxStringItem
+//class SfxBoolItem : public SfxPoolItem
+// class SvxAutoKernItem : public SfxBoolItem
+// class SvxBlinkItem : public SfxBoolItem
+// class SvxCharHiddenItem : public SfxBoolItem
+// class SvxContourItem : public SfxBoolItem
+// class SvxForbiddenRuleItem : public SfxBoolItem
+// class SvxHangingPunctuationItem : public SfxBoolItem
+// class SvxFormatKeepItem : public SfxBoolItem
+// class SvxNoHyphenItem : public SfxBoolItem
+// class SvxOpaqueItem : public SfxBoolItem
+// class SvxParaGridItem : public SfxBoolItem
+// class SvxPrintItem : public SfxBoolItem
+// class SvxScriptSpaceItem : public SfxBoolItem
+// class SvxShadowedItem : public SfxBoolItem
+// class SvxFormatSplitItem : public SfxBoolItem
+// class SvxWordLineModeItem : public SfxBoolItem
+// class SdrOnOffItem: public SfxBoolItem
+// class SdrGrafInvertItem : public SdrOnOffItem
+// class SdrTextFixedCellHeightItem : public SfxBoolItem
+// class SdrYesNoItem: public SfxBoolItem
+// class SdrTextAniStartInsideItem: public SdrYesNoItem
+// class SdrTextAniStopInsideItem: public SdrYesNoItem
+// class SdrCaptionEscIsRelItem: public SdrYesNoItem
+// class SdrCaptionFitLineLenItem: public SdrYesNoItem
+// class SdrMeasureBelowRefEdgeItem: public SdrYesNoItem
+// class SdrMeasureTextIsFixedAngleItem: public SdrYesNoItem
+// class SdrMeasureTextRota90Item: public SdrYesNoItem
+// class SdrMeasureTextUpsideDownItem: public SdrYesNoItem
+// class SdrMeasureTextAutoAngleItem: public SdrYesNoItem
+// class SdrObjPrintableItem: public SdrYesNoItem
+// class SdrObjVisibleItem: public SdrYesNoItem
+// class Svx3DReducedLineGeometryItem : public SfxBoolItem
+// class Svx3DSmoothNormalsItem : public SfxBoolItem
+// class Svx3DSmoothLidsItem : public SfxBoolItem
+// class Svx3DCharacterModeItem : public SfxBoolItem
+// class Svx3DCloseFrontItem : public SfxBoolItem
+// class Svx3DCloseBackItem : public SfxBoolItem
+// class XFillBackgroundItem : public SfxBoolItem
+// class XFillUseSlideBackgroundItem : public SfxBoolItem
+// class XFillBmpSizeLogItem : public SfxBoolItem
+// class XFillBmpTileItem : public SfxBoolItem
+// class XFillBmpStretchItem : public SfxBoolItem
+// class XFormTextMirrorItem : public SfxBoolItem
+// class XFormTextOutlineItem : public SfxBoolItem
+// class XLineEndCenterItem : public SfxBoolItem
+// class XLineStartCenterItem : public SfxBoolItem
+// class XFormTextHideFormItem : public SfxBoolItem
+// class SwFormatNoBalancedColumns : public SfxBoolItem
+// class SwFormatEditInReadonly : public SfxBoolItem
+// class SwFormatFollowTextFlow : public SfxBoolItem
+// class SwFormatLayoutSplit : public SfxBoolItem
+// class SwFormatRowSplit : public SfxBoolItem
+// class SwInvertGrf: public SfxBoolItem
+// class SwHeaderAndFooterEatSpacingItem : public SfxBoolItem
+// class SwRegisterItem : public SfxBoolItem
+// class SwParaConnectBorderItem : public SfxBoolItem
+// class SfxFlagItem: public SfxPoolItem
+// class SfxTemplateItem: public SfxFlagItem
+// class SfxGlobalNameItem: public SfxPoolItem
+// class SfxGrabBagItem : public SfxPoolItem
+// class SfxIntegerListItem : public SfxPoolItem
+// class SfxInt64Item : public SfxPoolItem
+// class SfxInt16Item: public SfxPoolItem
+// class SvxKerningItem : public SfxInt16Item
+// class SfxImageItem : public SfxInt16Item
+// class SdrSignedPercentItem : public SfxInt16Item
+// class SdrGrafRedItem : public SdrSignedPercentItem
+// class SdrGrafGreenItem : public SdrSignedPercentItem
+// class SdrGrafBlueItem : public SdrSignedPercentItem
+// class SdrGrafLuminanceItem : public SdrSignedPercentItem
+// class SdrGrafContrastItem : public SdrSignedPercentItem
+// class SdrTextAniAmountItem: public SfxInt16Item
+// class SdrMeasureDecimalPlacesItem: public SfxInt16Item
+// class ScMergeFlagAttr: public SfxInt16Item
+// class SwLuminanceGrf : public SfxInt16Item
+// class SwContrastGrf : public SfxInt16Item
+// class SwChannelGrf : public SfxInt16Item
+// class SfxLockBytesItem : public SfxPoolItem
+// class SvxMacroItem: public SfxPoolItem
+// class SfxVoidItem final: public SfxPoolItem
+// class SfxSetItem: public SfxPoolItem
+// class SvxScriptSetItem : public SfxSetItem
+// class SfxTabDialogItem: public SfxSetItem
+// class SvxSetItem: public SfxSetItem
+// class XFillAttrSetItem : public SfxSetItem
+// class XLineAttrSetItem : public SfxSetItem
+// class ScPatternAttr: public SfxSetItem
+// class SfxPointItem: public SfxPoolItem
+// class SfxRectangleItem: public SfxPoolItem
+// class SfxRangeItem : public SfxPoolItem
+// class SfxStringListItem : public SfxPoolItem
+// class SvxSearchItem : public SfxPoolItem
+// class SfxVisibilityItem: public SfxPoolItem
+// class AffineMatrixItem : public SfxPoolItem
+// class SvxMarginItem: public SfxPoolItem
+// class SvxDoubleItem : public SfxPoolItem
+// class SvxClipboardFormatItem : public SfxPoolItem
+// class SvxColorListItem: public SfxPoolItem
+// class SvxGradientListItem : public SfxPoolItem
+// class SvxHatchListItem : public SfxPoolItem
+// class SvxBitmapListItem : public SfxPoolItem
+// class SvxPatternListItem : public SfxPoolItem
+// class SvxDashListItem : public SfxPoolItem
+// class SvxLineEndListItem : public SfxPoolItem
+// class SvxB3DVectorItem : public SfxPoolItem
+// class SvxGalleryItem : public SfxPoolItem
+// class SvxGrfCrop : public SfxPoolItem
+// class SdrGrafCropItem : public SvxGrfCrop
+// class SwCropGrf : public SvxGrfCrop
+// class SvxHyperlinkItem : public SfxPoolItem
+// class SvxNumberInfoItem : public SfxPoolItem
+// class OfaPtrItem : public SfxPoolItem
+// class OfaXColorListItem : public SfxPoolItem
+// class SvxGridItem : public SvxOptionsGrid, public SfxPoolItem
+// class SdOptionsGridItem : public SvxGridItem
+// class SvxPageItem: public SfxPoolItem
+// class SvxLongLRSpaceItem : public SfxPoolItem
+// class SvxLongULSpaceItem : public SfxPoolItem
+// class SvxPagePosSizeItem : public SfxPoolItem
+// class SvxColumnItem : public SfxPoolItem
+// class SvxObjectItem : public SfxPoolItem
+// class SdrCustomShapeGeometryItem : public SfxPoolItem
+// class SvxSmartTagItem : public SfxPoolItem
+// class SvxGraphicItem: public SfxPoolItem
+// class SdrFractionItem: public SfxPoolItem
+// class SdrScaleItem: public SdrFractionItem
+// class SdrMeasureScaleItem: public SdrScaleItem
+// class SdrResizeXAllItem: public SdrFractionItem
+// class SdrResizeYAllItem: public SdrFractionItem
+// class SdrResizeXOneItem: public SdrFractionItem
+// class SdrResizeYOneItem: public SdrFractionItem
+// class ScMergeAttr: public SfxPoolItem
+// class ScProtectionAttr: public SfxPoolItem
+// class ScPageHFItem : public SfxPoolItem
+// class ScPageScaleToItem : public SfxPoolItem
+// class ScCondFormatItem : public SfxPoolItem
+// class ScTpDefaultsItem : public SfxPoolItem
+// class ScTpCalcItem : public SfxPoolItem
+// class ScTpFormulaItem : public SfxPoolItem
+// class ScTpPrintItem : public SfxPoolItem
+// class ScTpViewItem : public SfxPoolItem
+// class ScCondFormatDlgItem : public SfxPoolItem
+// class ScInputStatusItem : public SfxPoolItem
+// class ScSortItem : public SfxPoolItem
+// class ScQueryItem : public SfxPoolItem
+// class ScSubTotalItem : public SfxPoolItem
+// class cUserListItem : public SfxPoolItem
+// class ScConsolidateItem : public SfxPoolItem
+// class ScPivotItem : public SfxPoolItem
+// class ScSolveItem : public SfxPoolItem
+// class ScTabOpItem : public SfxPoolItem
+// class SdOptionsLayoutItem : public SfxPoolItem
+// class SdOptionsMiscItem : public SfxPoolItem
+// class SdOptionsSnapItem : public SfxPoolItem
+// class SdOptionsPrintItem : public SfxPoolItem
+// class SwCondCollItem : public SfxPoolItem
+// class SwTableBoxFormula : public SfxPoolItem, public SwTableFormula
+// class SwTableBoxValue : public SfxPoolItem
+// class SwFormatCharFormat: public SfxPoolItem, public SwClient
+// class SwFormatAnchor: public SfxPoolItem
+// class SwFormatAutoFormat: public SfxPoolItem
+// class SwFormatCol : public SfxPoolItem
+// class SwFormatChain: public SfxPoolItem
+// class SwFormatContent: public SfxPoolItem
+// class SwFormatFlyCnt : public SfxPoolItem
+// class SwFormatField : public SfxPoolItem
+// class SwFormatFootnote : public SfxPoolItem
+// class SwFormatHeader: public SfxPoolItem, public SwClient
+// class SwFormatFooter: public SfxPoolItem, public SwClient
+// class SwFormatINetFormat : public SfxPoolItem
+// class SwFormatLineNumber: public SfxPoolItem
+// class SwFormatMeta : public SfxPoolItem
+// class SwFormatVertOrient: public SfxPoolItem
+// class SwFormatHoriOrient: public SfxPoolItem
+// class SwFormatPageDesc : public SfxPoolItem, public SwClient
+// class SwFormatRefMark : public SfxPoolItem
+// class SwFormatRuby : public SfxPoolItem
+// class SwFormatURL: public SfxPoolItem
+// class SwFormatWrapInfluenceOnObjPos: public SfxPoolItem
+// class SwGammaGrf : public SfxPoolItem
+// class SwMsgPoolItem : public SfxPoolItem
+// class SwPtrMsgPoolItem : public SwMsgPoolItem
+// class SwFormatChg: public SwMsgPoolItem
+// class SwUpdateAttr : public SwMsgPoolItem
+// class SwTableFormulaUpdate : public SwMsgPoolItem
+// class SwAutoFormatGetDocNode: public SwMsgPoolItem
+// class SwAttrSetChg: public SwMsgPoolItem
+// class SwFindNearestNode : public SwMsgPoolItem
+// class SwStringMsgPoolItem : public SwMsgPoolItem
+// class SwFormatDrop: public SfxPoolItem, public SwClient
+// class SwTextGridItem : public SfxPoolItem
+// class SwTOXMark : public SfxPoolItem
+// class SwFltAnchor : public SfxPoolItem
+// class SwFltRedline : public SfxPoolItem
+// class SwFltBookmark : public SfxPoolItem
+// class SwFltRDFMark : public SfxPoolItem
+// class SwFltTOX : public SfxPoolItem
+// class SwDocDisplayItem : public SfxPoolItem
+// class SwElemItem : public SfxPoolItem
+// class SwAddPrinterItem : public SfxPoolItem, public SwPrintData
+// class SwShadowCursorItem : public SfxPoolItem
+// class SwTestItem : public SfxPoolItem
+// class SwEnvItem : public SfxPoolItem
+// class SwLabItem : public SfxPoolItem
+// class SwWrtShellItem: public SfxPoolItem
+// class SwPageFootnoteInfoItem : public SfxPoolItem
+// class SwPtrItem : public SfxPoolItem
+// class SwUINumRuleItem : public SfxPoolItem
+// class SwPaMItem : public SfxPoolItem
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG_UTIL
+static size_t nAllocatedSfxPoolItemCount(0);
+static size_t nUsedSfxPoolItemCount(0);
+size_t getAllocatedSfxPoolItemCount() { return nAllocatedSfxPoolItemCount; }
+size_t getUsedSfxPoolItemCount() { return nUsedSfxPoolItemCount; }
+static std::unordered_set<const SfxPoolItem*>& incarnatedSfxPoolItems()
+{
+ // Deferred instantiation to avoid initialization-order-fiasco:
+ static std::unordered_set<const SfxPoolItem*> items;
+ return items;
+}
+void listAllocatedSfxPoolItems()
+{
+ SAL_INFO("svl.items", "ITEM: List of still allocated SfxPoolItems:");
+ for (const auto& rCandidate : incarnatedSfxPoolItems())
+ {
+ SAL_INFO("svl.items", " ITEM: WhichID: " << rCandidate->Which() << " SerialNumber: "
+ << rCandidate->getSerialNumber()
+ << " Class: " << typeid(*rCandidate).name());
+ }
+}
+#endif
+
+SfxPoolItem::SfxPoolItem(sal_uInt16 const nWhich)
+ : m_nRefCount(0)
+ , m_nWhich(nWhich)
+#ifdef DBG_UTIL
+ , m_nSerialNumber(nUsedSfxPoolItemCount)
+#endif
+ , m_bIsVoidItem(false)
+ , m_bStaticDefault(false)
+ , m_bPoolDefault(false)
+ , m_bRegisteredAtPool(false)
+ , m_bExceptionalSCItem(false)
+ , m_bIsSetItem(false)
+#ifdef DBG_UTIL
+ , m_bDeleted(false)
+#endif
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxPoolItemCount++;
+ nUsedSfxPoolItemCount++;
+ incarnatedSfxPoolItems().insert(this);
+#endif
+ assert(nWhich <= SHRT_MAX);
+}
+
+SfxPoolItem::~SfxPoolItem()
+{
+#ifdef DBG_UTIL
+ nAllocatedSfxPoolItemCount--;
+ incarnatedSfxPoolItems().erase(this);
+ m_bDeleted = true;
+#endif
+ assert((m_nRefCount == 0 || m_nRefCount > SFX_ITEMS_MAXREF) && "destroying item in use");
+}
+
+bool SfxPoolItem::operator==(const SfxPoolItem& rCmp) const
+{
+ SAL_WARN_IF(typeid(rCmp) != typeid(*this), "svl",
+ "comparing different pool item subclasses " << typeid(rCmp).name() << " && "
+ << typeid(*this).name());
+ assert(typeid(rCmp) == typeid(*this) && "comparing different pool item subclasses");
+ (void)rCmp;
+ return true;
+}
+
+/**
+ * This virtual method allows to get a textual representation of the value
+ * for the SfxPoolItem subclasses. It should be overridden by all UI-relevant
+ * SfxPoolItem subclasses.
+ *
+ * Because the unit of measure of the value in the SfxItemPool is only
+ * queryable via @see SfxItemPool::GetMetric(sal_uInt16) const (and not
+ * via the SfxPoolItem instance or subclass, the own unit of measure is
+ * passed to 'eCoreMetric'.
+ *
+ * The corresponding unit of measure is passed as 'ePresentationMetric'.
+ *
+ *
+ * @return SfxItemPresentation SfxItemPresentation::Nameless
+ * A textual representation (if applicable
+ * with a unit of measure) could be created,
+ * but it doesn't contain any semantic meaning
+ *
+ * SfxItemPresentation::Complete
+ * A complete textual representation could be
+ * created with semantic meaning (if applicable
+ * with unit of measure)
+ *
+ * Example:
+ *
+ * pSvxFontItem->GetPresentation( SFX_PRESENTATION_NAMELESS, ... )
+ * "12pt" with return SfxItemPresentation::Nameless
+ *
+ * pSvxColorItem->GetPresentation( SFX_PRESENTATION_COMPLETE, ... )
+ * "red" with return SfxItemPresentation::Nameless
+ * Because the SvxColorItem does not know which color it represents
+ * it cannot provide a name, which is communicated by the return value
+ *
+ * pSvxBorderItem->GetPresentation( SFX_PRESENTATION_COMPLETE, ... )
+ * "1cm top border, 2cm left border, 0.2cm bottom border, ..."
+ */
+bool SfxPoolItem::GetPresentation(
+ SfxItemPresentation /*ePresentation*/, // IN: how we should format
+ MapUnit /*eCoreMetric*/, // IN: current metric of the SfxPoolItems
+ MapUnit /*ePresentationMetric*/, // IN: target metric of the presentation
+ OUString& /*rText*/, // OUT: textual representation
+ const IntlWrapper&) const
+{
+ return false;
+}
+
+void SfxPoolItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxPoolItem"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"),
+ BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("typeName"),
+ BAD_CAST(typeid(*this).name()));
+ OUString rText;
+ IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+ if (GetPresentation(SfxItemPresentation::Complete, MapUnit::Map100thMM, MapUnit::Map100thMM,
+ rText, aIntlWrapper))
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"),
+ BAD_CAST(rText.toUtf8().getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree SfxPoolItem::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree;
+ return aTree;
+}
+
+std::unique_ptr<SfxPoolItem> SfxPoolItem::CloneSetWhich(sal_uInt16 nNewWhich) const
+{
+ std::unique_ptr<SfxPoolItem> pItem(Clone());
+ pItem->SetWhich(nNewWhich);
+ return pItem;
+}
+
+void SfxPoolItem::ScaleMetrics(tools::Long /*lMult*/, tools::Long /*lDiv*/) {}
+
+bool SfxPoolItem::HasMetrics() const { return false; }
+
+bool SfxPoolItem::QueryValue(css::uno::Any&, sal_uInt8) const
+{
+ OSL_FAIL("There is no implementation for QueryValue for this item!");
+ return false;
+}
+
+bool SfxPoolItem::PutValue(const css::uno::Any&, sal_uInt8)
+{
+ OSL_FAIL("There is no implementation for PutValue for this item!");
+ return false;
+}
+
+bool areSfxPoolItemPtrsEqual(const SfxPoolItem* pItem1, const SfxPoolItem* pItem2)
+{
+#ifdef DBG_UTIL
+ if (nullptr != pItem1 && nullptr != pItem2 && pItem1->Which() == pItem2->Which()
+ && static_cast<const void*>(pItem1) != static_cast<const void*>(pItem2)
+ && typeid(*pItem1) == typeid(*pItem2) && *pItem1 == *pItem2)
+ {
+ SAL_INFO("svl.items", "ITEM: PtrCompare != ContentCompare (!)");
+ }
+#endif
+
+ // cast to void* to not trigger [loplugin:itemcompare]
+ return (static_cast<const void*>(pItem1) == static_cast<const void*>(pItem2));
+}
+
+bool SfxPoolItem::areSame(const SfxPoolItem* pItem1, const SfxPoolItem* pItem2)
+{
+ if (pItem1 == pItem2)
+ // pointer compare, this handles already
+ // nullptr, INVALID_POOL_ITEM, SfxVoidItem
+ // and if any Item is indeed handed over twice
+ return true;
+
+ if (nullptr == pItem1 || nullptr == pItem2)
+ // one ptr is nullptr, not both, that would
+ // have triggered above
+ return false;
+
+ if (pItem1->Which() != pItem2->Which())
+ // WhichIDs differ (fast)
+ return false;
+
+ if (typeid(*pItem1) != typeid(*pItem2))
+ // types differ (fast)
+ // NOTE: we can now use typeid since we do not have (-1)
+ // anymore for Invalid state -> safe
+ return false;
+
+ // return content compare using operator== at last
+ return *pItem1 == *pItem2;
+}
+
+bool SfxPoolItem::areSame(const SfxPoolItem& rItem1, const SfxPoolItem& rItem2)
+{
+ if (&rItem1 == &rItem2)
+ // still use pointer compare, this handles already
+ // nullptr, INVALID_POOL_ITEM, SfxVoidItem
+ // and if any Item is indeed handed over twice
+ return true;
+
+ if (rItem1.Which() != rItem2.Which())
+ // WhichIDs differ (fast)
+ return false;
+
+ if (typeid(rItem1) != typeid(rItem2))
+ // types differ (fast)
+ // NOTE: we can now use typeid since we do not have (-1)
+ // anymore for Invalid state -> safe
+ return false;
+
+ // return content compare using operator== at last
+ return rItem1 == rItem2;
+}
+
+namespace
+{
+class InvalidItem final : public SfxPoolItem
+{
+ virtual bool operator==(const SfxPoolItem&) const override { return true; }
+ virtual SfxPoolItem* Clone(SfxItemPool*) const override { return nullptr; }
+};
+InvalidItem aInvalidItem;
+}
+
+SfxPoolItem const* const INVALID_POOL_ITEM = &aInvalidItem;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/ptitem.cxx b/svl/source/items/ptitem.cxx
new file mode 100644
index 0000000000..361cb4f4fc
--- /dev/null
+++ b/svl/source/items/ptitem.cxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svl/ptitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <osl/diagnose.h>
+#include <tools/mapunit.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <svl/poolitem.hxx>
+#include <svl/memberid.h>
+
+using namespace ::com::sun::star;
+
+
+SfxPoolItem* SfxPointItem::CreateDefault() { return new SfxPointItem; }
+
+
+SfxPointItem::SfxPointItem()
+{
+}
+
+
+SfxPointItem::SfxPointItem( sal_uInt16 nW, const Point& rVal ) :
+ SfxPoolItem( nW ),
+ aVal( rVal )
+{
+}
+
+
+bool SfxPointItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+ rText = OUString::number(aVal.X()) + ", " + OUString::number(aVal.Y()) + ", ";
+ return true;
+}
+
+
+bool SfxPointItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return static_cast<const SfxPointItem&>(rItem).aVal == aVal;
+}
+
+SfxPointItem* SfxPointItem::Clone(SfxItemPool *) const
+{
+ return new SfxPointItem( *this );
+}
+
+bool SfxPointItem::QueryValue( uno::Any& rVal,
+ sal_uInt8 nMemberId ) const
+{
+ bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
+ awt::Point aTmp(aVal.X(), aVal.Y());
+ if( bConvert )
+ {
+ aTmp.X = convertTwipToMm100(aTmp.X);
+ aTmp.Y = convertTwipToMm100(aTmp.Y);
+ }
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case 0: rVal <<= aTmp; break;
+ case MID_X: rVal <<= aTmp.X; break;
+ case MID_Y: rVal <<= aTmp.Y; break;
+ default: OSL_FAIL("Wrong MemberId!"); return true;
+ }
+
+ return true;
+}
+
+
+bool SfxPointItem::PutValue( const uno::Any& rVal,
+ sal_uInt8 nMemberId )
+{
+ bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = false;
+ awt::Point aValue;
+ sal_Int32 nVal = 0;
+ if ( !nMemberId )
+ {
+ bRet = ( rVal >>= aValue );
+ if( bConvert )
+ {
+ aValue.X = o3tl::toTwips(aValue.X, o3tl::Length::mm100);
+ aValue.Y = o3tl::toTwips(aValue.Y, o3tl::Length::mm100);
+ }
+ }
+ else
+ {
+ bRet = ( rVal >>= nVal );
+ if( bConvert )
+ nVal = o3tl::toTwips(nVal, o3tl::Length::mm100);
+ }
+
+ if ( bRet )
+ {
+ switch ( nMemberId )
+ {
+ case 0: aVal.setX( aValue.X ); aVal.setY( aValue.Y ); break;
+ case MID_X: aVal.setX( nVal ); break;
+ case MID_Y: aVal.setY( nVal ); break;
+ default: OSL_FAIL("Wrong MemberId!"); return false;
+ }
+ }
+
+ return bRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/rectitem.cxx b/svl/source/items/rectitem.cxx
new file mode 100644
index 0000000000..f6a5db309d
--- /dev/null
+++ b/svl/source/items/rectitem.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svl/rectitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <osl/diagnose.h>
+
+#include <svl/poolitem.hxx>
+#include <svl/memberid.h>
+
+
+SfxPoolItem* SfxRectangleItem::CreateDefault() { return new SfxRectangleItem; }
+
+
+SfxRectangleItem::SfxRectangleItem()
+{
+}
+
+
+SfxRectangleItem::SfxRectangleItem( sal_uInt16 nW, const tools::Rectangle& rVal ) :
+ SfxPoolItem( nW ),
+ maVal( rVal )
+{
+}
+
+
+bool SfxRectangleItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+ rText = OUString::number(maVal.Top()) + ", " +
+ OUString::number(maVal.Left()) + ", " +
+ OUString::number(maVal.Bottom()) + ", " +
+ OUString::number(maVal.Right());
+ return true;
+}
+
+
+bool SfxRectangleItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return static_cast<const SfxRectangleItem&>(rItem).maVal == maVal;
+}
+
+SfxRectangleItem* SfxRectangleItem::Clone(SfxItemPool *) const
+{
+ return new SfxRectangleItem( *this );
+}
+
+bool SfxRectangleItem::QueryValue( css::uno::Any& rVal,
+ sal_uInt8 nMemberId) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ rVal <<= css::awt::Rectangle( maVal.Left(),
+ maVal.Top(),
+ maVal.getOpenWidth(),
+ maVal.getOpenHeight() );
+ break;
+ }
+ case MID_RECT_LEFT: rVal <<= maVal.Left(); break;
+ case MID_RECT_RIGHT: rVal <<= maVal.Top(); break;
+ case MID_WIDTH: rVal <<= maVal.getOpenWidth(); break;
+ case MID_HEIGHT: rVal <<= maVal.getOpenHeight(); break;
+ default: OSL_FAIL("Wrong MemberID!"); return false;
+ }
+
+ return true;
+}
+
+
+bool SfxRectangleItem::PutValue( const css::uno::Any& rVal,
+ sal_uInt8 nMemberId )
+{
+ bool bRet = false;
+ nMemberId &= ~CONVERT_TWIPS;
+ css::awt::Rectangle aValue;
+ sal_Int32 nVal = 0;
+ if ( !nMemberId )
+ bRet = (rVal >>= aValue);
+ else
+ bRet = (rVal >>= nVal);
+
+ if ( bRet )
+ {
+ switch ( nMemberId )
+ {
+ case 0:
+ maVal.SetLeft( aValue.X );
+ maVal.SetTop( aValue.Y );
+ maVal.setWidth( aValue.Width );
+ maVal.setHeight( aValue.Height );
+ break;
+ case MID_RECT_LEFT: maVal.SetPosX( nVal ); break;
+ case MID_RECT_RIGHT: maVal.SetPosY( nVal ); break;
+ case MID_WIDTH: maVal.setWidth( nVal ); break;
+ case MID_HEIGHT: maVal.setHeight( nVal ); break;
+ default: OSL_FAIL("Wrong MemberID!"); return false;
+ }
+ }
+
+ return bRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/rngitem.cxx b/svl/source/items/rngitem.cxx
new file mode 100644
index 0000000000..89f7e642ed
--- /dev/null
+++ b/svl/source/items/rngitem.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <svl/rngitem.hxx>
+
+
+SfxRangeItem::SfxRangeItem( sal_uInt16 which, sal_uInt16 from, sal_uInt16 to ):
+ SfxPoolItem( which ),
+ nFrom( from ),
+ nTo( to )
+{
+}
+
+
+bool SfxRangeItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+ rText = OUString::number(nFrom) + ":" + OUString::number(nTo);
+ return true;
+}
+
+
+bool SfxRangeItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ const SfxRangeItem& rT = static_cast<const SfxRangeItem&>(rItem);
+ return nFrom==rT.nFrom && nTo==rT.nTo;
+}
+
+SfxRangeItem* SfxRangeItem::Clone(SfxItemPool *) const
+{
+ return new SfxRangeItem( Which(), nFrom, nTo );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/sitem.cxx b/svl/source/items/sitem.cxx
new file mode 100644
index 0000000000..037097f7bc
--- /dev/null
+++ b/svl/source/items/sitem.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <rtl/ustring.hxx>
+#include <svl/itemset.hxx>
+#include <svl/setitem.hxx>
+#include <svl/poolitem.hxx>
+
+SfxSetItem::SfxSetItem( sal_uInt16 which, const SfxItemSet &rSet) :
+ SfxPoolItem(which),
+ maSet(rSet)
+{
+ assert(!dynamic_cast<const SfxAllItemSet*>(&rSet) && "cannot handle SfxAllItemSet here");
+ setIsSetItem();
+}
+
+
+SfxSetItem::SfxSetItem( sal_uInt16 which, SfxItemSet &&pS) :
+ SfxPoolItem(which),
+ maSet(pS)
+{
+ assert(!dynamic_cast<SfxAllItemSet*>(&pS) && "cannot handle SfxAllItemSet here");
+ setIsSetItem();
+}
+
+
+SfxSetItem::SfxSetItem( const SfxSetItem& rCopy, SfxItemPool *pPool ) :
+ SfxPoolItem(rCopy),
+ maSet(rCopy.maSet.CloneAsValue(true, pPool))
+{
+ assert(!dynamic_cast<const SfxAllItemSet*>(&rCopy.maSet) && "cannot handle SfxAllItemSet here");
+ setIsSetItem();
+}
+
+
+bool SfxSetItem::operator==( const SfxPoolItem& rCmp) const
+{
+ assert(SfxPoolItem::operator==(rCmp));
+ return maSet == static_cast<const SfxSetItem &>(rCmp).maSet;
+}
+
+
+bool SfxSetItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& /*rText*/,
+ const IntlWrapper&
+) const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/slstitm.cxx b/svl/source/items/slstitm.cxx
new file mode 100644
index 0000000000..02784446ca
--- /dev/null
+++ b/svl/source/items/slstitm.cxx
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svl/slstitm.hxx>
+#include <svl/poolitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <comphelper/sequence.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <tools/lineend.hxx>
+
+SfxPoolItem* SfxStringListItem::CreateDefault() { return new SfxStringListItem; }
+
+SfxStringListItem::SfxStringListItem()
+{
+}
+
+
+SfxStringListItem::SfxStringListItem( sal_uInt16 which, const std::vector<OUString>* pList ) :
+ SfxPoolItem( which )
+{
+ // FIXME: Putting an empty list does not work
+ // Therefore the query after the count is commented out
+ if( pList /*!!! && pList->Count() */ )
+ {
+ mpList = std::make_shared<std::vector<OUString>>(*pList);
+ }
+}
+
+
+SfxStringListItem::~SfxStringListItem()
+{
+}
+
+
+std::vector<OUString>& SfxStringListItem::GetList()
+{
+ if( !mpList )
+ mpList = std::make_shared<std::vector<OUString>>();
+ return *mpList;
+}
+
+const std::vector<OUString>& SfxStringListItem::GetList () const
+{
+ return const_cast< SfxStringListItem * >(this)->GetList();
+}
+
+
+bool SfxStringListItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+
+ const SfxStringListItem& rSSLItem = static_cast<const SfxStringListItem&>(rItem);
+
+ return mpList == rSSLItem.mpList;
+}
+
+
+bool SfxStringListItem::GetPresentation
+(
+ SfxItemPresentation /*ePresentation*/,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/,
+ OUString& rText,
+ const IntlWrapper&
+) const
+{
+ rText = "(List)";
+ return false;
+}
+
+SfxStringListItem* SfxStringListItem::Clone( SfxItemPool *) const
+{
+ return new SfxStringListItem( *this );
+}
+
+void SfxStringListItem::SetString( const OUString& rStr )
+{
+ mpList = std::make_shared<std::vector<OUString>>();
+
+ OUString aStr(convertLineEnd(rStr, LINEEND_CR));
+ // put last string only if not empty
+ for (sal_Int32 nStart = 0; nStart >= 0 && nStart < aStr.getLength();)
+ mpList->push_back(aStr.getToken(0, '\r', nStart));
+}
+
+
+OUString SfxStringListItem::GetString()
+{
+ OUStringBuffer aStr;
+ if ( mpList )
+ {
+ for (auto iter = mpList->begin(), end = mpList->end(); iter != end;)
+ {
+ aStr.append(*iter);
+ ++iter;
+
+ if (iter == end)
+ break;
+
+ aStr.append(SAL_NEWLINE_STRING);
+ }
+ }
+ return aStr.makeStringAndClear();
+}
+
+
+void SfxStringListItem::SetStringList( const css::uno::Sequence< OUString >& rList )
+{
+ mpList = std::make_shared<std::vector<OUString>>(
+ comphelper::sequenceToContainer<std::vector<OUString>>(rList));
+}
+
+void SfxStringListItem::GetStringList( css::uno::Sequence< OUString >& rList ) const
+{
+ size_t nCount = mpList->size();
+
+ rList.realloc( nCount );
+ auto pList = rList.getArray();
+ for( size_t i=0; i < nCount; i++ )
+ pList[i] = (*mpList)[i];
+}
+
+// virtual
+bool SfxStringListItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
+{
+ css::uno::Sequence< OUString > aValue;
+ if ( rVal >>= aValue )
+ {
+ SetStringList( aValue );
+ return true;
+ }
+
+ OSL_FAIL( "SfxStringListItem::PutValue - Wrong type!" );
+ return false;
+}
+
+// virtual
+bool SfxStringListItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
+{
+ css::uno::Sequence< OUString > aStringList;
+ GetStringList( aStringList );
+ rVal <<= aStringList;
+ return true;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/srchitem.cxx b/svl/source/items/srchitem.cxx
new file mode 100644
index 0000000000..1300bf744a
--- /dev/null
+++ b/svl/source/items/srchitem.cxx
@@ -0,0 +1,662 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <sal/log.hxx>
+#include <svl/srchitem.hxx>
+#include <sal/macros.h>
+#include <osl/diagnose.h>
+
+#include <comphelper/propertyvalue.hxx>
+#include <unotools/searchopt.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <svl/memberid.h>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <unordered_set>
+
+using namespace utl;
+using namespace com::sun::star;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+
+constexpr OUString CFG_ROOT_NODE = u"Office.Common/SearchOptions"_ustr;
+
+#define SRCH_PARAMS 13
+constexpr OUString SRCH_PARA_OPTIONS = u"Options"_ustr;
+constexpr OUString SRCH_PARA_FAMILY = u"Family"_ustr;
+constexpr OUString SRCH_PARA_COMMAND = u"Command"_ustr;
+constexpr OUString SRCH_PARA_CELLTYPE = u"CellType"_ustr;
+constexpr OUString SRCH_PARA_APPFLAG = u"AppFlag"_ustr;
+constexpr OUString SRCH_PARA_ROWDIR = u"RowDirection"_ustr;
+constexpr OUString SRCH_PARA_ALLTABLES = u"AllTables"_ustr;
+constexpr OUString SRCH_PARA_SEARCHFILTERED = u"SearchFiltered"_ustr;
+constexpr OUString SRCH_PARA_SEARCHFORMATTED = u"SearchFormatted"_ustr;
+constexpr OUString SRCH_PARA_BACKWARD = u"Backward"_ustr;
+constexpr OUString SRCH_PARA_PATTERN = u"Pattern"_ustr;
+constexpr OUString SRCH_PARA_CONTENT = u"Content"_ustr;
+constexpr OUString SRCH_PARA_ASIANOPT = u"AsianOptions"_ustr;
+
+SfxPoolItem* SvxSearchItem::CreateDefault() { return new SvxSearchItem(0);}
+
+
+static Sequence< OUString > lcl_GetNotifyNames()
+{
+ // names of transliteration relevant properties
+ static const char* aTranslitNames[] =
+ {
+ "IsMatchCase", // 0
+ "Japanese/IsMatchFullHalfWidthForms", // 1
+ "Japanese/IsMatchHiraganaKatakana", // 2
+ "Japanese/IsMatchContractions", // 3
+ "Japanese/IsMatchMinusDashCho-on", // 4
+ "Japanese/IsMatchRepeatCharMarks", // 5
+ "Japanese/IsMatchVariantFormKanji", // 6
+ "Japanese/IsMatchOldKanaForms", // 7
+ "Japanese/IsMatch_DiZi_DuZu", // 8
+ "Japanese/IsMatch_BaVa_HaFa", // 9
+ "Japanese/IsMatch_TsiThiChi_DhiZi", // 10
+ "Japanese/IsMatch_HyuIyu_ByuVyu", // 11
+ "Japanese/IsMatch_SeShe_ZeJe", // 12
+ "Japanese/IsMatch_IaIya", // 13
+ "Japanese/IsMatch_KiKu", // 14
+ "Japanese/IsIgnorePunctuation", // 15
+ "Japanese/IsIgnoreWhitespace", // 16
+ "Japanese/IsIgnoreProlongedSoundMark", // 17
+ "Japanese/IsIgnoreMiddleDot", // 18
+ "IsIgnoreDiacritics_CTL", // 19
+ "IsIgnoreKashida_CTL" // 20
+ };
+
+ const int nCount = SAL_N_ELEMENTS( aTranslitNames );
+ Sequence< OUString > aNames( nCount );
+ OUString* pNames = aNames.getArray();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ pNames[i] = OUString::createFromAscii( aTranslitNames[i] );
+
+ return aNames;
+}
+
+
+SvxSearchItem::SvxSearchItem( const sal_uInt16 nId ) :
+
+ SfxPoolItem( nId ),
+ ConfigItem( CFG_ROOT_NODE ),
+
+ m_aSearchOpt ( SearchFlags::LEV_RELAXED,
+ OUString(),
+ OUString(),
+ lang::Locale(),
+ 2, 2, 2,
+ TransliterationFlags::IGNORE_CASE,
+ SearchAlgorithms2::ABSOLUTE, '\\' ),
+ m_eFamily ( SfxStyleFamily::Para ),
+ m_nCommand ( SvxSearchCmd::FIND ),
+ m_nCellType ( SvxSearchCellType::FORMULA ),
+ m_nAppFlag ( SvxSearchApp::WRITER ),
+ m_bRowDirection ( true ),
+ m_bAllTables ( false ),
+ m_bSearchFiltered ( false ),
+ m_bSearchFormatted( false ),
+ m_bNotes ( false),
+ m_bBackward ( false ),
+ m_bPattern ( false ),
+ m_bContent ( false ),
+ m_bAsianOptions ( false ),
+ m_nStartPointX(0),
+ m_nStartPointY(0)
+{
+ EnableNotification( lcl_GetNotifyNames() );
+
+ SvtSearchOptions aOpt;
+
+ m_bBackward = aOpt.IsBackwards();
+ m_bAsianOptions = aOpt.IsUseAsianOptions();
+ m_bNotes = aOpt.IsNotes();
+
+ if (aOpt.IsUseWildcard())
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::WILDCARD;
+ }
+ if (aOpt.IsUseRegularExpression())
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::REGEXP;
+ }
+ if (aOpt.IsSimilaritySearch())
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::APPROXIMATE;
+ }
+ if (aOpt.IsWholeWordsOnly())
+ m_aSearchOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY;
+
+ TransliterationFlags& rFlags = m_aSearchOpt.transliterateFlags;
+
+ if (!aOpt.IsMatchCase())
+ rFlags |= TransliterationFlags::IGNORE_CASE;
+ if ( aOpt.IsMatchFullHalfWidthForms())
+ rFlags |= TransliterationFlags::IGNORE_WIDTH;
+ if ( aOpt.IsIgnoreDiacritics_CTL())
+ rFlags |= TransliterationFlags::IGNORE_DIACRITICS_CTL ;
+ if ( aOpt.IsIgnoreKashida_CTL())
+ rFlags |= TransliterationFlags::IGNORE_KASHIDA_CTL ;
+ if ( !m_bAsianOptions )
+ return;
+
+ if ( aOpt.IsMatchHiraganaKatakana())
+ rFlags |= TransliterationFlags::IGNORE_KANA;
+ if ( aOpt.IsMatchContractions())
+ rFlags |= TransliterationFlags::ignoreSize_ja_JP;
+ if ( aOpt.IsMatchMinusDashChoon())
+ rFlags |= TransliterationFlags::ignoreMinusSign_ja_JP;
+ if ( aOpt.IsMatchRepeatCharMarks())
+ rFlags |= TransliterationFlags::ignoreIterationMark_ja_JP;
+ if ( aOpt.IsMatchVariantFormKanji())
+ rFlags |= TransliterationFlags::ignoreTraditionalKanji_ja_JP;
+ if ( aOpt.IsMatchOldKanaForms())
+ rFlags |= TransliterationFlags::ignoreTraditionalKana_ja_JP;
+ if ( aOpt.IsMatchDiziDuzu())
+ rFlags |= TransliterationFlags::ignoreZiZu_ja_JP;
+ if ( aOpt.IsMatchBavaHafa())
+ rFlags |= TransliterationFlags::ignoreBaFa_ja_JP;
+ if ( aOpt.IsMatchTsithichiDhizi())
+ rFlags |= TransliterationFlags::ignoreTiJi_ja_JP;
+ if ( aOpt.IsMatchHyuiyuByuvyu())
+ rFlags |= TransliterationFlags::ignoreHyuByu_ja_JP;
+ if ( aOpt.IsMatchSesheZeje())
+ rFlags |= TransliterationFlags::ignoreSeZe_ja_JP;
+ if ( aOpt.IsMatchIaiya())
+ rFlags |= TransliterationFlags::ignoreIandEfollowedByYa_ja_JP;
+ if ( aOpt.IsMatchKiku())
+ rFlags |= TransliterationFlags::ignoreKiKuFollowedBySa_ja_JP;
+ if ( aOpt.IsIgnorePunctuation())
+ rFlags |= TransliterationFlags::ignoreSeparator_ja_JP;
+ if ( aOpt.IsIgnoreWhitespace())
+ rFlags |= TransliterationFlags::ignoreSpace_ja_JP;
+ if ( aOpt.IsIgnoreProlongedSoundMark())
+ rFlags |= TransliterationFlags::ignoreProlongedSoundMark_ja_JP;
+ if ( aOpt.IsIgnoreMiddleDot())
+ rFlags |= TransliterationFlags::ignoreMiddleDot_ja_JP;
+}
+
+
+SvxSearchItem::SvxSearchItem( const SvxSearchItem& rItem ) :
+
+ SfxPoolItem ( rItem ),
+ ConfigItem( CFG_ROOT_NODE ),
+
+ m_aSearchOpt ( rItem.m_aSearchOpt ),
+ m_eFamily ( rItem.m_eFamily ),
+ m_nCommand ( rItem.m_nCommand ),
+ m_nCellType ( rItem.m_nCellType ),
+ m_nAppFlag ( rItem.m_nAppFlag ),
+ m_bRowDirection ( rItem.m_bRowDirection ),
+ m_bAllTables ( rItem.m_bAllTables ),
+ m_bSearchFiltered ( rItem.m_bSearchFiltered ),
+ m_bSearchFormatted ( rItem.m_bSearchFormatted ),
+ m_bNotes ( rItem.m_bNotes),
+ m_bBackward ( rItem.m_bBackward ),
+ m_bPattern ( rItem.m_bPattern ),
+ m_bContent ( rItem.m_bContent ),
+ m_bAsianOptions ( rItem.m_bAsianOptions ),
+ m_nStartPointX(rItem.m_nStartPointX),
+ m_nStartPointY(rItem.m_nStartPointY)
+{
+ EnableNotification( lcl_GetNotifyNames() );
+}
+
+SvxSearchItem::~SvxSearchItem()
+{
+}
+
+SvxSearchItem* SvxSearchItem::Clone( SfxItemPool *) const
+{
+ return new SvxSearchItem(*this);
+}
+
+//! used below
+static bool equalsWithoutLocaleOrReplace(const i18nutil::SearchOptions2& rItem1,
+ const i18nutil::SearchOptions2& rItem2)
+{
+ return rItem1.searchFlag == rItem2.searchFlag &&
+ rItem1.searchString == rItem2.searchString &&
+ //rItem1.replaceString == rItem2.replaceString &&
+ //rItem1.Locale == rItem2.Locale &&
+ rItem1.changedChars == rItem2.changedChars &&
+ rItem1.deletedChars == rItem2.deletedChars &&
+ rItem1.insertedChars == rItem2.insertedChars &&
+ rItem1.transliterateFlags == rItem2.transliterateFlags &&
+ rItem1.AlgorithmType2 == rItem2.AlgorithmType2 &&
+ rItem1.WildcardEscapeCharacter == rItem2.WildcardEscapeCharacter;
+}
+
+
+bool SvxSearchItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ const SvxSearchItem &rSItem = static_cast<const SvxSearchItem &>(rItem);
+ return equalsIgnoring(rSItem, /*bIgnoreReplace=*/false, /*bIgnoreCommand=*/false);
+}
+
+bool SvxSearchItem::equalsIgnoring(const SvxSearchItem& rSItem, bool bIgnoreReplace,
+ bool bIgnoreCommand) const
+{
+ if (!bIgnoreReplace && m_aSearchOpt.replaceString != rSItem.m_aSearchOpt.replaceString)
+ return false;
+ if (!bIgnoreCommand && m_nCommand != rSItem.m_nCommand)
+ return false;
+
+ return ( m_bBackward == rSItem.m_bBackward ) &&
+ ( m_bPattern == rSItem.m_bPattern ) &&
+ ( m_bContent == rSItem.m_bContent ) &&
+ ( m_eFamily == rSItem.m_eFamily ) &&
+ ( m_bRowDirection == rSItem.m_bRowDirection ) &&
+ ( m_bAllTables == rSItem.m_bAllTables ) &&
+ ( m_bSearchFiltered == rSItem.m_bSearchFiltered ) &&
+ ( m_bSearchFormatted == rSItem.m_bSearchFormatted ) &&
+ ( m_nCellType == rSItem.m_nCellType ) &&
+ ( m_nAppFlag == rSItem.m_nAppFlag ) &&
+ ( m_bAsianOptions == rSItem.m_bAsianOptions ) &&
+ ( equalsWithoutLocaleOrReplace(m_aSearchOpt, rSItem.m_aSearchOpt )) &&
+ ( m_bNotes == rSItem.m_bNotes );
+}
+
+
+bool SvxSearchItem::GetPresentation
+(
+ SfxItemPresentation ,
+ MapUnit ,
+ MapUnit ,
+ OUString& ,
+ const IntlWrapper&
+) const
+{
+ return false;
+}
+
+void SvxSearchItem::Notify( const Sequence< OUString > & )
+{
+ // applies transliteration changes in the configuration database
+ // to the current SvxSearchItem
+ SetTransliterationFlags( SvtSearchOptions().GetTransliterationFlags() );
+}
+
+void SvxSearchItem::ImplCommit()
+{
+}
+
+void SvxSearchItem::SetMatchFullHalfWidthForms( bool bVal )
+{
+ if (bVal)
+ m_aSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_WIDTH;
+ else
+ m_aSearchOpt.transliterateFlags &= ~TransliterationFlags::IGNORE_WIDTH;
+}
+
+
+void SvxSearchItem::SetWordOnly( bool bVal )
+{
+ if (bVal)
+ m_aSearchOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY;
+ else
+ m_aSearchOpt.searchFlag &= ~SearchFlags::NORM_WORD_ONLY;
+}
+
+
+void SvxSearchItem::SetExact( bool bVal )
+{
+ if (!bVal)
+ m_aSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+ else
+ m_aSearchOpt.transliterateFlags &= ~TransliterationFlags::IGNORE_CASE;
+}
+
+
+void SvxSearchItem::SetSelection( bool bVal )
+{
+ if (bVal)
+ {
+ m_aSearchOpt.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
+ SearchFlags::REG_NOT_ENDOFLINE);
+ }
+ else
+ {
+ m_aSearchOpt.searchFlag &= ~(SearchFlags::REG_NOT_BEGINOFLINE |
+ SearchFlags::REG_NOT_ENDOFLINE);
+ }
+}
+
+
+void SvxSearchItem::SetRegExp( bool bVal )
+{
+ if ( bVal )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::REGEXP;
+ }
+ else if ( SearchAlgorithms2::REGEXP == m_aSearchOpt.AlgorithmType2 )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE;
+ }
+}
+
+
+void SvxSearchItem::SetWildcard( bool bVal )
+{
+ if ( bVal )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::WILDCARD;
+ }
+ else if ( SearchAlgorithms2::REGEXP == m_aSearchOpt.AlgorithmType2 )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE;
+ }
+}
+
+
+void SvxSearchItem::SetLEVRelaxed( bool bVal )
+{
+ if (bVal)
+ m_aSearchOpt.searchFlag |= SearchFlags::LEV_RELAXED;
+ else
+ m_aSearchOpt.searchFlag &= ~SearchFlags::LEV_RELAXED;
+}
+
+
+void SvxSearchItem::SetLevenshtein( bool bVal )
+{
+ if ( bVal )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::APPROXIMATE;
+ }
+ else if ( SearchAlgorithms2::APPROXIMATE == m_aSearchOpt.AlgorithmType2 )
+ {
+ m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE;
+ }
+}
+
+
+void SvxSearchItem::SetTransliterationFlags( TransliterationFlags nFlags )
+{
+ m_aSearchOpt.transliterateFlags = nFlags;
+}
+
+bool SvxSearchItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case 0 :
+ {
+ Sequence<PropertyValue> aSeq{
+ comphelper::makePropertyValue(SRCH_PARA_OPTIONS,
+ m_aSearchOpt.toUnoSearchOptions2()),
+ comphelper::makePropertyValue(SRCH_PARA_FAMILY, sal_Int16(m_eFamily)),
+ comphelper::makePropertyValue(SRCH_PARA_COMMAND,
+ static_cast<sal_uInt16>(m_nCommand)),
+ comphelper::makePropertyValue(SRCH_PARA_CELLTYPE,
+ static_cast<sal_uInt16>(m_nCellType)),
+ comphelper::makePropertyValue(SRCH_PARA_APPFLAG,
+ static_cast<sal_uInt16>(m_nAppFlag)),
+ comphelper::makePropertyValue(SRCH_PARA_ROWDIR, m_bRowDirection),
+ comphelper::makePropertyValue(SRCH_PARA_ALLTABLES, m_bAllTables),
+ comphelper::makePropertyValue(SRCH_PARA_SEARCHFILTERED, m_bSearchFiltered),
+ comphelper::makePropertyValue(SRCH_PARA_SEARCHFORMATTED, m_bSearchFormatted),
+ comphelper::makePropertyValue(SRCH_PARA_BACKWARD, m_bBackward),
+ comphelper::makePropertyValue(SRCH_PARA_PATTERN, m_bPattern),
+ comphelper::makePropertyValue(SRCH_PARA_CONTENT, m_bContent),
+ comphelper::makePropertyValue(SRCH_PARA_ASIANOPT, m_bAsianOptions)
+ };
+ assert(aSeq.getLength() == SRCH_PARAMS);
+ rVal <<= aSeq;
+ }
+ break;
+ case MID_SEARCH_COMMAND:
+ rVal <<= static_cast<sal_Int16>(m_nCommand); break;
+ case MID_SEARCH_STYLEFAMILY:
+ rVal <<= static_cast<sal_Int16>(m_eFamily); break;
+ case MID_SEARCH_CELLTYPE:
+ rVal <<= static_cast<sal_Int32>(m_nCellType); break;
+ case MID_SEARCH_ROWDIRECTION:
+ rVal <<= m_bRowDirection; break;
+ case MID_SEARCH_ALLTABLES:
+ rVal <<= m_bAllTables; break;
+ case MID_SEARCH_SEARCHFILTERED:
+ rVal <<= m_bSearchFiltered; break;
+ case MID_SEARCH_SEARCHFORMATTED:
+ rVal <<= m_bSearchFormatted; break;
+ case MID_SEARCH_BACKWARD:
+ rVal <<= m_bBackward; break;
+ case MID_SEARCH_PATTERN:
+ rVal <<= m_bPattern; break;
+ case MID_SEARCH_CONTENT:
+ rVal <<= m_bContent; break;
+ case MID_SEARCH_ASIANOPTIONS:
+ rVal <<= m_bAsianOptions; break;
+ case MID_SEARCH_ALGORITHMTYPE:
+ rVal <<= static_cast<sal_Int16>(i18nutil::downgradeSearchAlgorithms2(m_aSearchOpt.AlgorithmType2)); break;
+ case MID_SEARCH_ALGORITHMTYPE2:
+ rVal <<= m_aSearchOpt.AlgorithmType2; break;
+ case MID_SEARCH_FLAGS:
+ rVal <<= m_aSearchOpt.searchFlag; break;
+ case MID_SEARCH_SEARCHSTRING:
+ rVal <<= m_aSearchOpt.searchString; break;
+ case MID_SEARCH_REPLACESTRING:
+ rVal <<= m_aSearchOpt.replaceString; break;
+ case MID_SEARCH_CHANGEDCHARS:
+ rVal <<= m_aSearchOpt.changedChars; break;
+ case MID_SEARCH_DELETEDCHARS:
+ rVal <<= m_aSearchOpt.deletedChars; break;
+ case MID_SEARCH_INSERTEDCHARS:
+ rVal <<= m_aSearchOpt.insertedChars; break;
+ case MID_SEARCH_TRANSLITERATEFLAGS:
+ rVal <<= static_cast<sal_Int32>(m_aSearchOpt.transliterateFlags); break;
+ case MID_SEARCH_LOCALE:
+ {
+ LanguageType nLocale;
+ if (!m_aSearchOpt.Locale.Language.isEmpty() || !m_aSearchOpt.Locale.Country.isEmpty() )
+ nLocale = LanguageTag::convertToLanguageType( m_aSearchOpt.Locale );
+ else
+ nLocale = LANGUAGE_NONE;
+ rVal <<= static_cast<sal_Int16>(static_cast<sal_uInt16>(nLocale));
+ break;
+ }
+
+ default:
+ SAL_WARN( "svl.items", "SvxSearchItem::QueryValue(): Unknown MemberId" );
+ return false;
+ }
+
+ return true;
+}
+
+
+bool SvxSearchItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ auto ExtractNumericAny = [](const css::uno::Any& a, auto& target)
+ {
+ sal_Int32 nInt;
+ if (!(a >>= nInt))
+ return false;
+ target = static_cast<std::remove_reference_t<decltype(target)>>(nInt);
+ return true;
+ };
+ switch ( nMemberId )
+ {
+ case 0 :
+ {
+ Sequence< PropertyValue > aSeq;
+ if (!(rVal >>= aSeq) || aSeq.getLength() != SRCH_PARAMS)
+ break;
+ std::unordered_set<OUString> aConvertedParams;
+ for (const auto& rProp : aSeq)
+ {
+ if (rProp.Name == SRCH_PARA_OPTIONS)
+ {
+ if (css::util::SearchOptions2 nTmpSearchOpt2; rProp.Value >>= nTmpSearchOpt2)
+ {
+ m_aSearchOpt = nTmpSearchOpt2;
+ aConvertedParams.insert(rProp.Name);
+ }
+ }
+ else if (rProp.Name == SRCH_PARA_FAMILY)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_STYLEFAMILY))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_COMMAND)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_COMMAND))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_CELLTYPE)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_CELLTYPE))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_APPFLAG)
+ {
+ if (ExtractNumericAny(rProp.Value, m_nAppFlag))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_ROWDIR)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_ROWDIRECTION))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_ALLTABLES)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_ALLTABLES))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_SEARCHFILTERED)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_SEARCHFILTERED))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_SEARCHFORMATTED)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_SEARCHFORMATTED))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_BACKWARD)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_BACKWARD))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_PATTERN)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_PATTERN))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_CONTENT)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_CONTENT))
+ aConvertedParams.insert(rProp.Name);
+ }
+ else if (rProp.Name == SRCH_PARA_ASIANOPT)
+ {
+ if (SvxSearchItem::PutValue(rProp.Value, MID_SEARCH_ASIANOPTIONS))
+ aConvertedParams.insert(rProp.Name);
+ }
+ }
+ return aConvertedParams.size() == SRCH_PARAMS;
+ }
+ case MID_SEARCH_COMMAND:
+ return ExtractNumericAny(rVal, m_nCommand);
+ case MID_SEARCH_STYLEFAMILY:
+ return ExtractNumericAny(rVal, m_eFamily);
+ case MID_SEARCH_CELLTYPE:
+ return ExtractNumericAny(rVal, m_nCellType);
+ case MID_SEARCH_ROWDIRECTION:
+ return (rVal >>= m_bRowDirection);
+ case MID_SEARCH_ALLTABLES:
+ return (rVal >>= m_bAllTables);
+ case MID_SEARCH_SEARCHFILTERED:
+ return (rVal >>= m_bSearchFiltered);
+ case MID_SEARCH_SEARCHFORMATTED:
+ return (rVal >>= m_bSearchFormatted);
+ case MID_SEARCH_BACKWARD:
+ return (rVal >>= m_bBackward);
+ case MID_SEARCH_PATTERN:
+ return (rVal >>= m_bPattern);
+ case MID_SEARCH_CONTENT:
+ return (rVal >>= m_bContent);
+ case MID_SEARCH_ASIANOPTIONS:
+ return (rVal >>= m_bAsianOptions);
+ case MID_SEARCH_ALGORITHMTYPE:
+ if (SearchAlgorithms eVal; ExtractNumericAny(rVal, eVal))
+ {
+ m_aSearchOpt.AlgorithmType2 = i18nutil::upgradeSearchAlgorithms(eVal);
+ return true;
+ }
+ break;
+ case MID_SEARCH_ALGORITHMTYPE2:
+ return (rVal >>= m_aSearchOpt.AlgorithmType2);
+ case MID_SEARCH_FLAGS:
+ return (rVal >>= m_aSearchOpt.searchFlag);
+ case MID_SEARCH_SEARCHSTRING:
+ return (rVal >>= m_aSearchOpt.searchString);
+ case MID_SEARCH_REPLACESTRING:
+ return (rVal >>= m_aSearchOpt.replaceString);
+ case MID_SEARCH_CHANGEDCHARS:
+ return (rVal >>= m_aSearchOpt.changedChars);
+ case MID_SEARCH_DELETEDCHARS:
+ return (rVal >>= m_aSearchOpt.deletedChars);
+ case MID_SEARCH_INSERTEDCHARS:
+ return (rVal >>= m_aSearchOpt.insertedChars);
+ case MID_SEARCH_TRANSLITERATEFLAGS:
+ return ExtractNumericAny(rVal, m_aSearchOpt.transliterateFlags);
+ case MID_SEARCH_LOCALE:
+ if (LanguageType aVal; ExtractNumericAny(rVal, aVal))
+ {
+ m_aSearchOpt.Locale = (aVal == LANGUAGE_NONE) ? css::lang::Locale()
+ : LanguageTag::convertToLocale(aVal);
+ return true;
+ }
+ break;
+ case MID_SEARCH_STARTPOINTX:
+ return (rVal >>= m_nStartPointX);
+ case MID_SEARCH_STARTPOINTY:
+ return (rVal >>= m_nStartPointY);
+ default:
+ OSL_FAIL( "Unknown MemberId" );
+ }
+
+ return false;
+}
+
+sal_Int32 SvxSearchItem::GetStartPointX() const
+{
+ return m_nStartPointX;
+}
+
+sal_Int32 SvxSearchItem::GetStartPointY() const
+{
+ return m_nStartPointY;
+}
+
+bool SvxSearchItem::HasStartPoint() const
+{
+ return m_nStartPointX > 0 || m_nStartPointY > 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/stringio.cxx b/svl/source/items/stringio.cxx
new file mode 100644
index 0000000000..5345e165aa
--- /dev/null
+++ b/svl/source/items/stringio.cxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stringio.hxx>
+
+#include <tools/stream.hxx>
+
+OUString readByteString(SvStream& rStream)
+{
+ return rStream.ReadUniOrByteString(rStream.GetStreamCharSet());
+}
+
+void writeByteString(SvStream& rStream, std::u16string_view rString)
+{
+ rStream.WriteUniOrByteString(rString, rStream.GetStreamCharSet());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/stritem.cxx b/svl/source/items/stritem.cxx
new file mode 100644
index 0000000000..c0ec01a9ab
--- /dev/null
+++ b/svl/source/items/stritem.cxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/stritem.hxx>
+#include <libxml/xmlwriter.h>
+
+// virtual
+SfxStringItem* SfxStringItem::Clone(SfxItemPool *) const
+{
+ return new SfxStringItem(*this);
+}
+
+void SfxStringItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxStringItem"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(GetValue().toUtf8().getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+SfxPoolItem* SfxStringItem::CreateDefault()
+{
+ return new SfxStringItem();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/style.cxx b/svl/source/items/style.cxx
new file mode 100644
index 0000000000..41551e5064
--- /dev/null
+++ b/svl/source/items/style.cxx
@@ -0,0 +1,905 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <svl/style.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <unotools/intlwrapper.hxx>
+#include <svl/hint.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/itemset.hxx>
+#include <svl/itempool.hxx>
+#include <svl/IndexedStyleSheets.hxx>
+#include <svl/itemiter.hxx>
+#include <unotools/syslocale.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <utility>
+
+#ifdef DBG_UTIL
+namespace {
+
+class DbgStyleSheetReferences
+{
+public:
+ DbgStyleSheetReferences() : mnStyles(0), mnPools(0) {}
+ ~DbgStyleSheetReferences()
+ {
+ SAL_WARN_IF(
+ mnStyles != 0 || mnPools != 0, "svl.items",
+ "SfxStyleSheetBase left " << mnStyles
+ << "; SfxStyleSheetBasePool left " << mnPools);
+ }
+
+ sal_uInt32 mnStyles;
+ sal_uInt32 mnPools;
+};
+
+}
+
+static DbgStyleSheetReferences aDbgStyleSheetReferences;
+#endif
+
+
+SfxStyleSheetModifiedHint::SfxStyleSheetModifiedHint
+(
+ OUString aOldName,
+ SfxStyleSheetBase& rStyleSheet // Remains with the caller
+)
+: SfxStyleSheetHint( SfxHintId::StyleSheetModified, rStyleSheet ),
+ aName(std::move( aOldName ))
+{}
+
+
+SfxStyleSheetHint::SfxStyleSheetHint
+(
+ SfxHintId nAction,
+ SfxStyleSheetBase& rStyleSheet // Remains with the caller
+)
+: SfxHint(nAction), pStyleSh( &rStyleSheet )
+{}
+
+
+class SfxStyleSheetBasePool_Impl
+{
+private:
+ SfxStyleSheetBasePool_Impl(const SfxStyleSheetBasePool_Impl&) = delete;
+ SfxStyleSheetBasePool_Impl& operator=(const SfxStyleSheetBasePool_Impl&) = delete;
+public:
+ std::shared_ptr<SfxStyleSheetIterator> pIter;
+
+ /** This member holds the indexed style sheets.
+ *
+ * @internal
+ * This member is private and not protected in order to have more control which style sheets are added
+ * where. Ideally, all calls which add/remove/change style sheets are done in the base class.
+ */
+ std::shared_ptr<svl::IndexedStyleSheets> mxIndexedStyleSheets;
+
+ SfxStyleSheetBasePool_Impl() :
+ mxIndexedStyleSheets(std::make_shared<svl::IndexedStyleSheets>()) {}
+};
+
+
+SfxStyleSheetBase::SfxStyleSheetBase( const OUString& rName, SfxStyleSheetBasePool* p, SfxStyleFamily eFam, SfxStyleSearchBits mask )
+ : m_pPool( p )
+ , nFamily( eFam )
+ , aName( rName )
+ , aFollow( rName )
+ , pSet( nullptr )
+ , nMask(mask)
+ , nHelpId( 0 )
+ , bMySet( false )
+ , bHidden( false )
+{
+#ifdef DBG_UTIL
+ aDbgStyleSheetReferences.mnStyles++;
+#endif
+}
+
+SfxStyleSheetBase::SfxStyleSheetBase( const SfxStyleSheetBase& r )
+ : WeakImplHelper()
+ , m_pPool( r.m_pPool )
+ , nFamily( r.nFamily )
+ , aName( r.aName )
+ , aParent( r.aParent )
+ , aFollow( r.aFollow )
+ , aHelpFile( r.aHelpFile )
+ , nMask( r.nMask )
+ , nHelpId( r.nHelpId )
+ , bMySet( r.bMySet )
+ , bHidden( r.bHidden )
+{
+#ifdef DBG_UTIL
+ aDbgStyleSheetReferences.mnStyles++;
+#endif
+ if( r.pSet )
+ pSet = bMySet ? new SfxItemSet( *r.pSet ) : r.pSet;
+ else
+ pSet = nullptr;
+}
+
+SfxStyleSheetBase::~SfxStyleSheetBase()
+{
+#ifdef DBG_UTIL
+ --aDbgStyleSheetReferences.mnStyles;
+#endif
+
+ if( bMySet )
+ {
+ delete pSet;
+ pSet = nullptr;
+ }
+}
+
+// Change name
+const OUString& SfxStyleSheetBase::GetName() const
+{
+ return aName;
+}
+
+bool SfxStyleSheetBase::SetName(const OUString& rName, bool bReIndexNow)
+{
+ if(rName.isEmpty())
+ return false;
+
+ if( aName != rName )
+ {
+ OUString aOldName = aName;
+ SfxStyleSheetBase *pOther = m_pPool->Find( rName, nFamily ) ;
+ if ( pOther && pOther != this )
+ return false;
+
+ if ( !aName.isEmpty() )
+ m_pPool->ChangeParent(aName, rName, nFamily, false);
+
+ if ( aFollow == aName )
+ aFollow = rName;
+ aName = rName;
+ if (bReIndexNow)
+ m_pPool->Reindex();
+
+ m_pPool->Broadcast( SfxStyleSheetModifiedHint( aOldName, *this ) );
+ }
+ return true;
+}
+
+// Change Parent
+const OUString& SfxStyleSheetBase::GetParent() const
+{
+ return aParent;
+}
+
+bool SfxStyleSheetBase::SetParent( const OUString& rName )
+{
+ if ( rName == aName )
+ return false;
+
+ if( aParent != rName )
+ {
+ SfxStyleSheetBase* pIter = m_pPool->Find(rName, nFamily);
+ if( !rName.isEmpty() && !pIter )
+ {
+ OSL_FAIL( "StyleSheet-Parent not found" );
+ return false;
+ }
+ // prevent recursive linkages
+ if( !aName.isEmpty() )
+ {
+ while(pIter)
+ {
+ if(pIter->GetName() == aName)
+ return false;
+ pIter = m_pPool->Find(pIter->GetParent(), nFamily);
+ }
+ }
+ aParent = rName;
+ }
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
+ return true;
+}
+
+void SfxStyleSheetBase::SetHidden( bool hidden )
+{
+ bHidden = hidden;
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
+}
+
+/**
+ * Change follow
+ */
+const OUString& SfxStyleSheetBase::GetFollow() const
+{
+ return aFollow;
+}
+
+bool SfxStyleSheetBase::SetFollow( const OUString& rName )
+{
+ if( aFollow != rName )
+ {
+ if( !m_pPool->Find( rName, nFamily ) )
+ {
+ SAL_WARN( "svl.items", "StyleSheet-Follow not found" );
+ return false;
+ }
+ aFollow = rName;
+ }
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
+ return true;
+}
+
+/**
+ * Set Itemset
+ * The default implementation creates a new set
+ */
+SfxItemSet& SfxStyleSheetBase::GetItemSet()
+{
+ if( !pSet )
+ {
+ pSet = new SfxItemSet( m_pPool->GetPool() );
+ bMySet = true;
+ }
+ return *pSet;
+}
+
+std::optional<SfxItemSet> SfxStyleSheetBase::GetItemSetForPreview()
+{
+ return GetItemSet();
+}
+
+/**
+ * Set help file and ID and return it
+ */
+sal_uLong SfxStyleSheetBase::GetHelpId( OUString& rFile )
+{
+ rFile = aHelpFile;
+ return nHelpId;
+}
+
+void SfxStyleSheetBase::SetHelpId( const OUString& rFile, sal_uLong nId )
+{
+ aHelpFile = rFile;
+ nHelpId = nId;
+}
+
+/**
+ * Next style possible?
+ * Default: Yes
+ */
+bool SfxStyleSheetBase::HasFollowSupport() const
+{
+ return true;
+}
+
+/**
+ * Base template possible?
+ * Default: Yes
+ */
+bool SfxStyleSheetBase::HasParentSupport() const
+{
+ return true;
+}
+
+/**
+ * Setting base template to NULL possible?
+ * Default: No
+ */
+bool SfxStyleSheetBase::HasClearParentSupport() const
+{
+ return false;
+}
+
+/**
+ * By default all stylesheets are set to used
+ */
+bool SfxStyleSheetBase::IsUsed() const
+{
+ return true;
+}
+
+/**
+ * Return set attributes
+ */
+OUString SfxStyleSheetBase::GetDescription( MapUnit eMetric )
+{
+ SfxItemIter aIter( GetItemSet() );
+ OUStringBuffer aDesc;
+
+ IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ OUString aItemPresentation;
+
+ if ( !IsInvalidItem( pItem ) &&
+ m_pPool->GetPool().GetPresentation(
+ *pItem, eMetric, aItemPresentation, aIntlWrapper ) )
+ {
+ if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() )
+ aDesc.append(" + ");
+ if ( !aItemPresentation.isEmpty() )
+ aDesc.append(aItemPresentation);
+ }
+ }
+ return aDesc.makeStringAndClear();
+}
+
+SfxStyleFamily SfxStyleSheetIterator::GetSearchFamily() const
+{
+ return nSearchFamily;
+}
+
+inline bool SfxStyleSheetIterator::IsTrivialSearch() const
+{
+ return (( nMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible) &&
+ (GetSearchFamily() == SfxStyleFamily::All);
+}
+
+namespace {
+
+struct DoesStyleMatchStyleSheetPredicate final : public svl::StyleSheetPredicate
+{
+ explicit DoesStyleMatchStyleSheetPredicate(SfxStyleSheetIterator *it)
+ : mIterator(it) {}
+
+ bool
+ Check(const SfxStyleSheetBase& styleSheet) override
+ {
+ bool bMatchFamily = ((mIterator->GetSearchFamily() == SfxStyleFamily::All) ||
+ ( styleSheet.GetFamily() == mIterator->GetSearchFamily() ));
+
+ bool bUsed = mIterator->SearchUsed() && styleSheet.IsUsed( );
+
+ bool bSearchHidden( mIterator->GetSearchMask() & SfxStyleSearchBits::Hidden );
+ bool bMatchVisibility = bSearchHidden || !styleSheet.IsHidden() || bUsed;
+ bool bOnlyHidden = mIterator->GetSearchMask( ) == SfxStyleSearchBits::Hidden && styleSheet.IsHidden( );
+
+ bool bMatches = bMatchFamily && bMatchVisibility
+ && (( styleSheet.GetMask() & ( mIterator->GetSearchMask() & ~SfxStyleSearchBits::Used )) ||
+ bUsed || bOnlyHidden ||
+ ( mIterator->GetSearchMask() & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible );
+ return bMatches;
+ }
+
+ SfxStyleSheetIterator *mIterator;
+};
+
+}
+
+SfxStyleSheetIterator::SfxStyleSheetIterator(const SfxStyleSheetBasePool *pBase,
+ SfxStyleFamily eFam, SfxStyleSearchBits n)
+ : pBasePool(pBase)
+ , pCurrentStyle(nullptr)
+ , mnCurrentPosition(0)
+{
+ nSearchFamily=eFam;
+ bSearchUsed=false;
+ if( (( n & SfxStyleSearchBits::AllVisible ) != SfxStyleSearchBits::AllVisible )
+ && ((n & SfxStyleSearchBits::Used) == SfxStyleSearchBits::Used))
+ {
+ bSearchUsed = true;
+ n &= ~SfxStyleSearchBits::Used;
+ }
+ nMask=n;
+}
+
+SfxStyleSheetIterator::~SfxStyleSheetIterator()
+{
+}
+
+sal_Int32 SfxStyleSheetIterator::Count()
+{
+ sal_Int32 n = 0;
+ if( IsTrivialSearch())
+ {
+ n = static_cast<sal_uInt16>(pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheets());
+ }
+ else if(nMask == SfxStyleSearchBits::All)
+ {
+ n = static_cast<sal_uInt16>(pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetPositionsByFamily(nSearchFamily).size());
+ }
+ else
+ {
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ n = pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheetsWithPredicate(predicate);
+ }
+ return n;
+}
+
+SfxStyleSheetBase* SfxStyleSheetIterator::operator[](sal_Int32 nIdx)
+{
+ SfxStyleSheetBase* retval = nullptr;
+ if( IsTrivialSearch())
+ {
+ retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(nIdx);
+ mnCurrentPosition = nIdx;
+ }
+ else if(nMask == SfxStyleSearchBits::All)
+ {
+ rtl::Reference< SfxStyleSheetBase > ref =
+ pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(
+ pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetPositionsByFamily(nSearchFamily).at(nIdx))
+ ;
+ retval = ref.get();
+ mnCurrentPosition = nIdx;
+ }
+ else
+ {
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ rtl::Reference< SfxStyleSheetBase > ref =
+ pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(nIdx, predicate);
+ if (ref)
+ {
+ mnCurrentPosition = pBasePool->pImpl->mxIndexedStyleSheets->FindStyleSheetPosition(*ref);
+ retval = ref.get();
+ }
+ }
+
+ if (retval == nullptr)
+ {
+ OSL_FAIL("Incorrect index");
+ }
+
+ return retval;
+}
+
+SfxStyleSheetBase* SfxStyleSheetIterator::First()
+{
+ if (Count() != 0) {
+ return operator[](0);
+ }
+ else {
+ return nullptr;
+ }
+}
+
+SfxStyleSheetBase* SfxStyleSheetIterator::Next()
+{
+ SfxStyleSheetBase* retval = nullptr;
+
+ if ( IsTrivialSearch() )
+ {
+ sal_Int32 nStyleSheets = pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheets();
+ sal_Int32 newPosition = mnCurrentPosition + 1;
+ if (nStyleSheets > newPosition)
+ {
+ mnCurrentPosition = newPosition;
+ retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(mnCurrentPosition);
+ }
+ }
+ else if(nMask == SfxStyleSearchBits::All)
+ {
+ sal_Int32 newPosition = mnCurrentPosition + 1;
+ const std::vector<sal_Int32>& familyVector
+ =
+ pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetPositionsByFamily(nSearchFamily);
+ if (static_cast<sal_Int32>(familyVector.size()) > newPosition)
+ {
+ mnCurrentPosition = newPosition;
+ sal_Int32 stylePosition = familyVector[newPosition];
+ retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(stylePosition);
+ }
+ }
+ else
+ {
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ rtl::Reference< SfxStyleSheetBase > ref =
+ pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(
+ 0, predicate, mnCurrentPosition+1);
+ retval = ref.get();
+ if (retval != nullptr) {
+ mnCurrentPosition = pBasePool->pImpl->mxIndexedStyleSheets->FindStyleSheetPosition(*ref);
+ }
+ }
+ pCurrentStyle = retval;
+ return retval;
+}
+
+SfxStyleSheetBase* SfxStyleSheetIterator::Find(const OUString& rStr)
+{
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+
+ std::vector<sal_Int32> positions =
+ pBasePool->pImpl->mxIndexedStyleSheets->FindPositionsByNameAndPredicate(rStr, predicate,
+ svl::IndexedStyleSheets::SearchBehavior::ReturnFirst);
+ if (positions.empty()) {
+ return nullptr;
+ }
+
+ sal_Int32 pos = positions.front();
+ SfxStyleSheetBase* pStyle = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(pos);
+ mnCurrentPosition = pos;
+ pCurrentStyle = pStyle;
+ return pCurrentStyle;
+}
+
+SfxStyleSearchBits SfxStyleSheetIterator::GetSearchMask() const
+{
+ SfxStyleSearchBits mask = nMask;
+
+ if ( bSearchUsed )
+ mask |= SfxStyleSearchBits::Used;
+ return mask;
+}
+
+SfxStyleSheetIterator* SfxStyleSheetBasePool::GetCachedIterator()
+{
+ return pImpl->pIter.get();
+}
+
+SfxStyleSheetIterator& SfxStyleSheetBasePool::GetIterator_Impl(SfxStyleFamily eFamily, SfxStyleSearchBits eMask)
+{
+ if (!pImpl->pIter || (pImpl->pIter->GetSearchMask() != eMask) || (pImpl->pIter->GetSearchFamily() != eFamily))
+ pImpl->pIter = CreateIterator(eFamily, eMask);
+ return *pImpl->pIter;
+}
+
+SfxStyleSheetBasePool::SfxStyleSheetBasePool( SfxItemPool& r ) :
+ pImpl(new SfxStyleSheetBasePool_Impl),
+ rPool(r)
+{
+#ifdef DBG_UTIL
+ aDbgStyleSheetReferences.mnPools++;
+#endif
+}
+
+SfxStyleSheetBasePool::SfxStyleSheetBasePool( const SfxStyleSheetBasePool& r ) :
+ SfxBroadcaster( r ),
+ WeakImplHelper(),
+ pImpl(new SfxStyleSheetBasePool_Impl),
+ rPool(r.rPool)
+{
+#ifdef DBG_UTIL
+ aDbgStyleSheetReferences.mnPools++;
+#endif
+
+ *this += r;
+}
+
+SfxStyleSheetBasePool::~SfxStyleSheetBasePool()
+{
+#ifdef DBG_UTIL
+ aDbgStyleSheetReferences.mnPools--;
+#endif
+
+ Broadcast( SfxHint(SfxHintId::Dying) );
+ Clear();
+}
+
+std::unique_ptr<SfxStyleSheetIterator> SfxStyleSheetBasePool::CreateIterator
+(
+ SfxStyleFamily eFam,
+ SfxStyleSearchBits mask
+)
+{
+ return std::make_unique<SfxStyleSheetIterator>(this,eFam,mask);
+}
+
+rtl::Reference<SfxStyleSheetBase> SfxStyleSheetBasePool::Create
+(
+ const OUString& rName,
+ SfxStyleFamily eFam,
+ SfxStyleSearchBits mask
+)
+{
+ return new SfxStyleSheetBase( rName, this, eFam, mask );
+}
+
+rtl::Reference<SfxStyleSheetBase> SfxStyleSheetBasePool::Create( const SfxStyleSheetBase& r )
+{
+ return new SfxStyleSheetBase( r );
+}
+
+SfxStyleSheetBase& SfxStyleSheetBasePool::Make( const OUString& rName, SfxStyleFamily eFam, SfxStyleSearchBits mask)
+{
+ OSL_ENSURE( eFam != SfxStyleFamily::All, "svl::SfxStyleSheetBasePool::Make(), FamilyAll is not an allowed Family" );
+
+ SfxStyleSheetIterator aIter(this, eFam, mask);
+ rtl::Reference< SfxStyleSheetBase > xStyle( aIter.Find( rName ) );
+ OSL_ENSURE( !xStyle.is(), "svl::SfxStyleSheetBasePool::Make(), StyleSheet already exists" );
+
+ if( !xStyle.is() )
+ {
+ xStyle = Create( rName, eFam, mask );
+ StoreStyleSheet(xStyle);
+ Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetCreated, *xStyle));
+ }
+ return *xStyle;
+}
+
+/**
+ * Helper function: If a template with this name exists it is created
+ * anew. All templates that have this template as a parent are reconnected.
+ */
+void SfxStyleSheetBasePool::Add( const SfxStyleSheetBase& rSheet )
+{
+ SfxStyleSheetIterator aIter(this, rSheet.GetFamily(), SfxStyleSearchBits::All);
+ SfxStyleSheetBase* pOld = aIter.Find( rSheet.GetName() );
+ if (pOld) {
+ Remove( pOld );
+ }
+ rtl::Reference< SfxStyleSheetBase > xNew( Create( rSheet ) );
+ pImpl->mxIndexedStyleSheets->AddStyleSheet(xNew);
+ Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetChanged, *xNew));
+}
+
+SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator=( const SfxStyleSheetBasePool& r )
+{
+ if( &r != this )
+ {
+ Clear();
+ *this += r;
+ }
+ return *this;
+}
+
+namespace {
+struct AddStyleSheetCallback : svl::StyleSheetCallback
+{
+ explicit AddStyleSheetCallback(SfxStyleSheetBasePool *pool)
+ : mPool(pool) {}
+
+ void DoIt(const SfxStyleSheetBase& ssheet) override
+ {
+ mPool->Add(ssheet);
+ }
+
+ SfxStyleSheetBasePool *mPool;
+};
+}
+
+SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator+=( const SfxStyleSheetBasePool& r )
+{
+ if( &r != this )
+ {
+ AddStyleSheetCallback callback(this);
+ pImpl->mxIndexedStyleSheets->ApplyToAllStyleSheets(callback);
+ }
+ return *this;
+}
+
+SfxStyleSheetBase* SfxStyleSheetBasePool::Find(const OUString& rName,
+ SfxStyleFamily eFamily,
+ SfxStyleSearchBits eMask)
+{
+ SfxStyleSheetIterator aIter(this, eFamily, eMask);
+ return aIter.Find(rName);
+}
+
+SfxStyleSheetBase* SfxStyleSheetBasePool::First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask)
+{
+ return GetIterator_Impl(eFamily, eMask).First();
+}
+
+SfxStyleSheetBase* SfxStyleSheetBasePool::Next()
+{
+ assert(pImpl->pIter && "Next called without a previous First");
+ return pImpl->pIter->Next();
+}
+
+void SfxStyleSheetBasePool::Remove( SfxStyleSheetBase* p )
+{
+ if( !p )
+ return;
+
+ // Reference to keep p alive until after Broadcast call!
+ rtl::Reference<SfxStyleSheetBase> xP(p);
+ bool bWasRemoved = pImpl->mxIndexedStyleSheets->RemoveStyleSheet(xP);
+ if( !bWasRemoved )
+ return;
+
+ // Adapt all styles which have this style as parent
+ ChangeParent(p->GetName(), p->GetParent(), p->GetFamily());
+
+ // #120015# Do not dispose, the removed StyleSheet may still be used in
+ // existing SdrUndoAttrObj incarnations. Rely on refcounting for disposal,
+ // this works well under normal conditions (checked breaking and counting
+ // on SfxStyleSheetBase constructors and destructors)
+
+ // css::uno::Reference< css::lang::XComponent > xComp( getXWeak((*aIter).get()), css::uno::UNO_QUERY );
+ // if( xComp.is() ) try
+ // {
+ // xComp->dispose();
+ // }
+ // catch( css::uno::Exception& )
+ // {
+ // }
+ Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetErased, *p ) );
+}
+
+void SfxStyleSheetBasePool::Insert( SfxStyleSheetBase* p )
+{
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE( p, "svl::SfxStyleSheetBasePool::Insert(), no stylesheet?" );
+
+ SfxStyleSheetIterator aIter(this, p->GetFamily(), p->GetMask());
+ SfxStyleSheetBase* pOld = aIter.Find( p->GetName() );
+ OSL_ENSURE( !pOld, "svl::SfxStyleSheetBasePool::Insert(), StyleSheet already inserted" );
+ if( !p->GetParent().isEmpty() )
+ {
+ pOld = aIter.Find( p->GetParent() );
+ OSL_ENSURE( pOld, "svl::SfxStyleSheetBasePool::Insert(), Parent not found!" );
+ }
+#endif
+ StoreStyleSheet(rtl::Reference< SfxStyleSheetBase >( p ) );
+ Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetCreated, *p ) );
+}
+
+namespace
+{
+
+struct StyleSheetDisposerFunctor final : public svl::StyleSheetDisposer
+{
+ explicit StyleSheetDisposerFunctor(SfxStyleSheetBasePool* pool)
+ : mPool(pool) {}
+
+ void
+ Dispose(rtl::Reference<SfxStyleSheetBase> styleSheet) override
+ {
+ cppu::OWeakObject* weakObject = styleSheet.get();
+ css::uno::Reference< css::lang::XComponent > xComp( weakObject, css::uno::UNO_QUERY );
+ if( xComp.is() ) try
+ {
+ xComp->dispose();
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+ mPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetErased, *styleSheet));
+ }
+
+ SfxStyleSheetBasePool* mPool;
+};
+
+}
+
+void SfxStyleSheetBasePool::Clear()
+{
+ StyleSheetDisposerFunctor cleanup(this);
+ pImpl->mxIndexedStyleSheets->Clear(cleanup);
+}
+
+void SfxStyleSheetBasePool::ChangeParent(std::u16string_view rOld,
+ const OUString& rNew,
+ SfxStyleFamily eFamily,
+ bool bVirtual)
+{
+ for( SfxStyleSheetBase* p = First(eFamily); p; p = Next() )
+ {
+ if( p->GetParent() == rOld )
+ {
+ if(bVirtual)
+ p->SetParent( rNew );
+ else
+ p->aParent = rNew;
+ }
+ }
+}
+
+SfxStyleSheet::SfxStyleSheet(const OUString &rName,
+ const SfxStyleSheetBasePool& r_Pool,
+ SfxStyleFamily eFam,
+ SfxStyleSearchBits mask )
+ : SfxStyleSheetBase(rName, const_cast< SfxStyleSheetBasePool* >( &r_Pool ), eFam, mask)
+{
+}
+
+SfxStyleSheet::SfxStyleSheet(const SfxStyleSheet& rStyle)
+ : SfxStyleSheetBase(rStyle)
+ , SfxListener( rStyle )
+ , SfxBroadcaster( rStyle )
+ , svl::StyleSheetUser()
+{
+}
+
+SfxStyleSheet::~SfxStyleSheet()
+{
+ Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetInDestruction, *this ) );
+}
+
+
+bool SfxStyleSheet::SetParent( const OUString& rName )
+{
+ if(aParent == rName)
+ return true;
+ const OUString aOldParent(aParent);
+ if(SfxStyleSheetBase::SetParent(rName))
+ {
+ // Remove from notification chain of the old parent if applicable
+ if(!aOldParent.isEmpty())
+ {
+ SfxStyleSheet *pParent = static_cast<SfxStyleSheet *>(m_pPool->Find(aOldParent, nFamily));
+ if(pParent)
+ EndListening(*pParent);
+ }
+ // Add to the notification chain of the new parent
+ if(!aParent.isEmpty())
+ {
+ SfxStyleSheet *pParent = static_cast<SfxStyleSheet *>(m_pPool->Find(aParent, nFamily));
+ if(pParent)
+ StartListening(*pParent);
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Notify all listeners
+ */
+void SfxStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ Forward(rBC, rHint);
+}
+
+bool SfxStyleSheet::isUsedByModel() const
+{
+ return IsUsed();
+}
+
+
+SfxStyleSheetPool::SfxStyleSheetPool( SfxItemPool const& rSet)
+: SfxStyleSheetBasePool( const_cast< SfxItemPool& >( rSet ) )
+{
+}
+
+rtl::Reference<SfxStyleSheetBase> SfxStyleSheetPool::Create( const OUString& rName,
+ SfxStyleFamily eFam, SfxStyleSearchBits mask )
+{
+ return new SfxStyleSheet( rName, *this, eFam, mask );
+}
+
+SfxUnoStyleSheet::SfxUnoStyleSheet( const OUString& _rName, const SfxStyleSheetBasePool& _rPool, SfxStyleFamily _eFamily, SfxStyleSearchBits _nMask )
+: cppu::ImplInheritanceHelper<SfxStyleSheet, css::style::XStyle>(_rName, _rPool, _eFamily, _nMask)
+{
+}
+
+SfxUnoStyleSheet* SfxUnoStyleSheet::getUnoStyleSheet( const css::uno::Reference< css::style::XStyle >& xStyle )
+{
+ return dynamic_cast<SfxUnoStyleSheet*>(xStyle.get());
+}
+
+void
+SfxStyleSheetBasePool::StoreStyleSheet(const rtl::Reference< SfxStyleSheetBase >& xStyle)
+{
+ pImpl->mxIndexedStyleSheets->AddStyleSheet(xStyle);
+}
+
+void
+SfxStyleSheetBasePool::Reindex()
+{
+ pImpl->mxIndexedStyleSheets->Reindex();
+}
+
+const svl::IndexedStyleSheets&
+SfxStyleSheetBasePool::GetIndexedStyleSheets() const
+{
+ return *pImpl->mxIndexedStyleSheets;
+}
+
+SfxStyleSheetBase*
+SfxStyleSheetBasePool::GetStyleSheetByPositionInIndex(unsigned pos)
+{
+ return pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(pos);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/stylepool.cxx b/svl/source/items/stylepool.cxx
new file mode 100644
index 0000000000..9de8d87d13
--- /dev/null
+++ b/svl/source/items/stylepool.cxx
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/stylepool.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/itempool.hxx>
+#include <tools/debug.hxx>
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <optional>
+#include <vector>
+
+namespace {
+ /** A "Node" represents a subset of inserted SfxItemSets
+ * The root node represents the empty set
+ * The other nodes contain a SfxPoolItem and represents an item set which contains their
+ * pool item and the pool items of their parents.
+ */
+ class Node
+ {
+ std::vector<std::unique_ptr<Node>> mChildren; // child nodes, create by findChildNode(..)
+ // container of shared pointers of inserted item sets; for non-poolable
+ // items more than one item set is needed
+ std::vector< std::shared_ptr<SfxItemSet> > maItemSet;
+ std::unique_ptr<const SfxPoolItem> mpItem; // my pool item
+ Node *mpUpper; // if I'm a child node that's my parent node
+ // #i86923#
+ const bool mbIsItemIgnorable;
+ public:
+ // #i86923#
+ Node() // root node Ctor
+ : mpUpper( nullptr ),
+ mbIsItemIgnorable( false )
+ {}
+ Node( const SfxPoolItem& rItem, Node* pParent, const bool bIgnorable ) // child node Ctor
+ : mpItem( rItem.Clone() ),
+ mpUpper( pParent ),
+ mbIsItemIgnorable( bIgnorable )
+ {}
+ // #i86923#
+ bool hasItemSet( const bool bCheckUsage ) const;
+ // #i87808#
+ std::shared_ptr<SfxItemSet> const & getItemSet() const
+ {
+ return maItemSet.back();
+ }
+ std::shared_ptr<SfxItemSet> const & getUsedOrLastAddedItemSet() const;
+ void setItemSet( const SfxItemSet& rSet ){ maItemSet.push_back( std::shared_ptr<SfxItemSet>( rSet.Clone() ) ); }
+ // #i86923#
+ Node* findChildNode( const SfxPoolItem& rItem,
+ const bool bIsItemIgnorable );
+ Node* nextItemSet( Node const * pLast,
+ const bool bSkipUnusedItemSet,
+ const bool bSkipIgnorable );
+ // #i86923#
+ bool hasIgnorableChildren( const bool bCheckUsage ) const;
+ std::shared_ptr<SfxItemSet> getItemSetOfIgnorableChild(
+ const bool bSkipUnusedItemSets ) const;
+ };
+
+ // #i87808#
+ std::shared_ptr<SfxItemSet> const & Node::getUsedOrLastAddedItemSet() const
+ {
+ auto aIter = std::find_if(maItemSet.rbegin(), maItemSet.rend(),
+ [](const std::shared_ptr<SfxItemSet>& rxItemSet) { return rxItemSet.use_count() > 1; });
+
+ if (aIter != maItemSet.rend())
+ return *aIter;
+
+ return maItemSet.back();
+ }
+
+ // #i86923#
+ bool Node::hasItemSet( const bool bCheckUsage ) const
+ {
+ bool bHasItemSet = false;
+
+ if ( !maItemSet.empty())
+ {
+ if ( bCheckUsage )
+ {
+ bHasItemSet = std::any_of(maItemSet.rbegin(), maItemSet.rend(),
+ [](const std::shared_ptr<SfxItemSet>& rxItemSet) { return rxItemSet.use_count() > 1; });
+ }
+ else
+ {
+ bHasItemSet = true;
+ }
+ }
+ return bHasItemSet;
+ }
+
+ // #i86923#
+ Node* Node::findChildNode( const SfxPoolItem& rItem,
+ const bool bIsItemIgnorable )
+ {
+ for( auto const & rChild : mChildren )
+ {
+ if( rItem.Which() == rChild->mpItem->Which() &&
+ rItem == *rChild->mpItem )
+ return rChild.get();
+ }
+ // #i86923#
+ auto pNextNode = new Node( rItem, this, bIsItemIgnorable );
+ mChildren.emplace_back( pNextNode );
+ return pNextNode;
+ }
+
+ /**
+ * Find the next node which has a SfxItemSet.
+ * The input parameter pLast has a sophisticated meaning:
+ * downstairs only:
+ * pLast == 0 => scan your children and their children
+ * but neither your parents neither your siblings
+ * downstairs and upstairs:
+ * pLast == this => scan your children, their children,
+ * the children of your parent behind you, and so on
+ * partial downstairs and upstairs
+ * pLast != 0 && pLast != this => scan your children behind the given children,
+ * the children of your parent behind you and so on.
+ *
+ * OD 2008-03-11 #i86923#
+ * introduce parameters <bSkipUnusedItemSets> and <bSkipIgnorable>
+ * and its handling.
+ */
+ Node* Node::nextItemSet( Node const * pLast,
+ const bool bSkipUnusedItemSets,
+ const bool bSkipIgnorable )
+ {
+ // Searching downstairs
+ auto aIter = mChildren.begin();
+ // For pLast == 0 and pLast == this all children are of interest
+ // for another pLast the search starts behind pLast...
+ if( pLast && pLast != this )
+ {
+ aIter = std::find_if( mChildren.begin(), mChildren.end(),
+ [&] (std::unique_ptr<Node> const &p) { return p.get() == pLast; });
+ if( aIter != mChildren.end() )
+ ++aIter;
+ }
+ Node *pNext = nullptr;
+ while( aIter != mChildren.end() )
+ {
+ // #i86923#
+ if ( bSkipIgnorable && (*aIter)->mbIsItemIgnorable )
+ {
+ ++aIter;
+ continue;
+ }
+ pNext = aIter->get();
+ // #i86923#
+ if ( pNext->hasItemSet( bSkipUnusedItemSets ) )
+ {
+ return pNext;
+ }
+ if ( bSkipIgnorable &&
+ pNext->hasIgnorableChildren( bSkipUnusedItemSets ) )
+ {
+ return pNext;
+ }
+ pNext = pNext->nextItemSet( nullptr, bSkipUnusedItemSets, bSkipIgnorable ); // 0 => downstairs only
+ if( pNext )
+ return pNext;
+ ++aIter;
+ }
+ // Searching upstairs
+ if( pLast && mpUpper )
+ {
+ // #i86923#
+ pNext = mpUpper->nextItemSet( this, bSkipUnusedItemSets, bSkipIgnorable );
+ }
+ return pNext;
+ }
+
+ // #i86923#
+ bool Node::hasIgnorableChildren( const bool bCheckUsage ) const
+ {
+ return std::any_of(mChildren.begin(), mChildren.end(),
+ [&bCheckUsage](const std::unique_ptr<Node>& rxChild) {
+ Node* pChild = rxChild.get();
+ return pChild->mbIsItemIgnorable &&
+ (!bCheckUsage ||
+ ( pChild->hasItemSet( bCheckUsage /* == true */ ) ||
+ pChild->hasIgnorableChildren( bCheckUsage /* == true */ ) ));
+ });
+ }
+
+ std::shared_ptr<SfxItemSet> Node::getItemSetOfIgnorableChild(
+ const bool bSkipUnusedItemSets ) const
+ {
+ DBG_ASSERT( hasIgnorableChildren( bSkipUnusedItemSets ),
+ "<Node::getItemSetOfIgnorableChild> - node has no ignorable children" );
+
+ for( const auto& rxChild : mChildren )
+ {
+ Node* pChild = rxChild.get();
+ if ( pChild->mbIsItemIgnorable )
+ {
+ if ( pChild->hasItemSet( bSkipUnusedItemSets ) )
+ {
+ return pChild->getUsedOrLastAddedItemSet();
+ }
+ else
+ {
+ pChild = pChild->nextItemSet( nullptr, bSkipUnusedItemSets, false );
+ if ( pChild )
+ {
+ return pChild->getUsedOrLastAddedItemSet();
+ }
+ }
+ }
+ }
+
+ std::shared_ptr<SfxItemSet> pReturn;
+ return pReturn;
+ }
+
+ class Iterator : public IStylePoolIteratorAccess
+ {
+ std::map< const SfxItemSet*, Node >& mrRoot;
+ std::map< const SfxItemSet*, Node >::iterator mpCurrNode;
+ Node* mpNode;
+ const bool mbSkipUnusedItemSets;
+ const bool mbSkipIgnorable;
+ /// List of item set parents, ordered by their name.
+ std::vector<const SfxItemSet*> maParents;
+ /// The iterator's current position.
+ std::vector<const SfxItemSet*>::iterator mpCurrParent;
+ public:
+ // #i86923#
+ Iterator( std::map< const SfxItemSet*, Node >& rR,
+ const bool bSkipUnusedItemSets,
+ const bool bSkipIgnorable,
+ const std::map< const SfxItemSet*, OUString>& rParentNames )
+ : mrRoot( rR ),
+ mpNode(nullptr),
+ mbSkipUnusedItemSets( bSkipUnusedItemSets ),
+ mbSkipIgnorable( bSkipIgnorable )
+ {
+ // Collect the parent pointers into a vector we can sort.
+ for (const auto& rParent : mrRoot)
+ maParents.push_back(rParent.first);
+
+ // Sort the parents using their name, if they have one.
+ if (!rParentNames.empty())
+ {
+ std::stable_sort(maParents.begin(), maParents.end(),
+ [&rParentNames](const SfxItemSet* pA, const SfxItemSet* pB) {
+ OUString aA;
+ OUString aB;
+ auto it = rParentNames.find(pA);
+ if (it != rParentNames.end())
+ aA = it->second;
+ it = rParentNames.find(pB);
+ if (it != rParentNames.end())
+ aB = it->second;
+ return aA < aB;
+ });
+ }
+
+ // Start the iteration.
+ mpCurrParent = maParents.begin();
+ if (mpCurrParent != maParents.end())
+ mpCurrNode = mrRoot.find(*mpCurrParent);
+ }
+ virtual std::shared_ptr<SfxItemSet> getNext() override;
+ };
+
+ std::shared_ptr<SfxItemSet> Iterator::getNext()
+ {
+ std::shared_ptr<SfxItemSet> pReturn;
+ while( mpNode || mpCurrParent != maParents.end() )
+ {
+ if( !mpNode )
+ {
+ mpNode = &mpCurrNode->second;
+ // Perform the actual increment.
+ ++mpCurrParent;
+ if (mpCurrParent != maParents.end())
+ mpCurrNode = mrRoot.find(*mpCurrParent);
+ // #i86923#
+ if ( mpNode->hasItemSet( mbSkipUnusedItemSets ) )
+ {
+ // #i87808#
+ return mpNode->getUsedOrLastAddedItemSet();
+ }
+ }
+ // #i86923#
+ mpNode = mpNode->nextItemSet( mpNode, mbSkipUnusedItemSets, mbSkipIgnorable );
+ if ( mpNode && mpNode->hasItemSet( mbSkipUnusedItemSets ) )
+ {
+ // #i87808#
+ return mpNode->getUsedOrLastAddedItemSet();
+ }
+ if ( mbSkipIgnorable &&
+ mpNode && mpNode->hasIgnorableChildren( mbSkipUnusedItemSets ) )
+ {
+ return mpNode->getItemSetOfIgnorableChild( mbSkipUnusedItemSets );
+ }
+ }
+ return pReturn;
+ }
+
+}
+
+/**
+ * This static method creates a unique name from a shared pointer to a SfxItemSet
+ * The name is the memory address of the SfxItemSet itself.
+ */
+OUString StylePool::nameOf( const std::shared_ptr<SfxItemSet>& pSet )
+{
+ return OUString::number( reinterpret_cast<sal_IntPtr>( pSet.get() ), 16 );
+}
+
+/**
+ * class StylePoolImpl organized a tree-structure where every node represents a SfxItemSet.
+ * The insertItemSet method adds a SfxItemSet into the tree if necessary and returns a shared_ptr
+ * to a copy of the SfxItemSet.
+ * The aRoot-Node represents an empty SfxItemSet.
+ */
+class StylePoolImpl
+{
+private:
+ std::map< const SfxItemSet*, Node > maRoot;
+ /// Names of maRoot keys.
+ std::map< const SfxItemSet*, OUString> maParentNames;
+ // #i86923#
+ std::unique_ptr<SfxItemSet> mpIgnorableItems;
+#ifdef DEBUG
+ sal_Int32 mnCount;
+#endif
+public:
+ // #i86923#
+ explicit StylePoolImpl( SfxItemSet const * pIgnorableItems )
+ :
+#ifdef DEBUG
+ mnCount(0),
+#endif
+ mpIgnorableItems( pIgnorableItems != nullptr
+ ? pIgnorableItems->Clone( false )
+ : nullptr )
+ {
+ DBG_ASSERT( !pIgnorableItems || !pIgnorableItems->Count(),
+ "<StylePoolImpl::StylePoolImpl(..)> - misusage: item set for ignorable item should be empty. Please correct usage." );
+ DBG_ASSERT( !mpIgnorableItems || !mpIgnorableItems->Count(),
+ "<StylePoolImpl::StylePoolImpl(..)> - <SfxItemSet::Clone( sal_False )> does not work as expected - <mpIgnorableItems> is not empty." );
+ }
+
+ std::shared_ptr<SfxItemSet> insertItemSet( const SfxItemSet& rSet, const OUString* pParentName = nullptr );
+
+ // #i86923#
+ std::unique_ptr<IStylePoolIteratorAccess> createIterator( bool bSkipUnusedItemSets,
+ bool bSkipIgnorableItems );
+};
+
+
+std::shared_ptr<SfxItemSet> StylePoolImpl::insertItemSet( const SfxItemSet& rSet, const OUString* pParentName )
+{
+ bool bNonShareable(false);
+ Node* pCurNode = &maRoot[ rSet.GetParent() ];
+ if (pParentName)
+ maParentNames[ rSet.GetParent() ] = *pParentName;
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ // Every SfxPoolItem in the SfxItemSet causes a step deeper into the tree,
+ // a complete empty SfxItemSet would stay at the root node.
+ // #i86923# insert ignorable items to the tree leaves.
+ std::optional<SfxItemSet> xFoundIgnorableItems;
+ if ( mpIgnorableItems )
+ {
+ xFoundIgnorableItems.emplace( *mpIgnorableItems );
+ }
+ while( pItem )
+ {
+ if (!rSet.GetPool()->Shareable(pItem->Which()))
+ bNonShareable = true;
+ if (!xFoundIgnorableItems || (xFoundIgnorableItems->Put(*pItem) == nullptr))
+ {
+ pCurNode = pCurNode->findChildNode( *pItem, false );
+ }
+ pItem = aIter.NextItem();
+ }
+ if ( xFoundIgnorableItems && xFoundIgnorableItems->Count() > 0 )
+ {
+ SfxItemIter aIgnorableItemsIter( *xFoundIgnorableItems );
+ pItem = aIgnorableItemsIter.GetCurItem();
+ while( pItem )
+ {
+ if (!rSet.GetPool()->Shareable(pItem->Which()))
+ bNonShareable = true;
+ pCurNode = pCurNode->findChildNode( *pItem, true );
+ pItem = aIgnorableItemsIter.NextItem();
+ }
+ }
+ // Every leaf node represents an inserted item set, but "non-leaf" nodes represents subsets
+ // of inserted itemsets.
+ // These nodes could have but does not need to have a shared_ptr to an item set.
+ if( !pCurNode->hasItemSet( false ) )
+ {
+ pCurNode->setItemSet( rSet );
+ bNonShareable = false; // to avoid a double insertion
+#ifdef DEBUG
+ ++mnCount;
+#endif
+ }
+ // If rSet contains at least one non poolable item, a new itemset has to be inserted
+ if( bNonShareable )
+ pCurNode->setItemSet( rSet );
+#ifdef DEBUG
+ {
+ sal_Int32 nCheck = -1;
+ std::unique_ptr<IStylePoolIteratorAccess> pIter = createIterator(false,false);
+ std::shared_ptr<SfxItemSet> pTemp;
+ do
+ {
+ ++nCheck;
+ pTemp = pIter->getNext();
+ } while( pTemp.get() );
+ DBG_ASSERT( mnCount == nCheck, "Wrong counting");
+ }
+#endif
+ return pCurNode->getItemSet();
+}
+
+// #i86923#
+std::unique_ptr<IStylePoolIteratorAccess> StylePoolImpl::createIterator( bool bSkipUnusedItemSets,
+ bool bSkipIgnorableItems )
+{
+ return std::make_unique<Iterator>( maRoot, bSkipUnusedItemSets, bSkipIgnorableItems, maParentNames );
+}
+// Ctor, Dtor and redirected methods of class StylePool, nearly inline ;-)
+
+// #i86923#
+StylePool::StylePool( SfxItemSet const * pIgnorableItems )
+ : pImpl( new StylePoolImpl( pIgnorableItems ) )
+{}
+
+std::shared_ptr<SfxItemSet> StylePool::insertItemSet( const SfxItemSet& rSet, const OUString* pParentName )
+{ return pImpl->insertItemSet( rSet, pParentName ); }
+
+// #i86923#
+std::unique_ptr<IStylePoolIteratorAccess> StylePool::createIterator( const bool bSkipUnusedItemSets,
+ const bool bSkipIgnorableItems )
+{
+ return pImpl->createIterator( bSkipUnusedItemSets, bSkipIgnorableItems );
+}
+
+StylePool::~StylePool()
+{}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/visitem.cxx b/svl/source/items/visitem.cxx
new file mode 100644
index 0000000000..c1788c32d1
--- /dev/null
+++ b/svl/source/items/visitem.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <svl/visitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <osl/diagnose.h>
+
+
+// virtual
+bool SfxVisibilityItem::operator ==(const SfxPoolItem & rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ return m_nValue.bVisible == static_cast< const SfxVisibilityItem * >(&rItem)->
+ m_nValue.bVisible;
+}
+
+// virtual
+bool SfxVisibilityItem::GetPresentation(SfxItemPresentation,
+ MapUnit, MapUnit,
+ OUString & rText,
+ const IntlWrapper&) const
+{
+ rText = m_nValue.bVisible ? std::u16string_view(u"TRUE") : std::u16string_view(u"FALSE");
+ return true;
+}
+
+
+// virtual
+bool SfxVisibilityItem::QueryValue(css::uno::Any& rVal, sal_uInt8) const
+{
+ rVal <<= m_nValue;
+ return true;
+}
+
+// virtual
+bool SfxVisibilityItem::PutValue(const css::uno::Any& rVal, sal_uInt8)
+{
+ if (rVal >>= m_nValue)
+ return true;
+
+ OSL_FAIL( "SfxInt16Item::PutValue - Wrong type!" );
+ return false;
+}
+
+// virtual
+SfxVisibilityItem* SfxVisibilityItem::Clone(SfxItemPool *) const
+{
+ return new SfxVisibilityItem(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/voiditem.cxx b/svl/source/items/voiditem.cxx
new file mode 100644
index 0000000000..32057e1e2c
--- /dev/null
+++ b/svl/source/items/voiditem.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/voiditem.hxx>
+#include <libxml/xmlwriter.h>
+
+SfxPoolItem* SfxVoidItem::CreateDefault() { return new SfxVoidItem(0); }
+
+SfxVoidItem::SfxVoidItem(sal_uInt16 which)
+ : SfxPoolItem(which)
+{
+ setIsVoidItem();
+}
+
+SfxVoidItem::SfxVoidItem(const SfxVoidItem& rCopy)
+ : SfxPoolItem(rCopy.Which())
+{
+ setIsVoidItem();
+}
+
+SfxVoidItem::SfxVoidItem(SfxVoidItem&& rOrig)
+ : SfxPoolItem(rOrig)
+{
+ setIsVoidItem();
+}
+
+bool SfxVoidItem::operator==(const SfxPoolItem& rCmp) const
+{
+ assert(SfxPoolItem::operator==(rCmp));
+ (void)rCmp;
+ return true;
+}
+
+bool SfxVoidItem::GetPresentation(SfxItemPresentation /*ePresentation*/, MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresentationMetric*/, OUString& rText,
+ const IntlWrapper&) const
+{
+ rText = "Void";
+ return true;
+}
+
+void SfxVoidItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxVoidItem"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"),
+ BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+SfxVoidItem* SfxVoidItem::Clone(SfxItemPool*) const { return new SfxVoidItem(*this); }
+
+SfxVoidItem::~SfxVoidItem() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/whiter.cxx b/svl/source/items/whiter.cxx
new file mode 100644
index 0000000000..13915415df
--- /dev/null
+++ b/svl/source/items/whiter.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/itemset.hxx>
+#include <svl/whiter.hxx>
+
+SfxWhichIter::SfxWhichIter(const SfxItemSet& rSet)
+ : m_rItemSet(rSet)
+ , m_pCurrentWhichPair(rSet.m_pWhichRanges.begin())
+ , m_nOffsetFromStartOfCurrentWhichPair(0)
+ , m_nItemsOffset(0)
+{
+}
+
+sal_uInt16 SfxWhichIter::GetCurWhich() const
+{
+ const WhichRangesContainer& rWhichRanges = m_rItemSet.m_pWhichRanges;
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
+ return 0;
+ return m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
+}
+
+sal_uInt16 SfxWhichIter::NextWhich()
+{
+ const WhichRangesContainer& rWhichRanges = m_rItemSet.m_pWhichRanges;
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
+ return 0;
+
+ const sal_uInt16 nLastWhich = m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
+ ++m_nOffsetFromStartOfCurrentWhichPair;
+ if (m_pCurrentWhichPair->second == nLastWhich)
+ {
+ m_nItemsOffset += m_pCurrentWhichPair->second - m_pCurrentWhichPair->first + 1;
+ ++m_pCurrentWhichPair;
+ m_nOffsetFromStartOfCurrentWhichPair = 0;
+ }
+ if (m_pCurrentWhichPair >= (rWhichRanges.begin() + rWhichRanges.size()))
+ return 0;
+ return m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair;
+}
+
+sal_uInt16 SfxWhichIter::FirstWhich()
+{
+ m_pCurrentWhichPair = m_rItemSet.m_pWhichRanges.begin();
+ m_nOffsetFromStartOfCurrentWhichPair = 0;
+ m_nItemsOffset = 0;
+ return m_pCurrentWhichPair->first;
+}
+
+SfxItemState SfxWhichIter::GetItemState(bool bSrchInParent, const SfxPoolItem** ppItem) const
+{
+ const sal_uInt16 nOffset(m_nItemsOffset + m_nOffsetFromStartOfCurrentWhichPair);
+
+ // we have the offset, so use it to profit. It is always valid, so no need
+ // to check if smaller than TotalCount()
+ SfxItemState eState(m_rItemSet.GetItemState_ForOffset(nOffset, ppItem));
+
+ // search in parent?
+ if (bSrchInParent && nullptr != m_rItemSet.GetParent() && (SfxItemState::UNKNOWN == eState || SfxItemState::DEFAULT == eState))
+ {
+ // nOffset was only valid for *local* SfxItemSet, need to continue with WhichID
+ // Use the *highest* SfxItemState as result
+ const sal_uInt16 nWhich(m_pCurrentWhichPair->first + m_nOffsetFromStartOfCurrentWhichPair);
+ return m_rItemSet.GetParent()->GetItemState_ForWhichID( eState, nWhich, true, ppItem);
+ }
+
+ return eState;
+}
+
+void SfxWhichIter::ClearItem()
+{
+ // we have the offset, so use it to profit. It is always valid, so no need
+ // to check if smaller than TotalCount()
+ const_cast<SfxItemSet&>(m_rItemSet).ClearSingleItem_ForOffset(m_nItemsOffset + m_nOffsetFromStartOfCurrentWhichPair);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */