LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xeformula.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 709 1204 58.9 %
Date: 2014-11-03 Functions: 140 180 77.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <list>
      21             : #include <map>
      22             : #include "addincol.hxx"
      23             : #include "compiler.hxx"
      24             : #include "document.hxx"
      25             : #include "externalrefmgr.hxx"
      26             : #include "rangelst.hxx"
      27             : #include "token.hxx"
      28             : #include "tokenarray.hxx"
      29             : #include "scmatrix.hxx"
      30             : #include "xeformula.hxx"
      31             : #include "xehelper.hxx"
      32             : #include "xelink.hxx"
      33             : #include "xename.hxx"
      34             : #include "xestream.hxx"
      35             : 
      36             : using namespace ::formula;
      37             : 
      38             : // External reference log =====================================================
      39             : 
      40           0 : XclExpRefLogEntry::XclExpRefLogEntry() :
      41             :     mpUrl( 0 ),
      42             :     mpFirstTab( 0 ),
      43             :     mpLastTab( 0 ),
      44             :     mnFirstXclTab( EXC_TAB_DELETED ),
      45           0 :     mnLastXclTab( EXC_TAB_DELETED )
      46             : {
      47           0 : }
      48             : 
      49             : // Formula compiler ===========================================================
      50             : 
      51             : namespace {
      52             : 
      53             : /** Wrapper structure for a processed Calc formula token with additional
      54             :     settings (whitespaces). */
      55             : struct XclExpScToken
      56             : {
      57             :     const FormulaToken* mpScToken;          /// Currently processed Calc token.
      58             :     sal_uInt8           mnSpaces;           /// Number of spaces before the Calc token.
      59             : 
      60        5720 :     inline explicit     XclExpScToken() : mpScToken( 0 ), mnSpaces( 0 ) {}
      61       17552 :     inline bool         Is() const { return mpScToken != 0; }
      62        3686 :     inline StackVar     GetType() const { return mpScToken ? mpScToken->GetType() : static_cast< StackVar >( svUnknown ); }
      63       70742 :     inline OpCode       GetOpCode() const { return mpScToken ? mpScToken->GetOpCode() : static_cast< OpCode >( ocNone ); }
      64             : };
      65             : 
      66             : /** Effective token class conversion types. */
      67             : enum XclExpClassConv
      68             : {
      69             :     EXC_CLASSCONV_ORG,          /// Keep original class of the token.
      70             :     EXC_CLASSCONV_VAL,          /// Convert ARR tokens to VAL class (REF remains uncahnged).
      71             :     EXC_CLASSCONV_ARR           /// Convert VAL tokens to ARR class (REF remains uncahnged).
      72             : };
      73             : 
      74             : /** Token class conversion and position of a token in the token array. */
      75             : struct XclExpTokenConvInfo
      76             : {
      77             :     sal_uInt16          mnTokPos;       /// Position of the token in the token array.
      78             :     XclFuncParamConv    meConv;         /// Token class conversion type.
      79             :     bool                mbValType;      /// Data type (false = REFTYPE, true = VALTYPE).
      80             : };
      81             : 
      82             : /** Vector of token position and conversion for all operands of an operator,
      83             :     or for all parameters of a function. */
      84        2026 : struct XclExpOperandList : public ::std::vector< XclExpTokenConvInfo >
      85             : {
      86        2026 :     inline explicit     XclExpOperandList() { reserve( 2 ); }
      87             :     void                AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType );
      88             : };
      89             : 
      90        3504 : void XclExpOperandList::AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType )
      91             : {
      92        3504 :     resize( size() + 1 );
      93        3504 :     XclExpTokenConvInfo& rConvInfo = back();
      94        3504 :     rConvInfo.mnTokPos = nTokPos;
      95        3504 :     rConvInfo.meConv = eConv;
      96        3504 :     rConvInfo.mbValType = bValType;
      97        3504 : }
      98             : 
      99             : typedef boost::shared_ptr< XclExpOperandList > XclExpOperandListRef;
     100             : typedef ::std::vector< XclExpOperandListRef > XclExpOperandListVector;
     101             : 
     102             : /** Encapsulates all data needed for a call to an external function (macro, add-in). */
     103        2700 : struct XclExpExtFuncData
     104             : {
     105             :     OUString            maFuncName;         /// Name of the function.
     106             :     bool                mbVBasic;           /// True = Visual Basic macro call.
     107             :     bool                mbHidden;           /// True = Create hidden defined name.
     108             : 
     109         900 :     inline explicit     XclExpExtFuncData() : mbVBasic( false ), mbHidden( false ) {}
     110             :     void                Set( const OUString& rFuncName, bool bVBasic, bool bHidden );
     111             : };
     112             : 
     113         704 : void XclExpExtFuncData::Set( const OUString& rFuncName, bool bVBasic, bool bHidden )
     114             : {
     115         704 :     maFuncName = rFuncName;
     116         704 :     mbVBasic = bVBasic;
     117         704 :     mbHidden = bHidden;
     118         704 : }
     119             : 
     120             : /** Encapsulates all data needed to process an entire function. */
     121         900 : class XclExpFuncData
     122             : {
     123             : public:
     124             :     explicit            XclExpFuncData(
     125             :                             const XclExpScToken& rTokData,
     126             :                             const XclFunctionInfo& rFuncInfo,
     127             :                             const XclExpExtFuncData& rExtFuncData );
     128             : 
     129           0 :     inline const FormulaToken& GetScToken() const { return *mrTokData.mpScToken; }
     130       10386 :     inline OpCode       GetOpCode() const { return mrFuncInfo.meOpCode; }
     131         900 :     inline sal_uInt16   GetXclFuncIdx() const { return mrFuncInfo.mnXclFunc; }
     132         900 :     inline bool         IsVolatile() const { return mrFuncInfo.IsVolatile(); }
     133         896 :     inline bool         IsFixedParamCount() const { return mrFuncInfo.IsFixedParamCount(); }
     134         704 :     inline bool         IsAddInEquivalent() const { return mrFuncInfo.IsAddInEquivalent(); }
     135         712 :     inline bool         IsMacroFunc() const { return mrFuncInfo.IsMacroFunc(); }
     136         900 :     inline sal_uInt8    GetSpaces() const { return mrTokData.mnSpaces; }
     137         352 :     inline const XclExpExtFuncData& GetExtFuncData() const { return maExtFuncData; }
     138         900 :     inline sal_uInt8    GetReturnClass() const { return mrFuncInfo.mnRetClass; }
     139             : 
     140             :     const XclFuncParamInfo& GetParamInfo() const;
     141             :     bool                IsCalcOnlyParam() const;
     142             :     bool                IsExcelOnlyParam() const;
     143             :     void                IncParamInfoIdx();
     144             : 
     145         900 :     inline sal_uInt8    GetMinParamCount() const { return mrFuncInfo.mnMinParamCount; }
     146         900 :     inline sal_uInt8    GetMaxParamCount() const { return mrFuncInfo.mnMaxParamCount; }
     147       10896 :     inline sal_uInt8    GetParamCount() const { return static_cast< sal_uInt8 >( mxOperands->size() ); }
     148             :     void                FinishParam( sal_uInt16 nTokPos );
     149         900 :     inline XclExpOperandListRef GetOperandList() const { return mxOperands; }
     150             : 
     151           0 :     inline ScfUInt16Vec& GetAttrPosVec() { return maAttrPosVec; }
     152           0 :     inline void         AppendAttrPos( sal_uInt16 nPos ) { maAttrPosVec.push_back( nPos ); }
     153             : 
     154             : private:
     155             :     ScfUInt16Vec        maAttrPosVec;       /// Token array positions of tAttr tokens.
     156             :     const XclExpScToken& mrTokData;         /// Data about processed function name token.
     157             :     const XclFunctionInfo& mrFuncInfo;      /// Constant data about processed function.
     158             :     XclExpExtFuncData   maExtFuncData;      /// Data for external functions (macro, add-in).
     159             :     XclExpOperandListRef mxOperands;        /// Class conversion and position of all parameters.
     160             :     const XclFuncParamInfo* mpParamInfo;    /// Information for current parameter.
     161             : };
     162             : 
     163         900 : XclExpFuncData::XclExpFuncData( const XclExpScToken& rTokData,
     164             :         const XclFunctionInfo& rFuncInfo, const XclExpExtFuncData& rExtFuncData ) :
     165             :     mrTokData( rTokData ),
     166             :     mrFuncInfo( rFuncInfo ),
     167             :     maExtFuncData( rExtFuncData ),
     168         900 :     mxOperands( new XclExpOperandList ),
     169        1800 :     mpParamInfo( rFuncInfo.mpParamInfos )
     170             : {
     171             :     OSL_ENSURE( mrTokData.mpScToken, "XclExpFuncData::XclExpFuncData - missing core token" );
     172             :     // set name of an add-in function
     173         900 :     if( (maExtFuncData.maFuncName.isEmpty()) && dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) )
     174           0 :         maExtFuncData.Set( GetScToken().GetExternal(), true, false );
     175         900 : }
     176             : 
     177        3264 : const XclFuncParamInfo& XclExpFuncData::GetParamInfo() const
     178             : {
     179             :     static const XclFuncParamInfo saInvalidInfo = { EXC_PARAM_NONE, EXC_PARAMCONV_ORG, false };
     180        3264 :     return mpParamInfo ? *mpParamInfo : saInvalidInfo;
     181             : }
     182             : 
     183        5008 : bool XclExpFuncData::IsCalcOnlyParam() const
     184             : {
     185        5008 :     return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_CALCONLY);
     186             : }
     187             : 
     188        5712 : bool XclExpFuncData::IsExcelOnlyParam() const
     189             : {
     190        5712 :     return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_EXCELONLY);
     191             : }
     192             : 
     193        3264 : void XclExpFuncData::IncParamInfoIdx()
     194             : {
     195        3264 :     if( mpParamInfo )
     196             :     {
     197             :         // move pointer to next entry, if something explicit follows
     198        3264 :         if( (static_cast< size_t >( mpParamInfo - mrFuncInfo.mpParamInfos + 1 ) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
     199         816 :             ++mpParamInfo;
     200             :         // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
     201        2448 :         else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
     202           0 :             mpParamInfo = 0;
     203             :         // points to last info, but parameter pairs expected, move to previous info
     204        2448 :         else if( mrFuncInfo.IsParamPairs() )
     205           0 :             --mpParamInfo;
     206             :         // otherwise: repeat last parameter class
     207             :     }
     208        3264 : }
     209             : 
     210        3264 : void XclExpFuncData::FinishParam( sal_uInt16 nTokPos )
     211             : {
     212             :     // write token class conversion info for this parameter
     213        3264 :     const XclFuncParamInfo& rParamInfo = GetParamInfo();
     214        3264 :     mxOperands->AppendOperand( nTokPos, rParamInfo.meConv, rParamInfo.mbValType );
     215             :     // move to next parameter info structure
     216        3264 :     IncParamInfoIdx();
     217        3264 : }
     218             : 
     219             : // compiler configuration -----------------------------------------------------
     220             : 
     221             : /** Type of token class handling. */
     222             : enum XclExpFmlaClassType
     223             : {
     224             :     EXC_CLASSTYPE_CELL,         /// Cell formula, shared formula.
     225             :     EXC_CLASSTYPE_ARRAY,        /// Array formula, conditional formatting, data validation.
     226             :     EXC_CLASSTYPE_NAME          /// Defined name, range list.
     227             : };
     228             : 
     229             : /** Configuration data of the formula compiler. */
     230             : struct XclExpCompConfig
     231             : {
     232             :     XclFormulaType      meType;         /// Type of the formula to be created.
     233             :     XclExpFmlaClassType meClassType;    /// Token class handling type.
     234             :     bool                mbLocalLinkMgr; /// True = local (per-sheet) link manager, false = global.
     235             :     bool                mbFromCell;     /// True = Any kind of cell formula (cell, array, shared).
     236             :     bool                mb3DRefOnly;    /// True = Only 3D references allowed (e.g. names).
     237             :     bool                mbAllowArrays;  /// True = Allow inline arrays.
     238             : };
     239             : 
     240             : /** The table containing configuration data for all formula types. */
     241             : static const XclExpCompConfig spConfigTable[] =
     242             : {
     243             :     // formula type         token class type     lclLM  inCell 3dOnly allowArray
     244             :     { EXC_FMLATYPE_CELL,    EXC_CLASSTYPE_CELL,  true,  true,  false, true  },
     245             :     { EXC_FMLATYPE_SHARED,  EXC_CLASSTYPE_CELL,  true,  true,  false, true  },
     246             :     { EXC_FMLATYPE_MATRIX,  EXC_CLASSTYPE_ARRAY, true,  true,  false, true  },
     247             :     { EXC_FMLATYPE_CONDFMT, EXC_CLASSTYPE_ARRAY, true,  false, false, false },
     248             :     { EXC_FMLATYPE_DATAVAL, EXC_CLASSTYPE_ARRAY, true,  false, false, false },
     249             :     { EXC_FMLATYPE_NAME,    EXC_CLASSTYPE_NAME,  false, false, true,  true  },
     250             :     { EXC_FMLATYPE_CHART,   EXC_CLASSTYPE_NAME,  true,  false, true,  true  },
     251             :     { EXC_FMLATYPE_CONTROL, EXC_CLASSTYPE_NAME,  true,  false, false, false },
     252             :     { EXC_FMLATYPE_WQUERY,  EXC_CLASSTYPE_NAME,  true,  false, true,  false },
     253             :     { EXC_FMLATYPE_LISTVAL, EXC_CLASSTYPE_NAME,  true,  false, false, false }
     254             : };
     255             : 
     256             : /** Working data of the formula compiler. Used to push onto a stack for recursive calls. */
     257        1898 : struct XclExpCompData
     258             : {
     259             :     typedef boost::shared_ptr< ScTokenArray > ScTokenArrayRef;
     260             : 
     261             :     const XclExpCompConfig& mrCfg;          /// Configuration for current formula type.
     262             :     ScTokenArrayRef     mxOwnScTokArr;      /// Own clone of a Calc token array.
     263             :     XclTokenArrayIterator maTokArrIt;       /// Iterator in Calc token array.
     264             :     XclExpLinkManager*  mpLinkMgr;          /// Link manager for current context (local/global).
     265             :     XclExpRefLog*       mpRefLog;           /// Log for external references.
     266             :     const ScAddress*    mpScBasePos;        /// Current cell position of the formula.
     267             : 
     268             :     ScfUInt8Vec         maTokVec;           /// Byte vector containing token data.
     269             :     ScfUInt8Vec         maExtDataVec;       /// Byte vector containing extended data (arrays, stacked NLRs).
     270             :     XclExpOperandListVector maOpListVec;    /// Formula structure, maps operators to their operands.
     271             :     ScfUInt16Vec        maOpPosStack;       /// Stack with positions of operand tokens waiting for an operator.
     272             :     bool                mbStopAtSep;        /// True = Stop subexpression creation at an ocSep token.
     273             :     bool                mbVolatile;         /// True = Formula contains volatile function.
     274             :     bool                mbOk;               /// Current state of the compiler.
     275             : 
     276             :     explicit            XclExpCompData( const XclExpCompConfig* pCfg );
     277             : };
     278             : 
     279        1898 : XclExpCompData::XclExpCompData( const XclExpCompConfig* pCfg ) :
     280             :     mrCfg( pCfg ? *pCfg : spConfigTable[ 0 ] ),
     281             :     mpLinkMgr( 0 ),
     282             :     mpRefLog( 0 ),
     283             :     mpScBasePos( 0 ),
     284             :     mbStopAtSep( false ),
     285             :     mbVolatile( false ),
     286        1898 :     mbOk( pCfg != 0 )
     287             : {
     288             :     OSL_ENSURE( pCfg, "XclExpFmlaCompImpl::Init - unknown formula type" );
     289        1898 : }
     290             : 
     291             : } // namespace
     292             : 
     293             : /** Implementation class of the export formula compiler. */
     294         128 : class XclExpFmlaCompImpl : protected XclExpRoot, protected XclTokenArrayHelper
     295             : {
     296             : public:
     297             :     explicit            XclExpFmlaCompImpl( const XclExpRoot& rRoot );
     298             : 
     299             :     /** Creates an Excel token array from the passed Calc token array. */
     300             :     XclTokenArrayRef    CreateFormula(
     301             :                             XclFormulaType eType, const ScTokenArray& rScTokArr,
     302             :                             const ScAddress* pScBasePos = 0, XclExpRefLog* pRefLog = 0 );
     303             :     /** Creates a single error token containing the passed error code. */
     304             :     XclTokenArrayRef    CreateErrorFormula( sal_uInt8 nErrCode );
     305             :     /** Creates a single token for a special cell reference. */
     306             :     XclTokenArrayRef    CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos );
     307             :     /** Creates a single tNameXR token for a reference to an external name. */
     308             :     XclTokenArrayRef    CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName );
     309             : 
     310             :     /** Returns true, if the passed formula type allows 3D references only. */
     311             :     bool                Is3DRefOnly( XclFormulaType eType ) const;
     312             : 
     313             :     bool IsRef2D( const ScSingleRefData& rRefData, bool bCheck3DFlag ) const;
     314             :     bool IsRef2D( const ScComplexRefData& rRefData, bool bCheck3DFlag ) const;
     315             : 
     316             : private:
     317             :     const XclExpCompConfig* GetConfigForType( XclFormulaType eType ) const;
     318        9088 :     inline sal_uInt16   GetSize() const { return static_cast< sal_uInt16 >( mxData->maTokVec.size() ); }
     319             : 
     320             :     void                Init( XclFormulaType eType );
     321             :     void                Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
     322             :                             const ScAddress* pScBasePos, XclExpRefLog* pRefLog );
     323             : 
     324             :     void                RecalcTokenClasses();
     325             :     void                RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass );
     326             : 
     327             :     void                FinalizeFormula();
     328             :     XclTokenArrayRef    CreateTokenArray();
     329             : 
     330             :     // compiler ---------------------------------------------------------------
     331             :     // XclExpScToken: pass-by-value and return-by-value is intended
     332             : 
     333             :     const FormulaToken* GetNextRawToken();
     334             :     const FormulaToken* PeekNextRawToken( bool bSkipSpaces ) const;
     335             : 
     336             :     bool                GetNextToken( XclExpScToken& rTokData );
     337             :     XclExpScToken       GetNextToken();
     338             : 
     339             :     XclExpScToken       Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep );
     340             :     XclExpScToken       SkipExpression( XclExpScToken aTokData, bool bStopAtSep );
     341             : 
     342             :     XclExpScToken       OrTerm( XclExpScToken aTokData, bool bInParentheses );
     343             :     XclExpScToken       AndTerm( XclExpScToken aTokData, bool bInParentheses );
     344             :     XclExpScToken       CompareTerm( XclExpScToken aTokData, bool bInParentheses );
     345             :     XclExpScToken       ConcatTerm( XclExpScToken aTokData, bool bInParentheses );
     346             :     XclExpScToken       AddSubTerm( XclExpScToken aTokData, bool bInParentheses );
     347             :     XclExpScToken       MulDivTerm( XclExpScToken aTokData, bool bInParentheses );
     348             :     XclExpScToken       PowTerm( XclExpScToken aTokData, bool bInParentheses );
     349             :     XclExpScToken       UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses );
     350             :     XclExpScToken       UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses );
     351             :     XclExpScToken       ListTerm( XclExpScToken aTokData, bool bInParentheses );
     352             :     XclExpScToken       IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp );
     353             :     XclExpScToken       RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp );
     354             :     XclExpScToken       Factor( XclExpScToken aTokData );
     355             : 
     356             :     // formula structure ------------------------------------------------------
     357             : 
     358             :     void                ProcessDouble( const XclExpScToken& rTokData );
     359             :     void                ProcessString( const XclExpScToken& rTokData );
     360             :     void                ProcessMissing( const XclExpScToken& rTokData );
     361             :     void                ProcessBad( const XclExpScToken& rTokData );
     362             :     void                ProcessParentheses( const XclExpScToken& rTokData );
     363             :     void                ProcessBoolean( const XclExpScToken& rTokData );
     364             :     void                ProcessDdeLink( const XclExpScToken& rTokData );
     365             :     void                ProcessExternal( const XclExpScToken& rTokData );
     366             :     void                ProcessMatrix( const XclExpScToken& rTokData );
     367             : 
     368             :     void                ProcessFunction( const XclExpScToken& rTokData );
     369             :     void                PrepareFunction( XclExpFuncData& rFuncData );
     370             :     void                FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces );
     371             :     void                FinishIfFunction( XclExpFuncData& rFuncData );
     372             :     void                FinishChooseFunction( XclExpFuncData& rFuncData );
     373             : 
     374             :     XclExpScToken       ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData );
     375             :     void                PrepareParam( XclExpFuncData& rFuncData );
     376             :     void                FinishParam( XclExpFuncData& rFuncData );
     377             :     void                AppendDefaultParam( XclExpFuncData& rFuncData );
     378             :     void                AppendTrailingParam( XclExpFuncData& rFuncData );
     379             : 
     380             :     // reference handling -----------------------------------------------------
     381             : 
     382             :     SCTAB               GetScTab( const ScSingleRefData& rRefData ) const;
     383             : 
     384             :     void                ConvertRefData( ScSingleRefData& rRefData, XclAddress& rXclPos,
     385             :                             bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const;
     386             :     void                ConvertRefData( ScComplexRefData& rRefData, XclRange& rXclRange,
     387             :                             bool bNatLangRef ) const;
     388             : 
     389             :     XclExpRefLogEntry*  GetNewRefLogEntry();
     390             :     void                ProcessCellRef( const XclExpScToken& rTokData );
     391             :     void                ProcessRangeRef( const XclExpScToken& rTokData );
     392             :     void                ProcessExternalCellRef( const XclExpScToken& rTokData );
     393             :     void                ProcessExternalRangeRef( const XclExpScToken& rTokData );
     394             :     void                ProcessDefinedName( const XclExpScToken& rTokData );
     395             :     void                ProcessExternalName( const XclExpScToken& rTokData );
     396             : 
     397             :     // token vector -----------------------------------------------------------
     398             : 
     399             :     void                PushOperandPos( sal_uInt16 nTokPos );
     400             :     void                PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands );
     401             :     sal_uInt16          PopOperandPos();
     402             : 
     403             :     void                Append( sal_uInt8 nData );
     404             :     void                Append( sal_uInt8 nData, size_t nCount );
     405             :     void                Append( sal_uInt16 nData );
     406             :     void                Append( sal_uInt32 nData );
     407             :     void                Append( double fData );
     408             :     void                Append( const OUString& rString );
     409             : 
     410             :     void                AppendAddress( const XclAddress& rXclPos );
     411             :     void                AppendRange( const XclRange& rXclRange );
     412             : 
     413             :     void                AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount );
     414             : 
     415             :     void                AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
     416             :     void                AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces = 0 );
     417             :     void                AppendNumToken( double fValue, sal_uInt8 nSpaces = 0 );
     418             :     void                AppendBoolToken( bool bValue, sal_uInt8 nSpaces = 0 );
     419             :     void                AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces = 0 );
     420             :     void                AppendMissingToken( sal_uInt8 nSpaces = 0 );
     421             :     void                AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces = 0 );
     422             :     void                AppendMissingNameToken( const OUString& rName, sal_uInt8 nSpaces = 0 );
     423             :     void                AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces = 0 );
     424             :     void                AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
     425             :     void                AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
     426             :     void                AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
     427             : 
     428             :     void                AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces = 0 );
     429             :     void                AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
     430             :     void                AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces = 0 );
     431             :     void                AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount );
     432             :     void                AppendFuncToken( const XclExpFuncData& rFuncData );
     433             : 
     434             :     void                AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 );
     435             :     void                AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType );
     436             : 
     437             :     void                InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize );
     438             :     void                Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset );
     439             : 
     440             :     void                UpdateAttrGoto( sal_uInt16 nAttrPos );
     441             : 
     442             :     bool                IsSpaceToken( sal_uInt16 nPos ) const;
     443             :     void                RemoveTrailingParen();
     444             : 
     445             :     void                AppendExt( sal_uInt8 nData );
     446             :     void                AppendExt( sal_uInt8 nData, size_t nCount );
     447             :     void                AppendExt( sal_uInt16 nData );
     448             :     void                AppendExt( double fData );
     449             :     void                AppendExt( const OUString& rString );
     450             : 
     451             : private:
     452             :     typedef ::std::map< XclFormulaType, XclExpCompConfig >  XclExpCompConfigMap;
     453             :     typedef boost::shared_ptr< XclExpCompData >             XclExpCompDataRef;
     454             :     typedef ::std::vector< XclExpCompDataRef >              XclExpCompDataVector;
     455             : 
     456             :     XclExpCompConfigMap maCfgMap;       /// Compiler configuration map for all formula types.
     457             :     XclFunctionProvider maFuncProv;     /// Excel function data provider.
     458             :     XclExpCompDataRef   mxData;         /// Working data for current formula.
     459             :     XclExpCompDataVector maDataStack;   /// Stack for working data, when compiler is called recursively.
     460             :     const XclBiff       meBiff;         /// Cached BIFF version to save GetBiff() calls.
     461             :     const SCsCOL        mnMaxAbsCol;    /// Maximum column index.
     462             :     const SCsROW        mnMaxAbsRow;    /// Maximum row index.
     463             :     const SCsCOL        mnMaxScCol;     /// Maximum column index in Calc itself.
     464             :     const SCsROW        mnMaxScRow;     /// Maximum row index in Calc itself.
     465             :     const sal_uInt16    mnMaxColMask;   /// Mask to delete invalid bits in column fields.
     466             :     const sal_uInt32    mnMaxRowMask;   /// Mask to delete invalid bits in row fields.
     467             : };
     468             : 
     469          64 : XclExpFmlaCompImpl::XclExpFmlaCompImpl( const XclExpRoot& rRoot ) :
     470             :     XclExpRoot( rRoot ),
     471             :     maFuncProv( rRoot ),
     472          64 :     meBiff( rRoot.GetBiff() ),
     473          64 :     mnMaxAbsCol( static_cast< SCsCOL >( rRoot.GetXclMaxPos().Col() ) ),
     474          64 :     mnMaxAbsRow( static_cast< SCsROW >( rRoot.GetXclMaxPos().Row() ) ),
     475          64 :     mnMaxScCol( static_cast< SCsCOL >( rRoot.GetScMaxPos().Col() ) ),
     476          64 :     mnMaxScRow( static_cast< SCsROW >( rRoot.GetScMaxPos().Row() ) ),
     477          64 :     mnMaxColMask( static_cast< sal_uInt16 >( rRoot.GetXclMaxPos().Col() ) ),
     478         448 :     mnMaxRowMask( static_cast< sal_uInt32 >( rRoot.GetXclMaxPos().Row() ) )
     479             : {
     480             :     // build the configuration map
     481         704 :     for( const XclExpCompConfig* pEntry = spConfigTable; pEntry != STATIC_ARRAY_END( spConfigTable ); ++pEntry )
     482         640 :         maCfgMap[ pEntry->meType ] = *pEntry;
     483          64 : }
     484             : 
     485        1006 : XclTokenArrayRef XclExpFmlaCompImpl::CreateFormula( XclFormulaType eType,
     486             :         const ScTokenArray& rScTokArr, const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
     487             : {
     488             :     // initialize the compiler
     489        1006 :     Init( eType, rScTokArr, pScBasePos, pRefLog );
     490             : 
     491             :     // start compilation, if initialization didn't fail
     492        1006 :     if( mxData->mbOk )
     493             :     {
     494        1006 :         XclExpScToken aTokData( GetNextToken() );
     495        1006 :         sal_uInt16 nScError = rScTokArr.GetCodeError();
     496        1006 :         if( (nScError != 0) && (!aTokData.Is() || (aTokData.GetOpCode() == ocStop)) )
     497             :         {
     498             :             // #i50253# convert simple ocStop token to error code formula (e.g. =#VALUE!)
     499           0 :             AppendErrorToken( XclTools::GetXclErrorCode( nScError ), aTokData.mnSpaces );
     500             :         }
     501        1006 :         else if( aTokData.Is() )
     502             :         {
     503        1006 :             aTokData = Expression( aTokData, false, false );
     504             :         }
     505             :         else
     506             :         {
     507             :             OSL_FAIL( "XclExpFmlaCompImpl::CreateFormula - empty token array" );
     508           0 :             mxData->mbOk = false;
     509             :         }
     510             : 
     511        1006 :         if( mxData->mbOk )
     512             :         {
     513             :             // #i44907# auto-generated SUBTOTAL formula cells have trailing ocStop token
     514        1006 :             mxData->mbOk = !aTokData.Is() || (aTokData.GetOpCode() == ocStop);
     515             :             OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula" );
     516             :         }
     517             :     }
     518             : 
     519             :     // finalize (add tAttrVolatile token, calculate all token classes)
     520        1006 :     RecalcTokenClasses();
     521        1006 :     FinalizeFormula();
     522             : 
     523             :     // leave recursive call, create and return the final token array
     524        1006 :     return CreateTokenArray();
     525             : }
     526             : 
     527         120 : XclTokenArrayRef XclExpFmlaCompImpl::CreateErrorFormula( sal_uInt8 nErrCode )
     528             : {
     529         120 :     Init( EXC_FMLATYPE_NAME );
     530         120 :     AppendErrorToken( nErrCode );
     531         120 :     return CreateTokenArray();
     532             : }
     533             : 
     534         772 : XclTokenArrayRef XclExpFmlaCompImpl::CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos )
     535             : {
     536         772 :     Init( EXC_FMLATYPE_NAME );
     537         772 :     AppendOperandTokenId( nTokenId );
     538         772 :     Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
     539         772 :     Append( rXclPos.mnCol );    // do not use AppendAddress(), we always need 16-bit column here
     540         772 :     return CreateTokenArray();
     541             : }
     542             : 
     543           0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName )
     544             : {
     545           0 :     Init( EXC_FMLATYPE_NAME );
     546           0 :     AppendNameXToken( nExtSheet, nExtName );
     547           0 :     return CreateTokenArray();
     548             : }
     549             : 
     550           0 : bool XclExpFmlaCompImpl::Is3DRefOnly( XclFormulaType eType ) const
     551             : {
     552           0 :     const XclExpCompConfig* pCfg = GetConfigForType( eType );
     553           0 :     return pCfg && pCfg->mb3DRefOnly;
     554             : }
     555             : 
     556             : // private --------------------------------------------------------------------
     557             : 
     558        1898 : const XclExpCompConfig* XclExpFmlaCompImpl::GetConfigForType( XclFormulaType eType ) const
     559             : {
     560        1898 :     XclExpCompConfigMap::const_iterator aIt = maCfgMap.find( eType );
     561             :     OSL_ENSURE( aIt != maCfgMap.end(), "XclExpFmlaCompImpl::GetConfigForType - unknown formula type" );
     562        1898 :     return (aIt == maCfgMap.end()) ? 0 : &aIt->second;
     563             : }
     564             : 
     565        1898 : void XclExpFmlaCompImpl::Init( XclFormulaType eType )
     566             : {
     567             :     // compiler invoked recursively? - store old working data
     568        1898 :     if( mxData.get() )
     569         120 :         maDataStack.push_back( mxData );
     570             :     // new compiler working data structure
     571        1898 :     mxData.reset( new XclExpCompData( GetConfigForType( eType ) ) );
     572        1898 : }
     573             : 
     574        1006 : void XclExpFmlaCompImpl::Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
     575             :         const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
     576             : {
     577             :     // common initialization
     578        1006 :     Init( eType );
     579             : 
     580             :     // special initialization
     581        1006 :     if( mxData->mbOk ) switch( mxData->mrCfg.meType )
     582             :     {
     583             :         case EXC_FMLATYPE_CELL:
     584             :         case EXC_FMLATYPE_MATRIX:
     585             :         case EXC_FMLATYPE_CHART:
     586         734 :             mxData->mbOk = pScBasePos != 0;
     587             :             OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
     588         734 :             mxData->mpScBasePos = pScBasePos;
     589         734 :         break;
     590             :         case EXC_FMLATYPE_SHARED:
     591         252 :             mxData->mbOk = pScBasePos != 0;
     592             :             OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
     593             :             // clone the passed token array, convert references relative to current cell position
     594         252 :             mxData->mxOwnScTokArr.reset( rScTokArr.Clone() );
     595         252 :             ScCompiler::MoveRelWrap( *mxData->mxOwnScTokArr, GetDocPtr(), *pScBasePos, MAXCOL, MAXROW );
     596             :             // don't remember pScBasePos in mxData->mpScBasePos, shared formulas use real relative refs
     597         252 :         break;
     598             :         default:;
     599             :     }
     600             : 
     601        1006 :     if( mxData->mbOk )
     602             :     {
     603             :         // link manager to be used
     604        1006 :         mxData->mpLinkMgr = mxData->mrCfg.mbLocalLinkMgr ? &GetLocalLinkManager() : &GetGlobalLinkManager();
     605             : 
     606             :         // token array iterator (use cloned token array if present)
     607        1006 :         mxData->maTokArrIt.Init( mxData->mxOwnScTokArr ? *mxData->mxOwnScTokArr : rScTokArr, false );
     608        1006 :         mxData->mpRefLog = pRefLog;
     609             :     }
     610        1006 : }
     611             : 
     612        1006 : void XclExpFmlaCompImpl::RecalcTokenClasses()
     613             : {
     614        1006 :     if( mxData->mbOk )
     615             :     {
     616        1006 :         mxData->mbOk = mxData->maOpPosStack.size() == 1;
     617             :         OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::RecalcTokenClasses - position of root token expected on stack" );
     618        1006 :         if( mxData->mbOk )
     619             :         {
     620             :             /*  Cell and array formulas start with VAL conversion and VALTYPE
     621             :                 parameter type, defined names start with ARR conversion and
     622             :                 REFTYPE parameter type for the root token. */
     623        1006 :             XclExpOperandList aOperands;
     624        1006 :             bool bNameFmla = mxData->mrCfg.meClassType == EXC_CLASSTYPE_NAME;
     625        1006 :             XclFuncParamConv eParamConv = bNameFmla ? EXC_PARAMCONV_ARR : EXC_PARAMCONV_VAL;
     626        1006 :             XclExpClassConv eClassConv = bNameFmla ? EXC_CLASSCONV_ARR : EXC_CLASSCONV_VAL;
     627        1006 :             XclExpTokenConvInfo aConvInfo = { PopOperandPos(), eParamConv, !bNameFmla };
     628        1006 :             RecalcTokenClass( aConvInfo, eParamConv, eClassConv, bNameFmla );
     629             :         }
     630             : 
     631             :         // clear operand vectors (calls to the expensive InsertZeros() may follow)
     632        1006 :         mxData->maOpListVec.clear();
     633        1006 :         mxData->maOpPosStack.clear();
     634             :     }
     635        1006 : }
     636             : 
     637        4510 : void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo,
     638             :         XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass )
     639             : {
     640             :     OSL_ENSURE( rConvInfo.mnTokPos < GetSize(), "XclExpFmlaCompImpl::RecalcTokenClass - invalid token position" );
     641        4510 :     sal_uInt8& rnTokenId = mxData->maTokVec[ rConvInfo.mnTokPos ];
     642        4510 :     sal_uInt8 nTokClass = GetTokenClass( rnTokenId );
     643             : 
     644             :     // REF tokens in VALTYPE parameters behave like VAL tokens
     645        4510 :     if( rConvInfo.mbValType && (nTokClass == EXC_TOKCLASS_REF) )
     646         318 :         ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );
     647             : 
     648             :     // replace RPO conversion of operator with parent conversion
     649        4510 :     XclFuncParamConv eConv = (rConvInfo.meConv == EXC_PARAMCONV_RPO) ? ePrevConv : rConvInfo.meConv;
     650             : 
     651             :     // find the effective token class conversion to be performed for this token
     652        4510 :     XclExpClassConv eClassConv = EXC_CLASSCONV_ORG;
     653        4510 :     switch( eConv )
     654             :     {
     655             :         case EXC_PARAMCONV_ORG:
     656             :             // conversion is forced independent of parent conversion
     657        1492 :             eClassConv = EXC_CLASSCONV_ORG;
     658        1492 :         break;
     659             :         case EXC_PARAMCONV_VAL:
     660             :             // conversion is forced independent of parent conversion
     661        1192 :             eClassConv = EXC_CLASSCONV_VAL;
     662        1192 :         break;
     663             :         case EXC_PARAMCONV_ARR:
     664             :             // conversion is forced independent of parent conversion
     665          54 :             eClassConv = EXC_CLASSCONV_ARR;
     666          54 :         break;
     667             :         case EXC_PARAMCONV_RPT:
     668         432 :             switch( ePrevConv )
     669             :             {
     670             :                 case EXC_PARAMCONV_ORG:
     671             :                 case EXC_PARAMCONV_VAL:
     672             :                 case EXC_PARAMCONV_ARR:
     673             :                     /*  If parent token has REF class (REF token in REFTYPE
     674             :                         function parameter), then RPT does not repeat the
     675             :                         previous explicit ORG or ARR conversion, but always
     676             :                         falls back to VAL conversion. */
     677         432 :                     eClassConv = bWasRefClass ? EXC_CLASSCONV_VAL : ePrevClassConv;
     678         432 :                 break;
     679             :                 case EXC_PARAMCONV_RPT:
     680             :                     // nested RPT repeats the previous effective conversion
     681           0 :                     eClassConv = ePrevClassConv;
     682           0 :                 break;
     683             :                 case EXC_PARAMCONV_RPX:
     684             :                     /*  If parent token has REF class (REF token in REFTYPE
     685             :                         function parameter), then RPX repeats the previous
     686             :                         effective conversion (which will be either ORG or ARR,
     687             :                         but never VAL), otherwise falls back to ORG conversion. */
     688           0 :                     eClassConv = bWasRefClass ? ePrevClassConv : EXC_CLASSCONV_ORG;
     689           0 :                 break;
     690             :                 case EXC_PARAMCONV_RPO: // does not occur
     691           0 :                 break;
     692             :             }
     693         432 :         break;
     694             :         case EXC_PARAMCONV_RPX:
     695             :             /*  If current token still has REF class, set previous effective
     696             :                 conversion as current conversion. This will not have an effect
     697             :                 on the REF token but is needed for RPT parameters of this
     698             :                 function that want to repeat this conversion type. If current
     699             :                 token is VAL or ARR class, the previous ARR conversion will be
     700             :                 repeated on the token, but VAL conversion will not. */
     701         160 :             eClassConv = ((nTokClass == EXC_TOKCLASS_REF) || (ePrevClassConv == EXC_CLASSCONV_ARR)) ?
     702        2520 :                 ePrevClassConv : EXC_CLASSCONV_ORG;
     703        1340 :         break;
     704             :         case EXC_PARAMCONV_RPO: // does not occur (see above)
     705           0 :         break;
     706             :     }
     707             : 
     708             :     // do the token class conversion
     709        4510 :     switch( eClassConv )
     710             :     {
     711             :         case EXC_CLASSCONV_ORG:
     712             :             /*  Cell formulas: leave the current token class. Cell formulas
     713             :                 are the only type of formulas where all tokens can keep
     714             :                 their original token class.
     715             :                 Array and defined name formulas: convert VAL to ARR. */
     716        1652 :             if( (mxData->mrCfg.meClassType != EXC_CLASSTYPE_CELL) && (nTokClass == EXC_TOKCLASS_VAL) )
     717           0 :                 ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
     718        1652 :         break;
     719             :         case EXC_CLASSCONV_VAL:
     720             :             // convert ARR to VAL
     721        2804 :             if( nTokClass == EXC_TOKCLASS_ARR )
     722           6 :                 ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );
     723        2804 :         break;
     724             :         case EXC_CLASSCONV_ARR:
     725             :             // convert VAL to ARR
     726          54 :             if( nTokClass == EXC_TOKCLASS_VAL )
     727           0 :                 ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
     728          54 :         break;
     729             :     }
     730             : 
     731             :     // do conversion for nested operands, if token is an operator or function
     732        4510 :     if( rConvInfo.mnTokPos < mxData->maOpListVec.size() )
     733        4356 :         if( const XclExpOperandList* pOperands = mxData->maOpListVec[ rConvInfo.mnTokPos ].get() )
     734        4524 :             for( XclExpOperandList::const_iterator aIt = pOperands->begin(), aEnd = pOperands->end(); aIt != aEnd; ++aIt )
     735        3504 :                 RecalcTokenClass( *aIt, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF );
     736        4510 : }
     737             : 
     738        1006 : void XclExpFmlaCompImpl::FinalizeFormula()
     739             : {
     740        1006 :     if( mxData->mbOk )
     741             :     {
     742             :         // Volatile? Add a tAttrVolatile token at the beginning of the token array.
     743        1006 :         if( mxData->mbVolatile )
     744             :         {
     745             :             // tAttrSpace token can be extended with volatile flag
     746           0 :             if( !IsSpaceToken( 0 ) )
     747             :             {
     748           0 :                 InsertZeros( 0, 4 );
     749           0 :                 mxData->maTokVec[ 0 ] = EXC_TOKID_ATTR;
     750             :             }
     751           0 :             mxData->maTokVec[ 1 ] |= EXC_TOK_ATTR_VOLATILE;
     752             :         }
     753             : 
     754             :         // Token array too long? -> error
     755        1006 :         mxData->mbOk = mxData->maTokVec.size() <= EXC_TOKARR_MAXLEN;
     756             :     }
     757             : 
     758        1006 :     if( !mxData->mbOk )
     759             :     {
     760             :         // Any unrecoverable error? -> Create a =#NA formula.
     761           0 :         mxData->maTokVec.clear();
     762           0 :         mxData->maExtDataVec.clear();
     763           0 :         mxData->mbVolatile = false;
     764           0 :         AppendErrorToken( EXC_ERR_NA );
     765             :     }
     766        1006 : }
     767             : 
     768        1898 : XclTokenArrayRef XclExpFmlaCompImpl::CreateTokenArray()
     769             : {
     770             :     // create the Excel token array from working data before resetting mxData
     771             :     OSL_ENSURE( mxData->mrCfg.mbAllowArrays || mxData->maExtDataVec.empty(), "XclExpFmlaCompImpl::CreateTokenArray - unexpected extended data" );
     772        1898 :     if( !mxData->mrCfg.mbAllowArrays )
     773          20 :         mxData->maExtDataVec.clear();
     774        1898 :     XclTokenArrayRef xTokArr( new XclTokenArray( mxData->maTokVec, mxData->maExtDataVec, mxData->mbVolatile ) );
     775        1898 :     mxData.reset();
     776             : 
     777             :     // compiler invoked recursively? - restore old working data
     778        1898 :     if( !maDataStack.empty() )
     779             :     {
     780         120 :         mxData = maDataStack.back();
     781         120 :         maDataStack.pop_back();
     782             :     }
     783             : 
     784        1898 :     return xTokArr;
     785             : }
     786             : 
     787             : // compiler -------------------------------------------------------------------
     788             : 
     789        8672 : const FormulaToken* XclExpFmlaCompImpl::GetNextRawToken()
     790             : {
     791        8672 :     const FormulaToken* pScToken = mxData->maTokArrIt.Get();
     792        8672 :     ++mxData->maTokArrIt;
     793        8672 :     return pScToken;
     794             : }
     795             : 
     796           0 : const FormulaToken* XclExpFmlaCompImpl::PeekNextRawToken( bool bSkipSpaces ) const
     797             : {
     798             :     /*  Returns pointer to next raw token in the token array. The token array
     799             :         iterator already points to the next token (A call to GetNextToken()
     800             :         always increases the iterator), so this function just returns the token
     801             :         the iterator points to. To skip space tokens, a copy of the iterator is
     802             :         created and set to the passed skip-spaces mode. If spaces have to be
     803             :         skipped, and the iterator currently points to a space token, the
     804             :         constructor will move it to the next non-space token. */
     805           0 :     XclTokenArrayIterator aTempIt( mxData->maTokArrIt, bSkipSpaces );
     806           0 :     return aTempIt.Get();
     807             : }
     808             : 
     809        8288 : bool XclExpFmlaCompImpl::GetNextToken( XclExpScToken& rTokData )
     810             : {
     811        8288 :     rTokData.mpScToken = GetNextRawToken();
     812        8288 :     rTokData.mnSpaces = (rTokData.GetOpCode() == ocSpaces) ? rTokData.mpScToken->GetByte() : 0;
     813       16960 :     while( rTokData.GetOpCode() == ocSpaces )
     814         384 :         rTokData.mpScToken = GetNextRawToken();
     815        8288 :     return rTokData.Is();
     816             : }
     817             : 
     818        4820 : XclExpScToken XclExpFmlaCompImpl::GetNextToken()
     819             : {
     820        4820 :     XclExpScToken aTokData;
     821        4820 :     GetNextToken( aTokData );
     822        4820 :     return aTokData;
     823             : }
     824             : 
     825             : namespace {
     826             : 
     827             : /** Returns the Excel token ID of a comparison operator or EXC_TOKID_NONE. */
     828        3650 : inline sal_uInt8 lclGetCompareTokenId( OpCode eOpCode )
     829             : {
     830        3650 :     switch( eOpCode )
     831             :     {
     832           0 :         case ocLess:            return EXC_TOKID_LT;
     833           0 :         case ocLessEqual:       return EXC_TOKID_LE;
     834          82 :         case ocEqual:           return EXC_TOKID_EQ;
     835           0 :         case ocGreaterEqual:    return EXC_TOKID_GE;
     836           0 :         case ocGreater:         return EXC_TOKID_GT;
     837           2 :         case ocNotEqual:        return EXC_TOKID_NE;
     838             :         default:;
     839             :     }
     840        3566 :     return EXC_TOKID_NONE;
     841             : }
     842             : 
     843             : /** Returns the Excel token ID of a string concatenation operator or EXC_TOKID_NONE. */
     844        3650 : inline sal_uInt8 lclGetConcatTokenId( OpCode eOpCode )
     845             : {
     846        3650 :     return (eOpCode == ocAmpersand) ? EXC_TOKID_CONCAT : EXC_TOKID_NONE;
     847             : }
     848             : 
     849             : /** Returns the Excel token ID of an addition/subtraction operator or EXC_TOKID_NONE. */
     850        3666 : inline sal_uInt8 lclGetAddSubTokenId( OpCode eOpCode )
     851             : {
     852        3666 :     switch( eOpCode )
     853             :     {
     854          16 :         case ocAdd:     return EXC_TOKID_ADD;
     855           0 :         case ocSub:     return EXC_TOKID_SUB;
     856             :         default:;
     857             :     }
     858        3650 :     return EXC_TOKID_NONE;
     859             : }
     860             : 
     861             : /** Returns the Excel token ID of a multiplication/division operator or EXC_TOKID_NONE. */
     862        3686 : inline sal_uInt8 lclGetMulDivTokenId( OpCode eOpCode )
     863             : {
     864        3686 :     switch( eOpCode )
     865             :     {
     866           0 :         case ocMul:     return EXC_TOKID_MUL;
     867          20 :         case ocDiv:     return EXC_TOKID_DIV;
     868             :         default:;
     869             :     }
     870        3666 :     return EXC_TOKID_NONE;
     871             : }
     872             : 
     873             : /** Returns the Excel token ID of a power operator or EXC_TOKID_NONE. */
     874        3686 : inline sal_uInt8 lclGetPowTokenId( OpCode eOpCode )
     875             : {
     876        3686 :     return (eOpCode == ocPow) ? EXC_TOKID_POWER : EXC_TOKID_NONE;
     877             : }
     878             : 
     879             : /** Returns the Excel token ID of a trailing unary operator or EXC_TOKID_NONE. */
     880        3686 : inline sal_uInt8 lclGetUnaryPostTokenId( OpCode eOpCode )
     881             : {
     882        3686 :     return (eOpCode == ocPercentSign) ? EXC_TOKID_PERCENT : EXC_TOKID_NONE;
     883             : }
     884             : 
     885             : /** Returns the Excel token ID of a leading unary operator or EXC_TOKID_NONE. */
     886        3686 : inline sal_uInt8 lclGetUnaryPreTokenId( OpCode eOpCode )
     887             : {
     888        3686 :     switch( eOpCode )
     889             :     {
     890           0 :         case ocAdd:     return EXC_TOKID_UPLUS;     // +(1)
     891           0 :         case ocNeg:     return EXC_TOKID_UMINUS;    // NEG(1)
     892           0 :         case ocNegSub:  return EXC_TOKID_UMINUS;    // -(1)
     893             :         default:;
     894             :     }
     895        3686 :     return EXC_TOKID_NONE;
     896             : }
     897             : 
     898             : /** Returns the Excel token ID of a reference list operator or EXC_TOKID_NONE. */
     899        3686 : inline sal_uInt8 lclGetListTokenId( OpCode eOpCode, bool bStopAtSep )
     900             : {
     901        3686 :     return ((eOpCode == ocUnion) || (!bStopAtSep && (eOpCode == ocSep))) ? EXC_TOKID_LIST : EXC_TOKID_NONE;
     902             : }
     903             : 
     904             : /** Returns the Excel token ID of a reference intersection operator or EXC_TOKID_NONE. */
     905        3686 : inline sal_uInt8 lclGetIntersectTokenId( OpCode eOpCode )
     906             : {
     907        3686 :     return (eOpCode == ocIntersect) ? EXC_TOKID_ISECT : EXC_TOKID_NONE;
     908             : }
     909             : 
     910             : /** Returns the Excel token ID of a reference range operator or EXC_TOKID_NONE. */
     911        3686 : inline sal_uInt8 lclGetRangeTokenId( OpCode eOpCode )
     912             : {
     913        3686 :     return (eOpCode == ocRange) ? EXC_TOKID_RANGE : EXC_TOKID_NONE;
     914             : }
     915             : 
     916             : } // namespace
     917             : 
     918        3566 : XclExpScToken XclExpFmlaCompImpl::Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep )
     919             : {
     920        3566 :     if( mxData->mbOk && aTokData.Is() )
     921             :     {
     922             :         // remember old stop-at-ocSep mode, restored below
     923        3566 :         bool bOldStopAtSep = mxData->mbStopAtSep;
     924        3566 :         mxData->mbStopAtSep = bStopAtSep;
     925             :         // start compilation of the subexpression
     926        3566 :         aTokData = OrTerm( aTokData, bInParentheses );
     927             :         // restore old stop-at-ocSep mode
     928        3566 :         mxData->mbStopAtSep = bOldStopAtSep;
     929             :     }
     930        3566 :     return aTokData;
     931             : }
     932             : 
     933           0 : XclExpScToken XclExpFmlaCompImpl::SkipExpression( XclExpScToken aTokData, bool bStopAtSep )
     934             : {
     935           0 :     while( mxData->mbOk && aTokData.Is() && (aTokData.GetOpCode() != ocClose) && (!bStopAtSep || (aTokData.GetOpCode() != ocSep)) )
     936             :     {
     937           0 :         if( aTokData.GetOpCode() == ocOpen )
     938             :         {
     939           0 :             aTokData = SkipExpression( GetNextToken(), false );
     940           0 :             if( mxData->mbOk ) mxData->mbOk = aTokData.GetOpCode() == ocClose;
     941             :         }
     942           0 :         aTokData = GetNextToken();
     943             :     }
     944           0 :     return aTokData;
     945             : }
     946             : 
     947        3566 : XclExpScToken XclExpFmlaCompImpl::OrTerm( XclExpScToken aTokData, bool bInParentheses )
     948             : {
     949        3566 :     aTokData = AndTerm( aTokData, bInParentheses );
     950        3566 :     sal_uInt8 nParamCount = 1;
     951        7132 :     while( mxData->mbOk && (aTokData.GetOpCode() == ocOr) )
     952             :     {
     953           0 :         RemoveTrailingParen();
     954           0 :         aTokData = AndTerm( GetNextToken(), bInParentheses );
     955           0 :         RemoveTrailingParen();
     956           0 :         ++nParamCount;
     957           0 :         if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
     958             :     }
     959        3566 :     if( mxData->mbOk && (nParamCount > 1) )
     960           0 :         AppendLogicalOperatorToken( EXC_FUNCID_OR, nParamCount );
     961        3566 :     return aTokData;
     962             : }
     963             : 
     964        3566 : XclExpScToken XclExpFmlaCompImpl::AndTerm( XclExpScToken aTokData, bool bInParentheses )
     965             : {
     966        3566 :     aTokData = CompareTerm( aTokData, bInParentheses );
     967        3566 :     sal_uInt8 nParamCount = 1;
     968        7132 :     while( mxData->mbOk && (aTokData.GetOpCode() == ocAnd) )
     969             :     {
     970           0 :         RemoveTrailingParen();
     971           0 :         aTokData = CompareTerm( GetNextToken(), bInParentheses );
     972           0 :         RemoveTrailingParen();
     973           0 :         ++nParamCount;
     974           0 :         if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
     975             :     }
     976        3566 :     if( mxData->mbOk && (nParamCount > 1) )
     977           0 :         AppendLogicalOperatorToken( EXC_FUNCID_AND, nParamCount );
     978        3566 :     return aTokData;
     979             : }
     980             : 
     981        3566 : XclExpScToken XclExpFmlaCompImpl::CompareTerm( XclExpScToken aTokData, bool bInParentheses )
     982             : {
     983        3566 :     aTokData = ConcatTerm( aTokData, bInParentheses );
     984        3566 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
     985        7216 :     while( mxData->mbOk && ((nOpTokenId = lclGetCompareTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
     986             :     {
     987          84 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
     988          84 :         aTokData = ConcatTerm( GetNextToken(), bInParentheses );
     989          84 :         AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
     990             :     }
     991        3566 :     return aTokData;
     992             : }
     993             : 
     994        3650 : XclExpScToken XclExpFmlaCompImpl::ConcatTerm( XclExpScToken aTokData, bool bInParentheses )
     995             : {
     996        3650 :     aTokData = AddSubTerm( aTokData, bInParentheses );
     997        3650 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
     998        7300 :     while( mxData->mbOk && ((nOpTokenId = lclGetConcatTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
     999             :     {
    1000           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1001           0 :         aTokData = AddSubTerm( GetNextToken(), bInParentheses );
    1002           0 :         AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    1003             :     }
    1004        3650 :     return aTokData;
    1005             : }
    1006             : 
    1007        3650 : XclExpScToken XclExpFmlaCompImpl::AddSubTerm( XclExpScToken aTokData, bool bInParentheses )
    1008             : {
    1009        3650 :     aTokData = MulDivTerm( aTokData, bInParentheses );
    1010        3650 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1011        7316 :     while( mxData->mbOk && ((nOpTokenId = lclGetAddSubTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1012             :     {
    1013          16 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1014          16 :         aTokData = MulDivTerm( GetNextToken(), bInParentheses );
    1015          16 :         AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    1016             :     }
    1017        3650 :     return aTokData;
    1018             : }
    1019             : 
    1020        3666 : XclExpScToken XclExpFmlaCompImpl::MulDivTerm( XclExpScToken aTokData, bool bInParentheses )
    1021             : {
    1022        3666 :     aTokData = PowTerm( aTokData, bInParentheses );
    1023        3666 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1024        7352 :     while( mxData->mbOk && ((nOpTokenId = lclGetMulDivTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1025             :     {
    1026          20 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1027          20 :         aTokData = PowTerm( GetNextToken(), bInParentheses );
    1028          20 :         AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    1029             :     }
    1030        3666 :     return aTokData;
    1031             : }
    1032             : 
    1033        3686 : XclExpScToken XclExpFmlaCompImpl::PowTerm( XclExpScToken aTokData, bool bInParentheses )
    1034             : {
    1035        3686 :     aTokData = UnaryPostTerm( aTokData, bInParentheses );
    1036        3686 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1037        7372 :     while( mxData->mbOk && ((nOpTokenId = lclGetPowTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1038             :     {
    1039           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1040           0 :         aTokData = UnaryPostTerm( GetNextToken(), bInParentheses );
    1041           0 :         AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    1042             :     }
    1043        3686 :     return aTokData;
    1044             : }
    1045             : 
    1046        3686 : XclExpScToken XclExpFmlaCompImpl::UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses )
    1047             : {
    1048        3686 :     aTokData = UnaryPreTerm( aTokData, bInParentheses );
    1049        3686 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1050        7372 :     while( mxData->mbOk && ((nOpTokenId = lclGetUnaryPostTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1051             :     {
    1052           0 :         AppendUnaryOperatorToken( nOpTokenId, aTokData.mnSpaces );
    1053           0 :         GetNextToken( aTokData );
    1054             :     }
    1055        3686 :     return aTokData;
    1056             : }
    1057             : 
    1058        3686 : XclExpScToken XclExpFmlaCompImpl::UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses )
    1059             : {
    1060        3686 :     sal_uInt8 nOpTokenId = mxData->mbOk ? lclGetUnaryPreTokenId( aTokData.GetOpCode() ) : EXC_TOKID_NONE;
    1061        3686 :     if( nOpTokenId != EXC_TOKID_NONE )
    1062             :     {
    1063           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1064           0 :         aTokData = UnaryPreTerm( GetNextToken(), bInParentheses );
    1065           0 :         AppendUnaryOperatorToken( nOpTokenId, nSpaces );
    1066             :     }
    1067             :     else
    1068             :     {
    1069        3686 :         aTokData = ListTerm( aTokData, bInParentheses );
    1070             :     }
    1071        3686 :     return aTokData;
    1072             : }
    1073             : 
    1074        3686 : XclExpScToken XclExpFmlaCompImpl::ListTerm( XclExpScToken aTokData, bool bInParentheses )
    1075             : {
    1076        3686 :     sal_uInt16 nSubExprPos = GetSize();
    1077        3686 :     bool bHasAnyRefOp = false;
    1078        3686 :     bool bHasListOp = false;
    1079        3686 :     aTokData = IntersectTerm( aTokData, bHasAnyRefOp );
    1080        3686 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1081        7372 :     while( mxData->mbOk && ((nOpTokenId = lclGetListTokenId( aTokData.GetOpCode(), mxData->mbStopAtSep )) != EXC_TOKID_NONE) )
    1082             :     {
    1083           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1084           0 :         aTokData = IntersectTerm( GetNextToken(), bHasAnyRefOp );
    1085           0 :         AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
    1086           0 :         bHasAnyRefOp = bHasListOp = true;
    1087             :     }
    1088        3686 :     if( bHasAnyRefOp )
    1089             :     {
    1090             :         // add a tMemFunc token enclosing the entire reference subexpression
    1091           0 :         sal_uInt16 nSubExprSize = GetSize() - nSubExprPos;
    1092           0 :         InsertZeros( nSubExprPos, 3 );
    1093           0 :         mxData->maTokVec[ nSubExprPos ] = GetTokenId( EXC_TOKID_MEMFUNC, EXC_TOKCLASS_REF );
    1094           0 :         Overwrite( nSubExprPos + 1, nSubExprSize );
    1095             :         // update the operand/operator stack (set the list expression as operand of the tMemFunc)
    1096           0 :         XclExpOperandListRef xOperands( new XclExpOperandList );
    1097           0 :         xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_VAL, false );
    1098           0 :         PushOperatorPos( nSubExprPos, xOperands );
    1099             :     }
    1100             :     // #i86439# enclose list operator into parentheses, e.g. Calc's =AREAS(A1~A2) to Excel's =AREAS((A1;A2))
    1101        3686 :     if( bHasListOp && !bInParentheses )
    1102           0 :         AppendParenToken();
    1103        3686 :     return aTokData;
    1104             : }
    1105             : 
    1106        3686 : XclExpScToken XclExpFmlaCompImpl::IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp )
    1107             : {
    1108        3686 :     aTokData = RangeTerm( aTokData, rbHasRefOp );
    1109        3686 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1110        7372 :     while( mxData->mbOk && ((nOpTokenId = lclGetIntersectTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1111             :     {
    1112           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1113           0 :         aTokData = RangeTerm( GetNextToken(), rbHasRefOp );
    1114           0 :         AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
    1115           0 :         rbHasRefOp = true;
    1116             :     }
    1117        3686 :     return aTokData;
    1118             : }
    1119             : 
    1120        3686 : XclExpScToken XclExpFmlaCompImpl::RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp )
    1121             : {
    1122        3686 :     aTokData = Factor( aTokData );
    1123        3686 :     sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    1124        7372 :     while( mxData->mbOk && ((nOpTokenId = lclGetRangeTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    1125             :     {
    1126           0 :         sal_uInt8 nSpaces = aTokData.mnSpaces;
    1127           0 :         aTokData = Factor( GetNextToken() );
    1128           0 :         AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
    1129           0 :         rbHasRefOp = true;
    1130             :     }
    1131        3686 :     return aTokData;
    1132             : }
    1133             : 
    1134        3686 : XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData )
    1135             : {
    1136        3686 :     if( !mxData->mbOk || !aTokData.Is() ) return XclExpScToken();
    1137             : 
    1138        3686 :     switch( aTokData.GetType() )
    1139             :     {
    1140           0 :         case svUnknown:             mxData->mbOk = false;                   break;
    1141         556 :         case svDouble:              ProcessDouble( aTokData );              break;
    1142           8 :         case svString:              ProcessString( aTokData );              break;
    1143        1646 :         case svSingleRef:           ProcessCellRef( aTokData );             break;
    1144         560 :         case svDoubleRef:           ProcessRangeRef( aTokData );            break;
    1145           2 :         case svExternalSingleRef:   ProcessExternalCellRef( aTokData );     break;
    1146           0 :         case svExternalDoubleRef:   ProcessExternalRangeRef( aTokData );    break;
    1147           0 :         case svExternalName:        ProcessExternalName( aTokData );        break;
    1148           6 :         case svMatrix:              ProcessMatrix( aTokData );              break;
    1149           0 :         case svExternal:            ProcessExternal( aTokData );            break;
    1150             : 
    1151         908 :         default: switch( aTokData.GetOpCode() )
    1152             :         {
    1153           0 :             case ocNone:        /* do nothing */                    break;
    1154           4 :             case ocMissing:     ProcessMissing( aTokData );         break;
    1155           0 :             case ocBad:         ProcessBad( aTokData );             break;
    1156           0 :             case ocOpen:        ProcessParentheses( aTokData );     break;
    1157           0 :             case ocName:        ProcessDefinedName( aTokData );     break;
    1158             :             case ocFalse:
    1159           4 :             case ocTrue:        ProcessBoolean( aTokData );         break;
    1160           0 :             case ocDde:         ProcessDdeLink( aTokData );         break;
    1161         900 :             default:            ProcessFunction( aTokData );
    1162             :         }
    1163             :     }
    1164             : 
    1165        3686 :     return GetNextToken();
    1166             : }
    1167             : 
    1168             : // formula structure ----------------------------------------------------------
    1169             : 
    1170         556 : void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData )
    1171             : {
    1172         556 :     double fValue = rTokData.mpScToken->GetDouble();
    1173             :     double fInt;
    1174         556 :     double fFrac = modf( fValue, &fInt );
    1175         556 :     if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) )
    1176         500 :         AppendIntToken( static_cast< sal_uInt16 >( fInt ), rTokData.mnSpaces );
    1177             :     else
    1178          56 :         AppendNumToken( fValue, rTokData.mnSpaces );
    1179         556 : }
    1180             : 
    1181           8 : void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData )
    1182             : {
    1183           8 :     AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces );
    1184           8 :     Append( rTokData.mpScToken->GetString().getString() );
    1185           8 : }
    1186             : 
    1187           4 : void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData )
    1188             : {
    1189           4 :     AppendMissingToken( rTokData.mnSpaces );
    1190           4 : }
    1191             : 
    1192           0 : void XclExpFmlaCompImpl::ProcessBad( const XclExpScToken& rTokData )
    1193             : {
    1194           0 :     AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
    1195           0 : }
    1196             : 
    1197           0 : void XclExpFmlaCompImpl::ProcessParentheses( const XclExpScToken& rTokData )
    1198             : {
    1199           0 :     XclExpScToken aTokData = Expression( GetNextToken(), true, false );
    1200           0 :     mxData->mbOk = aTokData.GetOpCode() == ocClose;
    1201           0 :     AppendParenToken( rTokData.mnSpaces, aTokData.mnSpaces );
    1202           0 : }
    1203             : 
    1204           4 : void XclExpFmlaCompImpl::ProcessBoolean( const XclExpScToken& rTokData )
    1205             : {
    1206           4 :     mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
    1207           4 :     if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
    1208           4 :     if( mxData->mbOk )
    1209           4 :         AppendBoolToken( rTokData.GetOpCode() == ocTrue, rTokData.mnSpaces );
    1210           4 : }
    1211             : 
    1212             : namespace {
    1213             : 
    1214           0 : inline bool lclGetTokenString( OUString& rString, const XclExpScToken& rTokData )
    1215             : {
    1216           0 :     bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush);
    1217           0 :     if( bIsStr )
    1218           0 :         rString = rTokData.mpScToken->GetString().getString();
    1219           0 :     return bIsStr;
    1220             : }
    1221             : 
    1222             : } // namespace
    1223             : 
    1224           0 : void XclExpFmlaCompImpl::ProcessDdeLink( const XclExpScToken& rTokData )
    1225             : {
    1226           0 :     OUString aApplic, aTopic, aItem;
    1227             : 
    1228           0 :     mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
    1229           0 :     if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aApplic, GetNextToken() );
    1230           0 :     if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
    1231           0 :     if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aTopic, GetNextToken() );
    1232           0 :     if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
    1233           0 :     if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aItem, GetNextToken() );
    1234           0 :     if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
    1235           0 :     if( mxData->mbOk ) mxData->mbOk = !aApplic.isEmpty() && !aTopic.isEmpty() && !aItem.isEmpty();
    1236           0 :     if( mxData->mbOk )
    1237             :     {
    1238           0 :         sal_uInt16 nExtSheet(0), nExtName(0);
    1239           0 :         if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertDde( nExtSheet, nExtName, aApplic, aTopic, aItem ) )
    1240           0 :             AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
    1241             :         else
    1242           0 :             AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
    1243           0 :     }
    1244           0 : }
    1245             : 
    1246           0 : void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData )
    1247             : {
    1248             :     /*  #i47228# Excel import generates svExternal/ocMacro tokens for invalid
    1249             :         names and for external/invalid function calls. This function looks for
    1250             :         the next token in the token array. If it is an opening parenthesis, the
    1251             :         token is processed as external function call, otherwise as undefined name. */
    1252           0 :     const FormulaToken* pNextScToken = PeekNextRawToken( true );
    1253           0 :     if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) )
    1254           0 :         AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces );
    1255             :     else
    1256           0 :         ProcessFunction( rTokData );
    1257           0 : }
    1258             : 
    1259           6 : void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData )
    1260             : {
    1261           6 :     const ScMatrix* pMatrix = rTokData.mpScToken->GetMatrix();
    1262           6 :     if( pMatrix && mxData->mrCfg.mbAllowArrays )
    1263             :     {
    1264             :         SCSIZE nScCols, nScRows;
    1265           6 :         pMatrix->GetDimensions( nScCols, nScRows );
    1266             :         OSL_ENSURE( (nScCols > 0) && (nScRows > 0), "XclExpFmlaCompImpl::ProcessMatrix - invalid matrix size" );
    1267           6 :         sal_uInt16 nCols = ::limit_cast< sal_uInt16 >( nScCols, 0, 256 );
    1268           6 :         sal_uInt16 nRows = ::limit_cast< sal_uInt16 >( nScRows, 0, 1024 );
    1269             : 
    1270             :         // create the tArray token
    1271           6 :         AppendOperandTokenId( GetTokenId( EXC_TOKID_ARRAY, EXC_TOKCLASS_ARR ), rTokData.mnSpaces );
    1272           6 :         Append( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
    1273           6 :         Append( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
    1274           6 :         Append( static_cast< sal_uInt32 >( 0 ) );
    1275             : 
    1276             :         // create the extended data containing the array values
    1277           6 :         AppendExt( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
    1278           6 :         AppendExt( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
    1279          20 :         for( SCSIZE nScRow = 0; nScRow < nScRows; ++nScRow )
    1280             :         {
    1281          46 :             for( SCSIZE nScCol = 0; nScCol < nScCols; ++nScCol )
    1282             :             {
    1283          32 :                 ScMatrixValue nMatVal = pMatrix->Get( nScCol, nScRow );
    1284          32 :                 if( ScMatrix::IsValueType( nMatVal.nType ) )    // value, boolean, or error
    1285             :                 {
    1286          32 :                     if( ScMatrix::IsBooleanType( nMatVal.nType ) )
    1287             :                     {
    1288           0 :                         AppendExt( EXC_CACHEDVAL_BOOL );
    1289           0 :                         AppendExt( static_cast< sal_uInt8 >( nMatVal.GetBoolean() ? 1 : 0 ) );
    1290           0 :                         AppendExt( 0, 7 );
    1291             :                     }
    1292          32 :                     else if( sal_uInt16 nErr = nMatVal.GetError() )
    1293             :                     {
    1294           0 :                         AppendExt( EXC_CACHEDVAL_ERROR );
    1295           0 :                         AppendExt( XclTools::GetXclErrorCode( nErr ) );
    1296           0 :                         AppendExt( 0, 7 );
    1297             :                     }
    1298             :                     else
    1299             :                     {
    1300          32 :                         AppendExt( EXC_CACHEDVAL_DOUBLE );
    1301          32 :                         AppendExt( nMatVal.fVal );
    1302             :                     }
    1303             :                 }
    1304             :                 else    // string or empty
    1305             :                 {
    1306           0 :                     const OUString aStr( nMatVal.GetString().getString());
    1307           0 :                     if( aStr.isEmpty() )
    1308             :                     {
    1309           0 :                         AppendExt( EXC_CACHEDVAL_EMPTY );
    1310           0 :                         AppendExt( 0, 8 );
    1311             :                     }
    1312             :                     else
    1313             :                     {
    1314           0 :                         AppendExt( EXC_CACHEDVAL_STRING );
    1315           0 :                         AppendExt( aStr );
    1316           0 :                     }
    1317             :                 }
    1318          32 :             }
    1319             :         }
    1320             :     }
    1321             :     else
    1322             :     {
    1323             :         // array in places that do not allow it (cond fmts, data validation)
    1324           0 :         AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
    1325             :     }
    1326           6 : }
    1327             : 
    1328         900 : void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData )
    1329             : {
    1330         900 :     OpCode eOpCode = rTokData.GetOpCode();
    1331         900 :     const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( eOpCode );
    1332             : 
    1333         900 :     XclExpExtFuncData aExtFuncData;
    1334             : 
    1335             :     // no exportable function found - try to create an external macro call
    1336         900 :     if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) )
    1337             :     {
    1338           0 :         const OUString& rFuncName = ScCompiler::GetNativeSymbol( eOpCode );
    1339           0 :         if( !rFuncName.isEmpty() )
    1340             :         {
    1341           0 :             aExtFuncData.Set( rFuncName, true, false );
    1342           0 :             pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( ocMacro );
    1343             :         }
    1344             :     }
    1345             : 
    1346         900 :     mxData->mbOk = pFuncInfo != 0;
    1347        1800 :     if( !mxData->mbOk ) return;
    1348             : 
    1349             :     // internal functions equivalent to an existing add-in
    1350         900 :     if( pFuncInfo->IsAddInEquivalent() )
    1351           0 :         aExtFuncData.Set( pFuncInfo->GetAddInEquivalentFuncName(), true, false );
    1352             :     // functions simulated by a macro call in file format
    1353         900 :     else if( pFuncInfo->IsMacroFunc() )
    1354         704 :         aExtFuncData.Set( pFuncInfo->GetMacroFuncName(), false, true );
    1355             : 
    1356        1800 :     XclExpFuncData aFuncData( rTokData, *pFuncInfo, aExtFuncData );
    1357         900 :     XclExpScToken aTokData;
    1358             : 
    1359             :     // preparations for special functions, before function processing starts
    1360         900 :     PrepareFunction( aFuncData );
    1361             : 
    1362             :     enum { STATE_START, STATE_OPEN, STATE_PARAM, STATE_SEP, STATE_CLOSE, STATE_END }
    1363         900 :         eState = STATE_START;
    1364        8728 :     while( eState != STATE_END ) switch( eState )
    1365             :     {
    1366             :         case STATE_START:
    1367         900 :             mxData->mbOk = GetNextToken( aTokData ) && (aTokData.GetOpCode() == ocOpen);
    1368         900 :             eState = mxData->mbOk ? STATE_OPEN : STATE_END;
    1369         900 :         break;
    1370             :         case STATE_OPEN:
    1371         900 :             mxData->mbOk = GetNextToken( aTokData );
    1372         900 :             eState = mxData->mbOk ? ((aTokData.GetOpCode() == ocClose) ? STATE_CLOSE : STATE_PARAM) : STATE_END;
    1373         900 :         break;
    1374             :         case STATE_PARAM:
    1375        2560 :             aTokData = ProcessParam( aTokData, aFuncData );
    1376        2560 :             switch( aTokData.GetOpCode() )
    1377             :             {
    1378        1668 :                 case ocSep:     eState = STATE_SEP;                 break;
    1379         892 :                 case ocClose:   eState = STATE_CLOSE;               break;
    1380           0 :                 default:        mxData->mbOk = false;
    1381             :             }
    1382        2560 :             if( !mxData->mbOk ) eState = STATE_END;
    1383        2560 :         break;
    1384             :         case STATE_SEP:
    1385        1668 :             mxData->mbOk = (aFuncData.GetParamCount() < EXC_FUNC_MAXPARAM) && GetNextToken( aTokData );
    1386        1668 :             eState = mxData->mbOk ? STATE_PARAM : STATE_END;
    1387        1668 :         break;
    1388             :         case STATE_CLOSE:
    1389         900 :             FinishFunction( aFuncData, aTokData.mnSpaces );
    1390         900 :             eState = STATE_END;
    1391         900 :         break;
    1392             :         default:;
    1393         900 :     }
    1394             : }
    1395             : 
    1396         900 : void XclExpFmlaCompImpl::PrepareFunction( XclExpFuncData& rFuncData )
    1397             : {
    1398             :     // For OOXML these are not rewritten anymore.
    1399         900 :     if (GetOutput() != EXC_OUTPUT_XML_2007)
    1400             :     {
    1401         454 :         switch( rFuncData.GetOpCode() )
    1402             :         {
    1403             :             case ocCosecant:                // simulate CSC(x) by (1/SIN(x))
    1404             :             case ocSecant:                  // simulate SEC(x) by (1/COS(x))
    1405             :             case ocCot:                     // simulate COT(x) by (1/TAN(x))
    1406             :             case ocCosecantHyp:             // simulate CSCH(x) by (1/SINH(x))
    1407             :             case ocSecantHyp:               // simulate SECH(x) by (1/COSH(x))
    1408             :             case ocCotHyp:                  // simulate COTH(x) by (1/TANH(x))
    1409           0 :                 AppendIntToken( 1 );
    1410           0 :                 break;
    1411             :             case ocArcCot:                  // simulate ACOT(x) by (PI/2-ATAN(x))
    1412           0 :                 AppendNumToken( F_PI2 );
    1413           0 :                 break;
    1414             :             default:;
    1415             :         }
    1416             :     }
    1417         900 : }
    1418             : 
    1419         900 : void XclExpFmlaCompImpl::FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces )
    1420             : {
    1421             :     // append missing parameters required in Excel, may modify param count
    1422         900 :     AppendTrailingParam( rFuncData );
    1423             : 
    1424             :     // check if parameter count fits into the limits of the function
    1425         900 :     sal_uInt8 nParamCount = rFuncData.GetParamCount();
    1426         900 :     if( (rFuncData.GetMinParamCount() <= nParamCount) && (nParamCount <= rFuncData.GetMaxParamCount()) )
    1427             :     {
    1428             :         // first put the tAttrSpace tokens, they must not be included in tAttrGoto handling
    1429         900 :         AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
    1430         900 :         AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, rFuncData.GetSpaces() );
    1431             : 
    1432             :         // add tAttrGoto tokens for IF or CHOOSE functions
    1433         900 :         switch( rFuncData.GetOpCode() )
    1434             :         {
    1435             :             case ocIf:
    1436             :             case ocChose:
    1437           0 :                 AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
    1438           0 :             break;
    1439             :             default:;
    1440             :         }
    1441             : 
    1442             :         // put the tFunc or tFuncVar token (or another special token, e.g. tAttrSum)
    1443         900 :         AppendFuncToken( rFuncData );
    1444             : 
    1445             :         // update volatile flag - is set if at least one used function is volatile
    1446         900 :         mxData->mbVolatile |= rFuncData.IsVolatile();
    1447             : 
    1448             :         // update jump tokens for specific functions, add additional tokens
    1449         900 :         switch( rFuncData.GetOpCode() )
    1450             :         {
    1451             :             case ocIf:
    1452           0 :                 FinishIfFunction( rFuncData );
    1453           0 :             break;
    1454             :             case ocChose:
    1455           0 :                 FinishChooseFunction( rFuncData );
    1456           0 :             break;
    1457             : 
    1458             :             case ocCosecant:                // simulate CSC(x) by (1/SIN(x))
    1459             :             case ocSecant:                  // simulate SEC(x) by (1/COS(x))
    1460             :             case ocCot:                     // simulate COT(x) by (1/TAN(x))
    1461             :             case ocCosecantHyp:             // simulate CSCH(x) by (1/SINH(x))
    1462             :             case ocSecantHyp:               // simulate SECH(x) by (1/COSH(x))
    1463             :             case ocCotHyp:                  // simulate COTH(x) by (1/TANH(x))
    1464             :                 // For OOXML not rewritten anymore.
    1465           0 :                 if (GetOutput() != EXC_OUTPUT_XML_2007)
    1466             :                 {
    1467           0 :                     AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
    1468           0 :                     AppendParenToken();
    1469             :                 }
    1470           0 :             break;
    1471             :             case ocArcCot:                  // simulate ACOT(x) by (PI/2-ATAN(x))
    1472             :                 // For OOXML not rewritten anymore.
    1473           0 :                 if (GetOutput() != EXC_OUTPUT_XML_2007)
    1474             :                 {
    1475           0 :                     AppendBinaryOperatorToken( EXC_TOKID_SUB, true );
    1476           0 :                     AppendParenToken();
    1477             :                 }
    1478           0 :             break;
    1479             : 
    1480             :             default:;
    1481             :         }
    1482             :     }
    1483             :     else
    1484           0 :         mxData->mbOk = false;
    1485         900 : }
    1486             : 
    1487           0 : void XclExpFmlaCompImpl::FinishIfFunction( XclExpFuncData& rFuncData )
    1488             : {
    1489           0 :     sal_uInt16 nParamCount = rFuncData.GetParamCount();
    1490             :     OSL_ENSURE( (nParamCount == 2) || (nParamCount == 3), "XclExpFmlaCompImpl::FinishIfFunction - wrong parameter count" );
    1491           0 :     const ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
    1492             :     OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishIfFunction - wrong number of tAttr tokens" );
    1493             :     // update tAttrIf token following the condition parameter
    1494           0 :     Overwrite( rAttrPos[ 0 ] + 2, static_cast< sal_uInt16 >( rAttrPos[ 1 ] - rAttrPos[ 0 ] ) );
    1495             :     // update the tAttrGoto tokens following true and false parameters
    1496           0 :     UpdateAttrGoto( rAttrPos[ 1 ] );
    1497           0 :     if( nParamCount == 3 )
    1498           0 :         UpdateAttrGoto( rAttrPos[ 2 ] );
    1499           0 : }
    1500             : 
    1501           0 : void XclExpFmlaCompImpl::FinishChooseFunction( XclExpFuncData& rFuncData )
    1502             : {
    1503           0 :     sal_uInt16 nParamCount = rFuncData.GetParamCount();
    1504           0 :     ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
    1505             :     OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishChooseFunction - wrong number of tAttr tokens" );
    1506             :     // number of choices is parameter count minus 1
    1507           0 :     sal_uInt16 nChoices = nParamCount - 1;
    1508             :     // tAttrChoose token contains number of choices
    1509           0 :     Overwrite( rAttrPos[ 0 ] + 2, nChoices );
    1510             :     // cache position of the jump table (follows number of choices in tAttrChoose token)
    1511           0 :     sal_uInt16 nJumpArrPos = rAttrPos[ 0 ] + 4;
    1512             :     // size of jump table: number of choices, plus 1 for error position
    1513           0 :     sal_uInt16 nJumpArrSize = 2 * (nChoices + 1);
    1514             :     // insert the jump table into the tAttrChoose token
    1515           0 :     InsertZeros( nJumpArrPos, nJumpArrSize );
    1516             :     // update positions of tAttrGoto tokens after jump table insertion
    1517             :     sal_uInt16 nIdx;
    1518           0 :     for( nIdx = 1; nIdx < nParamCount; ++nIdx )
    1519           0 :         rAttrPos[ nIdx ] = rAttrPos[ nIdx ] + nJumpArrSize;
    1520             :     // update the tAttrGoto tokens (they contain a value one-less to real distance)
    1521           0 :     for( nIdx = 1; nIdx < nParamCount; ++nIdx )
    1522           0 :         UpdateAttrGoto( rAttrPos[ nIdx ] );
    1523             :     // update the distances in the jump table
    1524           0 :     Overwrite( nJumpArrPos, nJumpArrSize );
    1525           0 :     for( nIdx = 1; nIdx < nParamCount; ++nIdx )
    1526           0 :         Overwrite( nJumpArrPos + 2 * nIdx, static_cast< sal_uInt16 >( rAttrPos[ nIdx ] + 4 - nJumpArrPos ) );
    1527           0 : }
    1528             : 
    1529        2560 : XclExpScToken XclExpFmlaCompImpl::ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData )
    1530             : {
    1531        2560 :     if( rFuncData.IsCalcOnlyParam() )
    1532             :     {
    1533             :         // skip Calc-only parameter, stop at next ocClose or ocSep
    1534           0 :         aTokData = SkipExpression( aTokData, true );
    1535           0 :         rFuncData.IncParamInfoIdx();
    1536             :     }
    1537             :     else
    1538             :     {
    1539             :         // insert Excel-only parameters, modifies param count and class in rFuncData
    1540        5824 :         while( rFuncData.IsExcelOnlyParam() )
    1541         704 :             AppendDefaultParam( rFuncData );
    1542             : 
    1543             :         // process the parameter, stop at next ocClose or ocSep
    1544        2560 :         PrepareParam( rFuncData );
    1545             :         /*  #i37355# insert tMissArg token for missing parameters --
    1546             :             Excel import filter adds ocMissing token (handled in Factor()),
    1547             :             but Calc itself does not do this if a new formula is entered. */
    1548        2560 :         switch( aTokData.GetOpCode() )
    1549             :         {
    1550             :             case ocSep:
    1551           0 :             case ocClose:   AppendMissingToken();   break;  // empty parameter
    1552        2560 :             default:        aTokData = Expression( aTokData, false, true );
    1553             :         }
    1554             :         // finalize the parameter and add special tokens, e.g. for IF or CHOOSE parameters
    1555        2560 :         if( mxData->mbOk ) FinishParam( rFuncData );
    1556             :     }
    1557        2560 :     return aTokData;
    1558             : }
    1559             : 
    1560        3264 : void XclExpFmlaCompImpl::PrepareParam( XclExpFuncData& rFuncData )
    1561             : {
    1562             :     // index of this parameter is equal to number of already finished parameters
    1563        3264 :     sal_uInt8 nParamIdx = rFuncData.GetParamCount();
    1564             : 
    1565        3264 :     switch( rFuncData.GetOpCode() )
    1566             :     {
    1567             :         case ocIf:
    1568           0 :             switch( nParamIdx )
    1569             :             {
    1570             :                 // add a tAttrIf token before true-parameter (second parameter)
    1571           0 :                 case 1:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_IF );      break;
    1572             :                 // add a tAttrGoto token before false-parameter (third parameter)
    1573           0 :                 case 2:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );    break;
    1574             :             }
    1575           0 :         break;
    1576             : 
    1577             :         case ocChose:
    1578           0 :             switch( nParamIdx )
    1579             :             {
    1580             :                 // do nothing for first parameter
    1581           0 :                 case 0:                                                         break;
    1582             :                 // add a tAttrChoose token before first value parameter (second parameter)
    1583           0 :                 case 1:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_CHOOSE );  break;
    1584             :                 // add a tAttrGoto token before other value parameters
    1585           0 :                 default:    AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
    1586             :             }
    1587           0 :         break;
    1588             : 
    1589             :         case ocArcCotHyp:               // simulate ACOTH(x) by ATANH(1/(x))
    1590           0 :             if( nParamIdx == 0 )
    1591           0 :                 AppendIntToken( 1 );
    1592           0 :         break;
    1593             :         default:;
    1594             :     }
    1595        3264 : }
    1596             : 
    1597        3264 : void XclExpFmlaCompImpl::FinishParam( XclExpFuncData& rFuncData )
    1598             : {
    1599             :     // increase parameter count, update operand stack
    1600        3264 :     rFuncData.FinishParam( PopOperandPos() );
    1601             : 
    1602             :     // append more tokens for parameters of some special functions
    1603        3264 :     sal_uInt8 nParamIdx = rFuncData.GetParamCount() - 1;
    1604        3264 :     switch( rFuncData.GetOpCode() )
    1605             :     {
    1606             :         case ocArcCotHyp:               // simulate ACOTH(x) by ATANH(1/(x))
    1607           0 :             if( nParamIdx == 0 )
    1608             :             {
    1609           0 :                 AppendParenToken();
    1610           0 :                 AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
    1611             :             }
    1612           0 :         break;
    1613             :         default:;
    1614             :     }
    1615        3264 : }
    1616             : 
    1617         704 : void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
    1618             : {
    1619             :     // prepare parameters of some special functions
    1620         704 :     PrepareParam( rFuncData );
    1621             : 
    1622         704 :     switch( rFuncData.GetOpCode() )
    1623             :     {
    1624             :         case ocExternal:
    1625           0 :             AppendAddInCallToken( rFuncData.GetExtFuncData() );
    1626           0 :         break;
    1627             :         case ocEuroConvert:
    1628           0 :             AppendEuroToolCallToken( rFuncData.GetExtFuncData() );
    1629           0 :         break;
    1630             :         case ocMacro:
    1631           0 :             AppendMacroCallToken( rFuncData.GetExtFuncData() );
    1632           0 :         break;
    1633             :         default:
    1634             :         {
    1635         704 :             if( rFuncData.IsAddInEquivalent() )
    1636             :             {
    1637           0 :                 AppendAddInCallToken( rFuncData.GetExtFuncData() );
    1638             :             }
    1639         704 :             else if( rFuncData.IsMacroFunc() )
    1640             :             {
    1641             :                 // Do not write the OOXML <definedName> element for new _xlfn.
    1642             :                 // prefixed functions.
    1643         704 :                 if (GetOutput() == EXC_OUTPUT_XML_2007)
    1644         352 :                     AppendNameToken( 0, 0);     // dummy to keep parameter count valid
    1645             :                 else
    1646         352 :                     AppendMacroCallToken( rFuncData.GetExtFuncData() );
    1647             :             }
    1648             :             else
    1649             :             {
    1650             :                 SAL_WARN( "sc.filter", "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" );
    1651           0 :                 AppendMissingToken();   // to keep parameter count valid
    1652             :             }
    1653             :         }
    1654             :     }
    1655             : 
    1656             :     // update parameter count, add special parameter tokens
    1657         704 :     FinishParam( rFuncData );
    1658         704 : }
    1659             : 
    1660         900 : void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
    1661             : {
    1662         900 :     sal_uInt8 nParamCount = rFuncData.GetParamCount();
    1663         900 :     switch( rFuncData.GetOpCode() )
    1664             :     {
    1665             :         case ocIf:
    1666           0 :             if( nParamCount == 1 )
    1667             :             {
    1668             :                 // Excel needs at least two parameters in IF function
    1669           0 :                 PrepareParam( rFuncData );
    1670           0 :                 AppendBoolToken( true );
    1671           0 :                 FinishParam( rFuncData );
    1672             :             }
    1673           0 :         break;
    1674             : 
    1675             :         case ocRound:
    1676             :         case ocRoundUp:
    1677             :         case ocRoundDown:
    1678         160 :             if( nParamCount == 1 )
    1679             :             {
    1680             :                 // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
    1681           0 :                 PrepareParam( rFuncData );
    1682           0 :                 AppendIntToken( 0 );
    1683           0 :                 FinishParam( rFuncData );
    1684             :             }
    1685         160 :         break;
    1686             : 
    1687             :         case ocIndex:
    1688           0 :             if( nParamCount == 1 )
    1689             :             {
    1690             :                 // INDEX function needs at least 2 parameters in Excel
    1691           0 :                 PrepareParam( rFuncData );
    1692           0 :                 AppendMissingToken();
    1693           0 :                 FinishParam( rFuncData );
    1694             :             }
    1695           0 :         break;
    1696             : 
    1697             :         case ocExternal:
    1698             :         case ocMacro:
    1699             :             // external or macro call without parameters needs the external name reference
    1700           0 :             if( nParamCount == 0 )
    1701           0 :                 AppendDefaultParam( rFuncData );
    1702           0 :         break;
    1703             : 
    1704             :         case ocGammaDist:
    1705           0 :             if( nParamCount == 3 )
    1706             :             {
    1707             :                 // GAMMADIST function needs 4 parameters in Excel
    1708           0 :                 PrepareParam( rFuncData );
    1709           0 :                 AppendIntToken( 1 );
    1710           0 :                 FinishParam( rFuncData );
    1711             :             }
    1712           0 :         break;
    1713             : 
    1714             :         case ocPoissonDist:
    1715           0 :             if( nParamCount == 2 )
    1716             :             {
    1717             :                 // POISSON function needs 3 parameters in Excel
    1718           0 :                 PrepareParam( rFuncData );
    1719           0 :                 AppendIntToken( 1 );
    1720           0 :                 FinishParam( rFuncData );
    1721             :             }
    1722           0 :         break;
    1723             : 
    1724             :         case ocNormDist:
    1725           0 :             if( nParamCount == 3 )
    1726             :             {
    1727             :                 // NORMDIST function needs 4 parameters in Excel
    1728           0 :                 PrepareParam( rFuncData );
    1729           0 :                 AppendBoolToken( true );
    1730           0 :                 FinishParam( rFuncData );
    1731             :             }
    1732           0 :         break;
    1733             : 
    1734             :         case ocLogNormDist:
    1735           0 :             switch( nParamCount )
    1736             :              {
    1737             :                 // LOGNORMDIST function needs 3 parameters in Excel
    1738             :                 case 1:
    1739           0 :                     PrepareParam( rFuncData );
    1740           0 :                     AppendIntToken( 0 );
    1741           0 :                     FinishParam( rFuncData );
    1742             :                  // do not break, add next default parameter
    1743             :                 case 2:
    1744           0 :                     PrepareParam( rFuncData );
    1745           0 :                     AppendIntToken( 1 );
    1746           0 :                     FinishParam( rFuncData );
    1747           0 :                     break;
    1748             :                 default:;
    1749             :              }
    1750             : 
    1751           0 :         break;
    1752             : 
    1753             :         default:
    1754             :             // #i108420# function without parameters stored as macro call needs the external name reference
    1755         740 :             if( (nParamCount == 0) && rFuncData.IsMacroFunc() )
    1756           0 :                 AppendDefaultParam( rFuncData );
    1757             : 
    1758             :     }
    1759         900 : }
    1760             : 
    1761             : // reference handling ---------------------------------------------------------
    1762             : 
    1763             : namespace {
    1764             : 
    1765         840 : inline bool lclIsRefRel2D( const ScSingleRefData& rRefData )
    1766             : {
    1767         840 :     return rRefData.IsColRel() || rRefData.IsRowRel();
    1768             : }
    1769             : 
    1770        2264 : inline bool lclIsRefDel2D( const ScSingleRefData& rRefData )
    1771             : {
    1772        2264 :     return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
    1773             : }
    1774             : 
    1775         168 : inline bool lclIsRefRel2D( const ScComplexRefData& rRefData )
    1776             : {
    1777         168 :     return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
    1778             : }
    1779             : 
    1780         560 : inline bool lclIsRefDel2D( const ScComplexRefData& rRefData )
    1781             : {
    1782         560 :     return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
    1783             : }
    1784             : 
    1785             : } // namespace
    1786             : 
    1787         170 : SCTAB XclExpFmlaCompImpl::GetScTab( const ScSingleRefData& rRefData ) const
    1788             : {
    1789         170 :     if (rRefData.IsTabDeleted())
    1790           0 :         return SCTAB_INVALID;
    1791             : 
    1792         170 :     if (!rRefData.IsTabRel())
    1793             :         // absolute address
    1794         170 :         return rRefData.Tab();
    1795             : 
    1796           0 :     if (!mxData->mpScBasePos)
    1797           0 :         return SCTAB_INVALID;
    1798             : 
    1799           0 :     return rRefData.toAbs(*mxData->mpScBasePos).Tab();
    1800             : }
    1801             : 
    1802        6616 : bool XclExpFmlaCompImpl::IsRef2D( const ScSingleRefData& rRefData, bool bCheck3DFlag ) const
    1803             : {
    1804             :     /*  rRefData.IsFlag3D() determines if sheet name is always visible, even on
    1805             :         the own sheet. If 3D references are allowed, the passed reference does
    1806             :         not count as 2D reference. */
    1807             : 
    1808        6616 :     if (bCheck3DFlag && rRefData.IsFlag3D())
    1809          84 :         return false;
    1810             : 
    1811        6532 :     if (rRefData.IsTabDeleted())
    1812           0 :         return false;
    1813             : 
    1814        6532 :     if (rRefData.IsTabRel())
    1815        6532 :         return rRefData.Tab() == 0;
    1816             :     else
    1817           0 :         return rRefData.Tab() == GetCurrScTab();
    1818             : }
    1819             : 
    1820        1004 : bool XclExpFmlaCompImpl::IsRef2D( const ScComplexRefData& rRefData, bool bCheck3DFlag ) const
    1821             : {
    1822        1004 :     return IsRef2D(rRefData.Ref1, bCheck3DFlag) && IsRef2D(rRefData.Ref2, bCheck3DFlag);
    1823             : }
    1824             : 
    1825        2768 : void XclExpFmlaCompImpl::ConvertRefData(
    1826             :     ScSingleRefData& rRefData, XclAddress& rXclPos,
    1827             :     bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const
    1828             : {
    1829        2768 :     if( mxData->mpScBasePos )
    1830             :     {
    1831             :         // *** reference position exists (cell, matrix) - convert to absolute ***
    1832        1928 :         ScAddress aAbs = rRefData.toAbs(*mxData->mpScBasePos);
    1833             : 
    1834             :         // convert column index
    1835        1928 :         if (bTruncMaxCol && (aAbs.Col() == mnMaxScCol))
    1836           0 :             aAbs.SetCol(mnMaxAbsCol);
    1837        1928 :         else if ((aAbs.Col() < 0) || (aAbs.Col() > mnMaxAbsCol))
    1838           0 :             rRefData.SetColDeleted(true);
    1839        1928 :         rXclPos.mnCol = static_cast<sal_uInt16>(aAbs.Col()) & mnMaxColMask;
    1840             : 
    1841             :         // convert row index
    1842        1928 :         if (bTruncMaxRow && (aAbs.Row() == mnMaxScRow))
    1843           0 :             aAbs.SetRow(mnMaxAbsRow);
    1844        1928 :         else if ((aAbs.Row() < 0) || (aAbs.Row() > mnMaxAbsRow))
    1845           0 :             rRefData.SetRowDeleted(true);
    1846        1928 :         rXclPos.mnRow = static_cast<sal_uInt32>(aAbs.Row()) & mnMaxRowMask;
    1847             : 
    1848             :         // Update the reference.
    1849        1928 :         rRefData.SetAddress(aAbs, *mxData->mpScBasePos);
    1850             :     }
    1851             :     else
    1852             :     {
    1853             :         // *** no reference position (shared, names, condfmt) - use relative values ***
    1854             : 
    1855             :         // convert column index (2-step-cast ScsCOL->sal_Int16->sal_uInt16 to get all bits correctly)
    1856         840 :         sal_Int16 nXclRelCol = static_cast<sal_Int16>(rRefData.Col());
    1857         840 :         rXclPos.mnCol = static_cast< sal_uInt16 >( nXclRelCol ) & mnMaxColMask;
    1858             : 
    1859             :         // convert row index (2-step-cast ScsROW->sal_Int16->sal_uInt16 to get all bits correctly)
    1860         840 :         sal_Int16 nXclRelRow = static_cast<sal_Int32>(rRefData.Row());
    1861         840 :         rXclPos.mnRow = static_cast< sal_uInt32 >( nXclRelRow ) & mnMaxRowMask;
    1862             :     }
    1863             : 
    1864             :     // flags for relative column and row
    1865        2768 :     if( bNatLangRef )
    1866             :     {
    1867             :         OSL_ENSURE( meBiff == EXC_BIFF8, "XclExpFmlaCompImpl::ConvertRefData - NLRs only for BIFF8" );
    1868             :         // Calc does not support absolute reference mode in natural language references
    1869           0 :         ::set_flag( rXclPos.mnCol, EXC_TOK_NLR_REL );
    1870             :     }
    1871             :     else
    1872             :     {
    1873        2768 :         sal_uInt16 rnRelRow = rXclPos.mnRow;
    1874        2768 :         sal_uInt16& rnRelField = (meBiff <= EXC_BIFF5) ? rnRelRow : rXclPos.mnCol;
    1875        2768 :         ::set_flag( rnRelField, EXC_TOK_REF_COLREL, rRefData.IsColRel() );
    1876        2768 :         ::set_flag( rnRelField, EXC_TOK_REF_ROWREL, rRefData.IsRowRel() );
    1877             :     }
    1878        2768 : }
    1879             : 
    1880         560 : void XclExpFmlaCompImpl::ConvertRefData(
    1881             :         ScComplexRefData& rRefData, XclRange& rXclRange, bool bNatLangRef ) const
    1882             : {
    1883             :     // convert start and end of the range
    1884         560 :     ConvertRefData( rRefData.Ref1, rXclRange.maFirst, bNatLangRef, false, false );
    1885         560 :     bool bTruncMaxCol = !rRefData.Ref1.IsColDeleted() && (rXclRange.maFirst.mnCol == 0);
    1886         560 :     bool bTruncMaxRow = !rRefData.Ref1.IsRowDeleted() && (rXclRange.maFirst.mnRow == 0);
    1887         560 :     ConvertRefData( rRefData.Ref2, rXclRange.maLast, bNatLangRef, bTruncMaxCol, bTruncMaxRow );
    1888         560 : }
    1889             : 
    1890         132 : XclExpRefLogEntry* XclExpFmlaCompImpl::GetNewRefLogEntry()
    1891             : {
    1892         132 :     if( mxData->mpRefLog )
    1893             :     {
    1894           0 :         mxData->mpRefLog->resize( mxData->mpRefLog->size() + 1 );
    1895           0 :         return &mxData->mpRefLog->back();
    1896             :     }
    1897         132 :     return 0;
    1898             : }
    1899             : 
    1900        1646 : void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData )
    1901             : {
    1902             :     // get the Excel address components, adjust internal data in aRefData
    1903        1646 :     bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
    1904        1646 :     ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
    1905        1646 :     XclAddress aXclPos( ScAddress::UNINITIALIZED );
    1906        1646 :     ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false );
    1907             : 
    1908        1646 :     if( bNatLangRef )
    1909             :     {
    1910             :         OSL_ENSURE( aRefData.IsColRel() != aRefData.IsRowRel(),
    1911             :             "XclExpFmlaCompImpl::ProcessCellRef - broken natural language reference" );
    1912             :         // create tNlr token for natural language reference
    1913           0 :         sal_uInt8 nSubId = aRefData.IsColRel() ? EXC_TOK_NLR_COLV : EXC_TOK_NLR_ROWV;
    1914           0 :         AppendOperandTokenId( EXC_TOKID_NLR, rTokData.mnSpaces );
    1915           0 :         Append( nSubId );
    1916           0 :         AppendAddress( aXclPos );
    1917             :     }
    1918             :     else
    1919             :     {
    1920             :         // store external cell contents in CRN records
    1921        1646 :         if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
    1922        1120 :             mxData->mpLinkMgr->StoreCell(aRefData, *mxData->mpScBasePos);
    1923             : 
    1924             :         // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
    1925        1646 :         if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != 0))
    1926             :         {
    1927             :             // 2D reference (not in defined names, but allowed in range lists)
    1928        2060 :             sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_REFN :
    1929        2608 :                 (lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR : EXC_TOKID_REF);
    1930        1556 :             AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    1931        1556 :             AppendAddress( aXclPos );
    1932             :         }
    1933          90 :         else if( mxData->mpLinkMgr )    // 3D reference
    1934             :         {
    1935             :             // 1-based EXTERNSHEET index and 0-based Excel sheet index
    1936             :             sal_uInt16 nExtSheet, nXclTab;
    1937          90 :             mxData->mpLinkMgr->FindExtSheet( nExtSheet, nXclTab, GetScTab( aRefData ), GetNewRefLogEntry() );
    1938             :             // write the token
    1939          90 :             sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
    1940          90 :             AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    1941          90 :             Append( nExtSheet );
    1942          90 :             if( meBiff <= EXC_BIFF5 )
    1943             :             {
    1944           0 :                 Append( 0, 8 );
    1945           0 :                 Append( nXclTab );
    1946           0 :                 Append( nXclTab );
    1947             :             }
    1948          90 :             AppendAddress( aXclPos );
    1949             :         }
    1950             :         else
    1951             :         {
    1952             :             // 3D ref in cond. format, or 2D ref in name
    1953           0 :             AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    1954             :         }
    1955             :     }
    1956        1646 : }
    1957             : 
    1958         560 : void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData )
    1959             : {
    1960             :     // get the Excel address components, adjust internal data in aRefData
    1961         560 :     ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
    1962         560 :     XclRange aXclRange( ScAddress::UNINITIALIZED );
    1963         560 :     ConvertRefData( aRefData, aXclRange, false );
    1964             : 
    1965             :     // store external cell contents in CRN records
    1966         560 :     if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
    1967         360 :         mxData->mpLinkMgr->StoreCellRange(aRefData, *mxData->mpScBasePos);
    1968             : 
    1969             :     // create the tArea, tAreaErr, tAreaN, tArea3d, or tAreaErr3d token
    1970         560 :     if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != 0))
    1971             :     {
    1972             :         // 2D reference (not in name formulas, but allowed in range lists)
    1973         688 :         sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_AREAN :
    1974        1040 :              (lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR : EXC_TOKID_AREA);
    1975         520 :         AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    1976         520 :         AppendRange( aXclRange );
    1977             :     }
    1978          40 :     else if( mxData->mpLinkMgr )    // 3D reference
    1979             :     {
    1980             :         // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
    1981             :         sal_uInt16 nExtSheet, nFirstXclTab, nLastXclTab;
    1982          40 :         mxData->mpLinkMgr->FindExtSheet( nExtSheet, nFirstXclTab, nLastXclTab,
    1983          80 :             GetScTab( aRefData.Ref1 ), GetScTab( aRefData.Ref2 ), GetNewRefLogEntry() );
    1984             :         // write the token
    1985          40 :         sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
    1986          40 :         AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    1987          40 :         Append( nExtSheet );
    1988          40 :         if( meBiff <= EXC_BIFF5 )
    1989             :         {
    1990           0 :             Append( 0, 8 );
    1991           0 :             Append( nFirstXclTab );
    1992           0 :             Append( nLastXclTab );
    1993             :         }
    1994          40 :         AppendRange( aXclRange );
    1995             :     }
    1996             :     else
    1997             :     {
    1998             :         // 3D ref in cond. format, or 2D ref in name
    1999           0 :         AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    2000             :     }
    2001         560 : }
    2002             : 
    2003           2 : void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData )
    2004             : {
    2005           2 :     if( mxData->mpLinkMgr )
    2006             :     {
    2007             :         // get the Excel address components, adjust internal data in aRefData
    2008           2 :         ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
    2009           2 :         XclAddress aXclPos( ScAddress::UNINITIALIZED );
    2010           2 :         ConvertRefData( aRefData, aXclPos, false, false, false );
    2011             : 
    2012             :         // store external cell contents in CRN records
    2013           2 :         sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
    2014           2 :         OUString aTabName = rTokData.mpScToken->GetString().getString();
    2015           2 :         if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
    2016           2 :             mxData->mpLinkMgr->StoreCell(nFileId, aTabName, aRefData.toAbs(*mxData->mpScBasePos));
    2017             : 
    2018             :         // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
    2019             :         sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
    2020           2 :         mxData->mpLinkMgr->FindExtSheet( nFileId, aTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
    2021             :         // write the token
    2022           2 :         sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
    2023           2 :         AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    2024           2 :         Append( nExtSheet );
    2025           2 :         if( meBiff <= EXC_BIFF5 )
    2026             :         {
    2027           0 :             Append( 0, 8 );
    2028           0 :             Append( nFirstSBTab );
    2029           0 :             Append( nLastSBTab );
    2030             :         }
    2031           2 :         AppendAddress( aXclPos );
    2032             :     }
    2033             :     else
    2034             :     {
    2035           0 :         AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    2036             :     }
    2037           2 : }
    2038             : 
    2039           0 : void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData )
    2040             : {
    2041           0 :     if( mxData->mpLinkMgr )
    2042             :     {
    2043             :         // get the Excel address components, adjust internal data in aRefData
    2044           0 :         ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
    2045           0 :         XclRange aXclRange( ScAddress::UNINITIALIZED );
    2046           0 :         ConvertRefData( aRefData, aXclRange, false );
    2047             : 
    2048             :         // store external cell contents in CRN records
    2049           0 :         sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
    2050           0 :         OUString aTabName = rTokData.mpScToken->GetString().getString();
    2051           0 :         if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
    2052           0 :             mxData->mpLinkMgr->StoreCellRange(nFileId, aTabName, aRefData.toAbs(*mxData->mpScBasePos));
    2053             : 
    2054             :         // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
    2055             :         sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
    2056           0 :         sal_uInt16 nTabSpan = static_cast<sal_uInt16>(aRefData.Ref2.Tab() - aRefData.Ref1.Tab() + 1);
    2057           0 :         mxData->mpLinkMgr->FindExtSheet(
    2058           0 :             nFileId, aTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry());
    2059             :         // write the token
    2060           0 :         sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
    2061           0 :         AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
    2062           0 :         Append( nExtSheet );
    2063           0 :         if( meBiff <= EXC_BIFF5 )
    2064             :         {
    2065           0 :             Append( 0, 8 );
    2066           0 :             Append( nFirstSBTab );
    2067           0 :             Append( nLastSBTab );
    2068             :         }
    2069           0 :         AppendRange( aXclRange );
    2070             :     }
    2071             :     else
    2072             :     {
    2073           0 :         AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    2074             :     }
    2075           0 : }
    2076             : 
    2077           0 : void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
    2078             : {
    2079           0 :     SCTAB nTab = SCTAB_GLOBAL;
    2080           0 :     bool bGlobal = rTokData.mpScToken->IsGlobal();
    2081           0 :     if (!bGlobal && mxData->mpScBasePos)
    2082           0 :         nTab = mxData->mpScBasePos->Tab();
    2083             : 
    2084           0 :     XclExpNameManager& rNameMgr = GetNameManager();
    2085           0 :     sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex());
    2086           0 :     if( nNameIdx != 0 )
    2087             :     {
    2088             :         // global names always with tName token, local names dependent on config
    2089           0 :         SCTAB nScTab = rNameMgr.GetScTab( nNameIdx );
    2090           0 :         if( (nScTab == SCTAB_GLOBAL) || (!mxData->mrCfg.mb3DRefOnly && (nScTab == GetCurrScTab())) )
    2091             :         {
    2092           0 :             AppendNameToken( nNameIdx, rTokData.mnSpaces );
    2093             :         }
    2094           0 :         else if( mxData->mpLinkMgr )
    2095             :         {
    2096             :             // use the same special EXTERNNAME to refer to any local name
    2097           0 :             sal_uInt16 nExtSheet = mxData->mpLinkMgr->FindExtSheet( EXC_EXTSH_OWNDOC );
    2098           0 :             AppendNameXToken( nExtSheet, nNameIdx, rTokData.mnSpaces );
    2099             :         }
    2100             :         else
    2101           0 :             AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
    2102             :         // volatile names (containing volatile functions)
    2103           0 :         mxData->mbVolatile |= rNameMgr.IsVolatile( nNameIdx );
    2104             :     }
    2105             :     else
    2106           0 :         AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
    2107           0 : }
    2108             : 
    2109           0 : void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
    2110             : {
    2111           0 :     if( mxData->mpLinkMgr )
    2112             :     {
    2113           0 :         ScExternalRefManager& rExtRefMgr = *GetDoc().GetExternalRefManager();
    2114           0 :         sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
    2115           0 :         OUString aName = rTokData.mpScToken->GetString().getString();
    2116           0 :         ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, aName );
    2117           0 :         if( xArray.get() )
    2118             :         {
    2119             :             // store external cell contents in CRN records
    2120           0 :             if( mxData->mpScBasePos )
    2121             :             {
    2122           0 :                 for( FormulaToken* pScToken = xArray->First(); pScToken; pScToken = xArray->Next() )
    2123             :                 {
    2124           0 :                     if( pScToken->IsExternalRef() )
    2125             :                     {
    2126           0 :                         switch( pScToken->GetType() )
    2127             :                         {
    2128             :                             case svExternalSingleRef:
    2129             :                             {
    2130           0 :                                 ScSingleRefData aRefData = *pScToken->GetSingleRef();
    2131           0 :                                 mxData->mpLinkMgr->StoreCell(
    2132           0 :                                     nFileId, pScToken->GetString().getString(), aRefData.toAbs(*mxData->mpScBasePos));
    2133             :                             }
    2134           0 :                             break;
    2135             :                             case svExternalDoubleRef:
    2136             :                             {
    2137           0 :                                 ScComplexRefData aRefData = *pScToken->GetDoubleRef();
    2138           0 :                                 mxData->mpLinkMgr->StoreCellRange(
    2139           0 :                                     nFileId, pScToken->GetString().getString(), aRefData.toAbs(*mxData->mpScBasePos));
    2140             :                             }
    2141             :                             default:
    2142             :                                 ;   // nothing, avoid compiler warning
    2143             :                         }
    2144             :                     }
    2145             :                 }
    2146             :             }
    2147             : 
    2148             :             // insert the new external name and create the tNameX token
    2149           0 :             sal_uInt16 nExtSheet = 0, nExtName = 0;
    2150           0 :             const OUString* pFile = rExtRefMgr.getExternalFileName( nFileId );
    2151           0 :             if( pFile && mxData->mpLinkMgr->InsertExtName( nExtSheet, nExtName, *pFile, aName, xArray ) )
    2152             :             {
    2153           0 :                 AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
    2154           0 :                 return;
    2155             :             }
    2156           0 :         }
    2157             :     }
    2158             : 
    2159             :     // on any error: create a #NAME? error
    2160           0 :     AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
    2161             : }
    2162             : 
    2163             : // token vector ---------------------------------------------------------------
    2164             : 
    2165        5402 : void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos )
    2166             : {
    2167        5402 :     mxData->maOpPosStack.push_back( nTokPos );
    2168        5402 : }
    2169             : 
    2170        1020 : void XclExpFmlaCompImpl::PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands )
    2171             : {
    2172        1020 :     PushOperandPos( nTokPos );
    2173             :     OSL_ENSURE( rxOperands.get(), "XclExpFmlaCompImpl::AppendOperatorTokenId - missing operand list" );
    2174        1020 :     if( mxData->maOpListVec.size() <= nTokPos )
    2175        1020 :         mxData->maOpListVec.resize( nTokPos + 1, XclExpOperandListRef() );
    2176        1020 :     mxData->maOpListVec[ nTokPos ] = rxOperands;
    2177        1020 : }
    2178             : 
    2179        4510 : sal_uInt16 XclExpFmlaCompImpl::PopOperandPos()
    2180             : {
    2181             :     OSL_ENSURE( !mxData->mbOk || !mxData->maOpPosStack.empty(), "XclExpFmlaCompImpl::PopOperandPos - token stack broken" );
    2182        4510 :     mxData->mbOk &= !mxData->maOpPosStack.empty();
    2183        4510 :     if( mxData->mbOk )
    2184             :     {
    2185        4510 :         sal_uInt16 nTokPos = mxData->maOpPosStack.back();
    2186        4510 :         mxData->maOpPosStack.pop_back();
    2187        4510 :         return nTokPos;
    2188             :     }
    2189           0 :     return 0;
    2190             : }
    2191             : 
    2192             : namespace {
    2193             : 
    2194        8976 : inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt16 nData )
    2195             : {
    2196        8976 :     orVector.resize( orVector.size() + 2 );
    2197        8976 :     ShortToSVBT16( nData, &*(orVector.end() - 2) );
    2198        8976 : }
    2199             : 
    2200           6 : inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt32 nData )
    2201             : {
    2202           6 :     orVector.resize( orVector.size() + 4 );
    2203           6 :     UInt32ToSVBT32( nData, &*(orVector.end() - 4) );
    2204           6 : }
    2205             : 
    2206          88 : inline void lclAppend( ScfUInt8Vec& orVector, double fData )
    2207             : {
    2208          88 :     orVector.resize( orVector.size() + 8 );
    2209          88 :     DoubleToSVBT64( fData, &*(orVector.end() - 8) );
    2210          88 : }
    2211             : 
    2212           8 : inline void lclAppend( ScfUInt8Vec& orVector, const XclExpRoot& rRoot, const OUString& rString, XclStrFlags nStrFlags )
    2213             : {
    2214           8 :     XclExpStringRef xXclStr = XclExpStringHelper::CreateString( rRoot, rString, nStrFlags, EXC_TOK_STR_MAXLEN );
    2215           8 :     size_t nSize = orVector.size();
    2216           8 :     orVector.resize( nSize + xXclStr->GetSize() );
    2217           8 :     xXclStr->WriteToMem( &orVector[ nSize ] );
    2218           8 : }
    2219             : 
    2220             : } // namespace
    2221             : 
    2222        8160 : void XclExpFmlaCompImpl::Append( sal_uInt8 nData )
    2223             : {
    2224        8160 :     mxData->maTokVec.push_back( nData );
    2225        8160 : }
    2226             : 
    2227         352 : void XclExpFmlaCompImpl::Append( sal_uInt8 nData, size_t nCount )
    2228             : {
    2229         352 :     mxData->maTokVec.resize( mxData->maTokVec.size() + nCount, nData );
    2230         352 : }
    2231             : 
    2232        8970 : void XclExpFmlaCompImpl::Append( sal_uInt16 nData )
    2233             : {
    2234        8970 :     lclAppend( mxData->maTokVec, nData );
    2235        8970 : }
    2236             : 
    2237           6 : void XclExpFmlaCompImpl::Append( sal_uInt32 nData )
    2238             : {
    2239           6 :     lclAppend( mxData->maTokVec, nData );
    2240           6 : }
    2241             : 
    2242          56 : void XclExpFmlaCompImpl::Append( double fData )
    2243             : {
    2244          56 :     lclAppend( mxData->maTokVec, fData );
    2245          56 : }
    2246             : 
    2247           8 : void XclExpFmlaCompImpl::Append( const OUString& rString )
    2248             : {
    2249           8 :     lclAppend( mxData->maTokVec, GetRoot(), rString, EXC_STR_8BITLENGTH );
    2250           8 : }
    2251             : 
    2252        1648 : void XclExpFmlaCompImpl::AppendAddress( const XclAddress& rXclPos )
    2253             : {
    2254        1648 :     Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
    2255        1648 :     if( meBiff <= EXC_BIFF5 )
    2256           0 :         Append( static_cast< sal_uInt8 >( rXclPos.mnCol ) );
    2257             :     else
    2258        1648 :         Append( rXclPos.mnCol );
    2259        1648 : }
    2260             : 
    2261         560 : void XclExpFmlaCompImpl::AppendRange( const XclRange& rXclRange )
    2262             : {
    2263         560 :     Append( static_cast<sal_uInt16>(rXclRange.maFirst.mnRow) );
    2264         560 :     Append( static_cast<sal_uInt16>(rXclRange.maLast.mnRow) );
    2265         560 :     if( meBiff <= EXC_BIFF5 )
    2266             :     {
    2267           0 :         Append( static_cast< sal_uInt8 >( rXclRange.maFirst.mnCol ) );
    2268           0 :         Append( static_cast< sal_uInt8 >( rXclRange.maLast.mnCol ) );
    2269             :     }
    2270             :     else
    2271             :     {
    2272         560 :         Append( rXclRange.maFirst.mnCol );
    2273         560 :         Append( rXclRange.maLast.mnCol );
    2274             :     }
    2275         560 : }
    2276             : 
    2277        7202 : void XclExpFmlaCompImpl::AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount )
    2278             : {
    2279        7202 :     if( nCount > 0 )
    2280             :     {
    2281         384 :         Append( EXC_TOKID_ATTR );
    2282         384 :         Append( EXC_TOK_ATTR_SPACE );
    2283         384 :         Append( nType );
    2284         384 :         Append( nCount );
    2285             :     }
    2286        7202 : }
    2287             : 
    2288        4382 : void XclExpFmlaCompImpl::AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
    2289             : {
    2290        4382 :     AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
    2291        4382 :     PushOperandPos( GetSize() );
    2292        4382 :     Append( nTokenId );
    2293        4382 : }
    2294             : 
    2295         500 : void XclExpFmlaCompImpl::AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces )
    2296             : {
    2297         500 :     AppendOperandTokenId( EXC_TOKID_INT, nSpaces );
    2298         500 :     Append( nValue );
    2299         500 : }
    2300             : 
    2301          56 : void XclExpFmlaCompImpl::AppendNumToken( double fValue, sal_uInt8 nSpaces )
    2302             : {
    2303          56 :     AppendOperandTokenId( EXC_TOKID_NUM, nSpaces );
    2304          56 :     Append( fValue );
    2305          56 : }
    2306             : 
    2307           4 : void XclExpFmlaCompImpl::AppendBoolToken( bool bValue, sal_uInt8 nSpaces )
    2308             : {
    2309           4 :     AppendOperandTokenId( EXC_TOKID_BOOL, nSpaces );
    2310           4 :     Append( bValue ? EXC_TOK_BOOL_TRUE : EXC_TOK_BOOL_FALSE );
    2311           4 : }
    2312             : 
    2313         472 : void XclExpFmlaCompImpl::AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces )
    2314             : {
    2315         472 :     AppendOperandTokenId( EXC_TOKID_ERR, nSpaces );
    2316         472 :     Append( nErrCode );
    2317         472 : }
    2318             : 
    2319           4 : void XclExpFmlaCompImpl::AppendMissingToken( sal_uInt8 nSpaces )
    2320             : {
    2321           4 :     AppendOperandTokenId( EXC_TOKID_MISSARG, nSpaces );
    2322           4 : }
    2323             : 
    2324         704 : void XclExpFmlaCompImpl::AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces )
    2325             : {
    2326         704 :     if( nNameIdx > 0 )
    2327             :     {
    2328         352 :         AppendOperandTokenId( GetTokenId( EXC_TOKID_NAME, EXC_TOKCLASS_REF ), nSpaces );
    2329         352 :         Append( nNameIdx );
    2330         352 :         Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
    2331             :     }
    2332             :     else
    2333         352 :         AppendErrorToken( EXC_ERR_NAME );
    2334         704 : }
    2335             : 
    2336           0 : void XclExpFmlaCompImpl::AppendMissingNameToken( const OUString& rName, sal_uInt8 nSpaces )
    2337             : {
    2338           0 :     sal_uInt16 nNameIdx = GetNameManager().InsertRawName( rName );
    2339           0 :     AppendNameToken( nNameIdx, nSpaces );
    2340           0 : }
    2341             : 
    2342           0 : void XclExpFmlaCompImpl::AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces )
    2343             : {
    2344           0 :     AppendOperandTokenId( GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), nSpaces );
    2345           0 :     Append( nExtSheet );
    2346           0 :     if( meBiff <= EXC_BIFF5 )
    2347           0 :         Append( 0, 8 );
    2348           0 :     Append( nExtName );
    2349           0 :     Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
    2350           0 : }
    2351             : 
    2352         352 : void XclExpFmlaCompImpl::AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
    2353             : {
    2354         352 :     sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rExtFuncData.maFuncName, rExtFuncData.mbVBasic, true, rExtFuncData.mbHidden );
    2355         352 :     AppendNameToken( nNameIdx, nSpaces );
    2356         352 : }
    2357             : 
    2358           0 : void XclExpFmlaCompImpl::AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
    2359             : {
    2360           0 :     OUString aXclFuncName;
    2361           0 :     if( mxData->mpLinkMgr && ScGlobal::GetAddInCollection()->GetExcelName( rExtFuncData.maFuncName, GetUILanguage(), aXclFuncName ) )
    2362             :     {
    2363             :         sal_uInt16 nExtSheet, nExtName;
    2364           0 :         if( mxData->mpLinkMgr->InsertAddIn( nExtSheet, nExtName, aXclFuncName ) )
    2365             :         {
    2366           0 :             AppendNameXToken( nExtSheet, nExtName, nSpaces );
    2367           0 :             return;
    2368             :         }
    2369             :     }
    2370           0 :     AppendMacroCallToken( rExtFuncData, nSpaces );
    2371             : }
    2372             : 
    2373           0 : void XclExpFmlaCompImpl::AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
    2374             : {
    2375           0 :     sal_uInt16 nExtSheet(0), nExtName(0);
    2376           0 :     if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
    2377           0 :         AppendNameXToken( nExtSheet, nExtName, nSpaces );
    2378             :     else
    2379           0 :         AppendMacroCallToken( rExtFuncData, nSpaces );
    2380           0 : }
    2381             : 
    2382        1020 : void XclExpFmlaCompImpl::AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces )
    2383             : {
    2384        1020 :     AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
    2385        1020 :     PushOperatorPos( GetSize(), rxOperands );
    2386        1020 :     Append( nTokenId );
    2387        1020 : }
    2388             : 
    2389           0 : void XclExpFmlaCompImpl::AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
    2390             : {
    2391           0 :     XclExpOperandListRef xOperands( new XclExpOperandList );
    2392           0 :     xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, true );
    2393           0 :     AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
    2394           0 : }
    2395             : 
    2396         120 : void XclExpFmlaCompImpl::AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces )
    2397             : {
    2398         120 :     XclExpOperandListRef xOperands( new XclExpOperandList );
    2399         120 :     xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
    2400         120 :     xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
    2401         120 :     AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
    2402         120 : }
    2403             : 
    2404           0 : void XclExpFmlaCompImpl::AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount )
    2405             : {
    2406           0 :     XclExpOperandListRef xOperands( new XclExpOperandList );
    2407           0 :     for( sal_uInt8 nOpIdx = 0; nOpIdx < nOpCount; ++nOpIdx  )
    2408           0 :         xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPX, false );
    2409           0 :     AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, EXC_TOKCLASS_VAL ), xOperands );
    2410           0 :     Append( nOpCount );
    2411           0 :     Append( nXclFuncIdx );
    2412           0 : }
    2413             : 
    2414         900 : void XclExpFmlaCompImpl::AppendFuncToken( const XclExpFuncData& rFuncData )
    2415             : {
    2416         900 :     sal_uInt16 nXclFuncIdx = rFuncData.GetXclFuncIdx();
    2417         900 :     sal_uInt8 nParamCount = rFuncData.GetParamCount();
    2418         900 :     sal_uInt8 nRetClass = rFuncData.GetReturnClass();
    2419             : 
    2420         900 :     if( (nXclFuncIdx == EXC_FUNCID_SUM) && (nParamCount == 1) )
    2421             :     {
    2422             :         // SUM with only one parameter
    2423           4 :         AppendOperatorTokenId( EXC_TOKID_ATTR, rFuncData.GetOperandList() );
    2424           4 :         Append( EXC_TOK_ATTR_SUM );
    2425           4 :         Append( sal_uInt16( 0 ) );
    2426             :     }
    2427         896 :     else if( rFuncData.IsFixedParamCount() )
    2428             :     {
    2429             :         // fixed number of parameters
    2430         160 :         AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNC, nRetClass ), rFuncData.GetOperandList() );
    2431         160 :         Append( nXclFuncIdx );
    2432             :     }
    2433             :     else
    2434             :     {
    2435             :         // variable number of parameters
    2436         736 :         AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, nRetClass ), rFuncData.GetOperandList() );
    2437         736 :         Append( nParamCount );
    2438         736 :         Append( nXclFuncIdx );
    2439             :     }
    2440         900 : }
    2441             : 
    2442           0 : void XclExpFmlaCompImpl::AppendParenToken( sal_uInt8 nOpenSpaces, sal_uInt8 nCloseSpaces )
    2443             : {
    2444           0 :     AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_OPEN, nOpenSpaces );
    2445           0 :     AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
    2446           0 :     Append( EXC_TOKID_PAREN );
    2447           0 : }
    2448             : 
    2449           0 : void XclExpFmlaCompImpl::AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType )
    2450             : {
    2451             :     // store the start position of the token
    2452           0 :     rFuncData.AppendAttrPos( GetSize() );
    2453             :     // create the tAttr token
    2454           0 :     Append( EXC_TOKID_ATTR );
    2455           0 :     Append( nAttrType );
    2456           0 :     Append( sal_uInt16( 0 ) );  // placeholder that will be updated later
    2457           0 : }
    2458             : 
    2459           0 : void XclExpFmlaCompImpl::InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize )
    2460             : {
    2461             :     // insert zeros into the token array
    2462             :     OSL_ENSURE( nInsertPos < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Insert - invalid position" );
    2463           0 :     mxData->maTokVec.insert( mxData->maTokVec.begin() + nInsertPos, nInsertSize, 0 );
    2464             : 
    2465             :     // update positions of operands waiting for an operator
    2466           0 :     for( ScfUInt16Vec::iterator aIt = mxData->maOpPosStack.begin(), aEnd = mxData->maOpPosStack.end(); aIt != aEnd; ++aIt )
    2467           0 :         if( nInsertPos <= *aIt )
    2468           0 :             *aIt = *aIt + nInsertSize;
    2469             : 
    2470             :     // update operand lists of all operator tokens
    2471           0 :     if( nInsertPos < mxData->maOpListVec.size() )
    2472           0 :         mxData->maOpListVec.insert( mxData->maOpListVec.begin() + nInsertPos, nInsertSize, XclExpOperandListRef() );
    2473           0 :     for( XclExpOperandListVector::iterator aIt = mxData->maOpListVec.begin(), aEnd = mxData->maOpListVec.end(); aIt != aEnd; ++aIt )
    2474           0 :         if( aIt->get() )
    2475           0 :             for( XclExpOperandList::iterator aIt2 = (*aIt)->begin(), aEnd2 = (*aIt)->end(); aIt2 != aEnd2; ++aIt2 )
    2476           0 :                 if( nInsertPos <= aIt2->mnTokPos )
    2477           0 :                     aIt2->mnTokPos = aIt2->mnTokPos + nInsertSize;
    2478           0 : }
    2479             : 
    2480           0 : void XclExpFmlaCompImpl::Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset )
    2481             : {
    2482             :     OSL_ENSURE( static_cast< size_t >( nWriteToPos + 1 ) < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Overwrite - invalid position" );
    2483           0 :     ShortToSVBT16( nOffset, &mxData->maTokVec[ nWriteToPos ] );
    2484           0 : }
    2485             : 
    2486           0 : void XclExpFmlaCompImpl::UpdateAttrGoto( sal_uInt16 nAttrPos )
    2487             : {
    2488             :     /*  tAttrGoto contains distance from end of tAttr token to position behind
    2489             :         the function token (for IF or CHOOSE function), which is currently at
    2490             :         the end of the token array. Additionally this distance is decreased by
    2491             :         one, for whatever reason. So we have to subtract 4 and 1 from the
    2492             :         distance between the tAttr token start and the end of the token array. */
    2493           0 :     Overwrite( nAttrPos + 2, static_cast< sal_uInt16 >( GetSize() - nAttrPos - 5 ) );
    2494           0 : }
    2495             : 
    2496           0 : bool XclExpFmlaCompImpl::IsSpaceToken( sal_uInt16 nPos ) const
    2497             : {
    2498             :     return
    2499           0 :         (static_cast< size_t >( nPos + 4 ) <= mxData->maTokVec.size()) &&
    2500           0 :         (mxData->maTokVec[ nPos ] == EXC_TOKID_ATTR) &&
    2501           0 :         (mxData->maTokVec[ nPos + 1 ] == EXC_TOK_ATTR_SPACE);
    2502             : }
    2503             : 
    2504           0 : void XclExpFmlaCompImpl::RemoveTrailingParen()
    2505             : {
    2506             :     // remove trailing tParen token
    2507           0 :     if( !mxData->maTokVec.empty() && (mxData->maTokVec.back() == EXC_TOKID_PAREN) )
    2508           0 :         mxData->maTokVec.pop_back();
    2509             :     // remove remaining tAttrSpace tokens
    2510           0 :     while( (mxData->maTokVec.size() >= 4) && IsSpaceToken( GetSize() - 4 ) )
    2511           0 :         mxData->maTokVec.erase( mxData->maTokVec.end() - 4, mxData->maTokVec.end() );
    2512           0 : }
    2513             : 
    2514          38 : void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData )
    2515             : {
    2516          38 :     mxData->maExtDataVec.push_back( nData );
    2517          38 : }
    2518             : 
    2519           0 : void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData, size_t nCount )
    2520             : {
    2521           0 :     mxData->maExtDataVec.resize( mxData->maExtDataVec.size() + nCount, nData );
    2522           0 : }
    2523             : 
    2524           6 : void XclExpFmlaCompImpl::AppendExt( sal_uInt16 nData )
    2525             : {
    2526           6 :     lclAppend( mxData->maExtDataVec, nData );
    2527           6 : }
    2528             : 
    2529          32 : void XclExpFmlaCompImpl::AppendExt( double fData )
    2530             : {
    2531          32 :     lclAppend( mxData->maExtDataVec, fData );
    2532          32 : }
    2533             : 
    2534           0 : void XclExpFmlaCompImpl::AppendExt( const OUString& rString )
    2535             : {
    2536           0 :     lclAppend( mxData->maExtDataVec, GetRoot(), rString, (meBiff == EXC_BIFF8) ? EXC_STR_DEFAULT : EXC_STR_8BITLENGTH );
    2537           0 : }
    2538             : 
    2539             : namespace {
    2540             : 
    2541           0 : void lclInitOwnTab( ScSingleRefData& rRef, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
    2542             : {
    2543           0 :     if( b3DRefOnly )
    2544             :     {
    2545             :         // no reduction to 2D reference, if global link manager is used
    2546           0 :         rRef.SetFlag3D(true);
    2547             :     }
    2548           0 :     else if( rScPos.Tab() == nCurrScTab )
    2549             :     {
    2550           0 :         rRef.SetRelTab(0);
    2551             :     }
    2552           0 : }
    2553             : 
    2554           0 : void lclPutCellToTokenArray( ScTokenArray& rScTokArr, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
    2555             : {
    2556             :     ScSingleRefData aRef;
    2557           0 :     aRef.InitAddress( rScPos );
    2558           0 :     lclInitOwnTab( aRef, rScPos, nCurrScTab, b3DRefOnly );
    2559           0 :     rScTokArr.AddSingleReference( aRef );
    2560           0 : }
    2561             : 
    2562           0 : void lclPutRangeToTokenArray( ScTokenArray& rScTokArr, const ScRange& rScRange, SCTAB nCurrScTab, bool b3DRefOnly )
    2563             : {
    2564           0 :     if( rScRange.aStart == rScRange.aEnd )
    2565             :     {
    2566           0 :         lclPutCellToTokenArray( rScTokArr, rScRange.aStart, nCurrScTab, b3DRefOnly );
    2567             :     }
    2568             :     else
    2569             :     {
    2570             :         ScComplexRefData aRef;
    2571           0 :         aRef.InitRange( rScRange );
    2572           0 :         lclInitOwnTab( aRef.Ref1, rScRange.aStart, nCurrScTab, b3DRefOnly );
    2573           0 :         lclInitOwnTab( aRef.Ref2, rScRange.aEnd, nCurrScTab, b3DRefOnly );
    2574           0 :         rScTokArr.AddDoubleReference( aRef );
    2575             :     }
    2576           0 : }
    2577             : 
    2578             : } // namespace
    2579             : 
    2580          64 : XclExpFormulaCompiler::XclExpFormulaCompiler( const XclExpRoot& rRoot ) :
    2581             :     XclExpRoot( rRoot ),
    2582          64 :     mxImpl( new XclExpFmlaCompImpl( rRoot ) )
    2583             : {
    2584          64 : }
    2585             : 
    2586         128 : XclExpFormulaCompiler::~XclExpFormulaCompiler()
    2587             : {
    2588         128 : }
    2589             : 
    2590        1006 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula(
    2591             :         XclFormulaType eType, const ScTokenArray& rScTokArr,
    2592             :         const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
    2593             : {
    2594        1006 :     return mxImpl->CreateFormula( eType, rScTokArr, pScBasePos, pRefLog );
    2595             : }
    2596             : 
    2597           0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScAddress& rScPos )
    2598             : {
    2599           0 :     ScTokenArray aScTokArr;
    2600           0 :     lclPutCellToTokenArray( aScTokArr, rScPos, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
    2601           0 :     return mxImpl->CreateFormula( eType, aScTokArr );
    2602             : }
    2603             : 
    2604           0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRange& rScRange )
    2605             : {
    2606           0 :     ScTokenArray aScTokArr;
    2607           0 :     lclPutRangeToTokenArray( aScTokArr, rScRange, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
    2608           0 :     return mxImpl->CreateFormula( eType, aScTokArr );
    2609             : }
    2610             : 
    2611           0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRangeList& rScRanges )
    2612             : {
    2613           0 :     size_t nCount = rScRanges.size();
    2614           0 :     if( nCount == 0 )
    2615           0 :         return XclTokenArrayRef();
    2616             : 
    2617           0 :     ScTokenArray aScTokArr;
    2618           0 :     SCTAB nCurrScTab = GetCurrScTab();
    2619           0 :     bool b3DRefOnly = mxImpl->Is3DRefOnly( eType );
    2620           0 :     for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
    2621             :     {
    2622           0 :         if( nIdx > 0 )
    2623           0 :             aScTokArr.AddOpCode( ocUnion );
    2624           0 :         lclPutRangeToTokenArray( aScTokArr, *rScRanges[ nIdx ], nCurrScTab, b3DRefOnly );
    2625             :     }
    2626           0 :     return mxImpl->CreateFormula( eType, aScTokArr );
    2627             : }
    2628             : 
    2629         120 : XclTokenArrayRef XclExpFormulaCompiler::CreateErrorFormula( sal_uInt8 nErrCode )
    2630             : {
    2631         120 :     return mxImpl->CreateErrorFormula( nErrCode );
    2632             : }
    2633             : 
    2634         772 : XclTokenArrayRef XclExpFormulaCompiler::CreateSpecialRefFormula(
    2635             :         sal_uInt8 nTokenId, const XclAddress& rXclPos )
    2636             : {
    2637         772 :     return mxImpl->CreateSpecialRefFormula( nTokenId, rXclPos );
    2638             : }
    2639             : 
    2640           0 : XclTokenArrayRef XclExpFormulaCompiler::CreateNameXFormula(
    2641             :         sal_uInt16 nExtSheet, sal_uInt16 nExtName )
    2642             : {
    2643           0 :     return mxImpl->CreateNameXFormula( nExtSheet, nExtName );
    2644             : }
    2645             : 
    2646        2992 : bool XclExpFormulaCompiler::IsRef2D( const ScSingleRefData& rRefData ) const
    2647             : {
    2648        2992 :     return mxImpl->IsRef2D(rRefData, true);
    2649             : }
    2650             : 
    2651         476 : bool XclExpFormulaCompiler::IsRef2D( const ScComplexRefData& rRefData ) const
    2652             : {
    2653         476 :     return mxImpl->IsRef2D(rRefData, true);
    2654          48 : }
    2655             : 
    2656             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10