xref: /trunk/main/sc/source/core/tool/token.cxx (revision 43f0f119)
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