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

Generated by: LCOV version 1.10