Files
libreoffice/sc/source/core/tool/token.cxx

2282 lines
64 KiB
C++
Raw Normal View History

2000-09-18 23:16:46 +00:00
/*************************************************************************
*
* $RCSfile: token.cxx,v $
*
* $Revision: 1.21 $
2000-09-18 23:16:46 +00:00
*
* last change: $Author: kz $ $Date: 2004-09-07 10:42:41 $
2000-09-18 23:16:46 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#ifdef PCH
#include "core_pch.hxx"
#endif
#pragma hdrstop
// INCLUDE ---------------------------------------------------------------
#if STLPORT_VERSION<321
#include <stddef.h>
#else
#include <cstddef>
#endif
#include <string.h>
#ifndef _SVMEMPOOL_HXX //autogen
#include <tools/mempool.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif
#include "token.hxx"
#include "tokenarray.hxx"
2000-09-18 23:16:46 +00:00
#include "compiler.hxx"
#include "rechead.hxx"
#include "parclass.hxx"
2000-09-18 23:16:46 +00:00
// ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
// SubCode via ScTokenIterator Push/Pop moeglich
IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 );
2001-02-21 17:39:37 +00:00
// Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
// Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
// ScRawToken size is FixMembers + MAXSTRLEN ~= 264
IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken, 8, 4 );
// Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
const USHORT nMemPoolDoubleRawToken = 0x0400 / sizeof(ScDoubleRawToken);
IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken, nMemPoolDoubleRawToken, nMemPoolDoubleRawToken );
// Need a whole bunch of ScSingleRefToken
const USHORT nMemPoolSingleRefToken = (0x4000 - 64) / sizeof(ScSingleRefToken);
IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken, nMemPoolSingleRefToken, nMemPoolSingleRefToken );
// Need a lot of ScDoubleToken
const USHORT nMemPoolDoubleToken = (0x3000 - 64) / sizeof(ScDoubleToken);
2000-09-18 23:16:46 +00:00
IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleToken, nMemPoolDoubleToken, nMemPoolDoubleToken );
2001-02-21 17:39:37 +00:00
// Need a lot of ScByteToken
const USHORT nMemPoolByteToken = (0x3000 - 64) / sizeof(ScByteToken);
IMPL_FIXEDMEMPOOL_NEWDEL( ScByteToken, nMemPoolByteToken, nMemPoolByteToken );
// Need quite a lot of ScDoubleRefToken
const USHORT nMemPoolDoubleRefToken = (0x2000 - 64) / sizeof(ScDoubleRefToken);
IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken, nMemPoolDoubleRefToken, nMemPoolDoubleRefToken );
// Need several ScStringToken
const USHORT nMemPoolStringToken = (0x1000 - 64) / sizeof(ScStringToken);
IMPL_FIXEDMEMPOOL_NEWDEL( ScStringToken, nMemPoolStringToken, nMemPoolStringToken );
2000-09-18 23:16:46 +00:00
2001-02-21 17:39:37 +00:00
// --- helpers --------------------------------------------------------------
2000-09-18 23:16:46 +00:00
inline BOOL lcl_IsReference( OpCode eOp, StackVar eType )
{
return
(eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
|| (eOp == ocColRowNameAuto && eType == svDoubleRef)
|| (eOp == ocColRowName && eType == svSingleRef)
|| (eOp == ocMatRef && eType == svSingleRef)
2000-09-18 23:16:46 +00:00
;
}
2001-02-21 17:39:37 +00:00
// --- class ScRawToken -----------------------------------------------------
xub_StrLen ScRawToken::GetStrLen( const sal_Unicode* pStr )
2000-09-18 23:16:46 +00:00
{
if ( !pStr )
return 0;
register const sal_Unicode* p = pStr;
while ( *p )
p++;
return p - pStr;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetOpCode( OpCode e )
2000-09-18 23:16:46 +00:00
{
eOp = e;
if( eOp == ocIf )
{
eType = svJump; nJump[ 0 ] = 3; // If, Else, Behind
}
else if( eOp == ocChose )
{
eType = svJump; nJump[ 0 ] = MAXJUMPCOUNT+1;
}
else if( eOp == ocMissing )
eType = svMissing;
else
{
eType = svByte;
sbyte.cByte = 0;
sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
}
2000-09-18 23:16:46 +00:00
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetString( const sal_Unicode* pStr )
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svString;
if ( pStr )
{
xub_StrLen nLen = GetStrLen( pStr ) + 1;
if( nLen > MAXSTRLEN )
nLen = MAXSTRLEN;
memcpy( cStr, pStr, GetStrLenBytes( nLen ) );
cStr[ nLen-1 ] = 0;
}
else
cStr[0] = 0;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetSingleReference( const SingleRefData& rRef )
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svSingleRef;
aRef.Ref1 =
aRef.Ref2 = rRef;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetDoubleReference( const ComplRefData& rRef )
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svDoubleRef;
aRef = rRef;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetReference( ComplRefData& rRef )
2000-09-18 23:16:46 +00:00
{
DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "SetReference: no Ref" );
aRef = rRef;
if( GetType() == svSingleRef )
aRef.Ref2 = aRef.Ref1;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetDouble(double rVal)
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svDouble;
nValue = rVal;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetInt(int rVal)
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svDouble;
nValue = (double)rVal;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetName( USHORT n )
2000-09-18 23:16:46 +00:00
{
eOp = ocName;
eType = svIndex;
nIndex = n;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
ComplRefData& ScRawToken::GetReference()
2000-09-18 23:16:46 +00:00
{
DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
return aRef;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetExternal( const sal_Unicode* pStr )
2000-09-18 23:16:46 +00:00
{
eOp = ocExternal;
eType = svExternal;
xub_StrLen nLen = GetStrLen( pStr ) + 1;
if( nLen >= MAXSTRLEN )
nLen = MAXSTRLEN-1;
// Platz fuer Byte-Parameter lassen!
memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
cStr[ nLen+1 ] = 0;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
void ScRawToken::SetMatrix( ScMatrix* p )
2000-09-18 23:16:46 +00:00
{
eOp = ocPush;
eType = svMatrix;
pMat = p;
nRefCnt = 0;
}
2001-02-21 17:39:37 +00:00
ScRawToken* ScRawToken::Clone() const
2000-09-18 23:16:46 +00:00
{
2001-02-21 17:39:37 +00:00
ScRawToken* p;
2000-09-18 23:16:46 +00:00
if ( eType == svDouble )
{
2001-02-21 17:39:37 +00:00
p = (ScRawToken*) new ScDoubleRawToken;
2000-09-18 23:16:46 +00:00
p->eOp = eOp;
p->eType = eType;
p->nValue = nValue;
}
else
{
USHORT n = offsetof( ScRawToken, sbyte );
2000-09-18 23:16:46 +00:00
switch( eType )
{
case svByte: n += sizeof(ScRawToken::sbyte); break;
2000-09-18 23:16:46 +00:00
case svDouble: n += sizeof(double); break;
case svString: n += GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ); break;
case svSingleRef:
case svDoubleRef: n += sizeof(aRef); break;
case svMatrix: n += sizeof(ScMatrix*); break;
case svIndex: n += sizeof(USHORT); break;
case svJump: n += nJump[ 0 ] * 2 + 2; break;
case svExternal: n += GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ); break;
default: n += *((BYTE*)cStr); // read in unknown!
2000-09-18 23:16:46 +00:00
}
2001-02-21 17:39:37 +00:00
p = (ScRawToken*) new BYTE[ n ];
2000-09-18 23:16:46 +00:00
memcpy( p, this, n * sizeof(BYTE) );
}
p->nRefCnt = 0;
p->bRaw = FALSE;
return p;
}
2001-02-21 17:39:37 +00:00
ScToken* ScRawToken::CreateToken() const
{
switch ( GetType() )
2000-09-18 23:16:46 +00:00
{
2001-02-21 17:39:37 +00:00
case svByte :
return new ScByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
2001-02-21 17:39:37 +00:00
break;
case svDouble :
return new ScDoubleToken( eOp, nValue );
break;
case svString :
return new ScStringToken( eOp, String( cStr ) );
break;
case svSingleRef :
return new ScSingleRefToken( eOp, aRef.Ref1 );
break;
case svDoubleRef :
return new ScDoubleRefToken( eOp, aRef );
break;
case svMatrix :
return new ScMatrixToken( eOp, pMat );
break;
case svIndex :
return new ScIndexToken( eOp, nIndex );
break;
case svJump :
return new ScJumpToken( eOp, (short*) nJump );
break;
case svExternal :
return new ScExternalToken( eOp, sbyte.cByte, String( cStr+1 ) );
2001-02-21 17:39:37 +00:00
break;
2002-09-27 16:19:11 +00:00
case svFAP :
return new ScFAPToken( eOp, sbyte.cByte, NULL );
2002-09-27 16:19:11 +00:00
break;
2001-02-21 17:39:37 +00:00
case svMissing :
return new ScMissingToken( eOp );
break;
case svErr :
return new ScErrToken( eOp );
break;
default:
// read in unknown!
return new ScUnknownToken( eOp, GetType(), (BYTE*) cStr );
2000-09-18 23:16:46 +00:00
}
}
2001-02-21 17:39:37 +00:00
void ScRawToken::Delete()
2000-09-18 23:16:46 +00:00
{
if ( bRaw )
2001-02-21 17:39:37 +00:00
delete this; // FixedMemPool ScRawToken
2000-09-18 23:16:46 +00:00
else
2001-02-21 17:39:37 +00:00
{ // created per Clone
2000-09-18 23:16:46 +00:00
switch ( eType )
{
case svDouble :
2001-02-21 17:39:37 +00:00
delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken
2000-09-18 23:16:46 +00:00
break;
default:
delete [] (BYTE*) this;
}
}
}
2001-02-21 17:39:37 +00:00
// --- class ScToken --------------------------------------------------------
SingleRefData lcl_ScToken_InitSingleRef()
{
SingleRefData aRef;
aRef.InitAddress( ScAddress() );
return aRef;
}
ComplRefData lcl_ScToken_InitDoubleRef()
{
ComplRefData aRef;
aRef.Ref1 = lcl_ScToken_InitSingleRef();
aRef.Ref2 = aRef.Ref1;
return aRef;
}
SingleRefData ScToken::aDummySingleRef = lcl_ScToken_InitSingleRef();
ComplRefData ScToken::aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
String ScToken::aDummyString;
ScToken::~ScToken()
{
}
BOOL ScToken::IsFunction() const
{
return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
(GetByte() != 0 // x parameters
|| (ocEndUnOp < eOp && eOp <= ocEndNoPar) // no parameter
|| (ocIf == eOp || ocChose == eOp ) // @ jump commands
|| (ocEndNoPar < eOp && eOp <= ocEnd1Par) // one parameter
|| (ocEnd1Par < eOp && eOp <= ocEnd2Par) // x parameters (cByte==0 in
// FuncAutoPilot)
|| eOp == ocMacro || eOp == ocExternal // macros, AddIns
|| eOp == ocAnd || eOp == ocOr // former binary, now x parameters
|| eOp == ocNot || eOp == ocNeg // unary but function
|| (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // internal
));
}
BYTE ScToken::GetParamCount() const
{
if ( eOp <= ocEndDiv && eOp != ocExternal && eOp != ocMacro &&
eOp != ocIf && eOp != ocChose && eOp != ocPercentSign )
2001-02-21 17:39:37 +00:00
return 0; // parameters and specials
// ocIf and ocChose not for FAP, have cByte then
//2do: BOOL parameter whether FAP or not?
else if ( GetByte() )
return GetByte(); // all functions, also ocExternal and ocMacro
else if ( ocEndDiv < eOp && eOp <= ocEndBinOp )
return 2; // binary
else if ( (ocEndBinOp < eOp && eOp <= ocEndUnOp) || eOp == ocPercentSign )
2001-02-21 17:39:37 +00:00
return 1; // unary
else if ( ocEndUnOp < eOp && eOp <= ocEndNoPar )
return 0; // no parameter
else if ( ocEndNoPar < eOp && eOp <= ocEnd1Par )
return 1; // one parameter
else if ( eOp == ocIf || eOp == ocChose )
return 1; // only the condition counts as parameter
2001-02-21 17:39:37 +00:00
else
return 0; // all the rest, no Parameter, or
// if so then it should be in cByte
}
BOOL ScToken::IsMatrixFunction() const
{
switch ( eOp )
{
case ocDde :
case ocGrowth :
case ocTrend :
case ocRKP :
case ocRGP :
case ocFrequency :
case ocMatTrans :
case ocMatMult :
case ocMatInv :
case ocMatrixUnit :
return TRUE;
break;
}
return FALSE;
}
ScToken* ScToken::Clone() const
{
switch ( GetType() )
{
case svByte :
return new ScByteToken( *static_cast<const ScByteToken*>(this) );
break;
case svDouble :
return new ScDoubleToken( *static_cast<const ScDoubleToken*>(this) );
break;
case svString :
return new ScStringToken( *static_cast<const ScStringToken*>(this) );
break;
case svSingleRef :
return new ScSingleRefToken( *static_cast<const ScSingleRefToken*>(this) );
break;
case svDoubleRef :
return new ScDoubleRefToken( *static_cast<const ScDoubleRefToken*>(this) );
break;
case svMatrix :
return new ScMatrixToken( *static_cast<const ScMatrixToken*>(this) );
break;
case svIndex :
return new ScIndexToken( *static_cast<const ScIndexToken*>(this) );
break;
case svJump :
return new ScJumpToken( *static_cast<const ScJumpToken*>(this) );
break;
case svJumpMatrix :
return new ScJumpMatrixToken( *static_cast<const ScJumpMatrixToken*>(this) );
break;
2001-02-21 17:39:37 +00:00
case svExternal :
return new ScExternalToken( *static_cast<const ScExternalToken*>(this) );
break;
2002-09-27 16:19:11 +00:00
case svFAP :
return new ScFAPToken( *static_cast<const ScFAPToken*>(this) );
break;
2001-02-21 17:39:37 +00:00
case svMissing :
return new ScMissingToken( *static_cast<const ScMissingToken*>(this) );
break;
case svErr :
return new ScErrToken( *static_cast<const ScErrToken*>(this) );
break;
default:
// read in unknown!
return new ScUnknownToken( *static_cast<const ScUnknownToken*>(this) );
}
}
BOOL ScToken::operator==( const ScToken& rToken ) const
{
// don't compare reference count!
return eOp == rToken.eOp && eType == rToken.eType;
}
// TextEqual: if same formula entered (for optimization in sort)
BOOL ScToken::TextEqual( const ScToken& rToken ) const
2000-09-18 23:16:46 +00:00
{
if ( eType == svSingleRef || eType == svDoubleRef )
{
2001-02-21 17:39:37 +00:00
// in relative Refs only compare relative parts
2000-09-18 23:16:46 +00:00
if ( eOp != rToken.eOp || eType != rToken.eType )
return FALSE;
2001-02-21 17:39:37 +00:00
ComplRefData aTemp1;
if ( eType == svSingleRef )
{
aTemp1.Ref1 = GetSingleRef();
aTemp1.Ref2 = aTemp1.Ref1;
}
else
aTemp1 = GetDoubleRef();
ComplRefData aTemp2;
if ( rToken.eType == svSingleRef )
{
aTemp2.Ref1 = rToken.GetSingleRef();
aTemp2.Ref2 = aTemp2.Ref1;
}
else
aTemp2 = rToken.GetDoubleRef();
2000-09-18 23:16:46 +00:00
ScAddress aPos;
aTemp1.SmartRelAbs(aPos);
aTemp2.SmartRelAbs(aPos);
2001-02-21 17:39:37 +00:00
// memcmp doesn't work because of the alignment byte after bFlags.
// After SmartRelAbs only absolute parts have to be compared.
2000-09-18 23:16:46 +00:00
return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol &&
aTemp1.Ref1.nRow == aTemp2.Ref1.nRow &&
aTemp1.Ref1.nTab == aTemp2.Ref1.nTab &&
aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags &&
aTemp1.Ref2.nCol == aTemp2.Ref2.nCol &&
aTemp1.Ref2.nRow == aTemp2.Ref2.nRow &&
aTemp1.Ref2.nTab == aTemp2.Ref2.nTab &&
aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags;
}
else
2001-02-21 17:39:37 +00:00
return *this == rToken; // else normal operator==
}
BOOL ScToken::Is3DRef() const
{
switch ( eType )
{
case svDoubleRef :
if ( GetSingleRef2().IsFlag3D() )
return TRUE;
//! fallthru
case svSingleRef :
if ( GetSingleRef().IsFlag3D() )
return TRUE;
}
return FALSE;
}
BOOL ScToken::IsRPNReferenceAbsName() const
{
if ( GetRef() == 1 && GetOpCode() == ocPush )
{ // only in RPN and not ocColRowNameAuto or similar
switch ( GetType() )
{
case svDoubleRef :
if ( !GetSingleRef2().IsRelName() )
return TRUE;
//! fallthru
case svSingleRef :
if ( !GetSingleRef().IsRelName() )
return TRUE;
}
}
return FALSE;
}
// --- virtual dummy methods -------------------------------------------------
2001-02-21 17:39:37 +00:00
BYTE ScToken::GetByte() const
{
// ok to be called for any derived class
return 0;
}
void ScToken::SetByte( BYTE n )
{
DBG_ERRORFILE( "ScToken::SetByte: virtual dummy called" );
}
bool ScToken::HasForceArray() const
{
// ok to be called for any derived class
return false;
}
void ScToken::SetForceArray( bool b )
{
DBG_ERRORFILE( "ScToken::SetForceArray: virtual dummy called" );
}
2001-02-21 17:39:37 +00:00
double ScToken::GetDouble() const
{
DBG_ERRORFILE( "ScToken::GetDouble: virtual dummy called" );
return 0.0;
2000-09-18 23:16:46 +00:00
}
2001-02-21 17:39:37 +00:00
const String& ScToken::GetString() const
{
DBG_ERRORFILE( "ScToken::GetString: virtual dummy called" );
return aDummyString;
}
const SingleRefData& ScToken::GetSingleRef() const
{
DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
return aDummySingleRef;
}
SingleRefData& ScToken::GetSingleRef()
{
DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" );
return aDummySingleRef;
}
const ComplRefData& ScToken::GetDoubleRef() const
{
DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
return aDummyDoubleRef;
}
ComplRefData& ScToken::GetDoubleRef()
{
DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" );
return aDummyDoubleRef;
}
const SingleRefData& ScToken::GetSingleRef2() const
{
DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
return aDummySingleRef;
}
SingleRefData& ScToken::GetSingleRef2()
{
DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" );
return aDummySingleRef;
}
2001-02-21 17:39:37 +00:00
void ScToken::CalcAbsIfRel( const ScAddress& rPos )
{
DBG_ERRORFILE( "ScToken::CalcAbsIfRel: virtual dummy called" );
}
void ScToken::CalcRelFromAbs( const ScAddress& rPos )
{
DBG_ERRORFILE( "ScToken::CalcRelFromAbs: virtual dummy called" );
}
ScMatrix* ScToken::GetMatrix() const
{
DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" );
return NULL;
}
USHORT ScToken::GetIndex() const
{
DBG_ERRORFILE( "ScToken::GetIndex: virtual dummy called" );
return 0;
}
void ScToken::SetIndex( USHORT n )
{
DBG_ERRORFILE( "ScToken::SetIndex: virtual dummy called" );
}
short* ScToken::GetJump() const
{
DBG_ERRORFILE( "ScToken::GetJump: virtual dummy called" );
return NULL;
}
ScJumpMatrix* ScToken::GetJumpMatrix() const
{
DBG_ERRORFILE( "ScToken::GetJumpMatrix: virtual dummy called" );
return NULL;
}
2001-02-21 17:39:37 +00:00
const String& ScToken::GetExternal() const
{
DBG_ERRORFILE( "ScToken::GetExternal: virtual dummy called" );
return aDummyString;
}
BYTE* ScToken::GetUnknown() const
{
DBG_ERRORFILE( "ScToken::GetUnknown: virtual dummy called" );
return NULL;
}
2002-09-27 16:19:11 +00:00
ScToken* ScToken::GetFAPOrigToken() const
{
DBG_ERRORFILE( "ScToken::GetFAPOrigToken: virtual dummy called" );
return NULL;
}
2001-02-21 17:39:37 +00:00
// real implementations of virtual functions
BYTE ScByteToken::GetByte() const { return nByte; }
void ScByteToken::SetByte( BYTE n ) { nByte = n; }
bool ScByteToken::HasForceArray() const { return bHasForceArray; }
void ScByteToken::SetForceArray( bool b ) { bHasForceArray = b; }
2001-02-21 17:39:37 +00:00
BOOL ScByteToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && nByte == r.GetByte() &&
bHasForceArray == r.HasForceArray();
2001-02-21 17:39:37 +00:00
}
2002-09-27 16:19:11 +00:00
ScToken* ScFAPToken::GetFAPOrigToken() const { return pOrigToken; }
BOOL ScFAPToken::operator==( const ScToken& r ) const
{
return ScByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken();
2002-09-27 16:19:11 +00:00
}
2001-02-21 17:39:37 +00:00
double ScDoubleToken::GetDouble() const { return fDouble; }
BOOL ScDoubleToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && fDouble == r.GetDouble();
}
const String& ScStringToken::GetString() const { return aString; }
BOOL ScStringToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && aString == r.GetString();
}
const SingleRefData& ScSingleRefToken::GetSingleRef() const { return aSingleRef; }
SingleRefData& ScSingleRefToken::GetSingleRef() { return aSingleRef; }
void ScSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
{ aSingleRef.CalcAbsIfRel( rPos ); }
void ScSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
{ aSingleRef.CalcRelFromAbs( rPos ); }
BOOL ScSingleRefToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && aSingleRef == r.GetSingleRef();
}
const SingleRefData& ScDoubleRefToken::GetSingleRef() const { return aDoubleRef.Ref1; }
SingleRefData& ScDoubleRefToken::GetSingleRef() { return aDoubleRef.Ref1; }
const ComplRefData& ScDoubleRefToken::GetDoubleRef() const { return aDoubleRef; }
ComplRefData& ScDoubleRefToken::GetDoubleRef() { return aDoubleRef; }
const SingleRefData& ScDoubleRefToken::GetSingleRef2() const { return aDoubleRef.Ref2; }
SingleRefData& ScDoubleRefToken::GetSingleRef2() { return aDoubleRef.Ref2; }
2001-02-21 17:39:37 +00:00
void ScDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
{ aDoubleRef.CalcAbsIfRel( rPos ); }
void ScDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
{ aDoubleRef.CalcRelFromAbs( rPos ); }
BOOL ScDoubleRefToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && aDoubleRef == r.GetDoubleRef();
}
ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix; }
BOOL ScMatrixToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && pMatrix == r.GetMatrix();
}
USHORT ScIndexToken::GetIndex() const { return nIndex; }
void ScIndexToken::SetIndex( USHORT n ) { nIndex = n; }
BOOL ScIndexToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && nIndex == r.GetIndex();
}
short* ScJumpToken::GetJump() const { return pJump; }
BOOL ScJumpToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0;
}
ScJumpToken::~ScJumpToken()
{
delete [] pJump;
}
ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; }
BOOL ScJumpMatrixToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && pJumpMatrix == r.GetJumpMatrix();
}
2001-02-21 17:39:37 +00:00
const String& ScExternalToken::GetExternal() const { return aExternal; }
BYTE ScExternalToken::GetByte() const { return nByte; }
void ScExternalToken::SetByte( BYTE n ) { nByte = n; }
BOOL ScExternalToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && nByte == r.GetByte() &&
aExternal == r.GetExternal();
}
double ScMissingToken::GetDouble() const { return 0.0; }
const String& ScMissingToken::GetString() const { return aDummyString; }
BOOL ScMissingToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r );
}
BOOL ScErrToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r );
}
BYTE* ScUnknownToken::GetUnknown() const { return pUnknown; }
BOOL ScUnknownToken::operator==( const ScToken& r ) const
{
return ScToken::operator==( r ) && pUnknown[0] == r.GetUnknown()[0] &&
memcmp( pUnknown+1, r.GetUnknown()+1, pUnknown[0] * sizeof(BYTE) ) == 0;
}
ScUnknownToken::~ScUnknownToken()
{
delete [] pUnknown;
}
2000-09-18 23:16:46 +00:00
//////////////////////////////////////////////////////////////////////////
ScToken* ScTokenArray::GetNextReference()
{
while( nIndex < nLen )
{
ScToken* t = pCode[ nIndex++ ];
switch( t->GetType() )
{
case svSingleRef:
case svDoubleRef:
return t;
}
}
return NULL;
}
ScToken* ScTokenArray::GetNextColRowName()
{
while( nIndex < nLen )
{
ScToken* t = pCode[ nIndex++ ];
if ( t->GetOpCode() == ocColRowName )
return t;
}
return NULL;
}
ScToken* ScTokenArray::GetNextReferenceRPN()
{
while( nIndex < nRPN )
{
ScToken* t = pRPN[ nIndex++ ];
switch( t->GetType() )
{
case svSingleRef:
case svDoubleRef:
return t;
}
}
return NULL;
}
ScToken* ScTokenArray::GetNextReferenceOrName()
{
for( ScToken* t = Next(); t; t = Next() )
{
switch( t->GetType() )
{
case svSingleRef:
case svDoubleRef:
case svIndex:
return t;
}
}
return NULL;
}
ScToken* ScTokenArray::GetNextName()
{
for( ScToken* t = Next(); t; t = Next() )
{
if( t->GetType() == svIndex )
return t;
}
return NULL;
}
ScToken* ScTokenArray::GetNextDBArea()
{
for( ScToken* t = Next(); t; t = Next() )
{
if ( t->GetOpCode() == ocDBArea )
return t;
}
return NULL;
}
ScToken* ScTokenArray::GetNextOpCodeRPN( OpCode eOp )
{
while( nIndex < nRPN )
{
ScToken* t = pRPN[ nIndex++ ];
if ( t->GetOpCode() == eOp )
return t;
}
return NULL;
}
ScToken* ScTokenArray::Next()
{
if( pCode && nIndex < nLen )
return pCode[ nIndex++ ];
else
return NULL;
}
ScToken* ScTokenArray::NextNoSpaces()
{
if( pCode )
{
while( (nIndex < nLen) && (pCode[ nIndex ]->GetOpCode() == ocSpaces) )
++nIndex;
if( nIndex < nLen )
return pCode[ nIndex++ ];
}
return NULL;
}
2000-09-18 23:16:46 +00:00
ScToken* ScTokenArray::NextRPN()
{
if( pRPN && nIndex < nRPN )
return pRPN[ nIndex++ ];
else
return NULL;
}
ScToken* ScTokenArray::PrevRPN()
{
if( pRPN && nIndex )
return pRPN[ --nIndex ];
else
return NULL;
}
void ScTokenArray::DelRPN()
{
if( nRPN )
{
ScToken** p = pRPN;
for( USHORT i = 0; i < nRPN; i++ )
{
(*p++)->DecRef();
}
delete [] pRPN;
}
pRPN = NULL;
nRPN = nIndex = 0;
}
ScToken* ScTokenArray::PeekNext()
{
if( pCode && nIndex < nLen )
return pCode[ nIndex ];
else
return NULL;
}
ScToken* ScTokenArray::PeekNextNoSpaces()
{
if( pCode && nIndex < nLen )
{
USHORT j = nIndex;
while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
j++;
if ( j < nLen )
return pCode[ j ];
else
return NULL;
}
else
return NULL;
}
ScToken* ScTokenArray::PeekPrevNoSpaces()
{
if( pCode && nIndex > 1 )
{
USHORT j = nIndex - 2;
while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
j--;
if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
return pCode[ j ];
else
return NULL;
}
else
return NULL;
}
BOOL ScTokenArray::HasOpCodeRPN( OpCode eOp ) const
{
for ( USHORT j=0; j < nRPN; j++ )
{
if ( pRPN[j]->GetOpCode() == eOp )
return TRUE;
}
return FALSE;
}
BOOL ScTokenArray::HasName() const
{
for ( USHORT j=0; j < nLen; j++ )
{
if( pCode[j]->GetType() == svIndex )
return TRUE;
}
return FALSE;
}
2001-10-08 17:34:18 +00:00
BOOL ScTokenArray::HasNameOrColRowName() const
{
for ( USHORT j=0; j < nLen; j++ )
{
if( pCode[j]->GetType() == svIndex || pCode[j]->GetOpCode() == ocColRowName )
return TRUE;
}
return FALSE;
}
BOOL ScTokenArray::ImplGetReference( ScRange& rRange, BOOL bValidOnly ) const
2000-09-18 23:16:46 +00:00
{
BOOL bIs = FALSE;
if ( pCode && nLen == 1 )
{
2001-02-21 17:39:37 +00:00
const ScToken* pToken = pCode[0];
2000-09-18 23:16:46 +00:00
if ( pToken )
{
if ( pToken->GetType() == svSingleRef )
{
2001-02-21 17:39:37 +00:00
const SingleRefData& rRef = ((const ScSingleRefToken*)pToken)->GetSingleRef();
2000-09-18 23:16:46 +00:00
rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab );
bIs = !bValidOnly || !rRef.IsDeleted();
2000-09-18 23:16:46 +00:00
}
else if ( pToken->GetType() == svDoubleRef )
{
2001-02-21 17:39:37 +00:00
const ComplRefData& rCompl = ((const ScDoubleRefToken*)pToken)->GetDoubleRef();
const SingleRefData& rRef1 = rCompl.Ref1;
const SingleRefData& rRef2 = rCompl.Ref2;
2000-09-18 23:16:46 +00:00
rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab );
rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab );
bIs = !bValidOnly || (!rRef1.IsDeleted() && !rRef2.IsDeleted());
2000-09-18 23:16:46 +00:00
}
}
}
return bIs;
}
BOOL ScTokenArray::IsReference( ScRange& rRange ) const
{
return ImplGetReference( rRange, FALSE );
}
BOOL ScTokenArray::IsValidReference( ScRange& rRange ) const
{
return ImplGetReference( rRange, TRUE );
}
2000-09-18 23:16:46 +00:00
void ScTokenArray::Load30( SvStream& rStream, const ScAddress& rPos )
{
Clear();
ScToken* pToks[ MAXCODE ];
2001-02-21 17:39:37 +00:00
ScRawToken t;
2000-09-18 23:16:46 +00:00
for( nLen = 0; nLen < MAXCODE; nLen++ )
{
t.Load30( rStream );
if( t.GetOpCode() == ocStop )
break;
else if( t.GetOpCode() == ocPush
&& ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef ) )
{
nRefs++;
t.aRef.CalcRelFromAbs( rPos );
}
2001-02-21 17:39:37 +00:00
ScToken* p = pToks[ nLen ] = t.CreateToken();
2000-09-18 23:16:46 +00:00
p->IncRef();
}
pCode = new ScToken*[ nLen ];
memcpy( pCode, pToks, nLen * sizeof( ScToken* ) );
}
void ScTokenArray::Load( SvStream& rStream, USHORT nVer, const ScAddress& rPos )
{
Clear();
// 0x10 - nRefs
// 0x20 - nError
// 0x40 - TokenArray
// 0x80 - CodeArray
BYTE cData;
rStream >> cData;
if( cData & 0x0F )
rStream.SeekRel( cData & 0x0F );
if ( nVer < SC_RECALC_MODE_BITS )
{
BYTE cMode;
rStream >> cMode;
ImportRecalcMode40( (ScRecalcMode40) cMode );
}
else
rStream >> nMode;
if( cData & 0x10 )
rStream >> nRefs;
if( cData & 0x20 )
rStream >> nError;
ScToken* pToks[ MAXCODE ];
ScToken** pp = pToks;
2001-02-21 17:39:37 +00:00
ScRawToken t;
2000-09-18 23:16:46 +00:00
if( cData & 0x40 )
{
rStream >> nLen;
for( USHORT i = 0; i < nLen; i++ )
{
t.Load( rStream, nVer );
if ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef )
t.aRef.CalcRelFromAbs( rPos );
// gespeichert wurde und wird immer absolut
2001-02-21 17:39:37 +00:00
*pp = t.CreateToken();
2000-09-18 23:16:46 +00:00
(*pp++)->IncRef();
}
pCode = new ScToken*[ nLen ];
memcpy( pCode, pToks, nLen * sizeof( ScToken* ) );
}
pp = pToks;
if( cData & 0x80 )
{
rStream >> nRPN;
for( USHORT i = 0; i < nRPN; i++, pp++ )
{
BYTE b1, b2 = 0;
UINT16 nIdx;
rStream >> b1;
// 0xFF - Token folgt
// 0x40-0x7F - untere 6 Bits, 1 Byte mit 8 weiteren Bits
// 0x00-0x3F - Index
if( b1 == 0xFF )
{
t.Load( rStream, nVer );
if ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef )
t.aRef.CalcRelFromAbs( rPos );
// gespeichert wurde und wird immer absolut
2001-02-21 17:39:37 +00:00
*pp = t.CreateToken();
2000-09-18 23:16:46 +00:00
}
else
{
if( b1 & 0x40 )
{
rStream >> b2;
nIdx = ( b1 & 0x3F ) | ( b2 << 6 );
}
else
nIdx = b1;
*pp = pCode[ nIdx ];
}
(*pp)->IncRef();
// #73616# CONVERT function recalculated on each load
if ( nVer < SC_CONVERT_RECALC_ON_LOAD && (*pp)->GetOpCode() == ocConvert )
AddRecalcMode( RECALCMODE_ONLOAD );
}
pRPN = new ScToken*[ nRPN ];
memcpy( pRPN, pToks, nRPN * sizeof( ScToken* ) );
// Aeltere Versionen: kein UPN-Array laden
if( nVer < SC_NEWIF )
DelRPN();
}
}
void ScTokenArray::Store( SvStream& rStream, const ScAddress& rPos ) const
{
// 0x10 - nRefs
// 0x20 - nError
// 0x40 - TokenArray
// 0x80 - CodeArray
BYTE cFlags = 0;
if( nRefs )
cFlags |= 0x10;
if( nError )
cFlags |= 0x20;
if( nLen )
cFlags |= 0x40;
if( nRPN )
cFlags |= 0x80;
rStream << cFlags;
// Hier ggf. Zusatzdaten!
if ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 )
rStream << (BYTE) ExportRecalcMode40();
else
rStream << (BYTE) nMode;
if( cFlags & 0x10 )
rStream << (INT16) nRefs;
if( cFlags & 0x20 )
rStream << (UINT16) nError;
if( cFlags & 0x40 )
{
rStream << nLen;
ScToken** p = pCode;
for( USHORT i = 0; i < nLen; i++, p++ )
{
// gespeichert wurde und wird immer absolut
switch ( (*p)->GetType() )
{
case svSingleRef :
2001-02-21 17:39:37 +00:00
(*p)->GetSingleRef().CalcAbsIfRel( rPos );
2000-09-18 23:16:46 +00:00
break;
case svDoubleRef :
2001-02-21 17:39:37 +00:00
(*p)->GetDoubleRef().CalcAbsIfRel( rPos );
2000-09-18 23:16:46 +00:00
break;
}
(*p)->Store( rStream );
}
}
if( cFlags & 0x80 )
{
rStream << nRPN;
ScToken** p = pRPN;
for( USHORT i = 0; i < nRPN; i++, p++ )
{
ScToken* t = *p;
USHORT nIdx = 0xFFFF;
if( t->GetRef() > 1 )
{
ScToken** p2 = pCode;
for( USHORT j = 0; j < nLen; j++, p2++ )
{
if( *p2 == t )
{
nIdx = j; break;
}
}
}
// 0xFF - Token folgt
// 0x40-0x7F - untere 6 Bits, 1 Byte mit 8 weiteren Bits
// 0x00-0x3F - Index
if( nIdx == 0xFFFF )
{
// gespeichert wurde und wird immer absolut
switch ( t->GetType() )
{
case svSingleRef :
2001-02-21 17:39:37 +00:00
t->GetSingleRef().CalcAbsIfRel( rPos );
2000-09-18 23:16:46 +00:00
break;
case svDoubleRef :
2001-02-21 17:39:37 +00:00
t->GetDoubleRef().CalcAbsIfRel( rPos );
2000-09-18 23:16:46 +00:00
break;
}
rStream << (BYTE) 0xFF;
t->Store( rStream );
}
else
{
if( nIdx < 0x40 )
rStream << (BYTE) nIdx;
else
rStream << (BYTE) ( ( nIdx & 0x3F ) | 0x40 )
<< (BYTE) ( nIdx >> 6 );
}
}
}
}
////////////////////////////////////////////////////////////////////////////
ScTokenArray::ScTokenArray()
{
pCode = NULL; pRPN = NULL;
nError = nLen = nIndex = nRPN = nRefs = 0;
bHyperLink = FALSE;
2000-09-18 23:16:46 +00:00
ClearRecalcMode();
}
ScTokenArray::ScTokenArray( const ScTokenArray& rArr )
{
Assign( rArr );
}
ScTokenArray::~ScTokenArray()
{
Clear();
}
void ScTokenArray::Assign( const ScTokenArray& r )
{
nLen = r.nLen;
nRPN = r.nRPN;
nIndex = r.nIndex;
nError = r.nError;
nRefs = r.nRefs;
nMode = r.nMode;
bHyperLink = r.bHyperLink;
2000-09-18 23:16:46 +00:00
pCode = NULL;
pRPN = NULL;
ScToken** pp;
if( nLen )
{
pp = pCode = new ScToken*[ nLen ];
memcpy( pp, r.pCode, nLen * sizeof( ScToken* ) );
for( USHORT i = 0; i < nLen; i++ )
(*pp++)->IncRef();
}
if( nRPN )
{
pp = pRPN = new ScToken*[ nRPN ];
memcpy( pp, r.pRPN, nRPN * sizeof( ScToken* ) );
for( USHORT i = 0; i < nRPN; i++ )
(*pp++)->IncRef();
}
}
ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
{
Clear();
Assign( rArr );
return *this;
}
ScTokenArray* ScTokenArray::Clone() const
{
ScTokenArray* p = new ScTokenArray;
p->nLen = nLen;
p->nRPN = nRPN;
p->nRefs = nRefs;
p->nMode = nMode;
p->nError = nError;
p->bHyperLink = bHyperLink;
2000-09-18 23:16:46 +00:00
ScToken** pp;
if( nLen )
{
pp = p->pCode = new ScToken*[ nLen ];
memcpy( pp, pCode, nLen * sizeof( ScToken* ) );
for( USHORT i = 0; i < nLen; i++, pp++ )
{
*pp = (*pp)->Clone();
(*pp)->IncRef();
}
}
if( nRPN )
{
pp = p->pRPN = new ScToken*[ nRPN ];
memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) );
for( USHORT i = 0; i < nRPN; i++, pp++ )
{
ScToken* t = *pp;
if( t->GetRef() > 1 )
{
ScToken** p2 = pCode;
USHORT nIdx = 0xFFFF;
for( USHORT j = 0; j < nLen; j++, p2++ )
{
if( *p2 == t )
{
nIdx = j; break;
}
}
if( nIdx == 0xFFFF )
*pp = t->Clone();
else
*pp = p->pCode[ nIdx ];
}
else
*pp = t->Clone();
(*pp)->IncRef();
}
}
return p;
}
void ScTokenArray::Clear()
{
if( nRPN ) DelRPN();
if( pCode )
{
ScToken** p = pCode;
for( USHORT i = 0; i < nLen; i++ )
{
(*p++)->DecRef();
}
delete [] pCode;
}
pCode = NULL; pRPN = NULL;
nError = nLen = nIndex = nRPN = nRefs = 0;
bHyperLink = FALSE;
2000-09-18 23:16:46 +00:00
ClearRecalcMode();
}
2001-02-21 17:39:37 +00:00
ScToken* ScTokenArray::AddToken( const ScRawToken& r )
{
return Add( r.CreateToken() );
}
2000-09-18 23:16:46 +00:00
ScToken* ScTokenArray::AddToken( const ScToken& r )
{
return Add( r.Clone() );
}
// Wird auch vom Compiler genutzt. Das Token ist per new angelegt!
ScToken* ScTokenArray::Add( ScToken* t )
{
if( !pCode )
pCode = new ScToken*[ MAXCODE ];
if( nLen < MAXCODE-1 )
2000-09-18 23:16:46 +00:00
{
pCode[ nLen++ ] = t;
if( t->GetOpCode() == ocPush
&& ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
nRefs++;
t->IncRef();
return t;
}
else
{
t->Delete();
if ( nLen == MAXCODE-1 )
{
t = new ScByteToken( ocStop );
pCode[ nLen++ ] = t;
t->IncRef();
}
2000-09-18 23:16:46 +00:00
return NULL;
}
}
ScToken* ScTokenArray::AddOpCode( OpCode e )
{
2001-02-21 17:39:37 +00:00
ScRawToken t;
2000-09-18 23:16:46 +00:00
t.SetOpCode( e );
return AddToken( t );
}
ScToken* ScTokenArray::AddString( const sal_Unicode* pStr )
{
2001-02-21 17:39:37 +00:00
return AddString( String( pStr ) );
2000-09-18 23:16:46 +00:00
}
2001-02-21 17:39:37 +00:00
ScToken* ScTokenArray::AddString( const String& rStr )
2000-09-18 23:16:46 +00:00
{
2001-02-21 17:39:37 +00:00
return Add( new ScStringToken( rStr ) );
}
ScToken* ScTokenArray::AddDouble( double fVal )
{
return Add( new ScDoubleToken( fVal ) );
2000-09-18 23:16:46 +00:00
}
ScToken* ScTokenArray::AddSingleReference( const SingleRefData& rRef )
{
2001-02-21 17:39:37 +00:00
return Add( new ScSingleRefToken( rRef ) );
2000-09-18 23:16:46 +00:00
}
ScToken* ScTokenArray::AddDoubleReference( const ComplRefData& rRef )
{
2001-02-21 17:39:37 +00:00
return Add( new ScDoubleRefToken( rRef ) );
2000-09-18 23:16:46 +00:00
}
ScToken* ScTokenArray::AddName( USHORT n )
{
2001-02-21 17:39:37 +00:00
return Add( new ScIndexToken( ocName, n ) );
2000-09-18 23:16:46 +00:00
}
ScToken* ScTokenArray::AddExternal( const sal_Unicode* pStr )
{
2001-02-21 17:39:37 +00:00
return AddExternal( String( pStr ) );
}
ScToken* ScTokenArray::AddExternal( const String& rStr )
{
return Add( new ScExternalToken( ocExternal, rStr ) );
2000-09-18 23:16:46 +00:00
}
ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
{
2001-02-21 17:39:37 +00:00
return Add( new ScMatrixToken( p ) );
2000-09-18 23:16:46 +00:00
}
2000-09-22 12:42:36 +00:00
ScToken* ScTokenArray::AddColRowName( const SingleRefData& rRef )
{
2001-02-21 17:39:37 +00:00
return Add( new ScSingleRefToken( ocColRowName, rRef ) );
2000-09-22 12:42:36 +00:00
}
2000-09-18 23:16:46 +00:00
ScToken* ScTokenArray::AddBad( const sal_Unicode* pStr )
{
2001-02-21 17:39:37 +00:00
return AddBad( String( pStr ) );
}
ScToken* ScTokenArray::AddBad( const String& rStr )
{
return Add( new ScStringToken( ocBad, rStr ) );
2000-09-18 23:16:46 +00:00
}
BOOL ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
2000-09-18 23:16:46 +00:00
const ScAddress& rPos, ScDirection eDir )
{
SCCOL nCol;
SCROW nRow;
2000-09-18 23:16:46 +00:00
switch ( eDir )
{
case DIR_BOTTOM :
if ( rPos.Row() < MAXROW )
nRow = (nExtend = rPos.Row()) + 1;
else
return FALSE;
break;
case DIR_RIGHT :
if ( rPos.Col() < MAXCOL )
nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
2000-09-18 23:16:46 +00:00
else
return FALSE;
break;
case DIR_TOP :
if ( rPos.Row() > 0 )
nRow = (nExtend = rPos.Row()) - 1;
else
return FALSE;
break;
case DIR_LEFT :
if ( rPos.Col() > 0 )
nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
2000-09-18 23:16:46 +00:00
else
return FALSE;
break;
default:
DBG_ERRORFILE( "unknown Direction" );
return FALSE;
}
if ( pRPN && nRPN )
{
ScToken* t = pRPN[nRPN-1];
if ( t->GetType() == svByte )
{
2001-02-21 17:39:37 +00:00
BYTE nParamCount = t->GetByte();
2000-09-18 23:16:46 +00:00
if ( nParamCount && nRPN > nParamCount )
{
BOOL bRet = FALSE;
USHORT nParam = nRPN - nParamCount - 1;
for ( ; nParam < nRPN-1; nParam++ )
{
ScToken* p = pRPN[nParam];
switch ( p->GetType() )
{
case svSingleRef :
2001-02-21 17:39:37 +00:00
{
SingleRefData& rRef = p->GetSingleRef();
rRef.CalcAbsIfRel( rPos );
switch ( eDir )
{
case DIR_BOTTOM :
if ( rRef.nRow == nRow
&& rRef.nRow > nExtend )
{
nExtend = rRef.nRow;
bRet = TRUE;
}
break;
case DIR_RIGHT :
if ( rRef.nCol == nCol
&& static_cast<SCCOLROW>(rRef.nCol)
> nExtend )
2001-02-21 17:39:37 +00:00
{
nExtend = rRef.nCol;
bRet = TRUE;
}
break;
case DIR_TOP :
if ( rRef.nRow == nRow
&& rRef.nRow < nExtend )
{
nExtend = rRef.nRow;
bRet = TRUE;
}
break;
case DIR_LEFT :
if ( rRef.nCol == nCol
&& static_cast<SCCOLROW>(rRef.nCol)
< nExtend )
2001-02-21 17:39:37 +00:00
{
nExtend = rRef.nCol;
bRet = TRUE;
}
break;
}
}
break;
2000-09-18 23:16:46 +00:00
case svDoubleRef :
{
2001-02-21 17:39:37 +00:00
ComplRefData& rRef = p->GetDoubleRef();
2000-09-18 23:16:46 +00:00
rRef.CalcAbsIfRel( rPos );
switch ( eDir )
{
case DIR_BOTTOM :
if ( rRef.Ref1.nRow == nRow
&& rRef.Ref2.nRow > nExtend )
{
nExtend = rRef.Ref2.nRow;
bRet = TRUE;
}
break;
case DIR_RIGHT :
if ( rRef.Ref1.nCol == nCol &&
static_cast<SCCOLROW>(rRef.Ref2.nCol)
> nExtend )
2000-09-18 23:16:46 +00:00
{
nExtend = rRef.Ref2.nCol;
bRet = TRUE;
}
break;
case DIR_TOP :
if ( rRef.Ref2.nRow == nRow
&& rRef.Ref1.nRow < nExtend )
{
nExtend = rRef.Ref1.nRow;
bRet = TRUE;
}
break;
case DIR_LEFT :
if ( rRef.Ref2.nCol == nCol &&
static_cast<SCCOLROW>(rRef.Ref1.nCol)
< nExtend )
2000-09-18 23:16:46 +00:00
{
nExtend = rRef.Ref1.nCol;
bRet = TRUE;
}
break;
}
}
2001-02-21 17:39:37 +00:00
break;
2000-09-18 23:16:46 +00:00
} // switch
} // for
return bRet;
}
}
}
return FALSE;
}
void ScTokenArray::ImportRecalcMode40( ScRecalcMode40 eMode )
{
switch ( eMode )
{
case RC_NORMAL :
nMode = RECALCMODE_NORMAL;
break;
case RC_ALWAYS :
nMode = RECALCMODE_ALWAYS;
break;
case RC_ONLOAD :
nMode = RECALCMODE_ONLOAD;
break;
case RC_ONLOAD_ONCE :
nMode = RECALCMODE_ONLOAD_ONCE;
break;
case RC_FORCED :
nMode = RECALCMODE_NORMAL | RECALCMODE_FORCED;
break;
case RC_ONREFMOVE :
nMode = RECALCMODE_NORMAL | RECALCMODE_ONREFMOVE;
break;
default:
DBG_ERRORFILE( "ScTokenArray::ImportRecalcMode40: unknown ScRecalcMode40" );
nMode = RECALCMODE_NORMAL;
}
}
ScRecalcMode40 ScTokenArray::ExportRecalcMode40() const
{
//! Reihenfolge ist wichtig
if ( nMode & RECALCMODE_ALWAYS )
return RC_ALWAYS;
if ( nMode & RECALCMODE_ONLOAD )
return RC_ONLOAD;
if ( nMode & RECALCMODE_FORCED )
return RC_FORCED;
if ( nMode & RECALCMODE_ONREFMOVE )
return RC_ONREFMOVE;
// kommt eigentlich nicht vor weil in Calc bereits umgesetzt,
// und woanders gibt es keinen 4.0-Export, deswegen als letztes
if ( nMode & RECALCMODE_ONLOAD_ONCE )
return RC_ONLOAD_ONCE;
return RC_NORMAL;
}
void ScTokenArray::AddRecalcMode( ScRecalcMode nBits )
{
//! Reihenfolge ist wichtig
if ( nBits & RECALCMODE_ALWAYS )
SetRecalcModeAlways();
else if ( !IsRecalcModeAlways() )
{
if ( nBits & RECALCMODE_ONLOAD )
SetRecalcModeOnLoad();
else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
SetRecalcModeOnLoadOnce();
}
SetCombinedBitsRecalcMode( nBits );
}
BOOL ScTokenArray::HasMatrixDoubleRefOps()
{
if ( pRPN && nRPN )
{
// RPN-Interpreter Simulation
// als Ergebnis jeder Funktion wird einfach ein Double angenommen
ScToken** pStack = new ScToken* [nRPN];
2001-02-21 17:39:37 +00:00
ScToken* pResult = new ScDoubleToken( ocPush, 0.0 );
2000-09-18 23:16:46 +00:00
short sp = 0;
for ( USHORT j = 0; j < nRPN; j++ )
{
ScToken* t = pRPN[j];
OpCode eOp = t->GetOpCode();
BYTE nParams = t->GetParamCount();
switch ( eOp )
{
case ocAdd :
case ocSub :
case ocMul :
case ocDiv :
case ocPow :
case ocPower :
case ocAmpersand :
case ocEqual :
case ocNotEqual :
case ocLess :
case ocGreater :
case ocLessEqual :
case ocGreaterEqual :
{
for ( BYTE k = nParams; k; k-- )
{
if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
{
pResult->Delete();
delete [] pStack;
return TRUE;
}
}
}
break;
}
if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
pStack[sp++] = t;
else if ( eOp == ocIf || eOp == ocChose )
{ // Jumps ignorieren, vorheriges Result (Condition) poppen
if ( sp )
--sp;
}
else
{ // pop parameters, push result
sp -= nParams;
if ( sp < 0 )
{
DBG_ERROR( "ScTokenArray::HasMatrixDoubleRefOps: sp < 0" );
sp = 0;
}
pStack[sp++] = pResult;
}
}
pResult->Delete();
delete [] pStack;
}
return FALSE;
}
void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
const ScAddress& rNewPos )
{
for ( USHORT j=0; j<nLen; ++j )
{
switch ( pCode[j]->GetType() )
{
case svDoubleRef :
{
SingleRefData& rRef2 = pCode[j]->GetSingleRef2();
// Also adjust if the reference is of the form Sheet1.A2:A3
if ( rRef2.IsFlag3D() || pCode[j]->GetSingleRef().IsFlag3D() )
{
rRef2.CalcAbsIfRel( rOldPos );
rRef2.CalcRelFromAbs( rNewPos );
}
}
//! fallthru
case svSingleRef :
{
SingleRefData& rRef1 = pCode[j]->GetSingleRef();
if ( rRef1.IsFlag3D() )
{
rRef1.CalcAbsIfRel( rOldPos );
rRef1.CalcRelFromAbs( rNewPos );
}
}
}
}
}
2000-09-18 23:16:46 +00:00
///////////////////////////////////////////////////////////////////////////
2001-02-21 17:39:37 +00:00
void ScRawToken::Load30( SvStream& rStream )
2000-09-18 23:16:46 +00:00
{
#if SC_ROWLIMIT_STREAM_ACCESS
#error address types changed!
2000-09-18 23:16:46 +00:00
UINT16 nOp;
BYTE n;
nRefCnt = 0;
rStream >> nOp;
eOp = (OpCode) nOp;
switch( eOp )
{
case ocIf:
eType = svJump; nJump[ 0 ] = 3; break; // then, else, behind
case ocChose:
eType = svJump; nJump[ 0 ] = MAXJUMPCOUNT+1; break;
case ocPush:
rStream >> n;
eType = (StackVar) n;
switch( eType )
{
case svByte:
rStream >> sbyte.cByte;
sbyte.bHasForceArray = false;
2000-09-18 23:16:46 +00:00
break;
case svDouble:
rStream >> nValue;
break;
case svString:
{
sal_Char c[ MAXSTRLEN+1 ];
rStream >> nOp;
if( nOp > MAXSTRLEN-1 )
{
DBG_ERROR("Dokument huehnerich");
USHORT nDiff = nOp - (MAXSTRLEN-1);
nOp = MAXSTRLEN-1;
rStream.Read( c, nOp );
rStream.SeekRel( nDiff );
}
else
rStream.Read( c, nOp );
CharSet eSrc = rStream.GetStreamCharSet();
for ( BYTE j=0; j<nOp; j++ )
cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
cStr[ nOp ] = 0;
break;
}
case svSingleRef:
{
OldSingleRefBools aBools;
rStream >> aRef.Ref1.nCol
>> aRef.Ref1.nRow
>> aRef.Ref1.nTab
>> aBools.bRelCol
>> aBools.bRelRow
>> aBools.bRelTab
>> aBools.bOldFlag3D;
aRef.Ref1.OldBoolsToNewFlags( aBools );
aRef.Ref2 = aRef.Ref1;
break;
}
case svDoubleRef:
{
OldSingleRefBools aBools1;
OldSingleRefBools aBools2;
rStream >> aRef.Ref1.nCol
>> aRef.Ref1.nRow
>> aRef.Ref1.nTab
>> aRef.Ref2.nCol
>> aRef.Ref2.nRow
>> aRef.Ref2.nTab
>> aBools1.bRelCol
>> aBools1.bRelRow
>> aBools1.bRelTab
>> aBools2.bRelCol
>> aBools2.bRelRow
>> aBools2.bRelTab
>> aBools1.bOldFlag3D
>> aBools2.bOldFlag3D;
aRef.Ref1.OldBoolsToNewFlags( aBools1 );
aRef.Ref2.OldBoolsToNewFlags( aBools2 );
break;
}
default: DBG_ERROR("Unknown Stack Variable");
break;
}
break;
case ocName:
eType = svIndex;
rStream >> nIndex;
break;
case ocExternal:
{
sal_Char c[ MAXSTRLEN+1 ];
eType = svExternal;
rStream >> nOp;
// lieber ein rottes Dokument als stack overwrite
if( nOp > MAXSTRLEN-2 )
{
DBG_ERROR("Dokument huehnerich");
USHORT nDiff = nOp - (MAXSTRLEN-2);
nOp = MAXSTRLEN-2;
rStream.Read( c, nOp );
rStream.SeekRel( nDiff );
}
else
rStream.Read( c, nOp );
CharSet eSrc = rStream.GetStreamCharSet();
for ( BYTE j=1; j<nOp; j++ )
cStr[j] = ByteString::ConvertToUnicode( c[j-1], eSrc );
cStr[ 0 ] = 0; //! parameter count is what?!?
cStr[ nOp ] = 0;
break;
}
default:
eType = svByte;
sbyte.cByte = 0;
sbyte.bHasForceArray = false;
2000-09-18 23:16:46 +00:00
}
#endif // SC_ROWLIMIT_STREAM_ACCESS
2000-09-18 23:16:46 +00:00
}
// Bei unbekannten Tokens steht in cStr (k)ein Pascal-String (cStr[0] = Laenge),
// der nur gepuffert wird. cStr[0] = GESAMT-Laenge inkl. [0] !!!
2001-02-21 17:39:37 +00:00
void ScRawToken::Load( SvStream& rStream, USHORT nVer )
2000-09-18 23:16:46 +00:00
{
#if SC_ROWLIMIT_STREAM_ACCESS
#error address types changed!
2000-09-18 23:16:46 +00:00
BYTE n;
UINT16 nOp;
USHORT i;
rStream >> nOp >> n;
eOp = (OpCode) nOp;
eType = (StackVar) n;
switch( eType )
{
case svByte:
rStream >> sbyte.cByte;
sbyte.bHasForceArray = false;
2000-09-18 23:16:46 +00:00
break;
case svDouble:
rStream >> nValue;
break;
case svExternal:
{
sal_Char c[ MAXSTRLEN+1 ];
rStream >> sbyte.cByte >> n;
2000-09-18 23:16:46 +00:00
if( n > MAXSTRLEN-2 )
{
DBG_ERRORFILE( "bad string array boundary" );
USHORT nDiff = n - (MAXSTRLEN-2);
n = MAXSTRLEN-2;
rStream.Read( c+1, n );
rStream.SeekRel( nDiff );
}
else
rStream.Read( c+1, n );
//! parameter count is in sbyte.cByte (cStr[0] little endian)
2000-09-18 23:16:46 +00:00
CharSet eSrc = rStream.GetStreamCharSet();
for ( BYTE j=1; j<n+1; j++ )
cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
cStr[ n+1 ] = 0;
break;
}
case svString:
{
sal_Char c[ MAXSTRLEN+1 ];
rStream >> n;
if( n > MAXSTRLEN-1 )
{
DBG_ERRORFILE( "bad string array boundary" );
USHORT nDiff = n - (MAXSTRLEN-1);
n = MAXSTRLEN-1;
rStream.Read( c, n );
rStream.SeekRel( nDiff );
}
else
rStream.Read( c, n );
cStr[ n ] = 0;
CharSet eSrc = rStream.GetStreamCharSet();
for ( BYTE j=0; j<n; j++ )
cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
cStr[ n ] = 0;
break;
}
case svSingleRef:
case svDoubleRef:
{
SingleRefData& r = aRef.Ref1;
rStream >> r.nCol
>> r.nRow
>> r.nTab
>> n;
if ( nVer < SC_RELATIVE_REFS )
{
OldSingleRefBools aBools;
aBools.bRelCol = ( n & 0x03 );
aBools.bRelRow = ( ( n >> 2 ) & 0x03 );
aBools.bRelTab = ( ( n >> 4 ) & 0x03 );
aBools.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
r.OldBoolsToNewFlags( aBools );
}
else
r.CreateFlagsFromLoadByte( n );
if( eType == svSingleRef )
aRef.Ref2 = r;
else
{
SingleRefData& r = aRef.Ref2;
rStream >> r.nCol
>> r.nRow
>> r.nTab
>> n;
if ( nVer < SC_RELATIVE_REFS )
{
OldSingleRefBools aBools;
aBools.bRelCol = ( n & 0x03 );
aBools.bRelRow = ( ( n >> 2 ) & 0x03 );
aBools.bRelTab = ( ( n >> 4 ) & 0x03 );
aBools.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
r.OldBoolsToNewFlags( aBools );
}
else
r.CreateFlagsFromLoadByte( n );
}
break;
}
case svIndex:
rStream >> nIndex;
break;
case svJump:
rStream >> n;
nJump[ 0 ] = n;
for( i = 1; i <= n; i++ )
rStream >> nJump[ i ];
break;
case svMissing:
case svErr:
break;
default:
{
rStream >> n;
if( n > MAXSTRLEN-2 )
{
DBG_ERRORFILE( "bad unknown token type array boundary" );
USHORT nDiff = n - (MAXSTRLEN-2);
n = MAXSTRLEN-2;
rStream.Read( ((BYTE*)cStr)+1, n );
rStream.SeekRel( nDiff );
++n;
}
else if ( n > 1 )
rStream.Read( ((BYTE*)cStr)+1, n-1 );
else if ( n == 0 )
{
DBG_ERRORFILE( "unknown token type length==0" );
n = 1;
}
*((BYTE*)cStr) = n; // length including length byte
2000-09-18 23:16:46 +00:00
}
}
#endif // SC_ROWLIMIT_STREAM_ACCESS
2000-09-18 23:16:46 +00:00
}
void ScToken::Store( SvStream& rStream ) const
{
#if SC_ROWLIMIT_STREAM_ACCESS
#error address types changed!
2000-09-18 23:16:46 +00:00
short i;
rStream << (UINT16) eOp << (BYTE) eType;
switch( eType )
{
case svByte:
2001-02-21 17:39:37 +00:00
rStream << GetByte();
2000-09-18 23:16:46 +00:00
break;
case svDouble:
2001-02-21 17:39:37 +00:00
rStream << GetDouble();
2000-09-18 23:16:46 +00:00
break;
case svExternal:
{
2001-02-21 17:39:37 +00:00
ByteString aTmp( GetExternal(), rStream.GetStreamCharSet() );
aTmp.Erase( 255 ); // old SO5 can't handle more
rStream << GetByte()
2000-09-18 23:16:46 +00:00
<< (UINT8) aTmp.Len();
rStream.Write( aTmp.GetBuffer(), (UINT8) aTmp.Len() );
}
break;
case svString:
{
2001-02-21 17:39:37 +00:00
ByteString aTmp( GetString(), rStream.GetStreamCharSet() );
aTmp.Erase( 255 ); // old SO5 can't handle more
2000-09-18 23:16:46 +00:00
rStream << (UINT8) aTmp.Len();
rStream.Write( aTmp.GetBuffer(), (UINT8) aTmp.Len() );
}
break;
case svSingleRef:
{
2001-02-21 17:39:37 +00:00
const SingleRefData& r = GetSingleRef();
2000-09-18 23:16:46 +00:00
BYTE n = r.CreateStoreByteFromFlags();
rStream << (INT16) r.nCol
<< (INT16) r.nRow
<< (INT16) r.nTab
<< (BYTE) n;
2001-02-21 17:39:37 +00:00
}
2000-09-18 23:16:46 +00:00
break;
2001-02-21 17:39:37 +00:00
case svDoubleRef:
{
const ComplRefData& rRef = GetDoubleRef();
const SingleRefData& r1 = rRef.Ref1;
BYTE n = r1.CreateStoreByteFromFlags();
rStream << (INT16) r1.nCol
<< (INT16) r1.nRow
<< (INT16) r1.nTab
<< (BYTE) n;
const SingleRefData& r2 = rRef.Ref2;
n = r2.CreateStoreByteFromFlags();
rStream << (INT16) r2.nCol
<< (INT16) r2.nRow
<< (INT16) r2.nTab
<< (BYTE) n;
2000-09-18 23:16:46 +00:00
}
2001-02-21 17:39:37 +00:00
break;
2000-09-18 23:16:46 +00:00
case svIndex:
2001-02-21 17:39:37 +00:00
rStream << (UINT16) GetIndex();
2000-09-18 23:16:46 +00:00
break;
case svJump:
2001-02-21 17:39:37 +00:00
{
short* pJump = GetJump();
rStream << (BYTE) pJump[ 0 ];
for( i = 1; i <= pJump[ 0 ]; i++ )
rStream << (UINT16) pJump[ i ];
}
2000-09-18 23:16:46 +00:00
break;
case svMissing:
case svErr:
break;
default:
2001-02-21 17:39:37 +00:00
{
BYTE* pUnknown = GetUnknown();
if ( pUnknown )
rStream.Write( pUnknown, pUnknown[ 0 ] );
}
2000-09-18 23:16:46 +00:00
}
#endif // SC_ROWLIMIT_STREAM_ACCESS
2000-09-18 23:16:46 +00:00
}
/*----------------------------------------------------------------------*/
ScTokenIterator::ScTokenIterator( const ScTokenArray& rArr )
{
pCur = NULL;
Push( &rArr );
2000-09-18 23:16:46 +00:00
}
ScTokenIterator::~ScTokenIterator()
{
while( pCur )
Pop();
}
void ScTokenIterator::Push( const ScTokenArray* pArr )
2000-09-18 23:16:46 +00:00
{
ImpTokenIterator* p = new ImpTokenIterator;
p->pArr = pArr;
p->nPC = -1;
p->nStop = SHRT_MAX;
2000-09-18 23:16:46 +00:00
p->pNext = pCur;
pCur = p;
}
void ScTokenIterator::Pop()
{
ImpTokenIterator* p = pCur;
if( p )
{
pCur = p->pNext;
delete p;
}
}
void ScTokenIterator::Reset()
{
while( pCur->pNext )
Pop();
pCur->nPC = -1;
}
const ScToken* ScTokenIterator::First()
{
Reset();
return Next();
}
const ScToken* ScTokenIterator::Next()
{
const ScToken* t = NULL;
++pCur->nPC;
if( pCur->nPC < pCur->pArr->nRPN && pCur->nPC < pCur->nStop )
2000-09-18 23:16:46 +00:00
{
t = pCur->pArr->pRPN[ pCur->nPC ];
// such an OpCode ends an IF() or CHOOSE() path
2000-09-18 23:16:46 +00:00
if( t->GetOpCode() == ocSep || t->GetOpCode() == ocClose )
t = NULL;
}
if( !t && pCur->pNext )
{
Pop();
t = Next();
2000-09-18 23:16:46 +00:00
}
return t;
}
//! The nPC counts after a Push() are -1
2000-09-18 23:16:46 +00:00
void ScTokenIterator::Jump( short nStart, short nNext, short nStop )
2000-09-18 23:16:46 +00:00
{
pCur->nPC = nNext;
if( nStart != nNext )
{
Push( pCur->pArr );
pCur->nPC = nStart;
pCur->nStop = nStop;
}
}
bool ScTokenIterator::IsEndOfPath() const
{
USHORT nTest = pCur->nPC + 1;
if( nTest < pCur->pArr->nRPN && nTest < pCur->nStop )
{
const ScToken* t = pCur->pArr->pRPN[ nTest ];
// such an OpCode ends an IF() or CHOOSE() path
return t->GetOpCode() == ocSep || t->GetOpCode() == ocClose;
2000-09-18 23:16:46 +00:00
}
return true;
2000-09-18 23:16:46 +00:00
}