LCOV - code coverage report
Current view: top level - sw/source/core/bastyp - calc.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 260 620 41.9 %
Date: 2014-04-11 Functions: 24 37 64.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10