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