1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
28 #include "tokenarray.hxx"
29 #include "rangenam.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
;
43 using ::std::unary_function
;
47 ScRangeData::ScRangeData( ScDocument
* pDok
,
48 const OUString
& rName
,
49 const OUString
& rSymbol
,
50 const ScAddress
& rAddress
,
52 const FormulaGrammar::Grammar eGrammar
) :
54 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
59 eTempGrammar( eGrammar
),
65 if (!rSymbol
.isEmpty())
66 CompileRangeData( rSymbol
, pDoc
->IsImportingXML());
67 // Let the compiler set an error on unknown names for a subsequent
68 // CompileUnresolvedXML().
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
,
86 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
87 pCode ( new ScTokenArray( rArr
) ),
91 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED
),
97 pCode
->SetFromRangeName(true);
101 ScRangeData::ScRangeData( ScDocument
* pDok
,
102 const OUString
& rName
,
103 const ScAddress
& rTarget
) :
105 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
106 pCode ( new ScTokenArray() ),
110 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED
),
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() )
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()
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
);
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
166 pCode
->SetFromRangeName(true);
167 if( !pCode
->GetCodeError() )
170 FormulaToken
* p
= pCode
->GetNextReference();
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
;
178 eType
= eType
| RT_ABSAREA
;
180 // For manual input set an error for an incomplete formula.
181 if (!pDoc
->IsImportingXML())
183 aComp
.CompileTokenArray();
189 void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext
& rCxt
)
191 if (pCode
->GetCodeError() == errNoName
)
193 // Reconstruct the symbol/formula and then recompile.
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
;
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");
227 formula::FormulaToken
* t
;
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
264 ScCompiler
aComp(pDoc
, rPos
, *pCode
);
265 aComp
.SetGrammar(eGrammar
);
266 aComp
.CreateStringFromTokenArray( 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
;
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
);
317 bModified
= bChanged
;
320 void ScRangeData::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
322 bool bChanged
= false;
324 formula::FormulaToken
* t
;
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
);
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
]) )
372 bool ScRangeData::IsRangeAtBlock( const ScRange
& rBlock
) const
376 if ( IsReference(aRange
) )
377 bRet
= ( rBlock
== aRange
);
381 bool ScRangeData::IsReference( ScRange
& rRange
) const
383 if ( (eType
& ( RT_ABSAREA
| RT_REFAREA
| RT_ABSPOS
)) && pCode
)
384 return pCode
->IsReference(rRange
, aPos
);
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
);
397 bool ScRangeData::IsValidReference( ScRange
& rRange
) const
399 if ( (eType
& ( RT_ABSAREA
| RT_REFAREA
| RT_ABSPOS
) ) && pCode
)
400 return pCode
->IsValidReference(rRange
, aPos
);
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
439 sal_Int32 nLen
= rName
.getLength();
440 while ( nPos
< nLen
&& !ScCompiler::IsCharFlagAllConventions( rName
, nPos
, SC_COMPILER_C_NAME
) )
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
) )
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()
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( ".", "_" );
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. */
483 if (rName
.indexOf(a
) != -1)
486 sal_Int32 nLen
= rName
.getLength();
487 if ( !nLen
|| !ScCompiler::IsCharFlagAllConventions( rName
, nPos
++, SC_COMPILER_C_CHAR_NAME
) )
489 while ( nPos
< nLen
)
491 if ( !ScCompiler::IsCharFlagAllConventions( rName
, nPos
++, SC_COMPILER_C_NAME
) )
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
))
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
;
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
;
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
);
587 while ( ( t
= pCode
->GetNextReference() ) != NULL
)
589 switch (t
->GetType())
593 ScSingleRefData
& rRef
= *t
->GetSingleRef();
594 if (!rRef
.IsTabDeleted())
596 ScAddress aAbs
= rRef
.toAbs(aOldPos
);
597 rRef
.SetAddress(aAbs
, aPos
);
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
);
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);
631 void ScRangeData::InitCode()
633 if( !pCode
->GetCodeError() )
636 FormulaToken
* p
= pCode
->GetNextReference();
637 if( p
) // exact one reference at first
639 if( p
->GetType() == svSingleRef
)
640 eType
= eType
| RT_ABSPOS
;
642 eType
= eType
| RT_ABSAREA
;
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();
663 * Predicate to check if the name references the specified range.
665 class MatchByRange
: public unary_function
<ScRangeData
, bool>
667 const ScRange
& mrRange
;
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
) :
684 // boost::ptr_set clones and deletes, so each collection needs its own
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
722 // index should never be zero.
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
788 ScRangeName::iterator
ScRangeName::begin()
790 return maData
.begin();
793 ScRangeName::iterator
ScRangeName::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
)
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);
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
);
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
;
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())
855 void ScRangeName::erase(const iterator
& itr
)
857 sal_uInt16 nIndex
= itr
->second
->GetIndex();
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()
867 maIndexToData
.clear();
870 bool ScRangeName::operator== (const ScRangeName
& r
) const
872 return maData
== r
.maData
;
875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */