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 .
22 #include <boost/scoped_ptr.hpp>
23 #include <unotools/collatorwrapper.hxx>
24 #include <unotools/transliterationwrapper.hxx>
25 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
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"
38 #include "formula/errorcodes.hxx"
40 using namespace formula
;
42 using ::std::unary_function
;
46 ScRangeData::ScRangeData( ScDocument
* pDok
,
47 const OUString
& rName
,
48 const OUString
& rSymbol
,
49 const ScAddress
& rAddress
,
51 const FormulaGrammar::Grammar eGrammar
) :
53 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
58 eTempGrammar( eGrammar
),
64 if (!rSymbol
.isEmpty())
65 CompileRangeData( rSymbol
, pDoc
->IsImportingXML());
66 // Let the compiler set an error on unknown names for a subsequent
67 // CompileUnresolvedXML().
70 // #i63513#/#i65690# don't leave pCode as NULL.
71 // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
72 // to ensure same behavior if unnecessary copying is left out.
74 pCode
= new ScTokenArray();
78 ScRangeData::ScRangeData( ScDocument
* pDok
,
79 const OUString
& rName
,
80 const ScTokenArray
& rArr
,
81 const ScAddress
& rAddress
,
84 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
85 pCode ( new ScTokenArray( rArr
) ),
89 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED
),
98 ScRangeData::ScRangeData( ScDocument
* pDok
,
99 const OUString
& rName
,
100 const ScAddress
& rTarget
) :
102 aUpperName ( ScGlobal::pCharClass
->uppercase( rName
) ),
103 pCode ( new ScTokenArray() ),
107 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED
),
113 ScSingleRefData aRefData
;
114 aRefData
.InitAddress( rTarget
);
115 aRefData
.SetFlag3D( sal_True
);
116 pCode
->AddSingleReference( aRefData
);
117 ScCompiler
aComp( pDoc
, aPos
, *pCode
);
118 aComp
.SetGrammar(pDoc
->GetGrammar());
119 aComp
.CompileTokenArray();
120 if ( !pCode
->GetCodeError() )
124 ScRangeData::ScRangeData(const ScRangeData
& rScRangeData
, ScDocument
* pDocument
) :
125 aName (rScRangeData
.aName
),
126 aUpperName (rScRangeData
.aUpperName
),
127 pCode (rScRangeData
.pCode
? rScRangeData
.pCode
->Clone() : new ScTokenArray()), // make real copy (not copy-ctor)
128 aPos (rScRangeData
.aPos
),
129 eType (rScRangeData
.eType
),
130 pDoc (pDocument
? pDocument
: rScRangeData
.pDoc
),
131 eTempGrammar(rScRangeData
.eTempGrammar
),
132 nIndex (rScRangeData
.nIndex
),
133 bModified (rScRangeData
.bModified
),
134 mnMaxRow (rScRangeData
.mnMaxRow
),
135 mnMaxCol (rScRangeData
.mnMaxCol
)
138 ScRangeData::~ScRangeData()
143 void ScRangeData::CompileRangeData( const OUString
& rSymbol
, bool bSetError
)
145 if (eTempGrammar
== FormulaGrammar::GRAM_UNSPECIFIED
)
147 OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
148 // Anything is almost as bad as this, but we might have the best choice
149 // if not loading documents.
150 eTempGrammar
= FormulaGrammar::GRAM_NATIVE
;
153 ScCompiler
aComp( pDoc
, aPos
);
154 aComp
.SetGrammar( eTempGrammar
);
156 aComp
.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK
);
157 ScTokenArray
* pNewCode
= aComp
.CompileString( rSymbol
);
158 SAL_WNODEPRECATED_DECLARATIONS_PUSH
159 ::std::auto_ptr
<ScTokenArray
> pOldCode( pCode
); // old pCode will be deleted
160 SAL_WNODEPRECATED_DECLARATIONS_POP
162 if( !pCode
->GetCodeError() )
165 FormulaToken
* p
= pCode
->GetNextReference();
168 // first token is a reference
169 /* FIXME: wouldn't that need a check if it's exactly one reference? */
170 if( p
->GetType() == svSingleRef
)
171 eType
= eType
| RT_ABSPOS
;
173 eType
= eType
| RT_ABSAREA
;
175 // For manual input set an error for an incomplete formula.
176 if (!pDoc
->IsImportingXML())
178 aComp
.CompileTokenArray();
184 void ScRangeData::CompileUnresolvedXML()
186 if (pCode
->GetCodeError() == errNoName
)
188 // Reconstruct the symbol/formula and then recompile.
190 ScCompiler
aComp( pDoc
, aPos
, *pCode
);
191 aComp
.SetGrammar( eTempGrammar
);
192 aComp
.CreateStringFromTokenArray( aSymbol
);
193 // Don't let the compiler set an error for unknown names on final
194 // compile, errors are handled by the interpreter thereafter.
195 CompileRangeData( aSymbol
, false);
199 #if DEBUG_FORMULA_COMPILER
200 void ScRangeData::Dump() const
202 cout
<< "-- ScRangeData" << endl
;
203 cout
<< " name: " << aName
<< endl
;
204 cout
<< " ref position: (col=" << aPos
.Col() << ", row=" << aPos
.Row() << ", sheet=" << aPos
.Tab() << ")" << endl
;
211 void ScRangeData::GuessPosition()
213 // set a position that allows "absoluting" of all relative references
214 // in CalcAbsIfRel without errors
216 OSL_ENSURE(aPos
== ScAddress(), "position will go lost now");
224 while ( ( t
= static_cast<ScToken
*>(pCode
->GetNextReference()) ) != NULL
)
226 ScSingleRefData
& rRef1
= t
->GetSingleRef();
227 if ( rRef1
.IsColRel() && rRef1
.Col() < nMinCol
)
228 nMinCol
= rRef1
.Col();
229 if ( rRef1
.IsRowRel() && rRef1
.Row() < nMinRow
)
230 nMinRow
= rRef1
.Row();
231 if ( rRef1
.IsTabRel() && rRef1
.Tab() < nMinTab
)
232 nMinTab
= rRef1
.Tab();
234 if ( t
->GetType() == svDoubleRef
)
236 ScSingleRefData
& rRef2
= t
->GetDoubleRef().Ref2
;
237 if ( rRef2
.IsColRel() && rRef2
.Col() < nMinCol
)
238 nMinCol
= rRef2
.Col();
239 if ( rRef2
.IsRowRel() && rRef2
.Row() < nMinRow
)
240 nMinRow
= rRef2
.Row();
241 if ( rRef2
.IsTabRel() && rRef2
.Tab() < nMinTab
)
242 nMinTab
= rRef2
.Tab();
246 aPos
= ScAddress( (SCCOL
)(-nMinCol
), (SCROW
)(-nMinRow
), (SCTAB
)(-nMinTab
) );
249 void ScRangeData::GetSymbol( OUString
& rSymbol
, const FormulaGrammar::Grammar eGrammar
) const
251 ScCompiler
aComp(pDoc
, aPos
, *pCode
);
252 aComp
.SetGrammar(eGrammar
);
253 aComp
.CreateStringFromTokenArray( rSymbol
);
256 void ScRangeData::GetSymbol( OUString
& rSymbol
, const ScAddress
& rPos
, const FormulaGrammar::Grammar eGrammar
) const
259 ScCompiler
aComp(pDoc
, rPos
, *pCode
);
260 aComp
.SetGrammar(eGrammar
);
261 aComp
.CreateStringFromTokenArray( aStr
);
265 void ScRangeData::UpdateSymbol( OUStringBuffer
& rBuffer
, const ScAddress
& rPos
,
266 const FormulaGrammar::Grammar eGrammar
)
268 SAL_WNODEPRECATED_DECLARATIONS_PUSH
269 ::std::auto_ptr
<ScTokenArray
> pTemp( pCode
->Clone() );
270 SAL_WNODEPRECATED_DECLARATIONS_POP
271 ScCompiler
aComp( pDoc
, rPos
, *pTemp
.get());
272 aComp
.SetGrammar(eGrammar
);
273 aComp
.MoveRelWrap(GetMaxCol(), GetMaxRow());
274 aComp
.CreateStringFromTokenArray( rBuffer
);
277 void ScRangeData::UpdateReference( sc::RefUpdateContext
& rCxt
, SCTAB nLocalTab
)
279 sc::RefUpdateResult aRes
= pCode
->AdjustReferenceInName(rCxt
, aPos
);
280 bModified
= aRes
.mbReferenceModified
;
281 if (aRes
.mbReferenceModified
)
282 rCxt
.maUpdatedNames
.setUpdatedName(nLocalTab
, nIndex
);
285 void ScRangeData::UpdateTranspose( const ScRange
& rSource
, const ScAddress
& rDest
)
287 bool bChanged
= false;
292 while ( ( t
= static_cast<ScToken
*>(pCode
->GetNextReference()) ) != NULL
)
294 if( t
->GetType() != svIndex
)
296 SingleDoubleRefModifier
aMod( *t
);
297 ScComplexRefData
& rRef
= aMod
.Ref();
298 if (!rRef
.Ref1
.IsColRel() && !rRef
.Ref1
.IsRowRel() &&
299 (!rRef
.Ref1
.IsFlag3D() || !rRef
.Ref1
.IsTabRel()) &&
300 ( t
->GetType() == svSingleRef
||
301 (!rRef
.Ref2
.IsColRel() && !rRef
.Ref2
.IsRowRel() &&
302 (!rRef
.Ref2
.IsFlag3D() || !rRef
.Ref2
.IsTabRel()))))
304 ScRange aAbs
= rRef
.toAbs(aPos
);
305 if (ScRefUpdate::UpdateTranspose(pDoc
, rSource
, rDest
, aAbs
) != UR_NOTHING
)
307 rRef
.SetRange(aAbs
, aPos
);
314 bModified
= bChanged
;
317 void ScRangeData::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
319 bool bChanged
= false;
324 while ( ( t
= static_cast<ScToken
*>(pCode
->GetNextReference()) ) != NULL
)
326 if( t
->GetType() != svIndex
)
328 SingleDoubleRefModifier
aMod( *t
);
329 ScComplexRefData
& rRef
= aMod
.Ref();
330 if (!rRef
.Ref1
.IsColRel() && !rRef
.Ref1
.IsRowRel() &&
331 (!rRef
.Ref1
.IsFlag3D() || !rRef
.Ref1
.IsTabRel()) &&
332 ( t
->GetType() == svSingleRef
||
333 (!rRef
.Ref2
.IsColRel() && !rRef
.Ref2
.IsRowRel() &&
334 (!rRef
.Ref2
.IsFlag3D() || !rRef
.Ref2
.IsTabRel()))))
336 ScRange aAbs
= rRef
.toAbs(aPos
);
337 if (ScRefUpdate::UpdateGrow(rArea
, nGrowX
, nGrowY
, aAbs
) != UR_NOTHING
)
339 rRef
.SetRange(aAbs
, aPos
);
346 bModified
= bChanged
; // has to be evaluated immediately afterwards
349 bool ScRangeData::operator== (const ScRangeData
& rData
) const // for Undo
351 if ( nIndex
!= rData
.nIndex
||
352 aName
!= rData
.aName
||
353 aPos
!= rData
.aPos
||
354 eType
!= rData
.eType
) return false;
356 sal_uInt16 nLen
= pCode
->GetLen();
357 if ( nLen
!= rData
.pCode
->GetLen() ) return false;
359 FormulaToken
** ppThis
= pCode
->GetArray();
360 FormulaToken
** ppOther
= rData
.pCode
->GetArray();
362 for ( sal_uInt16 i
=0; i
<nLen
; i
++ )
363 if ( ppThis
[i
] != ppOther
[i
] && !(*ppThis
[i
] == *ppOther
[i
]) )
369 bool ScRangeData::IsRangeAtBlock( const ScRange
& rBlock
) const
373 if ( IsReference(aRange
) )
374 bRet
= ( rBlock
== aRange
);
378 bool ScRangeData::IsReference( ScRange
& rRange
) const
380 if ( (eType
& ( RT_ABSAREA
| RT_REFAREA
| RT_ABSPOS
)) && pCode
)
381 return pCode
->IsReference(rRange
, aPos
);
386 bool ScRangeData::IsReference( ScRange
& rRange
, const ScAddress
& rPos
) const
388 if ( (eType
& ( RT_ABSAREA
| RT_REFAREA
| RT_ABSPOS
) ) && pCode
)
389 return pCode
->IsReference(rRange
, rPos
);
394 bool ScRangeData::IsValidReference( ScRange
& rRange
) const
396 if ( (eType
& ( RT_ABSAREA
| RT_REFAREA
| RT_ABSPOS
) ) && pCode
)
397 return pCode
->IsValidReference(rRange
, aPos
);
402 void ScRangeData::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
, SCTAB nLocalTab
)
404 sc::RefUpdateResult aRes
= pCode
->AdjustReferenceOnInsertedTab(rCxt
, aPos
);
405 if (aRes
.mbReferenceModified
)
406 rCxt
.maUpdatedNames
.setUpdatedName(nLocalTab
, nIndex
);
408 if (rCxt
.mnInsertPos
<= aPos
.Tab())
409 aPos
.IncTab(rCxt
.mnSheets
);
412 void ScRangeData::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
, SCTAB nLocalTab
)
414 sc::RefUpdateResult aRes
= pCode
->AdjustReferenceOnDeletedTab(rCxt
, aPos
);
415 if (aRes
.mbReferenceModified
)
416 rCxt
.maUpdatedNames
.setUpdatedName(nLocalTab
, nIndex
);
418 if (rCxt
.mnDeletePos
<= aPos
.Tab())
419 aPos
.IncTab(-rCxt
.mnSheets
);
422 void ScRangeData::UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
, SCTAB nLocalTab
)
424 sc::RefUpdateResult aRes
= pCode
->AdjustReferenceOnMovedTab(rCxt
, aPos
);
425 if (aRes
.mbReferenceModified
)
426 rCxt
.maUpdatedNames
.setUpdatedName(nLocalTab
, nIndex
);
428 aPos
.SetTab(rCxt
.getNewTab(aPos
.Tab()));
431 void ScRangeData::MakeValidName( OUString
& rName
)
434 // strip leading invalid characters
436 sal_Int32 nLen
= rName
.getLength();
437 while ( nPos
< nLen
&& !ScCompiler::IsCharFlagAllConventions( rName
, nPos
, SC_COMPILER_C_NAME
) )
440 rName
= rName
.copy(nPos
);
442 // if the first character is an invalid start character, precede with '_'
443 if ( !rName
.isEmpty() && !ScCompiler::IsCharFlagAllConventions( rName
, 0, SC_COMPILER_C_CHAR_NAME
) )
446 // replace invalid with '_'
447 nLen
= rName
.getLength();
448 for (nPos
=0; nPos
<nLen
; nPos
++)
450 if ( !ScCompiler::IsCharFlagAllConventions( rName
, nPos
, SC_COMPILER_C_NAME
) )
451 rName
= rName
.replaceAt( nPos
, 1, "_" );
454 // Ensure that the proposed name is not a reference under any convention,
455 // same as in IsNameValid()
458 for (int nConv
= FormulaGrammar::CONV_UNSPECIFIED
; ++nConv
< FormulaGrammar::CONV_LAST
; )
460 ScAddress::Details
details( static_cast<FormulaGrammar::AddressConvention
>( nConv
) );
461 // Don't check Parse on VALID, any partial only VALID may result in
462 // #REF! during compile later!
463 while (aRange
.Parse( rName
, NULL
, details
) || aAddr
.Parse( rName
, NULL
, details
))
465 //! Range Parse is partially valid also with invalid sheet name,
466 //! Address Parse dito, during compile name would generate a #REF!
467 if ( rName
.indexOf( '.' ) == -1 )
468 rName
= rName
.replaceFirst( ".", "_" );
475 bool ScRangeData::IsNameValid( const OUString
& rName
, ScDocument
* pDoc
)
477 /* XXX If changed, sc/source/filter/ftools/ftools.cxx
478 * ScfTools::ConvertToScDefinedName needs to be changed too. */
480 if (rName
.indexOf(a
) != -1)
483 sal_Int32 nLen
= rName
.getLength();
484 if ( !nLen
|| !ScCompiler::IsCharFlagAllConventions( rName
, nPos
++, SC_COMPILER_C_CHAR_NAME
) )
486 while ( nPos
< nLen
)
488 if ( !ScCompiler::IsCharFlagAllConventions( rName
, nPos
++, SC_COMPILER_C_NAME
) )
493 for (int nConv
= FormulaGrammar::CONV_UNSPECIFIED
; ++nConv
< FormulaGrammar::CONV_LAST
; )
495 ScAddress::Details
details( static_cast<FormulaGrammar::AddressConvention
>( nConv
) );
496 // Don't check Parse on VALID, any partial only VALID may result in
497 // #REF! during compile later!
498 if (aRange
.Parse( rName
, pDoc
, details
) || aAddr
.Parse( rName
, pDoc
, details
))
504 SCROW
ScRangeData::GetMaxRow() const
506 return mnMaxRow
>= 0 ? mnMaxRow
: MAXROW
;
509 SCCOL
ScRangeData::GetMaxCol() const
511 return mnMaxCol
>= 0 ? mnMaxCol
: MAXCOL
;
514 sal_uInt16
ScRangeData::GetErrCode() const
516 return pCode
? pCode
->GetCodeError() : 0;
519 bool ScRangeData::HasReferences() const
521 return pCode
->HasReferences();
524 sal_uInt32
ScRangeData::GetUnoType() const
526 sal_uInt32 nUnoType
= 0;
527 if ( HasType(RT_CRITERIA
) ) nUnoType
|= com::sun::star::sheet::NamedRangeFlag::FILTER_CRITERIA
;
528 if ( HasType(RT_PRINTAREA
) ) nUnoType
|= com::sun::star::sheet::NamedRangeFlag::PRINT_AREA
;
529 if ( HasType(RT_COLHEADER
) ) nUnoType
|= com::sun::star::sheet::NamedRangeFlag::COLUMN_HEADER
;
530 if ( HasType(RT_ROWHEADER
) ) nUnoType
|= com::sun::star::sheet::NamedRangeFlag::ROW_HEADER
;
534 void ScRangeData::ValidateTabRefs()
536 // try to make sure all relative references and the reference position
537 // are within existing tables, so they can be represented as text
538 // (if the range of used tables is more than the existing tables,
539 // the result may still contain invalid tables, because the relative
540 // references aren't changed so formulas stay the same)
542 // find range of used tables
544 SCTAB nMinTab
= aPos
.Tab();
545 SCTAB nMaxTab
= nMinTab
;
548 while ( ( t
= static_cast<ScToken
*>(pCode
->GetNextReference()) ) != NULL
)
550 ScSingleRefData
& rRef1
= t
->GetSingleRef();
551 ScAddress aAbs
= rRef1
.toAbs(aPos
);
552 if ( rRef1
.IsTabRel() && !rRef1
.IsTabDeleted() )
554 if (aAbs
.Tab() < nMinTab
)
555 nMinTab
= aAbs
.Tab();
556 if (aAbs
.Tab() > nMaxTab
)
557 nMaxTab
= aAbs
.Tab();
559 if ( t
->GetType() == svDoubleRef
)
561 ScSingleRefData
& rRef2
= t
->GetDoubleRef().Ref2
;
562 aAbs
= rRef2
.toAbs(aPos
);
563 if ( rRef2
.IsTabRel() && !rRef2
.IsTabDeleted() )
565 if (aAbs
.Tab() < nMinTab
)
566 nMinTab
= aAbs
.Tab();
567 if (aAbs
.Tab() > nMaxTab
)
568 nMaxTab
= aAbs
.Tab();
573 SCTAB nTabCount
= pDoc
->GetTableCount();
574 if ( nMaxTab
>= nTabCount
&& nMinTab
> 0 )
576 // move position and relative tab refs
577 // The formulas that use the name are not changed by this
579 SCTAB nMove
= nMinTab
;
580 ScAddress aOldPos
= aPos
;
581 aPos
.SetTab( aPos
.Tab() - nMove
);
584 while ( ( t
= static_cast<ScToken
*>(pCode
->GetNextReference()) ) != NULL
)
586 switch (t
->GetType())
590 ScSingleRefData
& rRef
= t
->GetSingleRef();
591 if (!rRef
.IsTabDeleted())
593 ScAddress aAbs
= rRef
.toAbs(aOldPos
);
594 rRef
.SetAddress(aAbs
, aPos
);
600 ScComplexRefData
& rRef
= t
->GetDoubleRef();
601 if (!rRef
.Ref1
.IsTabDeleted())
603 ScAddress aAbs
= rRef
.Ref1
.toAbs(aOldPos
);
604 rRef
.Ref1
.SetAddress(aAbs
, aPos
);
606 if (!rRef
.Ref2
.IsTabDeleted())
608 ScAddress aAbs
= rRef
.Ref2
.toAbs(aOldPos
);
609 rRef
.Ref2
.SetAddress(aAbs
, aPos
);
620 void ScRangeData::SetCode( ScTokenArray
& rArr
)
622 boost::scoped_ptr
<ScTokenArray
> pOldCode( pCode
); // old pCode will be deleted
623 pCode
= new ScTokenArray( rArr
);
627 void ScRangeData::InitCode()
629 if( !pCode
->GetCodeError() )
632 FormulaToken
* p
= pCode
->GetNextReference();
633 if( p
) // exact one reference at first
635 if( p
->GetType() == svSingleRef
)
636 eType
= eType
| RT_ABSPOS
;
638 eType
= eType
| RT_ABSAREA
;
644 int SAL_CALL
ScRangeData_QsortNameCompare( const void* p1
, const void* p2
)
646 return (int) ScGlobal::GetCollator()->compareString(
647 (*(const ScRangeData
**)p1
)->GetName(),
648 (*(const ScRangeData
**)p2
)->GetName() );
651 bool operator<(const ScRangeData
& left
, const ScRangeData
& right
)
653 return left
.GetName() < right
.GetName();
659 * Predicate to check if the name references the specified range.
661 class MatchByRange
: public unary_function
<ScRangeData
, bool>
663 const ScRange
& mrRange
;
665 MatchByRange(const ScRange
& rRange
) : mrRange(rRange
) {}
666 template < typename Pair
>
667 bool operator() ( Pair
const& r
) const
669 return r
.second
->IsRangeAtBlock(mrRange
);
675 ScRangeName::ScRangeName() {}
677 ScRangeName::ScRangeName(const ScRangeName
& r
) :
680 // boost::ptr_set clones and deletes, so each collection needs its own
682 maIndexToData
.resize( r
.maIndexToData
.size(), NULL
);
683 DataType::const_iterator itr
= maData
.begin(), itrEnd
= maData
.end();
684 for (; itr
!= itrEnd
; ++itr
)
686 size_t nPos
= itr
->second
->GetIndex() - 1;
687 if (nPos
>= maIndexToData
.size())
689 OSL_FAIL( "ScRangeName copy-ctor: maIndexToData size doesn't fit");
690 maIndexToData
.resize(nPos
+1, NULL
);
692 maIndexToData
[nPos
] = const_cast<ScRangeData
*>(itr
->second
);
696 const ScRangeData
* ScRangeName::findByRange(const ScRange
& rRange
) const
698 DataType::const_iterator itr
= std::find_if(
699 maData
.begin(), maData
.end(), MatchByRange(rRange
));
700 return itr
== maData
.end() ? NULL
: itr
->second
;
703 ScRangeData
* ScRangeName::findByUpperName(const OUString
& rName
)
705 DataType::iterator itr
= maData
.find(rName
);
706 return itr
== maData
.end() ? NULL
: itr
->second
;
709 const ScRangeData
* ScRangeName::findByUpperName(const OUString
& rName
) const
711 DataType::const_iterator itr
= maData
.find(rName
);
712 return itr
== maData
.end() ? NULL
: itr
->second
;
715 ScRangeData
* ScRangeName::findByIndex(sal_uInt16 i
) const
718 // index should never be zero.
722 return nPos
< maIndexToData
.size() ? maIndexToData
[nPos
] : NULL
;
725 void ScRangeName::UpdateReference(sc::RefUpdateContext
& rCxt
, SCTAB nLocalTab
)
727 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
728 for (; itr
!= itrEnd
; ++itr
)
729 itr
->second
->UpdateReference(rCxt
, nLocalTab
);
732 void ScRangeName::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
, SCTAB nLocalTab
)
734 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
735 for (; itr
!= itrEnd
; ++itr
)
736 itr
->second
->UpdateInsertTab(rCxt
, nLocalTab
);
739 void ScRangeName::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
, SCTAB nLocalTab
)
741 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
742 for (; itr
!= itrEnd
; ++itr
)
743 itr
->second
->UpdateDeleteTab(rCxt
, nLocalTab
);
746 void ScRangeName::UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
, SCTAB nLocalTab
)
748 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
749 for (; itr
!= itrEnd
; ++itr
)
750 itr
->second
->UpdateMoveTab(rCxt
, nLocalTab
);
753 void ScRangeName::UpdateTranspose(const ScRange
& rSource
, const ScAddress
& rDest
)
755 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
756 for (; itr
!= itrEnd
; ++itr
)
757 itr
->second
->UpdateTranspose(rSource
, rDest
);
760 void ScRangeName::UpdateGrow(const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
762 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
763 for (; itr
!= itrEnd
; ++itr
)
764 itr
->second
->UpdateGrow(rArea
, nGrowX
, nGrowY
);
767 void ScRangeName::CompileUnresolvedXML()
769 DataType::iterator itr
= maData
.begin(), itrEnd
= maData
.end();
770 for (; itr
!= itrEnd
; ++itr
)
771 itr
->second
->CompileUnresolvedXML();
774 ScRangeName::const_iterator
ScRangeName::begin() const
776 return maData
.begin();
779 ScRangeName::const_iterator
ScRangeName::end() const
784 ScRangeName::iterator
ScRangeName::begin()
786 return maData
.begin();
789 ScRangeName::iterator
ScRangeName::end()
794 size_t ScRangeName::size() const
796 return maData
.size();
799 bool ScRangeName::empty() const
801 return maData
.empty();
804 bool ScRangeName::insert(ScRangeData
* p
)
811 // Assign a new index. An index must be unique and is never 0.
812 IndexDataType::iterator itr
= std::find(
813 maIndexToData
.begin(), maIndexToData
.end(), static_cast<ScRangeData
*>(NULL
));
814 if (itr
!= maIndexToData
.end())
816 // Empty slot exists. Re-use it.
817 size_t nPos
= std::distance(maIndexToData
.begin(), itr
);
818 p
->SetIndex(nPos
+ 1);
821 // No empty slot. Append it to the end.
822 p
->SetIndex(maIndexToData
.size() + 1);
825 OUString
aName(p
->GetUpperName());
826 erase(aName
); // ptr_map won't insert it if a duplicate name exists.
827 pair
<DataType::iterator
, bool> r
= maData
.insert(aName
, p
);
830 // Data inserted. Store its index for mapping.
831 size_t nPos
= p
->GetIndex() - 1;
832 if (nPos
>= maIndexToData
.size())
833 maIndexToData
.resize(nPos
+1, NULL
);
834 maIndexToData
[nPos
] = p
;
839 void ScRangeName::erase(const ScRangeData
& r
)
841 erase(r
.GetUpperName());
844 void ScRangeName::erase(const OUString
& rName
)
846 DataType::iterator itr
= maData
.find(rName
);
847 if (itr
!= maData
.end())
851 void ScRangeName::erase(const iterator
& itr
)
853 sal_uInt16 nIndex
= itr
->second
->GetIndex();
855 OSL_ENSURE( 0 < nIndex
&& nIndex
<= maIndexToData
.size(), "ScRangeName::erase: bad index");
856 if (0 < nIndex
&& nIndex
<= maIndexToData
.size())
857 maIndexToData
[nIndex
-1] = NULL
;
860 void ScRangeName::clear()
863 maIndexToData
.clear();
866 bool ScRangeName::operator== (const ScRangeName
& r
) const
868 return maData
== r
.maData
;
871 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */