xref: /trunk/main/sc/source/core/tool/rangenam.cxx (revision dffa72de)
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 
ScRangeData(sal_uInt16 n)54 ScRangeData::ScRangeData( sal_uInt16 n )
55            : pCode( NULL ), nIndex( n ), bModified( sal_False ), mnMaxRow(-1), mnMaxCol(-1), aRangeNameScope( MAXTABCOUNT )
56 {}
57 
ScRangeData(ScDocument * pDok,const String & rName,const String & rSymbol,const ScAddress & rAddress,RangeType nType,const FormulaGrammar::Grammar eGrammar)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 				aRangeNameScope( MAXTABCOUNT )
75 {
76 	if (rSymbol.Len() > 0)
77 	{
78 		ScCompiler aComp( pDoc, aPos );
79         aComp.SetGrammar(eGrammar);
80 		pCode = aComp.CompileString( rSymbol );
81 		if( !pCode->GetCodeError() )
82 		{
83 			pCode->Reset();
84 			FormulaToken* p = pCode->GetNextReference();
85 			if( p )// genau eine Referenz als erstes
86 			{
87 				if( p->GetType() == svSingleRef )
88 					eType = eType | RT_ABSPOS;
89 				else
90 					eType = eType | RT_ABSAREA;
91 			}
92 			// ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
93 			// Dies ist fuer die manuelle Eingabe
94 			aComp.CompileTokenArray();
95 			pCode->DelRPN();
96 		}
97 	}
98     else
99     {
100         // #i63513#/#i65690# don't leave pCode as NULL.
101         // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
102         // to ensure same behavior if unnecessary copying is left out.
103 
104         pCode = new ScTokenArray();
105     }
106 }
107 
ScRangeData(ScDocument * pDok,const String & rName,const ScTokenArray & rArr,const ScAddress & rAddress,RangeType nType)108 ScRangeData::ScRangeData( ScDocument* pDok,
109 						  const String& rName,
110 						  const ScTokenArray& rArr,
111                           const ScAddress& rAddress,
112 						  RangeType nType ) :
113 				aName		( rName ),
114                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
115 				pCode		( new ScTokenArray( rArr ) ),
116 				aPos		( rAddress ),
117 				eType		( nType ),
118 				pDoc		( pDok ),
119 				nIndex		( 0 ),
120                 bModified	( sal_False ),
121                 mnMaxRow    (-1),
122                 mnMaxCol    (-1),
123 				aRangeNameScope( MAXTABCOUNT )
124 {
125 	if( !pCode->GetCodeError() )
126 	{
127 		pCode->Reset();
128 		FormulaToken* p = pCode->GetNextReference();
129 		if( p )// genau eine Referenz als erstes
130 		{
131 			if( p->GetType() == svSingleRef )
132 				eType = eType | RT_ABSPOS;
133 			else
134 				eType = eType | RT_ABSAREA;
135 		}
136 		// Die Importfilter haben diesen Test nicht,
137 		// da die benannten Bereiche z.T. noch unvollstaendig sind.
138 //		if( !pCode->GetCodeLen() )
139 //		{
140 //			// ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
141 //			ScCompiler aComp( pDok, aPos, *pCode );
142 //			aComp.CompileTokenArray();
143 //			pCode->DelRPN();
144 //		}
145 	}
146 }
147 
ScRangeData(ScDocument * pDok,const String & rName,const ScAddress & rTarget)148 ScRangeData::ScRangeData( ScDocument* pDok,
149 						  const String& rName,
150 						  const ScAddress& rTarget ) :
151 				aName		( rName ),
152                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
153 				pCode		( new ScTokenArray() ),
154 				aPos		( rTarget ),
155 				eType		( RT_NAME ),
156 				pDoc		( pDok ),
157 				nIndex		( 0 ),
158                 bModified	( sal_False ),
159                 mnMaxRow    (-1),
160                 mnMaxCol    (-1),
161 				aRangeNameScope( MAXTABCOUNT )
162 {
163 	ScSingleRefData aRefData;
164 	aRefData.InitAddress( rTarget );
165 	aRefData.SetFlag3D( sal_True );
166 	pCode->AddSingleReference( aRefData );
167 	ScCompiler aComp( pDoc, aPos, *pCode );
168     aComp.SetGrammar(pDoc->GetGrammar());
169 	aComp.CompileTokenArray();
170 	if ( !pCode->GetCodeError() )
171 		eType |= RT_ABSPOS;
172 }
173 
ScRangeData(const ScRangeData & rScRangeData)174 ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
175     ScDataObject(),
176 	aName 	(rScRangeData.aName),
177     aUpperName  (rScRangeData.aUpperName),
178 	pCode		(rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()),		// echte Kopie erzeugen (nicht copy-ctor)
179 	aPos		(rScRangeData.aPos),
180 	eType		(rScRangeData.eType),
181 	pDoc		(rScRangeData.pDoc),
182 	nIndex   	(rScRangeData.nIndex),
183     bModified	(rScRangeData.bModified),
184     mnMaxRow    (rScRangeData.mnMaxRow),
185     mnMaxCol    (rScRangeData.mnMaxCol),
186 	aRangeNameScope (rScRangeData.aRangeNameScope)
187 {}
188 
~ScRangeData()189 ScRangeData::~ScRangeData()
190 {
191 	delete pCode;
192 }
193 
Clone() const194 ScDataObject* ScRangeData::Clone() const
195 {
196 	return new ScRangeData(*this);
197 }
198 
GuessPosition()199 void ScRangeData::GuessPosition()
200 {
201 	//	setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
202 	//	ohne Fehler verabsolutiert werden koennen
203 
204 	DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
205 
206 	SCsCOL nMinCol = 0;
207 	SCsROW nMinRow = 0;
208 	SCsTAB nMinTab = 0;
209 
210 	ScToken* t;
211 	pCode->Reset();
212     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
213 	{
214 		ScSingleRefData& rRef1 = t->GetSingleRef();
215 		if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol )
216 			nMinCol = rRef1.nRelCol;
217 		if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow )
218 			nMinRow = rRef1.nRelRow;
219 		if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab )
220 			nMinTab = rRef1.nRelTab;
221 
222 		if ( t->GetType() == svDoubleRef )
223 		{
224 			ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
225 			if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol )
226 				nMinCol = rRef2.nRelCol;
227 			if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow )
228 				nMinRow = rRef2.nRelRow;
229 			if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab )
230 				nMinTab = rRef2.nRelTab;
231 		}
232 	}
233 
234 	aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
235 
236 	//!	Test
237 //	DBG_ERROR(String("Pos ")+String((SCCOL)(-nMinCol))+String("/")+
238 //			String((SCROW)(-nMinRow))+String("/")+String((SCTAB)(-nMinTab)));
239 }
240 
GetSymbol(String & rSymbol,const FormulaGrammar::Grammar eGrammar) const241 void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
242 {
243 	ScCompiler aComp(pDoc, aPos, *pCode);
244     aComp.SetGrammar(eGrammar);
245 	aComp.CreateStringFromTokenArray( rSymbol );
246 }
247 
UpdateSymbol(rtl::OUStringBuffer & rBuffer,const ScAddress & rPos,const FormulaGrammar::Grammar eGrammar)248 void ScRangeData::UpdateSymbol(	rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
249 								const FormulaGrammar::Grammar eGrammar )
250 {
251     ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
252 	ScCompiler aComp( pDoc, rPos, *pTemp.get());
253     aComp.SetGrammar(eGrammar);
254     aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
255 	aComp.CreateStringFromTokenArray( rBuffer );
256 }
257 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & r,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)258 void ScRangeData::UpdateReference(	UpdateRefMode eUpdateRefMode,
259 									const ScRange& r,
260 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
261 {
262 	sal_Bool bChanged = sal_False;
263 
264 	pCode->Reset();
265 	if( pCode->GetNextReference() )
266 	{
267         sal_Bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED);
268 		ScCompiler aComp( pDoc, aPos, *pCode );
269         aComp.SetGrammar(pDoc->GetGrammar());
270 		const sal_Bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
271 													nDx, nDy, nDz,
272 													bChanged, bSharedFormula);
273 		if (bSharedFormula)
274 		{
275 			if (bRelRef)
276 				eType = eType | RT_SHAREDMOD;
277 			else
278 				eType = eType & ~RT_SHAREDMOD;
279 		}
280 	}
281 
282 	bModified = bChanged;
283 }
284 
285 
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest)286 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
287 {
288 	sal_Bool bChanged = sal_False;
289 
290 	ScToken* t;
291 	pCode->Reset();
292 
293 	while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
294 	{
295 		if( t->GetType() != svIndex )
296 		{
297 			SingleDoubleRefModifier aMod( *t );
298 			ScComplexRefData& rRef = aMod.Ref();
299 			if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
300 					(!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
301 				( t->GetType() == svSingleRef ||
302 				(!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
303 					(!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
304 			{
305 				if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING )
306 					bChanged = sal_True;
307 			}
308 		}
309 	}
310 
311 	bModified = bChanged;
312 }
313 
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)314 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
315 {
316 	sal_Bool bChanged = sal_False;
317 
318 	ScToken* t;
319 	pCode->Reset();
320 
321 	while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
322 	{
323 		if( t->GetType() != svIndex )
324 		{
325 			SingleDoubleRefModifier aMod( *t );
326 			ScComplexRefData& rRef = aMod.Ref();
327 			if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
328 					(!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
329 				( t->GetType() == svSingleRef ||
330 				(!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
331 					(!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
332 			{
333 				if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING )
334 					bChanged = sal_True;
335 			}
336 		}
337 	}
338 
339 	bModified = bChanged;			// muss direkt hinterher ausgewertet werden
340 }
341 
operator ==(const ScRangeData & rData) const342 sal_Bool ScRangeData::operator== (const ScRangeData& rData) const		// fuer Undo
343 {
344 	if ( nIndex	!= rData.nIndex	||
345 		 aName	!= rData.aName	||
346 		 aPos	!= rData.aPos	||
347 		 eType	!= rData.eType   || aRangeNameScope  != rData.aRangeNameScope  ) return sal_False;
348 
349 	sal_uInt16 nLen = pCode->GetLen();
350 	if ( nLen != rData.pCode->GetLen() ) return sal_False;
351 
352 	FormulaToken** ppThis = pCode->GetArray();
353 	FormulaToken** ppOther = rData.pCode->GetArray();
354 
355 	for ( sal_uInt16 i=0; i<nLen; i++ )
356 		if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
357 			return sal_False;
358 
359 	return sal_True;
360 }
361 
362 //UNUSED2009-05 sal_Bool ScRangeData::IsRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
363 //UNUSED2009-05 {
364 //UNUSED2009-05     sal_Bool bRet = sal_False;
365 //UNUSED2009-05     ScRange aRange;
366 //UNUSED2009-05     if ( IsReference(aRange) )
367 //UNUSED2009-05     {
368 //UNUSED2009-05         if ( bStartOnly )
369 //UNUSED2009-05             bRet = ( rPos == aRange.aStart );
370 //UNUSED2009-05         else
371 //UNUSED2009-05             bRet = ( aRange.In( rPos ) );
372 //UNUSED2009-05     }
373 //UNUSED2009-05     return bRet;
374 //UNUSED2009-05 }
375 
IsRangeAtBlock(const ScRange & rBlock) const376 sal_Bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
377 {
378 	sal_Bool bRet = sal_False;
379 	ScRange aRange;
380 	if ( IsReference(aRange) )
381 		bRet = ( rBlock == aRange );
382 	return bRet;
383 }
384 
IsReference(ScRange & rRange) const385 sal_Bool ScRangeData::IsReference( ScRange& rRange ) const
386 {
387 	if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
388 		return pCode->IsReference( rRange );
389 
390     return sal_False;
391 }
392 
IsReference(ScRange & rRange,const ScAddress & rPos) const393 sal_Bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
394 {
395 	if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
396     {
397         ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
398         ScCompiler aComp( pDoc, rPos, *pTemp);
399         aComp.SetGrammar(pDoc->GetGrammar());
400         aComp.MoveRelWrap(MAXCOL, MAXROW);
401         return pTemp->IsReference( rRange );
402     }
403 
404     return sal_False;
405 }
406 
IsValidReference(ScRange & rRange) const407 sal_Bool ScRangeData::IsValidReference( ScRange& rRange ) const
408 {
409     if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
410         return pCode->IsValidReference( rRange );
411 
412     return sal_False;
413 }
414 
415 /* modification to update named range scope */
UpdateTabRef(SCTAB nOldTable,sal_uInt16 nFlag,SCTAB nNewTable)416 void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
417 {
418 	pCode->Reset();
419 	if( pCode->GetNextReference() )
420 	{
421         ScRangeData* pRangeData = NULL;     // must not be dereferenced
422 		sal_Bool bChanged;
423 		ScCompiler aComp( pDoc, aPos, *pCode);
424         aComp.SetGrammar(pDoc->GetGrammar());
425 		switch (nFlag)
426 		{
427 			case 1:										// einfache InsertTab (doc.cxx)
428 			case 4:
429 			       pRangeData = aComp.UpdateInsertTab(nOldTable, true );	// und CopyTab (doc2.cxx)
430 				if ( (aRangeNameScope != MAXTABCOUNT) && ( aRangeNameScope >= nOldTable) && ( aRangeNameScope != MAXTAB ) )
431 					aRangeNameScope ++;
432 				break;
433 			case 2:										// einfaches delete (doc.cxx)
434 				pRangeData = aComp.UpdateDeleteTab(nOldTable, false, true, bChanged);
435 				if  ( aRangeNameScope != MAXTABCOUNT && aRangeNameScope > nOldTable )
436                                     aRangeNameScope --;
437 				break;
438 			case 3:										// move (doc2.cxx)
439 			{
440 				pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, true );
441 				if ( aRangeNameScope != MAXTABCOUNT )
442 				{
443 					if ( aRangeNameScope == nOldTable )
444 						aRangeNameScope = nNewTable;
445 					else if ( (aRangeNameScope > nOldTable) && (aRangeNameScope <= nNewTable) )
446 						aRangeNameScope--;
447 					else if ( (aRangeNameScope >= nNewTable) && (aRangeNameScope < nOldTable) )
448 						aRangeNameScope++;
449 				}
450 			}
451 			break;
452 			case 5:
453 			{
454                                 //when copying a sheet, this will be invoked to update the new name range's address in the new sheet
455                                 //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()
456                                 //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
457                                 //only need to change the first one's address to sheet1
458 				pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, true , true);
459 				aRangeNameScope = nNewTable;
460 			}
461 			break;
462 			default:
463 			{
464 				DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
465 			}
466 				break;
467 		}
468 		if (eType&RT_SHARED)
469 		{
470 			if (pRangeData)
471 				eType = eType | RT_SHAREDMOD;
472 			else
473 				eType = eType & ~RT_SHAREDMOD;
474 		}
475 	}
476 }
477 
478 
MakeValidName(String & rName)479 void ScRangeData::MakeValidName( String& rName )		// static
480 {
481     //ScCompiler::InitSymbolsNative();
482 
483     // strip leading invalid characters
484 	xub_StrLen nPos = 0;
485 	xub_StrLen nLen = rName.Len();
486 	while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
487 		++nPos;
488 	if ( nPos>0 )
489 		rName.Erase(0,nPos);
490 
491     // if the first character is an invalid start character, precede with '_'
492 	if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
493 		rName.Insert('_',0);
494 
495     // replace invalid with '_'
496 	nLen = rName.Len();
497 	for (nPos=0; nPos<nLen; nPos++)
498 	{
499 		if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
500 			rName.SetChar( nPos, '_' );
501 	}
502 
503     // Ensure that the proposed name is not a reference under any convention,
504     // same as in IsNameValid()
505 	ScAddress aAddr;
506 	ScRange aRange;
507     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
508     {
509         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
510         // Don't check Parse on VALID, any partial only VALID may result in
511         // #REF! during compile later!
512         while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
513         {
514             //! Range Parse is partially valid also with invalid sheet name,
515             //! Address Parse dito, during compile name would generate a #REF!
516             if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
517                 rName.Insert('_',0);
518         }
519     }
520 }
521 
IsNameValid(const String & rName,ScDocument * pDoc)522 sal_Bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
523 {
524     /* XXX If changed, sc/source/filter/ftools/ftools.cxx
525      * ScfTools::ConvertToScDefinedName needs to be changed too. */
526 	xub_StrLen nPos = 0;
527 	xub_StrLen nLen = rName.Len();
528 	if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
529 		return sal_False;
530 	while ( nPos < nLen )
531 	{
532 		if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
533 			return sal_False;
534 	}
535     ScAddress aAddr;
536 	ScRange aRange;
537     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
538     {
539         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
540         // Don't check Parse on VALID, any partial only VALID may result in
541         // #REF! during compile later!
542         if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
543 		    return sal_False;
544     }
545 	return sal_True;
546 }
547 
SetMaxRow(SCROW nRow)548 void ScRangeData::SetMaxRow(SCROW nRow)
549 {
550     mnMaxRow = nRow;
551 }
552 
GetMaxRow() const553 SCROW ScRangeData::GetMaxRow() const
554 {
555     return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
556 }
557 
SetMaxCol(SCCOL nCol)558 void ScRangeData::SetMaxCol(SCCOL nCol)
559 {
560     mnMaxCol = nCol;
561 }
562 
GetMaxCol() const563 SCCOL ScRangeData::GetMaxCol() const
564 {
565     return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
566 }
567 
568 /* MAXTABCOUNT - Global, 0 - sheet1, 1 - sheet2, ...		*/
569 /*	MAXTABCOUNT -- Global				*/
570 /*	return value: FALSE -- set fail		 	*/
571 /*			      TRUE  -- set successfully	*/
SetRangeScope(SCTAB Scope)572 bool ScRangeData::SetRangeScope( SCTAB Scope )
573 {
574 	 if ( Scope <= MAXTABCOUNT && Scope >=0 )
575 	 {
576 		aRangeNameScope = Scope;
577 	        return true;
578 	 }
579          return false;
580 
581 }
582 
GetScopeSheetName() const583  String ScRangeData::GetScopeSheetName() const
584 {
585 	if ( aRangeNameScope != MAXTABCOUNT )
586 	{
587             String aTableName;
588             pDoc->GetName( aRangeNameScope, aTableName );
589             return aTableName;
590 	}
591         return EMPTY_STRING;
592 }
593 /* end add */
594 
595 
GetErrCode()596 sal_uInt16 ScRangeData::GetErrCode()
597 {
598 	return pCode ? pCode->GetCodeError() : 0;
599 }
600 
HasReferences() const601 sal_Bool ScRangeData::HasReferences() const
602 {
603 	pCode->Reset();
604 	return sal_Bool( pCode->GetNextReference() != NULL );
605 }
606 
607 // bei TransferTab von einem in ein anderes Dokument anpassen,
608 // um Referenzen auf die eigene Tabelle mitzubekommen
609 
TransferTabRef(SCTAB nOldTab,SCTAB nNewTab)610 void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab )
611 {
612 	long nTabDiff = (long)nNewTab - nOldTab;
613 	long nPosDiff = (long)nNewTab - aPos.Tab();
614 	aPos.SetTab( nNewTab );
615 	ScToken* t;
616 	pCode->Reset();
617     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
618 	{
619 		ScSingleRefData& rRef1 = t->GetSingleRef();
620 		if ( rRef1.IsTabRel() )
621             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff );
622 		else
623             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff );
624 		if ( t->GetType() == svDoubleRef )
625 		{
626 			ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
627 			if ( rRef2.IsTabRel() )
628                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff );
629 			else
630                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nTabDiff );
631 		}
632 	}
633 }
634 
ReplaceRangeNamesInUse(const IndexMap & rMap)635 void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
636 {
637     bool bCompile = false;
638     for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
639     {
640         if ( p->GetOpCode() == ocName )
641         {
642             const sal_uInt16 nOldIndex = p->GetIndex();
643             IndexMap::const_iterator itr = rMap.find(nOldIndex);
644             const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
645             if ( nOldIndex != nNewIndex )
646             {
647                 p->SetIndex( nNewIndex );
648                 bCompile = true;
649             }
650         }
651     }
652     if ( bCompile )
653     {
654         ScCompiler aComp( pDoc, aPos, *pCode);
655         aComp.SetGrammar(pDoc->GetGrammar());
656         aComp.CompileTokenArray();
657     }
658 }
659 
660 
ValidateTabRefs()661 void ScRangeData::ValidateTabRefs()
662 {
663 	//	try to make sure all relative references and the reference position
664 	//	are within existing tables, so they can be represented as text
665 	//	(if the range of used tables is more than the existing tables,
666 	//	the result may still contain invalid tables, because the relative
667 	//	references aren't changed so formulas stay the same)
668 
669 	//	find range of used tables
670 
671 	SCTAB nMinTab = aPos.Tab();
672 	SCTAB nMaxTab = nMinTab;
673 	ScToken* t;
674 	pCode->Reset();
675     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
676 	{
677 		ScSingleRefData& rRef1 = t->GetSingleRef();
678 		if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
679 		{
680 			if ( rRef1.nTab < nMinTab )
681 				nMinTab = rRef1.nTab;
682 			if ( rRef1.nTab > nMaxTab )
683 				nMaxTab = rRef1.nTab;
684 		}
685 		if ( t->GetType() == svDoubleRef )
686 		{
687 			ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
688 			if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
689 			{
690 				if ( rRef2.nTab < nMinTab )
691 					nMinTab = rRef2.nTab;
692 				if ( rRef2.nTab > nMaxTab )
693 					nMaxTab = rRef2.nTab;
694 			}
695 		}
696 	}
697 
698 	SCTAB nTabCount = pDoc->GetTableCount();
699 	if ( nMaxTab >= nTabCount && nMinTab > 0 )
700 	{
701 		//	move position and relative tab refs
702 		//	The formulas that use the name are not changed by this
703 
704 		SCTAB nMove = nMinTab;
705 		aPos.SetTab( aPos.Tab() - nMove );
706 
707 		pCode->Reset();
708         while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
709 		{
710 			ScSingleRefData& rRef1 = t->GetSingleRef();
711 			if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
712                 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
713 			if ( t->GetType() == svDoubleRef )
714 			{
715 				ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
716 				if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
717                     rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove );
718 			}
719 		}
720 	}
721 }
722 
723 
724 extern "C" int
725 #ifdef WNT
726 __cdecl
727 #endif
ScRangeData_QsortNameCompare(const void * p1,const void * p2)728 ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
729 {
730 	return (int) ScGlobal::GetCollator()->compareString(
731 			(*(const ScRangeData**)p1)->GetName(),
732 			(*(const ScRangeData**)p2)->GetName() );
733 }
734 
735 
736 //========================================================================
737 // ScRangeName
738 //========================================================================
739 
ScRangeName(const ScRangeName & rScRangeName,ScDocument * pDocument)740 ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
741 				ScSortedCollection ( rScRangeName ),
742 				pDoc ( pDocument ),
743 				nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
744 {
745 	for (sal_uInt16 i = 0; i < nCount; i++)
746 	{
747 		((ScRangeData*)At(i))->SetDocument(pDocument);
748 		((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
749 	}
750 }
751 
Compare(ScDataObject * pKey1,ScDataObject * pKey2) const752 short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
753 {
754 	sal_uInt16 i1 = ((ScRangeData*)pKey1)->GetIndex();
755 	sal_uInt16 i2 = ((ScRangeData*)pKey2)->GetIndex();
756 	return (short) i1 - (short) i2;
757 }
758 
759 /* added  for scope support */
HasRangeinSheetScope(SCTAB Scope)760 bool ScRangeName::HasRangeinSheetScope(SCTAB Scope)
761 {
762     for (sal_uInt16 i = 0; i < nCount; i++)
763         if  (((*this)[i])->GetRangeScope() == Scope)
764             return true;
765 
766     return false;
767 }
768 /* if Scope is global, no range will be removed */
769 /* if no range is removed, return value is false */
RemoveRangeinScope(SCTAB Scope)770 bool ScRangeName::RemoveRangeinScope(SCTAB Scope)
771 {
772      bool bRemoved = false;
773 
774      if ( Scope == MAXTABCOUNT )
775          return bRemoved;
776 
777      sal_uInt16 i = 0;
778      while (i < nCount)
779      {
780           if  (((*this)[i])->GetRangeScope() == Scope)
781           {
782                Free( (*this)[i] );
783                bRemoved = true;
784           }
785           else
786                i++;
787      }
788 
789      return bRemoved;
790 }
791 /* it's designed for "Copy Sheet" action. So no name conflict check when copy range to new scope */
792 /* if the old scope or the new scope is global, no range will be copied */
793 /* if no range is copied, the return value is false */
CopyRangeinScope(SCTAB oldScope,SCTAB newScope)794 bool ScRangeName::CopyRangeinScope(SCTAB oldScope, SCTAB newScope)
795 {
796        bool bCopied = false;
797 
798        if ( (oldScope == MAXTABCOUNT)||(newScope ==MAXTABCOUNT) )
799            return bCopied;
800 
801        sal_uInt16 originalCount = nCount;
802        for ( sal_uInt16 i = 0; i < originalCount; i++)
803            if ( ((*this)[i])->GetRangeScope() == oldScope)
804            {
805                  ScRangeData * aCopiedRange = (ScRangeData *)(*this)[i]->Clone();
806                  aCopiedRange->UpdateTabRef(oldScope, 5 , newScope);
807                  aCopiedRange->SetIndex(GetEntryIndex());
808                  Insert( aCopiedRange );
809                  bCopied = true;
810            }
811 
812        return bCopied;
813 }
814 /* end add */
SearchNameUpper(const String & rUpperName,sal_uInt16 & rIndex,SCTAB Scope) const815 bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex, SCTAB Scope ) const
816 {
817     // SearchNameUpper must be called with an upper-case search string
818 
819     sal_uInt16 i = 0;
820     while (i < nCount)
821     {
822         if ( (((*this)[i])->GetUpperName() == rUpperName)
823 			&& (((*this)[i])->GetRangeScope() == Scope ))
824         {
825             rIndex = i;
826             return true;
827         }
828         i++;
829     }
830     return false;
831 }
832 
SearchName(const String & rName,sal_uInt16 & rIndex,SCTAB Scope) const833 bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex, SCTAB Scope ) const
834 {
835     if ( nCount > 0 )
836         return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex, Scope );
837     else
838         return false;
839 }
840 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)841 void ScRangeName::UpdateReference(	UpdateRefMode eUpdateRefMode,
842 									const ScRange& rRange,
843 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
844 {
845 	for (sal_uInt16 i=0; i<nCount; i++)
846 		((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
847 												   nDx, nDy, nDz);
848 }
849 
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest)850 void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
851 {
852 	for (sal_uInt16 i=0; i<nCount; i++)
853 		((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
854 }
855 
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)856 void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
857 {
858 	for (sal_uInt16 i=0; i<nCount; i++)
859 		((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
860 }
861 
IsEqual(ScDataObject * pKey1,ScDataObject * pKey2) const862 sal_Bool ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
863 {
864 	return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
865 }
866 
Insert(ScDataObject * pScDataObject)867 sal_Bool ScRangeName::Insert(ScDataObject* pScDataObject)
868 {
869 	if (!((ScRangeData*)pScDataObject)->GetIndex())		// schon gesetzt?
870 	{
871 		((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() );
872 	}
873 
874 	return ScSortedCollection::Insert(pScDataObject);
875 }
876 
877 // Suche nach einem freien Index
878 
GetEntryIndex()879 sal_uInt16 ScRangeName::GetEntryIndex()
880 {
881 	sal_uInt16 nLast = 0;
882 	for ( sal_uInt16 i = 0; i < nCount; i++ )
883 	{
884 		sal_uInt16 nIdx = ((ScRangeData*)pItems[i])->GetIndex();
885 		if( nIdx > nLast )
886 		{
887 			nLast = nIdx;
888 		}
889 	}
890 	return nLast + 1;
891 }
892 
FindIndex(sal_uInt16 nIndex)893 ScRangeData* ScRangeName::FindIndex( sal_uInt16 nIndex )
894 {
895 	ScRangeData aDataObj( nIndex );
896 	sal_uInt16 n;
897 	if( Search( &aDataObj, n ) )
898 		return (*this)[ n ];
899 	else
900 		return NULL;
901 }
902 
903 //UNUSED2009-05 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
904 //UNUSED2009-05 {
905 //UNUSED2009-05     if ( pItems )
906 //UNUSED2009-05     {
907 //UNUSED2009-05         for ( sal_uInt16 i = 0; i < nCount; i++ )
908 //UNUSED2009-05             if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
909 //UNUSED2009-05                 return (ScRangeData*)pItems[i];
910 //UNUSED2009-05     }
911 //UNUSED2009-05     return NULL;
912 //UNUSED2009-05 }
913 
GetRangeAtBlock(const ScRange & rBlock) const914 ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
915 {
916 	if ( pItems )
917 	{
918 		for ( sal_uInt16 i = 0; i < nCount; i++ )
919 			if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
920 				return (ScRangeData*)pItems[i];
921 	}
922 	return NULL;
923 }
924 
UpdateTabRef(SCTAB nOldTable,sal_uInt16 nFlag,SCTAB nNewTable)925 void ScRangeName::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
926 {
927        if (nFlag == 2)
928            RemoveRangeinScope( nOldTable );
929 
930        for (sal_uInt16 i=0; i<nCount; i++)
931             ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
932 
933        if (nFlag ==4)
934        {
935             SCTAB copyScope = nOldTable > nNewTable ? nNewTable : nNewTable+1;
936             CopyRangeinScope( copyScope, nOldTable);
937        }
938 }
939 
940 
941 
942