summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/unoobj/nameuno.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/unoobj/nameuno.cxx')
-rw-r--r--sc/source/ui/unoobj/nameuno.cxx1147
1 files changed, 1147 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx
new file mode 100644
index 0000000000..6a43a4c05f
--- /dev/null
+++ b/sc/source/ui/unoobj/nameuno.cxx
@@ -0,0 +1,1147 @@
+/* -*- 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 <o3tl/safeint.hxx>
+#include <svl/hint.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/sheet/NamedRangeFlag.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/charclass.hxx>
+
+#include <nameuno.hxx>
+#include <miscuno.hxx>
+#include <cellsuno.hxx>
+#include <convuno.hxx>
+#include <targuno.hxx>
+#include <tokenuno.hxx>
+#include <tokenarray.hxx>
+#include <docsh.hxx>
+#include <docfunc.hxx>
+#include <rangenam.hxx>
+#include <unonames.hxx>
+
+#include <scui_def.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+static std::span<const SfxItemPropertyMapEntry> lcl_GetNamedRangeMap()
+{
+ static const SfxItemPropertyMapEntry aNamedRangeMap_Impl[] =
+ {
+ { SC_UNO_LINKDISPBIT, 0, cppu::UnoType<awt::XBitmap>::get(), beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNO_LINKDISPNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TOKENINDEX, 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ISSHAREDFMLA, 0, cppu::UnoType<bool>::get(), 0, 0 },
+ };
+ return aNamedRangeMap_Impl;
+}
+
+static std::span<const SfxItemPropertyMapEntry> lcl_GetNamedRangesMap()
+{
+ static const SfxItemPropertyMapEntry aNamedRangesMap_Impl[] =
+ {
+ { SC_UNO_MODIFY_BROADCAST, 0, cppu::UnoType<bool>::get(), 0, 0 },
+ };
+ return aNamedRangesMap_Impl;
+}
+
+constexpr OUString SCNAMEDRANGEOBJ_SERVICE = u"com.sun.star.sheet.NamedRange"_ustr;
+
+SC_SIMPLE_SERVICE_INFO( ScLabelRangeObj, "ScLabelRangeObj", "com.sun.star.sheet.LabelRange" )
+SC_SIMPLE_SERVICE_INFO( ScLabelRangesObj, "ScLabelRangesObj", "com.sun.star.sheet.LabelRanges" )
+SC_SIMPLE_SERVICE_INFO( ScNamedRangesObj, "ScNamedRangesObj", "com.sun.star.sheet.NamedRanges" )
+
+// Database named ranges are not considered by getCount, hasByName, removeByName and getElementNames
+// Note that hidden named ranges are considered by these methods
+static bool lcl_UserVisibleName(const ScRangeData& rData)
+{
+ //! as method to ScRangeData
+ return !rData.HasType(ScRangeData::Type::Database);
+}
+
+ScNamedRangeObj::ScNamedRangeObj( rtl::Reference< ScNamedRangesObj > xParent, ScDocShell* pDocSh, OUString aNm, Reference<container::XNamed> const & xSheet):
+ mxParent(std::move(xParent)),
+ pDocShell( pDocSh ),
+ aName(std::move( aNm )),
+ mxSheet( xSheet )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScNamedRangeObj::~ScNamedRangeObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScNamedRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ // reference update is of no interest
+
+ if ( rHint.GetId() == SfxHintId::Dying )
+ pDocShell = nullptr; // became invalid
+}
+
+// Helper functions
+
+ScRangeData* ScNamedRangeObj::GetRangeData_Impl()
+{
+ ScRangeData* pRet = nullptr;
+ if (pDocShell)
+ {
+ ScRangeName* pNames;
+ SCTAB nTab = GetTab_Impl();
+ if (nTab >= 0)
+ pNames = pDocShell->GetDocument().GetRangeName(nTab);
+ else
+ pNames = pDocShell->GetDocument().GetRangeName();
+ if (pNames)
+ {
+ pRet = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
+ if (pRet)
+ pRet->ValidateTabRefs(); // adjust relative tab refs to valid tables
+ }
+ }
+ return pRet;
+}
+
+SCTAB ScNamedRangeObj::GetTab_Impl()
+{
+ if (mxSheet.is())
+ {
+ if (!pDocShell)
+ return -2;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ SCTAB nTab;
+ OUString sName = mxSheet->getName();
+ bool bFound = rDoc.GetTable(sName, nTab);
+ assert(bFound); (void)bFound; // fouled up?
+ return nTab;
+ }
+ else
+ return -1;//global range name
+}
+
+// sheet::XNamedRange
+
+void ScNamedRangeObj::Modify_Impl( const OUString* pNewName, const ScTokenArray* pNewTokens, const OUString* pNewContent,
+ const ScAddress* pNewPos, const ScRangeData::Type* pNewType,
+ const formula::FormulaGrammar::Grammar eGrammar )
+{
+ if (!pDocShell)
+ return;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangeName* pNames;
+ SCTAB nTab = GetTab_Impl();
+ if (nTab >= 0)
+ pNames = rDoc.GetRangeName(nTab);
+ else
+ pNames = rDoc.GetRangeName();
+ if (!pNames)
+ return;
+
+ const ScRangeData* pOld = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
+ if (!pOld)
+ return;
+
+ std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName(*pNames));
+
+ OUString aInsName = pOld->GetName();
+ if (pNewName)
+ aInsName = *pNewName;
+
+ // Content string based => no problems with changed positions and such.
+ OUString aContent = pOld->GetSymbol(eGrammar);
+ if (pNewContent)
+ aContent = *pNewContent;
+
+ ScAddress aPos = pOld->GetPos();
+ if (pNewPos)
+ aPos = *pNewPos;
+
+ ScRangeData::Type nType = pOld->GetType();
+ if (pNewType)
+ nType = *pNewType;
+
+ ScRangeData* pNew = nullptr;
+ if (pNewTokens)
+ pNew = new ScRangeData( rDoc, aInsName, *pNewTokens, aPos, nType );
+ else
+ pNew = new ScRangeData( rDoc, aInsName, aContent, aPos, nType, eGrammar );
+
+ pNew->SetIndex( pOld->GetIndex() );
+
+ pNewRanges->erase(*pOld);
+ if (pNewRanges->insert(pNew))
+ {
+ pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mxParent->IsModifyAndBroadcast(), nTab);
+
+ aName = aInsName; //! broadcast?
+ }
+ else
+ {
+ pNew = nullptr; //! uno::Exception/Error or something
+ }
+}
+
+OUString SAL_CALL ScNamedRangeObj::getName()
+{
+ SolarMutexGuard aGuard;
+ return aName;
+}
+
+void SAL_CALL ScNamedRangeObj::setName( const OUString& aNewName )
+{
+ SolarMutexGuard aGuard;
+ //! adapt formulas ?????
+
+ OUString aNewStr(aNewName);
+ // GRAM_API for API compatibility.
+ Modify_Impl( &aNewStr, nullptr, nullptr, nullptr, nullptr,formula::FormulaGrammar::GRAM_API );
+
+ if ( aName != aNewStr ) // some error occurred...
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+OUString SAL_CALL ScNamedRangeObj::getContent()
+{
+ SolarMutexGuard aGuard;
+ OUString aContent;
+ ScRangeData* pData = GetRangeData_Impl();
+ if (pData)
+ // GRAM_API for API compatibility.
+ aContent = pData->GetSymbol(formula::FormulaGrammar::GRAM_API);
+ return aContent;
+}
+
+void SAL_CALL ScNamedRangeObj::setContent( const OUString& aContent )
+{
+ SolarMutexGuard aGuard;
+ OUString aContStr(aContent);
+ // GRAM_API for API compatibility.
+ Modify_Impl( nullptr, nullptr, &aContStr, nullptr, nullptr,formula::FormulaGrammar::GRAM_API );
+}
+
+table::CellAddress SAL_CALL ScNamedRangeObj::getReferencePosition()
+{
+ SolarMutexGuard aGuard;
+ ScAddress aPos;
+ ScRangeData* pData = GetRangeData_Impl();
+ if (pData)
+ aPos = pData->GetPos();
+ table::CellAddress aAddress;
+ aAddress.Column = aPos.Col();
+ aAddress.Row = aPos.Row();
+ aAddress.Sheet = aPos.Tab();
+ if (pDocShell)
+ {
+ SCTAB nDocTabs = pDocShell->GetDocument().GetTableCount();
+ if ( aAddress.Sheet >= nDocTabs && nDocTabs > 0 )
+ {
+ // Even after ValidateTabRefs, the position can be invalid if
+ // the content points to preceding tables. The resulting string
+ // is invalid in any case, so the position is just shifted.
+ aAddress.Sheet = nDocTabs - 1;
+ }
+ }
+ return aAddress;
+}
+
+void SAL_CALL ScNamedRangeObj::setReferencePosition( const table::CellAddress& aReferencePosition )
+{
+ SolarMutexGuard aGuard;
+ ScAddress aPos( static_cast<SCCOL>(aReferencePosition.Column), static_cast<SCROW>(aReferencePosition.Row), aReferencePosition.Sheet );
+ // GRAM_API for API compatibility.
+ Modify_Impl( nullptr, nullptr, nullptr, &aPos, nullptr,formula::FormulaGrammar::GRAM_API );
+}
+
+sal_Int32 SAL_CALL ScNamedRangeObj::getType()
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nType=0;
+ ScRangeData* pData = GetRangeData_Impl();
+ if (pData)
+ {
+ // do not return internal ScRangeData::Type flags
+ if ( pData->HasType(ScRangeData::Type::Criteria) ) nType |= sheet::NamedRangeFlag::FILTER_CRITERIA;
+ if ( pData->HasType(ScRangeData::Type::PrintArea) ) nType |= sheet::NamedRangeFlag::PRINT_AREA;
+ if ( pData->HasType(ScRangeData::Type::ColHeader) ) nType |= sheet::NamedRangeFlag::COLUMN_HEADER;
+ if ( pData->HasType(ScRangeData::Type::RowHeader) ) nType |= sheet::NamedRangeFlag::ROW_HEADER;
+ if ( pData->HasType(ScRangeData::Type::Hidden) ) nType |= sheet::NamedRangeFlag::HIDDEN;
+ }
+ return nType;
+}
+
+void SAL_CALL ScNamedRangeObj::setType( sal_Int32 nUnoType )
+{
+ SolarMutexGuard aGuard;
+ ScRangeData::Type nNewType = ScRangeData::Type::Name;
+ if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria;
+ if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea;
+ if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader;
+ if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader;
+ if ( nUnoType & sheet::NamedRangeFlag::HIDDEN ) nNewType |= ScRangeData::Type::Hidden;
+
+ // GRAM_API for API compatibility.
+ Modify_Impl( nullptr, nullptr, nullptr, nullptr, &nNewType,formula::FormulaGrammar::GRAM_API );
+}
+
+// XFormulaTokens
+
+uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens()
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence<sheet::FormulaToken> aSequence;
+ ScRangeData* pData = GetRangeData_Impl();
+ if (pData && pDocShell)
+ {
+ ScTokenArray* pTokenArray = pData->GetCode();
+ if ( pTokenArray )
+ ScTokenConversion::ConvertToTokenSequence( pDocShell->GetDocument(), aSequence, *pTokenArray );
+ }
+ return aSequence;
+}
+
+void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
+{
+ SolarMutexGuard aGuard;
+ if( pDocShell )
+ {
+ ScTokenArray aTokenArray(pDocShell->GetDocument());
+ (void)ScTokenConversion::ConvertToTokenArray( pDocShell->GetDocument(), aTokenArray, rTokens );
+ // GRAM_API for API compatibility.
+ Modify_Impl( nullptr, &aTokenArray, nullptr, nullptr, nullptr, formula::FormulaGrammar::GRAM_API );
+ }
+}
+
+// XCellRangeSource
+
+uno::Reference<table::XCellRange> SAL_CALL ScNamedRangeObj::getReferredCells()
+{
+ SolarMutexGuard aGuard;
+ ScRange aRange;
+ ScRangeData* pData = GetRangeData_Impl();
+ if ( pData && pData->IsValidReference( aRange ) )
+ {
+ //! static function to create ScCellObj/ScCellRangeObj at ScCellRangeObj ???
+
+ if ( aRange.aStart == aRange.aEnd )
+ return new ScCellObj( pDocShell, aRange.aStart );
+ else
+ return new ScCellRangeObj( pDocShell, aRange );
+ }
+ return nullptr;
+}
+
+// beans::XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangeObj::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetNamedRangeMap() ));
+ return aRef;
+}
+
+void SAL_CALL ScNamedRangeObj::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& /*aValue*/ )
+{
+ if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
+ {
+ // Ignore this.
+ }
+}
+
+uno::Any SAL_CALL ScNamedRangeObj::getPropertyValue( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if ( rPropertyName == SC_UNO_LINKDISPBIT )
+ {
+ // no target bitmaps for individual entries (would be all equal)
+ // ScLinkTargetTypeObj::SetLinkTargetBitmap( aRet, SC_LINKTARGETTYPE_RANGENAME );
+ }
+ else if ( rPropertyName == SC_UNO_LINKDISPNAME )
+ aRet <<= aName;
+ else if ( rPropertyName == SC_UNONAME_TOKENINDEX )
+ {
+ // get index for use in formula tokens (read-only)
+ ScRangeData* pData = GetRangeData_Impl();
+ if (pData)
+ aRet <<= static_cast<sal_Int32>(pData->GetIndex());
+ }
+ else if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
+ {
+ if (GetRangeData_Impl())
+ aRet <<= false;
+ }
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScNamedRangeObj )
+
+// lang::XServiceInfo
+
+OUString SAL_CALL ScNamedRangeObj::getImplementationName()
+{
+ return "ScNamedRangeObj";
+}
+
+sal_Bool SAL_CALL ScNamedRangeObj::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ScNamedRangeObj::getSupportedServiceNames()
+{
+ return {SCNAMEDRANGEOBJ_SERVICE, SCLINKTARGET_SERVICE};
+}
+
+ScNamedRangesObj::ScNamedRangesObj(ScDocShell* pDocSh) :
+ mbModifyAndBroadcast(true),
+ pDocShell( pDocSh )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScNamedRangesObj::~ScNamedRangesObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScNamedRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ // reference update is of no interest
+
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ pDocShell = nullptr; // became invalid
+ }
+}
+
+// sheet::XNamedRanges
+
+void SAL_CALL ScNamedRangesObj::addNewByName( const OUString& aName,
+ const OUString& aContent, const table::CellAddress& aPosition,
+ sal_Int32 nUnoType )
+{
+ SolarMutexGuard aGuard;
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), aPosition.Sheet );
+
+ ScRangeData::Type nNewType = ScRangeData::Type::Name;
+ if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria;
+ if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea;
+ if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader;
+ if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader;
+ if ( nUnoType & sheet::NamedRangeFlag::HIDDEN ) nNewType |= ScRangeData::Type::Hidden;
+
+ bool bDone = false;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ // tdf#119457 - check for a valid range name and cell reference
+ switch (ScRangeData::IsNameValid(aName, rDoc))
+ {
+ case ScRangeData::IsNameValidType::NAME_INVALID_CELL_REF:
+ throw uno::RuntimeException(
+ "Invalid name. Reference to a cell, or a range of cells not allowed",
+ getXWeak());
+ break;
+ case ScRangeData::IsNameValidType::NAME_INVALID_BAD_STRING:
+ throw uno::RuntimeException(
+ "Invalid name. Start with a letter, use only letters, numbers and underscore",
+ getXWeak());
+ break;
+ case ScRangeData::IsNameValidType::NAME_VALID:
+ if (ScRangeName* pNames = GetRangeName_Impl();
+ pNames
+ && !pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName)))
+ {
+ std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName( *pNames ));
+ // GRAM_API for API compatibility.
+ ScRangeData* pNew = new ScRangeData( rDoc, aName, aContent,
+ aPos, nNewType,formula::FormulaGrammar::GRAM_API );
+ if ( pNewRanges->insert(pNew) )
+ {
+ pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mbModifyAndBroadcast, GetTab_Impl());
+ bDone = true;
+ }
+ else
+ {
+ pNew = nullptr;
+ }
+ }
+ }
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+void SAL_CALL ScNamedRangesObj::addNewFromTitles( const table::CellRangeAddress& aSource,
+ sheet::Border aBorder )
+{
+ SolarMutexGuard aGuard;
+ //! this cannot be an enum, because multiple bits can be set !!!
+
+ bool bTop = ( aBorder == sheet::Border_TOP );
+ bool bLeft = ( aBorder == sheet::Border_LEFT );
+ bool bBottom = ( aBorder == sheet::Border_BOTTOM );
+ bool bRight = ( aBorder == sheet::Border_RIGHT );
+
+ ScRange aRange;
+ ScUnoConversion::FillScRange( aRange, aSource );
+
+ CreateNameFlags nFlags = CreateNameFlags::NONE;
+ if (bTop) nFlags |= CreateNameFlags::Top;
+ if (bLeft) nFlags |= CreateNameFlags::Left;
+ if (bBottom) nFlags |= CreateNameFlags::Bottom;
+ if (bRight) nFlags |= CreateNameFlags::Right;
+
+ if (nFlags != CreateNameFlags::NONE)
+ pDocShell->GetDocFunc().CreateNames( aRange, nFlags, true, GetTab_Impl() );
+}
+
+void SAL_CALL ScNamedRangesObj::removeByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ if (pDocShell)
+ {
+ ScRangeName* pNames = GetRangeName_Impl();
+ if (pNames)
+ {
+ const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
+ if (pData && lcl_UserVisibleName(*pData))
+ {
+ std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName(*pNames));
+ pNewRanges->erase(*pData);
+ pDocShell->GetDocFunc().SetNewRangeNames( std::move(pNewRanges), mbModifyAndBroadcast, GetTab_Impl());
+ bDone = true;
+ }
+ }
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+void SAL_CALL ScNamedRangesObj::outputList( const table::CellAddress& aOutputPosition )
+{
+ SolarMutexGuard aGuard;
+ ScAddress aPos( static_cast<SCCOL>(aOutputPosition.Column), static_cast<SCROW>(aOutputPosition.Row), aOutputPosition.Sheet );
+ if (pDocShell)
+ pDocShell->GetDocFunc().InsertNameList( aPos, true );
+}
+
+// container::XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScNamedRangesObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return new ScIndexEnumeration(this, "com.sun.star.sheet.NamedRangesEnumeration");
+}
+
+// container::XIndexAccess
+
+sal_Int32 SAL_CALL ScNamedRangesObj::getCount()
+{
+ SolarMutexGuard aGuard;
+ tools::Long nRet = 0;
+ if (pDocShell)
+ {
+ ScRangeName* pNames = GetRangeName_Impl();
+ if (pNames)
+ {
+ for (const auto& rName : *pNames)
+ if (lcl_UserVisibleName(*rName.second))
+ ++nRet;
+ }
+ }
+ return nRet;
+}
+
+uno::Any SAL_CALL ScNamedRangesObj::getByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< sheet::XNamedRange > xRange(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
+ if ( !xRange.is() )
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any(xRange);
+}
+
+uno::Type SAL_CALL ScNamedRangesObj::getElementType()
+{
+ return cppu::UnoType<sheet::XNamedRange>::get(); // must be suitable for getByIndex
+}
+
+sal_Bool SAL_CALL ScNamedRangesObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return ( getCount() != 0 );
+}
+
+Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangesObj::getPropertySetInfo()
+{
+ static Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo(lcl_GetNamedRangesMap()));
+ return aRef;
+}
+
+void SAL_CALL ScNamedRangesObj::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& aValue )
+{
+ if ( rPropertyName == SC_UNO_MODIFY_BROADCAST )
+ {
+ aValue >>= mbModifyAndBroadcast;
+ }
+}
+
+Any SAL_CALL ScNamedRangesObj::getPropertyValue( const OUString& rPropertyName )
+{
+ Any aRet;
+ if ( rPropertyName == SC_UNO_MODIFY_BROADCAST )
+ {
+ aRet <<= mbModifyAndBroadcast;
+ }
+
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScNamedRangesObj )
+
+uno::Any SAL_CALL ScNamedRangesObj::getByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< sheet::XNamedRange > xRange(GetObjectByName_Impl(aName));
+ if ( !xRange.is() )
+ throw container::NoSuchElementException();
+
+ return uno::Any(xRange);
+}
+
+uno::Sequence<OUString> SAL_CALL ScNamedRangesObj::getElementNames()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScRangeName* pNames = GetRangeName_Impl();
+ if (pNames)
+ {
+ tools::Long nVisCount = getCount(); // names with lcl_UserVisibleName
+ uno::Sequence<OUString> aSeq(nVisCount);
+ OUString* pAry = aSeq.getArray();
+ sal_uInt16 nVisPos = 0;
+ for (const auto& rName : *pNames)
+ {
+ if (lcl_UserVisibleName(*rName.second))
+ pAry[nVisPos++] = rName.second->GetName();
+ }
+ return aSeq;
+ }
+ }
+ return {};
+}
+
+sal_Bool SAL_CALL ScNamedRangesObj::hasByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScRangeName* pNames = GetRangeName_Impl();
+ if (pNames)
+ {
+ const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
+ if (pData && lcl_UserVisibleName(*pData))
+ return true;
+ }
+ }
+ return false;
+}
+
+/** called from the XActionLockable interface methods on initial locking */
+void ScNamedRangesObj::lock()
+{
+ pDocShell->GetDocument().PreprocessRangeNameUpdate();
+}
+
+/** called from the XActionLockable interface methods on final unlock */
+void ScNamedRangesObj::unlock()
+{
+ pDocShell->GetDocument().CompileHybridFormula();
+}
+
+// document::XActionLockable
+
+sal_Bool ScNamedRangesObj::isActionLocked()
+{
+ SolarMutexGuard aGuard;
+ return pDocShell->GetDocument().GetNamedRangesLockCount() != 0;
+}
+
+void ScNamedRangesObj::addActionLock()
+{
+ SolarMutexGuard aGuard;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
+ ++nLockCount;
+ if ( nLockCount == 1 )
+ {
+ lock();
+ }
+ rDoc.SetNamedRangesLockCount( nLockCount );
+}
+
+void ScNamedRangesObj::removeActionLock()
+{
+ SolarMutexGuard aGuard;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
+ if ( nLockCount > 0 )
+ {
+ --nLockCount;
+ if ( nLockCount == 0 )
+ {
+ unlock();
+ }
+ rDoc.SetNamedRangesLockCount( nLockCount );
+ }
+}
+
+void ScNamedRangesObj::setActionLocks( sal_Int16 nLock )
+{
+ SolarMutexGuard aGuard;
+ if ( nLock < 0 )
+ return;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
+ if ( nLock == 0 && nLockCount > 0 )
+ {
+ unlock();
+ }
+ if ( nLock > 0 && nLockCount == 0 )
+ {
+ lock();
+ }
+ rDoc.SetNamedRangesLockCount( nLock );
+}
+
+sal_Int16 ScNamedRangesObj::resetActionLocks()
+{
+ SolarMutexGuard aGuard;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
+ if ( nLockCount > 0 )
+ {
+ unlock();
+ }
+ rDoc.SetNamedRangesLockCount( 0 );
+ return nLockCount;
+}
+
+ScGlobalNamedRangesObj::ScGlobalNamedRangesObj(ScDocShell* pDocSh)
+ : ScNamedRangesObj(pDocSh)
+{
+
+}
+
+ScGlobalNamedRangesObj::~ScGlobalNamedRangesObj()
+{
+
+}
+
+rtl::Reference<ScNamedRangeObj> ScGlobalNamedRangesObj::GetObjectByIndex_Impl(sal_uInt16 nIndex)
+{
+ if (!pDocShell)
+ return nullptr;
+
+ ScRangeName* pNames = pDocShell->GetDocument().GetRangeName();
+ if (!pNames)
+ return nullptr;
+
+ sal_uInt16 nPos = 0;
+ for (const auto& rName : *pNames)
+ {
+ if (lcl_UserVisibleName(*rName.second))
+ {
+ if (nPos == nIndex)
+ return new ScNamedRangeObj(this, pDocShell, rName.second->GetName());
+ }
+ ++nPos;
+ }
+ return nullptr;
+}
+
+rtl::Reference<ScNamedRangeObj> ScGlobalNamedRangesObj::GetObjectByName_Impl(const OUString& aName)
+{
+ if ( pDocShell && hasByName(aName) )
+ return new ScNamedRangeObj(this, pDocShell, aName);
+ return nullptr;
+}
+
+ScRangeName* ScGlobalNamedRangesObj::GetRangeName_Impl()
+{
+ return pDocShell->GetDocument().GetRangeName();
+}
+
+SCTAB ScGlobalNamedRangesObj::GetTab_Impl()
+{
+ return -1;
+}
+
+ScLocalNamedRangesObj::ScLocalNamedRangesObj( ScDocShell* pDocSh, uno::Reference<container::XNamed> xSheet )
+ : ScNamedRangesObj(pDocSh),
+ mxSheet(std::move(xSheet))
+{
+
+}
+
+ScLocalNamedRangesObj::~ScLocalNamedRangesObj()
+{
+
+}
+
+rtl::Reference<ScNamedRangeObj> ScLocalNamedRangesObj::GetObjectByName_Impl(const OUString& aName)
+{
+ if ( pDocShell && hasByName( aName ) )
+ return new ScNamedRangeObj( this, pDocShell, aName, mxSheet);
+ return nullptr;
+
+}
+
+rtl::Reference<ScNamedRangeObj> ScLocalNamedRangesObj::GetObjectByIndex_Impl( sal_uInt16 nIndex )
+{
+ if (!pDocShell)
+ return nullptr;
+
+ OUString aName = mxSheet->getName();
+ ScDocument& rDoc = pDocShell->GetDocument();
+ SCTAB nTab;
+ if (!rDoc.GetTable(aName, nTab))
+ return nullptr;
+
+ ScRangeName* pNames = rDoc.GetRangeName( nTab );
+ if (!pNames)
+ return nullptr;
+
+ sal_uInt16 nPos = 0;
+ for (const auto& rName : *pNames)
+ {
+ if (lcl_UserVisibleName(*rName.second))
+ {
+ if (nPos == nIndex)
+ return new ScNamedRangeObj(this, pDocShell, rName.second->GetName(), mxSheet);
+ }
+ ++nPos;
+ }
+ return nullptr;
+}
+
+ScRangeName* ScLocalNamedRangesObj::GetRangeName_Impl()
+{
+ SCTAB nTab = GetTab_Impl();
+ return pDocShell->GetDocument().GetRangeName( nTab );
+}
+
+SCTAB ScLocalNamedRangesObj::GetTab_Impl()
+{
+ SCTAB nTab;
+ (void)pDocShell->GetDocument().GetTable(mxSheet->getName(), nTab);
+ return nTab;
+}
+
+ScLabelRangeObj::ScLabelRangeObj(ScDocShell* pDocSh, bool bCol, const ScRange& rR) :
+ pDocShell( pDocSh ),
+ bColumn( bCol ),
+ aRange( rR )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScLabelRangeObj::~ScLabelRangeObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScLabelRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ //! Ref-Update !!!
+
+ if ( rHint.GetId() == SfxHintId::Dying )
+ pDocShell = nullptr; // became invalid
+}
+
+// Helper functions
+
+ScRangePair* ScLabelRangeObj::GetData_Impl()
+{
+ ScRangePair* pRet = nullptr;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+ if (pList)
+ pRet = pList->Find( aRange );
+ }
+ return pRet;
+}
+
+void ScLabelRangeObj::Modify_Impl( const ScRange* pLabel, const ScRange* pData )
+{
+ if (!pDocShell)
+ return;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+ if (!pOldList)
+ return;
+
+ ScRangePairListRef xNewList(pOldList->Clone());
+ ScRangePair* pEntry = xNewList->Find( aRange );
+ if (!pEntry)
+ return;
+
+ if ( pLabel )
+ pEntry->GetRange(0) = *pLabel;
+ if ( pData )
+ pEntry->GetRange(1) = *pData;
+
+ xNewList->Join( *pEntry, true );
+
+ if (bColumn)
+ rDoc.GetColNameRangesRef() = xNewList;
+ else
+ rDoc.GetRowNameRangesRef() = xNewList;
+
+ rDoc.CompileColRowNameFormula();
+ pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
+ pDocShell->SetDocumentModified();
+
+ //! Undo ?!?! (here and from dialog)
+
+ if ( pLabel )
+ aRange = *pLabel; // adapt object to find range again
+}
+
+// sheet::XLabelRange
+
+table::CellRangeAddress SAL_CALL ScLabelRangeObj::getLabelArea()
+{
+ SolarMutexGuard aGuard;
+ table::CellRangeAddress aRet;
+ ScRangePair* pData = GetData_Impl();
+ if (pData)
+ ScUnoConversion::FillApiRange( aRet, pData->GetRange(0) );
+ return aRet;
+}
+
+void SAL_CALL ScLabelRangeObj::setLabelArea( const table::CellRangeAddress& aLabelArea )
+{
+ SolarMutexGuard aGuard;
+ ScRange aLabelRange;
+ ScUnoConversion::FillScRange( aLabelRange, aLabelArea );
+ Modify_Impl( &aLabelRange, nullptr );
+}
+
+table::CellRangeAddress SAL_CALL ScLabelRangeObj::getDataArea()
+{
+ SolarMutexGuard aGuard;
+ table::CellRangeAddress aRet;
+ ScRangePair* pData = GetData_Impl();
+ if (pData)
+ ScUnoConversion::FillApiRange( aRet, pData->GetRange(1) );
+ return aRet;
+}
+
+void SAL_CALL ScLabelRangeObj::setDataArea( const table::CellRangeAddress& aDataArea )
+{
+ SolarMutexGuard aGuard;
+ ScRange aDataRange;
+ ScUnoConversion::FillScRange( aDataRange, aDataArea );
+ Modify_Impl( nullptr, &aDataRange );
+}
+
+ScLabelRangesObj::ScLabelRangesObj(ScDocShell* pDocSh, bool bCol) :
+ pDocShell( pDocSh ),
+ bColumn( bCol )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScLabelRangesObj::~ScLabelRangesObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScLabelRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ // reference update is of no interest
+
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ pDocShell = nullptr; // became invalid
+ }
+}
+
+// sheet::XLabelRanges
+
+rtl::Reference<ScLabelRangeObj> ScLabelRangesObj::GetObjectByIndex_Impl(size_t nIndex)
+{
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+ if ( pList && nIndex < pList->size() )
+ {
+ ScRangePair & rData = (*pList)[nIndex];
+ return new ScLabelRangeObj( pDocShell, bColumn, rData.GetRange(0) );
+ }
+ }
+ return nullptr;
+}
+
+void SAL_CALL ScLabelRangesObj::addNew( const table::CellRangeAddress& aLabelArea,
+ const table::CellRangeAddress& aDataArea )
+{
+ SolarMutexGuard aGuard;
+ if (!pDocShell)
+ return;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+ if (!pOldList)
+ return;
+
+ ScRangePairListRef xNewList(pOldList->Clone());
+
+ ScRange aLabelRange;
+ ScRange aDataRange;
+ ScUnoConversion::FillScRange( aLabelRange, aLabelArea );
+ ScUnoConversion::FillScRange( aDataRange, aDataArea );
+ xNewList->Join( ScRangePair( aLabelRange, aDataRange ) );
+
+ if (bColumn)
+ rDoc.GetColNameRangesRef() = xNewList;
+ else
+ rDoc.GetRowNameRangesRef() = xNewList;
+
+ rDoc.CompileColRowNameFormula();
+ pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
+ pDocShell->SetDocumentModified();
+
+ //! Undo ?!?! (here and from dialog)
+}
+
+void SAL_CALL ScLabelRangesObj::removeByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+
+ if ( pOldList && nIndex >= 0 && o3tl::make_unsigned(nIndex) < pOldList->size() )
+ {
+ ScRangePairListRef xNewList(pOldList->Clone());
+
+ xNewList->Remove( nIndex );
+
+ if (bColumn)
+ rDoc.GetColNameRangesRef() = xNewList;
+ else
+ rDoc.GetRowNameRangesRef() = xNewList;
+
+ rDoc.CompileColRowNameFormula();
+ pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
+ pDocShell->SetDocumentModified();
+ bDone = true;
+
+ //! Undo ?!?! (here and from dialog)
+ }
+ }
+ if (!bDone)
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+// container::XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScLabelRangesObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return new ScIndexEnumeration(this, "com.sun.star.sheet.LabelRangesEnumeration");
+}
+
+// container::XIndexAccess
+
+sal_Int32 SAL_CALL ScLabelRangesObj::getCount()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
+ if (pList)
+ return pList->size();
+ }
+ return 0;
+}
+
+uno::Any SAL_CALL ScLabelRangesObj::getByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< sheet::XLabelRange > xRange(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
+ if ( !xRange.is() )
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any(xRange);
+}
+
+uno::Type SAL_CALL ScLabelRangesObj::getElementType()
+{
+ return cppu::UnoType<sheet::XLabelRange>::get(); // must be suitable for getByIndex
+}
+
+sal_Bool SAL_CALL ScLabelRangesObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return ( getCount() != 0 );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */