1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE ---------------------------------------------------------------
30
31 #include <cstddef>
32 #include <cstdio>
33
34 #include <string.h>
35 #include <tools/mempool.hxx>
36 #include <tools/debug.hxx>
37
38 #include "token.hxx"
39 #include "tokenarray.hxx"
40 #include "compiler.hxx"
41 #include <formula/compiler.hrc>
42 #include "rechead.hxx"
43 #include "parclass.hxx"
44 #include "jumpmatrix.hxx"
45 #include "rangeseq.hxx"
46 #include "externalrefmgr.hxx"
47 #include "document.hxx"
48
49 using ::std::vector;
50
51 #include <com/sun/star/sheet/ComplexReference.hpp>
52 #include <com/sun/star/sheet/ExternalReference.hpp>
53 #include <com/sun/star/sheet/ReferenceFlags.hpp>
54
55 using namespace formula;
56 using namespace com::sun::star;
57
58 namespace
59 {
lcl_SingleRefToCalc(ScSingleRefData & rRef,const sheet::SingleReference & rAPI)60 void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
61 {
62 rRef.InitFlags();
63
64 rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
65 rRef.nRow = static_cast<SCsROW>(rAPI.Row);
66 rRef.nTab = static_cast<SCsTAB>(rAPI.Sheet);
67 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
68 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
69 rRef.nRelTab = static_cast<SCsTAB>(rAPI.RelativeSheet);
70
71 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
72 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
73 rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
74 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
75 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
76 rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
77 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
78 rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
79 }
80
lcl_ExternalRefToCalc(ScSingleRefData & rRef,const sheet::SingleReference & rAPI)81 void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
82 {
83 rRef.InitFlags();
84
85 rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
86 rRef.nRow = static_cast<SCsROW>(rAPI.Row);
87 rRef.nTab = 0;
88 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
89 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
90 rRef.nRelTab = 0;
91
92 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
93 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
94 rRef.SetTabRel( false ); // sheet index must be absolute for external refs
95 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
96 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
97 rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
98 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
99 rRef.SetRelName( false );
100 }
101 //
102 } // namespace
103 //
104 // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
105 // SubCode via FormulaTokenIterator Push/Pop moeglich
106 IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
107
108 // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
109
110 // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
111 // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
112 IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken, 8, 4 )
113 // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
114 const sal_uInt16 nMemPoolDoubleRawToken = 0x0400 / sizeof(ScDoubleRawToken);
115 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken, nMemPoolDoubleRawToken, nMemPoolDoubleRawToken )
116
117 // Need a whole bunch of ScSingleRefToken
118 const sal_uInt16 nMemPoolSingleRefToken = (0x4000 - 64) / sizeof(ScSingleRefToken);
119 IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken, nMemPoolSingleRefToken, nMemPoolSingleRefToken )
120 // Need quite a lot of ScDoubleRefToken
121 const sal_uInt16 nMemPoolDoubleRefToken = (0x2000 - 64) / sizeof(ScDoubleRefToken);
IMPL_FIXEDMEMPOOL_NEWDEL(ScDoubleRefToken,nMemPoolDoubleRefToken,nMemPoolDoubleRefToken)122 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken, nMemPoolDoubleRefToken, nMemPoolDoubleRefToken )
123
124 // --- helpers --------------------------------------------------------------
125
126 inline sal_Bool lcl_IsReference( OpCode eOp, StackVar eType )
127 {
128 return
129 (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
130 || (eOp == ocColRowNameAuto && eType == svDoubleRef)
131 || (eOp == ocColRowName && eType == svSingleRef)
132 || (eOp == ocMatRef && eType == svSingleRef)
133 ;
134 }
135
136
137 // --- class ScRawToken -----------------------------------------------------
138
GetStrLen(const sal_Unicode * pStr)139 xub_StrLen ScRawToken::GetStrLen( const sal_Unicode* pStr )
140 {
141 if ( !pStr )
142 return 0;
143 register const sal_Unicode* p = pStr;
144 while ( *p )
145 p++;
146 return sal::static_int_cast<xub_StrLen>( p - pStr );
147 }
148
149
SetOpCode(OpCode e)150 void ScRawToken::SetOpCode( OpCode e )
151 {
152 eOp = e;
153 switch (eOp)
154 {
155 case ocIf:
156 eType = svJump;
157 nJump[ 0 ] = 3; // If, Else, Behind
158 break;
159 case ocChose:
160 eType = svJump;
161 nJump[ 0 ] = MAXJUMPCOUNT+1;
162 break;
163 case ocMissing:
164 eType = svMissing;
165 break;
166 case ocSep:
167 case ocOpen:
168 case ocClose:
169 case ocArrayRowSep:
170 case ocArrayColSep:
171 case ocArrayOpen:
172 case ocArrayClose:
173 eType = svSep;
174 break;
175 default:
176 eType = svByte;
177 sbyte.cByte = 0;
178 sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
179 }
180 nRefCnt = 0;
181 }
182
SetString(const sal_Unicode * pStr)183 void ScRawToken::SetString( const sal_Unicode* pStr )
184 {
185 eOp = ocPush;
186 eType = svString;
187 if ( pStr )
188 {
189 xub_StrLen nLen = GetStrLen( pStr ) + 1;
190 if( nLen > MAXSTRLEN )
191 nLen = MAXSTRLEN;
192 memcpy( cStr, pStr, GetStrLenBytes( nLen ) );
193 cStr[ nLen-1 ] = 0;
194 }
195 else
196 cStr[0] = 0;
197 nRefCnt = 0;
198 }
199
SetSingleReference(const ScSingleRefData & rRef)200 void ScRawToken::SetSingleReference( const ScSingleRefData& rRef )
201 {
202 eOp = ocPush;
203 eType = svSingleRef;
204 aRef.Ref1 =
205 aRef.Ref2 = rRef;
206 nRefCnt = 0;
207 }
208
SetDoubleReference(const ScComplexRefData & rRef)209 void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef )
210 {
211 eOp = ocPush;
212 eType = svDoubleRef;
213 aRef = rRef;
214 nRefCnt = 0;
215 }
216
SetDouble(double rVal)217 void ScRawToken::SetDouble(double rVal)
218 {
219 eOp = ocPush;
220 eType = svDouble;
221 nValue = rVal;
222 nRefCnt = 0;
223 }
224
SetName(sal_uInt16 n)225 void ScRawToken::SetName( sal_uInt16 n )
226 {
227 eOp = ocName;
228 eType = svIndex;
229 nIndex = n;
230 nRefCnt = 0;
231 }
232
SetExternalSingleRef(sal_uInt16 nFileId,const String & rTabName,const ScSingleRefData & rRef)233 void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
234 {
235 eOp = ocExternalRef;
236 eType = svExternalSingleRef;
237 nRefCnt = 0;
238
239 extref.nFileId = nFileId;
240 extref.aRef.Ref1 =
241 extref.aRef.Ref2 = rRef;
242
243 xub_StrLen n = rTabName.Len();
244 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
245 extref.cTabName[n] = 0;
246 }
247
SetExternalDoubleRef(sal_uInt16 nFileId,const String & rTabName,const ScComplexRefData & rRef)248 void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
249 {
250 eOp = ocExternalRef;
251 eType = svExternalDoubleRef;
252 nRefCnt = 0;
253
254 extref.nFileId = nFileId;
255 extref.aRef = rRef;
256
257 xub_StrLen n = rTabName.Len();
258 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
259 extref.cTabName[n] = 0;
260 }
261
SetExternalName(sal_uInt16 nFileId,const String & rName)262 void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
263 {
264 eOp = ocExternalRef;
265 eType = svExternalName;
266 nRefCnt = 0;
267
268 extname.nFileId = nFileId;
269
270 xub_StrLen n = rName.Len();
271 memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode));
272 extname.cName[n] = 0;
273 }
274
275 //UNUSED2008-05 void ScRawToken::SetInt(int rVal)
276 //UNUSED2008-05 {
277 //UNUSED2008-05 eOp = ocPush;
278 //UNUSED2008-05 eType = svDouble;
279 //UNUSED2008-05 nValue = (double)rVal;
280 //UNUSED2008-05 nRefCnt = 0;
281 //UNUSED2008-05
282 //UNUSED2008-05 }
283 //UNUSED2008-05 void ScRawToken::SetMatrix( ScMatrix* p )
284 //UNUSED2008-05 {
285 //UNUSED2008-05 eOp = ocPush;
286 //UNUSED2008-05 eType = svMatrix;
287 //UNUSED2008-05 pMat = p;
288 //UNUSED2008-05 nRefCnt = 0;
289 //UNUSED2008-05 }
290 //UNUSED2008-05
291 //UNUSED2008-05 ScComplexRefData& ScRawToken::GetReference()
292 //UNUSED2008-05 {
293 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
294 //UNUSED2008-05 return aRef;
295 //UNUSED2008-05 }
296 //UNUSED2008-05
297 //UNUSED2008-05 void ScRawToken::SetReference( ScComplexRefData& rRef )
298 //UNUSED2008-05 {
299 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "SetReference: no Ref" );
300 //UNUSED2008-05 aRef = rRef;
301 //UNUSED2008-05 if( GetType() == svSingleRef )
302 //UNUSED2008-05 aRef.Ref2 = aRef.Ref1;
303 //UNUSED2008-05 }
304
SetExternal(const sal_Unicode * pStr)305 void ScRawToken::SetExternal( const sal_Unicode* pStr )
306 {
307 eOp = ocExternal;
308 eType = svExternal;
309 xub_StrLen nLen = GetStrLen( pStr ) + 1;
310 if( nLen >= MAXSTRLEN )
311 nLen = MAXSTRLEN-1;
312 // Platz fuer Byte-Parameter lassen!
313 memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
314 cStr[ nLen+1 ] = 0;
315 nRefCnt = 0;
316 }
317
lcl_ScRawTokenOffset()318 sal_uInt16 lcl_ScRawTokenOffset()
319 {
320 // offset of sbyte in ScRawToken
321 // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD
322
323 ScRawToken aToken;
324 return static_cast<sal_uInt16>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) );
325 }
326
Clone() const327 ScRawToken* ScRawToken::Clone() const
328 {
329 ScRawToken* p;
330 if ( eType == svDouble )
331 {
332 p = (ScRawToken*) new ScDoubleRawToken;
333 p->eOp = eOp;
334 p->eType = eType;
335 p->nValue = nValue;
336 }
337 else
338 {
339 static sal_uInt16 nOffset = lcl_ScRawTokenOffset(); // offset of sbyte
340 sal_uInt16 n = nOffset;
341
342 if (eOp == ocExternalRef)
343 {
344 switch (eType)
345 {
346 case svExternalSingleRef:
347 case svExternalDoubleRef: n += sizeof(extref); break;
348 case svExternalName: n += sizeof(extname); break;
349 default:
350 {
351 DBG_ERROR1( "unknown ScRawToken::Clone() external type %d", int(eType));
352 }
353 }
354 }
355 else
356 {
357 switch( eType )
358 {
359 case svSep: break;
360 case svByte: n += sizeof(ScRawToken::sbyte); break;
361 case svDouble: n += sizeof(double); break;
362 case svString: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
363 case svSingleRef:
364 case svDoubleRef: n += sizeof(aRef); break;
365 case svMatrix: n += sizeof(ScMatrix*); break;
366 case svIndex: n += sizeof(sal_uInt16); break;
367 case svJump: n += nJump[ 0 ] * 2 + 2; break;
368 case svExternal: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
369 default:
370 {
371 DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
372 }
373 }
374 }
375 p = (ScRawToken*) new sal_uInt8[ n ];
376 memcpy( p, this, n * sizeof(sal_uInt8) );
377 }
378 p->nRefCnt = 0;
379 p->bRaw = sal_False;
380 return p;
381 }
382
383
CreateToken() const384 FormulaToken* ScRawToken::CreateToken() const
385 {
386 #ifdef DBG_UTIL
387 #define IF_NOT_OPCODE_ERROR(o,c) if (eOp!=o) DBG_ERROR1( #c "::ctor: OpCode %d lost, converted to " #o "; maybe inherit from FormulaToken instead!", int(eOp))
388 #else
389 #define IF_NOT_OPCODE_ERROR(o,c)
390 #endif
391 switch ( GetType() )
392 {
393 case svByte :
394 return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
395 case svDouble :
396 IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken);
397 return new FormulaDoubleToken( nValue );
398 case svString :
399 if (eOp == ocPush)
400 return new FormulaStringToken( String( cStr ) );
401 else
402 return new FormulaStringOpToken( eOp, String( cStr ) );
403 case svSingleRef :
404 if (eOp == ocPush)
405 return new ScSingleRefToken( aRef.Ref1 );
406 else
407 return new ScSingleRefToken( aRef.Ref1, eOp );
408 case svDoubleRef :
409 if (eOp == ocPush)
410 return new ScDoubleRefToken( aRef );
411 else
412 return new ScDoubleRefToken( aRef, eOp );
413 case svMatrix :
414 IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
415 return new ScMatrixToken( pMat );
416 case svIndex :
417 return new FormulaIndexToken( eOp, nIndex );
418 case svExternalSingleRef:
419 {
420 String aTabName(extref.cTabName);
421 return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
422 }
423 case svExternalDoubleRef:
424 {
425 String aTabName(extref.cTabName);
426 return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
427 }
428 case svExternalName:
429 {
430 String aName(extname.cName);
431 return new ScExternalNameToken( extname.nFileId, aName );
432 }
433 case svJump :
434 return new FormulaJumpToken( eOp, (short*) nJump );
435 case svExternal :
436 return new FormulaExternalToken( eOp, sbyte.cByte, String( cStr+1 ) );
437 case svFAP :
438 return new FormulaFAPToken( eOp, sbyte.cByte, NULL );
439 case svMissing :
440 IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken);
441 return new FormulaMissingToken;
442 case svSep :
443 return new FormulaToken( svSep,eOp );
444 case svUnknown :
445 return new FormulaUnknownToken( eOp );
446 default:
447 {
448 DBG_ERROR1( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
449 return new FormulaUnknownToken( ocBad );
450 }
451 }
452 #undef IF_NOT_OPCODE_ERROR
453 }
454
455
Delete()456 void ScRawToken::Delete()
457 {
458 if ( bRaw )
459 delete this; // FixedMemPool ScRawToken
460 else
461 { // created per Clone
462 switch ( eType )
463 {
464 case svDouble :
465 delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken
466 break;
467 default:
468 delete [] (sal_uInt8*) this;
469 }
470 }
471 }
472
473
474 // --- class ScToken --------------------------------------------------------
475
lcl_ScToken_InitSingleRef()476 ScSingleRefData lcl_ScToken_InitSingleRef()
477 {
478 ScSingleRefData aRef;
479 aRef.InitAddress( ScAddress() );
480 return aRef;
481 }
482
lcl_ScToken_InitDoubleRef()483 ScComplexRefData lcl_ScToken_InitDoubleRef()
484 {
485 ScComplexRefData aRef;
486 aRef.Ref1 = lcl_ScToken_InitSingleRef();
487 aRef.Ref2 = aRef.Ref1;
488 return aRef;
489 }
490
~ScToken()491 ScToken::~ScToken()
492 {
493 }
494
495 // TextEqual: if same formula entered (for optimization in sort)
TextEqual(const FormulaToken & _rToken) const496 sal_Bool ScToken::TextEqual( const FormulaToken& _rToken ) const
497 {
498 if ( eType == svSingleRef || eType == svDoubleRef )
499 {
500 // in relative Refs only compare relative parts
501
502 if ( eType != _rToken.GetType() || GetOpCode() != _rToken.GetOpCode() )
503 return sal_False;
504
505 const ScToken& rToken = static_cast<const ScToken&>(_rToken);
506 ScComplexRefData aTemp1;
507 if ( eType == svSingleRef )
508 {
509 aTemp1.Ref1 = GetSingleRef();
510 aTemp1.Ref2 = aTemp1.Ref1;
511 }
512 else
513 aTemp1 = GetDoubleRef();
514
515 ScComplexRefData aTemp2;
516 if ( rToken.eType == svSingleRef )
517 {
518 aTemp2.Ref1 = rToken.GetSingleRef();
519 aTemp2.Ref2 = aTemp2.Ref1;
520 }
521 else
522 aTemp2 = rToken.GetDoubleRef();
523
524 ScAddress aPos;
525 aTemp1.SmartRelAbs(aPos);
526 aTemp2.SmartRelAbs(aPos);
527
528 // memcmp doesn't work because of the alignment byte after bFlags.
529 // After SmartRelAbs only absolute parts have to be compared.
530 return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol &&
531 aTemp1.Ref1.nRow == aTemp2.Ref1.nRow &&
532 aTemp1.Ref1.nTab == aTemp2.Ref1.nTab &&
533 aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags &&
534 aTemp1.Ref2.nCol == aTemp2.Ref2.nCol &&
535 aTemp1.Ref2.nRow == aTemp2.Ref2.nRow &&
536 aTemp1.Ref2.nTab == aTemp2.Ref2.nTab &&
537 aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags;
538 }
539 else
540 return *this == _rToken; // else normal operator==
541 }
542
543
Is3DRef() const544 sal_Bool ScToken::Is3DRef() const
545 {
546 switch ( eType )
547 {
548 case svDoubleRef :
549 if ( GetSingleRef2().IsFlag3D() )
550 return sal_True;
551 //! fallthru
552 case svSingleRef :
553 if ( GetSingleRef().IsFlag3D() )
554 return sal_True;
555 break;
556 case svExternalSingleRef:
557 case svExternalDoubleRef:
558 return sal_True;
559 default:
560 {
561 // added to avoid warnings
562 }
563 }
564 return sal_False;
565 }
566
567 // static
ExtendRangeReference(FormulaToken & rTok1,FormulaToken & rTok2,const ScAddress & rPos,bool bReuseDoubleRef)568 FormulaTokenRef ScToken::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2,
569 const ScAddress & rPos, bool bReuseDoubleRef )
570 {
571
572 StackVar sv1, sv2;
573 // Doing a RangeOp with RefList is probably utter nonsense, but Xcl
574 // supports it, so do we.
575 if (((sv1 = rTok1.GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList &&
576 sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef ) ||
577 ((sv2 = rTok2.GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
578 return NULL;
579
580 ScToken *p1 = static_cast<ScToken*>(&rTok1);
581 ScToken *p2 = static_cast<ScToken*>(&rTok2);
582
583 ScTokenRef xRes;
584 bool bExternal = (sv1 == svExternalSingleRef);
585 if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
586 {
587 // Range references like Sheet1.A1:A2 are generalized and built by
588 // first creating a DoubleRef from the first SingleRef, effectively
589 // generating Sheet1.A1:A1, and then extending that with A2 as if
590 // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
591 // references apply as well.
592
593 /* Given the current structure of external references an external
594 * reference can only be extended if the second reference does not
595 * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
596 * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
597 * svSingleRef whether the sheet would be different from the one given
598 * in the external reference, we have to bail out if there is any sheet
599 * specified. NOTE: Xcl does handle external 3D references as in
600 * '[file]Sheet1:Sheet2'!A1:A2
601 *
602 * FIXME: For OOo syntax be smart and remember an external singleref
603 * encountered and if followed by ocRange and singleref, create an
604 * external singleref for the second singleref. Both could then be
605 * merged here. For Xcl syntax already parse an external range
606 * reference entirely, cumbersome. */
607
608 const ScSingleRefData& rRef2 = p2->GetSingleRef();
609 if (bExternal && rRef2.IsFlag3D())
610 return NULL;
611
612 ScComplexRefData aRef;
613 aRef.Ref1 = aRef.Ref2 = p1->GetSingleRef();
614 aRef.Ref2.SetFlag3D( false);
615 aRef.Extend( rRef2, rPos);
616 if (bExternal)
617 xRes = new ScExternalDoubleRefToken( p1->GetIndex(), p1->GetString(), aRef);
618 else
619 xRes = new ScDoubleRefToken( aRef);
620 }
621 else
622 {
623 bExternal |= (sv1 == svExternalDoubleRef);
624 const ScRefList* pRefList = NULL;
625 if (sv1 == svDoubleRef)
626 {
627 xRes = (bReuseDoubleRef && p1->GetRef() == 1 ? p1 : static_cast<ScToken*>(p1->Clone()));
628 sv1 = svUnknown; // mark as handled
629 }
630 else if (sv2 == svDoubleRef)
631 {
632 xRes = (bReuseDoubleRef && p2->GetRef() == 1 ? p2 : static_cast<ScToken*>(p2->Clone()));
633 sv2 = svUnknown; // mark as handled
634 }
635 else if (sv1 == svRefList)
636 pRefList = p1->GetRefList();
637 else if (sv2 == svRefList)
638 pRefList = p2->GetRefList();
639 if (pRefList)
640 {
641 if (!pRefList->size())
642 return NULL;
643 if (bExternal)
644 return NULL; // external reference list not possible
645 xRes = new ScDoubleRefToken( (*pRefList)[0] );
646 }
647 if (!xRes)
648 return NULL; // shouldn't happen..
649 StackVar sv[2] = { sv1, sv2 };
650 ScToken* pt[2] = { p1, p2 };
651 ScComplexRefData& rRef = xRes->GetDoubleRef();
652 for (size_t i=0; i<2; ++i)
653 {
654 switch (sv[i])
655 {
656 case svSingleRef:
657 rRef.Extend( pt[i]->GetSingleRef(), rPos);
658 break;
659 case svDoubleRef:
660 rRef.Extend( pt[i]->GetDoubleRef(), rPos);
661 break;
662 case svRefList:
663 {
664 const ScRefList* p = pt[i]->GetRefList();
665 if (!p->size())
666 return NULL;
667 ScRefList::const_iterator it( p->begin());
668 ScRefList::const_iterator end( p->end());
669 for ( ; it != end; ++it)
670 {
671 rRef.Extend( *it, rPos);
672 }
673 }
674 break;
675 case svExternalSingleRef:
676 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
677 return NULL; // no other sheets with external refs
678 else
679 rRef.Extend( pt[i]->GetSingleRef(), rPos);
680 break;
681 case svExternalDoubleRef:
682 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
683 return NULL; // no other sheets with external refs
684 else
685 rRef.Extend( pt[i]->GetDoubleRef(), rPos);
686 break;
687 default:
688 ; // nothing, prevent compiler warning
689 }
690 }
691 }
692 return FormulaTokenRef(xRes.get());
693 }
694
GetSingleRef() const695 const ScSingleRefData& ScToken::GetSingleRef() const
696 {
697 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
698 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
699 return aDummySingleRef;
700 }
701
GetSingleRef()702 ScSingleRefData& ScToken::GetSingleRef()
703 {
704 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
705 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
706 return aDummySingleRef;
707 }
708
GetDoubleRef() const709 const ScComplexRefData& ScToken::GetDoubleRef() const
710 {
711 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
712 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
713 return aDummyDoubleRef;
714 }
715
GetDoubleRef()716 ScComplexRefData& ScToken::GetDoubleRef()
717 {
718 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
719 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
720 return aDummyDoubleRef;
721 }
722
GetSingleRef2() const723 const ScSingleRefData& ScToken::GetSingleRef2() const
724 {
725 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
726 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
727 return aDummySingleRef;
728 }
729
GetSingleRef2()730 ScSingleRefData& ScToken::GetSingleRef2()
731 {
732 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
733 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
734 return aDummySingleRef;
735 }
736
CalcAbsIfRel(const ScAddress &)737 void ScToken::CalcAbsIfRel( const ScAddress& /* rPos */ )
738 {
739 DBG_ERRORFILE( "ScToken::CalcAbsIfRel: virtual dummy called" );
740 }
741
CalcRelFromAbs(const ScAddress &)742 void ScToken::CalcRelFromAbs( const ScAddress& /* rPos */ )
743 {
744 DBG_ERRORFILE( "ScToken::CalcRelFromAbs: virtual dummy called" );
745 }
746
GetMatrix() const747 const ScMatrix* ScToken::GetMatrix() const
748 {
749 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" );
750 return NULL;
751 }
752
GetMatrix()753 ScMatrix* ScToken::GetMatrix()
754 {
755 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" );
756 return NULL;
757 }
758
759
GetJumpMatrix() const760 ScJumpMatrix* ScToken::GetJumpMatrix() const
761 {
762 DBG_ERRORFILE( "ScToken::GetJumpMatrix: virtual dummy called" );
763 return NULL;
764 }
GetRefList() const765 const ScRefList* ScToken::GetRefList() const
766 {
767 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" );
768 return NULL;
769 }
770
GetRefList()771 ScRefList* ScToken::GetRefList()
772 {
773 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" );
774 return NULL;
775 }
776 // ==========================================================================
777 // real implementations of virtual functions
778 // --------------------------------------------------------------------------
779
780
781
782
GetSingleRef() const783 const ScSingleRefData& ScSingleRefToken::GetSingleRef() const { return aSingleRef; }
GetSingleRef()784 ScSingleRefData& ScSingleRefToken::GetSingleRef() { return aSingleRef; }
CalcAbsIfRel(const ScAddress & rPos)785 void ScSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
786 { aSingleRef.CalcAbsIfRel( rPos ); }
CalcRelFromAbs(const ScAddress & rPos)787 void ScSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
788 { aSingleRef.CalcRelFromAbs( rPos ); }
operator ==(const FormulaToken & r) const789 sal_Bool ScSingleRefToken::operator==( const FormulaToken& r ) const
790 {
791 return FormulaToken::operator==( r ) && aSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
792 }
793
794
GetSingleRef() const795 const ScSingleRefData& ScDoubleRefToken::GetSingleRef() const { return aDoubleRef.Ref1; }
GetSingleRef()796 ScSingleRefData& ScDoubleRefToken::GetSingleRef() { return aDoubleRef.Ref1; }
GetDoubleRef() const797 const ScComplexRefData& ScDoubleRefToken::GetDoubleRef() const { return aDoubleRef; }
GetDoubleRef()798 ScComplexRefData& ScDoubleRefToken::GetDoubleRef() { return aDoubleRef; }
GetSingleRef2() const799 const ScSingleRefData& ScDoubleRefToken::GetSingleRef2() const { return aDoubleRef.Ref2; }
GetSingleRef2()800 ScSingleRefData& ScDoubleRefToken::GetSingleRef2() { return aDoubleRef.Ref2; }
CalcAbsIfRel(const ScAddress & rPos)801 void ScDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
802 { aDoubleRef.CalcAbsIfRel( rPos ); }
CalcRelFromAbs(const ScAddress & rPos)803 void ScDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
804 { aDoubleRef.CalcRelFromAbs( rPos ); }
operator ==(const FormulaToken & r) const805 sal_Bool ScDoubleRefToken::operator==( const FormulaToken& r ) const
806 {
807 return FormulaToken::operator==( r ) && aDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
808 }
809
810
GetRefList() const811 const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; }
GetRefList()812 ScRefList* ScRefListToken::GetRefList() { return &aRefList; }
CalcAbsIfRel(const ScAddress & rPos)813 void ScRefListToken::CalcAbsIfRel( const ScAddress& rPos )
814 {
815 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
816 (*it).CalcAbsIfRel( rPos);
817 }
CalcRelFromAbs(const ScAddress & rPos)818 void ScRefListToken::CalcRelFromAbs( const ScAddress& rPos )
819 {
820 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
821 (*it).CalcRelFromAbs( rPos);
822 }
operator ==(const FormulaToken & r) const823 sal_Bool ScRefListToken::operator==( const FormulaToken& r ) const
824 {
825 return FormulaToken::operator==( r ) && &aRefList == static_cast<const ScToken&>(r).GetRefList();
826 }
827
828
GetMatrix() const829 const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix; }
GetMatrix()830 ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix; }
operator ==(const FormulaToken & r) const831 sal_Bool ScMatrixToken::operator==( const FormulaToken& r ) const
832 {
833 return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
834 }
835
836 // ============================================================================
837
ScExternalSingleRefToken(sal_uInt16 nFileId,const String & rTabName,const ScSingleRefData & r)838 ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :
839 ScToken( svExternalSingleRef, ocExternalRef),
840 mnFileId(nFileId),
841 maTabName(rTabName),
842 maSingleRef(r)
843 {
844 }
845
ScExternalSingleRefToken(const ScExternalSingleRefToken & r)846 ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
847 ScToken(r),
848 mnFileId(r.mnFileId),
849 maTabName(r.maTabName),
850 maSingleRef(r.maSingleRef)
851 {
852 }
853
~ScExternalSingleRefToken()854 ScExternalSingleRefToken::~ScExternalSingleRefToken()
855 {
856 }
857
GetIndex() const858 sal_uInt16 ScExternalSingleRefToken::GetIndex() const
859 {
860 return mnFileId;
861 }
862
GetString() const863 const String& ScExternalSingleRefToken::GetString() const
864 {
865 return maTabName;
866 }
867
GetSingleRef() const868 const ScSingleRefData& ScExternalSingleRefToken::GetSingleRef() const
869 {
870 return maSingleRef;
871 }
872
GetSingleRef()873 ScSingleRefData& ScExternalSingleRefToken::GetSingleRef()
874 {
875 return maSingleRef;
876 }
877
CalcAbsIfRel(const ScAddress & rPos)878 void ScExternalSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
879 {
880 maSingleRef.CalcAbsIfRel( rPos );
881 }
882
CalcRelFromAbs(const ScAddress & rPos)883 void ScExternalSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
884 {
885 maSingleRef.CalcRelFromAbs( rPos );
886 }
887
operator ==(const FormulaToken & r) const888 sal_Bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
889 {
890 if (!FormulaToken::operator==(r))
891 return false;
892
893 if (mnFileId != r.GetIndex())
894 return false;
895
896 if (maTabName != r.GetString())
897 return false;
898
899 return maSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
900 }
901
902 // ============================================================================
903
ScExternalDoubleRefToken(sal_uInt16 nFileId,const String & rTabName,const ScComplexRefData & r)904 ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ) :
905 ScToken( svExternalDoubleRef, ocExternalRef),
906 mnFileId(nFileId),
907 maTabName(rTabName),
908 maDoubleRef(r)
909 {
910 }
911
ScExternalDoubleRefToken(const ScExternalDoubleRefToken & r)912 ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
913 ScToken(r),
914 mnFileId(r.mnFileId),
915 maTabName(r.maTabName),
916 maDoubleRef(r.maDoubleRef)
917 {
918 }
919
ScExternalDoubleRefToken(const ScExternalSingleRefToken & r)920 ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalSingleRefToken& r ) :
921 ScToken( svExternalDoubleRef, ocExternalRef),
922 mnFileId( r.GetIndex()),
923 maTabName( r.GetString())
924 {
925 maDoubleRef.Ref1 = maDoubleRef.Ref2 = r.GetSingleRef();
926 }
927
~ScExternalDoubleRefToken()928 ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
929 {
930 }
931
GetIndex() const932 sal_uInt16 ScExternalDoubleRefToken::GetIndex() const
933 {
934 return mnFileId;
935 }
936
GetString() const937 const String& ScExternalDoubleRefToken::GetString() const
938 {
939 return maTabName;
940 }
941
GetSingleRef() const942 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef() const
943 {
944 return maDoubleRef.Ref1;
945 }
946
GetSingleRef()947 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef()
948 {
949 return maDoubleRef.Ref1;
950 }
951
GetSingleRef2() const952 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2() const
953 {
954 return maDoubleRef.Ref2;
955 }
956
GetSingleRef2()957 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2()
958 {
959 return maDoubleRef.Ref2;
960 }
961
GetDoubleRef() const962 const ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef() const
963 {
964 return maDoubleRef;
965 }
966
GetDoubleRef()967 ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef()
968 {
969 return maDoubleRef;
970 }
971
CalcAbsIfRel(const ScAddress & rPos)972 void ScExternalDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
973 {
974 maDoubleRef.CalcAbsIfRel( rPos );
975 }
976
CalcRelFromAbs(const ScAddress & rPos)977 void ScExternalDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
978 {
979 maDoubleRef.CalcRelFromAbs( rPos );
980 }
981
operator ==(const FormulaToken & r) const982 sal_Bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
983 {
984 if (!ScToken::operator==(r))
985 return false;
986
987 if (mnFileId != r.GetIndex())
988 return false;
989
990 if (maTabName != r.GetString())
991 return false;
992
993 return maDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
994 }
995
996 // ============================================================================
997
ScExternalNameToken(sal_uInt16 nFileId,const String & rName)998 ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
999 ScToken( svExternalName, ocExternalRef),
1000 mnFileId(nFileId),
1001 maName(rName)
1002 {
1003 }
1004
ScExternalNameToken(const ScExternalNameToken & r)1005 ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
1006 ScToken(r),
1007 mnFileId(r.mnFileId),
1008 maName(r.maName)
1009 {
1010 }
1011
~ScExternalNameToken()1012 ScExternalNameToken::~ScExternalNameToken() {}
1013
GetIndex() const1014 sal_uInt16 ScExternalNameToken::GetIndex() const
1015 {
1016 return mnFileId;
1017 }
1018
GetString() const1019 const String& ScExternalNameToken::GetString() const
1020 {
1021 return maName;
1022 }
1023
operator ==(const FormulaToken & r) const1024 sal_Bool ScExternalNameToken::operator==( const FormulaToken& r ) const
1025 {
1026 if ( !FormulaToken::operator==(r) )
1027 return false;
1028
1029 if (mnFileId != r.GetIndex())
1030 return false;
1031
1032 xub_StrLen nLen = maName.Len();
1033 const String& rName = r.GetString();
1034 if (nLen != rName.Len())
1035 return false;
1036
1037 const sal_Unicode* p1 = maName.GetBuffer();
1038 const sal_Unicode* p2 = rName.GetBuffer();
1039 for (xub_StrLen j = 0; j < nLen; ++j)
1040 {
1041 if (p1[j] != p2[j])
1042 return false;
1043 }
1044 return true;
1045 }
1046
1047 // ============================================================================
1048
GetJumpMatrix() const1049 ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; }
operator ==(const FormulaToken & r) const1050 sal_Bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const
1051 {
1052 return FormulaToken::operator==( r ) && pJumpMatrix == static_cast<const ScToken&>(r).GetJumpMatrix();
1053 }
~ScJumpMatrixToken()1054 ScJumpMatrixToken::~ScJumpMatrixToken()
1055 {
1056 delete pJumpMatrix;
1057 }
1058
GetDouble() const1059 double ScEmptyCellToken::GetDouble() const { return 0.0; }
GetString() const1060 const String & ScEmptyCellToken::GetString() const
1061 {
1062 static String aDummyString;
1063 return aDummyString;
1064 }
operator ==(const FormulaToken & r) const1065 sal_Bool ScEmptyCellToken::operator==( const FormulaToken& r ) const
1066 {
1067 return FormulaToken::operator==( r ) &&
1068 bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
1069 bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
1070 }
1071
1072
GetDouble() const1073 double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); }
GetString() const1074 const String & ScMatrixCellResultToken::GetString() const { return xUpperLeft->GetString(); }
GetMatrix() const1075 const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix; }
1076 // Non-const GetMatrix() is private and unused but must be implemented to
1077 // satisfy vtable linkage.
GetMatrix()1078 ScMatrix* ScMatrixCellResultToken::GetMatrix()
1079 {
1080 return const_cast<ScMatrix*>(xMatrix.operator->());
1081 }
operator ==(const FormulaToken & r) const1082 sal_Bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
1083 {
1084 return FormulaToken::operator==( r ) &&
1085 xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
1086 xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
1087 }
1088
1089
operator ==(const FormulaToken & r) const1090 sal_Bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
1091 {
1092 const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
1093 return p && ScMatrixCellResultToken::operator==( r ) &&
1094 nCols == p->nCols && nRows == p->nRows;
1095 }
Assign(const formula::FormulaToken & r)1096 void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
1097 {
1098 if (this == &r)
1099 return;
1100 const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
1101 if (p)
1102 ScMatrixCellResultToken::Assign( *p);
1103 else
1104 {
1105 DBG_ASSERT( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1106 if (r.GetType() == svMatrix)
1107 {
1108 xUpperLeft = NULL;
1109 xMatrix = static_cast<const ScToken&>(r).GetMatrix();
1110 }
1111 else
1112 {
1113 xUpperLeft = &r;
1114 xMatrix = NULL;
1115 }
1116 }
1117 }
SetUpperLeftDouble(double f)1118 void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f )
1119 {
1120 switch (GetUpperLeftType())
1121 {
1122 case svDouble:
1123 const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
1124 break;
1125 case svUnknown:
1126 if (!xUpperLeft)
1127 {
1128 xUpperLeft = new FormulaDoubleToken( f);
1129 break;
1130 }
1131 // fall thru
1132 default:
1133 {
1134 DBG_ERRORFILE("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1135 }
1136 }
1137 }
1138
1139
GetDouble() const1140 double ScHybridCellToken::GetDouble() const { return fDouble; }
GetString() const1141 const String & ScHybridCellToken::GetString() const { return aString; }
operator ==(const FormulaToken & r) const1142 sal_Bool ScHybridCellToken::operator==( const FormulaToken& r ) const
1143 {
1144 return FormulaToken::operator==( r ) &&
1145 fDouble == r.GetDouble() && aString == r.GetString() &&
1146 aFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
1147 }
1148
1149
1150
1151
1152 //////////////////////////////////////////////////////////////////////////
1153
AddFormulaToken(const com::sun::star::sheet::FormulaToken & _aToken,formula::ExternalReferenceHelper * _pRef)1154 bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef)
1155 {
1156 bool bError = FormulaTokenArray::AddFormulaToken(_aToken,_pRef);
1157 if ( bError )
1158 {
1159 bError = false;
1160 const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment
1161
1162 const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
1163 switch ( eClass )
1164 {
1165 case uno::TypeClass_STRUCT:
1166 {
1167 uno::Type aType = _aToken.Data.getValueType();
1168 if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
1169 {
1170 ScSingleRefData aSingleRef;
1171 sheet::SingleReference aApiRef;
1172 _aToken.Data >>= aApiRef;
1173 lcl_SingleRefToCalc( aSingleRef, aApiRef );
1174 if ( eOpCode == ocPush )
1175 AddSingleReference( aSingleRef );
1176 else if ( eOpCode == ocColRowName )
1177 AddColRowName( aSingleRef );
1178 else
1179 bError = true;
1180 }
1181 else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
1182 {
1183 ScComplexRefData aComplRef;
1184 sheet::ComplexReference aApiRef;
1185 _aToken.Data >>= aApiRef;
1186 lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
1187 lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
1188
1189 if ( eOpCode == ocPush )
1190 AddDoubleReference( aComplRef );
1191 else
1192 bError = true;
1193 }
1194 else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
1195 {
1196 sheet::ExternalReference aApiExtRef;
1197 if( (eOpCode == ocPush) && (_aToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
1198 {
1199 sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
1200 sheet::SingleReference aApiSRef;
1201 sheet::ComplexReference aApiCRef;
1202 ::rtl::OUString aName;
1203 if( aApiExtRef.Reference >>= aApiSRef )
1204 {
1205 // try to resolve cache index to sheet name
1206 size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
1207 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1208 if( aTabName.Len() > 0 )
1209 {
1210 ScSingleRefData aSingleRef;
1211 // convert column/row settings, set sheet index to absolute
1212 lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1213 AddExternalSingleReference( nFileId, aTabName, aSingleRef );
1214 }
1215 else
1216 bError = true;
1217 }
1218 else if( aApiExtRef.Reference >>= aApiCRef )
1219 {
1220 // try to resolve cache index to sheet name.
1221 size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
1222 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1223 if( aTabName.Len() > 0 )
1224 {
1225 ScComplexRefData aComplRef;
1226 // convert column/row settings, set sheet index to absolute
1227 lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
1228 lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
1229 // NOTE: This assumes that cached sheets are in consecutive order!
1230 aComplRef.Ref2.nTab = aComplRef.Ref1.nTab + static_cast<SCsTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet);
1231 AddExternalDoubleReference( nFileId, aTabName, aComplRef );
1232 }
1233 else
1234 bError = true;
1235 }
1236 else if( aApiExtRef.Reference >>= aName )
1237 {
1238 if( aName.getLength() > 0 )
1239 AddExternalName( nFileId, aName );
1240 else
1241 bError = true;
1242 }
1243 else
1244 bError = true;
1245 }
1246 else
1247 bError = true;
1248 }
1249 else
1250 bError = true; // unknown struct
1251 }
1252 break;
1253 case uno::TypeClass_SEQUENCE:
1254 {
1255 if ( eOpCode != ocPush )
1256 bError = true; // not an inline array
1257 else if (!_aToken.Data.getValueType().equals( getCppuType(
1258 (uno::Sequence< uno::Sequence< uno::Any > > *)0)))
1259 bError = true; // unexpected sequence type
1260 else
1261 {
1262 ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( _aToken.Data);
1263 if (xMat)
1264 AddMatrix( xMat);
1265 else
1266 bError = true;
1267 }
1268 }
1269 break;
1270 default:
1271 bError = true;
1272 }
1273 }
1274 return bError;
1275 }
ImplGetReference(ScRange & rRange,sal_Bool bValidOnly) const1276 sal_Bool ScTokenArray::ImplGetReference( ScRange& rRange, sal_Bool bValidOnly ) const
1277 {
1278 sal_Bool bIs = sal_False;
1279 if ( pCode && nLen == 1 )
1280 {
1281 const FormulaToken* pToken = pCode[0];
1282 if ( pToken )
1283 {
1284 if ( pToken->GetType() == svSingleRef )
1285 {
1286 const ScSingleRefData& rRef = ((const ScSingleRefToken*)pToken)->GetSingleRef();
1287 rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab );
1288 bIs = !bValidOnly || !rRef.IsDeleted();
1289 }
1290 else if ( pToken->GetType() == svDoubleRef )
1291 {
1292 const ScComplexRefData& rCompl = ((const ScDoubleRefToken*)pToken)->GetDoubleRef();
1293 const ScSingleRefData& rRef1 = rCompl.Ref1;
1294 const ScSingleRefData& rRef2 = rCompl.Ref2;
1295 rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab );
1296 rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab );
1297 bIs = !bValidOnly || (!rRef1.IsDeleted() && !rRef2.IsDeleted());
1298 }
1299 }
1300 }
1301 return bIs;
1302 }
1303
IsReference(ScRange & rRange) const1304 sal_Bool ScTokenArray::IsReference( ScRange& rRange ) const
1305 {
1306 return ImplGetReference( rRange, sal_False );
1307 }
1308
IsValidReference(ScRange & rRange) const1309 sal_Bool ScTokenArray::IsValidReference( ScRange& rRange ) const
1310 {
1311 return ImplGetReference( rRange, sal_True );
1312 }
1313
1314 ////////////////////////////////////////////////////////////////////////////
1315
ScTokenArray()1316 ScTokenArray::ScTokenArray()
1317 {
1318 }
1319
ScTokenArray(const ScTokenArray & rArr)1320 ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) : FormulaTokenArray(rArr)
1321 {
1322 }
1323
~ScTokenArray()1324 ScTokenArray::~ScTokenArray()
1325 {
1326 }
1327
1328
1329
operator =(const ScTokenArray & rArr)1330 ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
1331 {
1332 Clear();
1333 Assign( rArr );
1334 return *this;
1335 }
1336
Clone() const1337 ScTokenArray* ScTokenArray::Clone() const
1338 {
1339 ScTokenArray* p = new ScTokenArray();
1340 p->nLen = nLen;
1341 p->nRPN = nRPN;
1342 p->nRefs = nRefs;
1343 p->nMode = nMode;
1344 p->nError = nError;
1345 p->bHyperLink = bHyperLink;
1346 FormulaToken** pp;
1347 if( nLen )
1348 {
1349 pp = p->pCode = new FormulaToken*[ nLen ];
1350 memcpy( pp, pCode, nLen * sizeof( ScToken* ) );
1351 for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
1352 {
1353 *pp = (*pp)->Clone();
1354 (*pp)->IncRef();
1355 }
1356 }
1357 if( nRPN )
1358 {
1359 pp = p->pRPN = new FormulaToken*[ nRPN ];
1360 memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) );
1361 for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
1362 {
1363 FormulaToken* t = *pp;
1364 if( t->GetRef() > 1 )
1365 {
1366 FormulaToken** p2 = pCode;
1367 sal_uInt16 nIdx = 0xFFFF;
1368 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
1369 {
1370 if( *p2 == t )
1371 {
1372 nIdx = j; break;
1373 }
1374 }
1375 if( nIdx == 0xFFFF )
1376 *pp = t->Clone();
1377 else
1378 *pp = p->pCode[ nIdx ];
1379 }
1380 else
1381 *pp = t->Clone();
1382 (*pp)->IncRef();
1383 }
1384 }
1385 return p;
1386 }
1387
AddRawToken(const ScRawToken & r)1388 FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
1389 {
1390 return Add( r.CreateToken() );
1391 }
1392
1393 // Utility function to ensure that there is strict alternation of values and
1394 // seperators.
1395 static bool
checkArraySep(bool & bPrevWasSep,bool bNewVal)1396 checkArraySep( bool & bPrevWasSep, bool bNewVal )
1397 {
1398 bool bResult = (bPrevWasSep == bNewVal);
1399 bPrevWasSep = bNewVal;
1400 return bResult;
1401 }
1402
MergeArray()1403 FormulaToken* ScTokenArray::MergeArray( )
1404 {
1405 int nCol = -1, nRow = 0;
1406 int i, nPrevRowSep = -1, nStart = 0;
1407 bool bPrevWasSep = false; // top of stack is ocArrayClose
1408 FormulaToken* t;
1409 bool bNumeric = false; // numeric value encountered in current element
1410
1411 // (1) Iterate from the end to the start to find matrix dims
1412 // and do basic validation.
1413 for ( i = nLen ; i-- > nStart ; )
1414 {
1415 t = pCode[i];
1416 switch ( t->GetOpCode() )
1417 {
1418 case ocPush :
1419 if( checkArraySep( bPrevWasSep, false ) )
1420 {
1421 return NULL;
1422 }
1423
1424 // no references or nested arrays
1425 if ( t->GetType() != svDouble && t->GetType() != svString )
1426 {
1427 return NULL;
1428 }
1429 bNumeric = (t->GetType() == svDouble);
1430 break;
1431
1432 case ocMissing :
1433 case ocTrue :
1434 case ocFalse :
1435 if( checkArraySep( bPrevWasSep, false ) )
1436 {
1437 return NULL;
1438 }
1439 bNumeric = false;
1440 break;
1441
1442 case ocArrayColSep :
1443 case ocSep :
1444 if( checkArraySep( bPrevWasSep, true ) )
1445 {
1446 return NULL;
1447 }
1448 bNumeric = false;
1449 break;
1450
1451 case ocArrayClose :
1452 // not possible with the , but check just in case
1453 // something changes in the future
1454 if( i != (nLen-1))
1455 {
1456 return NULL;
1457 }
1458
1459 if( checkArraySep( bPrevWasSep, true ) )
1460 {
1461 return NULL;
1462 }
1463
1464 nPrevRowSep = i;
1465 bNumeric = false;
1466 break;
1467
1468 case ocArrayOpen :
1469 nStart = i; // stop iteration
1470 // fall through to ArrayRowSep
1471
1472 case ocArrayRowSep :
1473 if( checkArraySep( bPrevWasSep, true ) )
1474 {
1475 return NULL;
1476 }
1477
1478 if( nPrevRowSep < 0 || // missing ocArrayClose
1479 ((nPrevRowSep - i) % 2) == 1) // no complex elements
1480 {
1481 return NULL;
1482 }
1483
1484 if( nCol < 0 )
1485 {
1486 nCol = (nPrevRowSep - i) / 2;
1487 }
1488 else if( (nPrevRowSep - i)/2 != nCol) // irregular array
1489 {
1490 return NULL;
1491 }
1492
1493 nPrevRowSep = i;
1494 nRow++;
1495 bNumeric = false;
1496 break;
1497
1498 case ocNegSub :
1499 case ocAdd :
1500 // negation or unary plus must precede numeric value
1501 if( !bNumeric )
1502 {
1503 return NULL;
1504 }
1505 --nPrevRowSep; // shorten this row by 1
1506 bNumeric = false; // one level only, no --42
1507 break;
1508
1509 case ocSpaces :
1510 // ignore spaces
1511 --nPrevRowSep; // shorten this row by 1
1512 break;
1513
1514 default :
1515 // no functions or operators
1516 return NULL;
1517 }
1518 }
1519 if( nCol <= 0 || nRow <= 0 )
1520 return NULL;
1521
1522 // fprintf (stderr, "Array (cols = %d, rows = %d)\n", nCol, nRow );
1523
1524 int nSign = 1;
1525 ScMatrix* pArray = new ScMatrix( nCol, nRow );
1526 for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
1527 {
1528 t = pCode[i];
1529
1530 switch ( t->GetOpCode() )
1531 {
1532 case ocPush :
1533 if ( t->GetType() == svDouble )
1534 {
1535 pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
1536 nSign = 1;
1537 }
1538 else if ( t->GetType() == svString )
1539 {
1540 pArray->PutString( t->GetString(), nCol, nRow );
1541 }
1542 break;
1543
1544 case ocMissing :
1545 pArray->PutEmpty( nCol, nRow );
1546 break;
1547
1548 case ocTrue :
1549 pArray->PutBoolean( true, nCol, nRow );
1550 break;
1551
1552 case ocFalse :
1553 pArray->PutBoolean( false, nCol, nRow );
1554 break;
1555
1556 case ocArrayColSep :
1557 case ocSep :
1558 nCol++;
1559 break;
1560
1561 case ocArrayRowSep :
1562 nRow++; nCol = 0;
1563 break;
1564
1565 case ocNegSub :
1566 nSign = -nSign;
1567 break;
1568
1569 default :
1570 break;
1571 }
1572 pCode[i] = NULL;
1573 t->DecRef();
1574 }
1575 nLen = sal_uInt16( nStart );
1576 return AddMatrix( pArray );
1577 }
1578
1579
MergeRangeReference(const ScAddress & rPos)1580 FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
1581 {
1582 if (!pCode || !nLen)
1583 return NULL;
1584 sal_uInt16 nIdx = nLen;
1585 FormulaToken *p1, *p2, *p3; // ref, ocRange, ref
1586 // The actual types are checked in ExtendRangeReference().
1587 if (((p3 = PeekPrev(nIdx)) != 0) &&
1588 (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
1589 ((p1 = PeekPrev(nIdx)) != 0))
1590 {
1591 FormulaTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
1592 if (p)
1593 {
1594 p->IncRef();
1595 p1->DecRef();
1596 p2->DecRef();
1597 p3->DecRef();
1598 nLen -= 2;
1599 pCode[ nLen-1 ] = p;
1600 nRefs--;
1601 }
1602 }
1603 return pCode[ nLen-1 ];
1604 }
1605
AddOpCode(OpCode e)1606 FormulaToken* ScTokenArray::AddOpCode( OpCode e )
1607 {
1608 ScRawToken t;
1609 t.SetOpCode( e );
1610 return AddRawToken( t );
1611 }
1612
AddSingleReference(const ScSingleRefData & rRef)1613 FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
1614 {
1615 return Add( new ScSingleRefToken( rRef ) );
1616 }
1617
AddMatrixSingleReference(const ScSingleRefData & rRef)1618 FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
1619 {
1620 return Add( new ScSingleRefToken( rRef, ocMatRef ) );
1621 }
1622
AddDoubleReference(const ScComplexRefData & rRef)1623 FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
1624 {
1625 return Add( new ScDoubleRefToken( rRef ) );
1626 }
1627
AddMatrix(ScMatrix * p)1628 FormulaToken* ScTokenArray::AddMatrix( ScMatrix* p )
1629 {
1630 return Add( new ScMatrixToken( p ) );
1631 }
1632
AddExternalName(sal_uInt16 nFileId,const String & rName)1633 FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const String& rName )
1634 {
1635 return Add( new ScExternalNameToken(nFileId, rName) );
1636 }
1637
AddExternalSingleReference(sal_uInt16 nFileId,const String & rTabName,const ScSingleRefData & rRef)1638 FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
1639 {
1640 return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
1641 }
1642
AddExternalDoubleReference(sal_uInt16 nFileId,const String & rTabName,const ScComplexRefData & rRef)1643 FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
1644 {
1645 return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
1646 }
1647
AddColRowName(const ScSingleRefData & rRef)1648 FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
1649 {
1650 return Add( new ScSingleRefToken( rRef, ocColRowName ) );
1651 }
1652
GetAdjacentExtendOfOuterFuncRefs(SCCOLROW & nExtend,const ScAddress & rPos,ScDirection eDir)1653 sal_Bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
1654 const ScAddress& rPos, ScDirection eDir )
1655 {
1656 SCCOL nCol = 0;
1657 SCROW nRow = 0;
1658 switch ( eDir )
1659 {
1660 case DIR_BOTTOM :
1661 if ( rPos.Row() < MAXROW )
1662 nRow = (nExtend = rPos.Row()) + 1;
1663 else
1664 return sal_False;
1665 break;
1666 case DIR_RIGHT :
1667 if ( rPos.Col() < MAXCOL )
1668 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
1669 else
1670 return sal_False;
1671 break;
1672 case DIR_TOP :
1673 if ( rPos.Row() > 0 )
1674 nRow = (nExtend = rPos.Row()) - 1;
1675 else
1676 return sal_False;
1677 break;
1678 case DIR_LEFT :
1679 if ( rPos.Col() > 0 )
1680 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
1681 else
1682 return sal_False;
1683 break;
1684 default:
1685 DBG_ERRORFILE( "unknown Direction" );
1686 return sal_False;
1687 }
1688 if ( pRPN && nRPN )
1689 {
1690 FormulaToken* t = pRPN[nRPN-1];
1691 if ( t->GetType() == svByte )
1692 {
1693 sal_uInt8 nParamCount = t->GetByte();
1694 if ( nParamCount && nRPN > nParamCount )
1695 {
1696 sal_Bool bRet = sal_False;
1697 sal_uInt16 nParam = nRPN - nParamCount - 1;
1698 for ( ; nParam < nRPN-1; nParam++ )
1699 {
1700 FormulaToken* p = pRPN[nParam];
1701 switch ( p->GetType() )
1702 {
1703 case svSingleRef :
1704 {
1705 ScSingleRefData& rRef = static_cast<ScToken*>(p)->GetSingleRef();
1706 rRef.CalcAbsIfRel( rPos );
1707 switch ( eDir )
1708 {
1709 case DIR_BOTTOM :
1710 if ( rRef.nRow == nRow
1711 && rRef.nRow > nExtend )
1712 {
1713 nExtend = rRef.nRow;
1714 bRet = sal_True;
1715 }
1716 break;
1717 case DIR_RIGHT :
1718 if ( rRef.nCol == nCol
1719 && static_cast<SCCOLROW>(rRef.nCol)
1720 > nExtend )
1721 {
1722 nExtend = rRef.nCol;
1723 bRet = sal_True;
1724 }
1725 break;
1726 case DIR_TOP :
1727 if ( rRef.nRow == nRow
1728 && rRef.nRow < nExtend )
1729 {
1730 nExtend = rRef.nRow;
1731 bRet = sal_True;
1732 }
1733 break;
1734 case DIR_LEFT :
1735 if ( rRef.nCol == nCol
1736 && static_cast<SCCOLROW>(rRef.nCol)
1737 < nExtend )
1738 {
1739 nExtend = rRef.nCol;
1740 bRet = sal_True;
1741 }
1742 break;
1743 }
1744 }
1745 break;
1746 case svDoubleRef :
1747 {
1748 ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1749 rRef.CalcAbsIfRel( rPos );
1750 switch ( eDir )
1751 {
1752 case DIR_BOTTOM :
1753 if ( rRef.Ref1.nRow == nRow
1754 && rRef.Ref2.nRow > nExtend )
1755 {
1756 nExtend = rRef.Ref2.nRow;
1757 bRet = sal_True;
1758 }
1759 break;
1760 case DIR_RIGHT :
1761 if ( rRef.Ref1.nCol == nCol &&
1762 static_cast<SCCOLROW>(rRef.Ref2.nCol)
1763 > nExtend )
1764 {
1765 nExtend = rRef.Ref2.nCol;
1766 bRet = sal_True;
1767 }
1768 break;
1769 case DIR_TOP :
1770 if ( rRef.Ref2.nRow == nRow
1771 && rRef.Ref1.nRow < nExtend )
1772 {
1773 nExtend = rRef.Ref1.nRow;
1774 bRet = sal_True;
1775 }
1776 break;
1777 case DIR_LEFT :
1778 if ( rRef.Ref2.nCol == nCol &&
1779 static_cast<SCCOLROW>(rRef.Ref1.nCol)
1780 < nExtend )
1781 {
1782 nExtend = rRef.Ref1.nCol;
1783 bRet = sal_True;
1784 }
1785 break;
1786 }
1787 }
1788 break;
1789 default:
1790 {
1791 // added to avoid warnings
1792 }
1793 } // switch
1794 } // for
1795 return bRet;
1796 }
1797 }
1798 }
1799 return sal_False;
1800 }
1801
1802
ReadjustRelative3DReferences(const ScAddress & rOldPos,const ScAddress & rNewPos)1803 void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
1804 const ScAddress& rNewPos )
1805 {
1806 for ( sal_uInt16 j=0; j<nLen; ++j )
1807 {
1808 switch ( pCode[j]->GetType() )
1809 {
1810 case svDoubleRef :
1811 {
1812 ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2();
1813 // Also adjust if the reference is of the form Sheet1.A2:A3
1814 if ( rRef2.IsFlag3D() || static_cast<ScToken*>(pCode[j])->GetSingleRef().IsFlag3D() )
1815 {
1816 rRef2.CalcAbsIfRel( rOldPos );
1817 rRef2.CalcRelFromAbs( rNewPos );
1818 }
1819 }
1820 //! fallthru
1821 case svSingleRef :
1822 {
1823 ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1824 if ( rRef1.IsFlag3D() )
1825 {
1826 rRef1.CalcAbsIfRel( rOldPos );
1827 rRef1.CalcRelFromAbs( rNewPos );
1828 }
1829 }
1830 break;
1831 case svExternalDoubleRef:
1832 {
1833 ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2();
1834 rRef2.CalcAbsIfRel( rOldPos );
1835 rRef2.CalcRelFromAbs( rNewPos );
1836 }
1837 //! fallthru
1838 case svExternalSingleRef:
1839 {
1840 ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1841 rRef1.CalcAbsIfRel( rOldPos );
1842 rRef1.CalcRelFromAbs( rNewPos );
1843 }
1844 break;
1845 default:
1846 {
1847 // added to avoid warnings
1848 }
1849 }
1850 }
1851 }
1852
1853
1854