Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <string.h>
30 : : #include <memory>
31 : : #include <unotools/collatorwrapper.hxx>
32 : : #include <unotools/transliterationwrapper.hxx>
33 : : #include <com/sun/star/sheet/NamedRangeFlag.hpp>
34 : :
35 : : #include "token.hxx"
36 : : #include "tokenarray.hxx"
37 : : #include "rangenam.hxx"
38 : : #include "global.hxx"
39 : : #include "compiler.hxx"
40 : : #include "rangeutl.hxx"
41 : : #include "rechead.hxx"
42 : : #include "refupdat.hxx"
43 : : #include "document.hxx"
44 : :
45 : : using namespace formula;
46 : : using ::std::pair;
47 : : using ::std::unary_function;
48 : : using ::rtl::OUString;
49 : :
50 : : //========================================================================
51 : : // ScRangeData
52 : : //========================================================================
53 : :
54 : 136 : ScRangeData::ScRangeData( ScDocument* pDok,
55 : : const rtl::OUString& rName,
56 : : const String& rSymbol,
57 : : const ScAddress& rAddress,
58 : : RangeType nType,
59 : : const FormulaGrammar::Grammar eGrammar ) :
60 : : aName ( rName ),
61 : : aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
62 : : pCode ( NULL ),
63 : : aPos ( rAddress ),
64 : : eType ( nType ),
65 : : pDoc ( pDok ),
66 : : eTempGrammar( eGrammar ),
67 : : nIndex ( 0 ),
68 : : bModified ( false ),
69 : : mnMaxRow (-1),
70 [ + - ]: 136 : mnMaxCol (-1)
71 : : {
72 [ + - ]: 136 : if (rSymbol.Len() > 0)
73 [ + - ]: 136 : CompileRangeData( rSymbol, pDoc->IsImportingXML());
74 : : // Let the compiler set an error on unknown names for a subsequent
75 : : // CompileUnresolvedXML().
76 : : else
77 : : {
78 : : // #i63513#/#i65690# don't leave pCode as NULL.
79 : : // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
80 : : // to ensure same behavior if unnecessary copying is left out.
81 : :
82 [ # # ][ # # ]: 0 : pCode = new ScTokenArray();
83 : : }
84 : 136 : }
85 : :
86 : 111 : ScRangeData::ScRangeData( ScDocument* pDok,
87 : : const rtl::OUString& rName,
88 : : const ScTokenArray& rArr,
89 : : const ScAddress& rAddress,
90 : : RangeType nType ) :
91 : : aName ( rName ),
92 : : aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
93 [ + - ]: 111 : pCode ( new ScTokenArray( rArr ) ),
94 : : aPos ( rAddress ),
95 : : eType ( nType ),
96 : : pDoc ( pDok ),
97 : : eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
98 : : nIndex ( 0 ),
99 : : bModified ( false ),
100 : : mnMaxRow (-1),
101 [ + - ][ + - ]: 222 : mnMaxCol (-1)
102 : : {
103 [ + - ]: 111 : if( !pCode->GetCodeError() )
104 : : {
105 : 111 : pCode->Reset();
106 [ + - ]: 111 : FormulaToken* p = pCode->GetNextReference();
107 [ + + ]: 111 : if( p )// genau eine Referenz als erstes
108 : : {
109 [ + + ]: 96 : if( p->GetType() == svSingleRef )
110 : 51 : eType = eType | RT_ABSPOS;
111 : : else
112 : 45 : eType = eType | RT_ABSAREA;
113 : : }
114 : : }
115 : 111 : }
116 : :
117 : 9 : ScRangeData::ScRangeData( ScDocument* pDok,
118 : : const rtl::OUString& rName,
119 : : const ScAddress& rTarget ) :
120 : : aName ( rName ),
121 : : aUpperName ( ScGlobal::pCharClass->uppercase( rName ) ),
122 : 0 : pCode ( new ScTokenArray() ),
123 : : aPos ( rTarget ),
124 : : eType ( RT_NAME ),
125 : : pDoc ( pDok ),
126 : : eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
127 : : nIndex ( 0 ),
128 : : bModified ( false ),
129 : : mnMaxRow (-1),
130 [ + - ][ + - ]: 9 : mnMaxCol (-1)
[ + - ]
131 : : {
132 : : ScSingleRefData aRefData;
133 : 9 : aRefData.InitAddress( rTarget );
134 : 9 : aRefData.SetFlag3D( sal_True );
135 [ + - ]: 9 : pCode->AddSingleReference( aRefData );
136 [ + - ]: 9 : ScCompiler aComp( pDoc, aPos, *pCode );
137 [ + - ][ + - ]: 9 : aComp.SetGrammar(pDoc->GetGrammar());
138 [ + - ]: 9 : aComp.CompileTokenArray();
139 [ + - ]: 9 : if ( !pCode->GetCodeError() )
140 [ + - ]: 9 : eType |= RT_ABSPOS;
141 : 9 : }
142 : :
143 : 697 : ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument) :
144 : : aName (rScRangeData.aName),
145 : : aUpperName (rScRangeData.aUpperName),
146 : 0 : pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor)
147 : : aPos (rScRangeData.aPos),
148 : : eType (rScRangeData.eType),
149 : : pDoc (pDocument ? pDocument : rScRangeData.pDoc),
150 : : eTempGrammar(rScRangeData.eTempGrammar),
151 : : nIndex (rScRangeData.nIndex),
152 : : bModified (rScRangeData.bModified),
153 : : mnMaxRow (rScRangeData.mnMaxRow),
154 [ + - ][ + - ]: 697 : mnMaxCol (rScRangeData.mnMaxCol)
[ # # ][ # # ]
[ + + ]
155 : 697 : {}
156 : :
157 : 926 : ScRangeData::~ScRangeData()
158 : : {
159 [ + - ][ + - ]: 926 : delete pCode;
160 : 926 : }
161 : :
162 : 139 : void ScRangeData::CompileRangeData( const String& rSymbol, bool bSetError )
163 : : {
164 [ - + ]: 139 : if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
165 : : {
166 : : OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
167 : : // Anything is almost as bad as this, but we might have the best choice
168 : : // if not loading documents.
169 : 0 : eTempGrammar = FormulaGrammar::GRAM_NATIVE;
170 : : }
171 : :
172 [ + - ]: 139 : ScCompiler aComp( pDoc, aPos );
173 [ + - ]: 139 : aComp.SetGrammar( eTempGrammar);
174 [ + + ]: 139 : if (bSetError)
175 : 74 : aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK);
176 [ + - ]: 139 : ScTokenArray* pNewCode = aComp.CompileString( rSymbol );
177 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
178 : 139 : ::std::auto_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted
179 : : SAL_WNODEPRECATED_DECLARATIONS_POP
180 : 139 : pCode = pNewCode;
181 [ + + ]: 139 : if( !pCode->GetCodeError() )
182 : : {
183 : 136 : pCode->Reset();
184 [ + - ]: 136 : FormulaToken* p = pCode->GetNextReference();
185 [ + + ]: 136 : if( p )
186 : : {
187 : : // first token is a reference
188 : : /* FIXME: wouldn't that need a check if it's exactly one reference? */
189 [ + + ]: 130 : if( p->GetType() == svSingleRef )
190 : 95 : eType = eType | RT_ABSPOS;
191 : : else
192 : 35 : eType = eType | RT_ABSAREA;
193 : : }
194 : : // For manual input set an error for an incomplete formula.
195 [ + + ]: 136 : if (!pDoc->IsImportingXML())
196 : : {
197 [ + - ]: 62 : aComp.CompileTokenArray();
198 [ + - ]: 62 : pCode->DelRPN();
199 : : }
200 [ + - ][ + - ]: 139 : }
201 : 139 : }
202 : :
203 : 74 : void ScRangeData::CompileUnresolvedXML()
204 : : {
205 [ + + ]: 74 : if (pCode->GetCodeError() == errNoName)
206 : : {
207 : : // Reconstruct the symbol/formula and then recompile.
208 [ + - ]: 3 : String aSymbol;
209 [ + - ]: 3 : ScCompiler aComp( pDoc, aPos, *pCode);
210 [ + - ]: 3 : aComp.SetGrammar( eTempGrammar);
211 [ + - ]: 3 : aComp.CreateStringFromTokenArray( aSymbol);
212 : : // Don't let the compiler set an error for unknown names on final
213 : : // compile, errors are handled by the interpreter thereafter.
214 [ + - ][ + - ]: 3 : CompileRangeData( aSymbol, false);
[ + - ]
215 : : }
216 : 74 : }
217 : :
218 : 102 : void ScRangeData::GuessPosition()
219 : : {
220 : : // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
221 : : // ohne Fehler verabsolutiert werden koennen
222 : :
223 : : OSL_ENSURE(aPos == ScAddress(), "die Position geht jetzt verloren");
224 : :
225 : 102 : SCsCOL nMinCol = 0;
226 : 102 : SCsROW nMinRow = 0;
227 : 102 : SCsTAB nMinTab = 0;
228 : :
229 : : ScToken* t;
230 : 102 : pCode->Reset();
231 [ + + ]: 189 : while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
232 : : {
233 : 87 : ScSingleRefData& rRef1 = t->GetSingleRef();
234 [ - + ][ - + ]: 87 : if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol )
[ + + ]
235 : 0 : nMinCol = rRef1.nRelCol;
236 [ + + ][ + - ]: 87 : if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow )
[ + + ]
237 : 3 : nMinRow = rRef1.nRelRow;
238 [ + + ][ - + ]: 87 : if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab )
[ - + ]
239 : 0 : nMinTab = rRef1.nRelTab;
240 : :
241 [ + + ]: 87 : if ( t->GetType() == svDoubleRef )
242 : : {
243 : 36 : ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
244 [ # # ][ - + ]: 36 : if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol )
[ - + ]
245 : 0 : nMinCol = rRef2.nRelCol;
246 [ - + ][ # # ]: 36 : if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow )
[ - + ]
247 : 0 : nMinRow = rRef2.nRelRow;
248 [ - + ][ # # ]: 36 : if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab )
[ - + ]
249 : 0 : nMinTab = rRef2.nRelTab;
250 : : }
251 : : }
252 : :
253 : 102 : aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
254 : 102 : }
255 : :
256 : 38 : void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
257 : : {
258 [ + - ]: 38 : ScCompiler aComp(pDoc, aPos, *pCode);
259 [ + - ]: 38 : aComp.SetGrammar(eGrammar);
260 [ + - ][ + - ]: 38 : aComp.CreateStringFromTokenArray( rSymbol );
261 : 38 : }
262 : :
263 : 0 : void ScRangeData::GetSymbol( OUString& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
264 : : {
265 [ # # ]: 0 : String aStr;
266 [ # # ]: 0 : GetSymbol(aStr, eGrammar);
267 [ # # ][ # # ]: 0 : rSymbol = aStr;
268 : 0 : }
269 : :
270 : 0 : void ScRangeData::GetSymbol( OUString& rSymbol, const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) const
271 : : {
272 [ # # ]: 0 : String aStr;
273 [ # # ]: 0 : ScCompiler aComp(pDoc, rPos, *pCode);
274 [ # # ]: 0 : aComp.SetGrammar(eGrammar);
275 [ # # ]: 0 : aComp.CreateStringFromTokenArray( aStr );
276 [ # # ][ # # ]: 0 : rSymbol = aStr;
[ # # ]
277 : 0 : }
278 : :
279 : 33 : void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
280 : : const FormulaGrammar::Grammar eGrammar )
281 : : {
282 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
283 [ + - ]: 33 : ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
284 : : SAL_WNODEPRECATED_DECLARATIONS_POP
285 [ + - ]: 33 : ScCompiler aComp( pDoc, rPos, *pTemp.get());
286 [ + - ]: 33 : aComp.SetGrammar(eGrammar);
287 [ + - ]: 33 : aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
288 [ + - ][ + - ]: 33 : aComp.CreateStringFromTokenArray( rBuffer );
[ + - ]
289 : 33 : }
290 : :
291 : 3 : void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode,
292 : : const ScRange& r,
293 : : SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal )
294 : : {
295 : 3 : bool bChanged = false;
296 : :
297 : 3 : pCode->Reset();
298 [ + - ][ + - ]: 3 : if( pCode->GetNextReference() )
299 : : {
300 : 3 : bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED);
301 [ + - ]: 3 : ScCompiler aComp( pDoc, aPos, *pCode );
302 [ + - ][ + - ]: 3 : aComp.SetGrammar(pDoc->GetGrammar());
303 : : const bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
304 : : nDx, nDy, nDz,
305 [ + - ]: 3 : bChanged, bSharedFormula, bLocal);
306 [ - + ]: 3 : if (bSharedFormula)
307 : : {
308 [ # # ]: 0 : if (bRelRef)
309 : 0 : eType = eType | RT_SHAREDMOD;
310 : : else
311 : 0 : eType = eType & ~RT_SHAREDMOD;
312 [ + - ]: 3 : }
313 : : }
314 : :
315 : 3 : bModified = bChanged;
316 : 3 : }
317 : :
318 : :
319 : 0 : void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
320 : : {
321 : 0 : bool bChanged = false;
322 : :
323 : : ScToken* t;
324 : 0 : pCode->Reset();
325 : :
326 [ # # ]: 0 : while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
327 : : {
328 [ # # ]: 0 : if( t->GetType() != svIndex )
329 : : {
330 [ # # ]: 0 : SingleDoubleRefModifier aMod( *t );
331 : 0 : ScComplexRefData& rRef = aMod.Ref();
332 [ # # # # : 0 : if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
# # # # #
# # # # #
# # ][ # # ]
[ # # ]
333 : 0 : (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
334 : 0 : ( t->GetType() == svSingleRef ||
335 : 0 : (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
336 : 0 : (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
337 : : {
338 [ # # ][ # # ]: 0 : if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING )
339 : 0 : bChanged = true;
340 : 0 : }
341 : : }
342 : : }
343 : :
344 : 0 : bModified = bChanged;
345 : 0 : }
346 : :
347 : 0 : void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
348 : : {
349 : 0 : bool bChanged = false;
350 : :
351 : : ScToken* t;
352 : 0 : pCode->Reset();
353 : :
354 [ # # ]: 0 : while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
355 : : {
356 [ # # ]: 0 : if( t->GetType() != svIndex )
357 : : {
358 [ # # ]: 0 : SingleDoubleRefModifier aMod( *t );
359 : 0 : ScComplexRefData& rRef = aMod.Ref();
360 [ # # # # : 0 : if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
# # # # #
# # # # #
# # ][ # # ]
[ # # ]
361 : 0 : (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
362 : 0 : ( t->GetType() == svSingleRef ||
363 : 0 : (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
364 : 0 : (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
365 : : {
366 [ # # ][ # # ]: 0 : if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING )
367 : 0 : bChanged = true;
368 : 0 : }
369 : : }
370 : : }
371 : :
372 : 0 : bModified = bChanged; // muss direkt hinterher ausgewertet werden
373 : 0 : }
374 : :
375 : 10 : bool ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo
376 : : {
377 [ + - + - : 30 : if ( nIndex != rData.nIndex ||
+ - ][ - + ]
[ - + ]
378 : 10 : aName != rData.aName ||
379 : 10 : aPos != rData.aPos ||
380 : 0 : eType != rData.eType ) return false;
381 : :
382 : 10 : sal_uInt16 nLen = pCode->GetLen();
383 [ - + ]: 10 : if ( nLen != rData.pCode->GetLen() ) return false;
384 : :
385 : 10 : FormulaToken** ppThis = pCode->GetArray();
386 : 10 : FormulaToken** ppOther = rData.pCode->GetArray();
387 : :
388 [ + + ]: 18 : for ( sal_uInt16 i=0; i<nLen; i++ )
389 [ + - ][ + + ]: 10 : if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
[ + + ]
390 : 2 : return false;
391 : :
392 : 10 : return true;
393 : : }
394 : :
395 : :
396 : 116 : bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
397 : : {
398 : 116 : bool bRet = false;
399 : 116 : ScRange aRange;
400 [ + + ][ + - ]: 116 : if ( IsReference(aRange) )
401 : 114 : bRet = ( rBlock == aRange );
402 : 116 : return bRet;
403 : : }
404 : :
405 : 125 : bool ScRangeData::IsReference( ScRange& rRange ) const
406 : : {
407 [ + - ][ + - ]: 125 : if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
408 : 125 : return pCode->IsReference( rRange );
409 : :
410 : 125 : return false;
411 : : }
412 : :
413 : 0 : bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
414 : : {
415 [ # # ][ # # ]: 0 : if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
416 : : {
417 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
418 [ # # ]: 0 : ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
419 : : SAL_WNODEPRECATED_DECLARATIONS_POP
420 [ # # ]: 0 : ScCompiler aComp( pDoc, rPos, *pTemp);
421 [ # # ][ # # ]: 0 : aComp.SetGrammar(pDoc->GetGrammar());
422 [ # # ]: 0 : aComp.MoveRelWrap(MAXCOL, MAXROW);
423 [ # # ][ # # ]: 0 : return pTemp->IsReference( rRange );
[ # # ]
424 : : }
425 : :
426 : 0 : return false;
427 : : }
428 : :
429 : 404 : bool ScRangeData::IsValidReference( ScRange& rRange ) const
430 : : {
431 [ + - ][ + - ]: 404 : if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
432 : 404 : return pCode->IsValidReference( rRange );
433 : :
434 : 404 : return false;
435 : : }
436 : :
437 : 40 : void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable, SCTAB nNewSheets)
438 : : {
439 : 40 : pCode->Reset();
440 [ + - ]: 40 : if( pCode->GetNextReference() )
441 : : {
442 : 40 : ScRangeData* pRangeData = NULL; // must not be dereferenced
443 : : bool bChanged;
444 [ + - ]: 40 : ScCompiler aComp( pDoc, aPos, *pCode);
445 [ + - ][ + - ]: 40 : aComp.SetGrammar(pDoc->GetGrammar());
446 [ + + + - ]: 40 : switch (nFlag)
447 : : {
448 : : case 1: // einfache InsertTab (doc.cxx)
449 [ + - ]: 8 : pRangeData = aComp.UpdateInsertTab(nOldTable, true, nNewSheets ); // und CopyTab (doc2.cxx)
450 : 8 : break;
451 : : case 2: // einfaches delete (doc.cxx)
452 [ + - ]: 29 : pRangeData = aComp.UpdateDeleteTab(nOldTable, false, true, bChanged);
453 : 29 : break;
454 : : case 3: // move (doc2.cxx)
455 : : {
456 [ + - ]: 3 : pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, true );
457 : : }
458 : 3 : break;
459 : : default:
460 : : {
461 : : OSL_FAIL("ScRangeName::UpdateTabRef: Unknown Flag");
462 : : }
463 : 0 : break;
464 : : }
465 [ - + ]: 40 : if (eType&RT_SHARED)
466 : : {
467 [ # # ]: 0 : if (pRangeData)
468 : 0 : eType = eType | RT_SHAREDMOD;
469 : : else
470 : 0 : eType = eType & ~RT_SHAREDMOD;
471 [ + - ]: 40 : }
472 : : }
473 : 40 : }
474 : :
475 : :
476 : 16 : void ScRangeData::MakeValidName( String& rName )
477 : : {
478 : :
479 : : // strip leading invalid characters
480 : 16 : xub_StrLen nPos = 0;
481 : 16 : xub_StrLen nLen = rName.Len();
482 [ + + ][ + - ]: 16 : while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
[ - + ][ - + ]
483 : 0 : ++nPos;
484 [ - + ]: 16 : if ( nPos>0 )
485 [ # # ]: 0 : rName.Erase(0,nPos);
486 : :
487 : : // if the first character is an invalid start character, precede with '_'
488 [ + + ][ + - ]: 16 : if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
[ - + ][ - + ]
489 [ # # ]: 0 : rName.Insert('_',0);
490 : :
491 : : // replace invalid with '_'
492 : 16 : nLen = rName.Len();
493 [ + + ]: 82 : for (nPos=0; nPos<nLen; nPos++)
494 : : {
495 [ + - ][ - + ]: 66 : if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
496 [ # # ]: 0 : rName.SetChar( nPos, '_' );
497 : : }
498 : :
499 : : // Ensure that the proposed name is not a reference under any convention,
500 : : // same as in IsNameValid()
501 : 16 : ScAddress aAddr;
502 : 16 : ScRange aRange;
503 [ + + ]: 112 : for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
504 : : {
505 : 96 : ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
506 : : // Don't check Parse on VALID, any partial only VALID may result in
507 : : // #REF! during compile later!
508 [ + - ][ + - ]: 96 : while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
[ + - ][ - + ]
[ - + ]
509 : : {
510 : : //! Range Parse is partially valid also with invalid sheet name,
511 : : //! Address Parse dito, during compile name would generate a #REF!
512 [ # # ][ # # ]: 0 : if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
513 [ # # ]: 0 : rName.Insert('_',0);
514 : : }
515 : : }
516 : 16 : }
517 : :
518 : 0 : bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
519 : : {
520 : : /* XXX If changed, sc/source/filter/ftools/ftools.cxx
521 : : * ScfTools::ConvertToScDefinedName needs to be changed too. */
522 : 0 : sal_Char a('.');
523 [ # # ][ # # ]: 0 : if (rName.Search(a, 0) != STRING_NOTFOUND)
524 : 0 : return false;
525 : 0 : xub_StrLen nPos = 0;
526 : 0 : xub_StrLen nLen = rName.Len();
527 [ # # ][ # # ]: 0 : if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
[ # # ][ # # ]
528 : 0 : return false;
529 [ # # ]: 0 : while ( nPos < nLen )
530 : : {
531 [ # # ][ # # ]: 0 : if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
532 : 0 : return false;
533 : : }
534 : 0 : ScAddress aAddr;
535 : 0 : ScRange aRange;
536 [ # # ]: 0 : for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
537 : : {
538 : 0 : ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
539 : : // Don't check Parse on VALID, any partial only VALID may result in
540 : : // #REF! during compile later!
541 [ # # ][ # # ]: 0 : if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
[ # # ][ # # ]
[ # # ]
542 : 0 : return false;
543 : : }
544 : 0 : return true;
545 : : }
546 : :
547 : 0 : void ScRangeData::SetMaxRow(SCROW nRow)
548 : : {
549 : 0 : mnMaxRow = nRow;
550 : 0 : }
551 : :
552 : 233 : SCROW ScRangeData::GetMaxRow() const
553 : : {
554 [ - + ]: 233 : return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
555 : : }
556 : :
557 : 0 : void ScRangeData::SetMaxCol(SCCOL nCol)
558 : : {
559 : 0 : mnMaxCol = nCol;
560 : 0 : }
561 : :
562 : 233 : SCCOL ScRangeData::GetMaxCol() const
563 : : {
564 [ - + ]: 233 : return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
565 : : }
566 : :
567 : :
568 : 218 : sal_uInt16 ScRangeData::GetErrCode() const
569 : : {
570 [ + - ]: 218 : return pCode ? pCode->GetCodeError() : 0;
571 : : }
572 : :
573 : 240 : bool ScRangeData::HasReferences() const
574 : : {
575 : 240 : pCode->Reset();
576 : 240 : return pCode->GetNextReference() != NULL;
577 : : }
578 : :
579 : 0 : sal_uInt32 ScRangeData::GetUnoType() const
580 : : {
581 : 0 : sal_uInt32 nUnoType = 0;
582 [ # # ]: 0 : if ( HasType(RT_CRITERIA) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::FILTER_CRITERIA;
583 [ # # ]: 0 : if ( HasType(RT_PRINTAREA) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::PRINT_AREA;
584 [ # # ]: 0 : if ( HasType(RT_COLHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::COLUMN_HEADER;
585 [ # # ]: 0 : if ( HasType(RT_ROWHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::ROW_HEADER;
586 : 0 : return nUnoType;
587 : : }
588 : :
589 : 46 : void ScRangeData::ValidateTabRefs()
590 : : {
591 : : // try to make sure all relative references and the reference position
592 : : // are within existing tables, so they can be represented as text
593 : : // (if the range of used tables is more than the existing tables,
594 : : // the result may still contain invalid tables, because the relative
595 : : // references aren't changed so formulas stay the same)
596 : :
597 : : // find range of used tables
598 : :
599 : 46 : SCTAB nMinTab = aPos.Tab();
600 : 46 : SCTAB nMaxTab = nMinTab;
601 : : ScToken* t;
602 : 46 : pCode->Reset();
603 [ + + ]: 92 : while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
604 : : {
605 : 46 : ScSingleRefData& rRef1 = t->GetSingleRef();
606 [ + - ][ + + ]: 46 : if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
[ + + ]
607 : : {
608 [ - + ]: 20 : if ( rRef1.nTab < nMinTab )
609 : 0 : nMinTab = rRef1.nTab;
610 [ - + ]: 20 : if ( rRef1.nTab > nMaxTab )
611 : 0 : nMaxTab = rRef1.nTab;
612 : : }
613 [ + + ]: 46 : if ( t->GetType() == svDoubleRef )
614 : : {
615 : 14 : ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
616 [ + - ][ + + ]: 14 : if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
[ + + ]
617 : : {
618 [ - + ]: 2 : if ( rRef2.nTab < nMinTab )
619 : 0 : nMinTab = rRef2.nTab;
620 [ - + ]: 2 : if ( rRef2.nTab > nMaxTab )
621 : 0 : nMaxTab = rRef2.nTab;
622 : : }
623 : : }
624 : : }
625 : :
626 : 46 : SCTAB nTabCount = pDoc->GetTableCount();
627 [ # # ][ - + ]: 46 : if ( nMaxTab >= nTabCount && nMinTab > 0 )
628 : : {
629 : : // move position and relative tab refs
630 : : // The formulas that use the name are not changed by this
631 : :
632 : 0 : SCTAB nMove = nMinTab;
633 : 0 : aPos.SetTab( aPos.Tab() - nMove );
634 : :
635 : 0 : pCode->Reset();
636 [ # # ]: 0 : while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
637 : : {
638 : 0 : ScSingleRefData& rRef1 = t->GetSingleRef();
639 [ # # ][ # # ]: 0 : if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
[ # # ]
640 : 0 : rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove );
641 [ # # ]: 0 : if ( t->GetType() == svDoubleRef )
642 : : {
643 : 0 : ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
644 [ # # ][ # # ]: 0 : if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
[ # # ]
645 : 0 : rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove );
646 : : }
647 : : }
648 : : }
649 : 46 : }
650 : :
651 : :
652 : : extern "C"
653 : 56 : int SAL_CALL ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
654 : : {
655 : : return (int) ScGlobal::GetCollator()->compareString(
656 : 56 : (*(const ScRangeData**)p1)->GetName(),
657 : 112 : (*(const ScRangeData**)p2)->GetName() );
658 : : }
659 : :
660 : 0 : bool operator<(const ScRangeData& left, const ScRangeData& right)
661 : : {
662 : 0 : return left.GetName() < right.GetName();
663 : : }
664 : :
665 : : namespace {
666 : :
667 : : /**
668 : : * Predicate to check if the name references the specified range.
669 : : */
670 : : class MatchByRange : public unary_function<ScRangeData, bool>
671 : : {
672 : : const ScRange& mrRange;
673 : : public:
674 : 202 : MatchByRange(const ScRange& rRange) : mrRange(rRange) {}
675 : : template < typename Pair >
676 : 116 : bool operator() ( Pair const& r) const
677 : : {
678 : 116 : return r.second->IsRangeAtBlock(mrRange);
679 : : }
680 : : };
681 : :
682 : : class MatchByIndex : public unary_function<ScRangeData, bool>
683 : : {
684 : : sal_uInt16 mnIndex;
685 : : public:
686 : : MatchByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
687 : : bool operator() (const ScRangeData& r) const
688 : : {
689 : : return mnIndex == r.GetIndex();
690 : : }
691 : : };
692 : :
693 : : }
694 : :
695 [ + - ]: 640 : ScRangeName::ScRangeName() {}
696 : :
697 : 163 : ScRangeName::ScRangeName(const ScRangeName& r) :
698 [ + - ]: 163 : maData(r.maData)
699 : : {
700 : : // boost::ptr_set clones and deletes, so each collection needs its own
701 : : // index to data.
702 [ + - ]: 163 : maIndexToData.resize( r.maIndexToData.size(), NULL);
703 [ + - ][ + - ]: 163 : DataType::const_iterator itr = maData.begin(), itrEnd = maData.end();
[ + - ][ + - ]
704 [ + - ][ + - ]: 844 : for (; itr != itrEnd; ++itr)
[ + + ]
705 : : {
706 [ + - ]: 681 : size_t nPos = itr->second->GetIndex() - 1;
707 [ - + ]: 681 : if (nPos >= maIndexToData.size())
708 : : {
709 : : OSL_FAIL( "ScRangeName copy-ctor: maIndexToData size doesn't fit");
710 [ # # ]: 0 : maIndexToData.resize(nPos+1, NULL);
711 : : }
712 [ + - ]: 681 : maIndexToData[nPos] = const_cast<ScRangeData*>(itr->second);
713 : : }
714 : 163 : }
715 : :
716 : 202 : const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
717 : : {
718 : : DataType::const_iterator itr = std::find_if(
719 [ + - ][ + - ]: 202 : maData.begin(), maData.end(), MatchByRange(rRange));
[ + - ]
720 [ + - ][ + - ]: 202 : return itr == maData.end() ? NULL : itr->second;
[ + - ][ # # ]
[ - + ][ # # ]
721 : : }
722 : :
723 : 948 : ScRangeData* ScRangeName::findByUpperName(const OUString& rName)
724 : : {
725 [ + - ]: 948 : DataType::iterator itr = maData.find(rName);
726 [ + - ][ + - ]: 948 : return itr == maData.end() ? NULL : itr->second;
[ + + ][ + - ]
[ + + ][ # # ]
727 : : }
728 : :
729 : 36 : const ScRangeData* ScRangeName::findByUpperName(const OUString& rName) const
730 : : {
731 [ + - ]: 36 : DataType::const_iterator itr = maData.find(rName);
732 [ + - ][ + - ]: 36 : return itr == maData.end() ? NULL : itr->second;
[ + - ][ # # ]
[ - + ][ # # ]
733 : : }
734 : :
735 : 371 : ScRangeData* ScRangeName::findByIndex(sal_uInt16 i) const
736 : : {
737 [ - + ]: 371 : if (!i)
738 : : // index should never be zero.
739 : 0 : return NULL;
740 : :
741 : 371 : size_t nPos = i - 1;
742 [ + - ]: 371 : return nPos < maIndexToData.size() ? maIndexToData[nPos] : NULL;
743 : : }
744 : :
745 : 40 : void ScRangeName::UpdateReference(
746 : : UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal)
747 : : {
748 [ + - ][ + - ]: 40 : DataType::iterator itr = maData.begin(), itrEnd = maData.end();
749 [ + - ][ + - ]: 43 : for (; itr != itrEnd; ++itr)
[ + + ]
750 [ + - ][ + - ]: 3 : itr->second->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz, bLocal);
751 : 40 : }
752 : :
753 : 191 : void ScRangeName::UpdateTabRef(SCTAB nTable, sal_uInt16 nFlag, SCTAB nNewTable, SCTAB nNewSheets)
754 : : {
755 [ + - ][ + - ]: 191 : DataType::iterator itr = maData.begin(), itrEnd = maData.end();
756 [ + - ][ + - ]: 231 : for (; itr != itrEnd; ++itr)
[ + + ]
757 [ + - ][ + - ]: 40 : itr->second->UpdateTabRef(nTable, nFlag, nNewTable, nNewSheets);
758 : 191 : }
759 : :
760 : 0 : void ScRangeName::UpdateTranspose(const ScRange& rSource, const ScAddress& rDest)
761 : : {
762 [ # # ][ # # ]: 0 : DataType::iterator itr = maData.begin(), itrEnd = maData.end();
763 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
764 [ # # ][ # # ]: 0 : itr->second->UpdateTranspose(rSource, rDest);
765 : 0 : }
766 : :
767 : 0 : void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
768 : : {
769 [ # # ][ # # ]: 0 : DataType::iterator itr = maData.begin(), itrEnd = maData.end();
770 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
771 [ # # ][ # # ]: 0 : itr->second->UpdateGrow(rArea, nGrowX, nGrowY);
772 : 0 : }
773 : :
774 : 29 : void ScRangeName::CompileUnresolvedXML()
775 : : {
776 [ + - ][ + - ]: 29 : DataType::iterator itr = maData.begin(), itrEnd = maData.end();
777 [ + - ][ + - ]: 103 : for (; itr != itrEnd; ++itr)
[ + + ]
778 [ + - ][ + - ]: 74 : itr->second->CompileUnresolvedXML();
779 : 29 : }
780 : :
781 : 0 : ScRangeName::const_iterator ScRangeName::begin() const
782 : : {
783 : 0 : return maData.begin();
784 : : }
785 : :
786 : 0 : ScRangeName::const_iterator ScRangeName::end() const
787 : : {
788 : 0 : return maData.end();
789 : : }
790 : :
791 : 99 : ScRangeName::iterator ScRangeName::begin()
792 : : {
793 : 99 : return maData.begin();
794 : : }
795 : :
796 : 102 : ScRangeName::iterator ScRangeName::end()
797 : : {
798 : 102 : return maData.end();
799 : : }
800 : :
801 : 0 : size_t ScRangeName::size() const
802 : : {
803 : 0 : return maData.size();
804 : : }
805 : :
806 : 1229 : bool ScRangeName::empty() const
807 : : {
808 : 1229 : return maData.empty();
809 : : }
810 : :
811 : 272 : bool ScRangeName::insert(ScRangeData* p)
812 : : {
813 [ - + ]: 272 : if (!p)
814 : 0 : return false;
815 : :
816 [ + + ]: 272 : if (!p->GetIndex())
817 : : {
818 : : // Assign a new index. An index must be unique and is never 0.
819 : : IndexDataType::iterator itr = std::find(
820 [ + - ]: 123 : maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(NULL));
821 [ + - ][ - + ]: 123 : if (itr != maIndexToData.end())
822 : : {
823 : : // Empty slot exists. Re-use it.
824 [ # # ]: 0 : size_t nPos = std::distance(maIndexToData.begin(), itr);
825 : 0 : p->SetIndex(nPos + 1);
826 : : }
827 : : else
828 : : // No empty slot. Append it to the end.
829 : 123 : p->SetIndex(maIndexToData.size() + 1);
830 : : }
831 : :
832 : 272 : rtl::OUString aName(p->GetUpperName());
833 [ + - ]: 272 : erase(aName); // ptr_map won't insert it if a duplicate name exists.
834 [ + - ]: 272 : pair<DataType::iterator, bool> r = maData.insert(aName, p);
835 [ + - ]: 272 : if (r.second)
836 : : {
837 : : // Data inserted. Store its index for mapping.
838 : 272 : size_t nPos = p->GetIndex() - 1;
839 [ + + ]: 272 : if (nPos >= maIndexToData.size())
840 [ + - ]: 246 : maIndexToData.resize(nPos+1, NULL);
841 : 272 : maIndexToData[nPos] = p;
842 : : }
843 : 272 : return r.second;
844 : : }
845 : :
846 : 22 : void ScRangeName::erase(const ScRangeData& r)
847 : : {
848 : 22 : erase(r.GetUpperName());
849 : 22 : }
850 : :
851 : 294 : void ScRangeName::erase(const rtl::OUString& rName)
852 : : {
853 [ + - ]: 294 : DataType::iterator itr = maData.find(rName);
854 [ + - ][ + - ]: 294 : if (itr != maData.end())
[ + + ]
855 [ + - ]: 22 : erase(itr);
856 : 294 : }
857 : :
858 : 22 : void ScRangeName::erase(const iterator& itr)
859 : : {
860 : 22 : sal_uInt16 nIndex = itr->second->GetIndex();
861 : 22 : maData.erase(itr);
862 : : OSL_ENSURE( 0 < nIndex && nIndex <= maIndexToData.size(), "ScRangeName::erase: bad index");
863 [ + - ][ + - ]: 22 : if (0 < nIndex && nIndex <= maIndexToData.size())
[ + - ]
864 : 22 : maIndexToData[nIndex-1] = NULL;
865 : 22 : }
866 : :
867 : 6 : void ScRangeName::clear()
868 : : {
869 : 6 : maData.clear();
870 : 6 : maIndexToData.clear();
871 : 6 : }
872 : :
873 : 36 : bool ScRangeName::operator== (const ScRangeName& r) const
874 : : {
875 : 36 : return maData == r.maData;
876 : : }
877 : :
878 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|