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

Generated by: LCOV version 1.11