xref: /trunk/main/sc/source/core/tool/rangenam.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 //------------------------------------------------------------------------
33 
34 #include <tools/debug.hxx>
35 #include <string.h>
36 #include <memory>
37 #include <unotools/collatorwrapper.hxx>
38 #include <unotools/transliterationwrapper.hxx>
39 
40 #include "token.hxx"
41 #include "tokenarray.hxx"
42 #include "rangenam.hxx"
43 #include "global.hxx"
44 #include "compiler.hxx"
45 #include "rangeutl.hxx"
46 #include "rechead.hxx"
47 #include "refupdat.hxx"
48 #include "document.hxx"
49 
50 using namespace formula;
51 
52 //========================================================================
53 // ScRangeData
54 //========================================================================
55 
56 // Interner ctor fuer das Suchen nach einem Index
57 
58 ScRangeData::ScRangeData( sal_uInt16 n )
59            : pCode( NULL ), nIndex( n ), bModified( sal_False ), mnMaxRow(-1), mnMaxCol(-1)
60 {}
61 
62 ScRangeData::ScRangeData( ScDocument* pDok,
63                           const String& rName,
64                           const String& rSymbol,
65                           const ScAddress& rAddress,
66                           RangeType nType,
67                           const FormulaGrammar::Grammar eGrammar ) :
68                 aName       ( rName ),
69                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
70                 pCode       ( NULL ),
71                 aPos        ( rAddress ),
72                 eType       ( nType ),
73                 pDoc        ( pDok ),
74                 nIndex      ( 0 ),
75                 bModified   ( sal_False ),
76                 mnMaxRow    (-1),
77                 mnMaxCol    (-1)
78 {
79     if (rSymbol.Len() > 0)
80     {
81         ScCompiler aComp( pDoc, aPos );
82         aComp.SetGrammar(eGrammar);
83         pCode = aComp.CompileString( rSymbol );
84         if( !pCode->GetCodeError() )
85         {
86             pCode->Reset();
87             FormulaToken* p = pCode->GetNextReference();
88             if( p )// genau eine Referenz als erstes
89             {
90                 if( p->GetType() == svSingleRef )
91                     eType = eType | RT_ABSPOS;
92                 else
93                     eType = eType | RT_ABSAREA;
94             }
95             // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
96             // Dies ist fuer die manuelle Eingabe
97             aComp.CompileTokenArray();
98             pCode->DelRPN();
99         }
100     }
101     else
102     {
103         // #i63513#/#i65690# don't leave pCode as NULL.
104         // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
105         // to ensure same behavior if unnecessary copying is left out.
106 
107         pCode = new ScTokenArray();
108     }
109 }
110 
111 ScRangeData::ScRangeData( ScDocument* pDok,
112                           const String& rName,
113                           const ScTokenArray& rArr,
114                           const ScAddress& rAddress,
115                           RangeType nType ) :
116                 aName       ( rName ),
117                 aUpperName  ( ScGlobal::pCharClass->upper( rName ) ),
118                 pCode       ( new ScTokenArray( rArr ) ),
119                 aPos        ( rAddress ),
120                 eType       ( nType ),
121                 pDoc        ( pDok ),
122                 nIndex      ( 0 ),
123                 bModified   ( sal_False ),
124                 mnMaxRow    (-1),
125                 mnMaxCol    (-1)
126 {
127     if( !pCode->GetCodeError() )
128     {
129         pCode->Reset();
130         FormulaToken* p = pCode->GetNextReference();
131         if( p )// genau eine Referenz als erstes
132         {
133             if( p->GetType() == svSingleRef )
134                 eType = eType | RT_ABSPOS;
135             else
136                 eType = eType | RT_ABSAREA;
137         }
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 //      }
147     }
148 }
149 
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   ( sal_False ),
161                 mnMaxRow    (-1),
162                 mnMaxCol    (-1)
163 {
164     ScSingleRefData aRefData;
165     aRefData.InitAddress( rTarget );
166     aRefData.SetFlag3D( sal_True );
167     pCode->AddSingleReference( aRefData );
168     ScCompiler aComp( pDoc, aPos, *pCode );
169     aComp.SetGrammar(pDoc->GetGrammar());
170     aComp.CompileTokenArray();
171     if ( !pCode->GetCodeError() )
172         eType |= RT_ABSPOS;
173 }
174 
175 ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
176     ScDataObject(),
177     aName   (rScRangeData.aName),
178     aUpperName  (rScRangeData.aUpperName),
179     pCode       (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()),        // echte Kopie erzeugen (nicht copy-ctor)
180     aPos        (rScRangeData.aPos),
181     eType       (rScRangeData.eType),
182     pDoc        (rScRangeData.pDoc),
183     nIndex      (rScRangeData.nIndex),
184     bModified   (rScRangeData.bModified),
185     mnMaxRow    (rScRangeData.mnMaxRow),
186     mnMaxCol    (rScRangeData.mnMaxCol)
187 {}
188 
189 ScRangeData::~ScRangeData()
190 {
191     delete pCode;
192 }
193 
194 ScDataObject* ScRangeData::Clone() const
195 {
196     return new ScRangeData(*this);
197 }
198 
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 
241 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 
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 
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 
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 
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 
342 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     ) 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 
376 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 
385 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 
393 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 
407 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 void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
416 {
417     pCode->Reset();
418     if( pCode->GetNextReference() )
419     {
420         ScRangeData* pRangeData = NULL;     // must not be dereferenced
421         sal_Bool bChanged;
422         ScCompiler aComp( pDoc, aPos, *pCode);
423         aComp.SetGrammar(pDoc->GetGrammar());
424         switch (nFlag)
425         {
426             case 1:                                     // einfache InsertTab (doc.cxx)
427                 pRangeData = aComp.UpdateInsertTab(nOldTable, sal_True );   // und CopyTab (doc2.cxx)
428                 break;
429             case 2:                                     // einfaches delete (doc.cxx)
430                 pRangeData = aComp.UpdateDeleteTab(nOldTable, sal_False, sal_True, bChanged);
431                 break;
432             case 3:                                     // move (doc2.cxx)
433             {
434                 pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, sal_True );
435             }
436                 break;
437             default:
438             {
439                 DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
440             }
441                 break;
442         }
443         if (eType&RT_SHARED)
444         {
445             if (pRangeData)
446                 eType = eType | RT_SHAREDMOD;
447             else
448                 eType = eType & ~RT_SHAREDMOD;
449         }
450     }
451 }
452 
453 
454 void ScRangeData::MakeValidName( String& rName )        // static
455 {
456     //ScCompiler::InitSymbolsNative();
457 
458     // strip leading invalid characters
459     xub_StrLen nPos = 0;
460     xub_StrLen nLen = rName.Len();
461     while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
462         ++nPos;
463     if ( nPos>0 )
464         rName.Erase(0,nPos);
465 
466     // if the first character is an invalid start character, precede with '_'
467     if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
468         rName.Insert('_',0);
469 
470     // replace invalid with '_'
471     nLen = rName.Len();
472     for (nPos=0; nPos<nLen; nPos++)
473     {
474         if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
475             rName.SetChar( nPos, '_' );
476     }
477 
478     // Ensure that the proposed name is not a reference under any convention,
479     // same as in IsNameValid()
480     ScAddress aAddr;
481     ScRange aRange;
482     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
483     {
484         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
485         // Don't check Parse on VALID, any partial only VALID may result in
486         // #REF! during compile later!
487         while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
488         {
489             //! Range Parse is partially valid also with invalid sheet name,
490             //! Address Parse dito, during compile name would generate a #REF!
491             if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
492                 rName.Insert('_',0);
493         }
494     }
495 }
496 
497 sal_Bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
498 {
499     /* XXX If changed, sc/source/filter/ftools/ftools.cxx
500      * ScfTools::ConvertToScDefinedName needs to be changed too. */
501     xub_StrLen nPos = 0;
502     xub_StrLen nLen = rName.Len();
503     if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
504         return sal_False;
505     while ( nPos < nLen )
506     {
507         if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
508             return sal_False;
509     }
510     ScAddress aAddr;
511     ScRange aRange;
512     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
513     {
514         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
515         // Don't check Parse on VALID, any partial only VALID may result in
516         // #REF! during compile later!
517         if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
518             return sal_False;
519     }
520     return sal_True;
521 }
522 
523 void ScRangeData::SetMaxRow(SCROW nRow)
524 {
525     mnMaxRow = nRow;
526 }
527 
528 SCROW ScRangeData::GetMaxRow() const
529 {
530     return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
531 }
532 
533 void ScRangeData::SetMaxCol(SCCOL nCol)
534 {
535     mnMaxCol = nCol;
536 }
537 
538 SCCOL ScRangeData::GetMaxCol() const
539 {
540     return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
541 }
542 
543 
544 sal_uInt16 ScRangeData::GetErrCode()
545 {
546     return pCode ? pCode->GetCodeError() : 0;
547 }
548 
549 sal_Bool ScRangeData::HasReferences() const
550 {
551     pCode->Reset();
552     return sal_Bool( pCode->GetNextReference() != NULL );
553 }
554 
555 // bei TransferTab von einem in ein anderes Dokument anpassen,
556 // um Referenzen auf die eigene Tabelle mitzubekommen
557 
558 void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab )
559 {
560     long nTabDiff = (long)nNewTab - nOldTab;
561     long nPosDiff = (long)nNewTab - aPos.Tab();
562     aPos.SetTab( nNewTab );
563     ScToken* t;
564     pCode->Reset();
565     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
566     {
567         ScSingleRefData& rRef1 = t->GetSingleRef();
568         if ( rRef1.IsTabRel() )
569             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff );
570         else
571             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff );
572         if ( t->GetType() == svDoubleRef )
573         {
574             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
575             if ( rRef2.IsTabRel() )
576                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff );
577             else
578                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nTabDiff );
579         }
580     }
581 }
582 
583 void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
584 {
585     bool bCompile = false;
586     for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
587     {
588         if ( p->GetOpCode() == ocName )
589         {
590             const sal_uInt16 nOldIndex = p->GetIndex();
591             IndexMap::const_iterator itr = rMap.find(nOldIndex);
592             const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
593             if ( nOldIndex != nNewIndex )
594             {
595                 p->SetIndex( nNewIndex );
596                 bCompile = true;
597             }
598         }
599     }
600     if ( bCompile )
601     {
602         ScCompiler aComp( pDoc, aPos, *pCode);
603         aComp.SetGrammar(pDoc->GetGrammar());
604         aComp.CompileTokenArray();
605     }
606 }
607 
608 
609 void ScRangeData::ValidateTabRefs()
610 {
611     //  try to make sure all relative references and the reference position
612     //  are within existing tables, so they can be represented as text
613     //  (if the range of used tables is more than the existing tables,
614     //  the result may still contain invalid tables, because the relative
615     //  references aren't changed so formulas stay the same)
616 
617     //  find range of used tables
618 
619     SCTAB nMinTab = aPos.Tab();
620     SCTAB nMaxTab = nMinTab;
621     ScToken* t;
622     pCode->Reset();
623     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
624     {
625         ScSingleRefData& rRef1 = t->GetSingleRef();
626         if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
627         {
628             if ( rRef1.nTab < nMinTab )
629                 nMinTab = rRef1.nTab;
630             if ( rRef1.nTab > nMaxTab )
631                 nMaxTab = rRef1.nTab;
632         }
633         if ( t->GetType() == svDoubleRef )
634         {
635             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
636             if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
637             {
638                 if ( rRef2.nTab < nMinTab )
639                     nMinTab = rRef2.nTab;
640                 if ( rRef2.nTab > nMaxTab )
641                     nMaxTab = rRef2.nTab;
642             }
643         }
644     }
645 
646     SCTAB nTabCount = pDoc->GetTableCount();
647     if ( nMaxTab >= nTabCount && nMinTab > 0 )
648     {
649         //  move position and relative tab refs
650         //  The formulas that use the name are not changed by this
651 
652         SCTAB nMove = nMinTab;
653         aPos.SetTab( aPos.Tab() - nMove );
654 
655         pCode->Reset();
656         while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
657         {
658             ScSingleRefData& rRef1 = t->GetSingleRef();
659             if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
660                 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
661             if ( t->GetType() == svDoubleRef )
662             {
663                 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
664                 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
665                     rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove );
666             }
667         }
668     }
669 }
670 
671 
672 extern "C" int
673 #ifdef WNT
674 __cdecl
675 #endif
676 ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
677 {
678     return (int) ScGlobal::GetCollator()->compareString(
679             (*(const ScRangeData**)p1)->GetName(),
680             (*(const ScRangeData**)p2)->GetName() );
681 }
682 
683 
684 //========================================================================
685 // ScRangeName
686 //========================================================================
687 
688 ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
689                 ScSortedCollection ( rScRangeName ),
690                 pDoc ( pDocument ),
691                 nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
692 {
693     for (sal_uInt16 i = 0; i < nCount; i++)
694     {
695         ((ScRangeData*)At(i))->SetDocument(pDocument);
696         ((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
697     }
698 }
699 
700 short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
701 {
702     sal_uInt16 i1 = ((ScRangeData*)pKey1)->GetIndex();
703     sal_uInt16 i2 = ((ScRangeData*)pKey2)->GetIndex();
704     return (short) i1 - (short) i2;
705 }
706 
707 sal_Bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex ) const
708 {
709     // SearchNameUpper must be called with an upper-case search string
710 
711     sal_uInt16 i = 0;
712     while (i < nCount)
713     {
714         if ( ((*this)[i])->GetUpperName() == rUpperName )
715         {
716             rIndex = i;
717             return sal_True;
718         }
719         i++;
720     }
721     return sal_False;
722 }
723 
724 sal_Bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex ) const
725 {
726     if ( nCount > 0 )
727         return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex );
728     else
729         return sal_False;
730 }
731 
732 void ScRangeName::UpdateReference(  UpdateRefMode eUpdateRefMode,
733                                     const ScRange& rRange,
734                                     SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
735 {
736     for (sal_uInt16 i=0; i<nCount; i++)
737         ((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
738                                                    nDx, nDy, nDz);
739 }
740 
741 void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
742 {
743     for (sal_uInt16 i=0; i<nCount; i++)
744         ((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
745 }
746 
747 void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
748 {
749     for (sal_uInt16 i=0; i<nCount; i++)
750         ((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
751 }
752 
753 sal_Bool ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
754 {
755     return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
756 }
757 
758 sal_Bool ScRangeName::Insert(ScDataObject* pScDataObject)
759 {
760     if (!((ScRangeData*)pScDataObject)->GetIndex())     // schon gesetzt?
761     {
762         ((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() );
763     }
764 
765     return ScSortedCollection::Insert(pScDataObject);
766 }
767 
768 // Suche nach einem freien Index
769 
770 sal_uInt16 ScRangeName::GetEntryIndex()
771 {
772     sal_uInt16 nLast = 0;
773     for ( sal_uInt16 i = 0; i < nCount; i++ )
774     {
775         sal_uInt16 nIdx = ((ScRangeData*)pItems[i])->GetIndex();
776         if( nIdx > nLast )
777         {
778             nLast = nIdx;
779         }
780     }
781     return nLast + 1;
782 }
783 
784 ScRangeData* ScRangeName::FindIndex( sal_uInt16 nIndex )
785 {
786     ScRangeData aDataObj( nIndex );
787     sal_uInt16 n;
788     if( Search( &aDataObj, n ) )
789         return (*this)[ n ];
790     else
791         return NULL;
792 }
793 
794 //UNUSED2009-05 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const
795 //UNUSED2009-05 {
796 //UNUSED2009-05     if ( pItems )
797 //UNUSED2009-05     {
798 //UNUSED2009-05         for ( sal_uInt16 i = 0; i < nCount; i++ )
799 //UNUSED2009-05             if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
800 //UNUSED2009-05                 return (ScRangeData*)pItems[i];
801 //UNUSED2009-05     }
802 //UNUSED2009-05     return NULL;
803 //UNUSED2009-05 }
804 
805 ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
806 {
807     if ( pItems )
808     {
809         for ( sal_uInt16 i = 0; i < nCount; i++ )
810             if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
811                 return (ScRangeData*)pItems[i];
812     }
813     return NULL;
814 }
815 
816 void ScRangeName::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable)
817 {
818     for (sal_uInt16 i=0; i<nCount; i++)
819         ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
820 }
821 
822 
823 
824 
825