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