LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/bastyp - calc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 182 619 29.4 %
Date: 2012-12-27 Functions: 18 37 48.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #if defined(MACOSX)
      21             : #include <stdlib.h>
      22             : #endif
      23             : 
      24             : #include <calc.hxx>
      25             : #include <cctype>
      26             : #include <cfloat>
      27             : #include <climits>
      28             : #include <comphelper/processfactory.hxx>
      29             : #include <comphelper/string.hxx>
      30             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      31             : #include <cstdlib>
      32             : #include <dbfld.hxx>
      33             : #include <dbmgr.hxx>
      34             : #include <docfld.hxx>
      35             : #include <docstat.hxx>
      36             : #include <doc.hxx>
      37             : #include <editeng/langitem.hxx>
      38             : #include <editeng/scripttypeitem.hxx>
      39             : #include <editeng/unolingu.hxx>
      40             : #include <expfld.hxx>
      41             : #include <hintids.hxx>
      42             : #include <osl/diagnose.hxx>
      43             : #include <rtl/math.hxx>
      44             : #include <shellres.hxx>
      45             : #include <svl/zforlist.hxx>
      46             : #include <swmodule.hxx>
      47             : #include <swtypes.hxx>
      48             : #include <unotools/charclass.hxx>
      49             : #include <unotools/localedatawrapper.hxx>
      50             : #include <unotools/useroptions.hxx>
      51             : #include <usrfld.hxx>
      52             : #include <viewsh.hxx>
      53             : 
      54             : using namespace ::com::sun::star;
      55             : 
      56             : // shortcut
      57             : #define RESOURCE ViewShell::GetShellRes()
      58             : 
      59             : const sal_Char sCalc_Add[]  =   "add";
      60             : const sal_Char sCalc_Sub[]  =   "sub";
      61             : const sal_Char sCalc_Mul[]  =   "mul";
      62             : const sal_Char sCalc_Div[]  =   "div";
      63             : const sal_Char sCalc_Phd[]  =   "phd";
      64             : const sal_Char sCalc_Sqrt[] =   "sqrt";
      65             : const sal_Char sCalc_Pow[]  =   "pow";
      66             : const sal_Char sCalc_Or[]   =   "or";
      67             : const sal_Char sCalc_Xor[]  =   "xor";
      68             : const sal_Char sCalc_And[]  =   "and";
      69             : const sal_Char sCalc_Not[]  =   "not";
      70             : const sal_Char sCalc_Eq[]   =   "eq";
      71             : const sal_Char sCalc_Neq[]  =   "neq";
      72             : const sal_Char sCalc_Leq[]  =   "leq";
      73             : const sal_Char sCalc_Geq[]  =   "geq";
      74             : const sal_Char sCalc_L[]    =   "l";
      75             : const sal_Char sCalc_G[]    =   "g";
      76             : const sal_Char sCalc_Sum[]  =   "sum";
      77             : const sal_Char sCalc_Mean[] =   "mean";
      78             : const sal_Char sCalc_Min[]  =   "min";
      79             : const sal_Char sCalc_Max[]  =   "max";
      80             : const sal_Char sCalc_Sin[]  =   "sin";
      81             : const sal_Char sCalc_Cos[]  =   "cos";
      82             : const sal_Char sCalc_Tan[]  =   "tan";
      83             : const sal_Char sCalc_Asin[] =   "asin";
      84             : const sal_Char sCalc_Acos[] =   "acos";
      85             : const sal_Char sCalc_Atan[] =   "atan";
      86             : const sal_Char sCalc_Round[]=   "round";
      87             : const sal_Char sCalc_Date[] =   "date";
      88             : 
      89             : // ATTENTION: sorted list of all operators
      90             : struct _CalcOp
      91             : {
      92             :     union{
      93             :         const sal_Char* pName;
      94             :         const String* pUName;
      95             :     };
      96             :     SwCalcOper eOp;
      97             : };
      98             : 
      99             : _CalcOp const aOpTable[] = {
     100             : /* ACOS */    {{sCalc_Acos},       CALC_ACOS},  // Arc cosine
     101             : /* ADD */     {{sCalc_Add},        CALC_PLUS},  // Addition
     102             : /* AND */     {{sCalc_And},        CALC_AND},   // log. AND
     103             : /* ASIN */    {{sCalc_Asin},       CALC_ASIN},  // Arc sine
     104             : /* ATAN */    {{sCalc_Atan},       CALC_ATAN},  // Arc tangent
     105             : /* COS */     {{sCalc_Cos},        CALC_COS},   // Cosine
     106             : /* DATE */    {{sCalc_Date},       CALC_DATE},  // Date
     107             : /* DIV */     {{sCalc_Div},        CALC_DIV},   // Division
     108             : /* EQ */      {{sCalc_Eq},         CALC_EQ},    // Equality
     109             : /* G */       {{sCalc_G},          CALC_GRE},   // Greater than
     110             : /* GEQ */     {{sCalc_Geq},        CALC_GEQ},   // Greater or equal
     111             : /* L */       {{sCalc_L},          CALC_LES},   // Less than
     112             : /* LEQ */     {{sCalc_Leq},        CALC_LEQ},   // Less or equal
     113             : /* MAX */     {{sCalc_Max},        CALC_MAX},   // Maximum value
     114             : /* MEAN */    {{sCalc_Mean},       CALC_MEAN},  // Mean
     115             : /* MIN */     {{sCalc_Min},        CALC_MIN},   // Minimum value
     116             : /* MUL */     {{sCalc_Mul},        CALC_MUL},   // Multiplication
     117             : /* NEQ */     {{sCalc_Neq},        CALC_NEQ},   // Not equal
     118             : /* NOT */     {{sCalc_Not},        CALC_NOT},   // log. NOT
     119             : /* OR */      {{sCalc_Or},         CALC_OR},    // log. OR
     120             : /* PHD */     {{sCalc_Phd},        CALC_PHD},   // Percentage
     121             : /* POW */     {{sCalc_Pow},        CALC_POW},   // Exponentiation
     122             : /* ROUND */   {{sCalc_Round},      CALC_ROUND}, // Rounding
     123             : /* SIN */     {{sCalc_Sin},        CALC_SIN},   // Sine
     124             : /* SQRT */    {{sCalc_Sqrt},       CALC_SQRT},  // Square root
     125             : /* SUB */     {{sCalc_Sub},        CALC_MINUS}, // Subtraction
     126             : /* SUM */     {{sCalc_Sum},        CALC_SUM},   // Sum
     127             : /* TAN */     {{sCalc_Tan},        CALC_TAN},   // Tangent
     128             : /* XOR */     {{sCalc_Xor},        CALC_XOR}    // log. XOR
     129             : };
     130             : 
     131             : double const nRoundVal[] = {
     132             :     5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
     133             :     0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,
     134             :     0.5e-15,0.5e-16
     135             : };
     136             : 
     137             : double const nKorrVal[] = {
     138             :     9, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
     139             :     9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14
     140             : };
     141             : 
     142             : // First character may be any alphabetic or underscore.
     143             : const sal_Int32 coStartFlags =
     144             :         i18n::KParseTokens::ANY_LETTER_OR_NUMBER |
     145             :         i18n::KParseTokens::ASC_UNDERSCORE |
     146             :         i18n::KParseTokens::IGNORE_LEADING_WS;
     147             : 
     148             : // Continuing characters may be any alphanumeric, underscore, or dot.
     149             : const sal_Int32 coContFlags =
     150             :     ( coStartFlags | i18n::KParseTokens::ASC_DOT )
     151             :         & ~i18n::KParseTokens::IGNORE_LEADING_WS;
     152             : 
     153             : extern "C" {
     154          20 : static int SAL_CALL OperatorCompare( const void *pFirst, const void *pSecond)
     155             : {
     156          20 :     int nRet = 0;
     157          20 :     if( CALC_NAME == ((_CalcOp*)pFirst)->eOp )
     158             :     {
     159          20 :         if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
     160             :             nRet = ((_CalcOp*)pFirst)->pUName->CompareTo(
     161           0 :                    *((_CalcOp*)pSecond)->pUName );
     162             :         else
     163             :             nRet = ((_CalcOp*)pFirst)->pUName->CompareToAscii(
     164          20 :                    ((_CalcOp*)pSecond)->pName );
     165             :     }
     166             :     else
     167             :     {
     168           0 :         if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
     169             :             nRet = -1 * ((_CalcOp*)pSecond)->pUName->CompareToAscii(
     170           0 :                         ((_CalcOp*)pFirst)->pName );
     171             :         else
     172             :             nRet = strcmp( ((_CalcOp*)pFirst)->pName,
     173           0 :                            ((_CalcOp*)pSecond)->pName );
     174             :     }
     175          20 :     return nRet;
     176             : }
     177             : }// extern "C"
     178             : 
     179           4 : _CalcOp* FindOperator( const String& rSrch )
     180             : {
     181             :     _CalcOp aSrch;
     182           4 :     aSrch.pUName = &rSrch;
     183           4 :     aSrch.eOp = CALC_NAME;
     184             : 
     185             :     return (_CalcOp*)bsearch( (void*) &aSrch,
     186             :                               (void*) aOpTable,
     187             :                               sizeof( aOpTable ) / sizeof( _CalcOp ),
     188             :                               sizeof( _CalcOp ),
     189           4 :                               OperatorCompare );
     190             : }
     191             : 
     192           5 : SwHash* Find( const String& rStr, SwHash** ppTable,
     193             :               sal_uInt16 nTblSize, sal_uInt16* pPos )
     194             : {
     195           5 :     sal_uLong ii = 0;
     196          60 :     for( xub_StrLen n = 0; n < rStr.Len(); ++n )
     197             :     {
     198          55 :         ii = ii << 1 ^ rStr.GetChar( n );
     199             :     }
     200           5 :     ii %= nTblSize;
     201             : 
     202           5 :     if( pPos )
     203           5 :         *pPos = (sal_uInt16)ii;
     204             : 
     205           5 :     for( SwHash* pEntry = *(ppTable+ii); pEntry; pEntry = pEntry->pNext )
     206             :     {
     207           0 :         if( rStr == pEntry->aStr )
     208             :         {
     209           0 :             return pEntry;
     210             :         }
     211             :     }
     212           5 :     return 0;
     213             : }
     214             : 
     215           2 : inline LanguageType GetDocAppScriptLang( SwDoc& rDoc )
     216             : {
     217             :     return ((SvxLanguageItem&)rDoc.GetDefault(
     218             :                GetWhichOfScript( RES_CHRATR_LANGUAGE,
     219           2 :                                  GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() ))
     220           2 :             )).GetLanguage();
     221             : }
     222             : 
     223           0 : static double lcl_ConvertToDateValue( SwDoc& rDoc, sal_Int32 nDate )
     224             : {
     225           0 :     double nRet = 0;
     226           0 :     SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
     227           0 :     if( pFormatter )
     228             :     {
     229           0 :         Date* pNull = pFormatter->GetNullDate();
     230           0 :         Date aDate( nDate >> 24, (nDate& 0x00FF0000) >> 16, nDate& 0x0000FFFF );
     231           0 :         nRet = aDate - *pNull;
     232             :     }
     233           0 :     return nRet;
     234             : }
     235             : 
     236           2 : SwCalc::SwCalc( SwDoc& rD )
     237             :     : aErrExpr( aEmptyStr, SwSbxValue(), 0 ),
     238             :     rDoc( rD ),
     239           2 :     pLclData( m_aSysLocale.GetLocaleDataPtr() ),
     240           2 :     pCharClass( &GetAppCharClass() ),
     241             :     nListPor( 0 ),
     242           6 :     eError( CALC_NOERR )
     243             : {
     244           2 :     aErrExpr.aStr.AssignAscii( "~C_ERR~" );
     245           2 :     memset( VarTable, 0, sizeof(VarTable) );
     246           2 :     LanguageType eLang = GetDocAppScriptLang( rDoc );
     247             : 
     248           2 :     if( eLang != pLclData->getLanguageTag().getLanguageType() ||
     249           0 :         eLang != pCharClass->getLanguageTag().getLanguageType() )
     250             :     {
     251           2 :         LanguageTag aLanguageTag( eLang );
     252           2 :         pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), aLanguageTag );
     253           2 :         pLclData = new LocaleDataWrapper( aLanguageTag );
     254             :     }
     255             : 
     256           2 :     sCurrSym = comphelper::string::strip(pLclData->getCurrSymbol(), ' ');
     257           2 :     sCurrSym  = pCharClass->lowercase( sCurrSym );
     258             : 
     259             :     static sal_Char const
     260             :         sNType0[] = "false",
     261             :         sNType1[] = "true",
     262             :         sNType2[] = "pi",
     263             :         sNType3[] = "e",
     264             :         sNType4[] = "tables",
     265             :         sNType5[] = "graf",
     266             :         sNType6[] = "ole",
     267             :         sNType7[] = "page",
     268             :         sNType8[] = "para",
     269             :         sNType9[] = "word",
     270             :         sNType10[]= "char",
     271             : 
     272             :         sNType11[] = "user_firstname" ,
     273             :         sNType12[] = "user_lastname" ,
     274             :         sNType13[] = "user_initials" ,
     275             :         sNType14[] = "user_company" ,
     276             :         sNType15[] = "user_street" ,
     277             :         sNType16[] = "user_country" ,
     278             :         sNType17[] = "user_zipcode" ,
     279             :         sNType18[] = "user_city" ,
     280             :         sNType19[] = "user_title" ,
     281             :         sNType20[] = "user_position" ,
     282             :         sNType21[] = "user_tel_work" ,
     283             :         sNType22[] = "user_tel_home" ,
     284             :         sNType23[] = "user_fax" ,
     285             :         sNType24[] = "user_email" ,
     286             :         sNType25[] = "user_state" ,
     287             :         sNType26[] = "graph"
     288             :         ;
     289             :     static const sal_Char* const sNTypeTab[ 27 ] =
     290             :     {
     291             :         sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
     292             :         sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
     293             :         sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
     294             :         sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
     295             :         sNType24,
     296             : 
     297             :         // those have two HashIds
     298             :         sNType25, sNType26
     299             :     };
     300             :     static sal_uInt16 const aHashValue[ 27 ] =
     301             :     {
     302             :         34, 38, 43,  7, 18, 32, 22, 29, 30, 33,  3,
     303             :         28, 24, 40,  9, 11, 26, 45,  4, 23, 36, 44, 19,  5,  1,
     304             :         // those have two HashIds
     305             :         11, 38
     306             :     };
     307             :     static sal_uInt16 const aAdrToken[ 12 ] =
     308             :     {
     309             :         USER_OPT_COMPANY, USER_OPT_STREET, USER_OPT_COUNTRY, USER_OPT_ZIP,
     310             :         USER_OPT_CITY, USER_OPT_TITLE, USER_OPT_POSITION, USER_OPT_TELEPHONEWORK,
     311             :         USER_OPT_TELEPHONEHOME, USER_OPT_FAX, USER_OPT_EMAIL, USER_OPT_STATE
     312             :     };
     313             : 
     314             :     static sal_uInt16 SwDocStat::* const aDocStat1[ 3 ] =
     315             :     {
     316             :         &SwDocStat::nTbl, &SwDocStat::nGrf, &SwDocStat::nOLE
     317             :     };
     318             :     static sal_uLong SwDocStat::* const aDocStat2[ 4 ] =
     319             :     {
     320             :         &SwDocStat::nPage, &SwDocStat::nPara,
     321             :         &SwDocStat::nWord, &SwDocStat::nChar
     322             :     };
     323             : 
     324             : #if TBLSZ != 47
     325             : #error Did you adjust all hash values?
     326             : #endif
     327             : 
     328           2 :     const SwDocStat& rDocStat = rDoc.GetDocStat();
     329             : 
     330           2 :     SwSbxValue nVal;
     331           2 :     String sTmpStr;
     332             :     sal_uInt16 n;
     333             : 
     334          52 :     for( n = 0; n < 25; ++n )
     335             :     {
     336          50 :         sTmpStr.AssignAscii( sNTypeTab[ n ] );
     337          50 :         VarTable[ aHashValue[ n ] ] = new SwCalcExp( sTmpStr, nVal, 0 );
     338             :     }
     339             : 
     340           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 0 ] ])->nValue.PutBool( sal_False );
     341           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 1 ] ])->nValue.PutBool( sal_True );
     342           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 2 ] ])->nValue.PutDouble( F_PI );
     343           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 3 ] ])->nValue.PutDouble( 2.7182818284590452354 );
     344             : 
     345           8 :     for( n = 0; n < 3; ++n )
     346           6 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 4 ] ])->nValue.PutLong( rDocStat.*aDocStat1[ n ]  );
     347          10 :     for( n = 0; n < 4; ++n )
     348           8 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 7 ] ])->nValue.PutLong( rDocStat.*aDocStat2[ n ]  );
     349             : 
     350           2 :     SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
     351             : 
     352           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 11 ] ])->nValue.PutString( (String)rUserOptions.GetFirstName() );
     353           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 12 ] ])->nValue.PutString( (String)rUserOptions.GetLastName() );
     354           2 :     ((SwCalcExp*)VarTable[ aHashValue[ 13 ] ])->nValue.PutString( (String)rUserOptions.GetID() );
     355             : 
     356          24 :     for( n = 0; n < 11; ++n )
     357          44 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 14 ] ])->nValue.PutString(
     358          66 :                                         (String)rUserOptions.GetToken( aAdrToken[ n ] ));
     359             : 
     360           2 :     nVal.PutString( (String)rUserOptions.GetToken( aAdrToken[ 11 ] ));
     361           2 :     sTmpStr.AssignAscii( sNTypeTab[ 25 ] );
     362           2 :     VarTable[ aHashValue[ 25 ] ]->pNext = new SwCalcExp( sTmpStr, nVal, 0 );
     363             : 
     364           2 : } // SwCalc::SwCalc
     365             : 
     366           4 : SwCalc::~SwCalc()
     367             : {
     368          96 :     for( sal_uInt16 n = 0; n < TBLSZ; ++n )
     369          94 :         delete VarTable[n];
     370             : 
     371           2 :     if( pLclData != m_aSysLocale.GetLocaleDataPtr() )
     372           2 :         delete pLclData;
     373           2 :     if( pCharClass != &GetAppCharClass() )
     374           2 :         delete pCharClass;
     375           2 : }
     376             : 
     377           2 : SwSbxValue SwCalc::Calculate( const String& rStr )
     378             : {
     379           2 :     eError = CALC_NOERR;
     380           2 :     SwSbxValue nResult;
     381             : 
     382           2 :     if( !rStr.Len() )
     383           0 :         return nResult;
     384             : 
     385           2 :     nListPor = 0;
     386           2 :     eCurrListOper = CALC_PLUS; // default: sum
     387             : 
     388           2 :     sCommand = rStr;
     389           2 :     nCommandPos = 0;
     390             : 
     391           6 :     while( (eCurrOper = GetToken()) != CALC_ENDCALC && eError == CALC_NOERR )
     392           2 :         nResult = Expr();
     393             : 
     394           2 :     if( eError )
     395           0 :         nResult.PutDouble( DBL_MAX );
     396             : 
     397           2 :     return nResult;
     398             : }
     399             : 
     400             : //TODO: provide documentation
     401             : /** ???
     402             : 
     403             :   @param rVal ???
     404             :   @param bRound In previous times <bRound> had a default value of <sal_True>.
     405             :                 There it should be only changed when calculating table cells,
     406             :                 so that no rounding errors would occur while composing a formula.
     407             :                 Now this parameter is ignored.
     408             :   @return ???
     409             : */
     410           0 : String SwCalc::GetStrResult( const SwSbxValue& rVal, sal_Bool bRound )
     411             : {
     412           0 :     if( !rVal.IsDouble() )
     413             :     {
     414           0 :         return rVal.GetOUString();
     415             :     }
     416           0 :     return GetStrResult( rVal.GetDouble(), bRound );
     417             : }
     418             : 
     419           0 : String SwCalc::GetStrResult( double nValue, sal_Bool )
     420             : {
     421           0 :     if( nValue >= DBL_MAX )
     422           0 :         switch( eError )
     423             :         {
     424           0 :         case CALC_SYNTAX    :   return RESOURCE->aCalc_Syntax;
     425           0 :         case CALC_ZERODIV   :   return RESOURCE->aCalc_ZeroDiv;
     426           0 :         case CALC_BRACK     :   return RESOURCE->aCalc_Brack;
     427           0 :         case CALC_POWERR    :   return RESOURCE->aCalc_Pow;
     428           0 :         case CALC_VARNFND   :   return RESOURCE->aCalc_VarNFnd;
     429           0 :         case CALC_OVERFLOW  :   return RESOURCE->aCalc_Overflow;
     430           0 :         case CALC_WRONGTIME :   return RESOURCE->aCalc_WrongTime;
     431           0 :         default             :   return RESOURCE->aCalc_Default;
     432             :         }
     433             : 
     434           0 :     sal_uInt16  nDec = 15;
     435             :     String aRetStr( ::rtl::math::doubleToUString(
     436             :                         nValue,
     437             :                         rtl_math_StringFormat_Automatic,
     438             :                         nDec,
     439           0 :                         pLclData->getNumDecimalSep()[0],
     440           0 :                         true ));
     441           0 :     return aRetStr;
     442             : }
     443             : 
     444           0 : SwCalcExp* SwCalc::VarInsert( const String &rStr )
     445             : {
     446           0 :     String aStr = pCharClass->lowercase( rStr );
     447           0 :     return VarLook( aStr, 1 );
     448             : }
     449             : 
     450           2 : SwCalcExp* SwCalc::VarLook( const String& rStr, sal_uInt16 ins )
     451             : {
     452           2 :     aErrExpr.nValue.SetVoidValue(false);
     453             : 
     454           2 :     sal_uInt16 ii = 0;
     455           2 :     String aStr = pCharClass->lowercase( rStr );
     456             : 
     457           2 :     SwHash* pFnd = Find( aStr, VarTable, TBLSZ, &ii );
     458             : 
     459           2 :     if( !pFnd )
     460             :     {
     461             :         // then check doc
     462           2 :         SwHash** ppDocTbl = rDoc.GetUpdtFlds().GetFldTypeTable();
     463           2 :         for( SwHash* pEntry = *(ppDocTbl+ii); pEntry; pEntry = pEntry->pNext )
     464             :         {
     465           2 :             if( aStr == pEntry->aStr )
     466             :             {
     467             :                 // then insert here
     468             :                 pFnd = new SwCalcExp( aStr, SwSbxValue(),
     469           2 :                                     ((SwCalcFldType*)pEntry)->pFldType );
     470           2 :                 pFnd->pNext = *(VarTable+ii);
     471           2 :                 *(VarTable+ii) = pFnd;
     472           2 :                 break;
     473             :             }
     474             :         }
     475             :     }
     476             : 
     477           2 :     if( pFnd )
     478             :     {
     479           2 :         SwCalcExp* pFndExp = (SwCalcExp*)pFnd;
     480             : 
     481           2 :         if( pFndExp->pFldType && pFndExp->pFldType->Which() == RES_USERFLD )
     482             :         {
     483           2 :             SwUserFieldType* pUFld = (SwUserFieldType*)pFndExp->pFldType;
     484           2 :             if( nsSwGetSetExpType::GSE_STRING & pUFld->GetType() )
     485             :             {
     486           2 :                 pFndExp->nValue.PutString( pUFld->GetContent() );
     487             :             }
     488           0 :             else if( !pUFld->IsValid() )
     489             :             {
     490             :                 // Save the current values...
     491           0 :                 sal_uInt16          nOld_ListPor        = nListPor;
     492           0 :                 SwSbxValue      nOld_LastLeft       = nLastLeft;
     493           0 :                 SwSbxValue      nOld_NumberValue    = nNumberValue;
     494           0 :                 xub_StrLen      nOld_CommandPos     = nCommandPos;
     495           0 :                 SwCalcOper      eOld_CurrOper       = eCurrOper;
     496           0 :                 SwCalcOper      eOld_CurrListOper   = eCurrListOper;
     497             : 
     498           0 :                 pFndExp->nValue.PutDouble( pUFld->GetValue( *this ) );
     499             : 
     500             :                 // ...and write them back.
     501           0 :                 nListPor        = nOld_ListPor;
     502           0 :                 nLastLeft       = nOld_LastLeft;
     503           0 :                 nNumberValue    = nOld_NumberValue;
     504           0 :                 nCommandPos     = nOld_CommandPos;
     505           0 :                 eCurrOper       = eOld_CurrOper;
     506           0 :                 eCurrListOper   = eOld_CurrListOper;
     507             :             }
     508             :             else
     509             :             {
     510           0 :                 pFndExp->nValue.PutDouble( pUFld->GetValue() );
     511             :             }
     512             :         }
     513           2 :         return pFndExp;
     514             :     }
     515             : 
     516             :     // At this point the "real" case variable has to be used
     517           0 :     String sTmpName( rStr );
     518           0 :     ::ReplacePoint( sTmpName );
     519             : 
     520           0 :     if( !ins )
     521             :     {
     522           0 :         SwNewDBMgr *pMgr = rDoc.GetNewDBMgr();
     523             : 
     524           0 :         String sDBName(GetDBName( sTmpName ));
     525           0 :         String sSourceName(sDBName.GetToken(0, DB_DELIM));
     526           0 :         String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM));
     527           0 :         if( pMgr && sSourceName.Len() && sTableName.Len() &&
     528           0 :             pMgr->OpenDataSource(sSourceName, sTableName, -1, false))
     529             :         {
     530           0 :             String sColumnName( GetColumnName( sTmpName ));
     531             :             OSL_ENSURE(sColumnName.Len(), "Missing DB column name");
     532             : 
     533           0 :             String sDBNum( SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD) );
     534           0 :             sDBNum = pCharClass->lowercase(sDBNum);
     535             : 
     536             :             // Initialize again because this doesn't happen in docfld anymore for
     537             :             // elements != RES_DBFLD. E.g. if there is an expression field before
     538             :             // an DB_Field in a document.
     539           0 :             VarChange( sDBNum, pMgr->GetSelectedRecordId(sSourceName, sTableName));
     540             : 
     541           0 :             if( sDBNum.EqualsIgnoreCaseAscii(sColumnName) )
     542             :             {
     543           0 :                 aErrExpr.nValue.PutLong(long(pMgr->GetSelectedRecordId(sSourceName, sTableName)));
     544           0 :                 return &aErrExpr;
     545             :             }
     546             : 
     547           0 :             sal_uLong nTmpRec = 0;
     548           0 :             if( 0 != ( pFnd = Find( sDBNum, VarTable, TBLSZ ) ) )
     549           0 :                 nTmpRec = ((SwCalcExp*)pFnd)->nValue.GetULong();
     550             : 
     551           0 :             rtl::OUString sResult;
     552           0 :             double nNumber = DBL_MAX;
     553             : 
     554           0 :             long nLang = pLclData->getLanguageTag().getLanguageType();
     555           0 :             if(pMgr->GetColumnCnt( sSourceName, sTableName, sColumnName,
     556           0 :                                     nTmpRec, nLang, sResult, &nNumber ))
     557             :             {
     558           0 :                 if (nNumber != DBL_MAX)
     559           0 :                     aErrExpr.nValue.PutDouble( nNumber );
     560             :                 else
     561           0 :                     aErrExpr.nValue.PutString( sResult );
     562             : 
     563           0 :                 return &aErrExpr;
     564           0 :             }
     565             :         }
     566             :         else
     567             :         {
     568             :             //data source was not available - set return to "NoValue"
     569           0 :             aErrExpr.nValue.SetVoidValue(true);
     570             :         }
     571             :         // NEVER save!
     572           0 :         return &aErrExpr;
     573             :     }
     574             : 
     575           0 :     SwCalcExp* pNewExp = new SwCalcExp( aStr, SwSbxValue(), 0 );
     576           0 :     pNewExp->pNext = VarTable[ ii ];
     577           0 :     VarTable[ ii ] = pNewExp;
     578             : 
     579           0 :     String sColumnName( GetColumnName( sTmpName ));
     580             :     OSL_ENSURE( sColumnName.Len(), "Missing DB column name" );
     581           0 :     if( sColumnName.EqualsIgnoreCaseAscii(
     582           0 :                             SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) ))
     583             :     {
     584           0 :         SwNewDBMgr *pMgr = rDoc.GetNewDBMgr();
     585           0 :         String sDBName(GetDBName( sTmpName ));
     586           0 :         String sSourceName(sDBName.GetToken(0, DB_DELIM));
     587           0 :         String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM));
     588           0 :         if( pMgr && sSourceName.Len() && sTableName.Len() &&
     589           0 :             pMgr->OpenDataSource(sSourceName, sTableName, -1, false) &&
     590           0 :             !pMgr->IsInMerge())
     591             :         {
     592           0 :             pNewExp->nValue.PutULong( pMgr->GetSelectedRecordId(sSourceName, sTableName));
     593             :         }
     594             :         else
     595             :         {
     596           0 :             pNewExp->nValue.SetVoidValue(true);
     597           0 :         }
     598             :     }
     599             : 
     600           0 :     return pNewExp;
     601             : }
     602             : 
     603           0 : void SwCalc::VarChange( const String& rStr, double nValue )
     604             : {
     605           0 :     SwSbxValue aVal( nValue );
     606           0 :     VarChange( rStr, aVal );
     607           0 : }
     608             : 
     609           0 : void SwCalc::VarChange( const String& rStr, const SwSbxValue& rValue )
     610             : {
     611           0 :     String aStr = pCharClass->lowercase( rStr );
     612             : 
     613           0 :     sal_uInt16 nPos = 0;
     614           0 :     SwCalcExp* pFnd = (SwCalcExp*)Find( aStr, VarTable, TBLSZ, &nPos );
     615             : 
     616           0 :     if( !pFnd )
     617             :     {
     618           0 :         pFnd = new SwCalcExp( aStr, SwSbxValue( rValue ), 0 );
     619           0 :         pFnd->pNext = VarTable[ nPos ];
     620           0 :         VarTable[ nPos ] = pFnd;
     621             :     }
     622             :     else
     623             :     {
     624           0 :         pFnd->nValue = rValue;
     625           0 :     }
     626           0 : }
     627             : 
     628           0 : bool SwCalc::Push( const SwUserFieldType* pUserFieldType )
     629             : {
     630           0 :     if( aRekurStk.end() != std::find(aRekurStk.begin(), aRekurStk.end(), pUserFieldType ) )
     631           0 :         return false;
     632             : 
     633           0 :     aRekurStk.push_back( pUserFieldType );
     634           0 :     return true;
     635             : }
     636             : 
     637           0 : void SwCalc::Pop()
     638             : {
     639             :     OSL_ENSURE( aRekurStk.size(), "SwCalc: Pop on an invalid pointer" );
     640             : 
     641           0 :     aRekurStk.pop_back();
     642           0 : }
     643             : 
     644          10 : SwCalcOper SwCalc::GetToken()
     645             : {
     646             : #if OSL_DEBUG_LEVEL > 1
     647             :     // static for switch back to the "old" implementation of the calculator
     648             :     // which doesn't use the I18N routines.
     649             :     static int nUseOld = 0;
     650             :     if( !nUseOld )
     651             :     {
     652             : #endif
     653             : 
     654          10 :     if( nCommandPos >= sCommand.Len() )
     655           4 :         return eCurrOper = CALC_ENDCALC;
     656             : 
     657             :     using namespace ::com::sun::star::i18n;
     658             :     {
     659             :         // Parse any token.
     660             :         ParseResult aRes = pCharClass->parseAnyToken( sCommand, nCommandPos,
     661             :                                                       coStartFlags, aEmptyStr,
     662           6 :                                                       coContFlags, aEmptyStr );
     663             : 
     664           6 :         bool bSetError = true;
     665           6 :         xub_StrLen nRealStt = nCommandPos + (xub_StrLen)aRes.LeadingWhiteSpace;
     666           6 :         if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) )
     667             :         {
     668           0 :             nNumberValue.PutDouble( aRes.Value );
     669           0 :             eCurrOper = CALC_NUMBER;
     670           0 :             bSetError = false;
     671             :         }
     672           6 :         else if( aRes.TokenType & KParseType::IDENTNAME )
     673             :         {
     674             :             String aName( sCommand.Copy( nRealStt,
     675           4 :                             static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
     676             :             //#101436#: The variable may contain a database name. It must not be
     677             :             // converted to lower case! Instead all further comparisons must be
     678             :             // done case-insensitive
     679           4 :             String sLowerCaseName = pCharClass->lowercase( aName );
     680             :             // catch currency symbol
     681           4 :             if( sLowerCaseName == sCurrSym )
     682             :             {
     683           0 :                 nCommandPos = (xub_StrLen)aRes.EndPos;
     684           0 :                 return GetToken(); // call again
     685             :             }
     686             : 
     687             :             // catch operators
     688           4 :             _CalcOp* pFnd = ::FindOperator( sLowerCaseName );
     689           4 :             if( pFnd )
     690             :             {
     691           2 :                 switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) )
     692             :                 {
     693             :                 case CALC_SUM:
     694             :                 case CALC_MEAN:
     695           0 :                     eCurrListOper = CALC_PLUS;
     696           0 :                     break;
     697             :                 case CALC_MIN:
     698           0 :                     eCurrListOper = CALC_MIN_IN;
     699           0 :                     break;
     700             :                 case CALC_MAX:
     701           0 :                     eCurrListOper = CALC_MAX_IN;
     702           0 :                     break;
     703             :                 case CALC_DATE:
     704           0 :                     eCurrListOper = CALC_MONTH;
     705           0 :                     break;
     706             :                 default:
     707           2 :                     break;
     708             :                 }
     709           2 :                 nCommandPos = (xub_StrLen)aRes.EndPos;
     710           2 :                 return eCurrOper;
     711             :             }
     712           2 :             aVarName = aName;
     713           2 :             eCurrOper = CALC_NAME;
     714           2 :             bSetError = false;
     715             :         }
     716           2 :         else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING )
     717             :         {
     718           2 :             nNumberValue.PutString( String( aRes.DequotedNameOrString ));
     719           2 :             eCurrOper = CALC_NUMBER;
     720           2 :             bSetError = false;
     721             :         }
     722           0 :         else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR )
     723             :         {
     724             :             String aName( sCommand.Copy( nRealStt,
     725           0 :                               static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
     726           0 :             if( 1 == aName.Len() )
     727             :             {
     728           0 :                 bSetError = false;
     729           0 :                 sal_Unicode ch = aName.GetChar( 0 );
     730           0 :                 switch( ch )
     731             :                 {
     732             :                 case ';':
     733           0 :                     if( CALC_MONTH == eCurrListOper || CALC_DAY == eCurrListOper )
     734             :                     {
     735           0 :                         eCurrOper = eCurrListOper;
     736           0 :                         break;
     737             :                     }
     738             : 
     739             :                 case '\n':
     740           0 :                     eCurrOper = CALC_PRINT;
     741           0 :                     break;
     742             : 
     743             :                 case '%':
     744             :                 case '^':
     745             :                 case '*':
     746             :                 case '/':
     747             :                 case '+':
     748             :                 case '-':
     749             :                 case '(':
     750             :                 case ')':
     751           0 :                     eCurrOper = SwCalcOper(ch);
     752           0 :                     break;
     753             : 
     754             :                 case '=':
     755             :                 case '!':
     756             :                     {
     757             :                         SwCalcOper eTmp2;
     758           0 :                         if( '=' == ch )
     759           0 :                             eCurrOper = SwCalcOper('='), eTmp2 = CALC_EQ;
     760             :                         else
     761           0 :                             eCurrOper = CALC_NOT, eTmp2 = CALC_NEQ;
     762             : 
     763           0 :                         if( aRes.EndPos < sCommand.Len() &&
     764           0 :                             '=' == sCommand.GetChar( (xub_StrLen)aRes.EndPos ) )
     765             :                         {
     766           0 :                             eCurrOper = eTmp2;
     767           0 :                             ++aRes.EndPos;
     768             :                         }
     769             :                     }
     770           0 :                     break;
     771             : 
     772             :                 case cListDelim:
     773           0 :                     eCurrOper = eCurrListOper;
     774           0 :                     break;
     775             : 
     776             :                 case '[':
     777           0 :                     if( aRes.EndPos < sCommand.Len() )
     778             :                     {
     779           0 :                         aVarName.Erase();
     780           0 :                         xub_StrLen nFndPos = (xub_StrLen)aRes.EndPos,
     781           0 :                                              nSttPos = nFndPos;
     782             : 
     783           0 :                         do {
     784           0 :                             if( STRING_NOTFOUND != ( nFndPos =
     785           0 :                                 sCommand.Search( ']', nFndPos )) )
     786             :                             {
     787             :                                 // ignore the ]
     788           0 :                                 if( '\\' == sCommand.GetChar(nFndPos-1))
     789             :                                 {
     790             :                                     aVarName += sCommand.Copy( nSttPos,
     791           0 :                                                     nFndPos - nSttPos - 1 );
     792           0 :                                     nSttPos = ++nFndPos;
     793             :                                 }
     794             :                                 else
     795           0 :                                     break;
     796             :                             }
     797             :                         } while( STRING_NOTFOUND != nFndPos );
     798             : 
     799           0 :                         if( STRING_NOTFOUND != nFndPos )
     800             :                         {
     801           0 :                             if( nSttPos != nFndPos )
     802             :                                 aVarName += sCommand.Copy( nSttPos,
     803           0 :                                                     nFndPos - nSttPos );
     804           0 :                             aRes.EndPos = nFndPos + 1;
     805           0 :                             eCurrOper = CALC_NAME;
     806             :                         }
     807             :                         else
     808           0 :                             bSetError = true;
     809             :                     }
     810             :                     else
     811             :                     {
     812           0 :                         bSetError = true;
     813             :                     }
     814           0 :                     break;
     815             : 
     816             :                 default:
     817           0 :                     bSetError = true;
     818           0 :                     break;
     819             :                 }
     820           0 :             }
     821             :         }
     822           0 :         else if( aRes.TokenType & KParseType::BOOLEAN )
     823             :         {
     824             :             String aName( sCommand.Copy( nRealStt,
     825           0 :                                          static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
     826           0 :             if( aName.Len() )
     827             :             {
     828           0 :                 sal_Unicode ch = aName.GetChar(0);
     829             : 
     830           0 :                 bSetError = true;
     831           0 :                 if ('<' == ch || '>' == ch)
     832             :                 {
     833           0 :                     bSetError = false;
     834             : 
     835           0 :                     SwCalcOper eTmp2 = ('<' == ch) ? CALC_LEQ : CALC_GEQ;
     836           0 :                     eCurrOper = ('<' == ch) ? CALC_LES : CALC_GRE;
     837             : 
     838           0 :                     if( 2 == aName.Len() && '=' == aName.GetChar(1) )
     839           0 :                         eCurrOper = eTmp2;
     840           0 :                     else if( 1 != aName.Len() )
     841           0 :                         bSetError = true;
     842             :                 }
     843           0 :             }
     844             :         }
     845           0 :         else if( nRealStt == sCommand.Len() )
     846             :         {
     847           0 :             eCurrOper = CALC_ENDCALC;
     848           0 :             bSetError = false;
     849             :         }
     850             : 
     851           4 :         if( bSetError )
     852             :         {
     853           0 :             eError = CALC_SYNTAX;
     854           0 :             eCurrOper = CALC_PRINT;
     855             :         }
     856           4 :         nCommandPos = (xub_StrLen)aRes.EndPos;
     857             :     };
     858             : 
     859             : #if OSL_DEBUG_LEVEL > 1
     860             : #define NextCh( s, n )  (nCommandPos < sCommand.Len() ? sCommand.GetChar( nCommandPos++ ) : 0)
     861             : 
     862             :     }
     863             :     else
     864             :     {
     865             :         sal_Unicode ch;
     866             :         sal_Unicode cTSep = pLclData->getNumThousandSep()[0],
     867             :                     cDSep = pLclData->getNumDecimalSep()[0];
     868             : 
     869             :         do {
     870             :             if( 0 == ( ch = NextCh( sCommand, nCommandPos ) ) )
     871             :                 return eCurrOper = CALC_ENDCALC;
     872             :         } while ( ch == '\t' || ch == ' ' || ch == cTSep );
     873             : 
     874             :         if( ch == cDSep )
     875             :             ch = '.';
     876             : 
     877             :         switch( ch )
     878             :         {
     879             :         case ';':
     880             :             if( CALC_MONTH == eCurrListOper || CALC_DAY == eCurrListOper )
     881             :             {
     882             :                 eCurrOper = eCurrListOper;
     883             :                 break;
     884             :             } // else .. no break
     885             :         case '\n':
     886             :             {
     887             :                 sal_Unicode c;
     888             :                 while( nCommandPos < sCommand.Len() &&
     889             :                        ( ( c = sCommand.GetChar( nCommandPos ) ) == ' ' ||
     890             :                        c == '\t' || c == '\x0a' || c == '\x0d' ))
     891             :                 {
     892             :                     ++nCommandPos;
     893             :                 }
     894             :                 eCurrOper = CALC_PRINT;
     895             :             }
     896             :             break;
     897             : 
     898             :         case '%':
     899             :         case '^':
     900             :         case '*':
     901             :         case '/':
     902             :         case '+':
     903             :         case '-':
     904             :         case '(':
     905             :         case ')':
     906             :             eCurrOper = SwCalcOper(ch);
     907             :             break;
     908             : 
     909             :         case '=':
     910             :             if( '=' == sCommand.GetChar( nCommandPos ) )
     911             :             {
     912             :                 ++nCommandPos;
     913             :                 eCurrOper = CALC_EQ;
     914             :             }
     915             :             else
     916             :             {
     917             :                 eCurrOper = SwCalcOper(ch);
     918             :             }
     919             :             break;
     920             : 
     921             :         case '!':
     922             :             if( '=' == sCommand.GetChar( nCommandPos ) )
     923             :             {
     924             :                 ++nCommandPos;
     925             :                 eCurrOper = CALC_NEQ;
     926             :             }
     927             :             else
     928             :             {
     929             :                 eCurrOper = CALC_NOT;
     930             :             }
     931             :             break;
     932             : 
     933             :         case '>':
     934             :         case '<':
     935             :             eCurrOper = '>' == ch  ? CALC_GRE : CALC_LES;
     936             :             if( '=' == (ch = sCommand.GetChar( nCommandPos ) ) )
     937             :             {
     938             :                 ++nCommandPos;
     939             :                 eCurrOper = CALC_GRE == eCurrOper ? CALC_GEQ : CALC_LEQ;
     940             :             }
     941             :             else if( ' ' != ch )
     942             :             {
     943             :                 eError = CALC_SYNTAX;
     944             :                 eCurrOper = CALC_PRINT;
     945             :             }
     946             :             break;
     947             : 
     948             :         case cListDelim :
     949             :             eCurrOper = eCurrListOper;
     950             :             break;
     951             : 
     952             :         case '0':   case '1':   case '2':   case '3':   case '4':
     953             :         case '5':   case '6':   case '7':   case '8':   case '9':
     954             :         case ',':
     955             :         case '.':
     956             :             {
     957             :                 double nVal;
     958             :                 --nCommandPos; //  back to the first char
     959             :                 if( Str2Double( sCommand, nCommandPos, nVal, pLclData ))
     960             :                 {
     961             :                     nNumberValue.PutDouble( nVal );
     962             :                     eCurrOper = CALC_NUMBER;
     963             :                 }
     964             :                 else
     965             :                 {
     966             :                     // erroneous number
     967             :                     eError = CALC_SYNTAX;
     968             :                     eCurrOper = CALC_PRINT;
     969             :                 }
     970             :             }
     971             :             break;
     972             : 
     973             :         case '[':
     974             :             {
     975             :                 String aStr;
     976             :                 bool bIgnore = false;
     977             :                 do {
     978             :                     while( 0 != ( ch = NextCh( sCommand, nCommandPos  )) &&
     979             :                            ch != ']' )
     980             :                     {
     981             :                         if( !bIgnore && '\\' == ch )
     982             :                             bIgnore = true;
     983             :                         else if( bIgnore )
     984             :                             bIgnore = false;
     985             :                         aStr += ch;
     986             :                     }
     987             : 
     988             :                     if( !bIgnore )
     989             :                         break;
     990             : 
     991             :                     aStr.SetChar( aStr.Len() - 1, ch );
     992             :                 } while( ch );
     993             : 
     994             :                 aVarName = aStr;
     995             :                 eCurrOper = CALC_NAME;
     996             :             }
     997             :             break;
     998             : 
     999             :         case '"':
    1000             :             {
    1001             :                 xub_StrLen nStt = nCommandPos;
    1002             :                 while( 0 != ( ch = NextCh( sCommand, nCommandPos ) ) &&
    1003             :                        '"' != ch )
    1004             :                 {
    1005             :                     ;
    1006             :                 }
    1007             : 
    1008             :                 xub_StrLen nLen = nCommandPos - nStt;
    1009             :                 if( '"' == ch )
    1010             :                     --nLen;
    1011             :                 nNumberValue.PutString( sCommand.Copy( nStt, nLen ));
    1012             :                 eCurrOper = CALC_NUMBER;
    1013             :             }
    1014             :             break;
    1015             : 
    1016             :         default:
    1017             :             if (ch && (pCharClass->isLetter( sCommand, nCommandPos - 1) ||
    1018             :                 '_' == ch))
    1019             :             {
    1020             :                 xub_StrLen nStt = nCommandPos-1;
    1021             :                 while( 0 != (ch = NextCh( sCommand, nCommandPos )) &&
    1022             :                        (pCharClass->isLetterNumeric( sCommand, nCommandPos - 1) ||
    1023             :                        ch == '_' || ch == '.' ) )
    1024             :                 {
    1025             :                     ;
    1026             :                 }
    1027             : 
    1028             :                 if( ch )
    1029             :                     --nCommandPos;
    1030             : 
    1031             :                 String aStr( sCommand.Copy( nStt, nCommandPos-nStt ));
    1032             :                 aStr = pCharClass->lowercase( aStr );
    1033             : 
    1034             :                 // catch currency symbol
    1035             :                 if( aStr == sCurrSym )
    1036             :                     return GetToken();  // call again
    1037             : 
    1038             :                 // catch operators
    1039             :                 _CalcOp* pFnd = ::FindOperator( aStr );
    1040             :                 if( pFnd )
    1041             :                 {
    1042             :                     switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) )
    1043             :                     {
    1044             :                     case CALC_SUM :
    1045             :                     case CALC_MEAN :
    1046             :                         eCurrListOper = CALC_PLUS;
    1047             :                         break;
    1048             :                     case CALC_MIN :
    1049             :                         eCurrListOper = CALC_MIN_IN;
    1050             :                         break;
    1051             :                     case CALC_MAX :
    1052             :                         eCurrListOper = CALC_MAX_IN;
    1053             :                         break;
    1054             :                     case CALC_DATE :
    1055             :                         eCurrListOper = CALC_MONTH;
    1056             :                         break;
    1057             :                     default :
    1058             :                         break;
    1059             :                     }
    1060             :                     return eCurrOper;
    1061             :                 }
    1062             :                 aVarName = aStr;
    1063             :                 eCurrOper = CALC_NAME;
    1064             :             }
    1065             :             else
    1066             :             {
    1067             :                 eError = CALC_SYNTAX;
    1068             :                 eCurrOper = CALC_PRINT;
    1069             :             }
    1070             :             break;
    1071             :         }
    1072             :     }
    1073             : #endif
    1074           4 :     return eCurrOper;
    1075             : }
    1076             : 
    1077           2 : SwSbxValue SwCalc::Term()
    1078             : {
    1079           2 :     SwSbxValue left( Prim() );
    1080           2 :     nLastLeft = left;
    1081           2 :     for(;;)
    1082             :     {
    1083           4 :         sal_uInt16 nSbxOper = USHRT_MAX;
    1084             : 
    1085           4 :         switch( eCurrOper )
    1086             :         {
    1087             :         case CALC_AND:
    1088             :             {
    1089           0 :                 GetToken();
    1090           0 :                 sal_Bool bB = Prim().GetBool();
    1091           0 :                 left.PutBool( left.GetBool() && bB );
    1092             :             }
    1093           0 :             break;
    1094             :         case CALC_OR:
    1095             :             {
    1096           0 :                 GetToken();
    1097           0 :                 sal_Bool bB = Prim().GetBool();
    1098           0 :                 left.PutBool( left.GetBool() || bB );
    1099             :             }
    1100           0 :             break;
    1101             :         case CALC_XOR:
    1102             :             {
    1103           0 :                 GetToken();
    1104           0 :                 sal_Bool bR = Prim().GetBool();
    1105           0 :                 sal_Bool bL = left.GetBool();
    1106           0 :                 left.PutBool( (bL && !bR) || (!bL && bR) );
    1107             :             }
    1108           0 :             break;
    1109             : 
    1110           0 :         case CALC_EQ:   nSbxOper = SbxEQ;   break;
    1111           2 :         case CALC_NEQ:  nSbxOper = SbxNE;   break;
    1112           0 :         case CALC_LEQ:  nSbxOper = SbxLE;   break;
    1113           0 :         case CALC_GEQ:  nSbxOper = SbxGE;   break;
    1114           0 :         case CALC_GRE:  nSbxOper = SbxGT;   break;
    1115           0 :         case CALC_LES:  nSbxOper = SbxLT;   break;
    1116             : 
    1117           0 :         case CALC_MUL:  nSbxOper = SbxMUL;  break;
    1118           0 :         case CALC_DIV:  nSbxOper = SbxDIV;  break;
    1119             : 
    1120             :         case CALC_MIN_IN:
    1121             :             {
    1122           0 :                 GetToken();
    1123           0 :                 SwSbxValue e = Prim();
    1124           0 :                 left = left.GetDouble() < e.GetDouble() ? left : e;
    1125             :             }
    1126           0 :             break;
    1127             :         case CALC_MAX_IN:
    1128             :             {
    1129           0 :                 GetToken();
    1130           0 :                 SwSbxValue e = Prim();
    1131           0 :                 left = left.GetDouble() > e.GetDouble() ? left : e;
    1132             :             }
    1133           0 :             break;
    1134             :         case CALC_MONTH:
    1135             :             {
    1136           0 :                 GetToken();
    1137           0 :                 SwSbxValue e = Prim();
    1138           0 :                 sal_Int32 nYear = (sal_Int32) floor( left.GetDouble() );
    1139           0 :                 nYear = nYear & 0x0000FFFF;
    1140           0 :                 sal_Int32 nMonth = (sal_Int32) floor( e.GetDouble() );
    1141           0 :                 nMonth = ( nMonth & 0x000000FF ) << 16;
    1142           0 :                 left.PutLong( nMonth + nYear );
    1143           0 :                 eCurrOper = CALC_DAY;
    1144             :             }
    1145           0 :             break;
    1146             :         case CALC_DAY:
    1147             :             {
    1148           0 :                 GetToken();
    1149           0 :                 SwSbxValue e = Prim();
    1150           0 :                 sal_Int32 nYearMonth = (sal_Int32) floor( left.GetDouble() );
    1151           0 :                 nYearMonth = nYearMonth & 0x00FFFFFF;
    1152           0 :                 sal_Int32 nDay = (sal_Int32) floor( e.GetDouble() );
    1153           0 :                 nDay = ( nDay & 0x000000FF ) << 24;
    1154           0 :                 left = lcl_ConvertToDateValue( rDoc, nDay + nYearMonth );
    1155             :             }
    1156           0 :             break;
    1157             :         case CALC_ROUND:
    1158             :             {
    1159           0 :                 GetToken();
    1160           0 :                 SwSbxValue e = Prim();
    1161             : 
    1162           0 :                 double fVal = 0;
    1163           0 :                 double fFac = 1;
    1164           0 :                 sal_Int32 nDec = (sal_Int32) floor( e.GetDouble() );
    1165           0 :                 if( nDec < -20 || nDec > 20 )
    1166             :                 {
    1167           0 :                     eError = CALC_OVERFLOW;
    1168           0 :                     left.Clear();
    1169             :                     return left;
    1170             :                 }
    1171           0 :                 fVal = left.GetDouble();
    1172             :                 sal_uInt16 i;
    1173           0 :                 if( nDec >= 0)
    1174             :                 {
    1175           0 :                     for (i = 0; i < (sal_uInt16) nDec; ++i )
    1176           0 :                         fFac *= 10.0;
    1177             :                 }
    1178             :                 else
    1179             :                 {
    1180           0 :                     for (i = 0; i < (sal_uInt16) -nDec; ++i )
    1181           0 :                         fFac /= 10.0;
    1182             :                 }
    1183             : 
    1184           0 :                 fVal *= fFac;
    1185             :                 bool bSign;
    1186           0 :                 if (fVal < 0.0)
    1187             :                 {
    1188           0 :                     fVal *= -1.0;
    1189           0 :                     bSign = true;
    1190             :                 }
    1191             :                 else
    1192             :                 {
    1193           0 :                     bSign = false;
    1194             :                 }
    1195             : 
    1196             :                 // rounding
    1197           0 :                 double fNum = fVal; // find the exponent
    1198           0 :                 int nExp = 0;
    1199           0 :                 if( fNum > 0 )
    1200             :                 {
    1201           0 :                     while( fNum < 1.0 )
    1202           0 :                         fNum *= 10.0, --nExp;
    1203           0 :                     while( fNum >= 10.0 )
    1204           0 :                         fNum /= 10.0, ++nExp;
    1205             :                 }
    1206           0 :                 nExp = 15 - nExp;
    1207           0 :                 if( nExp > 15 )
    1208           0 :                     nExp = 15;
    1209           0 :                 else if( nExp <= 1 )
    1210           0 :                     nExp = 0;
    1211           0 :                 fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] );
    1212             : 
    1213           0 :                 if (bSign)
    1214           0 :                     fVal *= -1.0;
    1215             : 
    1216           0 :                 fVal /= fFac;
    1217             : 
    1218           0 :                 left.PutDouble( fVal );
    1219             :             }
    1220           0 :             break;
    1221             : 
    1222             : //#77448# (=2*3^2 != 18)
    1223             : 
    1224             :         default:
    1225           2 :             return left;
    1226             :         }
    1227             : 
    1228           2 :         if( USHRT_MAX != nSbxOper )
    1229             :         {
    1230             :             // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
    1231           2 :             SbxOperator eSbxOper = (SbxOperator)nSbxOper;
    1232             : 
    1233           2 :             GetToken();
    1234           2 :             if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE )
    1235             :             {
    1236           2 :                 left.PutBool( left.Compare( eSbxOper, Prim() ));
    1237             :             }
    1238             :             else
    1239             :             {
    1240           0 :                 SwSbxValue aRight( Prim() );
    1241           0 :                 aRight.MakeDouble();
    1242           0 :                 left.MakeDouble();
    1243             : 
    1244           0 :                 if( SbxDIV == eSbxOper && !aRight.GetDouble() )
    1245           0 :                     eError = CALC_ZERODIV;
    1246             :                 else
    1247           0 :                     left.Compute( eSbxOper, aRight );
    1248             :             }
    1249             :         }
    1250           0 :     }
    1251             : }
    1252             : 
    1253             : extern "C" typedef double (*pfCalc)( double );
    1254             : 
    1255           4 : SwSbxValue SwCalc::Prim()
    1256             : {
    1257           4 :     SwSbxValue nErg;
    1258             : 
    1259           4 :     pfCalc pFnc = 0;
    1260             : 
    1261           4 :     bool bChkTrig = false, bChkPow = false;
    1262             : 
    1263           4 :     switch( eCurrOper )
    1264             :     {
    1265           0 :     case CALC_SIN:  pFnc = &sin;  break;
    1266           0 :     case CALC_COS:  pFnc = &cos;  break;
    1267           0 :     case CALC_TAN:  pFnc = &tan;  break;
    1268           0 :     case CALC_ATAN: pFnc = &atan; break;
    1269           0 :     case CALC_ASIN: pFnc = &asin; bChkTrig = true; break;
    1270           0 :     case CALC_ACOS: pFnc = &acos; bChkTrig = true; break;
    1271             : 
    1272             :     case CALC_NOT:
    1273             :         {
    1274           0 :             GetToken();
    1275           0 :             nErg = Prim();
    1276           0 :             if( SbxSTRING == nErg.GetType() )
    1277             :             {
    1278           0 :                 nErg.PutBool( nErg.GetOUString().isEmpty() );
    1279             :             }
    1280           0 :             else if(SbxBOOL == nErg.GetType() )
    1281             :             {
    1282           0 :                 nErg.PutBool(!nErg.GetBool());
    1283             :             }
    1284             :             // Evaluate arguments manually so that the binary NOT below does not
    1285             :             // get called. We want a BOOLEAN NOT.
    1286           0 :             else if (nErg.IsNumeric())
    1287             :             {
    1288           0 :                 nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 );
    1289             :             }
    1290             :             else
    1291             :             {
    1292             :                 OSL_FAIL( "unexpected case. computing binary NOT" );
    1293             :                 //!! computes a binary NOT
    1294           0 :                 nErg.Compute( SbxNOT, nErg );
    1295             :             }
    1296             :         }
    1297           0 :         break;
    1298             : 
    1299             :     case CALC_NUMBER:
    1300           2 :         if( GetToken() == CALC_PHD )
    1301             :         {
    1302           0 :             double aTmp = nNumberValue.GetDouble();
    1303           0 :             aTmp *= 0.01;
    1304           0 :             nErg.PutDouble( aTmp );
    1305           0 :             GetToken();
    1306             :         }
    1307           2 :         else if( eCurrOper == CALC_NAME )
    1308             :         {
    1309           0 :             eError = CALC_SYNTAX;
    1310             :         }
    1311             :         else
    1312             :         {
    1313           2 :             nErg = nNumberValue;
    1314           2 :             bChkPow = true;
    1315             :         }
    1316           2 :         break;
    1317             : 
    1318             :     case CALC_NAME:
    1319           2 :         if( GetToken() == CALC_ASSIGN )
    1320             :         {
    1321           0 :             SwCalcExp* n = VarInsert( aVarName );
    1322           0 :             GetToken();
    1323           0 :             nErg = n->nValue = Expr();
    1324             :         }
    1325             :         else
    1326             :         {
    1327           2 :             nErg = VarLook( aVarName )->nValue;
    1328           2 :             bChkPow = true;
    1329             :         }
    1330           2 :         break;
    1331             : 
    1332             :     case CALC_MINUS:
    1333           0 :         GetToken();
    1334           0 :         nErg.PutDouble( -(Prim().GetDouble()) );
    1335           0 :         break;
    1336             : 
    1337             :     case CALC_LP:
    1338             :         {
    1339           0 :             GetToken();
    1340           0 :             nErg = Expr();
    1341           0 :             if( eCurrOper != CALC_RP )
    1342             :             {
    1343           0 :                 eError = CALC_BRACK;
    1344             :             }
    1345             :             else
    1346             :             {
    1347           0 :                 GetToken();
    1348           0 :                 bChkPow = true; // in order for =(7)^2 to work
    1349             :             }
    1350             :         }
    1351           0 :         break;
    1352             : 
    1353             :     case CALC_MEAN:
    1354             :         {
    1355           0 :             nListPor = 1;
    1356           0 :             GetToken();
    1357           0 :             nErg = Expr();
    1358           0 :             double aTmp = nErg.GetDouble();
    1359           0 :             aTmp /= nListPor;
    1360           0 :             nErg.PutDouble( aTmp );
    1361             :         }
    1362           0 :         break;
    1363             : 
    1364             :     case CALC_SQRT:
    1365             :         {
    1366           0 :             GetToken();
    1367           0 :             nErg = Prim();
    1368           0 :             if( nErg.GetDouble() < 0 )
    1369           0 :                 eError = CALC_OVERFLOW;
    1370             :             else
    1371           0 :                 nErg.PutDouble( sqrt( nErg.GetDouble() ));
    1372             :         }
    1373           0 :         break;
    1374             : 
    1375             :     case CALC_SUM:
    1376             :     case CALC_DATE:
    1377             :     case CALC_MIN:
    1378             :     case CALC_MAX:
    1379           0 :         GetToken();
    1380           0 :         nErg = Expr();
    1381           0 :         break;
    1382             : 
    1383             :     case CALC_ENDCALC:
    1384           0 :         nErg.Clear();
    1385           0 :         break;
    1386             : 
    1387             :     default:
    1388           0 :         eError = CALC_SYNTAX;
    1389           0 :         break;
    1390             :     }
    1391             : 
    1392           4 :     if( pFnc )
    1393             :     {
    1394           0 :         GetToken();
    1395           0 :         double nVal = Prim().GetDouble();
    1396           0 :         if( !bChkTrig || ( nVal > -1 && nVal < 1 ) )
    1397           0 :             nErg.PutDouble( (*pFnc)( nVal ) );
    1398             :         else
    1399           0 :             eError = CALC_OVERFLOW;
    1400             :     }
    1401             : 
    1402           4 :     if( bChkPow && eCurrOper == CALC_POW )
    1403             :     {
    1404           0 :         double dleft = nErg.GetDouble();
    1405           0 :         GetToken();
    1406           0 :         double right = Prim().GetDouble();
    1407             : 
    1408             :         double fraction, integer;
    1409           0 :         fraction = modf( right, &integer );
    1410           0 :         if( ( dleft < 0.0 && 0.0 != fraction ) ||
    1411             :             ( 0.0 == dleft && right < 0.0 ) )
    1412             :         {
    1413           0 :             eError = CALC_OVERFLOW;
    1414           0 :             nErg.Clear();
    1415             :         }
    1416             :         else
    1417             :         {
    1418           0 :             dleft = pow(dleft, right );
    1419           0 :             if( dleft == HUGE_VAL )
    1420             :             {
    1421           0 :                 eError = CALC_POWERR;
    1422           0 :                 nErg.Clear();
    1423             :             }
    1424             :             else
    1425             :             {
    1426           0 :                 nErg.PutDouble( dleft );
    1427             :             }
    1428             :         }
    1429             :     }
    1430             : 
    1431           4 :     return nErg;
    1432             : }
    1433             : 
    1434           2 : SwSbxValue  SwCalc::Expr()
    1435             : {
    1436           2 :     SwSbxValue left = Term(), right;
    1437           2 :     nLastLeft = left;
    1438           0 :     for(;;)
    1439             :     {
    1440           2 :         switch(eCurrOper)
    1441             :         {
    1442             :         case CALC_PLUS:
    1443           0 :             GetToken();
    1444           0 :             left.MakeDouble();
    1445           0 :             ( right = Term() ).MakeDouble();
    1446           0 :             left.Compute( SbxPLUS, right );
    1447           0 :             nListPor++;
    1448           0 :             break;
    1449             : 
    1450             :         case CALC_MINUS:
    1451           0 :             GetToken();
    1452           0 :             left.MakeDouble();
    1453           0 :             ( right = Term() ).MakeDouble();
    1454           0 :             left.Compute( SbxMINUS, right );
    1455           0 :             break;
    1456             : 
    1457             :         default:
    1458           2 :             return left;
    1459             :         }
    1460           2 :     }
    1461             : }
    1462             : 
    1463           0 : String SwCalc::GetColumnName(const String& rName)
    1464             : {
    1465           0 :     xub_StrLen nPos = rName.Search(DB_DELIM);
    1466           0 :     if( STRING_NOTFOUND != nPos )
    1467             :     {
    1468           0 :         nPos = rName.Search(DB_DELIM, nPos + 1);
    1469             : 
    1470           0 :         if( STRING_NOTFOUND != nPos )
    1471           0 :             return rName.Copy(nPos + 1);
    1472             :     }
    1473           0 :     return rName;
    1474             : }
    1475             : 
    1476           0 : String SwCalc::GetDBName(const String& rName)
    1477             : {
    1478           0 :     xub_StrLen nPos = rName.Search(DB_DELIM);
    1479           0 :     if( STRING_NOTFOUND != nPos )
    1480             :     {
    1481           0 :         nPos = rName.Search(DB_DELIM, nPos + 1);
    1482             : 
    1483           0 :         if( STRING_NOTFOUND != nPos )
    1484           0 :             return rName.Copy( 0, nPos );
    1485             :     }
    1486           0 :     SwDBData aData = rDoc.GetDBData();
    1487           0 :     String sRet = aData.sDataSource;
    1488           0 :     sRet += DB_DELIM;
    1489           0 :     sRet += String(aData.sCommand);
    1490           0 :     return sRet;
    1491             : }
    1492             : 
    1493             : namespace
    1494             : {
    1495           0 :     static bool lcl_Str2Double( const String& rCommand, xub_StrLen& rCommandPos,
    1496             :                                 double& rVal,
    1497             :                                 const LocaleDataWrapper* const pLclData )
    1498             :     {
    1499             :         OSL_ASSERT(pLclData);
    1500           0 :         const sal_Unicode nCurrCmdPos = rCommandPos;
    1501             :         rtl_math_ConversionStatus eStatus;
    1502             :         const sal_Unicode* pEnd;
    1503           0 :         rVal = rtl_math_uStringToDouble( rCommand.GetBuffer() + rCommandPos,
    1504           0 :                                          rCommand.GetBuffer() + rCommand.Len(),
    1505           0 :                                          pLclData->getNumDecimalSep()[0],
    1506           0 :                                          pLclData->getNumThousandSep()[0],
    1507             :                                          &eStatus,
    1508           0 :                                          &pEnd );
    1509           0 :         rCommandPos = static_cast<xub_StrLen>(pEnd - rCommand.GetBuffer());
    1510             : 
    1511             :         return rtl_math_ConversionStatus_Ok == eStatus &&
    1512           0 :                nCurrCmdPos != rCommandPos;
    1513             :     }
    1514             : }
    1515             : 
    1516           0 : bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos,
    1517             :                          double& rVal, const LocaleDataWrapper* const pLclData )
    1518             : {
    1519           0 :     const SvtSysLocale aSysLocale;
    1520             :     return lcl_Str2Double( rCommand, rCommandPos, rVal,
    1521           0 :             pLclData ? pLclData : aSysLocale.GetLocaleDataPtr() );
    1522             : }
    1523             : 
    1524           0 : bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos,
    1525             :                          double& rVal, SwDoc* const pDoc )
    1526             : {
    1527           0 :     const SvtSysLocale aSysLocale;
    1528           0 :     ::std::auto_ptr<const LocaleDataWrapper> pLclD;
    1529           0 :     if( pDoc )
    1530             :     {
    1531           0 :         LanguageType eLang = GetDocAppScriptLang( *pDoc );
    1532           0 :         if (eLang != aSysLocale.GetLanguageTag().getLanguageType())
    1533             :         {
    1534           0 :             pLclD.reset( new LocaleDataWrapper( LanguageTag( eLang )) );
    1535             :         }
    1536             :     }
    1537             : 
    1538             :     bool const bRet = lcl_Str2Double( rCommand, rCommandPos, rVal,
    1539           0 :             (pLclD.get()) ? pLclD.get() : aSysLocale.GetLocaleDataPtr() );
    1540             : 
    1541           0 :     return bRet;
    1542             : }
    1543             : 
    1544           0 : sal_Bool SwCalc::IsValidVarName( const String& rStr, String* pValidName )
    1545             : {
    1546           0 :     sal_Bool bRet = sal_False;
    1547             :     using namespace ::com::sun::star::i18n;
    1548             :     {
    1549             :         // Parse any token.
    1550           0 :         ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0,
    1551             :                                                     coStartFlags, aEmptyStr,
    1552           0 :                                                      coContFlags, aEmptyStr );
    1553             : 
    1554           0 :         if( aRes.TokenType & KParseType::IDENTNAME )
    1555             :         {
    1556           0 :             bRet = aRes.EndPos == rStr.Len();
    1557           0 :             if( pValidName )
    1558             :             {
    1559           0 :                 xub_StrLen nRealStt = (xub_StrLen)aRes.LeadingWhiteSpace;
    1560             :                 *pValidName = rStr.Copy( nRealStt,
    1561           0 :                                   static_cast<xub_StrLen>(aRes.EndPos) - nRealStt );
    1562             :             }
    1563             :         }
    1564           0 :         else if( pValidName )
    1565           0 :             pValidName->Erase();
    1566             :     }
    1567           0 :     return bRet;
    1568             : }
    1569             : 
    1570          59 : SwHash::SwHash( const String& rStr ) :
    1571             :     aStr( rStr ),
    1572          59 :     pNext( 0 )
    1573             : {
    1574          59 : }
    1575             : 
    1576         114 : SwHash::~SwHash()
    1577             : {
    1578          57 :     delete pNext;
    1579          57 : }
    1580             : 
    1581           1 : void DeleteHashTable( SwHash **ppHashTable, sal_uInt16 nCount )
    1582             : {
    1583          36 :     for ( sal_uInt16 i = 0; i < nCount; ++i )
    1584          35 :         delete *(ppHashTable+i);
    1585           1 :     delete [] ppHashTable;
    1586           1 : }
    1587             : 
    1588          56 : SwCalcExp::SwCalcExp( const String& rStr, const SwSbxValue& rVal,
    1589             :                       const SwFieldType* pType )
    1590             :     : SwHash( rStr ),
    1591             :     nValue( rVal ),
    1592          56 :     pFldType( pType )
    1593             : {
    1594          56 : }
    1595             : 
    1596         148 : SwSbxValue::~SwSbxValue()
    1597             : {
    1598         148 : }
    1599             : 
    1600           2 : sal_Bool SwSbxValue::GetBool() const
    1601             : {
    1602           4 :     return SbxSTRING == GetType() ? !GetOUString().isEmpty()
    1603           4 :                                   : 0 != SbxValue::GetBool();
    1604             : }
    1605             : 
    1606           0 : double SwSbxValue::GetDouble() const
    1607             : {
    1608             :     double nRet;
    1609           0 :     if( SbxSTRING == GetType() )
    1610             :     {
    1611           0 :         xub_StrLen nStt = 0;
    1612           0 :         SwCalc::Str2Double( GetOUString(), nStt, nRet );
    1613             :     }
    1614           0 :     else if (IsBool())
    1615             :     {
    1616           0 :         nRet = 0 != GetBool() ? 1.0 : 0.0;
    1617             :     }
    1618             :     else
    1619             :     {
    1620           0 :         nRet = SbxValue::GetDouble();
    1621             :     }
    1622           0 :     return nRet;
    1623             : }
    1624             : 
    1625           0 : SwSbxValue& SwSbxValue::MakeDouble()
    1626             : {
    1627           0 :     if( GetType() == SbxSTRING  || GetType() == SbxBOOL )
    1628           0 :         PutDouble( GetDouble() );
    1629           0 :     return *this;
    1630             : }
    1631             : 
    1632             : #ifdef STANDALONE_HASHCALC
    1633             : 
    1634             : // this is example code how to create hash values in the CTOR:
    1635             : 
    1636             : #include <stdio.h>
    1637             : void main()
    1638             : {
    1639             :     static sal_Char
    1640             :         sNType0[] = "false",    sNType1[] = "true",     sNType2[] = "pi",
    1641             :         sNType3[] = "e",        sNType4[] = "tables",   sNType5[] = "graf",
    1642             :         sNType6[] = "ole",      sNType7[] = "page",     sNType8[] = "para",
    1643             :         sNType9[] = "word",     sNType10[]= "char",
    1644             :         sNType11[] = "user_company" ,       sNType12[] = "user_firstname" ,
    1645             :         sNType13[] = "user_lastname" ,      sNType14[] = "user_initials",
    1646             :         sNType15[] = "user_street" ,        sNType16[] = "user_country" ,
    1647             :         sNType17[] = "user_zipcode" ,       sNType18[] = "user_city" ,
    1648             :         sNType19[] = "user_title" ,         sNType20[] = "user_position" ,
    1649             :         sNType21[] = "user_tel_home",       sNType22[] = "user_tel_work",
    1650             :         sNType23[] = "user_fax" ,           sNType24[] = "user_email" ,
    1651             :         sNType25[] = "user_state",          sNType26[] = "graph"
    1652             :         ;
    1653             : 
    1654             :     static const sal_Char* sNTypeTab[ 27 ] =
    1655             :     {
    1656             :         sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
    1657             :         sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
    1658             :         sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
    1659             :         sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
    1660             :         sNType24, sNType25, sNType26
    1661             :     };
    1662             : 
    1663             :     const unsigned short nTblSize = 47;
    1664             :     int aArr[ nTblSize ] = { 0 };
    1665             :     sal_Char ch;
    1666             : 
    1667             :     for( int n = 0; n < 27; ++n )
    1668             :     {
    1669             :         unsigned long ii = 0;
    1670             :         const sal_Char* pp = sNTypeTab[ n ];
    1671             : 
    1672             :         while( *pp )
    1673             :         {
    1674             :             ii = ii << 1 ^ *pp++;
    1675             :         }
    1676             :         ii %= nTblSize;
    1677             : 
    1678             :         ch = aArr[ ii ] ? 'X' : ' ';
    1679             :         aArr[ ii ] = 1;
    1680             :         printf( "%-20s -> %3d [%c]\n", sNTypeTab[ n ], ii, ch );
    1681             :     }
    1682             : }
    1683             : 
    1684             : #endif
    1685             : 
    1686             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10