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