xref: /trunk/main/oox/source/xls/formulaparser.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/xls/formulaparser.hxx"
29 
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/sheet/ComplexReference.hpp>
32 #include <com/sun/star/sheet/ExternalReference.hpp>
33 #include <com/sun/star/sheet/FormulaToken.hpp>
34 #include <com/sun/star/sheet/ReferenceFlags.hpp>
35 #include <com/sun/star/sheet/SingleReference.hpp>
36 #include "oox/core/filterbase.hxx"
37 #include "oox/xls/addressconverter.hxx"
38 #include "oox/xls/biffinputstream.hxx"
39 #include "oox/xls/defnamesbuffer.hxx"
40 #include "oox/xls/externallinkbuffer.hxx"
41 #include "oox/xls/tablebuffer.hxx"
42 #include "oox/xls/worksheethelper.hxx"
43 
44 namespace oox {
45 namespace xls {
46 
47 // ============================================================================
48 
49 using namespace ::com::sun::star::sheet;
50 using namespace ::com::sun::star::sheet::ReferenceFlags;
51 using namespace ::com::sun::star::table;
52 using namespace ::com::sun::star::uno;
53 
54 using ::rtl::OUString;
55 
56 // ============================================================================
57 
58 namespace {
59 
60 sal_uInt16 lclReadFmlaSize( BiffInputStream& rStrm, BiffType eBiff, const sal_uInt16* pnFmlaSize )
61 {
62     return pnFmlaSize ? *pnFmlaSize : ((eBiff == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16());
63 }
64 
65 } // namespace
66 
67 // formula finalizer ==========================================================
68 
69 FormulaFinalizer::FormulaFinalizer( const OpCodeProvider& rOpCodeProv ) :
70     OpCodeProvider( rOpCodeProv ),
71     ApiOpCodes( getOpCodes() )
72 {
73     maTokens.reserve( 0x2000 );
74 }
75 
76 ApiTokenSequence FormulaFinalizer::finalizeTokenArray( const ApiTokenSequence& rTokens )
77 {
78     maTokens.clear();
79     if( rTokens.hasElements() )
80     {
81         const ApiToken* pToken = rTokens.getConstArray();
82         processTokens( pToken, pToken + rTokens.getLength() );
83     }
84     return ContainerHelper::vectorToSequence( maTokens );
85 }
86 
87 const FunctionInfo* FormulaFinalizer::resolveBadFuncName( const OUString& ) const
88 {
89     return 0;
90 }
91 
92 OUString FormulaFinalizer::resolveDefinedName( sal_Int32 ) const
93 {
94     return OUString();
95 }
96 
97 const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken )
98 {
99     // first, try to find a regular function info from token op-code
100     if( const FunctionInfo* pRegFuncInfo = getFuncInfoFromApiToken( orFuncToken ) )
101         return pRegFuncInfo;
102 
103     // try to recognize a function from an external library
104     if( (orFuncToken.OpCode == OPCODE_BAD) && orFuncToken.Data.has< OUString >() )
105     {
106         // virtual call to resolveBadFuncName()
107         if( const FunctionInfo* pLibFuncInfo = resolveBadFuncName( orFuncToken.Data.get< OUString >() ) )
108         {
109             // write function op-code to the OPCODE_BAD token
110             orFuncToken.OpCode = pLibFuncInfo->mnApiOpCode;
111             // if it is an external function, insert programmatic function name
112             if( (orFuncToken.OpCode == OPCODE_EXTERNAL) && (pLibFuncInfo->maExtProgName.getLength() > 0) )
113                 orFuncToken.Data <<= pLibFuncInfo->maExtProgName;
114             else
115                 orFuncToken.Data.clear();   // clear string from OPCODE_BAD
116             return pLibFuncInfo;
117         }
118     }
119 
120     // no success - return null
121     return 0;
122 }
123 
124 const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken )
125 {
126     // try to resolve the passed token to a supported sheet function
127     if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( rECToken ) )
128     {
129         orFuncToken.OpCode = pFuncInfo->mnApiOpCode;
130         // programmatic add-in function name
131         if( (pFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) )
132             orFuncToken.Data <<= pFuncInfo->maExtProgName;
133         // name of unsupported function, convert to OPCODE_BAD to preserve the name
134         else if( (pFuncInfo->mnApiOpCode == OPCODE_BAD) && (pFuncInfo->maOoxFuncName.getLength() > 0) )
135             orFuncToken.Data <<= pFuncInfo->maOoxFuncName;
136         return pFuncInfo;
137     }
138 
139     // macro call or unknown function name, move data to function token
140     if( (rECToken.OpCode == OPCODE_MACRO) || (rECToken.OpCode == OPCODE_BAD) )
141         orFuncToken = rECToken;
142 
143     // defined name used as function call, convert to OPCODE_BAD to preserve the name
144     if( (rECToken.OpCode == OPCODE_NAME) && rECToken.Data.has< sal_Int32 >() )
145     {
146         OUString aDefName = resolveDefinedName( rECToken.Data.get< sal_Int32 >() );
147         if( aDefName.getLength() > 0 )
148         {
149             orFuncToken.OpCode = OPCODE_BAD;
150             orFuncToken.Data <<= aDefName;
151         }
152     }
153 
154     return 0;
155 }
156 
157 void FormulaFinalizer::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd )
158 {
159     while( pToken < pTokenEnd )
160     {
161         // push the current token into the vector
162         bool bValid = appendFinalToken( *pToken );
163         // try to process a function
164         if( const FunctionInfo* pFuncInfo = bValid ? getFunctionInfo( maTokens.back() ) : 0 )
165             pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd );
166         // otherwise, go to next token
167         else
168             ++pToken;
169     }
170 }
171 
172 const ApiToken* FormulaFinalizer::processParameters(
173         const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd )
174 {
175     // remember position of the token containing the function op-code
176     size_t nFuncNameIdx = maTokens.size() - 1;
177 
178     // process a function, if an OPCODE_OPEN token is following
179     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::processParameters - OPCODE_OPEN expected" );
180     if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN) )
181     {
182         // append the OPCODE_OPEN token to the vector
183         maTokens.append( OPCODE_OPEN );
184 
185         // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE
186         ParameterPosVector aParams;
187         pToken = findParameters( aParams, pToken, pTokenEnd );
188         OSL_ENSURE( aParams.size() >= 2, "FormulaFinalizer::processParameters - missing tokens" );
189         size_t nParamCount = aParams.size() - 1;
190 
191         if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) )
192         {
193             /*  Empty pair of parentheses -> function call without parameters,
194                 process parameter, there might be spaces between parentheses. */
195             processTokens( aParams[ 0 ] + 1, aParams[ 1 ] );
196         }
197         else
198         {
199             const FunctionInfo* pRealFuncInfo = &rFuncInfo;
200             ParameterPosVector::const_iterator aPosIt = aParams.begin();
201 
202             /*  Preprocess EXTERN.CALL functions. The actual function name is
203                 contained as reference to a defined name in the first (hidden)
204                 parameter. */
205             if( rFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL )
206             {
207                 ApiToken& rFuncToken = maTokens[ nFuncNameIdx ];
208                 rFuncToken.OpCode = OPCODE_NONAME;
209 
210                 // try to initialize function token from first parameter
211                 if( const ApiToken* pECToken = getSingleToken( *aPosIt + 1, *(aPosIt + 1) ) )
212                     if( const FunctionInfo* pECFuncInfo = getExternCallInfo( rFuncToken, *pECToken ) )
213                         pRealFuncInfo = pECFuncInfo;
214 
215                 /*  On success (something has been inserted into rFuncToken),
216                     skip the first parameter. */
217                 if( rFuncToken.OpCode != OPCODE_NONAME )
218                 {
219                     --nParamCount;
220                     ++aPosIt;
221                 }
222             }
223 
224             // process all parameters
225             FunctionParamInfoIterator aParamInfoIt( *pRealFuncInfo );
226             size_t nLastValidSize = maTokens.size();
227             size_t nLastValidCount = 0;
228             for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aParamInfoIt )
229             {
230                 // add embedded Calc-only parameters
231                 if( aParamInfoIt.isCalcOnlyParam() )
232                 {
233                     appendCalcOnlyParameter( *pRealFuncInfo, nParam );
234                     while( aParamInfoIt.isCalcOnlyParam() ) ++aParamInfoIt;
235                 }
236 
237                 const ApiToken* pParamBegin = *aPosIt + 1;
238                 const ApiToken* pParamEnd = *(aPosIt + 1);
239                 bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd );
240 
241                 if( !aParamInfoIt.isExcelOnlyParam() )
242                 {
243                     // handle empty parameters
244                     if( bIsEmpty )
245                     {
246                         // append leading space tokens from original token array
247                         while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
248                             maTokens.push_back( *pParamBegin++ );
249                         // add default values for some empty parameters, or the OPCODE_MISSING token
250                         appendEmptyParameter( *pRealFuncInfo, nParam );
251                         // reset bIsEmpty flag, if something has been appended in appendEmptyParameter()
252                         bIsEmpty = maTokens.back().OpCode == OPCODE_MISSING;
253                         // skip OPCODE_MISSING token in the original token array
254                         OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode == OPCODE_MISSING), "FormulaFinalizer::processParameters - OPCODE_MISSING expected" );
255                         if( pParamBegin < pParamEnd ) ++pParamBegin;
256                         // append trailing space tokens from original token array
257                         while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
258                             maTokens.push_back( *pParamBegin++ );
259                     }
260                     else
261                     {
262                         // if parameter is not empty, process all tokens of the parameter
263                         processTokens( pParamBegin, pParamEnd );
264                     }
265 
266                     // append parameter separator token
267                     maTokens.append( OPCODE_SEP );
268                 }
269 
270                 /*  #84453# Update size of new token sequence with valid parameters
271                     to be able to remove trailing optional empty parameters. */
272                 if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) )
273                 {
274                     nLastValidSize = maTokens.size();
275                     nLastValidCount = nParam + 1;
276                 }
277             }
278 
279             // #84453# remove trailing optional empty parameters
280             maTokens.resize( nLastValidSize );
281 
282             // add trailing Calc-only parameters
283             if( aParamInfoIt.isCalcOnlyParam() )
284                 appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount );
285 
286             // add optional parameters that are required in Calc
287             appendRequiredParameters( *pRealFuncInfo, nLastValidCount );
288 
289             // remove last parameter separator token
290             if( maTokens.back().OpCode == OPCODE_SEP )
291                 maTokens.pop_back();
292         }
293 
294         /*  Append the OPCODE_CLOSE token to the vector, but only if there is
295             no OPCODE_BAD token at the end, this token already contains the
296             trailing closing parentheses. */
297         if( (pTokenEnd - 1)->OpCode != OPCODE_BAD )
298             maTokens.append( OPCODE_CLOSE );
299     }
300 
301     /*  Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell,
302         if no matching add-in function was found. */
303     ApiToken& rFuncNameToken = maTokens[ nFuncNameIdx ];
304     if( (rFuncNameToken.OpCode == OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() )
305         rFuncNameToken.OpCode = OPCODE_NONAME;
306 
307     return pToken;
308 }
309 
310 bool FormulaFinalizer::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
311 {
312     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
313     if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_MISSING) ) ++pToken;
314     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
315     return pToken == pTokenEnd;
316 }
317 
318 const ApiToken* FormulaFinalizer::getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
319 {
320     const ApiToken* pSingleToken = 0;
321     // skip leading whitespace tokens
322     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
323     // remember first non-whitespace token
324     if( pToken < pTokenEnd ) pSingleToken = pToken++;
325     // skip trailing whitespace tokens
326     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
327     // return null, if other non-whitespace tokens follow
328     return (pToken == pTokenEnd) ? pSingleToken : 0;
329 }
330 
331 const ApiToken* FormulaFinalizer::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
332 {
333     // skip tokens between OPCODE_OPEN and OPCODE_CLOSE
334     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" );
335     ++pToken;
336     while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) )
337     {
338         if( pToken->OpCode == OPCODE_OPEN )
339             pToken = skipParentheses( pToken, pTokenEnd );
340         else
341             ++pToken;
342     }
343     // skip the OPCODE_CLOSE token
344     OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" );
345     return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
346 }
347 
348 const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams,
349         const ApiToken* pToken, const ApiToken* pTokenEnd ) const
350 {
351     // push position of OPCODE_OPEN
352     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::findParameters - OPCODE_OPEN expected" );
353     rParams.push_back( pToken++ );
354 
355     // find positions of parameter separators
356     while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) )
357     {
358         if( pToken->OpCode == OPCODE_OPEN )
359             pToken = skipParentheses( pToken, pTokenEnd );
360         else if( pToken->OpCode == OPCODE_SEP )
361             rParams.push_back( pToken++ );
362         else
363             ++pToken;
364     }
365 
366     // push position of OPCODE_CLOSE
367     OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "FormulaFinalizer::findParameters - OPCODE_CLOSE expected" );
368     rParams.push_back( pToken );
369     return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
370 }
371 
372 void FormulaFinalizer::appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
373 {
374     // remeber old size of the token array
375     size_t nTokenArraySize = maTokens.size();
376 
377     switch( rFuncInfo.mnBiff12FuncId )
378     {
379         case BIFF_FUNC_IF:
380             if( (nParam == 1) || (nParam == 2) )
381                 maTokens.append< double >( OPCODE_PUSH, 0.0 );
382         break;
383         default:;
384     }
385 
386     // if no token has been added, append a OPCODE_MISSING token
387     if( nTokenArraySize == maTokens.size() )
388         maTokens.append( OPCODE_MISSING );
389 }
390 
391 void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
392 {
393     (void)nParam;   // prevent 'unused' warning
394     switch( rFuncInfo.mnBiff12FuncId )
395     {
396         case BIFF_FUNC_FLOOR:
397         case BIFF_FUNC_CEILING:
398             OSL_ENSURE( nParam == 2, "FormulaFinalizer::appendCalcOnlyParameter - unexpected parameter index" );
399             maTokens.append< double >( OPCODE_PUSH, 1.0 );
400             maTokens.append( OPCODE_SEP );
401         break;
402     }
403 }
404 
405 void FormulaFinalizer::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount )
406 {
407     switch( rFuncInfo.mnBiff12FuncId )
408     {
409         case BIFF_FUNC_WEEKNUM:
410             if( nParamCount == 1 )
411             {
412                 maTokens.append< double >( OPCODE_PUSH, 1.0 );
413                 maTokens.append( OPCODE_SEP );
414             }
415         break;
416     }
417 }
418 
419 bool FormulaFinalizer::appendFinalToken( const ApiToken& rToken )
420 {
421     // replace OPCODE_MACRO without macro name with #NAME? error code
422     bool bValid = (rToken.OpCode != OPCODE_MACRO) || rToken.Data.hasValue();
423     if( bValid )
424     {
425         maTokens.push_back( rToken );
426     }
427     else
428     {
429         maTokens.append( OPCODE_ARRAY_OPEN );
430         maTokens.append( OPCODE_PUSH, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ) );
431         maTokens.append( OPCODE_ARRAY_CLOSE );
432     }
433     return bValid;
434 }
435 
436 // parser implementation base =================================================
437 
438 class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper
439 {
440 public:
441     explicit            FormulaParserImpl( const FormulaParser& rParent );
442 
443     /** Converts an OOXML formula string. */
444     virtual ApiTokenSequence importOoxFormula(
445                             const CellAddress& rBaseAddress,
446                             const OUString& rFormulaString );
447 
448     /** Imports and converts a BIFF12 token array from the passed stream. */
449     virtual ApiTokenSequence importBiff12Formula(
450                             const CellAddress& rBaseAddress,
451                             FormulaType eType,
452                             SequenceInputStream& rStrm );
453 
454     /** Imports and converts a BIFF2-BIFF8 token array from the passed stream. */
455     virtual ApiTokenSequence importBiffFormula(
456                             const CellAddress& rBaseAddress,
457                             FormulaType eType,
458                             BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
459 
460     /** Tries to resolve the passed ref-id to an OLE target URL. */
461     OUString            resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const;
462 
463 protected:
464     typedef ::std::pair< sal_Int32, bool >  WhiteSpace;
465     typedef ::std::vector< WhiteSpace >     WhiteSpaceVec;
466 
467     /** Initializes the formula parser before importing a formula. */
468     void                initializeImport( const CellAddress& rBaseAddress, FormulaType eType );
469     /** Finalizes the internal token storage after import. */
470     ApiTokenSequence    finalizeImport();
471 
472     // token array ------------------------------------------------------------
473 
474     bool                resetSpaces();
475     static void         appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed );
476     void                appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed );
477     void                appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed );
478     void                appendClosingSpaces( sal_Int32 nCount, bool bLineFeed );
479 
480     size_t              getFormulaSize() const;
481     Any&                appendRawToken( sal_Int32 nOpCode );
482     Any&                insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd );
483     size_t              appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces );
484     size_t              insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd );
485 
486     size_t              getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const;
487     void                pushOperandSize( size_t nSize );
488     size_t              popOperandSize();
489 
490     ApiToken&           getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex );
491     void                removeOperand( size_t nOpCountFromEnd, size_t nOpIndex );
492     void                removeLastOperands( size_t nOpCountFromEnd );
493 
494     bool                pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
495     bool                pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
496     template< typename Type >
497     bool                pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
498     template< typename Type >
499     inline bool         pushValueOperandToken( const Type& rValue, const WhiteSpaceVec* pSpaces = 0 )
500                             { return pushValueOperandToken( rValue, OPCODE_PUSH, pSpaces ); }
501     bool                pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
502     bool                pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
503     bool                pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
504     bool                pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
505     bool                pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
506     bool                pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
507     bool                pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
508 
509     bool                pushOperand( sal_Int32 nOpCode );
510     bool                pushAnyOperand( const Any& rAny, sal_Int32 nOpCode );
511     template< typename Type >
512     bool                pushValueOperand( const Type& rValue, sal_Int32 nOpCode );
513     template< typename Type >
514     inline bool         pushValueOperand( const Type& rValue )
515                             { return pushValueOperand( rValue, OPCODE_PUSH ); }
516     bool                pushBoolOperand( bool bValue );
517     bool                pushErrorOperand( double fEncodedError );
518     bool                pushBiffBoolOperand( sal_uInt8 nValue );
519     bool                pushBiffErrorOperand( sal_uInt8 nErrorCode );
520     bool                pushParenthesesOperand();
521     bool                pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
522     bool                pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
523     template< typename Type >
524     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef );
525     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
526     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
527     bool                pushNlrOperand( const BinSingleRef2d& rRef );
528     bool                pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken );
529     bool                pushDefinedNameOperand( const DefinedNameRef& rxDefName );
530     bool                pushExternalFuncOperand( const FunctionInfo& rFuncInfo );
531     bool                pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem );
532     bool                pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink );
533     bool                pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable );
534 
535     bool                pushUnaryPreOperator( sal_Int32 nOpCode );
536     bool                pushUnaryPostOperator( sal_Int32 nOpCode );
537     bool                pushBinaryOperator( sal_Int32 nOpCode );
538     bool                pushParenthesesOperator();
539     bool                pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount );
540     bool                pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount );
541 
542 private:
543     // reference conversion ---------------------------------------------------
544 
545     void                initReference2d( SingleReference& orApiRef ) const;
546     void                initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const;
547     void                convertColRow( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bRelativeAsOffset ) const;
548     void                convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
549     void                convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
550     void                convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
551     void                convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
552     void                convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
553     void                convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
554 
555 private:
556     // finalize token sequence ------------------------------------------------
557 
558     virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const;
559     virtual ::rtl::OUString resolveDefinedName( sal_Int32 nTokenIndex ) const;
560 
561 protected:
562     const sal_Int32     mnMaxApiCol;                /// Maximum column index in own document.
563     const sal_Int32     mnMaxApiRow;                /// Maximum row index in own document.
564     const sal_Int32     mnMaxXlsCol;                /// Maximum column index in imported document.
565     const sal_Int32     mnMaxXlsRow;                /// Maximum row index in imported document.
566 
567     CellAddress         maBaseAddr;                 /// Base address for relative references.
568     bool                mbRelativeAsOffset;         /// True = relative row/column index is (signed) offset, false = explicit index.
569     bool                mb2dRefsAs3dRefs;           /// True = convert all 2D references to 3D references in sheet specified by base address.
570     bool                mbSpecialTokens;            /// True = special handling for tExp and tTbl tokens, false = exit with error.
571     bool                mbAllowNulChars;            /// True = keep NUL characters in string tokens.
572 
573 private:
574     typedef ::std::vector< size_t > SizeTypeVector;
575 
576     ApiTokenVector      maTokenStorage;             /// Raw unordered token storage.
577     SizeTypeVector      maTokenIndexes;             /// Indexes into maTokenStorage.
578     SizeTypeVector      maOperandSizeStack;         /// Stack with token sizes per operand.
579     WhiteSpaceVec       maLeadingSpaces;            /// List of whitespaces before next token.
580     WhiteSpaceVec       maOpeningSpaces;            /// List of whitespaces before opening parenthesis.
581     WhiteSpaceVec       maClosingSpaces;            /// List of whitespaces before closing parenthesis.
582 };
583 
584 // ----------------------------------------------------------------------------
585 
586 FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) :
587     FormulaFinalizer( rParent ),
588     WorkbookHelper( rParent ),
589     mnMaxApiCol( rParent.getAddressConverter().getMaxApiAddress().Column ),
590     mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ),
591     mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ),
592     mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ),
593     mbRelativeAsOffset( false ),
594     mb2dRefsAs3dRefs( false ),
595     mbAllowNulChars( false )
596 {
597     // reserve enough space to make resize(), push_back() etc. cheap
598     maTokenStorage.reserve( 0x2000 );
599     maTokenIndexes.reserve( 0x2000 );
600     maOperandSizeStack.reserve( 256 );
601     maLeadingSpaces.reserve( 256 );
602     maOpeningSpaces.reserve( 256 );
603     maClosingSpaces.reserve( 256 );
604 }
605 
606 ApiTokenSequence FormulaParserImpl::importOoxFormula( const CellAddress&, const OUString& )
607 {
608     OSL_ENSURE( false, "FormulaParserImpl::importOoxFormula - not implemented" );
609     return ApiTokenSequence();
610 }
611 
612 ApiTokenSequence FormulaParserImpl::importBiff12Formula( const CellAddress&, FormulaType, SequenceInputStream& )
613 {
614     OSL_ENSURE( false, "FormulaParserImpl::importBiff12Formula - not implemented" );
615     return ApiTokenSequence();
616 }
617 
618 ApiTokenSequence FormulaParserImpl::importBiffFormula( const CellAddress&, FormulaType, BiffInputStream&, const sal_uInt16* )
619 {
620     OSL_ENSURE( false, "FormulaParserImpl::importBiffFormula - not implemented" );
621     return ApiTokenSequence();
622 }
623 
624 OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const
625 {
626     const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, bUseRefSheets ).get();
627     OSL_ENSURE( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE), "FormulaParserImpl::resolveOleTarget - missing or wrong link" );
628     if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE) )
629          return getBaseFilter().getAbsoluteUrl( pExtLink->getTargetUrl() );
630     return OUString();
631 }
632 
633 void FormulaParserImpl::initializeImport( const CellAddress& rBaseAddr, FormulaType eType )
634 {
635     maBaseAddr = rBaseAddr;
636     mbRelativeAsOffset = mb2dRefsAs3dRefs = mbSpecialTokens = mbAllowNulChars = false;
637     switch( eType )
638     {
639         case FORMULATYPE_CELL:
640             mbSpecialTokens = true;
641         break;
642         case FORMULATYPE_ARRAY:
643         break;
644         case FORMULATYPE_SHAREDFORMULA:
645             mbRelativeAsOffset = true;
646         break;
647         case FORMULATYPE_CONDFORMAT:
648             mbRelativeAsOffset = true;
649         break;
650         case FORMULATYPE_VALIDATION:
651             mbRelativeAsOffset = true;
652             // enable NUL characters in BIFF import, string list is single tStr token with NUL separators
653             mbAllowNulChars = getFilterType() == FILTER_BIFF;
654         break;
655         case FORMULATYPE_DEFINEDNAME:
656             mbRelativeAsOffset = true;
657             // BIFF2-BIFF4: convert 2D referebces to absolute 3D references
658             mb2dRefsAs3dRefs = (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4);
659         break;
660     }
661 
662     maTokenStorage.clear();
663     maTokenIndexes.clear();
664     maOperandSizeStack.clear();
665 }
666 
667 ApiTokenSequence FormulaParserImpl::finalizeImport()
668 {
669     ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) );
670     if( aTokens.hasElements() )
671     {
672         ApiToken* pToken = aTokens.getArray();
673         for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken )
674             *pToken = maTokenStorage[ *aIt ];
675     }
676     return finalizeTokenArray( aTokens );
677 }
678 
679 // token array ----------------------------------------------------------------
680 
681 bool FormulaParserImpl::resetSpaces()
682 {
683     maLeadingSpaces.clear();
684     maOpeningSpaces.clear();
685     maClosingSpaces.clear();
686     return true;
687 }
688 
689 void FormulaParserImpl::appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed )
690 {
691     OSL_ENSURE( nCount >= 0, "FormulaParserImpl::appendSpaces - negative count" );
692     if( nCount > 0 )
693         orSpaces.push_back( WhiteSpace( nCount, bLineFeed ) );
694 }
695 
696 void FormulaParserImpl::appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed )
697 {
698     appendSpaces( maLeadingSpaces, nCount, bLineFeed );
699 }
700 
701 void FormulaParserImpl::appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed )
702 {
703     appendSpaces( maOpeningSpaces, nCount, bLineFeed );
704 }
705 
706 void FormulaParserImpl::appendClosingSpaces( sal_Int32 nCount, bool bLineFeed )
707 {
708     appendSpaces( maClosingSpaces, nCount, bLineFeed );
709 }
710 
711 size_t FormulaParserImpl::getFormulaSize() const
712 {
713     return maTokenIndexes.size();
714 }
715 
716 Any& FormulaParserImpl::appendRawToken( sal_Int32 nOpCode )
717 {
718     maTokenIndexes.push_back( maTokenStorage.size() );
719     return maTokenStorage.append( nOpCode );
720 }
721 
722 Any& FormulaParserImpl::insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd )
723 {
724     maTokenIndexes.insert( maTokenIndexes.end() - nIndexFromEnd, maTokenStorage.size() );
725     return maTokenStorage.append( nOpCode );
726 }
727 
728 size_t FormulaParserImpl::appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces )
729 {
730     if( pSpaces && !pSpaces->empty() )
731         for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt )
732             appendRawToken( OPCODE_SPACES ) <<= aIt->first;
733     return pSpaces ? pSpaces->size() : 0;
734 }
735 
736 size_t FormulaParserImpl::insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd )
737 {
738     if( pSpaces && !pSpaces->empty() )
739         for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt )
740             insertRawToken( OPCODE_SPACES, nIndexFromEnd ) <<= aIt->first;
741     return pSpaces ? pSpaces->size() : 0;
742 }
743 
744 size_t FormulaParserImpl::getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const
745 {
746     OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()),
747         "FormulaParserImpl::getOperandSize - invalid parameters" );
748     return maOperandSizeStack[ maOperandSizeStack.size() - nOpCountFromEnd + nOpIndex ];
749 }
750 
751 void FormulaParserImpl::pushOperandSize( size_t nSize )
752 {
753     maOperandSizeStack.push_back( nSize );
754 }
755 
756 size_t FormulaParserImpl::popOperandSize()
757 {
758     OSL_ENSURE( !maOperandSizeStack.empty(), "FormulaParserImpl::popOperandSize - invalid call" );
759     size_t nOpSize = maOperandSizeStack.back();
760     maOperandSizeStack.pop_back();
761     return nOpSize;
762 }
763 
764 ApiToken& FormulaParserImpl::getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex )
765 {
766     OSL_ENSURE( getOperandSize( nOpCountFromEnd, nOpIndex ) > nTokenIndex,
767         "FormulaParserImpl::getOperandToken - invalid parameters" );
768     SizeTypeVector::const_iterator aIndexIt = maTokenIndexes.end();
769     for( SizeTypeVector::const_iterator aEnd = maOperandSizeStack.end(), aIt = aEnd - nOpCountFromEnd + nOpIndex; aIt != aEnd; ++aIt )
770         aIndexIt -= *aIt;
771     return maTokenStorage[ *(aIndexIt + nTokenIndex) ];
772 }
773 
774 void FormulaParserImpl::removeOperand( size_t nOpCountFromEnd, size_t nOpIndex )
775 {
776     OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()),
777         "FormulaParserImpl::removeOperand - invalid parameters" );
778     // remove indexes into token storage, but do not touch storage itself
779     SizeTypeVector::iterator aSizeEnd = maOperandSizeStack.end();
780     SizeTypeVector::iterator aSizeIt = aSizeEnd - nOpCountFromEnd + nOpIndex;
781     size_t nRemainingSize = 0;
782     for( SizeTypeVector::iterator aIt = aSizeIt + 1; aIt != aSizeEnd; ++aIt )
783         nRemainingSize += *aIt;
784     maTokenIndexes.erase( maTokenIndexes.end() - nRemainingSize - *aSizeIt, maTokenIndexes.end() - nRemainingSize );
785     maOperandSizeStack.erase( aSizeIt );
786 }
787 
788 void FormulaParserImpl::removeLastOperands( size_t nOpCountFromEnd )
789 {
790     for( size_t nOpIndex = 0; nOpIndex < nOpCountFromEnd; ++nOpIndex )
791         removeOperand( 1, 0 );
792 }
793 
794 bool FormulaParserImpl::pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
795 {
796     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
797     appendRawToken( nOpCode );
798     pushOperandSize( nSpacesSize + 1 );
799     return true;
800 }
801 
802 bool FormulaParserImpl::pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
803 {
804     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
805     appendRawToken( nOpCode ) = rAny;
806     pushOperandSize( nSpacesSize + 1 );
807     return true;
808 }
809 
810 template< typename Type >
811 bool FormulaParserImpl::pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
812 {
813     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
814     appendRawToken( nOpCode ) <<= rValue;
815     pushOperandSize( nSpacesSize + 1 );
816     return true;
817 }
818 
819 bool FormulaParserImpl::pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces )
820 {
821     size_t nSpacesSize = appendWhiteSpaceTokens( pOpeningSpaces );
822     appendRawToken( OPCODE_OPEN );
823     nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces );
824     appendRawToken( OPCODE_CLOSE );
825     pushOperandSize( nSpacesSize + 2 );
826     return true;
827 }
828 
829 bool FormulaParserImpl::pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
830 {
831     bool bOk = maOperandSizeStack.size() >= 1;
832     if( bOk )
833     {
834         size_t nOpSize = popOperandSize();
835         size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOpSize );
836         insertRawToken( nOpCode, nOpSize );
837         pushOperandSize( nOpSize + nSpacesSize + 1 );
838     }
839     return bOk;
840 }
841 
842 bool FormulaParserImpl::pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
843 {
844     bool bOk = maOperandSizeStack.size() >= 1;
845     if( bOk )
846     {
847         size_t nOpSize = popOperandSize();
848         size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
849         appendRawToken( nOpCode );
850         pushOperandSize( nOpSize + nSpacesSize + 1 );
851     }
852     return bOk;
853 }
854 
855 bool FormulaParserImpl::pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
856 {
857     bool bOk = maOperandSizeStack.size() >= 2;
858     if( bOk )
859     {
860         size_t nOp2Size = popOperandSize();
861         size_t nOp1Size = popOperandSize();
862         size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOp2Size );
863         insertRawToken( nOpCode, nOp2Size );
864         pushOperandSize( nOp1Size + nSpacesSize + 1 + nOp2Size );
865     }
866     return bOk;
867 }
868 
869 bool FormulaParserImpl::pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces )
870 {
871     bool bOk = maOperandSizeStack.size() >= 1;
872     if( bOk )
873     {
874         size_t nOpSize = popOperandSize();
875         size_t nSpacesSize = insertWhiteSpaceTokens( pOpeningSpaces, nOpSize );
876         insertRawToken( OPCODE_OPEN, nOpSize );
877         nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces );
878         appendRawToken( OPCODE_CLOSE );
879         pushOperandSize( nOpSize + nSpacesSize + 2 );
880     }
881     return bOk;
882 }
883 
884 bool FormulaParserImpl::pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces )
885 {
886     /*  #i70925# if there are not enough tokens available on token stack, do
887         not exit with error, but reduce parameter count. */
888     nParamCount = ::std::min( maOperandSizeStack.size(), nParamCount );
889 
890     // convert all parameters on stack to a single operand separated with OPCODE_SEP
891     bool bOk = true;
892     for( size_t nParam = 1; bOk && (nParam < nParamCount); ++nParam )
893         bOk = pushBinaryOperatorToken( OPCODE_SEP );
894 
895     // add function parentheses and function name
896     return bOk &&
897         ((nParamCount > 0) ? pushParenthesesOperatorToken( 0, pClosingSpaces ) : pushParenthesesOperandToken( 0, pClosingSpaces )) &&
898         pushUnaryPreOperatorToken( nOpCode, pLeadingSpaces );
899 }
900 
901 bool FormulaParserImpl::pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces )
902 {
903     bool bOk = pushFunctionOperatorToken( rFuncInfo.mnApiOpCode, nParamCount, pLeadingSpaces, pClosingSpaces );
904     if( bOk )
905     {
906        // create an external add-in call for the passed built-in function
907         if( (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) && (rFuncInfo.maExtProgName.getLength() > 0) )
908             getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maExtProgName;
909         // create a bad token with unsupported function name
910         else if( (rFuncInfo.mnApiOpCode == OPCODE_BAD) && (rFuncInfo.maOoxFuncName.getLength() > 0) )
911             getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maOoxFuncName;
912     }
913     return bOk;
914 }
915 
916 bool FormulaParserImpl::pushOperand( sal_Int32 nOpCode )
917 {
918     return pushOperandToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
919 }
920 
921 bool FormulaParserImpl::pushAnyOperand( const Any& rAny, sal_Int32 nOpCode )
922 {
923     return pushAnyOperandToken( rAny, nOpCode, &maLeadingSpaces ) && resetSpaces();
924 }
925 
926 template< typename Type >
927 bool FormulaParserImpl::pushValueOperand( const Type& rValue, sal_Int32 nOpCode )
928 {
929     return pushValueOperandToken( rValue, nOpCode, &maLeadingSpaces ) && resetSpaces();
930 }
931 
932 bool FormulaParserImpl::pushBoolOperand( bool bValue )
933 {
934     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) )
935         return pushFunctionOperator( pFuncInfo->mnApiOpCode, 0 );
936     return pushValueOperand< double >( bValue ? 1.0 : 0.0 );
937 }
938 
939 bool FormulaParserImpl::pushErrorOperand( double fEncodedError )
940 {
941     // HACK: enclose all error codes into an 1x1 matrix
942     // start token array with opening brace and leading spaces
943     pushOperand( OPCODE_ARRAY_OPEN );
944     size_t nOpSize = popOperandSize();
945     size_t nOldArraySize = maTokenIndexes.size();
946     // push a double containing the Calc error code
947     appendRawToken( OPCODE_PUSH ) <<= fEncodedError;
948     // close token array and set resulting operand size
949     appendRawToken( OPCODE_ARRAY_CLOSE );
950     pushOperandSize( nOpSize + maTokenIndexes.size() - nOldArraySize );
951     return true;
952 }
953 
954 bool FormulaParserImpl::pushBiffBoolOperand( sal_uInt8 nValue )
955 {
956     return pushBoolOperand( nValue != BIFF_TOK_BOOL_FALSE );
957 }
958 
959 bool FormulaParserImpl::pushBiffErrorOperand( sal_uInt8 nErrorCode )
960 {
961     return pushErrorOperand( BiffHelper::calcDoubleFromError( nErrorCode ) );
962 }
963 
964 bool FormulaParserImpl::pushParenthesesOperand()
965 {
966     return pushParenthesesOperandToken( &maOpeningSpaces, &maClosingSpaces ) && resetSpaces();
967 }
968 
969 bool FormulaParserImpl::pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
970 {
971     SingleReference aApiRef;
972     convertReference2d( aApiRef, rRef, bDeleted, bRelativeAsOffset );
973     return pushValueOperand( aApiRef );
974 }
975 
976 bool FormulaParserImpl::pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
977 {
978     ComplexReference aApiRef;
979     convertReference2d( aApiRef, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset );
980     return pushValueOperand( aApiRef );
981 }
982 
983 template< typename Type >
984 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef )
985 {
986     if( rSheetRange.isExternal() )
987     {
988         ExternalReference aApiExtRef;
989         aApiExtRef.Index = rSheetRange.getDocLinkIndex();
990         aApiExtRef.Reference <<= rApiRef;
991         return pushValueOperand( aApiExtRef );
992     }
993     return pushValueOperand( rApiRef );
994 }
995 
996 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
997 {
998     if( rSheetRange.is3dRange() )
999     {
1000         // single-cell-range over several sheets, needs to create a ComplexReference
1001         ComplexReference aApiRef;
1002         convertReference3d( aApiRef, rSheetRange, rRef, rRef, bDeleted, bRelativeAsOffset );
1003         return pushReferenceOperand( rSheetRange, aApiRef );
1004     }
1005     SingleReference aApiRef;
1006     convertReference3d( aApiRef, rSheetRange.getFirstSheet(), rSheetRange.isSameSheet(), rRef, bDeleted, bRelativeAsOffset );
1007     return pushReferenceOperand( rSheetRange, aApiRef );
1008 }
1009 
1010 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
1011 {
1012     ComplexReference aApiRef;
1013     convertReference3d( aApiRef, rSheetRange, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset );
1014     return pushReferenceOperand( rSheetRange, aApiRef );
1015 }
1016 
1017 bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef )
1018 {
1019     SingleReference aApiRef;
1020     convertReference2d( aApiRef, rRef, false, false );
1021     return pushValueOperand( aApiRef, OPCODE_NLR );
1022 }
1023 
1024 bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken )
1025 {
1026     Any aRefAny = rName.getReference( maBaseAddr );
1027     if( aRefAny.hasValue() )
1028         return pushAnyOperand( aRefAny, OPCODE_PUSH );
1029     if( bPushBadToken && (rName.getModelName().getLength() > 0) && (rName.getModelName()[ 0 ] >= ' ') )
1030         return pushValueOperand( rName.getModelName(), OPCODE_BAD );
1031     return pushBiffErrorOperand( BIFF_ERR_NAME );
1032 }
1033 
1034 bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName )
1035 {
1036     if( !rxDefName || (rxDefName->getModelName().getLength() == 0) )
1037         return pushBiffErrorOperand( BIFF_ERR_NAME );
1038     if( rxDefName->isMacroFunction() )
1039         return pushValueOperand( rxDefName->getModelName(), OPCODE_MACRO );
1040     if( rxDefName->getTokenIndex() >= 0 )
1041         return pushValueOperand( rxDefName->getTokenIndex(), OPCODE_NAME );
1042     return pushEmbeddedRefOperand( *rxDefName, true );
1043 }
1044 
1045 bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo& rFuncInfo )
1046 {
1047     return (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ?
1048         pushValueOperand( rFuncInfo.maExtProgName, OPCODE_EXTERNAL ) :
1049         pushOperand( rFuncInfo.mnApiOpCode );
1050 }
1051 
1052 bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem )
1053 {
1054     // create the function call DDE("server";"topic";"item")
1055     return
1056         pushValueOperandToken( rDdeServer ) &&
1057         pushValueOperandToken( rDdeTopic ) &&
1058         pushValueOperandToken( rDdeItem ) &&
1059         pushFunctionOperator( OPCODE_DDE, 3 );
1060 }
1061 
1062 bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink )
1063 {
1064     if( rxExtName.get() ) switch( rExtLink.getLinkType() )
1065     {
1066         case LINKTYPE_INTERNAL:
1067         case LINKTYPE_EXTERNAL:
1068             return pushEmbeddedRefOperand( *rxExtName, false );
1069 
1070         case LINKTYPE_ANALYSIS:
1071             // TODO: need support for localized addin function names
1072             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) )
1073                 return pushExternalFuncOperand( *pFuncInfo );
1074         break;
1075 
1076         case LINKTYPE_LIBRARY:
1077             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) )
1078                 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == rExtLink.getFuncLibraryType()) )
1079                     return pushExternalFuncOperand( *pFuncInfo );
1080         break;
1081 
1082         case LINKTYPE_DDE:
1083         {
1084             OUString aDdeServer, aDdeTopic, aDdeItem;
1085             if( rxExtName->getDdeLinkData( aDdeServer, aDdeTopic, aDdeItem ) )
1086                 return pushDdeLinkOperand( aDdeServer, aDdeTopic, aDdeItem );
1087         }
1088         break;
1089 
1090         default:
1091             OSL_ENSURE( rExtLink.getLinkType() != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" );
1092     }
1093     return pushBiffErrorOperand( BIFF_ERR_NAME );
1094 }
1095 
1096 bool FormulaParserImpl::pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable )
1097 {
1098     CellAddress aBaseAddr( maBaseAddr.Sheet, rBaseAddr.mnCol, rBaseAddr.mnRow );
1099     ApiSpecialTokenInfo aTokenInfo( aBaseAddr, bTable );
1100     return mbSpecialTokens && (getFormulaSize() == 0) && pushValueOperand( aTokenInfo, OPCODE_BAD );
1101 }
1102 
1103 bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode )
1104 {
1105     return pushUnaryPreOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
1106 }
1107 
1108 bool FormulaParserImpl::pushUnaryPostOperator( sal_Int32 nOpCode )
1109 {
1110     return pushUnaryPostOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
1111 }
1112 
1113 bool FormulaParserImpl::pushBinaryOperator( sal_Int32 nOpCode )
1114 {
1115     return pushBinaryOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
1116 }
1117 
1118 bool FormulaParserImpl::pushParenthesesOperator()
1119 {
1120     return pushParenthesesOperatorToken( &maOpeningSpaces, &maClosingSpaces ) && resetSpaces();
1121 }
1122 
1123 bool FormulaParserImpl::pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount )
1124 {
1125     return pushFunctionOperatorToken( nOpCode, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces();
1126 }
1127 
1128 bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount )
1129 {
1130     return pushFunctionOperatorToken( rFuncInfo, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces();
1131 }
1132 
1133 // reference conversion -------------------------------------------------------
1134 
1135 void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const
1136 {
1137     if( mb2dRefsAs3dRefs )
1138     {
1139         initReference3d( orApiRef, maBaseAddr.Sheet, false );
1140     }
1141     else
1142     {
1143         orApiRef.Flags = SHEET_RELATIVE;
1144         // #i10184# absolute sheet index needed for relative references in shared formulas
1145         orApiRef.Sheet = maBaseAddr.Sheet;
1146         orApiRef.RelativeSheet = 0;
1147     }
1148 }
1149 
1150 void FormulaParserImpl::initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const
1151 {
1152     orApiRef.Flags = SHEET_3D;
1153     if( nSheet < 0 )
1154     {
1155         orApiRef.Sheet = 0;
1156         orApiRef.Flags |= SHEET_DELETED;
1157     }
1158     else if( bSameSheet )
1159     {
1160         OSL_ENSURE( nSheet == 0, "FormulaParserImpl::initReference3d - invalid sheet index" );
1161         orApiRef.Flags |= SHEET_RELATIVE;
1162         orApiRef.RelativeSheet = 0;
1163     }
1164     else
1165     {
1166         orApiRef.Sheet = nSheet;
1167     }
1168 }
1169 
1170 void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
1171 {
1172     if( bDeleted )
1173     {
1174         orApiRef.Column = 0;
1175         orApiRef.Row = 0;
1176         // no explicit information about whether row or column is deleted
1177         orApiRef.Flags |= COLUMN_DELETED | ROW_DELETED;
1178     }
1179     else
1180     {
1181         // column/row indexes and flags
1182         setFlag( orApiRef.Flags, COLUMN_RELATIVE, rRef.mbColRel );
1183         setFlag( orApiRef.Flags, ROW_RELATIVE, rRef.mbRowRel );
1184         (rRef.mbColRel ? orApiRef.RelativeColumn : orApiRef.Column) = rRef.mnCol;
1185         (rRef.mbRowRel ? orApiRef.RelativeRow : orApiRef.Row) = rRef.mnRow;
1186         // convert absolute indexes to relative offsets used in API
1187         if( !bRelativeAsOffset )
1188         {
1189             if( rRef.mbColRel )
1190                 orApiRef.RelativeColumn -= maBaseAddr.Column;
1191             if( rRef.mbRowRel )
1192                 orApiRef.RelativeRow -= maBaseAddr.Row;
1193         }
1194     }
1195 }
1196 
1197 void FormulaParserImpl::convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
1198 {
1199     convertReference( orApiRef.Reference1, rRef1, bDeleted, bRelativeAsOffset );
1200     convertReference( orApiRef.Reference2, rRef2, bDeleted, bRelativeAsOffset );
1201     /*  Handle references to complete rows or columns (e.g. $1:$2 or C:D),
1202         need to expand or shrink to limits of own document. */
1203     if( !bDeleted && !rRef1.mbColRel && !rRef2.mbColRel && (orApiRef.Reference1.Column == 0) && (orApiRef.Reference2.Column == mnMaxXlsCol) )
1204         orApiRef.Reference2.Column = mnMaxApiCol;
1205     if( !bDeleted && !rRef1.mbRowRel && !rRef2.mbRowRel && (orApiRef.Reference1.Row == 0) && (orApiRef.Reference2.Row == mnMaxXlsRow) )
1206         orApiRef.Reference2.Row = mnMaxApiRow;
1207 }
1208 
1209 void FormulaParserImpl::convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
1210 {
1211     initReference2d( orApiRef );
1212     convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset );
1213 }
1214 
1215 void FormulaParserImpl::convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
1216 {
1217     initReference2d( orApiRef.Reference1 );
1218     initReference2d( orApiRef.Reference2 );
1219     convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset );
1220     // remove sheet name from second part of reference
1221     setFlag( orApiRef.Reference2.Flags, SHEET_3D, false );
1222 }
1223 
1224 void FormulaParserImpl::convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
1225 {
1226     initReference3d( orApiRef, nSheet, bSameSheet );
1227     convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset );
1228 }
1229 
1230 void FormulaParserImpl::convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
1231 {
1232     bool bSameSheet = rSheetRange.isSameSheet();
1233     initReference3d( orApiRef.Reference1, rSheetRange.getFirstSheet(), bSameSheet );
1234     initReference3d( orApiRef.Reference2, rSheetRange.getLastSheet(), bSameSheet );
1235     convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset );
1236     // remove sheet name from second part of reference
1237     setFlag( orApiRef.Reference2.Flags, SHEET_3D, rSheetRange.is3dRange() );
1238 }
1239 
1240 // finalize token sequence ----------------------------------------------------
1241 
1242 const FunctionInfo* FormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const
1243 {
1244     /*  Try to parse calls to library functions. The format of such a function
1245         call is "[n]!funcname", n>0 being the link identifier of the function
1246         library spreadsheet file. */
1247     sal_Int32 nBracketOpen = rTokenData.indexOf( '[' );
1248     sal_Int32 nBracketClose = rTokenData.indexOf( ']' );
1249     sal_Int32 nExclamation = rTokenData.indexOf( '!' );
1250     if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < rTokenData.getLength()) )
1251     {
1252         sal_Int32 nRefId = rTokenData.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32();
1253         const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get();
1254         if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) )
1255         {
1256             OUString aFuncName = rTokenData.copy( nExclamation + 1 ).toAsciiUpperCase();
1257             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ) )
1258                 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) )
1259                     return pFuncInfo;
1260         }
1261     }
1262     return 0;
1263 }
1264 
1265 OUString FormulaParserImpl::resolveDefinedName( sal_Int32 nTokenIndex ) const
1266 {
1267     if( const DefinedName* pDefName = getDefinedNames().getByTokenIndex( nTokenIndex ).get() )
1268         return pDefName->getCalcName();
1269     return OUString();
1270 }
1271 
1272 // OOXML/BIFF12 parser implementation =========================================
1273 
1274 class OoxFormulaParserImpl : public FormulaParserImpl
1275 {
1276 public:
1277     explicit            OoxFormulaParserImpl( const FormulaParser& rParent );
1278 
1279     virtual ApiTokenSequence importOoxFormula(
1280                             const CellAddress& rBaseAddr,
1281                             const OUString& rFormulaString );
1282 
1283     virtual ApiTokenSequence importBiff12Formula(
1284                             const CellAddress& rBaseAddr,
1285                             FormulaType eType,
1286                             SequenceInputStream& rStrm );
1287 
1288 private:
1289     // import token contents and create API formula token ---------------------
1290 
1291     bool                importAttrToken( SequenceInputStream& rStrm );
1292     bool                importSpaceToken( SequenceInputStream& rStrm );
1293     bool                importTableToken( SequenceInputStream& rStrm );
1294     bool                importArrayToken( SequenceInputStream& rStrm );
1295     bool                importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1296     bool                importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1297     bool                importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1298     bool                importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1299     bool                importMemAreaToken( SequenceInputStream& rStrm, bool bAddData );
1300     bool                importMemFuncToken( SequenceInputStream& rStrm );
1301     bool                importNameToken( SequenceInputStream& rStrm );
1302     bool                importNameXToken( SequenceInputStream& rStrm );
1303     bool                importFuncToken( SequenceInputStream& rStrm );
1304     bool                importFuncVarToken( SequenceInputStream& rStrm );
1305     bool                importExpToken( SequenceInputStream& rStrm );
1306 
1307     LinkSheetRange      readSheetRange( SequenceInputStream& rStrm );
1308 
1309     void                swapStreamPosition( SequenceInputStream& rStrm );
1310     void                skipMemAreaAddData( SequenceInputStream& rStrm );
1311 
1312     // convert BIN token and push API operand or operator ---------------------
1313 
1314     bool                pushBiff12Name( sal_Int32 nNameId );
1315     bool                pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId );
1316     bool                pushBiff12Function( sal_uInt16 nFuncId );
1317     bool                pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount );
1318 
1319 private:
1320     ApiParserWrapper    maApiParser;        /// Wrapper for the API formula parser object.
1321     sal_Int64           mnAddDataPos;       /// Current stream position for additional data (tExp, tArray, tMemArea).
1322     bool                mbNeedExtRefs;      /// True = parser needs initialization of external reference info.
1323 };
1324 
1325 // ----------------------------------------------------------------------------
1326 
1327 OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) :
1328     FormulaParserImpl( rParent ),
1329     maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ),
1330     mnAddDataPos( 0 ),
1331     mbNeedExtRefs( true )
1332 {
1333 }
1334 
1335 ApiTokenSequence OoxFormulaParserImpl::importOoxFormula( const CellAddress& rBaseAddr, const OUString& rFormulaString )
1336 {
1337     if( mbNeedExtRefs )
1338     {
1339         maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() );
1340         mbNeedExtRefs = false;
1341     }
1342     return finalizeTokenArray( maApiParser.parseFormula( rFormulaString, rBaseAddr ) );
1343 }
1344 
1345 ApiTokenSequence OoxFormulaParserImpl::importBiff12Formula( const CellAddress& rBaseAddr, FormulaType eType, SequenceInputStream& rStrm )
1346 {
1347     initializeImport( rBaseAddr, eType );
1348 
1349     sal_Int32 nFmlaSize = rStrm.readInt32();
1350     sal_Int64 nFmlaPos = rStrm.tell();
1351     sal_Int64 nFmlaEndPos = nFmlaPos + nFmlaSize;
1352 
1353     rStrm.seek( nFmlaEndPos );
1354     sal_Int32 nAddDataSize = rStrm.readInt32();
1355     mnAddDataPos = rStrm.tell();
1356     sal_Int64 nAddDataEndPos = mnAddDataPos + nAddDataSize;
1357     rStrm.seek( nFmlaPos );
1358 
1359     bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0);
1360     bool bRelativeAsOffset = mbRelativeAsOffset;
1361 
1362     while( bOk && !rStrm.isEof() && (rStrm.tell() < nFmlaEndPos) )
1363     {
1364         sal_uInt8 nTokenId;
1365         rStrm >> nTokenId;
1366         sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK;
1367         sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK;
1368 
1369         if( nTokenClass == BIFF_TOKCLASS_NONE )
1370         {
1371             // base tokens
1372             switch( nBaseId )
1373             {
1374                 case BIFF_TOKID_EXP:        bOk = importExpToken( rStrm );                                      break;
1375                 case BIFF_TOKID_ADD:        bOk = pushBinaryOperator( OPCODE_ADD );                             break;
1376                 case BIFF_TOKID_SUB:        bOk = pushBinaryOperator( OPCODE_SUB );                             break;
1377                 case BIFF_TOKID_MUL:        bOk = pushBinaryOperator( OPCODE_MULT );                            break;
1378                 case BIFF_TOKID_DIV:        bOk = pushBinaryOperator( OPCODE_DIV );                             break;
1379                 case BIFF_TOKID_POWER:      bOk = pushBinaryOperator( OPCODE_POWER );                           break;
1380                 case BIFF_TOKID_CONCAT:     bOk = pushBinaryOperator( OPCODE_CONCAT );                          break;
1381                 case BIFF_TOKID_LT:         bOk = pushBinaryOperator( OPCODE_LESS );                            break;
1382                 case BIFF_TOKID_LE:         bOk = pushBinaryOperator( OPCODE_LESS_EQUAL );                      break;
1383                 case BIFF_TOKID_EQ:         bOk = pushBinaryOperator( OPCODE_EQUAL );                           break;
1384                 case BIFF_TOKID_GE:         bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL );                   break;
1385                 case BIFF_TOKID_GT:         bOk = pushBinaryOperator( OPCODE_GREATER );                         break;
1386                 case BIFF_TOKID_NE:         bOk = pushBinaryOperator( OPCODE_NOT_EQUAL );                       break;
1387                 case BIFF_TOKID_ISECT:      bOk = pushBinaryOperator( OPCODE_INTERSECT );                       break;
1388                 case BIFF_TOKID_LIST:       bOk = pushBinaryOperator( OPCODE_LIST );                            break;
1389                 case BIFF_TOKID_RANGE:      bOk = pushBinaryOperator( OPCODE_RANGE );                           break;
1390                 case BIFF_TOKID_UPLUS:      bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN );                     break;
1391                 case BIFF_TOKID_UMINUS:     bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN );                    break;
1392                 case BIFF_TOKID_PERCENT:    bOk = pushUnaryPostOperator( OPCODE_PERCENT );                      break;
1393                 case BIFF_TOKID_PAREN:      bOk = pushParenthesesOperator();                                    break;
1394                 case BIFF_TOKID_MISSARG:    bOk = pushOperand( OPCODE_MISSING );                                break;
1395                 case BIFF_TOKID_STR:        bOk = pushValueOperand( BiffHelper::readString( rStrm, false ) );   break;
1396                 case BIFF_TOKID_NLR:        bOk = importTableToken( rStrm );                                    break;
1397                 case BIFF_TOKID_ATTR:       bOk = importAttrToken( rStrm );                                     break;
1398                 case BIFF_TOKID_ERR:        bOk = pushBiffErrorOperand( rStrm.readuInt8() );                    break;
1399                 case BIFF_TOKID_BOOL:       bOk = pushBiffBoolOperand( rStrm.readuInt8() );                     break;
1400                 case BIFF_TOKID_INT:        bOk = pushValueOperand< double >( rStrm.readuInt16() );             break;
1401                 case BIFF_TOKID_NUM:        bOk = pushValueOperand( rStrm.readDouble() );                       break;
1402                 default:                    bOk = false;
1403             }
1404         }
1405         else
1406         {
1407             // classified tokens
1408             switch( nBaseId )
1409             {
1410                 case BIFF_TOKID_ARRAY:      bOk = importArrayToken( rStrm );                            break;
1411                 case BIFF_TOKID_FUNC:       bOk = importFuncToken( rStrm );                             break;
1412                 case BIFF_TOKID_FUNCVAR:    bOk = importFuncVarToken( rStrm );                          break;
1413                 case BIFF_TOKID_NAME:       bOk = importNameToken( rStrm );                             break;
1414                 case BIFF_TOKID_REF:        bOk = importRefToken( rStrm, false, false );                break;
1415                 case BIFF_TOKID_AREA:       bOk = importAreaToken( rStrm, false, false );               break;
1416                 case BIFF_TOKID_MEMAREA:    bOk = importMemAreaToken( rStrm, true );                    break;
1417                 case BIFF_TOKID_MEMERR:     bOk = importMemAreaToken( rStrm, false );                   break;
1418                 case BIFF_TOKID_MEMNOMEM:   bOk = importMemAreaToken( rStrm, false );                   break;
1419                 case BIFF_TOKID_MEMFUNC:    bOk = importMemFuncToken( rStrm );                          break;
1420                 case BIFF_TOKID_REFERR:     bOk = importRefToken( rStrm, true, false );                 break;
1421                 case BIFF_TOKID_AREAERR:    bOk = importAreaToken( rStrm, true, false );                break;
1422                 case BIFF_TOKID_REFN:       bOk = importRefToken( rStrm, false, true );                 break;
1423                 case BIFF_TOKID_AREAN:      bOk = importAreaToken( rStrm, false, true );                break;
1424                 case BIFF_TOKID_MEMAREAN:   bOk = importMemFuncToken( rStrm );                          break;
1425                 case BIFF_TOKID_MEMNOMEMN:  bOk = importMemFuncToken( rStrm );                          break;
1426                 case BIFF_TOKID_NAMEX:      bOk = importNameXToken( rStrm );                            break;
1427                 case BIFF_TOKID_REF3D:      bOk = importRef3dToken( rStrm, false, bRelativeAsOffset );  break;
1428                 case BIFF_TOKID_AREA3D:     bOk = importArea3dToken( rStrm, false, bRelativeAsOffset ); break;
1429                 case BIFF_TOKID_REFERR3D:   bOk = importRef3dToken( rStrm, true, bRelativeAsOffset );   break;
1430                 case BIFF_TOKID_AREAERR3D:  bOk = importArea3dToken( rStrm, true, bRelativeAsOffset );  break;
1431                 default:                    bOk = false;
1432             }
1433         }
1434     }
1435 
1436     // build and finalize the token sequence
1437     ApiTokenSequence aFinalTokens;
1438     if( bOk && (rStrm.tell() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) )
1439         aFinalTokens = finalizeImport();
1440 
1441     // seek behind token array
1442     if( (nFmlaSize >= 0) && (nAddDataSize >= 0) )
1443         rStrm.seek( nAddDataEndPos );
1444 
1445     // return the final token sequence
1446     return aFinalTokens;
1447 }
1448 
1449 // import token contents and create API formula token -------------------------
1450 
1451 bool OoxFormulaParserImpl::importAttrToken( SequenceInputStream& rStrm )
1452 {
1453     bool bOk = true;
1454     sal_uInt8 nType;
1455     rStrm >> nType;
1456     // equal flags in all BIFFs
1457     switch( nType )
1458     {
1459         case 0:     // sometimes, tAttrSkip tokens miss the type flag
1460         case BIFF_TOK_ATTR_VOLATILE:
1461         case BIFF_TOK_ATTR_IF:
1462         case BIFF_TOK_ATTR_SKIP:
1463         case BIFF_TOK_ATTR_ASSIGN:
1464         case BIFF_TOK_ATTR_IFERROR:
1465             rStrm.skip( 2 );
1466         break;
1467         case BIFF_TOK_ATTR_CHOOSE:
1468             rStrm.skip( 2 * rStrm.readuInt16() + 2 );
1469         break;
1470         case BIFF_TOK_ATTR_SUM:
1471             rStrm.skip( 2 );
1472             bOk = pushBiff12Function( BIFF_FUNC_SUM, 1 );
1473         break;
1474         case BIFF_TOK_ATTR_SPACE:
1475         case BIFF_TOK_ATTR_SPACE_VOLATILE:
1476             bOk = importSpaceToken( rStrm );
1477         break;
1478         default:
1479             bOk = false;
1480     }
1481     return bOk;
1482 }
1483 
1484 bool OoxFormulaParserImpl::importSpaceToken( SequenceInputStream& rStrm )
1485 {
1486     // equal constants in BIFF and OOX
1487     sal_uInt8 nType, nCount;
1488     rStrm >> nType >> nCount;
1489     switch( nType )
1490     {
1491         case BIFF_TOK_ATTR_SPACE_SP:
1492             appendLeadingSpaces( nCount, false );
1493         break;
1494         case BIFF_TOK_ATTR_SPACE_BR:
1495             appendLeadingSpaces( nCount, true );
1496         break;
1497         case BIFF_TOK_ATTR_SPACE_SP_OPEN:
1498             appendOpeningSpaces( nCount, false );
1499         break;
1500         case BIFF_TOK_ATTR_SPACE_BR_OPEN:
1501             appendOpeningSpaces( nCount, true );
1502         break;
1503         case BIFF_TOK_ATTR_SPACE_SP_CLOSE:
1504             appendClosingSpaces( nCount, false );
1505         break;
1506         case BIFF_TOK_ATTR_SPACE_BR_CLOSE:
1507             appendClosingSpaces( nCount, true );
1508         break;
1509     }
1510     return true;
1511 }
1512 
1513 bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm )
1514 {
1515     sal_uInt16 nFlags, nTableId, nCol1, nCol2;
1516     rStrm.skip( 3 );
1517     rStrm >> nFlags >> nTableId;
1518     rStrm.skip( 2 );
1519     rStrm >> nCol1 >> nCol2;
1520     TableRef xTable = getTables().getTable( nTableId );
1521     sal_Int32 nTokenIndex = xTable.get() ? xTable->getTokenIndex() : -1;
1522     if( nTokenIndex >= 0 )
1523     {
1524         sal_Int32 nWidth = xTable->getWidth();
1525         sal_Int32 nHeight = xTable->getHeight();
1526         sal_Int32 nStartCol = 0;
1527         sal_Int32 nEndCol = nWidth - 1;
1528         sal_Int32 nStartRow = 0;
1529         sal_Int32 nEndRow = nHeight - 1;
1530         bool bFixedStartRow = true;
1531         bool bFixedHeight = false;
1532 
1533         bool bSingleCol = getFlag( nFlags, BIFF12_TOK_TABLE_COLUMN );
1534         bool bColRange = getFlag( nFlags, BIFF12_TOK_TABLE_COLRANGE );
1535         bool bValidRef = !bSingleCol || !bColRange;
1536         OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" );
1537         if( bValidRef )
1538         {
1539             if( bSingleCol )
1540                 nStartCol = nEndCol = nCol1;
1541             else if( bColRange )
1542                 { nStartCol = nCol1; nEndCol = nCol2; }
1543             bValidRef = (nStartCol <= nEndCol) && (nEndCol < nWidth);
1544             OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid column range" );
1545         }
1546 
1547         if( bValidRef )
1548         {
1549             bool bAllRows    = getFlag( nFlags, BIFF12_TOK_TABLE_ALL );
1550             bool bHeaderRows = getFlag( nFlags, BIFF12_TOK_TABLE_HEADERS );
1551             bool bDataRows   = getFlag( nFlags, BIFF12_TOK_TABLE_DATA );
1552             bool bTotalsRows = getFlag( nFlags, BIFF12_TOK_TABLE_TOTALS );
1553             bool bThisRow    = getFlag( nFlags, BIFF12_TOK_TABLE_THISROW );
1554 
1555             sal_Int32 nStartDataRow = xTable->getHeaderRows();
1556             sal_Int32 nEndDataRow = nEndRow - xTable->getTotalsRows();
1557             bValidRef = (nStartRow <= nStartDataRow) && (nStartDataRow <= nEndDataRow) && (nEndDataRow <= nEndRow);
1558             OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid data row range" );
1559             if( bValidRef )
1560             {
1561                 if( bAllRows )
1562                 {
1563                     bValidRef = !bHeaderRows && !bDataRows && !bTotalsRows && !bThisRow;
1564                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" );
1565                 }
1566                 else if( bHeaderRows )
1567                 {
1568                     bValidRef = !bTotalsRows && !bThisRow;
1569                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" );
1570                     nEndRow = bDataRows ? nEndDataRow : (nStartDataRow - 1);
1571                     bFixedHeight = !bDataRows;
1572                 }
1573                 else if( bDataRows )
1574                 {
1575                     bValidRef = !bThisRow;
1576                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" );
1577                     nStartRow = nStartDataRow;
1578                     if( !bTotalsRows ) nEndRow = nEndDataRow;
1579                 }
1580                 else if( bTotalsRows )
1581                 {
1582                     bValidRef = !bThisRow;
1583                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" );
1584                     nStartRow = nEndDataRow + 1;
1585                     bFixedStartRow = false;
1586                     bFixedHeight = !bDataRows;
1587                 }
1588                 else if( bThisRow )
1589                 {
1590                     nStartRow = nEndRow = maBaseAddr.Row - xTable->getRange().StartRow;
1591                     bFixedHeight = true;
1592                 }
1593                 else
1594                 {
1595                     // nothing is the same as [#Data]
1596                     nStartRow = nStartDataRow;
1597                     nEndRow = nEndDataRow;
1598                 }
1599             }
1600             if( bValidRef )
1601                 bValidRef = (0 <= nStartRow) && (nStartRow <= nEndRow) && (nEndRow < nHeight);
1602         }
1603         if( bValidRef )
1604         {
1605             // push single database area token, if table token refers to entire table
1606             if( (nStartCol == 0) && (nEndCol + 1 == nWidth) && (nStartRow == 0) && (nEndRow + 1 == nHeight) )
1607                 return pushValueOperand( nTokenIndex, OPCODE_DBAREA );
1608             // create an OFFSET function call to refer to a subrange of the table
1609             const FunctionInfo* pRowsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_ROWS );
1610             const FunctionInfo* pColumnsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_COLUMNS );
1611             return
1612                 pRowsInfo && pColumnsInfo &&
1613                 pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1614                 (bFixedStartRow ?
1615                     pushValueOperandToken< double >( nStartRow ) :
1616                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1617                      pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
1618                      pushValueOperandToken< double >( nHeight - nStartRow ) &&
1619                      pushBinaryOperatorToken( OPCODE_SUB ))) &&
1620                 pushValueOperandToken< double >( nStartCol ) &&
1621                 (bFixedHeight ?
1622                     pushValueOperandToken< double >( nEndRow - nStartRow + 1 ) :
1623                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1624                      pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
1625                      (((nStartRow == 0) && (nEndRow + 1 == nHeight)) ||
1626                       (pushValueOperandToken< double >( nHeight - (nEndRow - nStartRow + 1) ) &&
1627                        pushBinaryOperatorToken( OPCODE_SUB ))))) &&
1628                 (((nStartCol == 0) && (nEndCol + 1 == nWidth)) ?
1629                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1630                      pushFunctionOperatorToken( *pColumnsInfo, 1 )) :
1631                     pushValueOperandToken< double >( nEndCol - nStartCol + 1 )) &&
1632                 pushBiff12Function( BIFF_FUNC_OFFSET, 5 );
1633         }
1634     }
1635     return pushBiffErrorOperand( BIFF_ERR_REF );
1636 }
1637 
1638 bool OoxFormulaParserImpl::importArrayToken( SequenceInputStream& rStrm )
1639 {
1640     rStrm.skip( 14 );
1641 
1642     // start token array with opening brace and leading spaces
1643     pushOperand( OPCODE_ARRAY_OPEN );
1644     size_t nOpSize = popOperandSize();
1645     size_t nOldArraySize = getFormulaSize();
1646 
1647     // read array size
1648     swapStreamPosition( rStrm );
1649     sal_Int32 nRows = rStrm.readInt32();
1650     sal_Int32 nCols = rStrm.readInt32();
1651     OSL_ENSURE( (nCols > 0) && (nRows > 0), "OoxFormulaParserImpl::importArrayToken - empty array" );
1652 
1653     // read array values and build token array
1654     for( sal_Int32 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow )
1655     {
1656         if( nRow > 0 )
1657             appendRawToken( OPCODE_ARRAY_ROWSEP );
1658         for( sal_Int32 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol )
1659         {
1660             if( nCol > 0 )
1661                 appendRawToken( OPCODE_ARRAY_COLSEP );
1662             switch( rStrm.readuInt8() )
1663             {
1664                 case BIFF_TOK_ARRAY_DOUBLE:
1665                     appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble();
1666                 break;
1667                 case BIFF_TOK_ARRAY_STRING:
1668                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::readString( rStrm, false );
1669                 break;
1670                 case BIFF_TOK_ARRAY_BOOL:
1671                     appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 );
1672                 break;
1673                 case BIFF_TOK_ARRAY_ERROR:
1674                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() );
1675                     rStrm.skip( 3 );
1676                 break;
1677                 default:
1678                     OSL_ENSURE( false, "OoxFormulaParserImpl::importArrayToken - unknown data type" );
1679                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA );
1680             }
1681         }
1682     }
1683     swapStreamPosition( rStrm );
1684 
1685     // close token array and set resulting operand size
1686     appendRawToken( OPCODE_ARRAY_CLOSE );
1687     pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize );
1688     return true;
1689 }
1690 
1691 bool OoxFormulaParserImpl::importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
1692 {
1693     BinSingleRef2d aRef;
1694     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1695     return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
1696 }
1697 
1698 bool OoxFormulaParserImpl::importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
1699 {
1700     BinComplexRef2d aRef;
1701     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1702     return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
1703 }
1704 
1705 bool OoxFormulaParserImpl::importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
1706 {
1707     LinkSheetRange aSheetRange = readSheetRange( rStrm );
1708     BinSingleRef2d aRef;
1709     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1710     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
1711 }
1712 
1713 bool OoxFormulaParserImpl::importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
1714 {
1715     LinkSheetRange aSheetRange = readSheetRange( rStrm );
1716     BinComplexRef2d aRef;
1717     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1718     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
1719 }
1720 
1721 bool OoxFormulaParserImpl::importMemAreaToken( SequenceInputStream& rStrm, bool bAddData )
1722 {
1723     rStrm.skip( 6 );
1724     if( bAddData )
1725         skipMemAreaAddData( rStrm );
1726     return true;
1727 }
1728 
1729 bool OoxFormulaParserImpl::importMemFuncToken( SequenceInputStream& rStrm )
1730 {
1731     rStrm.skip( 2 );
1732     return true;
1733 }
1734 
1735 bool OoxFormulaParserImpl::importNameToken( SequenceInputStream& rStrm )
1736 {
1737     return pushBiff12Name( rStrm.readInt32() );
1738 }
1739 
1740 bool OoxFormulaParserImpl::importNameXToken( SequenceInputStream& rStrm )
1741 {
1742     sal_Int32 nRefId = rStrm.readInt16();
1743     sal_Int32 nNameId = rStrm.readInt32();
1744     return pushBiff12ExtName( nRefId, nNameId );
1745 }
1746 
1747 bool OoxFormulaParserImpl::importFuncToken( SequenceInputStream& rStrm )
1748 {
1749     sal_uInt16 nFuncId;
1750     rStrm >> nFuncId;
1751     return pushBiff12Function( nFuncId );
1752 }
1753 
1754 bool OoxFormulaParserImpl::importFuncVarToken( SequenceInputStream& rStrm )
1755 {
1756     sal_uInt8 nParamCount;
1757     sal_uInt16 nFuncId;
1758     rStrm >> nParamCount >> nFuncId;
1759     return pushBiff12Function( nFuncId, nParamCount );
1760 }
1761 
1762 bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm )
1763 {
1764     BinAddress aBaseAddr;
1765     rStrm >> aBaseAddr.mnRow;
1766     swapStreamPosition( rStrm );
1767     rStrm >> aBaseAddr.mnCol;
1768     swapStreamPosition( rStrm );
1769     return pushSpecialTokenOperand( aBaseAddr, false );
1770 }
1771 
1772 LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm )
1773 {
1774     return getExternalLinks().getSheetRange( rStrm.readInt16() );
1775 }
1776 
1777 void OoxFormulaParserImpl::swapStreamPosition( SequenceInputStream& rStrm )
1778 {
1779     sal_Int64 nRecPos = rStrm.tell();
1780     rStrm.seek( mnAddDataPos );
1781     mnAddDataPos = nRecPos;
1782 }
1783 
1784 void OoxFormulaParserImpl::skipMemAreaAddData( SequenceInputStream& rStrm )
1785 {
1786     swapStreamPosition( rStrm );
1787     rStrm.skip( 16 * rStrm.readInt32() );
1788     swapStreamPosition( rStrm );
1789 }
1790 
1791 // convert BIN token and push API operand or operator -------------------------
1792 
1793 bool OoxFormulaParserImpl::pushBiff12Name( sal_Int32 nNameId )
1794 {
1795     // one-based in BIFF12 formulas
1796     return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId - 1 ) );
1797 }
1798 
1799 bool OoxFormulaParserImpl::pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId )
1800 {
1801     if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
1802     {
1803         if( pExtLink->getLinkType() == LINKTYPE_SELF )
1804             return pushBiff12Name( nNameId );
1805         // external name indexes are one-based in BIFF12
1806         ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 );
1807         return pushExternalNameOperand( xExtName, *pExtLink );
1808     }
1809     return pushBiffErrorOperand( BIFF_ERR_NAME );
1810 }
1811 
1812 bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId )
1813 {
1814     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
1815         if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount )
1816             return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount );
1817     return pushFunctionOperator( OPCODE_NONAME, 0 );
1818 }
1819 
1820 bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount )
1821 {
1822     if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) )
1823         nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK;
1824     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
1825         return pushFunctionOperator( *pFuncInfo, nParamCount );
1826     return pushFunctionOperator( OPCODE_NONAME, nParamCount );
1827 }
1828 
1829 // BIFF parser implementation =================================================
1830 
1831 namespace {
1832 
1833 /** A natural language reference struct with relative flag. */
1834 struct BiffNlr
1835 {
1836     sal_Int32           mnCol;              /// Column index.
1837     sal_Int32           mnRow;              /// Row index.
1838     bool                mbRel;              /// True = relative column/row reference.
1839 
1840     explicit            BiffNlr();
1841 
1842     void                readBiff8Data( BiffInputStream& rStrm );
1843 };
1844 
1845 BiffNlr::BiffNlr() :
1846     mnCol( 0 ),
1847     mnRow( 0 ),
1848     mbRel( false )
1849 {
1850 }
1851 
1852 void BiffNlr::readBiff8Data( BiffInputStream& rStrm )
1853 {
1854     sal_uInt16 nRow, nCol;
1855     rStrm >> nRow >> nCol;
1856     mnCol = nCol & BIFF_TOK_NLR_MASK;
1857     mnRow = nRow;
1858     mbRel = getFlag( nCol, BIFF_TOK_NLR_REL );
1859 }
1860 
1861 bool lclIsValidNlrStack( const BinAddress& rAddr1, const BinAddress& rAddr2, bool bRow )
1862 {
1863     return bRow ?
1864         ((rAddr1.mnRow == rAddr2.mnRow) && (rAddr1.mnCol + 1 == rAddr2.mnCol)) :
1865         ((rAddr1.mnCol == rAddr2.mnCol) && (rAddr1.mnRow + 1 == rAddr2.mnRow));
1866 }
1867 
1868 bool lclIsValidNlrRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow )
1869 {
1870     return bRow ?
1871         ((rNlr.mnRow == rRange.maFirst.mnRow) && (rNlr.mnCol + 1 == rRange.maFirst.mnCol) && (rRange.maFirst.mnRow == rRange.maLast.mnRow)) :
1872         ((rNlr.mnCol == rRange.maFirst.mnCol) && (rNlr.mnRow + 1 == rRange.maFirst.mnRow) && (rRange.maFirst.mnCol == rRange.maLast.mnCol));
1873 }
1874 
1875 } // namespace
1876 
1877 // ----------------------------------------------------------------------------
1878 
1879 class BiffFormulaParserImpl : public FormulaParserImpl
1880 {
1881 public:
1882     explicit            BiffFormulaParserImpl( const FormulaParser& rParent );
1883 
1884     virtual ApiTokenSequence importBiffFormula(
1885                             const CellAddress& rBaseAddr,
1886                             FormulaType eType,
1887                             BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
1888 
1889 private:
1890     // import token contents and create API formula token ---------------------
1891 
1892     bool                importTokenNotAvailable( BiffInputStream& rStrm );
1893     bool                importRefTokenNotAvailable( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1894     bool                importStrToken2( BiffInputStream& rStrm );
1895     bool                importStrToken8( BiffInputStream& rStrm );
1896     bool                importAttrToken( BiffInputStream& rStrm );
1897     bool                importSpaceToken3( BiffInputStream& rStrm );
1898     bool                importSpaceToken4( BiffInputStream& rStrm );
1899     bool                importSheetToken2( BiffInputStream& rStrm );
1900     bool                importSheetToken3( BiffInputStream& rStrm );
1901     bool                importEndSheetToken2( BiffInputStream& rStrm );
1902     bool                importEndSheetToken3( BiffInputStream& rStrm );
1903     bool                importNlrToken( BiffInputStream& rStrm );
1904     bool                importArrayToken( BiffInputStream& rStrm );
1905     bool                importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1906     bool                importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1907     bool                importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1908     bool                importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1909     bool                importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1910     bool                importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1911     bool                importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1912     bool                importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
1913     bool                importMemAreaToken( BiffInputStream& rStrm, bool bAddData );
1914     bool                importMemFuncToken( BiffInputStream& rStrm );
1915     bool                importNameToken( BiffInputStream& rStrm );
1916     bool                importNameXToken( BiffInputStream& rStrm );
1917     bool                importFuncToken2( BiffInputStream& rStrm );
1918     bool                importFuncToken4( BiffInputStream& rStrm );
1919     bool                importFuncVarToken2( BiffInputStream& rStrm );
1920     bool                importFuncVarToken4( BiffInputStream& rStrm );
1921     bool                importFuncCEToken( BiffInputStream& rStrm );
1922     bool                importExpToken( BiffInputStream& rStrm );
1923     bool                importTblToken( BiffInputStream& rStrm );
1924 
1925     bool                importNlrAddrToken( BiffInputStream& rStrm, bool bRow );
1926     bool                importNlrRangeToken( BiffInputStream& rStrm );
1927     bool                importNlrSAddrToken( BiffInputStream& rStrm, bool bRow );
1928     bool                importNlrSRangeToken( BiffInputStream& rStrm );
1929     bool                importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nSkip );
1930 
1931     sal_Int32           readRefId( BiffInputStream& rStrm );
1932     sal_uInt16          readNameId( BiffInputStream& rStrm );
1933     LinkSheetRange      readSheetRange5( BiffInputStream& rStrm );
1934     LinkSheetRange      readSheetRange8( BiffInputStream& rStrm );
1935 
1936     void                swapStreamPosition( BiffInputStream& rStrm );
1937     void                skipMemAreaAddData( BiffInputStream& rStrm );
1938     bool                readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow );
1939     bool                readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm );
1940 
1941     // convert BIFF token and push API operand or operator --------------------
1942 
1943     bool                pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
1944     bool                pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
1945     bool                pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow );
1946     bool                pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange );
1947     bool                pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow );
1948     bool                pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow );
1949     bool                pushBiffName( sal_uInt16 nNameId );
1950     bool                pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId );
1951     bool                pushBiffFunction( sal_uInt16 nFuncId );
1952     bool                pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount );
1953 
1954     // ------------------------------------------------------------------------
1955 private:
1956     typedef bool (BiffFormulaParserImpl::*ImportTokenFunc)( BiffInputStream& );
1957     typedef bool (BiffFormulaParserImpl::*ImportRefTokenFunc)( BiffInputStream&, bool, bool );
1958 
1959     ImportTokenFunc     mpImportStrToken;           /// Pointer to tStr import function (string constant).
1960     ImportTokenFunc     mpImportSpaceToken;         /// Pointer to tAttrSpace import function (spaces/line breaks).
1961     ImportTokenFunc     mpImportSheetToken;         /// Pointer to tSheet import function (external reference).
1962     ImportTokenFunc     mpImportEndSheetToken;      /// Pointer to tEndSheet import function (end of external reference).
1963     ImportTokenFunc     mpImportNlrToken;           /// Pointer to tNlr import function (natural language reference).
1964     ImportRefTokenFunc  mpImportRefToken;           /// Pointer to tRef import function (2d cell reference).
1965     ImportRefTokenFunc  mpImportAreaToken;          /// Pointer to tArea import function (2d area reference).
1966     ImportRefTokenFunc  mpImportRef3dToken;         /// Pointer to tRef3d import function (3d cell reference).
1967     ImportRefTokenFunc  mpImportArea3dToken;        /// Pointer to tArea3d import function (3d area reference).
1968     ImportTokenFunc     mpImportNameXToken;         /// Pointer to tNameX import function (external name).
1969     ImportTokenFunc     mpImportFuncToken;          /// Pointer to tFunc import function (function with fixed parameter count).
1970     ImportTokenFunc     mpImportFuncVarToken;       /// Pointer to tFuncVar import function (function with variable parameter count).
1971     ImportTokenFunc     mpImportFuncCEToken;        /// Pointer to tFuncCE import function (command macro call).
1972     sal_Int64           mnAddDataPos;               /// Current stream position for additional data (tArray, tMemArea, tNlr).
1973     sal_Int32           mnCurrRefId;                /// Current ref-id from tSheet token (BIFF2-BIFF4 only).
1974     sal_uInt16          mnAttrDataSize;             /// Size of one tAttr data element.
1975     sal_uInt16          mnArraySize;                /// Size of tArray data.
1976     sal_uInt16          mnNameSize;                 /// Size of tName data.
1977     sal_uInt16          mnMemAreaSize;              /// Size of tMemArea data.
1978     sal_uInt16          mnMemFuncSize;              /// Size of tMemFunc data.
1979     sal_uInt16          mnRefIdSize;                /// Size of unused data following a reference identifier.
1980 };
1981 
1982 // ----------------------------------------------------------------------------
1983 
1984 BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
1985     FormulaParserImpl( rParent ),
1986     mnAddDataPos( 0 ),
1987     mnCurrRefId( 0 )
1988 {
1989     switch( getBiff() )
1990     {
1991         case BIFF2:
1992             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
1993             mpImportSpaceToken = &BiffFormulaParserImpl::importTokenNotAvailable;
1994             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken2;
1995             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken2;
1996             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
1997             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
1998             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
1999             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2000             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2001             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2002             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
2003             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
2004             mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
2005             mnAttrDataSize = 1;
2006             mnArraySize = 6;
2007             mnNameSize = 5;
2008             mnMemAreaSize = 4;
2009             mnMemFuncSize = 1;
2010             mnRefIdSize = 1;
2011         break;
2012         case BIFF3:
2013             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
2014             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken3;
2015             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3;
2016             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3;
2017             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2018             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
2019             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
2020             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2021             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2022             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2023             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
2024             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
2025             mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
2026             mnAttrDataSize = 2;
2027             mnArraySize = 7;
2028             mnNameSize = 8;
2029             mnMemAreaSize = 6;
2030             mnMemFuncSize = 2;
2031             mnRefIdSize = 2;
2032         break;
2033         case BIFF4:
2034             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
2035             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
2036             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3;
2037             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3;
2038             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2039             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
2040             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
2041             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2042             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
2043             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2044             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
2045             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
2046             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2047             mnAttrDataSize = 2;
2048             mnArraySize = 7;
2049             mnNameSize = 8;
2050             mnMemAreaSize = 6;
2051             mnMemFuncSize = 2;
2052             mnRefIdSize = 2;
2053         break;
2054         case BIFF5:
2055             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
2056             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
2057             mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2058             mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2059             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2060             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
2061             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
2062             mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken5;
2063             mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken5;
2064             mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken;
2065             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
2066             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
2067             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2068             mnAttrDataSize = 2;
2069             mnArraySize = 7;
2070             mnNameSize = 12;
2071             mnMemAreaSize = 6;
2072             mnMemFuncSize = 2;
2073             mnRefIdSize = 8;
2074         break;
2075         case BIFF8:
2076             mpImportStrToken = &BiffFormulaParserImpl::importStrToken8;
2077             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
2078             mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2079             mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2080             mpImportNlrToken = &BiffFormulaParserImpl::importNlrToken;
2081             mpImportRefToken = &BiffFormulaParserImpl::importRefToken8;
2082             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken8;
2083             mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken8;
2084             mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken8;
2085             mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken;
2086             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
2087             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
2088             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
2089             mnAttrDataSize = 2;
2090             mnArraySize = 7;
2091             mnNameSize = 2;
2092             mnMemAreaSize = 6;
2093             mnMemFuncSize = 2;
2094             mnRefIdSize = 0;
2095         break;
2096         case BIFF_UNKNOWN: break;
2097     }
2098 }
2099 
2100 ApiTokenSequence BiffFormulaParserImpl::importBiffFormula( const CellAddress& rBaseAddr,
2101         FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
2102 {
2103     initializeImport( rBaseAddr, eType );
2104     mnCurrRefId = 0;
2105 
2106     sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize );
2107     sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize;
2108 
2109     bool bOk = true;
2110     while( bOk && !rStrm.isEof() && (rStrm.tell() < nEndPos) )
2111     {
2112         sal_uInt8 nTokenId;
2113         rStrm >> nTokenId;
2114         sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK;
2115         sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK;
2116 
2117         bOk = !getFlag( nTokenId, BIFF_TOKFLAG_INVALID );
2118         if( bOk )
2119         {
2120             if( nTokenClass == BIFF_TOKCLASS_NONE )
2121             {
2122                 // base tokens
2123                 switch( nBaseId )
2124                 {
2125                     case BIFF_TOKID_EXP:        bOk = importExpToken( rStrm );                          break;
2126                     case BIFF_TOKID_TBL:        bOk = importTblToken( rStrm );                          break;
2127                     case BIFF_TOKID_ADD:        bOk = pushBinaryOperator( OPCODE_ADD );                 break;
2128                     case BIFF_TOKID_SUB:        bOk = pushBinaryOperator( OPCODE_SUB );                 break;
2129                     case BIFF_TOKID_MUL:        bOk = pushBinaryOperator( OPCODE_MULT );                break;
2130                     case BIFF_TOKID_DIV:        bOk = pushBinaryOperator( OPCODE_DIV );                 break;
2131                     case BIFF_TOKID_POWER:      bOk = pushBinaryOperator( OPCODE_POWER );               break;
2132                     case BIFF_TOKID_CONCAT:     bOk = pushBinaryOperator( OPCODE_CONCAT );              break;
2133                     case BIFF_TOKID_LT:         bOk = pushBinaryOperator( OPCODE_LESS );                break;
2134                     case BIFF_TOKID_LE:         bOk = pushBinaryOperator( OPCODE_LESS_EQUAL );          break;
2135                     case BIFF_TOKID_EQ:         bOk = pushBinaryOperator( OPCODE_EQUAL );               break;
2136                     case BIFF_TOKID_GE:         bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL );       break;
2137                     case BIFF_TOKID_GT:         bOk = pushBinaryOperator( OPCODE_GREATER );             break;
2138                     case BIFF_TOKID_NE:         bOk = pushBinaryOperator( OPCODE_NOT_EQUAL );           break;
2139                     case BIFF_TOKID_ISECT:      bOk = pushBinaryOperator( OPCODE_INTERSECT );           break;
2140                     case BIFF_TOKID_LIST:       bOk = pushBinaryOperator( OPCODE_LIST );                break;
2141                     case BIFF_TOKID_RANGE:      bOk = pushBinaryOperator( OPCODE_RANGE );               break;
2142                     case BIFF_TOKID_UPLUS:      bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN );         break;
2143                     case BIFF_TOKID_UMINUS:     bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN );        break;
2144                     case BIFF_TOKID_PERCENT:    bOk = pushUnaryPostOperator( OPCODE_PERCENT );          break;
2145                     case BIFF_TOKID_PAREN:      bOk = pushParenthesesOperator();                        break;
2146                     case BIFF_TOKID_MISSARG:    bOk = pushOperand( OPCODE_MISSING );                    break;
2147                     case BIFF_TOKID_STR:        bOk = (this->*mpImportStrToken)( rStrm );               break;
2148                     case BIFF_TOKID_NLR:        bOk = (this->*mpImportNlrToken)( rStrm );               break;
2149                     case BIFF_TOKID_ATTR:       bOk = importAttrToken( rStrm );                         break;
2150                     case BIFF_TOKID_SHEET:      bOk = (this->*mpImportSheetToken)( rStrm );             break;
2151                     case BIFF_TOKID_ENDSHEET:   bOk = (this->*mpImportEndSheetToken)( rStrm );          break;
2152                     case BIFF_TOKID_ERR:        bOk = pushBiffErrorOperand( rStrm.readuInt8() );        break;
2153                     case BIFF_TOKID_BOOL:       bOk = pushBiffBoolOperand( rStrm.readuInt8() );         break;
2154                     case BIFF_TOKID_INT:        bOk = pushValueOperand< double >( rStrm.readuInt16() ); break;
2155                     case BIFF_TOKID_NUM:        bOk = pushValueOperand( rStrm.readDouble() );           break;
2156                     default:                    bOk = false;
2157                 }
2158             }
2159             else
2160             {
2161                 // classified tokens
2162                 switch( nBaseId )
2163                 {
2164                     case BIFF_TOKID_ARRAY:      bOk = importArrayToken( rStrm );                                        break;
2165                     case BIFF_TOKID_FUNC:       bOk = (this->*mpImportFuncToken)( rStrm );                              break;
2166                     case BIFF_TOKID_FUNCVAR:    bOk = (this->*mpImportFuncVarToken)( rStrm );                           break;
2167                     case BIFF_TOKID_NAME:       bOk = importNameToken( rStrm );                                         break;
2168                     case BIFF_TOKID_REF:        bOk = (this->*mpImportRefToken)( rStrm, false, false );                 break;
2169                     case BIFF_TOKID_AREA:       bOk = (this->*mpImportAreaToken)( rStrm, false, false );                break;
2170                     case BIFF_TOKID_MEMAREA:    bOk = importMemAreaToken( rStrm, true );                                break;
2171                     case BIFF_TOKID_MEMERR:     bOk = importMemAreaToken( rStrm, false );                               break;
2172                     case BIFF_TOKID_MEMNOMEM:   bOk = importMemAreaToken( rStrm, false );                               break;
2173                     case BIFF_TOKID_MEMFUNC:    bOk = importMemFuncToken( rStrm );                                      break;
2174                     case BIFF_TOKID_REFERR:     bOk = (this->*mpImportRefToken)( rStrm, true, false );                  break;
2175                     case BIFF_TOKID_AREAERR:    bOk = (this->*mpImportAreaToken)( rStrm, true, false );                 break;
2176                     case BIFF_TOKID_REFN:       bOk = (this->*mpImportRefToken)( rStrm, false, true );                  break;
2177                     case BIFF_TOKID_AREAN:      bOk = (this->*mpImportAreaToken)( rStrm, false, true );                 break;
2178                     case BIFF_TOKID_MEMAREAN:   bOk = importMemFuncToken( rStrm );                                      break;
2179                     case BIFF_TOKID_MEMNOMEMN:  bOk = importMemFuncToken( rStrm );                                      break;
2180                     case BIFF_TOKID_FUNCCE:     bOk = (this->*mpImportFuncCEToken)( rStrm );                            break;
2181                     case BIFF_TOKID_NAMEX:      bOk = (this->*mpImportNameXToken)( rStrm );                             break;
2182                     case BIFF_TOKID_REF3D:      bOk = (this->*mpImportRef3dToken)( rStrm, false, mbRelativeAsOffset );  break;
2183                     case BIFF_TOKID_AREA3D:     bOk = (this->*mpImportArea3dToken)( rStrm, false, mbRelativeAsOffset ); break;
2184                     case BIFF_TOKID_REFERR3D:   bOk = (this->*mpImportRef3dToken)( rStrm, true, mbRelativeAsOffset );   break;
2185                     case BIFF_TOKID_AREAERR3D:  bOk = (this->*mpImportArea3dToken)( rStrm, true, mbRelativeAsOffset );  break;
2186                     default:                    bOk = false;
2187                 }
2188             }
2189         }
2190     }
2191 
2192     // build and finalize the token sequence
2193     ApiTokenSequence aFinalTokens;
2194     if( bOk && (rStrm.tell() == nEndPos) )
2195         aFinalTokens = finalizeImport();
2196 
2197     // seek behind additional token data of tArray, tMemArea, tNlr tokens
2198     rStrm.seek( mnAddDataPos );
2199 
2200     // return the final token sequence
2201     return aFinalTokens;
2202 }
2203 
2204 // import token contents and create API formula token -------------------------
2205 
2206 bool BiffFormulaParserImpl::importTokenNotAvailable( BiffInputStream& )
2207 {
2208     // dummy function for pointer-to-member-function
2209     return false;
2210 }
2211 
2212 bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool )
2213 {
2214     // dummy function for pointer-to-member-function
2215     return false;
2216 }
2217 
2218 bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm )
2219 {
2220     return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ) );
2221 }
2222 
2223 bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm )
2224 {
2225     // read flags field for empty strings also
2226     return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), mbAllowNulChars ) );
2227 }
2228 
2229 bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm )
2230 {
2231     bool bOk = true;
2232     sal_uInt8 nType;
2233     rStrm >> nType;
2234     switch( nType )
2235     {
2236         case 0:     // sometimes, tAttrSkip tokens miss the type flag
2237         case BIFF_TOK_ATTR_VOLATILE:
2238         case BIFF_TOK_ATTR_IF:
2239         case BIFF_TOK_ATTR_SKIP:
2240         case BIFF_TOK_ATTR_ASSIGN:
2241             rStrm.skip( mnAttrDataSize );
2242         break;
2243         case BIFF_TOK_ATTR_CHOOSE:
2244             rStrm.skip( mnAttrDataSize * (1 + ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16())) );
2245         break;
2246         case BIFF_TOK_ATTR_SUM:
2247             rStrm.skip( mnAttrDataSize );
2248             bOk = pushBiffFunction( BIFF_FUNC_SUM, 1 );
2249         break;
2250         case BIFF_TOK_ATTR_SPACE:
2251         case BIFF_TOK_ATTR_SPACE_VOLATILE:
2252             bOk = (this->*mpImportSpaceToken)( rStrm );
2253         break;
2254         default:
2255             bOk = false;
2256     }
2257     return bOk;
2258 }
2259 
2260 bool BiffFormulaParserImpl::importSpaceToken3( BiffInputStream& rStrm )
2261 {
2262     rStrm.skip( 2 );
2263     return true;
2264 }
2265 
2266 bool BiffFormulaParserImpl::importSpaceToken4( BiffInputStream& rStrm )
2267 {
2268     sal_uInt8 nType, nCount;
2269     rStrm >> nType >> nCount;
2270     switch( nType )
2271     {
2272         case BIFF_TOK_ATTR_SPACE_SP:
2273             appendLeadingSpaces( nCount, false );
2274         break;
2275         case BIFF_TOK_ATTR_SPACE_BR:
2276             appendLeadingSpaces( nCount, true );
2277         break;
2278         case BIFF_TOK_ATTR_SPACE_SP_OPEN:
2279             appendOpeningSpaces( nCount, false );
2280         break;
2281         case BIFF_TOK_ATTR_SPACE_BR_OPEN:
2282             appendOpeningSpaces( nCount, true );
2283         break;
2284         case BIFF_TOK_ATTR_SPACE_SP_CLOSE:
2285             appendClosingSpaces( nCount, false );
2286         break;
2287         case BIFF_TOK_ATTR_SPACE_BR_CLOSE:
2288             appendClosingSpaces( nCount, true );
2289         break;
2290     }
2291     return true;
2292 }
2293 
2294 bool BiffFormulaParserImpl::importSheetToken2( BiffInputStream& rStrm )
2295 {
2296     rStrm.skip( 4 );
2297     mnCurrRefId = readRefId( rStrm );
2298     return true;
2299 }
2300 
2301 bool BiffFormulaParserImpl::importSheetToken3( BiffInputStream& rStrm )
2302 {
2303     rStrm.skip( 6 );
2304     mnCurrRefId = readRefId( rStrm );
2305     return true;
2306 }
2307 
2308 bool BiffFormulaParserImpl::importEndSheetToken2( BiffInputStream& rStrm )
2309 {
2310     rStrm.skip( 3 );
2311     mnCurrRefId = 0;
2312     return true;
2313 }
2314 
2315 bool BiffFormulaParserImpl::importEndSheetToken3( BiffInputStream& rStrm )
2316 {
2317     rStrm.skip( 4 );
2318     mnCurrRefId = 0;
2319     return true;
2320 }
2321 
2322 bool BiffFormulaParserImpl::importNlrToken( BiffInputStream& rStrm )
2323 {
2324     bool bOk = true;
2325     sal_uInt8 nNlrType;
2326     rStrm >> nNlrType;
2327     switch( nNlrType )
2328     {
2329         case BIFF_TOK_NLR_ERR:      bOk = importNlrErrToken( rStrm, 4 );        break;
2330         case BIFF_TOK_NLR_ROWR:     bOk = importNlrAddrToken( rStrm, true );    break;
2331         case BIFF_TOK_NLR_COLR:     bOk = importNlrAddrToken( rStrm, false );   break;
2332         case BIFF_TOK_NLR_ROWV:     bOk = importNlrAddrToken( rStrm, true );    break;
2333         case BIFF_TOK_NLR_COLV:     bOk = importNlrAddrToken( rStrm, false );   break;
2334         case BIFF_TOK_NLR_RANGE:    bOk = importNlrRangeToken( rStrm );         break;
2335         case BIFF_TOK_NLR_SRANGE:   bOk = importNlrSRangeToken( rStrm );        break;
2336         case BIFF_TOK_NLR_SROWR:    bOk = importNlrSAddrToken( rStrm, true );   break;
2337         case BIFF_TOK_NLR_SCOLR:    bOk = importNlrSAddrToken( rStrm, false );  break;
2338         case BIFF_TOK_NLR_SROWV:    bOk = importNlrSAddrToken( rStrm, true );   break;
2339         case BIFF_TOK_NLR_SCOLV:    bOk = importNlrSAddrToken( rStrm, false );  break;
2340         case BIFF_TOK_NLR_RANGEERR: bOk = importNlrErrToken( rStrm, 13 );       break;
2341         case BIFF_TOK_NLR_SXNAME:   bOk = importNlrErrToken( rStrm, 4 );        break;
2342         default:                    bOk = false;
2343     }
2344     return bOk;
2345 }
2346 
2347 bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm )
2348 {
2349     rStrm.skip( mnArraySize );
2350 
2351     // start token array with opening brace and leading spaces
2352     pushOperand( OPCODE_ARRAY_OPEN );
2353     size_t nOpSize = popOperandSize();
2354     size_t nOldArraySize = getFormulaSize();
2355     bool bBiff8 = getBiff() == BIFF8;
2356 
2357     // read array size
2358     swapStreamPosition( rStrm );
2359     sal_uInt16 nCols = rStrm.readuInt8();
2360     sal_uInt16 nRows = rStrm.readuInt16();
2361     if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256;
2362     OSL_ENSURE( (nCols > 0) && (nRows > 0), "BiffFormulaParserImpl::importArrayToken - empty array" );
2363 
2364     // read array values and build token array
2365     for( sal_uInt16 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow )
2366     {
2367         if( nRow > 0 )
2368             appendRawToken( OPCODE_ARRAY_ROWSEP );
2369         for( sal_uInt16 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol )
2370         {
2371             if( nCol > 0 )
2372                 appendRawToken( OPCODE_ARRAY_COLSEP );
2373             switch( rStrm.readuInt8() )
2374             {
2375                 case BIFF_DATATYPE_EMPTY:
2376                     appendRawToken( OPCODE_PUSH ) <<= OUString();
2377                     rStrm.skip( 8 );
2378                 break;
2379                 case BIFF_DATATYPE_DOUBLE:
2380                     appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble();
2381                 break;
2382                 case BIFF_DATATYPE_STRING:
2383                     appendRawToken( OPCODE_PUSH ) <<= bBiff8 ?
2384                         rStrm.readUniString( mbAllowNulChars ) :
2385                         rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars );
2386                 break;
2387                 case BIFF_DATATYPE_BOOL:
2388                     appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 );
2389                     rStrm.skip( 7 );
2390                 break;
2391                 case BIFF_DATATYPE_ERROR:
2392                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() );
2393                     rStrm.skip( 7 );
2394                 break;
2395                 default:
2396                     OSL_ENSURE( false, "BiffFormulaParserImpl::importArrayToken - unknown data type" );
2397                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA );
2398             }
2399         }
2400     }
2401     swapStreamPosition( rStrm );
2402 
2403     // close token array and set resulting operand size
2404     appendRawToken( OPCODE_ARRAY_CLOSE );
2405     pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize );
2406     return true;
2407 }
2408 
2409 bool BiffFormulaParserImpl::importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2410 {
2411     BinSingleRef2d aRef;
2412     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
2413     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
2414 }
2415 
2416 bool BiffFormulaParserImpl::importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2417 {
2418     BinSingleRef2d aRef;
2419     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
2420     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
2421 }
2422 
2423 bool BiffFormulaParserImpl::importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2424 {
2425     BinComplexRef2d aRef;
2426     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
2427     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
2428 }
2429 
2430 bool BiffFormulaParserImpl::importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2431 {
2432     BinComplexRef2d aRef;
2433     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
2434     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
2435 }
2436 
2437 bool BiffFormulaParserImpl::importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2438 {
2439     LinkSheetRange aSheetRange = readSheetRange5( rStrm );
2440     BinSingleRef2d aRef;
2441     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
2442     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
2443 }
2444 
2445 bool BiffFormulaParserImpl::importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2446 {
2447     LinkSheetRange aSheetRange = readSheetRange8( rStrm );
2448     BinSingleRef2d aRef;
2449     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
2450     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
2451 }
2452 
2453 bool BiffFormulaParserImpl::importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2454 {
2455     LinkSheetRange aSheetRange = readSheetRange5( rStrm );
2456     BinComplexRef2d aRef;
2457     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
2458     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
2459 }
2460 
2461 bool BiffFormulaParserImpl::importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
2462 {
2463     LinkSheetRange aSheetRange = readSheetRange8( rStrm );
2464     BinComplexRef2d aRef;
2465     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
2466     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
2467 }
2468 
2469 bool BiffFormulaParserImpl::importMemAreaToken( BiffInputStream& rStrm, bool bAddData )
2470 {
2471     rStrm.skip( mnMemAreaSize );
2472     if( bAddData )
2473         skipMemAreaAddData( rStrm );
2474     return true;
2475 }
2476 
2477 bool BiffFormulaParserImpl::importMemFuncToken( BiffInputStream& rStrm )
2478 {
2479     rStrm.skip( mnMemFuncSize );
2480     return true;
2481 }
2482 
2483 bool BiffFormulaParserImpl::importNameToken( BiffInputStream& rStrm )
2484 {
2485     sal_uInt16 nNameId = readNameId( rStrm );
2486     return (mnCurrRefId > 0) ? pushBiffExtName( mnCurrRefId, nNameId ) : pushBiffName( nNameId );
2487 }
2488 
2489 bool BiffFormulaParserImpl::importNameXToken( BiffInputStream& rStrm )
2490 {
2491     sal_Int32 nRefId = readRefId( rStrm );
2492     sal_uInt16 nNameId = readNameId( rStrm );
2493     return pushBiffExtName( nRefId, nNameId );
2494 }
2495 
2496 bool BiffFormulaParserImpl::importFuncToken2( BiffInputStream& rStrm )
2497 {
2498     sal_uInt8 nFuncId;
2499     rStrm >> nFuncId;
2500     return pushBiffFunction( nFuncId );
2501 }
2502 
2503 bool BiffFormulaParserImpl::importFuncToken4( BiffInputStream& rStrm )
2504 {
2505     sal_uInt16 nFuncId;
2506     rStrm >> nFuncId;
2507     return pushBiffFunction( nFuncId );
2508 }
2509 
2510 bool BiffFormulaParserImpl::importFuncVarToken2( BiffInputStream& rStrm )
2511 {
2512     sal_uInt8 nParamCount, nFuncId;
2513     rStrm >> nParamCount >> nFuncId;
2514     return pushBiffFunction( nFuncId, nParamCount );
2515 }
2516 
2517 bool BiffFormulaParserImpl::importFuncVarToken4( BiffInputStream& rStrm )
2518 {
2519     sal_uInt8 nParamCount;
2520     sal_uInt16 nFuncId;
2521     rStrm >> nParamCount >> nFuncId;
2522     return pushBiffFunction( nFuncId, nParamCount & BIFF_TOK_FUNCVAR_COUNTMASK );
2523 }
2524 
2525 bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm )
2526 {
2527     sal_uInt8 nParamCount, nFuncId;
2528     rStrm >> nParamCount >> nFuncId;
2529     sal_uInt16 nCmdId = nFuncId;
2530     setFlag( nCmdId, BIFF_TOK_FUNCVAR_CMD );
2531     return pushBiffFunction( nCmdId, nParamCount );
2532 }
2533 
2534 bool BiffFormulaParserImpl::importExpToken( BiffInputStream& rStrm )
2535 {
2536     BinAddress aBaseAddr;
2537     aBaseAddr.read( rStrm );
2538     return pushSpecialTokenOperand( aBaseAddr, false );
2539 }
2540 
2541 bool BiffFormulaParserImpl::importTblToken( BiffInputStream& rStrm )
2542 {
2543     BinAddress aBaseAddr;
2544     aBaseAddr.read( rStrm );
2545     return pushSpecialTokenOperand( aBaseAddr, true );
2546 }
2547 
2548 bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow )
2549 {
2550     BiffNlr aNlr;
2551     aNlr.readBiff8Data( rStrm );
2552     return pushBiffNlrAddr( aNlr, bRow );
2553 }
2554 
2555 bool BiffFormulaParserImpl::importNlrRangeToken( BiffInputStream& rStrm )
2556 {
2557     BiffNlr aNlr;
2558     aNlr.readBiff8Data( rStrm );
2559     rStrm.skip( 1 );
2560     BinRange aRange;
2561     rStrm >> aRange;
2562     return pushBiffNlrRange( aNlr, aRange );
2563 }
2564 
2565 bool BiffFormulaParserImpl::importNlrSAddrToken( BiffInputStream& rStrm, bool bRow )
2566 {
2567     rStrm.skip( 4 );
2568     BiffNlr aNlr;
2569     return readNlrSAddrAddData( aNlr, rStrm, bRow ) ? pushBiffNlrSAddr( aNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
2570 }
2571 
2572 bool BiffFormulaParserImpl::importNlrSRangeToken( BiffInputStream& rStrm )
2573 {
2574     rStrm.skip( 5 );
2575     BinRange aRange;
2576     rStrm >> aRange;
2577     BiffNlr aNlr;
2578     bool bRow;
2579     return readNlrSRangeAddData( aNlr, bRow, rStrm ) ? pushBiffNlrSRange( aNlr, aRange, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
2580 }
2581 
2582 bool BiffFormulaParserImpl::importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nIgnore )
2583 {
2584     rStrm.skip( nIgnore );
2585     return pushBiffErrorOperand( BIFF_ERR_NAME );
2586 }
2587 
2588 sal_Int32 BiffFormulaParserImpl::readRefId( BiffInputStream& rStrm )
2589 {
2590     sal_Int16 nRefId;
2591     rStrm >> nRefId;
2592     rStrm.skip( mnRefIdSize );
2593     return nRefId;
2594 }
2595 
2596 sal_uInt16 BiffFormulaParserImpl::readNameId( BiffInputStream& rStrm )
2597 {
2598     sal_uInt16 nNameId;
2599     rStrm >> nNameId;
2600     rStrm.skip( mnNameSize );
2601     return nNameId;
2602 }
2603 
2604 LinkSheetRange BiffFormulaParserImpl::readSheetRange5( BiffInputStream& rStrm )
2605 {
2606     sal_Int32 nRefId = readRefId( rStrm );
2607     sal_Int16 nTab1, nTab2;
2608     rStrm >> nTab1 >> nTab2;
2609     return getExternalLinks().getSheetRange( nRefId, nTab1, nTab2 );
2610 }
2611 
2612 LinkSheetRange BiffFormulaParserImpl::readSheetRange8( BiffInputStream& rStrm )
2613 {
2614     return getExternalLinks().getSheetRange( readRefId( rStrm ) );
2615 }
2616 
2617 void BiffFormulaParserImpl::swapStreamPosition( BiffInputStream& rStrm )
2618 {
2619     sal_Int64 nRecPos = rStrm.tell();
2620     rStrm.seek( mnAddDataPos );
2621     mnAddDataPos = nRecPos;
2622 }
2623 
2624 void BiffFormulaParserImpl::skipMemAreaAddData( BiffInputStream& rStrm )
2625 {
2626     swapStreamPosition( rStrm );
2627     sal_Int32 nCount = rStrm.readuInt16();
2628     rStrm.skip( ((getBiff() == BIFF8) ? 8 : 6) * nCount );
2629     swapStreamPosition( rStrm );
2630 }
2631 
2632 bool BiffFormulaParserImpl::readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow )
2633 {
2634     bool bIsRow;
2635     return readNlrSRangeAddData( orNlr, bIsRow, rStrm ) && (bIsRow == bRow);
2636 }
2637 
2638 bool BiffFormulaParserImpl::readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm )
2639 {
2640     swapStreamPosition( rStrm );
2641     // read number of cell addresses and relative flag
2642     sal_uInt32 nCount;
2643     rStrm >> nCount;
2644     bool bRel = getFlag( nCount, BIFF_TOK_NLR_ADDREL );
2645     nCount &= BIFF_TOK_NLR_ADDMASK;
2646     sal_Int64 nEndPos = rStrm.tell() + 4 * nCount;
2647     // read list of cell addresses
2648     bool bValid = false;
2649     if( nCount >= 2 )
2650     {
2651         // detect column/row orientation
2652         BinAddress aAddr1, aAddr2;
2653         rStrm >> aAddr1 >> aAddr2;
2654         orbIsRow = aAddr1.mnRow == aAddr2.mnRow;
2655         bValid = lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow );
2656         // read and verify additional cell positions
2657         for( sal_uInt32 nIndex = 2; bValid && (nIndex < nCount); ++nIndex )
2658         {
2659             aAddr1 = aAddr2;
2660             rStrm >> aAddr2;
2661             bValid = !rStrm.isEof() && lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow );
2662         }
2663         // check that last imported position (aAddr2) is not at the end of the sheet
2664         bValid = bValid && (orbIsRow ? (aAddr2.mnCol < mnMaxApiCol) : (aAddr2.mnRow < mnMaxApiRow));
2665         // fill the NLR struct with the last imported position
2666         if( bValid )
2667         {
2668             orNlr.mnCol = aAddr2.mnCol;
2669             orNlr.mnRow = aAddr2.mnRow;
2670             orNlr.mbRel = bRel;
2671         }
2672     }
2673     // seek to end of additional data for this token
2674     rStrm.seek( nEndPos );
2675     swapStreamPosition( rStrm );
2676 
2677     return bValid;
2678 }
2679 
2680 // convert BIFF token and push API operand or operator ------------------------
2681 
2682 bool BiffFormulaParserImpl::pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
2683 {
2684     return (mnCurrRefId > 0) ?
2685         pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) :
2686         pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset );
2687 }
2688 
2689 bool BiffFormulaParserImpl::pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
2690 {
2691     return (mnCurrRefId > 0) ?
2692         pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) :
2693         pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset );
2694 }
2695 
2696 bool BiffFormulaParserImpl::pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow )
2697 {
2698     BinSingleRef2d aRef;
2699     aRef.mnCol = rNlr.mnCol;
2700     aRef.mnRow = rNlr.mnRow;
2701     aRef.mbColRel = !bRow;
2702     aRef.mbRowRel = bRow;
2703     return pushNlrOperand( aRef );
2704 }
2705 
2706 bool BiffFormulaParserImpl::pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange )
2707 {
2708     bool bRow = rNlr.mnRow == rRange.maFirst.mnRow;
2709     return lclIsValidNlrRange( rNlr, rRange, bRow ) ?
2710         pushBiffNlrAddr( rNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
2711 }
2712 
2713 bool BiffFormulaParserImpl::pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow )
2714 {
2715     BinRange aRange;
2716     aRange.maFirst.mnCol = rNlr.mnCol + (bRow ? 1 : 0);
2717     aRange.maFirst.mnRow = rNlr.mnRow + (bRow ? 0 : 1);
2718     aRange.maLast.mnCol = bRow ? mnMaxApiCol : rNlr.mnCol;
2719     aRange.maLast.mnRow = bRow ? rNlr.mnRow : mnMaxApiRow;
2720     return pushBiffNlrSRange( rNlr, aRange, bRow );
2721 }
2722 
2723 bool BiffFormulaParserImpl::pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow )
2724 {
2725     if( lclIsValidNlrRange( rNlr, rRange, bRow ) )
2726     {
2727         BinComplexRef2d aRef;
2728         aRef.maRef1.mnCol = rRange.maFirst.mnCol;
2729         aRef.maRef1.mnRow = rRange.maFirst.mnRow;
2730         aRef.maRef2.mnCol = rRange.maLast.mnCol;
2731         aRef.maRef2.mnRow = rRange.maLast.mnRow;
2732         aRef.maRef1.mbColRel = aRef.maRef2.mbColRel = !bRow && rNlr.mbRel;
2733         aRef.maRef1.mbRowRel = aRef.maRef2.mbRowRel = bRow && rNlr.mbRel;
2734         return pushReferenceOperand( aRef, false, false );
2735     }
2736     return pushBiffErrorOperand( BIFF_ERR_REF );
2737 }
2738 
2739 bool BiffFormulaParserImpl::pushBiffName( sal_uInt16 nNameId )
2740 {
2741     // one-based in BIFF formulas
2742     return pushDefinedNameOperand( getDefinedNames().getByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ) );
2743 }
2744 
2745 bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId )
2746 {
2747     if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
2748     {
2749         if( pExtLink->getLinkType() == LINKTYPE_SELF )
2750             return pushBiffName( nNameId );
2751         // external name indexes are one-based in BIFF
2752         ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 );
2753         return pushExternalNameOperand( xExtName, *pExtLink );
2754     }
2755     return pushBiffErrorOperand( BIFF_ERR_NAME );
2756 }
2757 
2758 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId )
2759 {
2760     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) )
2761         if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount )
2762             return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount );
2763     return pushFunctionOperator( OPCODE_NONAME, 0 );
2764 }
2765 
2766 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount )
2767 {
2768     if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) )
2769         nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK;
2770     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) )
2771         return pushFunctionOperator( *pFuncInfo, nParamCount );
2772     return pushFunctionOperator( OPCODE_NONAME, nParamCount );
2773 }
2774 
2775 // ============================================================================
2776 
2777 namespace {
2778 
2779 /** Extracts the reference identifier and the remaining data from a formula in
2780     the format '[RefID]Remaining'. */
2781 bool lclExtractRefId( sal_Int32& rnRefId, OUString& rRemainder, const OUString& rFormulaString )
2782 {
2783     if( (rFormulaString.getLength() >= 4) && (rFormulaString[ 0 ] == '[') )
2784     {
2785         sal_Int32 nBracketClose = rFormulaString.indexOf( ']', 1 );
2786         if( nBracketClose >= 2 )
2787         {
2788             rnRefId = rFormulaString.copy( 1, nBracketClose - 1 ).toInt32();
2789             rRemainder = rFormulaString.copy( nBracketClose + 1 );
2790             return rRemainder.getLength() > 0;
2791         }
2792     }
2793     return false;
2794 }
2795 
2796 }
2797 
2798 // ----------------------------------------------------------------------------
2799 
2800 FormulaParser::FormulaParser( const WorkbookHelper& rHelper ) :
2801     FormulaProcessorBase( rHelper )
2802 {
2803     switch( getFilterType() )
2804     {
2805         case FILTER_OOXML:  mxImpl.reset( new OoxFormulaParserImpl( *this ) );  break;
2806         case FILTER_BIFF:   mxImpl.reset( new BiffFormulaParserImpl( *this ) ); break;
2807         case FILTER_UNKNOWN: break;
2808     }
2809 }
2810 
2811 FormulaParser::~FormulaParser()
2812 {
2813 }
2814 
2815 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, const OUString& rFormulaString ) const
2816 {
2817     return mxImpl->importOoxFormula( rBaseAddress, rFormulaString );
2818 }
2819 
2820 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, SequenceInputStream& rStrm ) const
2821 {
2822     return mxImpl->importBiff12Formula( rBaseAddress, eType, rStrm );
2823 }
2824 
2825 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const
2826 {
2827     return mxImpl->importBiffFormula( rBaseAddress, eType, rStrm, pnFmlaSize );
2828 }
2829 
2830 ApiTokenSequence FormulaParser::convertBoolToFormula( bool bValue ) const
2831 {
2832     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) )
2833     {
2834         ApiTokenSequence aTokens( 3 );
2835         aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode;
2836         aTokens[ 1 ].OpCode = OPCODE_OPEN;
2837         aTokens[ 2 ].OpCode = OPCODE_CLOSE;
2838         return aTokens;
2839     }
2840     return ApiTokenSequence();
2841 }
2842 
2843 ApiTokenSequence FormulaParser::convertErrorToFormula( sal_uInt8 nErrorCode ) const
2844 {
2845     ApiTokenSequence aTokens( 3 );
2846     // HACK: enclose all error codes into an 1x1 matrix
2847     aTokens[ 0 ].OpCode = OPCODE_ARRAY_OPEN;
2848     aTokens[ 1 ].OpCode = OPCODE_PUSH;
2849     aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode );
2850     aTokens[ 2 ].OpCode = OPCODE_ARRAY_CLOSE;
2851     return aTokens;
2852 }
2853 
2854 ApiTokenSequence FormulaParser::convertNameToFormula( sal_Int32 nTokenIndex ) const
2855 {
2856     if( nTokenIndex < 0 )
2857         return convertErrorToFormula( BIFF_ERR_REF );
2858 
2859     ApiTokenSequence aTokens( 1 );
2860     aTokens[ 0 ].OpCode = OPCODE_NAME;
2861     aTokens[ 0 ].Data <<= nTokenIndex;
2862     return aTokens;
2863 }
2864 
2865 ApiTokenSequence FormulaParser::convertNumberToHyperlink( const OUString& rUrl, double fValue ) const
2866 {
2867     OSL_ENSURE( rUrl.getLength() > 0, "FormulaParser::convertNumberToHyperlink - missing URL" );
2868     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( BIFF_FUNC_HYPERLINK ) )
2869     {
2870         ApiTokenSequence aTokens( 6 );
2871         aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode;
2872         aTokens[ 1 ].OpCode = OPCODE_OPEN;
2873         aTokens[ 2 ].OpCode = OPCODE_PUSH;
2874         aTokens[ 2 ].Data <<= rUrl;
2875         aTokens[ 3 ].OpCode = OPCODE_SEP;
2876         aTokens[ 4 ].OpCode = OPCODE_PUSH;
2877         aTokens[ 4 ].Data <<= fValue;
2878         aTokens[ 5 ].OpCode = OPCODE_CLOSE;
2879         return aTokens;
2880     }
2881     return ApiTokenSequence();
2882 }
2883 
2884 OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString )
2885 {
2886     sal_Int32 nRefId = -1;
2887     OUString aRemainder;
2888     if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() >= 3) &&
2889             (aRemainder[ 0 ] == '!') && (aRemainder[ 1 ] == '\'') && (aRemainder[ aRemainder.getLength() - 1 ] == '\'') )
2890         return mxImpl->resolveOleTarget( nRefId, false );
2891     return OUString();
2892 }
2893 
2894 OUString FormulaParser::importOleTargetLink( SequenceInputStream& rStrm )
2895 {
2896     OUString aTargetLink;
2897     sal_Int32 nFmlaSize = rStrm.readInt32();
2898     sal_Int64 nFmlaEndPos = rStrm.tell() + ::std::max< sal_Int32 >( nFmlaSize, 0 );
2899     if( (nFmlaSize == 7) && (rStrm.getRemaining() >= 7) )
2900     {
2901         sal_uInt8 nToken;
2902         sal_Int16 nRefId;
2903         sal_Int32 nNameId;
2904         rStrm >> nToken >> nRefId >> nNameId;
2905         if( nToken == (BIFF_TOKCLASS_VAL|BIFF_TOKID_NAMEX) )
2906             aTargetLink = mxImpl->resolveOleTarget( nRefId, true );
2907     }
2908     rStrm.seek( nFmlaEndPos );
2909     return aTargetLink;
2910 }
2911 
2912 OUString FormulaParser::importOleTargetLink( BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const
2913 {
2914     OUString aTargetLink;
2915     sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize );
2916     rStrm.skip( nFmlaSize );
2917     return aTargetLink;
2918 }
2919 
2920 OUString FormulaParser::importMacroName( const OUString& rFormulaString )
2921 {
2922     /*  Valid macros are either sheet macros or VBA macros. OOXML and all BIFF
2923         documents store defined names for sheet macros, but OOXML documents do
2924         not store any defined name for VBA macros (while BIFF documents do).
2925         Sheet macros may be defined locally to a sheet, or globally to the
2926         document. As a result, all of the following macro specifiers are valid:
2927 
2928         1) Macros located in the own document:
2929             [0]!MySheetMacro    (global sheet macro 'MySheetMacro')
2930             Macro1!MyMacro      (sheet-local sheet macro 'MyMacro')
2931             [0]!MyVBAProc       (VBA macro 'MyVBAProc')
2932             [0]!Mod1.MyVBAProc  (VBA macro 'MyVBAProc' from code module 'Mod1')
2933 
2934         2) Macros from an external document:
2935             [2]!MySheetMacro    (global external sheet macro 'MySheetMacro')
2936             [2]Macro1!MyMacro   (sheet-local external sheet macro 'MyMacro')
2937             [2]!MyVBAProc       (external VBA macro 'MyVBAProc')
2938             [2]!Mod1.MyVBAProc  (external VBA macro from code module 'Mod1')
2939 
2940         This implementation is only interested in VBA macros from the own
2941         document, ignoring the valid syntax 'Macro1!MyMacro' for sheet-local
2942         sheet macros.
2943      */
2944     sal_Int32 nRefId = -1;
2945     OUString aRemainder;
2946     if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() > 1) && (aRemainder[ 0 ] == '!') )
2947     {
2948         /*  In BIFF12 documents, the reference identifier is always the
2949             one-based index of the external link as it is in OOXML documents
2950             (it is not an index into the list of reference sheets as used in
2951             cell formulas). Index 0 is an implicit placeholder for the own
2952             document. In BIFF12 documents, the reference to the own document is
2953             stored explicitly, mostly at the top of the list, so index 1 may
2954             resolve to the own document too.
2955             Passing 'false' to getExternalLink() specifies to ignore the
2956             reference sheets list (if existing) and to access the list of
2957             external links directly. */
2958         const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, false ).get();
2959         OSL_ENSURE( pExtLink, "FormulaParser::importMacroName - missing link" );
2960         // do not accept macros in external documents (not supported)
2961         if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_SELF) )
2962         {
2963             // ignore sheet macros (defined name for VBA macros may not exist, see above)
2964             OUString aMacroName = aRemainder.copy( 1 );
2965             const DefinedName* pDefName = getDefinedNames().getByModelName( aMacroName ).get();
2966             if( !pDefName || pDefName->isVBName() )
2967                 return aMacroName;
2968         }
2969     }
2970     return OUString();
2971 }
2972 
2973 // ============================================================================
2974 
2975 } // namespace xls
2976 } // namespace oox
2977