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

Generated by: LCOV version 1.10