Update ooo320-m1
[ooovba.git] / sc / source / core / tool / token.cxx
blobfddce054946e3c505a429e01fb74a9f88e5d5629
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: token.cxx,v $
10 * $Revision: 1.33.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #if STLPORT_VERSION<321
39 #include <stddef.h>
40 #else
41 #include <cstddef>
42 #endif
43 #include <cstdio>
45 #include <string.h>
46 #include <tools/mempool.hxx>
47 #include <tools/debug.hxx>
49 #include "token.hxx"
50 #include "tokenarray.hxx"
51 #include "compiler.hxx"
52 #include <formula/compiler.hrc>
53 #include "rechead.hxx"
54 #include "parclass.hxx"
55 #include "jumpmatrix.hxx"
56 #include "rangeseq.hxx"
57 #include "externalrefmgr.hxx"
58 #include "document.hxx"
60 using ::std::vector;
62 #include <com/sun/star/sheet/ComplexReference.hpp>
63 #include <com/sun/star/sheet/ExternalReference.hpp>
64 #include <com/sun/star/sheet/ReferenceFlags.hpp>
66 using namespace formula;
67 using namespace com::sun::star;
69 namespace
71 void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
73 rRef.InitFlags();
75 rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
76 rRef.nRow = static_cast<SCsROW>(rAPI.Row);
77 rRef.nTab = static_cast<SCsTAB>(rAPI.Sheet);
78 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
79 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
80 rRef.nRelTab = static_cast<SCsTAB>(rAPI.RelativeSheet);
82 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
83 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
84 rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
85 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
86 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
87 rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
88 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
89 rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
92 void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
94 rRef.InitFlags();
96 rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
97 rRef.nRow = static_cast<SCsROW>(rAPI.Row);
98 rRef.nTab = 0;
99 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
100 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
101 rRef.nRelTab = 0;
103 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
104 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
105 rRef.SetTabRel( false ); // sheet index must be absolute for external refs
106 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
107 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
108 rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
109 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
110 rRef.SetRelName( false );
113 } // namespace
115 // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
116 // SubCode via FormulaTokenIterator Push/Pop moeglich
117 IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
119 // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
121 // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
122 // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
123 IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken, 8, 4 )
124 // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
125 const USHORT nMemPoolDoubleRawToken = 0x0400 / sizeof(ScDoubleRawToken);
126 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken, nMemPoolDoubleRawToken, nMemPoolDoubleRawToken )
128 // Need a whole bunch of ScSingleRefToken
129 const USHORT nMemPoolSingleRefToken = (0x4000 - 64) / sizeof(ScSingleRefToken);
130 IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken, nMemPoolSingleRefToken, nMemPoolSingleRefToken )
131 // Need quite a lot of ScDoubleRefToken
132 const USHORT nMemPoolDoubleRefToken = (0x2000 - 64) / sizeof(ScDoubleRefToken);
133 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken, nMemPoolDoubleRefToken, nMemPoolDoubleRefToken )
135 // --- helpers --------------------------------------------------------------
137 inline BOOL lcl_IsReference( OpCode eOp, StackVar eType )
139 return
140 (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
141 || (eOp == ocColRowNameAuto && eType == svDoubleRef)
142 || (eOp == ocColRowName && eType == svSingleRef)
143 || (eOp == ocMatRef && eType == svSingleRef)
148 // --- class ScRawToken -----------------------------------------------------
150 xub_StrLen ScRawToken::GetStrLen( const sal_Unicode* pStr )
152 if ( !pStr )
153 return 0;
154 register const sal_Unicode* p = pStr;
155 while ( *p )
156 p++;
157 return sal::static_int_cast<xub_StrLen>( p - pStr );
161 void ScRawToken::SetOpCode( OpCode e )
163 eOp = e;
164 switch (eOp)
166 case ocIf:
167 eType = svJump;
168 nJump[ 0 ] = 3; // If, Else, Behind
169 break;
170 case ocChose:
171 eType = svJump;
172 nJump[ 0 ] = MAXJUMPCOUNT+1;
173 break;
174 case ocMissing:
175 eType = svMissing;
176 break;
177 case ocSep:
178 case ocOpen:
179 case ocClose:
180 case ocArrayRowSep:
181 case ocArrayColSep:
182 case ocArrayOpen:
183 case ocArrayClose:
184 eType = svSep;
185 break;
186 default:
187 eType = svByte;
188 sbyte.cByte = 0;
189 sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
191 nRefCnt = 0;
194 void ScRawToken::SetString( const sal_Unicode* pStr )
196 eOp = ocPush;
197 eType = svString;
198 if ( pStr )
200 xub_StrLen nLen = GetStrLen( pStr ) + 1;
201 if( nLen > MAXSTRLEN )
202 nLen = MAXSTRLEN;
203 memcpy( cStr, pStr, GetStrLenBytes( nLen ) );
204 cStr[ nLen-1 ] = 0;
206 else
207 cStr[0] = 0;
208 nRefCnt = 0;
211 void ScRawToken::SetSingleReference( const ScSingleRefData& rRef )
213 eOp = ocPush;
214 eType = svSingleRef;
215 aRef.Ref1 =
216 aRef.Ref2 = rRef;
217 nRefCnt = 0;
220 void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef )
222 eOp = ocPush;
223 eType = svDoubleRef;
224 aRef = rRef;
225 nRefCnt = 0;
228 void ScRawToken::SetDouble(double rVal)
230 eOp = ocPush;
231 eType = svDouble;
232 nValue = rVal;
233 nRefCnt = 0;
236 void ScRawToken::SetName( USHORT n )
238 eOp = ocName;
239 eType = svIndex;
240 nIndex = n;
241 nRefCnt = 0;
244 void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
246 eOp = ocExternalRef;
247 eType = svExternalSingleRef;
248 nRefCnt = 0;
250 extref.nFileId = nFileId;
251 extref.aRef.Ref1 =
252 extref.aRef.Ref2 = rRef;
254 xub_StrLen n = rTabName.Len();
255 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
256 extref.cTabName[n] = 0;
259 void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
261 eOp = ocExternalRef;
262 eType = svExternalDoubleRef;
263 nRefCnt = 0;
265 extref.nFileId = nFileId;
266 extref.aRef = rRef;
268 xub_StrLen n = rTabName.Len();
269 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
270 extref.cTabName[n] = 0;
273 void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
275 eOp = ocExternalRef;
276 eType = svExternalName;
277 nRefCnt = 0;
279 extname.nFileId = nFileId;
281 xub_StrLen n = rName.Len();
282 memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode));
283 extname.cName[n] = 0;
286 //UNUSED2008-05 void ScRawToken::SetInt(int rVal)
287 //UNUSED2008-05 {
288 //UNUSED2008-05 eOp = ocPush;
289 //UNUSED2008-05 eType = svDouble;
290 //UNUSED2008-05 nValue = (double)rVal;
291 //UNUSED2008-05 nRefCnt = 0;
292 //UNUSED2008-05
293 //UNUSED2008-05 }
294 //UNUSED2008-05 void ScRawToken::SetMatrix( ScMatrix* p )
295 //UNUSED2008-05 {
296 //UNUSED2008-05 eOp = ocPush;
297 //UNUSED2008-05 eType = svMatrix;
298 //UNUSED2008-05 pMat = p;
299 //UNUSED2008-05 nRefCnt = 0;
300 //UNUSED2008-05 }
301 //UNUSED2008-05
302 //UNUSED2008-05 ScComplexRefData& ScRawToken::GetReference()
303 //UNUSED2008-05 {
304 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
305 //UNUSED2008-05 return aRef;
306 //UNUSED2008-05 }
307 //UNUSED2008-05
308 //UNUSED2008-05 void ScRawToken::SetReference( ScComplexRefData& rRef )
309 //UNUSED2008-05 {
310 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "SetReference: no Ref" );
311 //UNUSED2008-05 aRef = rRef;
312 //UNUSED2008-05 if( GetType() == svSingleRef )
313 //UNUSED2008-05 aRef.Ref2 = aRef.Ref1;
314 //UNUSED2008-05 }
316 void ScRawToken::SetExternal( const sal_Unicode* pStr )
318 eOp = ocExternal;
319 eType = svExternal;
320 xub_StrLen nLen = GetStrLen( pStr ) + 1;
321 if( nLen >= MAXSTRLEN )
322 nLen = MAXSTRLEN-1;
323 // Platz fuer Byte-Parameter lassen!
324 memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
325 cStr[ nLen+1 ] = 0;
326 nRefCnt = 0;
329 USHORT lcl_ScRawTokenOffset()
331 // offset of sbyte in ScRawToken
332 // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD
334 ScRawToken aToken;
335 return static_cast<USHORT>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) );
338 ScRawToken* ScRawToken::Clone() const
340 ScRawToken* p;
341 if ( eType == svDouble )
343 p = (ScRawToken*) new ScDoubleRawToken;
344 p->eOp = eOp;
345 p->eType = eType;
346 p->nValue = nValue;
348 else
350 static USHORT nOffset = lcl_ScRawTokenOffset(); // offset of sbyte
351 USHORT n = nOffset;
353 if (eOp == ocExternalRef)
355 switch (eType)
357 case svExternalSingleRef:
358 case svExternalDoubleRef: n += sizeof(extref); break;
359 case svExternalName: n += sizeof(extname); break;
360 default:
362 DBG_ERROR1( "unknown ScRawToken::Clone() external type %d", int(eType));
366 else
368 switch( eType )
370 case svSep: break;
371 case svByte: n += sizeof(ScRawToken::sbyte); break;
372 case svDouble: n += sizeof(double); break;
373 case svString: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
374 case svSingleRef:
375 case svDoubleRef: n += sizeof(aRef); break;
376 case svMatrix: n += sizeof(ScMatrix*); break;
377 case svIndex: n += sizeof(USHORT); break;
378 case svJump: n += nJump[ 0 ] * 2 + 2; break;
379 case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
380 default:
382 DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
386 p = (ScRawToken*) new BYTE[ n ];
387 memcpy( p, this, n * sizeof(BYTE) );
389 p->nRefCnt = 0;
390 p->bRaw = FALSE;
391 return p;
395 FormulaToken* ScRawToken::CreateToken() const
397 #ifndef PRODUCT
398 #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))
399 #else
400 #define IF_NOT_OPCODE_ERROR(o,c)
401 #endif
402 switch ( GetType() )
404 case svByte :
405 return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
406 case svDouble :
407 IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken);
408 return new FormulaDoubleToken( nValue );
409 case svString :
410 if (eOp == ocPush)
411 return new FormulaStringToken( String( cStr ) );
412 else
413 return new FormulaStringOpToken( eOp, String( cStr ) );
414 case svSingleRef :
415 if (eOp == ocPush)
416 return new ScSingleRefToken( aRef.Ref1 );
417 else
418 return new ScSingleRefToken( aRef.Ref1, eOp );
419 case svDoubleRef :
420 if (eOp == ocPush)
421 return new ScDoubleRefToken( aRef );
422 else
423 return new ScDoubleRefToken( aRef, eOp );
424 case svMatrix :
425 IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
426 return new ScMatrixToken( pMat );
427 case svIndex :
428 return new FormulaIndexToken( eOp, nIndex );
429 case svExternalSingleRef:
431 String aTabName(extref.cTabName);
432 return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
434 case svExternalDoubleRef:
436 String aTabName(extref.cTabName);
437 return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
439 case svExternalName:
441 String aName(extname.cName);
442 return new ScExternalNameToken( extname.nFileId, aName );
444 case svJump :
445 return new FormulaJumpToken( eOp, (short*) nJump );
446 case svExternal :
447 return new FormulaExternalToken( eOp, sbyte.cByte, String( cStr+1 ) );
448 case svFAP :
449 return new FormulaFAPToken( eOp, sbyte.cByte, NULL );
450 case svMissing :
451 IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken);
452 return new FormulaMissingToken;
453 case svSep :
454 return new FormulaToken( svSep,eOp );
455 case svUnknown :
456 return new FormulaUnknownToken( eOp );
457 default:
459 DBG_ERROR1( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
460 return new FormulaUnknownToken( ocBad );
463 #undef IF_NOT_OPCODE_ERROR
467 void ScRawToken::Delete()
469 if ( bRaw )
470 delete this; // FixedMemPool ScRawToken
471 else
472 { // created per Clone
473 switch ( eType )
475 case svDouble :
476 delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken
477 break;
478 default:
479 delete [] (BYTE*) this;
485 // --- class ScToken --------------------------------------------------------
487 ScSingleRefData lcl_ScToken_InitSingleRef()
489 ScSingleRefData aRef;
490 aRef.InitAddress( ScAddress() );
491 return aRef;
494 ScComplexRefData lcl_ScToken_InitDoubleRef()
496 ScComplexRefData aRef;
497 aRef.Ref1 = lcl_ScToken_InitSingleRef();
498 aRef.Ref2 = aRef.Ref1;
499 return aRef;
502 ScToken::~ScToken()
506 // TextEqual: if same formula entered (for optimization in sort)
507 BOOL ScToken::TextEqual( const FormulaToken& _rToken ) const
509 if ( eType == svSingleRef || eType == svDoubleRef )
511 // in relative Refs only compare relative parts
513 if ( eType != _rToken.GetType() || GetOpCode() != _rToken.GetOpCode() )
514 return FALSE;
516 const ScToken& rToken = static_cast<const ScToken&>(_rToken);
517 ScComplexRefData aTemp1;
518 if ( eType == svSingleRef )
520 aTemp1.Ref1 = GetSingleRef();
521 aTemp1.Ref2 = aTemp1.Ref1;
523 else
524 aTemp1 = GetDoubleRef();
526 ScComplexRefData aTemp2;
527 if ( rToken.eType == svSingleRef )
529 aTemp2.Ref1 = rToken.GetSingleRef();
530 aTemp2.Ref2 = aTemp2.Ref1;
532 else
533 aTemp2 = rToken.GetDoubleRef();
535 ScAddress aPos;
536 aTemp1.SmartRelAbs(aPos);
537 aTemp2.SmartRelAbs(aPos);
539 // memcmp doesn't work because of the alignment byte after bFlags.
540 // After SmartRelAbs only absolute parts have to be compared.
541 return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol &&
542 aTemp1.Ref1.nRow == aTemp2.Ref1.nRow &&
543 aTemp1.Ref1.nTab == aTemp2.Ref1.nTab &&
544 aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags &&
545 aTemp1.Ref2.nCol == aTemp2.Ref2.nCol &&
546 aTemp1.Ref2.nRow == aTemp2.Ref2.nRow &&
547 aTemp1.Ref2.nTab == aTemp2.Ref2.nTab &&
548 aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags;
550 else
551 return *this == _rToken; // else normal operator==
555 BOOL ScToken::Is3DRef() const
557 switch ( eType )
559 case svDoubleRef :
560 if ( GetSingleRef2().IsFlag3D() )
561 return TRUE;
562 //! fallthru
563 case svSingleRef :
564 if ( GetSingleRef().IsFlag3D() )
565 return TRUE;
566 break;
567 default:
569 // added to avoid warnings
572 return FALSE;
575 // static
576 FormulaTokenRef ScToken::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2,
577 const ScAddress & rPos, bool bReuseDoubleRef )
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;
588 ScToken *p1 = static_cast<ScToken*>(&rTok1);
589 ScToken *p2 = static_cast<ScToken*>(&rTok2);
591 ScTokenRef xRes;
592 bool bExternal = (sv1 == svExternalSingleRef);
593 if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
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.
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
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. */
616 const ScSingleRefData& rRef2 = p2->GetSingleRef();
617 if (bExternal && rRef2.IsFlag3D())
618 return NULL;
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);
629 else
631 bExternal |= (sv1 == svExternalDoubleRef);
632 const ScRefList* pRefList = NULL;
633 if (sv1 == svDoubleRef)
635 xRes = (bReuseDoubleRef && p1->GetRef() == 1 ? p1 : static_cast<ScToken*>(p1->Clone()));
636 sv1 = svUnknown; // mark as handled
638 else if (sv2 == svDoubleRef)
640 xRes = (bReuseDoubleRef && p2->GetRef() == 1 ? p2 : static_cast<ScToken*>(p2->Clone()));
641 sv2 = svUnknown; // mark as handled
643 else if (sv1 == svRefList)
644 pRefList = p1->GetRefList();
645 else if (sv2 == svRefList)
646 pRefList = p2->GetRefList();
647 if (pRefList)
649 if (!pRefList->size())
650 return NULL;
651 if (bExternal)
652 return NULL; // external reference list not possible
653 xRes = new ScDoubleRefToken( (*pRefList)[0] );
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)
662 switch (sv[i])
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:
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)
679 rRef.Extend( *it, rPos);
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
700 return FormulaTokenRef(xRes.get());
703 const ScSingleRefData& ScToken::GetSingleRef() const
705 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
706 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
707 return aDummySingleRef;
710 ScSingleRefData& ScToken::GetSingleRef()
712 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
713 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
714 return aDummySingleRef;
717 const ScComplexRefData& ScToken::GetDoubleRef() const
719 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
720 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
721 return aDummyDoubleRef;
724 ScComplexRefData& ScToken::GetDoubleRef()
726 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
727 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
728 return aDummyDoubleRef;
731 const ScSingleRefData& ScToken::GetSingleRef2() const
733 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
734 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
735 return aDummySingleRef;
738 ScSingleRefData& ScToken::GetSingleRef2()
740 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
741 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
742 return aDummySingleRef;
745 void ScToken::CalcAbsIfRel( const ScAddress& /* rPos */ )
747 DBG_ERRORFILE( "ScToken::CalcAbsIfRel: virtual dummy called" );
750 void ScToken::CalcRelFromAbs( const ScAddress& /* rPos */ )
752 DBG_ERRORFILE( "ScToken::CalcRelFromAbs: virtual dummy called" );
755 const ScMatrix* ScToken::GetMatrix() const
757 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" );
758 return NULL;
761 ScMatrix* ScToken::GetMatrix()
763 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" );
764 return NULL;
768 ScJumpMatrix* ScToken::GetJumpMatrix() const
770 DBG_ERRORFILE( "ScToken::GetJumpMatrix: virtual dummy called" );
771 return NULL;
773 const ScRefList* ScToken::GetRefList() const
775 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" );
776 return NULL;
779 ScRefList* ScToken::GetRefList()
781 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" );
782 return NULL;
784 // ==========================================================================
785 // real implementations of virtual functions
786 // --------------------------------------------------------------------------
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 BOOL ScSingleRefToken::operator==( const FormulaToken& r ) const
799 return FormulaToken::operator==( r ) && aSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
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 BOOL ScDoubleRefToken::operator==( const FormulaToken& r ) const
815 return FormulaToken::operator==( r ) && aDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
819 const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; }
820 ScRefList* ScRefListToken::GetRefList() { return &aRefList; }
821 void ScRefListToken::CalcAbsIfRel( const ScAddress& rPos )
823 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
824 (*it).CalcAbsIfRel( rPos);
826 void ScRefListToken::CalcRelFromAbs( const ScAddress& rPos )
828 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
829 (*it).CalcRelFromAbs( rPos);
831 BOOL ScRefListToken::operator==( const FormulaToken& r ) const
833 return FormulaToken::operator==( r ) && &aRefList == static_cast<const ScToken&>(r).GetRefList();
837 const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix; }
838 ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix; }
839 BOOL ScMatrixToken::operator==( const FormulaToken& r ) const
841 return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
844 // ============================================================================
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)
854 ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
855 ScToken(r),
856 mnFileId(r.mnFileId),
857 maTabName(r.maTabName),
858 maSingleRef(r.maSingleRef)
862 ScExternalSingleRefToken::~ScExternalSingleRefToken()
866 USHORT ScExternalSingleRefToken::GetIndex() const
868 return mnFileId;
871 const String& ScExternalSingleRefToken::GetString() const
873 return maTabName;
876 const ScSingleRefData& ScExternalSingleRefToken::GetSingleRef() const
878 return maSingleRef;
881 ScSingleRefData& ScExternalSingleRefToken::GetSingleRef()
883 return maSingleRef;
886 void ScExternalSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
888 maSingleRef.CalcAbsIfRel( rPos );
891 void ScExternalSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
893 maSingleRef.CalcRelFromAbs( rPos );
896 BOOL ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
898 if (!FormulaToken::operator==(r))
899 return false;
901 if (mnFileId != r.GetIndex())
902 return false;
904 if (maTabName != r.GetString())
905 return false;
907 return maSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
910 // ============================================================================
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)
920 ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
921 ScToken(r),
922 mnFileId(r.mnFileId),
923 maTabName(r.maTabName),
924 maDoubleRef(r.maDoubleRef)
928 ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
932 USHORT ScExternalDoubleRefToken::GetIndex() const
934 return mnFileId;
937 const String& ScExternalDoubleRefToken::GetString() const
939 return maTabName;
942 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef() const
944 return maDoubleRef.Ref1;
947 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef()
949 return maDoubleRef.Ref1;
952 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2() const
954 return maDoubleRef.Ref2;
957 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2()
959 return maDoubleRef.Ref2;
962 const ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef() const
964 return maDoubleRef;
967 ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef()
969 return maDoubleRef;
972 void ScExternalDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
974 maDoubleRef.CalcAbsIfRel( rPos );
977 void ScExternalDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
979 maDoubleRef.CalcRelFromAbs( rPos );
982 BOOL ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
984 if (!ScToken::operator==(r))
985 return false;
987 if (mnFileId != r.GetIndex())
988 return false;
990 if (maTabName != r.GetString())
991 return false;
993 return maDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
996 // ============================================================================
998 ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
999 ScToken( svExternalName, ocExternalRef),
1000 mnFileId(nFileId),
1001 maName(rName)
1005 ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
1006 ScToken(r),
1007 mnFileId(r.mnFileId),
1008 maName(r.maName)
1012 ScExternalNameToken::~ScExternalNameToken() {}
1014 USHORT ScExternalNameToken::GetIndex() const
1016 return mnFileId;
1019 const String& ScExternalNameToken::GetString() const
1021 return maName;
1024 BOOL ScExternalNameToken::operator==( const FormulaToken& r ) const
1026 if ( !FormulaToken::operator==(r) )
1027 return false;
1029 if (mnFileId != r.GetIndex())
1030 return false;
1032 xub_StrLen nLen = maName.Len();
1033 const String& rName = r.GetString();
1034 if (nLen != rName.Len())
1035 return false;
1037 const sal_Unicode* p1 = maName.GetBuffer();
1038 const sal_Unicode* p2 = rName.GetBuffer();
1039 for (xub_StrLen j = 0; j < nLen; ++j)
1041 if (p1[j] != p2[j])
1042 return false;
1044 return true;
1047 // ============================================================================
1049 ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; }
1050 BOOL ScJumpMatrixToken::operator==( const FormulaToken& r ) const
1052 return FormulaToken::operator==( r ) && pJumpMatrix == static_cast<const ScToken&>(r).GetJumpMatrix();
1054 ScJumpMatrixToken::~ScJumpMatrixToken()
1056 delete pJumpMatrix;
1059 double ScEmptyCellToken::GetDouble() const { return 0.0; }
1060 const String & ScEmptyCellToken::GetString() const
1062 static String aDummyString;
1063 return aDummyString;
1065 BOOL ScEmptyCellToken::operator==( const FormulaToken& r ) const
1067 return FormulaToken::operator==( r ) &&
1068 bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
1069 bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
1073 double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); }
1074 const String & ScMatrixCellResultToken::GetString() const { return xUpperLeft->GetString(); }
1075 const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix; }
1076 // Non-const GetMatrix() is private and unused but must be implemented to
1077 // satisfy vtable linkage.
1078 ScMatrix* ScMatrixCellResultToken::GetMatrix()
1080 return const_cast<ScMatrix*>(xMatrix.operator->());
1082 BOOL ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
1084 return FormulaToken::operator==( r ) &&
1085 xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
1086 xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
1090 BOOL ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
1092 const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
1093 return p && ScMatrixCellResultToken::operator==( r ) &&
1094 nCols == p->nCols && nRows == p->nRows;
1096 void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
1098 if (this == &r)
1099 return;
1100 const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
1101 if (p)
1102 ScMatrixCellResultToken::Assign( *p);
1103 else
1105 DBG_ASSERT( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1106 if (r.GetType() == svMatrix)
1108 xUpperLeft = NULL;
1109 xMatrix = static_cast<const ScToken&>(r).GetMatrix();
1111 else
1113 xUpperLeft = &r;
1114 xMatrix = NULL;
1118 void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f )
1120 switch (GetUpperLeftType())
1122 case svDouble:
1123 const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
1124 break;
1125 case svUnknown:
1126 if (!xUpperLeft)
1128 xUpperLeft = new FormulaDoubleToken( f);
1129 break;
1131 // fall thru
1132 default:
1134 DBG_ERRORFILE("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1140 double ScHybridCellToken::GetDouble() const { return fDouble; }
1141 const String & ScHybridCellToken::GetString() const { return aString; }
1142 BOOL ScHybridCellToken::operator==( const FormulaToken& r ) const
1144 return FormulaToken::operator==( r ) &&
1145 fDouble == r.GetDouble() && aString == r.GetString() &&
1146 aFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
1152 //////////////////////////////////////////////////////////////////////////
1154 bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef)
1156 bool bError = FormulaTokenArray::AddFormulaToken(_aToken,_pRef);
1157 if ( bError )
1159 bError = false;
1160 const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment
1162 const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
1163 switch ( eClass )
1165 case uno::TypeClass_STRUCT:
1167 uno::Type aType = _aToken.Data.getValueType();
1168 if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
1170 ScSingleRefData aSingleRef;
1171 sheet::SingleReference aApiRef;
1172 _aToken.Data >>= aApiRef;
1173 lcl_SingleRefToCalc( aSingleRef, aApiRef );
1174 if ( eOpCode == ocPush )
1175 AddSingleReference( aSingleRef );
1176 else if ( eOpCode == ocColRowName )
1177 AddColRowName( aSingleRef );
1178 else
1179 bError = true;
1181 else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
1183 ScComplexRefData aComplRef;
1184 sheet::ComplexReference aApiRef;
1185 _aToken.Data >>= aApiRef;
1186 lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
1187 lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
1189 if ( eOpCode == ocPush )
1190 AddDoubleReference( aComplRef );
1191 else
1192 bError = true;
1194 else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
1196 sheet::ExternalReference aApiExtRef;
1197 if( (eOpCode == ocPush) && (_aToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
1199 sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
1200 sheet::SingleReference aApiSRef;
1201 sheet::ComplexReference aApiCRef;
1202 ::rtl::OUString aName;
1203 if( aApiExtRef.Reference >>= aApiSRef )
1205 // try to resolve cache index to sheet name
1206 size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
1207 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1208 if( aTabName.Len() > 0 )
1210 ScSingleRefData aSingleRef;
1211 // convert column/row settings, set sheet index to absolute
1212 lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1213 AddExternalSingleReference( nFileId, aTabName, aSingleRef );
1215 else
1216 bError = true;
1218 else if( aApiExtRef.Reference >>= aApiCRef )
1220 // try to resolve cache index to sheet name.
1221 size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
1222 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1223 if( aTabName.Len() > 0 )
1225 ScComplexRefData aComplRef;
1226 // convert column/row settings, set sheet index to absolute
1227 lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
1228 lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
1229 // NOTE: This assumes that cached sheets are in consecutive order!
1230 aComplRef.Ref2.nTab = aComplRef.Ref1.nTab + static_cast<SCsTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet);
1231 AddExternalDoubleReference( nFileId, aTabName, aComplRef );
1233 else
1234 bError = true;
1236 else if( aApiExtRef.Reference >>= aName )
1238 if( aName.getLength() > 0 )
1239 AddExternalName( nFileId, aName );
1240 else
1241 bError = true;
1243 else
1244 bError = true;
1246 else
1247 bError = true;
1249 else
1250 bError = true; // unknown struct
1252 break;
1253 case uno::TypeClass_SEQUENCE:
1255 if ( eOpCode != ocPush )
1256 bError = true; // not an inline array
1257 else if (!_aToken.Data.getValueType().equals( getCppuType(
1258 (uno::Sequence< uno::Sequence< uno::Any > > *)0)))
1259 bError = true; // unexpected sequence type
1260 else
1262 ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( _aToken.Data);
1263 if (xMat)
1264 AddMatrix( xMat);
1265 else
1266 bError = true;
1269 break;
1270 default:
1271 bError = true;
1274 return bError;
1276 BOOL ScTokenArray::ImplGetReference( ScRange& rRange, BOOL bValidOnly ) const
1278 BOOL bIs = FALSE;
1279 if ( pCode && nLen == 1 )
1281 const FormulaToken* pToken = pCode[0];
1282 if ( pToken )
1284 if ( pToken->GetType() == svSingleRef )
1286 const ScSingleRefData& rRef = ((const ScSingleRefToken*)pToken)->GetSingleRef();
1287 rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab );
1288 bIs = !bValidOnly || !rRef.IsDeleted();
1290 else if ( pToken->GetType() == svDoubleRef )
1292 const ScComplexRefData& rCompl = ((const ScDoubleRefToken*)pToken)->GetDoubleRef();
1293 const ScSingleRefData& rRef1 = rCompl.Ref1;
1294 const ScSingleRefData& rRef2 = rCompl.Ref2;
1295 rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab );
1296 rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab );
1297 bIs = !bValidOnly || (!rRef1.IsDeleted() && !rRef2.IsDeleted());
1301 return bIs;
1304 BOOL ScTokenArray::IsReference( ScRange& rRange ) const
1306 return ImplGetReference( rRange, FALSE );
1309 BOOL ScTokenArray::IsValidReference( ScRange& rRange ) const
1311 return ImplGetReference( rRange, TRUE );
1314 ////////////////////////////////////////////////////////////////////////////
1316 ScTokenArray::ScTokenArray()
1320 ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) : FormulaTokenArray(rArr)
1324 ScTokenArray::~ScTokenArray()
1330 ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
1332 Clear();
1333 Assign( rArr );
1334 return *this;
1337 ScTokenArray* ScTokenArray::Clone() const
1339 ScTokenArray* p = new ScTokenArray();
1340 p->nLen = nLen;
1341 p->nRPN = nRPN;
1342 p->nRefs = nRefs;
1343 p->nMode = nMode;
1344 p->nError = nError;
1345 p->bHyperLink = bHyperLink;
1346 FormulaToken** pp;
1347 if( nLen )
1349 pp = p->pCode = new FormulaToken*[ nLen ];
1350 memcpy( pp, pCode, nLen * sizeof( ScToken* ) );
1351 for( USHORT i = 0; i < nLen; i++, pp++ )
1353 *pp = (*pp)->Clone();
1354 (*pp)->IncRef();
1357 if( nRPN )
1359 pp = p->pRPN = new FormulaToken*[ nRPN ];
1360 memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) );
1361 for( USHORT i = 0; i < nRPN; i++, pp++ )
1363 FormulaToken* t = *pp;
1364 if( t->GetRef() > 1 )
1366 FormulaToken** p2 = pCode;
1367 USHORT nIdx = 0xFFFF;
1368 for( USHORT j = 0; j < nLen; j++, p2++ )
1370 if( *p2 == t )
1372 nIdx = j; break;
1375 if( nIdx == 0xFFFF )
1376 *pp = t->Clone();
1377 else
1378 *pp = p->pCode[ nIdx ];
1380 else
1381 *pp = t->Clone();
1382 (*pp)->IncRef();
1385 return p;
1388 FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
1390 return Add( r.CreateToken() );
1393 // Utility function to ensure that there is strict alternation of values and
1394 // seperators.
1395 static bool
1396 checkArraySep( bool & bPrevWasSep, bool bNewVal )
1398 bool bResult = (bPrevWasSep == bNewVal);
1399 bPrevWasSep = bNewVal;
1400 return bResult;
1403 FormulaToken* ScTokenArray::MergeArray( )
1405 int nCol = -1, nRow = 0;
1406 int i, nPrevRowSep = -1, nStart = 0;
1407 bool bPrevWasSep = false; // top of stack is ocArrayClose
1408 FormulaToken* t;
1409 bool bNumeric = false; // numeric value encountered in current element
1411 // (1) Iterate from the end to the start to find matrix dims
1412 // and do basic validation.
1413 for ( i = nLen ; i-- > nStart ; )
1415 t = pCode[i];
1416 switch ( t->GetOpCode() )
1418 case ocPush :
1419 if( checkArraySep( bPrevWasSep, false ) )
1421 return NULL;
1424 // no references or nested arrays
1425 if ( t->GetType() != svDouble && t->GetType() != svString )
1427 return NULL;
1429 bNumeric = (t->GetType() == svDouble);
1430 break;
1432 case ocMissing :
1433 case ocTrue :
1434 case ocFalse :
1435 if( checkArraySep( bPrevWasSep, false ) )
1437 return NULL;
1439 bNumeric = false;
1440 break;
1442 case ocArrayColSep :
1443 case ocSep :
1444 if( checkArraySep( bPrevWasSep, true ) )
1446 return NULL;
1448 bNumeric = false;
1449 break;
1451 case ocArrayClose :
1452 // not possible with the , but check just in case
1453 // something changes in the future
1454 if( i != (nLen-1))
1456 return NULL;
1459 if( checkArraySep( bPrevWasSep, true ) )
1461 return NULL;
1464 nPrevRowSep = i;
1465 bNumeric = false;
1466 break;
1468 case ocArrayOpen :
1469 nStart = i; // stop iteration
1470 // fall through to ArrayRowSep
1472 case ocArrayRowSep :
1473 if( checkArraySep( bPrevWasSep, true ) )
1475 return NULL;
1478 if( nPrevRowSep < 0 || // missing ocArrayClose
1479 ((nPrevRowSep - i) % 2) == 1) // no complex elements
1481 return NULL;
1484 if( nCol < 0 )
1486 nCol = (nPrevRowSep - i) / 2;
1488 else if( (nPrevRowSep - i)/2 != nCol) // irregular array
1490 return NULL;
1493 nPrevRowSep = i;
1494 nRow++;
1495 bNumeric = false;
1496 break;
1498 case ocNegSub :
1499 case ocAdd :
1500 // negation or unary plus must precede numeric value
1501 if( !bNumeric )
1503 return NULL;
1505 --nPrevRowSep; // shorten this row by 1
1506 bNumeric = false; // one level only, no --42
1507 break;
1509 case ocSpaces :
1510 // ignore spaces
1511 --nPrevRowSep; // shorten this row by 1
1512 break;
1514 default :
1515 // no functions or operators
1516 return NULL;
1519 if( nCol <= 0 || nRow <= 0 )
1520 return NULL;
1522 // fprintf (stderr, "Array (cols = %d, rows = %d)\n", nCol, nRow );
1524 int nSign = 1;
1525 ScMatrix* pArray = new ScMatrix( nCol, nRow );
1526 for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
1528 t = pCode[i];
1530 switch ( t->GetOpCode() )
1532 case ocPush :
1533 if ( t->GetType() == svDouble )
1535 pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
1536 nSign = 1;
1538 else if ( t->GetType() == svString )
1540 pArray->PutString( t->GetString(), nCol, nRow );
1542 break;
1544 case ocMissing :
1545 pArray->PutEmpty( nCol, nRow );
1546 break;
1548 case ocTrue :
1549 pArray->PutBoolean( true, nCol, nRow );
1550 break;
1552 case ocFalse :
1553 pArray->PutBoolean( false, nCol, nRow );
1554 break;
1556 case ocArrayColSep :
1557 case ocSep :
1558 nCol++;
1559 break;
1561 case ocArrayRowSep :
1562 nRow++; nCol = 0;
1563 break;
1565 case ocNegSub :
1566 nSign = -nSign;
1567 break;
1569 default :
1570 break;
1572 pCode[i] = NULL;
1573 t->DecRef();
1575 nLen = USHORT( nStart );
1576 return AddMatrix( pArray );
1580 FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
1582 if (!pCode || !nLen)
1583 return NULL;
1584 USHORT nIdx = nLen;
1585 FormulaToken *p1, *p2, *p3; // ref, ocRange, ref
1586 // The actual types are checked in ExtendRangeReference().
1587 if (((p3 = PeekPrev(nIdx)) != 0) &&
1588 (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
1589 ((p1 = PeekPrev(nIdx)) != 0))
1591 FormulaTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
1592 if (p)
1594 p->IncRef();
1595 p1->DecRef();
1596 p2->DecRef();
1597 p3->DecRef();
1598 nLen -= 2;
1599 pCode[ nLen-1 ] = p;
1600 nRefs--;
1603 return pCode[ nLen-1 ];
1606 FormulaToken* ScTokenArray::AddOpCode( OpCode e )
1608 ScRawToken t;
1609 t.SetOpCode( e );
1610 return AddRawToken( t );
1613 FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
1615 return Add( new ScSingleRefToken( rRef ) );
1618 FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
1620 return Add( new ScSingleRefToken( rRef, ocMatRef ) );
1623 FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
1625 return Add( new ScDoubleRefToken( rRef ) );
1628 FormulaToken* ScTokenArray::AddMatrix( ScMatrix* p )
1630 return Add( new ScMatrixToken( p ) );
1633 FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const String& rName )
1635 return Add( new ScExternalNameToken(nFileId, rName) );
1638 FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
1640 return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
1643 FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
1645 return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
1648 FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
1650 return Add( new ScSingleRefToken( rRef, ocColRowName ) );
1653 BOOL ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
1654 const ScAddress& rPos, ScDirection eDir )
1656 SCCOL nCol = 0;
1657 SCROW nRow = 0;
1658 switch ( eDir )
1660 case DIR_BOTTOM :
1661 if ( rPos.Row() < MAXROW )
1662 nRow = (nExtend = rPos.Row()) + 1;
1663 else
1664 return FALSE;
1665 break;
1666 case DIR_RIGHT :
1667 if ( rPos.Col() < MAXCOL )
1668 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
1669 else
1670 return FALSE;
1671 break;
1672 case DIR_TOP :
1673 if ( rPos.Row() > 0 )
1674 nRow = (nExtend = rPos.Row()) - 1;
1675 else
1676 return FALSE;
1677 break;
1678 case DIR_LEFT :
1679 if ( rPos.Col() > 0 )
1680 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
1681 else
1682 return FALSE;
1683 break;
1684 default:
1685 DBG_ERRORFILE( "unknown Direction" );
1686 return FALSE;
1688 if ( pRPN && nRPN )
1690 FormulaToken* t = pRPN[nRPN-1];
1691 if ( t->GetType() == svByte )
1693 BYTE nParamCount = t->GetByte();
1694 if ( nParamCount && nRPN > nParamCount )
1696 BOOL bRet = FALSE;
1697 USHORT nParam = nRPN - nParamCount - 1;
1698 for ( ; nParam < nRPN-1; nParam++ )
1700 FormulaToken* p = pRPN[nParam];
1701 switch ( p->GetType() )
1703 case svSingleRef :
1705 ScSingleRefData& rRef = static_cast<ScToken*>(p)->GetSingleRef();
1706 rRef.CalcAbsIfRel( rPos );
1707 switch ( eDir )
1709 case DIR_BOTTOM :
1710 if ( rRef.nRow == nRow
1711 && rRef.nRow > nExtend )
1713 nExtend = rRef.nRow;
1714 bRet = TRUE;
1716 break;
1717 case DIR_RIGHT :
1718 if ( rRef.nCol == nCol
1719 && static_cast<SCCOLROW>(rRef.nCol)
1720 > nExtend )
1722 nExtend = rRef.nCol;
1723 bRet = TRUE;
1725 break;
1726 case DIR_TOP :
1727 if ( rRef.nRow == nRow
1728 && rRef.nRow < nExtend )
1730 nExtend = rRef.nRow;
1731 bRet = TRUE;
1733 break;
1734 case DIR_LEFT :
1735 if ( rRef.nCol == nCol
1736 && static_cast<SCCOLROW>(rRef.nCol)
1737 < nExtend )
1739 nExtend = rRef.nCol;
1740 bRet = TRUE;
1742 break;
1745 break;
1746 case svDoubleRef :
1748 ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1749 rRef.CalcAbsIfRel( rPos );
1750 switch ( eDir )
1752 case DIR_BOTTOM :
1753 if ( rRef.Ref1.nRow == nRow
1754 && rRef.Ref2.nRow > nExtend )
1756 nExtend = rRef.Ref2.nRow;
1757 bRet = TRUE;
1759 break;
1760 case DIR_RIGHT :
1761 if ( rRef.Ref1.nCol == nCol &&
1762 static_cast<SCCOLROW>(rRef.Ref2.nCol)
1763 > nExtend )
1765 nExtend = rRef.Ref2.nCol;
1766 bRet = TRUE;
1768 break;
1769 case DIR_TOP :
1770 if ( rRef.Ref2.nRow == nRow
1771 && rRef.Ref1.nRow < nExtend )
1773 nExtend = rRef.Ref1.nRow;
1774 bRet = TRUE;
1776 break;
1777 case DIR_LEFT :
1778 if ( rRef.Ref2.nCol == nCol &&
1779 static_cast<SCCOLROW>(rRef.Ref1.nCol)
1780 < nExtend )
1782 nExtend = rRef.Ref1.nCol;
1783 bRet = TRUE;
1785 break;
1788 break;
1789 default:
1791 // added to avoid warnings
1793 } // switch
1794 } // for
1795 return bRet;
1799 return FALSE;
1803 void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
1804 const ScAddress& rNewPos )
1806 for ( USHORT j=0; j<nLen; ++j )
1808 switch ( pCode[j]->GetType() )
1810 case svDoubleRef :
1812 ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2();
1813 // Also adjust if the reference is of the form Sheet1.A2:A3
1814 if ( rRef2.IsFlag3D() || static_cast<ScToken*>(pCode[j])->GetSingleRef().IsFlag3D() )
1816 rRef2.CalcAbsIfRel( rOldPos );
1817 rRef2.CalcRelFromAbs( rNewPos );
1820 //! fallthru
1821 case svSingleRef :
1823 ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1824 if ( rRef1.IsFlag3D() )
1826 rRef1.CalcAbsIfRel( rOldPos );
1827 rRef1.CalcRelFromAbs( rNewPos );
1830 break;
1831 default:
1833 // added to avoid warnings