/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" //------------------------------------------------------------------------ #include #include #include #include #include #include "token.hxx" #include "tokenarray.hxx" #include "rangenam.hxx" #include "global.hxx" #include "compiler.hxx" #include "rangeutl.hxx" #include "rechead.hxx" #include "refupdat.hxx" #include "document.hxx" using namespace formula; //======================================================================== // ScRangeData //======================================================================== // Interner ctor fuer das Suchen nach einem Index ScRangeData::ScRangeData( sal_uInt16 n ) : pCode( NULL ), nIndex( n ), bModified( sal_False ), mnMaxRow(-1), mnMaxCol(-1), aRangeNameScope( MAXTABCOUNT ) {} ScRangeData::ScRangeData( ScDocument* pDok, const String& rName, const String& rSymbol, const ScAddress& rAddress, RangeType nType, const FormulaGrammar::Grammar eGrammar ) : aName ( rName ), aUpperName ( ScGlobal::pCharClass->upper( rName ) ), pCode ( NULL ), aPos ( rAddress ), eType ( nType ), pDoc ( pDok ), nIndex ( 0 ), bModified ( sal_False ), mnMaxRow (-1), mnMaxCol (-1), aRangeNameScope( MAXTABCOUNT ) { if (rSymbol.Len() > 0) { ScCompiler aComp( pDoc, aPos ); aComp.SetGrammar(eGrammar); pCode = aComp.CompileString( rSymbol ); if( !pCode->GetCodeError() ) { pCode->Reset(); FormulaToken* p = pCode->GetNextReference(); if( p )// genau eine Referenz als erstes { if( p->GetType() == svSingleRef ) eType = eType | RT_ABSPOS; else eType = eType | RT_ABSAREA; } // ggf. den Fehlercode wg. unvollstaendiger Formel setzen! // Dies ist fuer die manuelle Eingabe aComp.CompileTokenArray(); pCode->DelRPN(); } } else { // #i63513#/#i65690# don't leave pCode as NULL. // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too, // to ensure same behavior if unnecessary copying is left out. pCode = new ScTokenArray(); } } ScRangeData::ScRangeData( ScDocument* pDok, const String& rName, const ScTokenArray& rArr, const ScAddress& rAddress, RangeType nType ) : aName ( rName ), aUpperName ( ScGlobal::pCharClass->upper( rName ) ), pCode ( new ScTokenArray( rArr ) ), aPos ( rAddress ), eType ( nType ), pDoc ( pDok ), nIndex ( 0 ), bModified ( sal_False ), mnMaxRow (-1), mnMaxCol (-1), aRangeNameScope( MAXTABCOUNT ) { if( !pCode->GetCodeError() ) { pCode->Reset(); FormulaToken* p = pCode->GetNextReference(); if( p )// genau eine Referenz als erstes { if( p->GetType() == svSingleRef ) eType = eType | RT_ABSPOS; else eType = eType | RT_ABSAREA; } // Die Importfilter haben diesen Test nicht, // da die benannten Bereiche z.T. noch unvollstaendig sind. // if( !pCode->GetCodeLen() ) // { // // ggf. den Fehlercode wg. unvollstaendiger Formel setzen! // ScCompiler aComp( pDok, aPos, *pCode ); // aComp.CompileTokenArray(); // pCode->DelRPN(); // } } } ScRangeData::ScRangeData( ScDocument* pDok, const String& rName, const ScAddress& rTarget ) : aName ( rName ), aUpperName ( ScGlobal::pCharClass->upper( rName ) ), pCode ( new ScTokenArray() ), aPos ( rTarget ), eType ( RT_NAME ), pDoc ( pDok ), nIndex ( 0 ), bModified ( sal_False ), mnMaxRow (-1), mnMaxCol (-1), aRangeNameScope( MAXTABCOUNT ) { ScSingleRefData aRefData; aRefData.InitAddress( rTarget ); aRefData.SetFlag3D( sal_True ); pCode->AddSingleReference( aRefData ); ScCompiler aComp( pDoc, aPos, *pCode ); aComp.SetGrammar(pDoc->GetGrammar()); aComp.CompileTokenArray(); if ( !pCode->GetCodeError() ) eType |= RT_ABSPOS; } ScRangeData::ScRangeData(const ScRangeData& rScRangeData) : ScDataObject(), aName (rScRangeData.aName), aUpperName (rScRangeData.aUpperName), pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor) aPos (rScRangeData.aPos), eType (rScRangeData.eType), pDoc (rScRangeData.pDoc), nIndex (rScRangeData.nIndex), bModified (rScRangeData.bModified), mnMaxRow (rScRangeData.mnMaxRow), mnMaxCol (rScRangeData.mnMaxCol), aRangeNameScope (rScRangeData.aRangeNameScope) {} ScRangeData::~ScRangeData() { delete pCode; } ScDataObject* ScRangeData::Clone() const { return new ScRangeData(*this); } void ScRangeData::GuessPosition() { // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel // ohne Fehler verabsolutiert werden koennen DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren"); SCsCOL nMinCol = 0; SCsROW nMinRow = 0; SCsTAB nMinTab = 0; ScToken* t; pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { ScSingleRefData& rRef1 = t->GetSingleRef(); if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol ) nMinCol = rRef1.nRelCol; if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow ) nMinRow = rRef1.nRelRow; if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab ) nMinTab = rRef1.nRelTab; if ( t->GetType() == svDoubleRef ) { ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol ) nMinCol = rRef2.nRelCol; if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow ) nMinRow = rRef2.nRelRow; if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab ) nMinTab = rRef2.nRelTab; } } aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) ); //! Test // DBG_ERROR(String("Pos ")+String((SCCOL)(-nMinCol))+String("/")+ // String((SCROW)(-nMinRow))+String("/")+String((SCTAB)(-nMinTab))); } void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const { ScCompiler aComp(pDoc, aPos, *pCode); aComp.SetGrammar(eGrammar); aComp.CreateStringFromTokenArray( rSymbol ); } void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) { ::std::auto_ptr pTemp( pCode->Clone() ); ScCompiler aComp( pDoc, rPos, *pTemp.get()); aComp.SetGrammar(eGrammar); aComp.MoveRelWrap(GetMaxCol(), GetMaxRow()); aComp.CreateStringFromTokenArray( rBuffer ); } void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) { sal_Bool bChanged = sal_False; pCode->Reset(); if( pCode->GetNextReference() ) { sal_Bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED); ScCompiler aComp( pDoc, aPos, *pCode ); aComp.SetGrammar(pDoc->GetGrammar()); const sal_Bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r, nDx, nDy, nDz, bChanged, bSharedFormula); if (bSharedFormula) { if (bRelRef) eType = eType | RT_SHAREDMOD; else eType = eType & ~RT_SHAREDMOD; } } bModified = bChanged; } void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest ) { sal_Bool bChanged = sal_False; ScToken* t; pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { if( t->GetType() != svIndex ) { SingleDoubleRefModifier aMod( *t ); ScComplexRefData& rRef = aMod.Ref(); if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) && ( t->GetType() == svSingleRef || (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() && (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel())))) { if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING ) bChanged = sal_True; } } } bModified = bChanged; } void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ) { sal_Bool bChanged = sal_False; ScToken* t; pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { if( t->GetType() != svIndex ) { SingleDoubleRefModifier aMod( *t ); ScComplexRefData& rRef = aMod.Ref(); if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) && ( t->GetType() == svSingleRef || (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() && (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel())))) { if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING ) bChanged = sal_True; } } } bModified = bChanged; // muss direkt hinterher ausgewertet werden } sal_Bool ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo { if ( nIndex != rData.nIndex || aName != rData.aName || aPos != rData.aPos || eType != rData.eType || aRangeNameScope != rData.aRangeNameScope ) return sal_False; sal_uInt16 nLen = pCode->GetLen(); if ( nLen != rData.pCode->GetLen() ) return sal_False; FormulaToken** ppThis = pCode->GetArray(); FormulaToken** ppOther = rData.pCode->GetArray(); for ( sal_uInt16 i=0; iIsReference( rRange ); return sal_False; } sal_Bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const { if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode ) { ::std::auto_ptr pTemp( pCode->Clone() ); ScCompiler aComp( pDoc, rPos, *pTemp); aComp.SetGrammar(pDoc->GetGrammar()); aComp.MoveRelWrap(MAXCOL, MAXROW); return pTemp->IsReference( rRange ); } return sal_False; } sal_Bool ScRangeData::IsValidReference( ScRange& rRange ) const { if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode ) return pCode->IsValidReference( rRange ); return sal_False; } /* modification to update named range scope */ void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable) { pCode->Reset(); if( pCode->GetNextReference() ) { ScRangeData* pRangeData = NULL; // must not be dereferenced sal_Bool bChanged; ScCompiler aComp( pDoc, aPos, *pCode); aComp.SetGrammar(pDoc->GetGrammar()); switch (nFlag) { case 1: // einfache InsertTab (doc.cxx) case 4: pRangeData = aComp.UpdateInsertTab(nOldTable, true ); // und CopyTab (doc2.cxx) if ( (aRangeNameScope != MAXTABCOUNT) && ( aRangeNameScope >= nOldTable) && ( aRangeNameScope != MAXTAB ) ) aRangeNameScope ++; break; case 2: // einfaches delete (doc.cxx) pRangeData = aComp.UpdateDeleteTab(nOldTable, false, true, bChanged); if ( aRangeNameScope != MAXTABCOUNT && aRangeNameScope > nOldTable ) aRangeNameScope --; break; case 3: // move (doc2.cxx) { pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, true ); if ( aRangeNameScope != MAXTABCOUNT ) { if ( aRangeNameScope == nOldTable ) aRangeNameScope = nNewTable; else if ( (aRangeNameScope > nOldTable) && (aRangeNameScope <= nNewTable) ) aRangeNameScope--; else if ( (aRangeNameScope >= nNewTable) && (aRangeNameScope < nOldTable) ) aRangeNameScope++; } } break; case 5: { //when copying a sheet, this will be invoked to update the new name range's address in the new sheet //only need to update the address if the address's tab same as the range scope. because if they are different, the address's tab have been updated in ScRangeName::UpdateTabRef() //for example, in sheet5(scope is sheet5), there are two name range, one address is sheet5, the other is sheet4, if copy sheet5 to sheet1 //only need to change the first one's address to sheet1 pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, true , true); aRangeNameScope = nNewTable; } break; default: { DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag"); } break; } if (eType&RT_SHARED) { if (pRangeData) eType = eType | RT_SHAREDMOD; else eType = eType & ~RT_SHAREDMOD; } } } void ScRangeData::MakeValidName( String& rName ) // static { //ScCompiler::InitSymbolsNative(); // strip leading invalid characters xub_StrLen nPos = 0; xub_StrLen nLen = rName.Len(); while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) ) ++nPos; if ( nPos>0 ) rName.Erase(0,nPos); // if the first character is an invalid start character, precede with '_' if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) ) rName.Insert('_',0); // replace invalid with '_' nLen = rName.Len(); for (nPos=0; nPos( nConv ) ); // Don't check Parse on VALID, any partial only VALID may result in // #REF! during compile later! while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details)) { //! Range Parse is partially valid also with invalid sheet name, //! Address Parse dito, during compile name would generate a #REF! if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND ) rName.Insert('_',0); } } } sal_Bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc ) { /* XXX If changed, sc/source/filter/ftools/ftools.cxx * ScfTools::ConvertToScDefinedName needs to be changed too. */ xub_StrLen nPos = 0; xub_StrLen nLen = rName.Len(); if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) ) return sal_False; while ( nPos < nLen ) { if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) ) return sal_False; } ScAddress aAddr; ScRange aRange; for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; ) { ScAddress::Details details( static_cast( nConv ) ); // Don't check Parse on VALID, any partial only VALID may result in // #REF! during compile later! if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details)) return sal_False; } return sal_True; } void ScRangeData::SetMaxRow(SCROW nRow) { mnMaxRow = nRow; } SCROW ScRangeData::GetMaxRow() const { return mnMaxRow >= 0 ? mnMaxRow : MAXROW; } void ScRangeData::SetMaxCol(SCCOL nCol) { mnMaxCol = nCol; } SCCOL ScRangeData::GetMaxCol() const { return mnMaxCol >= 0 ? mnMaxCol : MAXCOL; } /* MAXTABCOUNT - Global, 0 - sheet1, 1 - sheet2, ... */ /* MAXTABCOUNT -- Global */ /* return value: FALSE -- set fail */ /* TRUE -- set successfully */ bool ScRangeData::SetRangeScope( SCTAB Scope ) { if ( Scope <= MAXTABCOUNT && Scope >=0 ) { aRangeNameScope = Scope; return true; } return false; } String ScRangeData::GetScopeSheetName() const { if ( aRangeNameScope != MAXTABCOUNT ) { String aTableName; pDoc->GetName( aRangeNameScope, aTableName ); return aTableName; } return EMPTY_STRING; } /* end add */ sal_uInt16 ScRangeData::GetErrCode() { return pCode ? pCode->GetCodeError() : 0; } sal_Bool ScRangeData::HasReferences() const { pCode->Reset(); return sal_Bool( pCode->GetNextReference() != NULL ); } // bei TransferTab von einem in ein anderes Dokument anpassen, // um Referenzen auf die eigene Tabelle mitzubekommen void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab ) { long nTabDiff = (long)nNewTab - nOldTab; long nPosDiff = (long)nNewTab - aPos.Tab(); aPos.SetTab( nNewTab ); ScToken* t; pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { ScSingleRefData& rRef1 = t->GetSingleRef(); if ( rRef1.IsTabRel() ) rRef1.nTab = sal::static_int_cast( rRef1.nTab + nPosDiff ); else rRef1.nTab = sal::static_int_cast( rRef1.nTab + nTabDiff ); if ( t->GetType() == svDoubleRef ) { ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; if ( rRef2.IsTabRel() ) rRef2.nTab = sal::static_int_cast( rRef2.nTab + nPosDiff ); else rRef2.nTab = sal::static_int_cast( rRef2.nTab + nTabDiff ); } } } void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap ) { bool bCompile = false; for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() ) { if ( p->GetOpCode() == ocName ) { const sal_uInt16 nOldIndex = p->GetIndex(); IndexMap::const_iterator itr = rMap.find(nOldIndex); const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second; if ( nOldIndex != nNewIndex ) { p->SetIndex( nNewIndex ); bCompile = true; } } } if ( bCompile ) { ScCompiler aComp( pDoc, aPos, *pCode); aComp.SetGrammar(pDoc->GetGrammar()); aComp.CompileTokenArray(); } } void ScRangeData::ValidateTabRefs() { // try to make sure all relative references and the reference position // are within existing tables, so they can be represented as text // (if the range of used tables is more than the existing tables, // the result may still contain invalid tables, because the relative // references aren't changed so formulas stay the same) // find range of used tables SCTAB nMinTab = aPos.Tab(); SCTAB nMaxTab = nMinTab; ScToken* t; pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { ScSingleRefData& rRef1 = t->GetSingleRef(); if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() ) { if ( rRef1.nTab < nMinTab ) nMinTab = rRef1.nTab; if ( rRef1.nTab > nMaxTab ) nMaxTab = rRef1.nTab; } if ( t->GetType() == svDoubleRef ) { ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() ) { if ( rRef2.nTab < nMinTab ) nMinTab = rRef2.nTab; if ( rRef2.nTab > nMaxTab ) nMaxTab = rRef2.nTab; } } } SCTAB nTabCount = pDoc->GetTableCount(); if ( nMaxTab >= nTabCount && nMinTab > 0 ) { // move position and relative tab refs // The formulas that use the name are not changed by this SCTAB nMove = nMinTab; aPos.SetTab( aPos.Tab() - nMove ); pCode->Reset(); while ( ( t = static_cast(pCode->GetNextReference()) ) != NULL ) { ScSingleRefData& rRef1 = t->GetSingleRef(); if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() ) rRef1.nTab = sal::static_int_cast( rRef1.nTab - nMove ); if ( t->GetType() == svDoubleRef ) { ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() ) rRef2.nTab = sal::static_int_cast( rRef2.nTab - nMove ); } } } } extern "C" int #ifdef WNT __cdecl #endif ScRangeData_QsortNameCompare( const void* p1, const void* p2 ) { return (int) ScGlobal::GetCollator()->compareString( (*(const ScRangeData**)p1)->GetName(), (*(const ScRangeData**)p2)->GetName() ); } //======================================================================== // ScRangeName //======================================================================== ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) : ScSortedCollection ( rScRangeName ), pDoc ( pDocument ), nSharedMaxIndex (rScRangeName.nSharedMaxIndex) { for (sal_uInt16 i = 0; i < nCount; i++) { ((ScRangeData*)At(i))->SetDocument(pDocument); ((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex()); } } short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const { sal_uInt16 i1 = ((ScRangeData*)pKey1)->GetIndex(); sal_uInt16 i2 = ((ScRangeData*)pKey2)->GetIndex(); return (short) i1 - (short) i2; } /* added for scope support */ bool ScRangeName::HasRangeinSheetScope(SCTAB Scope) { for (sal_uInt16 i = 0; i < nCount; i++) if (((*this)[i])->GetRangeScope() == Scope) return true; return false; } /* if Scope is global, no range will be removed */ /* if no range is removed, return value is false */ bool ScRangeName::RemoveRangeinScope(SCTAB Scope) { bool bRemoved = false; if ( Scope == MAXTABCOUNT ) return bRemoved; sal_uInt16 i = 0; while (i < nCount) { if (((*this)[i])->GetRangeScope() == Scope) { Free( (*this)[i] ); bRemoved = true; } else i++; } return bRemoved; } /* it's designed for "Copy Sheet" action. So no name conflict check when copy range to new scope */ /* if the old scope or the new scope is global, no range will be copied */ /* if no range is copied, the return value is false */ bool ScRangeName::CopyRangeinScope(SCTAB oldScope, SCTAB newScope) { bool bCopied = false; if ( (oldScope == MAXTABCOUNT)||(newScope ==MAXTABCOUNT) ) return bCopied; sal_uInt16 originalCount = nCount; for ( sal_uInt16 i = 0; i < originalCount; i++) if ( ((*this)[i])->GetRangeScope() == oldScope) { ScRangeData * aCopiedRange = (ScRangeData *)(*this)[i]->Clone(); aCopiedRange->UpdateTabRef(oldScope, 5 , newScope); aCopiedRange->SetIndex(GetEntryIndex()); Insert( aCopiedRange ); bCopied = true; } return bCopied; } /* end add */ bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex, SCTAB Scope ) const { // SearchNameUpper must be called with an upper-case search string sal_uInt16 i = 0; while (i < nCount) { if ( (((*this)[i])->GetUpperName() == rUpperName) && (((*this)[i])->GetRangeScope() == Scope )) { rIndex = i; return true; } i++; } return false; } bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex, SCTAB Scope ) const { if ( nCount > 0 ) return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex, Scope ); else return false; } void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) { for (sal_uInt16 i=0; iUpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz); } void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest ) { for (sal_uInt16 i=0; iUpdateTranspose( rSource, rDest ); } void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ) { for (sal_uInt16 i=0; iUpdateGrow( rArea, nGrowX, nGrowY ); } sal_Bool ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const { return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2; } sal_Bool ScRangeName::Insert(ScDataObject* pScDataObject) { if (!((ScRangeData*)pScDataObject)->GetIndex()) // schon gesetzt? { ((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() ); } return ScSortedCollection::Insert(pScDataObject); } // Suche nach einem freien Index sal_uInt16 ScRangeName::GetEntryIndex() { sal_uInt16 nLast = 0; for ( sal_uInt16 i = 0; i < nCount; i++ ) { sal_uInt16 nIdx = ((ScRangeData*)pItems[i])->GetIndex(); if( nIdx > nLast ) { nLast = nIdx; } } return nLast + 1; } ScRangeData* ScRangeName::FindIndex( sal_uInt16 nIndex ) { ScRangeData aDataObj( nIndex ); sal_uInt16 n; if( Search( &aDataObj, n ) ) return (*this)[ n ]; else return NULL; } //UNUSED2009-05 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const //UNUSED2009-05 { //UNUSED2009-05 if ( pItems ) //UNUSED2009-05 { //UNUSED2009-05 for ( sal_uInt16 i = 0; i < nCount; i++ ) //UNUSED2009-05 if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) ) //UNUSED2009-05 return (ScRangeData*)pItems[i]; //UNUSED2009-05 } //UNUSED2009-05 return NULL; //UNUSED2009-05 } ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const { if ( pItems ) { for ( sal_uInt16 i = 0; i < nCount; i++ ) if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) ) return (ScRangeData*)pItems[i]; } return NULL; } void ScRangeName::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable) { if (nFlag == 2) RemoveRangeinScope( nOldTable ); for (sal_uInt16 i=0; iUpdateTabRef(nOldTable, nFlag, nNewTable); if (nFlag ==4) { SCTAB copyScope = nOldTable > nNewTable ? nNewTable : nNewTable+1; CopyRangeinScope( copyScope, nOldTable); } }