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