fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / rangenam.cxx
blob4235ef772f2282aa39cae35fa74db544517bd512
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
21 #include <boost/scoped_ptr.hpp>
22 #include <unotools/collatorwrapper.hxx>
23 #include <unotools/transliterationwrapper.hxx>
24 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
25 #include <osl/diagnose.h>
27 #include "token.hxx"
28 #include "tokenarray.hxx"
29 #include "rangenam.hxx"
30 #include "global.hxx"
31 #include "compiler.hxx"
32 #include "rangeutl.hxx"
33 #include "rechead.hxx"
34 #include "refupdat.hxx"
35 #include "document.hxx"
36 #include "refupdatecontext.hxx"
37 #include <tokenstringcontext.hxx>
39 #include <formula/errorcodes.hxx>
41 using namespace formula;
42 using ::std::pair;
43 using ::std::unary_function;
45 // ScRangeData
47 ScRangeData::ScRangeData( ScDocument* pDok,
48 const OUString& rName,
49 const OUString& rSymbol,
50 const ScAddress& rAddress,
51 RangeType nType,
52 const FormulaGrammar::Grammar eGrammar ) :
53 aName ( rName ),
54 aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
55 pCode ( NULL ),
56 aPos ( rAddress ),
57 eType ( nType ),
58 pDoc ( pDok ),
59 eTempGrammar( eGrammar ),
60 nIndex ( 0 ),
61 bModified ( false ),
62 mnMaxRow (-1),
63 mnMaxCol (-1)
65 if (!rSymbol.isEmpty())
66 CompileRangeData( rSymbol, pDoc->IsImportingXML());
67 // Let the compiler set an error on unknown names for a subsequent
68 // CompileUnresolvedXML().
69 else
71 // #i63513#/#i65690# don't leave pCode as NULL.
72 // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
73 // to ensure same behavior if unnecessary copying is left out.
75 pCode = new ScTokenArray();
76 pCode->SetFromRangeName(true);
80 ScRangeData::ScRangeData( ScDocument* pDok,
81 const OUString& rName,
82 const ScTokenArray& rArr,
83 const ScAddress& rAddress,
84 RangeType nType ) :
85 aName ( rName ),
86 aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
87 pCode ( new ScTokenArray( rArr ) ),
88 aPos ( rAddress ),
89 eType ( nType ),
90 pDoc ( pDok ),
91 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
92 nIndex ( 0 ),
93 bModified ( false ),
94 mnMaxRow (-1),
95 mnMaxCol (-1)
97 pCode->SetFromRangeName(true);
98 InitCode();
101 ScRangeData::ScRangeData( ScDocument* pDok,
102 const OUString& rName,
103 const ScAddress& rTarget ) :
104 aName ( rName ),
105 aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
106 pCode ( new ScTokenArray() ),
107 aPos ( rTarget ),
108 eType ( RT_NAME ),
109 pDoc ( pDok ),
110 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
111 nIndex ( 0 ),
112 bModified ( false ),
113 mnMaxRow (-1),
114 mnMaxCol (-1)
116 ScSingleRefData aRefData;
117 aRefData.InitAddress( rTarget );
118 aRefData.SetFlag3D( true );
119 pCode->AddSingleReference( aRefData );
120 pCode->SetFromRangeName(true);
121 ScCompiler aComp( pDoc, aPos, *pCode );
122 aComp.SetGrammar(pDoc->GetGrammar());
123 aComp.CompileTokenArray();
124 if ( !pCode->GetCodeError() )
125 eType |= RT_ABSPOS;
128 ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument) :
129 aName (rScRangeData.aName),
130 aUpperName (rScRangeData.aUpperName),
131 pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // make real copy (not copy-ctor)
132 aPos (rScRangeData.aPos),
133 eType (rScRangeData.eType),
134 pDoc (pDocument ? pDocument : rScRangeData.pDoc),
135 eTempGrammar(rScRangeData.eTempGrammar),
136 nIndex (rScRangeData.nIndex),
137 bModified (rScRangeData.bModified),
138 mnMaxRow (rScRangeData.mnMaxRow),
139 mnMaxCol (rScRangeData.mnMaxCol)
141 pCode->SetFromRangeName(true);
144 ScRangeData::~ScRangeData()
146 delete pCode;
149 void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError )
151 if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
153 OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
154 // Anything is almost as bad as this, but we might have the best choice
155 // if not loading documents.
156 eTempGrammar = FormulaGrammar::GRAM_NATIVE;
159 ScCompiler aComp( pDoc, aPos );
160 aComp.SetGrammar( eTempGrammar);
161 if (bSetError)
162 aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK);
163 ScTokenArray* pNewCode = aComp.CompileString( rSymbol );
164 boost::scoped_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted
165 pCode = pNewCode;
166 pCode->SetFromRangeName(true);
167 if( !pCode->GetCodeError() )
169 pCode->Reset();
170 FormulaToken* p = pCode->GetNextReference();
171 if( p )
173 // first token is a reference
174 /* FIXME: wouldn't that need a check if it's exactly one reference? */
175 if( p->GetType() == svSingleRef )
176 eType = eType | RT_ABSPOS;
177 else
178 eType = eType | RT_ABSAREA;
180 // For manual input set an error for an incomplete formula.
181 if (!pDoc->IsImportingXML())
183 aComp.CompileTokenArray();
184 pCode->DelRPN();
189 void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt )
191 if (pCode->GetCodeError() == errNoName)
193 // Reconstruct the symbol/formula and then recompile.
194 OUString aSymbol;
195 rCxt.setGrammar(eTempGrammar);
196 ScCompiler aComp(rCxt, aPos, *pCode);
197 aComp.CreateStringFromTokenArray( aSymbol);
198 // Don't let the compiler set an error for unknown names on final
199 // compile, errors are handled by the interpreter thereafter.
200 CompileRangeData( aSymbol, false);
204 #if DEBUG_FORMULA_COMPILER
205 void ScRangeData::Dump() const
207 cout << "-- ScRangeData" << endl;
208 cout << " name: " << aName << endl;
209 cout << " ref position: (col=" << aPos.Col() << ", row=" << aPos.Row() << ", sheet=" << aPos.Tab() << ")" << endl;
211 if (pCode)
212 pCode->Dump();
214 #endif
216 void ScRangeData::GuessPosition()
218 // set a position that allows "absoluting" of all relative references
219 // in CalcAbsIfRel without errors
221 OSL_ENSURE(aPos == ScAddress(), "position will go lost now");
223 SCsCOL nMinCol = 0;
224 SCsROW nMinRow = 0;
225 SCsTAB nMinTab = 0;
227 formula::FormulaToken* t;
228 pCode->Reset();
229 while ( ( t = pCode->GetNextReference() ) != NULL )
231 ScSingleRefData& rRef1 = *t->GetSingleRef();
232 if ( rRef1.IsColRel() && rRef1.Col() < nMinCol )
233 nMinCol = rRef1.Col();
234 if ( rRef1.IsRowRel() && rRef1.Row() < nMinRow )
235 nMinRow = rRef1.Row();
236 if ( rRef1.IsTabRel() && rRef1.Tab() < nMinTab )
237 nMinTab = rRef1.Tab();
239 if ( t->GetType() == svDoubleRef )
241 ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
242 if ( rRef2.IsColRel() && rRef2.Col() < nMinCol )
243 nMinCol = rRef2.Col();
244 if ( rRef2.IsRowRel() && rRef2.Row() < nMinRow )
245 nMinRow = rRef2.Row();
246 if ( rRef2.IsTabRel() && rRef2.Tab() < nMinTab )
247 nMinTab = rRef2.Tab();
251 aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
254 void ScRangeData::GetSymbol( OUString& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
256 ScCompiler aComp(pDoc, aPos, *pCode);
257 aComp.SetGrammar(eGrammar);
258 aComp.CreateStringFromTokenArray( rSymbol );
261 void ScRangeData::GetSymbol( OUString& rSymbol, const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) const
263 OUString aStr;
264 ScCompiler aComp(pDoc, rPos, *pCode);
265 aComp.SetGrammar(eGrammar);
266 aComp.CreateStringFromTokenArray( aStr );
267 rSymbol = aStr;
270 void ScRangeData::UpdateSymbol( OUStringBuffer& rBuffer, const ScAddress& rPos,
271 const FormulaGrammar::Grammar eGrammar )
273 boost::scoped_ptr<ScTokenArray> pTemp( pCode->Clone() );
274 ScCompiler aComp( pDoc, rPos, *pTemp.get());
275 aComp.SetGrammar(eGrammar);
276 aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
277 aComp.CreateStringFromTokenArray( rBuffer );
280 void ScRangeData::UpdateReference( sc::RefUpdateContext& rCxt, SCTAB nLocalTab )
282 sc::RefUpdateResult aRes = pCode->AdjustReferenceInName(rCxt, aPos);
283 bModified = aRes.mbReferenceModified;
284 if (aRes.mbReferenceModified)
285 rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
288 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
290 bool bChanged = false;
292 formula::FormulaToken* t;
293 pCode->Reset();
295 while ( ( t = pCode->GetNextReference() ) != NULL )
297 if( t->GetType() != svIndex )
299 SingleDoubleRefModifier aMod( *t );
300 ScComplexRefData& rRef = aMod.Ref();
301 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
302 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
303 ( t->GetType() == svSingleRef ||
304 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
305 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
307 ScRange aAbs = rRef.toAbs(aPos);
308 if (ScRefUpdate::UpdateTranspose(pDoc, rSource, rDest, aAbs) != UR_NOTHING)
310 rRef.SetRange(aAbs, aPos);
311 bChanged = true;
317 bModified = bChanged;
320 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
322 bool bChanged = false;
324 formula::FormulaToken* t;
325 pCode->Reset();
327 while ( ( t = pCode->GetNextReference() ) != NULL )
329 if( t->GetType() != svIndex )
331 SingleDoubleRefModifier aMod( *t );
332 ScComplexRefData& rRef = aMod.Ref();
333 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
334 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
335 ( t->GetType() == svSingleRef ||
336 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
337 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
339 ScRange aAbs = rRef.toAbs(aPos);
340 if (ScRefUpdate::UpdateGrow(rArea, nGrowX, nGrowY, aAbs) != UR_NOTHING)
342 rRef.SetRange(aAbs, aPos);
343 bChanged = true;
349 bModified = bChanged; // has to be evaluated immediately afterwards
352 bool ScRangeData::operator== (const ScRangeData& rData) const // for Undo
354 if ( nIndex != rData.nIndex ||
355 aName != rData.aName ||
356 aPos != rData.aPos ||
357 eType != rData.eType ) return false;
359 sal_uInt16 nLen = pCode->GetLen();
360 if ( nLen != rData.pCode->GetLen() ) return false;
362 FormulaToken** ppThis = pCode->GetArray();
363 FormulaToken** ppOther = rData.pCode->GetArray();
365 for ( sal_uInt16 i=0; i<nLen; i++ )
366 if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
367 return false;
369 return true;
372 bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
374 bool bRet = false;
375 ScRange aRange;
376 if ( IsReference(aRange) )
377 bRet = ( rBlock == aRange );
378 return bRet;
381 bool ScRangeData::IsReference( ScRange& rRange ) const
383 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
384 return pCode->IsReference(rRange, aPos);
386 return false;
389 bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
391 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
392 return pCode->IsReference(rRange, rPos);
394 return false;
397 bool ScRangeData::IsValidReference( ScRange& rRange ) const
399 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
400 return pCode->IsValidReference(rRange, aPos);
402 return false;
405 void ScRangeData::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt, SCTAB nLocalTab )
407 sc::RefUpdateResult aRes = pCode->AdjustReferenceOnInsertedTab(rCxt, aPos);
408 if (aRes.mbReferenceModified)
409 rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
411 if (rCxt.mnInsertPos <= aPos.Tab())
412 aPos.IncTab(rCxt.mnSheets);
415 void ScRangeData::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt, SCTAB nLocalTab )
417 sc::RefUpdateResult aRes = pCode->AdjustReferenceOnDeletedTab(rCxt, aPos);
418 if (aRes.mbReferenceModified)
419 rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
421 if (rCxt.mnDeletePos <= aPos.Tab())
422 aPos.IncTab(-rCxt.mnSheets);
425 void ScRangeData::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nLocalTab )
427 sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMovedTab(rCxt, aPos);
428 if (aRes.mbReferenceModified)
429 rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
431 aPos.SetTab(rCxt.getNewTab(aPos.Tab()));
434 void ScRangeData::MakeValidName( OUString& rName )
437 // strip leading invalid characters
438 sal_Int32 nPos = 0;
439 sal_Int32 nLen = rName.getLength();
440 while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
441 ++nPos;
442 if ( nPos>0 )
443 rName = rName.copy(nPos);
445 // if the first character is an invalid start character, precede with '_'
446 if ( !rName.isEmpty() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
447 rName = "_" + rName;
449 // replace invalid with '_'
450 nLen = rName.getLength();
451 for (nPos=0; nPos<nLen; nPos++)
453 if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
454 rName = rName.replaceAt( nPos, 1, "_" );
457 // Ensure that the proposed name is not a reference under any convention,
458 // same as in IsNameValid()
459 ScAddress aAddr;
460 ScRange aRange;
461 for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
463 ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
464 // Don't check Parse on VALID, any partial only VALID may result in
465 // #REF! during compile later!
466 while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
468 // Range Parse is partially valid also with invalid sheet name,
469 // Address Parse dito, during compile name would generate a #REF!
470 if ( rName.indexOf( '.' ) != -1 )
471 rName = rName.replaceFirst( ".", "_" );
472 else
473 rName = "_" + rName;
478 bool ScRangeData::IsNameValid( const OUString& rName, ScDocument* pDoc )
480 /* XXX If changed, sc/source/filter/ftools/ftools.cxx
481 * ScfTools::ConvertToScDefinedName needs to be changed too. */
482 sal_Char a('.');
483 if (rName.indexOf(a) != -1)
484 return false;
485 sal_Int32 nPos = 0;
486 sal_Int32 nLen = rName.getLength();
487 if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
488 return false;
489 while ( nPos < nLen )
491 if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
492 return false;
494 ScAddress aAddr;
495 ScRange aRange;
496 for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
498 ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
499 // Don't check Parse on VALID, any partial only VALID may result in
500 // #REF! during compile later!
501 if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
502 return false;
504 return true;
507 SCROW ScRangeData::GetMaxRow() const
509 return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
512 SCCOL ScRangeData::GetMaxCol() const
514 return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
517 sal_uInt16 ScRangeData::GetErrCode() const
519 return pCode ? pCode->GetCodeError() : 0;
522 bool ScRangeData::HasReferences() const
524 return pCode->HasReferences();
527 sal_uInt32 ScRangeData::GetUnoType() const
529 sal_uInt32 nUnoType = 0;
530 if ( HasType(RT_CRITERIA) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::FILTER_CRITERIA;
531 if ( HasType(RT_PRINTAREA) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::PRINT_AREA;
532 if ( HasType(RT_COLHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::COLUMN_HEADER;
533 if ( HasType(RT_ROWHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::ROW_HEADER;
534 return nUnoType;
537 void ScRangeData::ValidateTabRefs()
539 // try to make sure all relative references and the reference position
540 // are within existing tables, so they can be represented as text
541 // (if the range of used tables is more than the existing tables,
542 // the result may still contain invalid tables, because the relative
543 // references aren't changed so formulas stay the same)
545 // find range of used tables
547 SCTAB nMinTab = aPos.Tab();
548 SCTAB nMaxTab = nMinTab;
549 formula::FormulaToken* t;
550 pCode->Reset();
551 while ( ( t = pCode->GetNextReference() ) != NULL )
553 ScSingleRefData& rRef1 = *t->GetSingleRef();
554 ScAddress aAbs = rRef1.toAbs(aPos);
555 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
557 if (aAbs.Tab() < nMinTab)
558 nMinTab = aAbs.Tab();
559 if (aAbs.Tab() > nMaxTab)
560 nMaxTab = aAbs.Tab();
562 if ( t->GetType() == svDoubleRef )
564 ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
565 aAbs = rRef2.toAbs(aPos);
566 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
568 if (aAbs.Tab() < nMinTab)
569 nMinTab = aAbs.Tab();
570 if (aAbs.Tab() > nMaxTab)
571 nMaxTab = aAbs.Tab();
576 SCTAB nTabCount = pDoc->GetTableCount();
577 if ( nMaxTab >= nTabCount && nMinTab > 0 )
579 // move position and relative tab refs
580 // The formulas that use the name are not changed by this
582 SCTAB nMove = nMinTab;
583 ScAddress aOldPos = aPos;
584 aPos.SetTab( aPos.Tab() - nMove );
586 pCode->Reset();
587 while ( ( t = pCode->GetNextReference() ) != NULL )
589 switch (t->GetType())
591 case svSingleRef:
593 ScSingleRefData& rRef = *t->GetSingleRef();
594 if (!rRef.IsTabDeleted())
596 ScAddress aAbs = rRef.toAbs(aOldPos);
597 rRef.SetAddress(aAbs, aPos);
600 break;
601 case svDoubleRef:
603 ScComplexRefData& rRef = *t->GetDoubleRef();
604 if (!rRef.Ref1.IsTabDeleted())
606 ScAddress aAbs = rRef.Ref1.toAbs(aOldPos);
607 rRef.Ref1.SetAddress(aAbs, aPos);
609 if (!rRef.Ref2.IsTabDeleted())
611 ScAddress aAbs = rRef.Ref2.toAbs(aOldPos);
612 rRef.Ref2.SetAddress(aAbs, aPos);
615 break;
616 default:
623 void ScRangeData::SetCode( ScTokenArray& rArr )
625 boost::scoped_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted
626 pCode = new ScTokenArray( rArr );
627 pCode->SetFromRangeName(true);
628 InitCode();
631 void ScRangeData::InitCode()
633 if( !pCode->GetCodeError() )
635 pCode->Reset();
636 FormulaToken* p = pCode->GetNextReference();
637 if( p ) // exact one reference at first
639 if( p->GetType() == svSingleRef )
640 eType = eType | RT_ABSPOS;
641 else
642 eType = eType | RT_ABSAREA;
647 extern "C"
648 int SAL_CALL ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
650 return (int) ScGlobal::GetCollator()->compareString(
651 (*static_cast<const ScRangeData* const *>(p1))->GetName(),
652 (*static_cast<const ScRangeData* const *>(p2))->GetName() );
655 bool operator<(const ScRangeData& left, const ScRangeData& right)
657 return left.GetName() < right.GetName();
660 namespace {
663 * Predicate to check if the name references the specified range.
665 class MatchByRange : public unary_function<ScRangeData, bool>
667 const ScRange& mrRange;
668 public:
669 MatchByRange(const ScRange& rRange) : mrRange(rRange) {}
670 template < typename Pair >
671 bool operator() ( Pair const& r) const
673 return r.second->IsRangeAtBlock(mrRange);
679 ScRangeName::ScRangeName() {}
681 ScRangeName::ScRangeName(const ScRangeName& r) :
682 maData(r.maData)
684 // boost::ptr_set clones and deletes, so each collection needs its own
685 // index to data.
686 maIndexToData.resize( r.maIndexToData.size(), NULL);
687 DataType::const_iterator itr = maData.begin(), itrEnd = maData.end();
688 for (; itr != itrEnd; ++itr)
690 size_t nPos = itr->second->GetIndex() - 1;
691 if (nPos >= maIndexToData.size())
693 OSL_FAIL( "ScRangeName copy-ctor: maIndexToData size doesn't fit");
694 maIndexToData.resize(nPos+1, NULL);
696 maIndexToData[nPos] = const_cast<ScRangeData*>(itr->second);
700 const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
702 DataType::const_iterator itr = std::find_if(
703 maData.begin(), maData.end(), MatchByRange(rRange));
704 return itr == maData.end() ? NULL : itr->second;
707 ScRangeData* ScRangeName::findByUpperName(const OUString& rName)
709 DataType::iterator itr = maData.find(rName);
710 return itr == maData.end() ? NULL : itr->second;
713 const ScRangeData* ScRangeName::findByUpperName(const OUString& rName) const
715 DataType::const_iterator itr = maData.find(rName);
716 return itr == maData.end() ? NULL : itr->second;
719 ScRangeData* ScRangeName::findByIndex(sal_uInt16 i) const
721 if (!i)
722 // index should never be zero.
723 return NULL;
725 size_t nPos = i - 1;
726 return nPos < maIndexToData.size() ? maIndexToData[nPos] : NULL;
729 void ScRangeName::UpdateReference(sc::RefUpdateContext& rCxt, SCTAB nLocalTab )
731 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
732 for (; itr != itrEnd; ++itr)
733 itr->second->UpdateReference(rCxt, nLocalTab);
736 void ScRangeName::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt, SCTAB nLocalTab )
738 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
739 for (; itr != itrEnd; ++itr)
740 itr->second->UpdateInsertTab(rCxt, nLocalTab);
743 void ScRangeName::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt, SCTAB nLocalTab )
745 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
746 for (; itr != itrEnd; ++itr)
747 itr->second->UpdateDeleteTab(rCxt, nLocalTab);
750 void ScRangeName::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nLocalTab )
752 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
753 for (; itr != itrEnd; ++itr)
754 itr->second->UpdateMoveTab(rCxt, nLocalTab);
757 void ScRangeName::UpdateTranspose(const ScRange& rSource, const ScAddress& rDest)
759 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
760 for (; itr != itrEnd; ++itr)
761 itr->second->UpdateTranspose(rSource, rDest);
764 void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
766 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
767 for (; itr != itrEnd; ++itr)
768 itr->second->UpdateGrow(rArea, nGrowX, nGrowY);
771 void ScRangeName::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt )
773 DataType::iterator itr = maData.begin(), itrEnd = maData.end();
774 for (; itr != itrEnd; ++itr)
775 itr->second->CompileUnresolvedXML(rCxt);
778 ScRangeName::const_iterator ScRangeName::begin() const
780 return maData.begin();
783 ScRangeName::const_iterator ScRangeName::end() const
785 return maData.end();
788 ScRangeName::iterator ScRangeName::begin()
790 return maData.begin();
793 ScRangeName::iterator ScRangeName::end()
795 return maData.end();
798 size_t ScRangeName::size() const
800 return maData.size();
803 bool ScRangeName::empty() const
805 return maData.empty();
808 bool ScRangeName::insert(ScRangeData* p)
810 if (!p)
811 return false;
813 if (!p->GetIndex())
815 // Assign a new index. An index must be unique and is never 0.
816 IndexDataType::iterator itr = std::find(
817 maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(NULL));
818 if (itr != maIndexToData.end())
820 // Empty slot exists. Re-use it.
821 size_t nPos = std::distance(maIndexToData.begin(), itr);
822 p->SetIndex(nPos + 1);
824 else
825 // No empty slot. Append it to the end.
826 p->SetIndex(maIndexToData.size() + 1);
829 OUString aName(p->GetUpperName());
830 erase(aName); // ptr_map won't insert it if a duplicate name exists.
831 pair<DataType::iterator, bool> r = maData.insert(aName, p);
832 if (r.second)
834 // Data inserted. Store its index for mapping.
835 size_t nPos = p->GetIndex() - 1;
836 if (nPos >= maIndexToData.size())
837 maIndexToData.resize(nPos+1, NULL);
838 maIndexToData[nPos] = p;
840 return r.second;
843 void ScRangeName::erase(const ScRangeData& r)
845 erase(r.GetUpperName());
848 void ScRangeName::erase(const OUString& rName)
850 DataType::iterator itr = maData.find(rName);
851 if (itr != maData.end())
852 erase(itr);
855 void ScRangeName::erase(const iterator& itr)
857 sal_uInt16 nIndex = itr->second->GetIndex();
858 maData.erase(itr);
859 OSL_ENSURE( 0 < nIndex && nIndex <= maIndexToData.size(), "ScRangeName::erase: bad index");
860 if (0 < nIndex && nIndex <= maIndexToData.size())
861 maIndexToData[nIndex-1] = NULL;
864 void ScRangeName::clear()
866 maData.clear();
867 maIndexToData.clear();
870 bool ScRangeName::operator== (const ScRangeName& r) const
872 return maData == r.maData;
875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */