LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/tool - interpr1.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1216 4465 27.2 %
Date: 2012-12-27 Functions: 74 181 40.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10