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