LCOV - code coverage report
Current view: top level - sc/source/core/tool - interpr2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 224 1672 13.4 %
Date: 2012-08-25 Functions: 11 88 12.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 189 2041 9.3 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <sfx2/linkmgr.hxx>
      30                 :            : #include <sfx2/dispatch.hxx>
      31                 :            : #include <sfx2/objsh.hxx>
      32                 :            : #include <svl/stritem.hxx>
      33                 :            : #include <svl/zforlist.hxx>
      34                 :            : #include <rtl/logfile.hxx>
      35                 :            : #include <sal/macros.h>
      36                 :            : 
      37                 :            : #include "interpre.hxx"
      38                 :            : #include "attrib.hxx"
      39                 :            : #include "sc.hrc"
      40                 :            : #include "ddelink.hxx"
      41                 :            : #include "scmatrix.hxx"
      42                 :            : #include "compiler.hxx"
      43                 :            : #include "cell.hxx"
      44                 :            : #include "document.hxx"
      45                 :            : #include "dociter.hxx"
      46                 :            : #include "docoptio.hxx"
      47                 :            : #include "unitconv.hxx"
      48                 :            : #include "globstr.hrc"
      49                 :            : #include "hints.hxx"
      50                 :            : #include "dpobject.hxx"
      51                 :            : #include "postit.hxx"
      52                 :            : 
      53                 :            : #include <string.h>
      54                 :            : #include <math.h>
      55                 :            : 
      56                 :            : using namespace formula;
      57                 :            : // STATIC DATA -----------------------------------------------------------
      58                 :            : 
      59                 :            : #define D_TIMEFACTOR              86400.0
      60                 :            : #define SCdEpsilon                1.0E-7
      61                 :            : 
      62                 :            : //-----------------------------------------------------------------------------
      63                 :            : // Datum und Zeit
      64                 :            : //-----------------------------------------------------------------------------
      65                 :            : 
      66                 :          0 : double ScInterpreter::GetDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
      67                 :            :         bool bStrict, bool bCheckGregorian )
      68                 :            : {
      69                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDateSerial" );
      70 [ #  # ][ #  # ]:          0 :     if ( nYear < 100 && !bStrict )
      71         [ #  # ]:          0 :         nYear = pFormatter->ExpandTwoDigitYear( nYear );
      72                 :            :     // Do not use a default Date ctor here because it asks system time with a
      73                 :            :     // performance penalty.
      74                 :            :     sal_Int16 nY, nM, nD;
      75         [ #  # ]:          0 :     if (bStrict)
      76                 :          0 :         nY = nYear, nM = nMonth, nD = nDay;
      77                 :            :     else
      78                 :            :     {
      79         [ #  # ]:          0 :         if (nMonth > 0)
      80                 :            :         {
      81                 :          0 :             nY = nYear + (nMonth-1) / 12;
      82                 :          0 :             nM = ((nMonth-1) % 12) + 1;
      83                 :            :         }
      84                 :            :         else
      85                 :            :         {
      86                 :          0 :             nY = nYear + (nMonth-12) / 12;
      87                 :          0 :             nM = 12 - (-nMonth) % 12;
      88                 :            :         }
      89                 :          0 :         nD = 1;
      90                 :            :     }
      91                 :          0 :     Date aDate( nD, nM, nY);
      92         [ #  # ]:          0 :     if (!bStrict)
      93         [ #  # ]:          0 :         aDate += nDay - 1;
      94 [ #  # ][ #  # ]:          0 :     if ((!bCheckGregorian && aDate.IsValidDate()) || (bCheckGregorian && aDate.IsValidAndGregorian()))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      95 [ #  # ][ #  # ]:          0 :         return (double) (aDate - *(pFormatter->GetNullDate()));
      96                 :            :     else
      97                 :            :     {
      98                 :          0 :         SetError(errNoValue);
      99                 :          0 :         return 0;
     100                 :            :     }
     101                 :            : }
     102                 :            : 
     103                 :            : //-----------------------------------------------------------------------------
     104                 :            : // Funktionen
     105                 :            : //-----------------------------------------------------------------------------
     106                 :            : 
     107                 :          0 : void ScInterpreter::ScGetActDate()
     108                 :            : {
     109                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetActDate" );
     110                 :          0 :     nFuncFmtType = NUMBERFORMAT_DATE;
     111         [ #  # ]:          0 :     Date aActDate( Date::SYSTEM );
     112 [ #  # ][ #  # ]:          0 :     long nDiff = aActDate - *(pFormatter->GetNullDate());
     113         [ #  # ]:          0 :     PushDouble((double) nDiff);
     114                 :          0 : }
     115                 :            : 
     116                 :          9 : void ScInterpreter::ScGetActTime()
     117                 :            : {
     118                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetActTime" );
     119                 :          9 :     nFuncFmtType = NUMBERFORMAT_DATETIME;
     120         [ +  - ]:          9 :     Date aActDate( Date::SYSTEM );
     121 [ +  - ][ +  - ]:          9 :     long nDiff = aActDate - *(pFormatter->GetNullDate());
     122         [ +  - ]:          9 :     Time aActTime( Time::SYSTEM );
     123                 :          9 :     double nTime = ((double)aActTime.Get100Sec() / 100 +
     124                 :          9 :                     (double)(aActTime.GetSec()        +
     125                 :          9 :                             (aActTime.GetMin()  * 60) +
     126                 :          9 :                             (aActTime.GetHour() * 3600))) / D_TIMEFACTOR;
     127         [ +  - ]:          9 :     PushDouble( (double) nDiff + nTime );
     128                 :          9 : }
     129                 :            : 
     130                 :          0 : void ScInterpreter::ScGetYear()
     131                 :            : {
     132                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetYear" );
     133         [ #  # ]:          0 :     Date aDate = *(pFormatter->GetNullDate());
     134 [ #  # ][ #  # ]:          0 :     aDate += (long) ::rtl::math::approxFloor(GetDouble());
     135         [ #  # ]:          0 :     PushDouble( (double) aDate.GetYear() );
     136                 :          0 : }
     137                 :            : 
     138                 :          0 : void ScInterpreter::ScGetMonth()
     139                 :            : {
     140                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetMonth" );
     141         [ #  # ]:          0 :     Date aDate = *(pFormatter->GetNullDate());
     142 [ #  # ][ #  # ]:          0 :     aDate += (long) ::rtl::math::approxFloor(GetDouble());
     143         [ #  # ]:          0 :     PushDouble( (double) aDate.GetMonth() );
     144                 :          0 : }
     145                 :            : 
     146                 :          0 : void ScInterpreter::ScGetDay()
     147                 :            : {
     148                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDay" );
     149         [ #  # ]:          0 :     Date aDate = *(pFormatter->GetNullDate());
     150 [ #  # ][ #  # ]:          0 :     aDate += (long)::rtl::math::approxFloor(GetDouble());
     151         [ #  # ]:          0 :     PushDouble((double) aDate.GetDay());
     152                 :          0 : }
     153                 :            : 
     154                 :          0 : void ScInterpreter::ScGetMin()
     155                 :            : {
     156                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetMin" );
     157                 :          0 :     double fTime = GetDouble();
     158                 :          0 :     fTime -= ::rtl::math::approxFloor(fTime);       // Datumsanteil weg
     159                 :          0 :     long nVal = (long)::rtl::math::approxFloor(fTime*D_TIMEFACTOR+0.5) % 3600;
     160                 :          0 :     PushDouble( (double) (nVal/60) );
     161                 :          0 : }
     162                 :            : 
     163                 :          0 : void ScInterpreter::ScGetSec()
     164                 :            : {
     165                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetSec" );
     166                 :          0 :     double fTime = GetDouble();
     167                 :          0 :     fTime -= ::rtl::math::approxFloor(fTime);       // Datumsanteil weg
     168                 :          0 :     long nVal = (long)::rtl::math::approxFloor(fTime*D_TIMEFACTOR+0.5) % 60;
     169                 :          0 :     PushDouble( (double) nVal );
     170                 :          0 : }
     171                 :            : 
     172                 :          0 : void ScInterpreter::ScGetHour()
     173                 :            : {
     174                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetHour" );
     175                 :          0 :     double fTime = GetDouble();
     176                 :          0 :     fTime -= ::rtl::math::approxFloor(fTime);       // Datumsanteil weg
     177                 :          0 :     long nVal = (long)::rtl::math::approxFloor(fTime*D_TIMEFACTOR+0.5) / 3600;
     178                 :          0 :     PushDouble((double) nVal);
     179                 :          0 : }
     180                 :            : 
     181                 :          0 : void ScInterpreter::ScGetDateValue()
     182                 :            : {
     183                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDateValue" );
     184 [ #  # ][ #  # ]:          0 :     String aInputString = GetString();
     185                 :          0 :     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
     186                 :            :     double fVal;
     187 [ #  # ][ #  # ]:          0 :     if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
     188                 :            :     {
     189         [ #  # ]:          0 :         short eType = pFormatter->GetType(nFIndex);
     190 [ #  # ][ #  # ]:          0 :         if (eType == NUMBERFORMAT_DATE || eType == NUMBERFORMAT_DATETIME)
     191         [ #  # ]:          0 :             PushDouble(::rtl::math::approxFloor(fVal));
     192                 :            :         else
     193         [ #  # ]:          0 :             PushIllegalArgument();
     194                 :            :     }
     195                 :            :     else
     196 [ #  # ][ #  # ]:          0 :         PushIllegalArgument();
     197                 :          0 : }
     198                 :            : 
     199                 :          0 : void ScInterpreter::ScGetDayOfWeek()
     200                 :            : {
     201                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDayOfWeek" );
     202                 :          0 :     sal_uInt8 nParamCount = GetByte();
     203         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
     204                 :            :     {
     205                 :            :         short nFlag;
     206         [ #  # ]:          0 :         if (nParamCount == 2)
     207         [ #  # ]:          0 :             nFlag = (short) ::rtl::math::approxFloor(GetDouble());
     208                 :            :         else
     209                 :          0 :             nFlag = 1;
     210                 :            : 
     211         [ #  # ]:          0 :         Date aDate = *(pFormatter->GetNullDate());
     212 [ #  # ][ #  # ]:          0 :         aDate += (long)::rtl::math::approxFloor(GetDouble());
     213         [ #  # ]:          0 :         int nVal = (int) aDate.GetDayOfWeek();
     214         [ #  # ]:          0 :         if (nFlag == 1)
     215                 :            :         {
     216         [ #  # ]:          0 :             if (nVal == 6)
     217                 :          0 :                 nVal = 1;
     218                 :            :             else
     219                 :          0 :                 nVal += 2;
     220                 :            :         }
     221         [ #  # ]:          0 :         else if (nFlag == 2)
     222                 :          0 :             nVal += 1;
     223         [ #  # ]:          0 :         PushInt( nVal );
     224                 :            :     }
     225                 :          0 : }
     226                 :            : 
     227                 :          0 : void ScInterpreter::ScGetWeekOfYear()
     228                 :            : {
     229                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetWeekOfYear" );
     230         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
     231                 :            :     {
     232         [ #  # ]:          0 :         short nFlag = (short) ::rtl::math::approxFloor(GetDouble());
     233                 :            : 
     234         [ #  # ]:          0 :         Date aDate = *(pFormatter->GetNullDate());
     235 [ #  # ][ #  # ]:          0 :         aDate += (long)::rtl::math::approxFloor(GetDouble());
     236 [ #  # ][ #  # ]:          0 :         PushInt( (int) aDate.GetWeekOfYear( nFlag == 1 ? SUNDAY : MONDAY ));
                 [ #  # ]
     237                 :            :     }
     238                 :          0 : }
     239                 :            : 
     240                 :          0 : void ScInterpreter::ScEasterSunday()
     241                 :            : {
     242                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEasterSunday" );
     243                 :          0 :     nFuncFmtType = NUMBERFORMAT_DATE;
     244         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 1 ) )
     245                 :            :     {
     246                 :            :         sal_Int16 nDay, nMonth, nYear;
     247                 :          0 :         nYear = (sal_Int16) ::rtl::math::approxFloor( GetDouble() );
     248         [ #  # ]:          0 :         if ( nYear < 100 )
     249                 :          0 :             nYear = pFormatter->ExpandTwoDigitYear( nYear );
     250                 :            :         // don't worry, be happy :)
     251                 :            :         int B,C,D,E,F,G,H,I,K,L,M,N,O;
     252                 :          0 :         N = nYear % 19;
     253                 :          0 :         B = int(nYear / 100);
     254                 :          0 :         C = nYear % 100;
     255                 :          0 :         D = int(B / 4);
     256                 :          0 :         E = B % 4;
     257                 :          0 :         F = int((B + 8) / 25);
     258                 :          0 :         G = int((B - F + 1) / 3);
     259                 :          0 :         H = (19 * N + B - D - G + 15) % 30;
     260                 :          0 :         I = int(C / 4);
     261                 :          0 :         K = C % 4;
     262                 :          0 :         L = (32 + 2 * E + 2 * I - H - K) % 7;
     263                 :          0 :         M = int((N + 11 * H + 22 * L) / 451);
     264                 :          0 :         O = H + L - 7 * M + 114;
     265                 :          0 :         nDay = sal::static_int_cast<sal_Int16>( O % 31 + 1 );
     266                 :          0 :         nMonth = sal::static_int_cast<sal_Int16>( int(O / 31) );
     267                 :          0 :         PushDouble( GetDateSerial( nYear, nMonth, nDay, true, true ) );
     268                 :            :     }
     269                 :          0 : }
     270                 :            : 
     271                 :          0 : void ScInterpreter::ScGetDate()
     272                 :            : {
     273                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDate" );
     274                 :          0 :     nFuncFmtType = NUMBERFORMAT_DATE;
     275         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
     276                 :            :     {
     277                 :          0 :         sal_Int16 nDay   = (sal_Int16) ::rtl::math::approxFloor(GetDouble());
     278                 :          0 :         sal_Int16 nMonth = (sal_Int16) ::rtl::math::approxFloor(GetDouble());
     279                 :          0 :         sal_Int16 nYear  = (sal_Int16) ::rtl::math::approxFloor(GetDouble());
     280         [ #  # ]:          0 :         if (nYear < 0)
     281                 :          0 :             PushIllegalArgument();
     282                 :            :         else
     283                 :            :         {
     284                 :          0 :             PushDouble(GetDateSerial(nYear, nMonth, nDay, false, true));
     285                 :            :         }
     286                 :            :     }
     287                 :          0 : }
     288                 :            : 
     289                 :          0 : void ScInterpreter::ScGetTime()
     290                 :            : {
     291                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetTime" );
     292                 :          0 :     nFuncFmtType = NUMBERFORMAT_TIME;
     293         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
     294                 :            :     {
     295                 :          0 :         double nSec = GetDouble();
     296                 :          0 :         double nMin = GetDouble();
     297                 :          0 :         double nHour = GetDouble();
     298                 :          0 :         double fTime = fmod( (nHour * 3600) + (nMin * 60) + nSec, D_TIMEFACTOR) / D_TIMEFACTOR;
     299         [ #  # ]:          0 :         if (fTime < 0)
     300                 :          0 :             PushIllegalArgument();
     301                 :            :         else
     302                 :          0 :             PushDouble( fTime);
     303                 :            :     }
     304                 :          0 : }
     305                 :            : 
     306                 :          0 : void ScInterpreter::ScGetDiffDate()
     307                 :            : {
     308                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDiffDate" );
     309         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
     310                 :            :     {
     311                 :          0 :         double nDate2 = GetDouble();
     312                 :          0 :         double nDate1 = GetDouble();
     313                 :          0 :         PushDouble(nDate1 - nDate2);
     314                 :            :     }
     315                 :          0 : }
     316                 :            : 
     317                 :          0 : void ScInterpreter::ScGetDiffDate360()
     318                 :            : {
     319                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDiffDate360" );
     320                 :            :     /* Implementation follows
     321                 :            :      * http://www.bondmarkets.com/eCommerce/SMD_Fields_030802.pdf
     322                 :            :      * Appendix B: Day-Count Bases, there are 7 different ways to calculate the
     323                 :            :      * 30-days count. That document also claims that Excel implements the "PSA
     324                 :            :      * 30" or "NASD 30" method (funny enough they also state that Excel is the
     325                 :            :      * only tool that does so).
     326                 :            :      *
     327                 :            :      * Note that the definiton given in
     328                 :            :      * http://msdn.microsoft.com/library/en-us/office97/html/SEB7C.asp
     329                 :            :      * is _not_ the way how it is actually calculated by Excel (that would not
     330                 :            :      * even match any of the 7 methods mentioned above) and would result in the
     331                 :            :      * following test cases producing wrong results according to that appendix B:
     332                 :            :      *
     333                 :            :      * 28-Feb-95  31-Aug-95  181 instead of 180
     334                 :            :      * 29-Feb-96  31-Aug-96  181 instead of 180
     335                 :            :      * 30-Jan-96  31-Mar-96   61 instead of  60
     336                 :            :      * 31-Jan-96  31-Mar-96   61 instead of  60
     337                 :            :      *
     338                 :            :      * Still, there is a difference between OOoCalc and Excel:
     339                 :            :      * In Excel:
     340                 :            :      * 02-Feb-99 31-Mar-00 results in  419
     341                 :            :      * 31-Mar-00 02-Feb-99 results in -418
     342                 :            :      * In Calc the result is 419 respectively -419. I consider the -418 a bug in Excel.
     343                 :            :      */
     344                 :            : 
     345                 :          0 :     sal_uInt8 nParamCount = GetByte();
     346         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
     347                 :            :     {
     348                 :            :         bool bFlag;
     349         [ #  # ]:          0 :         if (nParamCount == 3)
     350                 :          0 :             bFlag = GetBool();
     351                 :            :         else
     352                 :          0 :             bFlag = false;
     353                 :          0 :         double nDate2 = GetDouble();
     354                 :          0 :         double nDate1 = GetDouble();
     355         [ #  # ]:          0 :         if (nGlobalError)
     356                 :          0 :             PushError( nGlobalError);
     357                 :            :         else
     358                 :            :         {
     359                 :            :             double fSign;
     360                 :            :             // #i84934# only for non-US European algorithm swap dates. Else
     361                 :            :             // follow Excel's meaningless extrapolation for "interoperability".
     362 [ #  # ][ #  # ]:          0 :             if (bFlag && (nDate2 < nDate1))
     363                 :            :             {
     364                 :          0 :                 fSign = nDate1;
     365                 :          0 :                 nDate1 = nDate2;
     366                 :          0 :                 nDate2 = fSign;
     367                 :          0 :                 fSign = -1.0;
     368                 :            :             }
     369                 :            :             else
     370                 :          0 :                 fSign = 1.0;
     371         [ #  # ]:          0 :             Date aDate1 = *(pFormatter->GetNullDate());
     372         [ #  # ]:          0 :             aDate1 += (long) ::rtl::math::approxFloor(nDate1);
     373         [ #  # ]:          0 :             Date aDate2 = *(pFormatter->GetNullDate());
     374         [ #  # ]:          0 :             aDate2 += (long) ::rtl::math::approxFloor(nDate2);
     375         [ #  # ]:          0 :             if (aDate1.GetDay() == 31)
     376         [ #  # ]:          0 :                 aDate1 -= (sal_uLong) 1;
     377         [ #  # ]:          0 :             else if (!bFlag)
     378                 :            :             {
     379         [ #  # ]:          0 :                 if (aDate1.GetMonth() == 2)
     380                 :            :                 {
     381      [ #  #  # ]:          0 :                     switch ( aDate1.GetDay() )
     382                 :            :                     {
     383                 :            :                         case 28 :
     384 [ #  # ][ #  # ]:          0 :                             if ( !aDate1.IsLeapYear() )
     385         [ #  # ]:          0 :                                 aDate1.SetDay(30);
     386                 :          0 :                         break;
     387                 :            :                         case 29 :
     388         [ #  # ]:          0 :                             aDate1.SetDay(30);
     389                 :          0 :                         break;
     390                 :            :                     }
     391                 :            :                 }
     392                 :            :             }
     393         [ #  # ]:          0 :             if (aDate2.GetDay() == 31)
     394                 :            :             {
     395         [ #  # ]:          0 :                 if (!bFlag )
     396                 :            :                 {
     397         [ #  # ]:          0 :                     if (aDate1.GetDay() == 30)
     398         [ #  # ]:          0 :                         aDate2 -= (sal_uLong) 1;
     399                 :            :                 }
     400                 :            :                 else
     401         [ #  # ]:          0 :                     aDate2.SetDay(30);
     402                 :            :             }
     403                 :            :             PushDouble( fSign * (double)
     404                 :          0 :                 (  (double) aDate2.GetDay() + (double) aDate2.GetMonth() * 30.0 +
     405                 :          0 :                    (double) aDate2.GetYear() * 360.0
     406                 :          0 :                  - (double) aDate1.GetDay() - (double) aDate1.GetMonth() * 30.0
     407         [ #  # ]:          0 :                  - (double)aDate1.GetYear() * 360.0) );
     408                 :            :         }
     409                 :            :     }
     410                 :          0 : }
     411                 :            : 
     412                 :            : // fdo#44456 function DATEDIF as defined in ODF1.2 (Par. 6.10.3)
     413                 :        270 : void ScInterpreter::ScGetDateDif()
     414                 :            : {
     415                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDateDif" );
     416         [ +  - ]:        270 :     if ( MustHaveParamCount( GetByte(), 3 ) )
     417                 :            :     {
     418 [ +  - ][ +  - ]:        270 :         String aInterval = GetString();
     419         [ +  - ]:        270 :         double nDate2    = GetDouble();
     420         [ +  - ]:        270 :         double nDate1    = GetDouble();
     421                 :            : 
     422         [ +  + ]:        270 :         if (nGlobalError)
     423                 :            :         {
     424         [ +  - ]:         60 :             PushError( nGlobalError);
     425                 :            :             return;
     426                 :            :         }
     427                 :            : 
     428                 :            :         // Excel doesn't swap dates or return negative numbers, so don't we.
     429         [ +  + ]:        210 :         if (nDate1 > nDate2)
     430                 :            :         {
     431         [ +  - ]:         18 :             PushIllegalArgument();
     432                 :            :             return;
     433                 :            :         }
     434                 :            : 
     435                 :        192 :         long dd = nDate2 - nDate1;
     436                 :            :         // Zero difference or number of days can be returned immediately.
     437 [ +  - ][ +  - ]:        192 :         if (dd == 0 || aInterval.EqualsIgnoreCaseAscii( "d" ))
         [ +  + ][ +  + ]
     438                 :            :         {
     439         [ +  - ]:         42 :             PushDouble( dd );
     440                 :            :             return;
     441                 :            :         }
     442                 :            : 
     443                 :            :         // split dates in day, month, year for use with formats other than "d"
     444                 :            :         sal_uInt16 d1, m1, y1, d2, m2, y2;
     445         [ +  - ]:        150 :         Date aDate1( *( pFormatter->GetNullDate()));
     446         [ +  - ]:        150 :         aDate1 += (long) ::rtl::math::approxFloor( nDate1 );
     447                 :        150 :         y1 = aDate1.GetYear();
     448                 :        150 :         m1 = aDate1.GetMonth();
     449                 :        150 :         d1 = aDate1.GetDay();
     450         [ +  - ]:        150 :         Date aDate2( *( pFormatter->GetNullDate()));
     451         [ +  - ]:        150 :         aDate2 += (long) ::rtl::math::approxFloor( nDate2 );
     452                 :        150 :         y2 = aDate2.GetYear();
     453                 :        150 :         m2 = aDate2.GetMonth();
     454                 :        150 :         d2 = aDate2.GetDay();
     455                 :            : 
     456 [ +  + ][ +  - ]:        150 :         if (  aInterval.EqualsIgnoreCaseAscii( "m" ) )
     457                 :            :         {
     458                 :            :             // Return number of months.
     459                 :         36 :             int md = m2 - m1 + 12 * (y2 - y1);
     460         [ +  + ]:         36 :             if (d1 > d2)
     461                 :         12 :                 --md;
     462         [ +  - ]:         36 :             PushInt( md );
     463                 :            :         }
     464 [ +  - ][ +  + ]:        114 :         else if ( aInterval.EqualsIgnoreCaseAscii( "y" ) )
     465                 :            :         {
     466                 :            :             // Return number of years.
     467                 :            :             int yd;
     468         [ +  + ]:         18 :             if ( y2 > y1 )
     469                 :            :             {
     470 [ +  - ][ -  + ]:         12 :                 if (m2 > m1 || (m2 == m1 && d2 >= d1))
                 [ #  # ]
     471                 :          0 :                     yd = y2 - y1;       // complete years between dates
     472                 :            :                 else
     473                 :         12 :                     yd = y2 - y1 - 1;   // one incomplete year
     474                 :            :             }
     475                 :            :             else
     476                 :            :             {
     477                 :            :                 // Year is equal as we don't allow reversed arguments, no
     478                 :            :                 // complete year between dates.
     479                 :          6 :                 yd = 0;
     480                 :            :             }
     481         [ +  - ]:         18 :             PushInt( yd );
     482                 :            :         }
     483 [ +  - ][ +  + ]:         96 :         else if ( aInterval.EqualsIgnoreCaseAscii( "md" ) )
     484                 :            :         {
     485                 :            :             // Return number of days, excluding months and years.
     486                 :            :             // This is actually the remainder of days when subtracting years
     487                 :            :             // and months from the difference of dates. Birthday-like 23 years
     488                 :            :             // and 10 months and 19 days.
     489                 :            : 
     490                 :            :             // Algorithm's roll-over behavior extracted from Excel by try and
     491                 :            :             // error..
     492                 :            :             // If day1 <= day2 then simply day2 - day1.
     493                 :            :             // If day1 > day2 then set month1 to month2-1 and year1 to
     494                 :            :             // year2(-1) and subtract dates, e.g. for 2012-01-28,2012-03-01 set
     495                 :            :             // 2012-02-28 and then (2012-03-01)-(2012-02-28) => 2 days (leap
     496                 :            :             // year).
     497                 :            :             // For 2011-01-29,2011-03-01 the non-existent 2011-02-29 rolls over
     498                 :            :             // to 2011-03-01 so the result is 0. Same for day 31 in months with
     499                 :            :             // only 30 days.
     500                 :            : 
     501                 :            :             long nd;
     502         [ +  - ]:         54 :             if (d1 <= d2)
     503                 :         54 :                 nd = d2 - d1;
     504                 :            :             else
     505                 :            :             {
     506         [ #  # ]:          0 :                 if (m2 == 1)
     507                 :            :                 {
     508         [ #  # ]:          0 :                     aDate1.SetYear( y2 - 1 );
     509         [ #  # ]:          0 :                     aDate1.SetMonth( 12 );
     510                 :            :                 }
     511                 :            :                 else
     512                 :            :                 {
     513         [ #  # ]:          0 :                     aDate1.SetYear( y2 );
     514         [ #  # ]:          0 :                     aDate1.SetMonth( m2 - 1 );
     515                 :            :                 }
     516         [ #  # ]:          0 :                 aDate1.Normalize();
     517         [ #  # ]:          0 :                 nd = aDate2 - aDate1;
     518                 :            :             }
     519         [ +  - ]:         54 :             PushDouble( nd );
     520                 :            :         }
     521 [ +  - ][ +  + ]:         42 :         else if ( aInterval.EqualsIgnoreCaseAscii( "ym" ) )
     522                 :            :         {
     523                 :            :             // Return number of months, excluding years.
     524                 :         18 :             int md = m2 - m1 + 12 * (y2 - y1);
     525         [ +  + ]:         18 :             if (d1 > d2)
     526                 :         12 :                 --md;
     527                 :         18 :             md %= 12;
     528         [ +  - ]:         18 :             PushInt( md );
     529                 :            :         }
     530 [ +  - ][ +  - ]:         24 :         else if ( aInterval.EqualsIgnoreCaseAscii( "yd" ) )
     531                 :            :         {
     532                 :            :             // Return number of days, excluding years.
     533                 :            : 
     534                 :            :             /* TODO: check what Excel really does, though this seems to be
     535                 :            :              * reasonable */
     536                 :            : 
     537                 :            :             // Condition corresponds with "y".
     538 [ +  + ][ -  + ]:         24 :             if (m2 > m1 || (m2 == m1 && d2 >= d1))
                 [ #  # ]
     539         [ +  - ]:         12 :                 aDate1.SetYear( y2 );
     540                 :            :             else
     541         [ +  - ]:         12 :                 aDate1.SetYear( y2 - 1 );
     542                 :            :                 // XXX NOTE: Excel for the case 1988-06-22,2012-05-11 returns
     543                 :            :                 // 323, whereas the result here is 324. Don't they use the leap
     544                 :            :                 // year of 2012?
     545                 :            :                 // http://www.cpearson.com/excel/datedif.aspx "DATEDIF And Leap
     546                 :            :                 // Years" is not correct and Excel 2010 correctly returns 0 in
     547                 :            :                 // both cases mentioned there. Also using year1 as mentioned
     548                 :            :                 // produces incorrect results in other cases and different from
     549                 :            :                 // Excel 2010. Apparently they fixed some calculations.
     550         [ +  - ]:         24 :             aDate1.Normalize();
     551         [ +  - ]:         24 :             double nd = aDate2 - aDate1;
     552         [ +  - ]:         24 :             PushDouble( nd );
     553                 :            :         }
     554                 :            :         else
     555 [ #  # ][ +  - ]:        270 :             PushIllegalArgument();               // unsupported format
                 [ +  + ]
     556                 :            :     }
     557                 :            : }
     558                 :            : 
     559                 :          0 : void ScInterpreter::ScGetTimeValue()
     560                 :            : {
     561                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetTimeValue" );
     562 [ #  # ][ #  # ]:          0 :     String aInputString = GetString();
     563                 :          0 :     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
     564                 :            :     double fVal;
     565 [ #  # ][ #  # ]:          0 :     if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
     566                 :            :     {
     567         [ #  # ]:          0 :         short eType = pFormatter->GetType(nFIndex);
     568 [ #  # ][ #  # ]:          0 :         if (eType == NUMBERFORMAT_TIME || eType == NUMBERFORMAT_DATETIME)
     569                 :            :         {
     570                 :          0 :             double fDateVal = rtl::math::approxFloor(fVal);
     571                 :          0 :             double fTimeVal = fVal - fDateVal;
     572         [ #  # ]:          0 :             PushDouble(fTimeVal);
     573                 :            :         }
     574                 :            :         else
     575         [ #  # ]:          0 :             PushIllegalArgument();
     576                 :            :     }
     577                 :            :     else
     578 [ #  # ][ #  # ]:          0 :         PushIllegalArgument();
     579                 :          0 : }
     580                 :            : 
     581                 :          0 : void ScInterpreter::ScPlusMinus()
     582                 :            : {
     583                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPlusMinus" );
     584                 :          0 :     double nVal = GetDouble();
     585                 :          0 :     short n = 0;
     586         [ #  # ]:          0 :     if (nVal < 0.0)
     587                 :          0 :         n = -1;
     588         [ #  # ]:          0 :     else if (nVal > 0.0)
     589                 :          0 :         n = 1;
     590                 :          0 :     PushInt( n );
     591                 :          0 : }
     592                 :            : 
     593                 :          9 : void ScInterpreter::ScAbs()
     594                 :            : {
     595                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAbs" );
     596                 :          9 :     PushDouble(fabs(GetDouble()));
     597                 :          9 : }
     598                 :            : 
     599                 :          0 : void ScInterpreter::ScInt()
     600                 :            : {
     601                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScInt" );
     602                 :          0 :     PushDouble(::rtl::math::approxFloor(GetDouble()));
     603                 :          0 : }
     604                 :            : 
     605                 :            : 
     606                 :         12 : void ScInterpreter::RoundNumber( rtl_math_RoundingMode eMode )
     607                 :            : {
     608                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::RoundNumber" );
     609                 :         12 :     sal_uInt8 nParamCount = GetByte();
     610         [ +  - ]:         12 :     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
     611                 :            :     {
     612                 :         12 :         double fVal = 0.0;
     613         [ -  + ]:         12 :         if (nParamCount == 1)
     614                 :          0 :             fVal = ::rtl::math::round( GetDouble(), 0, eMode );
     615                 :            :         else
     616                 :            :         {
     617                 :         12 :             sal_Int32 nDec = (sal_Int32) ::rtl::math::approxFloor(GetDouble());
     618 [ -  + ][ +  - ]:         12 :             if( nDec < -20 || nDec > 20 )
     619                 :          0 :                 PushIllegalArgument();
     620                 :            :             else
     621                 :         12 :                 fVal = ::rtl::math::round( GetDouble(), (short)nDec, eMode );
     622                 :            :         }
     623                 :         12 :         PushDouble(fVal);
     624                 :            :     }
     625                 :         12 : }
     626                 :            : 
     627                 :         12 : void ScInterpreter::ScRound()
     628                 :            : {
     629                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRound" );
     630                 :         12 :     RoundNumber( rtl_math_RoundingMode_Corrected );
     631                 :         12 : }
     632                 :            : 
     633                 :          0 : void ScInterpreter::ScRoundDown()
     634                 :            : {
     635                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRoundDown" );
     636                 :          0 :     RoundNumber( rtl_math_RoundingMode_Down );
     637                 :          0 : }
     638                 :            : 
     639                 :          0 : void ScInterpreter::ScRoundUp()
     640                 :            : {
     641                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRoundUp" );
     642                 :          0 :     RoundNumber( rtl_math_RoundingMode_Up );
     643                 :          0 : }
     644                 :            : 
     645                 :          0 : void ScInterpreter::ScCeil()
     646                 :            : {
     647                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCeil" );
     648                 :          0 :     sal_uInt8 nParamCount = GetByte();
     649         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
     650                 :            :     {
     651         [ #  # ]:          0 :         bool bAbs = ( nParamCount == 3 ? GetBool() : false );
     652                 :          0 :         double fDec = GetDouble();
     653                 :          0 :         double fVal = GetDouble();
     654         [ #  # ]:          0 :         if ( fDec == 0.0 )
     655                 :          0 :             PushInt(0);
     656         [ #  # ]:          0 :         else if (fVal*fDec < 0.0)
     657                 :          0 :             PushIllegalArgument();
     658                 :            :         else
     659                 :            :         {
     660 [ #  # ][ #  # ]:          0 :             if ( !bAbs && fVal < 0.0 )
     661                 :          0 :                 PushDouble(::rtl::math::approxFloor(fVal/fDec) * fDec);
     662                 :            :             else
     663                 :          0 :                 PushDouble(::rtl::math::approxCeil(fVal/fDec) * fDec);
     664                 :            :         }
     665                 :            :     }
     666                 :          0 : }
     667                 :            : 
     668                 :          0 : void ScInterpreter::ScFloor()
     669                 :            : {
     670                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFloor" );
     671                 :          0 :     sal_uInt8 nParamCount = GetByte();
     672         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
     673                 :            :     {
     674         [ #  # ]:          0 :         bool bAbs = ( nParamCount == 3 ? GetBool() : false );
     675                 :          0 :         double fDec = GetDouble();
     676                 :          0 :         double fVal = GetDouble();
     677         [ #  # ]:          0 :         if ( fDec == 0.0 )
     678                 :          0 :             PushInt(0);
     679         [ #  # ]:          0 :         else if (fVal*fDec < 0.0)
     680                 :          0 :             PushIllegalArgument();
     681                 :            :         else
     682                 :            :         {
     683 [ #  # ][ #  # ]:          0 :             if ( !bAbs && fVal < 0.0 )
     684                 :          0 :                 PushDouble(::rtl::math::approxCeil(fVal/fDec) * fDec);
     685                 :            :             else
     686                 :          0 :                 PushDouble(::rtl::math::approxFloor(fVal/fDec) * fDec);
     687                 :            :         }
     688                 :            :     }
     689                 :          0 : }
     690                 :            : 
     691                 :         18 : void ScInterpreter::ScEven()
     692                 :            : {
     693                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEven" );
     694                 :         18 :     double fVal = GetDouble();
     695         [ +  + ]:         18 :     if (fVal < 0.0)
     696                 :          6 :         PushDouble(::rtl::math::approxFloor(fVal/2.0) * 2.0);
     697                 :            :     else
     698                 :         12 :         PushDouble(::rtl::math::approxCeil(fVal/2.0) * 2.0);
     699                 :         18 : }
     700                 :            : 
     701                 :         18 : void ScInterpreter::ScOdd()
     702                 :            : {
     703                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOdd" );
     704                 :         18 :     double fVal = GetDouble();
     705         [ +  + ]:         18 :     if (fVal >= 0.0)
     706                 :            :     {
     707                 :         12 :         fVal = ::rtl::math::approxCeil(fVal);
     708         [ +  + ]:         12 :         if (fmod(fVal, 2.0) == 0.0)
     709                 :          9 :             fVal += 1.0;
     710                 :            :     }
     711                 :            :     else
     712                 :            :     {
     713                 :          6 :         fVal = ::rtl::math::approxFloor(fVal);
     714         [ +  + ]:          6 :         if (fmod(fVal, 2.0) == 0.0)
     715                 :          3 :             fVal -= 1.0;
     716                 :            :     }
     717                 :         18 :     PushDouble(fVal);
     718                 :         18 : }
     719                 :            : 
     720                 :          0 : void ScInterpreter::ScArcTan2()
     721                 :            : {
     722                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTan2" );
     723         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
     724                 :            :     {
     725                 :          0 :         double nVal2 = GetDouble();
     726                 :          0 :         double nVal1 = GetDouble();
     727                 :          0 :         PushDouble(atan2(nVal2, nVal1));
     728                 :            :     }
     729                 :          0 : }
     730                 :            : 
     731                 :          0 : void ScInterpreter::ScLog()
     732                 :            : {
     733                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLog" );
     734                 :          0 :     sal_uInt8 nParamCount = GetByte();
     735         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
     736                 :            :     {
     737                 :            :         double nBase;
     738         [ #  # ]:          0 :         if (nParamCount == 2)
     739                 :          0 :             nBase = GetDouble();
     740                 :            :         else
     741                 :          0 :             nBase = 10.0;
     742                 :          0 :         double nVal = GetDouble();
     743 [ #  # ][ #  # ]:          0 :         if (nVal > 0.0 && nBase > 0.0 && nBase != 1.0)
                 [ #  # ]
     744                 :          0 :             PushDouble(log(nVal) / log(nBase));
     745                 :            :         else
     746                 :          0 :             PushIllegalArgument();
     747                 :            :     }
     748                 :          0 : }
     749                 :            : 
     750                 :          0 : void ScInterpreter::ScLn()
     751                 :            : {
     752                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLn" );
     753                 :          0 :     double fVal = GetDouble();
     754         [ #  # ]:          0 :     if (fVal > 0.0)
     755                 :          0 :         PushDouble(log(fVal));
     756                 :            :     else
     757                 :          0 :         PushIllegalArgument();
     758                 :          0 : }
     759                 :            : 
     760                 :          0 : void ScInterpreter::ScLog10()
     761                 :            : {
     762                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLog10" );
     763                 :          0 :     double fVal = GetDouble();
     764         [ #  # ]:          0 :     if (fVal > 0.0)
     765                 :          0 :         PushDouble(log10(fVal));
     766                 :            :     else
     767                 :          0 :         PushIllegalArgument();
     768                 :          0 : }
     769                 :            : 
     770                 :          0 : void ScInterpreter::ScNPV()
     771                 :            : {
     772                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNPV" );
     773                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
     774                 :          0 :     short nParamCount = GetByte();
     775 [ #  # ][ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 31 ) )
     776                 :            :     {
     777                 :          0 :         double nVal = 0.0;
     778                 :            :         // Wir drehen den Stack um!!
     779                 :            :         FormulaToken* pTemp[ 31 ];
     780         [ #  # ]:          0 :         for( short i = 0; i < nParamCount; i++ )
     781                 :          0 :             pTemp[ i ] = pStack[ sp - i - 1 ];
     782                 :          0 :         memcpy( &pStack[ sp - nParamCount ], pTemp, nParamCount * sizeof( FormulaToken* ) );
     783         [ #  # ]:          0 :         if (nGlobalError == 0)
     784                 :            :         {
     785                 :          0 :             double  nCount = 1.0;
     786         [ #  # ]:          0 :             double  nZins = GetDouble();
     787                 :          0 :             --nParamCount;
     788                 :          0 :             size_t nRefInList = 0;
     789                 :          0 :             ScRange aRange;
     790         [ #  # ]:          0 :             while (nParamCount-- > 0)
     791                 :            :             {
     792         [ #  # ]:          0 :                 switch (GetStackType())
           [ #  #  #  # ]
     793                 :            :                 {
     794                 :            :                     case svDouble :
     795                 :            :                     {
     796         [ #  # ]:          0 :                         nVal += (GetDouble() / pow(1.0 + nZins, (double)nCount));
     797                 :          0 :                         nCount++;
     798                 :            :                     }
     799                 :          0 :                     break;
     800                 :            :                     case svSingleRef :
     801                 :            :                     {
     802                 :          0 :                         ScAddress aAdr;
     803         [ #  # ]:          0 :                         PopSingleRef( aAdr );
     804         [ #  # ]:          0 :                         ScBaseCell* pCell = GetCell( aAdr );
     805 [ #  # ][ #  # ]:          0 :                         if (!HasCellEmptyData(pCell) && HasCellValueData(pCell))
         [ #  # ][ #  # ]
                 [ #  # ]
     806                 :            :                         {
     807         [ #  # ]:          0 :                             double nCellVal = GetCellValue( aAdr, pCell );
     808                 :          0 :                             nVal += (nCellVal / pow(1.0 + nZins, (double)nCount));
     809                 :          0 :                             nCount++;
     810                 :            :                         }
     811                 :            :                     }
     812                 :          0 :                     break;
     813                 :            :                     case svDoubleRef :
     814                 :            :                     case svRefList :
     815                 :            :                     {
     816                 :          0 :                         sal_uInt16 nErr = 0;
     817                 :            :                         double nCellVal;
     818         [ #  # ]:          0 :                         PopDoubleRef( aRange, nParamCount, nRefInList);
     819         [ #  # ]:          0 :                         ScHorizontalValueIterator aValIter( pDok, aRange, glSubTotal);
     820 [ #  # ][ #  # ]:          0 :                         while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
         [ #  # ][ #  # ]
     821                 :            :                         {
     822                 :          0 :                             nVal += (nCellVal / pow(1.0 + nZins, (double)nCount));
     823                 :          0 :                             nCount++;
     824                 :            :                         }
     825         [ #  # ]:          0 :                         if ( nErr != 0 )
     826         [ #  # ]:          0 :                             SetError(nErr);
     827                 :            :                     }
     828                 :          0 :                     break;
     829                 :          0 :                     default : SetError(errIllegalParameter); break;
     830                 :            :                 }
     831                 :            :             }
     832                 :            :         }
     833         [ #  # ]:          0 :         PushDouble(nVal);
     834                 :            :     }
     835                 :          0 : }
     836                 :            : 
     837                 :          0 : void ScInterpreter::ScIRR()
     838                 :            : {
     839                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIRR" );
     840                 :            :     double fSchaetzwert;
     841                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
     842                 :          0 :     sal_uInt8 nParamCount = GetByte();
     843 [ #  # ][ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 1, 2 ) )
     844                 :            :         return;
     845         [ #  # ]:          0 :     if (nParamCount == 2)
     846         [ #  # ]:          0 :         fSchaetzwert = GetDouble();
     847                 :            :     else
     848                 :          0 :         fSchaetzwert = 0.1;
     849                 :          0 :     sal_uInt16 sPos = sp;                       // Stack-Position merken
     850                 :          0 :     double fEps = 1.0;
     851                 :            :     double x, xNeu, fWert, fZaehler, fNenner, nCount;
     852         [ #  # ]:          0 :     if (fSchaetzwert == -1.0)
     853                 :          0 :         x = 0.1;                            // default gegen Nulldivisionen
     854                 :            :     else
     855                 :          0 :         x = fSchaetzwert;                   // Startwert
     856 [ #  # ][ #  # ]:          0 :     switch (GetStackType())
     857                 :            :     {
     858                 :            :         case svDoubleRef :
     859                 :          0 :         break;
     860                 :            :         default:
     861                 :            :         {
     862         [ #  # ]:          0 :             PushIllegalParameter();
     863                 :            :             return;
     864                 :            :         }
     865                 :            :     }
     866                 :          0 :     const sal_uInt16 nIterationsMax = 20;
     867                 :          0 :     sal_uInt16 nItCount = 0;
     868                 :          0 :     ScRange aRange;
     869 [ #  # ][ #  # ]:          0 :     while (fEps > SCdEpsilon && nItCount < nIterationsMax)
                 [ #  # ]
     870                 :            :     {                                       // Newton-Verfahren:
     871                 :          0 :         sp = sPos;                          // Stack zuruecksetzen
     872                 :          0 :         nCount = 0.0;
     873                 :          0 :         fZaehler = 0.0;
     874                 :          0 :         fNenner = 0.0;
     875                 :          0 :         sal_uInt16 nErr = 0;
     876         [ #  # ]:          0 :         PopDoubleRef( aRange );
     877         [ #  # ]:          0 :         ScValueIterator aValIter(pDok, aRange, glSubTotal);
     878 [ #  # ][ #  # ]:          0 :         if (aValIter.GetFirst(fWert, nErr))
     879                 :            :         {
     880                 :          0 :             fZaehler +=           fWert / pow(1.0+x,(double)nCount);
     881                 :          0 :             fNenner  += -nCount * fWert / pow(1.0+x,nCount+1.0);
     882                 :          0 :             nCount++;
     883 [ #  # ][ #  # ]:          0 :             while ((nErr == 0) && aValIter.GetNext(fWert, nErr))
         [ #  # ][ #  # ]
     884                 :            :             {
     885                 :          0 :                 fZaehler +=           fWert / pow(1.0+x,(double)nCount);
     886                 :          0 :                 fNenner  += -nCount * fWert / pow(1.0+x,nCount+1.0);
     887                 :          0 :                 nCount++;
     888                 :            :             }
     889                 :          0 :             SetError(nErr);
     890                 :            :         }
     891                 :          0 :         xNeu = x - fZaehler / fNenner;  // x(i+1) = x(i)-f(x(i))/f'(x(i))
     892                 :          0 :         nItCount++;
     893                 :          0 :         fEps = fabs(xNeu - x);
     894                 :          0 :         x = xNeu;
     895                 :            :     }
     896 [ #  # ][ #  # ]:          0 :     if (fSchaetzwert == 0.0 && fabs(x) < SCdEpsilon)
     897                 :          0 :         x = 0.0;                        // auf Null normieren
     898         [ #  # ]:          0 :     if (fEps < SCdEpsilon)
     899         [ #  # ]:          0 :         PushDouble(x);
     900                 :            :     else
     901         [ #  # ]:          0 :         PushError( errNoConvergence);
     902                 :            : }
     903                 :            : 
     904                 :          0 : void ScInterpreter::ScMIRR()
     905                 :            : {   // range_of_values ; rate_invest ; rate_reinvest
     906                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
     907         [ #  # ]:          0 :     if( MustHaveParamCount( GetByte(), 3 ) )
     908                 :            :     {
     909         [ #  # ]:          0 :         double fRate1_reinvest = GetDouble() + 1;
     910         [ #  # ]:          0 :         double fRate1_invest = GetDouble() + 1;
     911                 :            : 
     912                 :          0 :         ScRange aRange;
     913         [ #  # ]:          0 :         PopDoubleRef( aRange );
     914                 :            : 
     915         [ #  # ]:          0 :         if( nGlobalError )
     916         [ #  # ]:          0 :             PushError( nGlobalError);
     917                 :            :         else
     918                 :            :         {
     919                 :          0 :             double fNPV_reinvest = 0.0;
     920                 :          0 :             double fPow_reinvest = 1.0;
     921                 :          0 :             double fNPV_invest = 0.0;
     922                 :          0 :             double fPow_invest = 1.0;
     923         [ #  # ]:          0 :             ScValueIterator aValIter( pDok, aRange, glSubTotal );
     924                 :            :             double fCellValue;
     925                 :          0 :             sal_uLong nCount = 0;
     926                 :          0 :             sal_uInt16 nIterError = 0;
     927                 :            : 
     928         [ #  # ]:          0 :             bool bLoop = aValIter.GetFirst( fCellValue, nIterError );
     929         [ #  # ]:          0 :             while( bLoop )
     930                 :            :             {
     931         [ #  # ]:          0 :                 if( fCellValue > 0.0 )          // reinvestments
     932                 :          0 :                     fNPV_reinvest += fCellValue * fPow_reinvest;
     933         [ #  # ]:          0 :                 else if( fCellValue < 0.0 )     // investments
     934                 :          0 :                     fNPV_invest += fCellValue * fPow_invest;
     935                 :          0 :                 fPow_reinvest /= fRate1_reinvest;
     936                 :          0 :                 fPow_invest /= fRate1_invest;
     937                 :          0 :                 nCount++;
     938                 :            : 
     939         [ #  # ]:          0 :                 bLoop = aValIter.GetNext( fCellValue, nIterError );
     940                 :            :             }
     941         [ #  # ]:          0 :             if( nIterError )
     942         [ #  # ]:          0 :                 PushError( nIterError );
     943                 :            :             else
     944                 :            :             {
     945                 :          0 :                 double fResult = -fNPV_reinvest / fNPV_invest;
     946                 :          0 :                 fResult *= pow( fRate1_reinvest, (double) nCount - 1 );
     947                 :          0 :                 fResult = pow( fResult, 1.0 / (nCount - 1) );
     948         [ #  # ]:          0 :                 PushDouble( fResult - 1.0 );
     949                 :            :             }
     950                 :            :         }
     951                 :            :     }
     952                 :          0 : }
     953                 :            : 
     954                 :            : 
     955                 :          0 : void ScInterpreter::ScISPMT()
     956                 :            : {   // rate ; period ; total_periods ; invest
     957         [ #  # ]:          0 :     if( MustHaveParamCount( GetByte(), 4 ) )
     958                 :            :     {
     959                 :          0 :         double fInvest = GetDouble();
     960                 :          0 :         double fTotal = GetDouble();
     961                 :          0 :         double fPeriod = GetDouble();
     962                 :          0 :         double fRate = GetDouble();
     963                 :            : 
     964         [ #  # ]:          0 :         if( nGlobalError )
     965                 :          0 :             PushError( nGlobalError);
     966                 :            :         else
     967                 :          0 :             PushDouble( fInvest * fRate * (fPeriod / fTotal - 1.0) );
     968                 :            :     }
     969                 :          0 : }
     970                 :            : 
     971                 :            : 
     972                 :            : //----------------------- Finanzfunktionen ------------------------------------
     973                 :            : 
     974                 :          0 : double ScInterpreter::ScGetBw(double fZins, double fZzr, double fRmz,
     975                 :            :                               double fZw, double fF)
     976                 :            : {
     977                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMIRR" );
     978                 :            :     double fBw;
     979         [ #  # ]:          0 :     if (fZins == 0.0)
     980                 :          0 :         fBw = fZw + fRmz * fZzr;
     981         [ #  # ]:          0 :     else if (fF > 0.0)
     982                 :          0 :         fBw = (fZw * pow(1.0 + fZins, -fZzr))
     983                 :          0 :                 + (fRmz * (1.0 - pow(1.0 + fZins, -fZzr + 1.0)) / fZins)
     984                 :          0 :                 + fRmz;
     985                 :            :     else
     986                 :          0 :         fBw = (fZw * pow(1.0 + fZins, -fZzr))
     987                 :          0 :                 + (fRmz * (1.0 - pow(1.0 + fZins, -fZzr)) / fZins);
     988                 :          0 :     return -fBw;
     989                 :            : }
     990                 :            : 
     991                 :          0 : void ScInterpreter::ScBW()
     992                 :            : {
     993                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBW" );
     994                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
     995                 :          0 :     double nRmz, nZzr, nZins, nZw = 0, nFlag = 0;
     996                 :          0 :     sal_uInt8 nParamCount = GetByte();
     997         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
     998                 :          0 :         return;
     999         [ #  # ]:          0 :     if (nParamCount == 5)
    1000                 :          0 :         nFlag = GetDouble();
    1001         [ #  # ]:          0 :     if (nParamCount >= 4)
    1002                 :          0 :         nZw   = GetDouble();
    1003                 :          0 :     nRmz  = GetDouble();
    1004                 :          0 :     nZzr  = GetDouble();
    1005                 :          0 :     nZins = GetDouble();
    1006                 :          0 :     PushDouble(ScGetBw(nZins, nZzr, nRmz, nZw, nFlag));
    1007                 :            : }
    1008                 :            : 
    1009                 :          0 : void ScInterpreter::ScDIA()
    1010                 :            : {
    1011                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDIA" );
    1012                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1013         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 4 ) )
    1014                 :            :     {
    1015                 :          0 :         double nZr = GetDouble();
    1016                 :          0 :         double nDauer = GetDouble();
    1017                 :          0 :         double nRest = GetDouble();
    1018                 :          0 :         double nWert = GetDouble();
    1019                 :            :         double nDia = ((nWert - nRest) * (nDauer - nZr + 1.0)) /
    1020                 :          0 :                       ((nDauer * (nDauer + 1.0)) / 2.0);
    1021                 :          0 :         PushDouble(nDia);
    1022                 :            :     }
    1023                 :          0 : }
    1024                 :            : 
    1025                 :          0 : double ScInterpreter::ScGetGDA(double fWert, double fRest, double fDauer,
    1026                 :            :                 double fPeriode, double fFaktor)
    1027                 :            : {
    1028                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetGDA" );
    1029                 :            :     double fGda, fZins, fAlterWert, fNeuerWert;
    1030                 :          0 :     fZins = fFaktor / fDauer;
    1031         [ #  # ]:          0 :     if (fZins >= 1.0)
    1032                 :            :     {
    1033                 :          0 :         fZins = 1.0;
    1034         [ #  # ]:          0 :         if (fPeriode == 1.0)
    1035                 :          0 :             fAlterWert = fWert;
    1036                 :            :         else
    1037                 :          0 :             fAlterWert = 0.0;
    1038                 :            :     }
    1039                 :            :     else
    1040                 :          0 :         fAlterWert = fWert * pow(1.0 - fZins, fPeriode - 1.0);
    1041                 :          0 :     fNeuerWert = fWert * pow(1.0 - fZins, fPeriode);
    1042                 :            : 
    1043         [ #  # ]:          0 :     if (fNeuerWert < fRest)
    1044                 :          0 :         fGda = fAlterWert - fRest;
    1045                 :            :     else
    1046                 :          0 :         fGda = fAlterWert - fNeuerWert;
    1047         [ #  # ]:          0 :     if (fGda < 0.0)
    1048                 :          0 :         fGda = 0.0;
    1049                 :          0 :     return fGda;
    1050                 :            : }
    1051                 :            : 
    1052                 :          0 : void ScInterpreter::ScGDA()
    1053                 :            : {
    1054                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGDA" );
    1055                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1056                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1057         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 4, 5 ) )
    1058                 :            :     {
    1059                 :            :         double nFaktor;
    1060         [ #  # ]:          0 :         if (nParamCount == 5)
    1061                 :          0 :             nFaktor = GetDouble();
    1062                 :            :         else
    1063                 :          0 :             nFaktor = 2.0;
    1064                 :          0 :         double nPeriode = GetDouble();
    1065                 :          0 :         double nDauer   = GetDouble();
    1066                 :          0 :         double nRest    = GetDouble();
    1067                 :          0 :         double nWert    = GetDouble();
    1068 [ #  # ][ #  # ]:          0 :         if (nWert < 0.0 || nRest < 0.0 || nFaktor <= 0.0 || nRest > nWert
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1069                 :            :                         || nPeriode < 1.0 || nPeriode > nDauer)
    1070                 :          0 :             PushIllegalArgument();
    1071                 :            :         else
    1072                 :          0 :             PushDouble(ScGetGDA(nWert, nRest, nDauer, nPeriode, nFaktor));
    1073                 :            :     }
    1074                 :          0 : }
    1075                 :            : 
    1076                 :          0 : void ScInterpreter::ScGDA2()
    1077                 :            : {
    1078                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGDA2" );
    1079                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1080                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1081         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 4, 5 ) )
    1082                 :          0 :         return ;
    1083                 :            :     double nMonate;
    1084         [ #  # ]:          0 :     if (nParamCount == 4)
    1085                 :          0 :         nMonate = 12.0;
    1086                 :            :     else
    1087                 :          0 :         nMonate = ::rtl::math::approxFloor(GetDouble());
    1088                 :          0 :     double nPeriode = GetDouble();
    1089                 :          0 :     double nDauer = GetDouble();
    1090                 :          0 :     double nRest = GetDouble();
    1091                 :          0 :     double nWert = GetDouble();
    1092 [ #  # ][ #  # ]:          0 :     if (nMonate < 1.0 || nMonate > 12.0 || nDauer > 1200.0 || nRest < 0.0 ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1093                 :            :         nPeriode > (nDauer + 1.0) || nRest > nWert || nWert < 0.0)
    1094                 :            :     {
    1095                 :          0 :         PushIllegalArgument();
    1096                 :          0 :         return;
    1097                 :            :     }
    1098                 :          0 :     double nAbRate = 1.0 - pow(nRest / nWert, 1.0 / nDauer);
    1099                 :          0 :     nAbRate = ::rtl::math::approxFloor((nAbRate * 1000.0) + 0.5) / 1000.0;
    1100                 :          0 :     double nErsteAbRate = nWert * nAbRate * nMonate / 12.0;
    1101                 :          0 :     double nGda2 = 0.0;
    1102         [ #  # ]:          0 :     if (::rtl::math::approxFloor(nPeriode) == 1)
    1103                 :          0 :         nGda2 = nErsteAbRate;
    1104                 :            :     else
    1105                 :            :     {
    1106                 :          0 :         double nSummAbRate = nErsteAbRate;
    1107                 :          0 :         double nMin = nDauer;
    1108         [ #  # ]:          0 :         if (nMin > nPeriode) nMin = nPeriode;
    1109                 :          0 :         sal_uInt16 iMax = (sal_uInt16)::rtl::math::approxFloor(nMin);
    1110         [ #  # ]:          0 :         for (sal_uInt16 i = 2; i <= iMax; i++)
    1111                 :            :         {
    1112                 :          0 :             nGda2 = (nWert - nSummAbRate) * nAbRate;
    1113                 :          0 :             nSummAbRate += nGda2;
    1114                 :            :         }
    1115         [ #  # ]:          0 :         if (nPeriode > nDauer)
    1116                 :          0 :             nGda2 = ((nWert - nSummAbRate) * nAbRate * (12.0 - nMonate)) / 12.0;
    1117                 :            :     }
    1118                 :          0 :     PushDouble(nGda2);
    1119                 :            : }
    1120                 :            : 
    1121                 :            : 
    1122                 :          0 : double ScInterpreter::ScInterVDB(double fWert,double fRest,double fDauer,
    1123                 :            :                              double fDauer1,double fPeriode,double fFaktor)
    1124                 :            : {
    1125                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScInterVDB" );
    1126                 :          0 :     double fVdb=0;
    1127                 :          0 :     double fIntEnd   = ::rtl::math::approxCeil(fPeriode);
    1128                 :          0 :     sal_uLong nLoopEnd   = (sal_uLong) fIntEnd;
    1129                 :            : 
    1130                 :            :     double fTerm, fLia;
    1131                 :          0 :     double fRestwert = fWert - fRest;
    1132                 :          0 :     bool bNowLia = false;
    1133                 :            : 
    1134                 :            :     double fGda;
    1135                 :            :     sal_uLong i;
    1136                 :          0 :     fLia=0;
    1137         [ #  # ]:          0 :     for ( i = 1; i <= nLoopEnd; i++)
    1138                 :            :     {
    1139         [ #  # ]:          0 :         if(!bNowLia)
    1140                 :            :         {
    1141                 :          0 :             fGda = ScGetGDA(fWert, fRest, fDauer, (double) i, fFaktor);
    1142                 :          0 :             fLia = fRestwert/ (fDauer1 - (double) (i-1));
    1143                 :            : 
    1144         [ #  # ]:          0 :             if (fLia > fGda)
    1145                 :            :             {
    1146                 :          0 :                 fTerm = fLia;
    1147                 :          0 :                 bNowLia = true;
    1148                 :            :             }
    1149                 :            :             else
    1150                 :            :             {
    1151                 :          0 :                 fTerm = fGda;
    1152                 :          0 :                 fRestwert -= fGda;
    1153                 :            :             }
    1154                 :            :         }
    1155                 :            :         else
    1156                 :            :         {
    1157                 :          0 :             fTerm = fLia;
    1158                 :            :         }
    1159                 :            : 
    1160         [ #  # ]:          0 :         if ( i == nLoopEnd)
    1161                 :          0 :             fTerm *= ( fPeriode + 1.0 - fIntEnd );
    1162                 :            : 
    1163                 :          0 :         fVdb += fTerm;
    1164                 :            :     }
    1165                 :          0 :     return fVdb;
    1166                 :            : }
    1167                 :            : 
    1168                 :            : 
    1169                 :          0 : inline double DblMin( double a, double b )
    1170                 :            : {
    1171         [ #  # ]:          0 :     return (a < b) ? a : b;
    1172                 :            : }
    1173                 :            : 
    1174                 :          0 : void ScInterpreter::ScVDB()
    1175                 :            : {
    1176                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVDB" );
    1177                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1178                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1179         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 5, 7 ) )
    1180                 :            :     {
    1181                 :          0 :         double fWert, fRest, fDauer, fAnfang, fEnde, fFaktor, fVdb = 0.0;
    1182                 :            :         bool bFlag;
    1183         [ #  # ]:          0 :         if (nParamCount == 7)
    1184                 :          0 :             bFlag = GetBool();
    1185                 :            :         else
    1186                 :          0 :             bFlag = false;
    1187         [ #  # ]:          0 :         if (nParamCount >= 6)
    1188                 :          0 :             fFaktor = GetDouble();
    1189                 :            :         else
    1190                 :          0 :             fFaktor = 2.0;
    1191                 :          0 :         fEnde   = GetDouble();
    1192                 :          0 :         fAnfang = GetDouble();
    1193                 :          0 :         fDauer  = GetDouble();
    1194                 :          0 :         fRest   = GetDouble();
    1195                 :          0 :         fWert   = GetDouble();
    1196 [ #  # ][ #  # ]:          0 :         if (fAnfang < 0.0 || fEnde < fAnfang || fEnde > fDauer || fWert < 0.0
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1197                 :            :                           || fRest > fWert || fFaktor <= 0.0)
    1198                 :          0 :             PushIllegalArgument();
    1199                 :            :         else
    1200                 :            :         {
    1201                 :          0 :             double fIntStart = ::rtl::math::approxFloor(fAnfang);
    1202                 :          0 :             double fIntEnd   = ::rtl::math::approxCeil(fEnde);
    1203                 :          0 :             sal_uLong nLoopStart = (sal_uLong) fIntStart;
    1204                 :          0 :             sal_uLong nLoopEnd   = (sal_uLong) fIntEnd;
    1205                 :            : 
    1206                 :          0 :             fVdb = 0.0;
    1207         [ #  # ]:          0 :             if (bFlag)
    1208                 :            :             {
    1209         [ #  # ]:          0 :                 for (sal_uLong i = nLoopStart + 1; i <= nLoopEnd; i++)
    1210                 :            :                 {
    1211                 :          0 :                     double fTerm = ScGetGDA(fWert, fRest, fDauer, (double) i, fFaktor);
    1212                 :            : 
    1213                 :            :                     //  Teilperioden am Anfang / Ende beruecksichtigen:
    1214         [ #  # ]:          0 :                     if ( i == nLoopStart+1 )
    1215                 :          0 :                         fTerm *= ( DblMin( fEnde, fIntStart + 1.0 ) - fAnfang );
    1216         [ #  # ]:          0 :                     else if ( i == nLoopEnd )
    1217                 :          0 :                         fTerm *= ( fEnde + 1.0 - fIntEnd );
    1218                 :            : 
    1219                 :          0 :                     fVdb += fTerm;
    1220                 :            :                 }
    1221                 :            :             }
    1222                 :            :             else
    1223                 :            :             {
    1224                 :            : 
    1225                 :          0 :                 double fDauer1=fDauer;
    1226                 :            : 
    1227                 :            :                 //@Die Frage aller Fragen: "Ist das hier richtig"
    1228         [ #  # ]:          0 :                 if(!::rtl::math::approxEqual(fAnfang,::rtl::math::approxFloor(fAnfang)))
    1229                 :            :                 {
    1230         [ #  # ]:          0 :                     if(fFaktor>1)
    1231                 :            :                     {
    1232 [ #  # ][ #  # ]:          0 :                         if(fAnfang>fDauer/2 || ::rtl::math::approxEqual(fAnfang,fDauer/2))
                 [ #  # ]
    1233                 :            :                         {
    1234                 :          0 :                             double fPart=fAnfang-fDauer/2;
    1235                 :          0 :                             fAnfang=fDauer/2;
    1236                 :          0 :                             fEnde-=fPart;
    1237                 :          0 :                             fDauer1+=1;
    1238                 :            :                         }
    1239                 :            :                     }
    1240                 :            :                 }
    1241                 :            : 
    1242                 :          0 :                 fWert-=ScInterVDB(fWert,fRest,fDauer,fDauer1,fAnfang,fFaktor);
    1243                 :          0 :                 fVdb=ScInterVDB(fWert,fRest,fDauer,fDauer-fAnfang,fEnde-fAnfang,fFaktor);
    1244                 :            :             }
    1245                 :            :         }
    1246                 :          0 :         PushDouble(fVdb);
    1247                 :            :     }
    1248                 :          0 : }
    1249                 :            : 
    1250                 :          0 : void ScInterpreter::ScLaufz()
    1251                 :            : {
    1252                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLaufz" );
    1253         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
    1254                 :            :     {
    1255                 :          0 :         double nZukunft = GetDouble();
    1256                 :          0 :         double nGegenwart = GetDouble();
    1257                 :          0 :         double nZins = GetDouble();
    1258                 :          0 :         PushDouble(log(nZukunft / nGegenwart) / log(1.0 + nZins));
    1259                 :            :     }
    1260                 :          0 : }
    1261                 :            : 
    1262                 :          0 : void ScInterpreter::ScLIA()
    1263                 :            : {
    1264                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLIA" );
    1265                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1266         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
    1267                 :            :     {
    1268                 :          0 :         double nDauer = GetDouble();
    1269                 :          0 :         double nRest = GetDouble();
    1270                 :          0 :         double nWert = GetDouble();
    1271                 :          0 :         PushDouble((nWert - nRest) / nDauer);
    1272                 :            :     }
    1273                 :          0 : }
    1274                 :            : 
    1275                 :          0 : double ScInterpreter::ScGetRmz(double fRate, double fNper, double fPv,
    1276                 :            :                        double fFv, double fPaytype)
    1277                 :            : {
    1278                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetRmz" );
    1279                 :            :     double fPayment;
    1280         [ #  # ]:          0 :     if (fRate == 0.0)
    1281                 :          0 :         fPayment = (fPv + fFv) / fNper;
    1282                 :            :     else
    1283                 :            :     {
    1284         [ #  # ]:          0 :         if (fPaytype > 0.0) // payment in advance
    1285                 :          0 :             fPayment = (fFv + fPv * exp( fNper * ::rtl::math::log1p(fRate) ) ) * fRate /
    1286                 :          0 :                 (::rtl::math::expm1( (fNper + 1) * ::rtl::math::log1p(fRate) ) - fRate);
    1287                 :            :         else  // payment in arrear
    1288                 :          0 :             fPayment = (fFv + fPv * exp(fNper * ::rtl::math::log1p(fRate) ) ) * fRate /
    1289                 :          0 :                 ::rtl::math::expm1( fNper * ::rtl::math::log1p(fRate) );
    1290                 :            :     }
    1291                 :          0 :     return -fPayment;
    1292                 :            : }
    1293                 :            : 
    1294                 :          0 : void ScInterpreter::ScRMZ()
    1295                 :            : {
    1296                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRMZ" );
    1297                 :          0 :     double nZins, nZzr, nBw, nZw = 0, nFlag = 0;
    1298                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1299                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1300         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
    1301                 :          0 :         return;
    1302         [ #  # ]:          0 :     if (nParamCount == 5)
    1303                 :          0 :         nFlag = GetDouble();
    1304         [ #  # ]:          0 :     if (nParamCount >= 4)
    1305                 :          0 :         nZw   = GetDouble();
    1306                 :          0 :     nBw   = GetDouble();
    1307                 :          0 :     nZzr  = GetDouble();
    1308                 :          0 :     nZins = GetDouble();
    1309                 :          0 :     PushDouble(ScGetRmz(nZins, nZzr, nBw, nZw, nFlag));
    1310                 :            : }
    1311                 :            : 
    1312                 :          0 : void ScInterpreter::ScZGZ()
    1313                 :            : {
    1314                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZGZ" );
    1315                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
    1316         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
    1317                 :            :     {
    1318                 :          0 :         double nZukunftswert = GetDouble();
    1319                 :          0 :         double nGegenwartswert = GetDouble();
    1320                 :          0 :         double nZeitraum = GetDouble();
    1321                 :          0 :         PushDouble(pow(nZukunftswert / nGegenwartswert, 1.0 / nZeitraum) - 1.0);
    1322                 :            :     }
    1323                 :          0 : }
    1324                 :            : 
    1325                 :          0 : double ScInterpreter::ScGetZw(double fZins, double fZzr, double fRmz,
    1326                 :            :                               double fBw, double fF)
    1327                 :            : {
    1328                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetZw" );
    1329                 :            :     double fZw;
    1330         [ #  # ]:          0 :     if (fZins == 0.0)
    1331                 :          0 :         fZw = fBw + fRmz * fZzr;
    1332                 :            :     else
    1333                 :            :     {
    1334                 :          0 :         double fTerm = pow(1.0 + fZins, fZzr);
    1335         [ #  # ]:          0 :         if (fF > 0.0)
    1336                 :          0 :             fZw = fBw * fTerm + fRmz*(1.0 + fZins)*(fTerm - 1.0)/fZins;
    1337                 :            :         else
    1338                 :          0 :             fZw = fBw * fTerm + fRmz*(fTerm - 1.0)/fZins;
    1339                 :            :     }
    1340                 :          0 :     return -fZw;
    1341                 :            : }
    1342                 :            : 
    1343                 :          0 : void ScInterpreter::ScZW()
    1344                 :            : {
    1345                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZW" );
    1346                 :          0 :     double nZins, nZzr, nRmz, nBw = 0, nFlag = 0;
    1347                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1348                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1349         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
    1350                 :          0 :         return;
    1351         [ #  # ]:          0 :     if (nParamCount == 5)
    1352                 :          0 :         nFlag = GetDouble();
    1353         [ #  # ]:          0 :     if (nParamCount >= 4)
    1354                 :          0 :         nBw   = GetDouble();
    1355                 :          0 :     nRmz  = GetDouble();
    1356                 :          0 :     nZzr  = GetDouble();
    1357                 :          0 :     nZins = GetDouble();
    1358                 :          0 :     PushDouble(ScGetZw(nZins, nZzr, nRmz, nBw, nFlag));
    1359                 :            : }
    1360                 :            : 
    1361                 :          0 : void ScInterpreter::ScZZR()
    1362                 :            : {
    1363                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZZR" );
    1364                 :          0 :     double nZins, nRmz, nBw, nZw = 0, nFlag = 0;
    1365                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1366         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
    1367                 :          0 :         return;
    1368         [ #  # ]:          0 :     if (nParamCount == 5)
    1369                 :          0 :         nFlag = GetDouble();
    1370         [ #  # ]:          0 :     if (nParamCount >= 4)
    1371                 :          0 :         nZw   = GetDouble();
    1372                 :          0 :     nBw   = GetDouble();
    1373                 :          0 :     nRmz  = GetDouble();
    1374                 :          0 :     nZins = GetDouble();
    1375         [ #  # ]:          0 :     if (nZins == 0.0)
    1376                 :          0 :         PushDouble(-(nBw + nZw)/nRmz);
    1377         [ #  # ]:          0 :     else if (nFlag > 0.0)
    1378                 :          0 :         PushDouble(log(-(nZins*nZw-nRmz*(1.0+nZins))/(nZins*nBw+nRmz*(1.0+nZins)))
    1379                 :          0 :                   /log(1.0+nZins));
    1380                 :            :     else
    1381                 :          0 :         PushDouble(log(-(nZins*nZw-nRmz)/(nZins*nBw+nRmz))/log(1.0+nZins));
    1382                 :            : }
    1383                 :            : 
    1384                 :          0 : bool ScInterpreter::RateIteration( double fNper, double fPayment, double fPv,
    1385                 :            :                                    double fFv, double fPayType, double & fGuess )
    1386                 :            : {
    1387                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::RateIteration" );
    1388                 :            :     // See also #i15090#
    1389                 :            :     // Newton-Raphson method: x(i+1) = x(i) - f(x(i)) / f'(x(i))
    1390                 :            :     // This solution handles integer and non-integer values of Nper different.
    1391                 :            :     // If ODFF will constraint Nper to integer, the distinction of cases can be
    1392                 :            :     // removed; only the integer-part is needed then.
    1393                 :          0 :     bool bValid = true, bFound = false;
    1394                 :            :     double fX, fXnew, fTerm, fTermDerivation;
    1395                 :            :     double fGeoSeries, fGeoSeriesDerivation;
    1396                 :          0 :     const sal_uInt16 nIterationsMax = 150;
    1397                 :          0 :     sal_uInt16 nCount = 0;
    1398                 :          0 :     const double fEpsilonSmall = 1.0E-14;
    1399                 :            :     // convert any fPayType situation to fPayType == zero situation
    1400                 :          0 :     fFv = fFv - fPayment * fPayType;
    1401                 :          0 :     fPv = fPv + fPayment * fPayType;
    1402         [ #  # ]:          0 :     if (fNper == ::rtl::math::round( fNper, 0, rtl_math_RoundingMode_Corrected ))
    1403                 :            :     { // Nper is an integer value
    1404                 :          0 :         fX = fGuess;
    1405                 :            :         double fPowN, fPowNminus1;  // for (1.0+fX)^Nper and (1.0+fX)^(Nper-1)
    1406 [ #  # ][ #  # ]:          0 :         while (!bFound && nCount < nIterationsMax)
                 [ #  # ]
    1407                 :            :         {
    1408                 :          0 :             fPowNminus1 = pow( 1.0+fX, fNper-1.0);
    1409                 :          0 :             fPowN = fPowNminus1 * (1.0+fX);
    1410         [ #  # ]:          0 :             if (rtl::math::approxEqual( fabs(fX), 0.0))
    1411                 :            :             {
    1412                 :          0 :                 fGeoSeries = fNper;
    1413                 :          0 :                 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
    1414                 :            :             }
    1415                 :            :             else
    1416                 :            :             {
    1417                 :          0 :                 fGeoSeries = (fPowN-1.0)/fX;
    1418                 :          0 :                 fGeoSeriesDerivation = fNper * fPowNminus1 / fX - fGeoSeries / fX;
    1419                 :            :             }
    1420                 :          0 :             fTerm = fFv + fPv *fPowN+ fPayment * fGeoSeries;
    1421                 :          0 :             fTermDerivation = fPv * fNper * fPowNminus1 + fPayment * fGeoSeriesDerivation;
    1422         [ #  # ]:          0 :             if (fabs(fTerm) < fEpsilonSmall)
    1423                 :          0 :                 bFound = true;  // will catch root which is at an extreme
    1424                 :            :             else
    1425                 :            :             {
    1426         [ #  # ]:          0 :                 if (rtl::math::approxEqual( fabs(fTermDerivation), 0.0))
    1427                 :          0 :                     fXnew = fX + 1.1 * SCdEpsilon;  // move away from zero slope
    1428                 :            :                 else
    1429                 :          0 :                     fXnew = fX - fTerm / fTermDerivation;
    1430                 :          0 :             nCount++;
    1431                 :            :             // more accuracy not possible in oscillating cases
    1432                 :          0 :             bFound = (fabs(fXnew - fX) < SCdEpsilon);
    1433                 :          0 :             fX = fXnew;
    1434                 :            :             }
    1435                 :            :         }
    1436                 :            :         // Gnumeric returns roots < -1, Excel gives an error in that cases,
    1437                 :            :         // ODFF says nothing about it. Enable the statement, if you want Excel's
    1438                 :            :         // behavior
    1439                 :            :         //bValid =(fX >=-1.0);
    1440                 :            :     }
    1441                 :            :     else
    1442                 :            :     { // Nper is not an integer value.
    1443         [ #  # ]:          0 :         fX = (fGuess < -1.0) ? -1.0 : fGuess;   // start with a valid fX
    1444 [ #  # ][ #  # ]:          0 :         while (bValid && !bFound && nCount < nIterationsMax)
         [ #  # ][ #  # ]
    1445                 :            :         {
    1446         [ #  # ]:          0 :             if (rtl::math::approxEqual( fabs(fX), 0.0))
    1447                 :            :             {
    1448                 :          0 :                 fGeoSeries = fNper;
    1449                 :          0 :                 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
    1450                 :            :             }
    1451                 :            :             else
    1452                 :            :             {
    1453                 :          0 :                 fGeoSeries = (pow( 1.0+fX, fNper) - 1.0) / fX;
    1454                 :          0 :                 fGeoSeriesDerivation = fNper * pow( 1.0+fX, fNper-1.0) / fX - fGeoSeries / fX;
    1455                 :            :             }
    1456                 :          0 :             fTerm = fFv + fPv *pow(1.0 + fX,fNper)+ fPayment * fGeoSeries;
    1457                 :          0 :             fTermDerivation = fPv * fNper * pow( 1.0+fX, fNper-1.0) + fPayment * fGeoSeriesDerivation;
    1458         [ #  # ]:          0 :             if (fabs(fTerm) < fEpsilonSmall)
    1459                 :          0 :                 bFound = true;  // will catch root which is at an extreme
    1460                 :            :             else
    1461                 :            :             {
    1462         [ #  # ]:          0 :                 if (rtl::math::approxEqual( fabs(fTermDerivation), 0.0))
    1463                 :          0 :                     fXnew = fX + 1.1 * SCdEpsilon;  // move away from zero slope
    1464                 :            :                 else
    1465                 :          0 :                     fXnew = fX - fTerm / fTermDerivation;
    1466                 :          0 :             nCount++;
    1467                 :            :              // more accuracy not possible in oscillating cases
    1468                 :          0 :             bFound = (fabs(fXnew - fX) < SCdEpsilon);
    1469                 :          0 :             fX = fXnew;
    1470                 :          0 :             bValid = (fX >= -1.0);  // otherwise pow(1.0+fX,fNper) will fail
    1471                 :            :             }
    1472                 :            :         }
    1473                 :            :     }
    1474                 :          0 :     fGuess = fX;    // return approximate root
    1475 [ #  # ][ #  # ]:          0 :     return bValid && bFound;
    1476                 :            : }
    1477                 :            : 
    1478                 :            : // In Calc UI it is the function RATE(Nper;Pmt;Pv;Fv;Type;Guess)
    1479                 :          0 : void ScInterpreter::ScZins()
    1480                 :            : {
    1481                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZins" );
    1482                 :            :     double fPv, fPayment, fNper;
    1483                 :            :     // defaults for missing arguments, see ODFF spec
    1484                 :          0 :     double fFv = 0, fPayType = 0, fGuess = 0.1;
    1485                 :          0 :     bool bValid = true;
    1486                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
    1487                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1488 [ #  # ][ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 3, 6 ) )
    1489                 :            :         return;
    1490         [ #  # ]:          0 :     if (nParamCount == 6)
    1491         [ #  # ]:          0 :         fGuess = GetDouble();
    1492         [ #  # ]:          0 :     if (nParamCount >= 5)
    1493         [ #  # ]:          0 :         fPayType = GetDouble();
    1494         [ #  # ]:          0 :     if (nParamCount >= 4)
    1495         [ #  # ]:          0 :         fFv = GetDouble();
    1496         [ #  # ]:          0 :     fPv = GetDouble();
    1497         [ #  # ]:          0 :     fPayment = GetDouble();
    1498         [ #  # ]:          0 :     fNper = GetDouble();
    1499         [ #  # ]:          0 :     if (fNper <= 0.0) // constraint from ODFF spec
    1500                 :            :     {
    1501         [ #  # ]:          0 :         PushIllegalArgument();
    1502                 :            :         return;
    1503                 :            :     }
    1504                 :            :     // other values for fPayType might be meaningful,
    1505                 :            :     // ODFF spec is not clear yet, enable statement if you want only 0 and 1
    1506                 :            :     //if (fPayType != 0.0) fPayType = 1.0;
    1507                 :          0 :     bValid = RateIteration(fNper, fPayment, fPv, fFv, fPayType, fGuess);
    1508         [ #  # ]:          0 :     if (!bValid)
    1509                 :          0 :         SetError(errNoConvergence);
    1510         [ #  # ]:          0 :     PushDouble(fGuess);
    1511                 :            : }
    1512                 :            : 
    1513                 :          0 : double ScInterpreter::ScGetZinsZ(double fZins, double fZr, double fZzr, double fBw,
    1514                 :            :                                  double fZw, double fF, double& fRmz)
    1515                 :            : {
    1516                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetZinsZ" );
    1517                 :          0 :     fRmz = ScGetRmz(fZins, fZzr, fBw, fZw, fF);     // fuer kapz auch bei fZr == 1
    1518                 :            :     double fZinsZ;
    1519                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1520         [ #  # ]:          0 :     if (fZr == 1.0)
    1521                 :            :     {
    1522         [ #  # ]:          0 :         if (fF > 0.0)
    1523                 :          0 :             fZinsZ = 0.0;
    1524                 :            :         else
    1525                 :          0 :             fZinsZ = -fBw;
    1526                 :            :     }
    1527                 :            :     else
    1528                 :            :     {
    1529         [ #  # ]:          0 :         if (fF > 0.0)
    1530                 :          0 :             fZinsZ = ScGetZw(fZins, fZr-2.0, fRmz, fBw, 1.0) - fRmz;
    1531                 :            :         else
    1532                 :          0 :             fZinsZ = ScGetZw(fZins, fZr-1.0, fRmz, fBw, 0.0);
    1533                 :            :     }
    1534                 :          0 :     return fZinsZ * fZins;
    1535                 :            : }
    1536                 :            : 
    1537                 :          0 : void ScInterpreter::ScZinsZ()
    1538                 :            : {
    1539                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScZinsZ" );
    1540                 :          0 :     double nZins, nZr, nZzr, nBw, nZw = 0, nFlag = 0;
    1541                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1542                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1543         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 4, 6 ) )
    1544                 :          0 :         return;
    1545         [ #  # ]:          0 :     if (nParamCount == 6)
    1546                 :          0 :         nFlag = GetDouble();
    1547         [ #  # ]:          0 :     if (nParamCount >= 5)
    1548                 :          0 :         nZw   = GetDouble();
    1549                 :          0 :     nBw   = GetDouble();
    1550                 :          0 :     nZzr  = GetDouble();
    1551                 :          0 :     nZr   = GetDouble();
    1552                 :          0 :     nZins = GetDouble();
    1553 [ #  # ][ #  # ]:          0 :     if (nZr < 1.0 || nZr > nZzr)
    1554                 :          0 :         PushIllegalArgument();
    1555                 :            :     else
    1556                 :            :     {
    1557                 :            :         double nRmz;
    1558         [ #  # ]:          0 :         PushDouble(ScGetZinsZ(nZins, nZr, nZzr, nBw, nZw, nFlag, nRmz));
    1559                 :            :     }
    1560                 :            : }
    1561                 :            : 
    1562                 :          0 : void ScInterpreter::ScKapz()
    1563                 :            : {
    1564                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKapz" );
    1565                 :          0 :     double nZins, nZr, nZzr, nBw, nZw = 0, nFlag = 0;
    1566                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1567                 :          0 :     sal_uInt8 nParamCount = GetByte();
    1568         [ #  # ]:          0 :     if ( !MustHaveParamCount( nParamCount, 4, 6 ) )
    1569                 :          0 :         return;
    1570         [ #  # ]:          0 :     if (nParamCount == 6)
    1571                 :          0 :         nFlag = GetDouble();
    1572         [ #  # ]:          0 :     if (nParamCount >= 5)
    1573                 :          0 :         nZw   = GetDouble();
    1574                 :          0 :     nBw   = GetDouble();
    1575                 :          0 :     nZzr  = GetDouble();
    1576                 :          0 :     nZr   = GetDouble();
    1577                 :          0 :     nZins = GetDouble();
    1578 [ #  # ][ #  # ]:          0 :     if (nZr < 1.0 || nZr > nZzr)
    1579                 :          0 :         PushIllegalArgument();
    1580                 :            :     else
    1581                 :            :     {
    1582                 :            :         double nRmz;
    1583                 :          0 :         double nZinsz = ScGetZinsZ(nZins, nZr, nZzr, nBw, nZw, nFlag, nRmz);
    1584         [ #  # ]:          0 :         PushDouble(nRmz - nZinsz);
    1585                 :            :     }
    1586                 :            : }
    1587                 :            : 
    1588                 :          0 : void ScInterpreter::ScKumZinsZ()
    1589                 :            : {
    1590                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKumZinsZ" );
    1591                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1592         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 6 ) )
    1593                 :            :     {
    1594                 :            :         double fZins, fZzr, fBw, fAnfang, fEnde, fF;
    1595                 :          0 :         fF      = GetDouble();
    1596                 :          0 :         fEnde   = ::rtl::math::approxFloor(GetDouble());
    1597                 :          0 :         fAnfang = ::rtl::math::approxFloor(GetDouble());
    1598                 :          0 :         fBw     = GetDouble();
    1599                 :          0 :         fZzr    = GetDouble();
    1600                 :          0 :         fZins   = GetDouble();
    1601 [ #  # ][ #  # ]:          0 :         if (fAnfang < 1.0 || fEnde < fAnfang || fZins <= 0.0 ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1602                 :            :             fEnde > fZzr  || fZzr <= 0.0 || fBw <= 0.0)
    1603                 :          0 :             PushIllegalArgument();
    1604                 :            :         else
    1605                 :            :         {
    1606                 :          0 :             sal_uLong nAnfang = (sal_uLong) fAnfang;
    1607                 :          0 :             sal_uLong nEnde = (sal_uLong) fEnde ;
    1608                 :          0 :             double fRmz = ScGetRmz(fZins, fZzr, fBw, 0.0, fF);
    1609                 :          0 :             double fZinsZ = 0.0;
    1610         [ #  # ]:          0 :             if (nAnfang == 1)
    1611                 :            :             {
    1612         [ #  # ]:          0 :                 if (fF <= 0.0)
    1613                 :          0 :                     fZinsZ = -fBw;
    1614                 :          0 :                 nAnfang++;
    1615                 :            :             }
    1616         [ #  # ]:          0 :             for (sal_uLong i = nAnfang; i <= nEnde; i++)
    1617                 :            :             {
    1618         [ #  # ]:          0 :                 if (fF > 0.0)
    1619                 :          0 :                     fZinsZ += ScGetZw(fZins, (double)(i-2), fRmz, fBw, 1.0) - fRmz;
    1620                 :            :                 else
    1621                 :          0 :                     fZinsZ += ScGetZw(fZins, (double)(i-1), fRmz, fBw, 0.0);
    1622                 :            :             }
    1623                 :          0 :             fZinsZ *= fZins;
    1624                 :          0 :             PushDouble(fZinsZ);
    1625                 :            :         }
    1626                 :            :     }
    1627                 :          0 : }
    1628                 :            : 
    1629                 :          0 : void ScInterpreter::ScKumKapZ()
    1630                 :            : {
    1631                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScKumKapZ" );
    1632                 :          0 :     nFuncFmtType = NUMBERFORMAT_CURRENCY;
    1633         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 6 ) )
    1634                 :            :     {
    1635                 :            :         double fZins, fZzr, fBw, fAnfang, fEnde, fF;
    1636                 :          0 :         fF      = GetDouble();
    1637                 :          0 :         fEnde   = ::rtl::math::approxFloor(GetDouble());
    1638                 :          0 :         fAnfang = ::rtl::math::approxFloor(GetDouble());
    1639                 :          0 :         fBw     = GetDouble();
    1640                 :          0 :         fZzr    = GetDouble();
    1641                 :          0 :         fZins   = GetDouble();
    1642 [ #  # ][ #  # ]:          0 :         if (fAnfang < 1.0 || fEnde < fAnfang || fZins <= 0.0 ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1643                 :            :             fEnde > fZzr  || fZzr <= 0.0 || fBw <= 0.0)
    1644                 :          0 :             PushIllegalArgument();
    1645                 :            :         else
    1646                 :            :         {
    1647                 :          0 :             double fRmz = ScGetRmz(fZins, fZzr, fBw, 0.0, fF);
    1648                 :          0 :             double fKapZ = 0.0;
    1649                 :          0 :             sal_uLong nAnfang = (sal_uLong) fAnfang;
    1650                 :          0 :             sal_uLong nEnde = (sal_uLong) fEnde;
    1651         [ #  # ]:          0 :             if (nAnfang == 1)
    1652                 :            :             {
    1653         [ #  # ]:          0 :                 if (fF <= 0.0)
    1654                 :          0 :                     fKapZ = fRmz + fBw * fZins;
    1655                 :            :                 else
    1656                 :          0 :                     fKapZ = fRmz;
    1657                 :          0 :                 nAnfang++;
    1658                 :            :             }
    1659         [ #  # ]:          0 :             for (sal_uLong i = nAnfang; i <= nEnde; i++)
    1660                 :            :             {
    1661         [ #  # ]:          0 :                 if (fF > 0.0)
    1662                 :          0 :                     fKapZ += fRmz - (ScGetZw(fZins, (double)(i-2), fRmz, fBw, 1.0) - fRmz) * fZins;
    1663                 :            :                 else
    1664                 :          0 :                     fKapZ += fRmz - ScGetZw(fZins, (double)(i-1), fRmz, fBw, 0.0) * fZins;
    1665                 :            :             }
    1666                 :          0 :             PushDouble(fKapZ);
    1667                 :            :         }
    1668                 :            :     }
    1669                 :          0 : }
    1670                 :            : 
    1671                 :          0 : void ScInterpreter::ScEffektiv()
    1672                 :            : {
    1673                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEffektiv" );
    1674                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
    1675         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
    1676                 :            :     {
    1677                 :          0 :         double fPerioden = GetDouble();
    1678                 :          0 :         double fNominal = GetDouble();
    1679 [ #  # ][ #  # ]:          0 :         if (fPerioden < 1.0 || fNominal <= 0.0)
    1680                 :          0 :             PushIllegalArgument();
    1681                 :            :         else
    1682                 :            :         {
    1683                 :          0 :             fPerioden = ::rtl::math::approxFloor(fPerioden);
    1684                 :          0 :             PushDouble(pow(1.0 + fNominal/fPerioden, fPerioden) - 1.0);
    1685                 :            :         }
    1686                 :            :     }
    1687                 :          0 : }
    1688                 :            : 
    1689                 :          0 : void ScInterpreter::ScNominal()
    1690                 :            : {
    1691                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNominal" );
    1692                 :          0 :     nFuncFmtType = NUMBERFORMAT_PERCENT;
    1693         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
    1694                 :            :     {
    1695                 :          0 :         double fPerioden = GetDouble();
    1696                 :          0 :         double fEffektiv = GetDouble();
    1697 [ #  # ][ #  # ]:          0 :         if (fPerioden < 1.0 || fEffektiv <= 0.0)
    1698                 :          0 :             PushIllegalArgument();
    1699                 :            :         else
    1700                 :            :         {
    1701                 :          0 :             fPerioden = ::rtl::math::approxFloor(fPerioden);
    1702                 :          0 :             PushDouble( (pow(fEffektiv + 1.0, 1.0 / fPerioden) - 1.0) * fPerioden );
    1703                 :            :         }
    1704                 :            :     }
    1705                 :          0 : }
    1706                 :            : 
    1707                 :          0 : void ScInterpreter::ScMod()
    1708                 :            : {
    1709                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMod" );
    1710         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
    1711                 :            :     {
    1712                 :          0 :         double fVal2 = GetDouble(); // Denominator
    1713                 :          0 :         double fVal1 = GetDouble(); // Numerator
    1714         [ #  # ]:          0 :         if (fVal2 == floor(fVal2))  // a pure integral number stored in double
    1715                 :            :         {
    1716                 :          0 :             double fResult = fmod(fVal1,fVal2);
    1717 [ #  # ][ #  # ]:          0 :             if ( (fResult != 0.0) &&
         [ #  # ][ #  # ]
                 [ #  # ]
    1718                 :            :                 ((fVal1 > 0.0 && fVal2 < 0.0) || (fVal1 < 0.0 && fVal2 > 0.0)))
    1719                 :          0 :                 fResult += fVal2 ;
    1720                 :          0 :             PushDouble( fResult );
    1721                 :            :         }
    1722                 :            :         else
    1723                 :            :         {
    1724                 :            :             PushDouble( ::rtl::math::approxSub( fVal1,
    1725                 :          0 :                     ::rtl::math::approxFloor(fVal1 / fVal2) * fVal2));
    1726                 :            :         }
    1727                 :            :     }
    1728                 :          0 : }
    1729                 :            : 
    1730                 :            : /** (Goal Seek) Find a value of x that is a root of f(x)
    1731                 :            : 
    1732                 :            :     This function is used internally for the goal seek operation.  It uses the
    1733                 :            :     Regula Falsi (aka false position) algorithm to find a root of f(x).  The
    1734                 :            :     start value and the target value are to be given by the user in the
    1735                 :            :     goal seek dialog.  The f(x) in this case is defined as the formula in the
    1736                 :            :     formula cell minus target value.  This function may also perform additional
    1737                 :            :     search in the horizontal directions when the f(x) is discrete in order to
    1738                 :            :     ensure a non-zero slope necessary for deriving a subsequent x that is
    1739                 :            :     reasonably close to the root of interest.
    1740                 :            : 
    1741                 :            :     @change 24.10.2004 by Kohei Yoshida (kohei@openoffice.org)
    1742                 :            : 
    1743                 :            :     @see #i28955#
    1744                 :            : */
    1745                 :          3 : void ScInterpreter::ScBackSolver()
    1746                 :            : {
    1747                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBackSolver" );
    1748         [ +  - ]:          3 :     if ( MustHaveParamCount( GetByte(), 3 ) )
    1749                 :            :     {
    1750                 :          3 :         bool bDoneIteration = false;
    1751                 :          3 :         ScAddress aValueAdr, aFormulaAdr;
    1752         [ +  - ]:          3 :         double fTargetVal = GetDouble();
    1753         [ +  - ]:          3 :         PopSingleRef( aFormulaAdr );
    1754         [ +  - ]:          3 :         PopSingleRef( aValueAdr );
    1755                 :            : 
    1756         [ +  - ]:          3 :         if (nGlobalError == 0)
    1757                 :            :         {
    1758         [ +  - ]:          3 :             ScBaseCell* pVCell = GetCell( aValueAdr );
    1759                 :            :             // CELLTYPE_NOTE: kein Value aber von Formel referiert
    1760         [ +  - ]:          3 :             ScBaseCell* pFCell = GetCell( aFormulaAdr );
    1761                 :            : 
    1762 [ +  - ][ +  - ]:          6 :             if ( ((pVCell && pVCell->GetCellType() == CELLTYPE_VALUE))
           [ +  -  +  - ]
                 [ +  - ]
    1763                 :          3 :                 && pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
    1764                 :            :             {
    1765                 :          3 :                 ScRange aVRange( aValueAdr, aValueAdr );    // fuer SetDirty
    1766                 :            :                 double fSaveVal; // Original value to be restored later if necessary
    1767                 :            : 
    1768         [ +  - ]:          3 :                 fSaveVal = GetCellValue( aValueAdr, pVCell );
    1769                 :            : 
    1770                 :          3 :                 const sal_uInt16 nMaxIter = 100;
    1771                 :          3 :                 const double fEps = 1E-10;
    1772                 :          3 :                 const double fDelta = 1E-6;
    1773                 :            : 
    1774                 :            :                 double fBestX, fXPrev;
    1775                 :            :                 double fBestF, fFPrev;
    1776                 :          3 :                 fBestX = fXPrev = fSaveVal;
    1777                 :            : 
    1778         [ +  - ]:          3 :                 ScFormulaCell* pFormula = (ScFormulaCell*) pFCell;
    1779                 :          3 :                 ScValueCell* pValue = (ScValueCell*) pVCell;
    1780                 :            : 
    1781         [ +  - ]:          3 :                 pFormula->Interpret();
    1782         [ +  - ]:          3 :                 bool bError = ( pFormula->GetErrCode() != 0 );
    1783                 :            :                 // bError always corresponds with fF
    1784                 :            : 
    1785         [ +  - ]:          3 :                 fFPrev = pFormula->GetValue() - fTargetVal;
    1786                 :            : 
    1787                 :          3 :                 fBestF = fabs( fFPrev );
    1788         [ -  + ]:          3 :                 if ( fBestF < fDelta )
    1789                 :          0 :                     bDoneIteration = true;
    1790                 :            : 
    1791                 :          3 :                 double fX = fXPrev + fEps;
    1792                 :          3 :                 double fF = fFPrev;
    1793                 :            :                 double fSlope;
    1794                 :            : 
    1795                 :          3 :                 sal_uInt16 nIter = 0;
    1796                 :            : 
    1797                 :          3 :                 bool bHorMoveError = false;
    1798                 :            :                                                 // Nach der Regula Falsi Methode
    1799 [ +  + ][ +  + ]:        118 :                 while ( !bDoneIteration && ( nIter++ < nMaxIter ) )
                 [ +  + ]
    1800                 :            :                 {
    1801                 :        115 :                     pValue->SetValue( fX );
    1802         [ +  - ]:        115 :                     pDok->SetDirty( aVRange );
    1803         [ +  - ]:        115 :                     pFormula->Interpret();
    1804         [ +  - ]:        115 :                     bError = ( pFormula->GetErrCode() != 0 );
    1805         [ +  - ]:        115 :                     fF = pFormula->GetValue() - fTargetVal;
    1806                 :            : 
    1807 [ -  + ][ #  # ]:        115 :                     if ( fF == fFPrev && !bError )
    1808                 :            :                     {
    1809                 :            :                         // HORIZONTAL SEARCH: Keep moving x in both directions until the f(x)
    1810                 :            :                         // becomes different from the previous f(x).  This routine is needed
    1811                 :            :                         // when a given function is discrete, in which case the resulting slope
    1812                 :            :                         // may become zero which ultimately causes the goal seek operation
    1813                 :            :                         // to fail. #i28955#
    1814                 :            : 
    1815                 :          0 :                         sal_uInt16 nHorIter = 0;
    1816                 :          0 :                         const double fHorStepAngle = 5.0;
    1817                 :          0 :                         const double fHorMaxAngle = 80.0;
    1818                 :          0 :                         int nHorMaxIter = static_cast<int>( fHorMaxAngle / fHorStepAngle );
    1819                 :          0 :                         bool bDoneHorMove = false;
    1820                 :            : 
    1821 [ #  # ][ #  # ]:          0 :                         while ( !bDoneHorMove && !bHorMoveError && nHorIter++ < nHorMaxIter )
         [ #  # ][ #  # ]
    1822                 :            :                         {
    1823                 :          0 :                             double fHorAngle = fHorStepAngle * static_cast<double>( nHorIter );
    1824                 :          0 :                             double fHorTangent = ::rtl::math::tan( fHorAngle * F_PI / 180 );
    1825                 :            : 
    1826                 :          0 :                             sal_uInt16 nIdx = 0;
    1827 [ #  # ][ #  # ]:          0 :                             while( nIdx++ < 2 && !bDoneHorMove )
                 [ #  # ]
    1828                 :            :                             {
    1829                 :            :                                 double fHorX;
    1830         [ #  # ]:          0 :                                 if ( nIdx == 1 )
    1831                 :          0 :                                     fHorX = fX + fabs(fF)*fHorTangent;
    1832                 :            :                                 else
    1833                 :          0 :                                     fHorX = fX - fabs(fF)*fHorTangent;
    1834                 :            : 
    1835                 :          0 :                                 pValue->SetValue( fHorX );
    1836         [ #  # ]:          0 :                                 pDok->SetDirty( aVRange );
    1837         [ #  # ]:          0 :                                 pFormula->Interpret();
    1838         [ #  # ]:          0 :                                 bHorMoveError = ( pFormula->GetErrCode() != 0 );
    1839         [ #  # ]:          0 :                                 if ( bHorMoveError )
    1840                 :          0 :                                     break;
    1841                 :            : 
    1842         [ #  # ]:          0 :                                 fF = pFormula->GetValue() - fTargetVal;
    1843         [ #  # ]:          0 :                                 if ( fF != fFPrev )
    1844                 :            :                                 {
    1845                 :          0 :                                     fX = fHorX;
    1846                 :          0 :                                     bDoneHorMove = true;
    1847                 :            :                                 }
    1848                 :            :                             }
    1849                 :            :                         }
    1850         [ #  # ]:          0 :                         if ( !bDoneHorMove )
    1851                 :          0 :                             bHorMoveError = true;
    1852                 :            :                     }
    1853                 :            : 
    1854         [ +  + ]:        115 :                     if ( bError )
    1855                 :            :                     {
    1856                 :            :                         // move closer to last valid value (fXPrev), keep fXPrev & fFPrev
    1857                 :         93 :                         double fDiff = ( fXPrev - fX ) / 2;
    1858         [ -  + ]:         93 :                         if (fabs(fDiff) < fEps)
    1859         [ #  # ]:          0 :                             fDiff = (fDiff < 0.0) ? - fEps : fEps;
    1860                 :         93 :                         fX += fDiff;
    1861                 :            :                     }
    1862         [ -  + ]:         22 :                     else if ( bHorMoveError )
    1863                 :          0 :                         break;
    1864         [ +  + ]:         22 :                     else if ( fabs(fF) < fDelta )
    1865                 :            :                     {
    1866                 :            :                         // converged to root
    1867                 :          2 :                         fBestX = fX;
    1868                 :          2 :                         bDoneIteration = true;
    1869                 :            :                     }
    1870                 :            :                     else
    1871                 :            :                     {
    1872         [ +  + ]:         20 :                         if ( fabs(fF) + fDelta < fBestF )
    1873                 :            :                         {
    1874                 :         17 :                             fBestX = fX;
    1875                 :         17 :                             fBestF = fabs(fF);
    1876                 :            :                         }
    1877                 :            : 
    1878         [ +  - ]:         20 :                         if ( ( fXPrev - fX ) != 0 )
    1879                 :            :                         {
    1880                 :         20 :                             fSlope = ( fFPrev - fF ) / ( fXPrev - fX );
    1881         [ -  + ]:         20 :                             if ( fabs( fSlope ) < fEps )
    1882         [ #  # ]:          0 :                                 fSlope = fSlope < 0.0 ? -fEps : fEps;
    1883                 :            :                         }
    1884                 :            :                         else
    1885                 :          0 :                             fSlope = fEps;
    1886                 :            : 
    1887                 :         20 :                         fXPrev = fX;
    1888                 :         20 :                         fFPrev = fF;
    1889                 :         20 :                         fX = fX - ( fF / fSlope );
    1890                 :            :                     }
    1891                 :            :                 }
    1892                 :            : 
    1893                 :            :                 // Try a nice rounded input value if possible.
    1894 [ +  + ][ +  - ]:          3 :                 const double fNiceDelta = (bDoneIteration && fabs(fBestX) >= 1e-3 ? 1e-3 : fDelta);
    1895                 :          3 :                 double nX = ::rtl::math::approxFloor((fBestX / fNiceDelta) + 0.5) * fNiceDelta;
    1896                 :            : 
    1897         [ +  + ]:          3 :                 if ( bDoneIteration )
    1898                 :            :                 {
    1899                 :          2 :                     pValue->SetValue( nX );
    1900         [ +  - ]:          2 :                     pDok->SetDirty( aVRange );
    1901         [ +  - ]:          2 :                     pFormula->Interpret();
    1902 [ +  - ][ +  + ]:          2 :                     if ( fabs( pFormula->GetValue() - fTargetVal ) > fabs( fF ) )
    1903                 :          1 :                         nX = fBestX;
    1904                 :            :                 }
    1905 [ -  + ][ #  # ]:          1 :                 else if ( bError || bHorMoveError )
    1906                 :            :                 {
    1907                 :          1 :                     nX = fBestX;
    1908                 :            :                 }
    1909                 :          3 :                 pValue->SetValue( fSaveVal );
    1910         [ +  - ]:          3 :                 pDok->SetDirty( aVRange );
    1911         [ +  - ]:          3 :                 pFormula->Interpret();
    1912         [ +  + ]:          3 :                 if ( !bDoneIteration )
    1913                 :          1 :                     SetError(NOTAVAILABLE);
    1914         [ +  - ]:          3 :                 PushDouble(nX);
    1915                 :            :             }
    1916                 :            :             else
    1917                 :            :             {
    1918         [ #  # ]:          0 :                 if ( !bDoneIteration )
    1919                 :          0 :                     SetError(NOTAVAILABLE);
    1920         [ #  # ]:          0 :                 PushInt(0);         // falsche Zelltypen
    1921                 :            :             }
    1922                 :            :         }
    1923                 :            :         else
    1924                 :            :         {
    1925         [ #  # ]:          0 :             if ( !bDoneIteration )
    1926                 :          0 :                 SetError(NOTAVAILABLE);
    1927         [ #  # ]:          3 :             PushInt(0);             // nGlobalError
    1928                 :            :         }
    1929                 :            :     }
    1930                 :          3 : }
    1931                 :            : 
    1932                 :          0 : void ScInterpreter::ScIntersect()
    1933                 :            : {
    1934                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIntersect" );
    1935         [ #  # ]:          0 :     formula::FormulaTokenRef p2nd = PopToken();
    1936         [ #  # ]:          0 :     formula::FormulaTokenRef p1st = PopToken();
    1937                 :            : 
    1938 [ #  # ][ #  # ]:          0 :     if (nGlobalError || !p2nd || !p1st)
         [ #  # ][ #  # ]
    1939                 :            :     {
    1940         [ #  # ]:          0 :         PushIllegalArgument();
    1941                 :            :         return;
    1942                 :            :     }
    1943                 :            : 
    1944                 :          0 :     StackVar sv1 = p1st->GetType();
    1945                 :          0 :     StackVar sv2 = p2nd->GetType();
    1946 [ #  # ][ #  # ]:          0 :     if ((sv1 != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1947                 :            :         (sv2 != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
    1948                 :            :     {
    1949         [ #  # ]:          0 :         PushIllegalArgument();
    1950                 :            :         return;
    1951                 :            :     }
    1952                 :            : 
    1953                 :          0 :     ScToken* x1 = static_cast<ScToken*>(p1st.get());
    1954                 :          0 :     ScToken* x2 = static_cast<ScToken*>(p2nd.get());
    1955 [ #  # ][ #  # ]:          0 :     if (sv1 == svRefList || sv2 == svRefList)
    1956                 :            :     {
    1957                 :            :         // Now this is a bit nasty but it simplifies things, and having
    1958                 :            :         // intersections with lists isn't too common, if at all..
    1959                 :            :         // Convert a reference to list.
    1960                 :          0 :         ScToken* xt[2] = { x1, x2 };
    1961                 :          0 :         StackVar sv[2] = { sv1, sv2 };
    1962         [ #  # ]:          0 :         for (size_t i=0; i<2; ++i)
    1963                 :            :         {
    1964         [ #  # ]:          0 :             if (sv[i] == svSingleRef)
    1965                 :            :             {
    1966                 :            :                 ScComplexRefData aRef;
    1967         [ #  # ]:          0 :                 aRef.Ref1 = aRef.Ref2 = xt[i]->GetSingleRef();
    1968 [ #  # ][ #  # ]:          0 :                 xt[i] = new ScRefListToken;
    1969 [ #  # ][ #  # ]:          0 :                 xt[i]->GetRefList()->push_back( aRef);
    1970                 :            :             }
    1971         [ #  # ]:          0 :             else if (sv[i] == svDoubleRef)
    1972                 :            :             {
    1973         [ #  # ]:          0 :                 ScComplexRefData aRef = xt[i]->GetDoubleRef();
    1974 [ #  # ][ #  # ]:          0 :                 xt[i] = new ScRefListToken;
    1975 [ #  # ][ #  # ]:          0 :                 xt[i]->GetRefList()->push_back( aRef);
    1976                 :            :             }
    1977                 :            :         }
    1978                 :          0 :         x1 = xt[0], x2 = xt[1];
    1979                 :            : 
    1980         [ #  # ]:          0 :         x1->CalcAbsIfRel( aPos);
    1981         [ #  # ]:          0 :         x2->CalcAbsIfRel( aPos);
    1982 [ #  # ][ #  # ]:          0 :         ScTokenRef xRes = new ScRefListToken;
    1983         [ #  # ]:          0 :         ScRefList* pRefList = xRes->GetRefList();
    1984 [ #  # ][ #  # ]:          0 :         ScRefList::const_iterator end1( x1->GetRefList()->end());
    1985 [ #  # ][ #  # ]:          0 :         ScRefList::const_iterator end2( x2->GetRefList()->end());
    1986 [ #  # ][ #  # ]:          0 :         for (ScRefList::const_iterator it1( x1->GetRefList()->begin());
         [ #  # ][ #  # ]
    1987                 :            :                 it1 != end1; ++it1)
    1988                 :            :         {
    1989                 :          0 :             const ScSingleRefData& r11 = (*it1).Ref1;
    1990                 :          0 :             const ScSingleRefData& r12 = (*it1).Ref2;
    1991 [ #  # ][ #  # ]:          0 :             for (ScRefList::const_iterator it2( x2->GetRefList()->begin());
         [ #  # ][ #  # ]
    1992                 :            :                     it2 != end2; ++it2)
    1993                 :            :             {
    1994                 :          0 :                 const ScSingleRefData& r21 = (*it2).Ref1;
    1995                 :          0 :                 const ScSingleRefData& r22 = (*it2).Ref2;
    1996         [ #  # ]:          0 :                 SCCOL nCol1 = ::std::max( r11.nCol, r21.nCol);
    1997         [ #  # ]:          0 :                 SCROW nRow1 = ::std::max( r11.nRow, r21.nRow);
    1998         [ #  # ]:          0 :                 SCTAB nTab1 = ::std::max( r11.nTab, r21.nTab);
    1999         [ #  # ]:          0 :                 SCCOL nCol2 = ::std::min( r12.nCol, r22.nCol);
    2000         [ #  # ]:          0 :                 SCROW nRow2 = ::std::min( r12.nRow, r22.nRow);
    2001         [ #  # ]:          0 :                 SCTAB nTab2 = ::std::min( r12.nTab, r22.nTab);
    2002 [ #  # ][ #  # ]:          0 :                 if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
                 [ #  # ]
    2003                 :            :                     ;   // nothing
    2004                 :            :                 else
    2005                 :            :                 {
    2006                 :            :                     ScComplexRefData aRef;
    2007                 :          0 :                     aRef.InitRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
    2008         [ #  # ]:          0 :                     pRefList->push_back( aRef);
    2009                 :            :                 }
    2010                 :            :             }
    2011                 :            :         }
    2012                 :          0 :         size_t n = pRefList->size();
    2013         [ #  # ]:          0 :         if (!n)
    2014         [ #  # ]:          0 :             PushError( errNoRef);
    2015         [ #  # ]:          0 :         else if (n == 1)
    2016                 :            :         {
    2017                 :          0 :             const ScComplexRefData& rRef = (*pRefList)[0];
    2018 [ #  # ][ #  # ]:          0 :             if (rRef.Ref1 == rRef.Ref2)
    2019 [ #  # ][ #  # ]:          0 :                 PushTempToken( new ScSingleRefToken( rRef.Ref1));
                 [ #  # ]
    2020                 :            :             else
    2021 [ #  # ][ #  # ]:          0 :                 PushTempToken( new ScDoubleRefToken( rRef));
                 [ #  # ]
    2022                 :            :         }
    2023                 :            :         else
    2024 [ #  # ][ #  # ]:          0 :             PushTempToken( xRes.get());
    2025                 :            :     }
    2026                 :            :     else
    2027                 :            :     {
    2028                 :          0 :         ScToken* pt[2] = { x1, x2 };
    2029                 :          0 :         StackVar sv[2] = { sv1, sv2 };
    2030                 :            :         SCCOL nC1[2], nC2[2];
    2031                 :            :         SCROW nR1[2], nR2[2];
    2032                 :            :         SCTAB nT1[2], nT2[2];
    2033         [ #  # ]:          0 :         for (size_t i=0; i<2; ++i)
    2034                 :            :         {
    2035         [ #  # ]:          0 :             switch (sv[i])
    2036                 :            :             {
    2037                 :            :                 case svSingleRef:
    2038                 :            :                 case svDoubleRef:
    2039         [ #  # ]:          0 :                     pt[i]->CalcAbsIfRel( aPos);
    2040                 :            :                     {
    2041         [ #  # ]:          0 :                         const ScSingleRefData& r = pt[i]->GetSingleRef();
    2042                 :          0 :                         nC1[i] = r.nCol;
    2043                 :          0 :                         nR1[i] = r.nRow;
    2044                 :          0 :                         nT1[i] = r.nTab;
    2045                 :            :                     }
    2046         [ #  # ]:          0 :                     if (sv[i] == svDoubleRef)
    2047                 :            :                     {
    2048         [ #  # ]:          0 :                         const ScSingleRefData& r = pt[i]->GetSingleRef2();
    2049                 :          0 :                         nC2[i] = r.nCol;
    2050                 :          0 :                         nR2[i] = r.nRow;
    2051                 :          0 :                         nT2[i] = r.nTab;
    2052                 :            :                     }
    2053                 :            :                     else
    2054                 :            :                     {
    2055                 :          0 :                         nC2[i] = nC1[i];
    2056                 :          0 :                         nR2[i] = nR1[i];
    2057                 :          0 :                         nT2[i] = nT1[i];
    2058                 :            :                     }
    2059                 :          0 :                     break;
    2060                 :            :                 default:
    2061                 :            :                     ;   // nothing, prevent compiler warning
    2062                 :            :             }
    2063                 :            :         }
    2064         [ #  # ]:          0 :         SCCOL nCol1 = ::std::max( nC1[0], nC1[1]);
    2065         [ #  # ]:          0 :         SCROW nRow1 = ::std::max( nR1[0], nR1[1]);
    2066         [ #  # ]:          0 :         SCTAB nTab1 = ::std::max( nT1[0], nT1[1]);
    2067         [ #  # ]:          0 :         SCCOL nCol2 = ::std::min( nC2[0], nC2[1]);
    2068         [ #  # ]:          0 :         SCROW nRow2 = ::std::min( nR2[0], nR2[1]);
    2069         [ #  # ]:          0 :         SCTAB nTab2 = ::std::min( nT2[0], nT2[1]);
    2070 [ #  # ][ #  # ]:          0 :         if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
                 [ #  # ]
    2071         [ #  # ]:          0 :             PushError( errNoRef);
    2072 [ #  # ][ #  # ]:          0 :         else if (nCol2 == nCol1 && nRow2 == nRow1 && nTab2 == nTab1)
                 [ #  # ]
    2073         [ #  # ]:          0 :             PushSingleRef( nCol1, nRow1, nTab1);
    2074                 :            :         else
    2075         [ #  # ]:          0 :             PushDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
    2076 [ #  # ][ #  # ]:          0 :     }
         [ #  # ][ #  # ]
    2077                 :            : }
    2078                 :            : 
    2079                 :            : 
    2080                 :          0 : void ScInterpreter::ScRangeFunc()
    2081                 :            : {
    2082                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRangeFunc" );
    2083         [ #  # ]:          0 :     formula::FormulaTokenRef x2 = PopToken();
    2084         [ #  # ]:          0 :     formula::FormulaTokenRef x1 = PopToken();
    2085                 :            : 
    2086 [ #  # ][ #  # ]:          0 :     if (nGlobalError || !x2 || !x1)
         [ #  # ][ #  # ]
    2087                 :            :     {
    2088         [ #  # ]:          0 :         PushIllegalArgument();
    2089                 :          0 :         return;
    2090                 :            :     }
    2091         [ #  # ]:          0 :     FormulaTokenRef xRes = ScToken::ExtendRangeReference( *x1, *x2, aPos, false);
    2092         [ #  # ]:          0 :     if (!xRes)
    2093         [ #  # ]:          0 :         PushIllegalArgument();
    2094                 :            :     else
    2095 [ #  # ][ #  # ]:          0 :         PushTempToken( xRes.get());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2096                 :            : }
    2097                 :            : 
    2098                 :            : 
    2099                 :          0 : void ScInterpreter::ScUnionFunc()
    2100                 :            : {
    2101                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnionFunc" );
    2102         [ #  # ]:          0 :     formula::FormulaTokenRef p2nd = PopToken();
    2103         [ #  # ]:          0 :     formula::FormulaTokenRef p1st = PopToken();
    2104                 :            : 
    2105 [ #  # ][ #  # ]:          0 :     if (nGlobalError || !p2nd || !p1st)
         [ #  # ][ #  # ]
    2106                 :            :     {
    2107         [ #  # ]:          0 :         PushIllegalArgument();
    2108                 :            :         return;
    2109                 :            :     }
    2110                 :            : 
    2111                 :          0 :     StackVar sv1 = p1st->GetType();
    2112                 :          0 :     StackVar sv2 = p2nd->GetType();
    2113 [ #  # ][ #  # ]:          0 :     if ((sv1 != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2114                 :            :         (sv2 != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
    2115                 :            :     {
    2116         [ #  # ]:          0 :         PushIllegalArgument();
    2117                 :            :         return;
    2118                 :            :     }
    2119                 :            : 
    2120                 :          0 :     ScToken* x1 = static_cast<ScToken*>(p1st.get());
    2121                 :          0 :     ScToken* x2 = static_cast<ScToken*>(p2nd.get());
    2122                 :            : 
    2123                 :            : 
    2124                 :          0 :     ScTokenRef xRes;
    2125                 :            :     // Append to an existing RefList if there is one.
    2126         [ #  # ]:          0 :     if (sv1 == svRefList)
    2127                 :            :     {
    2128         [ #  # ]:          0 :         xRes = x1;
    2129                 :          0 :         sv1 = svUnknown;    // mark as handled
    2130                 :            :     }
    2131         [ #  # ]:          0 :     else if (sv2 == svRefList)
    2132                 :            :     {
    2133         [ #  # ]:          0 :         xRes = x2;
    2134                 :          0 :         sv2 = svUnknown;    // mark as handled
    2135                 :            :     }
    2136                 :            :     else
    2137 [ #  # ][ #  # ]:          0 :         xRes = new ScRefListToken;
                 [ #  # ]
    2138         [ #  # ]:          0 :     ScRefList* pRes = xRes->GetRefList();
    2139                 :          0 :     ScToken* pt[2] = { x1, x2 };
    2140                 :          0 :     StackVar sv[2] = { sv1, sv2 };
    2141         [ #  # ]:          0 :     for (size_t i=0; i<2; ++i)
    2142                 :            :     {
    2143         [ #  # ]:          0 :         if (pt[i] == xRes)
    2144                 :          0 :             continue;
    2145   [ #  #  #  # ]:          0 :         switch (sv[i])
    2146                 :            :         {
    2147                 :            :             case svSingleRef:
    2148                 :            :                 {
    2149                 :            :                     ScComplexRefData aRef;
    2150         [ #  # ]:          0 :                     aRef.Ref1 = aRef.Ref2 = pt[i]->GetSingleRef();
    2151         [ #  # ]:          0 :                     pRes->push_back( aRef);
    2152                 :            :                 }
    2153                 :          0 :                 break;
    2154                 :            :             case svDoubleRef:
    2155 [ #  # ][ #  # ]:          0 :                 pRes->push_back( pt[i]->GetDoubleRef());
    2156                 :          0 :                 break;
    2157                 :            :             case svRefList:
    2158                 :            :                 {
    2159         [ #  # ]:          0 :                     const ScRefList* p = pt[i]->GetRefList();
    2160                 :          0 :                     ScRefList::const_iterator it( p->begin());
    2161                 :          0 :                     ScRefList::const_iterator end( p->end());
    2162 [ #  # ][ #  # ]:          0 :                     for ( ; it != end; ++it)
    2163                 :            :                     {
    2164         [ #  # ]:          0 :                         pRes->push_back( *it);
    2165                 :            :                     }
    2166                 :            :                 }
    2167                 :          0 :                 break;
    2168                 :            :             default:
    2169                 :            :                 ;   // nothing, prevent compiler warning
    2170                 :            :         }
    2171                 :            :     }
    2172         [ #  # ]:          0 :     ValidateRef( *pRes);    // set #REF! if needed
    2173 [ #  # ][ #  # ]:          0 :     PushTempToken( xRes.get());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2174                 :            : }
    2175                 :            : 
    2176                 :            : 
    2177                 :          3 : void ScInterpreter::ScCurrent()
    2178                 :            : {
    2179                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCurrent" );
    2180         [ +  - ]:          3 :     FormulaTokenRef xTok( PopToken());
    2181         [ +  - ]:          3 :     if (xTok)
    2182                 :            :     {
    2183         [ +  - ]:          3 :         PushTempToken( xTok.get());
    2184         [ +  - ]:          3 :         PushTempToken( xTok.get());
    2185                 :            :     }
    2186                 :            :     else
    2187 [ #  # ][ +  - ]:          3 :         PushError( errUnknownStackVariable);
    2188                 :          3 : }
    2189                 :            : 
    2190                 :          0 : void ScInterpreter::ScStyle()
    2191                 :            : {
    2192                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStyle" );
    2193                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2194 [ #  # ][ #  # ]:          0 :     if (nParamCount >= 1 && nParamCount <= 3)
    2195                 :            :     {
    2196         [ #  # ]:          0 :         String aStyle2;                             // Vorlage nach Timer
    2197         [ #  # ]:          0 :         if (nParamCount >= 3)
    2198 [ #  # ][ #  # ]:          0 :             aStyle2 = GetString();
    2199                 :          0 :         long nTimeOut = 0;                          // Timeout
    2200         [ #  # ]:          0 :         if (nParamCount >= 2)
    2201         [ #  # ]:          0 :             nTimeOut = (long)(GetDouble()*1000.0);
    2202 [ #  # ][ #  # ]:          0 :         String aStyle1 = GetString();               // Vorlage fuer sofort
    2203                 :            : 
    2204         [ #  # ]:          0 :         if (nTimeOut < 0)
    2205                 :          0 :             nTimeOut = 0;
    2206                 :            : 
    2207                 :            :         //
    2208                 :            :         //  Request ausfuehren, um Vorlage anzuwenden
    2209                 :            :         //
    2210                 :            : 
    2211         [ #  # ]:          0 :         if ( !pDok->IsClipOrUndo() )
    2212                 :            :         {
    2213                 :          0 :             SfxObjectShell* pShell = pDok->GetDocumentShell();
    2214         [ #  # ]:          0 :             if (pShell)
    2215                 :            :             {
    2216                 :            :                 //! notify object shell directly
    2217                 :            : 
    2218                 :          0 :                 ScRange aRange(aPos);
    2219         [ #  # ]:          0 :                 ScAutoStyleHint aHint( aRange, aStyle1, nTimeOut, aStyle2 );
    2220 [ #  # ][ #  # ]:          0 :                 pShell->Broadcast( aHint );
    2221                 :            :             }
    2222                 :            :         }
    2223                 :            : 
    2224 [ #  # ][ #  # ]:          0 :         PushDouble(0.0);
                 [ #  # ]
    2225                 :            :     }
    2226                 :            :     else
    2227                 :          0 :         PushIllegalParameter();
    2228                 :          0 : }
    2229                 :            : 
    2230                 :          8 : ScDdeLink* lcl_GetDdeLink( sfx2::LinkManager* pLinkMgr,
    2231                 :            :                                 const String& rA, const String& rT, const String& rI, sal_uInt8 nM )
    2232                 :            : {
    2233                 :          8 :     sal_uInt16 nCount = pLinkMgr->GetLinks().size();
    2234         [ +  + ]:          8 :     for (sal_uInt16 i=0; i<nCount; i++ )
    2235                 :            :     {
    2236                 :          5 :         ::sfx2::SvBaseLink* pBase = *pLinkMgr->GetLinks()[i];
    2237         [ +  - ]:          5 :         if (pBase->ISA(ScDdeLink))
    2238                 :            :         {
    2239                 :          5 :             ScDdeLink* pLink = (ScDdeLink*)pBase;
    2240   [ +  -  +  -  :         20 :             if ( pLink->GetAppl() == rA &&
             +  -  +  - ]
                 [ +  - ]
    2241                 :          5 :                  pLink->GetTopic() == rT &&
    2242                 :          5 :                  pLink->GetItem() == rI &&
    2243                 :          5 :                  pLink->GetMode() == nM )
    2244                 :          5 :                 return pLink;
    2245                 :            :         }
    2246                 :            :     }
    2247                 :            : 
    2248                 :          8 :     return NULL;
    2249                 :            : }
    2250                 :            : 
    2251                 :          8 : void ScInterpreter::ScDde()
    2252                 :            : {
    2253                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDde" );
    2254                 :            :     //  Applikation, Datei, Bereich
    2255                 :            :     //  Application, Topic, Item
    2256                 :            : 
    2257                 :          8 :     sal_uInt8 nParamCount = GetByte();
    2258         [ +  - ]:          8 :     if ( MustHaveParamCount( nParamCount, 3, 4 ) )
    2259                 :            :     {
    2260                 :          8 :         sal_uInt8 nMode = SC_DDE_DEFAULT;
    2261         [ -  + ]:          8 :         if (nParamCount == 4)
    2262         [ #  # ]:          0 :             nMode = (sal_uInt8) ::rtl::math::approxFloor(GetDouble());
    2263 [ +  - ][ +  - ]:          8 :         String aItem  = GetString();
    2264 [ +  - ][ +  - ]:          8 :         String aTopic = GetString();
    2265 [ +  - ][ +  - ]:          8 :         String aAppl  = GetString();
    2266                 :            : 
    2267         [ -  + ]:          8 :         if (nMode > SC_DDE_TEXT)
    2268                 :          0 :             nMode = SC_DDE_DEFAULT;
    2269                 :            : 
    2270                 :            :         //  temporary documents (ScFunctionAccess) have no DocShell
    2271                 :            :         //  and no LinkManager -> abort
    2272                 :            : 
    2273         [ +  - ]:          8 :         sfx2::LinkManager* pLinkMgr = pDok->GetLinkManager();
    2274         [ -  + ]:          8 :         if (!pLinkMgr)
    2275                 :            :         {
    2276         [ #  # ]:          0 :             PushNoValue();
    2277                 :          8 :             return;
    2278                 :            :         }
    2279                 :            : 
    2280                 :            :             //  Nach dem Laden muss neu interpretiert werden (Verknuepfungen aufbauen)
    2281                 :            : 
    2282         [ +  - ]:          8 :         if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
    2283                 :          8 :             pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
    2284                 :            : 
    2285                 :            :             //  solange der Link nicht ausgewertet ist, Idle abklemmen
    2286                 :            :             //  (um zirkulaere Referenzen zu vermeiden)
    2287                 :            : 
    2288                 :          8 :         bool bOldDis = pDok->IsIdleDisabled();
    2289                 :          8 :         pDok->DisableIdle( true );
    2290                 :            : 
    2291                 :            :             //  Link-Objekt holen / anlegen
    2292                 :            : 
    2293         [ +  - ]:          8 :         ScDdeLink* pLink = lcl_GetDdeLink( pLinkMgr, aAppl, aTopic, aItem, nMode );
    2294                 :            : 
    2295                 :            :         //! Dde-Links (zusaetzlich) effizienter am Dokument speichern !!!!!
    2296                 :            :         //      ScDdeLink* pLink = pDok->GetDdeLink( aAppl, aTopic, aItem );
    2297                 :            : 
    2298         [ +  - ]:          8 :         bool bWasError = ( pMyFormulaCell->GetRawError() != 0 );
    2299                 :            : 
    2300         [ +  + ]:          8 :         if (!pLink)
    2301                 :            :         {
    2302 [ +  - ][ +  - ]:          3 :             pLink = new ScDdeLink( pDok, aAppl, aTopic, aItem, nMode );
    2303         [ +  - ]:          3 :             pLinkMgr->InsertDDELink( pLink, aAppl, aTopic, aItem );
    2304         [ +  - ]:          3 :             if ( pLinkMgr->GetLinks().size() == 1 )                    // erster ?
    2305                 :            :             {
    2306         [ +  - ]:          3 :                 SfxBindings* pBindings = pDok->GetViewBindings();
    2307         [ +  - ]:          3 :                 if (pBindings)
    2308         [ +  - ]:          3 :                     pBindings->Invalidate( SID_LINKS );             // Link-Manager enablen
    2309                 :            :             }
    2310                 :            : 
    2311                 :            :                                     //! asynchron auswerten ???
    2312         [ +  - ]:          3 :             pLink->TryUpdate();     //  TryUpdate ruft Update nicht mehrfach auf
    2313                 :            : 
    2314                 :            :             // StartListening erst nach dem Update, sonst circular reference
    2315         [ +  - ]:          3 :             pMyFormulaCell->StartListening( *pLink );
    2316                 :            :         }
    2317                 :            :         else
    2318                 :            :         {
    2319         [ +  - ]:          5 :             pMyFormulaCell->StartListening( *pLink );
    2320                 :            :         }
    2321                 :            : 
    2322                 :            :         //  Wenn aus dem Reschedule beim Ausfuehren des Links ein Fehler
    2323                 :            :         //  (z.B. zirkulaere Referenz) entstanden ist, der vorher nicht da war,
    2324                 :            :         //  das Fehler-Flag zuruecksetzen:
    2325                 :            : 
    2326 [ +  - ][ -  + ]:          8 :         if ( pMyFormulaCell->GetRawError() && !bWasError )
         [ #  # ][ -  + ]
    2327         [ #  # ]:          0 :             pMyFormulaCell->SetErrCode(0);
    2328                 :            : 
    2329                 :            :             //  Wert abfragen
    2330                 :            : 
    2331         [ +  - ]:          8 :         const ScMatrix* pLinkMat = pLink->GetResult();
    2332         [ +  - ]:          8 :         if (pLinkMat)
    2333                 :            :         {
    2334                 :            :             SCSIZE nC, nR;
    2335         [ +  - ]:          8 :             pLinkMat->GetDimensions(nC, nR);
    2336         [ +  - ]:          8 :             ScMatrixRef pNewMat = GetNewMat( nC, nR);
    2337         [ +  - ]:          8 :             if (pNewMat)
    2338                 :            :             {
    2339         [ +  - ]:          8 :                 pLinkMat->MatCopy(*pNewMat);        // kopieren
    2340         [ +  - ]:          8 :                 PushMatrix( pNewMat );
    2341                 :            :             }
    2342                 :            :             else
    2343 [ #  # ][ +  - ]:          8 :                 PushIllegalArgument();
    2344                 :            :         }
    2345                 :            :         else
    2346         [ #  # ]:          0 :             PushNA();
    2347                 :            : 
    2348                 :          8 :         pDok->DisableIdle( bOldDis );
    2349 [ +  - ][ -  + ]:          8 :         pLinkMgr->CloseCachedComps();
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2350                 :            :     }
    2351                 :            : }
    2352                 :            : 
    2353                 :          0 : void ScInterpreter::ScBase()
    2354                 :            : {   // Value, Base [, MinLen]
    2355                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2356         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 3 ) )
    2357                 :            :     {
    2358                 :            :         static const sal_Unicode pDigits[] = {
    2359                 :            :             '0','1','2','3','4','5','6','7','8','9',
    2360                 :            :             'A','B','C','D','E','F','G','H','I','J','K','L','M',
    2361                 :            :             'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
    2362                 :            :             0
    2363                 :            :         };
    2364                 :            :         static const int nDigits = (sizeof (pDigits)/sizeof(pDigits[0]))-1;
    2365                 :            :         xub_StrLen nMinLen;
    2366         [ #  # ]:          0 :         if ( nParamCount == 3 )
    2367                 :            :         {
    2368                 :          0 :             double fLen = ::rtl::math::approxFloor( GetDouble() );
    2369 [ #  # ][ #  # ]:          0 :             if ( 1.0 <= fLen && fLen < STRING_MAXLEN )
    2370                 :          0 :                 nMinLen = (xub_StrLen) fLen;
    2371         [ #  # ]:          0 :             else if ( fLen == 0.0 )
    2372                 :          0 :                 nMinLen = 1;
    2373                 :            :             else
    2374                 :          0 :                 nMinLen = 0;    // Error
    2375                 :            :         }
    2376                 :            :         else
    2377                 :          0 :             nMinLen = 1;
    2378                 :          0 :         double fBase = ::rtl::math::approxFloor( GetDouble() );
    2379                 :          0 :         double fVal = ::rtl::math::approxFloor( GetDouble() );
    2380                 :            :         double fChars = ((fVal > 0.0 && fBase > 0.0) ?
    2381                 :          0 :             (ceil( log( fVal ) / log( fBase ) ) + 2.0) :
    2382 [ #  # ][ #  # ]:          0 :             2.0);
    2383         [ #  # ]:          0 :         if ( fChars >= STRING_MAXLEN )
    2384                 :          0 :             nMinLen = 0;    // Error
    2385                 :            : 
    2386 [ #  # ][ #  # ]:          0 :         if ( !nGlobalError && nMinLen && 2 <= fBase && fBase <= nDigits && 0 <= fVal )
         [ #  # ][ #  # ]
                 [ #  # ]
    2387                 :            :         {
    2388                 :          0 :             const xub_StrLen nConstBuf = 128;
    2389                 :            :             sal_Unicode aBuf[nConstBuf];
    2390                 :          0 :             xub_StrLen nBuf = Max( (xub_StrLen) fChars, (xub_StrLen) (nMinLen+1) );
    2391 [ #  # ][ #  # ]:          0 :             sal_Unicode* pBuf = (nBuf <= nConstBuf ? aBuf : new sal_Unicode[nBuf]);
    2392         [ #  # ]:          0 :             for ( xub_StrLen j = 0; j < nBuf; ++j )
    2393                 :            :             {
    2394                 :          0 :                 pBuf[j] = '0';
    2395                 :            :             }
    2396                 :          0 :             sal_Unicode* p = pBuf + nBuf - 1;
    2397                 :          0 :             *p = 0;
    2398         [ #  # ]:          0 :             if ( fVal <= (sal_uLong)(~0) )
    2399                 :            :             {
    2400                 :          0 :                 sal_uLong nVal = (sal_uLong) fVal;
    2401                 :          0 :                 sal_uLong nBase = (sal_uLong) fBase;
    2402 [ #  # ][ #  # ]:          0 :                 while ( nVal && p > pBuf )
                 [ #  # ]
    2403                 :            :                 {
    2404                 :          0 :                     *--p = pDigits[ nVal % nBase ];
    2405                 :          0 :                     nVal /= nBase;
    2406                 :            :                 }
    2407                 :          0 :                 fVal = (double) nVal;
    2408                 :            :             }
    2409                 :            :             else
    2410                 :            :             {
    2411                 :          0 :                 bool bDirt = false;
    2412 [ #  # ][ #  # ]:          0 :                 while ( fVal && p > pBuf )
                 [ #  # ]
    2413                 :            :                 {
    2414                 :            : //! mit fmod Rundungsfehler ab 2**48
    2415                 :            : //                  double fDig = ::rtl::math::approxFloor( fmod( fVal, fBase ) );
    2416                 :            : // so ist es etwas besser
    2417                 :          0 :                     double fInt = ::rtl::math::approxFloor( fVal / fBase );
    2418                 :          0 :                     double fMult = fInt * fBase;
    2419                 :            : #if OSL_DEBUG_LEVEL > 1
    2420                 :            :                     // =BASIS(1e308;36) => GPF mit
    2421                 :            :                     // nDig = (size_t) ::rtl::math::approxFloor( fVal - fMult );
    2422                 :            :                     // trotz vorheriger Pruefung ob fVal >= fMult
    2423                 :            :                     double fDebug1 = fVal - fMult;
    2424                 :            :                     // fVal    := 7,5975311883090e+290
    2425                 :            :                     // fMult   := 7,5975311883090e+290
    2426                 :            :                     // fDebug1 := 1,3848924157003e+275  <- RoundOff-Error
    2427                 :            :                     // fVal != fMult, aber: ::rtl::math::approxEqual( fVal, fMult ) == TRUE
    2428                 :            :                     double fDebug2 = ::rtl::math::approxSub( fVal, fMult );
    2429                 :            :                     // und ::rtl::math::approxSub( fVal, fMult ) == 0
    2430                 :            :                     double fDebug3 = ( fInt ? fVal / fInt : 0.0 );
    2431                 :            :                     // Nach dem strange fDebug1 und fVal < fMult  ist eigentlich
    2432                 :            :                     // fDebug2 == fBase, trotzdem wird das mit einem Vergleich
    2433                 :            :                     // nicht erkannt, dann schlaegt bDirt zu und alles wird wieder gut..
    2434                 :            : 
    2435                 :            :                     // prevent compiler warnings
    2436                 :            :                     (void)fDebug1; (void)fDebug2; (void)fDebug3;
    2437                 :            : #endif
    2438                 :            :                     size_t nDig;
    2439         [ #  # ]:          0 :                     if ( fVal < fMult )
    2440                 :            :                     {   // da ist was gekippt
    2441                 :          0 :                         bDirt = true;
    2442                 :          0 :                         nDig = 0;
    2443                 :            :                     }
    2444                 :            :                     else
    2445                 :            :                     {
    2446                 :          0 :                         double fDig = ::rtl::math::approxFloor( ::rtl::math::approxSub( fVal, fMult ) );
    2447         [ #  # ]:          0 :                         if ( bDirt )
    2448                 :            :                         {
    2449                 :          0 :                             bDirt = false;
    2450                 :          0 :                             --fDig;
    2451                 :            :                         }
    2452         [ #  # ]:          0 :                         if ( fDig <= 0.0 )
    2453                 :          0 :                             nDig = 0;
    2454         [ #  # ]:          0 :                         else if ( fDig >= fBase )
    2455                 :          0 :                             nDig = ((size_t) fBase) - 1;
    2456                 :            :                         else
    2457                 :          0 :                             nDig = (size_t) fDig;
    2458                 :            :                     }
    2459                 :          0 :                     *--p = pDigits[ nDig ];
    2460                 :          0 :                     fVal = fInt;
    2461                 :            :                 }
    2462                 :            :             }
    2463         [ #  # ]:          0 :             if ( fVal )
    2464         [ #  # ]:          0 :                 PushError( errStringOverflow );
    2465                 :            :             else
    2466                 :            :             {
    2467         [ #  # ]:          0 :                 if ( nBuf - (p - pBuf) <= nMinLen )
    2468                 :          0 :                     p = pBuf + nBuf - 1 - nMinLen;
    2469         [ #  # ]:          0 :                 PushStringBuffer( p );
    2470                 :            :             }
    2471         [ #  # ]:          0 :             if ( pBuf != aBuf )
    2472         [ #  # ]:          0 :                 delete [] pBuf;
    2473                 :            :         }
    2474                 :            :         else
    2475                 :          0 :             PushIllegalArgument();
    2476                 :            :     }
    2477                 :          0 : }
    2478                 :            : 
    2479                 :            : 
    2480                 :          0 : void ScInterpreter::ScDecimal()
    2481                 :            : {   // Text, Base
    2482         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 2 ) )
    2483                 :            :     {
    2484         [ #  # ]:          0 :         double fBase = ::rtl::math::approxFloor( GetDouble() );
    2485 [ #  # ][ #  # ]:          0 :         String aStr( GetString() );
    2486 [ #  # ][ #  # ]:          0 :         if ( !nGlobalError && 2 <= fBase && fBase <= 36 )
                 [ #  # ]
    2487                 :            :         {
    2488                 :          0 :             double fVal = 0.0;
    2489                 :          0 :             int nBase = (int) fBase;
    2490                 :          0 :             register const sal_Unicode* p = aStr.GetBuffer();
    2491 [ #  # ][ #  # ]:          0 :             while ( *p == ' ' || *p == '\t' )
                 [ #  # ]
    2492                 :          0 :                 p++;        // strip leading white space
    2493         [ #  # ]:          0 :             if ( nBase == 16 )
    2494                 :            :             {   // evtl. hex-prefix strippen
    2495 [ #  # ][ #  # ]:          0 :                 if ( *p == 'x' || *p == 'X' )
    2496                 :          0 :                     p++;
    2497 [ #  # ][ #  # ]:          0 :                 else if ( *p == '0' && (*(p+1) == 'x' || *(p+1) == 'X') )
                 [ #  # ]
    2498                 :          0 :                     p += 2;
    2499                 :            :             }
    2500         [ #  # ]:          0 :             while ( *p )
    2501                 :            :             {
    2502                 :            :                 int n;
    2503 [ #  # ][ #  # ]:          0 :                 if ( '0' <= *p && *p <= '9' )
    2504                 :          0 :                     n = *p - '0';
    2505 [ #  # ][ #  # ]:          0 :                 else if ( 'A' <= *p && *p <= 'Z' )
    2506                 :          0 :                     n = 10 + (*p - 'A');
    2507 [ #  # ][ #  # ]:          0 :                 else if ( 'a' <= *p && *p <= 'z' )
    2508                 :          0 :                     n = 10 + (*p - 'a');
    2509                 :            :                 else
    2510                 :          0 :                     n = nBase;
    2511         [ #  # ]:          0 :                 if ( nBase <= n )
    2512                 :            :                 {
    2513 [ #  # ][ #  # ]:          0 :                     if ( *(p+1) == 0 &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2514                 :            :                             ( (nBase ==  2 && (*p == 'b' || *p == 'B'))
    2515                 :            :                             ||(nBase == 16 && (*p == 'h' || *p == 'H')) )
    2516                 :            :                         )
    2517                 :            :                         ;       // 101b und F00Dh sind ok
    2518                 :            :                     else
    2519                 :            :                     {
    2520         [ #  # ]:          0 :                         PushIllegalArgument();
    2521                 :          0 :                         return ;
    2522                 :            :                     }
    2523                 :            :                 }
    2524                 :            :                 else
    2525                 :          0 :                     fVal = fVal * fBase + n;
    2526                 :          0 :                 p++;
    2527                 :            : 
    2528                 :            :             }
    2529         [ #  # ]:          0 :             PushDouble( fVal );
    2530                 :            :         }
    2531                 :            :         else
    2532 [ #  # ][ #  # ]:          0 :             PushIllegalArgument();
                 [ #  # ]
    2533                 :            :     }
    2534                 :            : }
    2535                 :            : 
    2536                 :            : 
    2537                 :          0 : void ScInterpreter::ScConvert()
    2538                 :            : {   // Value, FromUnit, ToUnit
    2539         [ #  # ]:          0 :     if ( MustHaveParamCount( GetByte(), 3 ) )
    2540                 :            :     {
    2541 [ #  # ][ #  # ]:          0 :         String aToUnit( GetString() );
    2542 [ #  # ][ #  # ]:          0 :         String aFromUnit( GetString() );
    2543         [ #  # ]:          0 :         double fVal = GetDouble();
    2544         [ #  # ]:          0 :         if ( nGlobalError )
    2545         [ #  # ]:          0 :             PushError( nGlobalError);
    2546                 :            :         else
    2547                 :            :         {   // erst die angegebene Reihenfolge suchen, wenn nicht gefunden den Kehrwert
    2548                 :            :             double fConv;
    2549 [ #  # ][ #  # ]:          0 :             if ( ScGlobal::GetUnitConverter()->GetValue( fConv, aFromUnit, aToUnit ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    2550         [ #  # ]:          0 :                 PushDouble( fVal * fConv );
    2551 [ #  # ][ #  # ]:          0 :             else if ( ScGlobal::GetUnitConverter()->GetValue( fConv, aToUnit, aFromUnit ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    2552         [ #  # ]:          0 :                 PushDouble( fVal / fConv );
    2553                 :            :             else
    2554         [ #  # ]:          0 :                 PushNA();
    2555 [ #  # ][ #  # ]:          0 :         }
    2556                 :            :     }
    2557                 :          0 : }
    2558                 :            : 
    2559                 :            : 
    2560                 :          0 : void ScInterpreter::ScRoman()
    2561                 :            : {   // Value [Mode]
    2562                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2563         [ #  # ]:          0 :     if( MustHaveParamCount( nParamCount, 1, 2 ) )
    2564                 :            :     {
    2565         [ #  # ]:          0 :         double fMode = (nParamCount == 2) ? ::rtl::math::approxFloor( GetDouble() ) : 0.0;
    2566                 :          0 :         double fVal = ::rtl::math::approxFloor( GetDouble() );
    2567         [ #  # ]:          0 :         if( nGlobalError )
    2568                 :          0 :             PushError( nGlobalError);
    2569 [ #  # ][ #  # ]:          0 :         else if( (fMode >= 0.0) && (fMode < 5.0) && (fVal >= 0.0) && (fVal < 4000.0) )
         [ #  # ][ #  # ]
    2570                 :            :         {
    2571                 :            :             static const sal_Unicode pChars[] = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
    2572                 :            :             static const sal_uInt16 pValues[] = { 1000, 500, 100, 50, 10, 5, 1 };
    2573                 :            :             static const sal_uInt16 nMaxIndex = (sal_uInt16)((sizeof(pValues)/sizeof(pValues[0])) - 1);
    2574                 :            : 
    2575         [ #  # ]:          0 :             String aRoman;
    2576                 :          0 :             sal_uInt16 nVal = (sal_uInt16) fVal;
    2577                 :          0 :             sal_uInt16 nMode = (sal_uInt16) fMode;
    2578                 :            : 
    2579         [ #  # ]:          0 :             for( sal_uInt16 i = 0; i <= nMaxIndex / 2; i++ )
    2580                 :            :             {
    2581                 :          0 :                 sal_uInt16 nIndex = 2 * i;
    2582                 :          0 :                 sal_uInt16 nDigit = nVal / pValues[ nIndex ];
    2583                 :            : 
    2584         [ #  # ]:          0 :                 if( (nDigit % 5) == 4 )
    2585                 :            :                 {
    2586         [ #  # ]:          0 :                     sal_uInt16 nIndex2 = (nDigit == 4) ? nIndex - 1 : nIndex - 2;
    2587                 :          0 :                     sal_uInt16 nSteps = 0;
    2588 [ #  # ][ #  # ]:          0 :                     while( (nSteps < nMode) && (nIndex < nMaxIndex) )
                 [ #  # ]
    2589                 :            :                     {
    2590                 :          0 :                         nSteps++;
    2591         [ #  # ]:          0 :                         if( pValues[ nIndex2 ] - pValues[ nIndex + 1 ] <= nVal )
    2592                 :          0 :                             nIndex++;
    2593                 :            :                         else
    2594                 :          0 :                             nSteps = nMode;
    2595                 :            :                     }
    2596         [ #  # ]:          0 :                     aRoman += pChars[ nIndex ];
    2597         [ #  # ]:          0 :                     aRoman += pChars[ nIndex2 ];
    2598                 :          0 :                     nVal = sal::static_int_cast<sal_uInt16>( nVal + pValues[ nIndex ] );
    2599                 :          0 :                     nVal = sal::static_int_cast<sal_uInt16>( nVal - pValues[ nIndex2 ] );
    2600                 :            :                 }
    2601                 :            :                 else
    2602                 :            :                 {
    2603         [ #  # ]:          0 :                     if( nDigit > 4 )
    2604         [ #  # ]:          0 :                         aRoman += pChars[ nIndex - 1 ];
    2605         [ #  # ]:          0 :                     aRoman.Expand( aRoman.Len() + (nDigit % 5), pChars[ nIndex ] );
    2606                 :          0 :                     nVal %= pValues[ nIndex ];
    2607                 :            :                 }
    2608                 :            :             }
    2609                 :            : 
    2610 [ #  # ][ #  # ]:          0 :             PushString( aRoman );
    2611                 :            :         }
    2612                 :            :         else
    2613                 :          0 :             PushIllegalArgument();
    2614                 :            :     }
    2615                 :          0 : }
    2616                 :            : 
    2617                 :            : 
    2618                 :          0 : bool lcl_GetArabicValue( sal_Unicode cChar, sal_uInt16& rnValue, bool& rbIsDec )
    2619                 :            : {
    2620                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBase" );
    2621   [ #  #  #  #  :          0 :     switch( cChar )
             #  #  #  # ]
    2622                 :            :     {
    2623                 :          0 :         case 'M':   rnValue = 1000; rbIsDec = true;     break;
    2624                 :          0 :         case 'D':   rnValue = 500;  rbIsDec = false;    break;
    2625                 :          0 :         case 'C':   rnValue = 100;  rbIsDec = true;     break;
    2626                 :          0 :         case 'L':   rnValue = 50;   rbIsDec = false;    break;
    2627                 :          0 :         case 'X':   rnValue = 10;   rbIsDec = true;     break;
    2628                 :          0 :         case 'V':   rnValue = 5;    rbIsDec = false;    break;
    2629                 :          0 :         case 'I':   rnValue = 1;    rbIsDec = true;     break;
    2630                 :          0 :         default:    return false;
    2631                 :            :     }
    2632                 :          0 :     return true;
    2633                 :            : }
    2634                 :            : 
    2635                 :            : 
    2636                 :          0 : void ScInterpreter::ScArabic()
    2637                 :            : {
    2638                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArabic" );
    2639 [ #  # ][ #  # ]:          0 :     String aRoman( GetString() );
    2640         [ #  # ]:          0 :     if( nGlobalError )
    2641         [ #  # ]:          0 :         PushError( nGlobalError);
    2642                 :            :     else
    2643                 :            :     {
    2644         [ #  # ]:          0 :         aRoman.ToUpperAscii();
    2645                 :            : 
    2646                 :          0 :         sal_uInt16 nValue = 0;
    2647                 :          0 :         sal_uInt16 nValidRest = 3999;
    2648                 :          0 :         sal_uInt16 nCharIndex = 0;
    2649                 :          0 :         sal_uInt16 nCharCount = aRoman.Len();
    2650                 :          0 :         bool bValid = true;
    2651                 :            : 
    2652 [ #  # ][ #  # ]:          0 :         while( bValid && (nCharIndex < nCharCount) )
                 [ #  # ]
    2653                 :            :         {
    2654                 :          0 :             sal_uInt16 nDigit1 = 0;
    2655                 :          0 :             sal_uInt16 nDigit2 = 0;
    2656                 :          0 :             bool bIsDec1 = false;
    2657                 :          0 :             bool bIsDec2 = false;
    2658                 :          0 :             bValid = lcl_GetArabicValue( aRoman.GetChar( nCharIndex ), nDigit1, bIsDec1 );
    2659 [ #  # ][ #  # ]:          0 :             if( bValid && (nCharIndex + 1 < nCharCount) )
    2660                 :          0 :                 bValid = lcl_GetArabicValue( aRoman.GetChar( nCharIndex + 1 ), nDigit2, bIsDec2 );
    2661         [ #  # ]:          0 :             if( bValid )
    2662                 :            :             {
    2663         [ #  # ]:          0 :                 if( nDigit1 >= nDigit2 )
    2664                 :            :                 {
    2665                 :          0 :                     nValue = sal::static_int_cast<sal_uInt16>( nValue + nDigit1 );
    2666         [ #  # ]:          0 :                     nValidRest %= (nDigit1 * (bIsDec1 ? 5 : 2));
    2667                 :          0 :                     bValid = (nValidRest >= nDigit1);
    2668         [ #  # ]:          0 :                     if( bValid )
    2669                 :          0 :                         nValidRest = sal::static_int_cast<sal_uInt16>( nValidRest - nDigit1 );
    2670                 :          0 :                     nCharIndex++;
    2671                 :            :                 }
    2672         [ #  # ]:          0 :                 else if( nDigit1 * 2 != nDigit2 )
    2673                 :            :                 {
    2674                 :          0 :                     sal_uInt16 nDiff = nDigit2 - nDigit1;
    2675                 :          0 :                     nValue = sal::static_int_cast<sal_uInt16>( nValue + nDiff );
    2676                 :          0 :                     bValid = (nValidRest >= nDiff);
    2677         [ #  # ]:          0 :                     if( bValid )
    2678                 :          0 :                         nValidRest = nDigit1 - 1;
    2679                 :          0 :                     nCharIndex += 2;
    2680                 :            :                 }
    2681                 :            :                 else
    2682                 :          0 :                     bValid = false;
    2683                 :            :             }
    2684                 :            :         }
    2685         [ #  # ]:          0 :         if( bValid )
    2686         [ #  # ]:          0 :             PushInt( nValue );
    2687                 :            :         else
    2688         [ #  # ]:          0 :             PushIllegalArgument();
    2689         [ #  # ]:          0 :     }
    2690                 :          0 : }
    2691                 :            : 
    2692                 :            : 
    2693                 :          0 : void ScInterpreter::ScHyperLink()
    2694                 :            : {
    2695                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHyperLink" );
    2696                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2697         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 1, 2 ) )
    2698                 :            :     {
    2699                 :          0 :         double fVal = 0.0;
    2700         [ #  # ]:          0 :         String aStr;
    2701                 :          0 :         ScMatValType nResultType = SC_MATVAL_STRING;
    2702                 :            : 
    2703         [ #  # ]:          0 :         if ( nParamCount == 2 )
    2704                 :            :         {
    2705 [ #  # ][ #  #  :          0 :             switch ( GetStackType() )
             #  #  #  # ]
    2706                 :            :             {
    2707                 :            :                 case svDouble:
    2708         [ #  # ]:          0 :                     fVal = GetDouble();
    2709                 :          0 :                     nResultType = SC_MATVAL_VALUE;
    2710                 :          0 :                 break;
    2711                 :            :                 case svString:
    2712 [ #  # ][ #  # ]:          0 :                     aStr = GetString();
    2713                 :          0 :                 break;
    2714                 :            :                 case svSingleRef:
    2715                 :            :                 case svDoubleRef:
    2716                 :            :                 {
    2717                 :          0 :                     ScAddress aAdr;
    2718 [ #  # ][ #  # ]:          0 :                     if ( !PopDoubleRefOrSingleRef( aAdr ) )
    2719                 :            :                         break;
    2720         [ #  # ]:          0 :                     ScBaseCell* pCell = GetCell( aAdr );
    2721 [ #  # ][ #  # ]:          0 :                     if (HasCellEmptyData( pCell))
    2722                 :          0 :                         nResultType = SC_MATVAL_EMPTY;
    2723                 :            :                     else
    2724                 :            :                     {
    2725         [ #  # ]:          0 :                         sal_uInt16 nErr = GetCellErrCode( pCell );
    2726         [ #  # ]:          0 :                         if (nErr)
    2727                 :          0 :                             SetError( nErr);
    2728 [ #  # ][ #  # ]:          0 :                         else if (HasCellValueData( pCell))
    2729                 :            :                         {
    2730         [ #  # ]:          0 :                             fVal = GetCellValue( aAdr, pCell );
    2731                 :          0 :                             nResultType = SC_MATVAL_VALUE;
    2732                 :            :                         }
    2733                 :            :                         else
    2734         [ #  # ]:          0 :                             GetCellString( aStr, pCell );
    2735                 :            :                     }
    2736                 :            :                 }
    2737                 :          0 :                 break;
    2738                 :            :                 case svMatrix:
    2739         [ #  # ]:          0 :                     nResultType = GetDoubleOrStringFromMatrix( fVal, aStr);
    2740                 :          0 :                 break;
    2741                 :            :                 case svMissing:
    2742                 :            :                 case svEmptyCell:
    2743         [ #  # ]:          0 :                     Pop();
    2744                 :            :                     // mimic xcl
    2745                 :          0 :                     fVal = 0.0;
    2746                 :          0 :                     nResultType = SC_MATVAL_VALUE;
    2747                 :          0 :                 break;
    2748                 :            :                 default:
    2749         [ #  # ]:          0 :                     PopError();
    2750                 :          0 :                     SetError( errIllegalArgument);
    2751                 :            :             }
    2752                 :            :         }
    2753 [ #  # ][ #  # ]:          0 :         String aUrl = GetString();
    2754         [ #  # ]:          0 :         ScMatrixRef pResMat = GetNewMat( 1, 2);
    2755         [ #  # ]:          0 :         if (nGlobalError)
    2756                 :            :         {
    2757                 :          0 :             fVal = CreateDoubleError( nGlobalError);
    2758                 :          0 :             nResultType = SC_MATVAL_VALUE;
    2759                 :            :         }
    2760 [ #  # ][ #  # ]:          0 :         if (nParamCount == 2 || nGlobalError)
    2761                 :            :         {
    2762         [ #  # ]:          0 :             if (ScMatrix::IsValueType( nResultType))
    2763         [ #  # ]:          0 :                 pResMat->PutDouble( fVal, 0);
    2764         [ #  # ]:          0 :             else if (ScMatrix::IsRealStringType( nResultType))
    2765 [ #  # ][ #  # ]:          0 :                 pResMat->PutString( aStr, 0);
    2766                 :            :             else    // EmptyType, EmptyPathType, mimic xcl
    2767         [ #  # ]:          0 :                 pResMat->PutDouble( 0.0, 0 );
    2768                 :            :         }
    2769                 :            :         else
    2770 [ #  # ][ #  # ]:          0 :             pResMat->PutString( aUrl, 0 );
    2771 [ #  # ][ #  # ]:          0 :         pResMat->PutString( aUrl, 1 );
    2772                 :          0 :         bMatrixFormula = true;
    2773 [ #  # ][ #  # ]:          0 :         PushMatrix(pResMat);
         [ #  # ][ #  # ]
    2774                 :            :     }
    2775                 :          0 : }
    2776                 :            : 
    2777                 :            : 
    2778                 :          0 : bool lclConvertMoney( const String& aSearchUnit, double& rfRate, int& rnDec )
    2779                 :            : {
    2780                 :            :     struct ConvertInfo
    2781                 :            :     {
    2782                 :            :         const sal_Char* pCurrText;
    2783                 :            :         double          fRate;
    2784                 :            :         int             nDec;
    2785                 :            :     };
    2786                 :            :     ConvertInfo aConvertTable[] = {
    2787                 :            :         { "EUR", 1.0,      2 },
    2788                 :            :         { "ATS", 13.7603,  2 },
    2789                 :            :         { "BEF", 40.3399,  0 },
    2790                 :            :         { "DEM", 1.95583,  2 },
    2791                 :            :         { "ESP", 166.386,  0 },
    2792                 :            :         { "FIM", 5.94573,  2 },
    2793                 :            :         { "FRF", 6.55957,  2 },
    2794                 :            :         { "IEP", 0.787564, 2 },
    2795                 :            :         { "ITL", 1936.27,  0 },
    2796                 :            :         { "LUF", 40.3399,  0 },
    2797                 :            :         { "NLG", 2.20371,  2 },
    2798                 :            :         { "PTE", 200.482,  2 },
    2799                 :            :         { "GRD", 340.750,  2 },
    2800                 :            :         { "SIT", 239.640,  2 },
    2801                 :            :         { "MTL", 0.429300, 2 },
    2802                 :            :         { "CYP", 0.585274, 2 },
    2803                 :            :         { "SKK", 30.1260,  2 }
    2804                 :          0 :     };
    2805                 :            : 
    2806                 :          0 :     const size_t nConversionCount = sizeof( aConvertTable ) / sizeof( aConvertTable[0] );
    2807         [ #  # ]:          0 :     for ( size_t i = 0; i < nConversionCount; i++ )
    2808 [ #  # ][ #  # ]:          0 :         if ( aSearchUnit.EqualsIgnoreCaseAscii( aConvertTable[i].pCurrText ) )
    2809                 :            :         {
    2810                 :          0 :             rfRate = aConvertTable[i].fRate;
    2811                 :          0 :             rnDec  = aConvertTable[i].nDec;
    2812                 :          0 :             return true;
    2813                 :            :         }
    2814                 :          0 :     return false;
    2815                 :            : }
    2816                 :            : 
    2817                 :          0 : void ScInterpreter::ScEuroConvert()
    2818                 :            : {   //Value, FromUnit, ToUnit[, FullPrecision, [TriangulationPrecision]]
    2819                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2820         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 3, 5 ) )
    2821                 :            :     {
    2822                 :          0 :         double nPrecision = 0.0;
    2823         [ #  # ]:          0 :         if ( nParamCount == 5 )
    2824                 :            :         {
    2825         [ #  # ]:          0 :             nPrecision = ::rtl::math::approxFloor(GetDouble());
    2826         [ #  # ]:          0 :             if ( nPrecision < 3 )
    2827                 :            :             {
    2828         [ #  # ]:          0 :                 PushIllegalArgument();
    2829                 :          0 :                 return;
    2830                 :            :             }
    2831                 :            :         }
    2832                 :          0 :         bool bFullPrecision = false;
    2833         [ #  # ]:          0 :         if ( nParamCount >= 4 )
    2834         [ #  # ]:          0 :             bFullPrecision = GetBool();
    2835 [ #  # ][ #  # ]:          0 :         String aToUnit( GetString() );
    2836 [ #  # ][ #  # ]:          0 :         String aFromUnit( GetString() );
    2837         [ #  # ]:          0 :         double fVal = GetDouble();
    2838         [ #  # ]:          0 :         if ( nGlobalError )
    2839         [ #  # ]:          0 :             PushError( nGlobalError);
    2840                 :            :         else
    2841                 :            :         {
    2842                 :            :             double fFromRate;
    2843                 :            :             double fToRate;
    2844                 :            :             int    nFromDec;
    2845                 :            :             int    nToDec;
    2846         [ #  # ]:          0 :             String aEur( RTL_CONSTASCII_USTRINGPARAM("EUR"));
    2847 [ #  # ][ #  # ]:          0 :             if ( lclConvertMoney( aFromUnit, fFromRate, nFromDec )
         [ #  # ][ #  # ]
    2848         [ #  # ]:          0 :                 && lclConvertMoney( aToUnit, fToRate, nToDec ) )
    2849                 :            :             {
    2850                 :            :                 double fRes;
    2851 [ #  # ][ #  # ]:          0 :                 if ( aFromUnit.EqualsIgnoreCaseAscii( aToUnit ) )
    2852                 :          0 :                     fRes = fVal;
    2853                 :            :                 else
    2854                 :            :                 {
    2855 [ #  # ][ #  # ]:          0 :                     if ( aFromUnit.EqualsIgnoreCaseAscii( aEur ) )
    2856                 :          0 :                        fRes = fVal * fToRate;
    2857                 :            :                     else
    2858                 :            :                     {
    2859                 :          0 :                         double fIntermediate = fVal / fFromRate;
    2860         [ #  # ]:          0 :                         if ( nPrecision )
    2861                 :            :                             fIntermediate = ::rtl::math::round( fIntermediate,
    2862                 :          0 :                                                             (int) nPrecision );
    2863                 :          0 :                         fRes = fIntermediate * fToRate;
    2864                 :            :                     }
    2865         [ #  # ]:          0 :                     if ( !bFullPrecision )
    2866                 :          0 :                         fRes = ::rtl::math::round( fRes, nToDec );
    2867                 :            :                 }
    2868         [ #  # ]:          0 :                 PushDouble( fRes );
    2869                 :            :             }
    2870                 :            :             else
    2871 [ #  # ][ #  # ]:          0 :                 PushIllegalArgument();
    2872 [ #  # ][ #  # ]:          0 :         }
    2873                 :            :     }
    2874                 :            : }
    2875                 :            : 
    2876                 :            : 
    2877                 :            : // BAHTTEXT ===================================================================
    2878                 :            : 
    2879                 :            : #define UTF8_TH_0       "\340\270\250\340\270\271\340\270\231\340\270\242\340\271\214"
    2880                 :            : #define UTF8_TH_1       "\340\270\253\340\270\231\340\270\266\340\271\210\340\270\207"
    2881                 :            : #define UTF8_TH_2       "\340\270\252\340\270\255\340\270\207"
    2882                 :            : #define UTF8_TH_3       "\340\270\252\340\270\262\340\270\241"
    2883                 :            : #define UTF8_TH_4       "\340\270\252\340\270\265\340\271\210"
    2884                 :            : #define UTF8_TH_5       "\340\270\253\340\271\211\340\270\262"
    2885                 :            : #define UTF8_TH_6       "\340\270\253\340\270\201"
    2886                 :            : #define UTF8_TH_7       "\340\271\200\340\270\210\340\271\207\340\270\224"
    2887                 :            : #define UTF8_TH_8       "\340\271\201\340\270\233\340\270\224"
    2888                 :            : #define UTF8_TH_9       "\340\271\200\340\270\201\340\271\211\340\270\262"
    2889                 :            : #define UTF8_TH_10      "\340\270\252\340\270\264\340\270\232"
    2890                 :            : #define UTF8_TH_11      "\340\271\200\340\270\255\340\271\207\340\270\224"
    2891                 :            : #define UTF8_TH_20      "\340\270\242\340\270\265\340\271\210"
    2892                 :            : #define UTF8_TH_1E2     "\340\270\243\340\271\211\340\270\255\340\270\242"
    2893                 :            : #define UTF8_TH_1E3     "\340\270\236\340\270\261\340\270\231"
    2894                 :            : #define UTF8_TH_1E4     "\340\270\253\340\270\241\340\270\267\340\271\210\340\270\231"
    2895                 :            : #define UTF8_TH_1E5     "\340\271\201\340\270\252\340\270\231"
    2896                 :            : #define UTF8_TH_1E6     "\340\270\245\340\271\211\340\270\262\340\270\231"
    2897                 :            : #define UTF8_TH_DOT0    "\340\270\226\340\271\211\340\270\247\340\270\231"
    2898                 :            : #define UTF8_TH_BAHT    "\340\270\232\340\270\262\340\270\227"
    2899                 :            : #define UTF8_TH_SATANG  "\340\270\252\340\270\225\340\270\262\340\270\207\340\270\204\340\271\214"
    2900                 :            : #define UTF8_TH_MINUS   "\340\270\245\340\270\232"
    2901                 :            : 
    2902                 :            : // local functions ------------------------------------------------------------
    2903                 :            : 
    2904                 :            : namespace {
    2905                 :            : 
    2906                 :          0 : inline void lclSplitBlock( double& rfInt, sal_Int32& rnBlock, double fValue, double fSize )
    2907                 :            : {
    2908                 :          0 :     rnBlock = static_cast< sal_Int32 >( modf( (fValue + 0.1) / fSize, &rfInt ) * fSize + 0.1 );
    2909                 :          0 : }
    2910                 :            : 
    2911                 :            : /** Appends a digit (0 to 9) to the passed string. */
    2912                 :          0 : void lclAppendDigit( rtl::OStringBuffer& rText, sal_Int32 nDigit )
    2913                 :            : {
    2914   [ #  #  #  #  :          0 :     switch( nDigit )
          #  #  #  #  #  
                   #  # ]
    2915                 :            :     {
    2916                 :          0 :         case 0: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_0) ); break;
    2917                 :          0 :         case 1: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1) ); break;
    2918                 :          0 :         case 2: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_2) ); break;
    2919                 :          0 :         case 3: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_3) ); break;
    2920                 :          0 :         case 4: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_4) ); break;
    2921                 :          0 :         case 5: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_5) ); break;
    2922                 :          0 :         case 6: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_6) ); break;
    2923                 :          0 :         case 7: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_7) ); break;
    2924                 :          0 :         case 8: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_8) ); break;
    2925                 :          0 :         case 9: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_9) ); break;
    2926                 :            :         default:    OSL_FAIL( "lclAppendDigit - illegal digit" );
    2927                 :            :     }
    2928                 :          0 : }
    2929                 :            : 
    2930                 :            : /** Appends a value raised to a power of 10: nDigit*10^nPow10.
    2931                 :            :     @param nDigit  A digit in the range from 1 to 9.
    2932                 :            :     @param nPow10  A value in the range from 2 to 5.
    2933                 :            :  */
    2934                 :          0 : void lclAppendPow10( rtl::OStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 )
    2935                 :            : {
    2936                 :            :     OSL_ENSURE( (1 <= nDigit) && (nDigit <= 9), "lclAppendPow10 - illegal digit" );
    2937                 :          0 :     lclAppendDigit( rText, nDigit );
    2938   [ #  #  #  #  :          0 :     switch( nPow10 )
                      # ]
    2939                 :            :     {
    2940                 :          0 :         case 2: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1E2) );   break;
    2941                 :          0 :         case 3: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1E3) );   break;
    2942                 :          0 :         case 4: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1E4) );   break;
    2943                 :          0 :         case 5: rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1E5) );   break;
    2944                 :            :         default:    OSL_FAIL( "lclAppendPow10 - illegal power" );
    2945                 :            :     }
    2946                 :          0 : }
    2947                 :            : 
    2948                 :            : /** Appends a block of 6 digits (value from 1 to 999,999) to the passed string. */
    2949                 :          0 : void lclAppendBlock( rtl::OStringBuffer& rText, sal_Int32 nValue )
    2950                 :            : {
    2951                 :            :     OSL_ENSURE( (1 <= nValue) && (nValue <= 999999), "lclAppendBlock - illegal value" );
    2952         [ #  # ]:          0 :     if( nValue >= 100000 )
    2953                 :            :     {
    2954                 :          0 :         lclAppendPow10( rText, nValue / 100000, 5 );
    2955                 :          0 :         nValue %= 100000;
    2956                 :            :     }
    2957         [ #  # ]:          0 :     if( nValue >= 10000 )
    2958                 :            :     {
    2959                 :          0 :         lclAppendPow10( rText, nValue / 10000, 4 );
    2960                 :          0 :         nValue %= 10000;
    2961                 :            :     }
    2962         [ #  # ]:          0 :     if( nValue >= 1000 )
    2963                 :            :     {
    2964                 :          0 :         lclAppendPow10( rText, nValue / 1000, 3 );
    2965                 :          0 :         nValue %= 1000;
    2966                 :            :     }
    2967         [ #  # ]:          0 :     if( nValue >= 100 )
    2968                 :            :     {
    2969                 :          0 :         lclAppendPow10( rText, nValue / 100, 2 );
    2970                 :          0 :         nValue %= 100;
    2971                 :            :     }
    2972         [ #  # ]:          0 :     if( nValue > 0 )
    2973                 :            :     {
    2974                 :          0 :         sal_Int32 nTen = nValue / 10;
    2975                 :          0 :         sal_Int32 nOne = nValue % 10;
    2976         [ #  # ]:          0 :         if( nTen >= 1 )
    2977                 :            :         {
    2978         [ #  # ]:          0 :             if( nTen >= 3 )
    2979                 :          0 :                 lclAppendDigit( rText, nTen );
    2980         [ #  # ]:          0 :             else if( nTen == 2 )
    2981                 :          0 :                 rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_20) );
    2982                 :          0 :             rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_10) );
    2983                 :            :         }
    2984 [ #  # ][ #  # ]:          0 :         if( (nTen > 0) && (nOne == 1) )
    2985                 :          0 :             rText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_11) );
    2986         [ #  # ]:          0 :         else if( nOne > 0 )
    2987                 :          0 :             lclAppendDigit( rText, nOne );
    2988                 :            :     }
    2989                 :          0 : }
    2990                 :            : 
    2991                 :            : } // namespace
    2992                 :            : 
    2993                 :            : // ----------------------------------------------------------------------------
    2994                 :            : 
    2995                 :          0 : void ScInterpreter::ScBahtText()
    2996                 :            : {
    2997                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBahtText" );
    2998                 :          0 :     sal_uInt8 nParamCount = GetByte();
    2999         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 1 ) )
    3000                 :            :     {
    3001         [ #  # ]:          0 :         double fValue = GetDouble();
    3002         [ #  # ]:          0 :         if( nGlobalError )
    3003                 :            :         {
    3004         [ #  # ]:          0 :             PushError( nGlobalError);
    3005                 :          0 :             return;
    3006                 :            :         }
    3007                 :            : 
    3008                 :            :         // sign
    3009                 :          0 :         bool bMinus = fValue < 0.0;
    3010                 :          0 :         fValue = fabs( fValue );
    3011                 :            : 
    3012                 :            :         // round to 2 digits after decimal point, fValue contains Satang as integer
    3013                 :          0 :         fValue = ::rtl::math::approxFloor( fValue * 100.0 + 0.5 );
    3014                 :            : 
    3015                 :            :         // split Baht and Satang
    3016                 :          0 :         double fBaht = 0.0;
    3017                 :          0 :         sal_Int32 nSatang = 0;
    3018                 :          0 :         lclSplitBlock( fBaht, nSatang, fValue, 100.0 );
    3019                 :            : 
    3020                 :          0 :         rtl::OStringBuffer aText;
    3021                 :            : 
    3022                 :            :         // generate text for Baht value
    3023         [ #  # ]:          0 :         if( fBaht == 0.0 )
    3024                 :            :         {
    3025         [ #  # ]:          0 :             if( nSatang == 0 )
    3026         [ #  # ]:          0 :                 aText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_0) );
    3027                 :            :         }
    3028         [ #  # ]:          0 :         else while( fBaht > 0.0 )
    3029                 :            :         {
    3030                 :          0 :             rtl::OStringBuffer aBlock;
    3031                 :          0 :             sal_Int32 nBlock = 0;
    3032                 :          0 :             lclSplitBlock( fBaht, nBlock, fBaht, 1.0e6 );
    3033         [ #  # ]:          0 :             if( nBlock > 0 )
    3034         [ #  # ]:          0 :                 lclAppendBlock( aBlock, nBlock );
    3035                 :            :             // add leading "million", if there will come more blocks
    3036         [ #  # ]:          0 :             if( fBaht > 0.0 )
    3037                 :            :                 aBlock.insert(
    3038         [ #  # ]:          0 :                     0, rtl::OString(RTL_CONSTASCII_STRINGPARAM(UTF8_TH_1E6)));
    3039                 :            : 
    3040         [ #  # ]:          0 :             aText.insert(0, aBlock.makeStringAndClear());
    3041                 :          0 :         }
    3042         [ #  # ]:          0 :         if (aText.getLength() > 0)
    3043         [ #  # ]:          0 :             aText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_BAHT) );
    3044                 :            : 
    3045                 :            :         // generate text for Satang value
    3046         [ #  # ]:          0 :         if( nSatang == 0 )
    3047                 :            :         {
    3048         [ #  # ]:          0 :             aText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_DOT0) );
    3049                 :            :         }
    3050                 :            :         else
    3051                 :            :         {
    3052         [ #  # ]:          0 :             lclAppendBlock( aText, nSatang );
    3053         [ #  # ]:          0 :             aText.append( RTL_CONSTASCII_STRINGPARAM(UTF8_TH_SATANG) );
    3054                 :            :         }
    3055                 :            : 
    3056                 :            :         // add the minus sign
    3057         [ #  # ]:          0 :         if( bMinus )
    3058                 :            :             aText.insert(
    3059         [ #  # ]:          0 :                 0, rtl::OString(RTL_CONSTASCII_STRINGPARAM(UTF8_TH_MINUS)));
    3060                 :            : 
    3061 [ #  # ][ #  # ]:          0 :         PushString( rtl::OStringToOUString(aText.makeStringAndClear(), RTL_TEXTENCODING_UTF8) );
         [ #  # ][ #  # ]
    3062                 :            :     }
    3063                 :            : }
    3064                 :            : 
    3065                 :            : // ============================================================================
    3066                 :            : 
    3067                 :          0 : void ScInterpreter::ScGetPivotData()
    3068                 :            : {
    3069                 :            :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetPivotData" );
    3070                 :          0 :     sal_uInt8 nParamCount = GetByte();
    3071                 :            : 
    3072         [ #  # ]:          0 :     if ( MustHaveParamCount( nParamCount, 2, 30 ) )
    3073                 :            :     {
    3074                 :            :         // there must be an even number of args
    3075                 :            :         //      target, ref, then field/item pairs
    3076         [ #  # ]:          0 :         if( (nParamCount % 2) == 1)
    3077                 :            :             goto failed;
    3078                 :            : 
    3079                 :          0 :         bool bOldSyntax = false;
    3080         [ #  # ]:          0 :         if ( nParamCount == 2 )
    3081                 :            :         {
    3082                 :            :             // if the first parameter is a ref, assume old syntax
    3083         [ #  # ]:          0 :             StackVar eFirstType = GetStackType( 2 );
    3084 [ #  # ][ #  # ]:          0 :             if ( eFirstType == svSingleRef || eFirstType == svDoubleRef )
    3085                 :          0 :                 bOldSyntax = true;
    3086                 :            :         }
    3087                 :            : 
    3088                 :          0 :         ScDPGetPivotDataField aTarget;                  // target field, and returns result
    3089         [ #  # ]:          0 :         std::vector< ScDPGetPivotDataField > aFilters;
    3090         [ #  # ]:          0 :         String aFilterList;
    3091         [ #  # ]:          0 :         if ( bOldSyntax )
    3092 [ #  # ][ #  # ]:          0 :             aFilterList = GetString();      // old syntax: second parameter is list of constraints
    3093                 :            :         else
    3094                 :            :         {
    3095                 :            :             // new syntax: separate name/value pairs
    3096                 :            : 
    3097                 :          0 :             sal_uInt16 nFilterCount = nParamCount / 2 - 1;
    3098         [ #  # ]:          0 :             aFilters.resize( nFilterCount );
    3099                 :            : 
    3100                 :          0 :             sal_uInt16 i = nFilterCount;
    3101         [ #  # ]:          0 :             while( i-- > 0 )
    3102                 :            :             {
    3103                 :            :                 //! should allow numeric constraint values
    3104                 :          0 :                 aFilters[i].mbValIsStr = true;
    3105 [ #  # ][ #  # ]:          0 :                 aFilters[i].maValStr = GetString();
    3106                 :            : 
    3107 [ #  # ][ #  # ]:          0 :                 aFilters[i].maFieldName = GetString();
    3108                 :            :             }
    3109                 :            :         }
    3110                 :            : 
    3111                 :            :         // common to both syntaxes: a reference to the data pilot table
    3112                 :            : 
    3113                 :          0 :         ScRange aBlock;
    3114      [ #  #  # ]:          0 :         switch ( GetStackType() )
                 [ #  # ]
    3115                 :            :         {
    3116                 :            :             case svDoubleRef :
    3117         [ #  # ]:          0 :                 PopDoubleRef( aBlock );
    3118                 :          0 :                 break;
    3119                 :            : 
    3120                 :            :             case svSingleRef :
    3121                 :            :                 {
    3122                 :          0 :                     ScAddress aAddr;
    3123         [ #  # ]:          0 :                     PopSingleRef( aAddr );
    3124                 :          0 :                     aBlock = aAddr;
    3125                 :            :                     break;
    3126                 :            :                 }
    3127                 :            :             default:
    3128                 :            :                 goto failed;
    3129                 :            :         }
    3130                 :            :         // NOTE : MS Excel docs claim to use the 'most recent' which is not
    3131                 :            :         // exactly the same as what we do in ScDocument::GetDPAtBlock
    3132                 :            :         // However we do need to use GetDPABlock
    3133         [ #  # ]:          0 :         ScDPObject* pDPObj = pDok->GetDPAtBlock ( aBlock );
    3134         [ #  # ]:          0 :         if( NULL == pDPObj)
    3135                 :            :             goto failed;
    3136                 :            : 
    3137         [ #  # ]:          0 :         if ( bOldSyntax )
    3138                 :            :         {
    3139                 :            :             // fill aFilters / aTarget from aFilterList string
    3140 [ #  # ][ #  # ]:          0 :             if ( !pDPObj->ParseFilters( aTarget, aFilters, aFilterList ) )
                 [ #  # ]
    3141                 :            :                 goto failed;
    3142                 :            :         }
    3143                 :            :         else
    3144 [ #  # ][ #  # ]:          0 :             aTarget.maFieldName = GetString();      // new syntax: first parameter is data field name
    3145                 :            : 
    3146 [ #  # ][ #  # ]:          0 :         if( pDPObj->GetPivotData( aTarget, aFilters ) )
    3147                 :            :         {
    3148         [ #  # ]:          0 :             if( aTarget.mbValIsStr )
    3149 [ #  # ][ #  # ]:          0 :                 PushString( aTarget.maValStr );
                 [ #  # ]
    3150                 :            :             else
    3151         [ #  # ]:          0 :                 PushDouble( aTarget.mnValNum );
    3152                 :          0 :             return;
    3153         [ #  # ]:          0 :         }
              [ #  #  # ]
              [ #  #  # ]
              [ #  #  # ]
    3154                 :            :     }
    3155                 :            : 
    3156                 :            : failed :
    3157                 :          0 :     PushError( errNoRef );
    3158                 :            : }
    3159                 :            : 
    3160                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10