LCOV - code coverage report
Current view: top level - sw/source/core/bastyp - calc.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 265 621 42.7 %
Date: 2014-11-03 Functions: 27 39 69.2 %
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         240 : static int SAL_CALL OperatorCompare( const void *pFirst, const void *pSecond)
     151             : {
     152         240 :     int nRet = 0;
     153         240 :     if( CALC_NAME == ((_CalcOp*)pFirst)->eOp )
     154             :     {
     155         240 :         if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
     156             :             nRet = ((_CalcOp*)pFirst)->pUName->compareTo(
     157           0 :                    *((_CalcOp*)pSecond)->pUName );
     158             :         else
     159             :             nRet = ((_CalcOp*)pFirst)->pUName->compareToAscii(
     160         240 :                    ((_CalcOp*)pSecond)->pName );
     161             :     }
     162             :     else
     163             :     {
     164           0 :         if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
     165             :             nRet = -1 * ((_CalcOp*)pSecond)->pUName->compareToAscii(
     166           0 :                         ((_CalcOp*)pFirst)->pName );
     167             :         else
     168             :             nRet = strcmp( ((_CalcOp*)pFirst)->pName,
     169           0 :                            ((_CalcOp*)pSecond)->pName );
     170             :     }
     171         240 :     return nRet;
     172             : }
     173             : }// extern "C"
     174             : 
     175          48 : _CalcOp* FindOperator( const OUString& rSrch )
     176             : {
     177             :     _CalcOp aSrch;
     178          48 :     aSrch.pUName = &rSrch;
     179          48 :     aSrch.eOp = CALC_NAME;
     180             : 
     181             :     return (_CalcOp*)bsearch( (void*) &aSrch,
     182             :                               (void*) aOpTable,
     183             :                               sizeof( aOpTable ) / sizeof( _CalcOp ),
     184             :                               sizeof( _CalcOp ),
     185          48 :                               OperatorCompare );
     186             : }
     187             : 
     188         214 : SwHash* Find( const OUString& rStr, SwHash** ppTable,
     189             :               sal_uInt16 nTblSize, sal_uInt16* pPos )
     190             : {
     191         214 :     sal_uLong ii = 0;
     192        2756 :     for( sal_Int32 n = 0; n < rStr.getLength(); ++n )
     193             :     {
     194        2542 :         ii = ii << 1 ^ rStr[n];
     195             :     }
     196         214 :     ii %= nTblSize;
     197             : 
     198         214 :     if( pPos )
     199         212 :         *pPos = (sal_uInt16)ii;
     200             : 
     201         264 :     for( SwHash* pEntry = *(ppTable+ii); pEntry; pEntry = pEntry->pNext )
     202             :     {
     203          64 :         if( rStr == pEntry->aStr )
     204             :         {
     205          14 :             return pEntry;
     206             :         }
     207             :     }
     208         200 :     return 0;
     209             : }
     210             : 
     211         484 : inline LanguageType GetDocAppScriptLang( SwDoc& rDoc )
     212             : {
     213             :     return ((SvxLanguageItem&)rDoc.GetDefault(
     214             :                GetWhichOfScript( RES_CHRATR_LANGUAGE,
     215         484 :                                  GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() ))
     216         484 :             )).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          42 : SwCalc::SwCalc( SwDoc& rD )
     233             :     : aErrExpr( OUString(), SwSbxValue(), 0 )
     234             :     , nCommandPos(0)
     235             :     , rDoc( rD )
     236          42 :     , pLclData( m_aSysLocale.GetLocaleDataPtr() )
     237          42 :     , pCharClass( &GetAppCharClass() )
     238             :     , nListPor( 0 )
     239             :     , eCurrOper( CALC_NAME )
     240             :     , eCurrListOper( CALC_NAME )
     241         126 :     , eError( CALC_NOERR )
     242             : {
     243          42 :     aErrExpr.aStr = "~C_ERR~";
     244          42 :     memset( VarTable, 0, sizeof(VarTable) );
     245          42 :     LanguageType eLang = GetDocAppScriptLang( rDoc );
     246             : 
     247          68 :     if( eLang != pLclData->getLanguageTag().getLanguageType() ||
     248          26 :         eLang != pCharClass->getLanguageTag().getLanguageType() )
     249             :     {
     250          16 :         LanguageTag aLanguageTag( eLang );
     251          16 :         pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), aLanguageTag );
     252          16 :         pLclData = new LocaleDataWrapper( aLanguageTag );
     253             :     }
     254             : 
     255          42 :     sCurrSym = comphelper::string::strip(pLclData->getCurrSymbol(), ' ');
     256          42 :     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 sal_uInt16 const aAdrToken[ 12 ] =
     307             :     {
     308             :         USER_OPT_COMPANY, USER_OPT_STREET, USER_OPT_COUNTRY, USER_OPT_ZIP,
     309             :         USER_OPT_CITY, USER_OPT_TITLE, USER_OPT_POSITION, USER_OPT_TELEPHONEWORK,
     310             :         USER_OPT_TELEPHONEHOME, USER_OPT_FAX, USER_OPT_EMAIL, USER_OPT_STATE
     311             :     };
     312             : 
     313             :     static sal_uInt16 SwDocStat::* const aDocStat1[ 3 ] =
     314             :     {
     315             :         &SwDocStat::nTbl, &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          42 :     const SwDocStat& rDocStat = rDoc.getIDocumentStatistics().GetDocStat();
     328             : 
     329          42 :     SwSbxValue nVal;
     330          84 :     OUString sTmpStr;
     331             :     sal_uInt16 n;
     332             : 
     333        1092 :     for( n = 0; n < 25; ++n )
     334             :     {
     335        1050 :         sTmpStr = OUString::createFromAscii(sNTypeTab[n]);
     336        1050 :         VarTable[ aHashValue[ n ] ] = new SwCalcExp( sTmpStr, nVal, 0 );
     337             :     }
     338             : 
     339          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 0 ] ])->nValue.PutBool( false );
     340          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 1 ] ])->nValue.PutBool( true );
     341          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 2 ] ])->nValue.PutDouble( F_PI );
     342          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 3 ] ])->nValue.PutDouble( 2.7182818284590452354 );
     343             : 
     344         168 :     for( n = 0; n < 3; ++n )
     345         126 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 4 ] ])->nValue.PutLong( rDocStat.*aDocStat1[ n ]  );
     346         210 :     for( n = 0; n < 4; ++n )
     347         168 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 7 ] ])->nValue.PutLong( rDocStat.*aDocStat2[ n ]  );
     348             : 
     349          42 :     SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
     350             : 
     351          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 11 ] ])->nValue.PutString( rUserOptions.GetFirstName() );
     352          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 12 ] ])->nValue.PutString( rUserOptions.GetLastName() );
     353          42 :     ((SwCalcExp*)VarTable[ aHashValue[ 13 ] ])->nValue.PutString( rUserOptions.GetID() );
     354             : 
     355         504 :     for( n = 0; n < 11; ++n )
     356         924 :         ((SwCalcExp*)VarTable[ aHashValue[ n + 14 ] ])->nValue.PutString(
     357        1386 :                                         rUserOptions.GetToken( aAdrToken[ n ] ));
     358             : 
     359          42 :     nVal.PutString( rUserOptions.GetToken( aAdrToken[ 11 ] ));
     360          42 :     sTmpStr = OUString::createFromAscii(sNTypeTab[25]);
     361          84 :     VarTable[ aHashValue[ 25 ] ]->pNext = new SwCalcExp( sTmpStr, nVal, 0 );
     362             : 
     363          42 : } // SwCalc::SwCalc
     364             : 
     365          84 : SwCalc::~SwCalc()
     366             : {
     367        2016 :     for( sal_uInt16 n = 0; n < TBLSZ; ++n )
     368        1974 :         delete VarTable[n];
     369             : 
     370          42 :     if( pLclData != m_aSysLocale.GetLocaleDataPtr() )
     371          16 :         delete pLclData;
     372          42 :     if( pCharClass != &GetAppCharClass() )
     373          16 :         delete pCharClass;
     374          42 : }
     375             : 
     376          38 : SwSbxValue SwCalc::Calculate( const OUString& rStr )
     377             : {
     378          38 :     eError = CALC_NOERR;
     379          38 :     SwSbxValue nResult;
     380             : 
     381          38 :     if( rStr.isEmpty() )
     382           0 :         return nResult;
     383             : 
     384          38 :     nListPor = 0;
     385          38 :     eCurrListOper = CALC_PLUS; // default: sum
     386             : 
     387          38 :     sCommand = rStr;
     388          38 :     nCommandPos = 0;
     389             : 
     390         114 :     while( (eCurrOper = GetToken()) != CALC_ENDCALC && eError == CALC_NOERR )
     391          38 :         nResult = Expr();
     392             : 
     393          38 :     if( eError )
     394           0 :         nResult.PutDouble( DBL_MAX );
     395             : 
     396          38 :     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 <sal_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 :     sal_uInt16  nDec = 15;
     434             :     OUString aRetStr( ::rtl::math::doubleToUString(
     435             :                         nValue,
     436             :                         rtl_math_StringFormat_Automatic,
     437             :                         nDec,
     438           0 :                         pLclData->getNumDecimalSep()[0],
     439           0 :                         true ));
     440           0 :     return aRetStr;
     441             : }
     442             : 
     443           4 : SwCalcExp* SwCalc::VarInsert( const OUString &rStr )
     444             : {
     445           4 :     OUString aStr = pCharClass->lowercase( rStr );
     446           4 :     return VarLook( aStr, 1 );
     447             : }
     448             : 
     449          38 : SwCalcExp* SwCalc::VarLook( const OUString& rStr, sal_uInt16 ins )
     450             : {
     451          38 :     aErrExpr.nValue.SetVoidValue(false);
     452             : 
     453          38 :     sal_uInt16 ii = 0;
     454          38 :     OUString aStr = pCharClass->lowercase( rStr );
     455             : 
     456          38 :     SwHash* pFnd = Find( aStr, VarTable, TBLSZ, &ii );
     457             : 
     458          38 :     if( !pFnd )
     459             :     {
     460             :         // then check doc
     461          30 :         SwHash** ppDocTbl = rDoc.getIDocumentFieldsAccess().GetUpdtFlds().GetFldTypeTable();
     462          30 :         for( SwHash* pEntry = *(ppDocTbl+ii); pEntry; pEntry = pEntry->pNext )
     463             :         {
     464          10 :             if( aStr == pEntry->aStr )
     465             :             {
     466             :                 // then insert here
     467             :                 pFnd = new SwCalcExp( aStr, SwSbxValue(),
     468          10 :                                     ((SwCalcFldType*)pEntry)->pFldType );
     469          10 :                 pFnd->pNext = *(VarTable+ii);
     470          10 :                 *(VarTable+ii) = pFnd;
     471          10 :                 break;
     472             :             }
     473             :         }
     474             :     }
     475             : 
     476          38 :     if( pFnd )
     477             :     {
     478          18 :         SwCalcExp* pFndExp = (SwCalcExp*)pFnd;
     479             : 
     480          18 :         if( pFndExp->pFldType && pFndExp->pFldType->Which() == RES_USERFLD )
     481             :         {
     482           4 :             SwUserFieldType* pUFld = (SwUserFieldType*)pFndExp->pFldType;
     483           4 :             if( nsSwGetSetExpType::GSE_STRING & pUFld->GetType() )
     484             :             {
     485           4 :                 pFndExp->nValue.PutString( pUFld->GetContent() );
     486             :             }
     487           0 :             else if( !pUFld->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( pUFld->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( pUFld->GetValue() );
     510             :             }
     511             :         }
     512          18 :         return pFndExp;
     513             :     }
     514             : 
     515             :     // At this point the "real" case variable has to be used
     516          40 :     OUString const sTmpName( ::ReplacePoint(rStr) );
     517             : 
     518          20 :     if( !ins )
     519             :     {
     520             : #if HAVE_FEATURE_DBCONNECTIVITY
     521          20 :         SwDBManager *pMgr = rDoc.GetDBManager();
     522             : 
     523          20 :         OUString sDBName(GetDBName( sTmpName ));
     524          40 :         OUString sSourceName(sDBName.getToken(0, DB_DELIM));
     525          40 :         OUString sTableName(sDBName.getToken(0, ';').getToken(1, DB_DELIM));
     526          20 :         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 = ((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          20 :             aErrExpr.nValue.SetVoidValue(true);
     570             :         }
     571             :         // NEVER save!
     572          40 :         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 :     OUString sColumnName( GetColumnName( sTmpName ));
     580             :     OSL_ENSURE( !sColumnName.isEmpty(), "Missing DB column name" );
     581           0 :     if( sColumnName.equalsIgnoreAsciiCase(
     582           0 :                             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          38 :     return pNewExp;
     603             : }
     604             : 
     605          28 : void SwCalc::VarChange( const OUString& rStr, double nValue )
     606             : {
     607          28 :     SwSbxValue aVal( nValue );
     608          28 :     VarChange( rStr, aVal );
     609          28 : }
     610             : 
     611          32 : void SwCalc::VarChange( const OUString& rStr, const SwSbxValue& rValue )
     612             : {
     613          32 :     OUString aStr = pCharClass->lowercase( rStr );
     614             : 
     615          32 :     sal_uInt16 nPos = 0;
     616          32 :     SwCalcExp* pFnd = (SwCalcExp*)Find( aStr, VarTable, TBLSZ, &nPos );
     617             : 
     618          32 :     if( !pFnd )
     619             :     {
     620          32 :         pFnd = new SwCalcExp( aStr, SwSbxValue( rValue ), 0 );
     621          32 :         pFnd->pNext = VarTable[ nPos ];
     622          32 :         VarTable[ nPos ] = pFnd;
     623             :     }
     624             :     else
     625             :     {
     626           0 :         pFnd->nValue = rValue;
     627          32 :     }
     628          32 : }
     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         150 : 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         150 :     if( nCommandPos >= sCommand.getLength() )
     657          76 :         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          74 :                                                       coContFlags, OUString());
     665             : 
     666          74 :         bool bSetError = true;
     667          74 :         sal_Int32 nRealStt = nCommandPos + aRes.LeadingWhiteSpace;
     668          74 :         if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) )
     669             :         {
     670          10 :             nNumberValue.PutDouble( aRes.Value );
     671          10 :             eCurrOper = CALC_NUMBER;
     672          10 :             bSetError = false;
     673             :         }
     674          64 :         else if( aRes.TokenType & KParseType::IDENTNAME )
     675             :         {
     676             :             OUString aName( sCommand.copy( nRealStt,
     677          48 :                             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          86 :             OUString sLowerCaseName = pCharClass->lowercase( aName );
     682             :             // catch currency symbol
     683          48 :             if( sLowerCaseName == sCurrSym )
     684             :             {
     685           0 :                 nCommandPos = aRes.EndPos;
     686           0 :                 return GetToken(); // call again
     687             :             }
     688             : 
     689             :             // catch operators
     690          48 :             _CalcOp* pFnd = ::FindOperator( sLowerCaseName );
     691          48 :             if( pFnd )
     692             :             {
     693          10 :                 switch( ( eCurrOper = ((_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          10 :                     break;
     710             :                 }
     711          10 :                 nCommandPos = aRes.EndPos;
     712          10 :                 return eCurrOper;
     713             :             }
     714          38 :             aVarName = aName;
     715          38 :             eCurrOper = CALC_NAME;
     716          76 :             bSetError = false;
     717             :         }
     718          16 :         else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING )
     719             :         {
     720           8 :             nNumberValue.PutString( aRes.DequotedNameOrString );
     721           8 :             eCurrOper = CALC_NUMBER;
     722           8 :             bSetError = false;
     723             :         }
     724           8 :         else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR )
     725             :         {
     726             :             OUString aName( sCommand.copy( nRealStt,
     727           8 :                               aRes.EndPos - nRealStt ));
     728           8 :             if( 1 == aName.getLength() )
     729             :             {
     730           8 :                 bSetError = false;
     731           8 :                 sal_Unicode ch = aName[0];
     732           8 :                 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           0 :                     eCurrOper = SwCalcOper(ch);
     754           0 :                     break;
     755             : 
     756             :                 case '=':
     757             :                 case '!':
     758             :                     {
     759             :                         SwCalcOper eTmp2;
     760           8 :                         if( '=' == ch )
     761           8 :                             eCurrOper = SwCalcOper('='), eTmp2 = CALC_EQ;
     762             :                         else
     763           0 :                             eCurrOper = CALC_NOT, eTmp2 = CALC_NEQ;
     764             : 
     765          16 :                         if( aRes.EndPos < sCommand.getLength() &&
     766           8 :                             '=' == sCommand[aRes.EndPos] )
     767             :                         {
     768           4 :                             eCurrOper = eTmp2;
     769           4 :                             ++aRes.EndPos;
     770             :                         }
     771             :                     }
     772           8 :                     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 = "";
     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           8 :             }
     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          64 :         if( bSetError )
     854             :         {
     855           0 :             eError = CALC_SYNTAX;
     856           0 :             eCurrOper = CALC_PRINT;
     857             :         }
     858          64 :         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 = ((_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          64 :     return eCurrOper;
    1077             : }
    1078             : 
    1079          42 : SwSbxValue SwCalc::Term()
    1080             : {
    1081          42 :     SwSbxValue left( Prim() );
    1082          42 :     nLastLeft = left;
    1083             :     for(;;)
    1084             :     {
    1085          56 :         sal_uInt16 nSbxOper = USHRT_MAX;
    1086             : 
    1087          56 :         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          10 :         case CALC_EQ:   nSbxOper = SbxEQ;   break;
    1113           4 :         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             :                 sal_uInt16 i;
    1175           0 :                 if( nDec >= 0)
    1176             :                 {
    1177           0 :                     for (i = 0; i < (sal_uInt16) nDec; ++i )
    1178           0 :                         fFac *= 10.0;
    1179             :                 }
    1180             :                 else
    1181             :                 {
    1182           0 :                     for (i = 0; i < (sal_uInt16) -nDec; ++i )
    1183           0 :                         fFac /= 10.0;
    1184             :                 }
    1185             : 
    1186           0 :                 fVal *= fFac;
    1187             :                 bool bSign;
    1188           0 :                 if (fVal < 0.0)
    1189             :                 {
    1190           0 :                     fVal *= -1.0;
    1191           0 :                     bSign = true;
    1192             :                 }
    1193             :                 else
    1194             :                 {
    1195           0 :                     bSign = false;
    1196             :                 }
    1197             : 
    1198             :                 // rounding
    1199           0 :                 double fNum = fVal; // find the exponent
    1200           0 :                 int nExp = 0;
    1201           0 :                 if( fNum > 0 )
    1202             :                 {
    1203           0 :                     while( fNum < 1.0 )
    1204           0 :                         fNum *= 10.0, --nExp;
    1205           0 :                     while( fNum >= 10.0 )
    1206           0 :                         fNum /= 10.0, ++nExp;
    1207             :                 }
    1208           0 :                 nExp = 15 - nExp;
    1209           0 :                 if( nExp > 15 )
    1210           0 :                     nExp = 15;
    1211           0 :                 else if( nExp <= 1 )
    1212           0 :                     nExp = 0;
    1213           0 :                 fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] );
    1214             : 
    1215           0 :                 if (bSign)
    1216           0 :                     fVal *= -1.0;
    1217             : 
    1218           0 :                 fVal /= fFac;
    1219             : 
    1220           0 :                 left.PutDouble( fVal );
    1221             :             }
    1222           0 :             break;
    1223             : 
    1224             : //#77448# (=2*3^2 != 18)
    1225             : 
    1226             :         default:
    1227          42 :             return left;
    1228             :         }
    1229             : 
    1230          14 :         if( USHRT_MAX != nSbxOper )
    1231             :         {
    1232             :             // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
    1233          14 :             SbxOperator eSbxOper = (SbxOperator)nSbxOper;
    1234             : 
    1235          14 :             GetToken();
    1236          14 :             if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE )
    1237             :             {
    1238          14 :                 left.PutBool( left.Compare( eSbxOper, Prim() ));
    1239             :             }
    1240             :             else
    1241             :             {
    1242           0 :                 SwSbxValue aRight( Prim() );
    1243           0 :                 aRight.MakeDouble();
    1244           0 :                 left.MakeDouble();
    1245             : 
    1246           0 :                 if( SbxDIV == eSbxOper && !aRight.GetDouble() )
    1247           0 :                     eError = CALC_ZERODIV;
    1248             :                 else
    1249           0 :                     left.Compute( eSbxOper, aRight );
    1250             :             }
    1251             :         }
    1252          14 :     }
    1253             : }
    1254             : 
    1255             : extern "C" typedef double (*pfCalc)( double );
    1256             : 
    1257          56 : SwSbxValue SwCalc::Prim()
    1258             : {
    1259          56 :     SwSbxValue nErg;
    1260             : 
    1261          56 :     pfCalc pFnc = 0;
    1262             : 
    1263          56 :     bool bChkTrig = false, bChkPow = false;
    1264             : 
    1265          56 :     switch( eCurrOper )
    1266             :     {
    1267           0 :     case CALC_SIN:  pFnc = &sin;  break;
    1268           0 :     case CALC_COS:  pFnc = &cos;  break;
    1269           0 :     case CALC_TAN:  pFnc = &tan;  break;
    1270           0 :     case CALC_ATAN: pFnc = &atan; break;
    1271           0 :     case CALC_ASIN: pFnc = &asin; bChkTrig = true; break;
    1272           0 :     case CALC_ACOS: pFnc = &acos; bChkTrig = true; break;
    1273             : 
    1274             :     case CALC_NOT:
    1275             :         {
    1276           0 :             GetToken();
    1277           0 :             nErg = Prim();
    1278           0 :             if( SbxSTRING == nErg.GetType() )
    1279             :             {
    1280           0 :                 nErg.PutBool( nErg.GetOUString().isEmpty() );
    1281             :             }
    1282           0 :             else if(SbxBOOL == nErg.GetType() )
    1283             :             {
    1284           0 :                 nErg.PutBool(!nErg.GetBool());
    1285             :             }
    1286             :             // Evaluate arguments manually so that the binary NOT below does not
    1287             :             // get called. We want a BOOLEAN NOT.
    1288           0 :             else if (nErg.IsNumeric())
    1289             :             {
    1290           0 :                 nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 );
    1291             :             }
    1292             :             else
    1293             :             {
    1294             :                 OSL_FAIL( "unexpected case. computing binary NOT" );
    1295             :                 //!! computes a binary NOT
    1296           0 :                 nErg.Compute( SbxNOT, nErg );
    1297             :             }
    1298             :         }
    1299           0 :         break;
    1300             : 
    1301             :     case CALC_NUMBER:
    1302          18 :         if( GetToken() == CALC_PHD )
    1303             :         {
    1304           0 :             double aTmp = nNumberValue.GetDouble();
    1305           0 :             aTmp *= 0.01;
    1306           0 :             nErg.PutDouble( aTmp );
    1307           0 :             GetToken();
    1308             :         }
    1309          18 :         else if( eCurrOper == CALC_NAME )
    1310             :         {
    1311           0 :             eError = CALC_SYNTAX;
    1312             :         }
    1313             :         else
    1314             :         {
    1315          18 :             nErg = nNumberValue;
    1316          18 :             bChkPow = true;
    1317             :         }
    1318          18 :         break;
    1319             : 
    1320             :     case CALC_NAME:
    1321          38 :         if( GetToken() == CALC_ASSIGN )
    1322             :         {
    1323           4 :             SwCalcExp* n = VarInsert( aVarName );
    1324           4 :             GetToken();
    1325           4 :             nErg = n->nValue = Expr();
    1326             :         }
    1327             :         else
    1328             :         {
    1329          34 :             nErg = VarLook( aVarName )->nValue;
    1330          34 :             bChkPow = true;
    1331             :         }
    1332          38 :         break;
    1333             : 
    1334             :     case CALC_MINUS:
    1335           0 :         GetToken();
    1336           0 :         nErg.PutDouble( -(Prim().GetDouble()) );
    1337           0 :         break;
    1338             : 
    1339             :     case CALC_LP:
    1340             :         {
    1341           0 :             GetToken();
    1342           0 :             nErg = Expr();
    1343           0 :             if( eCurrOper != CALC_RP )
    1344             :             {
    1345           0 :                 eError = CALC_BRACK;
    1346             :             }
    1347             :             else
    1348             :             {
    1349           0 :                 GetToken();
    1350           0 :                 bChkPow = true; // in order for =(7)^2 to work
    1351             :             }
    1352             :         }
    1353           0 :         break;
    1354             : 
    1355             :     case CALC_MEAN:
    1356             :         {
    1357           0 :             nListPor = 1;
    1358           0 :             GetToken();
    1359           0 :             nErg = Expr();
    1360           0 :             double aTmp = nErg.GetDouble();
    1361           0 :             aTmp /= nListPor;
    1362           0 :             nErg.PutDouble( aTmp );
    1363             :         }
    1364           0 :         break;
    1365             : 
    1366             :     case CALC_SQRT:
    1367             :         {
    1368           0 :             GetToken();
    1369           0 :             nErg = Prim();
    1370           0 :             if( nErg.GetDouble() < 0 )
    1371           0 :                 eError = CALC_OVERFLOW;
    1372             :             else
    1373           0 :                 nErg.PutDouble( sqrt( nErg.GetDouble() ));
    1374             :         }
    1375           0 :         break;
    1376             : 
    1377             :     case CALC_SUM:
    1378             :     case CALC_DATE:
    1379             :     case CALC_MIN:
    1380             :     case CALC_MAX:
    1381           0 :         GetToken();
    1382           0 :         nErg = Expr();
    1383           0 :         break;
    1384             : 
    1385             :     case CALC_ENDCALC:
    1386           0 :         nErg.Clear();
    1387           0 :         break;
    1388             : 
    1389             :     default:
    1390           0 :         eError = CALC_SYNTAX;
    1391           0 :         break;
    1392             :     }
    1393             : 
    1394          56 :     if( pFnc )
    1395             :     {
    1396           0 :         GetToken();
    1397           0 :         double nVal = Prim().GetDouble();
    1398           0 :         if( !bChkTrig || ( nVal > -1 && nVal < 1 ) )
    1399           0 :             nErg.PutDouble( (*pFnc)( nVal ) );
    1400             :         else
    1401           0 :             eError = CALC_OVERFLOW;
    1402             :     }
    1403             : 
    1404          56 :     if( bChkPow && eCurrOper == CALC_POW )
    1405             :     {
    1406           0 :         double dleft = nErg.GetDouble();
    1407           0 :         GetToken();
    1408           0 :         double right = Prim().GetDouble();
    1409             : 
    1410             :         double fraction, integer;
    1411           0 :         fraction = modf( right, &integer );
    1412           0 :         if( ( dleft < 0.0 && 0.0 != fraction ) ||
    1413           0 :             ( 0.0 == dleft && right < 0.0 ) )
    1414             :         {
    1415           0 :             eError = CALC_OVERFLOW;
    1416           0 :             nErg.Clear();
    1417             :         }
    1418             :         else
    1419             :         {
    1420           0 :             dleft = pow(dleft, right );
    1421           0 :             if( dleft == HUGE_VAL )
    1422             :             {
    1423           0 :                 eError = CALC_POWERR;
    1424           0 :                 nErg.Clear();
    1425             :             }
    1426             :             else
    1427             :             {
    1428           0 :                 nErg.PutDouble( dleft );
    1429             :             }
    1430             :         }
    1431             :     }
    1432             : 
    1433          56 :     return nErg;
    1434             : }
    1435             : 
    1436          42 : SwSbxValue  SwCalc::Expr()
    1437             : {
    1438          84 :     SwSbxValue left = Term(), right;
    1439          42 :     nLastLeft = left;
    1440             :     for(;;)
    1441             :     {
    1442          42 :         switch(eCurrOper)
    1443             :         {
    1444             :         case CALC_PLUS:
    1445           0 :             GetToken();
    1446           0 :             left.MakeDouble();
    1447           0 :             ( right = Term() ).MakeDouble();
    1448           0 :             left.Compute( SbxPLUS, right );
    1449           0 :             nListPor++;
    1450           0 :             break;
    1451             : 
    1452             :         case CALC_MINUS:
    1453           0 :             GetToken();
    1454           0 :             left.MakeDouble();
    1455           0 :             ( right = Term() ).MakeDouble();
    1456           0 :             left.Compute( SbxMINUS, right );
    1457           0 :             break;
    1458             : 
    1459             :         default:
    1460          84 :             return left;
    1461             :         }
    1462             :     }
    1463             : }
    1464             : 
    1465           0 : OUString SwCalc::GetColumnName(const OUString& rName)
    1466             : {
    1467           0 :     sal_Int32 nPos = rName.indexOf(DB_DELIM);
    1468           0 :     if( -1 != nPos )
    1469             :     {
    1470           0 :         nPos = rName.indexOf(DB_DELIM, nPos + 1);
    1471             : 
    1472           0 :         if( -1 != nPos )
    1473           0 :             return rName.copy(nPos + 1);
    1474             :     }
    1475           0 :     return rName;
    1476             : }
    1477             : 
    1478          20 : OUString SwCalc::GetDBName(const OUString& rName)
    1479             : {
    1480          20 :     sal_Int32 nPos = rName.indexOf(DB_DELIM);
    1481          20 :     if( -1 != nPos )
    1482             :     {
    1483           0 :         nPos = rName.indexOf(DB_DELIM, nPos + 1);
    1484             : 
    1485           0 :         if( -1 != nPos )
    1486           0 :             return rName.copy( 0, nPos );
    1487             :     }
    1488          20 :     SwDBData aData = rDoc.GetDBData();
    1489          40 :     OUString sRet = aData.sDataSource;
    1490          20 :     sRet += OUString(DB_DELIM);
    1491          20 :     sRet += aData.sCommand;
    1492          40 :     return sRet;
    1493             : }
    1494             : 
    1495             : namespace
    1496             : {
    1497         442 :     static bool lcl_Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
    1498             :                                 double& rVal,
    1499             :                                 const LocaleDataWrapper* const pLclData )
    1500             :     {
    1501             :         OSL_ASSERT(pLclData);
    1502         442 :         const sal_Unicode nCurrCmdPos = rCommandPos;
    1503             :         rtl_math_ConversionStatus eStatus;
    1504             :         const sal_Unicode* pEnd;
    1505         442 :         rVal = rtl_math_uStringToDouble( rCommand.getStr() + rCommandPos,
    1506         442 :                                          rCommand.getStr() + rCommand.getLength(),
    1507         442 :                                          pLclData->getNumDecimalSep()[0],
    1508         442 :                                          pLclData->getNumThousandSep()[0],
    1509             :                                          &eStatus,
    1510        1768 :                                          &pEnd );
    1511         442 :         rCommandPos = static_cast<sal_Int32>(pEnd - rCommand.getStr());
    1512             : 
    1513         884 :         return rtl_math_ConversionStatus_Ok == eStatus &&
    1514         884 :                nCurrCmdPos != rCommandPos;
    1515             :     }
    1516             : }
    1517             : 
    1518           0 : bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
    1519             :                          double& rVal, const LocaleDataWrapper* const pLclData )
    1520             : {
    1521           0 :     const SvtSysLocale aSysLocale;
    1522             :     return lcl_Str2Double( rCommand, rCommandPos, rVal,
    1523           0 :             pLclData ? pLclData : aSysLocale.GetLocaleDataPtr() );
    1524             : }
    1525             : 
    1526         442 : bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
    1527             :                          double& rVal, SwDoc* const pDoc )
    1528             : {
    1529         442 :     const SvtSysLocale aSysLocale;
    1530         884 :     boost::scoped_ptr<const LocaleDataWrapper> pLclD;
    1531         442 :     if( pDoc )
    1532             :     {
    1533         442 :         LanguageType eLang = GetDocAppScriptLang( *pDoc );
    1534         442 :         if (eLang != aSysLocale.GetLanguageTag().getLanguageType())
    1535             :         {
    1536         224 :             pLclD.reset( new LocaleDataWrapper( LanguageTag( eLang )) );
    1537             :         }
    1538             :     }
    1539             : 
    1540             :     bool const bRet = lcl_Str2Double( rCommand, rCommandPos, rVal,
    1541         442 :             (pLclD.get()) ? pLclD.get() : aSysLocale.GetLocaleDataPtr() );
    1542             : 
    1543         884 :     return bRet;
    1544             : }
    1545             : 
    1546           0 : bool SwCalc::IsValidVarName( const OUString& rStr, OUString* pValidName )
    1547             : {
    1548           0 :     bool bRet = false;
    1549             :     using namespace ::com::sun::star::i18n;
    1550             :     {
    1551             :         // Parse any token.
    1552           0 :         ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0,
    1553             :                                                     coStartFlags, OUString(),
    1554           0 :                                                      coContFlags, OUString() );
    1555             : 
    1556           0 :         if( aRes.TokenType & KParseType::IDENTNAME )
    1557             :         {
    1558           0 :             bRet = aRes.EndPos == rStr.getLength();
    1559           0 :             if( pValidName )
    1560             :             {
    1561           0 :                 *pValidName = rStr.copy( aRes.LeadingWhiteSpace,
    1562           0 :                                          aRes.EndPos - aRes.LeadingWhiteSpace );
    1563             :             }
    1564             :         }
    1565           0 :         else if( pValidName )
    1566           0 :             *pValidName = OUString();
    1567             :     }
    1568           0 :     return bRet;
    1569             : }
    1570             : 
    1571        1312 : SwHash::SwHash(const OUString& rStr)
    1572             :     : aStr(rStr)
    1573        1312 :     , pNext(0)
    1574             : {
    1575        1312 : }
    1576             : 
    1577        2624 : SwHash::~SwHash()
    1578             : {
    1579        1312 :     delete pNext;
    1580        1312 : }
    1581             : 
    1582          22 : void DeleteHashTable( SwHash **ppHashTable, sal_uInt16 nCount )
    1583             : {
    1584         848 :     for ( sal_uInt16 i = 0; i < nCount; ++i )
    1585         826 :         delete *(ppHashTable+i);
    1586          22 :     delete [] ppHashTable;
    1587          22 : }
    1588             : 
    1589        1176 : SwCalcExp::SwCalcExp(const OUString& rStr, const SwSbxValue& rVal,
    1590             :                       const SwFieldType* pType)
    1591             :     : SwHash(rStr)
    1592             :     , nValue(rVal)
    1593        1176 :     , pFldType(pType)
    1594             : {
    1595        1176 : }
    1596             : 
    1597        1554 : SwSbxValue::~SwSbxValue()
    1598             : {
    1599        1554 : }
    1600             : 
    1601          28 : bool SwSbxValue::GetBool() const
    1602             : {
    1603          56 :     return SbxSTRING == GetType() ? !GetOUString().isEmpty()
    1604          84 :                                   : SbxValue::GetBool();
    1605             : }
    1606             : 
    1607           4 : double SwSbxValue::GetDouble() const
    1608             : {
    1609             :     double nRet;
    1610           4 :     if( SbxSTRING == GetType() )
    1611             :     {
    1612           0 :         sal_Int32 nStt = 0;
    1613           0 :         SwCalc::Str2Double( GetOUString(), nStt, nRet );
    1614             :     }
    1615           4 :     else if (IsBool())
    1616             :     {
    1617           0 :         nRet = GetBool() ? 1.0 : 0.0;
    1618             :     }
    1619             :     else
    1620             :     {
    1621           4 :         nRet = SbxValue::GetDouble();
    1622             :     }
    1623           4 :     return nRet;
    1624             : }
    1625             : 
    1626           0 : SwSbxValue& SwSbxValue::MakeDouble()
    1627             : {
    1628           0 :     if( GetType() == SbxSTRING  || GetType() == SbxBOOL )
    1629           0 :         PutDouble( GetDouble() );
    1630           0 :     return *this;
    1631         270 : }
    1632             : 
    1633             : #ifdef STANDALONE_HASHCALC
    1634             : 
    1635             : // this is example code how to create hash values in the CTOR:
    1636             : 
    1637             : #include <stdio.h>
    1638             : void main()
    1639             : {
    1640             :     static sal_Char
    1641             :         sNType0[] = "false",    sNType1[] = "true",     sNType2[] = "pi",
    1642             :         sNType3[] = "e",        sNType4[] = "tables",   sNType5[] = "graf",
    1643             :         sNType6[] = "ole",      sNType7[] = "page",     sNType8[] = "para",
    1644             :         sNType9[] = "word",     sNType10[]= "char",
    1645             :         sNType11[] = "user_company" ,       sNType12[] = "user_firstname" ,
    1646             :         sNType13[] = "user_lastname" ,      sNType14[] = "user_initials",
    1647             :         sNType15[] = "user_street" ,        sNType16[] = "user_country" ,
    1648             :         sNType17[] = "user_zipcode" ,       sNType18[] = "user_city" ,
    1649             :         sNType19[] = "user_title" ,         sNType20[] = "user_position" ,
    1650             :         sNType21[] = "user_tel_home",       sNType22[] = "user_tel_work",
    1651             :         sNType23[] = "user_fax" ,           sNType24[] = "user_email" ,
    1652             :         sNType25[] = "user_state",          sNType26[] = "graph"
    1653             :         ;
    1654             : 
    1655             :     static const sal_Char* sNTypeTab[ 27 ] =
    1656             :     {
    1657             :         sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
    1658             :         sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
    1659             :         sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
    1660             :         sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
    1661             :         sNType24, sNType25, sNType26
    1662             :     };
    1663             : 
    1664             :     const unsigned short nTblSize = 47;
    1665             :     int aArr[ nTblSize ] = { 0 };
    1666             :     sal_Char ch;
    1667             : 
    1668             :     for( int n = 0; n < 27; ++n )
    1669             :     {
    1670             :         unsigned long ii = 0;
    1671             :         const sal_Char* pp = sNTypeTab[ n ];
    1672             : 
    1673             :         while( *pp )
    1674             :         {
    1675             :             ii = ii << 1 ^ *pp++;
    1676             :         }
    1677             :         ii %= nTblSize;
    1678             : 
    1679             :         ch = aArr[ ii ] ? 'X' : ' ';
    1680             :         aArr[ ii ] = 1;
    1681             :         printf( "%-20s -> %3d [%c]\n", sNTypeTab[ n ], ii, ch );
    1682             :     }
    1683             : }
    1684             : 
    1685             : #endif
    1686             : 
    1687             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10