LibreOffice Module sc (master) 1
token.cxx
Go to the documentation of this file.
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 <functional>
21
22#include <string.h>
23#include <osl/diagnose.h>
24#include <sal/log.hxx>
25
26#include <token.hxx>
27#include <tokenarray.hxx>
28#include <reftokenhelper.hxx>
29#include <clipparam.hxx>
30#include <compiler.hxx>
31#include <interpre.hxx>
33#include <formula/compiler.hxx>
34#include <formula/opcode.hxx>
35#include <jumpmatrix.hxx>
36#include <rangeseq.hxx>
37#include <rangeutl.hxx>
38#include <externalrefmgr.hxx>
39#include <document.hxx>
40#include <refupdatecontext.hxx>
42#include <types.hxx>
43#include <addincol.hxx>
44#include <dbdata.hxx>
45#include <reordermap.hxx>
46#include <svl/sharedstring.hxx>
47#include <scmatrix.hxx>
48
49using ::std::vector;
50
51#include <com/sun/star/sheet/ComplexReference.hpp>
52#include <com/sun/star/sheet/ExternalReference.hpp>
53#include <com/sun/star/sheet/FormulaToken.hpp>
54#include <com/sun/star/sheet/ReferenceFlags.hpp>
55#include <com/sun/star/sheet/NameToken.hpp>
56#include <utility>
57#include <o3tl/safeint.hxx>
59
60using namespace formula;
61using namespace com::sun::star;
62
63namespace
64{
65 void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
66 {
67 rRef.InitFlags();
68
69 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
70 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
71 rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
72 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
73 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
74 rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
75 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
76 rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
77
78 if (rRef.IsColRel())
79 rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
80 else
81 rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
82
83 if (rRef.IsRowRel())
84 rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
85 else
86 rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
87
88 if (rRef.IsTabRel())
89 rRef.SetRelTab(static_cast<SCTAB>(rAPI.RelativeSheet));
90 else
91 rRef.SetAbsTab(static_cast<SCTAB>(rAPI.Sheet));
92 }
93
94 void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
95 {
96 rRef.InitFlags();
97
98 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
99 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
100 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
101 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
102 rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
103 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
104 rRef.SetRelName( false );
105
106 if (rRef.IsColRel())
107 rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
108 else
109 rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
110
111 if (rRef.IsRowRel())
112 rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
113 else
114 rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
115
116 // sheet index must be absolute for external refs
117 rRef.SetAbsTab(0);
118 }
119
120 struct TokenPointerRange
121 {
123 FormulaToken** mpStop;
124
125 TokenPointerRange() : mpStart(nullptr), mpStop(nullptr) {}
126 TokenPointerRange( FormulaToken** p, sal_uInt16 n ) :
127 mpStart(p), mpStop( p + static_cast<size_t>(n)) {}
128 };
129 struct TokenPointers
130 {
131 TokenPointerRange maPointerRange[2];
132 bool mbSkipRelName;
133
134 TokenPointers( FormulaToken** pCode, sal_uInt16 nLen, FormulaToken** pRPN, sal_uInt16 nRPN,
135 bool bSkipRelName = true ) :
136 mbSkipRelName(bSkipRelName)
137 {
138 maPointerRange[0] = TokenPointerRange( pCode, nLen);
139 maPointerRange[1] = TokenPointerRange( pRPN, nRPN);
140 }
141
142 bool skipToken( size_t i, const FormulaToken* const * pp )
143 {
144 // Handle all code tokens, and tokens in RPN only if they have a
145 // reference count of 1, which means they are not referenced in the
146 // code array. Doing it the other way would skip code tokens that
147 // are held by flat copied token arrays and thus are shared. For
148 // flat copy arrays the caller has to know what it does and should
149 // discard all RPN, update only one array and regenerate all RPN.
150 if (i == 1)
151 {
152 if ((*pp)->GetRef() > 1)
153 return true;
154
155 if (mbSkipRelName)
156 {
157 // Skip (do not adjust) relative references resulting from
158 // named expressions. Resolved expressions are only in RPN.
159 switch ((*pp)->GetType())
160 {
161 case svSingleRef:
162 return (*pp)->GetSingleRef()->IsRelName();
163 case svDoubleRef:
164 {
165 const ScComplexRefData& rRef = *(*pp)->GetDoubleRef();
166 return rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName();
167 }
168 default:
169 ; // nothing
170 }
171 }
172 }
173
174 return false;
175 }
176
177 FormulaToken* getHandledToken( size_t i, FormulaToken* const * pp )
178 {
179 if (skipToken( i, pp))
180 return nullptr;
181
182 FormulaToken* p = *pp;
183 if (p->GetOpCode() == ocTableRef)
184 {
185 // Return the inner reference token if it is not in RPN.
186 ScTableRefToken* pTR = dynamic_cast<ScTableRefToken*>(p);
187 if (!pTR)
188 return p;
189 p = pTR->GetAreaRefRPN();
190 if (!p)
191 return pTR;
192 if (p->GetRef() > 1)
193 // Reference handled in RPN, but do not return nullptr so
194 // loops will process ocTableRef via pp instead of issuing
195 // a continue.
196 return pTR;
197 }
198 return p;
199 }
200 };
201
202} // namespace
203
204
205// --- class ScRawToken -----------------------------------------------------
206
208{
209 eOp = e;
210 switch (eOp)
211 {
212 case ocIf:
213 eType = svJump;
214 nJump[ 0 ] = 3; // If, Else, Behind
215 break;
216 case ocIfError:
217 case ocIfNA:
218 eType = svJump;
219 nJump[ 0 ] = 2; // If, Behind
220 break;
221 case ocChoose:
222 eType = svJump;
223 nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
224 break;
225 case ocMissing:
227 break;
228 case ocSep:
229 case ocOpen:
230 case ocClose:
231 case ocArrayRowSep:
232 case ocArrayColSep:
233 case ocArrayOpen:
234 case ocArrayClose:
235 case ocTableRefOpen:
236 case ocTableRefClose:
237 eType = svSep;
238 break;
239 case ocWhitespace:
240 eType = svByte;
241 whitespace.nCount = 1;
242 whitespace.cChar = 0x20;
243 break;
244 default:
245 eType = svByte;
246 sbyte.cByte = 0;
247 sbyte.eInForceArray = ParamClass::Unknown;
248 }
249}
250
251void ScRawToken::SetString( rtl_uString* pData, rtl_uString* pDataIgnoreCase )
252{
253 eOp = ocPush;
254 eType = svString;
255
256 sharedstring.mpData = pData;
257 sharedstring.mpDataIgnoreCase = pDataIgnoreCase;
258}
259
261{
262 eOp = ocPush;
264 aRef.Ref1 =
265 aRef.Ref2 = rRef;
266}
267
269{
270 eOp = ocPush;
272 aRef = rRef;
273}
274
275void ScRawToken::SetDouble(double rVal)
276{
277 eOp = ocPush;
278 eType = svDouble;
279 nValue = rVal;
280}
281
283{
284 eOp = ocPush;
285 eType = svError;
286 nError = nErr;
287}
288
289void ScRawToken::SetName(sal_Int16 nSheet, sal_uInt16 nIndex)
290{
291 eOp = ocName;
292 eType = svIndex;
293
294 name.nSheet = nSheet;
295 name.nIndex = nIndex;
296}
297
298void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
299{
300 eOp = ocPush;
302
303 extref.nFileId = nFileId;
304 extref.aRef.Ref1 =
305 extref.aRef.Ref2 = rRef;
306 maExternalName = rTabName;
307}
308
309void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
310{
311 eOp = ocPush;
313
314 extref.nFileId = nFileId;
315 extref.aRef = rRef;
316 maExternalName = rTabName;
317}
318
319void ScRawToken::SetExternalName( sal_uInt16 nFileId, const OUString& rName )
320{
321 eOp = ocPush;
323
324 extname.nFileId = nFileId;
325 maExternalName = rName;
326}
327
328void ScRawToken::SetExternal( const OUString& rStr )
329{
330 eOp = ocExternal;
332 maExternalName = rStr;
333}
334
336{
337 switch (eType)
338 {
339 case svSingleRef:
340 return aRef.Ref1.Valid(rDoc);
341 case svDoubleRef:
342 return aRef.Valid(rDoc);
345 return true;
346 default:
347 ; // nothing
348 }
349 return false;
350}
351
353{
354#define IF_NOT_OPCODE_ERROR(o,c) SAL_WARN_IF((eOp!=o), "sc.core", #c "::ctor: OpCode " << static_cast<int>(eOp) << " lost, converted to " #o "; maybe inherit from FormulaToken instead!")
355 switch ( GetType() )
356 {
357 case svByte :
358 if (eOp == ocWhitespace)
359 return new FormulaSpaceToken( whitespace.nCount, whitespace.cChar );
360 else
361 return new FormulaByteToken( eOp, sbyte.cByte, sbyte.eInForceArray );
362 case svDouble :
364 return new FormulaDoubleToken( nValue );
365 case svString :
366 {
367 svl::SharedString aSS(sharedstring.mpData, sharedstring.mpDataIgnoreCase);
368 if (eOp == ocPush)
369 return new FormulaStringToken(std::move(aSS));
370 else
371 return new FormulaStringOpToken(eOp, std::move(aSS));
372 }
373 case svSingleRef :
374 if (eOp == ocPush)
375 return new ScSingleRefToken(rLimits, aRef.Ref1 );
376 else
377 return new ScSingleRefToken(rLimits, aRef.Ref1, eOp );
378 case svDoubleRef :
379 if (eOp == ocPush)
380 return new ScDoubleRefToken(rLimits, aRef );
381 else
382 return new ScDoubleRefToken(rLimits, aRef, eOp );
383 case svMatrix :
385 return new ScMatrixToken( pMat );
386 case svIndex :
387 if (eOp == ocTableRef)
388 return new ScTableRefToken( table.nIndex, table.eItem);
389 else
390 return new FormulaIndexToken( eOp, name.nIndex, name.nSheet);
392 {
393 svl::SharedString aTabName(maExternalName); // string not interned
394 return new ScExternalSingleRefToken(extref.nFileId, std::move(aTabName), extref.aRef.Ref1);
395 }
397 {
398 svl::SharedString aTabName(maExternalName); // string not interned
399 return new ScExternalDoubleRefToken(extref.nFileId, std::move(aTabName), extref.aRef);
400 }
401 case svExternalName:
402 {
403 svl::SharedString aName(maExternalName); // string not interned
404 return new ScExternalNameToken( extname.nFileId, std::move(aName) );
405 }
406 case svJump :
407 return new FormulaJumpToken( eOp, nJump );
408 case svExternal :
409 return new FormulaExternalToken( eOp, sbyte.cByte, maExternalName );
410 case svFAP :
411 return new FormulaFAPToken( eOp, sbyte.cByte, nullptr );
412 case svMissing :
414 return new FormulaMissingToken;
415 case svSep :
416 return new FormulaToken( svSep,eOp );
417 case svError :
418 return new FormulaErrorToken( nError );
419 case svUnknown :
420 return new FormulaUnknownToken( eOp );
421 default:
422 {
423 SAL_WARN("sc.core", "unknown ScRawToken::CreateToken() type " << int(GetType()));
424 return new FormulaUnknownToken( ocBad );
425 }
426 }
427#undef IF_NOT_OPCODE_ERROR
428}
429
430namespace {
431
432// TextEqual: if same formula entered (for optimization in sort)
433bool checkTextEqual( const ScSheetLimits& rLimits, const FormulaToken& _rToken1, const FormulaToken& _rToken2 )
434{
435 assert(
436 (_rToken1.GetType() == svSingleRef || _rToken1.GetType() == svDoubleRef)
437 && _rToken1.FormulaToken::operator ==(_rToken2));
438
439 // in relative Refs only compare relative parts
440
441 ScComplexRefData aTemp1;
442 if ( _rToken1.GetType() == svSingleRef )
443 {
444 aTemp1.Ref1 = *_rToken1.GetSingleRef();
445 aTemp1.Ref2 = aTemp1.Ref1;
446 }
447 else
448 aTemp1 = *_rToken1.GetDoubleRef();
449
450 ScComplexRefData aTemp2;
451 if ( _rToken2.GetType() == svSingleRef )
452 {
453 aTemp2.Ref1 = *_rToken2.GetSingleRef();
454 aTemp2.Ref2 = aTemp2.Ref1;
455 }
456 else
457 aTemp2 = *_rToken2.GetDoubleRef();
458
459 ScAddress aPos;
460 ScRange aRange1 = aTemp1.toAbs(rLimits, aPos), aRange2 = aTemp2.toAbs(rLimits, aPos);
461
462 // memcmp doesn't work because of the alignment byte after bFlags.
463 // After SmartRelAbs only absolute parts have to be compared.
464 return aRange1 == aRange2 && aTemp1.Ref1.FlagValue() == aTemp2.Ref1.FlagValue() && aTemp1.Ref2.FlagValue() == aTemp2.Ref2.FlagValue();
465}
466
467}
468
469#if DEBUG_FORMULA_COMPILER
470void DumpToken(formula::FormulaToken const & rToken)
471{
472 switch (rToken.GetType()) {
473 case svSingleRef:
474 cout << "-- ScSingleRefToken" << endl;
475 rToken.GetSingleRef()->Dump(1);
476 break;
477 case svDoubleRef:
478 cout << "-- ScDoubleRefToken" << endl;
479 rToken.GetDoubleRef()->Dump(1);
480 break;
481 default:
482 cout << "-- FormulaToken" << endl;
483 cout << " opcode: " << int(rToken.GetOpCode()) << " " <<
484 formula::FormulaCompiler::GetNativeSymbol( rToken.GetOpCode()).toUtf8().getStr() << endl;
485 cout << " type: " << static_cast<int>(rToken.GetType()) << endl;
486 switch (rToken.GetType())
487 {
488 case svDouble:
489 cout << " value: " << rToken.GetDouble() << endl;
490 break;
491 case svString:
492 cout << " string: "
493 << OUStringToOString(rToken.GetString().getString(), RTL_TEXTENCODING_UTF8).getStr()
494 << endl;
495 break;
496 default:
497 ;
498 }
499 break;
500 }
501}
502#endif
503
505 const ScAddress & rPos, bool bReuseDoubleRef )
506{
507
508 StackVar sv1 = rTok1.GetType();
509 // Doing a RangeOp with RefList is probably utter nonsense, but Xcl
510 // supports it, so do we.
511 if (sv1 != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList
512 && sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef)
513 return nullptr;
514 StackVar sv2 = rTok2.GetType();
515 if (sv2 != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList)
516 return nullptr;
517
518 ScTokenRef xRes;
519 bool bExternal = (sv1 == svExternalSingleRef);
520 if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
521 {
522 // Range references like Sheet1.A1:A2 are generalized and built by
523 // first creating a DoubleRef from the first SingleRef, effectively
524 // generating Sheet1.A1:A1, and then extending that with A2 as if
525 // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
526 // references apply as well.
527
528 /* Given the current structure of external references an external
529 * reference can only be extended if the second reference does not
530 * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
531 * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
532 * svSingleRef whether the sheet would be different from the one given
533 * in the external reference, we have to bail out if there is any sheet
534 * specified. NOTE: Xcl does handle external 3D references as in
535 * '[file]Sheet1:Sheet2'!A1:A2
536 *
537 * FIXME: For OOo syntax be smart and remember an external singleref
538 * encountered and if followed by ocRange and singleref, create an
539 * external singleref for the second singleref. Both could then be
540 * merged here. For Xcl syntax already parse an external range
541 * reference entirely, cumbersome. */
542
543 const ScSingleRefData& rRef2 = *rTok2.GetSingleRef();
544 if (bExternal && rRef2.IsFlag3D())
545 return nullptr;
546
547 ScComplexRefData aRef;
548 aRef.Ref1 = aRef.Ref2 = *rTok1.GetSingleRef();
549 aRef.Ref2.SetFlag3D( false);
550 aRef.Extend(rLimits, rRef2, rPos);
551 if (bExternal)
552 xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef);
553 else
554 xRes = new ScDoubleRefToken(rLimits, aRef);
555 }
556 else
557 {
558 bExternal |= (sv1 == svExternalDoubleRef);
559 const ScRefList* pRefList = nullptr;
560 if (sv1 == svDoubleRef)
561 {
562 xRes = (bReuseDoubleRef && rTok1.GetRef() == 1 ? &rTok1 : rTok1.Clone());
563 sv1 = svUnknown; // mark as handled
564 }
565 else if (sv2 == svDoubleRef)
566 {
567 xRes = (bReuseDoubleRef && rTok2.GetRef() == 1 ? &rTok2 : rTok2.Clone());
568 sv2 = svUnknown; // mark as handled
569 }
570 else if (sv1 == svRefList)
571 pRefList = rTok1.GetRefList();
572 else if (sv2 == svRefList)
573 pRefList = rTok2.GetRefList();
574 if (pRefList)
575 {
576 if (pRefList->empty())
577 return nullptr;
578 if (bExternal)
579 return nullptr; // external reference list not possible
580 xRes = new ScDoubleRefToken(rLimits, (*pRefList)[0] );
581 }
582 if (!xRes)
583 return nullptr; // shouldn't happen...
584 StackVar sv[2] = { sv1, sv2 };
585 formula::FormulaToken* pt[2] = { &rTok1, &rTok2 };
586 ScComplexRefData& rRef = *xRes->GetDoubleRef();
587 for (size_t i=0; i<2; ++i)
588 {
589 switch (sv[i])
590 {
591 case svSingleRef:
592 rRef.Extend(rLimits, *pt[i]->GetSingleRef(), rPos);
593 break;
594 case svDoubleRef:
595 rRef.Extend(rLimits, *pt[i]->GetDoubleRef(), rPos);
596 break;
597 case svRefList:
598 {
599 const ScRefList* p = pt[i]->GetRefList();
600 if (p->empty())
601 return nullptr;
602 for (const auto& rRefData : *p)
603 {
604 rRef.Extend(rLimits, rRefData, rPos);
605 }
606 }
607 break;
609 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
610 return nullptr; // no other sheets with external refs
611 else
612 rRef.Extend(rLimits, *pt[i]->GetSingleRef(), rPos);
613 break;
615 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
616 return nullptr; // no other sheets with external refs
617 else
618 rRef.Extend(rLimits, *pt[i]->GetDoubleRef(), rPos);
619 break;
620 default:
621 ; // nothing, prevent compiler warning
622 }
623 }
624 }
625 return FormulaTokenRef(xRes.get());
626}
627
628// real implementations of virtual functions
629
632bool ScSingleRefToken::TextEqual( const FormulaToken& _rToken ) const
633{
634 return FormulaToken::operator ==(_rToken) && checkTextEqual(mrSheetLimits, *this, _rToken);
635}
637{
638 return FormulaToken::operator==( r ) && aSingleRef == *r.GetSingleRef();
639}
640
647bool ScDoubleRefToken::TextEqual( const FormulaToken& _rToken ) const
648{
649 return FormulaToken::operator ==(_rToken) && checkTextEqual(mrSheetLimits, *this, _rToken);
650}
652{
653 return FormulaToken::operator==( r ) && aDoubleRef == *r.GetDoubleRef();
654}
655
660{
661 if (!FormulaToken::operator==( r ) || &aRefList != r.GetRefList())
662 return false;
663 const ScRefListToken* p = dynamic_cast<const ScRefListToken*>(&r);
664 return p && mbArrayResult == p->IsArrayResult();
665}
666
668 FormulaToken(formula::svMatrix), pMatrix(std::move(p)) {}
669
671
672const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix.get(); }
675{
676 return FormulaToken::operator==( r ) && pMatrix == r.GetMatrix();
677}
678
680 FormulaToken(formula::svMatrix), mpMatrix(rMat.mpMat)
681{
682 maRef.InitRange(rMat.mnCol1, rMat.mnRow1, rMat.mnTab1, rMat.mnCol2, rMat.mnRow2, rMat.mnTab2);
683}
684
686
688{
690}
691
693{
694 return mpMatrix.get();
695}
696
698{
699 return mpMatrix.get();
700}
701
703{
704 return &maRef;
705}
706
708{
709 return &maRef;
710}
711
713{
714 return FormulaToken::operator==(r) && mpMatrix == r.GetMatrix();
715}
716
718{
719 return new ScMatrixRangeToken(*this);
720}
721
724 mnFileId(nFileId),
725 maTabName(std::move(aTabName)),
726 maSingleRef(r)
727{
728}
729
731{
732}
733
735{
736 return mnFileId;
737}
738
740{
741 return maTabName;
742}
743
745{
746 return &maSingleRef;
747}
748
750{
751 return &maSingleRef;
752}
753
755{
756 if (!FormulaToken::operator==(r))
757 return false;
758
759 if (mnFileId != r.GetIndex())
760 return false;
761
762 if (maTabName != r.GetString())
763 return false;
764
765 return maSingleRef == *r.GetSingleRef();
766}
767
770 mnFileId(nFileId),
771 maTabName(std::move(aTabName)),
772 maDoubleRef(r)
773{
774}
775
777{
778}
779
781{
782 return mnFileId;
783}
784
786{
787 return maTabName;
788}
789
791{
792 return &maDoubleRef.Ref1;
793}
794
796{
797 return &maDoubleRef.Ref1;
798}
799
801{
802 return &maDoubleRef.Ref2;
803}
804
806{
807 return &maDoubleRef.Ref2;
808}
809
811{
812 return &maDoubleRef;
813}
814
816{
817 return &maDoubleRef;
818}
819
821{
822 if (!FormulaToken::operator==(r))
823 return false;
824
825 if (mnFileId != r.GetIndex())
826 return false;
827
828 if (maTabName != r.GetString())
829 return false;
830
831 return maDoubleRef == *r.GetDoubleRef();
832}
833
836 mnFileId(nFileId),
837 maName(std::move(aName))
838{
839}
840
842
844{
845 return mnFileId;
846}
847
849{
850 return maName;
851}
852
854{
855 if ( !FormulaToken::operator==(r) )
856 return false;
857
858 if (mnFileId != r.GetIndex())
859 return false;
860
861 return maName.getData() == r.GetString().getData();
862}
863
867 meItem(eItem)
868{
869}
870
872 FormulaToken(r),
873 mxAreaRefRPN( r.mxAreaRefRPN ? r.mxAreaRefRPN->Clone() : nullptr),
874 mnIndex(r.mnIndex),
875 meItem(r.meItem)
876{
877}
878
880
882{
883 return mnIndex;
884}
885
886void ScTableRefToken::SetIndex( sal_uInt16 n )
887{
888 mnIndex = n;
889}
890
892{
893 // Code asking for this may have to be adapted as it might assume an
894 // svIndex token would always be ocName or ocDBArea.
895 SAL_WARN("sc.core","ScTableRefToken::GetSheet - maybe adapt caller to know about TableRef?");
896 // Database range is always global.
897 return -1;
898}
899
901{
902 return meItem;
903}
904
906{
907 meItem = static_cast<ScTableRefToken::Item>(meItem | eItem);
908}
909
911{
912 mxAreaRefRPN = pToken;
913}
914
916{
917 return mxAreaRefRPN.get();
918}
919
921{
922 if ( !FormulaToken::operator==(r) )
923 return false;
924
925 if (mnIndex != r.GetIndex())
926 return false;
927
928 const ScTableRefToken* p = dynamic_cast<const ScTableRefToken*>(&r);
929 if (!p)
930 return false;
931
932 if (meItem != p->GetItem())
933 return false;
934
935 if (!mxAreaRefRPN && !p->mxAreaRefRPN)
936 ; // nothing
937 else if (!mxAreaRefRPN || !p->mxAreaRefRPN)
938 return false;
939 else if (!(*mxAreaRefRPN == *(p->mxAreaRefRPN)))
940 return false;
941
942 return true;
943}
944
945ScJumpMatrixToken::ScJumpMatrixToken(std::shared_ptr<ScJumpMatrix> p)
947 , mpJumpMatrix(std::move(p))
948{}
949
951
953{
954 return mpJumpMatrix.get();
955}
956
958{
959 return FormulaToken::operator==( r ) && mpJumpMatrix.get() == r.GetJumpMatrix();
960}
961
963{
964}
965
966double ScEmptyCellToken::GetDouble() const { return 0.0; }
967
969{
971}
972
974{
975 return FormulaToken::operator==( r ) &&
976 bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
977 bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
978}
979
981 FormulaToken(formula::svMatrixCell), xMatrix(std::move(pMat)), xUpperLeft(pUL) {}
982
984
985double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); }
986
988
990{
991 return xUpperLeft->GetString();
992}
993
995// Non-const GetMatrix() is private and unused but must be implemented to
996// satisfy vtable linkage.
998{
999 return const_cast<ScMatrix*>(xMatrix.get());
1000}
1001
1003{
1004 return FormulaToken::operator==( r ) &&
1005 xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
1006 xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
1007}
1008
1010{
1011 return new ScMatrixCellResultToken(*this);
1012}
1013
1015{
1016 xMatrix = r.xMatrix;
1018}
1019
1021 SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL ) :
1022 ScMatrixCellResultToken(pMat, pUL), nRows(nR), nCols(nC)
1023{
1025}
1026
1028 ScMatrixCellResultToken(nullptr, nullptr), nRows(nR), nCols(nC) {}
1029
1031 ScMatrixCellResultToken(r), nRows(r.nRows), nCols(r.nCols)
1032{
1034}
1035
1037
1039{
1040 const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
1041 return p && ScMatrixCellResultToken::operator==( r ) &&
1042 nCols == p->nCols && nRows == p->nRows;
1043}
1044
1046{
1047 if (xUpperLeft && xUpperLeft->GetType() == svDouble)
1048 xUpperLeft = xUpperLeft->Clone();
1049}
1050
1052{
1054
1056}
1057
1059{
1060 if (this == &r)
1061 return;
1062 const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
1063 if (p)
1065 else
1066 {
1067 OSL_ENSURE( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1068 if (r.GetType() == svMatrix)
1069 {
1070 xUpperLeft = nullptr;
1071 xMatrix = r.GetMatrix();
1072 }
1073 else
1074 {
1075 xUpperLeft = &r;
1076 xMatrix = nullptr;
1078 }
1079 }
1080}
1081
1083{
1084 switch (GetUpperLeftType())
1085 {
1086 case svDouble:
1087 const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
1088 break;
1089 case svString:
1091 break;
1092 case svUnknown:
1093 if (!xUpperLeft)
1094 {
1096 break;
1097 }
1098 [[fallthrough]];
1099 default:
1100 {
1101 OSL_FAIL("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1102 }
1103 }
1104}
1105
1107{
1108 xMatrix = nullptr;
1109 xUpperLeft = nullptr;
1110}
1111
1113 double f, const svl::SharedString & rStr, OUString aFormula, bool bEmptyDisplayedAsString ) :
1115 mfDouble( f ), maString( rStr ),
1116 maFormula(std::move( aFormula )),
1117 mbEmptyDisplayedAsString( bEmptyDisplayedAsString)
1118{
1119 // caller, make up your mind...
1120 assert( !bEmptyDisplayedAsString || (f == 0.0 && rStr.getString().isEmpty()));
1121}
1122
1123double ScHybridCellToken::GetDouble() const { return mfDouble; }
1124
1126{
1127 return maString;
1128}
1129
1131{
1132 return FormulaToken::operator==( r ) &&
1133 mfDouble == r.GetDouble() && maString == r.GetString() &&
1134 maFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
1135}
1136
1138 const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, formula::ExternalReferenceHelper* pExtRef)
1139{
1140 bool bError = FormulaTokenArray::AddFormulaToken(rToken, rSPool, pExtRef);
1141 if ( bError )
1142 {
1143 bError = false;
1144 const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode); // assuming equal values for the moment
1145
1146 const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
1147 switch ( eClass )
1148 {
1149 case uno::TypeClass_STRUCT:
1150 {
1151 uno::Type aType = rToken.Data.getValueType();
1152 if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
1153 {
1154 ScSingleRefData aSingleRef;
1155 sheet::SingleReference aApiRef;
1156 rToken.Data >>= aApiRef;
1157 lcl_SingleRefToCalc( aSingleRef, aApiRef );
1158 if ( eOpCode == ocPush )
1159 AddSingleReference( aSingleRef );
1160 else if ( eOpCode == ocColRowName )
1161 AddColRowName( aSingleRef );
1162 else
1163 bError = true;
1164 }
1165 else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
1166 {
1167 ScComplexRefData aComplRef;
1168 sheet::ComplexReference aApiRef;
1169 rToken.Data >>= aApiRef;
1170 lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
1171 lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
1172
1173 if ( eOpCode == ocPush )
1174 AddDoubleReference( aComplRef );
1175 else
1176 bError = true;
1177 }
1178 else if ( aType.equals( cppu::UnoType<sheet::NameToken>::get() ) )
1179 {
1180 sheet::NameToken aTokenData;
1181 rToken.Data >>= aTokenData;
1182 if ( eOpCode == ocName )
1183 {
1184 SAL_WARN_IF( aTokenData.Sheet < -1 || std::numeric_limits<sal_Int16>::max() < aTokenData.Sheet,
1185 "sc.core",
1186 "ScTokenArray::AddFormulaToken - NameToken.Sheet out of limits: " << aTokenData.Sheet);
1187 sal_Int16 nSheet = static_cast<sal_Int16>(aTokenData.Sheet);
1188 AddRangeName(aTokenData.Index, nSheet);
1189 }
1190 else if (eOpCode == ocDBArea)
1191 AddDBRange(aTokenData.Index);
1192 else if (eOpCode == ocTableRef)
1193 bError = true; /* TODO: implementation */
1194 else
1195 bError = true;
1196 }
1197 else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
1198 {
1199 sheet::ExternalReference aApiExtRef;
1200 if( (eOpCode == ocPush) && (rToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
1201 {
1202 sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
1203 sheet::SingleReference aApiSRef;
1204 sheet::ComplexReference aApiCRef;
1205 OUString aName;
1206 if( aApiExtRef.Reference >>= aApiSRef )
1207 {
1208 // try to resolve cache index to sheet name
1209 size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
1210 OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
1211 if( !aTabName.isEmpty() )
1212 {
1213 ScSingleRefData aSingleRef;
1214 // convert column/row settings, set sheet index to absolute
1215 lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1216 AddExternalSingleReference( nFileId, rSPool.intern( aTabName), aSingleRef );
1217 }
1218 else
1219 bError = true;
1220 }
1221 else if( aApiExtRef.Reference >>= aApiCRef )
1222 {
1223 // try to resolve cache index to sheet name.
1224 size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
1225 OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
1226 if( !aTabName.isEmpty() )
1227 {
1228 ScComplexRefData aComplRef;
1229 // convert column/row settings, set sheet index to absolute
1230 lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
1231 lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
1232 // NOTE: This assumes that cached sheets are in consecutive order!
1233 aComplRef.Ref2.SetAbsTab(
1234 aComplRef.Ref1.Tab() + static_cast<SCTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet));
1235 AddExternalDoubleReference( nFileId, rSPool.intern( aTabName), aComplRef );
1236 }
1237 else
1238 bError = true;
1239 }
1240 else if( aApiExtRef.Reference >>= aName )
1241 {
1242 if( !aName.isEmpty() )
1243 AddExternalName( nFileId, rSPool.intern( aName) );
1244 else
1245 bError = true;
1246 }
1247 else
1248 bError = true;
1249 }
1250 else
1251 bError = true;
1252 }
1253 else
1254 bError = true; // unknown struct
1255 }
1256 break;
1257 case uno::TypeClass_SEQUENCE:
1258 {
1259 if ( eOpCode != ocPush )
1260 bError = true; // not an inline array
1261 else if (!rToken.Data.getValueType().equals( cppu::UnoType<
1262 uno::Sequence< uno::Sequence< uno::Any >>>::get()))
1263 bError = true; // unexpected sequence type
1264 else
1265 {
1267 if (xMat)
1268 AddMatrix( xMat);
1269 else
1270 bError = true;
1271 }
1272 }
1273 break;
1274 default:
1275 bError = true;
1276 }
1277 }
1278 return bError;
1279}
1280
1282{
1283#if HAVE_CPP_CONSTINIT_SORTED_VECTOR
1284 constinit
1285#endif
1286 static const o3tl::sorted_vector<OpCode> aThreadedCalcDenyList({
1287 ocIndirect,
1288 ocMacro,
1289 ocOffset,
1290 ocTableOp,
1291 ocCell,
1292 ocMatch,
1293 ocInfo,
1294 ocStyle,
1296 ocDBCount,
1297 ocDBCount2,
1298 ocDBGet,
1299 ocDBMax,
1300 ocDBMin,
1302 ocDBStdDev,
1304 ocDBSum,
1305 ocDBVar,
1306 ocDBVarP,
1307 ocText,
1308 ocSheet,
1309 ocExternal,
1310 ocDde,
1313 });
1314
1315 // Don't enable threading once we decided to disable it.
1316 if (!mbThreadingEnabled)
1317 return;
1318
1319 static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
1320
1321 if (bThreadingProhibited)
1322 {
1323 mbThreadingEnabled = false;
1324 return;
1325 }
1326
1327 OpCode eOp = r.GetOpCode();
1328
1329 if (aThreadedCalcDenyList.find(eOp) != aThreadedCalcDenyList.end())
1330 {
1331 SAL_INFO("sc.core.formulagroup", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
1332 << "(" << int(eOp) << ") disables threaded calculation of formula group");
1333 mbThreadingEnabled = false;
1334 return;
1335 }
1336
1337 if (eOp != ocPush)
1338 return;
1339
1340 switch (r.GetType())
1341 {
1344 case svExternalName:
1345 case svMatrix:
1346 SAL_INFO("sc.core.formulagroup", "opcode ocPush: variable type " << StackVarEnumToString(r.GetType())
1347 << " disables threaded calculation of formula group");
1348 mbThreadingEnabled = false;
1349 return;
1350 default:
1351 break;
1352 }
1353}
1354
1356{
1359
1361 return; // It's already disabled. No more checking needed.
1362
1363 OpCode eOp = r.GetOpCode();
1364
1366 {
1367 if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly &&
1368 ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end())
1369 {
1370 SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
1371 << "(" << int(eOp) << ") disables vectorisation for formula group");
1373 mbOpenCLEnabled = false;
1374 return;
1375 }
1376
1377 // We support vectorization for the following opcodes.
1378 switch (eOp)
1379 {
1380 case ocAverage:
1381 case ocMin:
1382 case ocMinA:
1383 case ocMax:
1384 case ocMaxA:
1385 case ocSum:
1386 case ocSumIfs:
1387 case ocSumProduct:
1388 case ocCount:
1389 case ocCount2:
1390 case ocVLookup:
1391 case ocSLN:
1392 case ocIRR:
1393 case ocMIRR:
1394 case ocPMT:
1395 case ocRate:
1396 case ocRRI:
1397 case ocPpmt:
1398 case ocFisher:
1399 case ocFisherInv:
1400 case ocGamma:
1401 case ocGammaLn:
1402 case ocNotAvail:
1403 case ocGauss:
1404 case ocGeoMean:
1405 case ocHarMean:
1406 case ocSYD:
1407 case ocCorrel:
1408 case ocNegBinomVert:
1409 case ocPearson:
1410 case ocRSQ:
1411 case ocCos:
1412 case ocCosecant:
1413 case ocCosecantHyp:
1414 case ocISPMT:
1415 case ocPDuration:
1416 case ocSinHyp:
1417 case ocAbs:
1418 case ocPV:
1419 case ocSin:
1420 case ocTan:
1421 case ocTanHyp:
1422 case ocStandard:
1423 case ocWeibull:
1424 case ocMedian:
1425 case ocDDB:
1426 case ocFV:
1427 case ocVBD:
1428 case ocKurt:
1429 case ocNper:
1430 case ocNormDist:
1431 case ocArcCos:
1432 case ocSqrt:
1433 case ocArcCosHyp:
1434 case ocNPV:
1435 case ocStdNormDist:
1436 case ocNormInv:
1437 case ocSNormInv:
1438 case ocPermut:
1439 case ocPermutationA:
1440 case ocPhi:
1441 case ocIpmt:
1442 case ocConfidence:
1443 case ocIntercept:
1444 case ocDB:
1445 case ocLogInv:
1446 case ocArcCot:
1447 case ocCosHyp:
1448 case ocCritBinom:
1449 case ocArcCotHyp:
1450 case ocArcSin:
1451 case ocArcSinHyp:
1452 case ocArcTan:
1453 case ocArcTanHyp:
1454 case ocBitAnd:
1455 case ocForecast:
1456 case ocLogNormDist:
1457 case ocGammaDist:
1458 case ocLn:
1459 case ocRound:
1460 case ocCot:
1461 case ocCotHyp:
1462 case ocFDist:
1463 case ocVar:
1464 case ocChiDist:
1465 case ocPower:
1466 case ocOdd:
1467 case ocChiSqDist:
1468 case ocChiSqInv:
1469 case ocGammaInv:
1470 case ocFloor:
1471 case ocFInv:
1472 case ocFTest:
1473 case ocB:
1474 case ocBetaDist:
1475 case ocExp:
1476 case ocLog10:
1477 case ocExpDist:
1478 case ocAverageIfs:
1479 case ocCountIfs:
1480 case ocCombinA:
1481 case ocEven:
1482 case ocLog:
1483 case ocMod:
1484 case ocTrunc:
1485 case ocSkew:
1486 case ocArcTan2:
1487 case ocBitOr:
1488 case ocBitLshift:
1489 case ocBitRshift:
1490 case ocBitXor:
1491 case ocChiInv:
1492 case ocPoissonDist:
1493 case ocSumSQ:
1494 case ocSkewp:
1495 case ocBinomDist:
1496 case ocVarP:
1497 case ocCeil:
1498 case ocCombin:
1499 case ocDevSq:
1500 case ocStDev:
1501 case ocSlope:
1502 case ocSTEYX:
1503 case ocZTest:
1504 case ocPi:
1505 case ocRandom:
1506 case ocProduct:
1507 case ocHypGeomDist:
1508 case ocSumX2MY2:
1509 case ocSumX2DY2:
1510 case ocBetaInv:
1511 case ocTTest:
1512 case ocTDist:
1513 case ocTInv:
1514 case ocSumXMY2:
1515 case ocStDevP:
1516 case ocCovar:
1517 case ocAnd:
1518 case ocOr:
1519 case ocNot:
1520 case ocXor:
1521 case ocDBMax:
1522 case ocDBMin:
1523 case ocDBProduct:
1524 case ocDBAverage:
1525 case ocDBStdDev:
1526 case ocDBStdDevP:
1527 case ocDBSum:
1528 case ocDBVar:
1529 case ocDBVarP:
1530 case ocAverageIf:
1531 case ocDBCount:
1532 case ocDBCount2:
1533 case ocDeg:
1534 case ocRoundUp:
1535 case ocRoundDown:
1536 case ocInt:
1537 case ocRad:
1538 case ocCountIf:
1539 case ocIsEven:
1540 case ocIsOdd:
1541 case ocFact:
1542 case ocAverageA:
1543 case ocVarA:
1544 case ocVarPA:
1545 case ocStDevA:
1546 case ocStDevPA:
1547 case ocSecant:
1548 case ocSecantHyp:
1549 case ocSumIf:
1550 case ocNegSub:
1551 case ocAveDev:
1552 // Don't change the state.
1553 break;
1554 default:
1555 SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
1556 << "(" << int(eOp) << ") disables vectorisation for formula group");
1558 mbOpenCLEnabled = false;
1559 return;
1560 }
1561 }
1562 else if (eOp == ocPush)
1563 {
1564 // This is a stack variable. See if this is a reference.
1565
1566 switch (r.GetType())
1567 {
1568 case svByte:
1569 case svDouble:
1570 case svString:
1571 // Don't change the state.
1572 break;
1573 case svSingleRef:
1574 case svDoubleRef:
1575 // Depends on the reference state.
1577 break;
1578 case svError:
1579 case svEmptyCell:
1580 case svExternal:
1582 case svExternalName:
1584 case svFAP:
1585 case svHybridCell:
1586 case svIndex:
1587 case svJump:
1588 case svJumpMatrix:
1589 case svMatrix:
1590 case svMatrixCell:
1591 case svMissing:
1592 case svRefList:
1593 case svSep:
1594 case svUnknown:
1595 // We don't support vectorization on these.
1596 SAL_INFO("sc.opencl", "opcode ocPush: variable type " << StackVarEnumToString(r.GetType()) << " disables vectorisation for formula group");
1598 mbOpenCLEnabled = false;
1599 return;
1600 default:
1601 ;
1602 }
1603 }
1604 else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
1605 {
1606 if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly &&
1607 ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end())
1608 {
1609 SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
1610 << "(" << int(eOp) << ") disables vectorisation for formula group");
1612 mbOpenCLEnabled = false;
1613 return;
1614 }
1615 }
1616 else
1617 {
1618 // All the rest, special commands, separators, error codes, ...
1619 switch (eOp)
1620 {
1621 default:
1622 // Default is off, no vectorization.
1623 // Mentioning some specific values below to indicate why.
1624
1625 case ocName:
1626 // Named expression would need "recursive" handling of its
1627 // token array for vector state in
1628 // ScFormulaCell::InterpretFormulaGroup() and below.
1629
1630 case ocDBArea:
1631 // Certainly not a vectorization of the entire area...
1632
1633 case ocTableRef:
1634 // May result in a single cell or range reference, depending on
1635 // context.
1636
1637 case ocColRowName:
1638 // The associated reference is the name cell with which to
1639 // create the implicit intersection.
1640
1641 case ocColRowNameAuto:
1642 // Auto column/row names lead to references computed in
1643 // interpreter.
1644
1645 SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
1646 << "(" << int(eOp) << ") disables vectorisation for formula group");
1648 mbOpenCLEnabled = false;
1649 return;
1650
1651 // Known good, don't change state.
1652 case ocStop:
1653 case ocExternal:
1654 case ocOpen:
1655 case ocClose:
1656 case ocSep:
1657 case ocArrayOpen:
1658 case ocArrayRowSep:
1659 case ocArrayColSep:
1660 case ocArrayClose:
1661 case ocMissing:
1662 case ocBad:
1663 case ocSpaces:
1664 case ocWhitespace:
1665 case ocSkip:
1666 case ocPercentSign:
1667 case ocErrNull:
1668 case ocErrDivZero:
1669 case ocErrValue:
1670 case ocErrRef:
1671 case ocErrName:
1672 case ocErrNum:
1673 case ocErrNA:
1674 break;
1675 case ocIf:
1676 case ocIfError:
1677 case ocIfNA:
1678 case ocChoose:
1679 // Jump commands are now supported.
1680 break;
1681 }
1682 }
1683}
1684
1685bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
1686{
1687 bool bIs = false;
1688 if ( pCode && nLen == 1 )
1689 {
1690 const FormulaToken* pToken = pCode[0];
1691 if ( pToken )
1692 {
1693 if ( pToken->GetType() == svSingleRef )
1694 {
1695 const ScSingleRefData& rRef = *static_cast<const ScSingleRefToken*>(pToken)->GetSingleRef();
1696 rRange.aStart = rRange.aEnd = rRef.toAbs(*mxSheetLimits, rPos);
1697 bIs = !bValidOnly || mxSheetLimits->ValidAddress(rRange.aStart);
1698 }
1699 else if ( pToken->GetType() == svDoubleRef )
1700 {
1701 const ScComplexRefData& rCompl = *static_cast<const ScDoubleRefToken*>(pToken)->GetDoubleRef();
1702 const ScSingleRefData& rRef1 = rCompl.Ref1;
1703 const ScSingleRefData& rRef2 = rCompl.Ref2;
1704 rRange.aStart = rRef1.toAbs(*mxSheetLimits, rPos);
1705 rRange.aEnd = rRef2.toAbs(*mxSheetLimits, rPos);
1706 bIs = !bValidOnly || mxSheetLimits->ValidRange(rRange);
1707 }
1708 }
1709 }
1710 return bIs;
1711}
1712
1713namespace {
1714
1715// we want to compare for similar not identical formulae
1716// so we can't use actual row & column indices.
1717size_t HashSingleRef( const ScSingleRefData& rRef )
1718{
1719 size_t nVal = 0;
1720
1721 nVal += size_t(rRef.IsColRel());
1722 nVal += (size_t(rRef.IsRowRel()) << 1);
1723 nVal += (size_t(rRef.IsTabRel()) << 2);
1724
1725 return nVal;
1726}
1727
1728}
1729
1731{
1732 static const OUStringHash aHasher;
1733
1734 size_t nHash = 1;
1735 OpCode eOp;
1737 const formula::FormulaToken* p;
1738 sal_uInt16 n = std::min<sal_uInt16>(nLen, 20);
1739 for (sal_uInt16 i = 0; i < n; ++i)
1740 {
1741 p = pCode[i];
1742 eOp = p->GetOpCode();
1743 if (eOp == ocPush)
1744 {
1745 // This is stack variable. Do additional differentiation.
1746 eType = p->GetType();
1747 switch (eType)
1748 {
1749 case svByte:
1750 {
1751 // Constant value.
1752 sal_uInt8 nVal = p->GetByte();
1753 nHash += static_cast<size_t>(nVal);
1754 }
1755 break;
1756 case svDouble:
1757 {
1758 // Constant value.
1759 double fVal = p->GetDouble();
1760 nHash += std::hash<double>()(fVal);
1761 }
1762 break;
1763 case svString:
1764 {
1765 // Constant string.
1766 OUString aStr = p->GetString().getString();
1767 nHash += aHasher(aStr);
1768 }
1769 break;
1770 case svSingleRef:
1771 {
1772 size_t nVal = HashSingleRef(*p->GetSingleRef());
1773 nHash += nVal;
1774 }
1775 break;
1776 case svDoubleRef:
1777 {
1778 const ScComplexRefData& rRef = *p->GetDoubleRef();
1779 size_t nVal1 = HashSingleRef(rRef.Ref1);
1780 size_t nVal2 = HashSingleRef(rRef.Ref2);
1781 nHash += nVal1;
1782 nHash += nVal2;
1783 }
1784 break;
1785 default:
1786 // Use the opcode value in all the other cases.
1787 nHash += static_cast<size_t>(eOp);
1788 }
1789 }
1790 else
1791 // Use the opcode value in all the other cases.
1792 nHash += static_cast<size_t>(eOp);
1793
1794 nHash = (nHash << 4) - nHash;
1795 }
1796
1797 mnHashValue = nHash;
1798}
1799
1801{
1805}
1806
1808{
1809 switch (meVectorState)
1810 {
1815 return true;
1816 default:
1817 ;
1818 }
1819
1820 return false;
1821}
1822
1824{
1825 FormulaToken** p = pCode.get();
1826 FormulaToken** pEnd = p + static_cast<size_t>(nLen);
1827 for (; p != pEnd; ++p)
1828 {
1829 switch ((*p)->GetType())
1830 {
1831 case svSingleRef:
1833 {
1834 const ScSingleRefData& rRef = *(*p)->GetSingleRef();
1835 if (rRef.IsRowRel())
1836 return false;
1837 }
1838 break;
1839 case svDoubleRef:
1841 {
1842 const ScComplexRefData& rRef = *(*p)->GetDoubleRef();
1843 if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
1844 return false;
1845 }
1846 break;
1847 case svIndex:
1848 return false;
1849 default:
1850 ;
1851 }
1852 }
1853
1854 return true;
1855}
1856
1857bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const
1858{
1859 return ImplGetReference(rRange, rPos, false);
1860}
1861
1862bool ScTokenArray::IsValidReference( ScRange& rRange, const ScAddress& rPos ) const
1863{
1864 return ImplGetReference(rRange, rPos, true);
1865}
1866
1868 mxSheetLimits(&rDoc.GetSheetLimits()),
1869 mnHashValue(0)
1870{
1872}
1873
1875 mxSheetLimits(&rLimits),
1876 mnHashValue(0)
1877{
1879}
1880
1882{
1883}
1884
1886{
1887 Clear();
1888 Assign( rArr );
1889 mnHashValue = rArr.mnHashValue;
1893 return *this;
1894}
1895
1897{
1898 mxSheetLimits = std::move(rArr.mxSheetLimits);
1899 mnHashValue = rArr.mnHashValue;
1900 meVectorState = rArr.meVectorState;
1901 mbOpenCLEnabled = rArr.mbOpenCLEnabled;
1902 mbThreadingEnabled = rArr.mbThreadingEnabled;
1903 Move(std::move(rArr));
1904 return *this;
1905}
1906
1908{
1909 // We only compare the non-RPN array
1910 if ( pArr2->nLen != nLen )
1911 return false;
1912
1913 FormulaToken** ppToken1 = GetArray();
1914 FormulaToken** ppToken2 = pArr2->GetArray();
1915 for (sal_uInt16 i=0; i<nLen; i++)
1916 {
1917 if ( ppToken1[i] != ppToken2[i] &&
1918 !(*ppToken1[i] == *ppToken2[i]) )
1919 return false; // Difference
1920 }
1921 return true; // All entries are the same
1922}
1923
1925{
1926 mnHashValue = 0;
1928 FormulaTokenArray::Clear();
1929}
1930
1931std::unique_ptr<ScTokenArray> ScTokenArray::Clone() const
1932{
1933 std::unique_ptr<ScTokenArray> p(new ScTokenArray(*mxSheetLimits));
1934 p->nLen = nLen;
1935 p->nRPN = nRPN;
1936 p->nMode = nMode;
1937 p->nError = nError;
1938 p->bHyperLink = bHyperLink;
1939 p->mnHashValue = mnHashValue;
1940 p->meVectorState = meVectorState;
1941 p->mbOpenCLEnabled = mbOpenCLEnabled;
1942 p->mbThreadingEnabled = mbThreadingEnabled;
1943 p->mbFromRangeName = mbFromRangeName;
1944 p->mbShareable = mbShareable;
1945
1946 FormulaToken** pp;
1947 if( nLen )
1948 {
1949 p->pCode.reset(new FormulaToken*[ nLen ]);
1950 pp = p->pCode.get();
1951 memcpy( pp, pCode.get(), nLen * sizeof( formula::FormulaToken* ) );
1952 for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
1953 {
1954 *pp = (*pp)->Clone();
1955 (*pp)->IncRef();
1956 }
1957 }
1958 if( nRPN )
1959 {
1960 pp = p->pRPN = new FormulaToken*[ nRPN ];
1961 memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) );
1962 for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
1963 {
1964 FormulaToken* t = *pp;
1965 if( t->GetRef() > 1 )
1966 {
1967 FormulaToken** p2 = pCode.get();
1968 sal_uInt16 nIdx = 0xFFFF;
1969 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
1970 {
1971 if( *p2 == t )
1972 {
1973 nIdx = j; break;
1974 }
1975 }
1976 if( nIdx == 0xFFFF )
1977 *pp = t->Clone();
1978 else
1979 *pp = p->pCode[ nIdx ];
1980 }
1981 else
1982 *pp = t->Clone();
1983 (*pp)->IncRef();
1984 }
1985 }
1986 return p;
1987}
1988
1990{
1992 aNew.nLen = nLen;
1993 aNew.nRPN = nRPN;
1994 aNew.nMode = nMode;
1995 aNew.nError = nError;
1996 aNew.bHyperLink = bHyperLink;
1997 aNew.mnHashValue = mnHashValue;
2002 aNew.mbShareable = mbShareable;
2003
2004 FormulaToken** pp;
2005 if( nLen )
2006 {
2007 aNew.pCode.reset(new FormulaToken*[ nLen ]);
2008 pp = aNew.pCode.get();
2009 memcpy( pp, pCode.get(), nLen * sizeof( formula::FormulaToken* ) );
2010 for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
2011 {
2012 *pp = (*pp)->Clone();
2013 (*pp)->IncRef();
2014 }
2015 }
2016 if( nRPN )
2017 {
2018 pp = aNew.pRPN = new FormulaToken*[ nRPN ];
2019 memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) );
2020 for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
2021 {
2022 FormulaToken* t = *pp;
2023 if( t->GetRef() > 1 )
2024 {
2025 FormulaToken** p2 = pCode.get();
2026 sal_uInt16 nIdx = 0xFFFF;
2027 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
2028 {
2029 if( *p2 == t )
2030 {
2031 nIdx = j; break;
2032 }
2033 }
2034 if( nIdx == 0xFFFF )
2035 *pp = t->Clone();
2036 else
2037 *pp = aNew.pCode[ nIdx ];
2038 }
2039 else
2040 *pp = t->Clone();
2041 (*pp)->IncRef();
2042 }
2043 }
2044 return aNew;
2045}
2046
2048{
2049 return Add( r.CreateToken(*mxSheetLimits) );
2050}
2051
2052// Utility function to ensure that there is strict alternation of values and
2053// separators.
2054static bool
2055checkArraySep( bool & bPrevWasSep, bool bNewVal )
2056{
2057 bool bResult = (bPrevWasSep == bNewVal);
2058 bPrevWasSep = bNewVal;
2059 return bResult;
2060}
2061
2063{
2064 int nCol = -1, nRow = 0;
2065 int i, nPrevRowSep = -1, nStart = 0;
2066 bool bPrevWasSep = false; // top of stack is ocArrayClose
2067 FormulaToken* t;
2068 bool bNumeric = false; // numeric value encountered in current element
2069
2070 // (1) Iterate from the end to the start to find matrix dims
2071 // and do basic validation.
2072 for ( i = nLen ; i-- > nStart ; )
2073 {
2074 t = pCode[i];
2075 switch ( t->GetOpCode() )
2076 {
2077 case ocPush :
2078 if( checkArraySep( bPrevWasSep, false ) )
2079 {
2080 return nullptr;
2081 }
2082
2083 // no references or nested arrays
2084 if ( t->GetType() != svDouble && t->GetType() != svString )
2085 {
2086 return nullptr;
2087 }
2088 bNumeric = (t->GetType() == svDouble);
2089 break;
2090
2091 case ocMissing :
2092 case ocTrue :
2093 case ocFalse :
2094 if( checkArraySep( bPrevWasSep, false ) )
2095 {
2096 return nullptr;
2097 }
2098 bNumeric = false;
2099 break;
2100
2101 case ocArrayColSep :
2102 case ocSep :
2103 if( checkArraySep( bPrevWasSep, true ) )
2104 {
2105 return nullptr;
2106 }
2107 bNumeric = false;
2108 break;
2109
2110 case ocArrayClose :
2111 // not possible with the , but check just in case
2112 // something changes in the future
2113 if( i != (nLen-1))
2114 {
2115 return nullptr;
2116 }
2117
2118 if( checkArraySep( bPrevWasSep, true ) )
2119 {
2120 return nullptr;
2121 }
2122
2123 nPrevRowSep = i;
2124 bNumeric = false;
2125 break;
2126
2127 case ocArrayOpen :
2128 nStart = i; // stop iteration
2129 [[fallthrough]]; // to ArrayRowSep
2130
2131 case ocArrayRowSep :
2132 if( checkArraySep( bPrevWasSep, true ) )
2133 {
2134 return nullptr;
2135 }
2136
2137 if( nPrevRowSep < 0 || // missing ocArrayClose
2138 ((nPrevRowSep - i) % 2) == 1) // no complex elements
2139 {
2140 return nullptr;
2141 }
2142
2143 if( nCol < 0 )
2144 {
2145 nCol = (nPrevRowSep - i) / 2;
2146 }
2147 else if( (nPrevRowSep - i)/2 != nCol) // irregular array
2148 {
2149 return nullptr;
2150 }
2151
2152 nPrevRowSep = i;
2153 nRow++;
2154 bNumeric = false;
2155 break;
2156
2157 case ocNegSub :
2158 case ocAdd :
2159 // negation or unary plus must precede numeric value
2160 if( !bNumeric )
2161 {
2162 return nullptr;
2163 }
2164 --nPrevRowSep; // shorten this row by 1
2165 bNumeric = false; // one level only, no --42
2166 break;
2167
2168 case ocSpaces :
2169 case ocWhitespace :
2170 // ignore spaces
2171 --nPrevRowSep; // shorten this row by 1
2172 break;
2173
2174 default :
2175 // no functions or operators
2176 return nullptr;
2177 }
2178 }
2179 if( nCol <= 0 || nRow <= 0 )
2180 return nullptr;
2181
2182 int nSign = 1;
2183 ScMatrix* pArray = new ScMatrix(nCol, nRow, 0.0);
2184 for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
2185 {
2186 t = pCode[i];
2187
2188 switch ( t->GetOpCode() )
2189 {
2190 case ocPush :
2191 if ( t->GetType() == svDouble )
2192 {
2193 pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
2194 nSign = 1;
2195 }
2196 else if ( t->GetType() == svString )
2197 {
2198 pArray->PutString(t->GetString(), nCol, nRow);
2199 }
2200 break;
2201
2202 case ocMissing :
2203 pArray->PutEmpty( nCol, nRow );
2204 break;
2205
2206 case ocTrue :
2207 pArray->PutBoolean( true, nCol, nRow );
2208 break;
2209
2210 case ocFalse :
2211 pArray->PutBoolean( false, nCol, nRow );
2212 break;
2213
2214 case ocArrayColSep :
2215 case ocSep :
2216 nCol++;
2217 break;
2218
2219 case ocArrayRowSep :
2220 nRow++; nCol = 0;
2221 break;
2222
2223 case ocNegSub :
2224 nSign = -nSign;
2225 break;
2226
2227 default :
2228 break;
2229 }
2230 pCode[i] = nullptr;
2231 t->DecRef();
2232 }
2233 nLen = sal_uInt16( nStart );
2234 return AddMatrix( pArray );
2235}
2236
2238{
2239 if (!pCode || !nLen)
2240 return;
2241 sal_uInt16 nIdx = nLen;
2242
2243 // The actual types are checked in extendRangeReference().
2244 FormulaToken *p3 = PeekPrev(nIdx); // ref
2245 if (!p3)
2246 return;
2247 FormulaToken *p2 = PeekPrev(nIdx); // ocRange
2248 if (!p2 || p2->GetOpCode() != ocRange)
2249 return;
2250 FormulaToken *p1 = PeekPrev(nIdx); // ref
2251 if (!p1)
2252 return;
2253 FormulaTokenRef p = extendRangeReference( *mxSheetLimits, *p1, *p3, rPos, true);
2254 if (p)
2255 {
2256 p->IncRef();
2257 p1->DecRef();
2258 p2->DecRef();
2259 p3->DecRef();
2260 nLen -= 2;
2261 pCode[ nLen-1 ] = p.get();
2262 }
2263}
2264
2266{
2267 ScRawToken t;
2268 t.SetOpCode( e );
2269 return AddRawToken( t );
2270}
2271
2273{
2274 return Add( new ScSingleRefToken( *mxSheetLimits, rRef ) );
2275}
2276
2278{
2279 return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocMatRef ) );
2280}
2281
2283{
2284 return Add( new ScDoubleRefToken(*mxSheetLimits, rRef ) );
2285}
2286
2288{
2289 return Add( new ScMatrixToken( p ) );
2290}
2291
2292void ScTokenArray::AddRangeName( sal_uInt16 n, sal_Int16 nSheet )
2293{
2294 Add( new FormulaIndexToken( ocName, n, nSheet));
2295}
2296
2298{
2299 return Add( new FormulaIndexToken( ocDBArea, n));
2300}
2301
2303{
2304 return Add( new ScExternalNameToken(nFileId, rName) );
2305}
2306
2307void ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const svl::SharedString& rTabName,
2308 const ScSingleRefData& rRef )
2309{
2310 Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
2311}
2312
2314 const ScComplexRefData& rRef )
2315{
2316 return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
2317}
2318
2320{
2321 return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocColRowName ) );
2322}
2323
2324void ScTokenArray::AssignXMLString( const OUString &rText, const OUString &rFormulaNmsp )
2325{
2326 sal_uInt16 nTokens = 1;
2327 FormulaToken *aTokens[2];
2328
2329 aTokens[0] = new FormulaStringOpToken( ocStringXML, svl::SharedString( rText) ); // string not interned
2330 if( !rFormulaNmsp.isEmpty() )
2331 aTokens[ nTokens++ ] = new FormulaStringOpToken( ocStringXML,
2332 svl::SharedString( rFormulaNmsp) ); // string not interned
2333
2334 Assign( nTokens, aTokens );
2335}
2336
2338 const ScAddress& rPos, ScDirection eDir )
2339{
2340 SCCOL nCol = 0;
2341 SCROW nRow = 0;
2342 switch ( eDir )
2343 {
2344 case DIR_BOTTOM :
2345 if ( rPos.Row() >= mxSheetLimits->mnMaxRow )
2346 return false;
2347 nExtend = rPos.Row();
2348 nRow = nExtend + 1;
2349 break;
2350 case DIR_RIGHT :
2351 if ( rPos.Col() >= mxSheetLimits->mnMaxCol )
2352 return false;
2353 nExtend = rPos.Col();
2354 nCol = static_cast<SCCOL>(nExtend) + 1;
2355 break;
2356 case DIR_TOP :
2357 if ( rPos.Row() <= 0 )
2358 return false;
2359 nExtend = rPos.Row();
2360 nRow = nExtend - 1;
2361 break;
2362 case DIR_LEFT :
2363 if ( rPos.Col() <= 0 )
2364 return false;
2365 nExtend = rPos.Col();
2366 nCol = static_cast<SCCOL>(nExtend) - 1;
2367 break;
2368 default:
2369 OSL_FAIL( "unknown Direction" );
2370 return false;
2371 }
2372 if ( pRPN && nRPN )
2373 {
2374 FormulaToken* t = pRPN[nRPN-1];
2375 if ( t->GetType() == svByte )
2376 {
2377 sal_uInt8 nParamCount = t->GetByte();
2378 if ( nParamCount && nRPN > nParamCount )
2379 {
2380 bool bRet = false;
2381 sal_uInt16 nParam = nRPN - nParamCount - 1;
2382 for ( ; nParam < nRPN-1; nParam++ )
2383 {
2384 FormulaToken* p = pRPN[nParam];
2385 switch ( p->GetType() )
2386 {
2387 case svSingleRef :
2388 {
2389 ScSingleRefData& rRef = *p->GetSingleRef();
2390 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos);
2391 switch ( eDir )
2392 {
2393 case DIR_BOTTOM :
2394 if (aAbs.Row() == nRow && aAbs.Row() > nExtend)
2395 {
2396 nExtend = aAbs.Row();
2397 bRet = true;
2398 }
2399 break;
2400 case DIR_RIGHT :
2401 if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) > nExtend)
2402 {
2403 nExtend = aAbs.Col();
2404 bRet = true;
2405 }
2406 break;
2407 case DIR_TOP :
2408 if (aAbs.Row() == nRow && aAbs.Row() < nExtend)
2409 {
2410 nExtend = aAbs.Row();
2411 bRet = true;
2412 }
2413 break;
2414 case DIR_LEFT :
2415 if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) < nExtend)
2416 {
2417 nExtend = aAbs.Col();
2418 bRet = true;
2419 }
2420 break;
2421 }
2422 }
2423 break;
2424 case svDoubleRef :
2425 {
2426 ScComplexRefData& rRef = *p->GetDoubleRef();
2427 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos);
2428 switch ( eDir )
2429 {
2430 case DIR_BOTTOM :
2431 if (aAbs.aStart.Row() == nRow && aAbs.aEnd.Row() > nExtend)
2432 {
2433 nExtend = aAbs.aEnd.Row();
2434 bRet = true;
2435 }
2436 break;
2437 case DIR_RIGHT :
2438 if (aAbs.aStart.Col() == nCol && static_cast<SCCOLROW>(aAbs.aEnd.Col()) > nExtend)
2439 {
2440 nExtend = aAbs.aEnd.Col();
2441 bRet = true;
2442 }
2443 break;
2444 case DIR_TOP :
2445 if (aAbs.aEnd.Row() == nRow && aAbs.aStart.Row() < nExtend)
2446 {
2447 nExtend = aAbs.aStart.Row();
2448 bRet = true;
2449 }
2450 break;
2451 case DIR_LEFT :
2452 if (aAbs.aEnd.Col() == nCol && static_cast<SCCOLROW>(aAbs.aStart.Col()) < nExtend)
2453 {
2454 nExtend = aAbs.aStart.Col();
2455 bRet = true;
2456 }
2457 break;
2458 }
2459 }
2460 break;
2461 default:
2462 {
2463 // added to avoid warnings
2464 }
2465 } // switch
2466 } // for
2467 return bRet;
2468 }
2469 }
2470 }
2471 return false;
2472}
2473
2474namespace {
2475
2476void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, OUString& rTabName, sal_uInt16& rFileId)
2477{
2478 const OUString& aFileName = pOldDoc->GetFileURL();
2479 rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
2480 rTabName = pOldDoc->GetCopyTabName(nTab);
2481 if (rTabName.isEmpty())
2482 pOldDoc->GetName(nTab, rTabName);
2483}
2484
2485bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
2486{
2487 ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
2488 return rClipParam.maRanges.Contains(rRange);
2489}
2490
2491bool SkipReference(formula::FormulaToken* pToken, const ScAddress& rPos, const ScDocument& rOldDoc, bool bRangeName, bool bCheckCopyArea)
2492{
2493 ScRange aRange;
2494
2495 if (!ScRefTokenHelper::getRangeFromToken(&rOldDoc, aRange, pToken, rPos))
2496 return true;
2497
2498 if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
2499 {
2500 switch (pToken->GetType())
2501 {
2502 case svDoubleRef:
2503 {
2504 ScSingleRefData& rRef = *pToken->GetSingleRef2();
2505 if (rRef.IsColRel() || rRef.IsRowRel())
2506 return true;
2507 }
2508 [[fallthrough]];
2509 case svSingleRef:
2510 {
2511 ScSingleRefData& rRef = *pToken->GetSingleRef();
2512 if (rRef.IsColRel() || rRef.IsRowRel())
2513 return true;
2514 }
2515 break;
2516 default:
2517 break;
2518 }
2519 }
2520
2521 if (bCheckCopyArea && IsInCopyRange(aRange, &rOldDoc))
2522 return true;
2523
2524 return false;
2525}
2526
2527void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
2528{
2529 SCCOL nCols = rNewPos.Col() - rOldPos.Col();
2530 SCROW nRows = rNewPos.Row() - rOldPos.Row();
2531 SCTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
2532
2533 if (!rRef.IsColRel())
2534 rRef.IncCol(nCols);
2535
2536 if (!rRef.IsRowRel())
2537 rRef.IncRow(nRows);
2538
2539 if (!rRef.IsTabRel())
2540 rRef.IncTab(nTabs);
2541}
2542
2543}
2544
2545void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument& rOldDoc, ScDocument& rNewDoc, const ScAddress& rPos, bool bRangeName )
2546{
2547 for ( sal_uInt16 j=0; j<nLen; ++j )
2548 {
2549 switch ( pCode[j]->GetType() )
2550 {
2551 case svDoubleRef :
2552 {
2553 if (SkipReference(pCode[j], rPos, rOldDoc, bRangeName, true))
2554 continue;
2555
2556 ScComplexRefData& rRef = *pCode[j]->GetDoubleRef();
2557 ScSingleRefData& rRef2 = rRef.Ref2;
2558 ScSingleRefData& rRef1 = rRef.Ref1;
2559
2560 if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) )
2561 {
2562 OUString aTabName;
2563 sal_uInt16 nFileId;
2564 GetExternalTableData(&rOldDoc, &rNewDoc, rRef1.Tab(), aTabName, nFileId);
2565 ReplaceToken( j, new ScExternalDoubleRefToken( nFileId,
2566 rNewDoc.GetSharedStringPool().intern( aTabName), rRef), CODE_AND_RPN);
2567 // ATTENTION: rRef can't be used after this point
2568 }
2569 }
2570 break;
2571 case svSingleRef :
2572 {
2573 if (SkipReference(pCode[j], rPos, rOldDoc, bRangeName, true))
2574 continue;
2575
2576 ScSingleRefData& rRef = *pCode[j]->GetSingleRef();
2577
2578 if ( rRef.IsFlag3D() && !rRef.IsTabRel() )
2579 {
2580 OUString aTabName;
2581 sal_uInt16 nFileId;
2582 GetExternalTableData(&rOldDoc, &rNewDoc, rRef.Tab(), aTabName, nFileId);
2583 ReplaceToken( j, new ScExternalSingleRefToken( nFileId,
2584 rNewDoc.GetSharedStringPool().intern( aTabName), rRef), CODE_AND_RPN);
2585 // ATTENTION: rRef can't be used after this point
2586 }
2587 }
2588 break;
2589 default:
2590 {
2591 // added to avoid warnings
2592 }
2593 }
2594 }
2595}
2596
2597void ScTokenArray::AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos,
2598 bool bCheckCopyRange)
2599{
2600 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, true);
2601 for (size_t j=0; j<2; ++j)
2602 {
2603 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
2604 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
2605 for (; pp != pEnd; ++pp)
2606 {
2607 FormulaToken* p = aPtrs.getHandledToken(j,pp);
2608 if (!p)
2609 continue;
2610
2611 switch ( p->GetType() )
2612 {
2613 case svDoubleRef :
2614 {
2615 if (!SkipReference(p, rOldPos, rOldDoc, false, bCheckCopyRange))
2616 continue;
2617
2618 ScComplexRefData& rRef = *p->GetDoubleRef();
2619 ScSingleRefData& rRef2 = rRef.Ref2;
2620 ScSingleRefData& rRef1 = rRef.Ref1;
2621
2622 AdjustSingleRefData( rRef1, rOldPos, rNewPos );
2623 AdjustSingleRefData( rRef2, rOldPos, rNewPos );
2624 }
2625 break;
2626 case svSingleRef :
2627 {
2628 if (!SkipReference(p, rOldPos, rOldDoc, false, bCheckCopyRange))
2629 continue;
2630
2631 ScSingleRefData& rRef = *p->GetSingleRef();
2632
2633 AdjustSingleRefData( rRef, rOldPos, rNewPos );
2634 }
2635 break;
2636 default:
2637 {
2638 // added to avoid warnings
2639 }
2640 }
2641 }
2642 }
2643}
2644
2646{
2647 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false);
2648 for (size_t j=0; j<2; ++j)
2649 {
2650 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
2651 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
2652 for (; pp != pEnd; ++pp)
2653 {
2654 FormulaToken* p = aPtrs.getHandledToken(j,pp);
2655 if (!p)
2656 continue;
2657
2658 switch ( p->GetType() )
2659 {
2660 case svDoubleRef :
2661 {
2662 ScComplexRefData& rRef = *p->GetDoubleRef();
2663 ScSingleRefData& rRef2 = rRef.Ref2;
2664 ScSingleRefData& rRef1 = rRef.Ref1;
2665
2666 if (!rRef1.IsTabRel() && rRef1.Tab() == nOldTab)
2667 rRef1.SetAbsTab( nNewTab);
2668 if (!rRef2.IsTabRel() && rRef2.Tab() == nOldTab)
2669 rRef2.SetAbsTab( nNewTab);
2670 if (!rRef1.IsTabRel() && !rRef2.IsTabRel() && rRef1.Tab() > rRef2.Tab())
2671 {
2672 SCTAB nTab = rRef1.Tab();
2673 rRef1.SetAbsTab( rRef2.Tab());
2674 rRef2.SetAbsTab( nTab);
2675 }
2676 }
2677 break;
2678 case svSingleRef :
2679 {
2680 ScSingleRefData& rRef = *p->GetSingleRef();
2681
2682 if (!rRef.IsTabRel() && rRef.Tab() == nOldTab)
2683 rRef.SetAbsTab( nNewTab);
2684 }
2685 break;
2686 default:
2687 ;
2688 }
2689 }
2690 }
2691}
2692
2693bool ScTokenArray::ReferencesSheet( SCTAB nTab, SCTAB nPosTab ) const
2694{
2695 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false);
2696 for (size_t j=0; j<2; ++j)
2697 {
2698 FormulaToken* const * pp = aPtrs.maPointerRange[j].mpStart;
2699 FormulaToken* const * const pEnd = aPtrs.maPointerRange[j].mpStop;
2700 for (; pp != pEnd; ++pp)
2701 {
2702 const FormulaToken* p = aPtrs.getHandledToken(j,pp);
2703 if (!p)
2704 continue;
2705
2706 switch ( p->GetType() )
2707 {
2708 case svDoubleRef :
2709 {
2710 const ScComplexRefData& rRef = *p->GetDoubleRef();
2711 const ScSingleRefData& rRef2 = rRef.Ref2;
2712 const ScSingleRefData& rRef1 = rRef.Ref1;
2713
2714 SCTAB nTab1 = (rRef1.IsTabRel() ? rRef1.Tab() + nPosTab : rRef1.Tab());
2715 SCTAB nTab2 = (rRef2.IsTabRel() ? rRef2.Tab() + nPosTab : rRef2.Tab());
2716 if (nTab1 <= nTab && nTab <= nTab2)
2717 return true;
2718 }
2719 break;
2720 case svSingleRef :
2721 {
2722 const ScSingleRefData& rRef = *p->GetSingleRef();
2723 if (rRef.IsTabRel())
2724 {
2725 if (rRef.Tab() + nPosTab == nTab)
2726 return true;
2727 }
2728 else
2729 {
2730 if (rRef.Tab() == nTab)
2731 return true;
2732 }
2733 }
2734 break;
2735 default:
2736 ;
2737 }
2738 }
2739 }
2740 return false;
2741}
2742
2743namespace {
2744
2745ScRange getSelectedRange( const sc::RefUpdateContext& rCxt )
2746{
2747 ScRange aSelectedRange(ScAddress::INITIALIZE_INVALID);
2748 if (rCxt.mnColDelta < 0)
2749 {
2750 // Delete and shift to left.
2751 aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab());
2752 aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
2753 }
2754 else if (rCxt.mnRowDelta < 0)
2755 {
2756 // Delete and shift up.
2757 aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab());
2758 aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab());
2759 }
2760 else if (rCxt.mnTabDelta < 0)
2761 {
2762 // Deleting sheets.
2763 // TODO : Figure out what to do here.
2764 }
2765 else if (rCxt.mnColDelta > 0)
2766 {
2767 // Insert and shift to the right.
2768 aSelectedRange.aStart = rCxt.maRange.aStart;
2769 aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
2770 }
2771 else if (rCxt.mnRowDelta > 0)
2772 {
2773 // Insert and shift down.
2774 aSelectedRange.aStart = rCxt.maRange.aStart;
2775 aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta-1, rCxt.maRange.aEnd.Tab());
2776 }
2777 else if (rCxt.mnTabDelta > 0)
2778 {
2779 // Inserting sheets.
2780 // TODO : Figure out what to do here.
2781 }
2782
2783 return aSelectedRange;
2784}
2785
2786void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
2787{
2788 if (rCxt.mnColDelta < 0)
2789 rRef.SetColDeleted(true);
2790 else if (rCxt.mnRowDelta < 0)
2791 rRef.SetRowDeleted(true);
2792 else if (rCxt.mnTabDelta < 0)
2793 rRef.SetTabDeleted(true);
2794}
2795
2796void restoreDeletedRef( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
2797{
2798 if (rCxt.mnColDelta)
2799 {
2800 if (rRef.IsColDeleted())
2801 rRef.SetColDeleted(false);
2802 }
2803 else if (rCxt.mnRowDelta)
2804 {
2805 if (rRef.IsRowDeleted())
2806 rRef.SetRowDeleted(false);
2807 }
2808 else if (rCxt.mnTabDelta)
2809 {
2810 if (rRef.IsTabDeleted())
2811 rRef.SetTabDeleted(false);
2812 }
2813}
2814
2815void setRefDeleted( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt )
2816{
2817 if (rCxt.mnColDelta < 0)
2818 {
2819 rRef.Ref1.SetColDeleted(true);
2820 rRef.Ref2.SetColDeleted(true);
2821 }
2822 else if (rCxt.mnRowDelta < 0)
2823 {
2824 rRef.Ref1.SetRowDeleted(true);
2825 rRef.Ref2.SetRowDeleted(true);
2826 }
2827 else if (rCxt.mnTabDelta < 0)
2828 {
2829 rRef.Ref1.SetTabDeleted(true);
2830 rRef.Ref2.SetTabDeleted(true);
2831 }
2832}
2833
2834void restoreDeletedRef( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt )
2835{
2836 restoreDeletedRef(rRef.Ref1, rCxt);
2837 restoreDeletedRef(rRef.Ref2, rCxt);
2838}
2839
2840enum ShrinkResult
2841{
2842 UNMODIFIED,
2843 SHRUNK,
2844 STICKY
2845};
2846
2847ShrinkResult shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rDeletedRange,
2848 const ScComplexRefData& rRef )
2849{
2850 if (!rDeletedRange.Intersects(rRefRange))
2851 return UNMODIFIED;
2852
2853 if (rCxt.mnColDelta < 0)
2854 {
2855 if (rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits()))
2856 // Entire rows are not affected, columns are anchored.
2857 return STICKY;
2858
2859 // Shifting left.
2860 if (rRefRange.aStart.Row() < rDeletedRange.aStart.Row() || rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
2861 // Deleted range is only partially overlapping in vertical direction. Bail out.
2862 return UNMODIFIED;
2863
2864 if (rDeletedRange.aStart.Col() <= rRefRange.aStart.Col())
2865 {
2866 if (rRefRange.aEnd.Col() <= rDeletedRange.aEnd.Col())
2867 {
2868 // Reference is entirely deleted.
2869 rRefRange.SetInvalid();
2870 }
2871 else
2872 {
2873 // The reference range is truncated on the left.
2874 SCCOL nOffset = rDeletedRange.aStart.Col() - rRefRange.aStart.Col();
2875 SCCOL nDelta = rRefRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
2876 rRefRange.IncEndColSticky(rCxt.mrDoc, nDelta+nOffset);
2877 rRefRange.aStart.IncCol(nOffset);
2878 }
2879 }
2880 else if (rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
2881 {
2882 if (rRefRange.IsEndColSticky(rCxt.mrDoc))
2883 // Sticky end not affected.
2884 return STICKY;
2885
2886 // Reference is deleted in the middle. Move the last column
2887 // position to the left.
2888 SCCOL nDelta = rDeletedRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
2889 rRefRange.IncEndColSticky(rCxt.mrDoc, nDelta);
2890 }
2891 else
2892 {
2893 if (rRefRange.IsEndColSticky(rCxt.mrDoc))
2894 // Sticky end not affected.
2895 return STICKY;
2896
2897 // The reference range is truncated on the right.
2898 SCCOL nDelta = rDeletedRange.aStart.Col() - rRefRange.aEnd.Col() - 1;
2899 rRefRange.IncEndColSticky(rCxt.mrDoc, nDelta);
2900 }
2901 return SHRUNK;
2902 }
2903 else if (rCxt.mnRowDelta < 0)
2904 {
2905 if (rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
2906 // Entire columns are not affected, rows are anchored.
2907 return STICKY;
2908
2909 // Shifting up.
2910
2911 if (rRefRange.aStart.Col() < rDeletedRange.aStart.Col() || rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
2912 // Deleted range is only partially overlapping in horizontal direction. Bail out.
2913 return UNMODIFIED;
2914
2915 if (rDeletedRange.aStart.Row() <= rRefRange.aStart.Row())
2916 {
2917 if (rRefRange.aEnd.Row() <= rDeletedRange.aEnd.Row())
2918 {
2919 // Reference is entirely deleted.
2920 rRefRange.SetInvalid();
2921 }
2922 else
2923 {
2924 // The reference range is truncated on the top.
2925 SCROW nOffset = rDeletedRange.aStart.Row() - rRefRange.aStart.Row();
2926 SCROW nDelta = rRefRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
2927 rRefRange.IncEndRowSticky(rCxt.mrDoc, nDelta+nOffset);
2928 rRefRange.aStart.IncRow(nOffset);
2929 }
2930 }
2931 else if (rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
2932 {
2933 if (rRefRange.IsEndRowSticky(rCxt.mrDoc))
2934 // Sticky end not affected.
2935 return STICKY;
2936
2937 // Reference is deleted in the middle. Move the last row
2938 // position upward.
2939 SCROW nDelta = rDeletedRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
2940 rRefRange.IncEndRowSticky(rCxt.mrDoc, nDelta);
2941 }
2942 else
2943 {
2944 if (rRefRange.IsEndRowSticky(rCxt.mrDoc))
2945 // Sticky end not affected.
2946 return STICKY;
2947
2948 // The reference range is truncated on the bottom.
2949 SCROW nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1;
2950 rRefRange.IncEndRowSticky(rCxt.mrDoc, nDelta);
2951 }
2952 return SHRUNK;
2953 }
2954
2955 return UNMODIFIED;
2956}
2957
2958bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange,
2959 const ScComplexRefData& rRef )
2960{
2961 if (!rSelectedRange.Intersects(rRefRange))
2962 return false;
2963
2964 if (rCxt.mnColDelta > 0)
2965 {
2966 if (rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits()))
2967 // Entire rows are not affected, columns are anchored.
2968 return false;
2969
2970 // Insert and shifting right.
2971 if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
2972 // Selected range is only partially overlapping in vertical direction. Bail out.
2973 return false;
2974
2975 if (rCxt.mrDoc.IsExpandRefs())
2976 {
2977 if (rRefRange.aEnd.Col() - rRefRange.aStart.Col() < 1)
2978 // Reference must be at least two columns wide.
2979 return false;
2980 }
2981 else
2982 {
2983 if (rSelectedRange.aStart.Col() <= rRefRange.aStart.Col())
2984 // Selected range is at the left end and the edge expansion is turned off. No expansion.
2985 return false;
2986 }
2987
2988 if (rRefRange.IsEndColSticky(rCxt.mrDoc))
2989 // Sticky end not affected.
2990 return false;
2991
2992 // Move the last column position to the right.
2993 SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
2994 rRefRange.IncEndColSticky(rCxt.mrDoc, nDelta);
2995 return true;
2996 }
2997 else if (rCxt.mnRowDelta > 0)
2998 {
2999 if (rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3000 // Entire columns are not affected, rows are anchored.
3001 return false;
3002
3003 // Insert and shifting down.
3004 if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
3005 // Selected range is only partially overlapping in horizontal direction. Bail out.
3006 return false;
3007
3008 if (rCxt.mrDoc.IsExpandRefs())
3009 {
3010 if (rRefRange.aEnd.Row() - rRefRange.aStart.Row() < 1)
3011 // Reference must be at least two rows tall.
3012 return false;
3013 }
3014 else
3015 {
3016 if (rSelectedRange.aStart.Row() <= rRefRange.aStart.Row())
3017 // Selected range is at the top end and the edge expansion is turned off. No expansion.
3018 return false;
3019 }
3020
3021 if (rRefRange.IsEndRowSticky(rCxt.mrDoc))
3022 // Sticky end not affected.
3023 return false;
3024
3025 // Move the last row position down.
3026 SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
3027 rRefRange.IncEndRowSticky(rCxt.mrDoc, nDelta);
3028 return true;
3029 }
3030 return false;
3031}
3032
3037bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange,
3038 const ScComplexRefData& rRef )
3039{
3040 if (!rCxt.mrDoc.IsExpandRefs())
3041 // Edge-expansion is turned off.
3042 return false;
3043
3044 if (rSelectedRange.aStart.Tab() > rRefRange.aStart.Tab() || rRefRange.aEnd.Tab() > rSelectedRange.aEnd.Tab())
3045 // Sheet references not within selected range.
3046 return false;
3047
3048 if (rCxt.mnColDelta > 0)
3049 {
3050 if (rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits()))
3051 // Entire rows are not affected, columns are anchored.
3052 return false;
3053
3054 // Insert and shift right.
3055
3056 if (rRefRange.aEnd.Col() - rRefRange.aStart.Col() < 1)
3057 // Reference must be at least two columns wide.
3058 return false;
3059
3060 if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
3061 // Selected range is only partially overlapping in vertical direction. Bail out.
3062 return false;
3063
3064 if (rSelectedRange.aStart.Col() - rRefRange.aEnd.Col() != 1)
3065 // Selected range is not immediately adjacent. Bail out.
3066 return false;
3067
3068 if (rRefRange.IsEndColSticky(rCxt.mrDoc))
3069 // Sticky end not affected.
3070 return false;
3071
3072 // Move the last column position to the right.
3073 SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
3074 rRefRange.IncEndColSticky(rCxt.mrDoc, nDelta);
3075 return true;
3076 }
3077 else if (rCxt.mnRowDelta > 0)
3078 {
3079 if (rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3080 // Entire columns are not affected, rows are anchored.
3081 return false;
3082
3083 if (rRefRange.aEnd.Row() - rRefRange.aStart.Row() < 1)
3084 // Reference must be at least two rows tall.
3085 return false;
3086
3087 if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
3088 // Selected range is only partially overlapping in horizontal direction. Bail out.
3089 return false;
3090
3091 if (rSelectedRange.aStart.Row() - rRefRange.aEnd.Row() != 1)
3092 // Selected range is not immediately adjacent. Bail out.
3093 return false;
3094
3095 if (rRefRange.IsEndRowSticky(rCxt.mrDoc))
3096 // Sticky end not affected.
3097 return false;
3098
3099 // Move the last row position down.
3100 SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
3101 rRefRange.IncEndRowSticky(rCxt.mrDoc, nDelta);
3102 return true;
3103 }
3104
3105 return false;
3106}
3107
3108bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken )
3109{
3110 SCTAB nTab = -1;
3111 if (rToken.GetSheet() >= 0)
3112 nTab = nOldTab;
3113
3114 // Check if this named expression has been modified.
3115 return rUpdatedNames.isNameUpdated(nTab, rToken.GetIndex());
3116}
3117
3118bool isDBDataModified( const ScDocument& rDoc, const formula::FormulaToken& rToken )
3119{
3120 // Check if this DBData has been modified.
3121 const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex( rToken.GetIndex());
3122 if (!pDBData)
3123 return true;
3124
3125 return pDBData->IsModified();
3126}
3127
3128}
3129
3131{
3132 ScRange aSelectedRange = getSelectedRange(rCxt);
3133
3135 ScAddress aNewPos = rOldPos;
3136 bool bCellShifted = rCxt.maRange.Contains(rOldPos);
3137 if (bCellShifted)
3138 {
3140 if (!aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos, rCxt.mrDoc))
3141 {
3142 assert(!"can't move");
3143 }
3144 }
3145
3146 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
3147 for (size_t j=0; j<2; ++j)
3148 {
3149 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
3150 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
3151 for (; pp != pEnd; ++pp)
3152 {
3153 FormulaToken* p = aPtrs.getHandledToken(j,pp);
3154 if (!p)
3155 continue;
3156
3157 switch (p->GetType())
3158 {
3159 case svSingleRef:
3160 {
3161 ScSingleRefData& rRef = *p->GetSingleRef();
3162 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3163
3164 if (rCxt.isDeleted() && aSelectedRange.Contains(aAbs))
3165 {
3166 // This reference is in the deleted region.
3167 setRefDeleted(rRef, rCxt);
3168 aRes.mbValueChanged = true;
3169 break;
3170 }
3171
3172 if (!rCxt.isDeleted() && rRef.IsDeleted())
3173 {
3174 // Check if the token has reference to previously deleted region.
3175 ScAddress aCheckPos = rRef.toAbs(*mxSheetLimits, aNewPos);
3176 if (rCxt.maRange.Contains(aCheckPos))
3177 {
3178 restoreDeletedRef(rRef, rCxt);
3179 aRes.mbValueChanged = true;
3180 break;
3181 }
3182 }
3183
3184 if (rCxt.maRange.Contains(aAbs))
3185 {
3187 if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos, rCxt.mrDoc))
3188 aAbs = aErrorPos;
3189 aRes.mbReferenceModified = true;
3190 }
3191
3192 rRef.SetAddress(*mxSheetLimits, aAbs, aNewPos);
3193 }
3194 break;
3195 case svDoubleRef:
3196 {
3197 ScComplexRefData& rRef = *p->GetDoubleRef();
3198 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3199
3200 if (rCxt.isDeleted())
3201 {
3202 if (aSelectedRange.Contains(aAbs))
3203 {
3204 // This reference is in the deleted region.
3205 setRefDeleted(rRef, rCxt);
3206 aRes.mbValueChanged = true;
3207 break;
3208 }
3209 else if (aSelectedRange.Intersects(aAbs))
3210 {
3211 const ShrinkResult eSR = shrinkRange(rCxt, aAbs, aSelectedRange, rRef);
3212 if (eSR == SHRUNK)
3213 {
3214 // The reference range has been shrunk.
3215 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
3216 aRes.mbValueChanged = true;
3217 aRes.mbReferenceModified = true;
3218 break;
3219 }
3220 else if (eSR == STICKY)
3221 {
3222 // The reference range stays the same but a
3223 // new (empty) cell range is shifted in and
3224 // may change the calculation result.
3225 aRes.mbValueChanged = true;
3226 // Sticky when intersecting the selected
3227 // range means also that the other
3228 // conditions below are not met,
3229 // specifically not the
3230 // if (rCxt.maRange.Contains(aAbs))
3231 // that is able to update the reference,
3232 // but aSelectedRange does not intersect
3233 // with rCxt.maRange so that can't happen
3234 // and we can bail out early without
3235 // updating the reference.
3236 break;
3237 }
3238 }
3239 }
3240
3241 if (!rCxt.isDeleted() && rRef.IsDeleted())
3242 {
3243 // Check if the token has reference to previously deleted region.
3244 ScRange aCheckRange = rRef.toAbs(*mxSheetLimits, aNewPos);
3245 if (aSelectedRange.Contains(aCheckRange))
3246 {
3247 // This reference was previously in the deleted region. Restore it.
3248 restoreDeletedRef(rRef, rCxt);
3249 aRes.mbValueChanged = true;
3250 break;
3251 }
3252 }
3253
3254 if (rCxt.isInserted())
3255 {
3256 if (expandRange(rCxt, aAbs, aSelectedRange, rRef))
3257 {
3258 // The reference range has been expanded.
3259 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
3260 aRes.mbValueChanged = true;
3261 aRes.mbReferenceModified = true;
3262 break;
3263 }
3264
3265 if (expandRangeByEdge(rCxt, aAbs, aSelectedRange, rRef))
3266 {
3267 // The reference range has been expanded on the edge.
3268 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
3269 aRes.mbValueChanged = true;
3270 aRes.mbReferenceModified = true;
3271 break;
3272 }
3273 }
3274
3275 if (rCxt.maRange.Contains(aAbs))
3276 {
3277 // We shift either by column or by row, not both,
3278 // so moving the reference has only to be done in
3279 // the non-sticky case.
3280 if ((rCxt.mnRowDelta && rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3281 || (rCxt.mnColDelta && rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits())))
3282 {
3283 // In entire col/row, values are shifted within
3284 // the reference, which affects all positional
3285 // results like in MATCH or matrix positions.
3286 aRes.mbValueChanged = true;
3287 }
3288 else
3289 {
3290 ScRange aErrorRange( ScAddress::UNINITIALIZED );
3291 if (!aAbs.MoveSticky(rCxt.mrDoc, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange))
3292 aAbs = aErrorRange;
3293 aRes.mbReferenceModified = true;
3294 }
3295 }
3296 else if (rCxt.maRange.Intersects(aAbs))
3297 {
3298 // Part of the referenced range is being shifted. This
3299 // will change the values of the range.
3300 aRes.mbValueChanged = true;
3301 }
3302
3303 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
3304 }
3305 break;
3307 {
3308 // For external reference, just reset the reference with
3309 // respect to the new cell position.
3310 ScSingleRefData& rRef = *p->GetSingleRef();
3311 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3312 rRef.SetAddress(*mxSheetLimits, aAbs, aNewPos);
3313 }
3314 break;
3316 {
3317 // Same as above.
3318 ScComplexRefData& rRef = *p->GetDoubleRef();
3319 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3320 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
3321 }
3322 break;
3323 default:
3324 ;
3325 }
3326
3327 // For ocTableRef p is the inner token of *pp, so have a separate
3328 // condition here.
3329 if ((*pp)->GetType() == svIndex)
3330 {
3331 switch ((*pp)->GetOpCode())
3332 {
3333 case ocName:
3334 {
3335 SCTAB nOldTab = (*pp)->GetSheet();
3336 if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
3337 aRes.mbNameModified = true;
3338 if (rCxt.mnTabDelta &&
3339 rCxt.maRange.aStart.Tab() <= nOldTab && nOldTab <= rCxt.maRange.aEnd.Tab())
3340 {
3341 aRes.mbNameModified = true;
3342 (*pp)->SetSheet( nOldTab + rCxt.mnTabDelta);
3343 }
3344 }
3345 break;
3346 case ocDBArea:
3347 case ocTableRef:
3348 if (isDBDataModified(rCxt.mrDoc, **pp))
3349 aRes.mbNameModified = true;
3350 break;
3351 default:
3352 ; // nothing
3353 }
3354 }
3355 }
3356 }
3357
3358 return aRes;
3359}
3360
3362 const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos )
3363{
3365
3366 if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta)
3367 // The cell hasn't moved at all.
3368 return aRes;
3369
3370 // When moving, the range in the context is the destination range. We need
3371 // to use the old range prior to the move for hit analysis.
3372 ScRange aOldRange = rCxt.maRange;
3373 ScRange aErrorMoveRange( ScAddress::UNINITIALIZED );
3374 if (!aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorMoveRange, rCxt.mrDoc))
3375 {
3376 assert(!"can't move");
3377 }
3378
3379 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
3380 for (size_t j=0; j<2; ++j)
3381 {
3382 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
3383 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
3384 for (; pp != pEnd; ++pp)
3385 {
3386 FormulaToken* p = aPtrs.getHandledToken(j,pp);
3387 if (!p)
3388 continue;
3389
3390 switch (p->GetType())
3391 {
3392 case svSingleRef:
3393 {
3394 ScSingleRefData& rRef = *p->GetSingleRef();
3395 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3396
3397 // Do not update the reference in transposed case (cut paste transposed).
3398 // The reference will be updated in UpdateTranspose().
3399 // Additionally, do not update the references from cells within the moved
3400 // range as they lead to #REF! errors here. These #REF! cannot by fixed
3401 // later in UpdateTranspose().
3402 if (rCxt.mbTransposed && (aOldRange.Contains(rOldPos) || aOldRange.Contains(aAbs)))
3403 break;
3404
3405 if (aOldRange.Contains(aAbs))
3406 {
3408 if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos, rCxt.mrDoc))
3409 aAbs = aErrorPos;
3410 aRes.mbReferenceModified = true;
3411 }
3412 else if (rCxt.maRange.Contains(aAbs))
3413 {
3414 // Referenced cell has been overwritten.
3415 aRes.mbValueChanged = true;
3416 }
3417
3418 rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos);
3419 rRef.SetFlag3D(rRef.IsFlag3D() || !rRef.IsTabRel() || aAbs.Tab() != rNewPos.Tab());
3420 }
3421 break;
3422 case svDoubleRef:
3423 {
3424 ScComplexRefData& rRef = *p->GetDoubleRef();
3425 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3426
3427 // Do not update the reference in transposed case (cut paste transposed).
3428 // The reference will be updated in UpdateTranspose().
3429 // Additionally, do not update the references from cells within the moved
3430 // range as they lead to #REF! errors here. These #REF! cannot by fixed
3431 // later in UpdateTranspose().
3432 if (rCxt.mbTransposed && (aOldRange.Contains(rOldPos) || aOldRange.Contains(aAbs)))
3433 break;
3434
3435 if (aOldRange.Contains(aAbs))
3436 {
3437 ScRange aErrorRange( ScAddress::UNINITIALIZED );
3438 if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange, rCxt.mrDoc))
3439 aAbs = aErrorRange;
3440 aRes.mbReferenceModified = true;
3441 }
3442 else if (rCxt.maRange.Contains(aAbs))
3443 {
3444 // Referenced range has been entirely overwritten.
3445 aRes.mbValueChanged = true;
3446 }
3447
3448 rRef.SetRange(*mxSheetLimits, aAbs, rNewPos);
3449 bool b1, b2;
3450 if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
3451 {
3452 // More than one sheet referenced => has to have
3453 // both 3D flags.
3454 b1 = b2 = true;
3455 }
3456 else
3457 {
3458 // Keep given 3D flag even for relative sheet
3459 // reference to same sheet.
3460 // Absolute sheet reference => set 3D flag.
3461 // Reference to another sheet => set 3D flag.
3462 b1 = rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel() || rNewPos.Tab() != aAbs.aStart.Tab();
3463 b2 = rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel() || rNewPos.Tab() != aAbs.aEnd.Tab();
3464 // End part has 3D flag => start part must have it too.
3465 if (b2)
3466 b1 = true;
3467 // End part sheet reference is identical to start
3468 // part sheet reference and end part sheet
3469 // reference was not explicitly given => clear end
3470 // part 3D flag.
3471 if (b1 && b2 && rRef.Ref1.IsTabRel() == rRef.Ref2.IsTabRel() && !rRef.Ref2.IsFlag3D())
3472 b2 = false;
3473 }
3474 rRef.Ref1.SetFlag3D(b1);
3475 rRef.Ref2.SetFlag3D(b2);
3476 }
3477 break;
3479 {
3480 ScSingleRefData& rRef = *p->GetSingleRef();
3481 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3482 rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos);
3483 }
3484 break;
3486 {
3487 ScComplexRefData& rRef = *p->GetDoubleRef();
3488 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
3489 rRef.SetRange(*mxSheetLimits, aAbs, rNewPos);
3490 }
3491 break;
3492 default:
3493 ;
3494 }
3495
3496 // For ocTableRef p is the inner token of *pp, so have a separate
3497 // condition here.
3498 if ((*pp)->GetType() == svIndex)
3499 {
3500 switch ((*pp)->GetOpCode())
3501 {
3502 case ocName:
3503 {
3504 SCTAB nOldTab = (*pp)->GetSheet();
3505 if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
3506 aRes.mbNameModified = true;
3507 }
3508 break;
3509 case ocDBArea:
3510 case ocTableRef:
3511 if (isDBDataModified(rCxt.mrDoc, **pp))
3512 aRes.mbNameModified = true;
3513 break;
3514 default:
3515 ; // nothing
3516 }
3517 }
3518 }
3519 }
3520
3521 return aRes;
3522}
3523
3525 const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType& rColMap )
3526{
3527 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
3528 for (size_t j=0; j<2; ++j)
3529 {
3530 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
3531 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
3532 for (; pp != pEnd; ++pp)
3533 {
3534 FormulaToken* p = aPtrs.getHandledToken(j,pp);
3535 if (!p)
3536 continue;
3537
3538 switch (p->GetType())
3539 {
3540 case svSingleRef:
3541 {
3542 ScSingleRefData& rRef = *p->GetSingleRef();
3543 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos);
3544
3545 if (aAbs.Tab() == nTab && nRow1 <= aAbs.Row() && aAbs.Row() <= nRow2)
3546 {
3547 // Inside reordered row range.
3549 if (it != rColMap.end())
3550 {
3551 // This column is reordered.
3552 SCCOL nNewCol = it->second;
3553 aAbs.SetCol(nNewCol);
3554 rRef.SetAddress(*mxSheetLimits, aAbs, rPos);
3555 }
3556 }
3557 }
3558 break;
3559 case svDoubleRef:
3560 {
3561 ScComplexRefData& rRef = *p->GetDoubleRef();
3562 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos);
3563
3564 if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
3565 // Must be a single-sheet reference.
3566 break;
3567
3568 if (aAbs.aStart.Col() != aAbs.aEnd.Col())
3569 // Whole range must fit in a single column.
3570 break;
3571
3572 if (aAbs.aStart.Tab() == nTab && nRow1 <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= nRow2)
3573 {
3574 // Inside reordered row range.
3576 if (it != rColMap.end())
3577 {
3578 // This column is reordered.
3579 SCCOL nNewCol = it->second;
3580 aAbs.aStart.SetCol(nNewCol);
3581 aAbs.aEnd.SetCol(nNewCol);
3582 rRef.SetRange(*mxSheetLimits, aAbs, rPos);
3583 }
3584 }
3585 }
3586 break;
3587 default:
3588 ;
3589 }
3590 }
3591 }
3592}
3593
3594void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType& rRowMap )
3595{
3596 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
3597 for (size_t j=0; j<2; ++j)
3598 {
3599 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
3600 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
3601 for (; pp != pEnd; ++pp)
3602 {
3603 FormulaToken* p = aPtrs.getHandledToken(j,pp);
3604 if (!p)
3605 continue;
3606
3607 switch (p->GetType())
3608 {
3609 case svSingleRef:
3610 {
3611 ScSingleRefData& rRef = *p->GetSingleRef();
3612 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos);
3613
3614 if (aAbs.Tab() == nTab && nCol1 <= aAbs.Col() && aAbs.Col() <= nCol2)
3615 {
3616 // Inside reordered column range.
3618 if (it != rRowMap.end())
3619 {
3620 // This column is reordered.
3621 SCROW nNewRow = it->second;
3622 aAbs.SetRow(nNewRow);
3623 rRef.SetAddress(*mxSheetLimits, aAbs, rPos);
3624 }
3625 }
3626 }
3627 break;
3628 case svDoubleRef:
3629 {
3630 ScComplexRefData& rRef = *p->GetDoubleRef();
3631 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos);
3632
3633 if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
3634 // Must be a single-sheet reference.
3635 break;
3636
3637 if (aAbs.aStart.Row() != aAbs.aEnd.Row())
3638 // Whole range must fit in a single row.
3639 break;
3640
3641 if (aAbs.aStart.Tab() == nTab && nCol1 <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= nCol2)
3642 {
3643 // Inside reordered column range.
3645 if (it != rRowMap.end())
3646 {
3647 // This row is reordered.
3648 SCROW nNewRow = it->second;
3649 aAbs.aStart.SetRow(nNewRow);
3650 aAbs.aEnd.SetRow(nNewRow);
3651 rRef.SetRange(*mxSheetLimits, aAbs, rPos);
3652 }
3653 }
3654 }
3655 break;
3656 default:
3657 ;
3658 }
3659 }
3660 }
3661}
3662
3663namespace {
3664
3665bool adjustSingleRefInName(
3666 ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos,
3667 ScComplexRefData* pEndOfComplex )
3668{
3669 ScAddress aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3670
3671 if (aAbs.Tab() < rCxt.maRange.aStart.Tab() || rCxt.maRange.aEnd.Tab() < aAbs.Tab())
3672 {
3673 // This references a sheet that has not shifted. Don't change it.
3674 return false;
3675 }
3676
3677 if (!rCxt.maRange.Contains(rRef.toAbs(rCxt.mrDoc, rPos)))
3678 return false;
3679
3680 bool bChanged = false;
3681
3682 if (rCxt.mnColDelta && !rRef.IsColRel())
3683 {
3684 // Adjust absolute column reference.
3685 if (rCxt.maRange.aStart.Col() <= rRef.Col() && rRef.Col() <= rCxt.maRange.aEnd.Col())
3686 {
3687 if (pEndOfComplex)
3688 {
3689 if (pEndOfComplex->IncEndColSticky(rCxt.mrDoc, rCxt.mnColDelta, rPos))
3690 bChanged = true;
3691 }
3692 else
3693 {
3694 rRef.IncCol(rCxt.mnColDelta);
3695 bChanged = true;
3696 }
3697 }
3698 }
3699
3700 if (rCxt.mnRowDelta && !rRef.IsRowRel())
3701 {
3702 // Adjust absolute row reference.
3703 if (rCxt.maRange.aStart.Row() <= rRef.Row() && rRef.Row() <= rCxt.maRange.aEnd.Row())
3704 {
3705 if (pEndOfComplex)
3706 {
3707 if (pEndOfComplex->IncEndRowSticky(rCxt.mrDoc, rCxt.mnRowDelta, rPos))
3708 bChanged = true;
3709 }
3710 else
3711 {
3712 rRef.IncRow(rCxt.mnRowDelta);
3713 bChanged = true;
3714 }
3715 }
3716 }
3717
3718 if (!rRef.IsTabRel() && rCxt.mnTabDelta)
3719 {
3720 // Sheet range has already been checked above.
3721 rRef.IncTab(rCxt.mnTabDelta);
3722 bChanged = true;
3723 }
3724
3725 return bChanged;
3726}
3727
3728bool adjustDoubleRefInName(
3729 ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3730{
3731 bool bRefChanged = false;
3732 if (rCxt.mrDoc.IsExpandRefs())
3733 {
3734 if (rCxt.mnRowDelta > 0 && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel())
3735 {
3736 ScRange aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3737 // Expand only if at least two rows tall.
3738 if (aAbs.aStart.Row() < aAbs.aEnd.Row())
3739 {
3740 // Check and see if we should expand the range at the top.
3741 ScRange aSelectedRange = getSelectedRange(rCxt);
3742 if (aSelectedRange.Intersects(aAbs))
3743 {
3744 // Selection intersects the referenced range. Only expand the
3745 // bottom position.
3746 rRef.IncEndRowSticky(rCxt.mrDoc, rCxt.mnRowDelta, rPos);
3747 return true;
3748 }
3749 }
3750 }
3751 if (rCxt.mnColDelta > 0 && !rRef.Ref1.IsColRel() && !rRef.Ref2.IsColRel())
3752 {
3753 ScRange aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3754 // Expand only if at least two columns wide.
3755 if (aAbs.aStart.Col() < aAbs.aEnd.Col())
3756 {
3757 // Check and see if we should expand the range at the left.
3758 ScRange aSelectedRange = getSelectedRange(rCxt);
3759 if (aSelectedRange.Intersects(aAbs))
3760 {
3761 // Selection intersects the referenced range. Only expand the
3762 // right position.
3763 rRef.IncEndColSticky(rCxt.mrDoc, rCxt.mnColDelta, rPos);
3764 return true;
3765 }
3766 }
3767 }
3768 }
3769
3770 if ((rCxt.mnRowDelta && rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3771 || (rCxt.mnColDelta && rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits())))
3772 {
3773 sc::RefUpdateContext aCxt( rCxt.mrDoc);
3774 // We only need a few parameters of RefUpdateContext.
3775 aCxt.maRange = rCxt.maRange;
3776 aCxt.mnColDelta = rCxt.mnColDelta;
3777 aCxt.mnRowDelta = rCxt.mnRowDelta;
3778 aCxt.mnTabDelta = rCxt.mnTabDelta;
3779
3780 // References to entire col/row are not to be adjusted in the other axis.
3781 if (aCxt.mnRowDelta && rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3782 aCxt.mnRowDelta = 0;
3783 if (aCxt.mnColDelta && rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits()))
3784 aCxt.mnColDelta = 0;
3785 if (!aCxt.mnColDelta && !aCxt.mnRowDelta && !aCxt.mnTabDelta)
3786 // early bailout
3787 return bRefChanged;
3788
3789 // Ref2 before Ref1 for sticky ends.
3790 if (adjustSingleRefInName(rRef.Ref2, aCxt, rPos, &rRef))
3791 bRefChanged = true;
3792
3793 if (adjustSingleRefInName(rRef.Ref1, aCxt, rPos, nullptr))
3794 bRefChanged = true;
3795 }
3796 else
3797 {
3798 // Ref2 before Ref1 for sticky ends.
3799 if (adjustSingleRefInName(rRef.Ref2, rCxt, rPos, &rRef))
3800 bRefChanged = true;
3801
3802 if (adjustSingleRefInName(rRef.Ref1, rCxt, rPos, nullptr))
3803 bRefChanged = true;
3804 }
3805
3806 return bRefChanged;
3807}
3808
3809}
3810
3812 const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
3813{
3814 if (rCxt.meMode == URM_MOVE)
3815 return AdjustReferenceInMovedName(rCxt, rPos);
3816
3818
3819 if (rCxt.meMode == URM_COPY)
3820 // Copying cells does not modify named expressions.
3821 return aRes;
3822
3823 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
3824 for (size_t j=0; j<2; ++j)
3825 {
3826 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
3827 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
3828 for (; pp != pEnd; ++pp)
3829 {
3830 FormulaToken* p = aPtrs.getHandledToken(j,pp);
3831 if (!p)
3832 continue;
3833
3834 switch (p->GetType())
3835 {
3836 case svSingleRef:
3837 {
3838 ScSingleRefData& rRef = *p->GetSingleRef();
3839 if (rCxt.mnRowDelta < 0)
3840 {
3841 // row(s) deleted.
3842
3843 if (rRef.IsRowRel())
3844 // Don't modify relative references in names.
3845 break;
3846
3847 ScAddress aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3848
3849 if (aAbs.Col() < rCxt.maRange.aStart.Col() || rCxt.maRange.aEnd.Col() < aAbs.Col())
3850 // column of the reference is not in the deleted column range.
3851 break;
3852
3853 if (aAbs.Tab() > rCxt.maRange.aEnd.Tab() || aAbs.Tab() < rCxt.maRange.aStart.Tab())
3854 // wrong tables
3855 break;
3856
3857 const SCROW nDelStartRow = rCxt.maRange.aStart.Row() + rCxt.mnRowDelta;
3858 const SCROW nDelEndRow = nDelStartRow - rCxt.mnRowDelta - 1;
3859
3860 if (nDelStartRow <= aAbs.Row() && aAbs.Row() <= nDelEndRow)
3861 {
3862 // This reference is deleted.
3863 rRef.SetRowDeleted(true);
3864 aRes.mbReferenceModified = true;
3865 break;
3866 }
3867 }
3868 else if (rCxt.mnColDelta < 0)
3869 {
3870 // column(s) deleted.
3871
3872 if (rRef.IsColRel())
3873 // Don't modify relative references in names.
3874 break;
3875
3876 ScAddress aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3877
3878 if (aAbs.Row() < rCxt.maRange.aStart.Row() || rCxt.maRange.aEnd.Row() < aAbs.Row())
3879 // row of the reference is not in the deleted row range.
3880 break;
3881
3882 if (aAbs.Tab() > rCxt.maRange.aEnd.Tab() || aAbs.Tab() < rCxt.maRange.aStart.Tab())
3883 // wrong tables
3884 break;
3885
3886 const SCCOL nDelStartCol = rCxt.maRange.aStart.Col() + rCxt.mnColDelta;
3887 const SCCOL nDelEndCol = nDelStartCol - rCxt.mnColDelta - 1;
3888
3889 if (nDelStartCol <= aAbs.Col() && aAbs.Col() <= nDelEndCol)
3890 {
3891 // This reference is deleted.
3892 rRef.SetColDeleted(true);
3893 aRes.mbReferenceModified = true;
3894 break;
3895 }
3896 }
3897
3898 if (adjustSingleRefInName(rRef, rCxt, rPos, nullptr))
3899 aRes.mbReferenceModified = true;
3900 }
3901 break;
3902 case svDoubleRef:
3903 {
3904 ScComplexRefData& rRef = *p->GetDoubleRef();
3905 ScRange aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
3906
3907 if (aAbs.aStart.Tab() > rCxt.maRange.aEnd.Tab() || aAbs.aEnd.Tab() < rCxt.maRange.aStart.Tab())
3908 // Sheet references not affected.
3909 break;
3910
3911 if (rCxt.maRange.Contains(aAbs))
3912 {
3913 // This range is entirely within the shifted region.
3914 if (adjustDoubleRefInName(rRef, rCxt, rPos))
3915 aRes.mbReferenceModified = true;
3916 }
3917 else if (rCxt.mnRowDelta < 0)
3918 {
3919 // row(s) deleted.
3920
3921 if (rRef.IsEntireCol(rCxt.mrDoc.GetSheetLimits()))
3922 // Rows of entire columns are not affected.
3923 break;
3924
3925 if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
3926 // Don't modify relative references in names.
3927 break;
3928
3929 if (aAbs.aStart.Col() < rCxt.maRange.aStart.Col() || rCxt.maRange.aEnd.Col() < aAbs.aEnd.Col())
3930 // column range of the reference is not entirely in the deleted column range.
3931 break;
3932
3933 ScRange aDeleted = rCxt.maRange;
3934 aDeleted.aStart.IncRow(rCxt.mnRowDelta);
3935 aDeleted.aEnd.SetRow(aDeleted.aStart.Row()-rCxt.mnRowDelta-1);
3936
3937 if (aAbs.aEnd.Row() < aDeleted.aStart.Row() || aDeleted.aEnd.Row() < aAbs.aStart.Row())
3938 // reference range doesn't intersect with the deleted range.
3939 break;
3940
3941 if (aDeleted.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= aDeleted.aEnd.Row())
3942 {
3943 // This reference is entirely deleted.
3944 rRef.Ref1.SetRowDeleted(true);
3945 rRef.Ref2.SetRowDeleted(true);
3946 aRes.mbReferenceModified = true;
3947 break;
3948 }
3949
3950 if (aAbs.aStart.Row() < aDeleted.aStart.Row())
3951 {
3952 if (!aAbs.IsEndRowSticky(rCxt.mrDoc))
3953 {
3954 if (aDeleted.aEnd.Row() < aAbs.aEnd.Row())
3955 // Deleted in the middle. Make the reference shorter.
3956 rRef.Ref2.IncRow(rCxt.mnRowDelta);
3957 else
3958 // Deleted at tail end. Cut off the lower part.
3959 rRef.Ref2.SetAbsRow(aDeleted.aStart.Row()-1);
3960 }
3961 }
3962 else
3963 {
3964 // Deleted at the top. Cut the top off and shift up.
3965 rRef.Ref1.SetAbsRow(aDeleted.aEnd.Row()+1);
3966 rRef.Ref1.IncRow(rCxt.mnRowDelta);
3967 if (!aAbs.IsEndRowSticky(rCxt.mrDoc))
3968 rRef.Ref2.IncRow(rCxt.mnRowDelta);
3969 }
3970
3971 aRes.mbReferenceModified = true;
3972 }
3973 else if (rCxt.mnColDelta < 0)
3974 {
3975 // column(s) deleted.
3976
3977 if (rRef.IsEntireRow(rCxt.mrDoc.GetSheetLimits()))
3978 // Rows of entire rows are not affected.
3979 break;
3980
3981 if (rRef.Ref1.IsColRel() || rRef.Ref2.IsColRel())
3982 // Don't modify relative references in names.
3983 break;
3984
3985 if (aAbs.aStart.Row() < rCxt.maRange.aStart.Row() || rCxt.maRange.aEnd.Row() < aAbs.aEnd.Row())
3986 // row range of the reference is not entirely in the deleted row range.
3987 break;
3988
3989 ScRange aDeleted = rCxt.maRange;
3990 aDeleted.aStart.IncCol(rCxt.mnColDelta);
3991 aDeleted.aEnd.SetCol(aDeleted.aStart.Col()-rCxt.mnColDelta-1);
3992
3993 if (aAbs.aEnd.Col() < aDeleted.aStart.Col() || aDeleted.aEnd.Col() < aAbs.aStart.Col())
3994 // reference range doesn't intersect with the deleted range.
3995 break;
3996
3997 if (aDeleted.aStart.Col() <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= aDeleted.aEnd.Col())
3998 {
3999 // This reference is entirely deleted.
4000 rRef.Ref1.SetColDeleted(true);
4001 rRef.Ref2.SetColDeleted(true);
4002 aRes.mbReferenceModified = true;
4003 break;
4004 }
4005
4006 if (aAbs.aStart.Col() < aDeleted.aStart.Col())
4007 {
4008 if (!aAbs.IsEndColSticky(rCxt.mrDoc))
4009 {
4010 if (aDeleted.aEnd.Col() < aAbs.aEnd.Col())
4011 // Deleted in the middle. Make the reference shorter.
4012 rRef.Ref2.IncCol(rCxt.mnColDelta);
4013 else
4014 // Deleted at tail end. Cut off the right part.
4015 rRef.Ref2.SetAbsCol(aDeleted.aStart.Col()-1);
4016 }
4017 }
4018 else
4019 {
4020 // Deleted at the left. Cut the left off and shift left.
4021 rRef.Ref1.SetAbsCol(aDeleted.aEnd.Col()+1);
4022 rRef.Ref1.IncCol(rCxt.mnColDelta);
4023 if (!aAbs.IsEndColSticky(rCxt.mrDoc))
4024 rRef.Ref2.IncCol(rCxt.mnColDelta);
4025 }
4026
4027 aRes.mbReferenceModified = true;
4028 }
4029 else if (rCxt.maRange.Intersects(aAbs))
4030 {
4031 if (rCxt.mnColDelta && rCxt.maRange.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= rCxt.maRange.aEnd.Row())
4032 {
4033 if (adjustDoubleRefInName(rRef, rCxt, rPos))
4034 aRes.mbReferenceModified = true;
4035 }
4036 if (rCxt.mnRowDelta && rCxt.maRange.aStart.Col() <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= rCxt.maRange.aEnd.Col())
4037 {
4038 if (adjustDoubleRefInName(rRef, rCxt, rPos))
4039 aRes.mbReferenceModified = true;
4040 }
4041 }
4042 else if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
4043 {
4044 // Check if we could expand range reference by the bottom
4045 // edge. For named expressions, we only expand absolute
4046 // references. Reference must be at least two rows
4047 // tall.
4048 if (!rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel() &&
4049 aAbs.aStart.Row() < aAbs.aEnd.Row() &&
4050 aAbs.aEnd.Row()+1 == rCxt.maRange.aStart.Row())
4051 {
4052 // Expand by the bottom edge.
4053 rRef.Ref2.IncRow(rCxt.mnRowDelta);
4054 aRes.mbReferenceModified = true;
4055 }
4056 }
4057 else if (rCxt.mnColDelta > 0 && rCxt.mrDoc.IsExpandRefs())
4058 {
4059 // Check if we could expand range reference by the right
4060 // edge. For named expressions, we only expand absolute
4061 // references. Reference must be at least two
4062 // columns wide.
4063 if (!rRef.Ref1.IsColRel() && !rRef.Ref2.IsColRel() &&
4064 aAbs.aStart.Col() < aAbs.aEnd.Col() &&
4065 aAbs.aEnd.Col()+1 == rCxt.maRange.aStart.Col())
4066 {
4067 // Expand by the right edge.
4068 rRef.Ref2.IncCol(rCxt.mnColDelta);
4069 aRes.mbReferenceModified = true;
4070 }
4071 }
4072 }
4073 break;
4074 default:
4075 ;
4076 }
4077 }
4078 }
4079
4080 return aRes;
4081}
4082
4084{
4085 // When moving, the range is the destination range.
4086 ScRange aOldRange = rCxt.maRange;
4087 ScRange aErrorMoveRange( ScAddress::UNINITIALIZED );
4088 if (!aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorMoveRange, rCxt.mrDoc))
4089 {
4090 assert(!"can't move");
4091 }
4092
4093 // In a named expression, we'll move the reference only when the reference
4094 // is entirely absolute.
4095
4097
4098 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4099 for (size_t j=0; j<2; ++j)
4100 {
4101 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4102 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4103 for (; pp != pEnd; ++pp)
4104 {
4105 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4106 if (!p)
4107 continue;
4108
4109 switch (p->GetType())
4110 {
4111 case svSingleRef:
4112 {
4113 ScSingleRefData& rRef = *p->GetSingleRef();
4114 if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel())
4115 continue;
4116
4117 ScAddress aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
4118
4119 // Do not update the reference in transposed case (cut paste transposed).
4120 // The reference will be updated in UpdateTranspose().
4121 if (rCxt.mbTransposed && aOldRange.Contains(aAbs))
4122 break;
4123
4124 if (aOldRange.Contains(aAbs))
4125 {
4127 if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos, rCxt.mrDoc))
4128 aAbs = aErrorPos;
4129 aRes.mbReferenceModified = true;
4130 }
4131
4132 rRef.SetAddress(rCxt.mrDoc.GetSheetLimits(), aAbs, rPos);
4133 }
4134 break;
4135 case svDoubleRef:
4136 {
4137 ScComplexRefData& rRef = *p->GetDoubleRef();
4138 if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() ||
4139 rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel())
4140 continue;
4141
4142 ScRange aAbs = rRef.toAbs(rCxt.mrDoc, rPos);
4143
4144 // Do not update the reference in transposed case (cut paste transposed).
4145 // The reference will be updated in UpdateTranspose().
4146 if (rCxt.mbTransposed && aOldRange.Contains(aAbs))
4147 break;
4148
4149 if (aOldRange.Contains(aAbs))
4150 {
4151 ScRange aErrorRange( ScAddress::UNINITIALIZED );
4152 if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange, rCxt.mrDoc))
4153 aAbs = aErrorRange;
4154 aRes.mbReferenceModified = true;
4155 }
4156
4157 rRef.SetRange(rCxt.mrDoc.GetSheetLimits(), aAbs, rPos);
4158 }
4159 break;
4160 default:
4161 ;
4162 }
4163 }
4164 }
4165
4166 return aRes;
4167}
4168
4169namespace {
4170
4171bool adjustSingleRefOnDeletedTab( const ScSheetLimits& rLimits, ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
4172{
4173 ScAddress aAbs = rRef.toAbs(rLimits, rOldPos);
4174 if (nDelPos <= aAbs.Tab() && aAbs.Tab() < nDelPos + nSheets)
4175 {
4176 rRef.SetTabDeleted(true);
4177 return true;
4178 }
4179
4180 if (nDelPos < aAbs.Tab())
4181 {
4182 // Reference sheet needs to be adjusted.
4183 aAbs.IncTab(-1*nSheets);
4184 rRef.SetAddress(rLimits, aAbs, rNewPos);
4185 return true;
4186 }
4187 else if (rOldPos.Tab() != rNewPos.Tab())
4188 {
4189 // Cell itself has moved.
4190 rRef.SetAddress(rLimits, aAbs, rNewPos);
4191 return true;
4192 }
4193
4194 return false;
4195}
4196
4197bool adjustSingleRefOnInsertedTab( const ScSheetLimits& rLimits, ScSingleRefData& rRef, SCTAB nInsPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
4198{
4199 ScAddress aAbs = rRef.toAbs(rLimits, rOldPos);
4200 if (nInsPos <= aAbs.Tab())
4201 {
4202 // Reference sheet needs to be adjusted.
4203 aAbs.IncTab(nSheets);
4204 rRef.SetAddress(rLimits, aAbs, rNewPos);
4205 return true;
4206 }
4207 else if (rOldPos.Tab() != rNewPos.Tab())
4208 {
4209 // Cell itself has moved.
4210 rRef.SetAddress(rLimits, aAbs, rNewPos);
4211 return true;
4212 }
4213
4214 return false;
4215}
4216
4217bool adjustDoubleRefOnDeleteTab(const ScSheetLimits& rLimits, ScComplexRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos)
4218{
4219 ScSingleRefData& rRef1 = rRef.Ref1;
4220 ScSingleRefData& rRef2 = rRef.Ref2;
4221 ScAddress aStartPos = rRef1.toAbs(rLimits, rOldPos);
4222 ScAddress aEndPos = rRef2.toAbs(rLimits, rOldPos);
4223 bool bMoreThanOneTab = aStartPos.Tab() != aEndPos.Tab();
4224 bool bModified = false;
4225 if (bMoreThanOneTab && aStartPos.Tab() == nDelPos && nDelPos + nSheets <= aEndPos.Tab())
4226 {
4227 if (rRef1.IsTabRel() && aStartPos.Tab() < rOldPos.Tab())
4228 {
4229 rRef1.IncTab(nSheets);
4230 bModified = true;
4231 }
4232 }
4233 else
4234 {
4235 bModified = adjustSingleRefOnDeletedTab(rLimits, rRef1, nDelPos, nSheets, rOldPos, rNewPos);
4236 }
4237
4238 if (bMoreThanOneTab && aEndPos.Tab() == nDelPos && aStartPos.Tab() <= nDelPos - nSheets)
4239 {
4240 if (!rRef2.IsTabRel() || rOldPos.Tab() < aEndPos.Tab())
4241 {
4242 rRef2.IncTab(-nSheets);
4243 bModified = true;
4244 }
4245 }
4246 else
4247 {
4248 bModified |= adjustSingleRefOnDeletedTab(rLimits, rRef2, nDelPos, nSheets, rOldPos, rNewPos);
4249 }
4250 return bModified;
4251}
4252
4253}
4254
4256{
4258 ScAddress aNewPos = rOldPos;
4259 ScRangeUpdater::UpdateDeleteTab( aNewPos, rCxt);
4260
4261 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4262 for (size_t j=0; j<2; ++j)
4263 {
4264 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4265 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4266 for (; pp != pEnd; ++pp)
4267 {
4268 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4269 if (!p)
4270 continue;
4271
4272 switch (p->GetType())
4273 {
4274 case svSingleRef:
4275 {
4276 ScSingleRefData& rRef = *p->GetSingleRef();
4277 if (adjustSingleRefOnDeletedTab(*mxSheetLimits, rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
4278 aRes.mbReferenceModified = true;
4279 }
4280 break;
4281 case svDoubleRef:
4282 {
4283 ScComplexRefData& rRef = *p->GetDoubleRef();
4284 aRes.mbReferenceModified |= adjustDoubleRefOnDeleteTab(*mxSheetLimits, rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos);
4285 }
4286 break;
4287 default:
4288 ;
4289 }
4290
4291 // For ocTableRef p is the inner token of *pp, so have a separate
4292 // condition here.
4293 if ((*pp)->GetType() == svIndex)
4294 {
4295 switch ((*pp)->GetOpCode())
4296 {
4297 case ocName:
4298 {
4299 SCTAB nOldTab = (*pp)->GetSheet();
4300 if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
4301 aRes.mbNameModified = true;
4302 if (rCxt.mnDeletePos <= nOldTab)
4303 {
4304 aRes.mbNameModified = true;
4305 if (rCxt.mnDeletePos + rCxt.mnSheets <= nOldTab)
4306 (*pp)->SetSheet( nOldTab - rCxt.mnSheets);
4307 else
4308 // Would point to a deleted sheet. Invalidate.
4309 (*pp)->SetSheet( SCTAB_MAX);
4310 }
4311 }
4312 break;
4313 case ocDBArea:
4314 case ocTableRef:
4315 if (isDBDataModified(rCxt.mrDoc, **pp))
4316 aRes.mbNameModified = true;
4317 break;
4318 default:
4319 ; // nothing
4320 }
4321 }
4322 }
4323 }
4324 return aRes;
4325}
4326
4328{
4330 ScAddress aNewPos = rOldPos;
4331 if (rCxt.mnInsertPos <= rOldPos.Tab())
4332 aNewPos.IncTab(rCxt.mnSheets);
4333
4334 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4335 for (size_t j=0; j<2; ++j)
4336 {
4337 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4338 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4339 for (; pp != pEnd; ++pp)
4340 {
4341 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4342 if (!p)
4343 continue;
4344
4345 switch (p->GetType())
4346 {
4347 case svSingleRef:
4348 {
4349 ScSingleRefData& rRef = *p->GetSingleRef();
4350 if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
4351 aRes.mbReferenceModified = true;
4352 }
4353 break;
4354 case svDoubleRef:
4355 {
4356 ScComplexRefData& rRef = *p->GetDoubleRef();
4357 if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef.Ref1, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
4358 aRes.mbReferenceModified = true;
4359 if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef.Ref2, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
4360 aRes.mbReferenceModified = true;
4361 }
4362 break;
4363 default:
4364 ;
4365 }
4366
4367 // For ocTableRef p is the inner token of *pp, so have a separate
4368 // condition here.
4369 if ((*pp)->GetType() == svIndex)
4370 {
4371 switch ((*pp)->GetOpCode())
4372 {
4373 case ocName:
4374 {
4375 SCTAB nOldTab = (*pp)->GetSheet();
4376 if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
4377 aRes.mbNameModified = true;
4378 if (rCxt.mnInsertPos <= nOldTab)
4379 {
4380 aRes.mbNameModified = true;
4381 (*pp)->SetSheet( nOldTab + rCxt.mnSheets);
4382 }
4383 }
4384 break;
4385 case ocDBArea:
4386 case ocTableRef:
4387 if (isDBDataModified(rCxt.mrDoc, **pp))
4388 aRes.mbNameModified = true;
4389 break;
4390 default:
4391 ; // nothing
4392 }
4393 }
4394 }
4395 }
4396 return aRes;
4397}
4398
4399namespace {
4400
4401bool adjustTabOnMove( ScAddress& rPos, const sc::RefUpdateMoveTabContext& rCxt )
4402{
4403 SCTAB nNewTab = rCxt.getNewTab(rPos.Tab());
4404 if (nNewTab == rPos.Tab())
4405 return false;
4406
4407 rPos.SetTab(nNewTab);
4408 return true;
4409}
4410
4411}
4412
4414{
4416 if (rCxt.mnOldPos == rCxt.mnNewPos)
4417 return aRes;
4418
4419 ScAddress aNewPos = rOldPos;
4420 if (adjustTabOnMove(aNewPos, rCxt))
4421 aRes.mbReferenceModified = true;
4422
4423 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4424 for (size_t j=0; j<2; ++j)
4425 {
4426 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4427 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4428 for (; pp != pEnd; ++pp)
4429 {
4430 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4431 if (!p)
4432 continue;
4433
4434 switch (p->GetType())
4435 {
4436 case svSingleRef:
4437 {
4438 ScSingleRefData& rRef = *p->GetSingleRef();
4439 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4440 if (adjustTabOnMove(aAbs, rCxt))
4441 aRes.mbReferenceModified = true;
4442 rRef.SetAddress(*mxSheetLimits, aAbs, aNewPos);
4443 }
4444 break;
4445 case svDoubleRef:
4446 {
4447 ScComplexRefData& rRef = *p->GetDoubleRef();
4448 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4449 if (adjustTabOnMove(aAbs.aStart, rCxt))
4450 aRes.mbReferenceModified = true;
4451 if (adjustTabOnMove(aAbs.aEnd, rCxt))
4452 aRes.mbReferenceModified = true;
4453 rRef.SetRange(*mxSheetLimits, aAbs, aNewPos);
4454 }
4455 break;
4456 default:
4457 ;
4458 }
4459
4460 // For ocTableRef p is the inner token of *pp, so have a separate
4461 // condition here.
4462 if ((*pp)->GetType() == svIndex)
4463 {
4464 switch ((*pp)->GetOpCode())
4465 {
4466 case ocName:
4467 {
4468 SCTAB nOldTab = (*pp)->GetSheet();
4469 if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
4470 aRes.mbNameModified = true;
4471 SCTAB nNewTab = rCxt.getNewTab( nOldTab);
4472 if (nNewTab != nOldTab)
4473 {
4474 aRes.mbNameModified = true;
4475 (*pp)->SetSheet( nNewTab);
4476 }
4477 }
4478 break;
4479 case ocDBArea:
4480 case ocTableRef:
4481 if (isDBDataModified(rCxt.mrDoc, **pp))
4482 aRes.mbNameModified = true;
4483 break;
4484 default:
4485 ; // nothing
4486 }
4487 }
4488 }
4489 }
4490
4491 return aRes;
4492}
4493
4495{
4496 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4497 for (size_t j=0; j<2; ++j)
4498 {
4499 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4500 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4501 for (; pp != pEnd; ++pp)
4502 {
4503 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4504 if (!p)
4505 continue;
4506
4507 switch (p->GetType())
4508 {
4509 case svSingleRef:
4511 {
4512 ScSingleRefData& rRef = *p->GetSingleRef();
4513 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4514 rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos);
4515 }
4516 break;
4517 case svDoubleRef:
4519 {
4520 ScComplexRefData& rRef = *p->GetDoubleRef();
4521 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4522 rRef.SetRange(*mxSheetLimits, aAbs, rNewPos);
4523 }
4524 break;
4525 default:
4526 ;
4527 }
4528 }
4529 }
4530}
4531
4533{
4534 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4535 for (size_t j=0; j<2; ++j)
4536 {
4537 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4538 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4539 for (; pp != pEnd; ++pp)
4540 {
4541 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4542 if (!p)
4543 continue;
4544
4545 bool bAdjust = false;
4546 switch (p->GetType())
4547 {
4549 bAdjust = true; // always
4550 [[fallthrough]];
4551 case svSingleRef:
4552 {
4553 ScSingleRefData& rRef = *p->GetSingleRef();
4554 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4555 if (!bAdjust)
4556 bAdjust = (aAbs.Tab() != rOldPos.Tab());
4557 if (bAdjust)
4558 rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos);
4559 }
4560 break;
4562 bAdjust = true; // always
4563 [[fallthrough]];
4564 case svDoubleRef:
4565 {
4566 ScComplexRefData& rRef = *p->GetDoubleRef();
4567 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos);
4568 if (!bAdjust)
4569 bAdjust = (rOldPos.Tab() < aAbs.aStart.Tab() || aAbs.aEnd.Tab() < rOldPos.Tab());
4570 if (bAdjust)
4571 rRef.SetRange(*mxSheetLimits, aAbs, rNewPos);
4572 }
4573 break;
4574 default:
4575 ;
4576 }
4577 }
4578 }
4579}
4580
4582{
4583 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false);
4584 for (size_t j=0; j<2; ++j)
4585 {
4586 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4587 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4588 for (; pp != pEnd; ++pp)
4589 {
4590 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4591 if (!p)
4592 continue;
4593
4594 switch (p->GetType())
4595 {
4596 case svDoubleRef:
4597 {
4598 ScComplexRefData& rRef = *p->GetDoubleRef();
4599 rRef.PutInOrder( rNewPos);
4600 }
4601 break;
4602 default:
4603 ;
4604 }
4605 }
4606 }
4607}
4608
4609namespace {
4610
4611void clearTabDeletedFlag( const ScSheetLimits& rLimits, ScSingleRefData& rRef, const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
4612{
4613 if (!rRef.IsTabDeleted())
4614 return;
4615
4616 ScAddress aAbs = rRef.toAbs(rLimits, rPos);
4617 if (nStartTab <= aAbs.Tab() && aAbs.Tab() <= nEndTab)
4618 rRef.SetTabDeleted(false);
4619}
4620
4621}
4622
4623void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
4624{
4625 if (nEndTab < nStartTab)
4626 return;
4627
4628 FormulaToken** p = pCode.get();
4629 FormulaToken** pEnd = p + static_cast<size_t>(nLen);
4630 for (; p != pEnd; ++p)
4631 {
4632 switch ((*p)->GetType())
4633 {
4634 case svSingleRef:
4635 {
4636 formula::FormulaToken* pToken = *p;
4637 ScSingleRefData& rRef = *pToken->GetSingleRef();
4638 clearTabDeletedFlag(*mxSheetLimits, rRef, rPos, nStartTab, nEndTab);
4639 }
4640 break;
4641 case svDoubleRef:
4642 {
4643 formula::FormulaToken* pToken = *p;
4644 ScComplexRefData& rRef = *pToken->GetDoubleRef();
4645 clearTabDeletedFlag(*mxSheetLimits, rRef.Ref1, rPos, nStartTab, nEndTab);
4646 clearTabDeletedFlag(*mxSheetLimits, rRef.Ref2, rPos, nStartTab, nEndTab);
4647 }
4648 break;
4649 default:
4650 ;
4651 }
4652 }
4653}
4654
4655namespace {
4656
4657void checkBounds(
4658 const ScSheetLimits& rLimits,
4659 const ScAddress& rPos, SCROW nGroupLen, const ScRange& rCheckRange,
4660 const ScSingleRefData& rRef, std::vector<SCROW>& rBounds, const ScRange* pDeletedRange )
4661{
4662 if (!rRef.IsRowRel())
4663 return;
4664
4665 ScRange aAbs(rRef.toAbs(rLimits, rPos));
4666 aAbs.aEnd.IncRow(nGroupLen-1);
4667 if (!rCheckRange.Intersects(aAbs) && (!pDeletedRange || !pDeletedRange->Intersects(aAbs)))
4668 return;
4669
4670 // Get the boundary row positions.
4671 if (aAbs.aEnd.Row() < rCheckRange.aStart.Row() && (!pDeletedRange || aAbs.aEnd.Row() < pDeletedRange->aStart.Row()))
4672 // No intersections.
4673 return;
4674
4675 // rCheckRange may be a virtual non-existent row being shifted in.
4676 if (aAbs.aStart.Row() <= rCheckRange.aStart.Row() && rCheckRange.aStart.Row() < rLimits.GetMaxRowCount())
4677 {
4678 // +-+ <---- top
4679 // | |
4680 // +--+-+--+ <---- boundary row position
4681 // | | | |
4682 // | |
4683 // +-------+
4684
4685 // Add offset from the reference top to the cell position.
4686 SCROW nOffset = rCheckRange.aStart.Row() - aAbs.aStart.Row();
4687 rBounds.push_back(rPos.Row()+nOffset);
4688 }
4689 // Same for deleted range.
4690 if (pDeletedRange && aAbs.aStart.Row() <= pDeletedRange->aStart.Row())
4691 {
4692 SCROW nOffset = pDeletedRange->aStart.Row() - aAbs.aStart.Row();
4693 SCROW nRow = rPos.Row() + nOffset;
4694 // Unlike for rCheckRange, for pDeletedRange nRow can be anywhere>=0.
4695 if (rLimits.ValidRow(nRow))
4696 rBounds.push_back(nRow);
4697 }
4698
4699 if (aAbs.aEnd.Row() >= rCheckRange.aEnd.Row())
4700 {
4701 // only check for end range
4702
4703 // +-------+
4704 // | |
4705 // | | | |
4706 // +--+-+--+ <---- boundary row position
4707 // | |
4708 // +-+
4709
4710 // Ditto.
4711 SCROW nOffset = rCheckRange.aEnd.Row() + 1 - aAbs.aStart.Row();
4712 rBounds.push_back(rPos.Row()+nOffset);
4713 }
4714 // Same for deleted range.
4715 if (pDeletedRange && aAbs.aEnd.Row() >= pDeletedRange->aEnd.Row())
4716 {
4717 SCROW nOffset = pDeletedRange->aEnd.Row() + 1 - aAbs.aStart.Row();
4718 SCROW nRow = rPos.Row() + nOffset;
4719 // Unlike for rCheckRange, for pDeletedRange nRow can be ~anywhere.
4720 if (rLimits.ValidRow(nRow))
4721 rBounds.push_back(nRow);
4722 }
4723}
4724
4725void checkBounds(
4726 const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen,
4727 const ScSingleRefData& rRef, std::vector<SCROW>& rBounds)
4728{
4729 if (!rRef.IsRowRel())
4730 return;
4731
4732 ScRange aDeletedRange( ScAddress::UNINITIALIZED );
4733 const ScRange* pDeletedRange = nullptr;
4734
4735 ScRange aCheckRange = rCxt.maRange;
4736 if (rCxt.meMode == URM_MOVE)
4737 {
4738 // Check bounds against the old range prior to the move.
4739 ScRange aErrorRange( ScAddress::UNINITIALIZED );
4740 if (!aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorRange, rCxt.mrDoc))
4741 {
4742 assert(!"can't move");
4743 }
4744
4745 // Check bounds also against the range moved into.
4746 pDeletedRange = &rCxt.maRange;
4747 }
4748 else if (rCxt.meMode == URM_INSDEL &&
4749 ((rCxt.mnColDelta < 0 && rCxt.maRange.aStart.Col() > 0) ||
4750 (rCxt.mnRowDelta < 0 && rCxt.maRange.aStart.Row() > 0)))
4751 {
4752 // Check bounds also against deleted range where cells are shifted
4753 // into and references need to be invalidated.
4754 aDeletedRange = getSelectedRange( rCxt);
4755 pDeletedRange = &aDeletedRange;
4756 }
4757
4758 checkBounds(rCxt.mrDoc.GetSheetLimits(), rPos, nGroupLen, aCheckRange, rRef, rBounds, pDeletedRange);
4759}
4760
4761}
4762
4764 const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
4765{
4766 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4767 for (size_t j=0; j<2; ++j)
4768 {
4769 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4770 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4771 for (; pp != pEnd; ++pp)
4772 {
4773 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4774 if (!p)
4775 continue;
4776
4777 switch (p->GetType())
4778 {
4779 case svSingleRef:
4780 {
4781 checkBounds(rCxt, rPos, nGroupLen, *p->GetSingleRef(), rBounds);
4782 }
4783 break;
4784 case svDoubleRef:
4785 {
4786 const ScComplexRefData& rRef = *p->GetDoubleRef();
4787 checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
4788 checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
4789 }
4790 break;
4791 default:
4792 ;
4793 }
4794 }
4795 }
4796}
4797
4799 const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector<SCROW>& rBounds ) const
4800{
4801 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4802 for (size_t j=0; j<2; ++j)
4803 {
4804 FormulaToken** pp = aPtrs.maPointerRange[j].mpStart;
4805 FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
4806 for (; pp != pEnd; ++pp)
4807 {
4808 FormulaToken* p = aPtrs.getHandledToken(j,pp);
4809 if (!p)
4810 continue;
4811
4812 switch (p->GetType())
4813 {
4814 case svSingleRef:
4815 {
4816 const ScSingleRefData& rRef = *p->GetSingleRef();
4817 checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef, rBounds, nullptr);
4818 }
4819 break;
4820 case svDoubleRef:
4821 {
4822 const ScComplexRefData& rRef = *p->GetDoubleRef();
4823 checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr);
4824 checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr);
4825 }
4826 break;
4827 default:
4828 ;
4829 }
4830 }
4831 }
4832}
4833
4835 const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
4836{
4837 const SCROW nInsRow = rCxt.maRange.aStart.Row();
4838 TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN);
4839 for (size_t j=0; j<2; ++j)
4840 {
4841 FormulaToken* const * pp = aPtrs.maPointerRange[j].mpStart;
4842 const FormulaToken* const * pEnd = aPtrs.maPointerRange[j].mpStop;
4843 for (; pp != pEnd; ++pp)
4844 {
4845 const FormulaToken* p = aPtrs.getHandledToken(j,pp);
4846 if (!p)
4847 continue;
4848
4849 switch (p->GetType())
4850 {
4851 case svDoubleRef:
4852 {
4853 const ScComplexRefData& rRef = *p->GetDoubleRef();
4854 bool bStartRowRelative = rRef.Ref1.IsRowRel();
4855 bool bEndRowRelative = rRef.Ref2.IsRowRel();
4856
4857 // For absolute references nothing needs to be done, they stay
4858 // the same for all and if to be expanded the group will be
4859 // adjusted later.
4860 if (!bStartRowRelative && !bEndRowRelative)
4861 break; // switch
4862
4863 ScRange aAbsStart(rRef.toAbs(*mxSheetLimits, rPos));
4864 ScAddress aPos(rPos);
4865 aPos.IncRow(nGroupLen);
4866 ScRange aAbsEnd(rRef.toAbs(*mxSheetLimits, aPos));
4867 // References must be at least two rows to be expandable.
4868 if ((aAbsStart.aEnd.Row() - aAbsStart.aStart.Row() < 1) &&
4869 (aAbsEnd.aEnd.Row() - aAbsEnd.aStart.Row() < 1))
4870 break; // switch
4871
4872 // Only need to process if an edge may be touching the
4873 // insertion row anywhere within the run of the group.
4874 if (!((aAbsStart.aStart.Row() <= nInsRow && nInsRow <= aAbsEnd.aStart.Row()) ||
4875 (aAbsStart.aEnd.Row() <= nInsRow && nInsRow <= aAbsEnd.aEnd.Row())))
4876 break; // switch
4877
4878 SCROW nStartRow = aAbsStart.aStart.Row();
4879 SCROW nEndRow = aAbsStart.aEnd.Row();
4880 // Position on first relevant range.
4881 SCROW nOffset = 0;
4882 if (nEndRow + 1 < nInsRow)
4883 {
4884 if (bEndRowRelative)
4885 {
4886 nOffset = nInsRow - nEndRow - 1;
4887 nEndRow += nOffset;
4888 if (bStartRowRelative)
4889 nStartRow += nOffset;
4890 }
4891 else // bStartRowRelative==true
4892 {
4893 nOffset = nInsRow - nStartRow;
4894 nStartRow += nOffset;
4895 // Start is overtaking End, swap.
4896 bStartRowRelative = false;
4897 bEndRowRelative = true;
4898 }
4899 }
4900 for (SCROW i = nOffset; i < nGroupLen; ++i)
4901 {
4902 bool bSplit = (nStartRow == nInsRow || nEndRow + 1 == nInsRow);
4903 if (bSplit)
4904 rBounds.push_back( rPos.Row() + i);
4905
4906 if (bEndRowRelative)
4907 ++nEndRow;
4908 if (bStartRowRelative)
4909 {
4910 ++nStartRow;
4911 if (!bEndRowRelative && nStartRow == nEndRow)
4912 {
4913 // Start is overtaking End, swap.
4914 bStartRowRelative = false;
4915 bEndRowRelative = true;
4916 }
4917 }
4918 if (nInsRow < nStartRow || (!bStartRowRelative && nInsRow <= nEndRow))
4919 {
4920 if (bSplit && (++i < nGroupLen))
4921 rBounds.push_back( rPos.Row() + i);
4922 break; // for, out of range now
4923 }
4924 }
4925 }
4926 break;
4927 default:
4928 ;
4929 }
4930 }
4931 }
4932}
4933
4934namespace {
4935
4936void appendDouble( const sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, double fVal )
4937{
4938 if (rCxt.mxOpCodeMap->isEnglish())
4939 {
4940 rtl::math::doubleToUStringBuffer(
4941 rBuf, fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
4942 }
4943 else
4944 {
4945 SvtSysLocale aSysLocale;
4946 rtl::math::doubleToUStringBuffer(
4947 rBuf, fVal,
4948 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
4949 aSysLocale.GetLocaleData().getNumDecimalSep()[0], true);
4950 }
4951}
4952
4953void appendString( OUStringBuffer& rBuf, const OUString& rStr )
4954{
4955 rBuf.append('"');
4956 rBuf.append(rStr.replaceAll("\"", "\"\""));
4957 rBuf.append('"');
4958}
4959
4960void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken,
4961 const ScAddress& rPos, bool bFromRangeName )
4962{
4963 if (rToken.IsExternalRef())
4964 {
4965 size_t nFileId = rToken.GetIndex();
4966 OUString aTabName = rToken.GetString().getString();
4967 if (nFileId >= rCxt.maExternalFileNames.size())
4968 // out of bound
4969 return;
4970
4971 OUString aFileName = rCxt.maExternalFileNames[nFileId];
4972
4973 switch (rToken.GetType())
4974 {
4975 case svExternalName:
4976 rBuf.append(rCxt.mpRefConv->makeExternalNameStr(nFileId, aFileName, aTabName));
4977 break;
4980 rLimits, rBuf, rPos, nFileId, aFileName, aTabName, *rToken.GetSingleRef());
4981 break;
4983 {
4984 sc::TokenStringContext::IndexNamesMapType::const_iterator it =
4985 rCxt.maExternalCachedTabNames.find(nFileId);
4986
4987 if (it == rCxt.maExternalCachedTabNames.end())
4988 return;
4989
4991 rLimits, rBuf, rPos, nFileId, aFileName, it->second, aTabName,
4992 *rToken.GetDoubleRef());
4993 }
4994 break;
4995 default:
4996 // warning, not error, otherwise we may end up with a never
4997 // ending message box loop if this was the cursor cell to be redrawn.
4998 OSL_FAIL("appendTokenByType: unknown type of ocExternalRef");
4999 }
5000 return;
5001 }
5002
5003 OpCode eOp = rToken.GetOpCode();
5004 switch (rToken.GetType())
5005 {
5006 case svDouble:
5007 appendDouble(rCxt, rBuf, rToken.GetDouble());
5008 break;
5009 case svString:
5010 {
5011 OUString aStr = rToken.GetString().getString();
5012 if (eOp == ocBad || eOp == ocStringXML)
5013 {
5014 rBuf.append(aStr);
5015 return;
5016 }
5017
5018 appendString(rBuf, aStr);
5019 }
5020 break;
5021 case svSingleRef:
5022 {
5023 if (rCxt.mpRefConv)
5024 {
5025 const ScSingleRefData& rRef = *rToken.GetSingleRef();
5026 ScComplexRefData aRef;
5027 aRef.Ref1 = rRef;
5028 aRef.Ref2 = rRef;
5029 rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true,
5030 bFromRangeName);
5031 }
5032 else
5033 rBuf.append(rCxt.maErrRef);
5034 }
5035 break;
5036 case svDoubleRef:
5037 {
5038 if (rCxt.mpRefConv)
5039 {
5040 const ScComplexRefData& rRef = *rToken.GetDoubleRef();
5041 rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false,
5042 bFromRangeName);
5043 }
5044 else
5045 rBuf.append(rCxt.maErrRef);
5046 }
5047 break;
5048 case svMatrix:
5049 {
5050 const ScMatrix* pMat = rToken.GetMatrix();
5051 if (!pMat)
5052 return;
5053
5054 size_t nC, nMaxC, nR, nMaxR;
5055 pMat->GetDimensions(nMaxC, nMaxR);
5056
5057 rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayOpen));
5058 for (nR = 0 ; nR < nMaxR ; ++nR)
5059 {
5060 if (nR > 0)
5061 {
5062 rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayRowSep));
5063 }
5064
5065 for (nC = 0 ; nC < nMaxC ; ++nC)
5066 {
5067 if (nC > 0)
5068 {
5069 rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayColSep));
5070 }
5071
5072 if (pMat->IsValue(nC, nR))
5073 {
5074 if (pMat->IsBoolean(nC, nR))
5075 {
5076 bool bVal = pMat->GetDouble(nC, nR) != 0.0;
5077 rBuf.append(rCxt.mxOpCodeMap->getSymbol(bVal ? ocTrue : ocFalse));
5078 }
5079 else
5080 {
5081 FormulaError nErr = pMat->GetError(nC, nR);
5082 if (nErr != FormulaError::NONE)
5083 rBuf.append(ScGlobal::GetErrorString(nErr));
5084 else
5085 appendDouble(rCxt, rBuf, pMat->GetDouble(nC, nR));
5086 }
5087 }
5088 else if (pMat->IsEmpty(nC, nR))
5089 {
5090 // Skip it.
5091 }
5092 else if (pMat->IsStringOrEmpty(nC, nR))
5093 appendString(rBuf, pMat->GetString(nC, nR).getString());
5094 }
5095 }
5096 rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayClose));
5097 }
5098 break;
5099 case svIndex:
5100 {
5102
5103 sal_uInt16 nIndex = rToken.GetIndex();
5104 switch (eOp)
5105 {
5106 case ocName:
5107 {
5108 SCTAB nTab = rToken.GetSheet();
5109 if (nTab < 0)
5110 {
5111 // global named range
5112 NameType::const_iterator it = rCxt.maGlobalRangeNames.find(nIndex);
5113 if (it == rCxt.maGlobalRangeNames.end())
5114 {
5115 rBuf.append(ScCompiler::GetNativeSymbol(ocErrName));
5116 break;
5117 }
5118
5119 rBuf.append(it->second);
5120 }
5121 else
5122 {
5123 // sheet-local named range
5124 if (nTab != rPos.Tab())
5125 {
5126 // On other sheet.
5127 OUString aName;
5128 if (o3tl::make_unsigned(nTab) < rCxt.maTabNames.size())
5129 aName = rCxt.maTabNames[nTab];
5130 if (!aName.isEmpty())
5131 {
5133 rBuf.append( aName);
5134 }
5135 else
5136 rBuf.append(ScCompiler::GetNativeSymbol(ocErrName));
5138 }
5139
5140 sc::TokenStringContext::TabIndexMapType::const_iterator itTab = rCxt.maSheetRangeNames.find(nTab);
5141 if (itTab == rCxt.maSheetRangeNames.end())
5142 {
5143 rBuf.append(ScCompiler::GetNativeSymbol(ocErrName));
5144 break;
5145 }
5146
5147 const NameType& rNames = itTab->second;
5148 NameType::const_iterator it = rNames.find(nIndex);
5149 if (it == rNames.end())
5150 {
5151 rBuf.append(ScCompiler::GetNativeSymbol(ocErrName));
5152 break;
5153 }
5154
5155 rBuf.append(it->second);
5156 }
5157 }
5158 break;
5159 case ocDBArea:
5160 case ocTableRef:
5161 {
5162 NameType::const_iterator it = rCxt.maNamedDBs.find(nIndex);
5163 if (it != rCxt.maNamedDBs.end())
5164 rBuf.append(it->second);
5165 }
5166 break;
5167 default:
5168 rBuf.append(ScCompiler::GetNativeSymbol(ocErrName));
5169 }
5170 }
5171 break;
5172 case svExternal:
5173 {
5174 // mapped or translated name of AddIns
5175 OUString aAddIn = rToken.GetExternal();
5176 bool bMapped = rCxt.mxOpCodeMap->isPODF(); // ODF 1.1 directly uses programmatical name
5177 if (!bMapped && rCxt.mxOpCodeMap->hasExternals())
5178 {
5179 const ExternalHashMap& rExtMap = rCxt.mxOpCodeMap->getReverseExternalHashMap();
5180 ExternalHashMap::const_iterator it = rExtMap.find(aAddIn);
5181 if (it != rExtMap.end())
5182 {
5183 aAddIn = it->second;
5184 bMapped = true;
5185 }
5186 }
5187
5188 if (!bMapped && !rCxt.mxOpCodeMap->isEnglish())
5190
5191 rBuf.append(aAddIn);
5192 }
5193 break;
5194 case svError:
5195 {
5196 FormulaError nErr = rToken.GetError();
5197 OpCode eOpErr;
5198 switch (nErr)
5199 {
5200 break;
5201 case FormulaError::DivisionByZero:
5202 eOpErr = ocErrDivZero;
5203 break;
5204 case FormulaError::NoValue:
5205 eOpErr = ocErrValue;
5206 break;
5207 case FormulaError::NoRef:
5208 eOpErr = ocErrRef;
5209 break;
5210 case FormulaError::NoName:
5211 eOpErr = ocErrName;
5212 break;
5213 case FormulaError::IllegalFPOperation:
5214 eOpErr = ocErrNum;
5215 break;
5216 case FormulaError::NotAvailable:
5217 eOpErr = ocErrNA;
5218 break;
5219 case FormulaError::NoCode:
5220 default:
5221 eOpErr = ocErrNull;
5222 }
5223 rBuf.append(rCxt.mxOpCodeMap->getSymbol(eOpErr));
5224 }
5225 break;
5226 case svByte:
5227 case svJump:
5228 case svFAP:
5229 case svMissing:
5230 case svSep:
5231 default:
5232 ;
5233 }
5234}
5235
5236}
5237
5239{
5240 if (!nLen)
5241 return OUString();
5242
5243 OUStringBuffer aBuf;
5244
5245 FormulaToken** p = pCode.get();
5246 FormulaToken** pEnd = p + static_cast<size_t>(nLen);
5247 for (; p != pEnd; ++p)
5248 {
5249 const FormulaToken* pToken = *p;
5250 OpCode eOp = pToken->GetOpCode();
5251 /* FIXME: why does this ignore the count of spaces? */
5252 if (eOp == ocSpaces)
5253 {
5254 // TODO : Handle intersection operator '!!'.
5255 aBuf.append(' ');
5256 continue;
5257 }
5258 else if (eOp == ocWhitespace)
5259 {
5260 aBuf.append( pToken->GetChar());
5261 continue;
5262 }
5263
5264 if (eOp < rCxt.mxOpCodeMap->getSymbolCount())
5265 aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp));
5266
5267 appendTokenByType(*mxSheetLimits, rCxt, aBuf, *pToken, rPos, IsFromRangeName());
5268 }
5269
5270 return aBuf.makeStringAndClear();
5271}
5272
5273namespace {
5274
5275void wrapAddress( ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
5276{
5277 if (rPos.Col() > nMaxCol)
5278 rPos.SetCol(rPos.Col() % (nMaxCol+1));
5279 if (rPos.Row() > nMaxRow)
5280 rPos.SetRow(rPos.Row() % (nMaxRow+1));
5281}
5282
5283template<typename T> void wrapRange( T& n1, T& n2, T nMax )
5284{
5285 if (n2 > nMax)
5286 {
5287 if (n1 == 0)
5288 n2 = nMax; // Truncate to full range instead of wrapping to a weird range.
5289 else
5290 n2 = n2 % (nMax+1);
5291 }
5292 if (n1 > nMax)
5293 n1 = n1 % (nMax+1);
5294}
5295
5296void wrapColRange( ScRange& rRange, SCCOL nMaxCol )
5297{
5298 SCCOL nCol1 = rRange.aStart.Col();
5299 SCCOL nCol2 = rRange.aEnd.Col();
5300 wrapRange( nCol1, nCol2, nMaxCol);
5301 rRange.aStart.SetCol( nCol1);
5302 rRange.aEnd.SetCol( nCol2);
5303}
5304
5305void wrapRowRange( ScRange& rRange, SCROW nMaxRow )
5306{
5307 SCROW nRow1 = rRange.aStart.Row();
5308 SCROW nRow2 = rRange.aEnd.Row();
5309 wrapRange( nRow1, nRow2, nMaxRow);
5310 rRange.aStart.SetRow( nRow1);
5311 rRange.aEnd.SetRow( nRow2);
5312}
5313
5314}
5315
5316void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
5317{
5318 FormulaToken** p = pCode.get();
5319 FormulaToken** pEnd = p + static_cast<size_t>(nLen);
5320 for (; p != pEnd; ++p)
5321 {
5322 switch ((*p)->GetType())
5323 {
5324 case svSingleRef:
5325 {
5326 formula::FormulaToken* pToken = *p;
5327 ScSingleRefData& rRef = *pToken->GetSingleRef();
5328 ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos);
5329 wrapAddress(aAbs, nMaxCol, nMaxRow);
5330 rRef.SetAddress(*mxSheetLimits, aAbs, rPos);
5331 }
5332 break;
5333 case svDoubleRef:
5334 {
5335 formula::FormulaToken* pToken = *p;
5336 ScComplexRefData& rRef = *pToken->GetDoubleRef();
5337 ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos);
5338 // Entire columns/rows are sticky.
5339 if (!rRef.IsEntireCol(*mxSheetLimits) && !rRef.IsEntireRow(*mxSheetLimits))
5340 {
5341 wrapColRange( aAbs, nMaxCol);
5342 wrapRowRange( aAbs, nMaxRow);
5343 }
5344 else if (rRef.IsEntireCol(*mxSheetLimits) && !rRef.IsEntireRow(*mxSheetLimits))
5345 wrapColRange( aAbs, nMaxCol);
5346 else if (!rRef.IsEntireCol(*mxSheetLimits) && rRef.IsEntireRow(*mxSheetLimits))
5347 wrapRowRange( aAbs, nMaxRow);
5348 // else nothing if both, column and row, are entire.
5349 aAbs.PutInOrder();
5350 rRef.SetRange(*mxSheetLimits, aAbs, rPos);
5351 }
5352 break;
5353 default:
5354 ;
5355 }
5356 }
5357}
5358
5360{
5361 sal_Int32 nResult = 0;
5362 for (auto i = 0; i < nRPN; ++i)
5363 {
5364 switch ((*pRPN[i]).GetType())
5365 {
5366 case svDoubleRef:
5367 {
5368 const auto pComplexRef = (*pRPN[i]).GetDoubleRef();
5369
5370 // Number of cells referenced divided by 10.
5371 const double nRows = 1 + (pComplexRef->Ref2.Row() - pComplexRef->Ref1.Row());
5372 const double nCols = 1 + (pComplexRef->Ref2.Col() - pComplexRef->Ref1.Col());
5373 const double nNumCellsTerm = nRows * nCols / 10.0;
5374
5375 if (nNumCellsTerm + nResult < SAL_MAX_INT32)
5376 nResult += nNumCellsTerm;
5377 else
5378 nResult = SAL_MAX_INT32;
5379 }
5380 break;
5381 default:
5382 ;
5383 }
5384 }
5385
5386 if (nResult == 0)
5387 nResult = 1;
5388
5389 return nResult;
5390}
5391
5392#if DEBUG_FORMULA_COMPILER
5393
5394void ScTokenArray::Dump() const
5395{
5396 cout << "+++ Normal Tokens +++" << endl;
5397 for (sal_uInt16 i = 0; i < nLen; ++i)
5398 {
5399 DumpToken(*pCode[i]);
5400 }
5401
5402 cout << "+++ RPN Tokens +++" << endl;
5403 for (sal_uInt16 i = 0; i < nRPN; ++i)
5404 {
5405 DumpToken(*pRPN[i]);
5406 }
5407}
5408#endif
5409
5410/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define FORMULA_MAXJUMPCOUNT
XPropertyListType t
const SCTAB SCTAB_MAX
Definition: address.hxx:57
OUString maFormula
const B2DPoint * mpStart
OUString maName
const OUString & getNumDecimalSep() const
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:320
@ UNINITIALIZED
Definition: address.hxx:220
SCTAB Tab() const
Definition: address.hxx:283
void SetCol(SCCOL nColP)
Definition: address.hxx:291
SC_DLLPUBLIC bool Move(SCCOL nDeltaX, SCROW nDeltaY, SCTAB nDeltaZ, ScAddress &rErrorPos, const ScDocument &rDoc)
Definition: address.cxx:2280
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:316
SCROW Row() const
Definition: address.hxx:274
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
@ INITIALIZE_INVALID
Definition: address.hxx:221
SCCOL Col() const
Definition: address.hxx:279
static void CheckTabQuotes(OUString &aTabName, const formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO)
all
Definition: compiler.cxx:1954
ScDBData * findByIndex(sal_uInt16 nIndex)
Definition: dbdata.cxx:1214
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:324
bool IsModified() const
Definition: dbdata.hxx:215
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:898
const OUString & GetFileURL() const
Definition: document.hxx:611
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:625
OUString GetCopyTabName(SCTAB nTab) const
Definition: document.cxx:215
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:827
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:601
bool IsExpandRefs() const
Definition: document.hxx:2457
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:204
virtual const ScComplexRefData * GetDoubleRef() const override
Definition: token.cxx:643
virtual bool TextEqual(const formula::FormulaToken &rToken) const override
Definition: token.cxx:647
virtual const ScSingleRefData * GetSingleRef() const override
Definition: token.cxx:641
ScSheetLimits & mrSheetLimits
Definition: token.hxx:77
ScComplexRefData aDoubleRef
Definition: token.hxx:78
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:651
virtual const ScSingleRefData * GetSingleRef2() const override
Definition: token.cxx:645
bool bDisplayedAsString
Definition: token.hxx:279
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:973
virtual double GetDouble() const override
Definition: token.cxx:966
bool IsDisplayedAsString() const
Definition: token.hxx:286
bool IsInherited() const
Definition: token.hxx:285
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:968
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:785
virtual const ScSingleRefData * GetSingleRef2() const override
Definition: token.cxx:800
svl::SharedString maTabName
Definition: token.hxx:156
ScComplexRefData maDoubleRef
Definition: token.hxx:157
virtual sal_uInt16 GetIndex() const override
Definition: token.cxx:780
virtual const ScSingleRefData * GetSingleRef() const override
Definition: token.cxx:790
virtual ~ScExternalDoubleRefToken() override
Definition: token.cxx:776
virtual const ScComplexRefData * GetDoubleRef() const override
Definition: token.cxx:810
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:820
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:848
ScExternalNameToken()=delete
svl::SharedString maName
Definition: token.hxx:184
virtual ~ScExternalNameToken() override
Definition: token.cxx:841
sal_uInt16 mnFileId
Definition: token.hxx:183
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:853
virtual sal_uInt16 GetIndex() const override
Definition: token.cxx:843
sal_uInt16 getExternalFileId(const OUString &rFile)
ScSingleRefData maSingleRef
Definition: token.hxx:133
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:754
virtual const ScSingleRefData * GetSingleRef() const override
Definition: token.cxx:744
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:739
svl::SharedString maTabName
Definition: token.hxx:132
virtual ~ScExternalSingleRefToken() override
Definition: token.cxx:730
virtual sal_uInt16 GetIndex() const override
Definition: token.cxx:734
static SC_DLLPUBLIC ScUnoAddInCollection * GetAddInCollection()
Definition: global.cxx:283
static OUString GetErrorString(FormulaError nErrNumber)
Definition: global.cxx:315
const OUString & GetFormula() const
Definition: token.hxx:389
ScHybridCellToken(double f, const svl::SharedString &rStr, OUString aFormula, bool bEmptyDisplayedAsString)
Definition: token.cxx:1112
virtual double GetDouble() const override
Definition: token.cxx:1123
double mfDouble
Definition: token.hxx:381
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:1125
svl::SharedString maString
Definition: token.hxx:382
OUString maFormula
Definition: token.hxx:383
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:1130
static const ScCalcConfig & GetGlobalConfig()
Definition: interpr4.cxx:3902
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:957
virtual ~ScJumpMatrixToken() override
Definition: token.cxx:962
ScJumpMatrixToken(std::shared_ptr< ScJumpMatrix > p)
Definition: token.cxx:945
virtual ScJumpMatrix * GetJumpMatrix() const override
Definition: token.cxx:952
std::shared_ptr< ScJumpMatrix > mpJumpMatrix
Definition: token.hxx:247
Transports the result from the interpreter to the formula cell.
Definition: token.hxx:295
ScMatrixCellResultToken(ScConstMatrixRef pMat, const formula::FormulaToken *pUL)
Definition: token.cxx:980
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:989
formula::StackVar GetUpperLeftType() const
Definition: token.hxx:312
ScConstMatrixRef xMatrix
Definition: token.hxx:301
virtual FormulaToken * Clone() const override
Definition: token.cxx:1009
virtual ~ScMatrixCellResultToken() override
Definition: token.cxx:987
void Assign(const ScMatrixCellResultToken &r)
Definition: token.cxx:1014
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:1002
virtual double GetDouble() const override
Definition: token.cxx:985
virtual ScMatrix * GetMatrix() override
Definition: token.cxx:997
formula::FormulaConstTokenRef xUpperLeft
Definition: token.hxx:302
Stores the matrix result at the formula cell, additionally the range the matrix formula occupies.
Definition: token.hxx:325
void CloneUpperLeftIfNecessary()
xUpperLeft is modifiable through SetUpperLeftDouble(), so clone it whenever an svDouble token is assi...
Definition: token.cxx:1045
void Assign(const ScMatrixCellResultToken &r)
Assign matrix result, keep matrix formula dimension.
Definition: token.cxx:1051
void SetUpperLeftDouble(double f)
Modify xUpperLeft if formula::svDouble, or create new formula::FormulaDoubleToken if not set yet.
Definition: token.cxx:1082
void ResetResult()
Reset matrix and upper left, keep matrix formula dimension.
Definition: token.cxx:1106
ScMatrixFormulaCellToken(SCCOL nC, SCROW nR, const ScConstMatrixRef &pMat, const formula::FormulaToken *pUL)
Definition: token.cxx:1020
virtual ~ScMatrixFormulaCellToken() override
Definition: token.cxx:1036
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:1038
Token storing matrix that represents values in sheet range.
Definition: token.hxx:113
virtual const ScMatrix * GetMatrix() const override
Definition: token.cxx:692
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:712
ScMatrixRangeToken(const sc::RangeMatrix &rMat)
Definition: token.cxx:679
virtual sal_uInt8 GetByte() const override
Definition: token.cxx:687
virtual FormulaToken * Clone() const override
Definition: token.cxx:717
virtual const ScComplexRefData * GetDoubleRef() const override
Definition: token.cxx:702
ScMatrixRef mpMatrix
Definition: token.hxx:114
ScComplexRefData maRef
Definition: token.hxx:115
virtual const ScMatrix * GetMatrix() const override
Definition: token.cxx:672
ScMatrixToken(ScMatrixRef p)
Definition: token.cxx:667
ScMatrixRef pMatrix
Definition: token.hxx:96
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:674
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:101
void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
Definition: scmatrix.cxx:3213
svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3238
bool IsStringOrEmpty(SCSIZE nIndex) const
Definition: scmatrix.cxx:3258
bool IsEmpty(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3268
void PutString(const svl::SharedString &rStr, SCSIZE nC, SCSIZE nR)
Definition: scmatrix.cxx:3183
bool IsBoolean(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3303
double GetDouble(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3223
FormulaError GetError(SCSIZE nC, SCSIZE nR) const
May be used before obtaining the double value of an element to avoid passing its NAN around.
Definition: scmatrix.cxx:3218
void PutEmpty(SCSIZE nC, SCSIZE nR)
Definition: scmatrix.cxx:3198
void PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
Definition: scmatrix.cxx:3168
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
Definition: scmatrix.cxx:3143
bool IsValue(SCSIZE nIndex) const
Definition: scmatrix.cxx:3288
bool Contains(const ScRange &) const
Definition: rangelst.cxx:1082
bool IsEndRowSticky(const ScDocument &rDoc) const
If maximum end row should not be adapted during reference update.
Definition: address.cxx:2418
bool IsEndColSticky(const ScDocument &rDoc) const
If maximum end column should not be adapted during reference update.
Definition: address.cxx:2412
bool Move(SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ, ScRange &rErrorRange, const ScDocument &rDoc)
Definition: address.cxx:2328
void IncEndRowSticky(const ScDocument &rDoc, SCROW nDelta)
Increment or decrement end row unless sticky or until it becomes sticky.
Definition: address.cxx:2445
void SetInvalid()
Definition: address.hxx:539
void PutInOrder()
Definition: address.hxx:622
ScAddress aEnd
Definition: address.hxx:498
bool Intersects(const ScRange &rRange) const
Definition: address.hxx:734
void IncEndColSticky(const ScDocument &rDoc, SCCOL nDelta)
Increment or decrement end column unless sticky or until it becomes sticky.
Definition: address.cxx:2424
bool Contains(const ScAddress &) const
is Address& fully in Range?
Definition: address.hxx:718
bool MoveSticky(const ScDocument &rDoc, SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ, ScRange &rErrorRange)
Same as Move() but with sticky end col/row anchors.
Definition: address.cxx:2341
ScAddress aStart
Definition: address.hxx:497
bool mbArrayResult
Definition: token.hxx:263
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:659
bool IsArrayResult() const
Definition: token.cxx:658
ScRefList aRefList
Definition: token.hxx:262
virtual const ScRefList * GetRefList() const override
Definition: token.cxx:656
static ScMatrixRef CreateMixedMatrix(const css::uno::Any &rAny)
Convert a sequence of mixed elements to ScMatrix.
Definition: rangeseq.cxx:358
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:636
ScSingleRefData aSingleRef
Definition: token.hxx:63
virtual const ScSingleRefData * GetSingleRef() const override
Definition: token.cxx:630
virtual bool TextEqual(const formula::FormulaToken &rToken) const override
Definition: token.cxx:632
ScSheetLimits & mrSheetLimits
Definition: token.hxx:62
Special token to remember details of ocTableRef "structured references".
Definition: token.hxx:204
sal_uInt16 mnIndex
index into table / database range collection
Definition: token.hxx:238
ScTableRefToken()=delete
virtual sal_uInt16 GetIndex() const override
Definition: token.cxx:881
void SetAreaRefRPN(formula::FormulaToken *pToken)
Definition: token.cxx:910
formula::FormulaTokenRef mxAreaRefRPN
resulting RPN area
Definition: token.hxx:237
formula::FormulaToken * GetAreaRefRPN() const
Definition: token.cxx:915
Item GetItem() const
Definition: token.cxx:900
void AddItem(Item)
Definition: token.cxx:905
virtual void SetIndex(sal_uInt16 n) override
Definition: token.cxx:886
virtual sal_Int16 GetSheet() const override
Definition: token.cxx:891
virtual ~ScTableRefToken() override
Definition: token.cxx:879
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:920
void AddExternalSingleReference(sal_uInt16 nFileId, const svl::SharedString &rTabName, const ScSingleRefData &rRef)
Definition: token.cxx:2307
sc::RefUpdateResult AdjustReferenceOnMovedTab(const sc::RefUpdateMoveTabContext &rCxt, const ScAddress &rOldPos)
Definition: token.cxx:4413
void AdjustReferenceOnCopy(const ScAddress &rNewPos)
Adjust internal range references on base position change to justify / put in order the relative refer...
Definition: token.cxx:4581
void CheckExpandReferenceBounds(const sc::RefUpdateContext &rCxt, const ScAddress &rPos, SCROW nGroupLen, std::vector< SCROW > &rBounds) const
Definition: token.cxx:4834
virtual bool AddFormulaToken(const css::sheet::FormulaToken &rToken, svl::SharedStringPool &rSPool, formula::ExternalReferenceHelper *_pRef) override
Definition: token.cxx:1137
ScTokenArray CloneValue() const
True copy!
Definition: token.cxx:1989
sc::RefUpdateResult AdjustReferenceOnShift(const sc::RefUpdateContext &rCxt, const ScAddress &rOldPos)
Adjust all references in response to shifting of cells during cell insertion and deletion.
Definition: token.cxx:3130
virtual formula::FormulaToken * AddOpCode(OpCode eCode) override
Definition: token.cxx:2265
void CheckRelativeReferenceBounds(const sc::RefUpdateContext &rCxt, const ScAddress &rPos, SCROW nGroupLen, std::vector< SCROW > &rBounds) const
Definition: token.cxx:4763
formula::FormulaToken * AddColRowName(const ScSingleRefData &rRef)
ScSingleRefOpToken with ocColRowName.
Definition: token.cxx:2319
bool EqualTokens(const ScTokenArray *pArr2) const
Definition: token.cxx:1907
bool mbThreadingEnabled
Definition: tokenarray.hxx:59
void CheckForThreading(const formula::FormulaToken &r)
Definition: token.cxx:1281
virtual void CheckToken(const formula::FormulaToken &r) override
Definition: token.cxx:1355
virtual ~ScTokenArray() override
Definition: token.cxx:1881
std::unique_ptr< ScTokenArray > Clone() const
Definition: token.cxx:1931
formula::FormulaToken * AddMatrixSingleReference(const ScSingleRefData &rRef)
ScSingleRefOpToken with ocMatRef.
Definition: token.cxx:2277
void ResetVectorState()
Definition: token.cxx:1800
void AssignXMLString(const OUString &rText, const OUString &rFormulaNmsp)
Assign XML string placeholder to the array.
Definition: token.cxx:2324
void MoveReferenceColReorder(const ScAddress &rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType &rColMap)
Move reference positions in response to column reordering.
Definition: token.cxx:3524
ScTokenArray(const ScDocument &rDoc)
Definition: token.cxx:1867
bool IsFormulaVectorDisabled() const
Definition: token.cxx:1807
formula::FormulaToken * AddExternalDoubleReference(sal_uInt16 nFileId, const svl::SharedString &rTabName, const ScComplexRefData &rRef)
Definition: token.cxx:2313
void AdjustReferenceOnMovedOriginIfOtherSheet(const ScAddress &rOldPos, const ScAddress &rNewPos)
Adjust all internal references on base position change if they point to a sheet other than the one of...
Definition: token.cxx:4532
formula::FormulaToken * AddRawToken(const ScRawToken &)
Definition: token.cxx:2047
sc::RefUpdateResult AdjustReferenceOnDeletedTab(const sc::RefUpdateDeleteTabContext &rCxt, const ScAddress &rOldPos)
Adjust all references on sheet deletion.
Definition: token.cxx:4255
bool ReferencesSheet(SCTAB nTab, SCTAB nPosTab) const
Returns true if the sheet nTab is referenced in code.
Definition: token.cxx:2693
void WrapReference(const ScAddress &rPos, SCCOL nMaxCol, SCROW nMaxRow)
Definition: token.cxx:5316
formula::FormulaToken * AddDBRange(sal_uInt16 n)
Definition: token.cxx:2297
bool ImplGetReference(ScRange &rRange, const ScAddress &rPos, bool bValidOnly) const
Definition: token.cxx:1685
size_t mnHashValue
Definition: tokenarray.hxx:56
formula::FormulaToken * AddMatrix(const ScMatrixRef &p)
Definition: token.cxx:2287
bool mbOpenCLEnabled
Definition: tokenarray.hxx:58
sc::RefUpdateResult AdjustReferenceOnInsertedTab(const sc::RefUpdateInsertTabContext &rCxt, const ScAddress &rOldPos)
Definition: token.cxx:4327
rtl::Reference< ScSheetLimits > mxSheetLimits
Definition: tokenarray.hxx:55
sc::RefUpdateResult AdjustReferenceOnMove(const sc::RefUpdateContext &rCxt, const ScAddress &rOldPos, const ScAddress &rNewPos)
Definition: token.cxx:3361
void AdjustSheetLocalNameReferences(SCTAB nOldTab, SCTAB nNewTab)
When copying a sheet-local named expression, move sheet references that point to the originating shee...
Definition: token.cxx:2645
formula::FormulaToken * AddDoubleReference(const ScComplexRefData &rRef)
Definition: token.cxx:2282
sc::RefUpdateResult AdjustReferenceInMovedName(const sc::RefUpdateContext &rCxt, const ScAddress &rPos)
Definition: token.cxx:4083
void AdjustReferenceOnMovedOrigin(const ScAddress &rOldPos, const ScAddress &rNewPos)
Adjust all internal references on base position change.
Definition: token.cxx:4494
OUString CreateString(sc::TokenStringContext &rCxt, const ScAddress &rPos) const
Create a string representation of formula token array without modifying the internal state of the tok...
Definition: token.cxx:5238
sc::RefUpdateResult AdjustReferenceInName(const sc::RefUpdateContext &rCxt, const ScAddress &rPos)
Adjust all references in named expression.
Definition: token.cxx:3811
formula::FormulaToken * AddSingleReference(const ScSingleRefData &rRef)
ScSingleRefToken with ocPush.
Definition: token.cxx:2272
sal_Int32 GetWeight() const
Definition: token.cxx:5359
ScTokenArray & operator=(const ScTokenArray &)
Assignment with incrementing references of FormulaToken entries (not copied!)
Definition: token.cxx:1885
void AddRangeName(sal_uInt16 n, sal_Int16 nSheet)
Definition: token.cxx:2292
bool IsValidReference(ScRange &rRange, const ScAddress &rPos) const
Exactly and only one valid range (no #REF!s)
Definition: token.cxx:1862
bool IsInvariant() const
If the array contains at least one relative row reference or named expression, it's variant.
Definition: token.cxx:1823
void GenHash()
True copy!
Definition: token.cxx:1730
virtual formula::FormulaToken * MergeArray() override
Definition: token.cxx:2062
void MoveReferenceRowReorder(const ScAddress &rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType &rRowMap)
Definition: token.cxx:3594
void AdjustAbsoluteRefs(const ScDocument &rOldDoc, const ScAddress &rOldPos, const ScAddress &rNewPos, bool bCheckCopyArea)
Make all absolute references pointing to the copied range if the range is copied too.
Definition: token.cxx:2597
void ReadjustAbsolute3DReferences(const ScDocument &rOldDoc, ScDocument &rNewDoc, const ScAddress &rPos, bool bRangeName=false)
Make all absolute references external references pointing to the old document.
Definition: token.cxx:2545
ScFormulaVectorState meVectorState
Definition: tokenarray.hxx:57
void MergeRangeReference(const ScAddress &rPos)
Merge very last SingleRef+ocRange+SingleRef combination into DoubleRef and adjust pCode array,...
Definition: token.cxx:2237
virtual void Clear() override
Definition: token.cxx:1924
formula::FormulaToken * AddExternalName(sal_uInt16 nFileId, const svl::SharedString &rName)
Definition: token.cxx:2302
bool IsReference(ScRange &rRange, const ScAddress &rPos) const
Exactly and only one range (valid or deleted)
Definition: token.cxx:1857
bool GetAdjacentExtendOfOuterFuncRefs(SCCOLROW &nExtend, const ScAddress &rPos, ScDirection)
Determines the extent of direct adjacent references.
Definition: token.cxx:2337
void ClearTabDeleted(const ScAddress &rPos, SCTAB nStartTab, SCTAB nEndTab)
Clear sheet deleted flag from internal reference tokens if the sheet index falls within specified ran...
Definition: token.cxx:4623
void LocalizeString(OUString &rName)
modify rName - input: exact name
Definition: addincol.cxx:1255
const LocaleDataWrapper & GetLocaleData() const
virtual OUString getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const=0
static const OUString & GetNativeSymbol(OpCode eOp)
void Move(FormulaTokenArray &&)
void Assign(const FormulaTokenArray &)
FormulaToken * PeekPrev(sal_uInt16 &nIdx) const
FormulaToken * Add(FormulaToken *)
FormulaToken ** GetArray() const
FormulaToken * ReplaceToken(sal_uInt16 nOffset, FormulaToken *, ReplaceMode eMode)
std::unique_ptr< FormulaToken *[]> pCode
virtual const ScSingleRefData * GetSingleRef() const
oslInterlockedCount GetRef() const
virtual const ScSingleRefData * GetSingleRef2() const
virtual sal_uInt16 GetIndex() const
virtual sal_Int16 GetSheet() const
virtual const OUString & GetExternal() const
OpCode GetOpCode() const
virtual const std::vector< ScComplexRefData > * GetRefList() const
virtual FormulaToken * Clone() const
virtual sal_Unicode GetChar() const
StackVar GetType() const
virtual const ScComplexRefData * GetDoubleRef() const
virtual const svl::SharedString & GetString() const
virtual const ScMatrix * GetMatrix() const
bool IsExternalRef() const
virtual double GetDouble() const
virtual double & GetDoubleAsReference()
virtual FormulaError GetError() const
virtual ScJumpMatrix * GetJumpMatrix() const
const_iterator end() const
Definition: reordermap.hxx:26
DataType::const_iterator const_iterator
Definition: reordermap.hxx:23
const_iterator find(DataType::key_type key) const
Definition: reordermap.hxx:31
Keep track of all named expressions that have been updated during reference update.
bool isNameUpdated(SCTAB nTab, sal_uInt16 nIndex) const
SharedString intern(const OUString &rStr)
const OUString & getString() const
rtl_uString * getData()
static const SharedString & getEmptyString()
#define SC_OPCODE_START_FUNCTION
#define SC_OPCODE_STOP_UN_OP
#define SC_OPCODE_STOP_FUNCTION
#define SC_OPCODE_START_BIN_OP
OUString maString
FormulaError
DocumentType eType
@ URM_COPY
Definition: global.hxx:303
@ URM_MOVE
Definition: global.hxx:304
@ URM_INSDEL
Definition: global.hxx:302
ScDirection
Definition: global.hxx:343
@ DIR_LEFT
Definition: global.hxx:347
@ DIR_TOP
Definition: global.hxx:346
@ DIR_RIGHT
Definition: global.hxx:345
@ DIR_BOTTOM
Definition: global.hxx:344
sal_Int32 nIndex
OUString aName
void * p
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
aStr
aBuf
std::unique_ptr< sal_Int32[]> pData
int n2
int n1
bool getRangeFromToken(const ScDocument *pDoc, ScRange &rRange, const ScTokenRef &pToken, const ScAddress &rPos, bool bExternal=false)
std::unordered_map< OUString, OUString > ExternalHashMap
::boost::intrusive_ptr< FormulaToken > FormulaTokenRef
StackVar
svMissing
svIndex
svExternalDoubleRef
svUnknown
svExternalName
svDouble
svJumpMatrix
svSep
svError
svDoubleRef
svExternal
svExternalSingleRef
svMatrixCell
svString
svJump
svRefList
svMatrix
svFAP
svByte
svEmptyCell
svSingleRef
svHybridCell
std::string StackVarEnumToString(StackVar const e)
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::animations::XAnimationNode > Clone(const css::uno::Reference< css::animations::XAnimationNode > &xSourceNode, const SdPage *pSource=nullptr, const SdPage *pTarget=nullptr)
OpCode
ocSumProduct
ocArrayOpen
ocNot
ocCosHyp
ocCombinA
ocCountIfs
ocNegSub
ocSkew
ocTanHyp
ocIsEven
ocSqrt
ocChiDist
ocB
ocTableRef
ocSumIf
ocMod
ocTTest
ocCot
ocIRR
ocDBCount
ocDBMax
ocArcCosHyp
ocCountIf
ocHypGeomDist
ocFalse
ocRoundUp
ocStyle
ocGauss
ocInfo
ocNPV
ocChiSqDist
ocStringXML
ocSecant
ocEven
ocDDB
ocWebservice
ocRSQ
ocDde
ocTrunc
ocPermut
ocPearson
ocStDev
ocCell
ocWeibull
ocCosecantHyp
ocOr
ocFisherInv
ocAbs
ocSin
ocAverageIfs
ocArcTan2
ocIntercept
ocDBVarP
ocClose
ocDeg
ocPMT
ocColRowName
ocBetaInv
ocFloor
ocSumSQ
ocNormDist
ocIndirect
ocChiSqInv
ocGeoMean
ocFV
ocRound
ocArrayRowSep
ocPpmt
ocMacro
ocProduct
ocGammaLn
ocSYD
ocExp
ocAverageA
ocRad
ocSLN
ocAverage
ocMinA
ocSkewp
ocOffset
ocIfNA
ocBetaDist
ocPermutationA
ocXor
ocChiInv
ocStandard
ocArcSin
ocAdd
ocSNormInv
ocStop
ocSkip
ocRange
ocNormInv
ocDBVar
ocZTest
ocSecantHyp
ocErrName
ocSTEYX
ocArcTan
ocTan
ocCosecant
ocNper
ocBitOr
ocFInv
ocDBGet
ocSlope
ocIpmt
ocRRI
ocErrValue
ocFact
ocOpen
ocMIRR
ocAverageIf
ocDBMin
ocVarPA
ocHarMean
ocRandom
ocStdNormDist
ocCeil
ocColRowNameAuto
ocTrue
ocArcCot
ocISPMT
ocCorrel
ocArcTanHyp
ocExternal
ocNegBinomVert
ocSpaces
ocBitAnd
ocAnd
ocInt
ocPercentSign
ocErrNull
ocCount2
ocArcSinHyp
ocTDist
ocSep
ocMissing
ocTInv
ocMedian
ocBinomDist
ocVarP
ocDBCount2
ocLn
ocDevSq
ocVBD
ocPush
ocCotHyp
ocBad
ocArcCotHyp
ocErrNA
ocFTest
ocPDuration
ocDBArea
ocRate
ocStDevP
ocIfError
ocErrNum
ocKurt
ocPower
ocSumXMY2
ocWhitespace
ocTableRefClose
ocConfidence
ocRoundDown
ocMatRef
ocForecast
ocMin
ocSumX2MY2
ocPoissonDist
ocLogInv
ocErrDivZero
ocDB
ocArcCos
ocDBProduct
ocArrayClose
ocErrRef
ocDBAverage
ocBitLshift
ocGetPivotData
ocFisher
ocArrayColSep
ocCombin
ocPV
ocMatch
ocVLookup
ocStDevA
ocSumIfs
ocPhi
ocTableOp
ocDBSum
ocChoose
ocVarA
ocBitXor
ocVar
ocCovar
ocNotAvail
ocGamma
ocOdd
ocGammaInv
ocDBStdDev
ocIf
ocBitRshift
ocSumX2DY2
ocLog10
ocSheet
ocText
ocDBStdDevP
ocIsOdd
ocExpDist
ocGammaDist
ocLog
ocMaxA
ocFDist
ocStDevPA
ocLogNormDist
ocSinHyp
ocTableRefOpen
ocSum
ocAveDev
ocPi
ocName
ocCount
ocCritBinom
ocCos
ocMax
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
static bool isOpenCLEnabled()
Definition: calcconfig.cxx:69
OpCodeSet mpOpenCLSubsetOpCodes
Definition: calcconfig.hxx:69
static bool isThreadingEnabled()
Definition: calcconfig.cxx:80
This struct stores general clipboard parameters associated with a ScDocument instance created in clip...
Definition: clipparam.hxx:31
ScRangeList maRanges
Definition: clipparam.hxx:34
@ SHEET_SEPARATOR
Character between sheet name and address.
Definition: compiler.hxx:242
const formula::FormulaGrammar::AddressConvention meConv
Definition: compiler.hxx:193
virtual sal_Unicode getSpecialSymbol(SpecialSymbolType eSymType) const =0
virtual OUString makeExternalNameStr(sal_uInt16 nFileId, const OUString &rFile, const OUString &rName) const =0
virtual void makeExternalRefStr(ScSheetLimits &rLimits, OUStringBuffer &rBuffer, const ScAddress &rPos, sal_uInt16 nFileId, const OUString &rFileName, const OUString &rTabName, const ScSingleRefData &rRef) const =0
virtual void makeRefStr(ScSheetLimits &rLimits, OUStringBuffer &rBuffer, formula::FormulaGrammar::Grammar eGram, const ScAddress &rPos, const OUString &rErrRef, const std::vector< OUString > &rTabNames, const ScComplexRefData &rRef, bool bSingleRef, bool bFromRangeName) const =0
Complex reference (a range) into the sheet.
Definition: refdata.hxx:123
SC_DLLPUBLIC ScRange toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:493
void InitRange(const ScRange &rRange)
Definition: refdata.hxx:130
bool Valid(const ScDocument &rDoc) const
Definition: refdata.cxx:478
ScSingleRefData Ref2
Definition: refdata.hxx:125
bool IsEntireRow(const ScSheetLimits &rLimits) const
Whether this references entire rows, 1:1.
Definition: refdata.cxx:516
bool IsDeleted() const
Definition: refdata.cxx:580
bool IncEndRowSticky(const ScDocument &rDoc, SCROW nDelta, const ScAddress &rPos)
Increment or decrement end row unless or until sticky.
Definition: refdata.cxx:551
void SetRange(const ScSheetLimits &rLimits, const ScRange &rRange, const ScAddress &rPos)
Set a new range, assuming that the ordering of the range matches the ordering of the reference data f...
Definition: refdata.cxx:498
bool IncEndColSticky(const ScDocument &rDoc, SCCOL nDelta, const ScAddress &rPos)
Increment or decrement end column unless or until sticky.
Definition: refdata.cxx:522
bool IsEntireCol(const ScSheetLimits &rLimits) const
Whether this references entire columns, A:A.
Definition: refdata.cxx:509
ScComplexRefData & Extend(const ScSheetLimits &rLimits, const ScSingleRefData &rRef, const ScAddress &rPos)
Enlarge range if reference passed is not within existing range.
Definition: refdata.cxx:394
void PutInOrder(const ScAddress &rPos)
Adjust ordering (front-top-left/rear-bottom-right) to a new position.
Definition: refdata.cxx:504
ScSingleRefData Ref1
Definition: refdata.hxx:124
static void UpdateDeleteTab(ScAddress &rAddr, const sc::RefUpdateDeleteTabContext &rCxt)
This is for the base-cell-address of a defined name or conditional format, not for references.
Definition: rangeutl.cxx:1059
void SetExternalDoubleRef(sal_uInt16 nFileId, const OUString &rTabName, const ScComplexRefData &rRef)
Definition: token.cxx:309
sal_Int16 nSheet
Definition: compiler.hxx:128
void SetDouble(double fVal)
Definition: token.cxx:275
void SetString(rtl_uString *pData, rtl_uString *pDataIgnoreCase)
Definition: token.cxx:251
struct ScRawToken::@17::@24 table
void SetDoubleReference(const ScComplexRefData &rRef)
Definition: token.cxx:268
sal_uInt16 nFileId
Definition: compiler.hxx:121
short nJump[FORMULA_MAXJUMPCOUNT+1]
Definition: compiler.hxx:141
OpCode eOp
Definition: compiler.hxx:106
void SetExternalSingleRef(sal_uInt16 nFileId, const OUString &rTabName, const ScSingleRefData &rRef)
Definition: token.cxx:298
ScMatrix * pMat
Definition: compiler.hxx:139
ScComplexRefData aRef
Definition: compiler.hxx:119
void SetOpCode(OpCode eCode)
Definition: token.cxx:207
struct ScRawToken::@17::@19 whitespace
struct ScRawToken::@17::@20 sbyte
void SetName(sal_Int16 nSheet, sal_uInt16 nIndex)
Definition: token.cxx:289
sal_uInt16 nIndex
Definition: compiler.hxx:129
FormulaError nError
Definition: compiler.hxx:140
bool IsValidReference(const ScDocument &rDoc) const
If the token is a non-external reference, determine if the reference is valid.
Definition: token.cxx:335
struct ScRawToken::@17::@25 sharedstring
void SetSingleReference(const ScSingleRefData &rRef)
Definition: token.cxx:260
void SetErrorConstant(FormulaError nErr)
Definition: token.cxx:282
formula::StackVar GetType() const
only delete via Delete()
Definition: compiler.hxx:150
formula::StackVar eType
Definition: compiler.hxx:107
struct ScRawToken::@17::@21 extref
void SetExternalName(sal_uInt16 nFileId, const OUString &rName)
Definition: token.cxx:319
double nValue
Definition: compiler.hxx:110
OUString maExternalName
Definition: compiler.hxx:143
struct ScRawToken::@17::@23 name
void SetExternal(const OUString &rStr)
Definition: token.cxx:328
struct ScRawToken::@17::@22 extname
formula::FormulaToken * CreateToken(ScSheetLimits &rLimits) const
Definition: token.cxx:352
SCROW GetMaxRowCount() const
Definition: sheetlimits.hxx:66
bool ValidRow(SCROW nRow) const
Definition: sheetlimits.hxx:41
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
void SetAbsCol(SCCOL nVal)
Definition: refdata.cxx:59
void SetAbsTab(SCTAB nVal)
Definition: refdata.cxx:93
SCCOL Col() const
Definition: refdata.cxx:247
void SetAddress(const ScSheetLimits &rLimits, const ScAddress &rAddr, const ScAddress &rPos)
Definition: refdata.cxx:213
bool IsDeleted() const
Definition: refdata.cxx:125
bool IsRowDeleted() const
Definition: refdata.hxx:84
void IncRow(SCROW nInc)
Definition: refdata.cxx:88
void SetRowRel(bool bVal)
Definition: refdata.hxx:66
SCTAB Tab() const
Definition: refdata.cxx:254
void SetTabRel(bool bVal)
Definition: refdata.hxx:68
bool IsTabRel() const
Definition: refdata.hxx:69
SCROW Row() const
Definition: refdata.cxx:240
void SetColDeleted(bool bVal)
Definition: refdata.cxx:110
void SetRelRow(SCROW nVal)
Definition: refdata.cxx:82
bool IsRowRel() const
Definition: refdata.hxx:67
void SetRelTab(SCTAB nVal)
Definition: refdata.cxx:99
bool Valid(const ScDocument &rDoc) const
Definition: refdata.cxx:130
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
bool IsColRel() const
Definition: refdata.hxx:65
void IncCol(SCCOL nInc)
Definition: refdata.cxx:71
void SetAbsRow(SCROW nVal)
Definition: refdata.cxx:76
sal_uInt8 FlagValue() const
Definition: refdata.hxx:62
void SetRelCol(SCCOL nVal)
Definition: refdata.cxx:65
bool IsTabDeleted() const
Definition: refdata.hxx:86
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
void IncTab(SCTAB nInc)
Definition: refdata.cxx:105
bool IsFlag3D() const
Definition: refdata.hxx:90
void InitFlags()
No default ctor, because used in ScRawToken union, set InitFlags!
Definition: refdata.hxx:54
void SetRelName(bool bVal)
Definition: refdata.hxx:91
void SetRowDeleted(bool bVal)
Definition: refdata.cxx:115
bool IsColDeleted() const
Definition: refdata.hxx:82
void SetColRel(bool bVal)
Definition: refdata.hxx:64
bool IsRelName() const
Definition: refdata.hxx:92
void SetTabDeleted(bool bVal)
Definition: refdata.cxx:120
sal_Int32 mnRow2
Definition: types.hxx:89
sal_Int32 mnCol1
Definition: types.hxx:85
sal_Int32 mnCol2
Definition: types.hxx:88
sal_Int32 mnTab2
Definition: types.hxx:90
sal_Int32 mnTab1
Definition: types.hxx:87
sal_Int32 mnRow1
Definition: types.hxx:86
Context for reference update during shifting, moving or copying of cell ranges.
SCROW mnRowDelta
Amount and direction of movement in the row direction.
UpdateRefMode meMode
update mode - insert/delete, copy, or move.
SCCOL mnColDelta
Amount and direction of movement in the column direction.
bool mbTransposed
Are the data transposed?
SCTAB mnTabDelta
Amount and direction of movement in the sheet direction.
ScRange maRange
Range of cells that are about to be moved for insert/delete/move modes.
UpdatedRangeNames maUpdatedNames
SCTAB getNewTab(SCTAB nOldTab) const
bool mbReferenceModified
This flag indicates whether any reference in the token array has been modified.
bool mbValueChanged
When this flag is true, the result of the formula needs to be re-calculated either because it contain...
bool mbNameModified
When this flag is true, it indicates that the token array contains a range name that's been updated.
Context for creating string from an array of formula tokens, used in ScTokenArray::CreateString().
formula::FormulaCompiler::OpCodeMapPtr mxOpCodeMap
std::vector< OUString > maExternalFileNames
IndexNamesMapType maExternalCachedTabNames
TabIndexMapType maSheetRangeNames
const ScCompiler::Convention * mpRefConv
formula::FormulaGrammar::Grammar meGram
std::vector< OUString > maTabNames
IndexNameMapType maGlobalRangeNames
std::unordered_map< sal_uInt16, OUString > IndexNameMapType
sal_uInt32 mnIndex
FormulaTokenRef extendRangeReference(ScSheetLimits &rLimits, FormulaToken &rTok1, FormulaToken &rTok2, const ScAddress &rPos, bool bReuseDoubleRef)
If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge ranges as needed for ocRange.
Definition: token.cxx:504
#define IF_NOT_OPCODE_ERROR(o, c)
static bool checkArraySep(bool &bPrevWasSep, bool bNewVal)
Definition: token.cxx:2055
::std::vector< ScComplexRefData > ScRefList
Definition: token.hxx:37
#define MATRIX_TOKEN_HAS_RANGE
Definition: token.hxx:33
unsigned char sal_uInt8
#define SAL_MAX_UINT16
#define SAL_MAX_INT32
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
sal_Int16 SCTAB
Definition: types.hxx:22
::boost::intrusive_ptr< const ScMatrix > ScConstMatrixRef
Definition: types.hxx:26
sal_Int16 SCCOL
Definition: types.hxx:21
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:25
@ FormulaVectorDisabledByOpCode
Definition: types.hxx:55
@ FormulaVectorDisabledByStackVariable
Definition: types.hxx:56
@ FormulaVectorEnabled
Definition: types.hxx:58
@ FormulaVectorDisabledNotInSubSet
Definition: types.hxx:54
@ FormulaVectorDisabled
Definition: types.hxx:53
@ FormulaVectorCheckReference
Definition: types.hxx:59
::boost::intrusive_ptr< formula::FormulaToken > ScTokenRef
Definition: types.hxx:29
sal_Int32 SCROW
Definition: types.hxx:17
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)
Definition: xlstyle.cxx:518