diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /svl/source/items | |
parent | Initial commit. (diff) | |
download | libreoffice-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')
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: */ |