summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/rangenam.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/rangenam.cxx')
-rw-r--r--sc/source/core/tool/rangenam.cxx824
1 files changed, 824 insertions, 0 deletions
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
new file mode 100644
index 000000000000..cfd1b1135bec
--- /dev/null
+++ b/sc/source/core/tool/rangenam.cxx
@@ -0,0 +1,824 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+//------------------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <string.h>
+#include <memory>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/transliterationwrapper.hxx>
+
+#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)
+{}
+
+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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{}
+
+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<ScToken*>(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<ScTokenArray> 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<ScToken*>(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<ScToken*>(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 ) 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; i<nLen; i++ )
+ if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
+ return sal_False;
+
+ return sal_True;
+}
+
+//UNUSED2009-05 sal_Bool ScRangeData::IsRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
+//UNUSED2009-05 {
+//UNUSED2009-05 sal_Bool bRet = sal_False;
+//UNUSED2009-05 ScRange aRange;
+//UNUSED2009-05 if ( IsReference(aRange) )
+//UNUSED2009-05 {
+//UNUSED2009-05 if ( bStartOnly )
+//UNUSED2009-05 bRet = ( rPos == aRange.aStart );
+//UNUSED2009-05 else
+//UNUSED2009-05 bRet = ( aRange.In( rPos ) );
+//UNUSED2009-05 }
+//UNUSED2009-05 return bRet;
+//UNUSED2009-05 }
+
+sal_Bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
+{
+ sal_Bool bRet = sal_False;
+ ScRange aRange;
+ if ( IsReference(aRange) )
+ bRet = ( rBlock == aRange );
+ return bRet;
+}
+
+sal_Bool ScRangeData::IsReference( ScRange& rRange ) const
+{
+ if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
+ return pCode->IsReference( 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<ScTokenArray> 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;
+}
+
+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)
+ pRangeData = aComp.UpdateInsertTab(nOldTable, sal_True ); // und CopyTab (doc2.cxx)
+ break;
+ case 2: // einfaches delete (doc.cxx)
+ pRangeData = aComp.UpdateDeleteTab(nOldTable, sal_False, sal_True, bChanged);
+ break;
+ case 3: // move (doc2.cxx)
+ {
+ pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, sal_True );
+ }
+ 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<nLen; nPos++)
+ {
+ if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
+ rName.SetChar( nPos, '_' );
+ }
+
+ // Ensure that the proposed name is not a reference under any convention,
+ // same as in IsNameValid()
+ ScAddress aAddr;
+ ScRange aRange;
+ for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
+ {
+ ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( 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<FormulaGrammar::AddressConvention>( 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;
+}
+
+
+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<ScToken*>(pCode->GetNextReference()) ) != NULL )
+ {
+ ScSingleRefData& rRef1 = t->GetSingleRef();
+ if ( rRef1.IsTabRel() )
+ rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff );
+ else
+ rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff );
+ if ( t->GetType() == svDoubleRef )
+ {
+ ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+ if ( rRef2.IsTabRel() )
+ rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff );
+ else
+ rRef2.nTab = sal::static_int_cast<SCsTAB>( 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<ScToken*>(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<ScToken*>(pCode->GetNextReference()) ) != NULL )
+ {
+ ScSingleRefData& rRef1 = t->GetSingleRef();
+ if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
+ rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
+ if ( t->GetType() == svDoubleRef )
+ {
+ ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+ if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
+ rRef2.nTab = sal::static_int_cast<SCsTAB>( 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;
+}
+
+sal_Bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex ) const
+{
+ // SearchNameUpper must be called with an upper-case search string
+
+ sal_uInt16 i = 0;
+ while (i < nCount)
+ {
+ if ( ((*this)[i])->GetUpperName() == rUpperName )
+ {
+ rIndex = i;
+ return sal_True;
+ }
+ i++;
+ }
+ return sal_False;
+}
+
+sal_Bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex ) const
+{
+ if ( nCount > 0 )
+ return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex );
+ else
+ return sal_False;
+}
+
+void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange,
+ SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
+{
+ for (sal_uInt16 i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
+ nDx, nDy, nDz);
+}
+
+void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
+{
+ for (sal_uInt16 i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
+}
+
+void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
+{
+ for (sal_uInt16 i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateGrow( 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)
+{
+ for (sal_uInt16 i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
+}
+
+
+
+