diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /svl/source/items | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
34 files changed, 8681 insertions, 0 deletions
diff --git a/svl/source/items/IndexedStyleSheets.cxx b/svl/source/items/IndexedStyleSheets.cxx new file mode 100644 index 000000000..4d71e7e6f --- /dev/null +++ b/svl/source/items/IndexedStyleSheets.cxx @@ -0,0 +1,249 @@ +/* -*- 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, unsigned 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(); + } + + unsigned i = 0; + for (const auto& rxStyleSheet : mStyleSheets) { + SfxStyleSheetBase* p = rxStyleSheet.get(); + Register(*p, i); + ++i; + } +} + +unsigned +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) + { + unsigned pos = it->second; + if (mStyleSheets.at(pos) == style) + { + mStyleSheets.erase(mStyleSheets.begin() + pos); + Reindex(); + return true; + } + } + return false; +} + +std::vector<unsigned> +IndexedStyleSheets::FindPositionsByName(const OUString& name) const +{ + std::vector<unsigned> 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<unsigned> +IndexedStyleSheets::FindPositionsByNameAndPredicate(const OUString& name, + StyleSheetPredicate& predicate, SearchBehavior behavior) const +{ + std::vector<unsigned> r; + auto range = mPositionsByName.equal_range(name); + for (auto it = range.first; it != range.second; ++it) { + unsigned pos = it->second; + SfxStyleSheetBase *ssheet = mStyleSheets.at(pos).get(); + if (predicate.Check(*ssheet)) { + r.push_back(pos); + if (behavior == SearchBehavior::ReturnFirst) { + break; + } + } + } + return r; +} + + +unsigned +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( + unsigned n, + StyleSheetPredicate& predicate, + unsigned startAt) +{ + SfxStyleSheetBase* retval = nullptr; + unsigned 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; +} + +unsigned +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(unsigned pos) +{ + if( pos < 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<unsigned> +IndexedStyleSheets::FindPositionsByPredicate(StyleSheetPredicate& predicate) const +{ + std::vector<unsigned> 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<unsigned>& +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/aeitem.cxx b/svl/source/items/aeitem.cxx new file mode 100644 index 000000000..7c85153b6 --- /dev/null +++ b/svl/source/items/aeitem.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 <rtl/ustring.hxx> +#include <svl/aeitem.hxx> + +#include <climits> +#include <cstddef> + +SfxAllEnumItem::SfxAllEnumItem(sal_uInt16 which): + SfxPoolItem(which) +{ +} + +SfxAllEnumItem::SfxAllEnumItem(const SfxAllEnumItem &rCopy): + SfxPoolItem(rCopy), + m_Values(rCopy.m_Values) +{ +} + +SfxAllEnumItem::~SfxAllEnumItem() +{ +} + +sal_Int32 SfxAllEnumItem::GetTextCount() const +{ + return m_Values.size(); +} + +OUString const & SfxAllEnumItem::GetTextByPos( sal_uInt16 nPos ) const +{ + return m_Values[nPos]; +} + +SfxAllEnumItem* SfxAllEnumItem::Clone( SfxItemPool * ) const +{ + return new SfxAllEnumItem(*this); +} + +void SfxAllEnumItem::SetTextByPos( sal_uInt16 nPos, const OUString &rText ) +{ + if (nPos >= m_Values.size()) + m_Values.resize(nPos); + m_Values[nPos] = rText; +} + +bool SfxAllEnumItem::operator==( const SfxPoolItem& rCmp ) const +{ + if (!SfxPoolItem::operator==(rCmp)) + return false; + const SfxAllEnumItem& rOther = static_cast<const SfxAllEnumItem&>(rCmp); + return m_Values == rOther.m_Values; +} + + +/* 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 000000000..3d0b7e581 --- /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(dynamic_cast<const SfxBoolItem*>(&rItem) != nullptr); + 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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxBoolItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(GetValueTextByVal(m_bValue).toUtf8().getStr())); + 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 000000000..0f522f7a9 --- /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(dynamic_cast<const CntByteItem*>(&rItem) != nullptr); + 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(dynamic_cast<const CntUInt16Item*>(&rItem) != nullptr); + 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(dynamic_cast<const CntInt32Item*>(&rItem) != nullptr); + 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(dynamic_cast<const CntUInt32Item*>(&rItem) != nullptr); + 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 000000000..b6946a4f4 --- /dev/null +++ b/svl/source/items/custritm.cxx @@ -0,0 +1,80 @@ +/* -*- 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(dynamic_cast<const CntUnencodedStringItem*>( &rItem )); + return m_aValue + == static_cast< const CntUnencodedStringItem * >(&rItem)-> + m_aValue; +} + +bool CntUnencodedStringItem::operator<(const SfxPoolItem & rItem) const +{ + assert(dynamic_cast<const CntUnencodedStringItem*>( &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 000000000..fd96c5317 --- /dev/null +++ b/svl/source/items/flagitem.cxx @@ -0,0 +1,64 @@ +/* -*- 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/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) ? OUStringLiteral("true") : OUStringLiteral("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 000000000..3f8d3265d --- /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 000000000..39ee56686 --- /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 000000000..d9ddeae21 --- /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, const ::std::vector < sal_Int32 >& rList ) + : SfxPoolItem( which ) + , m_aList( 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 000000000..4959914b1 --- /dev/null +++ b/svl/source/items/imageitm.cxx @@ -0,0 +1,117 @@ +/* -*- 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; } + +struct SfxImageItem_Impl +{ + OUString aURL; + long nAngle; + bool bMirrored; + bool operator == ( const SfxImageItem_Impl& rOther ) const + { return nAngle == rOther.nAngle && bMirrored == rOther.bMirrored; } +}; + + +SfxImageItem::SfxImageItem( sal_uInt16 which ) + : SfxInt16Item( which, 0 ), + pImpl( new SfxImageItem_Impl) +{ + pImpl->nAngle = 0; + pImpl->bMirrored = false; +} + +SfxImageItem::SfxImageItem( const SfxImageItem& rItem ) + : SfxInt16Item( rItem ), + pImpl( new SfxImageItem_Impl( *rItem.pImpl ) ) +{ +} + +SfxImageItem::~SfxImageItem() +{ +} + +SfxImageItem* SfxImageItem::Clone( SfxItemPool* ) const +{ + return new SfxImageItem( *this ); +} + +bool SfxImageItem::operator==( const SfxPoolItem& rItem ) const +{ + return SfxInt16Item::operator==(rItem) && + *pImpl == *static_cast<const SfxImageItem&>(rItem).pImpl; +} + +bool SfxImageItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const +{ + css::uno::Sequence< css::uno::Any > aSeq( 4 ); + aSeq[0] <<= GetValue(); + aSeq[1] <<= pImpl->nAngle; + aSeq[2] <<= pImpl->bMirrored; + aSeq[3] <<= pImpl->aURL; + + 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(); + OUString aURL; + if ( aSeq[0] >>= nVal ) + SetValue( nVal ); + aSeq[1] >>= pImpl->nAngle; + aSeq[2] >>= pImpl->bMirrored; + if ( aSeq[3] >>= aURL ) + pImpl->aURL = aURL; + return true; + } + + return false; +} + +void SfxImageItem::SetRotation( long nValue ) +{ + pImpl->nAngle = nValue; +} + +long SfxImageItem::GetRotation() const +{ + return pImpl->nAngle; +} + +void SfxImageItem::SetMirrored( bool bSet ) +{ + pImpl->bMirrored = bSet; +} + +bool SfxImageItem::IsMirrored() const +{ + return pImpl->bMirrored; +} + +/* 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 000000000..06efd1fc9 --- /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 000000000..c0c4831a5 --- /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/json_parser.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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxUInt16Item")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr())); + 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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxInt32Item")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr())); + 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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxUInt32Item")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr())); + 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_uInt32 nValue): + SfxInt32Item(which, nValue) +{ +} + +// virtual +void SfxMetricItem::ScaleMetrics(long nMult, 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 000000000..fe0ee377f --- /dev/null +++ b/svl/source/items/itemiter.cxx @@ -0,0 +1,63 @@ +/* -*- 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_pItems.get(); + + // 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; +} + +SfxItemIter::~SfxItemIter() +{ +} + +// Precondition : m_nCurrent < m_nEnd +const SfxPoolItem* SfxItemIter::ImplNextItem() +{ + SfxPoolItem const** ppFnd = m_rSet.m_pItems.get(); + do { + m_nCurrent++; + } while (m_nCurrent < m_nEnd && !*(ppFnd + m_nCurrent )); + return *(ppFnd+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 000000000..82668c909 --- /dev/null +++ b/svl/source/items/itempool.cxx @@ -0,0 +1,947 @@ +/* -*- 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 <string.h> +#include <libxml/xmlwriter.h> + +#include <tools/solar.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 <algorithm> +#include <cassert> +#include <vector> + + +#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) \ + { \ + lcl_CheckSlots2(slotmap, *p, p->pItemInfos); \ + } \ +} while (false) + +#else +#define CHECK_SLOTS() do {} while (false) +#endif + + +void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser) +{ + // maintain sorted to reduce cost of remove + const auto insertIt = ::std::lower_bound( + pImpl->maSfxItemPoolUsers.begin(), pImpl->maSfxItemPoolUsers.end(), &rNewUser); + pImpl->maSfxItemPoolUsers.insert(insertIt, &rNewUser); +} + +void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser) +{ + const auto aFindResult = ::std::lower_bound( + pImpl->maSfxItemPoolUsers.begin(), pImpl->maSfxItemPoolUsers.end(), &rOldUser); + if(aFindResult != pImpl->maSfxItemPoolUsers.end() && *aFindResult == &rOldUser) + { + pImpl->maSfxItemPoolUsers.erase(aFindResult); + } +} + +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::IsItemPoolable_Impl( sal_uInt16 nPos ) const +{ + return pItemInfos[nPos]._bPoolable; +} + + +bool SfxItemPool::IsItemPoolable( sal_uInt16 nWhich ) const +{ + for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pImpl->mpSecondary ) + { + if ( pPool->IsInRange(nWhich) ) + return pPool->IsItemPoolable_Impl( pPool->GetIndex_Impl(nWhich)); + } + DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" ); + return false; +} + + +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*>*,sal_uInt16,sal_Bool) + * @see SfxItemPool::ReldaseDefaults(sal_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 ) ) +{ + pImpl->eDefMetric = MapUnit::MapTwip; + + if ( pDefaults ) + SetDefaults(pDefaults); +} + + +/** + * 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 */ +) : + pItemInfos(rPool.pItemInfos), + pImpl( new SfxItemPool_Impl( this, rPool.pImpl->aName, rPool.pImpl->mnStart, rPool.pImpl->mnEnd ) ) +{ + 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]->SetKind(SfxItemKind::StaticDefault); + } + + 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]->SetKind(SfxItemKind::PoolDefault); + } + + // Repair linkage + if ( rPool.pImpl->mpSecondary ) + SetSecondaryPool( rPool.pImpl->mpSecondary->Clone() ); +} + +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) + && "static defaults not sorted" ); + (*pImpl->mpStaticDefaults)[n]->SetKind(SfxItemKind::StaticDefault); + DBG_ASSERT( pImpl->maPoolItemArrays[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() +{ + if ( !pImpl->maPoolItemArrays.empty() && !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::Free(SfxItemPool* pPool) +{ + if(!pPool) + return; + + // tell all the registered SfxItemPoolUsers that the pool is in destruction + std::vector<SfxItemPoolUser*> aListCopy(pPool->pImpl->maSfxItemPoolUsers); + for(SfxItemPoolUser* pSfxItemPoolUser : aListCopy) + { + DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)"); + pSfxItemPoolUser->ObjectInDestruction(*pPool); + } + + // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser() + // when they get called from ObjectInDestruction(). + pPool->pImpl->maSfxItemPoolUsers.clear(); + + // delete pool + delete pPool; +} + + +void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) +{ + // Reset Master in attached Pools + if ( pImpl->mpSecondary ) + { +#ifdef DBG_UTIL + if (pImpl->mpStaticDefaults != nullptr && !pImpl->maPoolItemArrays.empty() + && !pImpl->mpSecondary->pImpl->maPoolItemArrays.empty()) + // 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 ) + bHasSetItems = dynamic_cast<const SfxSetItem *>((*pImpl->mpStaticDefaults)[i]) != nullptr; + + // Detached Pools must be empty + bool bOK = bHasSetItems; + for (auto const& rSecArray : pImpl->mpSecondary->pImpl->maPoolItemArrays) + { + if (!bOK) + break; + if (rSecArray.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; + for ( SfxItemPool *p = pImpl->mpSecondary->pImpl->mpSecondary; p; p = p->pImpl->mpSecondary ) + p->pImpl->mpMaster = pImpl->mpSecondary; + } + + // 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 ) + 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 ) +{ + pImpl->eDefMetric = eNewMetric; +} + +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 ); +} + + +SfxItemPool* SfxItemPool::Clone() const +{ + SfxItemPool *pPool = new SfxItemPool( *this ); + return pPool; +} + + +void SfxItemPool::Delete() +{ + // Already deleted? + if (pImpl->maPoolItemArrays.empty() || pImpl->maPoolDefaults.empty()) + return; + + // Inform e.g. running Requests + pImpl->aBC.Broadcast( SfxHint( SfxHintId::Dying ) ); + + // Iterate through twice: first for the SetItems. + if (pImpl->mpStaticDefaults != nullptr) { + 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 (dynamic_cast<const SfxSetItem*>(pStaticDefaultItem)) + { + // SfxSetItem found, remove PoolItems (and defaults) with same ID + auto& rArray = pImpl->maPoolItemArrays[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; + } + } + } + } + + // now remove remaining PoolItems (and defaults) who didn't have SetItems + for (auto& rArray : pImpl->maPoolItemArrays) + { + 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 + } + pImpl->maPoolItemArrays.clear(); + // 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->SetKind(SfxItemKind::PoolDefault); + if (rOldDefault) + { + rOldDefault->SetRefCount(0); + DELETEZ(rOldDefault); + } + 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); + DELETEZ(rOldDefault); + } + } + else if ( pImpl->mpSecondary ) + pImpl->mpSecondary->ResetPoolDefaultItem(nWhichId); + else + { + assert(false && "unknown WhichId - cannot reset pool default"); + } +} + + +const SfxPoolItem& SfxItemPool::PutImpl( const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership ) +{ + if ( 0 == nWhich ) + nWhich = rItem.Which(); + + // Find correct Secondary Pool + bool bSID = IsSlot(nWhich); + if ( !bSID && !IsInRange(nWhich) ) + { + if ( pImpl->mpSecondary ) + return pImpl->mpSecondary->PutImpl( rItem, nWhich, bPassingOwnership ); + OSL_FAIL( "unknown WhichId - cannot put item" ); + } + + // SID ? + if (bSID) + { + assert((rItem.Which() != nWhich || + !IsDefaultItem(&rItem) || rItem.GetKind() == SfxItemKind::DeleteOnIdle) + && "a non Pool Item is Default?!"); + SfxPoolItem *pPoolItem = rItem.Clone(pImpl->mpMaster); + pPoolItem->SetWhich(nWhich); + AddRef( *pPoolItem ); + if (bPassingOwnership) + delete &rItem; + return *pPoolItem; + } + + assert(!pImpl->mpStaticDefaults || + typeid(rItem) == typeid(GetDefaultItem(nWhich))); + + const sal_uInt16 nIndex = GetIndex_Impl(nWhich); + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[nIndex]; + + // Is this a 'poolable' item - ie. should we re-use and return + // the same underlying item for equivalent (==) SfxPoolItems? + if ( IsItemPoolable_Impl( nIndex ) ) + { + // if is already in a pool, then it is worth checking if it is in this one. + if ( IsPooledItem(&rItem) ) + { + // 1. search for an identical pointer in the pool + auto it = rItemArr.find(const_cast<SfxPoolItem *>(&rItem)); + if (it != rItemArr.end()) + { + AddRef(rItem); + assert(!bPassingOwnership && "can't be passing ownership and have the item already in the pool"); + return rItem; + } + } + + const SfxPoolItem* pFoundItem = nullptr; + // 2. search for an item with matching attributes. + if (rItem.IsSortable()) + { + pFoundItem = rItemArr.findByLessThan(&rItem); + if (pFoundItem) + assert(*pFoundItem == rItem); + } + else + { + for (auto itr = rItemArr.begin(); itr != rItemArr.end(); ++itr) + { + if (**itr == rItem) + { + pFoundItem = *itr; + break; + } + } + } + if (pFoundItem) + { + assert((!bPassingOwnership || (&rItem != pFoundItem)) && "can't be passing ownership and have the item already in the pool"); + AddRef(*pFoundItem); + if (bPassingOwnership) + delete &rItem; + return *pFoundItem; + } + } + + // 3. not found, so clone to insert into the pointer array. + SfxPoolItem* pNewItem; + if (bPassingOwnership) + { + assert(!dynamic_cast<const SfxItemSet*>(&rItem) && "can't pass ownership of SfxItem, they need to be cloned to the master pool"); + pNewItem = const_cast<SfxPoolItem*>(&rItem); + } + else + pNewItem = rItem.Clone(pImpl->mpMaster); + pNewItem->SetWhich(nWhich); + assert(typeid(rItem) == typeid(*pNewItem) && "SfxItemPool::Put(): unequal types, no Clone() override?"); + if (dynamic_cast<const SfxSetItem*>(&rItem) == nullptr) + { + assert((!IsItemPoolable(nWhich) || rItem == *pNewItem) + && "SfxItemPool::Put(): unequal items: no operator== override?"); + assert((!IsItemPoolable(*pNewItem) || *pNewItem == rItem) + && "SfxItemPool::Put(): unequal items: no operator== override?"); + } + AddRef( *pNewItem ); + + // 4. finally insert into the pointer array + rItemArr.insert( pNewItem ); + return *pNewItem; +} + +void SfxItemPool::Remove( const SfxPoolItem& rItem ) +{ + assert(!IsPoolDefaultItem(&rItem) && "cannot remove Pool Default"); + + // Find correct Secondary Pool + const sal_uInt16 nWhich = rItem.Which(); + bool bSID = IsSlot(nWhich); + if ( !bSID && !IsInRange(nWhich) ) + { + if ( pImpl->mpSecondary ) + { + pImpl->mpSecondary->Remove( rItem ); + return; + } + OSL_FAIL( "unknown WhichId - cannot remove item" ); + } + + // SID ? + if ( bSID ) + { + assert(!IsDefaultItem(&rItem) && "a non Pool Item is Default?!"); + if ( 0 == ReleaseRef(rItem) ) + { + delete &rItem; + } + return; + } + + assert(rItem.GetRefCount() && "RefCount == 0, Remove impossible"); + + const sal_uInt16 nIndex = GetIndex_Impl(nWhich); + // Static Defaults are just there + if ( IsStaticDefaultItem(&rItem) && + &rItem == (*pImpl->mpStaticDefaults)[nIndex]) + return; + + // Find Item in own Pool + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[nIndex]; + + auto it = rItemArr.find(const_cast<SfxPoolItem *>(&rItem)); + if (it != rItemArr.end()) + { + if ( rItem.GetRefCount() ) //! + ReleaseRef( rItem ); + else + { + assert(false && "removing Item without ref"); + } + + // FIXME: Hack, for as long as we have problems with the Outliner + // See other MI-REF + if ( 0 == rItem.GetRefCount() && nWhich < 4000 ) + { + rItemArr.erase(it); + delete &rItem; + } + + return; + } + + // not found + assert(false && "removing Item not in Pool"); +} + + +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; +} + +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() +{ + FillItemIdRanges_Impl( pImpl->mpPoolRanges ); +} + + +void SfxItemPool::FillItemIdRanges_Impl( std::unique_ptr<sal_uInt16[]>& pWhichRanges ) const +{ + DBG_ASSERT( !pImpl->mpPoolRanges, "GetFrozenRanges() would be faster!" ); + + const SfxItemPool *pPool; + sal_uInt16 nLevel = 0; + for( pPool = this; pPool; pPool = pPool->pImpl->mpSecondary ) + ++nLevel; + + pWhichRanges.reset(new sal_uInt16[ 2*nLevel + 1 ]); + + nLevel = 0; + for( pPool = this; pPool; pPool = pPool->pImpl->mpSecondary ) + { + pWhichRanges[nLevel++] = pPool->pImpl->mnStart; + pWhichRanges[nLevel++] = pPool->pImpl->mnEnd; + pWhichRanges[nLevel] = 0; + } +} + +const sal_uInt16* SfxItemPool::GetFrozenIdRanges() const +{ + return pImpl->mpPoolRanges.get(); +} + +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) ]; +} + +SfxItemPool::Item2Range SfxItemPool::GetItemSurrogates(sal_uInt16 nWhich) const +{ + static const o3tl::sorted_vector<SfxPoolItem*> EMPTY; + + if ( !IsInRange(nWhich) ) + { + if ( pImpl->mpSecondary ) + return pImpl->mpSecondary->GetItemSurrogates( nWhich ); + assert(false && "unknown WhichId - cannot resolve surrogate"); + return { EMPTY.end(), EMPTY.end() }; + } + + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[GetIndex_Impl(nWhich)]; + return { rItemArr.begin(), rItemArr.end() }; +} + +/* This is only valid for SfxPoolItem that override IsSortable and operator< */ +std::vector<const SfxPoolItem*> SfxItemPool::FindItemSurrogate(sal_uInt16 nWhich, SfxPoolItem const & rSample) const +{ + if ( !IsInRange(nWhich) ) + { + if ( pImpl->mpSecondary ) + return pImpl->mpSecondary->FindItemSurrogate( nWhich, rSample ); + assert(false && "unknown WhichId - cannot resolve surrogate"); + return std::vector<const SfxPoolItem*>(); + } + + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[GetIndex_Impl(nWhich)]; + return rItemArr.findSurrogateRange(&rSample); +} + +sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const +{ + if ( !IsInRange(nWhich) ) + { + if ( pImpl->mpSecondary ) + return pImpl->mpSecondary->GetItemCount2( nWhich ); + assert(false && "unknown WhichId - cannot resolve surrogate"); + return 0; + } + + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[GetIndex_Impl(nWhich)]; + return rItemArr.size(); +} + + +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::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemPool")); + for (auto const & rArray : pImpl->maPoolItemArrays) + for (auto const & rItem : rArray) + rItem->dumpAsXml(pWriter); + 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 000000000..5f4a4aacb --- /dev/null +++ b/svl/source/items/itemprop.cxx @@ -0,0 +1,343 @@ +/* -*- 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> +#include <unordered_map> +/* + * 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; + +typedef std::unordered_map< OUString, + SfxItemPropertySimpleEntry > SfxItemPropertyHashMap_t; + +class SfxItemPropertyMap_Impl : public SfxItemPropertyHashMap_t +{ +public: + mutable uno::Sequence< beans::Property > m_aPropSeq; + + SfxItemPropertyMap_Impl(){} + explicit SfxItemPropertyMap_Impl( const SfxItemPropertyMap_Impl* pSource ); +}; + +SfxItemPropertyMap_Impl::SfxItemPropertyMap_Impl( const SfxItemPropertyMap_Impl* pSource ) +{ + SfxItemPropertyHashMap_t::operator=( *pSource ); + m_aPropSeq = pSource->m_aPropSeq; +} + +SfxItemPropertyMap::SfxItemPropertyMap( const SfxItemPropertyMapEntry* pEntries ) : + m_pImpl( new SfxItemPropertyMap_Impl ) +{ + while( !pEntries->aName.isEmpty() ) + { + (*m_pImpl) [ pEntries->aName ] = pEntries; + ++pEntries; + } +} + +SfxItemPropertyMap::SfxItemPropertyMap( const SfxItemPropertyMap& rSource ) : + m_pImpl( new SfxItemPropertyMap_Impl( rSource.m_pImpl.get() ) ) +{ +} + +SfxItemPropertyMap::~SfxItemPropertyMap() +{ +} + +const SfxItemPropertySimpleEntry* SfxItemPropertyMap::getByName( const OUString &rName ) const +{ + SfxItemPropertyHashMap_t::const_iterator aIter = m_pImpl->find(rName); + if( aIter == m_pImpl->end() ) + return nullptr; + return &aIter->second; +} + +uno::Sequence<beans::Property> const & SfxItemPropertyMap::getProperties() const +{ + if( !m_pImpl->m_aPropSeq.hasElements() ) + { + m_pImpl->m_aPropSeq.realloc( m_pImpl->size() ); + beans::Property* pPropArray = m_pImpl->m_aPropSeq.getArray(); + sal_uInt32 n = 0; + for( const auto& rEntry : *m_pImpl ) + //for ( const SfxItemPropertyMap *pMap = _pMap; pMap->pName; ++pMap ) + { + const SfxItemPropertySimpleEntry* pEntry = &rEntry.second; + pPropArray[n].Name = rEntry.first; + pPropArray[n].Handle = pEntry->nWID; + pPropArray[n].Type = pEntry->aType; + pPropArray[n].Attributes = + sal::static_int_cast< sal_Int16 >(pEntry->nFlags); + n++; + } + } + + return m_pImpl->m_aPropSeq; +} + +beans::Property SfxItemPropertyMap::getPropertyByName( const OUString & rName ) const +{ + SfxItemPropertyHashMap_t::const_iterator aIter = m_pImpl->find(rName); + if( aIter == m_pImpl->end() ) + throw UnknownPropertyException(rName); + const SfxItemPropertySimpleEntry* pEntry = &aIter->second; + 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( const OUString& rName ) const +{ + SfxItemPropertyHashMap_t::const_iterator aIter = m_pImpl->find(rName); + return aIter != m_pImpl->end(); +} + +void SfxItemPropertyMap::mergeProperties( const uno::Sequence< beans::Property >& rPropSeq ) +{ + for( const beans::Property& rProp : rPropSeq ) + { + SfxItemPropertySimpleEntry aTemp( + sal::static_int_cast< sal_Int16 >( rProp.Handle ), //nWID + rProp.Type, //aType + rProp.Attributes); //nFlags + (*m_pImpl)[rProp.Name] = aTemp; + } +} + +PropertyEntryVector_t SfxItemPropertyMap::getPropertyEntries() const +{ + PropertyEntryVector_t aRet; + aRet.reserve(m_pImpl->size()); + + for( const auto& rEntry : *m_pImpl ) + { + const SfxItemPropertySimpleEntry* pEntry = &rEntry.second; + aRet.emplace_back( rEntry.first, * pEntry ); + } + return aRet; +} + +sal_uInt32 SfxItemPropertyMap::getSize() const +{ + return m_pImpl->size(); +} + +SfxItemPropertySet::~SfxItemPropertySet() +{ +} + +void SfxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry& 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 SfxItemPropertySimpleEntry* 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 SfxItemPropertySimpleEntry& 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( *pNewItem ); + } +} + +void SfxItemPropertySet::setPropertyValue( const OUString &rName, + const Any& aVal, + SfxItemSet& rSet ) const +{ + const SfxItemPropertySimpleEntry* pEntry = m_aMap.getByName( rName ); + if ( !pEntry ) + { + throw UnknownPropertyException(rName); + } + setPropertyValue(*pEntry, aVal, rSet); +} + +PropertyState SfxItemPropertySet::getPropertyState(const SfxItemPropertySimpleEntry& rEntry, const SfxItemSet& rSet) const + throw() +{ + 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 SfxItemPropertySimpleEntry* 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(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( const SfxItemPropertyMapEntry *pMap, + const Sequence<Property>& rPropSeq ) + : aExtMap( pMap ) +{ + aExtMap.mergeProperties( rPropSeq ); +} + +SfxExtItemPropertySetInfo::~SfxExtItemPropertySetInfo() +{ +} + +Sequence< Property > SAL_CALL SfxExtItemPropertySetInfo::getProperties( ) +{ + return aExtMap.getProperties(); +} + +Property SAL_CALL SfxExtItemPropertySetInfo::getPropertyByName( const OUString& rPropertyName ) +{ + return aExtMap.getPropertyByName( rPropertyName ); +} + +sal_Bool SAL_CALL SfxExtItemPropertySetInfo::hasPropertyByName( const OUString& rPropertyName ) +{ + return aExtMap.hasPropertyByName( rPropertyName ); +} + +/* 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 000000000..180c76a6a --- /dev/null +++ b/svl/source/items/itemset.cxx @@ -0,0 +1,1745 @@ +/* -*- 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/whiter.hxx> + +static const sal_uInt16 nInitCount = 10; // Single USHORTs => 5 pairs without '0' + +namespace +{ + +/** + * Determines the number of sal_uInt16s in a 0-terminated array of pairs of + * sal_uInt16s. + * The terminating 0 is not included in the count. + */ +sal_uInt16 Count_Impl( const sal_uInt16 *pRanges ) +{ + sal_uInt16 nCount = 0; + while ( *pRanges ) + { + nCount += 2; + pRanges += 2; + } + return nCount; +} + +/** + * Determines the total number of sal_uInt16s described in a 0-terminated + * array of pairs of sal_uInt16s, each representing a range of sal_uInt16s. + */ +sal_uInt16 Capacity_Impl( const sal_uInt16 *pRanges ) +{ + sal_uInt16 nCount = 0; + + if ( pRanges ) + { + while ( *pRanges ) + { + nCount += pRanges[1] - pRanges[0] + 1; + pRanges += 2; + } + } + return nCount; +} + +} + +/** + * 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. + */ +SfxItemSet::SfxItemSet(SfxItemPool& rPool) + : m_pPool( &rPool ) + , m_pParent(nullptr) + , m_nCount(0) +{ + m_pWhichRanges = const_cast<sal_uInt16*>(m_pPool->GetFrozenIdRanges()); + assert( m_pWhichRanges && "don't create ItemSets with full range before FreezeIdRanges()" ); + if (!m_pWhichRanges) + { + std::unique_ptr<sal_uInt16[]> tmp; + m_pPool->FillItemIdRanges_Impl(tmp); + m_pWhichRanges = tmp.release(); + } + + const sal_uInt16 nSize = TotalCount(); + m_pItems.reset(new const SfxPoolItem*[nSize]{}); +} + +void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable) +{ + sal_uInt16 nCnt = 0; + const sal_uInt16* pPtr = pWhichPairTable; + while( *pPtr ) + { + nCnt += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + + m_pItems.reset( new const SfxPoolItem*[nCnt]{} ); + + std::ptrdiff_t cnt = pPtr - pWhichPairTable +1; + m_pWhichRanges = new sal_uInt16[ cnt ]; + memcpy( m_pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt ); +} + +SfxItemSet::SfxItemSet( + SfxItemPool & pool, std::initializer_list<sal_uInt16> wids, + std::size_t items): + m_pPool(&pool), m_pParent(nullptr), + m_pItems(new SfxPoolItem const *[items]{}), + m_pWhichRanges(new sal_uInt16[wids.size() + 1]), + // cannot overflow, assuming std::size_t is no smaller than sal_uInt16, + // as wids.size() must be substantially smaller than + // std::numeric_limits<sal_uInt16>::max() by construction in + // SfxItemSet::create + m_nCount(0) +{ + assert(wids.size() != 0); + assert(wids.size() % 2 == 0); + std::copy(wids.begin(), wids.end(), m_pWhichRanges); + m_pWhichRanges[wids.size()] = 0; +} + +SfxItemSet::SfxItemSet( + SfxItemPool & pool, std::initializer_list<Pair> wids): + m_pPool(&pool), m_pParent(nullptr), + m_pWhichRanges(new sal_uInt16[2 * wids.size() + 1]), //TODO: overflow + m_nCount(0) +{ + assert(wids.size() != 0); + std::size_t i = 0; + std::size_t size = 0; +#if !defined NDEBUG + //TODO: sal_uInt16 prev = 0; +#endif + for (auto const & p: wids) { + assert(svl::detail::validRange(p.wid1, p.wid2)); + //TODO: assert(prev == 0 || svl::detail::validGap(prev, p.wid1)); + m_pWhichRanges[i++] = p.wid1; + m_pWhichRanges[i++] = p.wid2; + size += svl::detail::rangeSize(p.wid1, p.wid2); + // cannot overflow, assuming std::size_t is no smaller than + // sal_uInt16 +#if !defined NDEBUG + //TODO: prev = p.wid2; +#endif + } + m_pWhichRanges[i] = 0; + m_pItems.reset( new SfxPoolItem const *[size]{} ); +} + +SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ) + : m_pPool(&rPool) + , m_pParent(nullptr) + , m_pWhichRanges(nullptr) + , m_nCount(0) +{ + // pWhichPairTable == 0 is for the SfxAllEnumItemSet + if ( pWhichPairTable ) + InitRanges_Impl(pWhichPairTable); +} + +SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) + : m_pPool( rASet.m_pPool ) + , m_pParent( rASet.m_pParent ) + , m_nCount( rASet.m_nCount ) +{ + // Calculate the attribute count + sal_uInt16 nCnt = 0; + sal_uInt16* pPtr = rASet.m_pWhichRanges; + while( *pPtr ) + { + nCnt += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + + m_pItems.reset( new const SfxPoolItem* [ nCnt ] ); + + // Copy attributes + SfxPoolItem const** ppDst = m_pItems.get(); + SfxPoolItem const** ppSrc = rASet.m_pItems.get(); + for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc ) + if ( nullptr == *ppSrc || // Current Default? + IsInvalidItem(*ppSrc) || // DontCare? + IsStaticDefaultItem(*ppSrc) ) // Defaults that are not to be pooled? + // Just copy the pointer + *ppDst = *ppSrc; + else if (m_pPool->IsItemPoolable( **ppSrc )) + { + // Just copy the pointer and increase RefCount + *ppDst = *ppSrc; + (*ppDst)->AddRef(); + } + else if ( !(*ppSrc)->Which() ) + *ppDst = (*ppSrc)->Clone(); + else + // !IsPoolable() => assign via Pool + *ppDst = &m_pPool->Put( **ppSrc ); + + // Copy the WhichRanges + std::ptrdiff_t cnt = pPtr - rASet.m_pWhichRanges+1; + m_pWhichRanges = new sal_uInt16[ cnt ]; + memcpy( m_pWhichRanges, rASet.m_pWhichRanges, sizeof( sal_uInt16 ) * cnt); +} + +SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept + : m_pPool( rASet.m_pPool ) + , m_pParent( rASet.m_pParent ) + , m_pItems( std::move(rASet.m_pItems) ) + , m_pWhichRanges( rASet.m_pWhichRanges ) + , m_nCount( rASet.m_nCount ) +{ + rASet.m_pPool = nullptr; + rASet.m_pParent = nullptr; + rASet.m_pWhichRanges = nullptr; + rASet.m_nCount = 0; +} + +SfxItemSet::~SfxItemSet() +{ + if (m_pWhichRanges) // might be nullptr if we have been moved-from + { + sal_uInt16 nCount = TotalCount(); + if( Count() ) + { + SfxPoolItem const** ppFnd = m_pItems.get(); + for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd ) + if( *ppFnd && !IsInvalidItem(*ppFnd) ) + { + if( !(*ppFnd)->Which() ) + delete *ppFnd; + else { + // Still multiple references present, so just alter the RefCount + if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) ) + (*ppFnd)->ReleaseRef(); + else + if ( !IsDefaultItem(*ppFnd) ) + // Delete from Pool + m_pPool->Remove( **ppFnd ); + } + } + } + } + + m_pItems.reset(); + if (m_pPool && m_pWhichRanges != m_pPool->GetFrozenIdRanges()) + delete[] m_pWhichRanges; + m_pWhichRanges = nullptr; // for invariant-testing +} + +/** + * Delete single Items or all Items (nWhich == 0) + */ +sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich ) +{ + if( !Count() ) + return 0; + + sal_uInt16 nDel = 0; + SfxPoolItem const** ppFnd = m_pItems.get(); + + if( nWhich ) + { + const sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + // Within this range? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Actually set? + ppFnd += nWhich - *pPtr; + if( *ppFnd ) + { + // Due to the assertions in the sub calls, we need to do the following + --m_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = nullptr; + + if ( !IsInvalidItem(pItemToClear) ) + { + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + if ( pItemToClear->Which() ) + m_pPool->Remove( *pItemToClear ); + } + ++nDel; + } + + // found => break + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } + else + { + nDel = m_nCount; + + sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + // Due to the assertions in the sub calls, we need to do this + --m_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = nullptr; + + if ( !IsInvalidItem(pItemToClear) ) + { + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + + // #i32448# + // Take care of disabled items, too. + if (!pItemToClear->m_nWhich) + { + // item is disabled, delete it + delete pItemToClear; + } + else + { + // remove item from pool + m_pPool->Remove( *pItemToClear ); + } + } + } + pPtr += 2; + } + } + return nDel; +} + +void SfxItemSet::ClearInvalidItems() +{ + sal_uInt16* pPtr = m_pWhichRanges; + SfxPoolItem const** ppFnd = m_pItems.get(); + while( *pPtr ) + { + for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( IsInvalidItem(*ppFnd) ) + { + *ppFnd = nullptr; + --m_nCount; + } + pPtr += 2; + } +} + +void SfxItemSet::InvalidateAllItems() +{ + assert( !m_nCount && "There are still Items set" ); + m_nCount = TotalCount(); + memset(static_cast<void*>(m_pItems.get()), -1, m_nCount * sizeof(SfxPoolItem*)); +} + +SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich, + bool bSrchInParent, + const SfxPoolItem **ppItem ) const +{ + // Find the range in which the Which is located + const SfxItemSet* pCurrentSet = this; + SfxItemState eRet = SfxItemState::UNKNOWN; + do + { + SfxPoolItem const** ppFnd = pCurrentSet->m_pItems.get(); + const sal_uInt16* pPtr = pCurrentSet->m_pWhichRanges; + if (pPtr) + { + while ( *pPtr ) + { + if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Within this range + ppFnd += nWhich - *pPtr; + if ( !*ppFnd ) + { + eRet = SfxItemState::DEFAULT; + if( !bSrchInParent ) + return eRet; // Not present + break; // Keep searching in the parents! + } + + if ( IsInvalidItem(*ppFnd) ) + // Different ones are present + return SfxItemState::DONTCARE; + + if ( (*ppFnd)->IsVoidItem() ) + return SfxItemState::DISABLED; + + if (ppItem) + { + *ppItem = *ppFnd; + } + return SfxItemState::SET; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } + if (!bSrchInParent) + break; + pCurrentSet = pCurrentSet->m_pParent; + } while (nullptr != pCurrentSet); + return eRet; +} + +bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const +{ + bool bRet = SfxItemState::SET == GetItemState(nWhich, true, ppItem); + if (!bRet && ppItem) + *ppItem = nullptr; + return bRet; +} + +const SfxPoolItem* SfxItemSet::PutImpl( const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership ) +{ + if ( !nWhich ) + { + assert(!bPassingOwnership); + return nullptr; //FIXME: Only because of Outliner bug + } + + SfxPoolItem const** ppFnd = m_pItems.get(); + const sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Within this range + ppFnd += nWhich - *pPtr; + if( *ppFnd ) // Already one present + { + // Same Item already present? + if ( *ppFnd == &rItem ) + { + assert(!bPassingOwnership); + return nullptr; + } + + // Will 'dontcare' or 'disabled' be overwritten with some real value? + if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) ) + { + auto const old = *ppFnd; + *ppFnd = &m_pPool->PutImpl( rItem, nWhich, bPassingOwnership ); + if (!IsInvalidItem(old)) { + assert(old->Which() == 0); + delete old; + } + return *ppFnd; + } + + // Turns into disabled? + if( !rItem.Which() ) + { + if (IsInvalidItem(*ppFnd) || (*ppFnd)->Which() != 0) { + *ppFnd = rItem.Clone(m_pPool); + } + if (bPassingOwnership) + delete &rItem; + return nullptr; + } + else + { + // Same value already present? + if ( rItem == **ppFnd ) + { + if (bPassingOwnership) + delete &rItem; + return nullptr; + } + + // Add the new one, remove the old one + const SfxPoolItem& rNew = m_pPool->PutImpl( rItem, nWhich, bPassingOwnership ); + const SfxPoolItem* pOld = *ppFnd; + *ppFnd = &rNew; + if (SfxItemPool::IsWhich(nWhich)) + Changed( *pOld, rNew ); + m_pPool->Remove( *pOld ); + } + } + else + { + ++m_nCount; + if( !rItem.Which() ) + { + *ppFnd = rItem.Clone(m_pPool); + if (bPassingOwnership) + delete &rItem; + } + else + { + const SfxPoolItem& rNew = m_pPool->PutImpl( rItem, nWhich, bPassingOwnership ); + *ppFnd = &rNew; + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rOld = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + Changed( rOld, rNew ); + } + } + } + SAL_WARN_IF(!bPassingOwnership && m_pPool->IsItemPoolable(nWhich) && + dynamic_cast<const SfxSetItem*>( &rItem ) == nullptr && + **ppFnd != rItem, + "svl.items", "putted Item unequal, with ID/pos " << nWhich ); + return *ppFnd; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + if (bPassingOwnership) + delete &rItem; + return nullptr; +} + +bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault ) +{ + bool bRet = false; + if( rSet.Count() ) + { + SfxPoolItem const** ppFnd = rSet.m_pItems.get(); + const sal_uInt16* pPtr = rSet.m_pWhichRanges; + while ( *pPtr ) + { + for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + if ( IsInvalidItem( *ppFnd ) ) + { + if ( bInvalidAsDefault ) + bRet |= 0 != ClearItem( nWhich ); + // FIXME: Caused a SEGFAULT on non Windows-platforms: + // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + else + InvalidateItem( nWhich ); + } + else + bRet |= nullptr != Put( **ppFnd, nWhich ); + } + pPtr += 2; + } + } + return bRet; +} + +/** + * 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& rSet, // 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( rSet.Count()" because of dont-care + defaults + SfxPoolItem const** ppFnd = rSet.m_pItems.get(); + const sal_uInt16* pPtr = rSet.m_pWhichRanges; + while ( *pPtr ) + { + for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + if ( IsInvalidItem( *ppFnd ) ) + { + // Item is DontCare: + switch ( eDontCareAs ) + { + case SfxItemState::SET: + Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + break; + + case SfxItemState::DEFAULT: + ClearItem( nWhich ); + break; + + case SfxItemState::DONTCARE: + InvalidateItem( nWhich ); + break; + + default: + assert(!"invalid Argument for eDontCareAs"); + } + } + else + // Item is set: + Put( **ppFnd, nWhich ); + } + else + { + // Item is default: + switch ( eDefaultAs ) + { + case SfxItemState::SET: + Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + break; + + case SfxItemState::DEFAULT: + ClearItem( nWhich ); + break; + + case SfxItemState::DONTCARE: + InvalidateItem( nWhich ); + break; + + default: + assert(!"invalid Argument for eDefaultAs"); + } + } + pPtr += 2; + } +} + +/** + * 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 ) +{ + // special case: exactly one sal_uInt16 which is already included? + if (nFrom == nTo) + if (SfxItemState eItemState = GetItemState(nFrom, false); + eItemState == SfxItemState::DEFAULT || eItemState == SfxItemState::SET) + return; + +#ifdef DBG_UTIL + assert(nFrom <= nTo); + for (const sal_uInt16 *pRange = m_pWhichRanges; *pRange; pRange += 2) + { + assert(pRange[0] <= pRange[1]); + // ranges must be sorted and discrete + assert( + !pRange[2] || (pRange[2] > pRange[1] && pRange[2] - pRange[1] > 1)); + } +#endif + + // create vector of ranges (sal_uInt16 pairs of lower and upper bound) + const size_t nOldCount = Count_Impl(m_pWhichRanges); + std::vector<std::pair<sal_uInt16, sal_uInt16>> aRangesTable; + aRangesTable.reserve(nOldCount/2 + 1); + bool bAdded = false; + for (size_t i = 0; i < nOldCount; i += 2) + { + if (!bAdded && m_pWhichRanges[i] >= nFrom) + { // insert new range, keep ranges sorted + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(nFrom, nTo)); + bAdded = true; + } + // insert current range + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(m_pWhichRanges[i], m_pWhichRanges[i+1])); + } + if (!bAdded) + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(nFrom, nTo)); + + // true if ranges overlap or adjoin, false if ranges are separate + auto needMerge = [](std::pair<sal_uInt16, sal_uInt16> lhs, std::pair<sal_uInt16, sal_uInt16> rhs) + {return (lhs.first-1) <= rhs.second && (rhs.first-1) <= lhs.second;}; + + std::vector<std::pair<sal_uInt16, sal_uInt16> >::iterator it = aRangesTable.begin(); + // we got at least one range + for (;;) + { + auto itNext = std::next(it); + if (itNext == aRangesTable.end()) + break; + // check neighbouring ranges, find first range which overlaps or adjoins a previous range + 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); + aRangesTable.erase(itNext); + } + else + ++it; + } + + // construct range array + const size_t nNewSize = 2 * aRangesTable.size() + 1; + std::vector<sal_uInt16> aRanges(nNewSize); + for (size_t i = 0; i < (nNewSize - 1); i +=2) + std::tie(aRanges[i], aRanges[i+1]) = aRangesTable[i/2]; + + // null terminate to be compatible with sal_uInt16* array pointers + aRanges.back() = 0; + + SetRanges( aRanges.data() ); +} + +/** + * Modifies the ranges of settable items. Keeps state of items which + * are new ranges too. + */ +void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges ) +{ + // Identical Ranges? + if (m_pWhichRanges == pNewRanges) + return; + const sal_uInt16* pOld = m_pWhichRanges; + const sal_uInt16* pNew = pNewRanges; + while ( *pOld == *pNew ) + { + if ( !*pOld && !*pNew ) + return; + ++pOld; + ++pNew; + } + + // create new item-array (by iterating through all new ranges) + sal_uInt16 nSize = Capacity_Impl(pNewRanges); + SfxPoolItem const** aNewItems = new const SfxPoolItem* [ nSize ]; + sal_uInt16 nNewCount = 0; + if (m_nCount == 0) + memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) ); + else + { + sal_uInt16 n = 0; + for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 ) + { + // iterate through all ids in the range + for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n ) + { + // direct move of pointer (not via pool) + SfxItemState eState = GetItemState( nWID, false, aNewItems+n ); + if ( SfxItemState::SET == eState ) + { + // increment new item count and possibly increment ref count + ++nNewCount; + aNewItems[n]->AddRef(); + } + else if ( SfxItemState::DISABLED == eState ) + { + // put "disabled" item + ++nNewCount; + aNewItems[n] = new SfxVoidItem(0); + } + else if ( SfxItemState::DONTCARE == eState ) + { + ++nNewCount; + aNewItems[n] = INVALID_POOL_ITEM; + } + else + { + // default + aNewItems[n] = nullptr; + } + } + } + // free old items + sal_uInt16 nOldTotalCount = TotalCount(); + for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem ) + { + const SfxPoolItem *pItem = m_pItems[nItem]; + if ( pItem && !IsInvalidItem(pItem) && pItem->Which() ) + m_pPool->Remove(*pItem); + } + } + + // replace old items-array and ranges + m_pItems.reset( aNewItems ); + m_nCount = nNewCount; + + if( pNewRanges == GetPool()->GetFrozenIdRanges() ) + { + delete[] m_pWhichRanges; + m_pWhichRanges = const_cast<sal_uInt16*>(pNewRanges); + } + else + { + sal_uInt16 nCount = Count_Impl(pNewRanges) + 1; + if (m_pWhichRanges != m_pPool->GetFrozenIdRanges()) + delete[] m_pWhichRanges; + m_pWhichRanges = new sal_uInt16[ nCount ]; + memcpy( m_pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount ); + } +} + +/** + * 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 (m_nCount) + ClearItem(); + if ( bDeep ) + { + SfxWhichIter aIter(*this); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet.GetItemState( nWhich, true, &pItem ) ) + bRet |= nullptr != Put( *pItem, pItem->Which() ); + nWhich = aIter.NextWhich(); + } + } + else + bRet = Put(rSet, false); + + return bRet; +} + +const SfxPoolItem* SfxItemSet::GetItem(sal_uInt16 nId, bool bSearchInParent) const +{ + // Convert to WhichId + sal_uInt16 nWhich = GetPool()->GetWhich(nId); + + // Is the Item set or 'bDeep == true' available? + const SfxPoolItem *pItem = nullptr; + SfxItemState eState = GetItemState(nWhich, bSearchInParent, &pItem); + if (bSearchInParent && SfxItemState::DEFAULT == eState && SfxItemPool::IsWhich(nWhich)) + { + pItem = &m_pPool->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 SfxItemSet* pCurrentSet = this; + do + { + if( pCurrentSet->Count() ) + { + SfxPoolItem const** ppFnd = pCurrentSet->m_pItems.get(); + const sal_uInt16* pPtr = pCurrentSet->m_pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // In this Range + ppFnd += nWhich - *pPtr; + if( *ppFnd ) + { + if( IsInvalidItem(*ppFnd) ) { + //FIXME: The following code is duplicated further down + SAL_WARN_IF(!m_pPool, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich); + //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich); + //!return aDefault; + return m_pPool->GetDefaultItem( nWhich ); + } +#ifdef DBG_UTIL + const SfxPoolItem *pItem = *ppFnd; + if ( pItem->IsVoidItem() || !pItem->Which() ) + SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item"); +#endif + return **ppFnd; + } + break; // Continue with Parent + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } +//TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default?? +// if( !*pPtr ) // Until the end of the search Range? +// break; + if (!bSrchInParent) + break; + pCurrentSet = pCurrentSet->m_pParent; + } while (nullptr != pCurrentSet); + + // Get the Default from the Pool and return + SAL_WARN_IF(!m_pPool, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich); + const SfxPoolItem *pItem = &m_pPool->GetDefaultItem( nWhich ); + return *pItem; +} + +/** + * Notification callback + */ +void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& ) +{ +} + +sal_uInt16 SfxItemSet::TotalCount() const +{ + sal_uInt16 nRet = 0; + sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + nRet += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + return nRet; +} + +/** + * Only retain the Items that are also present in rSet + * (nevermind their value). + */ +void SfxItemSet::Intersect( const SfxItemSet& rSet ) +{ + assert(m_pPool && "Not implemented without Pool"); + if( !Count() ) // None set? + return; + + // Delete all Items not contained in rSet + if( !rSet.Count() ) + { + ClearItem(); // Delete everything + return; + } + + // Test whether the Which Ranges are different + sal_uInt16* pWh1 = m_pWhichRanges; + sal_uInt16* pWh2 = rSet.m_pWhichRanges; + sal_uInt16 nSize = 0; + + for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + break; + } + if( n & 1 ) + nSize += ( *pWh1 - *(pWh1-1) ) + 1; + } + bool bEqual = *pWh1 == *pWh2; // Also check for 0 + + // If the Ranges are identical, we can easily process it + if( bEqual ) + { + SfxPoolItem const** ppFnd1 = m_pItems.get(); + SfxPoolItem const** ppFnd2 = rSet.m_pItems.get(); + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && !*ppFnd2 ) + { + // Delete from Pool + if( !IsInvalidItem( *ppFnd1 ) ) + { + sal_uInt16 nWhich = (*ppFnd1)->Which(); + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + m_pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = nullptr; + --m_nCount; + } + } + else + { + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + do + { + sal_uInt16 nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) ) + ClearItem( nWhich ); // Delete + pItem = aIter.NextItem(); + } while (pItem); + } +} + +void SfxItemSet::Differentiate( const SfxItemSet& rSet ) +{ + if( !Count() || !rSet.Count() )// None set? + return; + + // Test whether the Which Ranges are different + sal_uInt16* pWh1 = m_pWhichRanges; + sal_uInt16* pWh2 = rSet.m_pWhichRanges; + sal_uInt16 nSize = 0; + + for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + break; + } + if( n & 1 ) + nSize += ( *pWh1 - *(pWh1-1) ) + 1; + } + bool bEqual = *pWh1 == *pWh2; // Also test for 0 + + // If the Ranges are identical, we can easily process it + if( bEqual ) + { + SfxPoolItem const** ppFnd1 = m_pItems.get(); + SfxPoolItem const** ppFnd2 = rSet.m_pItems.get(); + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && *ppFnd2 ) + { + // Delete from Pool + if( !IsInvalidItem( *ppFnd1 ) ) + { + sal_uInt16 nWhich = (*ppFnd1)->Which(); + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + m_pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = nullptr; + --m_nCount; + } + } + else + { + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + do + { + sal_uInt16 nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) ) + ClearItem( nWhich ); // Delete + pItem = aIter.NextItem(); + } while (pItem); + + } +} + +/** + * 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 - - - + */ +static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount, + 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 && + _pPool->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 = &_pPool->Put( *pFnd2 ); + + if ( *ppFnd1 ) + ++rCount; + } + + // 1st Item set? + else if ( !IsInvalidItem(*ppFnd1) ) + { + if ( !pFnd2 ) + { + // 2nd Item is Default + if ( !bIgnoreDefaults && + **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) ) + { + // Decision table: set, default, !=, sal_False + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = INVALID_POOL_ITEM; + } + } + else if ( IsInvalidItem(pFnd2) ) + { + // 2nd Item is dontcare + if ( !bIgnoreDefaults || + **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) ) + { + // Decision table: set, dontcare, doesn't matter, sal_False + // or: set, dontcare, !=, sal_True + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = INVALID_POOL_ITEM; + } + } + else + { + // 2nd Item is set + if ( **ppFnd1 != *pFnd2 ) + { + // Decision table: set, set, !=, doesn't matter + _pPool->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" ); + + // Test if the which Ranges are different + sal_uInt16* pWh1 = m_pWhichRanges; + sal_uInt16* pWh2 = rSet.m_pWhichRanges; + sal_uInt16 nSize = 0; + + for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + break; + } + if( n & 1 ) + nSize += ( *pWh1 - *(pWh1-1) ) + 1; + } + bool bEqual = *pWh1 == *pWh2; // Also check for 0 + + // If the Ranges match, they are easier to process! + if( bEqual ) + { + SfxPoolItem const** ppFnd1 = m_pItems.get(); + SfxPoolItem const** ppFnd2 = rSet.m_pItems.get(); + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + MergeItem_Impl(m_pPool, m_nCount, ppFnd1, *ppFnd2, false/*bIgnoreDefaults*/); + } + else + { + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich; + while( 0 != ( nWhich = aIter.NextWhich() ) ) + { + const SfxPoolItem* pItem = nullptr; + (void)rSet.GetItemState( nWhich, true, &pItem ); + if( !pItem ) + { + // Not set, so default + MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ) ); + } + else if( IsInvalidItem( pItem ) ) + // don't care + InvalidateItem( nWhich ); + else + MergeValue( *pItem ); + } + } +} + +void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, bool bIgnoreDefaults ) +{ + SfxPoolItem const** ppFnd = m_pItems.get(); + const sal_uInt16* pPtr = m_pWhichRanges; + const sal_uInt16 nWhich = rAttr.Which(); + while( *pPtr ) + { + // In this Range?? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + ppFnd += nWhich - *pPtr; + MergeItem_Impl(m_pPool, m_nCount, ppFnd, &rAttr, bIgnoreDefaults); + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } +} + +void SfxItemSet::InvalidateItem( sal_uInt16 nWhich ) +{ + SfxPoolItem const** ppFnd = m_pItems.get(); + const sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // In this Range? + ppFnd += nWhich - *pPtr; + + if( *ppFnd ) // Set for me + { + if( !IsInvalidItem(*ppFnd) ) + { + m_pPool->Remove( **ppFnd ); + *ppFnd = INVALID_POOL_ITEM; + } + } + else + { + *ppFnd = INVALID_POOL_ITEM; + ++m_nCount; + } + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } +} + +sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const +{ + sal_uInt16 n = 0; + sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) + { + n = ( *(pPtr+1) - *pPtr ) + 1; + if( nPos < n ) + return *pPtr + nPos; + nPos = nPos - n; + pPtr += 2; + } + assert(false); + return 0; +} + +bool SfxItemSet::operator==(const SfxItemSet &rCmp) const +{ + return Equals( rCmp, true); +} + +bool SfxItemSet::Equals(const SfxItemSet &rCmp, bool bComparePool) const +{ + // Values we can get quickly need to be the same + const bool bDifferentPools = (m_pPool != rCmp.m_pPool); + if ( (bComparePool && m_pParent != rCmp.m_pParent) || + (bComparePool && bDifferentPools) || + Count() != rCmp.Count() ) + return false; + + // If we reach here and bDifferentPools==true that means bComparePool==false. + + // Counting Ranges takes longer; they also need to be the same, however + sal_uInt16 nCount1 = TotalCount(); + sal_uInt16 nCount2 = rCmp.TotalCount(); + if ( nCount1 != nCount2 ) + return false; + + // Are the Ranges themselves unequal? + for (sal_uInt16 nRange = 0; m_pWhichRanges[nRange]; nRange += 2) + { + if (m_pWhichRanges[nRange] != rCmp.m_pWhichRanges[nRange] || + m_pWhichRanges[nRange+1] != rCmp.m_pWhichRanges[nRange+1]) + { + // We must use the slow method then + SfxWhichIter aIter( *this ); + for ( sal_uInt16 nWh = aIter.FirstWhich(); + nWh; + nWh = aIter.NextWhich() ) + { + // If the pointer of the poolable Items are unequal, the Items must match + const SfxPoolItem *pItem1 = nullptr, *pItem2 = nullptr; + if ( GetItemState( nWh, false, &pItem1 ) != + rCmp.GetItemState( nWh, false, &pItem2 ) || + ( pItem1 != pItem2 && + ( !pItem1 || IsInvalidItem(pItem1) || + (m_pPool->IsItemPoolable(*pItem1) && + *pItem1 != *pItem2 ) ) ) ) + return false; + } + + return true; + } + } + + // Are all pointers the same? + if (0 == memcmp( m_pItems.get(), rCmp.m_pItems.get(), nCount1 * sizeof(m_pItems[0]) )) + return true; + + // We need to compare each one separately then + const SfxPoolItem **ppItem1 = m_pItems.get(); + const SfxPoolItem **ppItem2 = rCmp.m_pItems.get(); + for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos ) + { + // If the pointers of the poolable Items are not the same, the Items + // must match + if ( *ppItem1 != *ppItem2 && + ( ( !*ppItem1 || !*ppItem2 ) || + ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) || + (!bDifferentPools && m_pPool->IsItemPoolable(**ppItem1)) || + **ppItem1 != **ppItem2 ) ) + return false; + + ++ppItem1; + ++ppItem2; + } + + return true; +} + +std::unique_ptr<SfxItemSet> SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const +{ + if (pToPool && pToPool != m_pPool) + { + std::unique_ptr<SfxItemSet> pNewSet(new SfxItemSet(*pToPool, m_pWhichRanges)); + if ( bItems ) + { + SfxWhichIter aIter(*pNewSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + const SfxPoolItem* pItem; + if ( SfxItemState::SET == GetItemState( 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(*m_pPool, m_pWhichRanges)); +} + +void SfxItemSet::PutDirect(const SfxPoolItem &rItem) +{ + SfxPoolItem const** ppFnd = m_pItems.get(); + const sal_uInt16* pPtr = m_pWhichRanges; + const sal_uInt16 nWhich = rItem.Which(); +#ifdef DBG_UTIL + IsPoolDefaultItem(&rItem) || m_pPool->CheckItemInPool(&rItem); + // Only cause assertion in the callees +#endif + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // In this Range? + ppFnd += nWhich - *pPtr; + const SfxPoolItem* pOld = *ppFnd; + if( pOld ) // One already present + { + if( rItem == **ppFnd ) + return; // Already present! + m_pPool->Remove( *pOld ); + } + else + ++m_nCount; + + // Add the new one + if( IsPoolDefaultItem(&rItem) ) + *ppFnd = &m_pPool->Put( rItem ); + else + { + *ppFnd = &rItem; + if( !IsStaticDefaultItem( &rItem ) ) + rItem.AddRef(); + } + + return; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } +} + +void SfxItemSet::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemSet")); + SfxItemIter aIter(*this); + for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) + pItem->dumpAsXml(pWriter); + xmlTextWriterEndElement(pWriter); +} + + +// ----------------------------------------------- class SfxAllItemSet + +SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool ) +: SfxItemSet(rPool, nullptr), + nFree(nInitCount) +{ + // Initially no Items + m_pItems = nullptr; + + // Allocate nInitCount pairs at USHORTs for Ranges + m_pWhichRanges = new sal_uInt16[nInitCount + 1]{}; +} + +SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy) +: SfxItemSet(rCopy), + nFree(0) +{ +} + +/** + * 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), + nFree(0) +{ +} + +/** + * This internal function creates a new WhichRanges array, which is copied + * from the 'nOldSize'-USHORTs long 'pUS'. It has new USHORTs at the end instead + * of 'nIncr'. + * The terminating sal_uInt16 with the '0' is neither accounted for in 'nOldSize' + * nor in 'nIncr', but always explicitly added. + * + * @returns the new WhichRanges array (the old 'pUS' is freed) + */ +static sal_uInt16 *AddRanges_Impl( + sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr) +{ + // Create new WhichRanges array + sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ]; + + // Take over the old Ranges + memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) ); + + // Initialize the new one to 0 + memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) ); + + // Free the old array + delete[] pUS; + + return pNew; +} + +/** + * This internal function creates a new ItemArray, which is copied from 'pItems', + * but has room for a new ItemPointer at 'nPos'. + * + * @returns the new ItemArray (the old 'pItems' is freed) + */ +static void AddItem_Impl(std::unique_ptr<SfxPoolItem const*[]> & rpItems, sal_uInt16 nOldSize, sal_uInt16 nPos) +{ + // Create new ItemArray + SfxPoolItem const** pNew = new const SfxPoolItem*[nOldSize+1]; + + // Was there one before? + if ( rpItems ) + { + // Copy all Items before nPos + if ( nPos ) + memcpy( static_cast<void*>(pNew), rpItems.get(), nPos * sizeof(SfxPoolItem *) ); + + // Copy all Items after nPos + if ( nPos < nOldSize ) + memcpy( static_cast<void*>(pNew + nPos + 1), rpItems.get() + nPos, + (nOldSize-nPos) * sizeof(SfxPoolItem *) ); + } + + // Initialize new Item + *(pNew + nPos) = nullptr; + + rpItems.reset(pNew); +} + +/** + * 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 ) +{ + sal_uInt16 nPos = 0; // Position for 'rItem' in 'm_pItems' + const sal_uInt16 nItemCount = TotalCount(); + + // Let's see first whether there's a suitable Range already + sal_uInt16 *pPtr = m_pWhichRanges; + while ( *pPtr ) + { + // WhichId is within this Range? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Insert + nPos += nWhich - *pPtr; + break; + } + + // Carry over the position of the Item in m_pItems + nPos += *(pPtr+1) - *pPtr + 1; + + // To the next Range + pPtr += 2; + } + + // WhichId not yet present? + if ( !*pPtr ) + { + // Let's see if we can attach it somewhere + pPtr = m_pWhichRanges; + nPos = 0; + while ( *pPtr ) + { + // WhichId is right before this Range? + if ( (nWhich+1) == *pPtr ) + { + // Range grows downwards + (*pPtr)--; + + // Make room before first Item of this Range + AddItem_Impl(m_pItems, nItemCount, nPos); + break; + } + + // WhichId is right after this Range? + else if ( (nWhich-1) == *(pPtr+1) ) + { + // Range grows upwards? + (*(pPtr+1))++; + + // Make room after last Item of this Range + nPos += nWhich - *pPtr; + AddItem_Impl(m_pItems, nItemCount, nPos); + break; + } + + // Carry over position of the Item in m_pItems + nPos += *(pPtr+1) - *pPtr + 1; + + // To the next Range + pPtr += 2; + } + } + + // No extensible Range found? + if ( !*pPtr ) + { + // No room left in m_pWhichRanges? => Expand! + std::ptrdiff_t nSize = pPtr - m_pWhichRanges; + if( !nFree ) + { + m_pWhichRanges = AddRanges_Impl(m_pWhichRanges, nSize, nInitCount); + nFree += nInitCount; + } + + // Attach new WhichRange + pPtr = m_pWhichRanges + nSize; + *pPtr++ = nWhich; + *pPtr = nWhich; + nFree -= 2; + + // Expand ItemArray + nPos = nItemCount; + AddItem_Impl(m_pItems, nItemCount, nPos); + } + + // Add new Item to Pool + const SfxPoolItem& rNew = m_pPool->PutImpl( rItem, nWhich, bPassingOwnership ); + + // Remember old Item + bool bIncrementCount = false; + const SfxPoolItem* pOld = m_pItems[nPos]; + if ( IsInvalidItem(pOld) ) // state "dontcare" + pOld = nullptr; + if ( !pOld ) + { + bIncrementCount = true; + pOld = m_pParent + ? &m_pParent->Get( nWhich ) + : (SfxItemPool::IsWhich(nWhich) + ? &m_pPool->GetDefaultItem(nWhich) + : nullptr); + } + + // Add new Item to ItemSet + m_pItems[nPos] = &rNew; + + // Send Changed Notification + if ( pOld ) + { + Changed( *pOld, rNew ); + if ( !IsDefaultItem(pOld) ) + m_pPool->Remove( *pOld ); + } + + if ( bIncrementCount ) + ++m_nCount; + + return &rNew; +} + +/** + * 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 != m_pPool) + { + std::unique_ptr<SfxAllItemSet> pNewSet(new SfxAllItemSet( *pToPool )); + if ( bItems ) + pNewSet->Set( *this ); + return std::unique_ptr<SfxItemSet>(pNewSet.release()); // clang3.8 does not seem to be able to upcast std::unique_ptr + } + else + return std::unique_ptr<SfxItemSet>(bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*m_pPool)); +} + +/* 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 000000000..87165ae50 --- /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 000000000..b0daa3b90 --- /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 000000000..b0750212e --- /dev/null +++ b/svl/source/items/macitem.cxx @@ -0,0 +1,238 @@ +/* -*- 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> + +SvxMacro::SvxMacro( const OUString &rMacName, const OUString &rLanguage) + : aMacName( rMacName ), 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 ) +{ + aMacroTable.Insert( nEvent, rMacro); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/poolcach.cxx b/svl/source/items/poolcach.cxx new file mode 100644 index 000000000..2d406e18c --- /dev/null +++ b/svl/source/items/poolcach.cxx @@ -0,0 +1,109 @@ +/* -*- 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/itemset.hxx> +#include <svl/poolcach.hxx> +#include <tools/debug.hxx> + +SfxItemPoolCache::SfxItemPoolCache( SfxItemPool *pItemPool, + const SfxPoolItem *pPutItem ): + pPool(pItemPool), + pSetToPut( nullptr ), + pItemToPut( &pItemPool->Put(*pPutItem) ) +{ + DBG_ASSERT(pItemPool, "No Pool provided"); +} + + +SfxItemPoolCache::SfxItemPoolCache( SfxItemPool *pItemPool, + const SfxItemSet *pPutSet ): + pPool(pItemPool), + pSetToPut( pPutSet ), + pItemToPut( nullptr ) +{ + DBG_ASSERT(pItemPool, "No Pool provided"); +} + + +SfxItemPoolCache::~SfxItemPoolCache() +{ + for (const SfxItemModifyImpl & rImpl : m_aCache) { + pPool->Remove( *rImpl.pPoolItem ); + pPool->Remove( *rImpl.pOrigItem ); + } + + if ( pItemToPut ) + pPool->Remove( *pItemToPut ); +} + + +const SfxSetItem& SfxItemPoolCache::ApplyTo( const SfxSetItem &rOrigItem ) +{ + DBG_ASSERT( pPool == rOrigItem.GetItemSet().GetPool(), "invalid Pool" ); + DBG_ASSERT( IsDefaultItem( &rOrigItem ) || IsPooledItem( &rOrigItem ), + "original not in pool" ); + + // Find whether this Transformations ever occurred + for (const SfxItemModifyImpl & rMapEntry : m_aCache) + { + if ( rMapEntry.pOrigItem == &rOrigItem ) + { + // Did anything change at all? + if ( rMapEntry.pPoolItem != &rOrigItem ) + { + rMapEntry.pPoolItem->AddRef(2); // One for the cache + pPool->Put( rOrigItem ); //FIXME: AddRef? + } + return *rMapEntry.pPoolItem; + } + } + + // Insert the new attributes in a new Set + std::unique_ptr<SfxSetItem> pNewItem(rOrigItem.Clone()); + if ( pItemToPut ) + { + pNewItem->GetItemSet().PutDirect( *pItemToPut ); + DBG_ASSERT( &pNewItem->GetItemSet().Get( pItemToPut->Which() ) == pItemToPut, + "wrong item in temporary set" ); + } + else + pNewItem->GetItemSet().Put( *pSetToPut ); + const SfxSetItem* pNewPoolItem = &pPool->Put( std::move(pNewItem) ); + + // Adapt refcount; one each for the cache + pNewPoolItem->AddRef( pNewPoolItem != &rOrigItem ? 2 : 1 ); + pPool->Put( rOrigItem ); //FIXME: AddRef? + + // Add the transformation to the cache + SfxItemModifyImpl aModify; + aModify.pOrigItem = &rOrigItem; + aModify.pPoolItem = const_cast<SfxSetItem*>(pNewPoolItem); + m_aCache.push_back( aModify ); + + DBG_ASSERT( !pItemToPut || + &pNewPoolItem->GetItemSet().Get( pItemToPut->Which() ) == pItemToPut, + "wrong item in resulting set" ); + + return *pNewPoolItem; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/poolio.cxx b/svl/source/items/poolio.cxx new file mode 100644 index 000000000..313c431e9 --- /dev/null +++ b/svl/source/items/poolio.cxx @@ -0,0 +1,96 @@ +/* -*- 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 <poolio.hxx> + +#include <sal/log.hxx> +#include <svl/itempool.hxx> + +#include <algorithm> +#include <memory> + +/// clear array of PoolItem variants +/// after all PoolItems are deleted +/// or all ref counts are decreased +void SfxPoolItemArray_Impl::clear() +{ + maPoolItemSet.clear(); + maSortablePoolItems.clear(); +} + +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; +} + + +bool SfxItemPool::CheckItemInPool(const SfxPoolItem *pItem) const +{ + DBG_ASSERT( pItem, "no 0-Pointer Surrogate" ); + DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" ); + DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" ); + + if ( !IsInRange(pItem->Which()) ) + { + if ( pImpl->mpSecondary ) + return pImpl->mpSecondary->CheckItemInPool( pItem ); + SAL_WARN( "svl.items", "unknown Which-Id - don't ask me for surrogates, with ID/pos " << pItem->Which()); + } + + // Pointer on static or pool-default attribute? + if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) ) + return true; + + SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[GetIndex_Impl(pItem->Which())]; + + for ( auto p : rItemArr ) + { + if ( p == pItem ) + return true; + } + SAL_WARN( "svl.items", "Item not in the pool, with ID/pos " << pItem->Which()); + return false; +} + +/* 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 000000000..c5e09ddf9 --- /dev/null +++ b/svl/source/items/poolitem.cxx @@ -0,0 +1,648 @@ +/* -*- 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 <libxml/xmlwriter.h> +#include <typeinfo> +#include <boost/property_tree/json_parser.hpp> + +////////////////////////////////////////////////////////////////////////////// +// 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 SvxBackgroundColorItem : public SvxColorItem +// 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 SfxAllEnumItem: 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 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 OfaRefItem : 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 SwInsText: public SwMsgPoolItem +// class SwDelChr: public SwMsgPoolItem +// class SwDelText: public SwMsgPoolItem +// class SwUpdateAttr : public SwMsgPoolItem +// class SwRefMarkFieldUpdate : public SwMsgPoolItem +// class SwDocPosUpdate : public SwMsgPoolItem +// class SwTableFormulaUpdate : public SwMsgPoolItem +// class SwAutoFormatGetDocNode: public SwMsgPoolItem +// class SwAttrSetChg: public SwMsgPoolItem +// class SwCondCollCondChg: public SwMsgPoolItem +// class SwVirtPageNumInfo: 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 +////////////////////////////////////////////////////////////////////////////// + +SfxPoolItem::SfxPoolItem(sal_uInt16 const nWhich) + : m_nRefCount(0) + , m_nWhich(nWhich) + , m_nKind(SfxItemKind::NONE) +{ + assert(nWhich <= SHRT_MAX); +} + + +SfxPoolItem::~SfxPoolItem() +{ + assert((m_nRefCount == 0 || m_nRefCount > SFX_ITEMS_MAXREF) + && "destroying item in use"); +} + + +bool SfxPoolItem::operator==( const SfxPoolItem& rCmp ) const +{ + 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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxPoolItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + 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)) + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(rText.getStr())); + 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; +} + +bool SfxPoolItem::IsVoidItem() const +{ + return false; +} + +SfxPoolItem* SfxVoidItem::CreateDefault() +{ + return new SfxVoidItem(0); +} + +SfxVoidItem::SfxVoidItem( sal_uInt16 which ): + SfxPoolItem(which) +{ +} + +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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxVoidItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterEndElement(pWriter); +} + +SfxVoidItem* SfxVoidItem::Clone(SfxItemPool *) const +{ + return new SfxVoidItem(*this); +} + +bool SfxVoidItem::IsVoidItem() const +{ + return true; +} + +void SfxPoolItem::ScaleMetrics( long /*lMult*/, 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; +} + +SfxVoidItem::~SfxVoidItem() +{ +} + +/* 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 000000000..08912f557 --- /dev/null +++ b/svl/source/items/ptitem.cxx @@ -0,0 +1,135 @@ +/* -*- 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 <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 = convertMm100ToTwip(aValue.X); + aValue.Y = convertMm100ToTwip(aValue.Y); + } + } + else + { + bRet = ( rVal >>= nVal ); + if( bConvert ) + nVal = convertMm100ToTwip( nVal ); + } + + 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 000000000..1d9d00aa5 --- /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 ), + aVal( rVal ) +{ +} + + +bool SfxRectangleItem::GetPresentation +( + SfxItemPresentation /*ePresentation*/, + MapUnit /*eCoreMetric*/, + MapUnit /*ePresentationMetric*/, + OUString& rText, + const IntlWrapper& +) const +{ + rText = OUString::number(aVal.Top()) + ", " + + OUString::number(aVal.Left()) + ", " + + OUString::number(aVal.Bottom()) + ", " + + OUString::number(aVal.Right()); + return true; +} + + +bool SfxRectangleItem::operator==( const SfxPoolItem& rItem ) const +{ + assert(SfxPoolItem::operator==(rItem)); + return static_cast<const SfxRectangleItem&>(rItem).aVal == aVal; +} + +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( aVal.getX(), + aVal.getY(), + aVal.getWidth(), + aVal.getHeight() ); + break; + } + case MID_RECT_LEFT: rVal <<= aVal.getX(); break; + case MID_RECT_RIGHT: rVal <<= aVal.getY(); break; + case MID_WIDTH: rVal <<= aVal.getWidth(); break; + case MID_HEIGHT: rVal <<= aVal.getHeight(); 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: + aVal.setX( aValue.X ); + aVal.setY( aValue.Y ); + aVal.setWidth( aValue.Width ); + aVal.setHeight( aValue.Height ); + break; + case MID_RECT_LEFT: aVal.setX( nVal ); break; + case MID_RECT_RIGHT: aVal.setY( nVal ); break; + case MID_WIDTH: aVal.setWidth( nVal ); break; + case MID_HEIGHT: aVal.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 000000000..89f7e642e --- /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 000000000..79a6aa93d --- /dev/null +++ b/svl/source/items/sitem.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <utility> + +#include <rtl/ustring.hxx> +#include <svl/itemset.hxx> +#include <svl/poolitem.hxx> +#include <tools/debug.hxx> + +SfxSetItem::SfxSetItem( sal_uInt16 which, const SfxItemSet &rSet) : + SfxPoolItem(which), + pSet(rSet.Clone()) +{ +} + + +SfxSetItem::SfxSetItem( sal_uInt16 which, std::unique_ptr<SfxItemSet> &&pS) : + SfxPoolItem(which), + pSet(std::move(pS)) +{ + DBG_ASSERT(pSet, "SfxSetItem without set constructed" ); +} + + +SfxSetItem::SfxSetItem( const SfxSetItem& rCopy, SfxItemPool *pPool ) : + SfxPoolItem(rCopy), + pSet(rCopy.pSet->Clone(true, pPool)) +{ +} + + +SfxSetItem::~SfxSetItem() +{ +} + + +bool SfxSetItem::operator==( const SfxPoolItem& rCmp) const +{ + assert(SfxPoolItem::operator==(rCmp)); + return *pSet == *static_cast<const SfxSetItem &>(rCmp).pSet; +} + + +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 000000000..54af34625 --- /dev/null +++ b/svl/source/items/slstitm.cxx @@ -0,0 +1,187 @@ +/* -*- 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>>(); + *mpList = *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>>(); + + sal_Int32 nStart = 0; + OUString aStr(convertLineEnd(rStr, LINEEND_CR)); + for (;;) + { + const sal_Int32 nDelimPos = aStr.indexOf( '\r', nStart ); + if ( nDelimPos < 0 ) + { + if (nStart<aStr.getLength()) + { + // put last string only if not empty + mpList->push_back(aStr.copy(nStart)); + } + break; + } + + mpList->push_back(aStr.copy(nStart, nDelimPos-nStart)); + + // skip both inserted string and delimiter + nStart = nDelimPos + 1 ; + } +} + + +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("\r"); + } + } + return convertLineEnd(aStr.makeStringAndClear(), GetSystemLineEnd()); +} + + +void SfxStringListItem::SetStringList( const css::uno::Sequence< OUString >& rList ) +{ + mpList = std::make_shared<std::vector<OUString>>(); + + // String belongs to the list + comphelper::sequenceToContainer(*mpList, rList); +} + +void SfxStringListItem::GetStringList( css::uno::Sequence< OUString >& rList ) const +{ + size_t nCount = mpList->size(); + + rList.realloc( nCount ); + for( size_t i=0; i < nCount; i++ ) + rList[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 +{ + // GetString() is not const!!! + SfxStringListItem* pThis = const_cast< SfxStringListItem * >( this ); + + css::uno::Sequence< OUString > aStringList; + pThis->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 000000000..4588d7a8b --- /dev/null +++ b/svl/source/items/srchitem.cxx @@ -0,0 +1,694 @@ +/* -*- 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 <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> + +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; + +#define CFG_ROOT_NODE "Office.Common/SearchOptions" + +#define SRCH_PARAMS 13 +#define SRCH_PARA_OPTIONS "Options" +#define SRCH_PARA_FAMILY "Family" +#define SRCH_PARA_COMMAND "Command" +#define SRCH_PARA_CELLTYPE "CellType" +#define SRCH_PARA_APPFLAG "AppFlag" +#define SRCH_PARA_ROWDIR "RowDirection" +#define SRCH_PARA_ALLTABLES "AllTables" +#define SRCH_PARA_SEARCHFILTERED "SearchFiltered" +#define SRCH_PARA_SEARCHFORMATTED "SearchFormatted" +#define SRCH_PARA_BACKWARD "Backward" +#define SRCH_PARA_PATTERN "Pattern" +#define SRCH_PARA_CONTENT "Content" +#define SRCH_PARA_ASIANOPT "AsianOptions" + +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 ( SearchAlgorithms_ABSOLUTE, + 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; + m_aSearchOpt.algorithmType = SearchAlgorithms_ABSOLUTE; // something valid + } + if (aOpt.IsUseRegularExpression()) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::REGEXP; + m_aSearchOpt.algorithmType = SearchAlgorithms_REGEXP; + } + if (aOpt.IsSimilaritySearch()) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::APPROXIMATE; + m_aSearchOpt.algorithmType = SearchAlgorithms_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 equalsWithoutLocale( const i18nutil::SearchOptions2& rItem1, const i18nutil::SearchOptions2& rItem2 ) +{ + return rItem1.algorithmType == rItem2.algorithmType && + 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 ( m_nCommand == rSItem.m_nCommand ) && + ( 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 ) && + ( equalsWithoutLocale(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; + m_aSearchOpt.algorithmType = SearchAlgorithms_REGEXP; + } + else if ( SearchAlgorithms2::REGEXP == m_aSearchOpt.AlgorithmType2 ) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE; + m_aSearchOpt.algorithmType = SearchAlgorithms_ABSOLUTE; + } +} + + +void SvxSearchItem::SetWildcard( bool bVal ) +{ + if ( bVal ) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::WILDCARD; + m_aSearchOpt.algorithmType = SearchAlgorithms_ABSOLUTE; // something valid + } + else if ( SearchAlgorithms2::REGEXP == m_aSearchOpt.AlgorithmType2 ) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE; + m_aSearchOpt.algorithmType = SearchAlgorithms_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; + m_aSearchOpt.algorithmType = SearchAlgorithms_APPROXIMATE; + } + else if ( SearchAlgorithms2::APPROXIMATE == m_aSearchOpt.AlgorithmType2 ) + { + m_aSearchOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE; + m_aSearchOpt.algorithmType = SearchAlgorithms_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( SRCH_PARAMS ); + aSeq[0].Name = SRCH_PARA_OPTIONS; + aSeq[0].Value <<= m_aSearchOpt.toUnoSearchOptions2(); + aSeq[1].Name = SRCH_PARA_FAMILY; + aSeq[1].Value <<= sal_Int16( m_eFamily ); + aSeq[2].Name = SRCH_PARA_COMMAND; + aSeq[2].Value <<= static_cast<sal_uInt16>(m_nCommand); + aSeq[3].Name = SRCH_PARA_CELLTYPE; + aSeq[3].Value <<= static_cast<sal_uInt16>(m_nCellType); + aSeq[4].Name = SRCH_PARA_APPFLAG; + aSeq[4].Value <<= static_cast<sal_uInt16>(m_nAppFlag); + aSeq[5].Name = SRCH_PARA_ROWDIR; + aSeq[5].Value <<= m_bRowDirection; + aSeq[6].Name = SRCH_PARA_ALLTABLES; + aSeq[6].Value <<= m_bAllTables; + aSeq[7].Name = SRCH_PARA_SEARCHFILTERED; + aSeq[7].Value <<= m_bSearchFiltered; + aSeq[8].Name = SRCH_PARA_SEARCHFORMATTED; + aSeq[8].Value <<= m_bSearchFormatted; + aSeq[9].Name = SRCH_PARA_BACKWARD; + aSeq[9].Value <<= m_bBackward; + aSeq[10].Name = SRCH_PARA_PATTERN; + aSeq[10].Value <<= m_bPattern; + aSeq[11].Name = SRCH_PARA_CONTENT; + aSeq[11].Value <<= m_bContent; + aSeq[12].Name = SRCH_PARA_ASIANOPT; + aSeq[12].Value <<= m_bAsianOptions; + 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>(m_aSearchOpt.algorithmType); 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; + bool bRet = false; + sal_Int32 nInt = 0; + switch ( nMemberId ) + { + case 0 : + { + Sequence< PropertyValue > aSeq; + if ( ( rVal >>= aSeq ) && ( aSeq.getLength() == SRCH_PARAMS ) ) + { + sal_Int16 nConvertedCount( 0 ); + for ( const auto& rProp : std::as_const(aSeq) ) + { + if ( rProp.Name == SRCH_PARA_OPTIONS ) + { + css::util::SearchOptions2 nTmpSearchOpt2; + if ( rProp.Value >>= nTmpSearchOpt2 ) + { + m_aSearchOpt = nTmpSearchOpt2; + ++nConvertedCount; + } + } + else if ( rProp.Name == SRCH_PARA_FAMILY ) + { + sal_uInt16 nTemp( 0 ); + if ( rProp.Value >>= nTemp ) + { + m_eFamily = SfxStyleFamily( nTemp ); + ++nConvertedCount; + } + } + else if ( rProp.Name == SRCH_PARA_COMMAND ) + { + sal_uInt16 nTmp; + if ( rProp.Value >>= nTmp ) + { + m_nCommand = static_cast<SvxSearchCmd>(nTmp); + ++nConvertedCount; + } + } + else if ( rProp.Name == SRCH_PARA_CELLTYPE ) + { + sal_uInt16 nTmp; + if ( rProp.Value >>= nTmp ) + { + m_nCellType = static_cast<SvxSearchCellType>(nTmp); + ++nConvertedCount; + } + } + else if ( rProp.Name == SRCH_PARA_APPFLAG ) + { + sal_uInt16 nTmp; + if ( rProp.Value >>= nTmp ) + { + m_nAppFlag = static_cast<SvxSearchApp>(nTmp); + ++nConvertedCount; + } + } + else if ( rProp.Name == SRCH_PARA_ROWDIR ) + { + if ( rProp.Value >>= m_bRowDirection ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_ALLTABLES ) + { + if ( rProp.Value >>= m_bAllTables ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_SEARCHFILTERED ) + { + if ( rProp.Value >>= m_bSearchFiltered ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_SEARCHFORMATTED ) + { + if ( rProp.Value >>= m_bSearchFormatted ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_BACKWARD ) + { + if ( rProp.Value >>= m_bBackward ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_PATTERN ) + { + if ( rProp.Value >>= m_bPattern ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_CONTENT ) + { + if ( rProp.Value >>= m_bContent ) + ++nConvertedCount; + } + else if ( rProp.Name == SRCH_PARA_ASIANOPT ) + { + if ( rProp.Value >>= m_bAsianOptions ) + ++nConvertedCount; + } + } + + bRet = ( nConvertedCount == SRCH_PARAMS ); + } + break; + } + case MID_SEARCH_COMMAND: + bRet = (rVal >>= nInt); m_nCommand = static_cast<SvxSearchCmd>(nInt); break; + case MID_SEARCH_STYLEFAMILY: + bRet = (rVal >>= nInt); m_eFamily = static_cast<SfxStyleFamily>(static_cast<sal_Int16>(nInt)); break; + case MID_SEARCH_CELLTYPE: + bRet = (rVal >>= nInt); m_nCellType = static_cast<SvxSearchCellType>(nInt); break; + case MID_SEARCH_ROWDIRECTION: + bRet = (rVal >>= m_bRowDirection); break; + case MID_SEARCH_ALLTABLES: + bRet = (rVal >>= m_bAllTables); break; + case MID_SEARCH_SEARCHFILTERED: + bRet = (rVal >>= m_bSearchFiltered); break; + case MID_SEARCH_SEARCHFORMATTED: + bRet = (rVal >>= m_bSearchFormatted); break; + case MID_SEARCH_BACKWARD: + bRet = (rVal >>= m_bBackward); break; + case MID_SEARCH_PATTERN: + bRet = (rVal >>= m_bPattern); break; + case MID_SEARCH_CONTENT: + bRet = (rVal >>= m_bContent); break; + case MID_SEARCH_ASIANOPTIONS: + bRet = (rVal >>= m_bAsianOptions); break; + case MID_SEARCH_ALGORITHMTYPE: + bRet = (rVal >>= nInt); m_aSearchOpt.algorithmType = static_cast<SearchAlgorithms>(static_cast<sal_Int16>(nInt)); break; + case MID_SEARCH_ALGORITHMTYPE2: + bRet = (rVal >>= nInt); m_aSearchOpt.AlgorithmType2 = static_cast<sal_Int16>(nInt); break; + case MID_SEARCH_FLAGS: + bRet = (rVal >>= m_aSearchOpt.searchFlag); break; + case MID_SEARCH_SEARCHSTRING: + bRet = (rVal >>= m_aSearchOpt.searchString); break; + case MID_SEARCH_REPLACESTRING: + bRet = (rVal >>= m_aSearchOpt.replaceString); break; + case MID_SEARCH_CHANGEDCHARS: + bRet = (rVal >>= m_aSearchOpt.changedChars); break; + case MID_SEARCH_DELETEDCHARS: + bRet = (rVal >>= m_aSearchOpt.deletedChars); break; + case MID_SEARCH_INSERTEDCHARS: + bRet = (rVal >>= m_aSearchOpt.insertedChars); break; + case MID_SEARCH_TRANSLITERATEFLAGS: + { + bRet = (rVal >>= nInt); + if (bRet) + m_aSearchOpt.transliterateFlags = static_cast<TransliterationFlags>(nInt); + break; + } + case MID_SEARCH_LOCALE: + { + bRet = (rVal >>= nInt); + if ( bRet ) + { + if ( LanguageType(nInt) == LANGUAGE_NONE ) + { + m_aSearchOpt.Locale = css::lang::Locale(); + } + else + { + m_aSearchOpt.Locale = LanguageTag::convertToLocale( LanguageType(nInt) ); + } + } + break; + } + case MID_SEARCH_STARTPOINTX: + { + bRet = (rVal >>= m_nStartPointX); + break; + } + case MID_SEARCH_STARTPOINTY: + { + bRet = (rVal >>= m_nStartPointY); + break; + } + default: + OSL_FAIL( "Unknown MemberId" ); + } + + return bRet; +} + +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 000000000..98b1cb707 --- /dev/null +++ b/svl/source/items/stringio.cxx @@ -0,0 +1,35 @@ +/* -*- 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, const OUString& 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 000000000..86e2087cd --- /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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SfxStringItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(GetValue().toUtf8().getStr())); + 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 000000000..db0ee8d42 --- /dev/null +++ b/svl/source/items/style.cxx @@ -0,0 +1,943 @@ +/* -*- 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 <string.h> + +#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 +( + const OUString& rOldName, + SfxStyleSheetBase& rStyleSheet // Remains with the caller +) +: SfxStyleSheetHint( SfxHintId::StyleSheetModified, rStyleSheet ), + aName( rOldName ) +{} + + +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 ) + , aParent() + , aFollow( rName ) + , pSet( nullptr ) + , nMask(mask) + , nHelpId( 0 ) + , bMySet( false ) + , bHidden( false ) +{ +#ifdef DBG_UTIL + aDbgStyleSheetReferences.mnStyles++; +#endif +} + +SfxStyleSheetBase::SfxStyleSheetBase( const SfxStyleSheetBase& r ) + : comphelper::OWeakTypeObject(r) + , 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::unique_ptr<SfxItemSet> SfxStyleSheetBase::GetItemSetForPreview() +{ + return std::make_unique<SfxItemSet>(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(SfxStyleSheetBasePool *pBase, + SfxStyleFamily eFam, SfxStyleSearchBits n) + : pCurrentStyle(nullptr) + , nCurrentPosition(0) +{ + pBasePool=pBase; + 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_uInt16 SfxStyleSheetIterator::Count() +{ + sal_uInt16 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_uInt16 nIdx) +{ + SfxStyleSheetBase* retval = nullptr; + if( IsTrivialSearch()) + { + retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(nIdx); + nCurrentPosition = nIdx; + } + else if(nMask == SfxStyleSearchBits::All) + { + rtl::Reference< SfxStyleSheetBase > ref = + pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition( + pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetPositionsByFamily(nSearchFamily).at(nIdx)) + ; + retval = ref.get(); + nCurrentPosition = nIdx; + } + else + { + DoesStyleMatchStyleSheetPredicate predicate(this); + rtl::Reference< SfxStyleSheetBase > ref = + pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(nIdx, predicate); + if (ref.get() != nullptr) + { + nCurrentPosition = 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() ) + { + unsigned nStyleSheets = pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheets(); + unsigned newPosition = nCurrentPosition +1; + if (nStyleSheets > newPosition) + { + nCurrentPosition = newPosition; + retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(nCurrentPosition); + } + } + else if(nMask == SfxStyleSearchBits::All) + { + unsigned newPosition = nCurrentPosition +1; + const std::vector<unsigned>& familyVector = + pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetPositionsByFamily(nSearchFamily); + if (familyVector.size() > newPosition) + { + nCurrentPosition = newPosition; + unsigned stylePosition = familyVector[newPosition]; + retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(stylePosition); + } + } + else + { + DoesStyleMatchStyleSheetPredicate predicate(this); + rtl::Reference< SfxStyleSheetBase > ref = + pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate( + 0, predicate, nCurrentPosition+1); + retval = ref.get(); + if (retval != nullptr) { + nCurrentPosition = pBasePool->pImpl->mxIndexedStyleSheets->FindStyleSheetPosition(*ref); + } + } + pCurrentStyle = retval; + return retval; +} + +SfxStyleSheetBase* SfxStyleSheetIterator::Find(const OUString& rStr) +{ + DoesStyleMatchStyleSheetPredicate predicate(this); + + std::vector<unsigned> positions = + pBasePool->pImpl->mxIndexedStyleSheets->FindPositionsByNameAndPredicate(rStr, predicate, + svl::IndexedStyleSheets::SearchBehavior::ReturnFirst); + if (positions.empty()) { + return nullptr; + } + + unsigned pos = positions.front(); + SfxStyleSheetBase* pStyle = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(pos); + nCurrentPosition = 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 ), + comphelper::OWeakTypeObject(r), + 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(); +} + +bool SfxStyleSheetBasePool::SetParent(SfxStyleFamily eFam, const OUString& rStyle, const OUString& rParent) +{ + SfxStyleSheetIterator aIter(this, eFam, SfxStyleSearchBits::All); + SfxStyleSheetBase *pStyle = aIter.Find(rStyle); + OSL_ENSURE(pStyle, "Template not found. Writer with solar <2541?"); + if(pStyle) + return pStyle->SetParent(rParent); + else + return false; +} + +std::unique_ptr<SfxStyleSheetIterator> SfxStyleSheetBasePool::CreateIterator +( + SfxStyleFamily eFam, + SfxStyleSearchBits mask +) +{ + return std::make_unique<SfxStyleSheetIterator>(this,eFam,mask); +} + +SfxStyleSheetBase* SfxStyleSheetBasePool::Create +( + const OUString& rName, + SfxStyleFamily eFam, + SfxStyleSearchBits mask +) +{ + return new SfxStyleSheetBase( rName, this, eFam, mask ); +} + +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( static_cast< ::cppu::OWeakObject* >((*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(const OUString& 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 ) ) +{ +} + +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, css::lang::XUnoTunnel>(_rName, _rPool, _eFamily, _nMask) +{ +} + +SfxUnoStyleSheet* SfxUnoStyleSheet::getUnoStyleSheet( const css::uno::Reference< css::style::XStyle >& xStyle ) +{ + SfxUnoStyleSheet* pRet = dynamic_cast< SfxUnoStyleSheet* >( xStyle.get() ); + if( !pRet ) + pRet = comphelper::getUnoTunnelImplementation<SfxUnoStyleSheet>(xStyle); + return pRet; +} + +/** + * XUnoTunnel + */ +::sal_Int64 SAL_CALL SfxUnoStyleSheet::getSomething( const css::uno::Sequence< ::sal_Int8 >& rId ) +{ + if( isUnoTunnelId<SfxUnoStyleSheet>(rId) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this)); + } + + return 0; +} + +void +SfxStyleSheetBasePool::StoreStyleSheet(const rtl::Reference< SfxStyleSheetBase >& xStyle) +{ + pImpl->mxIndexedStyleSheets->AddStyleSheet(xStyle); +} + +namespace +{ + class theSfxUnoStyleSheetIdentifier : public rtl::Static< UnoTunnelIdInit, theSfxUnoStyleSheetIdentifier > {}; +} + +const css::uno::Sequence< ::sal_Int8 >& SfxUnoStyleSheet::getUnoTunnelId() +{ + return theSfxUnoStyleSheetIdentifier::get().getSeq(); +} + +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 000000000..ea3efeaeb --- /dev/null +++ b/svl/source/items/stylepool.cxx @@ -0,0 +1,471 @@ +/* -*- 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 <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 + : mChildren(), + maItemSet(), + mpUpper( nullptr ), + mbIsItemIgnorable( false ) + {} + Node( const SfxPoolItem& rItem, Node* pParent, const bool bIgnorable ) // child node Ctor + : mChildren(), + maItemSet(), + 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::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 ) + : maRoot(), +#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 bNonPoolable = 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::unique_ptr<SfxItemSet> xFoundIgnorableItems; + if ( mpIgnorableItems ) + { + xFoundIgnorableItems.reset( new SfxItemSet( *mpIgnorableItems ) ); + } + while( pItem ) + { + if( !rSet.GetPool()->IsItemPoolable(pItem->Which() ) ) + bNonPoolable = 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()->IsItemPoolable(pItem->Which() ) ) + bNonPoolable = 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 ); + bNonPoolable = 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( bNonPoolable ) + 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 000000000..2ba61a517 --- /dev/null +++ b/svl/source/items/visitem.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 <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 ? OUStringLiteral("TRUE") : OUStringLiteral("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/whiter.cxx b/svl/source/items/whiter.cxx new file mode 100644 index 000000000..88b487b02 --- /dev/null +++ b/svl/source/items/whiter.cxx @@ -0,0 +1,53 @@ +/* -*- 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/whiter.hxx> +#include <svl/itemset.hxx> + +SfxWhichIter::SfxWhichIter( const SfxItemSet& rSet ): + pStart(rSet.GetRanges()), + pRanges(pStart), + nOffset(0) +{ +} + +sal_uInt16 SfxWhichIter::NextWhich() +{ + if ( 0 == pRanges[0] ) + return 0; + + const sal_uInt16 nLastWhich = pRanges[0] + nOffset; + ++nOffset; + if (pRanges[1] == nLastWhich) + { + pRanges += 2; + nOffset = 0; + } + return pRanges[0] + nOffset; +} + +sal_uInt16 SfxWhichIter::FirstWhich() +{ + pRanges = pStart; + nOffset = 0; + return pRanges[0]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |