xref: /aoo42x/main/sc/source/core/tool/rangenam.cxx (revision b3f79822)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 //------------------------------------------------------------------------
29 
30 #include <tools/debug.hxx>
31 #include <string.h>
32 #include <memory>
33 #include <unotools/collatorwrapper.hxx>
34 #include <unotools/transliterationwrapper.hxx>
35 
36 #include "token.hxx"
37 #include "tokenarray.hxx"
38 #include "rangenam.hxx"
39 #include "global.hxx"
40 #include "compiler.hxx"
41 #include "rangeutl.hxx"
42 #include "rechead.hxx"
43 #include "refupdat.hxx"
44 #include "document.hxx"
45 
46 using namespace formula;
47 
48 //========================================================================
49 // ScRangeData
50 //========================================================================
51 
52 // Interner ctor fuer das Suchen nach einem Index
53 
54 ScRangeData::ScRangeData( sal_uInt16 n )
55            : pCode( NULL ), nIndex( n ), bModified( sal_False ), mnMaxRow(-1), mnMaxCol(-1)
56 {}
57 
58 ScRangeData::ScRangeData( ScDocument* pDok,
59 						  const String& rName,
60 						  const String& rSymbol,
61                           const ScAddress& rAddress,
62 						  RangeType nType,
63 						  const FormulaGrammar::Grammar eGrammar ) :
64 				aName		( rName ),
65                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
66 				pCode		( NULL ),
67 				aPos		( rAddress ),
68 				eType		( nType ),
69 				pDoc		( pDok ),
70 				nIndex		( 0 ),
71                 bModified	( sal_False ),
72                 mnMaxRow    (-1),
73                 mnMaxCol    (-1)
74 {
75 	if (rSymbol.Len() > 0)
76 	{
77 		ScCompiler aComp( pDoc, aPos );
78         aComp.SetGrammar(eGrammar);
79 		pCode = aComp.CompileString( rSymbol );
80 		if( !pCode->GetCodeError() )
81 		{
82 			pCode->Reset();
83 			FormulaToken* p = pCode->GetNextReference();
84 			if( p )// genau eine Referenz als erstes
85 			{
86 				if( p->GetType() == svSingleRef )
87 					eType = eType | RT_ABSPOS;
88 				else
89 					eType = eType | RT_ABSAREA;
90 			}
91 			// ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
92 			// Dies ist fuer die manuelle Eingabe
93 			aComp.CompileTokenArray();
94 			pCode->DelRPN();
95 		}
96 	}
97     else
98     {
99         // #i63513#/#i65690# don't leave pCode as NULL.
100         // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
101         // to ensure same behavior if unnecessary copying is left out.
102 
103         pCode = new ScTokenArray();
104     }
105 }
106 
107 ScRangeData::ScRangeData( ScDocument* pDok,
108 						  const String& rName,
109 						  const ScTokenArray& rArr,
110                           const ScAddress& rAddress,
111 						  RangeType nType ) :
112 				aName		( rName ),
113                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
114 				pCode		( new ScTokenArray( rArr ) ),
115 				aPos		( rAddress ),
116 				eType		( nType ),
117 				pDoc		( pDok ),
118 				nIndex		( 0 ),
119                 bModified	( sal_False ),
120                 mnMaxRow    (-1),
121                 mnMaxCol    (-1)
122 {
123 	if( !pCode->GetCodeError() )
124 	{
125 		pCode->Reset();
126 		FormulaToken* p = pCode->GetNextReference();
127 		if( p )// genau eine Referenz als erstes
128 		{
129 			if( p->GetType() == svSingleRef )
130 				eType = eType | RT_ABSPOS;
131 			else
132 				eType = eType | RT_ABSAREA;
133 		}
134 		// Die Importfilter haben diesen Test nicht,
135 		// da die benannten Bereiche z.T. noch unvollstaendig sind.
136 //		if( !pCode->GetCodeLen() )
137 //		{
138 //			// ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
139 //			ScCompiler aComp( pDok, aPos, *pCode );
140 //			aComp.CompileTokenArray();
141 //			pCode->DelRPN();
142 //		}
143 	}
144 }
145 
146 ScRangeData::ScRangeData( ScDocument* pDok,
147 						  const String& rName,
148 						  const ScAddress& rTarget ) :
149 				aName		( rName ),
150                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
151 				pCode		( new ScTokenArray() ),
152 				aPos		( rTarget ),
153 				eType		( RT_NAME ),
154 				pDoc		( pDok ),
155 				nIndex		( 0 ),
156                 bModified	( sal_False ),
157                 mnMaxRow    (-1),
158                 mnMaxCol    (-1)
159 {
160 	ScSingleRefData aRefData;
161 	aRefData.InitAddress( rTarget );
162 	aRefData.SetFlag3D( sal_True );
163 	pCode->AddSingleReference( aRefData );
164 	ScCompiler aComp( pDoc, aPos, *pCode );
165     aComp.SetGrammar(pDoc->GetGrammar());
166 	aComp.CompileTokenArray();
167 	if ( !pCode->GetCodeError() )
168 		eType |= RT_ABSPOS;
169 }
170 
171 ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
172     ScDataObject(),
173 	aName 	(rScRangeData.aName),
174     aUpperName  (rScRangeData.aUpperName),
175 	pCode		(rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()),		// echte Kopie erzeugen (nicht copy-ctor)
176 	aPos		(rScRangeData.aPos),
177 	eType		(rScRangeData.eType),
178 	pDoc		(rScRangeData.pDoc),
179 	nIndex   	(rScRangeData.nIndex),
180     bModified	(rScRangeData.bModified),
181     mnMaxRow    (rScRangeData.mnMaxRow),
182     mnMaxCol    (rScRangeData.mnMaxCol)
183 {}
184 
185 ScRangeData::~ScRangeData()
186 {
187 	delete pCode;
188 }
189 
190 ScDataObject* ScRangeData::Clone() const
191 {
192 	return new ScRangeData(*this);
193 }
194 
195 void ScRangeData::GuessPosition()
196 {
197 	//	setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
198 	//	ohne Fehler verabsolutiert werden koennen
199 
200 	DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
201 
202 	SCsCOL nMinCol = 0;
203 	SCsROW nMinRow = 0;
204 	SCsTAB nMinTab = 0;
205 
206 	ScToken* t;
207 	pCode->Reset();
208     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
209 	{
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;
217 
218 		if ( t->GetType() == svDoubleRef )
219 		{
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;
227 		}
228 	}
229 
230 	aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
231 
232 	//!	Test
233 //	DBG_ERROR(String("Pos ")+String((SCCOL)(-nMinCol))+String("/")+
234 //			String((SCROW)(-nMinRow))+String("/")+String((SCTAB)(-nMinTab)));
235 }
236 
237 void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
238 {
239 	ScCompiler aComp(pDoc, aPos, *pCode);
240     aComp.SetGrammar(eGrammar);
241 	aComp.CreateStringFromTokenArray( rSymbol );
242 }
243 
244 void ScRangeData::UpdateSymbol(	rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
245 								const FormulaGrammar::Grammar eGrammar )
246 {
247     ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
248 	ScCompiler aComp( pDoc, rPos, *pTemp.get());
249     aComp.SetGrammar(eGrammar);
250     aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
251 	aComp.CreateStringFromTokenArray( rBuffer );
252 }
253 
254 void ScRangeData::UpdateReference(	UpdateRefMode eUpdateRefMode,
255 									const ScRange& r,
256 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
257 {
258 	sal_Bool bChanged = sal_False;
259 
260 	pCode->Reset();
261 	if( pCode->GetNextReference() )
262 	{
263         sal_Bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED);
264 		ScCompiler aComp( pDoc, aPos, *pCode );
265         aComp.SetGrammar(pDoc->GetGrammar());
266 		const sal_Bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
267 													nDx, nDy, nDz,
268 													bChanged, bSharedFormula);
269 		if (bSharedFormula)
270 		{
271 			if (bRelRef)
272 				eType = eType | RT_SHAREDMOD;
273 			else
274 				eType = eType & ~RT_SHAREDMOD;
275 		}
276 	}
277 
278 	bModified = bChanged;
279 }
280 
281 
282 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
283 {
284 	sal_Bool bChanged = sal_False;
285 
286 	ScToken* t;
287 	pCode->Reset();
288 
289 	while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
290 	{
291 		if( t->GetType() != svIndex )
292 		{
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()))))
300 			{
301 				if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING )
302 					bChanged = sal_True;
303 			}
304 		}
305 	}
306 
307 	bModified = bChanged;
308 }
309 
310 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
311 {
312 	sal_Bool bChanged = sal_False;
313 
314 	ScToken* t;
315 	pCode->Reset();
316 
317 	while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
318 	{
319 		if( t->GetType() != svIndex )
320 		{
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()))))
328 			{
329 				if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING )
330 					bChanged = sal_True;
331 			}
332 		}
333 	}
334 
335 	bModified = bChanged;			// muss direkt hinterher ausgewertet werden
336 }
337 
338 sal_Bool ScRangeData::operator== (const ScRangeData& rData) const		// fuer Undo
339 {
340 	if ( nIndex	!= rData.nIndex	||
341 		 aName	!= rData.aName	||
342 		 aPos	!= rData.aPos	||
343 		 eType	!= rData.eType     ) return sal_False;
344 
345 	sal_uInt16 nLen = pCode->GetLen();
346 	if ( nLen != rData.pCode->GetLen() ) return sal_False;
347 
348 	FormulaToken** ppThis = pCode->GetArray();
349 	FormulaToken** ppOther = rData.pCode->GetArray();
350 
351 	for ( sal_uInt16 i=0; i<nLen; i++ )
352 		if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
353 			return sal_False;
354 
355 	return sal_True;
356 }
357 
358 //UNUSED2009-05 sal_Bool ScRangeData::IsRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
359 //UNUSED2009-05 {
360 //UNUSED2009-05     sal_Bool bRet = sal_False;
361 //UNUSED2009-05     ScRange aRange;
362 //UNUSED2009-05     if ( IsReference(aRange) )
363 //UNUSED2009-05     {
364 //UNUSED2009-05         if ( bStartOnly )
365 //UNUSED2009-05             bRet = ( rPos == aRange.aStart );
366 //UNUSED2009-05         else
367 //UNUSED2009-05             bRet = ( aRange.In( rPos ) );
368 //UNUSED2009-05     }
369 //UNUSED2009-05     return bRet;
370 //UNUSED2009-05 }
371 
372 sal_Bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
373 {
374 	sal_Bool bRet = sal_False;
375 	ScRange aRange;
376 	if ( IsReference(aRange) )
377 		bRet = ( rBlock == aRange );
378 	return bRet;
379 }
380 
381 sal_Bool ScRangeData::IsReference( ScRange& rRange ) const
382 {
383 	if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
384 		return pCode->IsReference( rRange );
385 
386     return sal_False;
387 }
388 
389 sal_Bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
390 {
391 	if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
392     {
393         ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
394         ScCompiler aComp( pDoc, rPos, *pTemp);
395         aComp.SetGrammar(pDoc->GetGrammar());
396         aComp.MoveRelWrap(MAXCOL, MAXROW);
397         return pTemp->IsReference( rRange );
398     }
399 
400     return sal_False;
401 }
402 
403 sal_Bool ScRangeData::IsValidReference( ScRange& rRange ) const
404 {
405     if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
406         return pCode->IsValidReference( rRange );
407 
408     return sal_False;
409 }
410 
411 void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
412 {
413 	pCode->Reset();
414 	if( pCode->GetNextReference() )
415 	{
416         ScRangeData* pRangeData = NULL;     // must not be dereferenced
417 		sal_Bool bChanged;
418 		ScCompiler aComp( pDoc, aPos, *pCode);
419         aComp.SetGrammar(pDoc->GetGrammar());
420 		switch (nFlag)
421 		{
422 			case 1:										// einfache InsertTab (doc.cxx)
423 				pRangeData = aComp.UpdateInsertTab(nOldTable, sal_True );	// und CopyTab (doc2.cxx)
424 				break;
425 			case 2:										// einfaches delete (doc.cxx)
426 				pRangeData = aComp.UpdateDeleteTab(nOldTable, sal_False, sal_True, bChanged);
427 				break;
428 			case 3:										// move (doc2.cxx)
429 			{
430 				pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, sal_True );
431 			}
432 				break;
433 			default:
434 			{
435 				DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
436 			}
437 				break;
438 		}
439 		if (eType&RT_SHARED)
440 		{
441 			if (pRangeData)
442 				eType = eType | RT_SHAREDMOD;
443 			else
444 				eType = eType & ~RT_SHAREDMOD;
445 		}
446 	}
447 }
448 
449 
450 void ScRangeData::MakeValidName( String& rName )		// static
451 {
452     //ScCompiler::InitSymbolsNative();
453 
454     // strip leading invalid characters
455 	xub_StrLen nPos = 0;
456 	xub_StrLen nLen = rName.Len();
457 	while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
458 		++nPos;
459 	if ( nPos>0 )
460 		rName.Erase(0,nPos);
461 
462     // if the first character is an invalid start character, precede with '_'
463 	if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
464 		rName.Insert('_',0);
465 
466     // replace invalid with '_'
467 	nLen = rName.Len();
468 	for (nPos=0; nPos<nLen; nPos++)
469 	{
470 		if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
471 			rName.SetChar( nPos, '_' );
472 	}
473 
474     // Ensure that the proposed name is not a reference under any convention,
475     // same as in IsNameValid()
476 	ScAddress aAddr;
477 	ScRange aRange;
478     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
479     {
480         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
481         // Don't check Parse on VALID, any partial only VALID may result in
482         // #REF! during compile later!
483         while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
484         {
485             //! Range Parse is partially valid also with invalid sheet name,
486             //! Address Parse dito, during compile name would generate a #REF!
487             if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
488                 rName.Insert('_',0);
489         }
490     }
491 }
492 
493 sal_Bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
494 {
495     /* XXX If changed, sc/source/filter/ftools/ftools.cxx
496      * ScfTools::ConvertToScDefinedName needs to be changed too. */
497 	xub_StrLen nPos = 0;
498 	xub_StrLen nLen = rName.Len();
499 	if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
500 		return sal_False;
501 	while ( nPos < nLen )
502 	{
503 		if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
504 			return sal_False;
505 	}
506     ScAddress aAddr;
507 	ScRange aRange;
508     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
509     {
510         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
511         // Don't check Parse on VALID, any partial only VALID may result in
512         // #REF! during compile later!
513         if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
514 		    return sal_False;
515     }
516 	return sal_True;
517 }
518 
519 void ScRangeData::SetMaxRow(SCROW nRow)
520 {
521     mnMaxRow = nRow;
522 }
523 
524 SCROW ScRangeData::GetMaxRow() const
525 {
526     return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
527 }
528 
529 void ScRangeData::SetMaxCol(SCCOL nCol)
530 {
531     mnMaxCol = nCol;
532 }
533 
534 SCCOL ScRangeData::GetMaxCol() const
535 {
536     return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
537 }
538 
539 
540 sal_uInt16 ScRangeData::GetErrCode()
541 {
542 	return pCode ? pCode->GetCodeError() : 0;
543 }
544 
545 sal_Bool ScRangeData::HasReferences() const
546 {
547 	pCode->Reset();
548 	return sal_Bool( pCode->GetNextReference() != NULL );
549 }
550 
551 // bei TransferTab von einem in ein anderes Dokument anpassen,
552 // um Referenzen auf die eigene Tabelle mitzubekommen
553 
554 void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab )
555 {
556 	long nTabDiff = (long)nNewTab - nOldTab;
557 	long nPosDiff = (long)nNewTab - aPos.Tab();
558 	aPos.SetTab( nNewTab );
559 	ScToken* t;
560 	pCode->Reset();
561     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
562 	{
563 		ScSingleRefData& rRef1 = t->GetSingleRef();
564 		if ( rRef1.IsTabRel() )
565             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff );
566 		else
567             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff );
568 		if ( t->GetType() == svDoubleRef )
569 		{
570 			ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
571 			if ( rRef2.IsTabRel() )
572                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff );
573 			else
574                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nTabDiff );
575 		}
576 	}
577 }
578 
579 void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
580 {
581     bool bCompile = false;
582     for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
583     {
584         if ( p->GetOpCode() == ocName )
585         {
586             const sal_uInt16 nOldIndex = p->GetIndex();
587             IndexMap::const_iterator itr = rMap.find(nOldIndex);
588             const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
589             if ( nOldIndex != nNewIndex )
590             {
591                 p->SetIndex( nNewIndex );
592                 bCompile = true;
593             }
594         }
595     }
596     if ( bCompile )
597     {
598         ScCompiler aComp( pDoc, aPos, *pCode);
599         aComp.SetGrammar(pDoc->GetGrammar());
600         aComp.CompileTokenArray();
601     }
602 }
603 
604 
605 void ScRangeData::ValidateTabRefs()
606 {
607 	//	try to make sure all relative references and the reference position
608 	//	are within existing tables, so they can be represented as text
609 	//	(if the range of used tables is more than the existing tables,
610 	//	the result may still contain invalid tables, because the relative
611 	//	references aren't changed so formulas stay the same)
612 
613 	//	find range of used tables
614 
615 	SCTAB nMinTab = aPos.Tab();
616 	SCTAB nMaxTab = nMinTab;
617 	ScToken* t;
618 	pCode->Reset();
619     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
620 	{
621 		ScSingleRefData& rRef1 = t->GetSingleRef();
622 		if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
623 		{
624 			if ( rRef1.nTab < nMinTab )
625 				nMinTab = rRef1.nTab;
626 			if ( rRef1.nTab > nMaxTab )
627 				nMaxTab = rRef1.nTab;
628 		}
629 		if ( t->GetType() == svDoubleRef )
630 		{
631 			ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
632 			if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
633 			{
634 				if ( rRef2.nTab < nMinTab )
635 					nMinTab = rRef2.nTab;
636 				if ( rRef2.nTab > nMaxTab )
637 					nMaxTab = rRef2.nTab;
638 			}
639 		}
640 	}
641 
642 	SCTAB nTabCount = pDoc->GetTableCount();
643 	if ( nMaxTab >= nTabCount && nMinTab > 0 )
644 	{
645 		//	move position and relative tab refs
646 		//	The formulas that use the name are not changed by this
647 
648 		SCTAB nMove = nMinTab;
649 		aPos.SetTab( aPos.Tab() - nMove );
650 
651 		pCode->Reset();
652         while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
653 		{
654 			ScSingleRefData& rRef1 = t->GetSingleRef();
655 			if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
656                 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
657 			if ( t->GetType() == svDoubleRef )
658 			{
659 				ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
660 				if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
661                     rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove );
662 			}
663 		}
664 	}
665 }
666 
667 
668 extern "C" int
669 #ifdef WNT
670 __cdecl
671 #endif
672 ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
673 {
674 	return (int) ScGlobal::GetCollator()->compareString(
675 			(*(const ScRangeData**)p1)->GetName(),
676 			(*(const ScRangeData**)p2)->GetName() );
677 }
678 
679 
680 //========================================================================
681 // ScRangeName
682 //========================================================================
683 
684 ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
685 				ScSortedCollection ( rScRangeName ),
686 				pDoc ( pDocument ),
687 				nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
688 {
689 	for (sal_uInt16 i = 0; i < nCount; i++)
690 	{
691 		((ScRangeData*)At(i))->SetDocument(pDocument);
692 		((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
693 	}
694 }
695 
696 short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
697 {
698 	sal_uInt16 i1 = ((ScRangeData*)pKey1)->GetIndex();
699 	sal_uInt16 i2 = ((ScRangeData*)pKey2)->GetIndex();
700 	return (short) i1 - (short) i2;
701 }
702 
703 sal_Bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex ) const
704 {
705     // SearchNameUpper must be called with an upper-case search string
706 
707     sal_uInt16 i = 0;
708     while (i < nCount)
709     {
710         if ( ((*this)[i])->GetUpperName() == rUpperName )
711         {
712             rIndex = i;
713             return sal_True;
714         }
715         i++;
716     }
717     return sal_False;
718 }
719 
720 sal_Bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex ) const
721 {
722     if ( nCount > 0 )
723         return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex );
724     else
725         return sal_False;
726 }
727 
728 void ScRangeName::UpdateReference(	UpdateRefMode eUpdateRefMode,
729 									const ScRange& rRange,
730 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
731 {
732 	for (sal_uInt16 i=0; i<nCount; i++)
733 		((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
734 												   nDx, nDy, nDz);
735 }
736 
737 void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
738 {
739 	for (sal_uInt16 i=0; i<nCount; i++)
740 		((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
741 }
742 
743 void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
744 {
745 	for (sal_uInt16 i=0; i<nCount; i++)
746 		((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
747 }
748 
749 sal_Bool ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
750 {
751 	return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
752 }
753 
754 sal_Bool ScRangeName::Insert(ScDataObject* pScDataObject)
755 {
756 	if (!((ScRangeData*)pScDataObject)->GetIndex())		// schon gesetzt?
757 	{
758 		((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() );
759 	}
760 
761 	return ScSortedCollection::Insert(pScDataObject);
762 }
763 
764 // Suche nach einem freien Index
765 
766 sal_uInt16 ScRangeName::GetEntryIndex()
767 {
768 	sal_uInt16 nLast = 0;
769 	for ( sal_uInt16 i = 0; i < nCount; i++ )
770 	{
771 		sal_uInt16 nIdx = ((ScRangeData*)pItems[i])->GetIndex();
772 		if( nIdx > nLast )
773 		{
774 			nLast = nIdx;
775 		}
776 	}
777 	return nLast + 1;
778 }
779 
780 ScRangeData* ScRangeName::FindIndex( sal_uInt16 nIndex )
781 {
782 	ScRangeData aDataObj( nIndex );
783 	sal_uInt16 n;
784 	if( Search( &aDataObj, n ) )
785 		return (*this)[ n ];
786 	else
787 		return NULL;
788 }
789 
790 //UNUSED2009-05 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
791 //UNUSED2009-05 {
792 //UNUSED2009-05     if ( pItems )
793 //UNUSED2009-05     {
794 //UNUSED2009-05         for ( sal_uInt16 i = 0; i < nCount; i++ )
795 //UNUSED2009-05             if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
796 //UNUSED2009-05                 return (ScRangeData*)pItems[i];
797 //UNUSED2009-05     }
798 //UNUSED2009-05     return NULL;
799 //UNUSED2009-05 }
800 
801 ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
802 {
803 	if ( pItems )
804 	{
805 		for ( sal_uInt16 i = 0; i < nCount; i++ )
806 			if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
807 				return (ScRangeData*)pItems[i];
808 	}
809 	return NULL;
810 }
811 
812 void ScRangeName::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
813 {
814 	for (sal_uInt16 i=0; i<nCount; i++)
815 		((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
816 }
817 
818 
819 
820 
821