LCOV - code coverage report
Current view: top level - sw/source/core/bastyp - calc.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 272 621 43.8 %
Date: 2015-06-13 12:38:46 Functions: 28 39 71.8 %
Legend: Lines: hit not hit

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