Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <cstddef>
21 : #include <cstdio>
22 :
23 : #include <string.h>
24 : #include <tools/mempool.hxx>
25 : #include <osl/diagnose.h>
26 : #include <sfx2/docfile.hxx>
27 :
28 : #include "token.hxx"
29 : #include "tokenarray.hxx"
30 : #include "reftokenhelper.hxx"
31 : #include "clipparam.hxx"
32 : #include "compiler.hxx"
33 : #include <formula/compiler.hrc>
34 : #include "rechead.hxx"
35 : #include "parclass.hxx"
36 : #include "jumpmatrix.hxx"
37 : #include "rangeseq.hxx"
38 : #include "externalrefmgr.hxx"
39 : #include "document.hxx"
40 : #include "refupdatecontext.hxx"
41 : #include "tokenstringcontext.hxx"
42 : #include "types.hxx"
43 : #include "globstr.hrc"
44 : #include "addincol.hxx"
45 : #include <svl/sharedstring.hxx>
46 :
47 : using ::std::vector;
48 :
49 : #include <com/sun/star/sheet/ComplexReference.hpp>
50 : #include <com/sun/star/sheet/ExternalReference.hpp>
51 : #include <com/sun/star/sheet/ReferenceFlags.hpp>
52 : #include <com/sun/star/sheet/NameToken.hpp>
53 :
54 : using namespace formula;
55 : using namespace com::sun::star;
56 :
57 : namespace
58 : {
59 270 : void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
60 : {
61 270 : rRef.InitFlags();
62 :
63 270 : rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
64 270 : rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
65 270 : rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
66 270 : rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
67 270 : rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
68 270 : rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
69 270 : rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
70 270 : rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
71 :
72 270 : if (rRef.IsColRel())
73 12 : rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
74 : else
75 258 : rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
76 :
77 270 : if (rRef.IsRowRel())
78 12 : rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
79 : else
80 258 : rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
81 :
82 270 : if (rRef.IsTabRel())
83 12 : rRef.SetRelTab(static_cast<SCsTAB>(rAPI.RelativeSheet));
84 : else
85 258 : rRef.SetAbsTab(static_cast<SCsTAB>(rAPI.Sheet));
86 270 : }
87 :
88 0 : void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
89 : {
90 0 : rRef.InitFlags();
91 :
92 0 : rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
93 0 : rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
94 0 : rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
95 0 : rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
96 0 : rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
97 0 : rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
98 0 : rRef.SetRelName( false );
99 :
100 0 : if (rRef.IsColRel())
101 0 : rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
102 : else
103 0 : rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
104 :
105 0 : if (rRef.IsRowRel())
106 0 : rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
107 : else
108 0 : rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
109 :
110 : // sheet index must be absolute for external refs
111 0 : rRef.SetAbsTab(0);
112 0 : }
113 :
114 : } // namespace
115 :
116 : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
117 :
118 : // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
119 : // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
120 76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken )
121 : // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
122 76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken )
123 :
124 : // Need a whole bunch of ScSingleRefToken
125 76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken )
126 : // Need quite a lot of ScDoubleRefToken
127 76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken )
128 :
129 : // --- class ScRawToken -----------------------------------------------------
130 :
131 172 : sal_Int32 ScRawToken::GetStrLen( const sal_Unicode* pStr )
132 : {
133 172 : if ( !pStr )
134 0 : return 0;
135 172 : const sal_Unicode* p = pStr;
136 8196 : while ( *p )
137 7852 : p++;
138 172 : return sal::static_int_cast<sal_Int32>( p - pStr );
139 : }
140 :
141 61086 : void ScRawToken::SetOpCode( OpCode e )
142 : {
143 61086 : eOp = e;
144 61086 : switch (eOp)
145 : {
146 : case ocIf:
147 74 : eType = svJump;
148 74 : nJump[ 0 ] = 3; // If, Else, Behind
149 74 : break;
150 : case ocIfError:
151 : case ocIfNA:
152 24 : eType = svJump;
153 24 : nJump[ 0 ] = 2; // If, Behind
154 24 : break;
155 : case ocChose:
156 2 : eType = svJump;
157 2 : nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
158 2 : break;
159 : case ocMissing:
160 2 : eType = svMissing;
161 2 : break;
162 : case ocSep:
163 : case ocOpen:
164 : case ocClose:
165 : case ocArrayRowSep:
166 : case ocArrayColSep:
167 : case ocArrayOpen:
168 : case ocArrayClose:
169 37630 : eType = svSep;
170 37630 : break;
171 : default:
172 23354 : eType = svByte;
173 23354 : sbyte.cByte = 0;
174 23354 : sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
175 : }
176 61086 : nRefCnt = 0;
177 61086 : }
178 :
179 1052 : void ScRawToken::SetString( rtl_uString* pData, rtl_uString* pDataIgoreCase )
180 : {
181 1052 : eOp = ocPush;
182 1052 : eType = svString;
183 1052 : nRefCnt = 0;
184 :
185 1052 : sharedstring.mpData = pData;
186 1052 : sharedstring.mpDataIgnoreCase = pDataIgoreCase;
187 1052 : }
188 :
189 6682 : void ScRawToken::SetSingleReference( const ScSingleRefData& rRef )
190 : {
191 6682 : eOp = ocPush;
192 6682 : eType = svSingleRef;
193 : aRef.Ref1 =
194 6682 : aRef.Ref2 = rRef;
195 6682 : nRefCnt = 0;
196 6682 : }
197 :
198 4646 : void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef )
199 : {
200 4646 : eOp = ocPush;
201 4646 : eType = svDoubleRef;
202 4646 : aRef = rRef;
203 4646 : nRefCnt = 0;
204 4646 : }
205 :
206 4760 : void ScRawToken::SetDouble(double rVal)
207 : {
208 4760 : eOp = ocPush;
209 4760 : eType = svDouble;
210 4760 : nValue = rVal;
211 4760 : nRefCnt = 0;
212 4760 : }
213 :
214 46 : void ScRawToken::SetErrorConstant( sal_uInt16 nErr )
215 : {
216 46 : eOp = ocPush;
217 46 : eType = svError;
218 46 : nError = nErr;
219 46 : nRefCnt = 0;
220 46 : }
221 :
222 146 : void ScRawToken::SetName(bool bGlobal, sal_uInt16 nIndex)
223 : {
224 146 : eOp = ocName;
225 146 : eType = svIndex;
226 146 : nRefCnt = 0;
227 :
228 146 : name.bGlobal = bGlobal;
229 146 : name.nIndex = nIndex;
230 146 : }
231 :
232 76 : void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
233 : {
234 76 : eOp = ocPush;
235 76 : eType = svExternalSingleRef;
236 76 : nRefCnt = 0;
237 :
238 76 : extref.nFileId = nFileId;
239 : extref.aRef.Ref1 =
240 76 : extref.aRef.Ref2 = rRef;
241 :
242 76 : sal_Int32 n = rTabName.getLength();
243 76 : memcpy(extref.cTabName, rTabName.getStr(), n*sizeof(sal_Unicode));
244 76 : extref.cTabName[n] = 0;
245 76 : }
246 :
247 24 : void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
248 : {
249 24 : eOp = ocPush;
250 24 : eType = svExternalDoubleRef;
251 24 : nRefCnt = 0;
252 :
253 24 : extref.nFileId = nFileId;
254 24 : extref.aRef = rRef;
255 :
256 24 : sal_Int32 n = rTabName.getLength();
257 24 : memcpy(extref.cTabName, rTabName.getStr(), n*sizeof(sal_Unicode));
258 24 : extref.cTabName[n] = 0;
259 24 : }
260 :
261 0 : void ScRawToken::SetExternalName( sal_uInt16 nFileId, const OUString& rName )
262 : {
263 0 : eOp = ocPush;
264 0 : eType = svExternalName;
265 0 : nRefCnt = 0;
266 :
267 0 : extname.nFileId = nFileId;
268 :
269 0 : sal_Int32 n = rName.getLength();
270 0 : memcpy(extname.cName, rName.getStr(), n*sizeof(sal_Unicode));
271 0 : extname.cName[n] = 0;
272 0 : }
273 :
274 172 : void ScRawToken::SetExternal( const sal_Unicode* pStr )
275 : {
276 172 : eOp = ocExternal;
277 172 : eType = svExternal;
278 172 : sal_Int32 nLen = GetStrLen( pStr ) + 1;
279 172 : if( nLen >= MAXSTRLEN )
280 0 : nLen = MAXSTRLEN-1;
281 : // Platz fuer Byte-Parameter lassen!
282 172 : memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
283 172 : cStr[ nLen+1 ] = 0;
284 172 : nRefCnt = 0;
285 172 : }
286 :
287 10780 : bool ScRawToken::IsValidReference() const
288 : {
289 10780 : switch (eType)
290 : {
291 : case svSingleRef:
292 6278 : return aRef.Ref1.Valid();
293 : case svDoubleRef:
294 4428 : return aRef.Valid();
295 : case svExternalSingleRef:
296 : case svExternalDoubleRef:
297 74 : return true;
298 : default:
299 : ; // nothing
300 : }
301 0 : return false;
302 : }
303 :
304 0 : sal_uInt16 ScRawToken::sbyteOffset()
305 : {
306 : // offset of sbyte in ScRawToken
307 : // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD
308 :
309 0 : ScRawToken aToken;
310 0 : return static_cast<sal_uInt16>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) );
311 : }
312 :
313 0 : ScRawToken* ScRawToken::Clone() const
314 : {
315 : ScRawToken* p;
316 0 : if ( eType == svDouble )
317 : {
318 0 : p = (ScRawToken*) new ScDoubleRawToken;
319 0 : p->eOp = eOp;
320 0 : p->eType = eType;
321 0 : p->nValue = nValue;
322 : }
323 : else
324 : {
325 0 : static sal_uInt16 nOffset = sbyteOffset(); // offset of sbyte
326 0 : sal_uInt16 n = nOffset;
327 :
328 0 : switch( eType )
329 : {
330 0 : case svSep: break;
331 0 : case svByte: n += sizeof(ScRawToken::sbyte); break;
332 0 : case svDouble: n += sizeof(double); break;
333 0 : case svError: n += sizeof(nError); break;
334 0 : case svString: n += sizeof(sharedstring); break;
335 : case svSingleRef:
336 0 : case svDoubleRef: n += sizeof(aRef); break;
337 0 : case svMatrix: n += sizeof(ScMatrix*); break;
338 0 : case svIndex: n += sizeof(name); break;
339 0 : case svJump: n += nJump[ 0 ] * 2 + 2; break;
340 0 : case svExternal: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
341 :
342 : // external references
343 : case svExternalSingleRef:
344 0 : case svExternalDoubleRef: n += sizeof(extref); break;
345 0 : case svExternalName: n += sizeof(extname); break;
346 : default:
347 : {
348 : OSL_TRACE( "unknown ScRawToken::Clone() type %d", int(eType));
349 : }
350 : }
351 0 : p = (ScRawToken*) new sal_uInt8[ n ];
352 0 : memcpy( p, this, n * sizeof(sal_uInt8) );
353 : }
354 0 : p->nRefCnt = 0;
355 0 : p->bRaw = false;
356 0 : return p;
357 : }
358 :
359 78690 : FormulaToken* ScRawToken::CreateToken() const
360 : {
361 : #if OSL_DEBUG_LEVEL > 1
362 : #define IF_NOT_OPCODE_ERROR(o,c) if (eOp!=o) OSL_TRACE( #c "::ctor: OpCode %d lost, converted to " #o "; maybe inherit from FormulaToken instead!", int(eOp))
363 : #else
364 : #define IF_NOT_OPCODE_ERROR(o,c)
365 : #endif
366 78690 : switch ( GetType() )
367 : {
368 : case svByte :
369 23354 : return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
370 : case svDouble :
371 : IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken);
372 4760 : return new FormulaDoubleToken( nValue );
373 : case svString :
374 : {
375 1052 : svl::SharedString aSS(sharedstring.mpData, sharedstring.mpDataIgnoreCase);
376 1052 : if (eOp == ocPush)
377 1020 : return new FormulaStringToken(aSS);
378 : else
379 32 : return new FormulaStringOpToken(eOp, aSS);
380 : }
381 : case svSingleRef :
382 6682 : if (eOp == ocPush)
383 6682 : return new ScSingleRefToken( aRef.Ref1 );
384 : else
385 0 : return new ScSingleRefToken( aRef.Ref1, eOp );
386 : case svDoubleRef :
387 4646 : if (eOp == ocPush)
388 4646 : return new ScDoubleRefToken( aRef );
389 : else
390 0 : return new ScDoubleRefToken( aRef, eOp );
391 : case svMatrix :
392 : IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
393 0 : return new ScMatrixToken( pMat );
394 : case svIndex :
395 146 : return new FormulaIndexToken( eOp, name.nIndex, name.bGlobal);
396 : case svExternalSingleRef:
397 : {
398 76 : OUString aTabName(extref.cTabName);
399 76 : return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
400 : }
401 : case svExternalDoubleRef:
402 : {
403 24 : OUString aTabName(extref.cTabName);
404 24 : return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
405 : }
406 : case svExternalName:
407 : {
408 0 : OUString aName(extname.cName);
409 0 : return new ScExternalNameToken( extname.nFileId, aName );
410 : }
411 : case svJump :
412 100 : return new FormulaJumpToken( eOp, (short*) nJump );
413 : case svExternal :
414 172 : return new FormulaExternalToken( eOp, sbyte.cByte, OUString( cStr+1 ) );
415 : case svFAP :
416 0 : return new FormulaFAPToken( eOp, sbyte.cByte, NULL );
417 : case svMissing :
418 : IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken);
419 2 : return new FormulaMissingToken;
420 : case svSep :
421 37630 : return new FormulaToken( svSep,eOp );
422 : case svError :
423 46 : return new FormulaErrorToken( nError );
424 : case svUnknown :
425 0 : return new FormulaUnknownToken( eOp );
426 : default:
427 : {
428 : OSL_TRACE( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
429 0 : return new FormulaUnknownToken( ocBad );
430 : }
431 : }
432 : #undef IF_NOT_OPCODE_ERROR
433 : }
434 :
435 0 : void ScRawToken::Delete()
436 : {
437 0 : if ( bRaw )
438 0 : delete this; // FixedMemPool ScRawToken
439 : else
440 : { // created per Clone
441 0 : switch ( eType )
442 : {
443 : case svDouble :
444 0 : delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken
445 0 : break;
446 : default:
447 0 : delete [] (sal_uInt8*) this;
448 : }
449 : }
450 0 : }
451 :
452 : namespace {
453 :
454 : // TextEqual: if same formula entered (for optimization in sort)
455 8 : bool checkTextEqual( const FormulaToken& _rToken1, const FormulaToken& _rToken2 )
456 : {
457 : assert(
458 : (_rToken1.GetType() == svSingleRef || _rToken1.GetType() == svDoubleRef)
459 : && _rToken1.FormulaToken::operator ==(_rToken2));
460 :
461 : // in relative Refs only compare relative parts
462 :
463 : ScComplexRefData aTemp1;
464 8 : if ( _rToken1.GetType() == svSingleRef )
465 : {
466 8 : aTemp1.Ref1 = *_rToken1.GetSingleRef();
467 8 : aTemp1.Ref2 = aTemp1.Ref1;
468 : }
469 : else
470 0 : aTemp1 = *_rToken1.GetDoubleRef();
471 :
472 : ScComplexRefData aTemp2;
473 8 : if ( _rToken2.GetType() == svSingleRef )
474 : {
475 8 : aTemp2.Ref1 = *_rToken2.GetSingleRef();
476 8 : aTemp2.Ref2 = aTemp2.Ref1;
477 : }
478 : else
479 0 : aTemp2 = *_rToken2.GetDoubleRef();
480 :
481 8 : ScAddress aPos;
482 8 : ScRange aRange1 = aTemp1.toAbs(aPos), aRange2 = aTemp2.toAbs(aPos);
483 :
484 : // memcmp doesn't work because of the alignment byte after bFlags.
485 : // After SmartRelAbs only absolute parts have to be compared.
486 8 : return aRange1 == aRange2 && aTemp1.Ref1.FlagValue() == aTemp2.Ref1.FlagValue() && aTemp1.Ref2.FlagValue() == aTemp2.Ref2.FlagValue();
487 : }
488 :
489 : }
490 :
491 : #if DEBUG_FORMULA_COMPILER
492 : void DumpToken(formula::FormulaToken const & rToken)
493 : {
494 : switch (rToken.GetType()) {
495 : case svSingleRef:
496 : cout << "-- ScSingleRefToken" << endl;
497 : rToken.GetSingleRef()->Dump(1);
498 : break;
499 : case svDoubleRef:
500 : cout << "-- ScDoubleRefToken" << endl;
501 : rToken.GetDoubleRef()->Dump(1);
502 : break;
503 : default:
504 : cout << "-- FormulaToken" << endl;
505 : cout << " opcode: " << rToken.GetOpCode() << endl;
506 : cout << " type: " << static_cast<int>(rToken.GetType()) << endl;
507 : switch (rToken.GetType())
508 : {
509 : case svDouble:
510 : cout << " value: " << rToken.GetDouble() << endl;
511 : break;
512 : case svString:
513 : cout << " string: "
514 : << OUStringToOString(rToken.GetString().getString(), RTL_TEXTENCODING_UTF8).getStr()
515 : << endl;
516 : break;
517 : default:
518 : ;
519 : }
520 : break;
521 : }
522 : }
523 : #endif
524 :
525 0 : FormulaTokenRef extendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2,
526 : const ScAddress & rPos, bool bReuseDoubleRef )
527 : {
528 :
529 : StackVar sv1, sv2;
530 : // Doing a RangeOp with RefList is probably utter nonsense, but Xcl
531 : // supports it, so do we.
532 0 : if (((sv1 = rTok1.GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList &&
533 0 : sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef ) ||
534 0 : ((sv2 = rTok2.GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
535 0 : return NULL;
536 :
537 0 : ScTokenRef xRes;
538 0 : bool bExternal = (sv1 == svExternalSingleRef);
539 0 : if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
540 : {
541 : // Range references like Sheet1.A1:A2 are generalized and built by
542 : // first creating a DoubleRef from the first SingleRef, effectively
543 : // generating Sheet1.A1:A1, and then extending that with A2 as if
544 : // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
545 : // references apply as well.
546 :
547 : /* Given the current structure of external references an external
548 : * reference can only be extended if the second reference does not
549 : * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
550 : * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
551 : * svSingleRef whether the sheet would be different from the one given
552 : * in the external reference, we have to bail out if there is any sheet
553 : * specified. NOTE: Xcl does handle external 3D references as in
554 : * '[file]Sheet1:Sheet2'!A1:A2
555 : *
556 : * FIXME: For OOo syntax be smart and remember an external singleref
557 : * encountered and if followed by ocRange and singleref, create an
558 : * external singleref for the second singleref. Both could then be
559 : * merged here. For Xcl syntax already parse an external range
560 : * reference entirely, cumbersome. */
561 :
562 0 : const ScSingleRefData& rRef2 = *rTok2.GetSingleRef();
563 0 : if (bExternal && rRef2.IsFlag3D())
564 0 : return NULL;
565 :
566 : ScComplexRefData aRef;
567 0 : aRef.Ref1 = aRef.Ref2 = *rTok1.GetSingleRef();
568 0 : aRef.Ref2.SetFlag3D( false);
569 0 : aRef.Extend( rRef2, rPos);
570 0 : if (bExternal)
571 0 : xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef);
572 : else
573 0 : xRes = new ScDoubleRefToken( aRef);
574 : }
575 : else
576 : {
577 0 : bExternal |= (sv1 == svExternalDoubleRef);
578 0 : const ScRefList* pRefList = NULL;
579 0 : if (sv1 == svDoubleRef)
580 : {
581 0 : xRes = (bReuseDoubleRef && rTok1.GetRef() == 1 ? &rTok1 : rTok1.Clone());
582 0 : sv1 = svUnknown; // mark as handled
583 : }
584 0 : else if (sv2 == svDoubleRef)
585 : {
586 0 : xRes = (bReuseDoubleRef && rTok2.GetRef() == 1 ? &rTok2 : rTok2.Clone());
587 0 : sv2 = svUnknown; // mark as handled
588 : }
589 0 : else if (sv1 == svRefList)
590 0 : pRefList = rTok1.GetRefList();
591 0 : else if (sv2 == svRefList)
592 0 : pRefList = rTok2.GetRefList();
593 0 : if (pRefList)
594 : {
595 0 : if (!pRefList->size())
596 0 : return NULL;
597 0 : if (bExternal)
598 0 : return NULL; // external reference list not possible
599 0 : xRes = new ScDoubleRefToken( (*pRefList)[0] );
600 : }
601 0 : if (!xRes)
602 0 : return NULL; // shouldn't happen..
603 0 : StackVar sv[2] = { sv1, sv2 };
604 0 : formula::FormulaToken* pt[2] = { &rTok1, &rTok2 };
605 0 : ScComplexRefData& rRef = *xRes->GetDoubleRef();
606 0 : for (size_t i=0; i<2; ++i)
607 : {
608 0 : switch (sv[i])
609 : {
610 : case svSingleRef:
611 0 : rRef.Extend( *pt[i]->GetSingleRef(), rPos);
612 0 : break;
613 : case svDoubleRef:
614 0 : rRef.Extend( *pt[i]->GetDoubleRef(), rPos);
615 0 : break;
616 : case svRefList:
617 : {
618 0 : const ScRefList* p = pt[i]->GetRefList();
619 0 : if (!p->size())
620 0 : return NULL;
621 0 : ScRefList::const_iterator it( p->begin());
622 0 : ScRefList::const_iterator end( p->end());
623 0 : for ( ; it != end; ++it)
624 : {
625 0 : rRef.Extend( *it, rPos);
626 : }
627 : }
628 0 : break;
629 : case svExternalSingleRef:
630 0 : if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
631 0 : return NULL; // no other sheets with external refs
632 : else
633 0 : rRef.Extend( *pt[i]->GetSingleRef(), rPos);
634 0 : break;
635 : case svExternalDoubleRef:
636 0 : if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
637 0 : return NULL; // no other sheets with external refs
638 : else
639 0 : rRef.Extend( *pt[i]->GetDoubleRef(), rPos);
640 0 : break;
641 : default:
642 : ; // nothing, prevent compiler warning
643 : }
644 : }
645 : }
646 0 : return FormulaTokenRef(xRes.get());
647 : }
648 :
649 : // real implementations of virtual functions
650 :
651 38152 : const ScSingleRefData* ScSingleRefToken::GetSingleRef() const { return &aSingleRef; }
652 192672 : ScSingleRefData* ScSingleRefToken::GetSingleRef() { return &aSingleRef; }
653 8 : bool ScSingleRefToken::TextEqual( const FormulaToken& _rToken ) const
654 : {
655 8 : return FormulaToken::operator ==(_rToken) && checkTextEqual(*this, _rToken);
656 : }
657 6 : bool ScSingleRefToken::operator==( const FormulaToken& r ) const
658 : {
659 6 : return FormulaToken::operator==( r ) && aSingleRef == *r.GetSingleRef();
660 : }
661 :
662 12818 : const ScSingleRefData* ScDoubleRefToken::GetSingleRef() const { return &aDoubleRef.Ref1; }
663 8074 : ScSingleRefData* ScDoubleRefToken::GetSingleRef() { return &aDoubleRef.Ref1; }
664 16208 : const ScComplexRefData* ScDoubleRefToken::GetDoubleRef() const { return &aDoubleRef; }
665 68868 : ScComplexRefData* ScDoubleRefToken::GetDoubleRef() { return &aDoubleRef; }
666 12794 : const ScSingleRefData* ScDoubleRefToken::GetSingleRef2() const { return &aDoubleRef.Ref2; }
667 6542 : ScSingleRefData* ScDoubleRefToken::GetSingleRef2() { return &aDoubleRef.Ref2; }
668 0 : bool ScDoubleRefToken::TextEqual( const FormulaToken& _rToken ) const
669 : {
670 0 : return FormulaToken::operator ==(_rToken) && checkTextEqual(*this, _rToken);
671 : }
672 30 : bool ScDoubleRefToken::operator==( const FormulaToken& r ) const
673 : {
674 30 : return FormulaToken::operator==( r ) && aDoubleRef == *r.GetDoubleRef();
675 : }
676 :
677 0 : const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; }
678 0 : ScRefList* ScRefListToken::GetRefList() { return &aRefList; }
679 0 : bool ScRefListToken::operator==( const FormulaToken& r ) const
680 : {
681 0 : return FormulaToken::operator==( r ) && &aRefList == r.GetRefList();
682 : }
683 :
684 386 : ScMatrixToken::ScMatrixToken( const ScMatrixRef& p ) :
685 386 : FormulaToken(formula::svMatrix), pMatrix(p) {}
686 :
687 34 : ScMatrixToken::ScMatrixToken( const ScMatrixToken& r ) :
688 34 : FormulaToken(r), pMatrix(r.pMatrix) {}
689 :
690 10 : const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix.get(); }
691 262 : ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix.get(); }
692 0 : bool ScMatrixToken::operator==( const FormulaToken& r ) const
693 : {
694 0 : return FormulaToken::operator==( r ) && pMatrix == r.GetMatrix();
695 : }
696 :
697 0 : ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
698 0 : FormulaToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
699 :
700 0 : ScMatrixRangeToken::ScMatrixRangeToken( const sc::RangeMatrix& rMat ) :
701 0 : FormulaToken(formula::svMatrix), mpMatrix(rMat.mpMat)
702 : {
703 0 : maRef.InitRange(rMat.mnCol1, rMat.mnRow1, rMat.mnTab1, rMat.mnCol2, rMat.mnRow2, rMat.mnTab2);
704 0 : }
705 :
706 0 : ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
707 0 : FormulaToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
708 :
709 0 : sal_uInt8 ScMatrixRangeToken::GetByte() const
710 : {
711 0 : return MATRIX_TOKEN_HAS_RANGE;
712 : }
713 :
714 0 : const ScMatrix* ScMatrixRangeToken::GetMatrix() const
715 : {
716 0 : return mpMatrix.get();
717 : }
718 :
719 0 : ScMatrix* ScMatrixRangeToken::GetMatrix()
720 : {
721 0 : return mpMatrix.get();
722 : }
723 :
724 0 : const ScComplexRefData* ScMatrixRangeToken::GetDoubleRef() const
725 : {
726 0 : return &maRef;
727 : }
728 :
729 0 : ScComplexRefData* ScMatrixRangeToken::GetDoubleRef()
730 : {
731 0 : return &maRef;
732 : }
733 :
734 0 : bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const
735 : {
736 0 : return FormulaToken::operator==(r) && mpMatrix == r.GetMatrix();
737 : }
738 :
739 0 : FormulaToken* ScMatrixRangeToken::Clone() const
740 : {
741 0 : return new ScMatrixRangeToken(*this);
742 : }
743 :
744 88 : ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const svl::SharedString& rTabName, const ScSingleRefData& r ) :
745 : FormulaToken( svExternalSingleRef, ocPush),
746 : mnFileId(nFileId),
747 : maTabName(rTabName),
748 88 : maSingleRef(r)
749 : {
750 88 : }
751 :
752 156 : ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
753 : FormulaToken(r),
754 : mnFileId(r.mnFileId),
755 : maTabName(r.maTabName),
756 156 : maSingleRef(r.maSingleRef)
757 : {
758 156 : }
759 :
760 488 : ScExternalSingleRefToken::~ScExternalSingleRefToken()
761 : {
762 488 : }
763 :
764 180 : sal_uInt16 ScExternalSingleRefToken::GetIndex() const
765 : {
766 180 : return mnFileId;
767 : }
768 :
769 180 : svl::SharedString ScExternalSingleRefToken::GetString() const
770 : {
771 180 : return maTabName;
772 : }
773 :
774 8 : const ScSingleRefData* ScExternalSingleRefToken::GetSingleRef() const
775 : {
776 8 : return &maSingleRef;
777 : }
778 :
779 510 : ScSingleRefData* ScExternalSingleRefToken::GetSingleRef()
780 : {
781 510 : return &maSingleRef;
782 : }
783 :
784 0 : bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
785 : {
786 0 : if (!FormulaToken::operator==(r))
787 0 : return false;
788 :
789 0 : if (mnFileId != r.GetIndex())
790 0 : return false;
791 :
792 0 : if (maTabName != r.GetString())
793 0 : return false;
794 :
795 0 : return maSingleRef == *r.GetSingleRef();
796 : }
797 :
798 26 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const svl::SharedString& rTabName, const ScComplexRefData& r ) :
799 : FormulaToken( svExternalDoubleRef, ocPush),
800 : mnFileId(nFileId),
801 : maTabName(rTabName),
802 26 : maDoubleRef(r)
803 : {
804 26 : }
805 :
806 2 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
807 : FormulaToken(r),
808 : mnFileId(r.mnFileId),
809 : maTabName(r.maTabName),
810 2 : maDoubleRef(r.maDoubleRef)
811 : {
812 2 : }
813 :
814 56 : ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
815 : {
816 56 : }
817 :
818 40 : sal_uInt16 ScExternalDoubleRefToken::GetIndex() const
819 : {
820 40 : return mnFileId;
821 : }
822 :
823 40 : svl::SharedString ScExternalDoubleRefToken::GetString() const
824 : {
825 40 : return maTabName;
826 : }
827 :
828 0 : const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef() const
829 : {
830 0 : return &maDoubleRef.Ref1;
831 : }
832 :
833 12 : ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef()
834 : {
835 12 : return &maDoubleRef.Ref1;
836 : }
837 :
838 0 : const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2() const
839 : {
840 0 : return &maDoubleRef.Ref2;
841 : }
842 :
843 0 : ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2()
844 : {
845 0 : return &maDoubleRef.Ref2;
846 : }
847 :
848 0 : const ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef() const
849 : {
850 0 : return &maDoubleRef;
851 : }
852 :
853 46 : ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef()
854 : {
855 46 : return &maDoubleRef;
856 : }
857 :
858 0 : bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
859 : {
860 0 : if (!FormulaToken::operator==(r))
861 0 : return false;
862 :
863 0 : if (mnFileId != r.GetIndex())
864 0 : return false;
865 :
866 0 : if (maTabName != r.GetString())
867 0 : return false;
868 :
869 0 : return maDoubleRef == *r.GetDoubleRef();
870 : }
871 :
872 0 : ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const svl::SharedString& rName ) :
873 : FormulaToken( svExternalName, ocPush),
874 : mnFileId(nFileId),
875 0 : maName(rName)
876 : {
877 0 : }
878 :
879 0 : ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
880 : FormulaToken(r),
881 : mnFileId(r.mnFileId),
882 0 : maName(r.maName)
883 : {
884 0 : }
885 :
886 0 : ScExternalNameToken::~ScExternalNameToken() {}
887 :
888 0 : sal_uInt16 ScExternalNameToken::GetIndex() const
889 : {
890 0 : return mnFileId;
891 : }
892 :
893 0 : svl::SharedString ScExternalNameToken::GetString() const
894 : {
895 0 : return maName;
896 : }
897 :
898 0 : bool ScExternalNameToken::operator==( const FormulaToken& r ) const
899 : {
900 0 : if ( !FormulaToken::operator==(r) )
901 0 : return false;
902 :
903 0 : if (mnFileId != r.GetIndex())
904 0 : return false;
905 :
906 0 : return maName.getData() == r.GetString().getData();
907 : }
908 :
909 14 : ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; }
910 0 : bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const
911 : {
912 0 : return FormulaToken::operator==( r ) && pJumpMatrix == r.GetJumpMatrix();
913 : }
914 18 : ScJumpMatrixToken::~ScJumpMatrixToken()
915 : {
916 6 : delete pJumpMatrix;
917 12 : }
918 :
919 0 : double ScEmptyCellToken::GetDouble() const { return 0.0; }
920 :
921 0 : svl::SharedString ScEmptyCellToken::GetString() const
922 : {
923 0 : return svl::SharedString::getEmptyString();
924 : }
925 :
926 0 : bool ScEmptyCellToken::operator==( const FormulaToken& r ) const
927 : {
928 0 : return FormulaToken::operator==( r ) &&
929 0 : bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
930 0 : bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
931 : }
932 :
933 234 : ScMatrixCellResultToken::ScMatrixCellResultToken( const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) :
934 234 : FormulaToken(formula::svMatrixCell), xMatrix(pMat), xUpperLeft(pUL) {}
935 :
936 28 : ScMatrixCellResultToken::ScMatrixCellResultToken( const ScMatrixCellResultToken& r ) :
937 28 : FormulaToken(r), xMatrix(r.xMatrix), xUpperLeft(r.xUpperLeft) {}
938 :
939 0 : double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); }
940 :
941 0 : svl::SharedString ScMatrixCellResultToken::GetString() const
942 : {
943 0 : return xUpperLeft->GetString();
944 : }
945 :
946 638 : const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix.get(); }
947 : // Non-const GetMatrix() is private and unused but must be implemented to
948 : // satisfy vtable linkage.
949 0 : ScMatrix* ScMatrixCellResultToken::GetMatrix()
950 : {
951 0 : return const_cast<ScMatrix*>(xMatrix.get());
952 : }
953 :
954 0 : bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
955 : {
956 0 : return FormulaToken::operator==( r ) &&
957 0 : xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
958 0 : xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
959 : }
960 :
961 0 : FormulaToken* ScMatrixCellResultToken::Clone() const
962 : {
963 0 : return new ScMatrixCellResultToken(*this);
964 : }
965 :
966 48 : void ScMatrixCellResultToken::Assign( const ScMatrixCellResultToken & r )
967 : {
968 48 : xMatrix = r.xMatrix;
969 48 : xUpperLeft = r.xUpperLeft;
970 48 : }
971 :
972 140 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken(
973 : SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) :
974 140 : ScMatrixCellResultToken(pMat, pUL), nRows(nR), nCols(nC) {}
975 :
976 94 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) :
977 94 : ScMatrixCellResultToken(NULL, NULL), nRows(nR), nCols(nC) {}
978 :
979 28 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r ) :
980 28 : ScMatrixCellResultToken(r), nRows(r.nRows), nCols(r.nCols)
981 : {
982 : // xUpperLeft is modifiable through
983 : // SetUpperLeftDouble(), so clone it.
984 28 : if (xUpperLeft)
985 28 : xUpperLeft = xUpperLeft->Clone();
986 28 : }
987 :
988 0 : bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
989 : {
990 0 : const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
991 0 : return p && ScMatrixCellResultToken::operator==( r ) &&
992 0 : nCols == p->nCols && nRows == p->nRows;
993 : }
994 :
995 48 : void ScMatrixFormulaCellToken::Assign( const ScMatrixCellResultToken & r )
996 : {
997 48 : ScMatrixCellResultToken::Assign( r);
998 48 : }
999 :
1000 70 : void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
1001 : {
1002 70 : if (this == &r)
1003 70 : return;
1004 70 : const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
1005 70 : if (p)
1006 0 : ScMatrixCellResultToken::Assign( *p);
1007 : else
1008 : {
1009 : OSL_ENSURE( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1010 70 : if (r.GetType() == svMatrix)
1011 : {
1012 0 : xUpperLeft = NULL;
1013 0 : xMatrix = r.GetMatrix();
1014 : }
1015 : else
1016 : {
1017 70 : xUpperLeft = &r;
1018 70 : xMatrix = NULL;
1019 : }
1020 : }
1021 : }
1022 :
1023 32 : void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f )
1024 : {
1025 32 : switch (GetUpperLeftType())
1026 : {
1027 : case svDouble:
1028 10 : const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
1029 10 : break;
1030 : case svString:
1031 2 : xUpperLeft = new FormulaDoubleToken( f);
1032 2 : break;
1033 : case svUnknown:
1034 20 : if (!xUpperLeft)
1035 : {
1036 20 : xUpperLeft = new FormulaDoubleToken( f);
1037 20 : break;
1038 : }
1039 : // fall thru
1040 : default:
1041 : {
1042 : OSL_FAIL("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1043 : }
1044 : }
1045 32 : }
1046 :
1047 0 : void ScMatrixFormulaCellToken::ResetResult()
1048 : {
1049 0 : xMatrix = NULL;
1050 0 : xUpperLeft = NULL;
1051 0 : }
1052 :
1053 244 : ScHybridCellToken::ScHybridCellToken(
1054 : double f, const svl::SharedString & rStr, const OUString & rFormula ) :
1055 : FormulaToken( formula::svHybridCell ),
1056 : mfDouble( f ), maString( rStr ),
1057 244 : maFormula( rFormula )
1058 : {
1059 244 : }
1060 :
1061 0 : double ScHybridCellToken::GetDouble() const { return mfDouble; }
1062 :
1063 214 : svl::SharedString ScHybridCellToken::GetString() const
1064 : {
1065 214 : return maString;
1066 : }
1067 :
1068 0 : bool ScHybridCellToken::operator==( const FormulaToken& r ) const
1069 : {
1070 0 : return FormulaToken::operator==( r ) &&
1071 0 : mfDouble == r.GetDouble() && maString == r.GetString() &&
1072 0 : maFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
1073 : }
1074 :
1075 216 : bool ScTokenArray::AddFormulaToken(
1076 : const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, formula::ExternalReferenceHelper* pExtRef)
1077 : {
1078 216 : bool bError = FormulaTokenArray::AddFormulaToken(rToken, rSPool, pExtRef);
1079 216 : if ( bError )
1080 : {
1081 182 : bError = false;
1082 182 : const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode); //! assuming equal values for the moment
1083 :
1084 182 : const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
1085 182 : switch ( eClass )
1086 : {
1087 : case uno::TypeClass_STRUCT:
1088 : {
1089 180 : uno::Type aType = rToken.Data.getValueType();
1090 180 : if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
1091 : {
1092 : ScSingleRefData aSingleRef;
1093 86 : sheet::SingleReference aApiRef;
1094 86 : rToken.Data >>= aApiRef;
1095 86 : lcl_SingleRefToCalc( aSingleRef, aApiRef );
1096 86 : if ( eOpCode == ocPush )
1097 86 : AddSingleReference( aSingleRef );
1098 0 : else if ( eOpCode == ocColRowName )
1099 0 : AddColRowName( aSingleRef );
1100 : else
1101 0 : bError = true;
1102 : }
1103 94 : else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
1104 : {
1105 : ScComplexRefData aComplRef;
1106 92 : sheet::ComplexReference aApiRef;
1107 92 : rToken.Data >>= aApiRef;
1108 92 : lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
1109 92 : lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
1110 :
1111 92 : if ( eOpCode == ocPush )
1112 92 : AddDoubleReference( aComplRef );
1113 : else
1114 0 : bError = true;
1115 : }
1116 2 : else if ( aType.equals( cppu::UnoType<sheet::NameToken>::get() ) )
1117 : {
1118 2 : sheet::NameToken aTokenData;
1119 2 : rToken.Data >>= aTokenData;
1120 2 : if ( eOpCode == ocName )
1121 2 : AddRangeName(aTokenData.Index, aTokenData.Global);
1122 0 : else if (eOpCode == ocDBArea)
1123 0 : AddDBRange(aTokenData.Index);
1124 : else
1125 0 : bError = true;
1126 : }
1127 0 : else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
1128 : {
1129 0 : sheet::ExternalReference aApiExtRef;
1130 0 : if( (eOpCode == ocPush) && (rToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
1131 : {
1132 0 : sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
1133 0 : sheet::SingleReference aApiSRef;
1134 0 : sheet::ComplexReference aApiCRef;
1135 0 : OUString aName;
1136 0 : if( aApiExtRef.Reference >>= aApiSRef )
1137 : {
1138 : // try to resolve cache index to sheet name
1139 0 : size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
1140 0 : OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
1141 0 : if( !aTabName.isEmpty() )
1142 : {
1143 : ScSingleRefData aSingleRef;
1144 : // convert column/row settings, set sheet index to absolute
1145 0 : lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1146 0 : AddExternalSingleReference( nFileId, aTabName, aSingleRef );
1147 : }
1148 : else
1149 0 : bError = true;
1150 : }
1151 0 : else if( aApiExtRef.Reference >>= aApiCRef )
1152 : {
1153 : // try to resolve cache index to sheet name.
1154 0 : size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
1155 0 : OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
1156 0 : if( !aTabName.isEmpty() )
1157 : {
1158 : ScComplexRefData aComplRef;
1159 : // convert column/row settings, set sheet index to absolute
1160 0 : lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
1161 0 : lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
1162 : // NOTE: This assumes that cached sheets are in consecutive order!
1163 : aComplRef.Ref2.SetAbsTab(
1164 0 : aComplRef.Ref1.Tab() + static_cast<SCTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet));
1165 0 : AddExternalDoubleReference( nFileId, aTabName, aComplRef );
1166 : }
1167 : else
1168 0 : bError = true;
1169 : }
1170 0 : else if( aApiExtRef.Reference >>= aName )
1171 : {
1172 0 : if( !aName.isEmpty() )
1173 0 : AddExternalName( nFileId, aName );
1174 : else
1175 0 : bError = true;
1176 : }
1177 : else
1178 0 : bError = true;
1179 : }
1180 : else
1181 0 : bError = true;
1182 : }
1183 : else
1184 0 : bError = true; // unknown struct
1185 : }
1186 180 : break;
1187 : case uno::TypeClass_SEQUENCE:
1188 : {
1189 2 : if ( eOpCode != ocPush )
1190 0 : bError = true; // not an inline array
1191 4 : else if (!rToken.Data.getValueType().equals( getCppuType(
1192 4 : (uno::Sequence< uno::Sequence< uno::Any > > *)0)))
1193 0 : bError = true; // unexpected sequence type
1194 : else
1195 : {
1196 2 : ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( rToken.Data);
1197 2 : if (xMat)
1198 2 : AddMatrix( xMat);
1199 : else
1200 0 : bError = true;
1201 : }
1202 : }
1203 2 : break;
1204 : default:
1205 0 : bError = true;
1206 : }
1207 : }
1208 216 : return bError;
1209 : }
1210 :
1211 102928 : void ScTokenArray::CheckToken( const FormulaToken& r )
1212 : {
1213 102928 : if (meVectorState == FormulaVectorDisabled)
1214 : // It's already disabled. No more checking needed.
1215 20602 : return;
1216 :
1217 82326 : OpCode eOp = r.GetOpCode();
1218 :
1219 82326 : if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION)
1220 : {
1221 : // We support vectorization for the following opcodes.
1222 9830 : switch (eOp)
1223 : {
1224 : case ocIf:
1225 : case ocIfError:
1226 : case ocIfNA:
1227 : case ocChose:
1228 : // Jump commands are now supported.
1229 0 : break;
1230 : case ocAverage:
1231 : case ocMin:
1232 : case ocMinA:
1233 : case ocMax:
1234 : case ocMaxA:
1235 : case ocSum:
1236 : case ocSumIfs:
1237 : case ocSumProduct:
1238 : case ocCount:
1239 : case ocCount2:
1240 : case ocVLookup:
1241 : case ocLIA:
1242 : case ocIRR:
1243 : case ocMIRR:
1244 : case ocRMZ:
1245 : case ocZins:
1246 : case ocZGZ:
1247 : case ocKapz:
1248 : case ocFisher:
1249 : case ocFisherInv:
1250 : case ocGamma:
1251 : case ocGammaLn:
1252 : case ocNotAvail:
1253 : case ocGauss:
1254 : case ocGeoMean:
1255 : case ocHarMean:
1256 : case ocDIA:
1257 : case ocCorrel:
1258 : case ocNegBinomVert:
1259 : case ocPearson:
1260 : case ocRSQ:
1261 : case ocCos:
1262 : case ocCosecant:
1263 : case ocCosecantHyp:
1264 : case ocISPMT:
1265 : case ocLaufz:
1266 : case ocSinHyp:
1267 : case ocAbs:
1268 : case ocBW:
1269 : case ocSin:
1270 : case ocTan:
1271 : case ocTanHyp:
1272 : case ocStandard:
1273 : case ocWeibull:
1274 : case ocMedian:
1275 : case ocGDA:
1276 : case ocZW:
1277 : case ocVBD:
1278 : case ocKurt:
1279 : case ocZZR:
1280 : case ocNormDist:
1281 : case ocArcCos:
1282 : case ocSqrt:
1283 : case ocArcCosHyp:
1284 : case ocNPV:
1285 : case ocStdNormDist:
1286 : case ocNormInv:
1287 : case ocSNormInv:
1288 : case ocVariationen:
1289 : case ocVariationen2:
1290 : case ocPhi:
1291 : case ocZinsZ:
1292 : case ocConfidence:
1293 : case ocIntercept:
1294 : case ocGDA2:
1295 : case ocLogInv:
1296 : case ocArcCot:
1297 : case ocCosHyp:
1298 : case ocKritBinom:
1299 : case ocArcCotHyp:
1300 : case ocArcSin:
1301 : case ocArcSinHyp:
1302 : case ocArcTan:
1303 : case ocArcTanHyp:
1304 : case ocBitAnd:
1305 : case ocForecast:
1306 : case ocLogNormDist:
1307 : case ocGammaDist:
1308 : case ocLn:
1309 : case ocRound:
1310 : case ocCot:
1311 : case ocCotHyp:
1312 : case ocFDist:
1313 : case ocVar:
1314 : case ocChiDist:
1315 : case ocPower:
1316 : case ocOdd:
1317 : case ocChiSqDist:
1318 : case ocChiSqInv:
1319 : case ocGammaInv:
1320 : case ocFloor:
1321 : case ocFInv:
1322 : case ocFTest:
1323 : case ocB:
1324 : case ocBetaDist:
1325 : case ocExp:
1326 : case ocLog10:
1327 : case ocExpDist:
1328 : case ocAverageIfs:
1329 : case ocCountIfs:
1330 : case ocKombin2:
1331 : case ocEven:
1332 : case ocLog:
1333 : case ocMod:
1334 : case ocTrunc:
1335 : case ocSchiefe:
1336 : case ocArcTan2:
1337 : case ocBitOr:
1338 : case ocBitLshift:
1339 : case ocBitRshift:
1340 : case ocBitXor:
1341 : case ocChiInv:
1342 : case ocPoissonDist:
1343 : case ocSumSQ:
1344 : case ocSkewp:
1345 : case ocBinomDist:
1346 : case ocVarP:
1347 : case ocCeil:
1348 : case ocKombin:
1349 : case ocDevSq:
1350 : case ocStDev:
1351 : case ocSlope:
1352 : case ocSTEYX:
1353 : case ocZTest:
1354 : case ocPi:
1355 : case ocRandom:
1356 : case ocProduct:
1357 : case ocHypGeomDist:
1358 : case ocSumX2MY2:
1359 : case ocSumX2DY2:
1360 : case ocBetaInv:
1361 : case ocTTest:
1362 : case ocTDist:
1363 : case ocTInv:
1364 : case ocSumXMY2:
1365 : case ocStDevP:
1366 : case ocCovar:
1367 : case ocAnd:
1368 : case ocOr:
1369 : case ocNot:
1370 : case ocXor:
1371 : case ocDBMax:
1372 : case ocDBMin:
1373 : case ocDBProduct:
1374 : case ocDBAverage:
1375 : case ocDBStdDev:
1376 : case ocDBStdDevP:
1377 : case ocDBSum:
1378 : case ocDBVar:
1379 : case ocDBVarP:
1380 : case ocAverageIf:
1381 : case ocDBCount:
1382 : case ocDBCount2:
1383 : case ocDeg:
1384 : case ocRoundUp:
1385 : case ocRoundDown:
1386 : case ocInt:
1387 : case ocRad:
1388 : case ocCountIf:
1389 : case ocIsEven:
1390 : case ocIsOdd:
1391 : case ocFact:
1392 : case ocAverageA:
1393 : case ocVarA:
1394 : case ocVarPA:
1395 : case ocStDevA:
1396 : case ocStDevPA:
1397 : case ocSecant:
1398 : case ocSecantHyp:
1399 : case ocSumIf:
1400 : case ocNegSub:
1401 : case ocAveDev:
1402 : // Don't change the state.
1403 7346 : break;
1404 : default:
1405 2484 : meVectorState = FormulaVectorDisabled;
1406 : }
1407 9830 : return;
1408 : }
1409 :
1410 72496 : if (eOp == ocPush)
1411 : {
1412 : // This is a stack variable. See if this is a reference.
1413 :
1414 33172 : switch (r.GetType())
1415 : {
1416 : case svByte:
1417 : case svDouble:
1418 : case svString:
1419 : // Don't change the state.
1420 11116 : break;
1421 : case svSingleRef:
1422 : case svDoubleRef:
1423 : // Depends on the reference state.
1424 21846 : meVectorState = FormulaVectorCheckReference;
1425 21846 : break;
1426 : case svError:
1427 : case svEmptyCell:
1428 : case svExternal:
1429 : case svExternalDoubleRef:
1430 : case svExternalName:
1431 : case svExternalSingleRef:
1432 : case svFAP:
1433 : case svHybridCell:
1434 : case svHybridValueCell:
1435 : case svIndex:
1436 : case svJump:
1437 : case svJumpMatrix:
1438 : case svMatrix:
1439 : case svMatrixCell:
1440 : case svMissing:
1441 : case svRefList:
1442 : case svSep:
1443 : case svSubroutine:
1444 : case svUnknown:
1445 : // We don't support vectorization on these.
1446 210 : meVectorState = FormulaVectorDisabled;
1447 : default:
1448 : ;
1449 : }
1450 : }
1451 : }
1452 :
1453 1752 : bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
1454 : {
1455 1752 : bool bIs = false;
1456 1752 : if ( pCode && nLen == 1 )
1457 : {
1458 1592 : const FormulaToken* pToken = pCode[0];
1459 1592 : if ( pToken )
1460 : {
1461 1592 : if ( pToken->GetType() == svSingleRef )
1462 : {
1463 1218 : const ScSingleRefData& rRef = *static_cast<const ScSingleRefToken*>(pToken)->GetSingleRef();
1464 1218 : rRange.aStart = rRange.aEnd = rRef.toAbs(rPos);
1465 1218 : bIs = !bValidOnly || ValidAddress(rRange.aStart);
1466 : }
1467 374 : else if ( pToken->GetType() == svDoubleRef )
1468 : {
1469 354 : const ScComplexRefData& rCompl = *static_cast<const ScDoubleRefToken*>(pToken)->GetDoubleRef();
1470 354 : const ScSingleRefData& rRef1 = rCompl.Ref1;
1471 354 : const ScSingleRefData& rRef2 = rCompl.Ref2;
1472 354 : rRange.aStart = rRef1.toAbs(rPos);
1473 354 : rRange.aEnd = rRef2.toAbs(rPos);
1474 354 : bIs = !bValidOnly || ValidRange(rRange);
1475 : }
1476 : }
1477 : }
1478 1752 : return bIs;
1479 : }
1480 :
1481 : namespace {
1482 :
1483 : // we want to compare for similar not identical formulae
1484 : // so we can't use actual row & column indices.
1485 46874 : size_t HashSingleRef( const ScSingleRefData& rRef )
1486 : {
1487 46874 : size_t nVal = 0;
1488 :
1489 46874 : nVal += size_t(rRef.IsColRel());
1490 46874 : nVal += (size_t(rRef.IsRowRel()) << 1);
1491 46874 : nVal += (size_t(rRef.IsTabRel()) << 2);
1492 :
1493 46874 : return nVal;
1494 : }
1495 :
1496 : }
1497 :
1498 25966 : void ScTokenArray::GenHash()
1499 : {
1500 : static OUStringHash aHasher;
1501 :
1502 25966 : size_t nHash = 1;
1503 : OpCode eOp;
1504 : StackVar eType;
1505 : const formula::FormulaToken* p;
1506 25966 : sal_uInt16 n = std::min<sal_uInt16>(nLen, 20);
1507 160854 : for (sal_uInt16 i = 0; i < n; ++i)
1508 : {
1509 134888 : p = pCode[i];
1510 134888 : eOp = p->GetOpCode();
1511 134888 : if (eOp == ocPush)
1512 : {
1513 : // This is stack variable. Do additional differentiation.
1514 53356 : eType = p->GetType();
1515 53356 : switch (eType)
1516 : {
1517 : case svByte:
1518 : {
1519 : // Constant value.
1520 0 : sal_uInt8 nVal = p->GetByte();
1521 0 : nHash += static_cast<size_t>(nVal);
1522 : }
1523 0 : break;
1524 : case svDouble:
1525 : {
1526 : // Constant value.
1527 12446 : double fVal = p->GetDouble();
1528 12446 : nHash += static_cast<size_t>(fVal);
1529 : }
1530 12446 : break;
1531 : case svString:
1532 : {
1533 : // Constant string.
1534 4128 : OUString aStr = p->GetString().getString();
1535 4128 : nHash += aHasher(aStr);
1536 : }
1537 4128 : break;
1538 : case svSingleRef:
1539 : {
1540 26290 : size_t nVal = HashSingleRef(*p->GetSingleRef());
1541 26290 : nHash += nVal;
1542 : }
1543 26290 : break;
1544 : case svDoubleRef:
1545 : {
1546 10292 : const ScComplexRefData& rRef = *p->GetDoubleRef();
1547 10292 : size_t nVal1 = HashSingleRef(rRef.Ref1);
1548 10292 : size_t nVal2 = HashSingleRef(rRef.Ref2);
1549 10292 : nHash += nVal1;
1550 10292 : nHash += nVal2;
1551 : }
1552 10292 : break;
1553 : default:
1554 : // Use the opcode value in all the other cases.
1555 200 : nHash += static_cast<size_t>(eOp);
1556 : }
1557 : }
1558 : else
1559 : // Use the opcode value in all the other cases.
1560 81532 : nHash += static_cast<size_t>(eOp);
1561 :
1562 134888 : nHash = (nHash << 4) - nHash;
1563 : }
1564 :
1565 25966 : mnHashValue = nHash;
1566 25966 : }
1567 :
1568 10 : bool ScTokenArray::IsInvariant() const
1569 : {
1570 10 : FormulaToken** p = pCode;
1571 10 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
1572 26 : for (; p != pEnd; ++p)
1573 : {
1574 26 : switch ((*p)->GetType())
1575 : {
1576 : case svSingleRef:
1577 : case svExternalSingleRef:
1578 : {
1579 2 : const ScSingleRefData& rRef = *(*p)->GetSingleRef();
1580 2 : if (rRef.IsRowRel())
1581 2 : return false;
1582 : }
1583 0 : break;
1584 : case svDoubleRef:
1585 : case svExternalDoubleRef:
1586 : {
1587 0 : const ScComplexRefData& rRef = *(*p)->GetDoubleRef();
1588 0 : if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
1589 0 : return false;
1590 : }
1591 0 : break;
1592 : case svIndex:
1593 8 : return false;
1594 : default:
1595 : ;
1596 : }
1597 : }
1598 :
1599 0 : return true;
1600 : }
1601 :
1602 800 : bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const
1603 : {
1604 800 : return ImplGetReference(rRange, rPos, false);
1605 : }
1606 :
1607 952 : bool ScTokenArray::IsValidReference( ScRange& rRange, const ScAddress& rPos ) const
1608 : {
1609 952 : return ImplGetReference(rRange, rPos, true);
1610 : }
1611 :
1612 21070 : ScTokenArray::ScTokenArray() :
1613 : FormulaTokenArray(),
1614 : mnHashValue(0),
1615 21070 : meVectorState(FormulaVectorEnabled)
1616 : {
1617 21070 : }
1618 :
1619 21688 : ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) :
1620 : FormulaTokenArray(rArr),
1621 : mnHashValue(rArr.mnHashValue),
1622 21688 : meVectorState(rArr.meVectorState)
1623 : {
1624 21688 : }
1625 :
1626 73872 : ScTokenArray::~ScTokenArray()
1627 : {
1628 73872 : }
1629 :
1630 0 : ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
1631 : {
1632 0 : Clear();
1633 0 : Assign( rArr );
1634 0 : return *this;
1635 : }
1636 :
1637 6812 : ScTokenArray* ScTokenArray::Clone() const
1638 : {
1639 6812 : ScTokenArray* p = new ScTokenArray();
1640 6812 : p->nLen = nLen;
1641 6812 : p->nRPN = nRPN;
1642 6812 : p->nRefs = nRefs;
1643 6812 : p->nMode = nMode;
1644 6812 : p->nError = nError;
1645 6812 : p->bHyperLink = bHyperLink;
1646 6812 : p->mnHashValue = mnHashValue;
1647 6812 : p->meVectorState = meVectorState;
1648 :
1649 : FormulaToken** pp;
1650 6812 : if( nLen )
1651 : {
1652 6742 : pp = p->pCode = new FormulaToken*[ nLen ];
1653 6742 : memcpy( pp, pCode, nLen * sizeof( formula::FormulaToken* ) );
1654 34922 : for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
1655 : {
1656 28180 : *pp = (*pp)->Clone();
1657 28180 : (*pp)->IncRef();
1658 : }
1659 : }
1660 6812 : if( nRPN )
1661 : {
1662 2816 : pp = p->pRPN = new FormulaToken*[ nRPN ];
1663 2816 : memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) );
1664 11096 : for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
1665 : {
1666 8280 : FormulaToken* t = *pp;
1667 8280 : if( t->GetRef() > 1 )
1668 : {
1669 8166 : FormulaToken** p2 = pCode;
1670 8166 : sal_uInt16 nIdx = 0xFFFF;
1671 32644 : for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
1672 : {
1673 32644 : if( *p2 == t )
1674 : {
1675 8166 : nIdx = j; break;
1676 : }
1677 : }
1678 8166 : if( nIdx == 0xFFFF )
1679 0 : *pp = t->Clone();
1680 : else
1681 8166 : *pp = p->pCode[ nIdx ];
1682 : }
1683 : else
1684 114 : *pp = t->Clone();
1685 8280 : (*pp)->IncRef();
1686 : }
1687 : }
1688 6812 : return p;
1689 : }
1690 :
1691 42310 : FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
1692 : {
1693 42310 : return Add( r.CreateToken() );
1694 : }
1695 :
1696 : // Utility function to ensure that there is strict alternation of values and
1697 : // separators.
1698 : static bool
1699 304 : checkArraySep( bool & bPrevWasSep, bool bNewVal )
1700 : {
1701 304 : bool bResult = (bPrevWasSep == bNewVal);
1702 304 : bPrevWasSep = bNewVal;
1703 304 : return bResult;
1704 : }
1705 :
1706 36 : FormulaToken* ScTokenArray::MergeArray( )
1707 : {
1708 36 : int nCol = -1, nRow = 0;
1709 36 : int i, nPrevRowSep = -1, nStart = 0;
1710 36 : bool bPrevWasSep = false; // top of stack is ocArrayClose
1711 : FormulaToken* t;
1712 36 : bool bNumeric = false; // numeric value encountered in current element
1713 :
1714 : // (1) Iterate from the end to the start to find matrix dims
1715 : // and do basic validation.
1716 378 : for ( i = nLen ; i-- > nStart ; )
1717 : {
1718 306 : t = pCode[i];
1719 306 : switch ( t->GetOpCode() )
1720 : {
1721 : case ocPush :
1722 134 : if( checkArraySep( bPrevWasSep, false ) )
1723 : {
1724 0 : return NULL;
1725 : }
1726 :
1727 : // no references or nested arrays
1728 134 : if ( t->GetType() != svDouble && t->GetType() != svString )
1729 : {
1730 0 : return NULL;
1731 : }
1732 134 : bNumeric = (t->GetType() == svDouble);
1733 134 : break;
1734 :
1735 : case ocMissing :
1736 : case ocTrue :
1737 : case ocFalse :
1738 0 : if( checkArraySep( bPrevWasSep, false ) )
1739 : {
1740 0 : return NULL;
1741 : }
1742 0 : bNumeric = false;
1743 0 : break;
1744 :
1745 : case ocArrayColSep :
1746 : case ocSep :
1747 36 : if( checkArraySep( bPrevWasSep, true ) )
1748 : {
1749 0 : return NULL;
1750 : }
1751 36 : bNumeric = false;
1752 36 : break;
1753 :
1754 : case ocArrayClose :
1755 : // not possible with the , but check just in case
1756 : // something changes in the future
1757 36 : if( i != (nLen-1))
1758 : {
1759 0 : return NULL;
1760 : }
1761 :
1762 36 : if( checkArraySep( bPrevWasSep, true ) )
1763 : {
1764 0 : return NULL;
1765 : }
1766 :
1767 36 : nPrevRowSep = i;
1768 36 : bNumeric = false;
1769 36 : break;
1770 :
1771 : case ocArrayOpen :
1772 36 : nStart = i; // stop iteration
1773 : // fall through to ArrayRowSep
1774 :
1775 : case ocArrayRowSep :
1776 98 : if( checkArraySep( bPrevWasSep, true ) )
1777 : {
1778 0 : return NULL;
1779 : }
1780 :
1781 196 : if( nPrevRowSep < 0 || // missing ocArrayClose
1782 98 : ((nPrevRowSep - i) % 2) == 1) // no complex elements
1783 : {
1784 0 : return NULL;
1785 : }
1786 :
1787 98 : if( nCol < 0 )
1788 : {
1789 36 : nCol = (nPrevRowSep - i) / 2;
1790 : }
1791 62 : else if( (nPrevRowSep - i)/2 != nCol) // irregular array
1792 : {
1793 0 : return NULL;
1794 : }
1795 :
1796 98 : nPrevRowSep = i;
1797 98 : nRow++;
1798 98 : bNumeric = false;
1799 98 : break;
1800 :
1801 : case ocNegSub :
1802 : case ocAdd :
1803 : // negation or unary plus must precede numeric value
1804 2 : if( !bNumeric )
1805 : {
1806 0 : return NULL;
1807 : }
1808 2 : --nPrevRowSep; // shorten this row by 1
1809 2 : bNumeric = false; // one level only, no --42
1810 2 : break;
1811 :
1812 : case ocSpaces :
1813 : // ignore spaces
1814 0 : --nPrevRowSep; // shorten this row by 1
1815 0 : break;
1816 :
1817 : default :
1818 : // no functions or operators
1819 0 : return NULL;
1820 : }
1821 : }
1822 36 : if( nCol <= 0 || nRow <= 0 )
1823 0 : return NULL;
1824 :
1825 36 : int nSign = 1;
1826 36 : ScMatrix* pArray = new ScMatrix(nCol, nRow, 0.0);
1827 342 : for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
1828 : {
1829 306 : t = pCode[i];
1830 :
1831 306 : switch ( t->GetOpCode() )
1832 : {
1833 : case ocPush :
1834 134 : if ( t->GetType() == svDouble )
1835 : {
1836 56 : pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
1837 56 : nSign = 1;
1838 : }
1839 78 : else if ( t->GetType() == svString )
1840 : {
1841 78 : pArray->PutString(svl::SharedString(t->GetString()), nCol, nRow);
1842 : }
1843 134 : break;
1844 :
1845 : case ocMissing :
1846 0 : pArray->PutEmpty( nCol, nRow );
1847 0 : break;
1848 :
1849 : case ocTrue :
1850 0 : pArray->PutBoolean( true, nCol, nRow );
1851 0 : break;
1852 :
1853 : case ocFalse :
1854 0 : pArray->PutBoolean( false, nCol, nRow );
1855 0 : break;
1856 :
1857 : case ocArrayColSep :
1858 : case ocSep :
1859 36 : nCol++;
1860 36 : break;
1861 :
1862 : case ocArrayRowSep :
1863 62 : nRow++; nCol = 0;
1864 62 : break;
1865 :
1866 : case ocNegSub :
1867 2 : nSign = -nSign;
1868 2 : break;
1869 :
1870 : default :
1871 72 : break;
1872 : }
1873 306 : pCode[i] = NULL;
1874 306 : t->DecRef();
1875 : }
1876 36 : nLen = sal_uInt16( nStart );
1877 36 : return AddMatrix( pArray );
1878 : }
1879 :
1880 0 : FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
1881 : {
1882 0 : if (!pCode || !nLen)
1883 0 : return NULL;
1884 0 : sal_uInt16 nIdx = nLen;
1885 : FormulaToken *p1, *p2, *p3; // ref, ocRange, ref
1886 : // The actual types are checked in extendRangeReference().
1887 0 : if (((p3 = PeekPrev(nIdx)) != 0) &&
1888 0 : (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
1889 0 : ((p1 = PeekPrev(nIdx)) != 0))
1890 : {
1891 0 : FormulaTokenRef p = extendRangeReference( *p1, *p3, rPos, true);
1892 0 : if (p)
1893 : {
1894 0 : p->IncRef();
1895 0 : p1->DecRef();
1896 0 : p2->DecRef();
1897 0 : p3->DecRef();
1898 0 : nLen -= 2;
1899 0 : pCode[ nLen-1 ] = p.get();
1900 0 : nRefs--;
1901 0 : }
1902 : }
1903 0 : return pCode[ nLen-1 ];
1904 : }
1905 :
1906 41526 : FormulaToken* ScTokenArray::AddOpCode( OpCode e )
1907 : {
1908 41526 : ScRawToken t;
1909 41526 : t.SetOpCode( e );
1910 41526 : return AddRawToken( t );
1911 : }
1912 :
1913 10470 : FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
1914 : {
1915 10470 : return Add( new ScSingleRefToken( rRef ) );
1916 : }
1917 :
1918 94 : FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
1919 : {
1920 94 : return Add( new ScSingleRefToken( rRef, ocMatRef ) );
1921 : }
1922 :
1923 4852 : FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
1924 : {
1925 4852 : return Add( new ScDoubleRefToken( rRef ) );
1926 : }
1927 :
1928 52 : FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p )
1929 : {
1930 52 : return Add( new ScMatrixToken( p ) );
1931 : }
1932 :
1933 30 : FormulaToken* ScTokenArray::AddRangeName( sal_uInt16 n, bool bGlobal )
1934 : {
1935 30 : return Add( new FormulaIndexToken( ocName, n, bGlobal));
1936 : }
1937 :
1938 0 : FormulaToken* ScTokenArray::AddDBRange( sal_uInt16 n )
1939 : {
1940 0 : return Add( new FormulaIndexToken( ocDBArea, n));
1941 : }
1942 :
1943 0 : FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const OUString& rName )
1944 : {
1945 0 : return Add( new ScExternalNameToken(nFileId, rName) );
1946 : }
1947 :
1948 4 : FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
1949 : {
1950 4 : return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
1951 : }
1952 :
1953 0 : FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
1954 : {
1955 0 : return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
1956 : }
1957 :
1958 0 : FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
1959 : {
1960 0 : return Add( new ScSingleRefToken( rRef, ocColRowName ) );
1961 : }
1962 :
1963 1648 : void ScTokenArray::AssignXMLString( const OUString &rText, const OUString &rFormulaNmsp )
1964 : {
1965 1648 : sal_uInt16 nTokens = 1;
1966 : FormulaToken *aTokens[2];
1967 :
1968 1648 : aTokens[0] = new FormulaStringOpToken( ocStringXML, rText );
1969 1648 : if( !rFormulaNmsp.isEmpty() )
1970 0 : aTokens[ nTokens++ ] = new FormulaStringOpToken( ocStringXML, rFormulaNmsp );
1971 :
1972 1648 : Assign( nTokens, aTokens );
1973 1648 : }
1974 :
1975 0 : bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
1976 : const ScAddress& rPos, ScDirection eDir )
1977 : {
1978 0 : SCCOL nCol = 0;
1979 0 : SCROW nRow = 0;
1980 0 : switch ( eDir )
1981 : {
1982 : case DIR_BOTTOM :
1983 0 : if ( rPos.Row() < MAXROW )
1984 0 : nRow = (nExtend = rPos.Row()) + 1;
1985 : else
1986 0 : return false;
1987 0 : break;
1988 : case DIR_RIGHT :
1989 0 : if ( rPos.Col() < MAXCOL )
1990 0 : nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
1991 : else
1992 0 : return false;
1993 0 : break;
1994 : case DIR_TOP :
1995 0 : if ( rPos.Row() > 0 )
1996 0 : nRow = (nExtend = rPos.Row()) - 1;
1997 : else
1998 0 : return false;
1999 0 : break;
2000 : case DIR_LEFT :
2001 0 : if ( rPos.Col() > 0 )
2002 0 : nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
2003 : else
2004 0 : return false;
2005 0 : break;
2006 : default:
2007 : OSL_FAIL( "unknown Direction" );
2008 0 : return false;
2009 : }
2010 0 : if ( pRPN && nRPN )
2011 : {
2012 0 : FormulaToken* t = pRPN[nRPN-1];
2013 0 : if ( t->GetType() == svByte )
2014 : {
2015 0 : sal_uInt8 nParamCount = t->GetByte();
2016 0 : if ( nParamCount && nRPN > nParamCount )
2017 : {
2018 0 : bool bRet = false;
2019 0 : sal_uInt16 nParam = nRPN - nParamCount - 1;
2020 0 : for ( ; nParam < nRPN-1; nParam++ )
2021 : {
2022 0 : FormulaToken* p = pRPN[nParam];
2023 0 : switch ( p->GetType() )
2024 : {
2025 : case svSingleRef :
2026 : {
2027 0 : ScSingleRefData& rRef = *p->GetSingleRef();
2028 0 : ScAddress aAbs = rRef.toAbs(rPos);
2029 0 : switch ( eDir )
2030 : {
2031 : case DIR_BOTTOM :
2032 0 : if (aAbs.Row() == nRow && aAbs.Row() > nExtend)
2033 : {
2034 0 : nExtend = aAbs.Row();
2035 0 : bRet = true;
2036 : }
2037 0 : break;
2038 : case DIR_RIGHT :
2039 0 : if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) > nExtend)
2040 : {
2041 0 : nExtend = aAbs.Col();
2042 0 : bRet = true;
2043 : }
2044 0 : break;
2045 : case DIR_TOP :
2046 0 : if (aAbs.Row() == nRow && aAbs.Row() < nExtend)
2047 : {
2048 0 : nExtend = aAbs.Row();
2049 0 : bRet = true;
2050 : }
2051 0 : break;
2052 : case DIR_LEFT :
2053 0 : if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) < nExtend)
2054 : {
2055 0 : nExtend = aAbs.Col();
2056 0 : bRet = true;
2057 : }
2058 0 : break;
2059 : }
2060 : }
2061 0 : break;
2062 : case svDoubleRef :
2063 : {
2064 0 : ScComplexRefData& rRef = *p->GetDoubleRef();
2065 0 : ScRange aAbs = rRef.toAbs(rPos);
2066 0 : switch ( eDir )
2067 : {
2068 : case DIR_BOTTOM :
2069 0 : if (aAbs.aStart.Row() == nRow && aAbs.aEnd.Row() > nExtend)
2070 : {
2071 0 : nExtend = aAbs.aEnd.Row();
2072 0 : bRet = true;
2073 : }
2074 0 : break;
2075 : case DIR_RIGHT :
2076 0 : if (aAbs.aStart.Col() == nCol && static_cast<SCCOLROW>(aAbs.aEnd.Col()) > nExtend)
2077 : {
2078 0 : nExtend = aAbs.aEnd.Col();
2079 0 : bRet = true;
2080 : }
2081 0 : break;
2082 : case DIR_TOP :
2083 0 : if (aAbs.aEnd.Row() == nRow && aAbs.aStart.Row() < nExtend)
2084 : {
2085 0 : nExtend = aAbs.aStart.Row();
2086 0 : bRet = true;
2087 : }
2088 0 : break;
2089 : case DIR_LEFT :
2090 0 : if (aAbs.aEnd.Col() == nCol && static_cast<SCCOLROW>(aAbs.aStart.Col()) < nExtend)
2091 : {
2092 0 : nExtend = aAbs.aStart.Col();
2093 0 : bRet = true;
2094 : }
2095 0 : break;
2096 : }
2097 : }
2098 0 : break;
2099 : default:
2100 : {
2101 : // added to avoid warnings
2102 : }
2103 : } // switch
2104 : } // for
2105 0 : return bRet;
2106 : }
2107 : }
2108 : }
2109 0 : return false;
2110 : }
2111 :
2112 0 : void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
2113 : const ScAddress& rNewPos )
2114 : {
2115 0 : for ( sal_uInt16 j=0; j<nLen; ++j )
2116 : {
2117 0 : switch ( pCode[j]->GetType() )
2118 : {
2119 : case svDoubleRef :
2120 : {
2121 0 : ScSingleRefData& rRef2 = *pCode[j]->GetSingleRef2();
2122 : // Also adjust if the reference is of the form Sheet1.A2:A3
2123 0 : if ( rRef2.IsFlag3D() || pCode[j]->GetSingleRef()->IsFlag3D() )
2124 : {
2125 0 : ScAddress aAbs = rRef2.toAbs(rOldPos);
2126 0 : rRef2.SetAddress(aAbs, rNewPos);
2127 : }
2128 : }
2129 : //! fallthru
2130 : case svSingleRef :
2131 : {
2132 0 : ScSingleRefData& rRef1 = *pCode[j]->GetSingleRef();
2133 0 : if ( rRef1.IsFlag3D() )
2134 : {
2135 0 : ScAddress aAbs = rRef1.toAbs(rOldPos);
2136 0 : rRef1.SetAddress(aAbs, rNewPos);
2137 : }
2138 : }
2139 0 : break;
2140 : case svExternalDoubleRef :
2141 : {
2142 0 : ScSingleRefData& rRef2 = *pCode[j]->GetSingleRef2();
2143 0 : ScAddress aAbs = rRef2.toAbs(rOldPos);
2144 0 : rRef2.SetAddress(aAbs, rNewPos);
2145 : }
2146 : //! fallthru
2147 : case svExternalSingleRef :
2148 : {
2149 0 : ScSingleRefData& rRef1 = *pCode[j]->GetSingleRef();
2150 0 : ScAddress aAbs = rRef1.toAbs(rOldPos);
2151 0 : rRef1.SetAddress(aAbs, rNewPos);
2152 : }
2153 0 : break;
2154 : default:
2155 : {
2156 : // added to avoid warnings
2157 : }
2158 : }
2159 : }
2160 0 : }
2161 :
2162 : namespace {
2163 :
2164 8 : void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, OUString& rTabName, sal_uInt16& rFileId)
2165 : {
2166 8 : OUString aFileName = pOldDoc->GetFileURL();;
2167 8 : rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
2168 8 : rTabName = pOldDoc->GetCopyTabName(nTab);
2169 8 : if (rTabName.isEmpty())
2170 2 : pOldDoc->GetName(nTab, rTabName);
2171 8 : }
2172 :
2173 108 : bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
2174 : {
2175 108 : ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
2176 108 : return rClipParam.maRanges.In(rRange);
2177 : }
2178 :
2179 3058 : bool SkipReference(formula::FormulaToken* pToken, const ScAddress& rPos, const ScDocument* pOldDoc, bool bRangeName, bool bCheckCopyArea)
2180 : {
2181 3058 : ScRange aRange;
2182 :
2183 3058 : if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, rPos))
2184 0 : return true;
2185 :
2186 3058 : if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
2187 : {
2188 4 : switch (pToken->GetType())
2189 : {
2190 : case svDoubleRef:
2191 : {
2192 0 : ScSingleRefData& rRef = *pToken->GetSingleRef2();
2193 0 : if (rRef.IsColRel() || rRef.IsRowRel())
2194 0 : return true;
2195 : } // fall through
2196 : case svSingleRef:
2197 : {
2198 4 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2199 4 : if (rRef.IsColRel() || rRef.IsRowRel())
2200 0 : return true;
2201 : }
2202 4 : break;
2203 : default:
2204 0 : break;
2205 : }
2206 : }
2207 :
2208 3058 : if (bCheckCopyArea && IsInCopyRange(aRange, pOldDoc))
2209 96 : return true;
2210 :
2211 2962 : return false;
2212 : }
2213 :
2214 48 : void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
2215 : {
2216 48 : SCsCOL nCols = rNewPos.Col() - rOldPos.Col();
2217 48 : SCsROW nRows = rNewPos.Row() - rOldPos.Row();
2218 48 : SCsTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
2219 :
2220 48 : if (!rRef.IsColRel())
2221 8 : rRef.IncCol(nCols);
2222 :
2223 48 : if (!rRef.IsRowRel())
2224 8 : rRef.IncRow(nRows);
2225 :
2226 48 : if (!rRef.IsTabRel())
2227 4 : rRef.IncTab(nTabs);
2228 48 : }
2229 :
2230 : }
2231 :
2232 120 : void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName )
2233 : {
2234 298 : for ( sal_uInt16 j=0; j<nLen; ++j )
2235 : {
2236 178 : switch ( pCode[j]->GetType() )
2237 : {
2238 : case svDoubleRef :
2239 : {
2240 0 : if (SkipReference(pCode[j], rPos, pOldDoc, bRangeName, true))
2241 0 : continue;
2242 :
2243 0 : ScComplexRefData& rRef = *pCode[j]->GetDoubleRef();
2244 0 : ScSingleRefData& rRef2 = rRef.Ref2;
2245 0 : ScSingleRefData& rRef1 = rRef.Ref1;
2246 :
2247 0 : if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) )
2248 : {
2249 0 : OUString aTabName;
2250 : sal_uInt16 nFileId;
2251 0 : GetExternalTableData(pOldDoc, pNewDoc, rRef1.Tab(), aTabName, nFileId);
2252 0 : pCode[j]->DecRef();
2253 0 : ScExternalDoubleRefToken* pToken = new ScExternalDoubleRefToken(nFileId, aTabName, rRef);
2254 0 : pToken->IncRef();
2255 0 : pCode[j] = pToken;
2256 : }
2257 : }
2258 0 : break;
2259 : case svSingleRef :
2260 : {
2261 58 : if (SkipReference(pCode[j], rPos, pOldDoc, bRangeName, true))
2262 48 : continue;
2263 :
2264 10 : ScSingleRefData& rRef = *pCode[j]->GetSingleRef();
2265 :
2266 10 : if ( rRef.IsFlag3D() && !rRef.IsTabRel() )
2267 : {
2268 8 : OUString aTabName;
2269 : sal_uInt16 nFileId;
2270 8 : GetExternalTableData(pOldDoc, pNewDoc, rRef.Tab(), aTabName, nFileId);
2271 : //replace with ScExternalSingleRefToken and adjust references
2272 8 : ScExternalSingleRefToken* pToken = new ScExternalSingleRefToken(nFileId, aTabName, rRef);
2273 8 : pToken->IncRef();
2274 8 : pCode[j]->DecRef(); // ATTENTION: rRef can't be used after this point
2275 8 : pCode[j] = pToken;
2276 : }
2277 : }
2278 10 : break;
2279 : default:
2280 : {
2281 : // added to avoid warnings
2282 : }
2283 : }
2284 : }
2285 120 : }
2286 :
2287 1914 : void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName, bool bCheckCopyRange)
2288 : {
2289 10964 : for ( sal_uInt16 j=0; j<nLen; ++j )
2290 : {
2291 9050 : switch ( pCode[j]->GetType() )
2292 : {
2293 : case svDoubleRef :
2294 : {
2295 268 : if (!SkipReference(pCode[j], rOldPos, pOldDoc, false, bCheckCopyRange))
2296 268 : continue;
2297 :
2298 0 : ScComplexRefData& rRef = *pCode[j]->GetDoubleRef();
2299 0 : ScSingleRefData& rRef2 = rRef.Ref2;
2300 0 : ScSingleRefData& rRef1 = rRef.Ref1;
2301 :
2302 : // for range names only adjust if all parts are absolute
2303 0 : if (!bRangeName || !(rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel()))
2304 0 : AdjustSingleRefData( rRef1, rOldPos, rNewPos );
2305 0 : if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
2306 0 : AdjustSingleRefData( rRef2, rOldPos, rNewPos );
2307 : }
2308 0 : break;
2309 : case svSingleRef :
2310 : {
2311 2732 : if (!SkipReference(pCode[j], rOldPos, pOldDoc, false, bCheckCopyRange))
2312 2684 : continue;
2313 :
2314 48 : ScSingleRefData& rRef = *pCode[j]->GetSingleRef();
2315 :
2316 : // for range names only adjust if all parts are absolute
2317 48 : if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
2318 48 : AdjustSingleRefData( rRef, rOldPos, rNewPos );
2319 : }
2320 48 : break;
2321 : default:
2322 : {
2323 : // added to avoid warnings
2324 : }
2325 : }
2326 : }
2327 1914 : }
2328 :
2329 : namespace {
2330 :
2331 428 : ScRange getSelectedRange( const sc::RefUpdateContext& rCxt )
2332 : {
2333 428 : ScRange aSelectedRange(ScAddress::INITIALIZE_INVALID);
2334 428 : if (rCxt.mnColDelta < 0)
2335 : {
2336 : // Delete and shift to left.
2337 68 : aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab());
2338 68 : aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
2339 : }
2340 360 : else if (rCxt.mnRowDelta < 0)
2341 : {
2342 : // Delete and shift up.
2343 130 : aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab());
2344 130 : aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab());
2345 : }
2346 230 : else if (rCxt.mnTabDelta < 0)
2347 : {
2348 : // Deleting sheets.
2349 : // TODO : Figure out what to do here.
2350 : }
2351 230 : else if (rCxt.mnColDelta > 0)
2352 : {
2353 : // Insert and shift to the right.
2354 104 : aSelectedRange.aStart = rCxt.maRange.aStart;
2355 104 : aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
2356 : }
2357 126 : else if (rCxt.mnRowDelta > 0)
2358 : {
2359 : // Insert and shift down.
2360 126 : aSelectedRange.aStart = rCxt.maRange.aStart;
2361 126 : aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta-1, rCxt.maRange.aEnd.Tab());
2362 : }
2363 0 : else if (rCxt.mnTabDelta > 0)
2364 : {
2365 : // Inserting sheets.
2366 : // TODO : Figure out what to do here.
2367 : }
2368 :
2369 428 : return aSelectedRange;
2370 : }
2371 :
2372 26 : void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
2373 : {
2374 26 : if (rCxt.mnColDelta < 0)
2375 12 : rRef.SetColDeleted(true);
2376 14 : else if (rCxt.mnRowDelta < 0)
2377 14 : rRef.SetRowDeleted(true);
2378 0 : else if (rCxt.mnTabDelta < 0)
2379 0 : rRef.SetTabDeleted(true);
2380 26 : }
2381 :
2382 12 : void restoreDeletedRef( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
2383 : {
2384 12 : if (rCxt.mnColDelta)
2385 : {
2386 12 : if (rRef.IsColDeleted())
2387 12 : rRef.SetColDeleted(false);
2388 : }
2389 0 : else if (rCxt.mnRowDelta)
2390 : {
2391 0 : if (rRef.IsRowDeleted())
2392 0 : rRef.SetRowDeleted(false);
2393 : }
2394 0 : else if (rCxt.mnTabDelta)
2395 : {
2396 0 : if (rRef.IsTabDeleted())
2397 0 : rRef.SetTabDeleted(false);
2398 : }
2399 12 : }
2400 :
2401 4 : void setRefDeleted( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt )
2402 : {
2403 4 : if (rCxt.mnColDelta < 0)
2404 : {
2405 0 : rRef.Ref1.SetColDeleted(true);
2406 0 : rRef.Ref2.SetColDeleted(true);
2407 : }
2408 4 : else if (rCxt.mnRowDelta < 0)
2409 : {
2410 4 : rRef.Ref1.SetRowDeleted(true);
2411 4 : rRef.Ref2.SetRowDeleted(true);
2412 : }
2413 0 : else if (rCxt.mnTabDelta < 0)
2414 : {
2415 0 : rRef.Ref1.SetTabDeleted(true);
2416 0 : rRef.Ref2.SetTabDeleted(true);
2417 : }
2418 4 : }
2419 :
2420 50 : bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rDeletedRange )
2421 : {
2422 50 : if (!rDeletedRange.Intersects(rRefRange))
2423 0 : return false;
2424 :
2425 50 : if (rCxt.mnColDelta < 0)
2426 : {
2427 : // Shifting left.
2428 22 : if (rRefRange.aStart.Row() < rDeletedRange.aStart.Row() || rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
2429 : // Deleted range is only partially overlapping in vertical direction. Bail out.
2430 0 : return false;
2431 :
2432 22 : if (rDeletedRange.aStart.Col() <= rRefRange.aStart.Col())
2433 : {
2434 8 : if (rRefRange.aEnd.Col() <= rDeletedRange.aEnd.Col())
2435 : {
2436 : // Reference is entirely deleted.
2437 0 : rRefRange.SetInvalid();
2438 : }
2439 : else
2440 : {
2441 : // The reference range is truncated on the left.
2442 8 : SCCOL nOffset = rDeletedRange.aStart.Col() - rRefRange.aStart.Col();
2443 8 : SCCOL nDelta = rRefRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
2444 8 : rRefRange.aStart.IncCol(nOffset);
2445 8 : rRefRange.aEnd.IncCol(nDelta+nOffset);
2446 : }
2447 : }
2448 14 : else if (rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
2449 : {
2450 : // Reference is deleted in the middle. Move the last column
2451 : // position to the left.
2452 6 : SCCOL nDelta = rDeletedRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
2453 6 : rRefRange.aEnd.IncCol(nDelta);
2454 : }
2455 : else
2456 : {
2457 : // The reference range is truncated on the right.
2458 8 : SCCOL nDelta = rDeletedRange.aStart.Col() - rRefRange.aEnd.Col() - 1;
2459 8 : rRefRange.aEnd.IncCol(nDelta);
2460 : }
2461 22 : return true;
2462 : }
2463 28 : else if (rCxt.mnRowDelta < 0)
2464 : {
2465 : // Shifting up.
2466 :
2467 28 : if (rRefRange.aStart.Col() < rDeletedRange.aStart.Col() || rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
2468 : // Deleted range is only partially overlapping in horizontal direction. Bail out.
2469 4 : return false;
2470 :
2471 24 : if (rDeletedRange.aStart.Row() <= rRefRange.aStart.Row())
2472 : {
2473 8 : if (rRefRange.aEnd.Row() <= rDeletedRange.aEnd.Row())
2474 : {
2475 : // Reference is entirely deleted.
2476 0 : rRefRange.SetInvalid();
2477 : }
2478 : else
2479 : {
2480 : // The reference range is truncated on the top.
2481 8 : SCCOL nOffset = rDeletedRange.aStart.Row() - rRefRange.aStart.Row();
2482 8 : SCCOL nDelta = rRefRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
2483 8 : rRefRange.aStart.IncRow(nOffset);
2484 8 : rRefRange.aEnd.IncRow(nDelta+nOffset);
2485 : }
2486 : }
2487 16 : else if (rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
2488 : {
2489 : // Reference is deleted in the middle. Move the last row
2490 : // position upward.
2491 8 : SCCOL nDelta = rDeletedRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
2492 8 : rRefRange.aEnd.IncRow(nDelta);
2493 : }
2494 : else
2495 : {
2496 : // The reference range is truncated on the bottom.
2497 8 : SCCOL nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1;
2498 8 : rRefRange.aEnd.IncRow(nDelta);
2499 : }
2500 24 : return true;
2501 : }
2502 :
2503 0 : return false;
2504 : }
2505 :
2506 86 : bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange )
2507 : {
2508 86 : if (!rSelectedRange.Intersects(rRefRange))
2509 36 : return false;
2510 :
2511 50 : if (rCxt.mnColDelta > 0)
2512 : {
2513 : // Insert and shifting right.
2514 24 : if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
2515 : // Selected range is only partially overlapping in vertical direction. Bail out.
2516 0 : return false;
2517 :
2518 24 : if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Col() <= rRefRange.aStart.Col())
2519 : // Selected range is at the left end and the edge expansion is turned off. No expansion.
2520 14 : return false;
2521 :
2522 : // Move the last column position to the right.
2523 10 : SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
2524 10 : rRefRange.aEnd.IncCol(nDelta);
2525 10 : return true;
2526 : }
2527 26 : else if (rCxt.mnRowDelta > 0)
2528 : {
2529 : // Insert and shifting down.
2530 26 : if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
2531 : // Selected range is only partially overlapping in horizontal direction. Bail out.
2532 4 : return false;
2533 :
2534 22 : if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Row() <= rRefRange.aStart.Row())
2535 : // Selected range is at the top end and the edge expansion is turned off. No expansion.
2536 12 : return false;
2537 :
2538 : // Move the last row position down.
2539 10 : SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
2540 10 : rRefRange.aEnd.IncRow(nDelta);
2541 10 : return true;
2542 : }
2543 0 : return false;
2544 : }
2545 :
2546 : /**
2547 : * Check if the referenced range is expandable when the selected range is
2548 : * not overlapping the referenced range.
2549 : */
2550 66 : bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange )
2551 : {
2552 66 : if (!rCxt.mrDoc.IsExpandRefs())
2553 : // Edge-expansion is turned off.
2554 58 : return false;
2555 :
2556 8 : if (rCxt.mnColDelta > 0)
2557 : {
2558 : // Insert and shift right.
2559 4 : if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
2560 : // Selected range is only partially overlapping in vertical direction. Bail out.
2561 0 : return false;
2562 :
2563 4 : if (rSelectedRange.aStart.Col() - rRefRange.aEnd.Col() != 1)
2564 : // Selected range is not immediately adjacent. Bail out.
2565 0 : return false;
2566 :
2567 : // Move the last column position to the right.
2568 4 : SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
2569 4 : rRefRange.aEnd.IncCol(nDelta);
2570 4 : return true;
2571 : }
2572 4 : else if (rCxt.mnRowDelta > 0)
2573 : {
2574 4 : if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
2575 : // Selected range is only partially overlapping in horizontal direction. Bail out.
2576 0 : return false;
2577 :
2578 4 : if (rSelectedRange.aStart.Row() - rRefRange.aEnd.Row() != 1)
2579 : // Selected range is not immediately adjacent. Bail out.
2580 0 : return false;
2581 :
2582 : // Move the last row position down.
2583 4 : SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
2584 4 : rRefRange.aEnd.IncRow(nDelta);
2585 4 : return true;
2586 : }
2587 :
2588 0 : return false;
2589 : }
2590 :
2591 414 : bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken )
2592 : {
2593 414 : if (rToken.GetOpCode() != ocName)
2594 0 : return false;
2595 :
2596 414 : SCTAB nTab = -1;
2597 414 : if (!rToken.IsGlobal())
2598 4 : nTab = nOldTab;
2599 :
2600 : // Check if this named expression has been modified.
2601 414 : return rUpdatedNames.isNameUpdated(nTab, rToken.GetIndex());
2602 : }
2603 :
2604 : }
2605 :
2606 420 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos )
2607 : {
2608 420 : ScRange aSelectedRange = getSelectedRange(rCxt);
2609 :
2610 420 : sc::RefUpdateResult aRes;
2611 420 : ScAddress aNewPos = rOldPos;
2612 420 : bool bCellShifted = rCxt.maRange.In(rOldPos);
2613 420 : if (bCellShifted)
2614 204 : aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2615 :
2616 420 : FormulaToken** p = pCode;
2617 420 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
2618 1590 : for (; p != pEnd; ++p)
2619 : {
2620 1170 : switch ((*p)->GetType())
2621 : {
2622 : case svSingleRef:
2623 : {
2624 230 : formula::FormulaToken* pToken = *p;
2625 230 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2626 230 : ScAddress aAbs = rRef.toAbs(rOldPos);
2627 :
2628 230 : if (rCxt.isDeleted() && aSelectedRange.In(aAbs))
2629 : {
2630 : // This reference is in the deleted region.
2631 26 : setRefDeleted(rRef, rCxt);
2632 26 : aRes.mbValueChanged = true;
2633 64 : break;
2634 : }
2635 :
2636 204 : if (!rCxt.isDeleted() && rRef.IsDeleted())
2637 : {
2638 : // Check if the token has reference to previously deleted region.
2639 12 : ScAddress aCheckPos = rRef.toAbs(aNewPos);
2640 12 : if (rCxt.maRange.In(aCheckPos))
2641 : {
2642 12 : restoreDeletedRef(rRef, rCxt);
2643 12 : aRes.mbValueChanged = true;
2644 12 : break;
2645 : }
2646 : }
2647 :
2648 192 : if (rCxt.maRange.In(aAbs))
2649 : {
2650 108 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2651 108 : aRes.mbReferenceModified = true;
2652 : }
2653 :
2654 192 : rRef.SetAddress(aAbs, aNewPos);
2655 : }
2656 192 : break;
2657 : case svDoubleRef:
2658 : {
2659 164 : formula::FormulaToken* pToken = *p;
2660 164 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2661 164 : ScRange aAbs = rRef.toAbs(rOldPos);
2662 :
2663 164 : if (rCxt.isDeleted())
2664 : {
2665 78 : if (aSelectedRange.In(aAbs))
2666 : {
2667 : // This reference is in the deleted region.
2668 4 : setRefDeleted(rRef, rCxt);
2669 4 : aRes.mbValueChanged = true;
2670 82 : break;
2671 : }
2672 74 : else if (aSelectedRange.Intersects(aAbs))
2673 : {
2674 50 : if (shrinkRange(rCxt, aAbs, aSelectedRange))
2675 : {
2676 : // The reference range has been shrunk.
2677 46 : rRef.SetRange(aAbs, aNewPos);
2678 46 : aRes.mbValueChanged = true;
2679 46 : aRes.mbReferenceModified = true;
2680 46 : break;
2681 : }
2682 : }
2683 : }
2684 :
2685 114 : if (rCxt.isInserted())
2686 : {
2687 86 : if (expandRange(rCxt, aAbs, aSelectedRange))
2688 : {
2689 : // The reference range has been expanded.
2690 20 : rRef.SetRange(aAbs, aNewPos);
2691 20 : aRes.mbValueChanged = true;
2692 20 : aRes.mbReferenceModified = true;
2693 20 : break;
2694 : }
2695 :
2696 66 : if (expandRangeByEdge(rCxt, aAbs, aSelectedRange))
2697 : {
2698 : // The reference range has been expanded on the edge.
2699 8 : rRef.SetRange(aAbs, aNewPos);
2700 8 : aRes.mbValueChanged = true;
2701 8 : aRes.mbReferenceModified = true;
2702 8 : break;
2703 : }
2704 : }
2705 :
2706 86 : if (rCxt.maRange.In(aAbs))
2707 : {
2708 48 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2709 48 : aRes.mbReferenceModified = true;
2710 : }
2711 38 : else if (rCxt.maRange.Intersects(aAbs))
2712 : {
2713 : // Part of the referenced range is being shifted. This
2714 : // will change the values of the range.
2715 8 : aRes.mbValueChanged = true;
2716 : }
2717 :
2718 86 : rRef.SetRange(aAbs, aNewPos);
2719 : }
2720 86 : break;
2721 : case svExternalSingleRef:
2722 : {
2723 : // For external reference, just reset the reference with
2724 : // respect to the new cell position.
2725 18 : formula::FormulaToken* pToken = *p;
2726 18 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2727 18 : ScAddress aAbs = rRef.toAbs(rOldPos);
2728 18 : rRef.SetAddress(aAbs, aNewPos);
2729 : }
2730 18 : break;
2731 : case svExternalDoubleRef:
2732 : {
2733 : // Same as above.
2734 6 : formula::FormulaToken* pToken = *p;
2735 6 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2736 6 : ScRange aAbs = rRef.toAbs(rOldPos);
2737 6 : rRef.SetRange(aAbs, aNewPos);
2738 : }
2739 6 : break;
2740 : case svIndex:
2741 : {
2742 16 : if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
2743 10 : aRes.mbNameModified = true;
2744 : }
2745 16 : break;
2746 : default:
2747 : ;
2748 : }
2749 : }
2750 :
2751 420 : return aRes;
2752 : }
2753 :
2754 66 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
2755 : const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos )
2756 : {
2757 66 : sc::RefUpdateResult aRes;
2758 :
2759 66 : if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta)
2760 : // The cell hasn't moved at all.
2761 0 : return aRes;
2762 :
2763 : // When moving, the range is the destination range. We need to use the old
2764 : // range prior to the move for hit analysis.
2765 66 : ScRange aOldRange = rCxt.maRange;
2766 66 : aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
2767 :
2768 66 : bool b3DFlag = rOldPos.Tab() != rNewPos.Tab() || rCxt.mnTabDelta;
2769 :
2770 66 : FormulaToken** p = pCode;
2771 66 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
2772 262 : for (; p != pEnd; ++p)
2773 : {
2774 196 : switch ((*p)->GetType())
2775 : {
2776 : case svSingleRef:
2777 : {
2778 48 : formula::FormulaToken* pToken = *p;
2779 48 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2780 48 : ScAddress aAbs = rRef.toAbs(rOldPos);
2781 48 : if (aOldRange.In(aAbs))
2782 : {
2783 32 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2784 32 : aRes.mbReferenceModified = true;
2785 : }
2786 :
2787 48 : rRef.SetAddress(aAbs, rNewPos);
2788 48 : if (b3DFlag)
2789 6 : rRef.SetFlag3D(b3DFlag);
2790 : }
2791 48 : break;
2792 : case svDoubleRef:
2793 : {
2794 20 : formula::FormulaToken* pToken = *p;
2795 20 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2796 20 : ScRange aAbs = rRef.toAbs(rOldPos);
2797 20 : if (aOldRange.In(aAbs))
2798 : {
2799 8 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2800 8 : aRes.mbReferenceModified = true;
2801 : }
2802 :
2803 20 : rRef.SetRange(aAbs, rNewPos);
2804 20 : if (b3DFlag)
2805 2 : rRef.Ref1.SetFlag3D(true);
2806 : }
2807 20 : break;
2808 : case svIndex:
2809 : {
2810 8 : if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
2811 8 : aRes.mbNameModified = true;
2812 : }
2813 8 : break;
2814 : default:
2815 : ;
2816 : }
2817 : }
2818 :
2819 66 : return aRes;
2820 : }
2821 :
2822 22 : sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc::RefUpdateContext& rCxt )
2823 : {
2824 22 : sc::RefUpdateResult aRes;
2825 :
2826 22 : ScRange aOldRange = rCxt.maRange;
2827 22 : aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
2828 :
2829 22 : FormulaToken** p = pCode;
2830 22 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
2831 84 : for (; p != pEnd; ++p)
2832 : {
2833 62 : switch ((*p)->GetType())
2834 : {
2835 : case svSingleRef:
2836 : {
2837 22 : formula::FormulaToken* pToken = *p;
2838 22 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2839 22 : ScAddress aAbs = rRef.toAbs(rPos);
2840 22 : if (aOldRange.In(aAbs))
2841 : {
2842 20 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2843 20 : rRef.SetAddress(aAbs, rPos);
2844 20 : if (rCxt.mnTabDelta)
2845 2 : rRef.SetFlag3D(aAbs.Tab()!=rPos.Tab());
2846 : }
2847 : }
2848 22 : break;
2849 : case svDoubleRef:
2850 : {
2851 4 : formula::FormulaToken* pToken = *p;
2852 4 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2853 4 : ScRange aAbs = rRef.toAbs(rPos);
2854 4 : if (aOldRange.In(aAbs))
2855 : {
2856 4 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
2857 4 : rRef.SetRange(aAbs, rPos);
2858 4 : if (rCxt.mnTabDelta)
2859 0 : rRef.Ref1.SetFlag3D(aAbs.aStart.Tab()!=rPos.Tab());
2860 : }
2861 : }
2862 4 : break;
2863 : case svIndex:
2864 : {
2865 4 : if (isNameModified(rCxt.maUpdatedNames, aOldRange.aStart.Tab(), **p))
2866 4 : aRes.mbNameModified = true;
2867 : }
2868 4 : break;
2869 : default:
2870 : ;
2871 : }
2872 : }
2873 :
2874 22 : return aRes;
2875 : }
2876 :
2877 2 : void ScTokenArray::MoveReferenceColReorder(
2878 : const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType& rColMap )
2879 : {
2880 2 : FormulaToken** p = pCode;
2881 2 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
2882 18 : for (; p != pEnd; ++p)
2883 : {
2884 16 : switch ((*p)->GetType())
2885 : {
2886 : case svSingleRef:
2887 : {
2888 4 : formula::FormulaToken* pToken = *p;
2889 4 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2890 4 : ScAddress aAbs = rRef.toAbs(rPos);
2891 :
2892 4 : if (aAbs.Tab() == nTab && nRow1 <= aAbs.Row() && aAbs.Row() <= nRow2)
2893 : {
2894 : // Inside reordered row range.
2895 4 : sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.Col());
2896 4 : if (it != rColMap.end())
2897 : {
2898 : // This column is reordered.
2899 4 : SCCOL nNewCol = it->second;
2900 4 : aAbs.SetCol(nNewCol);
2901 4 : rRef.SetAddress(aAbs, rPos);
2902 : }
2903 : }
2904 : }
2905 4 : break;
2906 : case svDoubleRef:
2907 : {
2908 0 : formula::FormulaToken* pToken = *p;
2909 0 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2910 0 : ScRange aAbs = rRef.toAbs(rPos);
2911 :
2912 0 : if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
2913 : // Must be a single-sheet reference.
2914 0 : break;
2915 :
2916 0 : if (aAbs.aStart.Col() != aAbs.aEnd.Col())
2917 : // Whole range must fit in a single column.
2918 0 : break;
2919 :
2920 0 : if (aAbs.aStart.Tab() == nTab && nRow1 <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= nRow2)
2921 : {
2922 : // Inside reordered row range.
2923 0 : sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.aStart.Col());
2924 0 : if (it != rColMap.end())
2925 : {
2926 : // This column is reordered.
2927 0 : SCCOL nNewCol = it->second;
2928 0 : aAbs.aStart.SetCol(nNewCol);
2929 0 : aAbs.aEnd.SetCol(nNewCol);
2930 0 : rRef.SetRange(aAbs, rPos);
2931 : }
2932 : }
2933 : }
2934 0 : break;
2935 : default:
2936 : ;
2937 : }
2938 : }
2939 2 : }
2940 :
2941 236 : void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType& rRowMap )
2942 : {
2943 236 : FormulaToken** p = pCode;
2944 236 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
2945 804 : for (; p != pEnd; ++p)
2946 : {
2947 568 : switch ((*p)->GetType())
2948 : {
2949 : case svSingleRef:
2950 : {
2951 210 : formula::FormulaToken* pToken = *p;
2952 210 : ScSingleRefData& rRef = *pToken->GetSingleRef();
2953 210 : ScAddress aAbs = rRef.toAbs(rPos);
2954 :
2955 210 : if (aAbs.Tab() == nTab && nCol1 <= aAbs.Col() && aAbs.Col() <= nCol2)
2956 : {
2957 : // Inside reordered column range.
2958 210 : sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.Row());
2959 210 : if (it != rRowMap.end())
2960 : {
2961 : // This column is reordered.
2962 210 : SCROW nNewRow = it->second;
2963 210 : aAbs.SetRow(nNewRow);
2964 210 : rRef.SetAddress(aAbs, rPos);
2965 : }
2966 : }
2967 : }
2968 210 : break;
2969 : case svDoubleRef:
2970 : {
2971 40 : formula::FormulaToken* pToken = *p;
2972 40 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
2973 40 : ScRange aAbs = rRef.toAbs(rPos);
2974 :
2975 40 : if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
2976 : // Must be a single-sheet reference.
2977 0 : break;
2978 :
2979 40 : if (aAbs.aStart.Row() != aAbs.aEnd.Row())
2980 : // Whole range must fit in a single row.
2981 0 : break;
2982 :
2983 40 : if (aAbs.aStart.Tab() == nTab && nCol1 <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= nCol2)
2984 : {
2985 : // Inside reordered column range.
2986 40 : sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.aStart.Row());
2987 40 : if (it != rRowMap.end())
2988 : {
2989 : // This row is reordered.
2990 40 : SCCOL nNewRow = it->second;
2991 40 : aAbs.aStart.SetRow(nNewRow);
2992 40 : aAbs.aEnd.SetRow(nNewRow);
2993 40 : rRef.SetRange(aAbs, rPos);
2994 : }
2995 : }
2996 : }
2997 40 : break;
2998 : default:
2999 : ;
3000 : }
3001 : }
3002 236 : }
3003 :
3004 : namespace {
3005 :
3006 12 : bool adjustSingleRefInName(
3007 : ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3008 : {
3009 12 : ScAddress aAbs = rRef.toAbs(rPos);
3010 :
3011 12 : if (aAbs.Tab() < rCxt.maRange.aStart.Tab() || rCxt.maRange.aEnd.Tab() < aAbs.Tab())
3012 : {
3013 : // This references a sheet that has not shifted. Don't change it.
3014 2 : return false;
3015 : }
3016 :
3017 10 : if (rRef.IsColRel() || rRef.IsRowRel())
3018 : {
3019 : // Adjust references only when both column and row are absolute.
3020 6 : return false;
3021 : }
3022 :
3023 4 : bool bChanged = false;
3024 :
3025 4 : if (rCxt.mnColDelta)
3026 : {
3027 : // Adjust absolute column reference.
3028 4 : if (rCxt.maRange.aStart.Col() <= rRef.Col() && rRef.Col() <= rCxt.maRange.aEnd.Col())
3029 : {
3030 4 : rRef.IncCol(rCxt.mnColDelta);
3031 4 : bChanged = true;
3032 : }
3033 : }
3034 :
3035 4 : if (rCxt.mnRowDelta)
3036 : {
3037 : // Adjust absolute row reference.
3038 0 : if (rCxt.maRange.aStart.Row() <= rRef.Row() && rRef.Row() <= rCxt.maRange.aEnd.Row())
3039 : {
3040 0 : rRef.IncRow(rCxt.mnRowDelta);
3041 0 : bChanged = true;
3042 : }
3043 : }
3044 :
3045 4 : if (!rRef.IsTabRel() && rCxt.mnTabDelta)
3046 : {
3047 : // Sheet range has already been checked above.
3048 0 : rRef.IncTab(rCxt.mnTabDelta);
3049 0 : bChanged = true;
3050 : }
3051 :
3052 4 : return bChanged;
3053 : }
3054 :
3055 10 : bool adjustDoubleRefInName(
3056 : ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3057 : {
3058 10 : bool bRefChanged = false;
3059 10 : if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel())
3060 : {
3061 : // Check and see if we should expand the range at the top.
3062 8 : ScRange aSelectedRange = getSelectedRange(rCxt);
3063 8 : ScRange aAbs = rRef.toAbs(rPos);
3064 8 : if (aSelectedRange.Intersects(aAbs))
3065 : {
3066 : // Selection intersects the referenced range. Only expand the
3067 : // bottom position.
3068 8 : rRef.Ref2.IncRow(rCxt.mnRowDelta);
3069 8 : return true;
3070 : }
3071 : }
3072 :
3073 2 : if (adjustSingleRefInName(rRef.Ref1, rCxt, rPos))
3074 2 : bRefChanged = true;
3075 :
3076 2 : if (adjustSingleRefInName(rRef.Ref2, rCxt, rPos))
3077 2 : bRefChanged = true;
3078 :
3079 2 : return bRefChanged;
3080 : }
3081 :
3082 : }
3083 :
3084 62 : sc::RefUpdateResult ScTokenArray::AdjustReferenceInName(
3085 : const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3086 : {
3087 62 : if (rCxt.meMode == URM_MOVE)
3088 16 : return AdjustReferenceInMovedName(rCxt, rPos);
3089 :
3090 46 : sc::RefUpdateResult aRes;
3091 :
3092 46 : FormulaToken** p = pCode;
3093 46 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3094 108 : for (; p != pEnd; ++p)
3095 : {
3096 62 : switch ((*p)->GetType())
3097 : {
3098 : case svSingleRef:
3099 : {
3100 8 : formula::FormulaToken* pToken = *p;
3101 8 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3102 8 : if (adjustSingleRefInName(rRef, rCxt, rPos))
3103 0 : aRes.mbReferenceModified = true;
3104 : }
3105 8 : break;
3106 : case svDoubleRef:
3107 : {
3108 46 : formula::FormulaToken* pToken = *p;
3109 46 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3110 46 : ScRange aAbs = rRef.toAbs(rPos);
3111 46 : if (rCxt.maRange.In(aAbs))
3112 : {
3113 : // This range is entirely within the shifted region.
3114 6 : if (adjustDoubleRefInName(rRef, rCxt, rPos))
3115 6 : aRes.mbReferenceModified = true;
3116 : }
3117 40 : else if (rCxt.mnRowDelta < 0)
3118 : {
3119 : // row(s) deleted.
3120 12 : if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
3121 : // Don't modify relative references in names.
3122 6 : break;
3123 :
3124 12 : if (aAbs.aStart.Col() < rCxt.maRange.aStart.Col() || rCxt.maRange.aEnd.Col() < aAbs.aEnd.Col())
3125 : // column range of the reference is not entirely in the deleted column range.
3126 6 : break;
3127 :
3128 6 : ScRange aDeleted = rCxt.maRange;
3129 6 : aDeleted.aStart.IncRow(rCxt.mnRowDelta);
3130 6 : aDeleted.aEnd.SetRow(aDeleted.aStart.Row()-rCxt.mnRowDelta-1);
3131 :
3132 6 : if (aAbs.aEnd.Row() < aDeleted.aStart.Row() || aDeleted.aEnd.Row() < aAbs.aStart.Row())
3133 : // reference range doesn't intersect with the deleted range.
3134 0 : break;
3135 :
3136 6 : if (aDeleted.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= aDeleted.aEnd.Row())
3137 : {
3138 : // This reference is entirely deleted.
3139 0 : rRef.Ref1.SetRowDeleted(true);
3140 0 : rRef.Ref2.SetRowDeleted(true);
3141 0 : aRes.mbReferenceModified = true;
3142 0 : break;
3143 : }
3144 :
3145 6 : if (aAbs.aStart.Row() < aDeleted.aStart.Row())
3146 : {
3147 4 : if (aDeleted.aEnd.Row() < aAbs.aEnd.Row())
3148 : // Deleted in the middle. Make the reference shorter.
3149 2 : rRef.Ref2.IncRow(rCxt.mnRowDelta);
3150 : else
3151 : // Deleted at tail end. Cut off the lower part.
3152 2 : rRef.Ref2.SetAbsRow(aDeleted.aStart.Row()-1);
3153 : }
3154 : else
3155 : {
3156 : // Deleted at the top. Cut the top off and shift up.
3157 2 : rRef.Ref1.SetAbsRow(aDeleted.aEnd.Row()+1);
3158 2 : rRef.Ref1.IncRow(rCxt.mnRowDelta);
3159 2 : rRef.Ref2.IncRow(rCxt.mnRowDelta);
3160 : }
3161 :
3162 6 : aRes.mbReferenceModified = true;
3163 : }
3164 28 : else if (rCxt.maRange.Intersects(aAbs))
3165 : {
3166 8 : if (rCxt.mnColDelta && rCxt.maRange.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= rCxt.maRange.aEnd.Row())
3167 : {
3168 0 : if (adjustDoubleRefInName(rRef, rCxt, rPos))
3169 0 : aRes.mbReferenceModified = true;
3170 : }
3171 8 : if (rCxt.mnRowDelta && rCxt.maRange.aStart.Col() <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= rCxt.maRange.aEnd.Col())
3172 : {
3173 4 : if (adjustDoubleRefInName(rRef, rCxt, rPos))
3174 4 : aRes.mbReferenceModified = true;
3175 : }
3176 : }
3177 20 : else if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
3178 : {
3179 : // Check if we could expand range reference by the bottom
3180 : // edge. For named expressions, we only expand absolute
3181 : // references.
3182 4 : if (!rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel() && aAbs.aEnd.Row()+1 == rCxt.maRange.aStart.Row())
3183 : {
3184 : // Expand by the bottom edge.
3185 4 : rRef.Ref2.IncRow(rCxt.mnRowDelta);
3186 4 : aRes.mbReferenceModified = true;
3187 : }
3188 : }
3189 : }
3190 40 : break;
3191 : default:
3192 : ;
3193 : }
3194 : }
3195 :
3196 46 : return aRes;
3197 : }
3198 :
3199 16 : sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3200 : {
3201 : // When moving, the range is the destination range.
3202 16 : ScRange aOldRange = rCxt.maRange;
3203 16 : aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
3204 :
3205 : // In a named expression, we'll move the reference only when the reference
3206 : // is entirely absolute.
3207 :
3208 16 : sc::RefUpdateResult aRes;
3209 :
3210 16 : FormulaToken** p = pCode;
3211 16 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3212 36 : for (; p != pEnd; ++p)
3213 : {
3214 20 : switch ((*p)->GetType())
3215 : {
3216 : case svSingleRef:
3217 : {
3218 2 : formula::FormulaToken* pToken = *p;
3219 2 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3220 2 : if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel())
3221 0 : continue;
3222 :
3223 2 : ScAddress aAbs = rRef.toAbs(rPos);
3224 2 : if (aOldRange.In(aAbs))
3225 : {
3226 2 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
3227 2 : aRes.mbReferenceModified = true;
3228 : }
3229 :
3230 2 : rRef.SetAddress(aAbs, rPos);
3231 : }
3232 2 : break;
3233 : case svDoubleRef:
3234 : {
3235 16 : formula::FormulaToken* pToken = *p;
3236 16 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3237 64 : if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() ||
3238 48 : rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel())
3239 0 : continue;
3240 :
3241 16 : ScRange aAbs = rRef.toAbs(rPos);
3242 16 : if (aOldRange.In(aAbs))
3243 : {
3244 10 : aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
3245 10 : aRes.mbReferenceModified = true;
3246 : }
3247 :
3248 16 : rRef.SetRange(aAbs, rPos);
3249 : }
3250 16 : break;
3251 : default:
3252 : ;
3253 : }
3254 : }
3255 :
3256 16 : return aRes;
3257 : }
3258 :
3259 : namespace {
3260 :
3261 340 : bool adjustSingleRefOnDeletedTab( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
3262 : {
3263 340 : ScAddress aAbs = rRef.toAbs(rOldPos);
3264 340 : if (nDelPos <= aAbs.Tab() && aAbs.Tab() < nDelPos + nSheets)
3265 : {
3266 80 : rRef.SetTabDeleted(true);
3267 80 : return true;
3268 : }
3269 :
3270 260 : if (nDelPos < aAbs.Tab())
3271 : {
3272 : // Reference sheet needs to be adjusted.
3273 74 : aAbs.IncTab(-1*nSheets);
3274 74 : rRef.SetAddress(aAbs, rNewPos);
3275 74 : return true;
3276 : }
3277 186 : else if (rOldPos.Tab() != rNewPos.Tab())
3278 : {
3279 : // Cell itself has moved.
3280 8 : rRef.SetAddress(aAbs, rNewPos);
3281 8 : return true;
3282 : }
3283 :
3284 178 : return false;
3285 : }
3286 :
3287 330 : bool adjustSingleRefOnInsertedTab( ScSingleRefData& rRef, SCTAB nInsPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
3288 : {
3289 330 : ScAddress aAbs = rRef.toAbs(rOldPos);
3290 330 : if (nInsPos <= aAbs.Tab())
3291 : {
3292 : // Reference sheet needs to be adjusted.
3293 320 : aAbs.IncTab(nSheets);
3294 320 : rRef.SetAddress(aAbs, rNewPos);
3295 320 : return true;
3296 : }
3297 10 : else if (rOldPos.Tab() != rNewPos.Tab())
3298 : {
3299 : // Cell itself has moved.
3300 8 : rRef.SetAddress(aAbs, rNewPos);
3301 8 : return true;
3302 : }
3303 :
3304 2 : return false;
3305 : }
3306 :
3307 : }
3308 :
3309 268 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( sc::RefUpdateDeleteTabContext& rCxt, const ScAddress& rOldPos )
3310 : {
3311 268 : sc::RefUpdateResult aRes;
3312 268 : ScAddress aNewPos = rOldPos;
3313 268 : if (rCxt.mnDeletePos < rOldPos.Tab())
3314 50 : aNewPos.IncTab(-1*rCxt.mnSheets);
3315 :
3316 268 : FormulaToken** p = pCode;
3317 268 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3318 888 : for (; p != pEnd; ++p)
3319 : {
3320 620 : switch ((*p)->GetType())
3321 : {
3322 : case svSingleRef:
3323 : {
3324 244 : formula::FormulaToken* pToken = *p;
3325 244 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3326 244 : if (adjustSingleRefOnDeletedTab(rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
3327 130 : aRes.mbReferenceModified = true;
3328 : }
3329 244 : break;
3330 : case svDoubleRef:
3331 : {
3332 48 : formula::FormulaToken* pToken = *p;
3333 48 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3334 48 : if (adjustSingleRefOnDeletedTab(rRef.Ref1, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
3335 16 : aRes.mbReferenceModified = true;
3336 48 : if (adjustSingleRefOnDeletedTab(rRef.Ref2, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
3337 16 : aRes.mbReferenceModified = true;
3338 : }
3339 48 : break;
3340 : case svIndex:
3341 : {
3342 22 : if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
3343 10 : aRes.mbNameModified = true;
3344 : }
3345 22 : break;
3346 : default:
3347 : ;
3348 : }
3349 : }
3350 268 : return aRes;
3351 : }
3352 :
3353 600 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( sc::RefUpdateInsertTabContext& rCxt, const ScAddress& rOldPos )
3354 : {
3355 600 : sc::RefUpdateResult aRes;
3356 600 : ScAddress aNewPos = rOldPos;
3357 600 : if (rCxt.mnInsertPos <= rOldPos.Tab())
3358 598 : aNewPos.IncTab(rCxt.mnSheets);
3359 :
3360 600 : FormulaToken** p = pCode;
3361 600 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3362 1434 : for (; p != pEnd; ++p)
3363 : {
3364 834 : switch ((*p)->GetType())
3365 : {
3366 : case svSingleRef:
3367 : {
3368 310 : formula::FormulaToken* pToken = *p;
3369 310 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3370 310 : if (adjustSingleRefOnInsertedTab(rRef, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
3371 308 : aRes.mbReferenceModified = true;
3372 : }
3373 310 : break;
3374 : case svDoubleRef:
3375 : {
3376 10 : formula::FormulaToken* pToken = *p;
3377 10 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3378 10 : if (adjustSingleRefOnInsertedTab(rRef.Ref1, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
3379 10 : aRes.mbReferenceModified = true;
3380 10 : if (adjustSingleRefOnInsertedTab(rRef.Ref2, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
3381 10 : aRes.mbReferenceModified = true;
3382 : }
3383 10 : break;
3384 : case svIndex:
3385 : {
3386 364 : if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
3387 364 : aRes.mbNameModified = true;
3388 : }
3389 364 : break;
3390 : default:
3391 : ;
3392 : }
3393 : }
3394 600 : return aRes;
3395 : }
3396 :
3397 : namespace {
3398 :
3399 106 : bool adjustTabOnMove( ScAddress& rPos, sc::RefUpdateMoveTabContext& rCxt )
3400 : {
3401 106 : SCTAB nNewTab = rCxt.getNewTab(rPos.Tab());
3402 106 : if (nNewTab == rPos.Tab())
3403 40 : return false;
3404 :
3405 66 : rPos.SetTab(nNewTab);
3406 66 : return true;
3407 : }
3408 :
3409 : }
3410 :
3411 36 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTabContext& rCxt, const ScAddress& rOldPos )
3412 : {
3413 36 : sc::RefUpdateResult aRes;
3414 36 : if (rCxt.mnOldPos == rCxt.mnNewPos)
3415 0 : return aRes;
3416 :
3417 36 : ScAddress aNewPos = rOldPos;
3418 36 : if (adjustTabOnMove(aNewPos, rCxt))
3419 28 : aRes.mbReferenceModified = true;
3420 :
3421 36 : FormulaToken** p = pCode;
3422 36 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3423 168 : for (; p != pEnd; ++p)
3424 : {
3425 132 : switch ((*p)->GetType())
3426 : {
3427 : case svSingleRef:
3428 : {
3429 2 : formula::FormulaToken* pToken = *p;
3430 2 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3431 2 : ScAddress aAbs = rRef.toAbs(rOldPos);
3432 2 : if (adjustTabOnMove(aAbs, rCxt))
3433 2 : aRes.mbReferenceModified = true;
3434 2 : rRef.SetAddress(aAbs, aNewPos);
3435 : }
3436 2 : break;
3437 : case svDoubleRef:
3438 : {
3439 34 : formula::FormulaToken* pToken = *p;
3440 34 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3441 34 : ScRange aAbs = rRef.toAbs(rOldPos);
3442 34 : if (adjustTabOnMove(aAbs.aStart, rCxt))
3443 18 : aRes.mbReferenceModified = true;
3444 34 : if (adjustTabOnMove(aAbs.aEnd, rCxt))
3445 18 : aRes.mbReferenceModified = true;
3446 34 : rRef.SetRange(aAbs, aNewPos);
3447 : }
3448 34 : break;
3449 : case svIndex:
3450 : {
3451 0 : if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
3452 0 : aRes.mbNameModified = true;
3453 : }
3454 0 : break;
3455 : default:
3456 : ;
3457 : }
3458 : }
3459 :
3460 36 : return aRes;
3461 : }
3462 :
3463 344 : void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const ScAddress& rNewPos )
3464 : {
3465 344 : FormulaToken** p = pCode;
3466 344 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3467 962 : for (; p != pEnd; ++p)
3468 : {
3469 618 : switch ((*p)->GetType())
3470 : {
3471 : case svSingleRef:
3472 : case svExternalSingleRef:
3473 : {
3474 312 : formula::FormulaToken* pToken = *p;
3475 312 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3476 312 : ScAddress aAbs = rRef.toAbs(rOldPos);
3477 312 : rRef.SetAddress(aAbs, rNewPos);
3478 : }
3479 312 : break;
3480 : case svDoubleRef:
3481 : case svExternalDoubleRef:
3482 : {
3483 40 : formula::FormulaToken* pToken = *p;
3484 40 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3485 40 : ScRange aAbs = rRef.toAbs(rOldPos);
3486 40 : rRef.SetRange(aAbs, rNewPos);
3487 : }
3488 40 : break;
3489 : default:
3490 : ;
3491 : }
3492 : }
3493 344 : }
3494 :
3495 : namespace {
3496 :
3497 2 : void clearTabDeletedFlag( ScSingleRefData& rRef, const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
3498 : {
3499 2 : if (!rRef.IsTabDeleted())
3500 2 : return;
3501 :
3502 2 : ScAddress aAbs = rRef.toAbs(rPos);
3503 2 : if (nStartTab <= aAbs.Tab() && aAbs.Tab() <= nEndTab)
3504 2 : rRef.SetTabDeleted(false);
3505 : }
3506 :
3507 : }
3508 :
3509 2 : void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
3510 : {
3511 2 : if (nEndTab < nStartTab)
3512 2 : return;
3513 :
3514 2 : FormulaToken** p = pCode;
3515 2 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3516 4 : for (; p != pEnd; ++p)
3517 : {
3518 2 : switch ((*p)->GetType())
3519 : {
3520 : case svSingleRef:
3521 : {
3522 2 : formula::FormulaToken* pToken = *p;
3523 2 : ScSingleRefData& rRef = *pToken->GetSingleRef();
3524 2 : clearTabDeletedFlag(rRef, rPos, nStartTab, nEndTab);
3525 : }
3526 2 : break;
3527 : case svDoubleRef:
3528 : {
3529 0 : formula::FormulaToken* pToken = *p;
3530 0 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
3531 0 : clearTabDeletedFlag(rRef.Ref1, rPos, nStartTab, nEndTab);
3532 0 : clearTabDeletedFlag(rRef.Ref2, rPos, nStartTab, nEndTab);
3533 : }
3534 0 : break;
3535 : default:
3536 : ;
3537 : }
3538 : }
3539 : }
3540 :
3541 : namespace {
3542 :
3543 78 : void checkBounds(
3544 : const ScAddress& rPos, SCROW nGroupLen, const ScRange& rCheckRange,
3545 : const ScSingleRefData& rRef, std::vector<SCROW>& rBounds )
3546 : {
3547 78 : if (!rRef.IsRowRel())
3548 28 : return;
3549 :
3550 78 : ScRange aAbs(rRef.toAbs(rPos));
3551 78 : aAbs.aEnd.IncRow(nGroupLen-1);
3552 78 : if (!rCheckRange.Intersects(aAbs))
3553 28 : return;
3554 :
3555 : // Get the boundary row positions.
3556 50 : if (aAbs.aEnd.Row() < rCheckRange.aStart.Row())
3557 : // No intersections.
3558 0 : return;
3559 :
3560 50 : if (aAbs.aStart.Row() <= rCheckRange.aStart.Row())
3561 : {
3562 : // +-+ <---- top
3563 : // | |
3564 : // +--+-+--+ <---- boundary row position
3565 : // | | | |
3566 : // | |
3567 : // +-------+
3568 :
3569 : // Add offset from the reference top to the cell position.
3570 28 : SCROW nOffset = rCheckRange.aStart.Row() - aAbs.aStart.Row();
3571 28 : rBounds.push_back(rPos.Row()+nOffset);
3572 : }
3573 :
3574 50 : if (aAbs.aEnd.Row() >= rCheckRange.aEnd.Row())
3575 : {
3576 : // only check for end range
3577 :
3578 : // +-------+
3579 : // | |
3580 : // | | | |
3581 : // +--+-+--+ <---- boundary row position
3582 : // | |
3583 : // +-+
3584 :
3585 : // Ditto.
3586 16 : SCROW nOffset = rCheckRange.aEnd.Row() + 1 - aAbs.aStart.Row();
3587 16 : rBounds.push_back(rPos.Row()+nOffset);
3588 : }
3589 : }
3590 :
3591 86 : void checkBounds(
3592 : const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen,
3593 : const ScSingleRefData& rRef, std::vector<SCROW>& rBounds)
3594 : {
3595 86 : if (!rRef.IsRowRel())
3596 98 : return;
3597 :
3598 74 : ScRange aCheckRange = rCxt.maRange;
3599 74 : if (rCxt.meMode == URM_MOVE)
3600 : // Check bounds against the old range prior to the move.
3601 10 : aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
3602 :
3603 74 : checkBounds(rPos, nGroupLen, aCheckRange, rRef, rBounds);
3604 : }
3605 :
3606 : }
3607 :
3608 90 : void ScTokenArray::CheckRelativeReferenceBounds(
3609 : const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
3610 : {
3611 90 : FormulaToken** p = pCode;
3612 90 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3613 256 : for (; p != pEnd; ++p)
3614 : {
3615 166 : switch ((*p)->GetType())
3616 : {
3617 : case svSingleRef:
3618 : {
3619 82 : formula::FormulaToken* pToken = *p;
3620 82 : checkBounds(rCxt, rPos, nGroupLen, *pToken->GetSingleRef(), rBounds);
3621 : }
3622 82 : break;
3623 : case svDoubleRef:
3624 : {
3625 2 : formula::FormulaToken* pToken = *p;
3626 2 : const ScComplexRefData& rRef = *pToken->GetDoubleRef();
3627 2 : checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
3628 2 : checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
3629 : }
3630 2 : break;
3631 : default:
3632 : ;
3633 : }
3634 : }
3635 90 : }
3636 :
3637 2 : void ScTokenArray::CheckRelativeReferenceBounds(
3638 : const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector<SCROW>& rBounds ) const
3639 : {
3640 2 : FormulaToken** p = pCode;
3641 2 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3642 18 : for (; p != pEnd; ++p)
3643 : {
3644 16 : switch ((*p)->GetType())
3645 : {
3646 : case svSingleRef:
3647 : {
3648 4 : formula::FormulaToken* pToken = *p;
3649 4 : const ScSingleRefData& rRef = *pToken->GetSingleRef();
3650 4 : checkBounds(rPos, nGroupLen, rRange, rRef, rBounds);
3651 : }
3652 4 : break;
3653 : case svDoubleRef:
3654 : {
3655 0 : formula::FormulaToken* pToken = *p;
3656 0 : const ScComplexRefData& rRef = *pToken->GetDoubleRef();
3657 0 : checkBounds(rPos, nGroupLen, rRange, rRef.Ref1, rBounds);
3658 0 : checkBounds(rPos, nGroupLen, rRange, rRef.Ref2, rBounds);
3659 : }
3660 0 : break;
3661 : default:
3662 : ;
3663 : }
3664 : }
3665 2 : }
3666 :
3667 : namespace {
3668 :
3669 1748 : void appendDouble( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, double fVal )
3670 : {
3671 1748 : if (rCxt.mxOpCodeMap->isEnglish())
3672 : {
3673 : rtl::math::doubleToUStringBuffer(
3674 1748 : rBuf, fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
3675 : }
3676 : else
3677 : {
3678 0 : SvtSysLocale aSysLocale;
3679 : rtl::math::doubleToUStringBuffer(
3680 : rBuf, fVal,
3681 : rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
3682 0 : aSysLocale.GetLocaleDataPtr()->getNumDecimalSep()[0], true);
3683 : }
3684 1748 : }
3685 :
3686 16 : void appendString( OUStringBuffer& rBuf, const OUString& rStr )
3687 : {
3688 16 : rBuf.append('"');
3689 16 : rBuf.append(rStr.replaceAll("\"", "\"\""));
3690 16 : rBuf.append('"');
3691 16 : }
3692 :
3693 17140 : void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken, const ScAddress& rPos )
3694 : {
3695 17140 : if (rToken.IsExternalRef())
3696 : {
3697 6 : size_t nFileId = rToken.GetIndex();
3698 6 : OUString aTabName = rToken.GetString().getString();
3699 6 : if (nFileId >= rCxt.maExternalFileNames.size())
3700 : // out of bound
3701 0 : return;
3702 :
3703 12 : OUString aFileName = rCxt.maExternalFileNames[nFileId];
3704 :
3705 6 : switch (rToken.GetType())
3706 : {
3707 : case svExternalName:
3708 0 : rBuf.append(rCxt.mpRefConv->makeExternalNameStr(nFileId, aFileName, aTabName));
3709 0 : break;
3710 : case svExternalSingleRef:
3711 : rCxt.mpRefConv->makeExternalRefStr(
3712 6 : rBuf, rPos, nFileId, aFileName, aTabName, *rToken.GetSingleRef());
3713 6 : break;
3714 : case svExternalDoubleRef:
3715 : {
3716 : sc::TokenStringContext::IndexNamesMapType::const_iterator it =
3717 0 : rCxt.maExternalCachedTabNames.find(nFileId);
3718 :
3719 0 : if (it == rCxt.maExternalCachedTabNames.end())
3720 0 : return;
3721 :
3722 : rCxt.mpRefConv->makeExternalRefStr(
3723 0 : rBuf, rPos, nFileId, aFileName, it->second, aTabName,
3724 0 : *rToken.GetDoubleRef());
3725 : }
3726 0 : break;
3727 : default:
3728 : // warning, not error, otherwise we may end up with a never
3729 : // ending message box loop if this was the cursor cell to be redrawn.
3730 : OSL_FAIL("appendTokenByType: unknown type of ocExternalRef");
3731 : }
3732 12 : return;
3733 : }
3734 :
3735 17134 : OpCode eOp = rToken.GetOpCode();
3736 17134 : switch (rToken.GetType())
3737 : {
3738 : case svDouble:
3739 1748 : appendDouble(rCxt, rBuf, rToken.GetDouble());
3740 1748 : break;
3741 : case svString:
3742 : {
3743 16 : OUString aStr = rToken.GetString().getString();
3744 16 : if (eOp == ocBad || eOp == ocStringXML)
3745 : {
3746 0 : rBuf.append(aStr);
3747 0 : return;
3748 : }
3749 :
3750 16 : appendString(rBuf, aStr);
3751 : }
3752 16 : break;
3753 : case svSingleRef:
3754 : {
3755 3518 : if (rCxt.mpRefConv)
3756 : {
3757 3518 : const ScSingleRefData& rRef = *rToken.GetSingleRef();
3758 : ScComplexRefData aRef;
3759 3518 : aRef.Ref1 = rRef;
3760 3518 : aRef.Ref2 = rRef;
3761 3518 : rCxt.mpRefConv->makeRefStr(rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true);
3762 : }
3763 : else
3764 0 : rBuf.append(rCxt.maErrRef);
3765 : }
3766 3518 : break;
3767 : case svDoubleRef:
3768 : {
3769 912 : if (rCxt.mpRefConv)
3770 : {
3771 912 : const ScComplexRefData& rRef = *rToken.GetDoubleRef();
3772 912 : rCxt.mpRefConv->makeRefStr(rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false);
3773 : }
3774 : else
3775 0 : rBuf.append(rCxt.maErrRef);
3776 : }
3777 912 : break;
3778 : case svMatrix:
3779 : {
3780 0 : const ScMatrix* pMat = rToken.GetMatrix();
3781 0 : if (!pMat)
3782 0 : return;
3783 :
3784 : size_t nC, nMaxC, nR, nMaxR;
3785 0 : pMat->GetDimensions(nMaxC, nMaxR);
3786 :
3787 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayOpen));
3788 0 : for (nR = 0 ; nR < nMaxR ; ++nR)
3789 : {
3790 0 : if (nR > 0)
3791 : {
3792 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayRowSep));
3793 : }
3794 :
3795 0 : for (nC = 0 ; nC < nMaxC ; ++nC)
3796 : {
3797 0 : if (nC > 0)
3798 : {
3799 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayColSep));
3800 : }
3801 :
3802 0 : if (pMat->IsValue(nC, nR))
3803 : {
3804 0 : if (pMat->IsBoolean(nC, nR))
3805 : {
3806 0 : bool bVal = pMat->GetDouble(nC, nR) != 0.0;
3807 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(bVal ? ocTrue : ocFalse));
3808 : }
3809 : else
3810 : {
3811 0 : sal_uInt16 nErr = pMat->GetError(nC, nR);
3812 0 : if (nErr)
3813 0 : rBuf.append(ScGlobal::GetErrorString(nErr));
3814 : else
3815 0 : appendDouble(rCxt, rBuf, pMat->GetDouble(nC, nR));
3816 : }
3817 : }
3818 0 : else if (pMat->IsEmpty(nC, nR))
3819 : {
3820 : // Skip it.
3821 : }
3822 0 : else if (pMat->IsString(nC, nR))
3823 0 : appendString(rBuf, pMat->GetString(nC, nR).getString());
3824 : }
3825 : }
3826 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayClose));
3827 : }
3828 0 : break;
3829 : case svIndex:
3830 : {
3831 : typedef sc::TokenStringContext::IndexNameMapType NameType;
3832 :
3833 12 : sal_uInt16 nIndex = rToken.GetIndex();
3834 12 : switch (eOp)
3835 : {
3836 : case ocName:
3837 : {
3838 12 : if (rToken.IsGlobal())
3839 : {
3840 : // global named range
3841 6 : NameType::const_iterator it = rCxt.maGlobalRangeNames.find(nIndex);
3842 6 : if (it == rCxt.maGlobalRangeNames.end())
3843 : {
3844 0 : rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
3845 0 : break;
3846 : }
3847 :
3848 6 : rBuf.append(it->second);
3849 : }
3850 : else
3851 : {
3852 : // sheet-local named range
3853 6 : sc::TokenStringContext::TabIndexMapType::const_iterator itTab = rCxt.maSheetRangeNames.find(rPos.Tab());
3854 6 : if (itTab == rCxt.maSheetRangeNames.end())
3855 : {
3856 0 : rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
3857 0 : break;
3858 : }
3859 :
3860 6 : const NameType& rNames = itTab->second;
3861 6 : NameType::const_iterator it = rNames.find(nIndex);
3862 6 : if (it == rNames.end())
3863 : {
3864 0 : rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
3865 0 : break;
3866 : }
3867 :
3868 6 : rBuf.append(it->second);
3869 : }
3870 : }
3871 12 : break;
3872 : case ocDBArea:
3873 : {
3874 0 : NameType::const_iterator it = rCxt.maNamedDBs.find(nIndex);
3875 0 : if (it != rCxt.maNamedDBs.end())
3876 0 : rBuf.append(it->second);
3877 : }
3878 0 : break;
3879 : default:
3880 0 : rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
3881 : }
3882 : }
3883 12 : break;
3884 : case svExternal:
3885 : {
3886 : // mapped or translated name of AddIns
3887 0 : OUString aAddIn = rToken.GetExternal();
3888 0 : bool bMapped = rCxt.mxOpCodeMap->isPODF(); // ODF 1.1 directly uses programmatical name
3889 0 : if (!bMapped && rCxt.mxOpCodeMap->hasExternals())
3890 : {
3891 0 : const ExternalHashMap& rExtMap = *rCxt.mxOpCodeMap->getReverseExternalHashMap();
3892 0 : ExternalHashMap::const_iterator it = rExtMap.find(aAddIn);
3893 0 : if (it != rExtMap.end())
3894 : {
3895 0 : aAddIn = it->second;
3896 0 : bMapped = true;
3897 : }
3898 : }
3899 :
3900 0 : if (!bMapped && !rCxt.mxOpCodeMap->isEnglish())
3901 0 : ScGlobal::GetAddInCollection()->LocalizeString(aAddIn);
3902 :
3903 0 : rBuf.append(aAddIn);
3904 : }
3905 0 : break;
3906 : case svError:
3907 : {
3908 0 : sal_uInt16 nErr = rToken.GetError();
3909 : OpCode eOpErr;
3910 0 : switch (nErr)
3911 : {
3912 : break;
3913 : case errDivisionByZero:
3914 0 : eOpErr = ocErrDivZero;
3915 0 : break;
3916 : case errNoValue:
3917 0 : eOpErr = ocErrValue;
3918 0 : break;
3919 : case errNoRef:
3920 0 : eOpErr = ocErrRef;
3921 0 : break;
3922 : case errNoName:
3923 0 : eOpErr = ocErrName;
3924 0 : break;
3925 : case errIllegalFPOperation:
3926 0 : eOpErr = ocErrNum;
3927 0 : break;
3928 : case NOTAVAILABLE:
3929 0 : eOpErr = ocErrNA;
3930 0 : break;
3931 : case errNoCode:
3932 : default:
3933 0 : eOpErr = ocErrNull;
3934 : }
3935 0 : rBuf.append(rCxt.mxOpCodeMap->getSymbol(eOpErr));
3936 : }
3937 0 : break;
3938 : case svByte:
3939 : case svJump:
3940 : case svFAP:
3941 : case svMissing:
3942 : case svSep:
3943 : default:
3944 : ;
3945 : }
3946 : }
3947 :
3948 : }
3949 :
3950 1982 : OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddress& rPos ) const
3951 : {
3952 1982 : if (!nLen)
3953 0 : return OUString();
3954 :
3955 1982 : OUStringBuffer aBuf;
3956 :
3957 1982 : FormulaToken** p = pCode;
3958 1982 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3959 19756 : for (; p != pEnd; ++p)
3960 : {
3961 17774 : const FormulaToken* pToken = *p;
3962 17774 : OpCode eOp = pToken->GetOpCode();
3963 17774 : bool bCheckType = true;
3964 17774 : if (eOp == ocSpaces)
3965 : {
3966 : // TODO : Handle intersection operator '!!'.
3967 634 : aBuf.append(' ');
3968 634 : continue;
3969 : }
3970 :
3971 17140 : if (eOp < rCxt.mxOpCodeMap->getSymbolCount())
3972 17140 : aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp));
3973 :
3974 17140 : if (bCheckType)
3975 17140 : appendTokenByType(rCxt, aBuf, *pToken, rPos);
3976 : }
3977 :
3978 1982 : return aBuf.makeStringAndClear();
3979 : }
3980 :
3981 : namespace {
3982 :
3983 22214 : void wrapAddress( ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
3984 : {
3985 22214 : if (rPos.Col() > nMaxCol)
3986 1452 : rPos.SetCol(rPos.Col() - nMaxCol - 1);
3987 22214 : if (rPos.Row() > nMaxRow)
3988 0 : rPos.SetRow(rPos.Row() - nMaxRow - 1);
3989 22214 : }
3990 :
3991 : }
3992 :
3993 6980 : void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
3994 : {
3995 6980 : FormulaToken** p = pCode;
3996 6980 : FormulaToken** pEnd = p + static_cast<size_t>(nLen);
3997 80768 : for (; p != pEnd; ++p)
3998 : {
3999 73788 : switch ((*p)->GetType())
4000 : {
4001 : case svSingleRef:
4002 : {
4003 12810 : formula::FormulaToken* pToken = *p;
4004 12810 : ScSingleRefData& rRef = *pToken->GetSingleRef();
4005 12810 : ScAddress aAbs = rRef.toAbs(rPos);
4006 12810 : wrapAddress(aAbs, nMaxCol, nMaxRow);
4007 12810 : rRef.SetAddress(aAbs, rPos);
4008 : }
4009 12810 : break;
4010 : case svDoubleRef:
4011 : {
4012 4702 : formula::FormulaToken* pToken = *p;
4013 4702 : ScComplexRefData& rRef = *pToken->GetDoubleRef();
4014 4702 : ScRange aAbs = rRef.toAbs(rPos);
4015 4702 : wrapAddress(aAbs.aStart, nMaxCol, nMaxRow);
4016 4702 : wrapAddress(aAbs.aEnd, nMaxCol, nMaxRow);
4017 4702 : aAbs.PutInOrder();
4018 4702 : rRef.SetRange(aAbs, rPos);
4019 : }
4020 4702 : break;
4021 : default:
4022 : ;
4023 : }
4024 : }
4025 7208 : }
4026 :
4027 : #if DEBUG_FORMULA_COMPILER
4028 :
4029 : void ScTokenArray::Dump() const
4030 : {
4031 : cout << "+++ Normal Tokens +++" << endl;
4032 : for (sal_uInt16 i = 0; i < nLen; ++i)
4033 : {
4034 : DumpToken(*pCode[i]);
4035 : }
4036 :
4037 : cout << "+++ RPN Tokens +++" << endl;
4038 : for (sal_uInt16 i = 0; i < nRPN; ++i)
4039 : {
4040 : DumpToken(*pRPN[i]);
4041 : }
4042 : }
4043 : #endif
4044 :
4045 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|