xref: /trunk/main/sc/source/core/tool/interpr1.cxx (revision 5cd1c82638b65a86a575c9871d07bec79d4064b8)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "scitems.hxx"
30cdf0e10cSrcweir #include <editeng/langitem.hxx>
31cdf0e10cSrcweir #include <svx/algitem.hxx>
32cdf0e10cSrcweir #include <unotools/textsearch.hxx>
33cdf0e10cSrcweir #include <svl/zforlist.hxx>
34cdf0e10cSrcweir #include <svl/zformat.hxx>
35cdf0e10cSrcweir #include <tools/urlobj.hxx>
36cdf0e10cSrcweir #include <unotools/charclass.hxx>
37cdf0e10cSrcweir #include <sfx2/docfile.hxx>
38cdf0e10cSrcweir #include <sfx2/printer.hxx>
39cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
40cdf0e10cSrcweir #include <unotools/transliterationwrapper.hxx>
41cdf0e10cSrcweir #include <rtl/ustring.hxx>
42cdf0e10cSrcweir #include <rtl/logfile.hxx>
43b54ae672SPedro Giffuni #include <rtl/random.h>
4439c2db0bSWang Lei #include <unicode/uchar.h>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include "interpre.hxx"
47cdf0e10cSrcweir #include "patattr.hxx"
48cdf0e10cSrcweir #include "global.hxx"
49cdf0e10cSrcweir #include "document.hxx"
50cdf0e10cSrcweir #include "dociter.hxx"
51cdf0e10cSrcweir #include "cell.hxx"
52cdf0e10cSrcweir #include "scmatrix.hxx"
53cdf0e10cSrcweir #include "docoptio.hxx"
54cdf0e10cSrcweir #include "globstr.hrc"
55cdf0e10cSrcweir #include "attrib.hxx"
56cdf0e10cSrcweir #include "jumpmatrix.hxx"
57cdf0e10cSrcweir 
58cdf0e10cSrcweir #ifndef _COMPHELPER_PROCESSFACTORY_HXX_
59cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
60cdf0e10cSrcweir #endif
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #include <stdlib.h>
63cdf0e10cSrcweir #include <string.h>
64cdf0e10cSrcweir #include <math.h>
65cdf0e10cSrcweir #include <vector>
66cdf0e10cSrcweir #include <memory>
67cdf0e10cSrcweir #include "cellkeytranslator.hxx"
68cdf0e10cSrcweir #include "lookupcache.hxx"
69cdf0e10cSrcweir #include "rangenam.hxx"
70cdf0e10cSrcweir #include "compiler.hxx"
71cdf0e10cSrcweir #include "externalrefmgr.hxx"
72cdf0e10cSrcweir #include "doubleref.hxx"
73cdf0e10cSrcweir #include "queryparam.hxx"
74cdf0e10cSrcweir 
7576ea2deeSPedro Giffuni #include <boost/math/special_functions/acosh.hpp>
7676ea2deeSPedro Giffuni #include <boost/math/special_functions/asinh.hpp>
7776ea2deeSPedro Giffuni #include <boost/math/special_functions/atanh.hpp>
7876ea2deeSPedro Giffuni 
79cdf0e10cSrcweir #define SC_DOUBLE_MAXVALUE  1.7e307
80cdf0e10cSrcweir 
81cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
82cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScInterpreter, 32, 16 )
83cdf0e10cSrcweir 
84cdf0e10cSrcweir ScTokenStack* ScInterpreter::pGlobalStack = NULL;
85cdf0e10cSrcweir sal_Bool ScInterpreter::bGlobalStackInUse = sal_False;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir using namespace formula;
88cdf0e10cSrcweir using ::std::auto_ptr;
89cdf0e10cSrcweir 
90cdf0e10cSrcweir //-----------------------------------------------------------------------------
91cdf0e10cSrcweir // Funktionen
92cdf0e10cSrcweir //-----------------------------------------------------------------------------
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 
ScIfJump()95cdf0e10cSrcweir void ScInterpreter::ScIfJump()
96cdf0e10cSrcweir {
97cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfJump" );
98cdf0e10cSrcweir     const short* pJump = pCur->GetJump();
99cdf0e10cSrcweir     short nJumpCount = pJump[ 0 ];
100cdf0e10cSrcweir     MatrixDoubleRefToMatrix();
101cdf0e10cSrcweir     switch ( GetStackType() )
102cdf0e10cSrcweir     {
103cdf0e10cSrcweir         case svMatrix:
104cdf0e10cSrcweir         {
105cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
106cdf0e10cSrcweir             if ( !pMat )
107cdf0e10cSrcweir                 PushIllegalParameter();
108cdf0e10cSrcweir             else
109cdf0e10cSrcweir             {
110cdf0e10cSrcweir                 FormulaTokenRef xNew;
111cdf0e10cSrcweir                 ScTokenMatrixMap::const_iterator aMapIter;
112cdf0e10cSrcweir                 // DoubleError handled by JumpMatrix
113cdf0e10cSrcweir                 pMat->SetErrorInterpreter( NULL);
114cdf0e10cSrcweir                 SCSIZE nCols, nRows;
115cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows );
116cdf0e10cSrcweir                 if ( nCols == 0 || nRows == 0 )
117cdf0e10cSrcweir                     PushIllegalArgument();
118cdf0e10cSrcweir                 else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
119cdf0e10cSrcweir                                     pCur)) != pTokenMatrixMap->end()))
120cdf0e10cSrcweir                     xNew = (*aMapIter).second;
121cdf0e10cSrcweir                 else
122cdf0e10cSrcweir                 {
123cdf0e10cSrcweir                     ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
124cdf0e10cSrcweir                     for ( SCSIZE nC=0; nC < nCols; ++nC )
125cdf0e10cSrcweir                     {
126cdf0e10cSrcweir                         for ( SCSIZE nR=0; nR < nRows; ++nR )
127cdf0e10cSrcweir                         {
128cdf0e10cSrcweir                             double fVal;
129cdf0e10cSrcweir                             bool bTrue;
130cdf0e10cSrcweir                             ScMatValType nType = 0;
131cdf0e10cSrcweir                             const ScMatrixValue* pMatVal = pMat->Get( nC, nR,
132cdf0e10cSrcweir                                     nType);
133cdf0e10cSrcweir                             bool bIsValue = ScMatrix::IsValueType( nType);
134cdf0e10cSrcweir                             if ( bIsValue )
135cdf0e10cSrcweir                             {
136cdf0e10cSrcweir                                 fVal = pMatVal->fVal;
137cdf0e10cSrcweir                                 bIsValue = ::rtl::math::isFinite( fVal );
138cdf0e10cSrcweir                                 bTrue = bIsValue && (fVal != 0.0);
139cdf0e10cSrcweir                                 if ( bTrue )
140cdf0e10cSrcweir                                     fVal = 1.0;
141cdf0e10cSrcweir                             }
142cdf0e10cSrcweir                             else
143cdf0e10cSrcweir                             {
144cdf0e10cSrcweir                                 // Treat empty and empty path as 0, but string
145cdf0e10cSrcweir                                 // as error.
146cdf0e10cSrcweir                                 bIsValue = !ScMatrix::IsRealStringType( nType);
147cdf0e10cSrcweir                                 bTrue = false;
148cdf0e10cSrcweir                                 fVal = (bIsValue ? 0.0 : CreateDoubleError( errNoValue));
149cdf0e10cSrcweir                             }
150cdf0e10cSrcweir                             if ( bTrue )
151cdf0e10cSrcweir                             {   // TRUE
152cdf0e10cSrcweir                                 if( nJumpCount >= 2 )
153cdf0e10cSrcweir                                 {   // THEN path
154cdf0e10cSrcweir                                     pJumpMat->SetJump( nC, nR, fVal,
155cdf0e10cSrcweir                                             pJump[ 1 ],
156cdf0e10cSrcweir                                             pJump[ nJumpCount ]);
157cdf0e10cSrcweir                                 }
158cdf0e10cSrcweir                                 else
159cdf0e10cSrcweir                                 {   // no parameter given for THEN
160cdf0e10cSrcweir                                     pJumpMat->SetJump( nC, nR, fVal,
161cdf0e10cSrcweir                                             pJump[ nJumpCount ],
162cdf0e10cSrcweir                                             pJump[ nJumpCount ]);
163cdf0e10cSrcweir                                 }
164cdf0e10cSrcweir                             }
165cdf0e10cSrcweir                             else
166cdf0e10cSrcweir                             {   // FALSE
167cdf0e10cSrcweir                                 if( nJumpCount == 3 && bIsValue )
168cdf0e10cSrcweir                                 {   // ELSE path
169cdf0e10cSrcweir                                     pJumpMat->SetJump( nC, nR, fVal,
170cdf0e10cSrcweir                                             pJump[ 2 ],
171cdf0e10cSrcweir                                             pJump[ nJumpCount ]);
172cdf0e10cSrcweir                                 }
173cdf0e10cSrcweir                                 else
174cdf0e10cSrcweir                                 {   // no parameter given for ELSE,
175cdf0e10cSrcweir                                     // or DoubleError
176cdf0e10cSrcweir                                     pJumpMat->SetJump( nC, nR, fVal,
177cdf0e10cSrcweir                                             pJump[ nJumpCount ],
178cdf0e10cSrcweir                                             pJump[ nJumpCount ]);
179cdf0e10cSrcweir                                 }
180cdf0e10cSrcweir                             }
181cdf0e10cSrcweir                         }
182cdf0e10cSrcweir                     }
183cdf0e10cSrcweir                     xNew = new ScJumpMatrixToken( pJumpMat );
184cdf0e10cSrcweir                     GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(pCur, xNew));
185cdf0e10cSrcweir                 }
186cdf0e10cSrcweir                 PushTempToken( xNew);
187cdf0e10cSrcweir                 // set endpoint of path for main code line
188cdf0e10cSrcweir                 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
189cdf0e10cSrcweir             }
190cdf0e10cSrcweir         }
191cdf0e10cSrcweir         break;
192cdf0e10cSrcweir         default:
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             if ( GetBool() )
195cdf0e10cSrcweir             {   // TRUE
196cdf0e10cSrcweir                 if( nJumpCount >= 2 )
197cdf0e10cSrcweir                 {   // THEN path
198cdf0e10cSrcweir                     aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
199cdf0e10cSrcweir                 }
200cdf0e10cSrcweir                 else
201cdf0e10cSrcweir                 {   // no parameter given for THEN
202cdf0e10cSrcweir                     nFuncFmtType = NUMBERFORMAT_LOGICAL;
203cdf0e10cSrcweir                     PushInt(1);
204cdf0e10cSrcweir                     aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
205cdf0e10cSrcweir                 }
206cdf0e10cSrcweir             }
207cdf0e10cSrcweir             else
208cdf0e10cSrcweir             {   // FALSE
209cdf0e10cSrcweir                 if( nJumpCount == 3 )
210cdf0e10cSrcweir                 {   // ELSE path
211cdf0e10cSrcweir                     aCode.Jump( pJump[ 2 ], pJump[ nJumpCount ] );
212cdf0e10cSrcweir                 }
213cdf0e10cSrcweir                 else
214cdf0e10cSrcweir                 {   // no parameter given for ELSE
215cdf0e10cSrcweir                     nFuncFmtType = NUMBERFORMAT_LOGICAL;
216cdf0e10cSrcweir                     PushInt(0);
217cdf0e10cSrcweir                     aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
218cdf0e10cSrcweir                 }
219cdf0e10cSrcweir             }
220cdf0e10cSrcweir         }
221cdf0e10cSrcweir     }
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 
ScChoseJump()225cdf0e10cSrcweir void ScInterpreter::ScChoseJump()
226cdf0e10cSrcweir {
227cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChoseJump" );
228cdf0e10cSrcweir     // We have to set a jump, if there was none chosen because of an error set
229cdf0e10cSrcweir     // it to endpoint.
230cdf0e10cSrcweir     bool bHaveJump = false;
231cdf0e10cSrcweir     const short* pJump = pCur->GetJump();
232cdf0e10cSrcweir     short nJumpCount = pJump[ 0 ];
233cdf0e10cSrcweir     MatrixDoubleRefToMatrix();
234cdf0e10cSrcweir     switch ( GetStackType() )
235cdf0e10cSrcweir     {
236cdf0e10cSrcweir         case svMatrix:
237cdf0e10cSrcweir         {
238cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
239cdf0e10cSrcweir             if ( !pMat )
240cdf0e10cSrcweir                 PushIllegalParameter();
241cdf0e10cSrcweir             else
242cdf0e10cSrcweir             {
243cdf0e10cSrcweir                 FormulaTokenRef xNew;
244cdf0e10cSrcweir                 ScTokenMatrixMap::const_iterator aMapIter;
245cdf0e10cSrcweir                 // DoubleError handled by JumpMatrix
246cdf0e10cSrcweir                 pMat->SetErrorInterpreter( NULL);
247cdf0e10cSrcweir                 SCSIZE nCols, nRows;
248cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows );
249cdf0e10cSrcweir                 if ( nCols == 0 || nRows == 0 )
250cdf0e10cSrcweir                     PushIllegalParameter();
251cdf0e10cSrcweir                 else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
252cdf0e10cSrcweir                                     pCur)) != pTokenMatrixMap->end()))
253cdf0e10cSrcweir                     xNew = (*aMapIter).second;
254cdf0e10cSrcweir                 else
255cdf0e10cSrcweir                 {
256cdf0e10cSrcweir                     ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
257cdf0e10cSrcweir                     for ( SCSIZE nC=0; nC < nCols; ++nC )
258cdf0e10cSrcweir                     {
259cdf0e10cSrcweir                         for ( SCSIZE nR=0; nR < nRows; ++nR )
260cdf0e10cSrcweir                         {
261cdf0e10cSrcweir                             double fVal;
262cdf0e10cSrcweir                             ScMatValType nType;
263cdf0e10cSrcweir                             const ScMatrixValue* pMatVal = pMat->Get( nC, nR,
264cdf0e10cSrcweir                                     nType);
265cdf0e10cSrcweir                             bool bIsValue = ScMatrix::IsValueType( nType);
266cdf0e10cSrcweir                             if ( bIsValue )
267cdf0e10cSrcweir                             {
268cdf0e10cSrcweir                                 fVal = pMatVal->fVal;
269cdf0e10cSrcweir                                 bIsValue = ::rtl::math::isFinite( fVal );
270cdf0e10cSrcweir                                 if ( bIsValue )
271cdf0e10cSrcweir                                 {
272cdf0e10cSrcweir                                     fVal = ::rtl::math::approxFloor( fVal);
273cdf0e10cSrcweir                                     if ( (fVal < 1) || (fVal >= nJumpCount))
274cdf0e10cSrcweir                                     {
275cdf0e10cSrcweir                                         bIsValue = sal_False;
276cdf0e10cSrcweir                                         fVal = CreateDoubleError(
277cdf0e10cSrcweir                                                 errIllegalArgument);
278cdf0e10cSrcweir                                     }
279cdf0e10cSrcweir                                 }
280cdf0e10cSrcweir                             }
281cdf0e10cSrcweir                             else
282cdf0e10cSrcweir                             {
283cdf0e10cSrcweir                                 fVal = CreateDoubleError( errNoValue);
284cdf0e10cSrcweir                             }
285cdf0e10cSrcweir                             if ( bIsValue )
286cdf0e10cSrcweir                             {
287cdf0e10cSrcweir                                 pJumpMat->SetJump( nC, nR, fVal,
288cdf0e10cSrcweir                                         pJump[ (short)fVal ],
289cdf0e10cSrcweir                                         pJump[ nJumpCount ]);
290cdf0e10cSrcweir                             }
291cdf0e10cSrcweir                             else
292cdf0e10cSrcweir                             {
293cdf0e10cSrcweir                                 pJumpMat->SetJump( nC, nR, fVal,
294cdf0e10cSrcweir                                         pJump[ nJumpCount ],
295cdf0e10cSrcweir                                         pJump[ nJumpCount ]);
296cdf0e10cSrcweir                             }
297cdf0e10cSrcweir                         }
298cdf0e10cSrcweir                     }
299cdf0e10cSrcweir                     xNew = new ScJumpMatrixToken( pJumpMat );
300cdf0e10cSrcweir                     GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(
301cdf0e10cSrcweir                                 pCur, xNew));
302cdf0e10cSrcweir                 }
303cdf0e10cSrcweir                 PushTempToken( xNew);
304cdf0e10cSrcweir                 // set endpoint of path for main code line
305cdf0e10cSrcweir                 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
306cdf0e10cSrcweir                 bHaveJump = true;
307cdf0e10cSrcweir             }
308cdf0e10cSrcweir         }
309cdf0e10cSrcweir         break;
310cdf0e10cSrcweir         default:
311cdf0e10cSrcweir         {
312cdf0e10cSrcweir             double nJumpIndex = ::rtl::math::approxFloor( GetDouble() );
313cdf0e10cSrcweir             if (!nGlobalError && (nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
314cdf0e10cSrcweir             {
315cdf0e10cSrcweir                 aCode.Jump( pJump[ (short) nJumpIndex ], pJump[ nJumpCount ] );
316cdf0e10cSrcweir                 bHaveJump = true;
317cdf0e10cSrcweir             }
318cdf0e10cSrcweir             else
319cdf0e10cSrcweir                 PushIllegalArgument();
320cdf0e10cSrcweir         }
321cdf0e10cSrcweir     }
322cdf0e10cSrcweir     if (!bHaveJump)
323cdf0e10cSrcweir         aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
lcl_AdjustJumpMatrix(ScJumpMatrix * pJumpM,ScMatrixRef & pResMat,SCSIZE nParmCols,SCSIZE nParmRows)326cdf0e10cSrcweir void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir     SCSIZE nJumpCols, nJumpRows;
329cdf0e10cSrcweir     SCSIZE nResCols, nResRows;
330cdf0e10cSrcweir     SCSIZE nAdjustCols, nAdjustRows;
331cdf0e10cSrcweir     pJumpM->GetDimensions( nJumpCols, nJumpRows );
332cdf0e10cSrcweir     pJumpM->GetResMatDimensions( nResCols, nResRows );
333cdf0e10cSrcweir     if (( nJumpCols == 1 && nParmCols > nResCols ) ||
334cdf0e10cSrcweir         ( nJumpRows == 1 && nParmRows > nResRows ))
335cdf0e10cSrcweir     {
336cdf0e10cSrcweir         if ( nJumpCols == 1 && nJumpRows == 1 )
337cdf0e10cSrcweir         {
338cdf0e10cSrcweir             nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
339cdf0e10cSrcweir             nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
340cdf0e10cSrcweir         }
341cdf0e10cSrcweir         else if ( nJumpCols == 1 )
342cdf0e10cSrcweir         {
343cdf0e10cSrcweir             nAdjustCols = nParmCols;
344cdf0e10cSrcweir             nAdjustRows = nResRows;
345cdf0e10cSrcweir         }
346cdf0e10cSrcweir         else
347cdf0e10cSrcweir         {
348cdf0e10cSrcweir             nAdjustCols = nResCols;
349cdf0e10cSrcweir             nAdjustRows = nParmRows;
350cdf0e10cSrcweir         }
351cdf0e10cSrcweir         pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
352cdf0e10cSrcweir         pResMat = pJumpM->GetResultMatrix();
353cdf0e10cSrcweir     }
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
JumpMatrix(short nStackLevel)356cdf0e10cSrcweir bool ScInterpreter::JumpMatrix( short nStackLevel )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::JumpMatrix" );
359cdf0e10cSrcweir     pJumpMatrix = static_cast<ScToken*>(pStack[sp-nStackLevel])->GetJumpMatrix();
360cdf0e10cSrcweir     ScMatrixRef pResMat = pJumpMatrix->GetResultMatrix();
361cdf0e10cSrcweir     SCSIZE nC, nR;
362cdf0e10cSrcweir     if ( nStackLevel == 2 )
363cdf0e10cSrcweir     {
364cdf0e10cSrcweir         if ( aCode.HasStacked() )
365cdf0e10cSrcweir             aCode.Pop();    // pop what Jump() pushed
366cdf0e10cSrcweir         else
367cdf0e10cSrcweir         {
368cdf0e10cSrcweir             DBG_ERRORFILE( "ScInterpreter::JumpMatrix: pop goes the weasel" );
369cdf0e10cSrcweir         }
370cdf0e10cSrcweir 
371cdf0e10cSrcweir         if ( !pResMat )
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             Pop();
374cdf0e10cSrcweir             SetError( errUnknownStackVariable );
375cdf0e10cSrcweir         }
376cdf0e10cSrcweir         else
377cdf0e10cSrcweir         {
378cdf0e10cSrcweir             pJumpMatrix->GetPos( nC, nR );
379cdf0e10cSrcweir             switch ( GetStackType() )
380cdf0e10cSrcweir             {
381cdf0e10cSrcweir                 case svDouble:
382cdf0e10cSrcweir                 {
383cdf0e10cSrcweir                     double fVal = GetDouble();
384cdf0e10cSrcweir                     if ( nGlobalError )
385cdf0e10cSrcweir                     {
386cdf0e10cSrcweir                         fVal = CreateDoubleError( nGlobalError );
387cdf0e10cSrcweir                         nGlobalError = 0;
388cdf0e10cSrcweir                     }
389cdf0e10cSrcweir                     pResMat->PutDouble( fVal, nC, nR );
390cdf0e10cSrcweir                 }
391cdf0e10cSrcweir                 break;
392cdf0e10cSrcweir                 case svString:
393cdf0e10cSrcweir                 {
394cdf0e10cSrcweir                     const String& rStr = GetString();
395cdf0e10cSrcweir                     if ( nGlobalError )
396cdf0e10cSrcweir                     {
397cdf0e10cSrcweir                         pResMat->PutDouble( CreateDoubleError( nGlobalError),
398cdf0e10cSrcweir                                 nC, nR);
399cdf0e10cSrcweir                         nGlobalError = 0;
400cdf0e10cSrcweir                     }
401cdf0e10cSrcweir                     else
402cdf0e10cSrcweir                         pResMat->PutString( rStr, nC, nR );
403cdf0e10cSrcweir                 }
404cdf0e10cSrcweir                 break;
405cdf0e10cSrcweir                 case svSingleRef:
406cdf0e10cSrcweir                 {
407cdf0e10cSrcweir                     ScAddress aAdr;
408cdf0e10cSrcweir                     PopSingleRef( aAdr );
409cdf0e10cSrcweir                     if ( nGlobalError )
410cdf0e10cSrcweir                     {
411cdf0e10cSrcweir                         pResMat->PutDouble( CreateDoubleError( nGlobalError),
412cdf0e10cSrcweir                                 nC, nR);
413cdf0e10cSrcweir                         nGlobalError = 0;
414cdf0e10cSrcweir                     }
415cdf0e10cSrcweir                     else
416cdf0e10cSrcweir                     {
417cdf0e10cSrcweir                         ScBaseCell* pCell = GetCell( aAdr );
418cdf0e10cSrcweir                         if (HasCellEmptyData( pCell))
419cdf0e10cSrcweir                             pResMat->PutEmpty( nC, nR );
420cdf0e10cSrcweir                         else if (HasCellValueData( pCell))
421cdf0e10cSrcweir                         {
422cdf0e10cSrcweir                             double fVal = GetCellValue( aAdr, pCell);
423cdf0e10cSrcweir                             if ( nGlobalError )
424cdf0e10cSrcweir                             {
425cdf0e10cSrcweir                                 fVal = CreateDoubleError(
426cdf0e10cSrcweir                                         nGlobalError);
427cdf0e10cSrcweir                                 nGlobalError = 0;
428cdf0e10cSrcweir                             }
429cdf0e10cSrcweir                             pResMat->PutDouble( fVal, nC, nR );
430cdf0e10cSrcweir                         }
431cdf0e10cSrcweir                         else
432cdf0e10cSrcweir                         {
433cdf0e10cSrcweir                             String aStr;
434cdf0e10cSrcweir                             GetCellString( aStr, pCell );
435cdf0e10cSrcweir                             if ( nGlobalError )
436cdf0e10cSrcweir                             {
437cdf0e10cSrcweir                                 pResMat->PutDouble( CreateDoubleError(
438cdf0e10cSrcweir                                             nGlobalError), nC, nR);
439cdf0e10cSrcweir                                 nGlobalError = 0;
440cdf0e10cSrcweir                             }
441cdf0e10cSrcweir                             else
442cdf0e10cSrcweir                                 pResMat->PutString( aStr, nC, nR);
443cdf0e10cSrcweir                         }
444cdf0e10cSrcweir                     }
445cdf0e10cSrcweir                 }
446cdf0e10cSrcweir                 break;
447cdf0e10cSrcweir                 case svDoubleRef:
448cdf0e10cSrcweir                 {   // upper left plus offset within matrix
449cdf0e10cSrcweir                     double fVal;
450cdf0e10cSrcweir                     ScRange aRange;
451cdf0e10cSrcweir                     PopDoubleRef( aRange );
452cdf0e10cSrcweir                     if ( nGlobalError )
453cdf0e10cSrcweir                     {
454cdf0e10cSrcweir                         fVal = CreateDoubleError( nGlobalError );
455cdf0e10cSrcweir                         nGlobalError = 0;
456cdf0e10cSrcweir                         pResMat->PutDouble( fVal, nC, nR );
457cdf0e10cSrcweir                     }
458cdf0e10cSrcweir                     else
459cdf0e10cSrcweir                     {
460cdf0e10cSrcweir                         // Do not modify the original range because we use it
461cdf0e10cSrcweir                         // to adjust the size of the result matrix if necessary.
462cdf0e10cSrcweir                         ScAddress aAdr( aRange.aStart);
463cdf0e10cSrcweir                         sal_uLong nCol = (sal_uLong)aAdr.Col() + nC;
464cdf0e10cSrcweir                         sal_uLong nRow = (sal_uLong)aAdr.Row() + nR;
465cdf0e10cSrcweir                         if ((nCol > static_cast<sal_uLong>(aRange.aEnd.Col()) &&
466cdf0e10cSrcweir                                     aRange.aEnd.Col() != aRange.aStart.Col())
467cdf0e10cSrcweir                                 || (nRow > static_cast<sal_uLong>(aRange.aEnd.Row()) &&
468cdf0e10cSrcweir                                     aRange.aEnd.Row() != aRange.aStart.Row()))
469cdf0e10cSrcweir                           {
470cdf0e10cSrcweir                             fVal = CreateDoubleError( NOTAVAILABLE );
471cdf0e10cSrcweir                             pResMat->PutDouble( fVal, nC, nR );
472cdf0e10cSrcweir                           }
473cdf0e10cSrcweir                           else
474cdf0e10cSrcweir                           {
475cdf0e10cSrcweir                             // Replicate column and/or row of a vector if it is
476cdf0e10cSrcweir                             // one. Note that this could be a range reference
477cdf0e10cSrcweir                             // that in fact consists of only one cell, e.g. A1:A1
478cdf0e10cSrcweir                             if (aRange.aEnd.Col() == aRange.aStart.Col())
479cdf0e10cSrcweir                                 nCol = aRange.aStart.Col();
480cdf0e10cSrcweir                             if (aRange.aEnd.Row() == aRange.aStart.Row())
481cdf0e10cSrcweir                                 nRow = aRange.aStart.Row();
482cdf0e10cSrcweir                             aAdr.SetCol( static_cast<SCCOL>(nCol) );
483cdf0e10cSrcweir                             aAdr.SetRow( static_cast<SCROW>(nRow) );
484cdf0e10cSrcweir                             ScBaseCell* pCell = GetCell( aAdr );
485cdf0e10cSrcweir                             if (HasCellEmptyData( pCell))
486cdf0e10cSrcweir                                 pResMat->PutEmpty( nC, nR );
487cdf0e10cSrcweir                             else if (HasCellValueData( pCell))
488cdf0e10cSrcweir                               {
489cdf0e10cSrcweir                                 double fCellVal = GetCellValue( aAdr, pCell);
490cdf0e10cSrcweir                                 if ( nGlobalError )
491cdf0e10cSrcweir                                 {
492cdf0e10cSrcweir                                     fCellVal = CreateDoubleError(
493cdf0e10cSrcweir                                             nGlobalError);
494cdf0e10cSrcweir                                     nGlobalError = 0;
495cdf0e10cSrcweir                                 }
496cdf0e10cSrcweir                                 pResMat->PutDouble( fCellVal, nC, nR );
497cdf0e10cSrcweir                               }
498cdf0e10cSrcweir                               else
499cdf0e10cSrcweir                             {
500cdf0e10cSrcweir                                 String aStr;
501cdf0e10cSrcweir                                 GetCellString( aStr, pCell );
502cdf0e10cSrcweir                                 if ( nGlobalError )
503cdf0e10cSrcweir                                 {
504cdf0e10cSrcweir                                     pResMat->PutDouble( CreateDoubleError(
505cdf0e10cSrcweir                                                 nGlobalError), nC, nR);
506cdf0e10cSrcweir                                     nGlobalError = 0;
507cdf0e10cSrcweir                                 }
508cdf0e10cSrcweir                                 else
509cdf0e10cSrcweir                                     pResMat->PutString( aStr, nC, nR );
510cdf0e10cSrcweir                             }
511cdf0e10cSrcweir                           }
512cdf0e10cSrcweir                         SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
513cdf0e10cSrcweir                         SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
514cdf0e10cSrcweir                         lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
515cdf0e10cSrcweir                     }
516cdf0e10cSrcweir                 }
517cdf0e10cSrcweir                 break;
518cdf0e10cSrcweir                 case svMatrix:
519cdf0e10cSrcweir                 {   // match matrix offsets
520cdf0e10cSrcweir                     double fVal;
521cdf0e10cSrcweir                     ScMatrixRef pMat = PopMatrix();
522cdf0e10cSrcweir                     if ( nGlobalError )
523cdf0e10cSrcweir                     {
524cdf0e10cSrcweir                         fVal = CreateDoubleError( nGlobalError );
525cdf0e10cSrcweir                         nGlobalError = 0;
526cdf0e10cSrcweir                         pResMat->PutDouble( fVal, nC, nR );
527cdf0e10cSrcweir                     }
528cdf0e10cSrcweir                     else if ( !pMat )
529cdf0e10cSrcweir                     {
530cdf0e10cSrcweir                         fVal = CreateDoubleError( errUnknownVariable );
531cdf0e10cSrcweir                         pResMat->PutDouble( fVal, nC, nR );
532cdf0e10cSrcweir                     }
533cdf0e10cSrcweir                     else
534cdf0e10cSrcweir                     {
535cdf0e10cSrcweir                         SCSIZE nCols, nRows;
536cdf0e10cSrcweir                         pMat->GetDimensions( nCols, nRows );
537cdf0e10cSrcweir                         if ((nCols <= nC && nCols != 1) ||
538cdf0e10cSrcweir                             (nRows <= nR && nRows != 1))
539cdf0e10cSrcweir                         {
540cdf0e10cSrcweir                             fVal = CreateDoubleError( NOTAVAILABLE );
541cdf0e10cSrcweir                             pResMat->PutDouble( fVal, nC, nR );
542cdf0e10cSrcweir                         }
543cdf0e10cSrcweir                         else
544cdf0e10cSrcweir                         {
545cdf0e10cSrcweir                             if ( pMat->IsValue( nC, nR ) )
546cdf0e10cSrcweir                             {
547cdf0e10cSrcweir                                 fVal = pMat->GetDouble( nC, nR );
548cdf0e10cSrcweir                                 pResMat->PutDouble( fVal, nC, nR );
549cdf0e10cSrcweir                             }
550cdf0e10cSrcweir                             else if ( pMat->IsEmpty( nC, nR ) )
551cdf0e10cSrcweir                                 pResMat->PutEmpty( nC, nR );
552cdf0e10cSrcweir                             else
553cdf0e10cSrcweir                             {
554cdf0e10cSrcweir                                 const String& rStr = pMat->GetString( nC, nR );
555cdf0e10cSrcweir                                 pResMat->PutString( rStr, nC, nR );
556cdf0e10cSrcweir                             }
557cdf0e10cSrcweir                         }
558cdf0e10cSrcweir                         lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
559cdf0e10cSrcweir                     }
560cdf0e10cSrcweir                 }
561cdf0e10cSrcweir                 break;
562cdf0e10cSrcweir                 case svError:
563cdf0e10cSrcweir                 {
564cdf0e10cSrcweir                     PopError();
565cdf0e10cSrcweir                     double fVal = CreateDoubleError( nGlobalError);
566cdf0e10cSrcweir                     nGlobalError = 0;
567cdf0e10cSrcweir                     pResMat->PutDouble( fVal, nC, nR );
568cdf0e10cSrcweir                 }
569cdf0e10cSrcweir                 break;
570cdf0e10cSrcweir                 default:
571cdf0e10cSrcweir                 {
572cdf0e10cSrcweir                     Pop();
573cdf0e10cSrcweir                     double fVal = CreateDoubleError( errIllegalArgument);
574cdf0e10cSrcweir                     pResMat->PutDouble( fVal, nC, nR );
575cdf0e10cSrcweir                 }
576cdf0e10cSrcweir             }
577cdf0e10cSrcweir         }
578cdf0e10cSrcweir     }
579cdf0e10cSrcweir     bool bCont = pJumpMatrix->Next( nC, nR );
580cdf0e10cSrcweir     if ( bCont )
581cdf0e10cSrcweir     {
582cdf0e10cSrcweir         double fBool;
583cdf0e10cSrcweir         short nStart, nNext, nStop;
584cdf0e10cSrcweir         pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
585cdf0e10cSrcweir         while ( bCont && nStart == nNext )
586cdf0e10cSrcweir         {   // push all results that have no jump path
587cdf0e10cSrcweir             if ( pResMat )
588cdf0e10cSrcweir             {
589cdf0e10cSrcweir                 // a sal_False without path results in an empty path value
590cdf0e10cSrcweir                 if ( fBool == 0.0 )
591cdf0e10cSrcweir                     pResMat->PutEmptyPath( nC, nR );
592cdf0e10cSrcweir                 else
593cdf0e10cSrcweir                     pResMat->PutDouble( fBool, nC, nR );
594cdf0e10cSrcweir             }
595cdf0e10cSrcweir             bCont = pJumpMatrix->Next( nC, nR );
596cdf0e10cSrcweir             if ( bCont )
597cdf0e10cSrcweir                 pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
598cdf0e10cSrcweir         }
599cdf0e10cSrcweir         if ( bCont && nStart != nNext )
600cdf0e10cSrcweir         {
601cdf0e10cSrcweir             const ScTokenVec* pParams = pJumpMatrix->GetJumpParameters();
602cdf0e10cSrcweir             if ( pParams )
603cdf0e10cSrcweir             {
604cdf0e10cSrcweir                 for ( ScTokenVec::const_iterator i = pParams->begin();
605cdf0e10cSrcweir                         i != pParams->end(); ++i )
606cdf0e10cSrcweir                 {
607cdf0e10cSrcweir                     // This is not the current state of the interpreter, so
608cdf0e10cSrcweir                     // push without error, and elements' errors are coded into
609cdf0e10cSrcweir                     // double.
610cdf0e10cSrcweir                     PushWithoutError( *(*i));
611cdf0e10cSrcweir                 }
612cdf0e10cSrcweir             }
613cdf0e10cSrcweir             aCode.Jump( nStart, nNext, nStop );
614cdf0e10cSrcweir         }
615cdf0e10cSrcweir     }
616cdf0e10cSrcweir     if ( !bCont )
617cdf0e10cSrcweir     {   // we're done with it, throw away jump matrix, keep result
618cdf0e10cSrcweir         pJumpMatrix = NULL;
619cdf0e10cSrcweir         Pop();
620cdf0e10cSrcweir         PushMatrix( pResMat );
621cdf0e10cSrcweir         // Remove jump matrix from map and remember result matrix in case it
622cdf0e10cSrcweir         // could be reused in another path of the same condition.
623cdf0e10cSrcweir         if (pTokenMatrixMap)
624cdf0e10cSrcweir         {
625cdf0e10cSrcweir             pTokenMatrixMap->erase( pCur);
626cdf0e10cSrcweir             pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
627cdf0e10cSrcweir                         pStack[sp-1]));
628cdf0e10cSrcweir         }
629cdf0e10cSrcweir         return true;
630cdf0e10cSrcweir     }
631cdf0e10cSrcweir     return false;
632cdf0e10cSrcweir }
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 
ScCompareOptions(ScDocument * pDoc,const ScQueryEntry & rEntry,bool bReg)635cdf0e10cSrcweir ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
636cdf0e10cSrcweir     aQueryEntry(rEntry),
637cdf0e10cSrcweir     bRegEx(bReg),
638cdf0e10cSrcweir     bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
639cdf0e10cSrcweir     bIgnoreCase(true)
640cdf0e10cSrcweir {
641cdf0e10cSrcweir     bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
642cdf0e10cSrcweir     // Interpreter functions usually are case insensitive, except the simple
643cdf0e10cSrcweir     // comparison operators, for which these options aren't used. Override in
644cdf0e10cSrcweir     // struct if needed.
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir 
CompareFunc(const ScCompare & rComp,ScCompareOptions * pOptions)648cdf0e10cSrcweir double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
649cdf0e10cSrcweir {
650cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareFunc" );
651cdf0e10cSrcweir     // Keep DoubleError if encountered
652cdf0e10cSrcweir     // #i40539# if bEmpty is set, bVal/nVal are uninitialized
653cdf0e10cSrcweir     if ( !rComp.bEmpty[0] && rComp.bVal[0] && !::rtl::math::isFinite( rComp.nVal[0]))
654cdf0e10cSrcweir         return rComp.nVal[0];
655cdf0e10cSrcweir     if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1]))
656cdf0e10cSrcweir         return rComp.nVal[1];
657cdf0e10cSrcweir 
658cdf0e10cSrcweir     size_t nStringQuery = 0;    // 0:=no, 1:=0, 2:=1
659cdf0e10cSrcweir     double fRes = 0;
660cdf0e10cSrcweir     if ( rComp.bEmpty[ 0 ] )
661cdf0e10cSrcweir     {
662cdf0e10cSrcweir         if ( rComp.bEmpty[ 1 ] )
663cdf0e10cSrcweir             ;       // empty cell == empty cell, fRes 0
664cdf0e10cSrcweir         else if( rComp.bVal[ 1 ] )
665cdf0e10cSrcweir         {
666cdf0e10cSrcweir             if ( !::rtl::math::approxEqual( rComp.nVal[ 1 ], 0.0 ) )
667cdf0e10cSrcweir             {
668cdf0e10cSrcweir                 if ( rComp.nVal[ 1 ] < 0.0 )
669cdf0e10cSrcweir                     fRes = 1;       // empty cell > -x
670cdf0e10cSrcweir                 else
671cdf0e10cSrcweir                     fRes = -1;      // empty cell < x
672cdf0e10cSrcweir             }
673cdf0e10cSrcweir             // else: empty cell == 0.0
674cdf0e10cSrcweir         }
675cdf0e10cSrcweir         else
676cdf0e10cSrcweir         {
677cdf0e10cSrcweir             if ( rComp.pVal[ 1 ]->Len() )
678cdf0e10cSrcweir                 fRes = -1;      // empty cell < "..."
679cdf0e10cSrcweir             // else: empty cell == ""
680cdf0e10cSrcweir         }
681cdf0e10cSrcweir     }
682cdf0e10cSrcweir     else if ( rComp.bEmpty[ 1 ] )
683cdf0e10cSrcweir     {
684cdf0e10cSrcweir         if( rComp.bVal[ 0 ] )
685cdf0e10cSrcweir         {
686cdf0e10cSrcweir             if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], 0.0 ) )
687cdf0e10cSrcweir             {
688cdf0e10cSrcweir                 if ( rComp.nVal[ 0 ] < 0.0 )
689cdf0e10cSrcweir                     fRes = -1;      // -x < empty cell
690cdf0e10cSrcweir                 else
691cdf0e10cSrcweir                     fRes = 1;       // x > empty cell
692cdf0e10cSrcweir             }
693cdf0e10cSrcweir             // else: empty cell == 0.0
694cdf0e10cSrcweir         }
695cdf0e10cSrcweir         else
696cdf0e10cSrcweir         {
697cdf0e10cSrcweir             if ( rComp.pVal[ 0 ]->Len() )
698cdf0e10cSrcweir                 fRes = 1;       // "..." > empty cell
699cdf0e10cSrcweir             // else: "" == empty cell
700cdf0e10cSrcweir         }
701cdf0e10cSrcweir     }
702cdf0e10cSrcweir     else if( rComp.bVal[ 0 ] )
703cdf0e10cSrcweir     {
704cdf0e10cSrcweir         if( rComp.bVal[ 1 ] )
705cdf0e10cSrcweir         {
706cdf0e10cSrcweir             if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
707cdf0e10cSrcweir             {
708cdf0e10cSrcweir                 if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
709cdf0e10cSrcweir                     fRes = -1;
710cdf0e10cSrcweir                 else
711cdf0e10cSrcweir                     fRes = 1;
712cdf0e10cSrcweir             }
713cdf0e10cSrcweir         }
714cdf0e10cSrcweir         else
715cdf0e10cSrcweir         {
716cdf0e10cSrcweir             fRes = -1;          // number is less than string
717cdf0e10cSrcweir             nStringQuery = 2;   // 1+1
718cdf0e10cSrcweir         }
719cdf0e10cSrcweir     }
720cdf0e10cSrcweir     else if( rComp.bVal[ 1 ] )
721cdf0e10cSrcweir     {
722cdf0e10cSrcweir         fRes = 1;               // string is greater than number
723cdf0e10cSrcweir         nStringQuery = 1;       // 0+1
724cdf0e10cSrcweir     }
725cdf0e10cSrcweir     else
726cdf0e10cSrcweir     {
727cdf0e10cSrcweir         // Both strings.
728cdf0e10cSrcweir         if (pOptions)
729cdf0e10cSrcweir         {
730cdf0e10cSrcweir             // All similar to ScTable::ValidQuery(), *rComp.pVal[1] actually
731cdf0e10cSrcweir             // is/must be identical to *rEntry.pStr, which is essential for
732cdf0e10cSrcweir             // regex to work through GetSearchTextPtr().
733cdf0e10cSrcweir             ScQueryEntry& rEntry = pOptions->aQueryEntry;
734cdf0e10cSrcweir             DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options");
735cdf0e10cSrcweir             if (pOptions->bRegEx)
736cdf0e10cSrcweir             {
737cdf0e10cSrcweir                 xub_StrLen nStart = 0;
738cdf0e10cSrcweir                 xub_StrLen nStop  = rComp.pVal[0]->Len();
739cdf0e10cSrcweir                 bool bMatch = rEntry.GetSearchTextPtr(
740cdf0e10cSrcweir                         !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0],
741cdf0e10cSrcweir                             &nStart, &nStop);
742cdf0e10cSrcweir                 if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
743cdf0e10cSrcweir                     bMatch = false;     // RegEx must match entire string.
744cdf0e10cSrcweir                 fRes = (bMatch ? 0 : 1);
745cdf0e10cSrcweir             }
746cdf0e10cSrcweir             else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
747cdf0e10cSrcweir             {
748cdf0e10cSrcweir                 ::utl::TransliterationWrapper* pTransliteration =
749cdf0e10cSrcweir                     (pOptions->bIgnoreCase ? ScGlobal::GetpTransliteration() :
750cdf0e10cSrcweir                      ScGlobal::GetCaseTransliteration());
751cdf0e10cSrcweir                 bool bMatch;
752cdf0e10cSrcweir                 if (pOptions->bMatchWholeCell)
753cdf0e10cSrcweir                     bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
754cdf0e10cSrcweir                 else
755cdf0e10cSrcweir                 {
756cdf0e10cSrcweir                     String aCell( pTransliteration->transliterate(
757cdf0e10cSrcweir                                 *rComp.pVal[0], ScGlobal::eLnge, 0,
758cdf0e10cSrcweir                                 rComp.pVal[0]->Len(), NULL));
759cdf0e10cSrcweir                     String aQuer( pTransliteration->transliterate(
760cdf0e10cSrcweir                                 *rComp.pVal[1], ScGlobal::eLnge, 0,
761cdf0e10cSrcweir                                 rComp.pVal[1]->Len(), NULL));
762cdf0e10cSrcweir                     bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
763cdf0e10cSrcweir                 }
764cdf0e10cSrcweir                 fRes = (bMatch ? 0 : 1);
765cdf0e10cSrcweir             }
766cdf0e10cSrcweir             else if (pOptions->bIgnoreCase)
767cdf0e10cSrcweir                 fRes = (double) ScGlobal::GetCollator()->compareString(
768cdf0e10cSrcweir                         *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
769cdf0e10cSrcweir             else
770cdf0e10cSrcweir                 fRes = (double) ScGlobal::GetCaseCollator()->compareString(
771cdf0e10cSrcweir                         *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
772cdf0e10cSrcweir         }
773cdf0e10cSrcweir         else if (pDok->GetDocOptions().IsIgnoreCase())
774cdf0e10cSrcweir             fRes = (double) ScGlobal::GetCollator()->compareString(
775cdf0e10cSrcweir                 *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
776cdf0e10cSrcweir         else
777cdf0e10cSrcweir             fRes = (double) ScGlobal::GetCaseCollator()->compareString(
778cdf0e10cSrcweir                 *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
779cdf0e10cSrcweir     }
780cdf0e10cSrcweir     if (nStringQuery && pOptions)
781cdf0e10cSrcweir     {
782cdf0e10cSrcweir         const ScQueryEntry& rEntry = pOptions->aQueryEntry;
783cdf0e10cSrcweir         if (!rEntry.bQueryByString && rEntry.pStr->Len() &&
784cdf0e10cSrcweir                 (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL))
785cdf0e10cSrcweir         {
786cdf0e10cSrcweir             // As in ScTable::ValidQuery() match a numeric string for a
787cdf0e10cSrcweir             // number query that originated from a string, e.g. in SUMIF
788cdf0e10cSrcweir             // and COUNTIF. Transliteration is not needed here.
789cdf0e10cSrcweir             bool bEqual = rComp.pVal[nStringQuery-1]->Equals( *rEntry.pStr);
790cdf0e10cSrcweir             // match => fRes=0, else fRes=1
791cdf0e10cSrcweir             fRes = (rEntry.eOp == SC_NOT_EQUAL) ? bEqual : !bEqual;
792cdf0e10cSrcweir         }
793cdf0e10cSrcweir     }
794cdf0e10cSrcweir     return fRes;
795cdf0e10cSrcweir }
796cdf0e10cSrcweir 
797cdf0e10cSrcweir 
Compare()798cdf0e10cSrcweir double ScInterpreter::Compare()
799cdf0e10cSrcweir {
800cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Compare" );
801cdf0e10cSrcweir     String aVal1, aVal2;
802cdf0e10cSrcweir     ScCompare aComp( &aVal1, &aVal2 );
803cdf0e10cSrcweir     for( short i = 1; i >= 0; i-- )
804cdf0e10cSrcweir     {
805cdf0e10cSrcweir         switch ( GetRawStackType() )
806cdf0e10cSrcweir         {
807cdf0e10cSrcweir             case svEmptyCell:
808cdf0e10cSrcweir                 Pop();
809cdf0e10cSrcweir                 aComp.bEmpty[ i ] = sal_True;
810cdf0e10cSrcweir                 break;
811cdf0e10cSrcweir             case svMissing:
812cdf0e10cSrcweir             case svDouble:
813cdf0e10cSrcweir                 aComp.nVal[ i ] = GetDouble();
814cdf0e10cSrcweir                 aComp.bVal[ i ] = sal_True;
815cdf0e10cSrcweir                 break;
816cdf0e10cSrcweir             case svString:
817cdf0e10cSrcweir                 *aComp.pVal[ i ] = GetString();
818cdf0e10cSrcweir                 aComp.bVal[ i ] = sal_False;
819cdf0e10cSrcweir                 break;
820cdf0e10cSrcweir             case svDoubleRef :
821cdf0e10cSrcweir             case svSingleRef :
822cdf0e10cSrcweir             {
823cdf0e10cSrcweir                 ScAddress aAdr;
824cdf0e10cSrcweir                 if ( !PopDoubleRefOrSingleRef( aAdr ) )
825cdf0e10cSrcweir                     break;
826cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
827cdf0e10cSrcweir                 if (HasCellEmptyData( pCell))
828cdf0e10cSrcweir                     aComp.bEmpty[ i ] = sal_True;
829cdf0e10cSrcweir                 else if (HasCellStringData( pCell))
830cdf0e10cSrcweir                 {
831cdf0e10cSrcweir                     GetCellString( *aComp.pVal[ i ], pCell);
832cdf0e10cSrcweir                     aComp.bVal[ i ] = sal_False;
833cdf0e10cSrcweir                 }
834cdf0e10cSrcweir                 else
835cdf0e10cSrcweir                 {
836cdf0e10cSrcweir                     aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
837cdf0e10cSrcweir                     aComp.bVal[ i ] = sal_True;
838cdf0e10cSrcweir                 }
839cdf0e10cSrcweir             }
840cdf0e10cSrcweir             break;
841cdf0e10cSrcweir             default:
842cdf0e10cSrcweir                 SetError( errIllegalParameter);
843cdf0e10cSrcweir             break;
844cdf0e10cSrcweir         }
845cdf0e10cSrcweir     }
846cdf0e10cSrcweir     if( nGlobalError )
847cdf0e10cSrcweir         return 0;
848cdf0e10cSrcweir     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
849cdf0e10cSrcweir     return CompareFunc( aComp );
850cdf0e10cSrcweir }
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 
CompareMat(ScCompareOptions * pOptions)853cdf0e10cSrcweir ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
854cdf0e10cSrcweir {
855cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareMat" );
856cdf0e10cSrcweir     String aVal1, aVal2;
857cdf0e10cSrcweir     ScCompare aComp( &aVal1, &aVal2 );
858cdf0e10cSrcweir     ScMatrixRef pMat[2];
859cdf0e10cSrcweir     ScAddress aAdr;
860cdf0e10cSrcweir     for( short i = 1; i >= 0; i-- )
861cdf0e10cSrcweir     {
862cdf0e10cSrcweir         switch (GetRawStackType())
863cdf0e10cSrcweir         {
864cdf0e10cSrcweir             case svEmptyCell:
865cdf0e10cSrcweir                 Pop();
866cdf0e10cSrcweir                 aComp.bEmpty[ i ] = sal_True;
867cdf0e10cSrcweir                 break;
868cdf0e10cSrcweir             case svMissing:
869cdf0e10cSrcweir             case svDouble:
870cdf0e10cSrcweir                 aComp.nVal[ i ] = GetDouble();
871cdf0e10cSrcweir                 aComp.bVal[ i ] = sal_True;
872cdf0e10cSrcweir                 break;
873cdf0e10cSrcweir             case svString:
874cdf0e10cSrcweir                 *aComp.pVal[ i ] = GetString();
875cdf0e10cSrcweir                 aComp.bVal[ i ] = sal_False;
876cdf0e10cSrcweir                 break;
877cdf0e10cSrcweir             case svSingleRef:
878cdf0e10cSrcweir             {
879cdf0e10cSrcweir                 PopSingleRef( aAdr );
880cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
881cdf0e10cSrcweir                 if (HasCellEmptyData( pCell))
882cdf0e10cSrcweir                     aComp.bEmpty[ i ] = sal_True;
883cdf0e10cSrcweir                 else if (HasCellStringData( pCell))
884cdf0e10cSrcweir                 {
885cdf0e10cSrcweir                     GetCellString( *aComp.pVal[ i ], pCell);
886cdf0e10cSrcweir                     aComp.bVal[ i ] = sal_False;
887cdf0e10cSrcweir                 }
888cdf0e10cSrcweir                 else
889cdf0e10cSrcweir                 {
890cdf0e10cSrcweir                     aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
891cdf0e10cSrcweir                     aComp.bVal[ i ] = sal_True;
892cdf0e10cSrcweir                 }
893cdf0e10cSrcweir             }
894cdf0e10cSrcweir             break;
895cdf0e10cSrcweir             case svDoubleRef:
896cdf0e10cSrcweir             case svMatrix:
897cdf0e10cSrcweir                 pMat[ i ] = GetMatrix();
898cdf0e10cSrcweir                 if ( !pMat[ i ] )
899cdf0e10cSrcweir                     SetError( errIllegalParameter);
900cdf0e10cSrcweir                 else
901cdf0e10cSrcweir                     pMat[i]->SetErrorInterpreter( NULL);
902cdf0e10cSrcweir                     // errors are transported as DoubleError inside matrix
903cdf0e10cSrcweir                 break;
904cdf0e10cSrcweir             default:
905cdf0e10cSrcweir                 SetError( errIllegalParameter);
906cdf0e10cSrcweir             break;
907cdf0e10cSrcweir         }
908cdf0e10cSrcweir     }
909cdf0e10cSrcweir     ScMatrixRef pResMat = NULL;
910cdf0e10cSrcweir     if( !nGlobalError )
911cdf0e10cSrcweir     {
912cdf0e10cSrcweir         if ( pMat[0] && pMat[1] )
913cdf0e10cSrcweir         {
914cdf0e10cSrcweir             SCSIZE nC0, nC1;
915cdf0e10cSrcweir             SCSIZE nR0, nR1;
916cdf0e10cSrcweir             pMat[0]->GetDimensions( nC0, nR0 );
917cdf0e10cSrcweir             pMat[1]->GetDimensions( nC1, nR1 );
918cdf0e10cSrcweir             SCSIZE nC = Max( nC0, nC1 );
919cdf0e10cSrcweir             SCSIZE nR = Max( nR0, nR1 );
920cdf0e10cSrcweir             pResMat = GetNewMat( nC, nR);
921cdf0e10cSrcweir             if ( !pResMat )
922cdf0e10cSrcweir                 return NULL;
923cdf0e10cSrcweir             for ( SCSIZE j=0; j<nC; j++ )
924cdf0e10cSrcweir             {
925cdf0e10cSrcweir                 for ( SCSIZE k=0; k<nR; k++ )
926cdf0e10cSrcweir                 {
927cdf0e10cSrcweir                     SCSIZE nCol = j, nRow = k;
928cdf0e10cSrcweir                     if (    pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
929cdf0e10cSrcweir                             pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
930cdf0e10cSrcweir                     {
931cdf0e10cSrcweir                         for ( short i=1; i>=0; i-- )
932cdf0e10cSrcweir                         {
933cdf0e10cSrcweir                             if ( pMat[i]->IsString(j,k) )
934cdf0e10cSrcweir                             {
935cdf0e10cSrcweir                                 aComp.bVal[i] = sal_False;
936cdf0e10cSrcweir                                 *aComp.pVal[i] = pMat[i]->GetString(j,k);
937cdf0e10cSrcweir                                 aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
938cdf0e10cSrcweir                             }
939cdf0e10cSrcweir                             else
940cdf0e10cSrcweir                             {
941cdf0e10cSrcweir                                 aComp.bVal[i] = sal_True;
942cdf0e10cSrcweir                                 aComp.nVal[i] = pMat[i]->GetDouble(j,k);
943cdf0e10cSrcweir                                 aComp.bEmpty[i] = sal_False;
944cdf0e10cSrcweir                             }
945cdf0e10cSrcweir                         }
946cdf0e10cSrcweir                         pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
947cdf0e10cSrcweir                     }
948cdf0e10cSrcweir                     else
949cdf0e10cSrcweir                         pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
950cdf0e10cSrcweir                 }
951cdf0e10cSrcweir             }
952cdf0e10cSrcweir         }
953cdf0e10cSrcweir         else if ( pMat[0] || pMat[1] )
954cdf0e10cSrcweir         {
955cdf0e10cSrcweir             short i = ( pMat[0] ? 0 : 1);
956cdf0e10cSrcweir             SCSIZE nC, nR;
957cdf0e10cSrcweir             pMat[i]->GetDimensions( nC, nR );
958cdf0e10cSrcweir             pResMat = GetNewMat( nC, nR);
959cdf0e10cSrcweir             if ( !pResMat )
960cdf0e10cSrcweir                 return NULL;
961cdf0e10cSrcweir             SCSIZE n = nC * nR;
962cdf0e10cSrcweir             for ( SCSIZE j=0; j<n; j++ )
963cdf0e10cSrcweir             {
964cdf0e10cSrcweir                 if ( pMat[i]->IsValue(j) )
965cdf0e10cSrcweir                 {
966cdf0e10cSrcweir                     aComp.bVal[i] = sal_True;
967cdf0e10cSrcweir                     aComp.nVal[i] = pMat[i]->GetDouble(j);
968cdf0e10cSrcweir                     aComp.bEmpty[i] = sal_False;
969cdf0e10cSrcweir                 }
970cdf0e10cSrcweir                 else
971cdf0e10cSrcweir                 {
972cdf0e10cSrcweir                     aComp.bVal[i] = sal_False;
973cdf0e10cSrcweir                     *aComp.pVal[i] = pMat[i]->GetString(j);
974cdf0e10cSrcweir                     aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
975cdf0e10cSrcweir                 }
976cdf0e10cSrcweir                 pResMat->PutDouble( CompareFunc( aComp, pOptions ), j );
977cdf0e10cSrcweir             }
978cdf0e10cSrcweir         }
979cdf0e10cSrcweir     }
980cdf0e10cSrcweir     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
981cdf0e10cSrcweir     return pResMat;
982cdf0e10cSrcweir }
983cdf0e10cSrcweir 
984cdf0e10cSrcweir 
QueryMat(ScMatrix * pMat,ScCompareOptions & rOptions)985cdf0e10cSrcweir ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions )
986cdf0e10cSrcweir {
987cdf0e10cSrcweir     short nSaveCurFmtType = nCurFmtType;
988cdf0e10cSrcweir     short nSaveFuncFmtType = nFuncFmtType;
989cdf0e10cSrcweir     PushMatrix( pMat);
990cdf0e10cSrcweir     if (rOptions.aQueryEntry.bQueryByString)
991cdf0e10cSrcweir         PushString( *rOptions.aQueryEntry.pStr);
992cdf0e10cSrcweir     else
993cdf0e10cSrcweir         PushDouble( rOptions.aQueryEntry.nVal);
994cdf0e10cSrcweir     ScMatrixRef pResultMatrix = CompareMat( &rOptions);
995cdf0e10cSrcweir     nCurFmtType = nSaveCurFmtType;
996cdf0e10cSrcweir     nFuncFmtType = nSaveFuncFmtType;
997cdf0e10cSrcweir     if (nGlobalError || !pResultMatrix)
998cdf0e10cSrcweir     {
999cdf0e10cSrcweir         SetError( errIllegalParameter);
1000cdf0e10cSrcweir         return pResultMatrix;
1001cdf0e10cSrcweir     }
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir     switch (rOptions.aQueryEntry.eOp)
1004cdf0e10cSrcweir     {
1005cdf0e10cSrcweir         case SC_EQUAL:
1006cdf0e10cSrcweir             pResultMatrix->CompareEqual();
1007cdf0e10cSrcweir             break;
1008cdf0e10cSrcweir         case SC_LESS:
1009cdf0e10cSrcweir             pResultMatrix->CompareLess();
1010cdf0e10cSrcweir             break;
1011cdf0e10cSrcweir         case SC_GREATER:
1012cdf0e10cSrcweir             pResultMatrix->CompareGreater();
1013cdf0e10cSrcweir             break;
1014cdf0e10cSrcweir         case SC_LESS_EQUAL:
1015cdf0e10cSrcweir             pResultMatrix->CompareLessEqual();
1016cdf0e10cSrcweir             break;
1017cdf0e10cSrcweir         case SC_GREATER_EQUAL:
1018cdf0e10cSrcweir             pResultMatrix->CompareGreaterEqual();
1019cdf0e10cSrcweir             break;
1020cdf0e10cSrcweir         case SC_NOT_EQUAL:
1021cdf0e10cSrcweir             pResultMatrix->CompareNotEqual();
1022cdf0e10cSrcweir             break;
1023cdf0e10cSrcweir         default:
1024cdf0e10cSrcweir             SetError( errIllegalArgument);
1025cdf0e10cSrcweir             DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
1026cdf0e10cSrcweir     }
1027cdf0e10cSrcweir     return pResultMatrix;
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir 
ScEqual()1031cdf0e10cSrcweir void ScInterpreter::ScEqual()
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEqual" );
1034cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1035cdf0e10cSrcweir     {
1036cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1037cdf0e10cSrcweir         if ( !pMat )
1038cdf0e10cSrcweir             PushIllegalParameter();
1039cdf0e10cSrcweir         else
1040cdf0e10cSrcweir         {
1041cdf0e10cSrcweir             pMat->CompareEqual();
1042cdf0e10cSrcweir             PushMatrix( pMat );
1043cdf0e10cSrcweir         }
1044cdf0e10cSrcweir     }
1045cdf0e10cSrcweir     else
1046cdf0e10cSrcweir         PushInt( Compare() == 0 );
1047cdf0e10cSrcweir }
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir 
ScNotEqual()1050cdf0e10cSrcweir void ScInterpreter::ScNotEqual()
1051cdf0e10cSrcweir {
1052cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNotEqual" );
1053cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1054cdf0e10cSrcweir     {
1055cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1056cdf0e10cSrcweir         if ( !pMat )
1057cdf0e10cSrcweir             PushIllegalParameter();
1058cdf0e10cSrcweir         else
1059cdf0e10cSrcweir         {
1060cdf0e10cSrcweir             pMat->CompareNotEqual();
1061cdf0e10cSrcweir             PushMatrix( pMat );
1062cdf0e10cSrcweir         }
1063cdf0e10cSrcweir     }
1064cdf0e10cSrcweir     else
1065cdf0e10cSrcweir         PushInt( Compare() != 0 );
1066cdf0e10cSrcweir }
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir 
ScLess()1069cdf0e10cSrcweir void ScInterpreter::ScLess()
1070cdf0e10cSrcweir {
1071cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLess" );
1072cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1073cdf0e10cSrcweir     {
1074cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1075cdf0e10cSrcweir         if ( !pMat )
1076cdf0e10cSrcweir             PushIllegalParameter();
1077cdf0e10cSrcweir         else
1078cdf0e10cSrcweir         {
1079cdf0e10cSrcweir             pMat->CompareLess();
1080cdf0e10cSrcweir             PushMatrix( pMat );
1081cdf0e10cSrcweir         }
1082cdf0e10cSrcweir     }
1083cdf0e10cSrcweir     else
1084cdf0e10cSrcweir         PushInt( Compare() < 0 );
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir 
ScGreater()1088cdf0e10cSrcweir void ScInterpreter::ScGreater()
1089cdf0e10cSrcweir {
1090cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreater" );
1091cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1092cdf0e10cSrcweir     {
1093cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1094cdf0e10cSrcweir         if ( !pMat )
1095cdf0e10cSrcweir             PushIllegalParameter();
1096cdf0e10cSrcweir         else
1097cdf0e10cSrcweir         {
1098cdf0e10cSrcweir             pMat->CompareGreater();
1099cdf0e10cSrcweir             PushMatrix( pMat );
1100cdf0e10cSrcweir         }
1101cdf0e10cSrcweir     }
1102cdf0e10cSrcweir     else
1103cdf0e10cSrcweir         PushInt( Compare() > 0 );
1104cdf0e10cSrcweir }
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir 
ScLessEqual()1107cdf0e10cSrcweir void ScInterpreter::ScLessEqual()
1108cdf0e10cSrcweir {
1109cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLessEqual" );
1110cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1111cdf0e10cSrcweir     {
1112cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1113cdf0e10cSrcweir         if ( !pMat )
1114cdf0e10cSrcweir             PushIllegalParameter();
1115cdf0e10cSrcweir         else
1116cdf0e10cSrcweir         {
1117cdf0e10cSrcweir             pMat->CompareLessEqual();
1118cdf0e10cSrcweir             PushMatrix( pMat );
1119cdf0e10cSrcweir         }
1120cdf0e10cSrcweir     }
1121cdf0e10cSrcweir     else
1122cdf0e10cSrcweir         PushInt( Compare() <= 0 );
1123cdf0e10cSrcweir }
1124cdf0e10cSrcweir 
1125cdf0e10cSrcweir 
ScGreaterEqual()1126cdf0e10cSrcweir void ScInterpreter::ScGreaterEqual()
1127cdf0e10cSrcweir {
1128cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreaterEqual" );
1129cdf0e10cSrcweir     if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1130cdf0e10cSrcweir     {
1131cdf0e10cSrcweir         ScMatrixRef pMat = CompareMat();
1132cdf0e10cSrcweir         if ( !pMat )
1133cdf0e10cSrcweir             PushIllegalParameter();
1134cdf0e10cSrcweir         else
1135cdf0e10cSrcweir         {
1136cdf0e10cSrcweir             pMat->CompareGreaterEqual();
1137cdf0e10cSrcweir             PushMatrix( pMat );
1138cdf0e10cSrcweir         }
1139cdf0e10cSrcweir     }
1140cdf0e10cSrcweir     else
1141cdf0e10cSrcweir         PushInt( Compare() >= 0 );
1142cdf0e10cSrcweir }
1143cdf0e10cSrcweir 
ScBitAnd()11440f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitAnd() {
11450f94c4d7SDamjan Jovanovic     ScBitArithmeticOps(bitOperations::BITAND);
11460f94c4d7SDamjan Jovanovic }
11470f94c4d7SDamjan Jovanovic 
ScBitOr()11480f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitOr() {
11490f94c4d7SDamjan Jovanovic     ScBitArithmeticOps(bitOperations::BITOR);
11500f94c4d7SDamjan Jovanovic }
11510f94c4d7SDamjan Jovanovic 
ScBitXor()11520f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitXor() {
11530f94c4d7SDamjan Jovanovic     ScBitArithmeticOps(bitOperations::BITXOR);
11540f94c4d7SDamjan Jovanovic }
11550f94c4d7SDamjan Jovanovic 
11560f94c4d7SDamjan Jovanovic /* Helper function that calculates the result in bitwise arithmetic operations helping avoid code repetition */
doOperation(sal_uInt64 val,ScInterpreter::bitOperations::bitArithmetic bitOp,sal_uInt64 & res,sal_Bool & first)11570f94c4d7SDamjan Jovanovic static void doOperation( sal_uInt64 val, ScInterpreter::bitOperations::bitArithmetic bitOp, sal_uInt64 &res, sal_Bool &first )
11580f94c4d7SDamjan Jovanovic {
11590f94c4d7SDamjan Jovanovic     if ( first )
11600f94c4d7SDamjan Jovanovic     {
11610f94c4d7SDamjan Jovanovic         res = val;
11620f94c4d7SDamjan Jovanovic         first = sal_False;
11630f94c4d7SDamjan Jovanovic     }
11640f94c4d7SDamjan Jovanovic     else
11650f94c4d7SDamjan Jovanovic     {
11660f94c4d7SDamjan Jovanovic         if (bitOp == ScInterpreter::bitOperations::BITAND)
11670f94c4d7SDamjan Jovanovic             res = res & val;
11680f94c4d7SDamjan Jovanovic         else if (bitOp == ScInterpreter::bitOperations::BITOR)
11690f94c4d7SDamjan Jovanovic             res = res | val;
11700f94c4d7SDamjan Jovanovic         else if (bitOp == ScInterpreter::bitOperations::BITXOR)
11710f94c4d7SDamjan Jovanovic             res = res ^ val;
11720f94c4d7SDamjan Jovanovic     }
11730f94c4d7SDamjan Jovanovic }
11740f94c4d7SDamjan Jovanovic 
ScBitArithmeticOps(bitOperations::bitArithmetic bitOp)11750f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitArithmeticOps(bitOperations::bitArithmetic bitOp)
11760f94c4d7SDamjan Jovanovic {
11770f94c4d7SDamjan Jovanovic     nFuncFmtType = NUMBERFORMAT_NUMBER;
11780f94c4d7SDamjan Jovanovic     short nParamCount = GetByte();
11790f94c4d7SDamjan Jovanovic     static const sal_uInt64 max_val = SAL_CONST_UINT64( 281474976710656 );
11800f94c4d7SDamjan Jovanovic     static const int NUMBER_OF_ARGUMENTS = 2;
11810f94c4d7SDamjan Jovanovic 
11820f94c4d7SDamjan Jovanovic     if ( MustHaveParamCount( nParamCount, NUMBER_OF_ARGUMENTS ) )
11830f94c4d7SDamjan Jovanovic     {
11840f94c4d7SDamjan Jovanovic         double *arguments = new double[NUMBER_OF_ARGUMENTS];
11850f94c4d7SDamjan Jovanovic 
11860f94c4d7SDamjan Jovanovic         for (int i=0; i<NUMBER_OF_ARGUMENTS; i++)
11870f94c4d7SDamjan Jovanovic         {
11880f94c4d7SDamjan Jovanovic             arguments[i] = ::rtl::math::approxFloor( GetDouble() );
11890f94c4d7SDamjan Jovanovic             if ( arguments[i] < 0 || arguments[i] > max_val )
11900f94c4d7SDamjan Jovanovic             {
11910f94c4d7SDamjan Jovanovic                 PushIllegalArgument();
11920f94c4d7SDamjan Jovanovic             }
11930f94c4d7SDamjan Jovanovic         }
11940f94c4d7SDamjan Jovanovic 
11950f94c4d7SDamjan Jovanovic         sal_uInt64 res = 0;
11960f94c4d7SDamjan Jovanovic         sal_Bool first = sal_True;
11970f94c4d7SDamjan Jovanovic 
11980f94c4d7SDamjan Jovanovic 
11990f94c4d7SDamjan Jovanovic         for (int i=0; i<NUMBER_OF_ARGUMENTS; i++)
12000f94c4d7SDamjan Jovanovic         {
12010f94c4d7SDamjan Jovanovic             doOperation( ( sal_uInt64 )arguments[i], bitOp, res, first );
12020f94c4d7SDamjan Jovanovic         }
12030f94c4d7SDamjan Jovanovic 
12040f94c4d7SDamjan Jovanovic         delete[] arguments;
12050f94c4d7SDamjan Jovanovic         PushDouble( (double) res );
12060f94c4d7SDamjan Jovanovic 
12070f94c4d7SDamjan Jovanovic     }
12080f94c4d7SDamjan Jovanovic }
12090f94c4d7SDamjan Jovanovic 
ScBitRShift()1210a940b7f5Sasf-sync-process void ScInterpreter::ScBitRShift() {
1211a940b7f5Sasf-sync-process     ScBitShiftOps(bitOperations::BITRSHIFT);
1212a940b7f5Sasf-sync-process }
1213a940b7f5Sasf-sync-process 
ScBitLShift()1214a940b7f5Sasf-sync-process void ScInterpreter::ScBitLShift() {
1215a940b7f5Sasf-sync-process     ScBitShiftOps(bitOperations::BITLSHIFT);
1216a940b7f5Sasf-sync-process }
1217a940b7f5Sasf-sync-process 
ScBitShiftOps(bitOperations::bitShift bitOp)1218a940b7f5Sasf-sync-process void ScInterpreter::ScBitShiftOps(bitOperations::bitShift bitOp) {
1219a940b7f5Sasf-sync-process     if ( MustHaveParamCount( GetByte(), 2 ) )
1220a940b7f5Sasf-sync-process     {
1221a940b7f5Sasf-sync-process         double n = ::rtl::math::approxFloor( GetDouble() );
1222a940b7f5Sasf-sync-process         double val = ::rtl::math::approxFloor( GetDouble() );
1223a940b7f5Sasf-sync-process 
1224a940b7f5Sasf-sync-process         if ( val < 0 )
1225a940b7f5Sasf-sync-process         {
1226a940b7f5Sasf-sync-process             PushIllegalArgument();
1227a940b7f5Sasf-sync-process         }
1228a940b7f5Sasf-sync-process         else
1229a940b7f5Sasf-sync-process         {
1230a940b7f5Sasf-sync-process             double result;
1231a940b7f5Sasf-sync-process             if (n < 0)
1232a940b7f5Sasf-sync-process             {
1233a940b7f5Sasf-sync-process                 if (bitOp == bitOperations::BITLSHIFT)
1234a940b7f5Sasf-sync-process                     result = (sal_uInt64) val >> (sal_uInt64) -n;
1235a940b7f5Sasf-sync-process                 else
1236a940b7f5Sasf-sync-process                     result = (sal_uInt64) val << (sal_uInt64) -n;
1237a940b7f5Sasf-sync-process             }
1238a940b7f5Sasf-sync-process             else if( n == 0)
1239a940b7f5Sasf-sync-process                 result = val;
1240a940b7f5Sasf-sync-process             else
1241a940b7f5Sasf-sync-process             {
1242a940b7f5Sasf-sync-process                 if (bitOp == bitOperations::BITLSHIFT)
1243a940b7f5Sasf-sync-process                     result = (sal_uInt64) val << (sal_uInt64) n;
1244a940b7f5Sasf-sync-process                 else
1245a940b7f5Sasf-sync-process                     result = (sal_uInt64) val >> (sal_uInt64) n;
1246a940b7f5Sasf-sync-process 
1247a940b7f5Sasf-sync-process             }
1248a940b7f5Sasf-sync-process             PushDouble( result );
1249a940b7f5Sasf-sync-process         }
1250a940b7f5Sasf-sync-process     }
1251a940b7f5Sasf-sync-process }
1252cdf0e10cSrcweir 
ScAnd()1253cdf0e10cSrcweir void ScInterpreter::ScAnd()
1254cdf0e10cSrcweir {
1255cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAnd" );
1256cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1257cdf0e10cSrcweir     short nParamCount = GetByte();
1258cdf0e10cSrcweir     if ( MustHaveParamCountMin( nParamCount, 1 ) )
1259cdf0e10cSrcweir     {
1260cdf0e10cSrcweir         sal_Bool bHaveValue = sal_False;
1261cdf0e10cSrcweir         short nRes = sal_True;
1262cdf0e10cSrcweir         size_t nRefInList = 0;
1263cdf0e10cSrcweir         while( nParamCount-- > 0)
1264cdf0e10cSrcweir         {
1265cdf0e10cSrcweir             if ( !nGlobalError )
1266cdf0e10cSrcweir             {
1267cdf0e10cSrcweir                 switch ( GetStackType() )
1268cdf0e10cSrcweir                 {
1269cdf0e10cSrcweir                     case svDouble :
1270cdf0e10cSrcweir                         bHaveValue = sal_True;
1271cdf0e10cSrcweir                         nRes &= ( PopDouble() != 0.0 );
1272cdf0e10cSrcweir                     break;
1273cdf0e10cSrcweir                     case svString :
1274cdf0e10cSrcweir                         Pop();
1275cdf0e10cSrcweir                         SetError( errNoValue );
1276cdf0e10cSrcweir                     break;
1277cdf0e10cSrcweir                     case svSingleRef :
1278cdf0e10cSrcweir                     {
1279cdf0e10cSrcweir                         ScAddress aAdr;
1280cdf0e10cSrcweir                         PopSingleRef( aAdr );
1281cdf0e10cSrcweir                         if ( !nGlobalError )
1282cdf0e10cSrcweir                         {
1283cdf0e10cSrcweir                             ScBaseCell* pCell = GetCell( aAdr );
1284cdf0e10cSrcweir                             if ( HasCellValueData( pCell ) )
1285cdf0e10cSrcweir                             {
1286cdf0e10cSrcweir                                 bHaveValue = sal_True;
1287cdf0e10cSrcweir                                 nRes &= ( GetCellValue( aAdr, pCell ) != 0.0 );
1288cdf0e10cSrcweir                             }
1289cdf0e10cSrcweir                             // else: Xcl setzt hier keinen Fehler
1290cdf0e10cSrcweir                         }
1291cdf0e10cSrcweir                     }
1292cdf0e10cSrcweir                     break;
1293cdf0e10cSrcweir                     case svDoubleRef:
1294cdf0e10cSrcweir                     case svRefList:
1295cdf0e10cSrcweir                     {
1296cdf0e10cSrcweir                         ScRange aRange;
1297cdf0e10cSrcweir                         PopDoubleRef( aRange, nParamCount, nRefInList);
1298cdf0e10cSrcweir                         if ( !nGlobalError )
1299cdf0e10cSrcweir                         {
1300cdf0e10cSrcweir                             double fVal;
1301cdf0e10cSrcweir                             sal_uInt16 nErr = 0;
1302cdf0e10cSrcweir                             ScValueIterator aValIter( pDok, aRange );
1303cdf0e10cSrcweir                             if ( aValIter.GetFirst( fVal, nErr ) )
1304cdf0e10cSrcweir                             {
1305cdf0e10cSrcweir                                 bHaveValue = sal_True;
1306cdf0e10cSrcweir                                 do
1307cdf0e10cSrcweir                                 {
1308cdf0e10cSrcweir                                     nRes &= ( fVal != 0.0 );
1309cdf0e10cSrcweir                                 } while ( (nErr == 0) &&
1310cdf0e10cSrcweir                                     aValIter.GetNext( fVal, nErr ) );
1311cdf0e10cSrcweir                             }
1312cdf0e10cSrcweir                             SetError( nErr );
1313cdf0e10cSrcweir                         }
1314cdf0e10cSrcweir                     }
1315cdf0e10cSrcweir                     break;
1316cdf0e10cSrcweir                     case svMatrix:
1317cdf0e10cSrcweir                     {
1318cdf0e10cSrcweir                         ScMatrixRef pMat = GetMatrix();
1319cdf0e10cSrcweir                         if ( pMat )
1320cdf0e10cSrcweir                         {
1321cdf0e10cSrcweir                             bHaveValue = sal_True;
1322cdf0e10cSrcweir                             double fVal = pMat->And();
1323cdf0e10cSrcweir                             sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1324cdf0e10cSrcweir                             if ( nErr )
1325cdf0e10cSrcweir                             {
1326cdf0e10cSrcweir                                 SetError( nErr );
1327cdf0e10cSrcweir                                 nRes = sal_False;
1328cdf0e10cSrcweir                             }
1329cdf0e10cSrcweir                             else
1330cdf0e10cSrcweir                                 nRes &= (fVal != 0.0);
1331cdf0e10cSrcweir                         }
1332cdf0e10cSrcweir                         // else: GetMatrix did set errIllegalParameter
1333cdf0e10cSrcweir                     }
1334cdf0e10cSrcweir                     break;
1335cdf0e10cSrcweir                     default:
1336cdf0e10cSrcweir                         Pop();
1337cdf0e10cSrcweir                         SetError( errIllegalParameter);
1338cdf0e10cSrcweir                 }
1339cdf0e10cSrcweir             }
1340cdf0e10cSrcweir             else
1341cdf0e10cSrcweir                 Pop();
1342cdf0e10cSrcweir         }
1343cdf0e10cSrcweir         if ( bHaveValue )
1344cdf0e10cSrcweir             PushInt( nRes );
1345cdf0e10cSrcweir         else
1346cdf0e10cSrcweir             PushNoValue();
1347cdf0e10cSrcweir     }
1348cdf0e10cSrcweir }
1349cdf0e10cSrcweir 
1350cdf0e10cSrcweir 
ScOr()1351cdf0e10cSrcweir void ScInterpreter::ScOr()
1352cdf0e10cSrcweir {
1353cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOr" );
1354cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1355cdf0e10cSrcweir     short nParamCount = GetByte();
1356cdf0e10cSrcweir     if ( MustHaveParamCountMin( nParamCount, 1 ) )
1357cdf0e10cSrcweir     {
1358cdf0e10cSrcweir         sal_Bool bHaveValue = sal_False;
1359cdf0e10cSrcweir         short nRes = sal_False;
1360cdf0e10cSrcweir         size_t nRefInList = 0;
1361cdf0e10cSrcweir         while( nParamCount-- > 0)
1362cdf0e10cSrcweir         {
1363cdf0e10cSrcweir             if ( !nGlobalError )
1364cdf0e10cSrcweir             {
1365cdf0e10cSrcweir                 switch ( GetStackType() )
1366cdf0e10cSrcweir                 {
1367cdf0e10cSrcweir                     case svDouble :
1368cdf0e10cSrcweir                         bHaveValue = sal_True;
1369cdf0e10cSrcweir                         nRes |= ( PopDouble() != 0.0 );
1370cdf0e10cSrcweir                     break;
1371cdf0e10cSrcweir                     case svString :
1372cdf0e10cSrcweir                         Pop();
1373cdf0e10cSrcweir                         SetError( errNoValue );
1374cdf0e10cSrcweir                     break;
1375cdf0e10cSrcweir                     case svSingleRef :
1376cdf0e10cSrcweir                     {
1377cdf0e10cSrcweir                         ScAddress aAdr;
1378cdf0e10cSrcweir                         PopSingleRef( aAdr );
1379cdf0e10cSrcweir                         if ( !nGlobalError )
1380cdf0e10cSrcweir                         {
1381cdf0e10cSrcweir                             ScBaseCell* pCell = GetCell( aAdr );
1382cdf0e10cSrcweir                             if ( HasCellValueData( pCell ) )
1383cdf0e10cSrcweir                             {
1384cdf0e10cSrcweir                                 bHaveValue = sal_True;
1385cdf0e10cSrcweir                                 nRes |= ( GetCellValue( aAdr, pCell ) != 0.0 );
1386cdf0e10cSrcweir                             }
1387cdf0e10cSrcweir                             // else: Xcl setzt hier keinen Fehler
1388cdf0e10cSrcweir                         }
1389cdf0e10cSrcweir                     }
1390cdf0e10cSrcweir                     break;
1391cdf0e10cSrcweir                     case svDoubleRef:
1392cdf0e10cSrcweir                     case svRefList:
1393cdf0e10cSrcweir                     {
1394cdf0e10cSrcweir                         ScRange aRange;
1395cdf0e10cSrcweir                         PopDoubleRef( aRange, nParamCount, nRefInList);
1396cdf0e10cSrcweir                         if ( !nGlobalError )
1397cdf0e10cSrcweir                         {
1398cdf0e10cSrcweir                             double fVal;
1399cdf0e10cSrcweir                             sal_uInt16 nErr = 0;
1400cdf0e10cSrcweir                             ScValueIterator aValIter( pDok, aRange );
1401cdf0e10cSrcweir                             if ( aValIter.GetFirst( fVal, nErr ) )
1402cdf0e10cSrcweir                             {
1403cdf0e10cSrcweir                                 bHaveValue = sal_True;
1404cdf0e10cSrcweir                                 do
1405cdf0e10cSrcweir                                 {
1406cdf0e10cSrcweir                                     nRes |= ( fVal != 0.0 );
1407cdf0e10cSrcweir                                 } while ( (nErr == 0) &&
1408cdf0e10cSrcweir                                     aValIter.GetNext( fVal, nErr ) );
1409cdf0e10cSrcweir                             }
1410cdf0e10cSrcweir                             SetError( nErr );
1411cdf0e10cSrcweir                         }
1412cdf0e10cSrcweir                     }
1413cdf0e10cSrcweir                     break;
1414cdf0e10cSrcweir                     case svMatrix:
1415cdf0e10cSrcweir                     {
1416cdf0e10cSrcweir                         bHaveValue = sal_True;
1417cdf0e10cSrcweir                         ScMatrixRef pMat = GetMatrix();
1418cdf0e10cSrcweir                         if ( pMat )
1419cdf0e10cSrcweir                         {
1420cdf0e10cSrcweir                             bHaveValue = sal_True;
1421cdf0e10cSrcweir                             double fVal = pMat->Or();
1422cdf0e10cSrcweir                             sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1423cdf0e10cSrcweir                             if ( nErr )
1424cdf0e10cSrcweir                             {
1425cdf0e10cSrcweir                                 SetError( nErr );
1426cdf0e10cSrcweir                                 nRes = sal_False;
1427cdf0e10cSrcweir                             }
1428cdf0e10cSrcweir                             else
1429cdf0e10cSrcweir                                 nRes |= (fVal != 0.0);
1430cdf0e10cSrcweir                         }
1431cdf0e10cSrcweir                         // else: GetMatrix did set errIllegalParameter
1432cdf0e10cSrcweir                     }
1433cdf0e10cSrcweir                     break;
1434cdf0e10cSrcweir                     default:
1435cdf0e10cSrcweir                         Pop();
1436cdf0e10cSrcweir                         SetError( errIllegalParameter);
1437cdf0e10cSrcweir                 }
1438cdf0e10cSrcweir             }
1439cdf0e10cSrcweir             else
1440cdf0e10cSrcweir                 Pop();
1441cdf0e10cSrcweir         }
1442cdf0e10cSrcweir         if ( bHaveValue )
1443cdf0e10cSrcweir             PushInt( nRes );
1444cdf0e10cSrcweir         else
1445cdf0e10cSrcweir             PushNoValue();
1446cdf0e10cSrcweir     }
1447cdf0e10cSrcweir }
1448cdf0e10cSrcweir 
ScXor()1449245212b4SAndrew Rist void ScInterpreter::ScXor()
1450245212b4SAndrew Rist {
1451245212b4SAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScXor" );
1452245212b4SAndrew Rist     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1453245212b4SAndrew Rist     short nParamCount = GetByte();
1454245212b4SAndrew Rist     if ( MustHaveParamCountMin( nParamCount, 1 ) )
1455245212b4SAndrew Rist     {
1456245212b4SAndrew Rist         bool bHaveValue = false;
1457245212b4SAndrew Rist         short nRes = 0;
1458245212b4SAndrew Rist         size_t nRefInList = 0;
1459245212b4SAndrew Rist         while( nParamCount-- > 0)
1460245212b4SAndrew Rist         {
1461245212b4SAndrew Rist             if ( !nGlobalError )
1462245212b4SAndrew Rist             {
1463245212b4SAndrew Rist                 switch ( GetStackType() )
1464245212b4SAndrew Rist                 {
1465245212b4SAndrew Rist                     case svDouble :
1466245212b4SAndrew Rist                         bHaveValue = true;
1467245212b4SAndrew Rist                         nRes ^= ( PopDouble() != 0.0 );
1468245212b4SAndrew Rist                         break;
1469245212b4SAndrew Rist                     case svString :
1470245212b4SAndrew Rist                         Pop();
1471245212b4SAndrew Rist                         SetError( errNoValue );
1472245212b4SAndrew Rist                         break;
1473245212b4SAndrew Rist                     case svSingleRef :
1474245212b4SAndrew Rist                         {
1475245212b4SAndrew Rist                             ScAddress aAdr;
1476245212b4SAndrew Rist                             PopSingleRef( aAdr );
1477245212b4SAndrew Rist                             if ( !nGlobalError )
1478245212b4SAndrew Rist                             {
1479245212b4SAndrew Rist                                 ScBaseCell* pCell = GetCell( aAdr );
1480245212b4SAndrew Rist                                 if ( HasCellValueData( pCell ) )
1481245212b4SAndrew Rist                                 {
1482245212b4SAndrew Rist                                     bHaveValue = true;
1483245212b4SAndrew Rist                                     nRes ^= ( GetCellValue( aAdr, pCell ) != 0.0 );
1484245212b4SAndrew Rist                                 }
1485245212b4SAndrew Rist                                 /* TODO: set error? Excel doesn't have XOR, but
1486245212b4SAndrew Rist                                  * doesn't set an error in this case for AND and
1487245212b4SAndrew Rist                                  * OR. */
1488245212b4SAndrew Rist                             }
1489245212b4SAndrew Rist                         }
1490245212b4SAndrew Rist                         break;
1491245212b4SAndrew Rist                     case svDoubleRef:
1492245212b4SAndrew Rist                     case svRefList:
1493245212b4SAndrew Rist                         {
1494245212b4SAndrew Rist                             ScRange aRange;
1495245212b4SAndrew Rist                             PopDoubleRef( aRange, nParamCount, nRefInList);
1496245212b4SAndrew Rist                             if ( !nGlobalError )
1497245212b4SAndrew Rist                             {
1498245212b4SAndrew Rist                                 double fVal;
1499245212b4SAndrew Rist                                 sal_uInt16 nErr = 0;
1500245212b4SAndrew Rist                                 ScValueIterator aValIter( pDok, aRange );
1501245212b4SAndrew Rist                                 if ( aValIter.GetFirst( fVal, nErr ) )
1502245212b4SAndrew Rist                                 {
1503245212b4SAndrew Rist                                     bHaveValue = true;
1504245212b4SAndrew Rist                                     do
1505245212b4SAndrew Rist                                     {
1506245212b4SAndrew Rist                                         nRes ^= ( fVal != 0.0 );
1507245212b4SAndrew Rist                                     } while ( (nErr == 0) &&
1508245212b4SAndrew Rist                                             aValIter.GetNext( fVal, nErr ) );
1509245212b4SAndrew Rist                                 }
1510245212b4SAndrew Rist                                 SetError( nErr );
1511245212b4SAndrew Rist                             }
1512245212b4SAndrew Rist                         }
1513245212b4SAndrew Rist                         break;
1514245212b4SAndrew Rist                     case svMatrix:
1515245212b4SAndrew Rist                         {
1516245212b4SAndrew Rist                             bHaveValue = true;
1517245212b4SAndrew Rist                             ScMatrixRef pMat = GetMatrix();
1518245212b4SAndrew Rist                             if ( pMat )
1519245212b4SAndrew Rist                             {
1520245212b4SAndrew Rist                                 bHaveValue = true;
1521245212b4SAndrew Rist                                 double fVal = pMat->Xor();
1522245212b4SAndrew Rist                                 sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1523245212b4SAndrew Rist                                 if ( nErr )
1524245212b4SAndrew Rist                                 {
1525245212b4SAndrew Rist                                     SetError( nErr );
1526245212b4SAndrew Rist                                     nRes = 0;
1527245212b4SAndrew Rist                                 }
1528245212b4SAndrew Rist                                 else
1529245212b4SAndrew Rist                                     nRes ^= (fVal != 0.0);
1530245212b4SAndrew Rist                             }
1531245212b4SAndrew Rist                             // else: GetMatrix did set errIllegalParameter
1532245212b4SAndrew Rist                         }
1533245212b4SAndrew Rist                         break;
1534245212b4SAndrew Rist                     default:
1535245212b4SAndrew Rist                         Pop();
1536245212b4SAndrew Rist                         SetError( errIllegalParameter);
1537245212b4SAndrew Rist                 }
1538245212b4SAndrew Rist             }
1539245212b4SAndrew Rist             else
1540245212b4SAndrew Rist                 Pop();
1541245212b4SAndrew Rist         }
1542245212b4SAndrew Rist         if ( bHaveValue )
1543245212b4SAndrew Rist             PushInt( nRes );
1544245212b4SAndrew Rist         else
1545245212b4SAndrew Rist             PushNoValue();
1546245212b4SAndrew Rist     }
1547245212b4SAndrew Rist }
1548245212b4SAndrew Rist 
1549cdf0e10cSrcweir 
ScNeg()1550cdf0e10cSrcweir void ScInterpreter::ScNeg()
1551cdf0e10cSrcweir {
1552cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNeg" );
1553cdf0e10cSrcweir     // Simple negation doesn't change current format type to number, keep
1554cdf0e10cSrcweir     // current type.
1555cdf0e10cSrcweir     nFuncFmtType = nCurFmtType;
1556cdf0e10cSrcweir     switch ( GetStackType() )
1557cdf0e10cSrcweir     {
1558cdf0e10cSrcweir         case svMatrix :
1559cdf0e10cSrcweir         {
1560cdf0e10cSrcweir             ScMatrixRef pMat = GetMatrix();
1561cdf0e10cSrcweir             if ( !pMat )
1562cdf0e10cSrcweir                 PushIllegalParameter();
1563cdf0e10cSrcweir             else
1564cdf0e10cSrcweir             {
1565cdf0e10cSrcweir                 SCSIZE nC, nR;
1566cdf0e10cSrcweir                 pMat->GetDimensions( nC, nR );
1567cdf0e10cSrcweir                 ScMatrixRef pResMat = GetNewMat( nC, nR);
1568cdf0e10cSrcweir                 if ( !pResMat )
1569cdf0e10cSrcweir                     PushIllegalArgument();
1570cdf0e10cSrcweir                 else
1571cdf0e10cSrcweir                 {
1572cdf0e10cSrcweir                     SCSIZE nCount = nC * nR;
1573cdf0e10cSrcweir                     for ( SCSIZE j=0; j<nCount; ++j )
1574cdf0e10cSrcweir                     {
1575cdf0e10cSrcweir                         if ( pMat->IsValueOrEmpty(j) )
1576cdf0e10cSrcweir                             pResMat->PutDouble( -pMat->GetDouble(j), j );
1577cdf0e10cSrcweir                         else
1578cdf0e10cSrcweir                             pResMat->PutString(
1579cdf0e10cSrcweir                                 ScGlobal::GetRscString( STR_NO_VALUE ), j );
1580cdf0e10cSrcweir                     }
1581cdf0e10cSrcweir                     PushMatrix( pResMat );
1582cdf0e10cSrcweir                 }
1583cdf0e10cSrcweir             }
1584cdf0e10cSrcweir         }
1585cdf0e10cSrcweir         break;
1586cdf0e10cSrcweir         default:
1587cdf0e10cSrcweir             PushDouble( -GetDouble() );
1588cdf0e10cSrcweir     }
1589cdf0e10cSrcweir }
1590cdf0e10cSrcweir 
1591cdf0e10cSrcweir 
ScPercentSign()1592cdf0e10cSrcweir void ScInterpreter::ScPercentSign()
1593cdf0e10cSrcweir {
1594cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentSign" );
1595cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_PERCENT;
1596cdf0e10cSrcweir     const FormulaToken* pSaveCur = pCur;
1597cdf0e10cSrcweir     sal_uInt8 nSavePar = cPar;
1598cdf0e10cSrcweir     PushInt( 100 );
1599cdf0e10cSrcweir     cPar = 2;
1600cdf0e10cSrcweir     FormulaByteToken aDivOp( ocDiv, cPar );
1601cdf0e10cSrcweir     pCur = &aDivOp;
1602cdf0e10cSrcweir     ScDiv();
1603cdf0e10cSrcweir     pCur = pSaveCur;
1604cdf0e10cSrcweir     cPar = nSavePar;
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 
ScNot()1608cdf0e10cSrcweir void ScInterpreter::ScNot()
1609cdf0e10cSrcweir {
1610cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNot" );
1611cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1612cdf0e10cSrcweir     switch ( GetStackType() )
1613cdf0e10cSrcweir     {
1614cdf0e10cSrcweir         case svMatrix :
1615cdf0e10cSrcweir         {
1616cdf0e10cSrcweir             ScMatrixRef pMat = GetMatrix();
1617cdf0e10cSrcweir             if ( !pMat )
1618cdf0e10cSrcweir                 PushIllegalParameter();
1619cdf0e10cSrcweir             else
1620cdf0e10cSrcweir             {
1621cdf0e10cSrcweir                 SCSIZE nC, nR;
1622cdf0e10cSrcweir                 pMat->GetDimensions( nC, nR );
1623cdf0e10cSrcweir                 ScMatrixRef pResMat = GetNewMat( nC, nR);
1624cdf0e10cSrcweir                 if ( !pResMat )
1625cdf0e10cSrcweir                     PushIllegalArgument();
1626cdf0e10cSrcweir                 else
1627cdf0e10cSrcweir                 {
1628cdf0e10cSrcweir                     SCSIZE nCount = nC * nR;
1629cdf0e10cSrcweir                     for ( SCSIZE j=0; j<nCount; ++j )
1630cdf0e10cSrcweir                     {
1631cdf0e10cSrcweir                         if ( pMat->IsValueOrEmpty(j) )
1632cdf0e10cSrcweir                             pResMat->PutDouble( (pMat->GetDouble(j) == 0.0), j );
1633cdf0e10cSrcweir                         else
1634cdf0e10cSrcweir                             pResMat->PutString(
1635cdf0e10cSrcweir                                 ScGlobal::GetRscString( STR_NO_VALUE ), j );
1636cdf0e10cSrcweir                     }
1637cdf0e10cSrcweir                     PushMatrix( pResMat );
1638cdf0e10cSrcweir                 }
1639cdf0e10cSrcweir             }
1640cdf0e10cSrcweir         }
1641cdf0e10cSrcweir         break;
1642cdf0e10cSrcweir         default:
1643cdf0e10cSrcweir             PushInt( GetDouble() == 0.0 );
1644cdf0e10cSrcweir     }
1645cdf0e10cSrcweir }
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir 
ScPi()1648cdf0e10cSrcweir void ScInterpreter::ScPi()
1649cdf0e10cSrcweir {
1650cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPi" );
1651cdf0e10cSrcweir     PushDouble(F_PI);
1652cdf0e10cSrcweir }
1653cdf0e10cSrcweir 
1654b54ae672SPedro Giffuni #define SCRANDOMQ_SIZE 4194304
1655b54ae672SPedro Giffuni static sal_uInt32 nScRandomQ[SCRANDOMQ_SIZE], nScCarry = 0;
1656b54ae672SPedro Giffuni 
1657b54ae672SPedro Giffuni // Multiply with Carry
1658b54ae672SPedro Giffuni sal_uInt32
b32MWC(void)1659b54ae672SPedro Giffuni b32MWC(void)
1660b54ae672SPedro Giffuni {
1661b54ae672SPedro Giffuni         sal_uInt32 t, x;
1662b54ae672SPedro Giffuni     static int j = (SCRANDOMQ_SIZE - 1);
1663b54ae672SPedro Giffuni 
1664b54ae672SPedro Giffuni     j = (j + 1) & (SCRANDOMQ_SIZE - 1);
1665b54ae672SPedro Giffuni     x = nScRandomQ[j];
1666b54ae672SPedro Giffuni     t = (x << 28) + nScCarry;
1667b54ae672SPedro Giffuni     nScCarry = (x >> 4) - (t < x);
1668b54ae672SPedro Giffuni     return (nScRandomQ[j] = t - x);
1669b54ae672SPedro Giffuni }
1670b54ae672SPedro Giffuni 
1671b54ae672SPedro Giffuni // Congruential
1672c9b8e806SPedro Giffuni #define CNG ( ScCNG = 69069 * ScCNG + 13579 )
1673b54ae672SPedro Giffuni // Xorshift
1674c9b8e806SPedro Giffuni #define XS ( ScXS ^= (ScXS << 13), ScXS ^= (ScXS >> 17), ScXS ^= (ScXS << 5) )
1675b54ae672SPedro Giffuni 
1676b54ae672SPedro Giffuni #define KISS (b32MWC() + CNG + XS)
1677cdf0e10cSrcweir 
ScRandom()1678cdf0e10cSrcweir void ScInterpreter::ScRandom()
1679cdf0e10cSrcweir {
1680b54ae672SPedro Giffuni     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pfg", "ScInterpreter::ScRandom" );
168105aa205cSPedro Giffuni 
1682b54ae672SPedro Giffuni     static sal_Bool SqSeeded = sal_False;
1683c9b8e806SPedro Giffuni     static sal_uInt32 ScCNG, ScXS = 362436069;
168405aa205cSPedro Giffuni 
1685b54ae672SPedro Giffuni     // Seeding for the PRNG
1686b54ae672SPedro Giffuni     if (SqSeeded == sal_False) {
16875dfc2e73Spfg         rtlRandomPool aPool = rtl_random_createPool();
1688c9b8e806SPedro Giffuni         rtl_random_getBytes(aPool, &ScCNG, sizeof(ScCNG));
1689b54ae672SPedro Giffuni         rtl_random_getBytes(aPool, &nScRandomQ,
1690b54ae672SPedro Giffuni                             sizeof(nScRandomQ[0]) * SCRANDOMQ_SIZE);
16915dfc2e73Spfg         rtl_random_destroyPool(aPool);
1692b54ae672SPedro Giffuni         SqSeeded = sal_True;
1693cdf0e10cSrcweir         }
1694b54ae672SPedro Giffuni     PushDouble(static_cast<double>(KISS) / SAL_MAX_UINT32);
1695b54ae672SPedro Giffuni }
1696cdf0e10cSrcweir 
ScTrue()1697cdf0e10cSrcweir void ScInterpreter::ScTrue()
1698cdf0e10cSrcweir {
1699cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrue" );
1700cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1701cdf0e10cSrcweir     PushInt(1);
1702cdf0e10cSrcweir }
1703cdf0e10cSrcweir 
1704cdf0e10cSrcweir 
ScFalse()1705cdf0e10cSrcweir void ScInterpreter::ScFalse()
1706cdf0e10cSrcweir {
1707cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFalse" );
1708cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1709cdf0e10cSrcweir     PushInt(0);
1710cdf0e10cSrcweir }
1711cdf0e10cSrcweir 
1712cdf0e10cSrcweir 
ScDeg()1713cdf0e10cSrcweir void ScInterpreter::ScDeg()
1714cdf0e10cSrcweir {
1715cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDeg" );
1716cdf0e10cSrcweir     PushDouble((GetDouble() / F_PI) * 180.0);
1717cdf0e10cSrcweir }
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir 
ScRad()1720cdf0e10cSrcweir void ScInterpreter::ScRad()
1721cdf0e10cSrcweir {
1722cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRad" );
1723cdf0e10cSrcweir     PushDouble(GetDouble() * (F_PI / 180));
1724cdf0e10cSrcweir }
1725cdf0e10cSrcweir 
1726cdf0e10cSrcweir 
ScSin()1727cdf0e10cSrcweir void ScInterpreter::ScSin()
1728cdf0e10cSrcweir {
1729cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSin" );
1730cdf0e10cSrcweir     PushDouble(::rtl::math::sin(GetDouble()));
1731cdf0e10cSrcweir }
1732cdf0e10cSrcweir 
1733cdf0e10cSrcweir 
ScCos()1734cdf0e10cSrcweir void ScInterpreter::ScCos()
1735cdf0e10cSrcweir {
1736cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCos" );
1737cdf0e10cSrcweir     PushDouble(::rtl::math::cos(GetDouble()));
1738cdf0e10cSrcweir }
1739cdf0e10cSrcweir 
1740cdf0e10cSrcweir 
ScTan()1741cdf0e10cSrcweir void ScInterpreter::ScTan()
1742cdf0e10cSrcweir {
1743cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTan" );
1744cdf0e10cSrcweir     PushDouble(::rtl::math::tan(GetDouble()));
1745cdf0e10cSrcweir }
1746cdf0e10cSrcweir 
1747cdf0e10cSrcweir 
ScCot()1748cdf0e10cSrcweir void ScInterpreter::ScCot()
1749cdf0e10cSrcweir {
1750cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCot" );
1751cdf0e10cSrcweir     PushDouble(1.0 / ::rtl::math::tan(GetDouble()));
1752cdf0e10cSrcweir }
1753cdf0e10cSrcweir 
1754cdf0e10cSrcweir 
ScArcSin()1755cdf0e10cSrcweir void ScInterpreter::ScArcSin()
1756cdf0e10cSrcweir {
1757cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSin" );
1758cdf0e10cSrcweir     PushDouble(asin(GetDouble()));
1759cdf0e10cSrcweir }
1760cdf0e10cSrcweir 
1761cdf0e10cSrcweir 
ScArcCos()1762cdf0e10cSrcweir void ScInterpreter::ScArcCos()
1763cdf0e10cSrcweir {
1764cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCos" );
1765cdf0e10cSrcweir     PushDouble(acos(GetDouble()));
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir 
1768cdf0e10cSrcweir 
ScArcTan()1769cdf0e10cSrcweir void ScInterpreter::ScArcTan()
1770cdf0e10cSrcweir {
1771cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTan" );
1772cdf0e10cSrcweir     PushDouble(atan(GetDouble()));
1773cdf0e10cSrcweir }
1774cdf0e10cSrcweir 
1775cdf0e10cSrcweir 
ScArcCot()1776cdf0e10cSrcweir void ScInterpreter::ScArcCot()
1777cdf0e10cSrcweir {
1778cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCot" );
1779cdf0e10cSrcweir     PushDouble((F_PI2) - atan(GetDouble()));
1780cdf0e10cSrcweir }
1781cdf0e10cSrcweir 
1782cdf0e10cSrcweir 
ScSinHyp()1783cdf0e10cSrcweir void ScInterpreter::ScSinHyp()
1784cdf0e10cSrcweir {
1785cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSinHyp" );
1786cdf0e10cSrcweir     PushDouble(sinh(GetDouble()));
1787cdf0e10cSrcweir }
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir 
ScCosHyp()1790cdf0e10cSrcweir void ScInterpreter::ScCosHyp()
1791cdf0e10cSrcweir {
1792cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCosHyp" );
1793cdf0e10cSrcweir     PushDouble(cosh(GetDouble()));
1794cdf0e10cSrcweir }
1795cdf0e10cSrcweir 
1796cdf0e10cSrcweir 
ScTanHyp()1797cdf0e10cSrcweir void ScInterpreter::ScTanHyp()
1798cdf0e10cSrcweir {
1799cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTanHyp" );
1800cdf0e10cSrcweir     PushDouble(tanh(GetDouble()));
1801cdf0e10cSrcweir }
1802cdf0e10cSrcweir 
1803cdf0e10cSrcweir 
ScCotHyp()1804cdf0e10cSrcweir void ScInterpreter::ScCotHyp()
1805cdf0e10cSrcweir {
1806cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCotHyp" );
1807cdf0e10cSrcweir     PushDouble(1.0 / tanh(GetDouble()));
1808cdf0e10cSrcweir }
1809cdf0e10cSrcweir 
1810cdf0e10cSrcweir 
ScArcSinHyp()1811cdf0e10cSrcweir void ScInterpreter::ScArcSinHyp()
1812cdf0e10cSrcweir {
1813cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSinHyp" );
181476ea2deeSPedro Giffuni     PushDouble( ::boost::math::asinh( GetDouble()));
1815cdf0e10cSrcweir }
1816cdf0e10cSrcweir 
ScArcCosHyp()1817cdf0e10cSrcweir void ScInterpreter::ScArcCosHyp()
1818cdf0e10cSrcweir {
1819cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCosHyp" );
1820cdf0e10cSrcweir     double fVal = GetDouble();
1821cdf0e10cSrcweir     if (fVal < 1.0)
1822cdf0e10cSrcweir         PushIllegalArgument();
1823cdf0e10cSrcweir     else
182476ea2deeSPedro Giffuni         PushDouble( ::boost::math::acosh( fVal));
1825cdf0e10cSrcweir }
1826cdf0e10cSrcweir 
ScArcTanHyp()1827cdf0e10cSrcweir void ScInterpreter::ScArcTanHyp()
1828cdf0e10cSrcweir {
1829cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTanHyp" );
1830cdf0e10cSrcweir     double fVal = GetDouble();
1831cdf0e10cSrcweir     if (fabs(fVal) >= 1.0)
1832cdf0e10cSrcweir         PushIllegalArgument();
1833cdf0e10cSrcweir     else
183476ea2deeSPedro Giffuni         PushDouble( ::boost::math::atanh( fVal));
1835cdf0e10cSrcweir }
1836cdf0e10cSrcweir 
1837cdf0e10cSrcweir 
ScArcCotHyp()1838cdf0e10cSrcweir void ScInterpreter::ScArcCotHyp()
1839cdf0e10cSrcweir {
1840cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCotHyp" );
1841cdf0e10cSrcweir     double nVal = GetDouble();
1842cdf0e10cSrcweir     if (fabs(nVal) <= 1.0)
1843cdf0e10cSrcweir         PushIllegalArgument();
1844cdf0e10cSrcweir     else
1845cdf0e10cSrcweir         PushDouble(0.5 * log((nVal + 1.0) / (nVal - 1.0)));
1846cdf0e10cSrcweir }
1847cdf0e10cSrcweir 
ScCosecant()1848cdf0e10cSrcweir void ScInterpreter::ScCosecant()
1849cdf0e10cSrcweir {
1850cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecant" );
1851cdf0e10cSrcweir     PushDouble(1.0 / ::rtl::math::sin(GetDouble()));
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir 
ScSecant()1854cdf0e10cSrcweir void ScInterpreter::ScSecant()
1855cdf0e10cSrcweir {
1856cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecant" );
1857cdf0e10cSrcweir     PushDouble(1.0 / ::rtl::math::cos(GetDouble()));
1858cdf0e10cSrcweir }
1859cdf0e10cSrcweir 
ScCosecantHyp()1860cdf0e10cSrcweir void ScInterpreter::ScCosecantHyp()
1861cdf0e10cSrcweir {
1862cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecantHyp" );
1863cdf0e10cSrcweir     PushDouble(1.0 / sinh(GetDouble()));
1864cdf0e10cSrcweir }
1865cdf0e10cSrcweir 
ScSecantHyp()1866cdf0e10cSrcweir void ScInterpreter::ScSecantHyp()
1867cdf0e10cSrcweir {
1868cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecantHyp" );
1869cdf0e10cSrcweir     PushDouble(1.0 / cosh(GetDouble()));
1870cdf0e10cSrcweir }
1871cdf0e10cSrcweir 
1872cdf0e10cSrcweir 
ScExp()1873cdf0e10cSrcweir void ScInterpreter::ScExp()
1874cdf0e10cSrcweir {
1875cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExp" );
1876cdf0e10cSrcweir     PushDouble(exp(GetDouble()));
1877cdf0e10cSrcweir }
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir 
ScSqrt()1880cdf0e10cSrcweir void ScInterpreter::ScSqrt()
1881cdf0e10cSrcweir {
1882cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSqrt" );
1883cdf0e10cSrcweir     double fVal = GetDouble();
1884cdf0e10cSrcweir     if (fVal >= 0.0)
1885cdf0e10cSrcweir         PushDouble(sqrt(fVal));
1886cdf0e10cSrcweir     else
1887cdf0e10cSrcweir         PushIllegalArgument();
1888cdf0e10cSrcweir }
1889cdf0e10cSrcweir 
1890cdf0e10cSrcweir 
ScIsEmpty()1891cdf0e10cSrcweir void ScInterpreter::ScIsEmpty()
1892cdf0e10cSrcweir {
1893cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEmpty" );
1894cdf0e10cSrcweir     short nRes = 0;
1895cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1896cdf0e10cSrcweir     switch ( GetRawStackType() )
1897cdf0e10cSrcweir     {
1898cdf0e10cSrcweir         case svEmptyCell:
1899cdf0e10cSrcweir         {
1900cdf0e10cSrcweir             FormulaTokenRef p = PopToken();
1901cdf0e10cSrcweir             if (!static_cast<const ScEmptyCellToken*>(p.get())->IsInherited())
1902cdf0e10cSrcweir                 nRes = 1;
1903cdf0e10cSrcweir         }
1904cdf0e10cSrcweir         break;
1905cdf0e10cSrcweir         case svDoubleRef :
1906cdf0e10cSrcweir         case svSingleRef :
1907cdf0e10cSrcweir         {
1908cdf0e10cSrcweir             ScAddress aAdr;
1909cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
1910cdf0e10cSrcweir                 break;
1911cdf0e10cSrcweir             // NOTE: this could test also on inherited emptiness, but then the
1912cdf0e10cSrcweir             // cell tested wouldn't be empty. Must correspond with
1913cdf0e10cSrcweir             // ScCountEmptyCells().
1914cdf0e10cSrcweir             // if (HasCellEmptyData( GetCell( aAdr)))
1915cdf0e10cSrcweir             CellType eCellType = GetCellType( GetCell( aAdr ) );
1916cdf0e10cSrcweir             if((eCellType == CELLTYPE_NONE) || (eCellType == CELLTYPE_NOTE))
1917cdf0e10cSrcweir                 nRes = 1;
1918cdf0e10cSrcweir         }
1919cdf0e10cSrcweir         break;
1920cdf0e10cSrcweir         case svMatrix:
1921cdf0e10cSrcweir         {
1922cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
1923cdf0e10cSrcweir             if ( !pMat )
1924cdf0e10cSrcweir                 ;   // nothing
1925cdf0e10cSrcweir             else if ( !pJumpMatrix )
1926cdf0e10cSrcweir                 nRes = pMat->IsEmpty( 0 );
1927cdf0e10cSrcweir             else
1928cdf0e10cSrcweir             {
1929cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
1930cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
1931cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
1932cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
1933cdf0e10cSrcweir                     nRes = pMat->IsEmpty( nC, nR);
1934cdf0e10cSrcweir                 // else: sal_False, not empty (which is what Xcl does)
1935cdf0e10cSrcweir             }
1936cdf0e10cSrcweir         }
1937cdf0e10cSrcweir         break;
1938cdf0e10cSrcweir         default:
1939cdf0e10cSrcweir             Pop();
1940cdf0e10cSrcweir     }
1941cdf0e10cSrcweir     nGlobalError = 0;
1942cdf0e10cSrcweir     PushInt( nRes );
1943cdf0e10cSrcweir }
1944cdf0e10cSrcweir 
1945cdf0e10cSrcweir 
IsString()1946cdf0e10cSrcweir short ScInterpreter::IsString()
1947cdf0e10cSrcweir {
1948cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsString" );
1949cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
1950cdf0e10cSrcweir     short nRes = 0;
1951cdf0e10cSrcweir     switch ( GetRawStackType() )
1952cdf0e10cSrcweir     {
1953cdf0e10cSrcweir         case svString:
1954cdf0e10cSrcweir             Pop();
1955cdf0e10cSrcweir             nRes = 1;
1956cdf0e10cSrcweir         break;
1957cdf0e10cSrcweir         case svDoubleRef :
1958cdf0e10cSrcweir         case svSingleRef :
1959cdf0e10cSrcweir         {
1960cdf0e10cSrcweir             ScAddress aAdr;
1961cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
1962cdf0e10cSrcweir                 break;
1963cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
1964cdf0e10cSrcweir             if (GetCellErrCode( pCell ) == 0)
1965cdf0e10cSrcweir             {
1966cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
1967cdf0e10cSrcweir                 {
1968cdf0e10cSrcweir                     case CELLTYPE_STRING :
1969cdf0e10cSrcweir                     case CELLTYPE_EDIT :
1970cdf0e10cSrcweir                         nRes = 1;
1971cdf0e10cSrcweir                         break;
1972cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
1973cdf0e10cSrcweir                         nRes = !((ScFormulaCell*)pCell)->IsValue() &&
1974cdf0e10cSrcweir                             !((ScFormulaCell*)pCell)->IsEmpty();
1975cdf0e10cSrcweir                         break;
1976cdf0e10cSrcweir                     default:
1977cdf0e10cSrcweir                         ; // nothing
1978cdf0e10cSrcweir                 }
1979cdf0e10cSrcweir             }
1980cdf0e10cSrcweir         }
1981cdf0e10cSrcweir         break;
1982cdf0e10cSrcweir         case svMatrix:
1983cdf0e10cSrcweir         {
1984cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
1985cdf0e10cSrcweir             if ( !pMat )
1986cdf0e10cSrcweir                 ;   // nothing
1987cdf0e10cSrcweir             else if ( !pJumpMatrix )
1988cdf0e10cSrcweir                 nRes = pMat->IsString(0) && !pMat->IsEmpty(0);
1989cdf0e10cSrcweir             else
1990cdf0e10cSrcweir             {
1991cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
1992cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
1993cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
1994cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
1995cdf0e10cSrcweir                     nRes = pMat->IsString( nC, nR) && !pMat->IsEmpty( nC, nR);
1996cdf0e10cSrcweir             }
1997cdf0e10cSrcweir         }
1998cdf0e10cSrcweir         break;
1999cdf0e10cSrcweir         default:
2000cdf0e10cSrcweir             Pop();
2001cdf0e10cSrcweir     }
2002cdf0e10cSrcweir     nGlobalError = 0;
2003cdf0e10cSrcweir     return nRes;
2004cdf0e10cSrcweir }
2005cdf0e10cSrcweir 
2006cdf0e10cSrcweir 
ScIsString()2007cdf0e10cSrcweir void ScInterpreter::ScIsString()
2008cdf0e10cSrcweir {
2009cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsString" );
2010cdf0e10cSrcweir     PushInt( IsString() );
2011cdf0e10cSrcweir }
2012cdf0e10cSrcweir 
2013cdf0e10cSrcweir 
ScIsNonString()2014cdf0e10cSrcweir void ScInterpreter::ScIsNonString()
2015cdf0e10cSrcweir {
2016cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNonString" );
2017cdf0e10cSrcweir     PushInt( !IsString() );
2018cdf0e10cSrcweir }
2019cdf0e10cSrcweir 
2020cdf0e10cSrcweir 
ScIsLogical()2021cdf0e10cSrcweir void ScInterpreter::ScIsLogical()
2022cdf0e10cSrcweir {
2023cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsLogical" );
2024cdf0e10cSrcweir     short nRes = 0;
2025cdf0e10cSrcweir     switch ( GetStackType() )
2026cdf0e10cSrcweir     {
2027cdf0e10cSrcweir         case svDoubleRef :
2028cdf0e10cSrcweir         case svSingleRef :
2029cdf0e10cSrcweir         {
2030cdf0e10cSrcweir             ScAddress aAdr;
2031cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2032cdf0e10cSrcweir                 break;
2033cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2034cdf0e10cSrcweir             if (GetCellErrCode( pCell ) == 0)
2035cdf0e10cSrcweir             {
2036cdf0e10cSrcweir                 if (HasCellValueData(pCell))
2037cdf0e10cSrcweir                 {
2038cdf0e10cSrcweir                     sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2039cdf0e10cSrcweir                     nRes = ( pFormatter->GetType(nFormat)
2040cdf0e10cSrcweir                                                  == NUMBERFORMAT_LOGICAL);
2041cdf0e10cSrcweir                 }
2042cdf0e10cSrcweir             }
2043cdf0e10cSrcweir         }
2044cdf0e10cSrcweir         break;
2045cdf0e10cSrcweir         case svMatrix:
2046cdf0e10cSrcweir             // TODO: we don't have type information for arrays except
2047cdf0e10cSrcweir             // numerical/string.
2048cdf0e10cSrcweir         // Fall thru
2049cdf0e10cSrcweir         default:
2050cdf0e10cSrcweir             PopError();
2051cdf0e10cSrcweir             if ( !nGlobalError )
2052cdf0e10cSrcweir                 nRes = ( nCurFmtType == NUMBERFORMAT_LOGICAL );
2053cdf0e10cSrcweir     }
2054cdf0e10cSrcweir     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
2055cdf0e10cSrcweir     nGlobalError = 0;
2056cdf0e10cSrcweir     PushInt( nRes );
2057cdf0e10cSrcweir }
2058cdf0e10cSrcweir 
2059cdf0e10cSrcweir 
ScType()2060cdf0e10cSrcweir void ScInterpreter::ScType()
2061cdf0e10cSrcweir {
2062cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScType" );
2063cdf0e10cSrcweir     short nType = 0;
2064cdf0e10cSrcweir     switch ( GetStackType() )
2065cdf0e10cSrcweir     {
2066cdf0e10cSrcweir         case svDoubleRef :
2067cdf0e10cSrcweir         case svSingleRef :
2068cdf0e10cSrcweir         {
2069cdf0e10cSrcweir             ScAddress aAdr;
2070cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2071cdf0e10cSrcweir                 break;
2072cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2073cdf0e10cSrcweir             if (GetCellErrCode( pCell ) == 0)
2074cdf0e10cSrcweir             {
2075cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
2076cdf0e10cSrcweir                 {
2077cdf0e10cSrcweir                     // NOTE: this is Xcl nonsense!
2078cdf0e10cSrcweir                     case CELLTYPE_NOTE :
2079cdf0e10cSrcweir                         nType = 1;      // empty cell is value (0)
2080cdf0e10cSrcweir                         break;
2081cdf0e10cSrcweir                     case CELLTYPE_STRING :
2082cdf0e10cSrcweir                     case CELLTYPE_EDIT :
2083cdf0e10cSrcweir                         nType = 2;
2084cdf0e10cSrcweir                         break;
2085cdf0e10cSrcweir                     case CELLTYPE_VALUE :
2086cdf0e10cSrcweir                         {
2087cdf0e10cSrcweir                             sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2088cdf0e10cSrcweir                             if (pFormatter->GetType(nFormat)
2089cdf0e10cSrcweir                                                      == NUMBERFORMAT_LOGICAL)
2090cdf0e10cSrcweir                                 nType = 4;
2091cdf0e10cSrcweir                             else
2092cdf0e10cSrcweir                                 nType = 1;
2093cdf0e10cSrcweir                         }
2094cdf0e10cSrcweir                         break;
2095cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
2096cdf0e10cSrcweir                         nType = 8;
2097cdf0e10cSrcweir                         break;
2098cdf0e10cSrcweir                     default:
2099cdf0e10cSrcweir                         PushIllegalArgument();
2100cdf0e10cSrcweir                 }
2101cdf0e10cSrcweir             }
2102cdf0e10cSrcweir             else
2103cdf0e10cSrcweir                 nType = 16;
2104cdf0e10cSrcweir         }
2105cdf0e10cSrcweir         break;
2106cdf0e10cSrcweir         case svString:
2107cdf0e10cSrcweir             PopError();
2108cdf0e10cSrcweir             if ( nGlobalError )
2109cdf0e10cSrcweir             {
2110cdf0e10cSrcweir                 nType = 16;
2111cdf0e10cSrcweir                 nGlobalError = 0;
2112cdf0e10cSrcweir             }
2113cdf0e10cSrcweir             else
2114cdf0e10cSrcweir                 nType = 2;
2115cdf0e10cSrcweir         break;
2116cdf0e10cSrcweir         case svMatrix:
2117cdf0e10cSrcweir             PopMatrix();
2118cdf0e10cSrcweir             if ( nGlobalError )
2119cdf0e10cSrcweir             {
2120cdf0e10cSrcweir                 nType = 16;
2121cdf0e10cSrcweir                 nGlobalError = 0;
2122cdf0e10cSrcweir             }
2123cdf0e10cSrcweir             else
2124cdf0e10cSrcweir                 nType = 64;
2125cdf0e10cSrcweir                 // we could return the type of one element if in JumpMatrix or
2126cdf0e10cSrcweir                 // ForceArray mode, but Xcl doesn't ...
2127cdf0e10cSrcweir         break;
2128cdf0e10cSrcweir         default:
2129cdf0e10cSrcweir             PopError();
2130cdf0e10cSrcweir             if ( nGlobalError )
2131cdf0e10cSrcweir             {
2132cdf0e10cSrcweir                 nType = 16;
2133cdf0e10cSrcweir                 nGlobalError = 0;
2134cdf0e10cSrcweir             }
2135cdf0e10cSrcweir             else
2136cdf0e10cSrcweir                 nType = 1;
2137cdf0e10cSrcweir     }
2138cdf0e10cSrcweir     PushInt( nType );
2139cdf0e10cSrcweir }
2140cdf0e10cSrcweir 
2141cdf0e10cSrcweir 
lcl_FormatHasNegColor(const SvNumberformat * pFormat)2142cdf0e10cSrcweir inline sal_Bool lcl_FormatHasNegColor( const SvNumberformat* pFormat )
2143cdf0e10cSrcweir {
2144cdf0e10cSrcweir     return pFormat && pFormat->GetColor( 1 );
2145cdf0e10cSrcweir }
2146cdf0e10cSrcweir 
2147cdf0e10cSrcweir 
lcl_FormatHasOpenPar(const SvNumberformat * pFormat)2148cdf0e10cSrcweir inline sal_Bool lcl_FormatHasOpenPar( const SvNumberformat* pFormat )
2149cdf0e10cSrcweir {
2150cdf0e10cSrcweir     return pFormat && (pFormat->GetFormatstring().Search( '(' ) != STRING_NOTFOUND);
2151cdf0e10cSrcweir }
2152cdf0e10cSrcweir 
2153cdf0e10cSrcweir 
ScCell()2154cdf0e10cSrcweir void ScInterpreter::ScCell()
2155cdf0e10cSrcweir {   // ATTRIBUTE ; [REF]
2156cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
2157cdf0e10cSrcweir     if( MustHaveParamCount( nParamCount, 1, 2 ) )
2158cdf0e10cSrcweir     {
2159cdf0e10cSrcweir         ScAddress aCellPos( aPos );
2160cdf0e10cSrcweir         sal_Bool bError = sal_False;
2161cdf0e10cSrcweir         if( nParamCount == 2 )
2162cdf0e10cSrcweir             bError = !PopDoubleRefOrSingleRef( aCellPos );
2163cdf0e10cSrcweir         String aInfoType( GetString() );
2164cdf0e10cSrcweir         if( bError || nGlobalError )
2165cdf0e10cSrcweir             PushIllegalParameter();
2166cdf0e10cSrcweir         else
2167cdf0e10cSrcweir         {
2168cdf0e10cSrcweir             String          aFuncResult;
2169cdf0e10cSrcweir             ScBaseCell*     pCell = GetCell( aCellPos );
2170cdf0e10cSrcweir 
2171cdf0e10cSrcweir             ScCellKeywordTranslator::transKeyword(aInfoType, ScGlobal::GetLocale(), ocCell);
2172cdf0e10cSrcweir 
2173cdf0e10cSrcweir // *** ADDRESS INFO ***
2174cdf0e10cSrcweir             if( aInfoType.EqualsAscii( "COL" ) )
2175cdf0e10cSrcweir             {   // column number (1-based)
2176cdf0e10cSrcweir                 PushInt( aCellPos.Col() + 1 );
2177cdf0e10cSrcweir             }
2178cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "ROW" ) )
2179cdf0e10cSrcweir             {   // row number (1-based)
2180cdf0e10cSrcweir                 PushInt( aCellPos.Row() + 1 );
2181cdf0e10cSrcweir             }
2182cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "SHEET" ) )
2183cdf0e10cSrcweir             {   // table number (1-based)
2184cdf0e10cSrcweir                 PushInt( aCellPos.Tab() + 1 );
2185cdf0e10cSrcweir             }
2186cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "ADDRESS" ) )
2187cdf0e10cSrcweir             {   // address formatted as [['FILENAME'#]$TABLE.]$COL$ROW
2188cdf0e10cSrcweir                 sal_uInt16 nFlags = (aCellPos.Tab() == aPos.Tab()) ? (SCA_ABS) : (SCA_ABS_3D);
2189cdf0e10cSrcweir                 aCellPos.Format( aFuncResult, nFlags, pDok, pDok->GetAddressConvention() );
2190cdf0e10cSrcweir                 PushString( aFuncResult );
2191cdf0e10cSrcweir             }
2192cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "FILENAME" ) )
2193cdf0e10cSrcweir             {   // file name and table name: 'FILENAME'#$TABLE
2194cdf0e10cSrcweir                 SCTAB nTab = aCellPos.Tab();
2195cdf0e10cSrcweir                 if( nTab < pDok->GetTableCount() )
2196cdf0e10cSrcweir                 {
2197cdf0e10cSrcweir                     if( pDok->GetLinkMode( nTab ) == SC_LINK_VALUE )
2198cdf0e10cSrcweir                         pDok->GetName( nTab, aFuncResult );
2199cdf0e10cSrcweir                     else
2200cdf0e10cSrcweir                     {
2201cdf0e10cSrcweir                         SfxObjectShell* pShell = pDok->GetDocumentShell();
2202cdf0e10cSrcweir                         if( pShell && pShell->GetMedium() )
2203cdf0e10cSrcweir                         {
2204cdf0e10cSrcweir                             aFuncResult = (sal_Unicode) '\'';
2205cdf0e10cSrcweir                             const INetURLObject& rURLObj = pShell->GetMedium()->GetURLObject();
2206cdf0e10cSrcweir                             aFuncResult += String( rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) );
2207cdf0e10cSrcweir                             aFuncResult.AppendAscii( "'#$" );
2208cdf0e10cSrcweir                             String aTabName;
2209cdf0e10cSrcweir                             pDok->GetName( nTab, aTabName );
2210cdf0e10cSrcweir                             aFuncResult += aTabName;
2211cdf0e10cSrcweir                         }
2212cdf0e10cSrcweir                     }
2213cdf0e10cSrcweir                 }
2214cdf0e10cSrcweir                 PushString( aFuncResult );
2215cdf0e10cSrcweir             }
2216cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "COORD" ) )
2217cdf0e10cSrcweir             {   // address, lotus 1-2-3 formatted: $TABLE:$COL$ROW
2218cdf0e10cSrcweir                 // Yes, passing tab as col is intentional!
2219cdf0e10cSrcweir                 ScAddress( static_cast<SCCOL>(aCellPos.Tab()), 0, 0 ).Format(
2220cdf0e10cSrcweir                     aFuncResult, (SCA_COL_ABSOLUTE|SCA_VALID_COL), NULL, pDok->GetAddressConvention() );
2221cdf0e10cSrcweir                 aFuncResult += ':';
2222cdf0e10cSrcweir                 String aCellStr;
2223cdf0e10cSrcweir                 aCellPos.Format( aCellStr, (SCA_COL_ABSOLUTE|SCA_VALID_COL|SCA_ROW_ABSOLUTE|SCA_VALID_ROW),
2224cdf0e10cSrcweir                                  NULL, pDok->GetAddressConvention() );
2225cdf0e10cSrcweir                 aFuncResult += aCellStr;
2226cdf0e10cSrcweir                 PushString( aFuncResult );
2227cdf0e10cSrcweir             }
2228cdf0e10cSrcweir 
2229cdf0e10cSrcweir // *** CELL PROPERTIES ***
2230cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "CONTENTS" ) )
2231cdf0e10cSrcweir             {   // contents of the cell, no formatting
2232cdf0e10cSrcweir                 if( pCell && pCell->HasStringData() )
2233cdf0e10cSrcweir                 {
2234cdf0e10cSrcweir                     GetCellString( aFuncResult, pCell );
2235cdf0e10cSrcweir                     PushString( aFuncResult );
2236cdf0e10cSrcweir                 }
2237cdf0e10cSrcweir                 else
2238cdf0e10cSrcweir                     PushDouble( GetCellValue( aCellPos, pCell ) );
2239cdf0e10cSrcweir             }
2240cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "TYPE" ) )
2241cdf0e10cSrcweir             {   // b = blank; l = string (label); v = otherwise (value)
2242cdf0e10cSrcweir                 if( HasCellStringData( pCell ) )
2243cdf0e10cSrcweir                     aFuncResult = 'l';
2244cdf0e10cSrcweir                 else
2245cdf0e10cSrcweir                     aFuncResult = HasCellValueData( pCell ) ? 'v' : 'b';
2246cdf0e10cSrcweir                 PushString( aFuncResult );
2247cdf0e10cSrcweir             }
2248cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "WIDTH" ) )
2249cdf0e10cSrcweir             {   // column width (rounded off as count of zero characters in standard font and size)
2250cdf0e10cSrcweir                 Printer*    pPrinter = pDok->GetPrinter();
2251cdf0e10cSrcweir                 MapMode     aOldMode( pPrinter->GetMapMode() );
2252cdf0e10cSrcweir                 Font        aOldFont( pPrinter->GetFont() );
2253cdf0e10cSrcweir                 Font        aDefFont;
2254cdf0e10cSrcweir 
2255cdf0e10cSrcweir                 pPrinter->SetMapMode( MAP_TWIP );
2256cdf0e10cSrcweir                 // font color doesn't matter here
2257cdf0e10cSrcweir                 pDok->GetDefPattern()->GetFont( aDefFont, SC_AUTOCOL_BLACK, pPrinter );
2258cdf0e10cSrcweir                 pPrinter->SetFont( aDefFont );
2259cdf0e10cSrcweir                 long nZeroWidth = pPrinter->GetTextWidth( String( '0' ) );
2260cdf0e10cSrcweir                 pPrinter->SetFont( aOldFont );
2261cdf0e10cSrcweir                 pPrinter->SetMapMode( aOldMode );
2262cdf0e10cSrcweir                 int nZeroCount = (int)(pDok->GetColWidth( aCellPos.Col(), aCellPos.Tab() ) / nZeroWidth);
2263cdf0e10cSrcweir                 PushInt( nZeroCount );
2264cdf0e10cSrcweir             }
2265cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "PREFIX" ) )
2266cdf0e10cSrcweir             {   // ' = left; " = right; ^ = centered
2267cdf0e10cSrcweir                 if( HasCellStringData( pCell ) )
2268cdf0e10cSrcweir                 {
2269cdf0e10cSrcweir                     const SvxHorJustifyItem* pJustAttr = (const SvxHorJustifyItem*)
2270cdf0e10cSrcweir                         pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_HOR_JUSTIFY );
2271cdf0e10cSrcweir                     switch( pJustAttr->GetValue() )
2272cdf0e10cSrcweir                     {
2273cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_STANDARD:
2274cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_LEFT:
2275cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_BLOCK:     aFuncResult = '\''; break;
2276cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_CENTER:    aFuncResult = '^';  break;
2277cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_RIGHT:     aFuncResult = '"';  break;
2278cdf0e10cSrcweir                         case SVX_HOR_JUSTIFY_REPEAT:    aFuncResult = '\\'; break;
2279cdf0e10cSrcweir                     }
2280cdf0e10cSrcweir                 }
2281cdf0e10cSrcweir                 PushString( aFuncResult );
2282cdf0e10cSrcweir             }
2283cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "PROTECT" ) )
2284cdf0e10cSrcweir             {   // 1 = cell locked
2285cdf0e10cSrcweir                 const ScProtectionAttr* pProtAttr = (const ScProtectionAttr*)
2286cdf0e10cSrcweir                     pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION );
2287cdf0e10cSrcweir                 PushInt( pProtAttr->GetProtection() ? 1 : 0 );
2288cdf0e10cSrcweir             }
2289cdf0e10cSrcweir 
2290cdf0e10cSrcweir // *** FORMATTING ***
2291cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "FORMAT" ) )
2292cdf0e10cSrcweir             {   // specific format code for standard formats
2293cdf0e10cSrcweir                 sal_uLong   nFormat = pDok->GetNumberFormat( aCellPos );
2294cdf0e10cSrcweir                 sal_Bool    bAppendPrec = sal_True;
2295cdf0e10cSrcweir                 sal_uInt16  nPrec, nLeading;
2296cdf0e10cSrcweir                 sal_Bool    bThousand, bIsRed;
2297cdf0e10cSrcweir                 pFormatter->GetFormatSpecialInfo( nFormat, bThousand, bIsRed, nPrec, nLeading );
2298cdf0e10cSrcweir 
2299cdf0e10cSrcweir                 switch( pFormatter->GetType( nFormat ) )
2300cdf0e10cSrcweir                 {
2301cdf0e10cSrcweir                     case NUMBERFORMAT_NUMBER:       aFuncResult = (bThousand ? ',' : 'F');  break;
2302cdf0e10cSrcweir                     case NUMBERFORMAT_CURRENCY:     aFuncResult = 'C';                      break;
2303cdf0e10cSrcweir                     case NUMBERFORMAT_SCIENTIFIC:   aFuncResult = 'S';                      break;
2304cdf0e10cSrcweir                     case NUMBERFORMAT_PERCENT:      aFuncResult = 'P';                      break;
2305cdf0e10cSrcweir                     default:
2306cdf0e10cSrcweir                     {
2307cdf0e10cSrcweir                         bAppendPrec = sal_False;
2308cdf0e10cSrcweir                         switch( pFormatter->GetIndexTableOffset( nFormat ) )
2309cdf0e10cSrcweir                         {
2310cdf0e10cSrcweir                             case NF_DATE_SYSTEM_SHORT:
2311cdf0e10cSrcweir                             case NF_DATE_SYS_DMMMYY:
2312cdf0e10cSrcweir                             case NF_DATE_SYS_DDMMYY:
2313cdf0e10cSrcweir                             case NF_DATE_SYS_DDMMYYYY:
2314cdf0e10cSrcweir                             case NF_DATE_SYS_DMMMYYYY:
2315cdf0e10cSrcweir                             case NF_DATE_DIN_DMMMYYYY:
2316cdf0e10cSrcweir                             case NF_DATE_SYS_DMMMMYYYY:
2317cdf0e10cSrcweir                             case NF_DATE_DIN_DMMMMYYYY: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D1" ) );  break;
2318cdf0e10cSrcweir                             case NF_DATE_SYS_DDMMM:     aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D2" ) );  break;
2319cdf0e10cSrcweir                             case NF_DATE_SYS_MMYY:      aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D3" ) );  break;
2320cdf0e10cSrcweir                             case NF_DATETIME_SYSTEM_SHORT_HHMM:
2321cdf0e10cSrcweir                             case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
2322cdf0e10cSrcweir                                                         aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D4" ) );  break;
2323cdf0e10cSrcweir                             case NF_DATE_DIN_MMDD:      aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D5" ) );  break;
2324cdf0e10cSrcweir                             case NF_TIME_HHMMSSAMPM:    aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D6" ) );  break;
2325cdf0e10cSrcweir                             case NF_TIME_HHMMAMPM:      aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D7" ) );  break;
2326cdf0e10cSrcweir                             case NF_TIME_HHMMSS:        aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D8" ) );  break;
2327cdf0e10cSrcweir                             case NF_TIME_HHMM:          aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D9" ) );  break;
2328cdf0e10cSrcweir                             default:                    aFuncResult = 'G';
2329cdf0e10cSrcweir                         }
2330cdf0e10cSrcweir                     }
2331cdf0e10cSrcweir                 }
2332cdf0e10cSrcweir                 if( bAppendPrec )
2333cdf0e10cSrcweir                     aFuncResult += String::CreateFromInt32( nPrec );
2334cdf0e10cSrcweir                 const SvNumberformat* pFormat = pFormatter->GetEntry( nFormat );
2335cdf0e10cSrcweir                 if( lcl_FormatHasNegColor( pFormat ) )
2336cdf0e10cSrcweir                     aFuncResult += '-';
2337cdf0e10cSrcweir                 if( lcl_FormatHasOpenPar( pFormat ) )
2338cdf0e10cSrcweir                     aFuncResult.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "()" ) );
2339cdf0e10cSrcweir                 PushString( aFuncResult );
2340cdf0e10cSrcweir             }
2341cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "COLOR" ) )
2342cdf0e10cSrcweir             {   // 1 = negative values are colored, otherwise 0
2343cdf0e10cSrcweir                 const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2344cdf0e10cSrcweir                 PushInt( lcl_FormatHasNegColor( pFormat ) ? 1 : 0 );
2345cdf0e10cSrcweir             }
2346cdf0e10cSrcweir             else if( aInfoType.EqualsAscii( "PARENTHESES" ) )
2347cdf0e10cSrcweir             {   // 1 = format string contains a '(' character, otherwise 0
2348cdf0e10cSrcweir                 const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2349cdf0e10cSrcweir                 PushInt( lcl_FormatHasOpenPar( pFormat ) ? 1 : 0 );
2350cdf0e10cSrcweir             }
2351cdf0e10cSrcweir             else
2352cdf0e10cSrcweir                 PushIllegalArgument();
2353cdf0e10cSrcweir         }
2354cdf0e10cSrcweir     }
2355cdf0e10cSrcweir }
2356cdf0e10cSrcweir 
2357cdf0e10cSrcweir 
ScIsRef()2358cdf0e10cSrcweir void ScInterpreter::ScIsRef()
2359cdf0e10cSrcweir {
2360cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCell" );
2361cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2362cdf0e10cSrcweir     short nRes = 0;
2363cdf0e10cSrcweir     switch ( GetStackType() )
2364cdf0e10cSrcweir     {
2365cdf0e10cSrcweir         case svSingleRef :
2366cdf0e10cSrcweir         {
2367cdf0e10cSrcweir             ScAddress aAdr;
2368cdf0e10cSrcweir             PopSingleRef( aAdr );
2369cdf0e10cSrcweir             if ( !nGlobalError )
2370cdf0e10cSrcweir                 nRes = 1;
2371cdf0e10cSrcweir         }
2372cdf0e10cSrcweir         break;
2373cdf0e10cSrcweir         case svDoubleRef :
2374cdf0e10cSrcweir         {
2375cdf0e10cSrcweir             ScRange aRange;
2376cdf0e10cSrcweir             PopDoubleRef( aRange );
2377cdf0e10cSrcweir             if ( !nGlobalError )
2378cdf0e10cSrcweir                 nRes = 1;
2379cdf0e10cSrcweir         }
2380cdf0e10cSrcweir         break;
2381cdf0e10cSrcweir         case svRefList :
2382cdf0e10cSrcweir         {
2383cdf0e10cSrcweir             FormulaTokenRef x = PopToken();
2384cdf0e10cSrcweir             if ( !nGlobalError )
2385cdf0e10cSrcweir                 nRes = !static_cast<ScToken*>(x.get())->GetRefList()->empty();
2386cdf0e10cSrcweir         }
2387cdf0e10cSrcweir         break;
2388cdf0e10cSrcweir         default:
2389cdf0e10cSrcweir             Pop();
2390cdf0e10cSrcweir     }
2391cdf0e10cSrcweir     nGlobalError = 0;
2392cdf0e10cSrcweir     PushInt( nRes );
2393cdf0e10cSrcweir }
2394cdf0e10cSrcweir 
2395cdf0e10cSrcweir 
ScIsValue()2396cdf0e10cSrcweir void ScInterpreter::ScIsValue()
2397cdf0e10cSrcweir {
2398cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsValue" );
2399cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2400cdf0e10cSrcweir     short nRes = 0;
2401cdf0e10cSrcweir     switch ( GetRawStackType() )
2402cdf0e10cSrcweir     {
2403cdf0e10cSrcweir         case svDouble:
2404cdf0e10cSrcweir             Pop();
2405cdf0e10cSrcweir             nRes = 1;
2406cdf0e10cSrcweir         break;
2407cdf0e10cSrcweir         case svDoubleRef :
2408cdf0e10cSrcweir         case svSingleRef :
2409cdf0e10cSrcweir         {
2410cdf0e10cSrcweir             ScAddress aAdr;
2411cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2412cdf0e10cSrcweir                 break;
2413cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2414cdf0e10cSrcweir             if (GetCellErrCode( pCell ) == 0)
2415cdf0e10cSrcweir             {
2416cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
2417cdf0e10cSrcweir                 {
2418cdf0e10cSrcweir                     case CELLTYPE_VALUE :
2419cdf0e10cSrcweir                         nRes = 1;
2420cdf0e10cSrcweir                         break;
2421cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
2422cdf0e10cSrcweir                         nRes = ((ScFormulaCell*)pCell)->IsValue() &&
2423cdf0e10cSrcweir                             !((ScFormulaCell*)pCell)->IsEmpty();
2424cdf0e10cSrcweir                         break;
2425cdf0e10cSrcweir                     default:
2426cdf0e10cSrcweir                         ; // nothing
2427cdf0e10cSrcweir                 }
2428cdf0e10cSrcweir             }
2429cdf0e10cSrcweir         }
2430cdf0e10cSrcweir         break;
2431cdf0e10cSrcweir         case svMatrix:
2432cdf0e10cSrcweir         {
2433cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
2434cdf0e10cSrcweir             if ( !pMat )
2435cdf0e10cSrcweir                 ;   // nothing
2436cdf0e10cSrcweir             else if ( !pJumpMatrix )
2437cdf0e10cSrcweir             {
2438cdf0e10cSrcweir                 if (pMat->GetErrorIfNotString( 0 ) == 0)
2439cdf0e10cSrcweir                     nRes = pMat->IsValue( 0 );
2440cdf0e10cSrcweir             }
2441cdf0e10cSrcweir             else
2442cdf0e10cSrcweir             {
2443cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
2444cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
2445cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
2446cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
2447cdf0e10cSrcweir                     if (pMat->GetErrorIfNotString( nC, nR) == 0)
2448cdf0e10cSrcweir                         nRes = pMat->IsValue( nC, nR);
2449cdf0e10cSrcweir             }
2450cdf0e10cSrcweir         }
2451cdf0e10cSrcweir         break;
2452cdf0e10cSrcweir         default:
2453cdf0e10cSrcweir             Pop();
2454cdf0e10cSrcweir     }
2455cdf0e10cSrcweir     nGlobalError = 0;
2456cdf0e10cSrcweir     PushInt( nRes );
2457cdf0e10cSrcweir }
2458cdf0e10cSrcweir 
2459cdf0e10cSrcweir 
ScIsFormula()2460cdf0e10cSrcweir void ScInterpreter::ScIsFormula()
2461cdf0e10cSrcweir {
2462cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsFormula" );
2463cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2464cdf0e10cSrcweir     short nRes = 0;
2465cdf0e10cSrcweir     switch ( GetStackType() )
2466cdf0e10cSrcweir     {
2467cdf0e10cSrcweir         case svDoubleRef :
2468cdf0e10cSrcweir         case svSingleRef :
2469cdf0e10cSrcweir         {
2470cdf0e10cSrcweir             ScAddress aAdr;
2471cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2472cdf0e10cSrcweir                 break;
2473cdf0e10cSrcweir             nRes = (GetCellType( GetCell( aAdr ) ) == CELLTYPE_FORMULA);
2474cdf0e10cSrcweir         }
2475cdf0e10cSrcweir         break;
2476cdf0e10cSrcweir         default:
2477cdf0e10cSrcweir             Pop();
2478cdf0e10cSrcweir     }
2479cdf0e10cSrcweir     nGlobalError = 0;
2480cdf0e10cSrcweir     PushInt( nRes );
2481cdf0e10cSrcweir }
2482cdf0e10cSrcweir 
2483cdf0e10cSrcweir 
ScFormula()2484cdf0e10cSrcweir void ScInterpreter::ScFormula()
2485cdf0e10cSrcweir {
2486cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFormula" );
2487cdf0e10cSrcweir     String aFormula;
2488cdf0e10cSrcweir     switch ( GetStackType() )
2489cdf0e10cSrcweir     {
2490cdf0e10cSrcweir         case svDoubleRef :
2491cdf0e10cSrcweir         case svSingleRef :
2492cdf0e10cSrcweir         {
2493cdf0e10cSrcweir             ScAddress aAdr;
2494cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2495cdf0e10cSrcweir                 break;
2496cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2497cdf0e10cSrcweir             switch ( GetCellType( pCell ) )
2498cdf0e10cSrcweir             {
2499cdf0e10cSrcweir                 case CELLTYPE_FORMULA :
2500cdf0e10cSrcweir                     ((ScFormulaCell*)pCell)->GetFormula( aFormula );
2501cdf0e10cSrcweir                 break;
2502cdf0e10cSrcweir                 default:
2503cdf0e10cSrcweir                     SetError( NOTAVAILABLE );
2504cdf0e10cSrcweir             }
2505cdf0e10cSrcweir         }
2506cdf0e10cSrcweir         break;
2507cdf0e10cSrcweir         default:
2508cdf0e10cSrcweir             Pop();
2509cdf0e10cSrcweir             SetError( NOTAVAILABLE );
2510cdf0e10cSrcweir     }
2511cdf0e10cSrcweir     PushString( aFormula );
2512cdf0e10cSrcweir }
2513cdf0e10cSrcweir 
2514cdf0e10cSrcweir 
2515cdf0e10cSrcweir 
ScIsNV()2516cdf0e10cSrcweir void ScInterpreter::ScIsNV()
2517cdf0e10cSrcweir {
2518cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNV" );
2519cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2520cdf0e10cSrcweir     short nRes = 0;
2521cdf0e10cSrcweir     switch ( GetStackType() )
2522cdf0e10cSrcweir     {
2523cdf0e10cSrcweir         case svDoubleRef :
2524cdf0e10cSrcweir         case svSingleRef :
2525cdf0e10cSrcweir         {
2526cdf0e10cSrcweir             ScAddress aAdr;
2527cdf0e10cSrcweir             PopDoubleRefOrSingleRef( aAdr );
2528cdf0e10cSrcweir             if ( nGlobalError == NOTAVAILABLE )
2529cdf0e10cSrcweir                 nRes = 1;
2530cdf0e10cSrcweir             else
2531cdf0e10cSrcweir             {
2532cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
2533cdf0e10cSrcweir                 sal_uInt16 nErr = GetCellErrCode( pCell );
2534cdf0e10cSrcweir                 nRes = (nErr == NOTAVAILABLE);
2535cdf0e10cSrcweir             }
2536cdf0e10cSrcweir         }
2537cdf0e10cSrcweir         break;
2538cdf0e10cSrcweir         case svMatrix:
2539cdf0e10cSrcweir         {
2540cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
2541cdf0e10cSrcweir             if ( !pMat )
2542cdf0e10cSrcweir                 ;   // nothing
2543cdf0e10cSrcweir             else if ( !pJumpMatrix )
2544cdf0e10cSrcweir                 nRes = (pMat->GetErrorIfNotString( 0 ) == NOTAVAILABLE);
2545cdf0e10cSrcweir             else
2546cdf0e10cSrcweir             {
2547cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
2548cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
2549cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
2550cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
2551cdf0e10cSrcweir                     nRes = (pMat->GetErrorIfNotString( nC, nR) == NOTAVAILABLE);
2552cdf0e10cSrcweir             }
2553cdf0e10cSrcweir         }
2554cdf0e10cSrcweir         break;
2555cdf0e10cSrcweir         default:
2556cdf0e10cSrcweir             PopError();
2557cdf0e10cSrcweir             if ( nGlobalError == NOTAVAILABLE )
2558cdf0e10cSrcweir                 nRes = 1;
2559cdf0e10cSrcweir     }
2560cdf0e10cSrcweir     nGlobalError = 0;
2561cdf0e10cSrcweir     PushInt( nRes );
2562cdf0e10cSrcweir }
2563cdf0e10cSrcweir 
2564cdf0e10cSrcweir 
ScIsErr()2565cdf0e10cSrcweir void ScInterpreter::ScIsErr()
2566cdf0e10cSrcweir {
2567cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsErr" );
2568cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2569cdf0e10cSrcweir     short nRes = 0;
2570cdf0e10cSrcweir     switch ( GetStackType() )
2571cdf0e10cSrcweir     {
2572cdf0e10cSrcweir         case svDoubleRef :
2573cdf0e10cSrcweir         case svSingleRef :
2574cdf0e10cSrcweir         {
2575cdf0e10cSrcweir             ScAddress aAdr;
2576cdf0e10cSrcweir             PopDoubleRefOrSingleRef( aAdr );
2577cdf0e10cSrcweir             if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2578cdf0e10cSrcweir                 nRes = 1;
2579cdf0e10cSrcweir             else
2580cdf0e10cSrcweir             {
2581cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
2582cdf0e10cSrcweir                 sal_uInt16 nErr = GetCellErrCode( pCell );
2583cdf0e10cSrcweir                 nRes = (nErr && nErr != NOTAVAILABLE);
2584cdf0e10cSrcweir             }
2585cdf0e10cSrcweir         }
2586cdf0e10cSrcweir         break;
2587cdf0e10cSrcweir         case svMatrix:
2588cdf0e10cSrcweir         {
2589cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
2590cdf0e10cSrcweir             if ( nGlobalError || !pMat )
2591cdf0e10cSrcweir                 nRes = ((nGlobalError && nGlobalError != NOTAVAILABLE) || !pMat);
2592cdf0e10cSrcweir             else if ( !pJumpMatrix )
2593cdf0e10cSrcweir             {
2594cdf0e10cSrcweir                 sal_uInt16 nErr = pMat->GetErrorIfNotString( 0 );
2595cdf0e10cSrcweir                 nRes = (nErr && nErr != NOTAVAILABLE);
2596cdf0e10cSrcweir             }
2597cdf0e10cSrcweir             else
2598cdf0e10cSrcweir             {
2599cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
2600cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
2601cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
2602cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
2603cdf0e10cSrcweir                 {
2604cdf0e10cSrcweir                     sal_uInt16 nErr = pMat->GetErrorIfNotString( nC, nR);
2605cdf0e10cSrcweir                     nRes = (nErr && nErr != NOTAVAILABLE);
2606cdf0e10cSrcweir                 }
2607cdf0e10cSrcweir             }
2608cdf0e10cSrcweir         }
2609cdf0e10cSrcweir         break;
2610cdf0e10cSrcweir         default:
2611cdf0e10cSrcweir             PopError();
2612cdf0e10cSrcweir             if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2613cdf0e10cSrcweir                 nRes = 1;
2614cdf0e10cSrcweir     }
2615cdf0e10cSrcweir     nGlobalError = 0;
2616cdf0e10cSrcweir     PushInt( nRes );
2617cdf0e10cSrcweir }
2618cdf0e10cSrcweir 
2619cdf0e10cSrcweir 
ScIsError()2620cdf0e10cSrcweir void ScInterpreter::ScIsError()
2621cdf0e10cSrcweir {
2622cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsError" );
2623cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2624cdf0e10cSrcweir     short nRes = 0;
2625cdf0e10cSrcweir     switch ( GetStackType() )
2626cdf0e10cSrcweir     {
2627cdf0e10cSrcweir         case svDoubleRef :
2628cdf0e10cSrcweir         case svSingleRef :
2629cdf0e10cSrcweir         {
2630cdf0e10cSrcweir             ScAddress aAdr;
2631cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2632cdf0e10cSrcweir             {
2633cdf0e10cSrcweir                 nRes = 1;
2634cdf0e10cSrcweir                 break;
2635cdf0e10cSrcweir             }
2636cdf0e10cSrcweir             if ( nGlobalError )
2637cdf0e10cSrcweir                 nRes = 1;
2638cdf0e10cSrcweir             else
2639cdf0e10cSrcweir             {
2640cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
2641cdf0e10cSrcweir                 nRes = (GetCellErrCode( pCell ) != 0);
2642cdf0e10cSrcweir             }
2643cdf0e10cSrcweir         }
2644cdf0e10cSrcweir         break;
2645cdf0e10cSrcweir         case svMatrix:
2646cdf0e10cSrcweir         {
2647cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
2648cdf0e10cSrcweir             if ( nGlobalError || !pMat )
2649cdf0e10cSrcweir                 nRes = 1;
2650cdf0e10cSrcweir             else if ( !pJumpMatrix )
2651cdf0e10cSrcweir                 nRes = (pMat->GetErrorIfNotString( 0 ) != 0);
2652cdf0e10cSrcweir             else
2653cdf0e10cSrcweir             {
2654cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
2655cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
2656cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
2657cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
2658cdf0e10cSrcweir                     nRes = (pMat->GetErrorIfNotString( nC, nR) != 0);
2659cdf0e10cSrcweir             }
2660cdf0e10cSrcweir         }
2661cdf0e10cSrcweir         break;
2662cdf0e10cSrcweir         default:
2663cdf0e10cSrcweir             PopError();
2664cdf0e10cSrcweir             if ( nGlobalError )
2665cdf0e10cSrcweir                 nRes = 1;
2666cdf0e10cSrcweir     }
2667cdf0e10cSrcweir     nGlobalError = 0;
2668cdf0e10cSrcweir     PushInt( nRes );
2669cdf0e10cSrcweir }
2670cdf0e10cSrcweir 
2671cdf0e10cSrcweir 
IsEven()2672cdf0e10cSrcweir short ScInterpreter::IsEven()
2673cdf0e10cSrcweir {
2674cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsEven" );
2675cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
2676cdf0e10cSrcweir     short nRes = 0;
2677cdf0e10cSrcweir     double fVal = 0.0;
2678cdf0e10cSrcweir     switch ( GetStackType() )
2679cdf0e10cSrcweir     {
2680cdf0e10cSrcweir         case svDoubleRef :
2681cdf0e10cSrcweir         case svSingleRef :
2682cdf0e10cSrcweir         {
2683cdf0e10cSrcweir             ScAddress aAdr;
2684cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2685cdf0e10cSrcweir                 break;
2686cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2687cdf0e10cSrcweir             sal_uInt16 nErr = GetCellErrCode( pCell );
2688cdf0e10cSrcweir             if (nErr != 0)
2689cdf0e10cSrcweir                 SetError(nErr);
2690cdf0e10cSrcweir             else
2691cdf0e10cSrcweir             {
2692cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
2693cdf0e10cSrcweir                 {
2694cdf0e10cSrcweir                     case CELLTYPE_VALUE :
2695cdf0e10cSrcweir                         fVal = GetCellValue( aAdr, pCell );
2696cdf0e10cSrcweir                         nRes = 1;
2697cdf0e10cSrcweir                     break;
2698cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
2699cdf0e10cSrcweir                         if( ((ScFormulaCell*)pCell)->IsValue() )
2700cdf0e10cSrcweir                         {
2701cdf0e10cSrcweir                             fVal = GetCellValue( aAdr, pCell );
2702cdf0e10cSrcweir                             nRes = 1;
2703cdf0e10cSrcweir                         }
2704cdf0e10cSrcweir                     break;
2705cdf0e10cSrcweir                     default:
2706cdf0e10cSrcweir                         ; // nothing
2707cdf0e10cSrcweir                 }
2708cdf0e10cSrcweir             }
2709cdf0e10cSrcweir         }
2710cdf0e10cSrcweir         break;
2711cdf0e10cSrcweir         case svDouble:
2712cdf0e10cSrcweir         {
2713cdf0e10cSrcweir             fVal = PopDouble();
2714cdf0e10cSrcweir             nRes = 1;
2715cdf0e10cSrcweir         }
2716cdf0e10cSrcweir         break;
2717cdf0e10cSrcweir         case svMatrix:
2718cdf0e10cSrcweir         {
2719cdf0e10cSrcweir             ScMatrixRef pMat = PopMatrix();
2720cdf0e10cSrcweir             if ( !pMat )
2721cdf0e10cSrcweir                 ;   // nothing
2722cdf0e10cSrcweir             else if ( !pJumpMatrix )
2723cdf0e10cSrcweir             {
2724cdf0e10cSrcweir                 nRes = pMat->IsValue( 0 );
2725cdf0e10cSrcweir                 if ( nRes )
2726cdf0e10cSrcweir                     fVal = pMat->GetDouble( 0 );
2727cdf0e10cSrcweir             }
2728cdf0e10cSrcweir             else
2729cdf0e10cSrcweir             {
2730cdf0e10cSrcweir                 SCSIZE nCols, nRows, nC, nR;
2731cdf0e10cSrcweir                 pMat->GetDimensions( nCols, nRows);
2732cdf0e10cSrcweir                 pJumpMatrix->GetPos( nC, nR);
2733cdf0e10cSrcweir                 if ( nC < nCols && nR < nRows )
2734cdf0e10cSrcweir                 {
2735cdf0e10cSrcweir                     nRes = pMat->IsValue( nC, nR);
2736cdf0e10cSrcweir                     if ( nRes )
2737cdf0e10cSrcweir                         fVal = pMat->GetDouble( nC, nR);
2738cdf0e10cSrcweir                 }
2739cdf0e10cSrcweir                 else
2740cdf0e10cSrcweir                     SetError( errNoValue);
2741cdf0e10cSrcweir             }
2742cdf0e10cSrcweir         }
2743cdf0e10cSrcweir         break;
2744cdf0e10cSrcweir         default:
2745cdf0e10cSrcweir             ; // nothing
2746cdf0e10cSrcweir     }
2747cdf0e10cSrcweir     if ( !nRes )
2748cdf0e10cSrcweir         SetError( errIllegalParameter);
2749cdf0e10cSrcweir     else
2750cdf0e10cSrcweir         nRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
2751cdf0e10cSrcweir     return nRes;
2752cdf0e10cSrcweir }
2753cdf0e10cSrcweir 
2754cdf0e10cSrcweir 
ScIsEven()2755cdf0e10cSrcweir void ScInterpreter::ScIsEven()
2756cdf0e10cSrcweir {
2757cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEven" );
2758cdf0e10cSrcweir     PushInt( IsEven() );
2759cdf0e10cSrcweir }
2760cdf0e10cSrcweir 
2761cdf0e10cSrcweir 
ScIsOdd()2762cdf0e10cSrcweir void ScInterpreter::ScIsOdd()
2763cdf0e10cSrcweir {
2764cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsOdd" );
2765cdf0e10cSrcweir     PushInt( !IsEven() );
2766cdf0e10cSrcweir }
2767cdf0e10cSrcweir 
2768cdf0e10cSrcweir 
ScN()2769cdf0e10cSrcweir void ScInterpreter::ScN()
2770cdf0e10cSrcweir {
2771cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScN" );
2772cdf0e10cSrcweir     sal_uInt16 nErr = nGlobalError;
2773cdf0e10cSrcweir     nGlobalError = 0;
2774cdf0e10cSrcweir     // Temporarily override the ConvertStringToValue() error for
2775cdf0e10cSrcweir     // GetCellValue() / GetCellValueOrZero()
2776cdf0e10cSrcweir     sal_uInt16 nSErr = mnStringNoValueError;
2777cdf0e10cSrcweir     mnStringNoValueError = errCellNoValue;
2778cdf0e10cSrcweir     double fVal = GetDouble();
2779cdf0e10cSrcweir     mnStringNoValueError = nSErr;
2780cdf0e10cSrcweir     if ( nGlobalError == NOTAVAILABLE || nGlobalError == errCellNoValue )
2781cdf0e10cSrcweir         nGlobalError = 0;       // N(#NA) and N("text") are ok
2782cdf0e10cSrcweir     if ( !nGlobalError && nErr != NOTAVAILABLE )
2783cdf0e10cSrcweir         nGlobalError = nErr;
2784cdf0e10cSrcweir     PushDouble( fVal );
2785cdf0e10cSrcweir }
2786cdf0e10cSrcweir 
2787cdf0e10cSrcweir 
ScTrim()2788cdf0e10cSrcweir void ScInterpreter::ScTrim()
2789cdf0e10cSrcweir {   // trimmt nicht nur sondern schnibbelt auch doppelte raus!
2790cdf0e10cSrcweir     String aVal( GetString() );
2791cdf0e10cSrcweir     aVal.EraseLeadingChars();
2792cdf0e10cSrcweir     aVal.EraseTrailingChars();
2793cdf0e10cSrcweir     String aStr;
2794cdf0e10cSrcweir     register const sal_Unicode* p = aVal.GetBuffer();
2795cdf0e10cSrcweir     register const sal_Unicode* const pEnd = p + aVal.Len();
2796cdf0e10cSrcweir     while ( p < pEnd )
2797cdf0e10cSrcweir     {
2798cdf0e10cSrcweir         if ( *p != ' ' || p[-1] != ' ' )    // erster kann kein ' ' sein, -1 ist also ok
2799cdf0e10cSrcweir             aStr += *p;
2800cdf0e10cSrcweir         p++;
2801cdf0e10cSrcweir     }
2802cdf0e10cSrcweir     PushString( aStr );
2803cdf0e10cSrcweir }
2804cdf0e10cSrcweir 
2805cdf0e10cSrcweir 
ScUpper()2806cdf0e10cSrcweir void ScInterpreter::ScUpper()
2807cdf0e10cSrcweir {
2808cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrim" );
2809cdf0e10cSrcweir     String aString = GetString();
2810cdf0e10cSrcweir     ScGlobal::pCharClass->toUpper(aString);
2811cdf0e10cSrcweir     PushString(aString);
2812cdf0e10cSrcweir }
2813cdf0e10cSrcweir 
2814cdf0e10cSrcweir 
ScPropper()2815cdf0e10cSrcweir void ScInterpreter::ScPropper()
2816cdf0e10cSrcweir {
2817cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPropper" );
2818*5cd1c826Smseidel // TODO: what to do with I18N-CJK ?!?
2819cdf0e10cSrcweir     String aStr( GetString() );
2820cdf0e10cSrcweir     const xub_StrLen nLen = aStr.Len();
2821cdf0e10cSrcweir     // #i82487# don't try to write to empty string's BufferAccess
2822cdf0e10cSrcweir     // (would crash now that the empty string is const)
2823cdf0e10cSrcweir     if ( nLen > 0 )
2824cdf0e10cSrcweir     {
2825cdf0e10cSrcweir         String aUpr( ScGlobal::pCharClass->upper( aStr ) );
2826cdf0e10cSrcweir         String aLwr( ScGlobal::pCharClass->lower( aStr ) );
2827cdf0e10cSrcweir         register sal_Unicode* pStr = aStr.GetBufferAccess();
2828cdf0e10cSrcweir         const sal_Unicode* pUpr = aUpr.GetBuffer();
2829cdf0e10cSrcweir         const sal_Unicode* pLwr = aLwr.GetBuffer();
2830cdf0e10cSrcweir         *pStr = *pUpr;
2831cdf0e10cSrcweir         String aTmpStr( 'x' );
2832cdf0e10cSrcweir         xub_StrLen nPos = 1;
2833cdf0e10cSrcweir         while( nPos < nLen )
2834cdf0e10cSrcweir         {
2835cdf0e10cSrcweir             aTmpStr.SetChar( 0, pStr[nPos-1] );
2836cdf0e10cSrcweir             if ( !ScGlobal::pCharClass->isLetter( aTmpStr, 0 ) )
2837cdf0e10cSrcweir                 pStr[nPos] = pUpr[nPos];
2838cdf0e10cSrcweir             else
2839cdf0e10cSrcweir                 pStr[nPos] = pLwr[nPos];
2840cdf0e10cSrcweir             nPos++;
2841cdf0e10cSrcweir         }
2842cdf0e10cSrcweir         aStr.ReleaseBufferAccess( nLen );
2843cdf0e10cSrcweir     }
2844cdf0e10cSrcweir     PushString( aStr );
2845cdf0e10cSrcweir }
2846cdf0e10cSrcweir 
2847cdf0e10cSrcweir 
ScLower()2848cdf0e10cSrcweir void ScInterpreter::ScLower()
2849cdf0e10cSrcweir {
2850cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLower" );
2851cdf0e10cSrcweir     String aString( GetString() );
2852cdf0e10cSrcweir     ScGlobal::pCharClass->toLower(aString);
2853cdf0e10cSrcweir     PushString(aString);
2854cdf0e10cSrcweir }
2855cdf0e10cSrcweir 
2856cdf0e10cSrcweir 
ScLen()2857cdf0e10cSrcweir void ScInterpreter::ScLen()
2858cdf0e10cSrcweir {
2859cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLen" );
2860cdf0e10cSrcweir     String aStr( GetString() );
2861cdf0e10cSrcweir     PushDouble( aStr.Len() );
2862cdf0e10cSrcweir }
2863cdf0e10cSrcweir 
2864cdf0e10cSrcweir 
ScT()2865cdf0e10cSrcweir void ScInterpreter::ScT()
2866cdf0e10cSrcweir {
2867cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScT" );
2868cdf0e10cSrcweir     switch ( GetStackType() )
2869cdf0e10cSrcweir     {
2870cdf0e10cSrcweir         case svDoubleRef :
2871cdf0e10cSrcweir         case svSingleRef :
2872cdf0e10cSrcweir         {
2873cdf0e10cSrcweir             ScAddress aAdr;
2874cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
2875cdf0e10cSrcweir             {
2876cdf0e10cSrcweir                 PushInt(0);
2877cdf0e10cSrcweir                 return ;
2878cdf0e10cSrcweir             }
2879cdf0e10cSrcweir             sal_Bool bValue = sal_False;
2880cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
2881cdf0e10cSrcweir             if ( GetCellErrCode( pCell ) == 0 )
2882cdf0e10cSrcweir             {
2883cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
2884cdf0e10cSrcweir                 {
2885cdf0e10cSrcweir                     case CELLTYPE_VALUE :
2886cdf0e10cSrcweir                         bValue = sal_True;
2887cdf0e10cSrcweir                         break;
2888cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
2889cdf0e10cSrcweir                         bValue = ((ScFormulaCell*)pCell)->IsValue();
2890cdf0e10cSrcweir                         break;
2891cdf0e10cSrcweir                     default:
2892cdf0e10cSrcweir                         ; // nothing
2893cdf0e10cSrcweir                 }
2894cdf0e10cSrcweir             }
2895cdf0e10cSrcweir             if ( bValue )
2896cdf0e10cSrcweir                 PushString( EMPTY_STRING );
2897cdf0e10cSrcweir             else
2898cdf0e10cSrcweir             {
2899cdf0e10cSrcweir                 //  wie GetString()
2900cdf0e10cSrcweir                 GetCellString( aTempStr, pCell );
2901cdf0e10cSrcweir                 PushString( aTempStr );
2902cdf0e10cSrcweir             }
2903cdf0e10cSrcweir         }
2904cdf0e10cSrcweir         break;
2905cdf0e10cSrcweir         case svDouble :
2906cdf0e10cSrcweir         {
2907cdf0e10cSrcweir             PopError();
2908cdf0e10cSrcweir             PushString( EMPTY_STRING );
2909cdf0e10cSrcweir         }
2910cdf0e10cSrcweir         break;
2911cdf0e10cSrcweir         case svString :
2912cdf0e10cSrcweir             ;   // leave on stack
2913cdf0e10cSrcweir         break;
2914cdf0e10cSrcweir         default :
2915cdf0e10cSrcweir             PushError( errUnknownOpCode);
2916cdf0e10cSrcweir     }
2917cdf0e10cSrcweir }
2918cdf0e10cSrcweir 
2919cdf0e10cSrcweir 
ScValue()2920cdf0e10cSrcweir void ScInterpreter::ScValue()
2921cdf0e10cSrcweir {
2922cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScValue" );
2923cdf0e10cSrcweir     String aInputString;
2924cdf0e10cSrcweir     double fVal;
2925cdf0e10cSrcweir 
2926cdf0e10cSrcweir     switch ( GetRawStackType() )
2927cdf0e10cSrcweir     {
2928cdf0e10cSrcweir         case svMissing:
2929cdf0e10cSrcweir         case svEmptyCell:
2930cdf0e10cSrcweir             Pop();
2931cdf0e10cSrcweir             PushInt(0);
2932cdf0e10cSrcweir             return;
2933cdf0e10cSrcweir         case svDouble:
2934cdf0e10cSrcweir             return;     // leave on stack
2935cdf0e10cSrcweir             //break;
2936cdf0e10cSrcweir 
2937cdf0e10cSrcweir         case svSingleRef:
2938cdf0e10cSrcweir         case svDoubleRef:
2939cdf0e10cSrcweir             {
2940cdf0e10cSrcweir                 ScAddress aAdr;
2941cdf0e10cSrcweir                 if ( !PopDoubleRefOrSingleRef( aAdr ) )
2942cdf0e10cSrcweir                 {
2943cdf0e10cSrcweir                     PushInt(0);
2944cdf0e10cSrcweir                     return;
2945cdf0e10cSrcweir                 }
2946cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
2947cdf0e10cSrcweir                 if ( pCell && pCell->HasStringData() )
2948cdf0e10cSrcweir                     GetCellString( aInputString, pCell );
2949cdf0e10cSrcweir                 else if ( pCell && pCell->HasValueData() )
2950cdf0e10cSrcweir                 {
2951cdf0e10cSrcweir                     PushDouble( GetCellValue(aAdr, pCell) );
2952cdf0e10cSrcweir                     return;
2953cdf0e10cSrcweir                 }
2954cdf0e10cSrcweir                 else
2955cdf0e10cSrcweir                 {
2956cdf0e10cSrcweir                     PushDouble(0.0);
2957cdf0e10cSrcweir                     return;
2958cdf0e10cSrcweir                 }
2959cdf0e10cSrcweir             }
2960cdf0e10cSrcweir             break;
2961cdf0e10cSrcweir         case svMatrix:
2962cdf0e10cSrcweir             {
2963cdf0e10cSrcweir                 ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
2964cdf0e10cSrcweir                         aInputString);
2965cdf0e10cSrcweir                 switch (nType)
2966cdf0e10cSrcweir                 {
2967cdf0e10cSrcweir                     case SC_MATVAL_EMPTY:
2968cdf0e10cSrcweir                         fVal = 0.0;
2969cdf0e10cSrcweir                         // fallthru
2970cdf0e10cSrcweir                     case SC_MATVAL_VALUE:
2971cdf0e10cSrcweir                     case SC_MATVAL_BOOLEAN:
2972cdf0e10cSrcweir                         PushDouble( fVal);
2973cdf0e10cSrcweir                         return;
2974cdf0e10cSrcweir                         //break;
2975cdf0e10cSrcweir                     case SC_MATVAL_STRING:
2976cdf0e10cSrcweir                         // evaluated below
2977cdf0e10cSrcweir                         break;
2978cdf0e10cSrcweir                     default:
2979cdf0e10cSrcweir                         PushIllegalArgument();
2980cdf0e10cSrcweir                 }
2981cdf0e10cSrcweir             }
2982cdf0e10cSrcweir             break;
2983cdf0e10cSrcweir         default:
2984cdf0e10cSrcweir             aInputString = GetString();
2985cdf0e10cSrcweir             break;
2986cdf0e10cSrcweir     }
2987cdf0e10cSrcweir 
2988cdf0e10cSrcweir     sal_uInt32 nFIndex = 0;     // 0 for default locale
2989cdf0e10cSrcweir     if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
2990cdf0e10cSrcweir         PushDouble(fVal);
2991cdf0e10cSrcweir     else
2992cdf0e10cSrcweir         PushIllegalArgument();
2993cdf0e10cSrcweir }
2994cdf0e10cSrcweir 
2995cdf0e10cSrcweir 
2996*5cd1c826Smseidel // TODO: this should be a proper unicode string method
lcl_ScInterpreter_IsPrintable(sal_Unicode c)2997cdf0e10cSrcweir inline sal_Bool lcl_ScInterpreter_IsPrintable( sal_Unicode c )
2998cdf0e10cSrcweir {
2999cdf0e10cSrcweir     return 0x20 <= c && c != 0x7f;
3000cdf0e10cSrcweir }
3001cdf0e10cSrcweir 
ScClean()3002cdf0e10cSrcweir void ScInterpreter::ScClean()
3003cdf0e10cSrcweir {
3004cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScClean" );
3005cdf0e10cSrcweir     String aStr( GetString() );
3006cdf0e10cSrcweir     for ( xub_StrLen i = 0; i < aStr.Len(); i++ )
3007cdf0e10cSrcweir     {
3008cdf0e10cSrcweir         if ( !lcl_ScInterpreter_IsPrintable( aStr.GetChar( i ) ) )
3009cdf0e10cSrcweir             aStr.Erase(i,1);
3010cdf0e10cSrcweir     }
3011cdf0e10cSrcweir     PushString(aStr);
3012cdf0e10cSrcweir }
3013cdf0e10cSrcweir 
3014cdf0e10cSrcweir 
ScCode()3015cdf0e10cSrcweir void ScInterpreter::ScCode()
3016cdf0e10cSrcweir {
3017cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCode" );
3018*5cd1c826Smseidel // TODO: make it full range unicode?
3019cdf0e10cSrcweir     const String& rStr = GetString();
3020cdf0e10cSrcweir     PushInt( (sal_uChar) ByteString::ConvertFromUnicode( rStr.GetChar(0), gsl_getSystemTextEncoding() ) );
3021cdf0e10cSrcweir }
3022cdf0e10cSrcweir 
3023cdf0e10cSrcweir 
ScChar()3024cdf0e10cSrcweir void ScInterpreter::ScChar()
3025cdf0e10cSrcweir {
3026cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChar" );
3027*5cd1c826Smseidel // TODO: make it full range unicode?
3028cdf0e10cSrcweir     double fVal = GetDouble();
3029cdf0e10cSrcweir     if (fVal < 0.0 || fVal >= 256.0)
3030cdf0e10cSrcweir         PushIllegalArgument();
3031cdf0e10cSrcweir     else
3032cdf0e10cSrcweir     {
3033cdf0e10cSrcweir         String aStr( '0' );
3034cdf0e10cSrcweir         aStr.SetChar( 0, ByteString::ConvertToUnicode( (sal_Char) fVal, gsl_getSystemTextEncoding() ) );
3035cdf0e10cSrcweir         PushString( aStr );
3036cdf0e10cSrcweir     }
3037cdf0e10cSrcweir }
3038cdf0e10cSrcweir 
3039cdf0e10cSrcweir 
3040cdf0e10cSrcweir /* #i70213# fullwidth/halfwidth conversion provided by
3041cdf0e10cSrcweir  * Takashi Nakamoto <bluedwarf@ooo>
3042cdf0e10cSrcweir  * erAck: added Excel compatibility conversions as seen in issue's test case. */
3043cdf0e10cSrcweir 
lcl_convertIntoHalfWidth(const::rtl::OUString & rStr)3044cdf0e10cSrcweir static ::rtl::OUString lcl_convertIntoHalfWidth( const ::rtl::OUString & rStr )
3045cdf0e10cSrcweir {
3046cdf0e10cSrcweir     static bool bFirstASCCall = true;
3047cdf0e10cSrcweir     static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
3048cdf0e10cSrcweir 
3049cdf0e10cSrcweir     if( bFirstASCCall )
3050cdf0e10cSrcweir     {
3051cdf0e10cSrcweir         aTrans.loadModuleByImplName( ::rtl::OUString::createFromAscii( "FULLWIDTH_HALFWIDTH_LIKE_ASC" ), LANGUAGE_SYSTEM );
3052cdf0e10cSrcweir         bFirstASCCall = false;
3053cdf0e10cSrcweir     }
3054cdf0e10cSrcweir 
3055cdf0e10cSrcweir     return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
3056cdf0e10cSrcweir }
3057cdf0e10cSrcweir 
3058cdf0e10cSrcweir 
lcl_convertIntoFullWidth(const::rtl::OUString & rStr)3059cdf0e10cSrcweir static ::rtl::OUString lcl_convertIntoFullWidth( const ::rtl::OUString & rStr )
3060cdf0e10cSrcweir {
3061cdf0e10cSrcweir     static bool bFirstJISCall = true;
3062cdf0e10cSrcweir     static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
3063cdf0e10cSrcweir 
3064cdf0e10cSrcweir     if( bFirstJISCall )
3065cdf0e10cSrcweir     {
3066cdf0e10cSrcweir         aTrans.loadModuleByImplName( ::rtl::OUString::createFromAscii( "HALFWIDTH_FULLWIDTH_LIKE_JIS" ), LANGUAGE_SYSTEM );
3067cdf0e10cSrcweir         bFirstJISCall = false;
3068cdf0e10cSrcweir     }
3069cdf0e10cSrcweir 
3070cdf0e10cSrcweir     return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
3071cdf0e10cSrcweir }
3072cdf0e10cSrcweir 
3073cdf0e10cSrcweir 
3074cdf0e10cSrcweir /* ODFF:
3075cdf0e10cSrcweir  * Summary: Converts half-width to full-width ASCII and katakana characters.
3076cdf0e10cSrcweir  * Semantics: Conversion is done for half-width ASCII and katakana characters,
3077cdf0e10cSrcweir  * other characters are simply copied from T to the result. This is the
3078cdf0e10cSrcweir  * complementary function to ASC.
3079cdf0e10cSrcweir  * For references regarding halfwidth and fullwidth characters see
3080cdf0e10cSrcweir  * http://www.unicode.org/reports/tr11/
3081cdf0e10cSrcweir  * http://www.unicode.org/charts/charindex2.html#H
3082cdf0e10cSrcweir  * http://www.unicode.org/charts/charindex2.html#F
3083cdf0e10cSrcweir  */
ScJis()3084cdf0e10cSrcweir void ScInterpreter::ScJis()
3085cdf0e10cSrcweir {
3086cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScJis" );
3087cdf0e10cSrcweir     if (MustHaveParamCount( GetByte(), 1))
3088cdf0e10cSrcweir         PushString( lcl_convertIntoFullWidth( GetString()));
3089cdf0e10cSrcweir }
3090cdf0e10cSrcweir 
3091cdf0e10cSrcweir 
3092cdf0e10cSrcweir /* ODFF:
3093cdf0e10cSrcweir  * Summary: Converts full-width to half-width ASCII and katakana characters.
3094cdf0e10cSrcweir  * Semantics: Conversion is done for full-width ASCII and katakana characters,
3095cdf0e10cSrcweir  * other characters are simply copied from T to the result. This is the
3096cdf0e10cSrcweir  * complementary function to JIS.
3097cdf0e10cSrcweir  */
ScAsc()3098cdf0e10cSrcweir void ScInterpreter::ScAsc()
3099cdf0e10cSrcweir {
3100cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAsc" );
3101cdf0e10cSrcweir     if (MustHaveParamCount( GetByte(), 1))
3102cdf0e10cSrcweir         PushString( lcl_convertIntoHalfWidth( GetString()));
3103cdf0e10cSrcweir }
3104cdf0e10cSrcweir 
ScUnicode()3105cdf0e10cSrcweir void ScInterpreter::ScUnicode()
3106cdf0e10cSrcweir {
3107cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnicode" );
3108cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 1 ) )
3109cdf0e10cSrcweir     {
3110cdf0e10cSrcweir         const rtl::OUString& rStr = GetString();
3111cdf0e10cSrcweir         if (rStr.getLength() <= 0)
3112cdf0e10cSrcweir             PushIllegalParameter();
3113cdf0e10cSrcweir         else
3114cdf0e10cSrcweir         {
3115cdf0e10cSrcweir             sal_Int32 i = 0;
3116cdf0e10cSrcweir             PushDouble( rStr.iterateCodePoints(&i) );
3117cdf0e10cSrcweir         }
3118cdf0e10cSrcweir     }
3119cdf0e10cSrcweir }
3120cdf0e10cSrcweir 
ScUnichar()3121cdf0e10cSrcweir void ScInterpreter::ScUnichar()
3122cdf0e10cSrcweir {
3123cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnichar" );
3124cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 1 ) )
3125cdf0e10cSrcweir     {
3126cdf0e10cSrcweir         double dVal = ::rtl::math::approxFloor( GetDouble() );
3127cdf0e10cSrcweir         if ((dVal < 0x000000) || (dVal > 0x10FFFF))
3128cdf0e10cSrcweir             PushIllegalArgument();
3129cdf0e10cSrcweir         else
3130cdf0e10cSrcweir         {
3131cdf0e10cSrcweir             sal_uInt32 nCodePoint = static_cast<sal_uInt32>( dVal );
3132cdf0e10cSrcweir             rtl::OUString aStr( &nCodePoint, 1 );
3133cdf0e10cSrcweir             PushString( aStr );
3134cdf0e10cSrcweir         }
3135cdf0e10cSrcweir     }
3136cdf0e10cSrcweir }
3137cdf0e10cSrcweir 
3138cdf0e10cSrcweir 
ScMin(sal_Bool bTextAsZero)3139cdf0e10cSrcweir void ScInterpreter::ScMin( sal_Bool bTextAsZero )
3140cdf0e10cSrcweir {
3141cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMin" );
3142cdf0e10cSrcweir     short nParamCount = GetByte();
3143cdf0e10cSrcweir     if (!MustHaveParamCountMin( nParamCount, 1))
3144cdf0e10cSrcweir         return;
3145cdf0e10cSrcweir     double nMin = ::std::numeric_limits<double>::max();
3146cdf0e10cSrcweir     double nVal = 0.0;
3147cdf0e10cSrcweir     ScAddress aAdr;
3148cdf0e10cSrcweir     ScRange aRange;
3149cdf0e10cSrcweir     size_t nRefInList = 0;
3150cdf0e10cSrcweir     while (nParamCount-- > 0)
3151cdf0e10cSrcweir     {
3152cdf0e10cSrcweir         switch (GetStackType())
3153cdf0e10cSrcweir         {
3154cdf0e10cSrcweir             case svDouble :
3155cdf0e10cSrcweir             {
3156cdf0e10cSrcweir                 nVal = GetDouble();
3157cdf0e10cSrcweir                 if (nMin > nVal) nMin = nVal;
3158cdf0e10cSrcweir                 nFuncFmtType = NUMBERFORMAT_NUMBER;
3159cdf0e10cSrcweir             }
3160cdf0e10cSrcweir             break;
3161cdf0e10cSrcweir             case svSingleRef :
3162cdf0e10cSrcweir             {
3163cdf0e10cSrcweir                 PopSingleRef( aAdr );
3164cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
3165cdf0e10cSrcweir                 if (HasCellValueData(pCell))
3166cdf0e10cSrcweir                 {
3167cdf0e10cSrcweir                     nVal = GetCellValue( aAdr, pCell );
3168cdf0e10cSrcweir                     CurFmtToFuncFmt();
3169cdf0e10cSrcweir                     if (nMin > nVal) nMin = nVal;
3170cdf0e10cSrcweir                 }
3171cdf0e10cSrcweir                 else if ( bTextAsZero && HasCellStringData( pCell ) )
3172cdf0e10cSrcweir                 {
3173cdf0e10cSrcweir                     if ( nMin > 0.0 )
3174cdf0e10cSrcweir                         nMin = 0.0;
3175cdf0e10cSrcweir                 }
3176cdf0e10cSrcweir             }
3177cdf0e10cSrcweir             break;
3178cdf0e10cSrcweir             case svDoubleRef :
3179cdf0e10cSrcweir             case svRefList :
3180cdf0e10cSrcweir             {
3181cdf0e10cSrcweir                 sal_uInt16 nErr = 0;
3182cdf0e10cSrcweir                 PopDoubleRef( aRange, nParamCount, nRefInList);
3183cdf0e10cSrcweir                 ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3184cdf0e10cSrcweir                 if (aValIter.GetFirst(nVal, nErr))
3185cdf0e10cSrcweir                 {
3186cdf0e10cSrcweir                     if (nMin > nVal)
3187cdf0e10cSrcweir                         nMin = nVal;
3188cdf0e10cSrcweir                     aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3189cdf0e10cSrcweir                     while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
3190cdf0e10cSrcweir                     {
3191cdf0e10cSrcweir                         if (nMin > nVal)
3192cdf0e10cSrcweir                             nMin = nVal;
3193cdf0e10cSrcweir                     }
3194cdf0e10cSrcweir                     SetError(nErr);
3195cdf0e10cSrcweir                 }
3196cdf0e10cSrcweir             }
3197cdf0e10cSrcweir             break;
3198cdf0e10cSrcweir             case svMatrix :
3199cdf0e10cSrcweir             {
3200cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3201cdf0e10cSrcweir                 if (pMat)
3202cdf0e10cSrcweir                 {
3203cdf0e10cSrcweir                     SCSIZE nC, nR;
3204cdf0e10cSrcweir                     nFuncFmtType = NUMBERFORMAT_NUMBER;
3205cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3206cdf0e10cSrcweir                     if (pMat->IsNumeric())
3207cdf0e10cSrcweir                     {
3208cdf0e10cSrcweir                         for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3209cdf0e10cSrcweir                             for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3210cdf0e10cSrcweir                             {
3211cdf0e10cSrcweir                                 nVal = pMat->GetDouble(nMatCol,nMatRow);
3212cdf0e10cSrcweir                                 if (nMin > nVal) nMin = nVal;
3213cdf0e10cSrcweir                             }
3214cdf0e10cSrcweir                     }
3215cdf0e10cSrcweir                     else
3216cdf0e10cSrcweir                     {
3217cdf0e10cSrcweir                         for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3218cdf0e10cSrcweir                         {
3219cdf0e10cSrcweir                             for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3220cdf0e10cSrcweir                             {
3221cdf0e10cSrcweir                                 if (!pMat->IsString(nMatCol,nMatRow))
3222cdf0e10cSrcweir                                 {
3223cdf0e10cSrcweir                                     nVal = pMat->GetDouble(nMatCol,nMatRow);
3224cdf0e10cSrcweir                                     if (nMin > nVal) nMin = nVal;
3225cdf0e10cSrcweir                                 }
3226cdf0e10cSrcweir                                 else if ( bTextAsZero )
3227cdf0e10cSrcweir                                 {
3228cdf0e10cSrcweir                                     if ( nMin > 0.0 )
3229cdf0e10cSrcweir                                         nMin = 0.0;
3230cdf0e10cSrcweir                                 }
3231cdf0e10cSrcweir                             }
3232cdf0e10cSrcweir                          }
3233cdf0e10cSrcweir                     }
3234cdf0e10cSrcweir                 }
3235cdf0e10cSrcweir             }
3236cdf0e10cSrcweir             break;
3237cdf0e10cSrcweir             case svString :
3238cdf0e10cSrcweir             {
3239cdf0e10cSrcweir                 Pop();
3240cdf0e10cSrcweir                 if ( bTextAsZero )
3241cdf0e10cSrcweir                 {
3242cdf0e10cSrcweir                     if ( nMin > 0.0 )
3243cdf0e10cSrcweir                         nMin = 0.0;
3244cdf0e10cSrcweir                 }
3245cdf0e10cSrcweir                 else
3246cdf0e10cSrcweir                     SetError(errIllegalParameter);
3247cdf0e10cSrcweir             }
3248cdf0e10cSrcweir             break;
3249cdf0e10cSrcweir             default :
3250cdf0e10cSrcweir                 Pop();
3251cdf0e10cSrcweir                 SetError(errIllegalParameter);
3252cdf0e10cSrcweir         }
3253cdf0e10cSrcweir     }
3254cdf0e10cSrcweir     if ( nVal < nMin  )
3255cdf0e10cSrcweir         PushDouble(0.0);
3256cdf0e10cSrcweir     else
3257cdf0e10cSrcweir         PushDouble(nMin);
3258cdf0e10cSrcweir }
3259cdf0e10cSrcweir 
ScMax(sal_Bool bTextAsZero)3260cdf0e10cSrcweir void ScInterpreter::ScMax( sal_Bool bTextAsZero )
3261cdf0e10cSrcweir {
3262cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMax" );
3263cdf0e10cSrcweir     short nParamCount = GetByte();
3264cdf0e10cSrcweir     if (!MustHaveParamCountMin( nParamCount, 1))
3265cdf0e10cSrcweir         return;
3266cdf0e10cSrcweir     double nMax = -(::std::numeric_limits<double>::max());
3267cdf0e10cSrcweir     double nVal = 0.0;
3268cdf0e10cSrcweir     ScAddress aAdr;
3269cdf0e10cSrcweir     ScRange aRange;
3270cdf0e10cSrcweir     size_t nRefInList = 0;
3271cdf0e10cSrcweir     while (nParamCount-- > 0)
3272cdf0e10cSrcweir     {
3273cdf0e10cSrcweir         switch (GetStackType())
3274cdf0e10cSrcweir         {
3275cdf0e10cSrcweir             case svDouble :
3276cdf0e10cSrcweir             {
3277cdf0e10cSrcweir                 nVal = GetDouble();
3278cdf0e10cSrcweir                 if (nMax < nVal) nMax = nVal;
3279cdf0e10cSrcweir                 nFuncFmtType = NUMBERFORMAT_NUMBER;
3280cdf0e10cSrcweir             }
3281cdf0e10cSrcweir             break;
3282cdf0e10cSrcweir             case svSingleRef :
3283cdf0e10cSrcweir             {
3284cdf0e10cSrcweir                 PopSingleRef( aAdr );
3285cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
3286cdf0e10cSrcweir                 if (HasCellValueData(pCell))
3287cdf0e10cSrcweir                 {
3288cdf0e10cSrcweir                     nVal = GetCellValue( aAdr, pCell );
3289cdf0e10cSrcweir                     CurFmtToFuncFmt();
3290cdf0e10cSrcweir                     if (nMax < nVal) nMax = nVal;
3291cdf0e10cSrcweir                 }
3292cdf0e10cSrcweir                 else if ( bTextAsZero && HasCellStringData( pCell ) )
3293cdf0e10cSrcweir                 {
3294cdf0e10cSrcweir                     if ( nMax < 0.0 )
3295cdf0e10cSrcweir                         nMax = 0.0;
3296cdf0e10cSrcweir                 }
3297cdf0e10cSrcweir             }
3298cdf0e10cSrcweir             break;
3299cdf0e10cSrcweir             case svDoubleRef :
3300cdf0e10cSrcweir             case svRefList :
3301cdf0e10cSrcweir             {
3302cdf0e10cSrcweir                 sal_uInt16 nErr = 0;
3303cdf0e10cSrcweir                 PopDoubleRef( aRange, nParamCount, nRefInList);
3304cdf0e10cSrcweir                 ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3305cdf0e10cSrcweir                 if (aValIter.GetFirst(nVal, nErr))
3306cdf0e10cSrcweir                 {
3307cdf0e10cSrcweir                     if (nMax < nVal)
3308cdf0e10cSrcweir                         nMax = nVal;
3309cdf0e10cSrcweir                     aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3310cdf0e10cSrcweir                     while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
3311cdf0e10cSrcweir                     {
3312cdf0e10cSrcweir                         if (nMax < nVal)
3313cdf0e10cSrcweir                             nMax = nVal;
3314cdf0e10cSrcweir                     }
3315cdf0e10cSrcweir                     SetError(nErr);
3316cdf0e10cSrcweir                 }
3317cdf0e10cSrcweir             }
3318cdf0e10cSrcweir             break;
3319cdf0e10cSrcweir             case svMatrix :
3320cdf0e10cSrcweir             {
3321cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3322cdf0e10cSrcweir                 if (pMat)
3323cdf0e10cSrcweir                 {
3324cdf0e10cSrcweir                     nFuncFmtType = NUMBERFORMAT_NUMBER;
3325cdf0e10cSrcweir                     SCSIZE nC, nR;
3326cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3327cdf0e10cSrcweir                     if (pMat->IsNumeric())
3328cdf0e10cSrcweir                     {
3329cdf0e10cSrcweir                         for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3330cdf0e10cSrcweir                             for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3331cdf0e10cSrcweir                             {
3332cdf0e10cSrcweir                                 nVal = pMat->GetDouble(nMatCol,nMatRow);
3333cdf0e10cSrcweir                                 if (nMax < nVal) nMax = nVal;
3334cdf0e10cSrcweir                             }
3335cdf0e10cSrcweir                     }
3336cdf0e10cSrcweir                     else
3337cdf0e10cSrcweir                     {
3338cdf0e10cSrcweir                         for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3339cdf0e10cSrcweir                         {
3340cdf0e10cSrcweir                             for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3341cdf0e10cSrcweir                             {
3342cdf0e10cSrcweir                                 if (!pMat->IsString(nMatCol,nMatRow))
3343cdf0e10cSrcweir                                 {
3344cdf0e10cSrcweir                                     nVal = pMat->GetDouble(nMatCol,nMatRow);
3345cdf0e10cSrcweir                                     if (nMax < nVal) nMax = nVal;
3346cdf0e10cSrcweir                                 }
3347cdf0e10cSrcweir                                 else if ( bTextAsZero )
3348cdf0e10cSrcweir                                 {
3349cdf0e10cSrcweir                                     if ( nMax < 0.0 )
3350cdf0e10cSrcweir                                         nMax = 0.0;
3351cdf0e10cSrcweir                                 }
3352cdf0e10cSrcweir                             }
3353cdf0e10cSrcweir                         }
3354cdf0e10cSrcweir                     }
3355cdf0e10cSrcweir                 }
3356cdf0e10cSrcweir             }
3357cdf0e10cSrcweir             break;
3358cdf0e10cSrcweir             case svString :
3359cdf0e10cSrcweir             {
3360cdf0e10cSrcweir                 Pop();
3361cdf0e10cSrcweir                 if ( bTextAsZero )
3362cdf0e10cSrcweir                 {
3363cdf0e10cSrcweir                     if ( nMax < 0.0 )
3364cdf0e10cSrcweir                         nMax = 0.0;
3365cdf0e10cSrcweir                 }
3366cdf0e10cSrcweir                 else
3367cdf0e10cSrcweir                     SetError(errIllegalParameter);
3368cdf0e10cSrcweir             }
3369cdf0e10cSrcweir             break;
3370cdf0e10cSrcweir             default :
3371cdf0e10cSrcweir                 Pop();
3372cdf0e10cSrcweir                 SetError(errIllegalParameter);
3373cdf0e10cSrcweir         }
3374cdf0e10cSrcweir     }
3375cdf0e10cSrcweir     if ( nVal > nMax  )
3376cdf0e10cSrcweir         PushDouble(0.0);
3377cdf0e10cSrcweir     else
3378cdf0e10cSrcweir         PushDouble(nMax);
3379cdf0e10cSrcweir }
3380cdf0e10cSrcweir 
IterateParameters(ScIterFunc eFunc,sal_Bool bTextAsZero)3381cdf0e10cSrcweir double ScInterpreter::IterateParameters( ScIterFunc eFunc, sal_Bool bTextAsZero )
3382cdf0e10cSrcweir {
3383cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
3384cdf0e10cSrcweir     short nParamCount = GetByte();
3385cdf0e10cSrcweir     double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
3386cdf0e10cSrcweir     double fVal = 0.0;
3387cdf0e10cSrcweir     double fMem = 0.0;
3388cdf0e10cSrcweir     sal_Bool bNull = sal_True;
3389cdf0e10cSrcweir     sal_uLong nCount = 0;
3390cdf0e10cSrcweir     ScAddress aAdr;
3391cdf0e10cSrcweir     ScRange aRange;
3392cdf0e10cSrcweir     size_t nRefInList = 0;
3393cdf0e10cSrcweir     if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3394cdf0e10cSrcweir         nGlobalError = 0;
3395cdf0e10cSrcweir     while (nParamCount-- > 0)
3396cdf0e10cSrcweir     {
3397cdf0e10cSrcweir         switch (GetStackType())
3398cdf0e10cSrcweir         {
3399cdf0e10cSrcweir 
3400cdf0e10cSrcweir             case svString:
3401cdf0e10cSrcweir             {
3402cdf0e10cSrcweir                 if( eFunc == ifCOUNT )
3403cdf0e10cSrcweir                 {
3404cdf0e10cSrcweir                     String aStr( PopString() );
3405cdf0e10cSrcweir                     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
3406cdf0e10cSrcweir                     if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
3407cdf0e10cSrcweir                         nCount++;
3408cdf0e10cSrcweir                 }
3409cdf0e10cSrcweir                 else
3410cdf0e10cSrcweir                 {
3411cdf0e10cSrcweir                     switch ( eFunc )
3412cdf0e10cSrcweir                     {
3413cdf0e10cSrcweir                         case ifAVERAGE:
3414cdf0e10cSrcweir                         case ifSUM:
3415cdf0e10cSrcweir                         case ifSUMSQ:
3416cdf0e10cSrcweir                         case ifPRODUCT:
3417cdf0e10cSrcweir                         {
3418cdf0e10cSrcweir                             if ( bTextAsZero )
3419cdf0e10cSrcweir                             {
3420cdf0e10cSrcweir                                 Pop();
3421cdf0e10cSrcweir                                 nCount++;
3422cdf0e10cSrcweir                                 if ( eFunc == ifPRODUCT )
3423cdf0e10cSrcweir                                     fRes = 0.0;
3424cdf0e10cSrcweir                             }
3425cdf0e10cSrcweir                             else
3426cdf0e10cSrcweir                             {
3427cdf0e10cSrcweir                                 while (nParamCount-- > 0)
3428cdf0e10cSrcweir                                     Pop();
3429cdf0e10cSrcweir                                 SetError( errNoValue );
3430cdf0e10cSrcweir                             }
3431cdf0e10cSrcweir                         }
3432cdf0e10cSrcweir                         break;
3433cdf0e10cSrcweir                         default:
3434cdf0e10cSrcweir                             Pop();
3435cdf0e10cSrcweir                             nCount++;
3436cdf0e10cSrcweir                     }
3437cdf0e10cSrcweir                 }
3438cdf0e10cSrcweir             }
3439cdf0e10cSrcweir             break;
3440cdf0e10cSrcweir             case svDouble    :
3441cdf0e10cSrcweir                 fVal = GetDouble();
3442cdf0e10cSrcweir                 nCount++;
3443cdf0e10cSrcweir                 switch( eFunc )
3444cdf0e10cSrcweir                 {
3445cdf0e10cSrcweir                     case ifAVERAGE:
3446cdf0e10cSrcweir                     case ifSUM:
3447cdf0e10cSrcweir                         if ( bNull && fVal != 0.0 )
3448cdf0e10cSrcweir                         {
3449cdf0e10cSrcweir                             bNull = sal_False;
3450cdf0e10cSrcweir                             fMem = fVal;
3451cdf0e10cSrcweir                         }
3452cdf0e10cSrcweir                         else
3453cdf0e10cSrcweir                             fRes += fVal;
3454cdf0e10cSrcweir                         break;
3455cdf0e10cSrcweir                     case ifSUMSQ:   fRes += fVal * fVal; break;
3456cdf0e10cSrcweir                     case ifPRODUCT: fRes *= fVal; break;
3457cdf0e10cSrcweir                     default: ; // nothing
3458cdf0e10cSrcweir                 }
3459cdf0e10cSrcweir                 nFuncFmtType = NUMBERFORMAT_NUMBER;
3460cdf0e10cSrcweir                 break;
3461cdf0e10cSrcweir             case svSingleRef :
3462cdf0e10cSrcweir             {
3463cdf0e10cSrcweir                 PopSingleRef( aAdr );
3464cdf0e10cSrcweir                 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3465cdf0e10cSrcweir                 {
3466cdf0e10cSrcweir                     nGlobalError = 0;
3467cdf0e10cSrcweir                     if ( eFunc == ifCOUNT2 )
3468cdf0e10cSrcweir                         ++nCount;
3469cdf0e10cSrcweir                     break;
3470cdf0e10cSrcweir                 }
3471cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
3472cdf0e10cSrcweir                 if ( pCell )
3473cdf0e10cSrcweir                 {
3474cdf0e10cSrcweir                     if( eFunc == ifCOUNT2 )
3475cdf0e10cSrcweir                     {
3476cdf0e10cSrcweir                         CellType eCellType = pCell->GetCellType();
3477cdf0e10cSrcweir                         if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
3478cdf0e10cSrcweir                             nCount++;
3479cdf0e10cSrcweir                         if ( nGlobalError )
3480cdf0e10cSrcweir                             nGlobalError = 0;
3481cdf0e10cSrcweir                     }
3482cdf0e10cSrcweir                     else if ( pCell->HasValueData() )
3483cdf0e10cSrcweir                     {
3484cdf0e10cSrcweir                         nCount++;
3485cdf0e10cSrcweir                         fVal = GetCellValue( aAdr, pCell );
3486cdf0e10cSrcweir                         CurFmtToFuncFmt();
3487cdf0e10cSrcweir                         switch( eFunc )
3488cdf0e10cSrcweir                         {
3489cdf0e10cSrcweir                             case ifAVERAGE:
3490cdf0e10cSrcweir                             case ifSUM:
3491cdf0e10cSrcweir                                 if ( bNull && fVal != 0.0 )
3492cdf0e10cSrcweir                                 {
3493cdf0e10cSrcweir                                     bNull = sal_False;
3494cdf0e10cSrcweir                                     fMem = fVal;
3495cdf0e10cSrcweir                                 }
3496cdf0e10cSrcweir                                 else
3497cdf0e10cSrcweir                                     fRes += fVal;
3498cdf0e10cSrcweir                                 break;
3499cdf0e10cSrcweir                             case ifSUMSQ:   fRes += fVal * fVal; break;
3500cdf0e10cSrcweir                             case ifPRODUCT: fRes *= fVal; break;
3501cdf0e10cSrcweir                             case ifCOUNT:
3502cdf0e10cSrcweir                                 if ( nGlobalError )
3503cdf0e10cSrcweir                                 {
3504cdf0e10cSrcweir                                     nGlobalError = 0;
3505cdf0e10cSrcweir                                     nCount--;
3506cdf0e10cSrcweir                                 }
3507cdf0e10cSrcweir                                 break;
3508cdf0e10cSrcweir                             default: ; // nothing
3509cdf0e10cSrcweir                         }
3510cdf0e10cSrcweir                     }
3511cdf0e10cSrcweir                     else if ( bTextAsZero && pCell->HasStringData() )
3512cdf0e10cSrcweir                     {
3513cdf0e10cSrcweir                         nCount++;
3514cdf0e10cSrcweir                         if ( eFunc == ifPRODUCT )
3515cdf0e10cSrcweir                             fRes = 0.0;
3516cdf0e10cSrcweir                     }
3517cdf0e10cSrcweir                 }
3518cdf0e10cSrcweir             }
3519cdf0e10cSrcweir             break;
3520cdf0e10cSrcweir             case svDoubleRef :
3521cdf0e10cSrcweir             case svRefList :
3522cdf0e10cSrcweir             {
3523cdf0e10cSrcweir                 sal_uInt16 nErr = 0;
3524cdf0e10cSrcweir                 PopDoubleRef( aRange, nParamCount, nRefInList);
3525cdf0e10cSrcweir                 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3526cdf0e10cSrcweir                 {
3527cdf0e10cSrcweir                     nGlobalError = 0;
3528cdf0e10cSrcweir                     if ( eFunc == ifCOUNT2 )
3529cdf0e10cSrcweir                         ++nCount;
3530cdf0e10cSrcweir                     break;
3531cdf0e10cSrcweir                 }
3532cdf0e10cSrcweir                 if( eFunc == ifCOUNT2 )
3533cdf0e10cSrcweir                 {
3534cdf0e10cSrcweir                     ScBaseCell* pCell;
3535cdf0e10cSrcweir                     ScCellIterator aIter( pDok, aRange, glSubTotal );
3536cdf0e10cSrcweir                     if ( (pCell = aIter.GetFirst()) != NULL )
3537cdf0e10cSrcweir                     {
3538cdf0e10cSrcweir                         do
3539cdf0e10cSrcweir                         {
3540cdf0e10cSrcweir                             CellType eType = pCell->GetCellType();
3541cdf0e10cSrcweir                             if( eType != CELLTYPE_NONE && eType != CELLTYPE_NOTE )
3542cdf0e10cSrcweir                                 nCount++;
3543cdf0e10cSrcweir                         }
3544cdf0e10cSrcweir                         while ( (pCell = aIter.GetNext()) != NULL );
3545cdf0e10cSrcweir                     }
3546cdf0e10cSrcweir                     if ( nGlobalError )
3547cdf0e10cSrcweir                         nGlobalError = 0;
3548cdf0e10cSrcweir                 }
3549cdf0e10cSrcweir                 else
3550cdf0e10cSrcweir                 {
3551cdf0e10cSrcweir                     ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3552cdf0e10cSrcweir                     if (aValIter.GetFirst(fVal, nErr))
3553cdf0e10cSrcweir                     {
3554cdf0e10cSrcweir                         //  Schleife aus Performance-Gruenden nach innen verlegt:
3555cdf0e10cSrcweir                         aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3556cdf0e10cSrcweir                         switch( eFunc )
3557cdf0e10cSrcweir                         {
3558cdf0e10cSrcweir                             case ifAVERAGE:
3559cdf0e10cSrcweir                             case ifSUM:
3560cdf0e10cSrcweir                                     do
3561cdf0e10cSrcweir                                     {
3562cdf0e10cSrcweir                                         SetError(nErr);
3563cdf0e10cSrcweir                                         if ( bNull && fVal != 0.0 )
3564cdf0e10cSrcweir                                         {
3565cdf0e10cSrcweir                                             bNull = sal_False;
3566cdf0e10cSrcweir                                             fMem = fVal;
3567cdf0e10cSrcweir                                         }
3568cdf0e10cSrcweir                                         else
3569cdf0e10cSrcweir                                             fRes += fVal;
3570cdf0e10cSrcweir                                         nCount++;
3571cdf0e10cSrcweir                                     }
3572cdf0e10cSrcweir                                     while (aValIter.GetNext(fVal, nErr));
3573cdf0e10cSrcweir                                     break;
3574cdf0e10cSrcweir                             case ifSUMSQ:
3575cdf0e10cSrcweir                                     do
3576cdf0e10cSrcweir                                     {
3577cdf0e10cSrcweir                                         SetError(nErr);
3578cdf0e10cSrcweir                                         fRes += fVal * fVal;
3579cdf0e10cSrcweir                                         nCount++;
3580cdf0e10cSrcweir                                     }
3581cdf0e10cSrcweir                                     while (aValIter.GetNext(fVal, nErr));
3582cdf0e10cSrcweir                                     break;
3583cdf0e10cSrcweir                             case ifPRODUCT:
3584cdf0e10cSrcweir                                     do
3585cdf0e10cSrcweir                                     {
3586cdf0e10cSrcweir                                         SetError(nErr);
3587cdf0e10cSrcweir                                         fRes *= fVal;
3588cdf0e10cSrcweir                                         nCount++;
3589cdf0e10cSrcweir                                     }
3590cdf0e10cSrcweir                                     while (aValIter.GetNext(fVal, nErr));
3591cdf0e10cSrcweir                                     break;
3592cdf0e10cSrcweir                             case ifCOUNT:
3593cdf0e10cSrcweir                                     do
3594cdf0e10cSrcweir                                     {
3595cdf0e10cSrcweir                                         if ( !nErr )
3596cdf0e10cSrcweir                                             nCount++;
3597cdf0e10cSrcweir                                     }
3598cdf0e10cSrcweir                                     while (aValIter.GetNext(fVal, nErr));
3599cdf0e10cSrcweir                                     break;
3600cdf0e10cSrcweir                             default: ;  // nothing
3601cdf0e10cSrcweir                         }
3602cdf0e10cSrcweir                         SetError( nErr );
3603cdf0e10cSrcweir                     }
3604cdf0e10cSrcweir                 }
3605cdf0e10cSrcweir             }
3606cdf0e10cSrcweir             break;
3607cdf0e10cSrcweir             case svMatrix :
3608cdf0e10cSrcweir             {
3609cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3610cdf0e10cSrcweir                 if (pMat)
3611cdf0e10cSrcweir                 {
3612cdf0e10cSrcweir                     SCSIZE nC, nR;
3613cdf0e10cSrcweir                     nFuncFmtType = NUMBERFORMAT_NUMBER;
3614cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3615cdf0e10cSrcweir                     if( eFunc == ifCOUNT2 )
3616cdf0e10cSrcweir                         nCount += (sal_uLong) nC * nR;
3617cdf0e10cSrcweir                     else
3618cdf0e10cSrcweir                     {
3619cdf0e10cSrcweir                         for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3620cdf0e10cSrcweir                         {
3621cdf0e10cSrcweir                             for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3622cdf0e10cSrcweir                             {
3623cdf0e10cSrcweir                                 if (!pMat->IsString(nMatCol,nMatRow))
3624cdf0e10cSrcweir                                 {
3625cdf0e10cSrcweir                                     nCount++;
3626cdf0e10cSrcweir                                     fVal = pMat->GetDouble(nMatCol,nMatRow);
3627cdf0e10cSrcweir                                     switch( eFunc )
3628cdf0e10cSrcweir                                     {
3629cdf0e10cSrcweir                                         case ifAVERAGE:
3630cdf0e10cSrcweir                                         case ifSUM:
3631cdf0e10cSrcweir                                             if ( bNull && fVal != 0.0 )
3632cdf0e10cSrcweir                                             {
3633cdf0e10cSrcweir                                                 bNull = sal_False;
3634cdf0e10cSrcweir                                                 fMem = fVal;
3635cdf0e10cSrcweir                                             }
3636cdf0e10cSrcweir                                             else
3637cdf0e10cSrcweir                                                 fRes += fVal;
3638cdf0e10cSrcweir                                             break;
3639cdf0e10cSrcweir                                         case ifSUMSQ:   fRes += fVal * fVal; break;
3640cdf0e10cSrcweir                                         case ifPRODUCT: fRes *= fVal; break;
3641cdf0e10cSrcweir                                         default: ; // nothing
3642cdf0e10cSrcweir                                     }
3643cdf0e10cSrcweir                                 }
3644cdf0e10cSrcweir                                 else if ( bTextAsZero )
3645cdf0e10cSrcweir                                 {
3646cdf0e10cSrcweir                                     nCount++;
3647cdf0e10cSrcweir                                     if ( eFunc == ifPRODUCT )
3648cdf0e10cSrcweir                                         fRes = 0.0;
3649cdf0e10cSrcweir                                 }
3650cdf0e10cSrcweir                             }
3651cdf0e10cSrcweir                         }
3652cdf0e10cSrcweir                     }
3653cdf0e10cSrcweir                 }
3654cdf0e10cSrcweir             }
3655cdf0e10cSrcweir             break;
3656cdf0e10cSrcweir             case svError:
3657cdf0e10cSrcweir             {
3658cdf0e10cSrcweir                 Pop();
3659cdf0e10cSrcweir                 if ( eFunc == ifCOUNT )
3660cdf0e10cSrcweir                 {
3661cdf0e10cSrcweir                     nGlobalError = 0;
3662cdf0e10cSrcweir                 }
3663cdf0e10cSrcweir                 else if ( eFunc == ifCOUNT2 )
3664cdf0e10cSrcweir                 {
3665cdf0e10cSrcweir                     nCount++;
3666cdf0e10cSrcweir                     nGlobalError = 0;
3667cdf0e10cSrcweir                 }
3668cdf0e10cSrcweir             }
3669cdf0e10cSrcweir             break;
3670cdf0e10cSrcweir             default :
3671cdf0e10cSrcweir                 while (nParamCount-- > 0)
3672cdf0e10cSrcweir                     PopError();
3673cdf0e10cSrcweir                 SetError(errIllegalParameter);
3674cdf0e10cSrcweir         }
3675cdf0e10cSrcweir     }
3676cdf0e10cSrcweir     switch( eFunc )
3677cdf0e10cSrcweir     {
3678cdf0e10cSrcweir         case ifSUM:     fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
3679cdf0e10cSrcweir         case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
3680cdf0e10cSrcweir         case ifCOUNT2:
3681cdf0e10cSrcweir         case ifCOUNT:   fRes  = nCount; break;
3682cdf0e10cSrcweir         case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
3683cdf0e10cSrcweir         default: ; // nothing
3684cdf0e10cSrcweir     }
3685cdf0e10cSrcweir     // Bei Summen etc. macht ein sal_Bool-Ergebnis keinen Sinn
3686cdf0e10cSrcweir     // und Anzahl ist immer Number (#38345#)
3687cdf0e10cSrcweir     if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
3688cdf0e10cSrcweir         nFuncFmtType = NUMBERFORMAT_NUMBER;
3689cdf0e10cSrcweir     return fRes;
3690cdf0e10cSrcweir }
3691cdf0e10cSrcweir 
3692cdf0e10cSrcweir 
ScSumSQ()3693cdf0e10cSrcweir void ScInterpreter::ScSumSQ()
3694cdf0e10cSrcweir {
3695cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
3696cdf0e10cSrcweir     PushDouble( IterateParameters( ifSUMSQ ) );
3697cdf0e10cSrcweir }
3698cdf0e10cSrcweir 
3699cdf0e10cSrcweir 
ScSum()3700cdf0e10cSrcweir void ScInterpreter::ScSum()
3701cdf0e10cSrcweir {
3702cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSum" );
3703cdf0e10cSrcweir     PushDouble( IterateParameters( ifSUM ) );
3704cdf0e10cSrcweir }
3705cdf0e10cSrcweir 
3706cdf0e10cSrcweir 
ScProduct()3707cdf0e10cSrcweir void ScInterpreter::ScProduct()
3708cdf0e10cSrcweir {
3709cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
3710cdf0e10cSrcweir     PushDouble( IterateParameters( ifPRODUCT ) );
3711cdf0e10cSrcweir }
3712cdf0e10cSrcweir 
3713cdf0e10cSrcweir 
ScAverage(sal_Bool bTextAsZero)3714cdf0e10cSrcweir void ScInterpreter::ScAverage( sal_Bool bTextAsZero )
3715cdf0e10cSrcweir {
3716cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
3717cdf0e10cSrcweir     PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
3718cdf0e10cSrcweir }
3719cdf0e10cSrcweir 
3720cdf0e10cSrcweir 
ScCount()3721cdf0e10cSrcweir void ScInterpreter::ScCount()
3722cdf0e10cSrcweir {
3723cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount" );
3724cdf0e10cSrcweir     PushDouble( IterateParameters( ifCOUNT ) );
3725cdf0e10cSrcweir }
3726cdf0e10cSrcweir 
3727cdf0e10cSrcweir 
ScCount2()3728cdf0e10cSrcweir void ScInterpreter::ScCount2()
3729cdf0e10cSrcweir {
3730cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
3731cdf0e10cSrcweir     PushDouble( IterateParameters( ifCOUNT2 ) );
3732cdf0e10cSrcweir }
3733cdf0e10cSrcweir 
3734cdf0e10cSrcweir 
GetStVarParams(double & rVal,double & rValCount,sal_Bool bTextAsZero)3735cdf0e10cSrcweir void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
3736cdf0e10cSrcweir                 sal_Bool bTextAsZero )
3737cdf0e10cSrcweir {
3738cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStVarParams" );
3739cdf0e10cSrcweir     short nParamCount = GetByte();
3740cdf0e10cSrcweir 
3741cdf0e10cSrcweir     std::vector<double> values;
3742cdf0e10cSrcweir     double fSum    = 0.0;
3743cdf0e10cSrcweir     double vSum    = 0.0;
3744cdf0e10cSrcweir     double vMean    = 0.0;
3745cdf0e10cSrcweir     double fVal = 0.0;
3746cdf0e10cSrcweir     rValCount = 0.0;
3747cdf0e10cSrcweir     ScAddress aAdr;
3748cdf0e10cSrcweir     ScRange aRange;
3749cdf0e10cSrcweir     size_t nRefInList = 0;
3750cdf0e10cSrcweir     while (nParamCount-- > 0)
3751cdf0e10cSrcweir     {
3752cdf0e10cSrcweir         switch (GetStackType())
3753cdf0e10cSrcweir         {
3754cdf0e10cSrcweir             case svDouble :
3755cdf0e10cSrcweir             {
3756cdf0e10cSrcweir                 fVal = GetDouble();
3757cdf0e10cSrcweir                 values.push_back(fVal);
3758cdf0e10cSrcweir                 fSum    += fVal;
3759cdf0e10cSrcweir                 rValCount++;
3760cdf0e10cSrcweir             }
3761cdf0e10cSrcweir             break;
3762cdf0e10cSrcweir             case svSingleRef :
3763cdf0e10cSrcweir             {
3764cdf0e10cSrcweir                 PopSingleRef( aAdr );
3765cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
3766cdf0e10cSrcweir                 if (HasCellValueData(pCell))
3767cdf0e10cSrcweir                 {
3768cdf0e10cSrcweir                     fVal = GetCellValue( aAdr, pCell );
3769cdf0e10cSrcweir                     values.push_back(fVal);
3770cdf0e10cSrcweir                     fSum += fVal;
3771cdf0e10cSrcweir                     rValCount++;
3772cdf0e10cSrcweir                 }
3773cdf0e10cSrcweir                 else if ( bTextAsZero && HasCellStringData( pCell ) )
3774cdf0e10cSrcweir                 {
3775cdf0e10cSrcweir                     values.push_back(0.0);
3776cdf0e10cSrcweir                     rValCount++;
3777cdf0e10cSrcweir                 }
3778cdf0e10cSrcweir             }
3779cdf0e10cSrcweir             break;
3780cdf0e10cSrcweir             case svDoubleRef :
3781cdf0e10cSrcweir             case svRefList :
3782cdf0e10cSrcweir             {
3783cdf0e10cSrcweir                 sal_uInt16 nErr = 0;
3784cdf0e10cSrcweir                 PopDoubleRef( aRange, nParamCount, nRefInList);
3785cdf0e10cSrcweir                 ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3786cdf0e10cSrcweir                 if (aValIter.GetFirst(fVal, nErr))
3787cdf0e10cSrcweir                 {
3788cdf0e10cSrcweir                     do
3789cdf0e10cSrcweir                     {
3790cdf0e10cSrcweir                         values.push_back(fVal);
3791cdf0e10cSrcweir                         fSum += fVal;
3792cdf0e10cSrcweir                         rValCount++;
3793cdf0e10cSrcweir                     }
3794cdf0e10cSrcweir                     while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
3795cdf0e10cSrcweir                 }
3796cdf0e10cSrcweir             }
3797cdf0e10cSrcweir             break;
3798cdf0e10cSrcweir             case svMatrix :
3799cdf0e10cSrcweir             {
3800cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3801cdf0e10cSrcweir                 if (pMat)
3802cdf0e10cSrcweir                 {
3803cdf0e10cSrcweir                     SCSIZE nC, nR;
3804cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3805cdf0e10cSrcweir                     for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3806cdf0e10cSrcweir                     {
3807cdf0e10cSrcweir                         for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3808cdf0e10cSrcweir                         {
3809cdf0e10cSrcweir                             if (!pMat->IsString(nMatCol,nMatRow))
3810cdf0e10cSrcweir                             {
3811cdf0e10cSrcweir                                 fVal= pMat->GetDouble(nMatCol,nMatRow);
3812cdf0e10cSrcweir                                 values.push_back(fVal);
3813cdf0e10cSrcweir                                 fSum += fVal;
3814cdf0e10cSrcweir                                 rValCount++;
3815cdf0e10cSrcweir                             }
3816cdf0e10cSrcweir                             else if ( bTextAsZero )
3817cdf0e10cSrcweir                             {
3818cdf0e10cSrcweir                                 values.push_back(0.0);
3819cdf0e10cSrcweir                                 rValCount++;
3820cdf0e10cSrcweir                             }
3821cdf0e10cSrcweir                         }
3822cdf0e10cSrcweir                     }
3823cdf0e10cSrcweir                 }
3824cdf0e10cSrcweir             }
3825cdf0e10cSrcweir             break;
3826cdf0e10cSrcweir             case svString :
3827cdf0e10cSrcweir             {
3828cdf0e10cSrcweir                 Pop();
3829cdf0e10cSrcweir                 if ( bTextAsZero )
3830cdf0e10cSrcweir                 {
3831cdf0e10cSrcweir                     values.push_back(0.0);
3832cdf0e10cSrcweir                     rValCount++;
3833cdf0e10cSrcweir                 }
3834cdf0e10cSrcweir                 else
3835cdf0e10cSrcweir                     SetError(errIllegalParameter);
3836cdf0e10cSrcweir             }
3837cdf0e10cSrcweir             break;
3838cdf0e10cSrcweir             default :
3839cdf0e10cSrcweir                 Pop();
3840cdf0e10cSrcweir                 SetError(errIllegalParameter);
3841cdf0e10cSrcweir         }
3842cdf0e10cSrcweir     }
3843cdf0e10cSrcweir 
3844cdf0e10cSrcweir     ::std::vector<double>::size_type n = values.size();
3845cdf0e10cSrcweir     vMean = fSum / n;
3846cdf0e10cSrcweir     for (::std::vector<double>::size_type i = 0; i < n; i++)
3847cdf0e10cSrcweir         vSum += ::rtl::math::approxSub( values[i], vMean) * ::rtl::math::approxSub( values[i], vMean);
3848cdf0e10cSrcweir     rVal = vSum;
3849cdf0e10cSrcweir }
3850cdf0e10cSrcweir 
3851cdf0e10cSrcweir 
ScVar(sal_Bool bTextAsZero)3852cdf0e10cSrcweir void ScInterpreter::ScVar( sal_Bool bTextAsZero )
3853cdf0e10cSrcweir {
3854cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVar" );
3855cdf0e10cSrcweir     double nVal;
3856cdf0e10cSrcweir     double nValCount;
3857cdf0e10cSrcweir     GetStVarParams( nVal, nValCount, bTextAsZero );
3858cdf0e10cSrcweir 
3859cdf0e10cSrcweir     if (nValCount <= 1.0)
3860cdf0e10cSrcweir         PushError( errDivisionByZero );
3861cdf0e10cSrcweir     else
3862cdf0e10cSrcweir         PushDouble( nVal / (nValCount - 1.0));
3863cdf0e10cSrcweir }
3864cdf0e10cSrcweir 
3865cdf0e10cSrcweir 
ScVarP(sal_Bool bTextAsZero)3866cdf0e10cSrcweir void ScInterpreter::ScVarP( sal_Bool bTextAsZero )
3867cdf0e10cSrcweir {
3868cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVarP" );
3869cdf0e10cSrcweir     double nVal;
3870cdf0e10cSrcweir     double nValCount;
3871cdf0e10cSrcweir     GetStVarParams( nVal, nValCount, bTextAsZero );
3872cdf0e10cSrcweir 
3873cdf0e10cSrcweir     PushDouble( div( nVal, nValCount));
3874cdf0e10cSrcweir }
3875cdf0e10cSrcweir 
3876cdf0e10cSrcweir 
ScStDev(sal_Bool bTextAsZero)3877cdf0e10cSrcweir void ScInterpreter::ScStDev( sal_Bool bTextAsZero )
3878cdf0e10cSrcweir {
3879cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDev" );
3880cdf0e10cSrcweir     double nVal;
3881cdf0e10cSrcweir     double nValCount;
3882cdf0e10cSrcweir     GetStVarParams( nVal, nValCount, bTextAsZero );
3883cdf0e10cSrcweir     if (nValCount <= 1.0)
3884cdf0e10cSrcweir         PushError( errDivisionByZero );
3885cdf0e10cSrcweir     else
3886cdf0e10cSrcweir         PushDouble( sqrt( nVal / (nValCount - 1.0)));
3887cdf0e10cSrcweir }
3888cdf0e10cSrcweir 
3889cdf0e10cSrcweir 
ScStDevP(sal_Bool bTextAsZero)3890cdf0e10cSrcweir void ScInterpreter::ScStDevP( sal_Bool bTextAsZero )
3891cdf0e10cSrcweir {
3892cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDevP" );
3893cdf0e10cSrcweir     double nVal;
3894cdf0e10cSrcweir     double nValCount;
3895cdf0e10cSrcweir     GetStVarParams( nVal, nValCount, bTextAsZero );
3896cdf0e10cSrcweir     if (nValCount == 0.0)
3897cdf0e10cSrcweir         PushError( errDivisionByZero );
3898cdf0e10cSrcweir     else
3899cdf0e10cSrcweir         PushDouble( sqrt( nVal / nValCount));
3900cdf0e10cSrcweir 
3901cdf0e10cSrcweir     /* this was: PushDouble( sqrt( div( nVal, nValCount)));
3902cdf0e10cSrcweir      *
3903cdf0e10cSrcweir      * Besides that the special NAN gets lost in the call through sqrt(),
3904cdf0e10cSrcweir      * unxlngi6.pro then looped back and forth somewhere between div() and
3905cdf0e10cSrcweir      * ::rtl::math::setNan(). Tests showed that
3906cdf0e10cSrcweir      *
3907cdf0e10cSrcweir      *      sqrt( div( 1, 0));
3908cdf0e10cSrcweir      *
3909cdf0e10cSrcweir      * produced a loop, but
3910cdf0e10cSrcweir      *
3911cdf0e10cSrcweir      *      double f1 = div( 1, 0);
3912cdf0e10cSrcweir      *      sqrt( f1 );
3913cdf0e10cSrcweir      *
3914cdf0e10cSrcweir      * was fine. There seems to be some compiler optimization problem. It does
3915cdf0e10cSrcweir      * not occur when compiled with debug=t.
3916cdf0e10cSrcweir      */
3917cdf0e10cSrcweir }
3918cdf0e10cSrcweir 
3919cdf0e10cSrcweir 
ScColumns()3920cdf0e10cSrcweir void ScInterpreter::ScColumns()
3921cdf0e10cSrcweir {
3922cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumns" );
3923cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
3924cdf0e10cSrcweir     sal_uLong nVal = 0;
3925cdf0e10cSrcweir     SCCOL nCol1;
3926cdf0e10cSrcweir     SCROW nRow1;
3927cdf0e10cSrcweir     SCTAB nTab1;
3928cdf0e10cSrcweir     SCCOL nCol2;
3929cdf0e10cSrcweir     SCROW nRow2;
3930cdf0e10cSrcweir     SCTAB nTab2;
3931cdf0e10cSrcweir     while (nParamCount-- > 0)
3932cdf0e10cSrcweir     {
3933cdf0e10cSrcweir         switch ( GetStackType() )
3934cdf0e10cSrcweir         {
3935cdf0e10cSrcweir             case svSingleRef:
3936cdf0e10cSrcweir                 PopError();
3937cdf0e10cSrcweir                 nVal++;
3938cdf0e10cSrcweir                 break;
3939cdf0e10cSrcweir             case svDoubleRef:
3940cdf0e10cSrcweir                 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3941cdf0e10cSrcweir                 nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
3942cdf0e10cSrcweir                     static_cast<sal_uLong>(nCol2 - nCol1 + 1);
3943cdf0e10cSrcweir                 break;
3944cdf0e10cSrcweir             case svMatrix:
3945cdf0e10cSrcweir             {
3946cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3947cdf0e10cSrcweir                 if (pMat)
3948cdf0e10cSrcweir                 {
3949cdf0e10cSrcweir                     SCSIZE nC, nR;
3950cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3951cdf0e10cSrcweir                     nVal += nC;
3952cdf0e10cSrcweir                 }
3953cdf0e10cSrcweir             }
3954cdf0e10cSrcweir             break;
3955cdf0e10cSrcweir             default:
3956cdf0e10cSrcweir                 PopError();
3957cdf0e10cSrcweir                 SetError(errIllegalParameter);
3958cdf0e10cSrcweir         }
3959cdf0e10cSrcweir     }
3960cdf0e10cSrcweir     PushDouble((double)nVal);
3961cdf0e10cSrcweir }
3962cdf0e10cSrcweir 
3963cdf0e10cSrcweir 
ScRows()3964cdf0e10cSrcweir void ScInterpreter::ScRows()
3965cdf0e10cSrcweir {
3966cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRows" );
3967cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
3968cdf0e10cSrcweir     sal_uLong nVal = 0;
3969cdf0e10cSrcweir     SCCOL nCol1;
3970cdf0e10cSrcweir     SCROW nRow1;
3971cdf0e10cSrcweir     SCTAB nTab1;
3972cdf0e10cSrcweir     SCCOL nCol2;
3973cdf0e10cSrcweir     SCROW nRow2;
3974cdf0e10cSrcweir     SCTAB nTab2;
3975cdf0e10cSrcweir     while (nParamCount-- > 0)
3976cdf0e10cSrcweir     {
3977cdf0e10cSrcweir         switch ( GetStackType() )
3978cdf0e10cSrcweir         {
3979cdf0e10cSrcweir             case svSingleRef:
3980cdf0e10cSrcweir                 PopError();
3981cdf0e10cSrcweir                 nVal++;
3982cdf0e10cSrcweir                 break;
3983cdf0e10cSrcweir             case svDoubleRef:
3984cdf0e10cSrcweir                 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3985cdf0e10cSrcweir                 nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
3986cdf0e10cSrcweir                     static_cast<sal_uLong>(nRow2 - nRow1 + 1);
3987cdf0e10cSrcweir                 break;
3988cdf0e10cSrcweir             case svMatrix:
3989cdf0e10cSrcweir             {
3990cdf0e10cSrcweir                 ScMatrixRef pMat = PopMatrix();
3991cdf0e10cSrcweir                 if (pMat)
3992cdf0e10cSrcweir                 {
3993cdf0e10cSrcweir                     SCSIZE nC, nR;
3994cdf0e10cSrcweir                     pMat->GetDimensions(nC, nR);
3995cdf0e10cSrcweir                     nVal += nR;
3996cdf0e10cSrcweir                 }
3997cdf0e10cSrcweir             }
3998cdf0e10cSrcweir             break;
3999cdf0e10cSrcweir             default:
4000cdf0e10cSrcweir                 PopError();
4001cdf0e10cSrcweir                 SetError(errIllegalParameter);
4002cdf0e10cSrcweir         }
4003cdf0e10cSrcweir     }
4004cdf0e10cSrcweir     PushDouble((double)nVal);
4005cdf0e10cSrcweir }
4006cdf0e10cSrcweir 
ScTables()4007cdf0e10cSrcweir void ScInterpreter::ScTables()
4008cdf0e10cSrcweir {
4009cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTables" );
4010cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
4011cdf0e10cSrcweir     sal_uLong nVal;
4012cdf0e10cSrcweir     if ( nParamCount == 0 )
4013cdf0e10cSrcweir         nVal = pDok->GetTableCount();
4014cdf0e10cSrcweir     else
4015cdf0e10cSrcweir     {
4016cdf0e10cSrcweir         nVal = 0;
4017cdf0e10cSrcweir         SCCOL nCol1;
4018cdf0e10cSrcweir         SCROW nRow1;
4019cdf0e10cSrcweir         SCTAB nTab1;
4020cdf0e10cSrcweir         SCCOL nCol2;
4021cdf0e10cSrcweir         SCROW nRow2;
4022cdf0e10cSrcweir         SCTAB nTab2;
4023cdf0e10cSrcweir         while (nParamCount-- > 0)
4024cdf0e10cSrcweir         {
4025cdf0e10cSrcweir             switch ( GetStackType() )
4026cdf0e10cSrcweir             {
4027cdf0e10cSrcweir                 case svSingleRef:
4028cdf0e10cSrcweir                     PopError();
4029cdf0e10cSrcweir                     nVal++;
4030cdf0e10cSrcweir                 break;
4031cdf0e10cSrcweir                 case svDoubleRef:
4032cdf0e10cSrcweir                     PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4033cdf0e10cSrcweir                     nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4034cdf0e10cSrcweir                 break;
4035cdf0e10cSrcweir                 case svMatrix:
4036cdf0e10cSrcweir                     PopError();
4037cdf0e10cSrcweir                     nVal++;
4038cdf0e10cSrcweir                 break;
4039cdf0e10cSrcweir                 default:
4040cdf0e10cSrcweir                     PopError();
4041cdf0e10cSrcweir                     SetError( errIllegalParameter );
4042cdf0e10cSrcweir             }
4043cdf0e10cSrcweir         }
4044cdf0e10cSrcweir     }
4045cdf0e10cSrcweir     PushDouble( (double) nVal );
4046cdf0e10cSrcweir }
4047cdf0e10cSrcweir 
4048cdf0e10cSrcweir 
ScColumn()4049cdf0e10cSrcweir void ScInterpreter::ScColumn()
4050cdf0e10cSrcweir {
4051cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumn" );
4052cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
4053cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4054cdf0e10cSrcweir     {
4055cdf0e10cSrcweir         double nVal = 0;
4056cdf0e10cSrcweir         if (nParamCount == 0)
4057cdf0e10cSrcweir         {
4058cdf0e10cSrcweir             nVal = aPos.Col() + 1;
4059cdf0e10cSrcweir             if (bMatrixFormula)
4060cdf0e10cSrcweir             {
4061cdf0e10cSrcweir                 SCCOL nCols;
4062cdf0e10cSrcweir                 SCROW nRows;
4063cdf0e10cSrcweir                 pMyFormulaCell->GetMatColsRows( nCols, nRows);
4064cdf0e10cSrcweir                 ScMatrixRef pResMat = GetNewMat( static_cast<SCSIZE>(nCols), 1);
4065cdf0e10cSrcweir                 if (pResMat)
4066cdf0e10cSrcweir                 {
4067cdf0e10cSrcweir                     for (SCCOL i=0; i < nCols; ++i)
4068cdf0e10cSrcweir                         pResMat->PutDouble( nVal + i, static_cast<SCSIZE>(i), 0);
4069cdf0e10cSrcweir                     PushMatrix( pResMat);
4070cdf0e10cSrcweir                     return;
4071cdf0e10cSrcweir                 }
4072cdf0e10cSrcweir             }
4073cdf0e10cSrcweir         }
4074cdf0e10cSrcweir         else
4075cdf0e10cSrcweir         {
4076cdf0e10cSrcweir             switch ( GetStackType() )
4077cdf0e10cSrcweir             {
4078cdf0e10cSrcweir                 case svSingleRef :
4079cdf0e10cSrcweir                 {
4080cdf0e10cSrcweir                     SCCOL nCol1;
4081cdf0e10cSrcweir                     SCROW nRow1;
4082cdf0e10cSrcweir                     SCTAB nTab1;
4083cdf0e10cSrcweir                     PopSingleRef( nCol1, nRow1, nTab1 );
4084cdf0e10cSrcweir                     nVal = (double) (nCol1 + 1);
4085cdf0e10cSrcweir                 }
4086cdf0e10cSrcweir                 break;
4087cdf0e10cSrcweir                 case svDoubleRef :
4088cdf0e10cSrcweir                 {
4089cdf0e10cSrcweir                     SCCOL nCol1;
4090cdf0e10cSrcweir                     SCROW nRow1;
4091cdf0e10cSrcweir                     SCTAB nTab1;
4092cdf0e10cSrcweir                     SCCOL nCol2;
4093cdf0e10cSrcweir                     SCROW nRow2;
4094cdf0e10cSrcweir                     SCTAB nTab2;
4095cdf0e10cSrcweir                     PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4096cdf0e10cSrcweir                     if (nCol2 > nCol1)
4097cdf0e10cSrcweir                     {
4098cdf0e10cSrcweir                         ScMatrixRef pResMat = GetNewMat(
4099cdf0e10cSrcweir                                 static_cast<SCSIZE>(nCol2-nCol1+1), 1);
4100cdf0e10cSrcweir                         if (pResMat)
4101cdf0e10cSrcweir                         {
4102cdf0e10cSrcweir                             for (SCCOL i = nCol1; i <= nCol2; i++)
4103cdf0e10cSrcweir                                 pResMat->PutDouble((double)(i+1),
4104cdf0e10cSrcweir                                         static_cast<SCSIZE>(i-nCol1), 0);
4105cdf0e10cSrcweir                             PushMatrix(pResMat);
4106cdf0e10cSrcweir                             return;
4107cdf0e10cSrcweir                         }
4108cdf0e10cSrcweir                         else
4109cdf0e10cSrcweir                             nVal = 0.0;
4110cdf0e10cSrcweir                     }
4111cdf0e10cSrcweir                     else
4112cdf0e10cSrcweir                         nVal = (double) (nCol1 + 1);
4113cdf0e10cSrcweir                 }
4114cdf0e10cSrcweir                 break;
4115cdf0e10cSrcweir                 default:
4116cdf0e10cSrcweir                     SetError( errIllegalParameter );
4117cdf0e10cSrcweir                     nVal = 0.0;
4118cdf0e10cSrcweir             }
4119cdf0e10cSrcweir         }
4120cdf0e10cSrcweir         PushDouble( nVal );
4121cdf0e10cSrcweir     }
4122cdf0e10cSrcweir }
4123cdf0e10cSrcweir 
4124cdf0e10cSrcweir 
ScRow()4125cdf0e10cSrcweir void ScInterpreter::ScRow()
4126cdf0e10cSrcweir {
4127cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRow" );
4128cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
4129cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4130cdf0e10cSrcweir     {
4131cdf0e10cSrcweir         double nVal = 0;
4132cdf0e10cSrcweir         if (nParamCount == 0)
4133cdf0e10cSrcweir         {
4134cdf0e10cSrcweir             nVal = aPos.Row() + 1;
4135cdf0e10cSrcweir             if (bMatrixFormula)
4136cdf0e10cSrcweir             {
4137cdf0e10cSrcweir                 SCCOL nCols;
4138cdf0e10cSrcweir                 SCROW nRows;
4139cdf0e10cSrcweir                 pMyFormulaCell->GetMatColsRows( nCols, nRows);
4140cdf0e10cSrcweir                 ScMatrixRef pResMat = GetNewMat( 1, static_cast<SCSIZE>(nRows));
4141cdf0e10cSrcweir                 if (pResMat)
4142cdf0e10cSrcweir                 {
4143cdf0e10cSrcweir                     for (SCROW i=0; i < nRows; i++)
4144cdf0e10cSrcweir                         pResMat->PutDouble( nVal + i, 0, static_cast<SCSIZE>(i));
4145cdf0e10cSrcweir                     PushMatrix( pResMat);
4146cdf0e10cSrcweir                     return;
4147cdf0e10cSrcweir                 }
4148cdf0e10cSrcweir             }
4149cdf0e10cSrcweir         }
4150cdf0e10cSrcweir         else
4151cdf0e10cSrcweir         {
4152cdf0e10cSrcweir             switch ( GetStackType() )
4153cdf0e10cSrcweir             {
4154cdf0e10cSrcweir                 case svSingleRef :
4155cdf0e10cSrcweir                 {
4156cdf0e10cSrcweir                     SCCOL nCol1;
4157cdf0e10cSrcweir                     SCROW nRow1;
4158cdf0e10cSrcweir                     SCTAB nTab1;
4159cdf0e10cSrcweir                     PopSingleRef( nCol1, nRow1, nTab1 );
4160cdf0e10cSrcweir                     nVal = (double) (nRow1 + 1);
4161cdf0e10cSrcweir                 }
4162cdf0e10cSrcweir                 break;
4163cdf0e10cSrcweir                 case svDoubleRef :
4164cdf0e10cSrcweir                 {
4165cdf0e10cSrcweir                     SCCOL nCol1;
4166cdf0e10cSrcweir                     SCROW nRow1;
4167cdf0e10cSrcweir                     SCTAB nTab1;
4168cdf0e10cSrcweir                     SCCOL nCol2;
4169cdf0e10cSrcweir                     SCROW nRow2;
4170cdf0e10cSrcweir                     SCTAB nTab2;
4171cdf0e10cSrcweir                     PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4172cdf0e10cSrcweir                     if (nRow2 > nRow1)
4173cdf0e10cSrcweir                     {
4174cdf0e10cSrcweir                         ScMatrixRef pResMat = GetNewMat( 1,
4175cdf0e10cSrcweir                                 static_cast<SCSIZE>(nRow2-nRow1+1));
4176cdf0e10cSrcweir                         if (pResMat)
4177cdf0e10cSrcweir                         {
4178cdf0e10cSrcweir                             for (SCROW i = nRow1; i <= nRow2; i++)
4179cdf0e10cSrcweir                                 pResMat->PutDouble((double)(i+1), 0,
4180cdf0e10cSrcweir                                         static_cast<SCSIZE>(i-nRow1));
4181cdf0e10cSrcweir                             PushMatrix(pResMat);
4182cdf0e10cSrcweir                             return;
4183cdf0e10cSrcweir                         }
4184cdf0e10cSrcweir                         else
4185cdf0e10cSrcweir                             nVal = 0.0;
4186cdf0e10cSrcweir                     }
4187cdf0e10cSrcweir                     else
4188cdf0e10cSrcweir                         nVal = (double) (nRow1 + 1);
4189cdf0e10cSrcweir                 }
4190cdf0e10cSrcweir                 break;
4191cdf0e10cSrcweir                 default:
4192cdf0e10cSrcweir                     SetError( errIllegalParameter );
4193cdf0e10cSrcweir                     nVal = 0.0;
4194cdf0e10cSrcweir             }
4195cdf0e10cSrcweir         }
4196cdf0e10cSrcweir         PushDouble( nVal );
4197cdf0e10cSrcweir     }
4198cdf0e10cSrcweir }
4199cdf0e10cSrcweir 
ScTable()4200cdf0e10cSrcweir void ScInterpreter::ScTable()
4201cdf0e10cSrcweir {
4202cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTable" );
4203cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
4204cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4205cdf0e10cSrcweir     {
4206cdf0e10cSrcweir         SCTAB nVal = 0;
4207cdf0e10cSrcweir         if ( nParamCount == 0 )
4208cdf0e10cSrcweir             nVal = aPos.Tab() + 1;
4209cdf0e10cSrcweir         else
4210cdf0e10cSrcweir         {
4211cdf0e10cSrcweir             switch ( GetStackType() )
4212cdf0e10cSrcweir             {
4213cdf0e10cSrcweir                 case svString :
4214cdf0e10cSrcweir                 {
4215cdf0e10cSrcweir                     String aStr( PopString() );
4216cdf0e10cSrcweir                     if ( pDok->GetTable( aStr, nVal ) )
4217cdf0e10cSrcweir                         ++nVal;
4218cdf0e10cSrcweir                     else
4219cdf0e10cSrcweir                         SetError( errIllegalArgument );
4220cdf0e10cSrcweir                 }
4221cdf0e10cSrcweir                 break;
4222cdf0e10cSrcweir                 case svSingleRef :
4223cdf0e10cSrcweir                 {
4224cdf0e10cSrcweir                     SCCOL nCol1;
4225cdf0e10cSrcweir                     SCROW nRow1;
4226cdf0e10cSrcweir                     SCTAB nTab1;
4227cdf0e10cSrcweir                     PopSingleRef( nCol1, nRow1, nTab1 );
4228cdf0e10cSrcweir                     nVal = nTab1 + 1;
4229cdf0e10cSrcweir                 }
4230cdf0e10cSrcweir                 break;
4231cdf0e10cSrcweir                 case svDoubleRef :
4232cdf0e10cSrcweir                 {
4233cdf0e10cSrcweir                     SCCOL nCol1;
4234cdf0e10cSrcweir                     SCROW nRow1;
4235cdf0e10cSrcweir                     SCTAB nTab1;
4236cdf0e10cSrcweir                     SCCOL nCol2;
4237cdf0e10cSrcweir                     SCROW nRow2;
4238cdf0e10cSrcweir                     SCTAB nTab2;
4239cdf0e10cSrcweir                     PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4240cdf0e10cSrcweir                     nVal = nTab1 + 1;
4241cdf0e10cSrcweir                 }
4242cdf0e10cSrcweir                 break;
4243cdf0e10cSrcweir                 default:
4244cdf0e10cSrcweir                     SetError( errIllegalParameter );
4245cdf0e10cSrcweir             }
4246cdf0e10cSrcweir             if ( nGlobalError )
4247cdf0e10cSrcweir                 nVal = 0;
4248cdf0e10cSrcweir         }
4249cdf0e10cSrcweir         PushDouble( (double) nVal );
4250cdf0e10cSrcweir     }
4251cdf0e10cSrcweir }
4252cdf0e10cSrcweir 
4253cdf0e10cSrcweir /** returns -1 when the matrix value is smaller than the query value, 0 when
4254cdf0e10cSrcweir     they are equal, and 1 when the matrix value is larger than the query
4255cdf0e10cSrcweir     value. */
lcl_CompareMatrix2Query(SCSIZE i,const ScMatrix & rMat,const ScQueryEntry & rEntry)4256cdf0e10cSrcweir static sal_Int32 lcl_CompareMatrix2Query( SCSIZE i, const ScMatrix& rMat,
4257cdf0e10cSrcweir         const ScQueryEntry& rEntry)
4258cdf0e10cSrcweir {
4259cdf0e10cSrcweir     if (rMat.IsEmpty(i))
4260cdf0e10cSrcweir     {
4261cdf0e10cSrcweir         /* TODO: in case we introduced query for real empty this would have to
4262cdf0e10cSrcweir          * be changed! */
4263cdf0e10cSrcweir         return -1;      // empty always less than anything else
4264cdf0e10cSrcweir     }
4265cdf0e10cSrcweir 
4266cdf0e10cSrcweir     /* FIXME: what is an empty path (result of IF(false;true_path) in
4267cdf0e10cSrcweir      * comparisons? */
4268cdf0e10cSrcweir 
4269cdf0e10cSrcweir     if (rMat.IsValue(i))
4270cdf0e10cSrcweir     {
4271cdf0e10cSrcweir         if (rEntry.bQueryByString)
4272cdf0e10cSrcweir             return -1;  // numeric always less than string
4273cdf0e10cSrcweir 
4274cdf0e10cSrcweir         const double nVal1 = rMat.GetDouble(i);
4275cdf0e10cSrcweir         const double nVal2 = rEntry.nVal;
4276cdf0e10cSrcweir         if (nVal1 == nVal2)
4277cdf0e10cSrcweir             return 0;
4278cdf0e10cSrcweir 
4279cdf0e10cSrcweir         return nVal1 < nVal2 ? -1 : 1;
4280cdf0e10cSrcweir     }
4281cdf0e10cSrcweir 
4282cdf0e10cSrcweir     if (!rEntry.bQueryByString)
4283cdf0e10cSrcweir         return 1;       // string always greater than numeric
4284cdf0e10cSrcweir 
4285cdf0e10cSrcweir     if (!rEntry.pStr)
4286cdf0e10cSrcweir         // this should not happen!
4287cdf0e10cSrcweir         return 1;
4288cdf0e10cSrcweir 
4289cdf0e10cSrcweir     const String& rStr1 = rMat.GetString(i);
4290cdf0e10cSrcweir     const String& rStr2 = *rEntry.pStr;
4291cdf0e10cSrcweir 
4292cdf0e10cSrcweir     return ScGlobal::GetCollator()->compareString( rStr1, rStr2); // case-insensitive
4293cdf0e10cSrcweir }
4294cdf0e10cSrcweir 
4295cdf0e10cSrcweir /** returns the last item with the identical value as the original item
4296cdf0e10cSrcweir     value. */
lcl_GetLastMatch(SCSIZE & rIndex,const ScMatrix & rMat,SCSIZE nMatCount,bool bReverse)4297cdf0e10cSrcweir static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat,
4298cdf0e10cSrcweir         SCSIZE nMatCount, bool bReverse)
4299cdf0e10cSrcweir {
4300cdf0e10cSrcweir     if (rMat.IsValue(rIndex))
4301cdf0e10cSrcweir     {
4302cdf0e10cSrcweir         double nVal = rMat.GetDouble(rIndex);
4303cdf0e10cSrcweir         if (bReverse)
4304cdf0e10cSrcweir             while (rIndex > 0 && rMat.IsValue(rIndex-1) &&
4305cdf0e10cSrcweir                     nVal == rMat.GetDouble(rIndex-1))
4306cdf0e10cSrcweir                 --rIndex;
4307cdf0e10cSrcweir         else
4308cdf0e10cSrcweir             while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4309cdf0e10cSrcweir                     nVal == rMat.GetDouble(rIndex+1))
4310cdf0e10cSrcweir                 ++rIndex;
4311cdf0e10cSrcweir     }
4312cdf0e10cSrcweir     //! Order of IsEmptyPath, IsEmpty, IsString is significant!
4313cdf0e10cSrcweir     else if (rMat.IsEmptyPath(rIndex))
4314cdf0e10cSrcweir     {
4315cdf0e10cSrcweir         if (bReverse)
4316cdf0e10cSrcweir             while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1))
4317cdf0e10cSrcweir                 --rIndex;
4318cdf0e10cSrcweir         else
4319cdf0e10cSrcweir             while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4320cdf0e10cSrcweir                 ++rIndex;
4321cdf0e10cSrcweir     }
4322cdf0e10cSrcweir     else if (rMat.IsEmpty(rIndex))
4323cdf0e10cSrcweir     {
4324cdf0e10cSrcweir         if (bReverse)
4325cdf0e10cSrcweir             while (rIndex > 0 && rMat.IsEmpty(rIndex-1))
4326cdf0e10cSrcweir                 --rIndex;
4327cdf0e10cSrcweir         else
4328cdf0e10cSrcweir             while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4329cdf0e10cSrcweir                 ++rIndex;
4330cdf0e10cSrcweir     }
4331cdf0e10cSrcweir     else if (rMat.IsString(rIndex))
4332cdf0e10cSrcweir     {
4333cdf0e10cSrcweir         String aStr( rMat.GetString(rIndex));
4334cdf0e10cSrcweir         if (bReverse)
4335cdf0e10cSrcweir             while (rIndex > 0 && rMat.IsString(rIndex-1) &&
4336cdf0e10cSrcweir                     aStr == rMat.GetString(rIndex-1))
4337cdf0e10cSrcweir                 --rIndex;
4338cdf0e10cSrcweir         else
4339cdf0e10cSrcweir             while (rIndex < nMatCount-1 && rMat.IsString(rIndex+1) &&
4340cdf0e10cSrcweir                     aStr == rMat.GetString(rIndex+1))
4341cdf0e10cSrcweir                 ++rIndex;
4342cdf0e10cSrcweir     }
4343cdf0e10cSrcweir     else
4344cdf0e10cSrcweir     {
4345cdf0e10cSrcweir         DBG_ERRORFILE("lcl_GetLastMatch: unhandled matrix type");
4346cdf0e10cSrcweir     }
4347cdf0e10cSrcweir }
4348cdf0e10cSrcweir 
ScMatch()4349cdf0e10cSrcweir void ScInterpreter::ScMatch()
4350cdf0e10cSrcweir {
4351cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatch" );
4352cdf0e10cSrcweir     ScMatrixRef pMatSrc = NULL;
4353cdf0e10cSrcweir 
4354cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
4355cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
4356cdf0e10cSrcweir     {
4357cdf0e10cSrcweir         double fTyp;
4358cdf0e10cSrcweir         if (nParamCount == 3)
4359cdf0e10cSrcweir             fTyp = GetDouble();
4360cdf0e10cSrcweir         else
4361cdf0e10cSrcweir             fTyp = 1.0;
4362cdf0e10cSrcweir         SCCOL nCol1 = 0;
4363cdf0e10cSrcweir         SCROW nRow1 = 0;
4364cdf0e10cSrcweir         SCTAB nTab1 = 0;
4365cdf0e10cSrcweir         SCCOL nCol2 = 0;
4366cdf0e10cSrcweir         SCROW nRow2 = 0;
4367cdf0e10cSrcweir         SCTAB nTab2 = 0;
4368cdf0e10cSrcweir         if (GetStackType() == svDoubleRef)
4369cdf0e10cSrcweir         {
4370cdf0e10cSrcweir             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4371cdf0e10cSrcweir             if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4372cdf0e10cSrcweir             {
4373cdf0e10cSrcweir                 PushIllegalParameter();
4374cdf0e10cSrcweir                 return;
4375cdf0e10cSrcweir             }
4376cdf0e10cSrcweir         }
4377cdf0e10cSrcweir         else if (GetStackType() == svMatrix)
4378cdf0e10cSrcweir         {
4379cdf0e10cSrcweir             pMatSrc = PopMatrix();
4380cdf0e10cSrcweir             if (!pMatSrc)
4381cdf0e10cSrcweir             {
4382cdf0e10cSrcweir                 PushIllegalParameter();
4383cdf0e10cSrcweir                 return;
4384cdf0e10cSrcweir             }
4385cdf0e10cSrcweir         }
4386cdf0e10cSrcweir         else
4387cdf0e10cSrcweir         {
4388cdf0e10cSrcweir             PushIllegalParameter();
4389cdf0e10cSrcweir             return;
4390cdf0e10cSrcweir         }
4391cdf0e10cSrcweir         if (nGlobalError == 0)
4392cdf0e10cSrcweir         {
4393cdf0e10cSrcweir             double fVal;
4394cdf0e10cSrcweir             String sStr;
4395cdf0e10cSrcweir             ScQueryParam rParam;
4396cdf0e10cSrcweir             rParam.nCol1       = nCol1;
4397cdf0e10cSrcweir             rParam.nRow1       = nRow1;
4398cdf0e10cSrcweir             rParam.nCol2       = nCol2;
4399cdf0e10cSrcweir             rParam.nTab        = nTab1;
4400cdf0e10cSrcweir             rParam.bMixedComparison = sal_True;
4401cdf0e10cSrcweir 
4402cdf0e10cSrcweir             ScQueryEntry& rEntry = rParam.GetEntry(0);
4403cdf0e10cSrcweir             rEntry.bDoQuery = sal_True;
4404cdf0e10cSrcweir             if (fTyp < 0.0)
4405cdf0e10cSrcweir                 rEntry.eOp = SC_GREATER_EQUAL;
4406cdf0e10cSrcweir             else if (fTyp > 0.0)
4407cdf0e10cSrcweir                 rEntry.eOp = SC_LESS_EQUAL;
4408cdf0e10cSrcweir             switch ( GetStackType() )
4409cdf0e10cSrcweir             {
4410cdf0e10cSrcweir                 case svDouble:
4411cdf0e10cSrcweir                 {
4412cdf0e10cSrcweir                     fVal = GetDouble();
4413cdf0e10cSrcweir                     rEntry.bQueryByString = sal_False;
4414cdf0e10cSrcweir                     rEntry.nVal = fVal;
4415cdf0e10cSrcweir                 }
4416cdf0e10cSrcweir                 break;
4417cdf0e10cSrcweir                 case svString:
4418cdf0e10cSrcweir                 {
4419cdf0e10cSrcweir                     sStr = GetString();
4420cdf0e10cSrcweir                     rEntry.bQueryByString = sal_True;
4421cdf0e10cSrcweir                     *rEntry.pStr = sStr;
4422cdf0e10cSrcweir                 }
4423cdf0e10cSrcweir                 break;
4424cdf0e10cSrcweir                 case svDoubleRef :
4425cdf0e10cSrcweir                 case svSingleRef :
4426cdf0e10cSrcweir                 {
4427cdf0e10cSrcweir                     ScAddress aAdr;
4428cdf0e10cSrcweir                     if ( !PopDoubleRefOrSingleRef( aAdr ) )
4429cdf0e10cSrcweir                     {
4430cdf0e10cSrcweir                         PushInt(0);
4431cdf0e10cSrcweir                         return ;
4432cdf0e10cSrcweir                     }
4433cdf0e10cSrcweir                     ScBaseCell* pCell = GetCell( aAdr );
4434cdf0e10cSrcweir                     if (HasCellValueData(pCell))
4435cdf0e10cSrcweir                     {
4436cdf0e10cSrcweir                         fVal = GetCellValue( aAdr, pCell );
4437cdf0e10cSrcweir                         rEntry.bQueryByString = sal_False;
4438cdf0e10cSrcweir                         rEntry.nVal = fVal;
4439cdf0e10cSrcweir                     }
4440cdf0e10cSrcweir                     else
4441cdf0e10cSrcweir                     {
4442cdf0e10cSrcweir                         GetCellString(sStr, pCell);
4443cdf0e10cSrcweir                         rEntry.bQueryByString = sal_True;
4444cdf0e10cSrcweir                         *rEntry.pStr = sStr;
4445cdf0e10cSrcweir                     }
4446cdf0e10cSrcweir                 }
4447cdf0e10cSrcweir                 break;
4448cdf0e10cSrcweir                 case svMatrix :
4449cdf0e10cSrcweir                 {
4450cdf0e10cSrcweir                     ScMatValType nType = GetDoubleOrStringFromMatrix(
4451cdf0e10cSrcweir                             rEntry.nVal, *rEntry.pStr);
4452cdf0e10cSrcweir                     rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
4453cdf0e10cSrcweir                 }
4454cdf0e10cSrcweir                 break;
4455cdf0e10cSrcweir                 default:
4456cdf0e10cSrcweir                 {
4457cdf0e10cSrcweir                     PushIllegalParameter();
4458cdf0e10cSrcweir                     return;
4459cdf0e10cSrcweir                 }
4460cdf0e10cSrcweir             }
4461cdf0e10cSrcweir             if ( rEntry.bQueryByString )
4462cdf0e10cSrcweir                 rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
4463cdf0e10cSrcweir 
4464cdf0e10cSrcweir             if (pMatSrc) // The source data is matrix array.
4465cdf0e10cSrcweir             {
4466cdf0e10cSrcweir                 SCSIZE nC, nR;
4467cdf0e10cSrcweir                 pMatSrc->GetDimensions( nC, nR);
4468cdf0e10cSrcweir                 if (nC > 1 && nR > 1)
4469cdf0e10cSrcweir                 {
4470cdf0e10cSrcweir                     // The source matrix must be a vector.
4471cdf0e10cSrcweir                     PushIllegalParameter();
4472cdf0e10cSrcweir                     return;
4473cdf0e10cSrcweir                 }
4474cdf0e10cSrcweir                 SCSIZE nMatCount = (nC == 1) ? nR : nC;
4475cdf0e10cSrcweir 
4476cdf0e10cSrcweir                 // simple serial search for equality mode (source data doesn't
4477cdf0e10cSrcweir                 // need to be sorted).
4478cdf0e10cSrcweir 
4479cdf0e10cSrcweir                 if (rEntry.eOp == SC_EQUAL)
4480cdf0e10cSrcweir                 {
4481cdf0e10cSrcweir                     for (SCSIZE i = 0; i < nMatCount; ++i)
4482cdf0e10cSrcweir                     {
4483cdf0e10cSrcweir                         if (lcl_CompareMatrix2Query( i, *pMatSrc, rEntry) == 0)
4484cdf0e10cSrcweir                         {
4485cdf0e10cSrcweir                             PushDouble(i+1); // found !
4486cdf0e10cSrcweir                             return;
4487cdf0e10cSrcweir                         }
4488cdf0e10cSrcweir                     }
4489cdf0e10cSrcweir                     PushNA(); // not found
4490cdf0e10cSrcweir                     return;
4491cdf0e10cSrcweir                 }
4492cdf0e10cSrcweir 
4493cdf0e10cSrcweir                 // binary search for non-equality mode (the source data is
4494cdf0e10cSrcweir                 // assumed to be sorted).
4495cdf0e10cSrcweir 
4496cdf0e10cSrcweir                 bool bAscOrder = (rEntry.eOp == SC_LESS_EQUAL);
4497cdf0e10cSrcweir                 SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
4498cdf0e10cSrcweir                 for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
4499cdf0e10cSrcweir                 {
4500cdf0e10cSrcweir                     SCSIZE nMid = nFirst + nLen/2;
4501cdf0e10cSrcweir                     sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, *pMatSrc, rEntry);
4502cdf0e10cSrcweir                     if (nCmp == 0)
4503cdf0e10cSrcweir                     {
4504cdf0e10cSrcweir                         // exact match.  find the last item with the same value.
4505cdf0e10cSrcweir                         lcl_GetLastMatch( nMid, *pMatSrc, nMatCount, !bAscOrder);
4506cdf0e10cSrcweir                         PushDouble( nMid+1);
4507cdf0e10cSrcweir                         return;
4508cdf0e10cSrcweir                     }
4509cdf0e10cSrcweir 
4510cdf0e10cSrcweir                     if (nLen == 1) // first and last items are next to each other.
4511cdf0e10cSrcweir                     {
4512cdf0e10cSrcweir                         if (nCmp < 0)
4513cdf0e10cSrcweir                             nHitIndex = bAscOrder ? nLast : nFirst;
4514cdf0e10cSrcweir                         else
4515cdf0e10cSrcweir                             nHitIndex = bAscOrder ? nFirst : nLast;
4516cdf0e10cSrcweir                         break;
4517cdf0e10cSrcweir                     }
4518cdf0e10cSrcweir 
4519cdf0e10cSrcweir                     if (nCmp < 0)
4520cdf0e10cSrcweir                     {
4521cdf0e10cSrcweir                         if (bAscOrder)
4522cdf0e10cSrcweir                             nFirst = nMid;
4523cdf0e10cSrcweir                         else
4524cdf0e10cSrcweir                             nLast = nMid;
4525cdf0e10cSrcweir                     }
4526cdf0e10cSrcweir                     else
4527cdf0e10cSrcweir                     {
4528cdf0e10cSrcweir                         if (bAscOrder)
4529cdf0e10cSrcweir                             nLast = nMid;
4530cdf0e10cSrcweir                         else
4531cdf0e10cSrcweir                             nFirst = nMid;
4532cdf0e10cSrcweir                     }
4533cdf0e10cSrcweir                 }
4534cdf0e10cSrcweir 
4535cdf0e10cSrcweir                 if (nHitIndex == nMatCount-1) // last item
4536cdf0e10cSrcweir                 {
4537cdf0e10cSrcweir                     sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, *pMatSrc, rEntry);
4538cdf0e10cSrcweir                     if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
4539cdf0e10cSrcweir                     {
4540cdf0e10cSrcweir                         // either the last item is an exact match or the real
4541cdf0e10cSrcweir                         // hit is beyond the last item.
4542cdf0e10cSrcweir                         PushDouble( nHitIndex+1);
4543cdf0e10cSrcweir                         return;
4544cdf0e10cSrcweir                     }
4545cdf0e10cSrcweir                 }
4546cdf0e10cSrcweir 
4547cdf0e10cSrcweir                 if (nHitIndex > 0) // valid hit must be 2nd item or higher
4548cdf0e10cSrcweir                 {
4549cdf0e10cSrcweir                     PushDouble( nHitIndex); // non-exact match
4550cdf0e10cSrcweir                     return;
4551cdf0e10cSrcweir                 }
4552cdf0e10cSrcweir 
4553cdf0e10cSrcweir                 PushNA();
4554cdf0e10cSrcweir                 return;
4555cdf0e10cSrcweir             }
4556cdf0e10cSrcweir 
4557cdf0e10cSrcweir             SCCOLROW nDelta = 0;
4558cdf0e10cSrcweir             if (nCol1 == nCol2)
4559cdf0e10cSrcweir             {                                           // search row in column
4560cdf0e10cSrcweir                 rParam.nRow2 = nRow2;
4561cdf0e10cSrcweir                 rEntry.nField = nCol1;
4562cdf0e10cSrcweir                 ScAddress aResultPos( nCol1, nRow1, nTab1);
4563cdf0e10cSrcweir                 if (!LookupQueryWithCache( aResultPos, rParam))
4564cdf0e10cSrcweir                 {
4565cdf0e10cSrcweir                     PushNA();
4566cdf0e10cSrcweir                     return;
4567cdf0e10cSrcweir                 }
4568cdf0e10cSrcweir                 nDelta = aResultPos.Row() - nRow1;
4569cdf0e10cSrcweir             }
4570cdf0e10cSrcweir             else
4571cdf0e10cSrcweir             {                                           // search column in row
4572cdf0e10cSrcweir                 SCCOL nC;
4573cdf0e10cSrcweir                 rParam.bByRow = sal_False;
4574cdf0e10cSrcweir                 rParam.nRow2 = nRow1;
4575cdf0e10cSrcweir                 rEntry.nField = nCol1;
4576cdf0e10cSrcweir                 ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
4577cdf0e10cSrcweir                 // Advance Entry.nField in Iterator if column changed
4578cdf0e10cSrcweir                 aCellIter.SetAdvanceQueryParamEntryField( sal_True );
4579cdf0e10cSrcweir                 if (fTyp == 0.0)
4580cdf0e10cSrcweir                 {                                       // EQUAL
4581cdf0e10cSrcweir                     if ( aCellIter.GetFirst() )
4582cdf0e10cSrcweir                         nC = aCellIter.GetCol();
4583cdf0e10cSrcweir                     else
4584cdf0e10cSrcweir                     {
4585cdf0e10cSrcweir                         PushNA();
4586cdf0e10cSrcweir                         return;
4587cdf0e10cSrcweir                     }
4588cdf0e10cSrcweir                 }
4589cdf0e10cSrcweir                 else
4590cdf0e10cSrcweir                 {                                       // <= or >=
4591cdf0e10cSrcweir                     SCROW nR;
4592cdf0e10cSrcweir                     if ( !aCellIter.FindEqualOrSortedLastInRange( nC, nR ) )
4593cdf0e10cSrcweir                     {
4594cdf0e10cSrcweir                         PushNA();
4595cdf0e10cSrcweir                         return;
4596cdf0e10cSrcweir                     }
4597cdf0e10cSrcweir                 }
4598cdf0e10cSrcweir                 nDelta = nC - nCol1;
4599cdf0e10cSrcweir             }
4600cdf0e10cSrcweir             PushDouble((double) (nDelta + 1));
4601cdf0e10cSrcweir         }
4602cdf0e10cSrcweir         else
4603cdf0e10cSrcweir             PushIllegalParameter();
4604cdf0e10cSrcweir     }
4605cdf0e10cSrcweir }
4606cdf0e10cSrcweir 
4607cdf0e10cSrcweir 
ScCountEmptyCells()4608cdf0e10cSrcweir void ScInterpreter::ScCountEmptyCells()
4609cdf0e10cSrcweir {
4610cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountEmptyCells" );
4611cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 1 ) )
4612cdf0e10cSrcweir     {
4613cdf0e10cSrcweir         sal_uLong nMaxCount = 0, nCount = 0;
4614cdf0e10cSrcweir         CellType eCellType;
4615cdf0e10cSrcweir         switch (GetStackType())
4616cdf0e10cSrcweir         {
4617cdf0e10cSrcweir             case svSingleRef :
4618cdf0e10cSrcweir             {
4619cdf0e10cSrcweir                 nMaxCount = 1;
4620cdf0e10cSrcweir                 ScAddress aAdr;
4621cdf0e10cSrcweir                 PopSingleRef( aAdr );
4622cdf0e10cSrcweir                 eCellType = GetCellType( GetCell( aAdr ) );
4623cdf0e10cSrcweir                 if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
4624cdf0e10cSrcweir                     nCount = 1;
4625cdf0e10cSrcweir             }
4626cdf0e10cSrcweir             break;
4627cdf0e10cSrcweir             case svDoubleRef :
4628cdf0e10cSrcweir             case svRefList :
4629cdf0e10cSrcweir             {
4630cdf0e10cSrcweir                 ScRange aRange;
4631cdf0e10cSrcweir                 short nParam = 1;
4632cdf0e10cSrcweir                 size_t nRefInList = 0;
4633cdf0e10cSrcweir                 while (nParam-- > 0)
4634cdf0e10cSrcweir                 {
4635cdf0e10cSrcweir                     PopDoubleRef( aRange, nParam, nRefInList);
4636cdf0e10cSrcweir                     nMaxCount +=
4637cdf0e10cSrcweir                         static_cast<sal_uLong>(aRange.aEnd.Row() - aRange.aStart.Row() + 1) *
4638cdf0e10cSrcweir                         static_cast<sal_uLong>(aRange.aEnd.Col() - aRange.aStart.Col() + 1) *
4639cdf0e10cSrcweir                         static_cast<sal_uLong>(aRange.aEnd.Tab() - aRange.aStart.Tab() + 1);
4640cdf0e10cSrcweir                     ScBaseCell* pCell;
4641cdf0e10cSrcweir                     ScCellIterator aDocIter( pDok, aRange, glSubTotal);
4642cdf0e10cSrcweir                     if ( (pCell = aDocIter.GetFirst()) != NULL )
4643cdf0e10cSrcweir                     {
4644cdf0e10cSrcweir                         do
4645cdf0e10cSrcweir                         {
4646cdf0e10cSrcweir                             if ((eCellType = pCell->GetCellType()) != CELLTYPE_NONE
4647cdf0e10cSrcweir                                     && eCellType != CELLTYPE_NOTE)
4648cdf0e10cSrcweir                                 nCount++;
4649cdf0e10cSrcweir                         } while ( (pCell = aDocIter.GetNext()) != NULL );
4650cdf0e10cSrcweir                     }
4651cdf0e10cSrcweir                 }
4652cdf0e10cSrcweir             }
4653cdf0e10cSrcweir             break;
4654cdf0e10cSrcweir             default : SetError(errIllegalParameter); break;
4655cdf0e10cSrcweir         }
4656cdf0e10cSrcweir         PushDouble(nMaxCount - nCount);
4657cdf0e10cSrcweir     }
4658cdf0e10cSrcweir }
4659cdf0e10cSrcweir 
4660cdf0e10cSrcweir 
IterateParametersIf(ScIterFuncIf eFunc)4661f53782ebSAndrew Rist double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
4662f53782ebSAndrew Rist {
4663f53782ebSAndrew Rist     sal_uInt8 nParamCount = GetByte();
4664f53782ebSAndrew Rist     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
4665f53782ebSAndrew Rist     {
4666f53782ebSAndrew Rist         SCCOL nCol3 = 0;
4667f53782ebSAndrew Rist         SCROW nRow3 = 0;
4668f53782ebSAndrew Rist         SCTAB nTab3 = 0;
4669f53782ebSAndrew Rist 
4670f53782ebSAndrew Rist         ScMatrixRef pSumExtraMatrix;
4671f53782ebSAndrew Rist         bool bSumExtraRange = (nParamCount == 3);
4672f53782ebSAndrew Rist         if (bSumExtraRange)
4673f53782ebSAndrew Rist         {
4674f53782ebSAndrew Rist             // Save only the upperleft cell in case of cell range.  The geometry
4675f53782ebSAndrew Rist             // of the 3rd parameter is taken from the 1st parameter.
4676f53782ebSAndrew Rist 
4677f53782ebSAndrew Rist             switch ( GetStackType() )
4678f53782ebSAndrew Rist             {
4679f53782ebSAndrew Rist                 case svDoubleRef :
4680f53782ebSAndrew Rist                     {
4681f53782ebSAndrew Rist                         SCCOL nColJunk = 0;
4682f53782ebSAndrew Rist                         SCROW nRowJunk = 0;
4683f53782ebSAndrew Rist                         SCTAB nTabJunk = 0;
4684f53782ebSAndrew Rist                         PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
4685f53782ebSAndrew Rist                         if ( nTabJunk != nTab3 )
4686f53782ebSAndrew Rist                         {
4687f53782ebSAndrew Rist                             SetError( errIllegalParameter);
4688f53782ebSAndrew Rist                         }
4689f53782ebSAndrew Rist                     }
4690f53782ebSAndrew Rist                     break;
4691f53782ebSAndrew Rist                 case svSingleRef :
4692f53782ebSAndrew Rist                     PopSingleRef( nCol3, nRow3, nTab3 );
4693f53782ebSAndrew Rist                     break;
4694f53782ebSAndrew Rist                 case svMatrix:
4695f53782ebSAndrew Rist                     pSumExtraMatrix = PopMatrix();
4696f53782ebSAndrew Rist                     //! nCol3, nRow3, nTab3 remain 0
4697f53782ebSAndrew Rist                     break;
4698f53782ebSAndrew Rist                 default:
4699f53782ebSAndrew Rist                     SetError( errIllegalParameter);
4700f53782ebSAndrew Rist             }
4701f53782ebSAndrew Rist         }
4702f53782ebSAndrew Rist         String rString;
4703f53782ebSAndrew Rist         double fVal = 0.0;
4704f53782ebSAndrew Rist         bool bIsString = true;
4705f53782ebSAndrew Rist         switch ( GetStackType() )
4706f53782ebSAndrew Rist         {
4707f53782ebSAndrew Rist             case svDoubleRef :
4708f53782ebSAndrew Rist             case svSingleRef :
4709f53782ebSAndrew Rist                 {
4710f53782ebSAndrew Rist                     ScAddress aAdr;
4711f53782ebSAndrew Rist                     if ( !PopDoubleRefOrSingleRef( aAdr ) )
4712f53782ebSAndrew Rist                         return 0;
4713f53782ebSAndrew Rist 
4714f53782ebSAndrew Rist                     ScBaseCell* pCell = GetCell( aAdr );
4715f53782ebSAndrew Rist                     switch ( GetCellType( pCell ) )
4716f53782ebSAndrew Rist                     {
4717f53782ebSAndrew Rist                         case CELLTYPE_VALUE :
4718f53782ebSAndrew Rist                             fVal = GetCellValue( aAdr, pCell );
4719f53782ebSAndrew Rist                             bIsString = false;
4720f53782ebSAndrew Rist                             break;
4721f53782ebSAndrew Rist                         case CELLTYPE_FORMULA :
4722f53782ebSAndrew Rist                             if( ((ScFormulaCell*)pCell)->IsValue() )
4723f53782ebSAndrew Rist                             {
4724f53782ebSAndrew Rist                                 fVal = GetCellValue( aAdr, pCell );
4725f53782ebSAndrew Rist                                 bIsString = false;
4726f53782ebSAndrew Rist                             }
4727f53782ebSAndrew Rist                             else
4728f53782ebSAndrew Rist                                 GetCellString(rString, pCell);
4729f53782ebSAndrew Rist                             break;
4730f53782ebSAndrew Rist                         case CELLTYPE_STRING :
4731f53782ebSAndrew Rist                         case CELLTYPE_EDIT :
4732f53782ebSAndrew Rist                             GetCellString(rString, pCell);
4733f53782ebSAndrew Rist                             break;
4734f53782ebSAndrew Rist                         default:
4735f53782ebSAndrew Rist                             fVal = 0.0;
4736f53782ebSAndrew Rist                             bIsString = false;
4737f53782ebSAndrew Rist                     }
4738f53782ebSAndrew Rist                 }
4739f53782ebSAndrew Rist                 break;
4740f53782ebSAndrew Rist             case svString:
4741f53782ebSAndrew Rist                 rString = GetString();
4742f53782ebSAndrew Rist                 break;
4743f53782ebSAndrew Rist             case svMatrix :
4744f53782ebSAndrew Rist                 {
4745f53782ebSAndrew Rist                     ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
4746f53782ebSAndrew Rist                     bIsString = ScMatrix::IsNonValueType( nType);
4747f53782ebSAndrew Rist                 }
4748f53782ebSAndrew Rist                 break;
4749f53782ebSAndrew Rist             default:
4750f53782ebSAndrew Rist                 {
4751f53782ebSAndrew Rist                     fVal = GetDouble();
4752f53782ebSAndrew Rist                     bIsString = false;
4753f53782ebSAndrew Rist                 }
4754f53782ebSAndrew Rist         }
4755f53782ebSAndrew Rist 
4756f53782ebSAndrew Rist         double fSum = 0.0;
4757f53782ebSAndrew Rist         double fMem = 0.0;
4758f53782ebSAndrew Rist         double fRes = 0.0;
4759f53782ebSAndrew Rist         double fCount = 0.0;
4760f53782ebSAndrew Rist         bool bNull = true;
4761f53782ebSAndrew Rist         short nParam = 1;
4762f53782ebSAndrew Rist         size_t nRefInList = 0;
4763f53782ebSAndrew Rist         while (nParam-- > 0)
4764f53782ebSAndrew Rist         {
476551df7705SAndrew Rist             SCCOL nCol1 = 0;
476651df7705SAndrew Rist             SCROW nRow1 = 0;
476751df7705SAndrew Rist             SCTAB nTab1 = 0;
476851df7705SAndrew Rist             SCCOL nCol2 = 0;
476951df7705SAndrew Rist             SCROW nRow2 = 0;
477051df7705SAndrew Rist             SCTAB nTab2 = 0;
4771f53782ebSAndrew Rist             ScMatrixRef pQueryMatrix;
4772f53782ebSAndrew Rist             switch ( GetStackType() )
4773f53782ebSAndrew Rist             {
4774f53782ebSAndrew Rist                 case svRefList :
4775f53782ebSAndrew Rist                     if (bSumExtraRange)
4776f53782ebSAndrew Rist                     {
4777f53782ebSAndrew Rist                         SetError( errIllegalParameter);
4778f53782ebSAndrew Rist                     }
4779f53782ebSAndrew Rist                     else
4780f53782ebSAndrew Rist                     {
4781f53782ebSAndrew Rist                         ScRange aRange;
4782f53782ebSAndrew Rist                         PopDoubleRef( aRange, nParam, nRefInList);
4783f53782ebSAndrew Rist                         aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4784f53782ebSAndrew Rist                     }
4785f53782ebSAndrew Rist                     break;
4786f53782ebSAndrew Rist                 case svDoubleRef :
4787f53782ebSAndrew Rist                     PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4788f53782ebSAndrew Rist                     break;
4789f53782ebSAndrew Rist                 case svSingleRef :
4790f53782ebSAndrew Rist                     PopSingleRef( nCol1, nRow1, nTab1 );
4791f53782ebSAndrew Rist                     nCol2 = nCol1;
4792f53782ebSAndrew Rist                     nRow2 = nRow1;
4793f53782ebSAndrew Rist                     nTab2 = nTab1;
4794f53782ebSAndrew Rist                     break;
4795f53782ebSAndrew Rist                 case svMatrix:
4796f53782ebSAndrew Rist                     {
4797f53782ebSAndrew Rist                         pQueryMatrix = PopMatrix();
4798f53782ebSAndrew Rist                         if (!pQueryMatrix)
4799f53782ebSAndrew Rist                         {
4800f53782ebSAndrew Rist                             SetError( errIllegalParameter);
4801f53782ebSAndrew Rist                         }
4802f53782ebSAndrew Rist                         nCol1 = 0;
4803f53782ebSAndrew Rist                         nRow1 = 0;
4804f53782ebSAndrew Rist                         nTab1 = 0;
4805f53782ebSAndrew Rist                         SCSIZE nC, nR;
4806f53782ebSAndrew Rist                         pQueryMatrix->GetDimensions( nC, nR);
4807f53782ebSAndrew Rist                         nCol2 = static_cast<SCCOL>(nC - 1);
4808f53782ebSAndrew Rist                         nRow2 = static_cast<SCROW>(nR - 1);
4809f53782ebSAndrew Rist                         nTab2 = 0;
4810f53782ebSAndrew Rist                     }
4811f53782ebSAndrew Rist                     break;
4812f53782ebSAndrew Rist                 default:
4813f53782ebSAndrew Rist                     SetError( errIllegalParameter);
4814f53782ebSAndrew Rist             }
4815f53782ebSAndrew Rist             if ( nTab1 != nTab2 )
4816f53782ebSAndrew Rist             {
4817f53782ebSAndrew Rist                 SetError( errIllegalParameter);
4818f53782ebSAndrew Rist             }
4819f53782ebSAndrew Rist 
4820f53782ebSAndrew Rist             if (bSumExtraRange)
4821f53782ebSAndrew Rist             {
4822f53782ebSAndrew Rist                 // Take the range geometry of the 1st parameter and apply it to
4823f53782ebSAndrew Rist                 // the 3rd. If parts of the resulting range would point outside
4824f53782ebSAndrew Rist                 // the sheet, don't complain but silently ignore and simply cut
4825f53782ebSAndrew Rist                 // them away, this is what Xcl does :-/
4826f53782ebSAndrew Rist 
4827f53782ebSAndrew Rist                 // For the cut-away part we also don't need to determine the
4828f53782ebSAndrew Rist                 // criteria match, so shrink the source range accordingly,
4829f53782ebSAndrew Rist                 // instead of the result range.
4830f53782ebSAndrew Rist                 SCCOL nColDelta = nCol2 - nCol1;
4831f53782ebSAndrew Rist                 SCROW nRowDelta = nRow2 - nRow1;
4832f53782ebSAndrew Rist                 SCCOL nMaxCol;
4833f53782ebSAndrew Rist                 SCROW nMaxRow;
4834f53782ebSAndrew Rist                 if (pSumExtraMatrix)
4835f53782ebSAndrew Rist                 {
4836f53782ebSAndrew Rist                     SCSIZE nC, nR;
4837f53782ebSAndrew Rist                     pSumExtraMatrix->GetDimensions( nC, nR);
4838f53782ebSAndrew Rist                     nMaxCol = static_cast<SCCOL>(nC - 1);
4839f53782ebSAndrew Rist                     nMaxRow = static_cast<SCROW>(nR - 1);
4840f53782ebSAndrew Rist                 }
4841f53782ebSAndrew Rist                 else
4842f53782ebSAndrew Rist                 {
4843f53782ebSAndrew Rist                     nMaxCol = MAXCOL;
4844f53782ebSAndrew Rist                     nMaxRow = MAXROW;
4845f53782ebSAndrew Rist                 }
4846f53782ebSAndrew Rist                 if (nCol3 + nColDelta > nMaxCol)
4847f53782ebSAndrew Rist                 {
4848f53782ebSAndrew Rist                     SCCOL nNewDelta = nMaxCol - nCol3;
4849f53782ebSAndrew Rist                     nCol2 = nCol1 + nNewDelta;
4850f53782ebSAndrew Rist                 }
4851f53782ebSAndrew Rist 
4852f53782ebSAndrew Rist                 if (nRow3 + nRowDelta > nMaxRow)
4853f53782ebSAndrew Rist                 {
4854f53782ebSAndrew Rist                     SCROW nNewDelta = nMaxRow - nRow3;
4855f53782ebSAndrew Rist                     nRow2 = nRow1 + nNewDelta;
4856f53782ebSAndrew Rist                 }
4857f53782ebSAndrew Rist             }
4858f53782ebSAndrew Rist             else
4859f53782ebSAndrew Rist             {
4860f53782ebSAndrew Rist                 nCol3 = nCol1;
4861f53782ebSAndrew Rist                 nRow3 = nRow1;
4862f53782ebSAndrew Rist                 nTab3 = nTab1;
4863f53782ebSAndrew Rist             }
4864f53782ebSAndrew Rist 
4865f53782ebSAndrew Rist             if (nGlobalError == 0)
4866f53782ebSAndrew Rist             {
4867f53782ebSAndrew Rist                 ScQueryParam rParam;
4868f53782ebSAndrew Rist                 rParam.nRow1       = nRow1;
4869f53782ebSAndrew Rist                 rParam.nRow2       = nRow2;
4870f53782ebSAndrew Rist 
4871f53782ebSAndrew Rist                 ScQueryEntry& rEntry = rParam.GetEntry(0);
4872f53782ebSAndrew Rist                 rEntry.bDoQuery = true;
4873f53782ebSAndrew Rist                 if (!bIsString)
4874f53782ebSAndrew Rist                 {
4875f53782ebSAndrew Rist                     rEntry.bQueryByString = false;
4876f53782ebSAndrew Rist                     rEntry.nVal = fVal;
4877f53782ebSAndrew Rist                     rEntry.eOp = SC_EQUAL;
4878f53782ebSAndrew Rist                 }
4879f53782ebSAndrew Rist                 else
4880f53782ebSAndrew Rist                 {
4881f53782ebSAndrew Rist                     rParam.FillInExcelSyntax(rString, 0);
4882f53782ebSAndrew Rist                     sal_uInt32 nIndex = 0;
4883f53782ebSAndrew Rist                     rEntry.bQueryByString =
4884f53782ebSAndrew Rist                         !(pFormatter->IsNumberFormat(
4885f53782ebSAndrew Rist                                     *rEntry.pStr, nIndex, rEntry.nVal));
4886f53782ebSAndrew Rist                     if ( rEntry.bQueryByString )
4887f53782ebSAndrew Rist                         rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
4888f53782ebSAndrew Rist                 }
4889f53782ebSAndrew Rist                 ScAddress aAdr;
4890f53782ebSAndrew Rist                 aAdr.SetTab( nTab3 );
4891f53782ebSAndrew Rist                 rParam.nCol1  = nCol1;
4892f53782ebSAndrew Rist                 rParam.nCol2  = nCol2;
4893f53782ebSAndrew Rist                 rEntry.nField = nCol1;
4894f53782ebSAndrew Rist                 SCsCOL nColDiff = nCol3 - nCol1;
4895f53782ebSAndrew Rist                 SCsROW nRowDiff = nRow3 - nRow1;
4896f53782ebSAndrew Rist                 if (pQueryMatrix)
4897f53782ebSAndrew Rist                 {
4898f53782ebSAndrew Rist                     // Never case-sensitive.
4899f53782ebSAndrew Rist                     ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
4900f53782ebSAndrew Rist                     ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
4901f53782ebSAndrew Rist                     if (nGlobalError || !pResultMatrix)
4902f53782ebSAndrew Rist                     {
4903f53782ebSAndrew Rist                         SetError( errIllegalParameter);
4904f53782ebSAndrew Rist                     }
4905f53782ebSAndrew Rist 
4906f53782ebSAndrew Rist                     if (pSumExtraMatrix)
4907f53782ebSAndrew Rist                     {
4908f53782ebSAndrew Rist                         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
4909f53782ebSAndrew Rist                         {
4910f53782ebSAndrew Rist                             for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
4911f53782ebSAndrew Rist                             {
4912f53782ebSAndrew Rist                                 if (pResultMatrix->IsValue( nCol, nRow) &&
4913f53782ebSAndrew Rist                                         pResultMatrix->GetDouble( nCol, nRow))
4914f53782ebSAndrew Rist                                 {
4915f53782ebSAndrew Rist                                     SCSIZE nC = nCol + nColDiff;
4916f53782ebSAndrew Rist                                     SCSIZE nR = nRow + nRowDiff;
4917f53782ebSAndrew Rist                                     if (pSumExtraMatrix->IsValue( nC, nR))
4918f53782ebSAndrew Rist                                     {
4919f53782ebSAndrew Rist                                         fVal = pSumExtraMatrix->GetDouble( nC, nR);
4920f53782ebSAndrew Rist                                         ++fCount;
4921f53782ebSAndrew Rist                                         if ( bNull && fVal != 0.0 )
4922f53782ebSAndrew Rist                                         {
4923f53782ebSAndrew Rist                                             bNull = false;
4924f53782ebSAndrew Rist                                             fMem = fVal;
4925f53782ebSAndrew Rist                                         }
4926f53782ebSAndrew Rist                                         else
4927f53782ebSAndrew Rist                                             fSum += fVal;
4928f53782ebSAndrew Rist                                     }
4929f53782ebSAndrew Rist                                 }
4930f53782ebSAndrew Rist                             }
4931f53782ebSAndrew Rist                         }
4932f53782ebSAndrew Rist                     }
4933f53782ebSAndrew Rist                     else
4934f53782ebSAndrew Rist                     {
4935f53782ebSAndrew Rist                         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
4936f53782ebSAndrew Rist                         {
4937f53782ebSAndrew Rist                             for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
4938f53782ebSAndrew Rist                             {
4939f53782ebSAndrew Rist                                 if (pResultMatrix->GetDouble( nCol, nRow))
4940f53782ebSAndrew Rist                                 {
4941f53782ebSAndrew Rist                                     aAdr.SetCol( nCol + nColDiff);
4942f53782ebSAndrew Rist                                     aAdr.SetRow( nRow + nRowDiff);
4943f53782ebSAndrew Rist                                     ScBaseCell* pCell = GetCell( aAdr );
4944f53782ebSAndrew Rist                                     if ( HasCellValueData(pCell) )
4945f53782ebSAndrew Rist                                     {
4946f53782ebSAndrew Rist                                         fVal = GetCellValue( aAdr, pCell );
4947f53782ebSAndrew Rist                                         ++fCount;
4948f53782ebSAndrew Rist                                         if ( bNull && fVal != 0.0 )
4949f53782ebSAndrew Rist                                         {
4950f53782ebSAndrew Rist                                             bNull = false;
4951f53782ebSAndrew Rist                                             fMem = fVal;
4952f53782ebSAndrew Rist                                         }
4953f53782ebSAndrew Rist                                         else
4954f53782ebSAndrew Rist                                             fSum += fVal;
4955f53782ebSAndrew Rist                                     }
4956f53782ebSAndrew Rist                                 }
4957f53782ebSAndrew Rist                             }
4958f53782ebSAndrew Rist                         }
4959f53782ebSAndrew Rist                     }
4960f53782ebSAndrew Rist                 }
4961f53782ebSAndrew Rist                 else
4962f53782ebSAndrew Rist                 {
4963f53782ebSAndrew Rist                     ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
4964f53782ebSAndrew Rist                     // Increment Entry.nField in iterator when switching to next column.
4965f53782ebSAndrew Rist                     aCellIter.SetAdvanceQueryParamEntryField( true );
4966f53782ebSAndrew Rist                     if ( aCellIter.GetFirst() )
4967f53782ebSAndrew Rist                     {
4968f53782ebSAndrew Rist                         if (pSumExtraMatrix)
4969f53782ebSAndrew Rist                         {
4970f53782ebSAndrew Rist                             do
4971f53782ebSAndrew Rist                             {
4972f53782ebSAndrew Rist                                 SCSIZE nC = aCellIter.GetCol() + nColDiff;
4973f53782ebSAndrew Rist                                 SCSIZE nR = aCellIter.GetRow() + nRowDiff;
4974f53782ebSAndrew Rist                                 if (pSumExtraMatrix->IsValue( nC, nR))
4975f53782ebSAndrew Rist                                 {
4976f53782ebSAndrew Rist                                     fVal = pSumExtraMatrix->GetDouble( nC, nR);
4977f53782ebSAndrew Rist                                     ++fCount;
4978f53782ebSAndrew Rist                                     if ( bNull && fVal != 0.0 )
4979f53782ebSAndrew Rist                                     {
4980f53782ebSAndrew Rist                                         bNull = false;
4981f53782ebSAndrew Rist                                         fMem = fVal;
4982f53782ebSAndrew Rist                                     }
4983f53782ebSAndrew Rist                                     else
4984f53782ebSAndrew Rist                                         fSum += fVal;
4985f53782ebSAndrew Rist                                 }
4986f53782ebSAndrew Rist                             } while ( aCellIter.GetNext() );
4987f53782ebSAndrew Rist                         }
4988f53782ebSAndrew Rist                         else
4989f53782ebSAndrew Rist                         {
4990f53782ebSAndrew Rist                             do
4991f53782ebSAndrew Rist                             {
4992f53782ebSAndrew Rist                                 aAdr.SetCol( aCellIter.GetCol() + nColDiff);
4993f53782ebSAndrew Rist                                 aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
4994f53782ebSAndrew Rist                                 ScBaseCell* pCell = GetCell( aAdr );
4995f53782ebSAndrew Rist                                 if ( HasCellValueData(pCell) )
4996f53782ebSAndrew Rist                                 {
4997f53782ebSAndrew Rist                                     fVal = GetCellValue( aAdr, pCell );
4998f53782ebSAndrew Rist                                     ++fCount;
4999f53782ebSAndrew Rist                                     if ( bNull && fVal != 0.0 )
5000f53782ebSAndrew Rist                                     {
5001f53782ebSAndrew Rist                                         bNull = false;
5002f53782ebSAndrew Rist                                         fMem = fVal;
5003f53782ebSAndrew Rist                                     }
5004f53782ebSAndrew Rist                                     else
5005f53782ebSAndrew Rist                                         fSum += fVal;
5006f53782ebSAndrew Rist                                 }
5007f53782ebSAndrew Rist                             } while ( aCellIter.GetNext() );
5008f53782ebSAndrew Rist                         }
5009f53782ebSAndrew Rist                     }
5010f53782ebSAndrew Rist                 }
5011f53782ebSAndrew Rist             }
5012f53782ebSAndrew Rist             else
5013f53782ebSAndrew Rist             {
5014f53782ebSAndrew Rist                 SetError( errIllegalParameter);
5015f53782ebSAndrew Rist             }
5016f53782ebSAndrew Rist         }
5017f53782ebSAndrew Rist 
5018f53782ebSAndrew Rist         switch( eFunc )
5019f53782ebSAndrew Rist         {
5020f53782ebSAndrew Rist             case ifSUMIF:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
5021f53782ebSAndrew Rist             case ifAVERAGEIF: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
5022f53782ebSAndrew Rist         }
5023f53782ebSAndrew Rist         return fRes;
5024f53782ebSAndrew Rist     }
5025f53782ebSAndrew Rist     return 0;
5026f53782ebSAndrew Rist }
5027f53782ebSAndrew Rist 
ScSumIf()5028f53782ebSAndrew Rist void ScInterpreter::ScSumIf()
5029f53782ebSAndrew Rist {
5030f53782ebSAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumIf" );
5031f53782ebSAndrew Rist     PushDouble( IterateParametersIf( ifSUMIF));
5032f53782ebSAndrew Rist }
5033f53782ebSAndrew Rist 
ScAverageIf()5034f53782ebSAndrew Rist void ScInterpreter::ScAverageIf()
5035f53782ebSAndrew Rist {
5036f53782ebSAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIf" );
5037f53782ebSAndrew Rist     PushDouble( IterateParametersIf( ifAVERAGEIF));
5038f53782ebSAndrew Rist }
5039f53782ebSAndrew Rist 
ScCountIf()5040cdf0e10cSrcweir void ScInterpreter::ScCountIf()
5041cdf0e10cSrcweir {
5042cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
5043cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 2 ) )
5044cdf0e10cSrcweir     {
5045cdf0e10cSrcweir         String rString;
5046cdf0e10cSrcweir         double fVal = 0.0;
5047cdf0e10cSrcweir         sal_Bool bIsString = sal_True;
5048cdf0e10cSrcweir         switch ( GetStackType() )
5049cdf0e10cSrcweir         {
5050cdf0e10cSrcweir             case svDoubleRef :
5051cdf0e10cSrcweir             case svSingleRef :
5052cdf0e10cSrcweir             {
5053cdf0e10cSrcweir                 ScAddress aAdr;
5054cdf0e10cSrcweir                 if ( !PopDoubleRefOrSingleRef( aAdr ) )
5055cdf0e10cSrcweir                 {
5056cdf0e10cSrcweir                     PushInt(0);
5057cdf0e10cSrcweir                     return ;
5058cdf0e10cSrcweir                 }
5059cdf0e10cSrcweir                 ScBaseCell* pCell = GetCell( aAdr );
5060cdf0e10cSrcweir                 switch ( GetCellType( pCell ) )
5061cdf0e10cSrcweir                 {
5062cdf0e10cSrcweir                     case CELLTYPE_VALUE :
5063cdf0e10cSrcweir                         fVal = GetCellValue( aAdr, pCell );
5064cdf0e10cSrcweir                         bIsString = sal_False;
5065cdf0e10cSrcweir                         break;
5066cdf0e10cSrcweir                     case CELLTYPE_FORMULA :
5067cdf0e10cSrcweir                         if( ((ScFormulaCell*)pCell)->IsValue() )
5068cdf0e10cSrcweir                         {
5069cdf0e10cSrcweir                             fVal = GetCellValue( aAdr, pCell );
5070cdf0e10cSrcweir                             bIsString = sal_False;
5071cdf0e10cSrcweir                         }
5072cdf0e10cSrcweir                         else
5073cdf0e10cSrcweir                             GetCellString(rString, pCell);
5074cdf0e10cSrcweir                         break;
5075cdf0e10cSrcweir                     case CELLTYPE_STRING :
5076cdf0e10cSrcweir                     case CELLTYPE_EDIT :
5077cdf0e10cSrcweir                         GetCellString(rString, pCell);
5078cdf0e10cSrcweir                         break;
5079cdf0e10cSrcweir                     default:
5080cdf0e10cSrcweir                         fVal = 0.0;
5081cdf0e10cSrcweir                         bIsString = sal_False;
5082cdf0e10cSrcweir                 }
5083cdf0e10cSrcweir             }
5084cdf0e10cSrcweir             break;
5085cdf0e10cSrcweir             case svMatrix :
5086cdf0e10cSrcweir             {
5087f53782ebSAndrew Rist                 ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
5088cdf0e10cSrcweir                 bIsString = ScMatrix::IsNonValueType( nType);
5089cdf0e10cSrcweir             }
5090cdf0e10cSrcweir             break;
5091cdf0e10cSrcweir             case svString:
5092cdf0e10cSrcweir                 rString = GetString();
5093cdf0e10cSrcweir             break;
5094cdf0e10cSrcweir             default:
5095cdf0e10cSrcweir             {
5096cdf0e10cSrcweir                 fVal = GetDouble();
5097cdf0e10cSrcweir                 bIsString = sal_False;
5098cdf0e10cSrcweir             }
5099cdf0e10cSrcweir         }
5100f53782ebSAndrew Rist         double fCount = 0.0;
5101cdf0e10cSrcweir         short nParam = 1;
5102cdf0e10cSrcweir         size_t nRefInList = 0;
5103cdf0e10cSrcweir         while (nParam-- > 0)
5104cdf0e10cSrcweir         {
5105cdf0e10cSrcweir             SCCOL nCol1;
5106cdf0e10cSrcweir             SCROW nRow1;
5107cdf0e10cSrcweir             SCTAB nTab1;
5108cdf0e10cSrcweir             SCCOL nCol2;
5109cdf0e10cSrcweir             SCROW nRow2;
5110cdf0e10cSrcweir             SCTAB nTab2;
5111cdf0e10cSrcweir             ScMatrixRef pQueryMatrix;
5112cdf0e10cSrcweir             switch ( GetStackType() )
5113cdf0e10cSrcweir             {
5114cdf0e10cSrcweir                 case svDoubleRef :
5115cdf0e10cSrcweir                 case svRefList :
5116cdf0e10cSrcweir                     {
5117cdf0e10cSrcweir                         ScRange aRange;
5118cdf0e10cSrcweir                         PopDoubleRef( aRange, nParam, nRefInList);
5119cdf0e10cSrcweir                         aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5120cdf0e10cSrcweir                     }
5121cdf0e10cSrcweir                     break;
5122cdf0e10cSrcweir                 case svSingleRef :
5123cdf0e10cSrcweir                     PopSingleRef( nCol1, nRow1, nTab1 );
5124cdf0e10cSrcweir                     nCol2 = nCol1;
5125cdf0e10cSrcweir                     nRow2 = nRow1;
5126cdf0e10cSrcweir                     nTab2 = nTab1;
5127cdf0e10cSrcweir                     break;
5128cdf0e10cSrcweir                 case svMatrix:
5129cdf0e10cSrcweir                     {
5130cdf0e10cSrcweir                         pQueryMatrix = PopMatrix();
5131cdf0e10cSrcweir                         if (!pQueryMatrix)
5132cdf0e10cSrcweir                         {
5133cdf0e10cSrcweir                             PushIllegalParameter();
5134cdf0e10cSrcweir                             return;
5135cdf0e10cSrcweir                         }
5136cdf0e10cSrcweir                         nCol1 = 0;
5137cdf0e10cSrcweir                         nRow1 = 0;
5138cdf0e10cSrcweir                         nTab1 = 0;
5139cdf0e10cSrcweir                         SCSIZE nC, nR;
5140cdf0e10cSrcweir                         pQueryMatrix->GetDimensions( nC, nR);
5141cdf0e10cSrcweir                         nCol2 = static_cast<SCCOL>(nC - 1);
5142cdf0e10cSrcweir                         nRow2 = static_cast<SCROW>(nR - 1);
5143cdf0e10cSrcweir                         nTab2 = 0;
5144cdf0e10cSrcweir                     }
5145cdf0e10cSrcweir                     break;
5146cdf0e10cSrcweir                 default:
5147cdf0e10cSrcweir                     PushIllegalParameter();
5148cdf0e10cSrcweir                     return ;
5149cdf0e10cSrcweir             }
5150cdf0e10cSrcweir             if ( nTab1 != nTab2 )
5151cdf0e10cSrcweir             {
5152cdf0e10cSrcweir                 PushIllegalParameter();
5153cdf0e10cSrcweir                 return;
5154cdf0e10cSrcweir             }
5155cdf0e10cSrcweir             if (nCol1 > nCol2)
5156cdf0e10cSrcweir             {
5157cdf0e10cSrcweir                 PushIllegalParameter();
5158cdf0e10cSrcweir                 return;
5159cdf0e10cSrcweir             }
5160cdf0e10cSrcweir             if (nGlobalError == 0)
5161cdf0e10cSrcweir             {
5162cdf0e10cSrcweir                 ScQueryParam rParam;
5163cdf0e10cSrcweir                 rParam.nRow1       = nRow1;
5164cdf0e10cSrcweir                 rParam.nRow2       = nRow2;
5165cdf0e10cSrcweir 
5166cdf0e10cSrcweir                 ScQueryEntry& rEntry = rParam.GetEntry(0);
5167cdf0e10cSrcweir                 rEntry.bDoQuery = sal_True;
5168cdf0e10cSrcweir                 if (!bIsString)
5169cdf0e10cSrcweir                 {
5170cdf0e10cSrcweir                     rEntry.bQueryByString = sal_False;
5171cdf0e10cSrcweir                     rEntry.nVal = fVal;
5172cdf0e10cSrcweir                     rEntry.eOp = SC_EQUAL;
5173cdf0e10cSrcweir                 }
5174cdf0e10cSrcweir                 else
5175cdf0e10cSrcweir                 {
5176cdf0e10cSrcweir                     rParam.FillInExcelSyntax(rString, 0);
5177cdf0e10cSrcweir                     sal_uInt32 nIndex = 0;
5178cdf0e10cSrcweir                     rEntry.bQueryByString =
5179cdf0e10cSrcweir                         !(pFormatter->IsNumberFormat(
5180cdf0e10cSrcweir                                     *rEntry.pStr, nIndex, rEntry.nVal));
5181cdf0e10cSrcweir                     if ( rEntry.bQueryByString )
5182cdf0e10cSrcweir                         rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
5183cdf0e10cSrcweir                 }
5184cdf0e10cSrcweir                 rParam.nCol1  = nCol1;
5185cdf0e10cSrcweir                 rParam.nCol2  = nCol2;
5186cdf0e10cSrcweir                 rEntry.nField = nCol1;
5187cdf0e10cSrcweir                 if (pQueryMatrix)
5188cdf0e10cSrcweir                 {
5189cdf0e10cSrcweir                     // Never case-sensitive.
5190cdf0e10cSrcweir                     ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
5191cdf0e10cSrcweir                     ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
5192cdf0e10cSrcweir                     if (nGlobalError || !pResultMatrix)
5193cdf0e10cSrcweir                     {
5194cdf0e10cSrcweir                         PushIllegalParameter();
5195cdf0e10cSrcweir                         return;
5196cdf0e10cSrcweir                     }
5197cdf0e10cSrcweir 
5198cdf0e10cSrcweir                     SCSIZE nSize = pResultMatrix->GetElementCount();
5199cdf0e10cSrcweir                     for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
5200cdf0e10cSrcweir                     {
5201cdf0e10cSrcweir                         if (pResultMatrix->IsValue( nIndex) &&
5202cdf0e10cSrcweir                                 pResultMatrix->GetDouble( nIndex))
5203f53782ebSAndrew Rist                             ++fCount;
5204cdf0e10cSrcweir                     }
5205cdf0e10cSrcweir                 }
5206cdf0e10cSrcweir                 else
5207cdf0e10cSrcweir                 {
5208cdf0e10cSrcweir                     ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
5209cdf0e10cSrcweir                     // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
5210cdf0e10cSrcweir                     aCellIter.SetAdvanceQueryParamEntryField( sal_True );
5211cdf0e10cSrcweir                     if ( aCellIter.GetFirst() )
5212cdf0e10cSrcweir                     {
5213cdf0e10cSrcweir                         do
5214cdf0e10cSrcweir                         {
5215f53782ebSAndrew Rist                             fCount++;
5216cdf0e10cSrcweir                         } while ( aCellIter.GetNext() );
5217cdf0e10cSrcweir                     }
5218cdf0e10cSrcweir                 }
5219cdf0e10cSrcweir             }
5220cdf0e10cSrcweir             else
5221cdf0e10cSrcweir             {
5222cdf0e10cSrcweir                 PushIllegalParameter();
5223cdf0e10cSrcweir                 return;
5224cdf0e10cSrcweir             }
5225cdf0e10cSrcweir         }
5226f53782ebSAndrew Rist         PushDouble(fCount);
5227cdf0e10cSrcweir     }
5228cdf0e10cSrcweir }
5229cdf0e10cSrcweir 
IterateParametersIfs(ScIterFuncIfs eFunc)52301b1b70fbSAndrew Rist double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
52311b1b70fbSAndrew Rist {
52321b1b70fbSAndrew Rist     sal_uInt8 nParamCount = GetByte();
52331b1b70fbSAndrew Rist     sal_uInt8 nQueryCount = nParamCount / 2;
52341b1b70fbSAndrew Rist 
52351b1b70fbSAndrew Rist     bool bCheck;
52361b1b70fbSAndrew Rist     if ( eFunc == ifCOUNTIFS )
52371b1b70fbSAndrew Rist         bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
52381b1b70fbSAndrew Rist     else
52391b1b70fbSAndrew Rist         bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
52401b1b70fbSAndrew Rist 
52411b1b70fbSAndrew Rist     if ( !bCheck )
52421b1b70fbSAndrew Rist     {
52431b1b70fbSAndrew Rist         SetError( errParameterExpected);
52441b1b70fbSAndrew Rist     }
52451b1b70fbSAndrew Rist     else
52461b1b70fbSAndrew Rist     {
52471b1b70fbSAndrew Rist         ScMatrixRef pResMat;
52481b1b70fbSAndrew Rist         double fVal = 0.0;
52491b1b70fbSAndrew Rist         double fSum = 0.0;
52501b1b70fbSAndrew Rist         double fMem = 0.0;
52511b1b70fbSAndrew Rist         double fRes = 0.0;
52521b1b70fbSAndrew Rist         double fCount = 0.0;
52531b1b70fbSAndrew Rist         short nParam = 1;
52541b1b70fbSAndrew Rist         size_t nRefInList = 0;
52556e86bbc1SAndrew Rist         SCCOL nDimensionCols = 0;
52566e86bbc1SAndrew Rist         SCROW nDimensionRows = 0;
52571b1b70fbSAndrew Rist 
52581b1b70fbSAndrew Rist         while (nParamCount > 1 && !nGlobalError)
52591b1b70fbSAndrew Rist         {
52601b1b70fbSAndrew Rist             // take criteria
52611b1b70fbSAndrew Rist             String rString;
52621b1b70fbSAndrew Rist             fVal = 0.0;
52631b1b70fbSAndrew Rist             bool bIsString = true;
52641b1b70fbSAndrew Rist             switch ( GetStackType() )
52651b1b70fbSAndrew Rist             {
52661b1b70fbSAndrew Rist                 case svDoubleRef :
52671b1b70fbSAndrew Rist                 case svSingleRef :
52681b1b70fbSAndrew Rist                     {
52691b1b70fbSAndrew Rist                         ScAddress aAdr;
52701b1b70fbSAndrew Rist                         if ( !PopDoubleRefOrSingleRef( aAdr ) )
52711b1b70fbSAndrew Rist                             return 0;
52721b1b70fbSAndrew Rist 
52731b1b70fbSAndrew Rist                         ScBaseCell* pCell = GetCell( aAdr );
52741b1b70fbSAndrew Rist                         switch ( GetCellType( pCell ) )
52751b1b70fbSAndrew Rist                         {
52761b1b70fbSAndrew Rist                             case CELLTYPE_VALUE :
52771b1b70fbSAndrew Rist                                 fVal = GetCellValue( aAdr, pCell );
52781b1b70fbSAndrew Rist                                 bIsString = false;
52791b1b70fbSAndrew Rist                                 break;
52801b1b70fbSAndrew Rist                             case CELLTYPE_FORMULA :
52811b1b70fbSAndrew Rist                                 if( ((ScFormulaCell*)pCell)->IsValue() )
52821b1b70fbSAndrew Rist                                 {
52831b1b70fbSAndrew Rist                                     fVal = GetCellValue( aAdr, pCell );
52841b1b70fbSAndrew Rist                                     bIsString = false;
52851b1b70fbSAndrew Rist                                 }
52861b1b70fbSAndrew Rist                                 else
52871b1b70fbSAndrew Rist                                     GetCellString(rString, pCell);
52881b1b70fbSAndrew Rist                                 break;
52891b1b70fbSAndrew Rist                             case CELLTYPE_STRING :
52901b1b70fbSAndrew Rist                             case CELLTYPE_EDIT :
52911b1b70fbSAndrew Rist                                 GetCellString(rString, pCell);
52921b1b70fbSAndrew Rist                                 break;
52931b1b70fbSAndrew Rist                             default:
52941b1b70fbSAndrew Rist                                 fVal = 0.0;
52951b1b70fbSAndrew Rist                                 bIsString = false;
52961b1b70fbSAndrew Rist                         }
52971b1b70fbSAndrew Rist                     }
52981b1b70fbSAndrew Rist                     break;
52991b1b70fbSAndrew Rist                 case svString:
53001b1b70fbSAndrew Rist                     rString = GetString();
53011b1b70fbSAndrew Rist                     break;
53021b1b70fbSAndrew Rist                 case svMatrix :
53031b1b70fbSAndrew Rist                     {
53041b1b70fbSAndrew Rist                         ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
53051b1b70fbSAndrew Rist                         bIsString = ScMatrix::IsNonValueType( nType);
53061b1b70fbSAndrew Rist                     }
53071b1b70fbSAndrew Rist                     break;
53081b1b70fbSAndrew Rist                 default:
53091b1b70fbSAndrew Rist                     {
53101b1b70fbSAndrew Rist                         fVal = GetDouble();
53111b1b70fbSAndrew Rist                         bIsString = false;
53121b1b70fbSAndrew Rist                     }
53131b1b70fbSAndrew Rist             }
53141b1b70fbSAndrew Rist 
53156e86bbc1SAndrew Rist             if (nGlobalError)
53166e86bbc1SAndrew Rist                 continue;   // and bail out, no need to evaluate other arguments
53176e86bbc1SAndrew Rist 
53181b1b70fbSAndrew Rist             // take range
53191b1b70fbSAndrew Rist             nParam = 1;
53201b1b70fbSAndrew Rist             nRefInList = 0;
532151df7705SAndrew Rist             SCCOL nCol1 = 0;
532251df7705SAndrew Rist             SCROW nRow1 = 0;
532351df7705SAndrew Rist             SCTAB nTab1 = 0;
532451df7705SAndrew Rist             SCCOL nCol2 = 0;
532551df7705SAndrew Rist             SCROW nRow2 = 0;
532651df7705SAndrew Rist             SCTAB nTab2 = 0;
53271b1b70fbSAndrew Rist             ScMatrixRef pQueryMatrix;
53281b1b70fbSAndrew Rist             switch ( GetStackType() )
53291b1b70fbSAndrew Rist             {
53301b1b70fbSAndrew Rist                 case svRefList :
53311b1b70fbSAndrew Rist                     {
53321b1b70fbSAndrew Rist                         ScRange aRange;
53331b1b70fbSAndrew Rist                         PopDoubleRef( aRange, nParam, nRefInList);
53341b1b70fbSAndrew Rist                         aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
53351b1b70fbSAndrew Rist                     }
53361b1b70fbSAndrew Rist                     break;
53371b1b70fbSAndrew Rist                 case svDoubleRef :
53381b1b70fbSAndrew Rist                     PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
53391b1b70fbSAndrew Rist                     break;
53401b1b70fbSAndrew Rist                 case svSingleRef :
53411b1b70fbSAndrew Rist                     PopSingleRef( nCol1, nRow1, nTab1 );
53421b1b70fbSAndrew Rist                     nCol2 = nCol1;
53431b1b70fbSAndrew Rist                     nRow2 = nRow1;
53441b1b70fbSAndrew Rist                     nTab2 = nTab1;
53451b1b70fbSAndrew Rist                     break;
53461b1b70fbSAndrew Rist                 case svMatrix:
53471b1b70fbSAndrew Rist                     {
53481b1b70fbSAndrew Rist                         pQueryMatrix = PopMatrix();
53491b1b70fbSAndrew Rist                         if (!pQueryMatrix)
53501b1b70fbSAndrew Rist                         {
53511b1b70fbSAndrew Rist                             SetError( errIllegalParameter);
53521b1b70fbSAndrew Rist                         }
53531b1b70fbSAndrew Rist                         nCol1 = 0;
53541b1b70fbSAndrew Rist                         nRow1 = 0;
53551b1b70fbSAndrew Rist                         nTab1 = 0;
53561b1b70fbSAndrew Rist                         SCSIZE nC, nR;
53571b1b70fbSAndrew Rist                         pQueryMatrix->GetDimensions( nC, nR);
53581b1b70fbSAndrew Rist                         nCol2 = static_cast<SCCOL>(nC - 1);
53591b1b70fbSAndrew Rist                         nRow2 = static_cast<SCROW>(nR - 1);
53601b1b70fbSAndrew Rist                         nTab2 = 0;
53611b1b70fbSAndrew Rist                     }
53621b1b70fbSAndrew Rist                     break;
53631b1b70fbSAndrew Rist                 default:
53641b1b70fbSAndrew Rist                     SetError( errIllegalParameter);
53651b1b70fbSAndrew Rist             }
53661b1b70fbSAndrew Rist             if ( nTab1 != nTab2 )
53676e86bbc1SAndrew Rist                 SetError( errIllegalArgument);
53686e86bbc1SAndrew Rist 
53696e86bbc1SAndrew Rist             // All reference ranges must be of same dimension and size.
53706e86bbc1SAndrew Rist             if (!nDimensionCols)
53716e86bbc1SAndrew Rist                 nDimensionCols = nCol2 - nCol1 + 1;
53726e86bbc1SAndrew Rist             if (!nDimensionRows)
53736e86bbc1SAndrew Rist                 nDimensionRows = nRow2 - nRow1 + 1;
53746e86bbc1SAndrew Rist             if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
53756e86bbc1SAndrew Rist                 SetError ( errIllegalArgument);
53766e86bbc1SAndrew Rist 
53776e86bbc1SAndrew Rist             // recalculate matrix values
53786e86bbc1SAndrew Rist             if (nGlobalError == 0)
53791b1b70fbSAndrew Rist             {
53801b1b70fbSAndrew Rist                 // initialize temporary result matrix
53811b1b70fbSAndrew Rist                 if (!pResMat)
53821b1b70fbSAndrew Rist                 {
53831b1b70fbSAndrew Rist                     SCSIZE nResC, nResR;
53841b1b70fbSAndrew Rist                     nResC = nCol2 - nCol1 + 1;
53851b1b70fbSAndrew Rist                     nResR = nRow2 - nRow1 + 1;
53861b1b70fbSAndrew Rist                     pResMat = GetNewMat(nResC, nResR);
53871b1b70fbSAndrew Rist                     if (!pResMat)
53881b1b70fbSAndrew Rist                         SetError( errIllegalParameter);
53891b1b70fbSAndrew Rist                     else
53901b1b70fbSAndrew Rist                         pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
53911b1b70fbSAndrew Rist                 }
53926e86bbc1SAndrew Rist 
53931b1b70fbSAndrew Rist                 ScQueryParam rParam;
53941b1b70fbSAndrew Rist                 rParam.nRow1       = nRow1;
53951b1b70fbSAndrew Rist                 rParam.nRow2       = nRow2;
53961b1b70fbSAndrew Rist 
53971b1b70fbSAndrew Rist                 ScQueryEntry& rEntry = rParam.GetEntry(0);
53981b1b70fbSAndrew Rist                 rEntry.bDoQuery = true;
53991b1b70fbSAndrew Rist                 if (!bIsString)
54001b1b70fbSAndrew Rist                 {
54011b1b70fbSAndrew Rist                     rEntry.bQueryByString = false;
54021b1b70fbSAndrew Rist                     rEntry.nVal = fVal;
54031b1b70fbSAndrew Rist                     rEntry.eOp = SC_EQUAL;
54041b1b70fbSAndrew Rist                 }
54051b1b70fbSAndrew Rist                 else
54061b1b70fbSAndrew Rist                 {
54071b1b70fbSAndrew Rist                     rParam.FillInExcelSyntax(rString, 0);
54081b1b70fbSAndrew Rist                     sal_uInt32 nIndex = 0;
54091b1b70fbSAndrew Rist                     rEntry.bQueryByString =
54101b1b70fbSAndrew Rist                         !(pFormatter->IsNumberFormat(
54111b1b70fbSAndrew Rist                                     *rEntry.pStr, nIndex, rEntry.nVal));
54121b1b70fbSAndrew Rist                     if ( rEntry.bQueryByString )
54131b1b70fbSAndrew Rist                         rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
54141b1b70fbSAndrew Rist                 }
54151b1b70fbSAndrew Rist                 ScAddress aAdr;
54161b1b70fbSAndrew Rist                 aAdr.SetTab( nTab1 );
54171b1b70fbSAndrew Rist                 rParam.nCol1  = nCol1;
54181b1b70fbSAndrew Rist                 rParam.nCol2  = nCol2;
54191b1b70fbSAndrew Rist                 rEntry.nField = nCol1;
54201b1b70fbSAndrew Rist                 SCsCOL nColDiff = -nCol1;
54211b1b70fbSAndrew Rist                 SCsROW nRowDiff = -nRow1;
54221b1b70fbSAndrew Rist                 if (pQueryMatrix)
54231b1b70fbSAndrew Rist                 {
54241b1b70fbSAndrew Rist                     // Never case-sensitive.
54251b1b70fbSAndrew Rist                     ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
54261b1b70fbSAndrew Rist                     ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
54271b1b70fbSAndrew Rist                     if (nGlobalError || !pResultMatrix)
54281b1b70fbSAndrew Rist                     {
54291b1b70fbSAndrew Rist                         SetError( errIllegalParameter);
54301b1b70fbSAndrew Rist                     }
54311b1b70fbSAndrew Rist 
54321b1b70fbSAndrew Rist                     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
54331b1b70fbSAndrew Rist                     {
54341b1b70fbSAndrew Rist                         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
54351b1b70fbSAndrew Rist                         {
54361b1b70fbSAndrew Rist                             if (pResultMatrix->IsValue( nCol, nRow) &&
54371b1b70fbSAndrew Rist                                     pResultMatrix->GetDouble( nCol, nRow))
54381b1b70fbSAndrew Rist                             {
54391b1b70fbSAndrew Rist                                 SCSIZE nC = nCol + nColDiff;
54401b1b70fbSAndrew Rist                                 SCSIZE nR = nRow + nRowDiff;
54411b1b70fbSAndrew Rist                                 pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
54421b1b70fbSAndrew Rist                             }
54431b1b70fbSAndrew Rist                         }
54441b1b70fbSAndrew Rist                     }
54451b1b70fbSAndrew Rist                 }
54461b1b70fbSAndrew Rist                 else
54471b1b70fbSAndrew Rist                 {
54481b1b70fbSAndrew Rist                     ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
54491b1b70fbSAndrew Rist                     // Increment Entry.nField in iterator when switching to next column.
54501b1b70fbSAndrew Rist                     aCellIter.SetAdvanceQueryParamEntryField( true );
54511b1b70fbSAndrew Rist                     if ( aCellIter.GetFirst() )
54521b1b70fbSAndrew Rist                     {
54531b1b70fbSAndrew Rist                         do
54541b1b70fbSAndrew Rist                         {
54551b1b70fbSAndrew Rist                             SCSIZE nC = aCellIter.GetCol() + nColDiff;
54561b1b70fbSAndrew Rist                             SCSIZE nR = aCellIter.GetRow() + nRowDiff;
54571b1b70fbSAndrew Rist                             pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
54581b1b70fbSAndrew Rist                         } while ( aCellIter.GetNext() );
54591b1b70fbSAndrew Rist                     }
54601b1b70fbSAndrew Rist                 }
54611b1b70fbSAndrew Rist             }
54621b1b70fbSAndrew Rist             nParamCount -= 2;
54631b1b70fbSAndrew Rist         }
54641b1b70fbSAndrew Rist 
54656e86bbc1SAndrew Rist         if (nGlobalError)
54666e86bbc1SAndrew Rist             return 0;   // bail out
54676e86bbc1SAndrew Rist 
54681b1b70fbSAndrew Rist         // main range - only for AVERAGEIFS and SUMIFS
54691b1b70fbSAndrew Rist         if (nParamCount == 1)
54701b1b70fbSAndrew Rist         {
54711b1b70fbSAndrew Rist             nParam = 1;
54721b1b70fbSAndrew Rist             nRefInList = 0;
54731b1b70fbSAndrew Rist             bool bNull = true;
547451df7705SAndrew Rist             SCCOL nMainCol1 = 0;
547551df7705SAndrew Rist             SCROW nMainRow1 = 0;
547651df7705SAndrew Rist             SCTAB nMainTab1 = 0;
547751df7705SAndrew Rist             SCCOL nMainCol2 = 0;
547851df7705SAndrew Rist             SCROW nMainRow2 = 0;
547951df7705SAndrew Rist             SCTAB nMainTab2 = 0;
54801b1b70fbSAndrew Rist             ScMatrixRef pMainMatrix;
54811b1b70fbSAndrew Rist             switch ( GetStackType() )
54821b1b70fbSAndrew Rist             {
54831b1b70fbSAndrew Rist                 case svRefList :
54841b1b70fbSAndrew Rist                     {
54851b1b70fbSAndrew Rist                         ScRange aRange;
54861b1b70fbSAndrew Rist                         PopDoubleRef( aRange, nParam, nRefInList);
54871b1b70fbSAndrew Rist                         aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
54881b1b70fbSAndrew Rist                     }
54891b1b70fbSAndrew Rist                     break;
54901b1b70fbSAndrew Rist                 case svDoubleRef :
54911b1b70fbSAndrew Rist                     PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
54921b1b70fbSAndrew Rist                     break;
54931b1b70fbSAndrew Rist                 case svSingleRef :
54941b1b70fbSAndrew Rist                     PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
54951b1b70fbSAndrew Rist                     nMainCol2 = nMainCol1;
54961b1b70fbSAndrew Rist                     nMainRow2 = nMainRow1;
54971b1b70fbSAndrew Rist                     nMainTab2 = nMainTab1;
54981b1b70fbSAndrew Rist                     break;
54991b1b70fbSAndrew Rist                 case svMatrix:
55001b1b70fbSAndrew Rist                     {
55011b1b70fbSAndrew Rist                         pMainMatrix = PopMatrix();
55021b1b70fbSAndrew Rist                         if (!pMainMatrix)
55031b1b70fbSAndrew Rist                         {
55041b1b70fbSAndrew Rist                             SetError( errIllegalParameter);
55051b1b70fbSAndrew Rist                         }
55061b1b70fbSAndrew Rist                         nMainCol1 = 0;
55071b1b70fbSAndrew Rist                         nMainRow1 = 0;
55081b1b70fbSAndrew Rist                         nMainTab1 = 0;
55091b1b70fbSAndrew Rist                         SCSIZE nC, nR;
55101b1b70fbSAndrew Rist                         pMainMatrix->GetDimensions( nC, nR);
55111b1b70fbSAndrew Rist                         nMainCol2 = static_cast<SCCOL>(nC - 1);
55121b1b70fbSAndrew Rist                         nMainRow2 = static_cast<SCROW>(nR - 1);
55131b1b70fbSAndrew Rist                         nMainTab2 = 0;
55141b1b70fbSAndrew Rist                     }
55151b1b70fbSAndrew Rist                     break;
55161b1b70fbSAndrew Rist                 default:
55171b1b70fbSAndrew Rist                     SetError( errIllegalParameter);
55181b1b70fbSAndrew Rist             }
55191b1b70fbSAndrew Rist             if ( nMainTab1 != nMainTab2 )
55206e86bbc1SAndrew Rist                 SetError( errIllegalArgument);
55216e86bbc1SAndrew Rist 
55226e86bbc1SAndrew Rist             // All reference ranges must be of same dimension and size.
55236e86bbc1SAndrew Rist             if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
55246e86bbc1SAndrew Rist                 SetError ( errIllegalArgument);
55256e86bbc1SAndrew Rist 
55266e86bbc1SAndrew Rist             if (nGlobalError)
55276e86bbc1SAndrew Rist                 return 0;   // bail out
55286e86bbc1SAndrew Rist 
55291b1b70fbSAndrew Rist             // end-result calculation
55301b1b70fbSAndrew Rist             ScAddress aAdr;
55311b1b70fbSAndrew Rist             aAdr.SetTab( nMainTab1 );
55321b1b70fbSAndrew Rist             if (pMainMatrix)
55331b1b70fbSAndrew Rist             {
55341b1b70fbSAndrew Rist                 SCSIZE nC, nR;
55351b1b70fbSAndrew Rist                 pResMat->GetDimensions(nC, nR);
55361b1b70fbSAndrew Rist                 for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55371b1b70fbSAndrew Rist                 {
55381b1b70fbSAndrew Rist                     for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55391b1b70fbSAndrew Rist                     {
55401b1b70fbSAndrew Rist                         if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55411b1b70fbSAndrew Rist                         {
55421b1b70fbSAndrew Rist                             if (pMainMatrix->IsValue( nCol, nRow))
55431b1b70fbSAndrew Rist                             {
55441b1b70fbSAndrew Rist                                 fVal = pMainMatrix->GetDouble( nCol, nRow);
55451b1b70fbSAndrew Rist                                 ++fCount;
55461b1b70fbSAndrew Rist                                 if ( bNull && fVal != 0.0 )
55471b1b70fbSAndrew Rist                                 {
55481b1b70fbSAndrew Rist                                     bNull = false;
55491b1b70fbSAndrew Rist                                     fMem = fVal;
55501b1b70fbSAndrew Rist                                 }
55511b1b70fbSAndrew Rist                                 else
55521b1b70fbSAndrew Rist                                     fSum += fVal;
55531b1b70fbSAndrew Rist                             }
55541b1b70fbSAndrew Rist                         }
55551b1b70fbSAndrew Rist                     }
55561b1b70fbSAndrew Rist                 }
55571b1b70fbSAndrew Rist             }
55581b1b70fbSAndrew Rist             else
55591b1b70fbSAndrew Rist             {
55601b1b70fbSAndrew Rist                 SCSIZE nC, nR;
55611b1b70fbSAndrew Rist                 pResMat->GetDimensions(nC, nR);
55621b1b70fbSAndrew Rist                 for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55631b1b70fbSAndrew Rist                 {
55641b1b70fbSAndrew Rist                     for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55651b1b70fbSAndrew Rist                     {
55661b1b70fbSAndrew Rist                         if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55671b1b70fbSAndrew Rist                         {
556841f10097SAndrew Rist                             aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
556941f10097SAndrew Rist                             aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
55701b1b70fbSAndrew Rist                             ScBaseCell* pCell = GetCell( aAdr );
55711b1b70fbSAndrew Rist                             if ( HasCellValueData(pCell) )
55721b1b70fbSAndrew Rist                             {
55731b1b70fbSAndrew Rist                                 fVal = GetCellValue( aAdr, pCell );
55741b1b70fbSAndrew Rist                                 ++fCount;
55751b1b70fbSAndrew Rist                                 if ( bNull && fVal != 0.0 )
55761b1b70fbSAndrew Rist                                 {
55771b1b70fbSAndrew Rist                                     bNull = false;
55781b1b70fbSAndrew Rist                                     fMem = fVal;
55791b1b70fbSAndrew Rist                                 }
55801b1b70fbSAndrew Rist                                 else
55811b1b70fbSAndrew Rist                                     fSum += fVal;
55821b1b70fbSAndrew Rist                             }
55831b1b70fbSAndrew Rist                         }
55841b1b70fbSAndrew Rist                     }
55851b1b70fbSAndrew Rist                 }
55861b1b70fbSAndrew Rist             }
55871b1b70fbSAndrew Rist         }
55881b1b70fbSAndrew Rist         else
55891b1b70fbSAndrew Rist         {
55901b1b70fbSAndrew Rist             SCSIZE nC, nR;
55911b1b70fbSAndrew Rist             pResMat->GetDimensions(nC, nR);
55921b1b70fbSAndrew Rist             for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55931b1b70fbSAndrew Rist             {
55941b1b70fbSAndrew Rist                 for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55951b1b70fbSAndrew Rist                     if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55961b1b70fbSAndrew Rist                         ++fCount;
55971b1b70fbSAndrew Rist             }
55981b1b70fbSAndrew Rist         }
55996e86bbc1SAndrew Rist 
56001b1b70fbSAndrew Rist         switch( eFunc )
56011b1b70fbSAndrew Rist         {
56021b1b70fbSAndrew Rist             case ifSUMIFS:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
56031b1b70fbSAndrew Rist             case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
56041b1b70fbSAndrew Rist             case ifCOUNTIFS:   fRes = fCount; break;
56051b1b70fbSAndrew Rist             default: ; // nothing
56061b1b70fbSAndrew Rist         }
56071b1b70fbSAndrew Rist         return fRes;
56081b1b70fbSAndrew Rist     }
56091b1b70fbSAndrew Rist     return 0;
56101b1b70fbSAndrew Rist }
56111b1b70fbSAndrew Rist 
ScSumIfs()56121b1b70fbSAndrew Rist void ScInterpreter::ScSumIfs()
56131b1b70fbSAndrew Rist {
56141b1b70fbSAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScSumIfs" );
56151b1b70fbSAndrew Rist     PushDouble( IterateParametersIfs( ifSUMIFS));
56161b1b70fbSAndrew Rist }
56171b1b70fbSAndrew Rist 
ScAverageIfs()56181b1b70fbSAndrew Rist void ScInterpreter::ScAverageIfs()
56191b1b70fbSAndrew Rist {
56201b1b70fbSAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIfs" );
56211b1b70fbSAndrew Rist     PushDouble( IterateParametersIfs( ifAVERAGEIFS));
56221b1b70fbSAndrew Rist }
56231b1b70fbSAndrew Rist 
ScCountIfs()56241b1b70fbSAndrew Rist void ScInterpreter::ScCountIfs()
56251b1b70fbSAndrew Rist {
56261b1b70fbSAndrew Rist     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScCountIfs" );
56271b1b70fbSAndrew Rist     PushDouble( IterateParametersIfs( ifCOUNTIFS));
56281b1b70fbSAndrew Rist }
5629cdf0e10cSrcweir 
ScLookup()5630cdf0e10cSrcweir void ScInterpreter::ScLookup()
5631cdf0e10cSrcweir {
5632cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLookup" );
5633cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
5634cdf0e10cSrcweir     if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
5635cdf0e10cSrcweir         return ;
5636cdf0e10cSrcweir 
5637cdf0e10cSrcweir     ScMatrixRef pDataMat = NULL, pResMat = NULL;
5638cdf0e10cSrcweir     SCCOL nCol1 = 0, nCol2 = 0, nResCol1 = 0, nResCol2 = 0;
5639cdf0e10cSrcweir     SCROW nRow1 = 0, nRow2 = 0, nResRow1 = 0, nResRow2 = 0;
5640cdf0e10cSrcweir     SCTAB nTab1 = 0, nResTab = 0;
5641cdf0e10cSrcweir     SCSIZE nLenMajor = 0;   // length of major direction
5642cdf0e10cSrcweir     bool bVertical = true;  // whether to lookup vertically or horizontally
5643cdf0e10cSrcweir 
5644cdf0e10cSrcweir     // The third parameter, result array, for double, string and single reference.
5645cdf0e10cSrcweir     double fResVal = 0.0;
5646cdf0e10cSrcweir     String aResStr;
5647cdf0e10cSrcweir     ScAddress aResAdr;
5648cdf0e10cSrcweir     StackVar eResArrayType = svUnknown;
5649cdf0e10cSrcweir 
5650cdf0e10cSrcweir     if (nParamCount == 3)
5651cdf0e10cSrcweir     {
5652cdf0e10cSrcweir         eResArrayType = GetStackType();
5653cdf0e10cSrcweir         switch (eResArrayType)
5654cdf0e10cSrcweir         {
5655cdf0e10cSrcweir             case svDoubleRef:
5656cdf0e10cSrcweir             {
5657cdf0e10cSrcweir                 SCTAB nTabJunk;
5658cdf0e10cSrcweir                 PopDoubleRef(nResCol1, nResRow1, nResTab,
5659cdf0e10cSrcweir                              nResCol2, nResRow2, nTabJunk);
5660cdf0e10cSrcweir                 if (nResTab != nTabJunk ||
5661cdf0e10cSrcweir                     ((nResRow2 - nResRow1) > 0 && (nResCol2 - nResCol1) > 0))
5662cdf0e10cSrcweir                 {
5663cdf0e10cSrcweir                     // The result array must be a vector.
5664cdf0e10cSrcweir                     PushIllegalParameter();
5665cdf0e10cSrcweir                     return;
5666cdf0e10cSrcweir                 }
5667cdf0e10cSrcweir             }
5668cdf0e10cSrcweir             break;
5669cdf0e10cSrcweir             case svMatrix:
5670cdf0e10cSrcweir             {
5671cdf0e10cSrcweir                 pResMat = PopMatrix();
5672cdf0e10cSrcweir                 if (!pResMat)
5673cdf0e10cSrcweir                 {
5674cdf0e10cSrcweir                     PushIllegalParameter();
5675cdf0e10cSrcweir                     return;
5676cdf0e10cSrcweir                 }
5677cdf0e10cSrcweir                 SCSIZE nC, nR;
5678cdf0e10cSrcweir                 pResMat->GetDimensions(nC, nR);
5679cdf0e10cSrcweir                 if (nC != 1 && nR != 1)
5680cdf0e10cSrcweir                 {
5681cdf0e10cSrcweir                     // Result matrix must be a vector.
5682cdf0e10cSrcweir                     PushIllegalParameter();
5683cdf0e10cSrcweir                     return;
5684cdf0e10cSrcweir                 }
5685cdf0e10cSrcweir             }
5686cdf0e10cSrcweir             break;
5687cdf0e10cSrcweir             case svDouble:
5688cdf0e10cSrcweir                 fResVal = GetDouble();
5689cdf0e10cSrcweir             break;
5690cdf0e10cSrcweir             case svString:
5691cdf0e10cSrcweir                 aResStr = GetString();
5692cdf0e10cSrcweir             break;
5693cdf0e10cSrcweir             case svSingleRef:
5694cdf0e10cSrcweir                 PopSingleRef( aResAdr );
5695cdf0e10cSrcweir             break;
5696cdf0e10cSrcweir             default:
5697cdf0e10cSrcweir                 PushIllegalParameter();
5698cdf0e10cSrcweir                 return;
5699cdf0e10cSrcweir         }
5700cdf0e10cSrcweir     }
5701cdf0e10cSrcweir 
5702cdf0e10cSrcweir     // For double, string and single reference.
5703cdf0e10cSrcweir     double fDataVal = 0.0;
5704cdf0e10cSrcweir     String aDataStr;
5705cdf0e10cSrcweir     ScAddress aDataAdr;
5706cdf0e10cSrcweir     bool bValueData = false;
5707cdf0e10cSrcweir 
5708cdf0e10cSrcweir     // Get the data-result range and also determine whether this is vertical
5709cdf0e10cSrcweir     // lookup or horizontal lookup.
5710cdf0e10cSrcweir 
5711cdf0e10cSrcweir     StackVar eDataArrayType = GetStackType();
5712cdf0e10cSrcweir     switch (eDataArrayType)
5713cdf0e10cSrcweir     {
5714cdf0e10cSrcweir         case svDoubleRef:
5715cdf0e10cSrcweir         {
5716cdf0e10cSrcweir             SCTAB nTabJunk;
5717cdf0e10cSrcweir             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTabJunk);
5718cdf0e10cSrcweir             if (nTab1 != nTabJunk)
5719cdf0e10cSrcweir             {
5720cdf0e10cSrcweir                 PushIllegalParameter();
5721cdf0e10cSrcweir                 return;
5722cdf0e10cSrcweir             }
5723cdf0e10cSrcweir             bVertical = (nRow2 - nRow1) >= (nCol2 - nCol1);
5724cdf0e10cSrcweir             nLenMajor = bVertical ? nRow2 - nRow1 + 1 : nCol2 - nCol1 + 1;
5725cdf0e10cSrcweir         }
5726cdf0e10cSrcweir         break;
5727cdf0e10cSrcweir         case svMatrix:
5728cdf0e10cSrcweir         {
5729cdf0e10cSrcweir             pDataMat = PopMatrix();
5730cdf0e10cSrcweir             if (!pDataMat)
5731cdf0e10cSrcweir             {
5732cdf0e10cSrcweir                 PushIllegalParameter();
5733cdf0e10cSrcweir                 return;
5734cdf0e10cSrcweir             }
5735cdf0e10cSrcweir 
5736cdf0e10cSrcweir             SCSIZE nC, nR;
5737cdf0e10cSrcweir             pDataMat->GetDimensions(nC, nR);
5738cdf0e10cSrcweir             bVertical = (nR >= nC);
5739cdf0e10cSrcweir             nLenMajor = bVertical ? nR : nC;
5740cdf0e10cSrcweir         }
5741cdf0e10cSrcweir         break;
5742cdf0e10cSrcweir         case svDouble:
5743cdf0e10cSrcweir         {
5744cdf0e10cSrcweir             fDataVal = GetDouble();
5745cdf0e10cSrcweir             bValueData = true;
5746cdf0e10cSrcweir         }
5747cdf0e10cSrcweir         break;
5748cdf0e10cSrcweir         case svString:
5749cdf0e10cSrcweir         {
5750cdf0e10cSrcweir             aDataStr = GetString();
5751cdf0e10cSrcweir         }
5752cdf0e10cSrcweir         break;
5753cdf0e10cSrcweir         case svSingleRef:
5754cdf0e10cSrcweir         {
5755cdf0e10cSrcweir             PopSingleRef( aDataAdr );
5756cdf0e10cSrcweir             const ScBaseCell* pDataCell = GetCell( aDataAdr );
5757cdf0e10cSrcweir             if (HasCellEmptyData( pDataCell))
5758cdf0e10cSrcweir             {
5759cdf0e10cSrcweir                 // Empty cells aren't found anywhere, bail out early.
5760cdf0e10cSrcweir                 SetError( NOTAVAILABLE);
5761cdf0e10cSrcweir             }
5762cdf0e10cSrcweir             else if (HasCellValueData( pDataCell))
5763cdf0e10cSrcweir             {
5764cdf0e10cSrcweir                 fDataVal = GetCellValue( aDataAdr, pDataCell );
5765cdf0e10cSrcweir                 bValueData = true;
5766cdf0e10cSrcweir             }
5767cdf0e10cSrcweir             else
5768cdf0e10cSrcweir                 GetCellString( aDataStr, pDataCell );
5769cdf0e10cSrcweir         }
5770cdf0e10cSrcweir         break;
5771cdf0e10cSrcweir         default:
5772cdf0e10cSrcweir             SetError( errIllegalParameter);
5773cdf0e10cSrcweir     }
5774cdf0e10cSrcweir 
5775cdf0e10cSrcweir 
5776cdf0e10cSrcweir     if (nGlobalError)
5777cdf0e10cSrcweir     {
5778cdf0e10cSrcweir         PushError( nGlobalError);
5779cdf0e10cSrcweir         return;
5780cdf0e10cSrcweir     }
5781cdf0e10cSrcweir 
5782cdf0e10cSrcweir     // Get the lookup value.
5783cdf0e10cSrcweir 
5784cdf0e10cSrcweir     ScQueryParam aParam;
5785cdf0e10cSrcweir     ScQueryEntry& rEntry = aParam.GetEntry(0);
5786cdf0e10cSrcweir     if ( !FillEntry(rEntry) )
5787cdf0e10cSrcweir         return;
5788cdf0e10cSrcweir 
5789cdf0e10cSrcweir     if ( eDataArrayType == svDouble || eDataArrayType == svString ||
5790cdf0e10cSrcweir             eDataArrayType == svSingleRef )
5791cdf0e10cSrcweir     {
5792cdf0e10cSrcweir         // Delta position for a single value is always 0.
5793cdf0e10cSrcweir 
5794cdf0e10cSrcweir         // Found if data <= query, but not if query is string and found data is
5795cdf0e10cSrcweir         // numeric or vice versa. This is how Excel does it but doesn't
5796cdf0e10cSrcweir         // document it.
5797cdf0e10cSrcweir 
5798cdf0e10cSrcweir         bool bFound = false;
5799cdf0e10cSrcweir         if ( bValueData )
5800cdf0e10cSrcweir         {
5801cdf0e10cSrcweir             if ( rEntry.bQueryByString )
5802cdf0e10cSrcweir                 bFound = false;
5803cdf0e10cSrcweir             else
5804cdf0e10cSrcweir                 bFound = (fDataVal <= rEntry.nVal);
5805cdf0e10cSrcweir         }
5806cdf0e10cSrcweir         else
5807cdf0e10cSrcweir         {
5808cdf0e10cSrcweir             if ( !rEntry.bQueryByString )
5809cdf0e10cSrcweir                 bFound = false;
5810cdf0e10cSrcweir             else
5811cdf0e10cSrcweir                 bFound = (ScGlobal::GetCollator()->compareString( aDataStr, *rEntry.pStr) <= 0);
5812cdf0e10cSrcweir         }
5813cdf0e10cSrcweir 
5814cdf0e10cSrcweir         if (!bFound)
5815cdf0e10cSrcweir         {
5816cdf0e10cSrcweir             PushNA();
5817cdf0e10cSrcweir             return;
5818cdf0e10cSrcweir         }
5819cdf0e10cSrcweir 
5820cdf0e10cSrcweir         if (pResMat)
5821cdf0e10cSrcweir         {
5822cdf0e10cSrcweir             if (pResMat->IsValue( 0 ))
5823cdf0e10cSrcweir                 PushDouble(pResMat->GetDouble( 0 ));
5824cdf0e10cSrcweir             else
5825cdf0e10cSrcweir                 PushString(pResMat->GetString( 0 ));
5826cdf0e10cSrcweir         }
5827cdf0e10cSrcweir         else if (nParamCount == 3)
5828cdf0e10cSrcweir         {
5829cdf0e10cSrcweir             switch (eResArrayType)
5830cdf0e10cSrcweir             {
5831cdf0e10cSrcweir                 case svDouble:
5832cdf0e10cSrcweir                     PushDouble( fResVal );
5833cdf0e10cSrcweir                     break;
5834cdf0e10cSrcweir                 case svString:
5835cdf0e10cSrcweir                     PushString( aResStr );
5836cdf0e10cSrcweir                     break;
5837cdf0e10cSrcweir                 case svDoubleRef:
5838cdf0e10cSrcweir                     aResAdr.Set( nResCol1, nResRow1, nResTab);
5839cdf0e10cSrcweir                     // fallthru
5840cdf0e10cSrcweir                 case svSingleRef:
5841cdf0e10cSrcweir                     PushCellResultToken( true, aResAdr, NULL, NULL);
5842cdf0e10cSrcweir                     break;
5843cdf0e10cSrcweir                 default:
5844cdf0e10cSrcweir                     DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eResArrayType, single value data");
5845cdf0e10cSrcweir             }
5846cdf0e10cSrcweir         }
5847cdf0e10cSrcweir         else
5848cdf0e10cSrcweir         {
5849cdf0e10cSrcweir             switch (eDataArrayType)
5850cdf0e10cSrcweir             {
5851cdf0e10cSrcweir                 case svDouble:
5852cdf0e10cSrcweir                     PushDouble( fDataVal );
5853cdf0e10cSrcweir                     break;
5854cdf0e10cSrcweir                 case svString:
5855cdf0e10cSrcweir                     PushString( aDataStr );
5856cdf0e10cSrcweir                     break;
5857cdf0e10cSrcweir                 case svSingleRef:
5858cdf0e10cSrcweir                     PushCellResultToken( true, aDataAdr, NULL, NULL);
5859cdf0e10cSrcweir                     break;
5860cdf0e10cSrcweir                 default:
5861cdf0e10cSrcweir                     DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eDataArrayType, single value data");
5862cdf0e10cSrcweir             }
5863cdf0e10cSrcweir         }
5864cdf0e10cSrcweir         return;
5865cdf0e10cSrcweir     }
5866cdf0e10cSrcweir 
5867cdf0e10cSrcweir     // Now, perform the search to compute the delta position (nDelta).
5868cdf0e10cSrcweir 
5869cdf0e10cSrcweir     if (pDataMat)
5870cdf0e10cSrcweir     {
5871cdf0e10cSrcweir         // Data array is given as a matrix.
5872cdf0e10cSrcweir         rEntry.bDoQuery = true;
5873cdf0e10cSrcweir         rEntry.eOp = SC_LESS_EQUAL;
5874cdf0e10cSrcweir         bool bFound = false;
5875cdf0e10cSrcweir 
5876cdf0e10cSrcweir         SCSIZE nC, nR;
5877cdf0e10cSrcweir         pDataMat->GetDimensions(nC, nR);
5878cdf0e10cSrcweir 
5879cdf0e10cSrcweir         // In case of non-vector matrix, only search the first row or column.
5880cdf0e10cSrcweir         ScMatrixRef pDataMat2;
5881cdf0e10cSrcweir         if (bVertical)
5882cdf0e10cSrcweir         {
5883cdf0e10cSrcweir             ScMatrixRef pTempMat(new ScMatrix(1, nR));
5884cdf0e10cSrcweir             for (SCSIZE i = 0; i < nR; ++i)
5885cdf0e10cSrcweir                 if (pDataMat->IsValue(0, i))
5886cdf0e10cSrcweir                     pTempMat->PutDouble(pDataMat->GetDouble(0, i), 0, i);
5887cdf0e10cSrcweir                 else
5888cdf0e10cSrcweir                     pTempMat->PutString(pDataMat->GetString(0, i), 0, i);
5889cdf0e10cSrcweir             pDataMat2 = pTempMat;
5890cdf0e10cSrcweir         }
5891cdf0e10cSrcweir         else
5892cdf0e10cSrcweir         {
5893cdf0e10cSrcweir             ScMatrixRef pTempMat(new ScMatrix(nC, 1));
5894cdf0e10cSrcweir             for (SCSIZE i = 0; i < nC; ++i)
5895cdf0e10cSrcweir                 if (pDataMat->IsValue(i, 0))
5896cdf0e10cSrcweir                     pTempMat->PutDouble(pDataMat->GetDouble(i, 0), i, 0);
5897cdf0e10cSrcweir                 else
5898cdf0e10cSrcweir                     pTempMat->PutString(pDataMat->GetString(i, 0), i, 0);
5899cdf0e10cSrcweir             pDataMat2 = pTempMat;
5900cdf0e10cSrcweir         }
5901cdf0e10cSrcweir 
5902cdf0e10cSrcweir         // binary search for non-equality mode (the source data is
5903cdf0e10cSrcweir         // assumed to be sorted in ascending order).
5904cdf0e10cSrcweir 
5905cdf0e10cSrcweir         SCCOLROW nDelta = -1;
5906cdf0e10cSrcweir 
5907cdf0e10cSrcweir         SCSIZE nFirst = 0, nLast = nLenMajor-1; //, nHitIndex = 0;
5908cdf0e10cSrcweir         for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5909cdf0e10cSrcweir         {
5910cdf0e10cSrcweir             SCSIZE nMid = nFirst + nLen/2;
5911cdf0e10cSrcweir             sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, *pDataMat2, rEntry);
5912cdf0e10cSrcweir             if (nCmp == 0)
5913cdf0e10cSrcweir             {
5914cdf0e10cSrcweir                 // exact match.  find the last item with the same value.
5915cdf0e10cSrcweir                 lcl_GetLastMatch( nMid, *pDataMat2, nLenMajor, false);
5916cdf0e10cSrcweir                 nDelta = nMid;
5917cdf0e10cSrcweir                 bFound = true;
5918cdf0e10cSrcweir                 break;
5919cdf0e10cSrcweir             }
5920cdf0e10cSrcweir 
5921cdf0e10cSrcweir             if (nLen == 1) // first and last items are next to each other.
5922cdf0e10cSrcweir             {
5923cdf0e10cSrcweir                 nDelta = nCmp < 0 ? nLast - 1 : nFirst - 1;
5924cdf0e10cSrcweir                 // If already the 1st item is greater there's nothing found.
5925cdf0e10cSrcweir                 bFound = (nDelta >= 0);
5926cdf0e10cSrcweir                 break;
5927cdf0e10cSrcweir             }
5928cdf0e10cSrcweir 
5929cdf0e10cSrcweir             if (nCmp < 0)
5930cdf0e10cSrcweir                 nFirst = nMid;
5931cdf0e10cSrcweir             else
5932cdf0e10cSrcweir                 nLast = nMid;
5933cdf0e10cSrcweir         }
5934cdf0e10cSrcweir 
5935cdf0e10cSrcweir         if (nDelta == static_cast<SCCOLROW>(nLenMajor-2)) // last item
5936cdf0e10cSrcweir         {
5937cdf0e10cSrcweir             sal_Int32 nCmp = lcl_CompareMatrix2Query(nDelta+1, *pDataMat2, rEntry);
5938cdf0e10cSrcweir             if (nCmp <= 0)
5939cdf0e10cSrcweir             {
5940cdf0e10cSrcweir                 // either the last item is an exact match or the real
5941cdf0e10cSrcweir                 // hit is beyond the last item.
5942cdf0e10cSrcweir                 nDelta += 1;
5943cdf0e10cSrcweir                 bFound = true;
5944cdf0e10cSrcweir             }
5945cdf0e10cSrcweir         }
5946cdf0e10cSrcweir         else if (nDelta > 0) // valid hit must be 2nd item or higher
5947cdf0e10cSrcweir         {
5948cdf0e10cSrcweir             // non-exact match
5949cdf0e10cSrcweir             bFound = true;
5950cdf0e10cSrcweir         }
5951cdf0e10cSrcweir 
5952cdf0e10cSrcweir         // With 0-9 < A-Z, if query is numeric and data found is string, or
5953cdf0e10cSrcweir         // vice versa, the (yet another undocumented) Excel behavior is to
5954cdf0e10cSrcweir         // return #N/A instead.
5955cdf0e10cSrcweir 
5956cdf0e10cSrcweir         if (bFound)
5957cdf0e10cSrcweir         {
5958cdf0e10cSrcweir             SCCOLROW i = nDelta;
5959cdf0e10cSrcweir             SCSIZE n = pDataMat->GetElementCount();
5960cdf0e10cSrcweir             if (static_cast<SCSIZE>(i) >= n)
5961cdf0e10cSrcweir                 i = static_cast<SCCOLROW>(n);
5962cdf0e10cSrcweir             if (bool(rEntry.bQueryByString) == bool(pDataMat->IsValue(i)))
5963cdf0e10cSrcweir                 bFound = false;
5964cdf0e10cSrcweir         }
5965cdf0e10cSrcweir 
5966cdf0e10cSrcweir         if (!bFound)
5967cdf0e10cSrcweir         {
5968cdf0e10cSrcweir             PushNA();
5969cdf0e10cSrcweir             return;
5970cdf0e10cSrcweir         }
5971cdf0e10cSrcweir 
5972cdf0e10cSrcweir         // Now that we've found the delta, push the result back to the cell.
5973cdf0e10cSrcweir 
5974cdf0e10cSrcweir         if (pResMat)
5975cdf0e10cSrcweir         {
5976cdf0e10cSrcweir             // result array is matrix.
5977cdf0e10cSrcweir             if (static_cast<SCSIZE>(nDelta) >= pResMat->GetElementCount())
5978cdf0e10cSrcweir             {
5979cdf0e10cSrcweir                 PushNA();
5980cdf0e10cSrcweir                 return;
5981cdf0e10cSrcweir             }
5982cdf0e10cSrcweir             if (pResMat->IsValue(nDelta))
5983cdf0e10cSrcweir                 PushDouble(pResMat->GetDouble(nDelta));
5984cdf0e10cSrcweir             else
5985cdf0e10cSrcweir                 PushString(pResMat->GetString(nDelta));
5986cdf0e10cSrcweir         }
5987cdf0e10cSrcweir         else if (nParamCount == 3)
5988cdf0e10cSrcweir         {
5989cdf0e10cSrcweir             // result array is cell range.
5990cdf0e10cSrcweir             ScAddress aAdr;
5991cdf0e10cSrcweir             aAdr.SetTab(nResTab);
5992cdf0e10cSrcweir             bool bResVertical = (nResRow2 - nResRow1) > 0;
5993cdf0e10cSrcweir             if (bResVertical)
5994cdf0e10cSrcweir             {
5995cdf0e10cSrcweir                 SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
5996cdf0e10cSrcweir                 if (nTempRow > MAXROW)
5997cdf0e10cSrcweir                 {
5998cdf0e10cSrcweir                     PushDouble(0);
5999cdf0e10cSrcweir                     return;
6000cdf0e10cSrcweir                 }
6001cdf0e10cSrcweir                 aAdr.SetCol(nResCol1);
6002cdf0e10cSrcweir                 aAdr.SetRow(nTempRow);
6003cdf0e10cSrcweir             }
6004cdf0e10cSrcweir             else
6005cdf0e10cSrcweir             {
6006cdf0e10cSrcweir                 SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6007cdf0e10cSrcweir                 if (nTempCol > MAXCOL)
6008cdf0e10cSrcweir                 {
6009cdf0e10cSrcweir                     PushDouble(0);
6010cdf0e10cSrcweir                     return;
6011cdf0e10cSrcweir                 }
6012cdf0e10cSrcweir                 aAdr.SetCol(nTempCol);
6013cdf0e10cSrcweir                 aAdr.SetRow(nResRow1);
6014cdf0e10cSrcweir             }
6015cdf0e10cSrcweir             PushCellResultToken(true, aAdr, NULL, NULL);
6016cdf0e10cSrcweir         }
6017cdf0e10cSrcweir         else
6018cdf0e10cSrcweir         {
6019cdf0e10cSrcweir             // no result array.  Use the data array to get the final value from.
6020cdf0e10cSrcweir             if (bVertical)
6021cdf0e10cSrcweir             {
6022cdf0e10cSrcweir                 if (pDataMat->IsValue(nC-1, nDelta))
6023cdf0e10cSrcweir                     PushDouble(pDataMat->GetDouble(nC-1, nDelta));
6024cdf0e10cSrcweir                 else
6025cdf0e10cSrcweir                     PushString(pDataMat->GetString(nC-1, nDelta));
6026cdf0e10cSrcweir             }
6027cdf0e10cSrcweir             else
6028cdf0e10cSrcweir             {
6029cdf0e10cSrcweir                 if (pDataMat->IsValue(nDelta, nR-1))
6030cdf0e10cSrcweir                     PushDouble(pDataMat->GetDouble(nDelta, nR-1));
6031cdf0e10cSrcweir                 else
6032cdf0e10cSrcweir                     PushString(pDataMat->GetString(nDelta, nR-1));
6033cdf0e10cSrcweir             }
6034cdf0e10cSrcweir         }
6035cdf0e10cSrcweir 
6036cdf0e10cSrcweir         return;
6037cdf0e10cSrcweir     }
6038cdf0e10cSrcweir 
6039cdf0e10cSrcweir     // Perform cell range search.
6040cdf0e10cSrcweir 
6041cdf0e10cSrcweir     aParam.nCol1            = nCol1;
6042cdf0e10cSrcweir     aParam.nRow1            = nRow1;
6043cdf0e10cSrcweir     aParam.nCol2            = bVertical ? nCol1 : nCol2;
6044cdf0e10cSrcweir     aParam.nRow2            = bVertical ? nRow2 : nRow1;
6045cdf0e10cSrcweir     aParam.bByRow           = bVertical;
6046cdf0e10cSrcweir     aParam.bMixedComparison = true;
6047cdf0e10cSrcweir 
6048cdf0e10cSrcweir     rEntry.bDoQuery = sal_True;
6049cdf0e10cSrcweir     rEntry.eOp = SC_LESS_EQUAL;
6050cdf0e10cSrcweir     rEntry.nField = nCol1;
6051cdf0e10cSrcweir     if ( rEntry.bQueryByString )
6052cdf0e10cSrcweir         aParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6053cdf0e10cSrcweir 
6054cdf0e10cSrcweir     ScQueryCellIterator aCellIter(pDok, nTab1, aParam, sal_False);
6055cdf0e10cSrcweir     SCCOL nC;
6056cdf0e10cSrcweir     SCROW nR;
6057cdf0e10cSrcweir     // Advance Entry.nField in iterator upon switching columns if
6058cdf0e10cSrcweir     // lookup in row.
6059cdf0e10cSrcweir     aCellIter.SetAdvanceQueryParamEntryField(!bVertical);
6060cdf0e10cSrcweir     if ( !aCellIter.FindEqualOrSortedLastInRange(nC, nR) )
6061cdf0e10cSrcweir     {
6062cdf0e10cSrcweir         PushNA();
6063cdf0e10cSrcweir         return;
6064cdf0e10cSrcweir     }
6065cdf0e10cSrcweir 
6066cdf0e10cSrcweir     SCCOLROW nDelta = bVertical ? static_cast<SCSIZE>(nR-nRow1) : static_cast<SCSIZE>(nC-nCol1);
6067cdf0e10cSrcweir 
6068cdf0e10cSrcweir     if (pResMat)
6069cdf0e10cSrcweir     {
6070cdf0e10cSrcweir         // Use the matrix result array.
6071cdf0e10cSrcweir         if (pResMat->IsValue(nDelta))
6072cdf0e10cSrcweir             PushDouble(pResMat->GetDouble(nDelta));
6073cdf0e10cSrcweir         else
6074cdf0e10cSrcweir             PushString(pResMat->GetString(nDelta));
6075cdf0e10cSrcweir     }
6076cdf0e10cSrcweir     else if (nParamCount == 3)
6077cdf0e10cSrcweir     {
6078cdf0e10cSrcweir         switch (eResArrayType)
6079cdf0e10cSrcweir         {
6080cdf0e10cSrcweir             case svDoubleRef:
6081cdf0e10cSrcweir             {
6082cdf0e10cSrcweir                 // Use the result array vector.  Note that the result array is assumed
6083cdf0e10cSrcweir                 // to be a vector (i.e. 1-dimensinoal array).
6084cdf0e10cSrcweir 
6085cdf0e10cSrcweir                 ScAddress aAdr;
6086cdf0e10cSrcweir                 aAdr.SetTab(nResTab);
6087cdf0e10cSrcweir                 bool bResVertical = (nResRow2 - nResRow1) > 0;
6088cdf0e10cSrcweir                 if (bResVertical)
6089cdf0e10cSrcweir                 {
6090cdf0e10cSrcweir                     SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
6091cdf0e10cSrcweir                     if (nTempRow > MAXROW)
6092cdf0e10cSrcweir                     {
6093cdf0e10cSrcweir                         PushDouble(0);
6094cdf0e10cSrcweir                         return;
6095cdf0e10cSrcweir                     }
6096cdf0e10cSrcweir                     aAdr.SetCol(nResCol1);
6097cdf0e10cSrcweir                     aAdr.SetRow(nTempRow);
6098cdf0e10cSrcweir                 }
6099cdf0e10cSrcweir                 else
6100cdf0e10cSrcweir                 {
6101cdf0e10cSrcweir                     SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6102cdf0e10cSrcweir                     if (nTempCol > MAXCOL)
6103cdf0e10cSrcweir                     {
6104cdf0e10cSrcweir                         PushDouble(0);
6105cdf0e10cSrcweir                         return;
6106cdf0e10cSrcweir                     }
6107cdf0e10cSrcweir                     aAdr.SetCol(nTempCol);
6108cdf0e10cSrcweir                     aAdr.SetRow(nResRow1);
6109cdf0e10cSrcweir                 }
6110cdf0e10cSrcweir                 PushCellResultToken( true, aAdr, NULL, NULL);
6111cdf0e10cSrcweir             }
6112cdf0e10cSrcweir             break;
6113cdf0e10cSrcweir             case svDouble:
6114cdf0e10cSrcweir             case svString:
6115cdf0e10cSrcweir             case svSingleRef:
6116cdf0e10cSrcweir             {
6117cdf0e10cSrcweir                 if (nDelta != 0)
6118cdf0e10cSrcweir                     PushNA();
6119cdf0e10cSrcweir                 else
6120cdf0e10cSrcweir                 {
6121cdf0e10cSrcweir                     switch (eResArrayType)
6122cdf0e10cSrcweir                     {
6123cdf0e10cSrcweir                         case svDouble:
6124cdf0e10cSrcweir                             PushDouble( fResVal );
6125cdf0e10cSrcweir                             break;
6126cdf0e10cSrcweir                         case svString:
6127cdf0e10cSrcweir                             PushString( aResStr );
6128cdf0e10cSrcweir                             break;
6129cdf0e10cSrcweir                         case svSingleRef:
6130cdf0e10cSrcweir                             PushCellResultToken( true, aResAdr, NULL, NULL);
6131cdf0e10cSrcweir                             break;
6132cdf0e10cSrcweir                         default:
6133cdf0e10cSrcweir                             ;   // nothing
6134cdf0e10cSrcweir                     }
6135cdf0e10cSrcweir                 }
6136cdf0e10cSrcweir             }
6137cdf0e10cSrcweir             break;
6138cdf0e10cSrcweir             default:
6139cdf0e10cSrcweir                 DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eResArrayType, range search");
6140cdf0e10cSrcweir         }
6141cdf0e10cSrcweir     }
6142cdf0e10cSrcweir     else
6143cdf0e10cSrcweir     {
6144cdf0e10cSrcweir         // Regardless of whether or not the result array exists, the last
6145cdf0e10cSrcweir         // array is always used as the "result" array.
6146cdf0e10cSrcweir 
6147cdf0e10cSrcweir         ScAddress aAdr;
6148cdf0e10cSrcweir         aAdr.SetTab(nTab1);
6149cdf0e10cSrcweir         if (bVertical)
6150cdf0e10cSrcweir         {
6151cdf0e10cSrcweir             SCROW nTempRow = static_cast<SCROW>(nRow1 + nDelta);
6152cdf0e10cSrcweir             if (nTempRow > MAXROW)
6153cdf0e10cSrcweir             {
6154cdf0e10cSrcweir                 PushDouble(0);
6155cdf0e10cSrcweir                 return;
6156cdf0e10cSrcweir             }
6157cdf0e10cSrcweir             aAdr.SetCol(nCol2);
6158cdf0e10cSrcweir             aAdr.SetRow(nTempRow);
6159cdf0e10cSrcweir         }
6160cdf0e10cSrcweir         else
6161cdf0e10cSrcweir         {
6162cdf0e10cSrcweir             SCCOL nTempCol = static_cast<SCCOL>(nCol1 + nDelta);
6163cdf0e10cSrcweir             if (nTempCol > MAXCOL)
6164cdf0e10cSrcweir             {
6165cdf0e10cSrcweir                 PushDouble(0);
6166cdf0e10cSrcweir                 return;
6167cdf0e10cSrcweir             }
6168cdf0e10cSrcweir             aAdr.SetCol(nTempCol);
6169cdf0e10cSrcweir             aAdr.SetRow(nRow2);
6170cdf0e10cSrcweir         }
6171cdf0e10cSrcweir         PushCellResultToken(true, aAdr, NULL, NULL);
6172cdf0e10cSrcweir     }
6173cdf0e10cSrcweir }
6174cdf0e10cSrcweir 
6175cdf0e10cSrcweir 
ScHLookup()6176cdf0e10cSrcweir void ScInterpreter::ScHLookup()
6177cdf0e10cSrcweir {
6178cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHLookup" );
6179cdf0e10cSrcweir     CalculateLookup(sal_True);
6180cdf0e10cSrcweir }
CalculateLookup(sal_Bool HLookup)6181cdf0e10cSrcweir void ScInterpreter::CalculateLookup(sal_Bool HLookup)
6182cdf0e10cSrcweir {
6183cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateLookup" );
6184cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
6185cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 3, 4 ) )
6186cdf0e10cSrcweir     {
6187cdf0e10cSrcweir         sal_Bool bSorted;
6188cdf0e10cSrcweir         if (nParamCount == 4)
6189cdf0e10cSrcweir             bSorted = GetBool();
6190cdf0e10cSrcweir         else
6191cdf0e10cSrcweir             bSorted = sal_True;
6192cdf0e10cSrcweir         double fIndex = ::rtl::math::approxFloor( GetDouble() ) - 1.0;
6193cdf0e10cSrcweir         ScMatrixRef pMat = NULL;
6194cdf0e10cSrcweir         SCSIZE nC = 0, nR = 0;
6195cdf0e10cSrcweir         SCCOL nCol1 = 0;
6196cdf0e10cSrcweir         SCROW nRow1 = 0;
6197cdf0e10cSrcweir         SCTAB nTab1 = 0;
6198cdf0e10cSrcweir         SCCOL nCol2 = 0;
6199cdf0e10cSrcweir         SCROW nRow2 = 0;
6200cdf0e10cSrcweir         SCTAB nTab2;
6201cdf0e10cSrcweir         if (GetStackType() == svDoubleRef)
6202cdf0e10cSrcweir         {
6203cdf0e10cSrcweir             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
6204cdf0e10cSrcweir             if (nTab1 != nTab2)
6205cdf0e10cSrcweir             {
6206cdf0e10cSrcweir                 PushIllegalParameter();
6207cdf0e10cSrcweir                 return;
6208cdf0e10cSrcweir             }
6209cdf0e10cSrcweir         }
6210cdf0e10cSrcweir         else if (GetStackType() == svMatrix)
6211cdf0e10cSrcweir         {
6212cdf0e10cSrcweir             pMat = PopMatrix();
6213cdf0e10cSrcweir             if (pMat)
6214cdf0e10cSrcweir                 pMat->GetDimensions(nC, nR);
6215cdf0e10cSrcweir             else
6216cdf0e10cSrcweir             {
6217cdf0e10cSrcweir                 PushIllegalParameter();
6218cdf0e10cSrcweir                 return;
6219cdf0e10cSrcweir             }
6220cdf0e10cSrcweir         }
6221cdf0e10cSrcweir         else
6222cdf0e10cSrcweir         {
6223cdf0e10cSrcweir             PushIllegalParameter();
6224cdf0e10cSrcweir             return;
6225cdf0e10cSrcweir         }
6226cdf0e10cSrcweir         if ( fIndex < 0.0 || (HLookup ? (pMat ? (fIndex >= nR) : (fIndex+nRow1 > nRow2)) : (pMat ? (fIndex >= nC) : (fIndex+nCol1 > nCol2)) ) )
6227cdf0e10cSrcweir         {
6228cdf0e10cSrcweir             PushIllegalArgument();
6229cdf0e10cSrcweir             return;
6230cdf0e10cSrcweir         }
6231cdf0e10cSrcweir         SCROW nZIndex = static_cast<SCROW>(fIndex);
6232cdf0e10cSrcweir         SCCOL nSpIndex = static_cast<SCCOL>(fIndex);
6233cdf0e10cSrcweir 
6234cdf0e10cSrcweir         if (!pMat)
6235cdf0e10cSrcweir         {
6236cdf0e10cSrcweir             nZIndex += nRow1;                       // Wertzeile
6237cdf0e10cSrcweir             nSpIndex = sal::static_int_cast<SCCOL>( nSpIndex + nCol1 );     // value column
6238cdf0e10cSrcweir         }
6239cdf0e10cSrcweir 
6240cdf0e10cSrcweir         if (nGlobalError == 0)
6241cdf0e10cSrcweir         {
6242cdf0e10cSrcweir             ScQueryParam rParam;
6243cdf0e10cSrcweir             rParam.nCol1       = nCol1;
6244cdf0e10cSrcweir             rParam.nRow1       = nRow1;
6245cdf0e10cSrcweir             if ( HLookup )
6246cdf0e10cSrcweir             {
6247cdf0e10cSrcweir                 rParam.nCol2       = nCol2;
6248cdf0e10cSrcweir                 rParam.nRow2       = nRow1;     // nur in der ersten Zeile suchen
6249cdf0e10cSrcweir                 rParam.bByRow      = sal_False;
6250cdf0e10cSrcweir             } // if ( HLookup )
6251cdf0e10cSrcweir             else
6252cdf0e10cSrcweir             {
6253cdf0e10cSrcweir                 rParam.nCol2       = nCol1;     // nur in der ersten Spalte suchen
6254cdf0e10cSrcweir                 rParam.nRow2       = nRow2;
6255cdf0e10cSrcweir                 rParam.nTab        = nTab1;
6256cdf0e10cSrcweir             }
6257cdf0e10cSrcweir             rParam.bMixedComparison = sal_True;
6258cdf0e10cSrcweir 
6259cdf0e10cSrcweir             ScQueryEntry& rEntry = rParam.GetEntry(0);
6260cdf0e10cSrcweir             rEntry.bDoQuery = sal_True;
6261cdf0e10cSrcweir             if ( bSorted )
6262cdf0e10cSrcweir                 rEntry.eOp = SC_LESS_EQUAL;
6263cdf0e10cSrcweir             if ( !FillEntry(rEntry) )
6264cdf0e10cSrcweir                 return;
6265cdf0e10cSrcweir             if ( rEntry.bQueryByString )
6266cdf0e10cSrcweir                 rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6267cdf0e10cSrcweir             if (pMat)
6268cdf0e10cSrcweir             {
6269cdf0e10cSrcweir                 SCSIZE nMatCount = HLookup ? nC : nR;
6270cdf0e10cSrcweir                 SCSIZE nDelta = SCSIZE_MAX;
6271cdf0e10cSrcweir                 if (rEntry.bQueryByString)
6272cdf0e10cSrcweir                 {
6273cdf0e10cSrcweir         //!!!!!!!
6274cdf0e10cSrcweir         //! TODO: enable regex on matrix strings
6275cdf0e10cSrcweir         //!!!!!!!
6276cdf0e10cSrcweir                     String aParamStr = *rEntry.pStr;
6277cdf0e10cSrcweir                     if ( bSorted )
6278cdf0e10cSrcweir                     {
6279cdf0e10cSrcweir                         static CollatorWrapper* pCollator = ScGlobal::GetCollator();
6280cdf0e10cSrcweir                         for (SCSIZE i = 0; i < nMatCount; i++)
6281cdf0e10cSrcweir                         {
6282cdf0e10cSrcweir                             if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
6283cdf0e10cSrcweir                             {
6284cdf0e10cSrcweir                                 sal_Int32 nRes =
6285cdf0e10cSrcweir                                     pCollator->compareString( HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), aParamStr);
6286cdf0e10cSrcweir                                 if (nRes <= 0)
6287cdf0e10cSrcweir                                     nDelta = i;
6288cdf0e10cSrcweir                                 else if (i>0)   // #i2168# ignore first mismatch
6289cdf0e10cSrcweir                                     i = nMatCount+1;
6290cdf0e10cSrcweir                             }
6291cdf0e10cSrcweir                             else
6292cdf0e10cSrcweir                                 nDelta = i;
6293cdf0e10cSrcweir                         }
6294cdf0e10cSrcweir                     }
6295cdf0e10cSrcweir                     else
6296cdf0e10cSrcweir                     {
6297cdf0e10cSrcweir                         for (SCSIZE i = 0; i < nMatCount; i++)
6298cdf0e10cSrcweir                         {
6299cdf0e10cSrcweir                             if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
6300cdf0e10cSrcweir                             {
6301cdf0e10cSrcweir                                 if ( ScGlobal::GetpTransliteration()->isEqual(
6302cdf0e10cSrcweir                                     HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), aParamStr ) )
6303cdf0e10cSrcweir                                 {
6304cdf0e10cSrcweir                                     nDelta = i;
6305cdf0e10cSrcweir                                     i = nMatCount + 1;
6306cdf0e10cSrcweir                                 }
6307cdf0e10cSrcweir                             }
6308cdf0e10cSrcweir                         }
6309cdf0e10cSrcweir                     }
6310cdf0e10cSrcweir                 }
6311cdf0e10cSrcweir                 else
6312cdf0e10cSrcweir                 {
6313cdf0e10cSrcweir                     if ( bSorted )
6314cdf0e10cSrcweir                     {
6315cdf0e10cSrcweir                         // #i2168# ignore strings
6316cdf0e10cSrcweir                         for (SCSIZE i = 0; i < nMatCount; i++)
6317cdf0e10cSrcweir                         {
6318cdf0e10cSrcweir                             if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
6319cdf0e10cSrcweir                             {
6320cdf0e10cSrcweir                                 if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) <= rEntry.nVal)
6321cdf0e10cSrcweir                                     nDelta = i;
6322cdf0e10cSrcweir                                 else
6323cdf0e10cSrcweir                                     i = nMatCount+1;
6324cdf0e10cSrcweir                             }
6325cdf0e10cSrcweir                         }
6326cdf0e10cSrcweir                     }
6327cdf0e10cSrcweir                     else
6328cdf0e10cSrcweir                     {
6329cdf0e10cSrcweir                         for (SCSIZE i = 0; i < nMatCount; i++)
6330cdf0e10cSrcweir                         {
6331cdf0e10cSrcweir                             if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
6332cdf0e10cSrcweir                             {
6333cdf0e10cSrcweir                                 if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) == rEntry.nVal)
6334cdf0e10cSrcweir                                 {
6335cdf0e10cSrcweir                                     nDelta = i;
6336cdf0e10cSrcweir                                     i = nMatCount + 1;
6337cdf0e10cSrcweir                                 }
6338cdf0e10cSrcweir                             }
6339cdf0e10cSrcweir                         }
6340cdf0e10cSrcweir                     }
6341cdf0e10cSrcweir                 }
6342cdf0e10cSrcweir                 if ( nDelta != SCSIZE_MAX )
6343cdf0e10cSrcweir                 {
6344cdf0e10cSrcweir                     SCSIZE nX = static_cast<SCSIZE>(nSpIndex);
6345cdf0e10cSrcweir                     SCSIZE nY = nDelta;
6346cdf0e10cSrcweir                     if ( HLookup )
6347cdf0e10cSrcweir                     {
6348cdf0e10cSrcweir                         nX = nDelta;
6349cdf0e10cSrcweir                         nY = static_cast<SCSIZE>(nZIndex);
6350cdf0e10cSrcweir                     }
6351cdf0e10cSrcweir                     if ( pMat->IsString( nX, nY) )
6352cdf0e10cSrcweir                         PushString(pMat->GetString( nX,nY));
6353cdf0e10cSrcweir                     else
6354cdf0e10cSrcweir                         PushDouble(pMat->GetDouble( nX,nY));
6355cdf0e10cSrcweir                 }
6356cdf0e10cSrcweir                 else
6357cdf0e10cSrcweir                     PushNA();
6358cdf0e10cSrcweir             }
6359cdf0e10cSrcweir             else
6360cdf0e10cSrcweir             {
6361cdf0e10cSrcweir                 rEntry.nField = nCol1;
6362cdf0e10cSrcweir                 sal_Bool bFound = sal_False;
6363cdf0e10cSrcweir                 SCCOL nCol = 0;
6364cdf0e10cSrcweir                 SCROW nRow = 0;
6365cdf0e10cSrcweir                 if ( bSorted )
6366cdf0e10cSrcweir                     rEntry.eOp = SC_LESS_EQUAL;
6367cdf0e10cSrcweir                 if ( HLookup )
6368cdf0e10cSrcweir                 {
6369cdf0e10cSrcweir                     ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
6370cdf0e10cSrcweir                     // advance Entry.nField in Iterator upon switching columns
6371cdf0e10cSrcweir                     aCellIter.SetAdvanceQueryParamEntryField( sal_True );
6372cdf0e10cSrcweir                     if ( bSorted )
6373cdf0e10cSrcweir                     {
6374cdf0e10cSrcweir                         SCROW nRow1_temp;
6375cdf0e10cSrcweir                         bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow1_temp );
6376cdf0e10cSrcweir                     }
6377cdf0e10cSrcweir                     else if ( aCellIter.GetFirst() )
6378cdf0e10cSrcweir                     {
6379cdf0e10cSrcweir                         bFound = sal_True;
6380cdf0e10cSrcweir                         nCol = aCellIter.GetCol();
6381cdf0e10cSrcweir                     }
6382cdf0e10cSrcweir                     nRow = nZIndex;
6383cdf0e10cSrcweir                 } // if ( HLookup )
6384cdf0e10cSrcweir                 else
6385cdf0e10cSrcweir                 {
6386cdf0e10cSrcweir                     ScAddress aResultPos( nCol1, nRow1, nTab1);
6387cdf0e10cSrcweir                     bFound = LookupQueryWithCache( aResultPos, rParam);
6388cdf0e10cSrcweir                     nRow = aResultPos.Row();
6389cdf0e10cSrcweir                     nCol = nSpIndex;
6390cdf0e10cSrcweir                 }
6391cdf0e10cSrcweir                 if ( bFound )
6392cdf0e10cSrcweir                 {
6393cdf0e10cSrcweir                     ScAddress aAdr( nCol, nRow, nTab1 );
6394cdf0e10cSrcweir                     PushCellResultToken( true, aAdr, NULL, NULL);
6395cdf0e10cSrcweir                 }
6396cdf0e10cSrcweir                 else
6397cdf0e10cSrcweir                     PushNA();
6398cdf0e10cSrcweir             }
6399cdf0e10cSrcweir         }
6400cdf0e10cSrcweir         else
6401cdf0e10cSrcweir             PushIllegalParameter();
6402cdf0e10cSrcweir     }
6403cdf0e10cSrcweir }
6404cdf0e10cSrcweir 
FillEntry(ScQueryEntry & rEntry)6405cdf0e10cSrcweir bool ScInterpreter::FillEntry(ScQueryEntry& rEntry)
6406cdf0e10cSrcweir {
6407cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::FillEntry" );
6408cdf0e10cSrcweir     switch ( GetStackType() )
6409cdf0e10cSrcweir     {
6410cdf0e10cSrcweir         case svDouble:
6411cdf0e10cSrcweir         {
6412cdf0e10cSrcweir             rEntry.bQueryByString = sal_False;
6413cdf0e10cSrcweir             rEntry.nVal = GetDouble();
6414cdf0e10cSrcweir         }
6415cdf0e10cSrcweir         break;
6416cdf0e10cSrcweir         case svString:
6417cdf0e10cSrcweir         {
6418cdf0e10cSrcweir             const String sStr = GetString();
6419cdf0e10cSrcweir             rEntry.bQueryByString = sal_True;
6420cdf0e10cSrcweir             *rEntry.pStr = sStr;
6421cdf0e10cSrcweir         }
6422cdf0e10cSrcweir         break;
6423cdf0e10cSrcweir         case svDoubleRef :
6424cdf0e10cSrcweir         case svSingleRef :
6425cdf0e10cSrcweir         {
6426cdf0e10cSrcweir             ScAddress aAdr;
6427cdf0e10cSrcweir             if ( !PopDoubleRefOrSingleRef( aAdr ) )
6428cdf0e10cSrcweir             {
6429cdf0e10cSrcweir                 PushInt(0);
6430cdf0e10cSrcweir                 return false;
6431cdf0e10cSrcweir             }
6432cdf0e10cSrcweir             ScBaseCell* pCell = GetCell( aAdr );
6433cdf0e10cSrcweir             if (HasCellValueData(pCell))
6434cdf0e10cSrcweir             {
6435cdf0e10cSrcweir                 rEntry.bQueryByString = sal_False;
6436cdf0e10cSrcweir                 rEntry.nVal = GetCellValue( aAdr, pCell );
6437cdf0e10cSrcweir             }
6438cdf0e10cSrcweir             else
6439cdf0e10cSrcweir             {
6440cdf0e10cSrcweir                 if ( GetCellType( pCell ) == CELLTYPE_NOTE )
6441cdf0e10cSrcweir                 {
6442cdf0e10cSrcweir                     rEntry.bQueryByString = sal_False;
6443cdf0e10cSrcweir                     rEntry.nVal = 0.0;
6444cdf0e10cSrcweir                 }
6445cdf0e10cSrcweir                 else
6446cdf0e10cSrcweir                 {
6447cdf0e10cSrcweir                     String sStr;
6448cdf0e10cSrcweir                     GetCellString(sStr, pCell);
6449cdf0e10cSrcweir                     rEntry.bQueryByString = sal_True;
6450cdf0e10cSrcweir                     *rEntry.pStr = sStr;
6451cdf0e10cSrcweir                 }
6452cdf0e10cSrcweir             }
6453cdf0e10cSrcweir         }
6454cdf0e10cSrcweir         break;
6455cdf0e10cSrcweir         case svMatrix :
6456cdf0e10cSrcweir         {
6457cdf0e10cSrcweir             const ScMatValType nType = GetDoubleOrStringFromMatrix(rEntry.nVal, *rEntry.pStr);
6458cdf0e10cSrcweir             rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
6459cdf0e10cSrcweir         }
6460cdf0e10cSrcweir         break;
6461cdf0e10cSrcweir         default:
6462cdf0e10cSrcweir         {
6463cdf0e10cSrcweir             PushIllegalParameter();
6464cdf0e10cSrcweir             return false;
6465cdf0e10cSrcweir         }
6466cdf0e10cSrcweir     } // switch ( GetStackType() )
6467cdf0e10cSrcweir     return true;
6468cdf0e10cSrcweir }
ScVLookup()6469cdf0e10cSrcweir void ScInterpreter::ScVLookup()
6470cdf0e10cSrcweir {
6471cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVLookup" );
6472cdf0e10cSrcweir     CalculateLookup(sal_False);
6473cdf0e10cSrcweir }
6474cdf0e10cSrcweir 
ScSubTotal()6475cdf0e10cSrcweir void ScInterpreter::ScSubTotal()
6476cdf0e10cSrcweir {
6477cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubTotal" );
6478cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
6479cdf0e10cSrcweir     if ( MustHaveParamCountMin( nParamCount, 2 ) )
6480cdf0e10cSrcweir     {
6481cdf0e10cSrcweir         // We must fish the 1st parameter deep from the stack! And push it on top.
6482cdf0e10cSrcweir         const FormulaToken* p = pStack[ sp - nParamCount ];
6483cdf0e10cSrcweir         PushTempToken( *p );
6484cdf0e10cSrcweir         int nFunc = (int) ::rtl::math::approxFloor( GetDouble() );
6485cdf0e10cSrcweir         if( nFunc < 1 || nFunc > 11 )
6486cdf0e10cSrcweir             PushIllegalArgument();  // simulate return on stack, not SetError(...)
6487cdf0e10cSrcweir         else
6488cdf0e10cSrcweir         {
6489cdf0e10cSrcweir             cPar = nParamCount - 1;
6490cdf0e10cSrcweir             glSubTotal = sal_True;
6491cdf0e10cSrcweir             switch( nFunc )
6492cdf0e10cSrcweir             {
6493cdf0e10cSrcweir                 case SUBTOTAL_FUNC_AVE  : ScAverage(); break;
6494cdf0e10cSrcweir                 case SUBTOTAL_FUNC_CNT  : ScCount();   break;
6495cdf0e10cSrcweir                 case SUBTOTAL_FUNC_CNT2 : ScCount2();  break;
6496cdf0e10cSrcweir                 case SUBTOTAL_FUNC_MAX  : ScMax();     break;
6497cdf0e10cSrcweir                 case SUBTOTAL_FUNC_MIN  : ScMin();     break;
6498cdf0e10cSrcweir                 case SUBTOTAL_FUNC_PROD : ScProduct(); break;
6499cdf0e10cSrcweir                 case SUBTOTAL_FUNC_STD  : ScStDev();   break;
6500cdf0e10cSrcweir                 case SUBTOTAL_FUNC_STDP : ScStDevP();  break;
6501cdf0e10cSrcweir                 case SUBTOTAL_FUNC_SUM  : ScSum();     break;
6502cdf0e10cSrcweir                 case SUBTOTAL_FUNC_VAR  : ScVar();     break;
6503cdf0e10cSrcweir                 case SUBTOTAL_FUNC_VARP : ScVarP();    break;
6504cdf0e10cSrcweir                 default : PushIllegalArgument();       break;
6505cdf0e10cSrcweir             }
6506cdf0e10cSrcweir             glSubTotal = sal_False;
6507cdf0e10cSrcweir         }
6508cdf0e10cSrcweir         // Get rid of the 1st (fished) parameter.
6509cdf0e10cSrcweir         double nVal = GetDouble();
6510cdf0e10cSrcweir         Pop();
6511cdf0e10cSrcweir         PushDouble( nVal );
6512cdf0e10cSrcweir     }
6513cdf0e10cSrcweir }
6514cdf0e10cSrcweir 
GetDBParams(sal_Bool & rMissingField)6515cdf0e10cSrcweir ScDBQueryParamBase* ScInterpreter::GetDBParams( sal_Bool& rMissingField )
6516cdf0e10cSrcweir {
6517cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
6518cdf0e10cSrcweir     sal_Bool bAllowMissingField = sal_False;
6519cdf0e10cSrcweir     if ( rMissingField )
6520cdf0e10cSrcweir     {
6521cdf0e10cSrcweir         bAllowMissingField = sal_True;
6522cdf0e10cSrcweir         rMissingField = sal_False;
6523cdf0e10cSrcweir     }
6524cdf0e10cSrcweir     if ( GetByte() == 3 )
6525cdf0e10cSrcweir     {
6526cdf0e10cSrcweir         // First, get the query criteria range.
6527cdf0e10cSrcweir         ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
6528cdf0e10cSrcweir         if (!pQueryRef.get())
6529cdf0e10cSrcweir             return NULL;
6530cdf0e10cSrcweir 
6531cdf0e10cSrcweir         sal_Bool    bByVal = sal_True;
6532cdf0e10cSrcweir         double  nVal = 0.0;
6533cdf0e10cSrcweir         String  aStr;
6534cdf0e10cSrcweir         ScRange aMissingRange;
6535cdf0e10cSrcweir         sal_Bool bRangeFake = sal_False;
6536cdf0e10cSrcweir         switch (GetStackType())
6537cdf0e10cSrcweir         {
6538cdf0e10cSrcweir             case svDouble :
6539cdf0e10cSrcweir                 nVal = ::rtl::math::approxFloor( GetDouble() );
6540cdf0e10cSrcweir                 if ( bAllowMissingField && nVal == 0.0 )
6541cdf0e10cSrcweir                     rMissingField = sal_True;   // fake missing parameter
6542cdf0e10cSrcweir                 break;
6543cdf0e10cSrcweir             case svString :
6544cdf0e10cSrcweir                 bByVal = sal_False;
6545cdf0e10cSrcweir                 aStr = GetString();
6546cdf0e10cSrcweir                 break;
6547cdf0e10cSrcweir             case svSingleRef :
6548cdf0e10cSrcweir                 {
6549cdf0e10cSrcweir                     ScAddress aAdr;
6550cdf0e10cSrcweir                     PopSingleRef( aAdr );
6551cdf0e10cSrcweir                     ScBaseCell* pCell = GetCell( aAdr );
6552cdf0e10cSrcweir                     if (HasCellValueData(pCell))
6553cdf0e10cSrcweir                         nVal = GetCellValue( aAdr, pCell );
6554cdf0e10cSrcweir                     else
6555cdf0e10cSrcweir                     {
6556cdf0e10cSrcweir                         bByVal = sal_False;
6557cdf0e10cSrcweir                         GetCellString(aStr, pCell);
6558cdf0e10cSrcweir                     }
6559cdf0e10cSrcweir                 }
6560cdf0e10cSrcweir                 break;
6561cdf0e10cSrcweir             case svDoubleRef :
6562cdf0e10cSrcweir                 if ( bAllowMissingField )
6563cdf0e10cSrcweir                 {   // fake missing parameter for old SO compatibility
6564cdf0e10cSrcweir                     bRangeFake = sal_True;
6565cdf0e10cSrcweir                     PopDoubleRef( aMissingRange );
6566cdf0e10cSrcweir                 }
6567cdf0e10cSrcweir                 else
6568cdf0e10cSrcweir                 {
6569cdf0e10cSrcweir                     PopError();
6570cdf0e10cSrcweir                     SetError( errIllegalParameter );
6571cdf0e10cSrcweir                 }
6572cdf0e10cSrcweir                 break;
6573cdf0e10cSrcweir             case svMissing :
6574cdf0e10cSrcweir                 PopError();
6575cdf0e10cSrcweir                 if ( bAllowMissingField )
6576cdf0e10cSrcweir                     rMissingField = sal_True;
6577cdf0e10cSrcweir                 else
6578cdf0e10cSrcweir                     SetError( errIllegalParameter );
6579cdf0e10cSrcweir                 break;
6580cdf0e10cSrcweir             default:
6581cdf0e10cSrcweir                 PopError();
6582cdf0e10cSrcweir                 SetError( errIllegalParameter );
6583cdf0e10cSrcweir         }
6584cdf0e10cSrcweir 
6585cdf0e10cSrcweir         auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
6586cdf0e10cSrcweir 
6587cdf0e10cSrcweir         if (nGlobalError || !pDBRef.get())
6588cdf0e10cSrcweir             return NULL;
6589cdf0e10cSrcweir 
6590cdf0e10cSrcweir         if ( bRangeFake )
6591cdf0e10cSrcweir         {
6592cdf0e10cSrcweir             // range parameter must match entire database range
6593cdf0e10cSrcweir             if (pDBRef->isRangeEqual(aMissingRange))
6594cdf0e10cSrcweir                 rMissingField = sal_True;
6595cdf0e10cSrcweir             else
6596cdf0e10cSrcweir                 SetError( errIllegalParameter );
6597cdf0e10cSrcweir         }
6598cdf0e10cSrcweir 
6599cdf0e10cSrcweir         if (nGlobalError)
6600cdf0e10cSrcweir             return NULL;
6601cdf0e10cSrcweir 
6602cdf0e10cSrcweir         SCCOL nField = pDBRef->getFirstFieldColumn();
6603cdf0e10cSrcweir         if (rMissingField)
6604cdf0e10cSrcweir             ; // special case
6605cdf0e10cSrcweir         else if (bByVal)
6606cdf0e10cSrcweir             nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
6607cdf0e10cSrcweir         else
6608cdf0e10cSrcweir         {
6609cdf0e10cSrcweir             sal_uInt16 nErr = 0;
6610cdf0e10cSrcweir             nField = pDBRef->findFieldColumn(aStr, &nErr);
6611cdf0e10cSrcweir             SetError(nErr);
6612cdf0e10cSrcweir         }
6613cdf0e10cSrcweir 
6614cdf0e10cSrcweir         if (!ValidCol(nField))
6615cdf0e10cSrcweir             return NULL;
6616cdf0e10cSrcweir 
6617cdf0e10cSrcweir         auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
6618cdf0e10cSrcweir 
6619cdf0e10cSrcweir         if (pParam.get())
6620cdf0e10cSrcweir         {
6621cdf0e10cSrcweir             // An allowed missing field parameter sets the result field
6622cdf0e10cSrcweir             // to any of the query fields, just to be able to return
6623cdf0e10cSrcweir             // some cell from the iterator.
6624cdf0e10cSrcweir             if ( rMissingField )
6625cdf0e10cSrcweir                 nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
6626cdf0e10cSrcweir             pParam->mnField = nField;
6627cdf0e10cSrcweir 
6628cdf0e10cSrcweir             SCSIZE nCount = pParam->GetEntryCount();
6629cdf0e10cSrcweir             for ( SCSIZE i=0; i < nCount; i++ )
6630cdf0e10cSrcweir             {
6631cdf0e10cSrcweir                 ScQueryEntry& rEntry = pParam->GetEntry(i);
6632cdf0e10cSrcweir                 if ( rEntry.bDoQuery )
6633cdf0e10cSrcweir                 {
6634cdf0e10cSrcweir                     sal_uInt32 nIndex = 0;
6635cdf0e10cSrcweir                     rEntry.bQueryByString = !pFormatter->IsNumberFormat(
6636cdf0e10cSrcweir                         *rEntry.pStr, nIndex, rEntry.nVal );
6637cdf0e10cSrcweir                     if ( rEntry.bQueryByString && !pParam->bRegExp )
6638cdf0e10cSrcweir                         pParam->bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6639cdf0e10cSrcweir                 }
6640cdf0e10cSrcweir                 else
6641cdf0e10cSrcweir                     break;  // for
6642cdf0e10cSrcweir             }
6643cdf0e10cSrcweir             return pParam.release();
6644cdf0e10cSrcweir         }
6645cdf0e10cSrcweir     }
664646d2a04eSHerbert Dürr     return NULL;
6647cdf0e10cSrcweir }
6648cdf0e10cSrcweir 
6649cdf0e10cSrcweir 
DBIterator(ScIterFunc eFunc)6650cdf0e10cSrcweir void ScInterpreter::DBIterator( ScIterFunc eFunc )
6651cdf0e10cSrcweir {
6652cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
6653cdf0e10cSrcweir     double nErg = 0.0;
6654cdf0e10cSrcweir     double fMem = 0.0;
6655cdf0e10cSrcweir     sal_Bool bNull = sal_True;
6656cdf0e10cSrcweir     sal_uLong nCount = 0;
6657cdf0e10cSrcweir     sal_Bool bMissingField = sal_False;
6658cdf0e10cSrcweir     auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6659cdf0e10cSrcweir     if (pQueryParam.get())
6660cdf0e10cSrcweir     {
6661cdf0e10cSrcweir         ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6662cdf0e10cSrcweir         ScDBQueryDataIterator::Value aValue;
6663cdf0e10cSrcweir         if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6664cdf0e10cSrcweir         {
6665cdf0e10cSrcweir             switch( eFunc )
6666cdf0e10cSrcweir             {
6667cdf0e10cSrcweir                 case ifPRODUCT: nErg = 1; break;
6668cdf0e10cSrcweir                 case ifMAX:     nErg = -MAXDOUBLE; break;
6669cdf0e10cSrcweir                 case ifMIN:     nErg = MAXDOUBLE; break;
6670cdf0e10cSrcweir                 default: ; // nothing
6671cdf0e10cSrcweir             }
6672cdf0e10cSrcweir             do
6673cdf0e10cSrcweir             {
6674cdf0e10cSrcweir                 nCount++;
6675cdf0e10cSrcweir                 switch( eFunc )
6676cdf0e10cSrcweir                 {
6677cdf0e10cSrcweir                     case ifAVERAGE:
6678cdf0e10cSrcweir                     case ifSUM:
6679cdf0e10cSrcweir                         if ( bNull && aValue.mfValue != 0.0 )
6680cdf0e10cSrcweir                         {
6681cdf0e10cSrcweir                             bNull = sal_False;
6682cdf0e10cSrcweir                             fMem = aValue.mfValue;
6683cdf0e10cSrcweir                         }
6684cdf0e10cSrcweir                         else
6685cdf0e10cSrcweir                             nErg += aValue.mfValue;
6686cdf0e10cSrcweir                         break;
6687cdf0e10cSrcweir                     case ifSUMSQ:   nErg += aValue.mfValue * aValue.mfValue; break;
6688cdf0e10cSrcweir                     case ifPRODUCT: nErg *= aValue.mfValue; break;
6689cdf0e10cSrcweir                     case ifMAX:     if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
6690cdf0e10cSrcweir                     case ifMIN:     if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
6691cdf0e10cSrcweir                     default: ; // nothing
6692cdf0e10cSrcweir                 }
6693cdf0e10cSrcweir             }
6694cdf0e10cSrcweir             while ( aValIter.GetNext(aValue) && !aValue.mnError );
6695cdf0e10cSrcweir         }
6696cdf0e10cSrcweir         SetError(aValue.mnError);
6697cdf0e10cSrcweir     }
6698cdf0e10cSrcweir     else
6699cdf0e10cSrcweir         SetError( errIllegalParameter);
6700cdf0e10cSrcweir     switch( eFunc )
6701cdf0e10cSrcweir     {
6702cdf0e10cSrcweir         case ifCOUNT:   nErg = nCount; break;
6703cdf0e10cSrcweir         case ifSUM:     nErg = ::rtl::math::approxAdd( nErg, fMem ); break;
6704cdf0e10cSrcweir         case ifAVERAGE: nErg = ::rtl::math::approxAdd( nErg, fMem ) / nCount; break;
6705cdf0e10cSrcweir         default: ; // nothing
6706cdf0e10cSrcweir     }
6707cdf0e10cSrcweir     PushDouble( nErg );
6708cdf0e10cSrcweir }
6709cdf0e10cSrcweir 
6710cdf0e10cSrcweir 
ScDBSum()6711cdf0e10cSrcweir void ScInterpreter::ScDBSum()
6712cdf0e10cSrcweir {
6713cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBSum" );
6714cdf0e10cSrcweir     DBIterator( ifSUM );
6715cdf0e10cSrcweir }
6716cdf0e10cSrcweir 
6717cdf0e10cSrcweir 
ScDBCount()6718cdf0e10cSrcweir void ScInterpreter::ScDBCount()
6719cdf0e10cSrcweir {
6720cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
6721cdf0e10cSrcweir     sal_Bool bMissingField = sal_True;
6722cdf0e10cSrcweir     auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6723cdf0e10cSrcweir     if (pQueryParam.get())
6724cdf0e10cSrcweir     {
6725cdf0e10cSrcweir         sal_uLong nCount = 0;
6726cdf0e10cSrcweir         if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
6727cdf0e10cSrcweir         {   // count all matching records
6728cdf0e10cSrcweir             // TODO: currently the QueryIterators only return cell pointers of
6729cdf0e10cSrcweir             // existing cells, so if a query matches an empty cell there's
6730cdf0e10cSrcweir             // nothing returned, and therefor not counted!
6731cdf0e10cSrcweir             // Since this has ever been the case and this code here only came
673286e1cf34SPedro Giffuni             // into existence to fix #i6899 and it never worked before we'll
6733cdf0e10cSrcweir             // have to live with it until we reimplement the iterators to also
6734cdf0e10cSrcweir             // return empty cells, which would mean to adapt all callers of
6735cdf0e10cSrcweir             // iterators.
6736cdf0e10cSrcweir             ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
6737cdf0e10cSrcweir             SCTAB nTab = p->nTab;
6738cdf0e10cSrcweir             // ScQueryCellIterator doesn't make use of ScDBQueryParamBase::mnField,
6739cdf0e10cSrcweir             // so the source range has to be restricted, like before the introduction
6740cdf0e10cSrcweir             // of ScDBQueryParamBase.
6741cdf0e10cSrcweir             p->nCol1 = p->nCol2 = p->mnField;
6742cdf0e10cSrcweir             ScQueryCellIterator aCellIter( pDok, nTab, *p);
6743cdf0e10cSrcweir             if ( aCellIter.GetFirst() )
6744cdf0e10cSrcweir             {
6745cdf0e10cSrcweir                 do
6746cdf0e10cSrcweir                 {
6747cdf0e10cSrcweir                     nCount++;
6748cdf0e10cSrcweir                 } while ( aCellIter.GetNext() );
6749cdf0e10cSrcweir             }
6750cdf0e10cSrcweir         }
6751cdf0e10cSrcweir         else
6752cdf0e10cSrcweir         {   // count only matching records with a value in the "result" field
6753cdf0e10cSrcweir             ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6754cdf0e10cSrcweir             ScDBQueryDataIterator::Value aValue;
6755cdf0e10cSrcweir             if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6756cdf0e10cSrcweir             {
6757cdf0e10cSrcweir                 do
6758cdf0e10cSrcweir                 {
6759cdf0e10cSrcweir                     nCount++;
6760cdf0e10cSrcweir                 }
6761cdf0e10cSrcweir                 while ( aValIter.GetNext(aValue) && !aValue.mnError );
6762cdf0e10cSrcweir             }
6763cdf0e10cSrcweir             SetError(aValue.mnError);
6764cdf0e10cSrcweir         }
6765cdf0e10cSrcweir         PushDouble( nCount );
6766cdf0e10cSrcweir     }
6767cdf0e10cSrcweir     else
6768cdf0e10cSrcweir         PushIllegalParameter();
6769cdf0e10cSrcweir }
6770cdf0e10cSrcweir 
6771cdf0e10cSrcweir 
ScDBCount2()6772cdf0e10cSrcweir void ScInterpreter::ScDBCount2()
6773cdf0e10cSrcweir {
6774cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
6775cdf0e10cSrcweir     sal_Bool bMissingField = sal_True;
6776cdf0e10cSrcweir     auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6777cdf0e10cSrcweir     if (pQueryParam.get())
6778cdf0e10cSrcweir     {
6779cdf0e10cSrcweir         sal_uLong nCount = 0;
6780cdf0e10cSrcweir         pQueryParam->mbSkipString = false;
6781cdf0e10cSrcweir         ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6782cdf0e10cSrcweir         ScDBQueryDataIterator::Value aValue;
6783cdf0e10cSrcweir         if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6784cdf0e10cSrcweir         {
6785cdf0e10cSrcweir             do
6786cdf0e10cSrcweir             {
6787cdf0e10cSrcweir                 nCount++;
6788cdf0e10cSrcweir             }
6789cdf0e10cSrcweir             while ( aValIter.GetNext(aValue) && !aValue.mnError );
6790cdf0e10cSrcweir         }
6791cdf0e10cSrcweir         SetError(aValue.mnError);
6792cdf0e10cSrcweir         PushDouble( nCount );
6793cdf0e10cSrcweir     }
6794cdf0e10cSrcweir     else
6795cdf0e10cSrcweir         PushIllegalParameter();
6796cdf0e10cSrcweir }
6797cdf0e10cSrcweir 
6798cdf0e10cSrcweir 
ScDBAverage()6799cdf0e10cSrcweir void ScInterpreter::ScDBAverage()
6800cdf0e10cSrcweir {
6801cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBAverage" );
6802cdf0e10cSrcweir     DBIterator( ifAVERAGE );
6803cdf0e10cSrcweir }
6804cdf0e10cSrcweir 
6805cdf0e10cSrcweir 
ScDBMax()6806cdf0e10cSrcweir void ScInterpreter::ScDBMax()
6807cdf0e10cSrcweir {
6808cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMax" );
6809cdf0e10cSrcweir     DBIterator( ifMAX );
6810cdf0e10cSrcweir }
6811cdf0e10cSrcweir 
6812cdf0e10cSrcweir 
ScDBMin()6813cdf0e10cSrcweir void ScInterpreter::ScDBMin()
6814cdf0e10cSrcweir {
6815cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMin" );
6816cdf0e10cSrcweir     DBIterator( ifMIN );
6817cdf0e10cSrcweir }
6818cdf0e10cSrcweir 
6819cdf0e10cSrcweir 
ScDBProduct()6820cdf0e10cSrcweir void ScInterpreter::ScDBProduct()
6821cdf0e10cSrcweir {
6822cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBProduct" );
6823cdf0e10cSrcweir     DBIterator( ifPRODUCT );
6824cdf0e10cSrcweir }
6825cdf0e10cSrcweir 
6826cdf0e10cSrcweir 
GetDBStVarParams(double & rVal,double & rValCount)6827cdf0e10cSrcweir void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
6828cdf0e10cSrcweir {
6829cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBStVarParams" );
6830cdf0e10cSrcweir     std::vector<double> values;
6831cdf0e10cSrcweir     double vSum    = 0.0;
6832cdf0e10cSrcweir     double vMean    = 0.0;
6833cdf0e10cSrcweir 
6834cdf0e10cSrcweir     rValCount = 0.0;
6835cdf0e10cSrcweir     double fSum    = 0.0;
6836cdf0e10cSrcweir     sal_Bool bMissingField = sal_False;
6837cdf0e10cSrcweir     auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6838cdf0e10cSrcweir     if (pQueryParam.get())
6839cdf0e10cSrcweir     {
6840cdf0e10cSrcweir         ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6841cdf0e10cSrcweir         ScDBQueryDataIterator::Value aValue;
6842cdf0e10cSrcweir         if (aValIter.GetFirst(aValue) && !aValue.mnError)
6843cdf0e10cSrcweir         {
6844cdf0e10cSrcweir             do
6845cdf0e10cSrcweir             {
6846cdf0e10cSrcweir                 rValCount++;
6847cdf0e10cSrcweir                 values.push_back(aValue.mfValue);
6848cdf0e10cSrcweir                 fSum += aValue.mfValue;
6849cdf0e10cSrcweir             }
6850cdf0e10cSrcweir             while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
6851cdf0e10cSrcweir         }
6852cdf0e10cSrcweir         SetError(aValue.mnError);
6853cdf0e10cSrcweir     }
6854cdf0e10cSrcweir     else
6855cdf0e10cSrcweir         SetError( errIllegalParameter);
6856cdf0e10cSrcweir 
6857cdf0e10cSrcweir     vMean = fSum / values.size();
6858cdf0e10cSrcweir 
6859cdf0e10cSrcweir     for (size_t i = 0; i < values.size(); i++)
6860cdf0e10cSrcweir         vSum += (values[i] - vMean) * (values[i] - vMean);
6861cdf0e10cSrcweir 
6862cdf0e10cSrcweir     rVal = vSum;
6863cdf0e10cSrcweir }
6864cdf0e10cSrcweir 
6865cdf0e10cSrcweir 
ScDBStdDev()6866cdf0e10cSrcweir void ScInterpreter::ScDBStdDev()
6867cdf0e10cSrcweir {
6868cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDev" );
6869cdf0e10cSrcweir     double fVal, fCount;
6870cdf0e10cSrcweir     GetDBStVarParams( fVal, fCount );
6871cdf0e10cSrcweir     PushDouble( sqrt(fVal/(fCount-1)));
6872cdf0e10cSrcweir }
6873cdf0e10cSrcweir 
6874cdf0e10cSrcweir 
ScDBStdDevP()6875cdf0e10cSrcweir void ScInterpreter::ScDBStdDevP()
6876cdf0e10cSrcweir {
6877cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDevP" );
6878cdf0e10cSrcweir     double fVal, fCount;
6879cdf0e10cSrcweir     GetDBStVarParams( fVal, fCount );
6880cdf0e10cSrcweir     PushDouble( sqrt(fVal/fCount));
6881cdf0e10cSrcweir }
6882cdf0e10cSrcweir 
6883cdf0e10cSrcweir 
ScDBVar()6884cdf0e10cSrcweir void ScInterpreter::ScDBVar()
6885cdf0e10cSrcweir {
6886cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVar" );
6887cdf0e10cSrcweir     double fVal, fCount;
6888cdf0e10cSrcweir     GetDBStVarParams( fVal, fCount );
6889cdf0e10cSrcweir     PushDouble(fVal/(fCount-1));
6890cdf0e10cSrcweir }
6891cdf0e10cSrcweir 
6892cdf0e10cSrcweir 
ScDBVarP()6893cdf0e10cSrcweir void ScInterpreter::ScDBVarP()
6894cdf0e10cSrcweir {
6895cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVarP" );
6896cdf0e10cSrcweir     double fVal, fCount;
6897cdf0e10cSrcweir     GetDBStVarParams( fVal, fCount );
6898cdf0e10cSrcweir     PushDouble(fVal/fCount);
6899cdf0e10cSrcweir }
6900cdf0e10cSrcweir 
6901cdf0e10cSrcweir 
lcl_CreateExternalRefSubroutine(const ScAddress & rPos,ScDocument * pDoc,const ScAddress::ExternalInfo & rExtInfo,const ScRefAddress & rRefAd1,const ScRefAddress * pRefAd2)6902cdf0e10cSrcweir FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos, ScDocument* pDoc,
6903cdf0e10cSrcweir         const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1,
6904cdf0e10cSrcweir         const ScRefAddress* pRefAd2 )
6905cdf0e10cSrcweir {
6906cdf0e10cSrcweir     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
6907cdf0e10cSrcweir     size_t nSheets = 1;
6908cdf0e10cSrcweir     const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName);
6909cdf0e10cSrcweir     ScTokenArray* pTokenArray = new ScTokenArray;
6910cdf0e10cSrcweir     if (pRefAd2)
6911cdf0e10cSrcweir     {
6912cdf0e10cSrcweir         ScComplexRefData aRef;
6913cdf0e10cSrcweir         aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos);
6914cdf0e10cSrcweir         aRef.Ref1.SetColRel( rRefAd1.IsRelCol());
6915cdf0e10cSrcweir         aRef.Ref1.SetRowRel( rRefAd1.IsRelRow());
6916cdf0e10cSrcweir         aRef.Ref1.SetTabRel( rRefAd1.IsRelTab());
6917cdf0e10cSrcweir         aRef.Ref1.SetFlag3D( true);
6918cdf0e10cSrcweir         aRef.Ref2.SetColRel( pRefAd2->IsRelCol());
6919cdf0e10cSrcweir         aRef.Ref2.SetRowRel( pRefAd2->IsRelRow());
6920cdf0e10cSrcweir         aRef.Ref2.SetTabRel( pRefAd2->IsRelTab());
6921cdf0e10cSrcweir         nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1;
6922cdf0e10cSrcweir         aRef.Ref2.SetFlag3D( nSheets > 1 );
6923cdf0e10cSrcweir         pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId,
6924cdf0e10cSrcweir                 (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
6925cdf0e10cSrcweir     }
6926cdf0e10cSrcweir     else
6927cdf0e10cSrcweir     {
6928cdf0e10cSrcweir         ScSingleRefData aRef;
6929cdf0e10cSrcweir         aRef.InitAddressRel( rRefAd1.GetAddress(), rPos);
6930cdf0e10cSrcweir         aRef.SetColRel( rRefAd1.IsRelCol());
6931cdf0e10cSrcweir         aRef.SetRowRel( rRefAd1.IsRelRow());
6932cdf0e10cSrcweir         aRef.SetTabRel( rRefAd1.IsRelTab());
6933cdf0e10cSrcweir         aRef.SetFlag3D( true);
6934cdf0e10cSrcweir         pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId,
6935cdf0e10cSrcweir                 (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
6936cdf0e10cSrcweir     }
6937cdf0e10cSrcweir     // The indirect usage of the external table can't be detected during the
6938cdf0e10cSrcweir     // store-to-file cycle, mark it as permanently referenced so it gets stored
6939cdf0e10cSrcweir     // even if not directly referenced anywhere.
6940cdf0e10cSrcweir     pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId,
6941cdf0e10cSrcweir             rExtInfo.maTabName, nSheets);
6942cdf0e10cSrcweir     ScCompiler aComp( pDoc, rPos, *pTokenArray);
6943cdf0e10cSrcweir     aComp.CompileTokenArray();
6944cdf0e10cSrcweir     return new FormulaSubroutineToken( pTokenArray);
6945cdf0e10cSrcweir }
6946cdf0e10cSrcweir 
6947cdf0e10cSrcweir 
ScIndirect()6948cdf0e10cSrcweir void ScInterpreter::ScIndirect()
6949cdf0e10cSrcweir {
6950cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndirect" );
6951cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
6952cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 2 )  )
6953cdf0e10cSrcweir     {
6954cdf0e10cSrcweir         bool bTryXlA1 = true;   // whether to try XL_A1 style as well.
6955cdf0e10cSrcweir         FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO;
6956cdf0e10cSrcweir         if (nParamCount == 2 && 0.0 == ::rtl::math::approxFloor( GetDouble()))
6957cdf0e10cSrcweir         {
6958cdf0e10cSrcweir             eConv = FormulaGrammar::CONV_XL_R1C1;
6959cdf0e10cSrcweir             bTryXlA1 = false;
6960cdf0e10cSrcweir         }
6961cdf0e10cSrcweir         const ScAddress::Details aDetails( eConv, aPos );
6962cdf0e10cSrcweir         const ScAddress::Details aDetailsXlA1( FormulaGrammar::CONV_XL_A1, aPos );
6963cdf0e10cSrcweir         SCTAB nTab = aPos.Tab();
6964cdf0e10cSrcweir         String sRefStr( GetString() );
6965cdf0e10cSrcweir         ScRefAddress aRefAd, aRefAd2;
6966cdf0e10cSrcweir         ScAddress::ExternalInfo aExtInfo;
6967cdf0e10cSrcweir         if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) ||
6968cdf0e10cSrcweir                 (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
6969cdf0e10cSrcweir                                                aRefAd2, aDetailsXlA1, &aExtInfo)))
6970cdf0e10cSrcweir         {
6971cdf0e10cSrcweir             if (aExtInfo.mbExternal)
6972cdf0e10cSrcweir             {
6973cdf0e10cSrcweir                 // Push a subroutine that resolves the external reference as
6974cdf0e10cSrcweir                 // the next instruction.
6975cdf0e10cSrcweir                 PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok,
6976cdf0e10cSrcweir                             aExtInfo, aRefAd, &aRefAd2));
6977cdf0e10cSrcweir             }
6978cdf0e10cSrcweir             else
6979cdf0e10cSrcweir                 PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
6980cdf0e10cSrcweir                         aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
6981cdf0e10cSrcweir         }
6982cdf0e10cSrcweir         else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) ||
6983cdf0e10cSrcweir                 (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
6984cdf0e10cSrcweir                                                 aDetailsXlA1, &aExtInfo)))
6985cdf0e10cSrcweir         {
6986cdf0e10cSrcweir             if (aExtInfo.mbExternal)
6987cdf0e10cSrcweir             {
6988cdf0e10cSrcweir                 // Push a subroutine that resolves the external reference as
6989cdf0e10cSrcweir                 // the next instruction.
6990cdf0e10cSrcweir                 PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok,
6991cdf0e10cSrcweir                             aExtInfo, aRefAd, NULL));
6992cdf0e10cSrcweir             }
6993cdf0e10cSrcweir             else
6994cdf0e10cSrcweir                 PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
6995cdf0e10cSrcweir         }
6996cdf0e10cSrcweir         else
6997cdf0e10cSrcweir         {
6998cdf0e10cSrcweir             do
6999cdf0e10cSrcweir             {
7000cdf0e10cSrcweir                 ScRangeName* pNames = pDok->GetRangeName();
7001cdf0e10cSrcweir                 if (!pNames)
7002cdf0e10cSrcweir                     break;
7003cdf0e10cSrcweir 
7004cdf0e10cSrcweir                 sal_uInt16 nPos = 0;
7005cdf0e10cSrcweir                 if (!pNames->SearchName( sRefStr, nPos))
7006cdf0e10cSrcweir                     break;
7007cdf0e10cSrcweir 
7008cdf0e10cSrcweir                 ScRangeData* rData = (*pNames)[nPos];
7009cdf0e10cSrcweir                 if (!rData)
7010cdf0e10cSrcweir                     break;
7011cdf0e10cSrcweir 
7012cdf0e10cSrcweir                 // We need this in order to obtain a good range.
7013cdf0e10cSrcweir                 rData->ValidateTabRefs();
7014cdf0e10cSrcweir 
7015cdf0e10cSrcweir                 ScRange aRange;
7016cdf0e10cSrcweir #if 0
7017cdf0e10cSrcweir                 // This is some really odd Excel behavior and renders named
7018cdf0e10cSrcweir                 // ranges containing relative references totally useless.
7019cdf0e10cSrcweir                 if (!rData->IsReference(aRange, ScAddress( aPos.Tab(), 0, 0)))
7020cdf0e10cSrcweir                     break;
7021cdf0e10cSrcweir #else
7022cdf0e10cSrcweir                 // This is the usual way to treat named ranges containing
7023cdf0e10cSrcweir                 // relative references.
7024cdf0e10cSrcweir                 if (!rData->IsReference( aRange, aPos))
7025cdf0e10cSrcweir                     break;
7026cdf0e10cSrcweir #endif
7027cdf0e10cSrcweir 
7028cdf0e10cSrcweir                 if (aRange.aStart == aRange.aEnd)
7029cdf0e10cSrcweir                     PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7030cdf0e10cSrcweir                             aRange.aStart.Tab());
7031cdf0e10cSrcweir                 else
7032cdf0e10cSrcweir                     PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7033cdf0e10cSrcweir                             aRange.aStart.Tab(), aRange.aEnd.Col(),
7034cdf0e10cSrcweir                             aRange.aEnd.Row(), aRange.aEnd.Tab());
7035cdf0e10cSrcweir 
7036cdf0e10cSrcweir                 // success!
7037cdf0e10cSrcweir                 return;
7038cdf0e10cSrcweir             }
7039cdf0e10cSrcweir             while (false);
7040cdf0e10cSrcweir 
7041cdf0e10cSrcweir             PushIllegalArgument();
7042cdf0e10cSrcweir         }
7043cdf0e10cSrcweir     }
7044cdf0e10cSrcweir }
7045cdf0e10cSrcweir 
7046cdf0e10cSrcweir 
ScAddressFunc()7047cdf0e10cSrcweir void ScInterpreter::ScAddressFunc()
7048cdf0e10cSrcweir {
7049cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAddressFunc" );
7050cdf0e10cSrcweir     String  sTabStr;
7051cdf0e10cSrcweir 
7052cdf0e10cSrcweir     sal_uInt8    nParamCount = GetByte();
7053cdf0e10cSrcweir     if( !MustHaveParamCount( nParamCount, 2, 5 ) )
7054cdf0e10cSrcweir         return;
7055cdf0e10cSrcweir 
7056cdf0e10cSrcweir     if( nParamCount >= 5 )
7057cdf0e10cSrcweir         sTabStr = GetString();
7058cdf0e10cSrcweir 
7059cdf0e10cSrcweir     FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO;      // default
7060cdf0e10cSrcweir     if( nParamCount >= 4 && 0.0 == ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0)))
7061cdf0e10cSrcweir         eConv = FormulaGrammar::CONV_XL_R1C1;
7062cdf0e10cSrcweir 
7063cdf0e10cSrcweir     sal_uInt16  nFlags = SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE;   // default
7064cdf0e10cSrcweir     if( nParamCount >= 3 )
7065cdf0e10cSrcweir     {
7066cdf0e10cSrcweir         sal_uInt16 n = (sal_uInt16) ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0));
7067cdf0e10cSrcweir         switch ( n )
7068cdf0e10cSrcweir         {
7069cdf0e10cSrcweir             default :
7070cdf0e10cSrcweir                 PushNoValue();
7071cdf0e10cSrcweir                 return;
7072cdf0e10cSrcweir 
7073cdf0e10cSrcweir             case 5:
7074cdf0e10cSrcweir             case 1 : break; // default
7075cdf0e10cSrcweir             case 6:
7076cdf0e10cSrcweir             case 2 : nFlags = SCA_ROW_ABSOLUTE; break;
7077cdf0e10cSrcweir             case 7:
7078cdf0e10cSrcweir             case 3 : nFlags = SCA_COL_ABSOLUTE; break;
7079cdf0e10cSrcweir             case 8:
7080cdf0e10cSrcweir             case 4 : nFlags = 0; break; // both relative
7081cdf0e10cSrcweir         }
7082cdf0e10cSrcweir     }
7083cdf0e10cSrcweir     nFlags |= SCA_VALID | SCA_VALID_ROW | SCA_VALID_COL;
7084cdf0e10cSrcweir 
7085cdf0e10cSrcweir     SCCOL nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7086cdf0e10cSrcweir     SCROW nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7087cdf0e10cSrcweir     if( eConv == FormulaGrammar::CONV_XL_R1C1 )
7088cdf0e10cSrcweir     {
7089cdf0e10cSrcweir         // YUCK!  The XL interface actually treats rel R1C1 refs differently
7090cdf0e10cSrcweir         // than A1
7091cdf0e10cSrcweir         if( !(nFlags & SCA_COL_ABSOLUTE) )
7092cdf0e10cSrcweir             nCol += aPos.Col() + 1;
7093cdf0e10cSrcweir         if( !(nFlags & SCA_ROW_ABSOLUTE) )
7094cdf0e10cSrcweir             nRow += aPos.Row() + 1;
7095cdf0e10cSrcweir     }
7096cdf0e10cSrcweir 
7097cdf0e10cSrcweir     --nCol;
7098cdf0e10cSrcweir     --nRow;
7099cdf0e10cSrcweir     if(!ValidCol( nCol) || !ValidRow( nRow))
7100cdf0e10cSrcweir     {
7101cdf0e10cSrcweir         PushIllegalArgument();
7102cdf0e10cSrcweir         return;
7103cdf0e10cSrcweir     }
7104cdf0e10cSrcweir 
7105cdf0e10cSrcweir     String aRefStr;
7106cdf0e10cSrcweir     const ScAddress::Details aDetails( eConv, aPos );
7107cdf0e10cSrcweir     const ScAddress aAdr( nCol, nRow, 0);
7108cdf0e10cSrcweir     aAdr.Format( aRefStr, nFlags, pDok, aDetails );
7109cdf0e10cSrcweir 
7110cdf0e10cSrcweir     if( nParamCount >= 5 && sTabStr.Len() )
7111cdf0e10cSrcweir     {
7112cdf0e10cSrcweir         String aDoc;
7113cdf0e10cSrcweir         if (eConv == FormulaGrammar::CONV_OOO)
7114cdf0e10cSrcweir         {
7115cdf0e10cSrcweir             // Isolate Tab from 'Doc'#Tab
7116cdf0e10cSrcweir             xub_StrLen nPos = ScCompiler::GetDocTabPos( sTabStr);
7117cdf0e10cSrcweir             if (nPos != STRING_NOTFOUND)
7118cdf0e10cSrcweir             {
7119cdf0e10cSrcweir                 if (sTabStr.GetChar(nPos+1) == '$')
7120cdf0e10cSrcweir                     ++nPos;     // also split 'Doc'#$Tab
7121cdf0e10cSrcweir                 aDoc = sTabStr.Copy( 0, nPos+1);
7122cdf0e10cSrcweir                 sTabStr.Erase( 0, nPos+1);
7123cdf0e10cSrcweir             }
7124cdf0e10cSrcweir         }
7125cdf0e10cSrcweir         /* TODO: yet unsupported external reference in CONV_XL_R1C1 syntax may
7126cdf0e10cSrcweir          * need some extra handling to isolate Tab from Doc. */
7127cdf0e10cSrcweir         if (sTabStr.GetChar(0) != '\'' || sTabStr.GetChar(sTabStr.Len()-1) != '\'')
7128cdf0e10cSrcweir             ScCompiler::CheckTabQuotes( sTabStr, eConv);
7129cdf0e10cSrcweir         if (aDoc.Len())
7130cdf0e10cSrcweir             sTabStr.Insert( aDoc, 0);
7131cdf0e10cSrcweir         sTabStr += static_cast<sal_Unicode>(eConv == FormulaGrammar::CONV_XL_R1C1 ? '!' : '.');
7132cdf0e10cSrcweir         sTabStr += aRefStr;
7133cdf0e10cSrcweir         PushString( sTabStr );
7134cdf0e10cSrcweir     }
7135cdf0e10cSrcweir     else
7136cdf0e10cSrcweir         PushString( aRefStr );
7137cdf0e10cSrcweir }
7138cdf0e10cSrcweir 
7139cdf0e10cSrcweir 
lcl_CreateExternalRefSubroutine(const ScAddress & rPos,ScDocument * pDoc,const FormulaTokenRef & xExtRef)7140cdf0e10cSrcweir FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos,
7141cdf0e10cSrcweir         ScDocument* pDoc, const FormulaTokenRef& xExtRef )
7142cdf0e10cSrcweir {
7143cdf0e10cSrcweir     // The exact usage (which cell range) of the external table can't be
7144cdf0e10cSrcweir     // detected during the store-to-file cycle, mark it as permanently
7145cdf0e10cSrcweir     // referenced so it gets stored even if not directly referenced anywhere.
7146cdf0e10cSrcweir     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
7147cdf0e10cSrcweir     pRefMgr->setCacheTableReferencedPermanently(
7148cdf0e10cSrcweir             static_cast<const ScToken*>(xExtRef.get())->GetIndex(),
7149cdf0e10cSrcweir             static_cast<const ScToken*>(xExtRef.get())->GetString(), 1);
7150cdf0e10cSrcweir     ScTokenArray* pTokenArray = new ScTokenArray;
7151cdf0e10cSrcweir     pTokenArray->AddToken( *xExtRef);
7152cdf0e10cSrcweir     ScCompiler aComp( pDoc, rPos, *pTokenArray);
7153cdf0e10cSrcweir     aComp.CompileTokenArray();
7154cdf0e10cSrcweir     return new FormulaSubroutineToken( pTokenArray);
7155cdf0e10cSrcweir }
7156cdf0e10cSrcweir 
7157cdf0e10cSrcweir 
ScOffset()7158cdf0e10cSrcweir void ScInterpreter::ScOffset()
7159cdf0e10cSrcweir {
7160cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOffset" );
7161cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7162cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 3, 5 ) )
7163cdf0e10cSrcweir     {
7164cdf0e10cSrcweir         long nColNew = -1, nRowNew = -1, nColPlus, nRowPlus;
7165cdf0e10cSrcweir         if (nParamCount == 5)
7166cdf0e10cSrcweir             nColNew = (long) ::rtl::math::approxFloor(GetDouble());
7167cdf0e10cSrcweir         if (nParamCount >= 4)
7168cdf0e10cSrcweir             nRowNew = (long) ::rtl::math::approxFloor(GetDoubleWithDefault( -1.0 ));
7169cdf0e10cSrcweir         nColPlus = (long) ::rtl::math::approxFloor(GetDouble());
7170cdf0e10cSrcweir         nRowPlus = (long) ::rtl::math::approxFloor(GetDouble());
7171cdf0e10cSrcweir         SCCOL nCol1;
7172cdf0e10cSrcweir         SCROW nRow1;
7173cdf0e10cSrcweir         SCTAB nTab1;
7174cdf0e10cSrcweir         SCCOL nCol2;
7175cdf0e10cSrcweir         SCROW nRow2;
7176cdf0e10cSrcweir         SCTAB nTab2;
7177cdf0e10cSrcweir         if (nColNew == 0 || nRowNew == 0)
7178cdf0e10cSrcweir         {
7179cdf0e10cSrcweir             PushIllegalArgument();
7180cdf0e10cSrcweir             return;
7181cdf0e10cSrcweir         }
7182cdf0e10cSrcweir         FormulaTokenRef xExtRef;
7183cdf0e10cSrcweir         switch (GetStackType())
7184cdf0e10cSrcweir         {
7185cdf0e10cSrcweir             case svExternalSingleRef:
7186cdf0e10cSrcweir                 xExtRef = PopToken()->Clone();
7187cdf0e10cSrcweir                 // fallthru
7188cdf0e10cSrcweir             case svSingleRef:
7189cdf0e10cSrcweir                 {
7190cdf0e10cSrcweir                     if (xExtRef)
7191cdf0e10cSrcweir                     {
7192cdf0e10cSrcweir                         ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef();
7193cdf0e10cSrcweir                         rData.CalcAbsIfRel( aPos);
7194cdf0e10cSrcweir                         nCol1 = rData.nCol;
7195cdf0e10cSrcweir                         nRow1 = rData.nRow;
7196cdf0e10cSrcweir                         nTab1 = rData.nTab;
7197cdf0e10cSrcweir                     }
7198cdf0e10cSrcweir                     else
7199cdf0e10cSrcweir                         PopSingleRef( nCol1, nRow1, nTab1);
7200cdf0e10cSrcweir                     if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0))
7201cdf0e10cSrcweir                     {
7202cdf0e10cSrcweir                         nCol1 = (SCCOL)((long) nCol1 + nColPlus);
7203cdf0e10cSrcweir                         nRow1 = (SCROW)((long) nRow1 + nRowPlus);
7204cdf0e10cSrcweir                         if (!ValidCol(nCol1) || !ValidRow(nRow1))
7205cdf0e10cSrcweir                             PushIllegalArgument();
7206cdf0e10cSrcweir                         else if (xExtRef)
7207cdf0e10cSrcweir                         {
7208cdf0e10cSrcweir                             ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef();
7209cdf0e10cSrcweir                             rData.nCol = nCol1;
7210cdf0e10cSrcweir                             rData.nRow = nRow1;
7211cdf0e10cSrcweir                             rData.nTab = nTab1;
7212cdf0e10cSrcweir                             rData.CalcRelFromAbs( aPos);
7213cdf0e10cSrcweir                             // Push a subroutine that resolves the external
7214cdf0e10cSrcweir                             // reference as the next instruction.
7215cdf0e10cSrcweir                             PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7216cdf0e10cSrcweir                         }
7217cdf0e10cSrcweir                         else
7218cdf0e10cSrcweir                             PushSingleRef(nCol1, nRow1, nTab1);
7219cdf0e10cSrcweir                     }
7220cdf0e10cSrcweir                     else
7221cdf0e10cSrcweir                     {
7222cdf0e10cSrcweir                         if (nColNew < 0)
7223cdf0e10cSrcweir                             nColNew = 1;
7224cdf0e10cSrcweir                         if (nRowNew < 0)
7225cdf0e10cSrcweir                             nRowNew = 1;
7226cdf0e10cSrcweir                         nCol1 = (SCCOL)((long)nCol1+nColPlus);  // ! nCol1 is modified
7227cdf0e10cSrcweir                         nRow1 = (SCROW)((long)nRow1+nRowPlus);
7228cdf0e10cSrcweir                         nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7229cdf0e10cSrcweir                         nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7230cdf0e10cSrcweir                         if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
7231cdf0e10cSrcweir                                 !ValidCol(nCol2) || !ValidRow(nRow2))
7232cdf0e10cSrcweir                             PushIllegalArgument();
7233cdf0e10cSrcweir                         else if (xExtRef)
7234cdf0e10cSrcweir                         {
7235cdf0e10cSrcweir                             // Convert SingleRef to DoubleRef.
7236cdf0e10cSrcweir                             xExtRef = new ScExternalDoubleRefToken(
7237cdf0e10cSrcweir                                     *static_cast<const ScExternalSingleRefToken*>(xExtRef.get()));
7238cdf0e10cSrcweir                             ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7239cdf0e10cSrcweir                             rData.Ref1.nCol = nCol1;
7240cdf0e10cSrcweir                             rData.Ref1.nRow = nRow1;
7241cdf0e10cSrcweir                             rData.Ref1.nTab = nTab1;
7242cdf0e10cSrcweir                             rData.Ref2.nCol = nCol2;
7243cdf0e10cSrcweir                             rData.Ref2.nRow = nRow2;
7244cdf0e10cSrcweir                             rData.Ref2.nTab = nTab1;
7245cdf0e10cSrcweir                             rData.CalcRelFromAbs( aPos);
7246cdf0e10cSrcweir                             // Push a subroutine that resolves the external
7247cdf0e10cSrcweir                             // reference as the next instruction.
7248cdf0e10cSrcweir                             PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7249cdf0e10cSrcweir                         }
7250cdf0e10cSrcweir                         else
7251cdf0e10cSrcweir                             PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7252cdf0e10cSrcweir                     }
7253cdf0e10cSrcweir                 }
7254cdf0e10cSrcweir                 break;
7255cdf0e10cSrcweir             case svExternalDoubleRef:
7256cdf0e10cSrcweir                 xExtRef = PopToken()->Clone();
7257cdf0e10cSrcweir                 // fallthru
7258cdf0e10cSrcweir             case svDoubleRef:
7259cdf0e10cSrcweir                 {
7260cdf0e10cSrcweir                     if (xExtRef)
7261cdf0e10cSrcweir                     {
7262cdf0e10cSrcweir                         ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7263cdf0e10cSrcweir                         rData.CalcAbsIfRel( aPos);
7264cdf0e10cSrcweir                         nCol1 = rData.Ref1.nCol;
7265cdf0e10cSrcweir                         nRow1 = rData.Ref1.nRow;
7266cdf0e10cSrcweir                         nTab1 = rData.Ref1.nTab;
7267cdf0e10cSrcweir                         nCol2 = rData.Ref2.nCol;
7268cdf0e10cSrcweir                         nRow2 = rData.Ref2.nRow;
7269cdf0e10cSrcweir                         nTab2 = rData.Ref2.nTab;
7270cdf0e10cSrcweir                     }
7271cdf0e10cSrcweir                     else
7272cdf0e10cSrcweir                         PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7273cdf0e10cSrcweir                     if (nColNew < 0)
7274cdf0e10cSrcweir                         nColNew = nCol2 - nCol1 + 1;
7275cdf0e10cSrcweir                     if (nRowNew < 0)
7276cdf0e10cSrcweir                         nRowNew = nRow2 - nRow1 + 1;
7277cdf0e10cSrcweir                     nCol1 = (SCCOL)((long)nCol1+nColPlus);
7278cdf0e10cSrcweir                     nRow1 = (SCROW)((long)nRow1+nRowPlus);
7279cdf0e10cSrcweir                     nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7280cdf0e10cSrcweir                     nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7281cdf0e10cSrcweir                     if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
7282cdf0e10cSrcweir                             !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2)
7283cdf0e10cSrcweir                         PushIllegalArgument();
7284cdf0e10cSrcweir                     else if (xExtRef)
7285cdf0e10cSrcweir                     {
7286cdf0e10cSrcweir                         ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7287cdf0e10cSrcweir                         rData.Ref1.nCol = nCol1;
7288cdf0e10cSrcweir                         rData.Ref1.nRow = nRow1;
7289cdf0e10cSrcweir                         rData.Ref1.nTab = nTab1;
7290cdf0e10cSrcweir                         rData.Ref2.nCol = nCol2;
7291cdf0e10cSrcweir                         rData.Ref2.nRow = nRow2;
7292cdf0e10cSrcweir                         rData.Ref2.nTab = nTab1;
7293cdf0e10cSrcweir                         rData.CalcRelFromAbs( aPos);
7294cdf0e10cSrcweir                         // Push a subroutine that resolves the external
7295cdf0e10cSrcweir                         // reference as the next instruction.
7296cdf0e10cSrcweir                         PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7297cdf0e10cSrcweir                     }
7298cdf0e10cSrcweir                     else
7299cdf0e10cSrcweir                         PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7300cdf0e10cSrcweir                 }
7301cdf0e10cSrcweir                 break;
7302cdf0e10cSrcweir             default:
7303cdf0e10cSrcweir                 PushIllegalParameter();
7304cdf0e10cSrcweir         }
7305cdf0e10cSrcweir     }
7306cdf0e10cSrcweir }
7307cdf0e10cSrcweir 
7308cdf0e10cSrcweir 
ScIndex()7309cdf0e10cSrcweir void ScInterpreter::ScIndex()
7310cdf0e10cSrcweir {
7311cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndex" );
7312cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7313cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 4 ) )
7314cdf0e10cSrcweir     {
7315cdf0e10cSrcweir         long nArea;
7316cdf0e10cSrcweir         size_t nAreaCount;
7317cdf0e10cSrcweir         SCCOL nCol;
7318cdf0e10cSrcweir         SCROW nRow;
7319cdf0e10cSrcweir         if (nParamCount == 4)
7320cdf0e10cSrcweir             nArea = (long) ::rtl::math::approxFloor(GetDouble());
7321cdf0e10cSrcweir         else
7322cdf0e10cSrcweir             nArea = 1;
7323cdf0e10cSrcweir         if (nParamCount >= 3)
7324cdf0e10cSrcweir             nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7325cdf0e10cSrcweir         else
7326cdf0e10cSrcweir             nCol = 0;
7327cdf0e10cSrcweir         if (nParamCount >= 2)
7328cdf0e10cSrcweir             nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7329cdf0e10cSrcweir         else
7330cdf0e10cSrcweir             nRow = 0;
7331cdf0e10cSrcweir         if (GetStackType() == svRefList)
7332cdf0e10cSrcweir             nAreaCount = (sp ? static_cast<ScToken*>(pStack[sp-1])->GetRefList()->size() : 0);
7333cdf0e10cSrcweir         else
7334cdf0e10cSrcweir             nAreaCount = 1;     // one reference or array or whatever
7335cdf0e10cSrcweir         if (nAreaCount == 0 || (size_t)nArea > nAreaCount)
7336cdf0e10cSrcweir         {
7337cdf0e10cSrcweir             PushError( errNoRef);
7338cdf0e10cSrcweir             return;
7339cdf0e10cSrcweir         }
7340cdf0e10cSrcweir         else if (nArea < 1 || nCol < 0 || nRow < 0)
7341cdf0e10cSrcweir         {
7342cdf0e10cSrcweir             PushIllegalArgument();
7343cdf0e10cSrcweir             return;
7344cdf0e10cSrcweir         }
7345cdf0e10cSrcweir         switch (GetStackType())
7346cdf0e10cSrcweir         {
7347cdf0e10cSrcweir             case svMatrix:
7348cdf0e10cSrcweir                 {
7349cdf0e10cSrcweir                     if (nArea != 1)
7350cdf0e10cSrcweir                         SetError(errIllegalArgument);
7351cdf0e10cSrcweir                     sal_uInt16 nOldSp = sp;
7352cdf0e10cSrcweir                     ScMatrixRef pMat = GetMatrix();
7353cdf0e10cSrcweir                     if (pMat)
7354cdf0e10cSrcweir                     {
7355cdf0e10cSrcweir                         SCSIZE nC, nR;
7356cdf0e10cSrcweir                         pMat->GetDimensions(nC, nR);
7357cdf0e10cSrcweir                         // Access one element of a vector independent of col/row
7358cdf0e10cSrcweir                         // orientation?
7359cdf0e10cSrcweir                         bool bVector = ((nCol == 0 || nRow == 0) && (nC == 1 || nR == 1));
7360cdf0e10cSrcweir                         SCSIZE nElement = ::std::max( static_cast<SCSIZE>(nCol),
7361cdf0e10cSrcweir                                 static_cast<SCSIZE>(nRow));
7362cdf0e10cSrcweir                         if (nC == 0 || nR == 0 ||
7363cdf0e10cSrcweir                                 (!bVector && (static_cast<SCSIZE>(nCol) > nC ||
7364cdf0e10cSrcweir                                               static_cast<SCSIZE>(nRow) > nR)) ||
7365cdf0e10cSrcweir                                 (bVector && nElement > nC * nR))
7366cdf0e10cSrcweir                             PushIllegalArgument();
7367cdf0e10cSrcweir                         else if (nCol == 0 && nRow == 0)
7368cdf0e10cSrcweir                             sp = nOldSp;
7369cdf0e10cSrcweir                         else if (bVector)
7370cdf0e10cSrcweir                         {
7371cdf0e10cSrcweir                             --nElement;
7372cdf0e10cSrcweir                             if (pMat->IsString( nElement))
7373cdf0e10cSrcweir                                 PushString( pMat->GetString( nElement));
7374cdf0e10cSrcweir                             else
7375cdf0e10cSrcweir                                 PushDouble( pMat->GetDouble( nElement));
7376cdf0e10cSrcweir                         }
7377cdf0e10cSrcweir                         else if (nCol == 0)
7378cdf0e10cSrcweir                         {
7379cdf0e10cSrcweir                             ScMatrixRef pResMat = GetNewMat(nC, 1);
7380cdf0e10cSrcweir                             if (pResMat)
7381cdf0e10cSrcweir                             {
7382cdf0e10cSrcweir                                 SCSIZE nRowMinus1 = static_cast<SCSIZE>(nRow - 1);
7383cdf0e10cSrcweir                                 for (SCSIZE i = 0; i < nC; i++)
7384cdf0e10cSrcweir                                     if (!pMat->IsString(i, nRowMinus1))
7385cdf0e10cSrcweir                                         pResMat->PutDouble(pMat->GetDouble(i,
7386cdf0e10cSrcweir                                                     nRowMinus1), i, 0);
7387cdf0e10cSrcweir                                     else
7388cdf0e10cSrcweir                                         pResMat->PutString(pMat->GetString(i,
7389cdf0e10cSrcweir                                                     nRowMinus1), i, 0);
7390cdf0e10cSrcweir                                 PushMatrix(pResMat);
7391cdf0e10cSrcweir                             }
7392cdf0e10cSrcweir                             else
7393cdf0e10cSrcweir                                 PushIllegalArgument();
7394cdf0e10cSrcweir                         }
7395cdf0e10cSrcweir                         else if (nRow == 0)
7396cdf0e10cSrcweir                         {
7397cdf0e10cSrcweir                             ScMatrixRef pResMat = GetNewMat(1, nR);
7398cdf0e10cSrcweir                             if (pResMat)
7399cdf0e10cSrcweir                             {
7400cdf0e10cSrcweir                                 SCSIZE nColMinus1 = static_cast<SCSIZE>(nCol - 1);
7401cdf0e10cSrcweir                                 for (SCSIZE i = 0; i < nR; i++)
7402cdf0e10cSrcweir                                     if (!pMat->IsString(nColMinus1, i))
7403cdf0e10cSrcweir                                         pResMat->PutDouble(pMat->GetDouble(nColMinus1,
7404cdf0e10cSrcweir                                                     i), i);
7405cdf0e10cSrcweir                                     else
7406cdf0e10cSrcweir                                         pResMat->PutString(pMat->GetString(nColMinus1,
7407cdf0e10cSrcweir                                                     i), i);
7408cdf0e10cSrcweir                                 PushMatrix(pResMat);
7409cdf0e10cSrcweir                             }
7410cdf0e10cSrcweir                             else
7411cdf0e10cSrcweir                                 PushIllegalArgument();
7412cdf0e10cSrcweir                         }
7413cdf0e10cSrcweir                         else
7414cdf0e10cSrcweir                         {
7415cdf0e10cSrcweir                             if (!pMat->IsString( static_cast<SCSIZE>(nCol-1),
7416cdf0e10cSrcweir                                         static_cast<SCSIZE>(nRow-1)))
7417cdf0e10cSrcweir                                 PushDouble( pMat->GetDouble(
7418cdf0e10cSrcweir                                             static_cast<SCSIZE>(nCol-1),
7419cdf0e10cSrcweir                                             static_cast<SCSIZE>(nRow-1)));
7420cdf0e10cSrcweir                             else
7421cdf0e10cSrcweir                                 PushString( pMat->GetString(
7422cdf0e10cSrcweir                                             static_cast<SCSIZE>(nCol-1),
7423cdf0e10cSrcweir                                             static_cast<SCSIZE>(nRow-1)));
7424cdf0e10cSrcweir                         }
7425cdf0e10cSrcweir                     }
7426cdf0e10cSrcweir                 }
7427cdf0e10cSrcweir                 break;
7428cdf0e10cSrcweir             case svSingleRef:
7429cdf0e10cSrcweir                 {
7430cdf0e10cSrcweir                     SCCOL nCol1 = 0;
7431cdf0e10cSrcweir                     SCROW nRow1 = 0;
7432cdf0e10cSrcweir                     SCTAB nTab1 = 0;
7433cdf0e10cSrcweir                     PopSingleRef( nCol1, nRow1, nTab1);
7434cdf0e10cSrcweir                     if (nCol > 1 || nRow > 1)
7435cdf0e10cSrcweir                         PushIllegalArgument();
7436cdf0e10cSrcweir                     else
7437cdf0e10cSrcweir                         PushSingleRef( nCol1, nRow1, nTab1);
7438cdf0e10cSrcweir                 }
7439cdf0e10cSrcweir                 break;
7440cdf0e10cSrcweir             case svDoubleRef:
7441cdf0e10cSrcweir             case svRefList:
7442cdf0e10cSrcweir                 {
7443cdf0e10cSrcweir                     SCCOL nCol1 = 0;
7444cdf0e10cSrcweir                     SCROW nRow1 = 0;
7445cdf0e10cSrcweir                     SCTAB nTab1 = 0;
7446cdf0e10cSrcweir                     SCCOL nCol2 = 0;
7447cdf0e10cSrcweir                     SCROW nRow2 = 0;
7448cdf0e10cSrcweir                     SCTAB nTab2 = 0;
7449cdf0e10cSrcweir                     sal_Bool bRowArray = sal_False;
7450cdf0e10cSrcweir                     if (GetStackType() == svRefList)
7451cdf0e10cSrcweir                     {
7452cdf0e10cSrcweir                         FormulaTokenRef xRef = PopToken();
7453cdf0e10cSrcweir                         if (nGlobalError || !xRef)
7454cdf0e10cSrcweir                         {
7455cdf0e10cSrcweir                             PushIllegalParameter();
7456cdf0e10cSrcweir                             return;
7457cdf0e10cSrcweir                         }
7458cdf0e10cSrcweir                         ScRange aRange( ScAddress::UNINITIALIZED);
7459cdf0e10cSrcweir                         DoubleRefToRange( (*(static_cast<ScToken*>(xRef.get())->GetRefList()))[nArea-1], aRange);
7460cdf0e10cSrcweir                         aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7461cdf0e10cSrcweir                         if ( nParamCount == 2 && nRow1 == nRow2 )
7462cdf0e10cSrcweir                             bRowArray = sal_True;
7463cdf0e10cSrcweir                     }
7464cdf0e10cSrcweir                     else
7465cdf0e10cSrcweir                     {
7466cdf0e10cSrcweir                         PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7467cdf0e10cSrcweir                         if ( nParamCount == 2 && nRow1 == nRow2 )
7468cdf0e10cSrcweir                             bRowArray = sal_True;
7469cdf0e10cSrcweir                     }
7470cdf0e10cSrcweir                     if ( nTab1 != nTab2 ||
7471cdf0e10cSrcweir                             (nCol > 0 && nCol1+nCol-1 > nCol2) ||
7472cdf0e10cSrcweir                             (nRow > 0 && nRow1+nRow-1 > nRow2 && !bRowArray ) ||
7473cdf0e10cSrcweir                             ( nRow > nCol2 - nCol1 + 1 && bRowArray ))
7474cdf0e10cSrcweir                         PushIllegalArgument();
7475cdf0e10cSrcweir                     else if (nCol == 0 && nRow == 0)
7476cdf0e10cSrcweir                     {
7477cdf0e10cSrcweir                         if ( nCol1 == nCol2 && nRow1 == nRow2 )
7478cdf0e10cSrcweir                             PushSingleRef( nCol1, nRow1, nTab1 );
7479cdf0e10cSrcweir                         else
7480cdf0e10cSrcweir                             PushDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab1 );
7481cdf0e10cSrcweir                     }
7482cdf0e10cSrcweir                     else if (nRow == 0)
7483cdf0e10cSrcweir                     {
7484cdf0e10cSrcweir                         if ( nRow1 == nRow2 )
7485cdf0e10cSrcweir                             PushSingleRef( nCol1+nCol-1, nRow1, nTab1 );
7486cdf0e10cSrcweir                         else
7487cdf0e10cSrcweir                             PushDoubleRef( nCol1+nCol-1, nRow1, nTab1,
7488cdf0e10cSrcweir                                     nCol1+nCol-1, nRow2, nTab1 );
7489cdf0e10cSrcweir                     }
7490cdf0e10cSrcweir                     else if (nCol == 0)
7491cdf0e10cSrcweir                     {
7492cdf0e10cSrcweir                         if ( nCol1 == nCol2 )
7493cdf0e10cSrcweir                             PushSingleRef( nCol1, nRow1+nRow-1, nTab1 );
7494cdf0e10cSrcweir                         else if ( bRowArray )
7495cdf0e10cSrcweir                         {
7496cdf0e10cSrcweir                             nCol =(SCCOL) nRow;
7497cdf0e10cSrcweir                             nRow = 1;
7498cdf0e10cSrcweir                             PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7499cdf0e10cSrcweir                         }
7500cdf0e10cSrcweir                         else
7501cdf0e10cSrcweir                             PushDoubleRef( nCol1, nRow1+nRow-1, nTab1,
7502cdf0e10cSrcweir                                     nCol2, nRow1+nRow-1, nTab1);
7503cdf0e10cSrcweir                     }
7504cdf0e10cSrcweir                     else
7505cdf0e10cSrcweir                         PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7506cdf0e10cSrcweir                 }
7507cdf0e10cSrcweir                 break;
7508cdf0e10cSrcweir             default:
7509cdf0e10cSrcweir                 PushIllegalParameter();
7510cdf0e10cSrcweir         }
7511cdf0e10cSrcweir     }
7512cdf0e10cSrcweir }
7513cdf0e10cSrcweir 
7514cdf0e10cSrcweir 
ScMultiArea()7515cdf0e10cSrcweir void ScInterpreter::ScMultiArea()
7516cdf0e10cSrcweir {
7517cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMultiArea" );
7518cdf0e10cSrcweir     // Legacy support, convert to RefList
7519cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7520cdf0e10cSrcweir     if (MustHaveParamCountMin( nParamCount, 1))
7521cdf0e10cSrcweir     {
7522cdf0e10cSrcweir         while (!nGlobalError && nParamCount-- > 1)
7523cdf0e10cSrcweir         {
7524cdf0e10cSrcweir             ScUnionFunc();
7525cdf0e10cSrcweir         }
7526cdf0e10cSrcweir     }
7527cdf0e10cSrcweir }
7528cdf0e10cSrcweir 
7529cdf0e10cSrcweir 
ScAreas()7530cdf0e10cSrcweir void ScInterpreter::ScAreas()
7531cdf0e10cSrcweir {
7532cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAreas" );
7533cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7534cdf0e10cSrcweir     if (MustHaveParamCount( nParamCount, 1))
7535cdf0e10cSrcweir     {
7536cdf0e10cSrcweir         size_t nCount = 0;
7537cdf0e10cSrcweir         switch (GetStackType())
7538cdf0e10cSrcweir         {
7539cdf0e10cSrcweir             case svSingleRef:
7540cdf0e10cSrcweir                 {
7541cdf0e10cSrcweir                     FormulaTokenRef xT = PopToken();
7542cdf0e10cSrcweir                     ValidateRef( static_cast<ScToken*>(xT.get())->GetSingleRef());
7543cdf0e10cSrcweir                     ++nCount;
7544cdf0e10cSrcweir                 }
7545cdf0e10cSrcweir                 break;
7546cdf0e10cSrcweir             case svDoubleRef:
7547cdf0e10cSrcweir                 {
7548cdf0e10cSrcweir                     FormulaTokenRef xT = PopToken();
7549cdf0e10cSrcweir                     ValidateRef( static_cast<ScToken*>(xT.get())->GetDoubleRef());
7550cdf0e10cSrcweir                     ++nCount;
7551cdf0e10cSrcweir                 }
7552cdf0e10cSrcweir                 break;
7553cdf0e10cSrcweir             case svRefList:
7554cdf0e10cSrcweir                 {
7555cdf0e10cSrcweir                     FormulaTokenRef xT = PopToken();
7556cdf0e10cSrcweir                     ValidateRef( *(static_cast<ScToken*>(xT.get())->GetRefList()));
7557cdf0e10cSrcweir                     nCount += static_cast<ScToken*>(xT.get())->GetRefList()->size();
7558cdf0e10cSrcweir                 }
7559cdf0e10cSrcweir                 break;
7560cdf0e10cSrcweir             default:
7561cdf0e10cSrcweir                 SetError( errIllegalParameter);
7562cdf0e10cSrcweir         }
7563cdf0e10cSrcweir         PushDouble( double(nCount));
7564cdf0e10cSrcweir     }
7565cdf0e10cSrcweir }
7566cdf0e10cSrcweir 
7567cdf0e10cSrcweir 
ScCurrency()7568cdf0e10cSrcweir void ScInterpreter::ScCurrency()
7569cdf0e10cSrcweir {
7570cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCurrency" );
7571cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7572cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7573cdf0e10cSrcweir     {
7574cdf0e10cSrcweir         String aStr;
7575cdf0e10cSrcweir         double fDec;
7576cdf0e10cSrcweir         if (nParamCount == 2)
7577cdf0e10cSrcweir         {
7578cdf0e10cSrcweir             fDec = ::rtl::math::approxFloor(GetDouble());
7579cdf0e10cSrcweir             if (fDec < -15.0 || fDec > 15.0)
7580cdf0e10cSrcweir             {
7581cdf0e10cSrcweir                 PushIllegalArgument();
7582cdf0e10cSrcweir                 return;
7583cdf0e10cSrcweir             }
7584cdf0e10cSrcweir         }
7585cdf0e10cSrcweir         else
7586cdf0e10cSrcweir             fDec = 2.0;
7587cdf0e10cSrcweir         double fVal = GetDouble();
7588cdf0e10cSrcweir         double fFac;
7589cdf0e10cSrcweir         if ( fDec != 0.0 )
7590cdf0e10cSrcweir             fFac = pow( (double)10, fDec );
7591cdf0e10cSrcweir         else
7592cdf0e10cSrcweir             fFac = 1.0;
7593cdf0e10cSrcweir         if (fVal < 0.0)
7594cdf0e10cSrcweir             fVal = ceil(fVal*fFac-0.5)/fFac;
7595cdf0e10cSrcweir         else
7596cdf0e10cSrcweir             fVal = floor(fVal*fFac+0.5)/fFac;
7597cdf0e10cSrcweir         Color* pColor = NULL;
7598cdf0e10cSrcweir         if ( fDec < 0.0 )
7599cdf0e10cSrcweir             fDec = 0.0;
7600cdf0e10cSrcweir         sal_uLong nIndex = pFormatter->GetStandardFormat(
7601cdf0e10cSrcweir                                         NUMBERFORMAT_CURRENCY,
7602cdf0e10cSrcweir                                         ScGlobal::eLnge);
7603cdf0e10cSrcweir         if ( (sal_uInt16) fDec != pFormatter->GetFormatPrecision( nIndex ) )
7604cdf0e10cSrcweir         {
7605cdf0e10cSrcweir             String sFormatString;
7606cdf0e10cSrcweir             pFormatter->GenerateFormat(sFormatString,
7607cdf0e10cSrcweir                                                    nIndex,
7608cdf0e10cSrcweir                                                    ScGlobal::eLnge,
7609cdf0e10cSrcweir                                                    sal_True,        // mit Tausenderpunkt
7610cdf0e10cSrcweir                                                    sal_False,       // nicht rot
7611cdf0e10cSrcweir                                                   (sal_uInt16) fDec,// Nachkommastellen
7612cdf0e10cSrcweir                                                    1);          // 1 Vorkommanull
7613cdf0e10cSrcweir             if (!pFormatter->GetPreviewString(sFormatString,
7614cdf0e10cSrcweir                                                   fVal,
7615cdf0e10cSrcweir                                                   aStr,
7616cdf0e10cSrcweir                                                   &pColor,
7617cdf0e10cSrcweir                                                   ScGlobal::eLnge))
7618cdf0e10cSrcweir                 SetError(errIllegalArgument);
7619cdf0e10cSrcweir         }
7620cdf0e10cSrcweir         else
7621cdf0e10cSrcweir         {
7622cdf0e10cSrcweir             pFormatter->GetOutputString(fVal, nIndex, aStr, &pColor);
7623cdf0e10cSrcweir         }
7624cdf0e10cSrcweir         PushString(aStr);
7625cdf0e10cSrcweir     }
7626cdf0e10cSrcweir }
7627cdf0e10cSrcweir 
7628cdf0e10cSrcweir 
ScReplace()7629cdf0e10cSrcweir void ScInterpreter::ScReplace()
7630cdf0e10cSrcweir {
7631cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScReplace" );
7632cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 4 ) )
7633cdf0e10cSrcweir     {
7634cdf0e10cSrcweir         String aNewStr( GetString() );
7635cdf0e10cSrcweir         double fCount = ::rtl::math::approxFloor( GetDouble());
7636cdf0e10cSrcweir         double fPos   = ::rtl::math::approxFloor( GetDouble());
7637cdf0e10cSrcweir         String aOldStr( GetString() );
7638cdf0e10cSrcweir         if (fPos < 1.0 || fPos > static_cast<double>(STRING_MAXLEN)
7639cdf0e10cSrcweir                 || fCount < 0.0 || fCount > static_cast<double>(STRING_MAXLEN))
7640cdf0e10cSrcweir             PushIllegalArgument();
7641cdf0e10cSrcweir         else
7642cdf0e10cSrcweir         {
7643cdf0e10cSrcweir             xub_StrLen nCount = static_cast<xub_StrLen>(fCount);
7644cdf0e10cSrcweir             xub_StrLen nPos   = static_cast<xub_StrLen>(fPos);
7645cdf0e10cSrcweir             xub_StrLen nLen   = aOldStr.Len();
7646cdf0e10cSrcweir             if (nPos > nLen + 1)
7647cdf0e10cSrcweir                 nPos = nLen + 1;
7648cdf0e10cSrcweir             if (nCount > nLen - nPos + 1)
7649cdf0e10cSrcweir                 nCount = nLen - nPos + 1;
7650cdf0e10cSrcweir             aOldStr.Erase( nPos-1, nCount );
7651cdf0e10cSrcweir             if ( CheckStringResultLen( aOldStr, aNewStr ) )
7652cdf0e10cSrcweir                 aOldStr.Insert( aNewStr, nPos-1 );
7653cdf0e10cSrcweir             PushString( aOldStr );
7654cdf0e10cSrcweir         }
7655cdf0e10cSrcweir     }
7656cdf0e10cSrcweir }
7657cdf0e10cSrcweir 
7658cdf0e10cSrcweir 
ScFixed()7659cdf0e10cSrcweir void ScInterpreter::ScFixed()
7660cdf0e10cSrcweir {
7661cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFixed" );
7662cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7663cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 3 ) )
7664cdf0e10cSrcweir     {
7665cdf0e10cSrcweir         String aStr;
7666cdf0e10cSrcweir         double fDec;
7667cdf0e10cSrcweir         sal_Bool bThousand;
7668cdf0e10cSrcweir         if (nParamCount == 3)
7669cdf0e10cSrcweir             bThousand = !GetBool();     // Param TRUE: keine Tausenderpunkte
7670cdf0e10cSrcweir         else
7671cdf0e10cSrcweir             bThousand = sal_True;
7672cdf0e10cSrcweir         if (nParamCount >= 2)
7673cdf0e10cSrcweir         {
7674cdf0e10cSrcweir             fDec = ::rtl::math::approxFloor(GetDoubleWithDefault( 2.0 ));
7675cdf0e10cSrcweir             if (fDec < -15.0 || fDec > 15.0)
7676cdf0e10cSrcweir             {
7677cdf0e10cSrcweir                 PushIllegalArgument();
7678cdf0e10cSrcweir                 return;
7679cdf0e10cSrcweir             }
7680cdf0e10cSrcweir         }
7681cdf0e10cSrcweir         else
7682cdf0e10cSrcweir             fDec = 2.0;
7683cdf0e10cSrcweir         double fVal = GetDouble();
7684cdf0e10cSrcweir         double fFac;
7685cdf0e10cSrcweir         if ( fDec != 0.0 )
7686cdf0e10cSrcweir             fFac = pow( (double)10, fDec );
7687cdf0e10cSrcweir         else
7688cdf0e10cSrcweir             fFac = 1.0;
7689cdf0e10cSrcweir         if (fVal < 0.0)
7690cdf0e10cSrcweir             fVal = ceil(fVal*fFac-0.5)/fFac;
7691cdf0e10cSrcweir         else
7692cdf0e10cSrcweir             fVal = floor(fVal*fFac+0.5)/fFac;
7693cdf0e10cSrcweir         Color* pColor = NULL;
7694cdf0e10cSrcweir         String sFormatString;
7695cdf0e10cSrcweir         if (fDec < 0.0)
7696cdf0e10cSrcweir             fDec = 0.0;
7697cdf0e10cSrcweir         sal_uLong nIndex = pFormatter->GetStandardFormat(
7698cdf0e10cSrcweir                                             NUMBERFORMAT_NUMBER,
7699cdf0e10cSrcweir                                             ScGlobal::eLnge);
7700cdf0e10cSrcweir         pFormatter->GenerateFormat(sFormatString,
7701cdf0e10cSrcweir                                                nIndex,
7702cdf0e10cSrcweir                                                ScGlobal::eLnge,
7703cdf0e10cSrcweir                                                bThousand,   // mit Tausenderpunkt
7704cdf0e10cSrcweir                                                sal_False,       // nicht rot
7705cdf0e10cSrcweir                                                (sal_uInt16) fDec,// Nachkommastellen
7706cdf0e10cSrcweir                                                1);          // 1 Vorkommanull
7707cdf0e10cSrcweir         if (!pFormatter->GetPreviewString(sFormatString,
7708cdf0e10cSrcweir                                                   fVal,
7709cdf0e10cSrcweir                                                   aStr,
7710cdf0e10cSrcweir                                                   &pColor,
7711cdf0e10cSrcweir                                                   ScGlobal::eLnge))
7712cdf0e10cSrcweir             PushIllegalArgument();
7713cdf0e10cSrcweir         else
7714cdf0e10cSrcweir             PushString(aStr);
7715cdf0e10cSrcweir     }
7716cdf0e10cSrcweir }
7717cdf0e10cSrcweir 
7718cdf0e10cSrcweir 
ScFind()7719cdf0e10cSrcweir void ScInterpreter::ScFind()
7720cdf0e10cSrcweir {
7721cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFind" );
7722cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7723cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7724cdf0e10cSrcweir     {
7725cdf0e10cSrcweir         double fAnz;
7726cdf0e10cSrcweir         if (nParamCount == 3)
7727cdf0e10cSrcweir             fAnz = GetDouble();
7728cdf0e10cSrcweir         else
7729cdf0e10cSrcweir             fAnz = 1.0;
7730cdf0e10cSrcweir         String sStr = GetString();
7731cdf0e10cSrcweir         if( fAnz < 1.0 || fAnz > (double) sStr.Len() )
7732cdf0e10cSrcweir             PushNoValue();
7733cdf0e10cSrcweir         else
7734cdf0e10cSrcweir         {
7735cdf0e10cSrcweir             xub_StrLen nPos = sStr.Search( GetString(), (xub_StrLen) fAnz - 1 );
7736cdf0e10cSrcweir             if (nPos == STRING_NOTFOUND)
7737cdf0e10cSrcweir                 PushNoValue();
7738cdf0e10cSrcweir             else
7739cdf0e10cSrcweir                 PushDouble((double)(nPos + 1));
7740cdf0e10cSrcweir         }
7741cdf0e10cSrcweir     }
7742cdf0e10cSrcweir }
7743cdf0e10cSrcweir 
7744cdf0e10cSrcweir 
ScExact()7745cdf0e10cSrcweir void ScInterpreter::ScExact()
7746cdf0e10cSrcweir {
7747cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExact" );
7748cdf0e10cSrcweir     nFuncFmtType = NUMBERFORMAT_LOGICAL;
7749cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 2 ) )
7750cdf0e10cSrcweir     {
7751cdf0e10cSrcweir         String s1( GetString() );
7752cdf0e10cSrcweir         String s2( GetString() );
7753cdf0e10cSrcweir         PushInt( s1 == s2 );
7754cdf0e10cSrcweir     }
7755cdf0e10cSrcweir }
7756cdf0e10cSrcweir 
7757cdf0e10cSrcweir 
ScLeft()7758cdf0e10cSrcweir void ScInterpreter::ScLeft()
7759cdf0e10cSrcweir {
7760cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLeft" );
7761cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7762cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7763cdf0e10cSrcweir     {
7764cdf0e10cSrcweir         xub_StrLen n;
7765cdf0e10cSrcweir         if (nParamCount == 2)
7766cdf0e10cSrcweir         {
7767cdf0e10cSrcweir             double nVal = ::rtl::math::approxFloor(GetDouble());
7768cdf0e10cSrcweir             if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7769cdf0e10cSrcweir             {
7770cdf0e10cSrcweir                 PushIllegalArgument();
7771cdf0e10cSrcweir                 return ;
7772cdf0e10cSrcweir             }
7773cdf0e10cSrcweir             else
7774cdf0e10cSrcweir                 n = (xub_StrLen) nVal;
7775cdf0e10cSrcweir         }
7776cdf0e10cSrcweir         else
7777cdf0e10cSrcweir             n = 1;
7778cdf0e10cSrcweir         String aStr( GetString() );
7779cdf0e10cSrcweir         aStr.Erase( n );
7780cdf0e10cSrcweir         PushString( aStr );
7781cdf0e10cSrcweir     }
7782cdf0e10cSrcweir }
7783cdf0e10cSrcweir 
778439c2db0bSWang Lei typedef struct {
778539c2db0bSWang Lei     UBlockCode from;
778639c2db0bSWang Lei     UBlockCode to;
778739c2db0bSWang Lei } UBlockScript;
778839c2db0bSWang Lei 
778939c2db0bSWang Lei static UBlockScript scriptList[] = {
779039c2db0bSWang Lei     {UBLOCK_HANGUL_JAMO, UBLOCK_HANGUL_JAMO},
779139c2db0bSWang Lei     {UBLOCK_CJK_RADICALS_SUPPLEMENT, UBLOCK_HANGUL_SYLLABLES},
779239c2db0bSWang Lei     {UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS,UBLOCK_CJK_RADICALS_SUPPLEMENT },
779339c2db0bSWang Lei     {UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS},
779439c2db0bSWang Lei     {UBLOCK_CJK_COMPATIBILITY_FORMS, UBLOCK_CJK_COMPATIBILITY_FORMS},
779539c2db0bSWang Lei     {UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS, UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS},
779639c2db0bSWang Lei     {UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT},
779739c2db0bSWang Lei     {UBLOCK_CJK_STROKES, UBLOCK_CJK_STROKES}
779839c2db0bSWang Lei };
779939c2db0bSWang Lei #define scriptListCount sizeof (scriptList) / sizeof (UBlockScript)
lcl_getScriptClass(sal_uInt32 currentChar)780039c2db0bSWang Lei bool SAL_CALL lcl_getScriptClass(sal_uInt32 currentChar)
780139c2db0bSWang Lei {
780239c2db0bSWang Lei     // for the locale of ja-JP, character U+0x005c and U+0x20ac should be ScriptType::Asian
780339c2db0bSWang Lei     if( (currentChar == 0x005c || currentChar == 0x20ac) &&
780439c2db0bSWang Lei           (MsLangId::getSystemLanguage() == LANGUAGE_JAPANESE) )
780539c2db0bSWang Lei         return true;
780639c2db0bSWang Lei     sal_uInt16 i;
780739c2db0bSWang Lei     static sal_Int16 nRet = 0;
780839c2db0bSWang Lei     UBlockCode block = (UBlockCode)ublock_getCode((sal_uInt32)currentChar);
780939c2db0bSWang Lei     for ( i = 0; i < scriptListCount; i++) {
781039c2db0bSWang Lei         if (block <= scriptList[i].to) break;
781139c2db0bSWang Lei     }
781239c2db0bSWang Lei     nRet = (i < scriptListCount && block >= scriptList[i].from);
781339c2db0bSWang Lei     return nRet;
781439c2db0bSWang Lei }
IsDBCS(sal_Unicode ch)781539c2db0bSWang Lei bool IsDBCS(sal_Unicode ch)
781639c2db0bSWang Lei {
781739c2db0bSWang Lei     return lcl_getScriptClass(ch);
781839c2db0bSWang Lei }
getLengthB(String & str)781939c2db0bSWang Lei sal_Int32 getLengthB(String &str)
782039c2db0bSWang Lei {
7821a845386bSAndre Fischer     xub_StrLen index = 0;
782239c2db0bSWang Lei     sal_Int32 length = 0;
782339c2db0bSWang Lei     if(0 == str.Len())
782439c2db0bSWang Lei         return 0;
782539c2db0bSWang Lei     while(index < str.Len()){
782639c2db0bSWang Lei         if(IsDBCS(str.GetChar(index)))
782739c2db0bSWang Lei             length += 2;
782839c2db0bSWang Lei         else
782939c2db0bSWang Lei             length++;
783039c2db0bSWang Lei         index++;
783139c2db0bSWang Lei     }
783239c2db0bSWang Lei     return length;
783339c2db0bSWang Lei }
ScLenB()783439c2db0bSWang Lei void ScInterpreter::ScLenB()
783539c2db0bSWang Lei {
783639c2db0bSWang Lei     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLenB" );
783739c2db0bSWang Lei     String aStr( GetString() );
783839c2db0bSWang Lei     PushDouble( getLengthB(aStr) );
783939c2db0bSWang Lei }
lcl_RightB(String & aStr,sal_Int32 n)784039c2db0bSWang Lei void lcl_RightB(String &aStr, sal_Int32 n)
784139c2db0bSWang Lei {
784239c2db0bSWang Lei     if( n < getLengthB(aStr) )
784339c2db0bSWang Lei     {
784439c2db0bSWang Lei         sal_Int32 index = aStr.Len();
784539c2db0bSWang Lei         while(index-- >= 0)
784639c2db0bSWang Lei         {
784739c2db0bSWang Lei             if(0 == n)
784839c2db0bSWang Lei             {
784939c2db0bSWang Lei                 aStr.Erase( 0, index + 1);
785039c2db0bSWang Lei                 break;
785139c2db0bSWang Lei             }
785239c2db0bSWang Lei             if(-1 == n)
785339c2db0bSWang Lei             {
785439c2db0bSWang Lei                 aStr.Erase( 0, index + 2 );
785539c2db0bSWang Lei                 aStr.InsertAscii(" ", 0);
785639c2db0bSWang Lei                 break;
785739c2db0bSWang Lei             }
785839c2db0bSWang Lei             if(IsDBCS(aStr.GetChar(index)))
785939c2db0bSWang Lei                 n -= 2;
786039c2db0bSWang Lei             else
786139c2db0bSWang Lei                 n--;
786239c2db0bSWang Lei         }
786339c2db0bSWang Lei     }
786439c2db0bSWang Lei }
ScRightB()786539c2db0bSWang Lei void ScInterpreter::ScRightB()
786639c2db0bSWang Lei {
786739c2db0bSWang Lei     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScRightB" );
786839c2db0bSWang Lei     sal_uInt8 nParamCount = GetByte();
786939c2db0bSWang Lei     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
787039c2db0bSWang Lei     {
787139c2db0bSWang Lei         sal_Int32 n;
787239c2db0bSWang Lei         if (nParamCount == 2)
787339c2db0bSWang Lei         {
787439c2db0bSWang Lei             double nVal = ::rtl::math::approxFloor(GetDouble());
787539c2db0bSWang Lei             if ( nVal < 0.0 || nVal > STRING_MAXLEN )
787639c2db0bSWang Lei             {
787739c2db0bSWang Lei                 PushIllegalArgument();
787839c2db0bSWang Lei                 return ;
787939c2db0bSWang Lei             }
788039c2db0bSWang Lei             else
788139c2db0bSWang Lei                 n = (xub_StrLen) nVal;
788239c2db0bSWang Lei         }
788339c2db0bSWang Lei         else
788439c2db0bSWang Lei             n = 1;
788539c2db0bSWang Lei         String aStr( GetString() );
788639c2db0bSWang Lei         lcl_RightB(aStr, n);
788739c2db0bSWang Lei         PushString( aStr );
788839c2db0bSWang Lei     }
788939c2db0bSWang Lei }
lcl_LeftB(String & aStr,sal_Int32 n)789039c2db0bSWang Lei void lcl_LeftB(String &aStr, sal_Int32 n)
789139c2db0bSWang Lei {
789239c2db0bSWang Lei     if( n < getLengthB(aStr) )
789339c2db0bSWang Lei     {
789439c2db0bSWang Lei         sal_Int32 index = -1;
789539c2db0bSWang Lei         while(index++ < aStr.Len())
789639c2db0bSWang Lei         {
789739c2db0bSWang Lei             if(0 == n)
789839c2db0bSWang Lei             {
789939c2db0bSWang Lei                 aStr.Erase( index );
790039c2db0bSWang Lei                 break;
790139c2db0bSWang Lei             }
790239c2db0bSWang Lei             if(-1 == n)
790339c2db0bSWang Lei             {
790439c2db0bSWang Lei                 aStr.Erase( index - 1 );
790539c2db0bSWang Lei                 aStr.InsertAscii(" ");
790639c2db0bSWang Lei                 break;
790739c2db0bSWang Lei             }
790839c2db0bSWang Lei             if(IsDBCS(aStr.GetChar(index)))
790939c2db0bSWang Lei                 n -= 2;
791039c2db0bSWang Lei             else
791139c2db0bSWang Lei                 n--;
791239c2db0bSWang Lei         }
791339c2db0bSWang Lei     }
791439c2db0bSWang Lei }
ScLeftB()791539c2db0bSWang Lei void ScInterpreter::ScLeftB()
791639c2db0bSWang Lei {
791739c2db0bSWang Lei     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLeftB" );
791839c2db0bSWang Lei     sal_uInt8 nParamCount = GetByte();
791939c2db0bSWang Lei     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
792039c2db0bSWang Lei     {
792139c2db0bSWang Lei         sal_Int32 n;
792239c2db0bSWang Lei         if (nParamCount == 2)
792339c2db0bSWang Lei         {
792439c2db0bSWang Lei             double nVal = ::rtl::math::approxFloor(GetDouble());
792539c2db0bSWang Lei             if ( nVal < 0.0 || nVal > STRING_MAXLEN )
792639c2db0bSWang Lei             {
792739c2db0bSWang Lei                 PushIllegalArgument();
792839c2db0bSWang Lei                 return ;
792939c2db0bSWang Lei             }
793039c2db0bSWang Lei             else
793139c2db0bSWang Lei                 n = (xub_StrLen) nVal;
793239c2db0bSWang Lei         }
793339c2db0bSWang Lei         else
793439c2db0bSWang Lei             n = 1;
793539c2db0bSWang Lei         String aStr( GetString() );
793639c2db0bSWang Lei         lcl_LeftB(aStr, n);
793739c2db0bSWang Lei         PushString( aStr );
793839c2db0bSWang Lei     }
793939c2db0bSWang Lei }
ScMidB()794039c2db0bSWang Lei void ScInterpreter::ScMidB()
794139c2db0bSWang Lei {
794239c2db0bSWang Lei     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScMidB" );
794339c2db0bSWang Lei     if ( MustHaveParamCount( GetByte(), 3 ) )
794439c2db0bSWang Lei     {
794539c2db0bSWang Lei         double fAnz    = ::rtl::math::approxFloor(GetDouble());
794639c2db0bSWang Lei         double fAnfang = ::rtl::math::approxFloor(GetDouble());
794739c2db0bSWang Lei         String rStr( GetString() );
794839c2db0bSWang Lei         if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
794939c2db0bSWang Lei             PushIllegalArgument();
795039c2db0bSWang Lei         else
795139c2db0bSWang Lei         {
795239c2db0bSWang Lei 
795339c2db0bSWang Lei             lcl_LeftB(rStr, (xub_StrLen)fAnfang + (xub_StrLen)fAnz - 1);
795439c2db0bSWang Lei             sal_Int32 nCnt = getLengthB(rStr) - (xub_StrLen)fAnfang + 1;
795539c2db0bSWang Lei             lcl_RightB(rStr, nCnt>0 ? nCnt:0);
795639c2db0bSWang Lei             PushString(rStr);
795739c2db0bSWang Lei         }
795839c2db0bSWang Lei     }
795939c2db0bSWang Lei }
7960cdf0e10cSrcweir 
ScRight()7961cdf0e10cSrcweir void ScInterpreter::ScRight()
7962cdf0e10cSrcweir {
7963cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRight" );
7964cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7965cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7966cdf0e10cSrcweir     {
7967cdf0e10cSrcweir         xub_StrLen n;
7968cdf0e10cSrcweir         if (nParamCount == 2)
7969cdf0e10cSrcweir         {
7970cdf0e10cSrcweir             double nVal = ::rtl::math::approxFloor(GetDouble());
7971cdf0e10cSrcweir             if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7972cdf0e10cSrcweir             {
7973cdf0e10cSrcweir                 PushIllegalArgument();
7974cdf0e10cSrcweir                 return ;
7975cdf0e10cSrcweir             }
7976cdf0e10cSrcweir             else
7977cdf0e10cSrcweir                 n = (xub_StrLen) nVal;
7978cdf0e10cSrcweir         }
7979cdf0e10cSrcweir         else
7980cdf0e10cSrcweir             n = 1;
7981cdf0e10cSrcweir         String aStr( GetString() );
7982cdf0e10cSrcweir         if( n < aStr.Len() )
7983cdf0e10cSrcweir             aStr.Erase( 0, aStr.Len() - n );
7984cdf0e10cSrcweir         PushString( aStr );
7985cdf0e10cSrcweir     }
7986cdf0e10cSrcweir }
7987cdf0e10cSrcweir 
7988cdf0e10cSrcweir 
ScSearch()7989cdf0e10cSrcweir void ScInterpreter::ScSearch()
7990cdf0e10cSrcweir {
7991cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSearch" );
7992cdf0e10cSrcweir     double fAnz;
7993cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
7994cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7995cdf0e10cSrcweir     {
7996cdf0e10cSrcweir         if (nParamCount == 3)
7997cdf0e10cSrcweir         {
7998cdf0e10cSrcweir             fAnz = ::rtl::math::approxFloor(GetDouble());
7999cdf0e10cSrcweir             if (fAnz > double(STRING_MAXLEN))
8000cdf0e10cSrcweir             {
8001cdf0e10cSrcweir                 PushIllegalArgument();
8002cdf0e10cSrcweir                 return;
8003cdf0e10cSrcweir             }
8004cdf0e10cSrcweir         }
8005cdf0e10cSrcweir         else
8006cdf0e10cSrcweir             fAnz = 1.0;
8007cdf0e10cSrcweir         String sStr = GetString();
8008cdf0e10cSrcweir         String SearchStr = GetString();
8009cdf0e10cSrcweir         xub_StrLen nPos = (xub_StrLen) fAnz - 1;
8010cdf0e10cSrcweir         xub_StrLen nEndPos = sStr.Len();
8011cdf0e10cSrcweir         if( nPos >= nEndPos )
8012cdf0e10cSrcweir             PushNoValue();
8013cdf0e10cSrcweir         else
8014cdf0e10cSrcweir         {
8015cdf0e10cSrcweir             utl::SearchParam::SearchType eSearchType =
8016cdf0e10cSrcweir                 (MayBeRegExp( SearchStr, pDok ) ?
8017cdf0e10cSrcweir                 utl::SearchParam::SRCH_REGEXP : utl::SearchParam::SRCH_NORMAL);
8018cdf0e10cSrcweir             utl::SearchParam sPar(SearchStr, eSearchType, sal_False, sal_False, sal_False);
8019cdf0e10cSrcweir             utl::TextSearch sT( sPar, *ScGlobal::pCharClass );
8020cdf0e10cSrcweir             int nBool = sT.SearchFrwrd(sStr, &nPos, &nEndPos);
8021cdf0e10cSrcweir             if (!nBool)
8022cdf0e10cSrcweir                 PushNoValue();
8023cdf0e10cSrcweir             else
8024cdf0e10cSrcweir                 PushDouble((double)(nPos) + 1);
8025cdf0e10cSrcweir         }
8026cdf0e10cSrcweir     }
8027cdf0e10cSrcweir }
8028cdf0e10cSrcweir 
8029cdf0e10cSrcweir 
ScMid()8030cdf0e10cSrcweir void ScInterpreter::ScMid()
8031cdf0e10cSrcweir {
8032cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMid" );
8033cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 3 ) )
8034cdf0e10cSrcweir     {
8035cdf0e10cSrcweir         double fAnz    = ::rtl::math::approxFloor(GetDouble());
8036cdf0e10cSrcweir         double fAnfang = ::rtl::math::approxFloor(GetDouble());
8037cdf0e10cSrcweir         const String& rStr = GetString();
8038cdf0e10cSrcweir         if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
8039cdf0e10cSrcweir             PushIllegalArgument();
8040cdf0e10cSrcweir         else
8041cdf0e10cSrcweir             PushString(rStr.Copy( (xub_StrLen) fAnfang - 1, (xub_StrLen) fAnz ));
8042cdf0e10cSrcweir     }
8043cdf0e10cSrcweir }
8044cdf0e10cSrcweir 
8045cdf0e10cSrcweir 
ScText()8046cdf0e10cSrcweir void ScInterpreter::ScText()
8047cdf0e10cSrcweir {
8048cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScText" );
8049cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 2 ) )
8050cdf0e10cSrcweir     {
8051cdf0e10cSrcweir         String sFormatString = GetString();
8052cdf0e10cSrcweir         String aStr;
8053cdf0e10cSrcweir         bool bString = false;
8054cdf0e10cSrcweir         double fVal = 0.0;
8055cdf0e10cSrcweir         switch (GetStackType())
8056cdf0e10cSrcweir         {
8057cdf0e10cSrcweir             case svError:
8058cdf0e10cSrcweir                 PopError();
8059cdf0e10cSrcweir                 break;
8060cdf0e10cSrcweir             case svDouble:
8061cdf0e10cSrcweir                 fVal = PopDouble();
8062cdf0e10cSrcweir                 break;
8063cdf0e10cSrcweir             default:
8064cdf0e10cSrcweir                 {
8065cdf0e10cSrcweir                     FormulaTokenRef xTok( PopToken());
8066cdf0e10cSrcweir                     if (!nGlobalError)
8067cdf0e10cSrcweir                     {
8068cdf0e10cSrcweir                         PushTempToken( xTok);
8069cdf0e10cSrcweir                         // Temporarily override the ConvertStringToValue()
8070cdf0e10cSrcweir                         // error for GetCellValue() / GetCellValueOrZero()
8071cdf0e10cSrcweir                         sal_uInt16 nSErr = mnStringNoValueError;
8072cdf0e10cSrcweir                         mnStringNoValueError = errNotNumericString;
8073cdf0e10cSrcweir                         fVal = GetDouble();
8074cdf0e10cSrcweir                         mnStringNoValueError = nSErr;
8075cdf0e10cSrcweir                         if (nGlobalError == errNotNumericString)
8076cdf0e10cSrcweir                         {
8077cdf0e10cSrcweir                             // Not numeric.
8078cdf0e10cSrcweir                             nGlobalError = 0;
8079cdf0e10cSrcweir                             PushTempToken( xTok);
8080cdf0e10cSrcweir                             aStr = GetString();
8081cdf0e10cSrcweir                             bString = true;
8082cdf0e10cSrcweir                         }
8083cdf0e10cSrcweir                     }
8084cdf0e10cSrcweir                 }
8085cdf0e10cSrcweir         }
8086cdf0e10cSrcweir         if (nGlobalError)
8087cdf0e10cSrcweir             PushError( nGlobalError);
8088cdf0e10cSrcweir         else
8089cdf0e10cSrcweir         {
8090cdf0e10cSrcweir             String aResult;
8091cdf0e10cSrcweir             Color* pColor = NULL;
8092cdf0e10cSrcweir             LanguageType eCellLang;
8093cdf0e10cSrcweir             const ScPatternAttr* pPattern = pDok->GetPattern(
8094cdf0e10cSrcweir                     aPos.Col(), aPos.Row(), aPos.Tab() );
8095cdf0e10cSrcweir             if ( pPattern )
8096cdf0e10cSrcweir                 eCellLang = ((const SvxLanguageItem&)
8097cdf0e10cSrcweir                         pPattern->GetItem( ATTR_LANGUAGE_FORMAT )).GetValue();
8098cdf0e10cSrcweir             else
8099cdf0e10cSrcweir                 eCellLang = ScGlobal::eLnge;
8100cdf0e10cSrcweir             if (bString)
8101cdf0e10cSrcweir             {
8102cdf0e10cSrcweir                 if (!pFormatter->GetPreviewString( sFormatString, aStr,
8103cdf0e10cSrcweir                             aResult, &pColor, eCellLang))
8104cdf0e10cSrcweir                     PushIllegalArgument();
8105cdf0e10cSrcweir                 else
8106cdf0e10cSrcweir                     PushString( aResult);
8107cdf0e10cSrcweir             }
8108cdf0e10cSrcweir             else
8109cdf0e10cSrcweir             {
8110cdf0e10cSrcweir                 if (!pFormatter->GetPreviewStringGuess( sFormatString, fVal,
8111cdf0e10cSrcweir                             aResult, &pColor, eCellLang))
8112cdf0e10cSrcweir                     PushIllegalArgument();
8113cdf0e10cSrcweir                 else
8114cdf0e10cSrcweir                     PushString( aResult);
8115cdf0e10cSrcweir             }
8116cdf0e10cSrcweir         }
8117cdf0e10cSrcweir     }
8118cdf0e10cSrcweir }
8119cdf0e10cSrcweir 
8120cdf0e10cSrcweir 
ScSubstitute()8121cdf0e10cSrcweir void ScInterpreter::ScSubstitute()
8122cdf0e10cSrcweir {
8123cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubstitute" );
8124cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
8125cdf0e10cSrcweir     if ( MustHaveParamCount( nParamCount, 3, 4 ) )
8126cdf0e10cSrcweir     {
8127cdf0e10cSrcweir         xub_StrLen nAnz;
8128cdf0e10cSrcweir         if (nParamCount == 4)
8129cdf0e10cSrcweir         {
8130cdf0e10cSrcweir             double fAnz = ::rtl::math::approxFloor(GetDouble());
8131cdf0e10cSrcweir             if( fAnz < 1 || fAnz > STRING_MAXLEN )
8132cdf0e10cSrcweir             {
8133cdf0e10cSrcweir                 PushIllegalArgument();
8134cdf0e10cSrcweir                 return;
8135cdf0e10cSrcweir             }
8136cdf0e10cSrcweir             else
8137cdf0e10cSrcweir                 nAnz = (xub_StrLen) fAnz;
8138cdf0e10cSrcweir         }
8139cdf0e10cSrcweir         else
8140cdf0e10cSrcweir             nAnz = 0;
8141cdf0e10cSrcweir         String sNewStr = GetString();
8142cdf0e10cSrcweir         String sOldStr = GetString();
8143cdf0e10cSrcweir         String sStr    = GetString();
8144cdf0e10cSrcweir         xub_StrLen nPos = 0;
8145cdf0e10cSrcweir         xub_StrLen nCount = 0;
8146cdf0e10cSrcweir         xub_StrLen nNewLen = sNewStr.Len();
8147cdf0e10cSrcweir         xub_StrLen nOldLen = sOldStr.Len();
8148cdf0e10cSrcweir         while( sal_True )
8149cdf0e10cSrcweir         {
8150cdf0e10cSrcweir             nPos = sStr.Search( sOldStr, nPos );
8151cdf0e10cSrcweir             if (nPos != STRING_NOTFOUND)
8152cdf0e10cSrcweir             {
8153cdf0e10cSrcweir                 nCount++;
8154cdf0e10cSrcweir                 if( !nAnz || nCount == nAnz )
8155cdf0e10cSrcweir                 {
8156cdf0e10cSrcweir                     sStr.Erase(nPos,nOldLen);
8157cdf0e10cSrcweir                     if ( CheckStringResultLen( sStr, sNewStr ) )
8158cdf0e10cSrcweir                     {
8159cdf0e10cSrcweir                         sStr.Insert(sNewStr,nPos);
8160cdf0e10cSrcweir                         nPos = sal::static_int_cast<xub_StrLen>( nPos + nNewLen );
8161cdf0e10cSrcweir                     }
8162cdf0e10cSrcweir                     else
8163cdf0e10cSrcweir                         break;
8164cdf0e10cSrcweir                 }
8165cdf0e10cSrcweir                 else
8166cdf0e10cSrcweir                     nPos++;
8167cdf0e10cSrcweir             }
8168cdf0e10cSrcweir             else
8169cdf0e10cSrcweir                 break;
8170cdf0e10cSrcweir         }
8171cdf0e10cSrcweir         PushString( sStr );
8172cdf0e10cSrcweir     }
8173cdf0e10cSrcweir }
8174cdf0e10cSrcweir 
8175cdf0e10cSrcweir 
ScRept()8176cdf0e10cSrcweir void ScInterpreter::ScRept()
8177cdf0e10cSrcweir {
8178cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRept" );
8179cdf0e10cSrcweir     if ( MustHaveParamCount( GetByte(), 2 ) )
8180cdf0e10cSrcweir     {
8181cdf0e10cSrcweir         double fAnz = ::rtl::math::approxFloor(GetDouble());
8182cdf0e10cSrcweir         String aStr( GetString() );
8183cdf0e10cSrcweir         if ( fAnz < 0.0 )
8184cdf0e10cSrcweir             PushIllegalArgument();
8185cdf0e10cSrcweir         else if ( fAnz * aStr.Len() > STRING_MAXLEN )
8186cdf0e10cSrcweir         {
8187cdf0e10cSrcweir             PushError( errStringOverflow );
8188cdf0e10cSrcweir         }
8189cdf0e10cSrcweir         else if ( fAnz == 0.0 )
8190cdf0e10cSrcweir             PushString( EMPTY_STRING );
8191cdf0e10cSrcweir         else
8192cdf0e10cSrcweir         {
8193cdf0e10cSrcweir             xub_StrLen n = (xub_StrLen) fAnz;
8194cdf0e10cSrcweir             const xub_StrLen nLen = aStr.Len();
8195cdf0e10cSrcweir             String aRes;
8196cdf0e10cSrcweir             const sal_Unicode* const pSrc = aStr.GetBuffer();
8197cdf0e10cSrcweir             sal_Unicode* pDst = aRes.AllocBuffer( n * nLen );
8198cdf0e10cSrcweir             while( n-- )
8199cdf0e10cSrcweir             {
8200cdf0e10cSrcweir                 memcpy( pDst, pSrc, nLen * sizeof(sal_Unicode) );
8201cdf0e10cSrcweir                 pDst += nLen;
8202cdf0e10cSrcweir             }
8203cdf0e10cSrcweir             PushString( aRes );
8204cdf0e10cSrcweir         }
8205cdf0e10cSrcweir     }
8206cdf0e10cSrcweir }
8207cdf0e10cSrcweir 
8208cdf0e10cSrcweir 
ScConcat()8209cdf0e10cSrcweir void ScInterpreter::ScConcat()
8210cdf0e10cSrcweir {
8211cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScConcat" );
8212cdf0e10cSrcweir     sal_uInt8 nParamCount = GetByte();
8213cdf0e10cSrcweir     String aRes;
8214cdf0e10cSrcweir     while( nParamCount-- > 0)
8215cdf0e10cSrcweir     {
8216cdf0e10cSrcweir         const String& rStr = GetString();
8217cdf0e10cSrcweir         aRes.Insert( rStr, 0 );
8218cdf0e10cSrcweir     }
8219cdf0e10cSrcweir     PushString( aRes );
8220cdf0e10cSrcweir }
8221cdf0e10cSrcweir 
8222cdf0e10cSrcweir 
ScErrorType()8223cdf0e10cSrcweir void ScInterpreter::ScErrorType()
8224cdf0e10cSrcweir {
8225cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScErrorType" );
8226cdf0e10cSrcweir     sal_uInt16 nErr;
8227cdf0e10cSrcweir     sal_uInt16 nOldError = nGlobalError;
8228cdf0e10cSrcweir     nGlobalError = 0;
8229cdf0e10cSrcweir     switch ( GetStackType() )
8230cdf0e10cSrcweir     {
8231cdf0e10cSrcweir         case svRefList :
8232cdf0e10cSrcweir         {
8233cdf0e10cSrcweir             FormulaTokenRef x = PopToken();
8234cdf0e10cSrcweir             if (nGlobalError)
8235cdf0e10cSrcweir                 nErr = nGlobalError;
8236cdf0e10cSrcweir             else
8237cdf0e10cSrcweir             {
8238cdf0e10cSrcweir                 const ScRefList* pRefList = static_cast<ScToken*>(x.get())->GetRefList();
8239cdf0e10cSrcweir                 size_t n = pRefList->size();
8240cdf0e10cSrcweir                 if (!n)
8241cdf0e10cSrcweir                     nErr = errNoRef;
8242cdf0e10cSrcweir                 else if (n > 1)
8243cdf0e10cSrcweir                     nErr = errNoValue;
8244cdf0e10cSrcweir                 else
8245cdf0e10cSrcweir                 {
8246cdf0e10cSrcweir                     ScRange aRange;
8247cdf0e10cSrcweir                     DoubleRefToRange( (*pRefList)[0], aRange);
8248cdf0e10cSrcweir                     if (nGlobalError)
8249cdf0e10cSrcweir                         nErr = nGlobalError;
8250cdf0e10cSrcweir                     else
8251cdf0e10cSrcweir                     {
8252cdf0e10cSrcweir                         ScAddress aAdr;
8253cdf0e10cSrcweir                         if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8254cdf0e10cSrcweir                             nErr = pDok->GetErrCode( aAdr );
8255cdf0e10cSrcweir                         else
8256cdf0e10cSrcweir                             nErr = nGlobalError;
8257cdf0e10cSrcweir                     }
8258cdf0e10cSrcweir                 }
8259cdf0e10cSrcweir             }
8260cdf0e10cSrcweir         }
8261cdf0e10cSrcweir         break;
8262cdf0e10cSrcweir         case svDoubleRef :
8263cdf0e10cSrcweir         {
8264cdf0e10cSrcweir             ScRange aRange;
8265cdf0e10cSrcweir             PopDoubleRef( aRange );
8266cdf0e10cSrcweir             if ( nGlobalError )
8267cdf0e10cSrcweir                 nErr = nGlobalError;
8268cdf0e10cSrcweir             else
8269cdf0e10cSrcweir             {
8270cdf0e10cSrcweir                 ScAddress aAdr;
8271cdf0e10cSrcweir                 if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8272cdf0e10cSrcweir                     nErr = pDok->GetErrCode( aAdr );
8273cdf0e10cSrcweir                 else
8274cdf0e10cSrcweir                     nErr = nGlobalError;
8275cdf0e10cSrcweir             }
8276cdf0e10cSrcweir         }
8277cdf0e10cSrcweir         break;
8278cdf0e10cSrcweir         case svSingleRef :
8279cdf0e10cSrcweir         {
8280cdf0e10cSrcweir             ScAddress aAdr;
8281cdf0e10cSrcweir             PopSingleRef( aAdr );
8282cdf0e10cSrcweir             if ( nGlobalError )
8283cdf0e10cSrcweir                 nErr = nGlobalError;
8284cdf0e10cSrcweir             else
8285cdf0e10cSrcweir                 nErr = pDok->GetErrCode( aAdr );
8286cdf0e10cSrcweir         }
8287cdf0e10cSrcweir         break;
8288cdf0e10cSrcweir         default:
8289cdf0e10cSrcweir             PopError();
8290cdf0e10cSrcweir             nErr = nGlobalError;
8291cdf0e10cSrcweir     }
8292cdf0e10cSrcweir     if ( nErr )
8293cdf0e10cSrcweir     {
8294cdf0e10cSrcweir         nGlobalError = 0;
8295cdf0e10cSrcweir         PushDouble( nErr );
8296cdf0e10cSrcweir     }
8297cdf0e10cSrcweir     else
8298cdf0e10cSrcweir     {
8299cdf0e10cSrcweir         nGlobalError = nOldError;
8300cdf0e10cSrcweir         PushNA();
8301cdf0e10cSrcweir     }
8302cdf0e10cSrcweir }
8303cdf0e10cSrcweir 
8304cdf0e10cSrcweir 
MayBeRegExp(const String & rStr,const ScDocument * pDoc)8305cdf0e10cSrcweir sal_Bool ScInterpreter::MayBeRegExp( const String& rStr, const ScDocument* pDoc  )
8306cdf0e10cSrcweir {
8307cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::MayBeRegExp" );
8308cdf0e10cSrcweir     if ( pDoc && !pDoc->GetDocOptions().IsFormulaRegexEnabled() )
8309cdf0e10cSrcweir         return sal_False;
8310cdf0e10cSrcweir     if ( !rStr.Len() || (rStr.Len() == 1 && rStr.GetChar(0) != '.') )
8311cdf0e10cSrcweir         return sal_False;   // einzelnes Metazeichen kann keine RegExp sein
8312cdf0e10cSrcweir     static const sal_Unicode cre[] = { '.','*','+','?','[',']','^','$','\\','<','>','(',')','|', 0 };
8313cdf0e10cSrcweir     const sal_Unicode* p1 = rStr.GetBuffer();
8314cdf0e10cSrcweir     sal_Unicode c1;
8315cdf0e10cSrcweir     while ( ( c1 = *p1++ ) != 0 )
8316cdf0e10cSrcweir     {
8317cdf0e10cSrcweir         const sal_Unicode* p2 = cre;
8318cdf0e10cSrcweir         while ( *p2 )
8319cdf0e10cSrcweir         {
8320cdf0e10cSrcweir             if ( c1 == *p2++ )
8321cdf0e10cSrcweir                 return sal_True;
8322cdf0e10cSrcweir         }
8323cdf0e10cSrcweir     }
8324cdf0e10cSrcweir     return sal_False;
8325cdf0e10cSrcweir }
8326cdf0e10cSrcweir 
lcl_LookupQuery(ScAddress & o_rResultPos,ScDocument * pDoc,const ScQueryParam & rParam,const ScQueryEntry & rEntry)8327cdf0e10cSrcweir static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument * pDoc,
8328cdf0e10cSrcweir         const ScQueryParam & rParam, const ScQueryEntry & rEntry )
8329cdf0e10cSrcweir {
8330cdf0e10cSrcweir     bool bFound = false;
8331cdf0e10cSrcweir     ScQueryCellIterator aCellIter( pDoc, rParam.nTab, rParam, sal_False);
8332cdf0e10cSrcweir     if (rEntry.eOp != SC_EQUAL)
8333cdf0e10cSrcweir     {
8334cdf0e10cSrcweir         // range lookup <= or >=
8335cdf0e10cSrcweir         SCCOL nCol;
8336cdf0e10cSrcweir         SCROW nRow;
8337cdf0e10cSrcweir         bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow);
8338cdf0e10cSrcweir         if (bFound)
8339cdf0e10cSrcweir         {
8340cdf0e10cSrcweir             o_rResultPos.SetCol( nCol);
8341cdf0e10cSrcweir             o_rResultPos.SetRow( nRow);
8342cdf0e10cSrcweir         }
8343cdf0e10cSrcweir     }
8344cdf0e10cSrcweir     else if (aCellIter.GetFirst())
8345cdf0e10cSrcweir     {
8346cdf0e10cSrcweir         // EQUAL
8347cdf0e10cSrcweir         bFound = true;
8348cdf0e10cSrcweir         o_rResultPos.SetCol( aCellIter.GetCol());
8349cdf0e10cSrcweir         o_rResultPos.SetRow( aCellIter.GetRow());
8350cdf0e10cSrcweir     }
8351cdf0e10cSrcweir     return bFound;
8352cdf0e10cSrcweir }
8353cdf0e10cSrcweir 
8354cdf0e10cSrcweir #define erDEBUG_LOOKUPCACHE 0
8355cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8356cdf0e10cSrcweir #include <cstdio>
8357cdf0e10cSrcweir using ::std::fprintf;
8358cdf0e10cSrcweir using ::std::fflush;
8359cdf0e10cSrcweir static struct LookupCacheDebugCounter
8360cdf0e10cSrcweir {
8361cdf0e10cSrcweir     unsigned long nMiss;
8362cdf0e10cSrcweir     unsigned long nHit;
LookupCacheDebugCounterLookupCacheDebugCounter8363cdf0e10cSrcweir     LookupCacheDebugCounter() : nMiss(0), nHit(0) {}
~LookupCacheDebugCounterLookupCacheDebugCounter8364cdf0e10cSrcweir     ~LookupCacheDebugCounter()
8365cdf0e10cSrcweir     {
8366cdf0e10cSrcweir         fprintf( stderr, "\nmiss: %lu, hit: %lu, total: %lu, hit/miss: %lu, hit/total %lu%\n",
8367cdf0e10cSrcweir                 nMiss, nHit, nHit+nMiss, (nMiss>0 ? nHit/nMiss : 0),
8368cdf0e10cSrcweir                 ((nHit+nMiss)>0 ? (100*nHit)/(nHit+nMiss) : 0));
8369cdf0e10cSrcweir         fflush( stderr);
8370cdf0e10cSrcweir     }
8371cdf0e10cSrcweir } aLookupCacheDebugCounter;
8372cdf0e10cSrcweir #endif
8373cdf0e10cSrcweir 
LookupQueryWithCache(ScAddress & o_rResultPos,const ScQueryParam & rParam) const8374cdf0e10cSrcweir bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
8375cdf0e10cSrcweir         const ScQueryParam & rParam ) const
8376cdf0e10cSrcweir {
8377cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::LookupQueryWithCache" );
8378cdf0e10cSrcweir     bool bFound = false;
8379cdf0e10cSrcweir     const ScQueryEntry& rEntry = rParam.GetEntry(0);
8380cdf0e10cSrcweir     bool bColumnsMatch = (rParam.nCol1 == rEntry.nField);
8381cdf0e10cSrcweir     DBG_ASSERT( bColumnsMatch, "ScInterpreter::LookupQueryWithCache: columns don't match");
8382cdf0e10cSrcweir     if (!bColumnsMatch)
8383cdf0e10cSrcweir         bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8384cdf0e10cSrcweir     else
8385cdf0e10cSrcweir     {
8386cdf0e10cSrcweir         ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
8387cdf0e10cSrcweir                 rParam.nCol2, rParam.nRow2, rParam.nTab);
8388cdf0e10cSrcweir         ScLookupCache& rCache = pDok->GetLookupCache( aLookupRange);
8389cdf0e10cSrcweir         ScLookupCache::QueryCriteria aCriteria( rEntry);
8390cdf0e10cSrcweir         ScLookupCache::Result eCacheResult = rCache.lookup( o_rResultPos,
8391cdf0e10cSrcweir                 aCriteria, aPos);
8392cdf0e10cSrcweir         switch (eCacheResult)
8393cdf0e10cSrcweir         {
8394cdf0e10cSrcweir             case ScLookupCache::NOT_CACHED :
8395cdf0e10cSrcweir             case ScLookupCache::CRITERIA_DIFFERENT :
8396cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8397cdf0e10cSrcweir                 ++aLookupCacheDebugCounter.nMiss;
8398cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE > 1
8399cdf0e10cSrcweir                 fprintf( stderr, "miss %d,%d,%d\n", (int)aPos.Col(), (int)aPos.Row(), (int)aPos.Tab());
8400cdf0e10cSrcweir #endif
8401cdf0e10cSrcweir #endif
8402cdf0e10cSrcweir                 bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8403cdf0e10cSrcweir                 if (eCacheResult == ScLookupCache::NOT_CACHED)
8404cdf0e10cSrcweir                     rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
8405cdf0e10cSrcweir                 break;
8406cdf0e10cSrcweir             case ScLookupCache::FOUND :
8407cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8408cdf0e10cSrcweir                 ++aLookupCacheDebugCounter.nHit;
8409cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE > 1
8410cdf0e10cSrcweir                 fprintf( stderr, "hit  %d,%d,%d\n", (int)aPos.Col(), (int)aPos.Row(), (int)aPos.Tab());
8411cdf0e10cSrcweir #endif
8412cdf0e10cSrcweir #endif
8413cdf0e10cSrcweir                 bFound = true;
8414cdf0e10cSrcweir                 break;
8415cdf0e10cSrcweir             case ScLookupCache::NOT_AVAILABLE :
8416cdf0e10cSrcweir                 ;   // nothing, bFound remains FALSE
8417cdf0e10cSrcweir                 break;
8418cdf0e10cSrcweir         }
8419cdf0e10cSrcweir     }
8420cdf0e10cSrcweir     return bFound;
8421cdf0e10cSrcweir }
8422