update ooo310-m15
[ooovba.git] / sc / source / core / tool / rangenam.cxx
blobb68d44d6334c78500103eb3edb1ddf2b7952c680
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rangenam.cxx,v $
10 * $Revision: 1.28.30.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 //------------------------------------------------------------------------
37 #include <tools/debug.hxx>
38 #include <string.h>
39 #include <memory>
40 #include <unotools/collatorwrapper.hxx>
41 #include <unotools/transliterationwrapper.hxx>
43 #include "token.hxx"
44 #include "tokenarray.hxx"
45 #include "rangenam.hxx"
46 #include "global.hxx"
47 #include "compiler.hxx"
48 #include "rangeutl.hxx"
49 #include "rechead.hxx"
50 #include "refupdat.hxx"
51 #include "document.hxx"
52 #include "indexmap.hxx"
54 using namespace formula;
56 //========================================================================
57 // ScRangeData
58 //========================================================================
60 // Interner ctor fuer das Suchen nach einem Index
62 ScRangeData::ScRangeData( USHORT n )
63 : pCode( NULL ), nIndex( n ), bModified( FALSE )
66 ScRangeData::ScRangeData( ScDocument* pDok,
67 const String& rName,
68 const String& rSymbol,
69 const ScAddress& rAddress,
70 RangeType nType,
71 const FormulaGrammar::Grammar eGrammar ) :
72 aName ( rName ),
73 aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
74 pCode ( NULL ),
75 aPos ( rAddress ),
76 eType ( nType ),
77 pDoc ( pDok ),
78 nIndex ( 0 ),
79 bModified ( FALSE )
81 if (rSymbol.Len() > 0)
83 ScCompiler aComp( pDoc, aPos );
84 aComp.SetGrammar(eGrammar);
85 pCode = aComp.CompileString( rSymbol );
86 if( !pCode->GetCodeError() )
88 pCode->Reset();
89 FormulaToken* p = pCode->GetNextReference();
90 if( p )// genau eine Referenz als erstes
92 if( p->GetType() == svSingleRef )
93 eType = eType | RT_ABSPOS;
94 else
95 eType = eType | RT_ABSAREA;
97 // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
98 // Dies ist fuer die manuelle Eingabe
99 aComp.CompileTokenArray();
100 pCode->DelRPN();
103 else
105 // #i63513#/#i65690# don't leave pCode as NULL.
106 // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
107 // to ensure same behavior if unnecessary copying is left out.
109 pCode = new ScTokenArray();
113 ScRangeData::ScRangeData( ScDocument* pDok,
114 const String& rName,
115 const ScTokenArray& rArr,
116 const ScAddress& rAddress,
117 RangeType nType ) :
118 aName ( rName ),
119 aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
120 pCode ( new ScTokenArray( rArr ) ),
121 aPos ( rAddress ),
122 eType ( nType ),
123 pDoc ( pDok ),
124 nIndex ( 0 ),
125 bModified ( FALSE )
127 if( !pCode->GetCodeError() )
129 pCode->Reset();
130 FormulaToken* p = pCode->GetNextReference();
131 if( p )// genau eine Referenz als erstes
133 if( p->GetType() == svSingleRef )
134 eType = eType | RT_ABSPOS;
135 else
136 eType = eType | RT_ABSAREA;
138 // Die Importfilter haben diesen Test nicht,
139 // da die benannten Bereiche z.T. noch unvollstaendig sind.
140 // if( !pCode->GetCodeLen() )
141 // {
142 // // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
143 // ScCompiler aComp( pDok, aPos, *pCode );
144 // aComp.CompileTokenArray();
145 // pCode->DelRPN();
146 // }
150 ScRangeData::ScRangeData( ScDocument* pDok,
151 const String& rName,
152 const ScAddress& rTarget ) :
153 aName ( rName ),
154 aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
155 pCode ( new ScTokenArray() ),
156 aPos ( rTarget ),
157 eType ( RT_NAME ),
158 pDoc ( pDok ),
159 nIndex ( 0 ),
160 bModified ( FALSE )
162 ScSingleRefData aRefData;
163 aRefData.InitAddress( rTarget );
164 aRefData.SetFlag3D( TRUE );
165 pCode->AddSingleReference( aRefData );
166 ScCompiler aComp( pDoc, aPos, *pCode );
167 aComp.SetGrammar(pDoc->GetGrammar());
168 aComp.CompileTokenArray();
169 if ( !pCode->GetCodeError() )
170 eType |= RT_ABSPOS;
173 ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
174 ScDataObject(),
175 aName (rScRangeData.aName),
176 aUpperName (rScRangeData.aUpperName),
177 pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor)
178 aPos (rScRangeData.aPos),
179 eType (rScRangeData.eType),
180 pDoc (rScRangeData.pDoc),
181 nIndex (rScRangeData.nIndex),
182 bModified (rScRangeData.bModified)
185 ScRangeData::~ScRangeData()
187 delete pCode;
190 ScDataObject* ScRangeData::Clone() const
192 return new ScRangeData(*this);
195 void ScRangeData::GuessPosition()
197 // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
198 // ohne Fehler verabsolutiert werden koennen
200 DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
202 SCsCOL nMinCol = 0;
203 SCsROW nMinRow = 0;
204 SCsTAB nMinTab = 0;
206 ScToken* t;
207 pCode->Reset();
208 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
210 ScSingleRefData& rRef1 = t->GetSingleRef();
211 if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol )
212 nMinCol = rRef1.nRelCol;
213 if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow )
214 nMinRow = rRef1.nRelRow;
215 if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab )
216 nMinTab = rRef1.nRelTab;
218 if ( t->GetType() == svDoubleRef )
220 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
221 if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol )
222 nMinCol = rRef2.nRelCol;
223 if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow )
224 nMinRow = rRef2.nRelRow;
225 if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab )
226 nMinTab = rRef2.nRelTab;
230 aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
232 //! Test
233 // DBG_ERROR(String("Pos ")+String((SCCOL)(-nMinCol))+String("/")+
234 // String((SCROW)(-nMinRow))+String("/")+String((SCTAB)(-nMinTab)));
237 void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
239 ScCompiler aComp(pDoc, aPos, *pCode);
240 aComp.SetGrammar(eGrammar);
241 aComp.CreateStringFromTokenArray( rSymbol );
244 void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
245 const FormulaGrammar::Grammar eGrammar )
247 ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
248 ScCompiler aComp( pDoc, rPos, *pTemp.get());
249 aComp.SetGrammar(eGrammar);
250 aComp.MoveRelWrap();
251 aComp.CreateStringFromTokenArray( rBuffer );
254 void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode,
255 const ScRange& r,
256 SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
258 BOOL bChanged = FALSE;
260 pCode->Reset();
261 if( pCode->GetNextReference() )
263 BOOL bSharedFormula = ((eType & RT_SHARED) == RT_SHARED);
264 ScCompiler aComp( pDoc, aPos, *pCode );
265 aComp.SetGrammar(pDoc->GetGrammar());
266 const BOOL bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
267 nDx, nDy, nDz,
268 bChanged, bSharedFormula);
269 if (bSharedFormula)
271 if (bRelRef)
272 eType = eType | RT_SHAREDMOD;
273 else
274 eType = eType & ~RT_SHAREDMOD;
278 bModified = bChanged;
282 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
284 BOOL bChanged = FALSE;
286 ScToken* t;
287 pCode->Reset();
289 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
291 if( t->GetType() != svIndex )
293 SingleDoubleRefModifier aMod( *t );
294 ScComplexRefData& rRef = aMod.Ref();
295 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
296 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
297 ( t->GetType() == svSingleRef ||
298 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
299 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
301 if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING )
302 bChanged = TRUE;
307 bModified = bChanged;
310 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
312 BOOL bChanged = FALSE;
314 ScToken* t;
315 pCode->Reset();
317 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
319 if( t->GetType() != svIndex )
321 SingleDoubleRefModifier aMod( *t );
322 ScComplexRefData& rRef = aMod.Ref();
323 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
324 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
325 ( t->GetType() == svSingleRef ||
326 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
327 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
329 if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING )
330 bChanged = TRUE;
335 bModified = bChanged; // muss direkt hinterher ausgewertet werden
338 BOOL ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo
340 if ( nIndex != rData.nIndex ||
341 aName != rData.aName ||
342 aPos != rData.aPos ||
343 eType != rData.eType ) return FALSE;
345 USHORT nLen = pCode->GetLen();
346 if ( nLen != rData.pCode->GetLen() ) return FALSE;
348 FormulaToken** ppThis = pCode->GetArray();
349 FormulaToken** ppOther = rData.pCode->GetArray();
351 for ( USHORT i=0; i<nLen; i++ )
352 if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
353 return FALSE;
355 return TRUE;
358 BOOL ScRangeData::IsRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
360 BOOL bRet = FALSE;
361 ScRange aRange;
362 if ( IsReference(aRange) )
364 if ( bStartOnly )
365 bRet = ( rPos == aRange.aStart );
366 else
367 bRet = ( aRange.In( rPos ) );
369 return bRet;
372 BOOL ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
374 BOOL bRet = FALSE;
375 ScRange aRange;
376 if ( IsReference(aRange) )
377 bRet = ( rBlock == aRange );
378 return bRet;
381 BOOL ScRangeData::IsReference( ScRange& rRange ) const
383 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
384 return pCode->IsReference( rRange );
386 return FALSE;
389 BOOL ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
391 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
393 ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
394 ScCompiler aComp( pDoc, rPos, *pTemp);
395 aComp.SetGrammar(pDoc->GetGrammar());
396 aComp.MoveRelWrap();
397 return pTemp->IsReference( rRange );
400 return FALSE;
403 BOOL ScRangeData::IsValidReference( ScRange& rRange ) const
405 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
406 return pCode->IsValidReference( rRange );
408 return FALSE;
411 void ScRangeData::UpdateTabRef(SCTAB nOldTable, USHORT nFlag, SCTAB nNewTable)
413 pCode->Reset();
414 if( pCode->GetNextReference() )
416 ScRangeData* pRangeData = NULL; // must not be dereferenced
417 BOOL bChanged;
418 ScCompiler aComp( pDoc, aPos, *pCode);
419 aComp.SetGrammar(pDoc->GetGrammar());
420 switch (nFlag)
422 case 1: // einfache InsertTab (doc.cxx)
423 pRangeData = aComp.UpdateInsertTab(nOldTable, TRUE ); // und CopyTab (doc2.cxx)
424 break;
425 case 2: // einfaches delete (doc.cxx)
426 pRangeData = aComp.UpdateDeleteTab(nOldTable, FALSE, TRUE, bChanged);
427 break;
428 case 3: // move (doc2.cxx)
430 pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, TRUE );
432 break;
433 default:
435 DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
437 break;
439 if (eType&RT_SHARED)
441 if (pRangeData)
442 eType = eType | RT_SHAREDMOD;
443 else
444 eType = eType & ~RT_SHAREDMOD;
449 // wie beim Uebernehmen von Namen in Excel
451 void ScRangeData::MakeValidName( String& rName ) // static
453 //ScCompiler::InitSymbolsNative();
455 // ungueltige Zeichen vorne weglassen
456 xub_StrLen nPos = 0;
457 xub_StrLen nLen = rName.Len();
458 while ( nPos < nLen && !ScCompiler::IsWordChar( rName, nPos) )
459 ++nPos;
460 if ( nPos>0 )
461 rName.Erase(0,nPos);
463 // wenn vorne ein ungueltiges Anfangszeichen steht, '_' davor
464 if ( rName.Len() && !ScCompiler::IsCharWordChar( rName, 0 ) )
465 rName.Insert('_',0);
467 // ungueltige durch '_' ersetzen
468 nLen = rName.Len();
469 for (nPos=0; nPos<nLen; nPos++)
471 if ( !ScCompiler::IsWordChar( rName, nPos) )
472 rName.SetChar( nPos, '_' );
475 // Name darf keine Referenz beinhalten, wie in IsNameValid
476 ScAddress aAddr;
477 ScRange aRange;
478 int nConv = FormulaGrammar::CONV_UNSPECIFIED; // use int so that op++ works
480 // Ensure that the proposed name is not an address under any convention
481 while ( ++nConv != FormulaGrammar::CONV_LAST )
483 ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
484 while( aRange.Parse( rName, NULL, details )
485 || aAddr.Parse( rName, NULL, details ) )
487 //! Range Parse auch bei Bereich mit ungueltigem Tabellennamen gueltig
488 //! Address Parse dito, Name erzeugt deswegen bei Compile ein #REF!
489 if ( rName.SearchAndReplace( ':', '_' ) == STRING_NOTFOUND
490 && rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
491 rName.Insert('_',0);
496 BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
498 /* If changed, ScfTools::ConvertToScDefinedName (sc/source/filter/ftools/ftools.cxx)
499 needs to be changed too. */
500 xub_StrLen nPos = 0;
501 xub_StrLen nLen = rName.Len();
502 if ( !nLen || !ScCompiler::IsCharWordChar( rName, nPos++ ) )
503 return FALSE;
504 while ( nPos < nLen )
506 if ( !ScCompiler::IsWordChar( rName, nPos++ ) )
507 return FALSE;
509 // Parse nicht auf VALID pruefen, es reicht, wenn irgendein Bestandteil
510 // erkannt wurde
511 ScRange aRange;
512 if( aRange.Parse( rName, pDoc ) ) // THIS IS WRONG
513 return FALSE;
514 else
516 ScAddress aAddr;
517 if ( aAddr.Parse( rName, pDoc ) ) // THIS IS WRONG
518 return FALSE;
520 return TRUE;
524 USHORT ScRangeData::GetErrCode()
526 return pCode ? pCode->GetCodeError() : 0;
529 BOOL ScRangeData::HasReferences() const
531 pCode->Reset();
532 return BOOL( pCode->GetNextReference() != NULL );
535 // bei TransferTab von einem in ein anderes Dokument anpassen,
536 // um Referenzen auf die eigene Tabelle mitzubekommen
538 void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab )
540 long nTabDiff = (long)nNewTab - nOldTab;
541 long nPosDiff = (long)nNewTab - aPos.Tab();
542 aPos.SetTab( nNewTab );
543 ScToken* t;
544 pCode->Reset();
545 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
547 ScSingleRefData& rRef1 = t->GetSingleRef();
548 if ( rRef1.IsTabRel() )
549 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff );
550 else
551 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff );
552 if ( t->GetType() == svDoubleRef )
554 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
555 if ( rRef2.IsTabRel() )
556 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff );
557 else
558 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nTabDiff );
564 void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
566 BOOL bCompile = FALSE;
567 for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
569 if ( p->GetOpCode() == ocName )
571 const USHORT nOldIndex = p->GetIndex();
572 const USHORT nNewIndex = rMap.Find( nOldIndex );
573 if ( nOldIndex != nNewIndex )
575 p->SetIndex( nNewIndex );
576 bCompile = TRUE;
580 if ( bCompile )
582 ScCompiler aComp( pDoc, aPos, *pCode);
583 aComp.SetGrammar(pDoc->GetGrammar());
584 aComp.CompileTokenArray();
588 void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
590 bool bCompile = false;
591 for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
593 if ( p->GetOpCode() == ocName )
595 const sal_uInt16 nOldIndex = p->GetIndex();
596 IndexMap::const_iterator itr = rMap.find(nOldIndex);
597 const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
598 if ( nOldIndex != nNewIndex )
600 p->SetIndex( nNewIndex );
601 bCompile = true;
605 if ( bCompile )
607 ScCompiler aComp( pDoc, aPos, *pCode);
608 aComp.SetGrammar(pDoc->GetGrammar());
609 aComp.CompileTokenArray();
614 void ScRangeData::ValidateTabRefs()
616 // try to make sure all relative references and the reference position
617 // are within existing tables, so they can be represented as text
618 // (if the range of used tables is more than the existing tables,
619 // the result may still contain invalid tables, because the relative
620 // references aren't changed so formulas stay the same)
622 // find range of used tables
624 SCTAB nMinTab = aPos.Tab();
625 SCTAB nMaxTab = nMinTab;
626 ScToken* t;
627 pCode->Reset();
628 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
630 ScSingleRefData& rRef1 = t->GetSingleRef();
631 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
633 if ( rRef1.nTab < nMinTab )
634 nMinTab = rRef1.nTab;
635 if ( rRef1.nTab > nMaxTab )
636 nMaxTab = rRef1.nTab;
638 if ( t->GetType() == svDoubleRef )
640 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
641 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
643 if ( rRef2.nTab < nMinTab )
644 nMinTab = rRef2.nTab;
645 if ( rRef2.nTab > nMaxTab )
646 nMaxTab = rRef2.nTab;
651 SCTAB nTabCount = pDoc->GetTableCount();
652 if ( nMaxTab >= nTabCount && nMinTab > 0 )
654 // move position and relative tab refs
655 // The formulas that use the name are not changed by this
657 SCTAB nMove = nMinTab;
658 aPos.SetTab( aPos.Tab() - nMove );
660 pCode->Reset();
661 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
663 ScSingleRefData& rRef1 = t->GetSingleRef();
664 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
665 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
666 if ( t->GetType() == svDoubleRef )
668 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
669 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
670 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove );
677 extern "C" int
678 #ifdef WNT
679 __cdecl
680 #endif
681 ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
683 return (int) ScGlobal::pCollator->compareString(
684 (*(const ScRangeData**)p1)->GetName(),
685 (*(const ScRangeData**)p2)->GetName() );
689 //========================================================================
690 // ScRangeName
691 //========================================================================
693 ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
694 ScSortedCollection ( rScRangeName ),
695 pDoc ( pDocument ),
696 nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
698 for (USHORT i = 0; i < nCount; i++)
700 ((ScRangeData*)At(i))->SetDocument(pDocument);
701 ((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
705 short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
707 USHORT i1 = ((ScRangeData*)pKey1)->GetIndex();
708 USHORT i2 = ((ScRangeData*)pKey2)->GetIndex();
709 return (short) i1 - (short) i2;
712 BOOL ScRangeName::SearchNameUpper( const String& rUpperName, USHORT& rIndex ) const
714 // SearchNameUpper must be called with an upper-case search string
716 USHORT i = 0;
717 while (i < nCount)
719 if ( ((*this)[i])->GetUpperName() == rUpperName )
721 rIndex = i;
722 return TRUE;
724 i++;
726 return FALSE;
729 BOOL ScRangeName::SearchName( const String& rName, USHORT& rIndex ) const
731 if ( nCount > 0 )
732 return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex );
733 else
734 return FALSE;
737 void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode,
738 const ScRange& rRange,
739 SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
741 for (USHORT i=0; i<nCount; i++)
742 ((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
743 nDx, nDy, nDz);
746 void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
748 for (USHORT i=0; i<nCount; i++)
749 ((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
752 void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
754 for (USHORT i=0; i<nCount; i++)
755 ((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
758 BOOL ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
760 return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
763 BOOL ScRangeName::Insert(ScDataObject* pScDataObject)
765 if (!((ScRangeData*)pScDataObject)->GetIndex()) // schon gesetzt?
767 ((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() );
770 return ScSortedCollection::Insert(pScDataObject);
773 // Suche nach einem freien Index
775 USHORT ScRangeName::GetEntryIndex()
777 USHORT nLast = 0;
778 for ( USHORT i = 0; i < nCount; i++ )
780 USHORT nIdx = ((ScRangeData*)pItems[i])->GetIndex();
781 if( nIdx > nLast )
783 nLast = nIdx;
786 return nLast + 1;
789 ScRangeData* ScRangeName::FindIndex( USHORT nIndex )
791 ScRangeData aDataObj( nIndex );
792 USHORT n;
793 if( Search( &aDataObj, n ) )
794 return (*this)[ n ];
795 else
796 return NULL;
799 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
801 if ( pItems )
803 for ( USHORT i = 0; i < nCount; i++ )
804 if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
805 return (ScRangeData*)pItems[i];
807 return NULL;
810 ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
812 if ( pItems )
814 for ( USHORT i = 0; i < nCount; i++ )
815 if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
816 return (ScRangeData*)pItems[i];
818 return NULL;
821 void ScRangeName::UpdateTabRef(SCTAB nOldTable, USHORT nFlag, SCTAB nNewTable)
823 for (USHORT i=0; i<nCount; i++)
824 ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);