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