/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #if defined(MACOSX) #include #endif #include #include // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _DBMGR_HXX #include #endif #include #include #include using namespace ::com::sun::star; // tippt sich schneller #define RESOURCE ViewShell::GetShellRes() const sal_Char __FAR_DATA sCalc_Add[] = "add"; const sal_Char __FAR_DATA sCalc_Sub[] = "sub"; const sal_Char __FAR_DATA sCalc_Mul[] = "mul"; const sal_Char __FAR_DATA sCalc_Div[] = "div"; const sal_Char __FAR_DATA sCalc_Phd[] = "phd"; const sal_Char __FAR_DATA sCalc_Sqrt[] = "sqrt"; const sal_Char __FAR_DATA sCalc_Pow[] = "pow"; const sal_Char __FAR_DATA sCalc_Or[] = "or"; const sal_Char __FAR_DATA sCalc_Xor[] = "xor"; const sal_Char __FAR_DATA sCalc_And[] = "and"; const sal_Char __FAR_DATA sCalc_Not[] = "not"; const sal_Char __FAR_DATA sCalc_Eq[] = "eq"; const sal_Char __FAR_DATA sCalc_Neq[] = "neq"; const sal_Char __FAR_DATA sCalc_Leq[] = "leq"; const sal_Char __FAR_DATA sCalc_Geq[] = "geq"; const sal_Char __FAR_DATA sCalc_L[] = "l"; const sal_Char __FAR_DATA sCalc_G[] = "g"; const sal_Char __FAR_DATA sCalc_Sum[] = "sum"; const sal_Char __FAR_DATA sCalc_Mean[] = "mean"; const sal_Char __FAR_DATA sCalc_Min[] = "min"; const sal_Char __FAR_DATA sCalc_Max[] = "max"; const sal_Char __FAR_DATA sCalc_Sin[] = "sin"; const sal_Char __FAR_DATA sCalc_Cos[] = "cos"; const sal_Char __FAR_DATA sCalc_Tan[] = "tan"; const sal_Char __FAR_DATA sCalc_Asin[] = "asin"; const sal_Char __FAR_DATA sCalc_Acos[] = "acos"; const sal_Char __FAR_DATA sCalc_Atan[] = "atan"; const sal_Char __FAR_DATA sCalc_Round[] = "round"; const sal_Char __FAR_DATA sCalc_Date[] = "date"; //!!!!! ACHTUNG - Sortierte Liste aller Operatoren !!!!! struct _CalcOp { union{ const sal_Char* pName; const String* pUName; }; SwCalcOper eOp; }; _CalcOp __READONLY_DATA aOpTable[] = { /* ACOS */ {{sCalc_Acos}, CALC_ACOS}, // Arcuscosinus /* ADD */ {{sCalc_Add}, CALC_PLUS}, // Addition /* AND */ {{sCalc_And}, CALC_AND}, // log. und /* ASIN */ {{sCalc_Asin}, CALC_ASIN}, // Arcussinus /* ATAN */ {{sCalc_Atan}, CALC_ATAN}, // Arcustangens /* COS */ {{sCalc_Cos}, CALC_COS}, // Cosinus /* DATE */ {{sCalc_Date}, CALC_DATE}, // Date /* DIV */ {{sCalc_Div}, CALC_DIV}, // Dividieren /* EQ */ {{sCalc_Eq}, CALC_EQ}, // gleich /* G */ {{sCalc_G}, CALC_GRE}, // groesser /* GEQ */ {{sCalc_Geq}, CALC_GEQ}, // groesser gleich /* L */ {{sCalc_L}, CALC_LES}, // kleiner /* LEQ */ {{sCalc_Leq}, CALC_LEQ}, // kleiner gleich /* MAX */ {{sCalc_Max}, CALC_MAX}, // Maximalwert /* MEAN */ {{sCalc_Mean}, CALC_MEAN}, // Mittelwert /* MIN */ {{sCalc_Min}, CALC_MIN}, // Minimalwert /* MUL */ {{sCalc_Mul}, CALC_MUL}, // Multiplizieren /* NEQ */ {{sCalc_Neq}, CALC_NEQ}, // nicht gleich /* NOT */ {{sCalc_Not}, CALC_NOT}, // log. nicht /* OR */ {{sCalc_Or}, CALC_OR}, // log. oder /* PHD */ {{sCalc_Phd}, CALC_PHD}, // Prozent /* POW */ {{sCalc_Pow}, CALC_POW}, // Potenzieren /* ROUND */ {{sCalc_Round}, CALC_ROUND}, // Runden /* SIN */ {{sCalc_Sin}, CALC_SIN}, // Sinus /* SQRT */ {{sCalc_Sqrt}, CALC_SQRT}, // Wurzel /* SUB */ {{sCalc_Sub}, CALC_MINUS}, // Subtraktion /* SUM */ {{sCalc_Sum}, CALC_SUM}, // Summe /* TAN */ {{sCalc_Tan}, CALC_TAN}, // Tangens /* XOR */ {{sCalc_Xor}, CALC_XOR} // log. xoder }; double __READONLY_DATA nRoundVal[] = { 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14, 0.5e-15,0.5e-16 }; double __READONLY_DATA nKorrVal[] = { 9, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8, 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14 }; // First character may be any alphabetic or underscore. const sal_Int32 coStartFlags = i18n::KParseTokens::ANY_LETTER_OR_NUMBER | i18n::KParseTokens::ASC_UNDERSCORE | i18n::KParseTokens::IGNORE_LEADING_WS; // Continuing characters may be any alphanumeric or underscore or dot. const sal_Int32 coContFlags = ( coStartFlags | i18n::KParseTokens::ASC_DOT ) & ~i18n::KParseTokens::IGNORE_LEADING_WS; extern "C" { static int #if defined( WNT ) __cdecl #endif #if defined( ICC ) _Optlink #endif OperatorCompare( const void *pFirst, const void *pSecond) { int nRet = 0; if( CALC_NAME == ((_CalcOp*)pFirst)->eOp ) { if( CALC_NAME == ((_CalcOp*)pSecond)->eOp ) nRet = ((_CalcOp*)pFirst)->pUName->CompareTo( *((_CalcOp*)pSecond)->pUName ); else nRet = ((_CalcOp*)pFirst)->pUName->CompareToAscii( ((_CalcOp*)pSecond)->pName ); } else { if( CALC_NAME == ((_CalcOp*)pSecond)->eOp ) nRet = -1 * ((_CalcOp*)pSecond)->pUName->CompareToAscii( ((_CalcOp*)pFirst)->pName ); else nRet = strcmp( ((_CalcOp*)pFirst)->pName, ((_CalcOp*)pSecond)->pName ); } return nRet; } }// extern "C" _CalcOp* FindOperator( const String& rSrch ) { _CalcOp aSrch; aSrch.pUName = &rSrch; aSrch.eOp = CALC_NAME; return (_CalcOp*)bsearch( (void*) &aSrch, (void*) aOpTable, sizeof( aOpTable ) / sizeof( _CalcOp ), sizeof( _CalcOp ), OperatorCompare ); } //----------------------------------------------------------------------------- SwHash* Find( const String& rStr, SwHash** ppTable, sal_uInt16 nTblSize, sal_uInt16* pPos ) { sal_uLong ii = 0; for( xub_StrLen n = 0; n < rStr.Len(); ++n ) ii = ii << 1 ^ rStr.GetChar( n ); ii %= nTblSize; if( pPos ) *pPos = (sal_uInt16)ii; for( SwHash* pEntry = *(ppTable+ii); pEntry; pEntry = pEntry->pNext ) if( rStr == pEntry->aStr ) return pEntry; return 0; } inline LanguageType GetDocAppScriptLang( SwDoc& rDoc ) { return ((SvxLanguageItem&)rDoc.GetDefault( GetWhichOfScript( RES_CHRATR_LANGUAGE, GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() )) )).GetLanguage(); } double lcl_ConvertToDateValue( SwDoc& rDoc, sal_Int32 nDate ) { double nRet = 0; SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter(); if( pFormatter ) { Date* pNull = pFormatter->GetNullDate(); Date aDate( nDate >> 24, (nDate & 0x00FF0000) >> 16, nDate & 0x0000FFFF ); nRet = aDate - *pNull; } return nRet; } //----------------------------------------------------------------------------- /****************************************************************************** |* |* SwCalc::SwCalc( SwDoc* pD ) : |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung JP 03.11.95 |* |******************************************************************************/ SwCalc::SwCalc( SwDoc& rD ) : aErrExpr( aEmptyStr, SwSbxValue(), 0 ), rDoc( rD ), pLclData( m_aSysLocale.GetLocaleDataPtr() ), pCharClass( &GetAppCharClass() ), nListPor( 0 ), eError( CALC_NOERR ) { aErrExpr.aStr.AssignAscii( "~C_ERR~" ); memset( VarTable, 0, sizeof(VarTable) ); LanguageType eLang = GetDocAppScriptLang( rDoc ); if( eLang != SvxLocaleToLanguage( pLclData->getLocale() ) || eLang != SvxLocaleToLanguage( pCharClass->getLocale() ) ) { STAR_NMSPC::lang::Locale aLocale( SvxCreateLocale( eLang )); STAR_REFERENCE( lang::XMultiServiceFactory ) xMSF( ::comphelper::getProcessServiceFactory() ); pCharClass = new CharClass( xMSF, aLocale ); pLclData = new LocaleDataWrapper( xMSF, aLocale ); } sCurrSym = pLclData->getCurrSymbol(); sCurrSym.EraseLeadingChars().EraseTrailingChars(); pCharClass->toLower( sCurrSym ); static sal_Char __READONLY_DATA sNType0[] = "false", sNType1[] = "true", sNType2[] = "pi", sNType3[] = "e", sNType4[] = "tables", sNType5[] = "graf", sNType6[] = "ole", sNType7[] = "page", sNType8[] = "para", sNType9[] = "word", sNType10[]= "char", sNType11[] = "user_firstname" , sNType12[] = "user_lastname" , sNType13[] = "user_initials" , sNType14[] = "user_company" , sNType15[] = "user_street" , sNType16[] = "user_country" , sNType17[] = "user_zipcode" , sNType18[] = "user_city" , sNType19[] = "user_title" , sNType20[] = "user_position" , sNType21[] = "user_tel_work" , sNType22[] = "user_tel_home" , sNType23[] = "user_fax" , sNType24[] = "user_email" , sNType25[] = "user_state" , sNType26[] = "graph" ; static const sal_Char* __READONLY_DATA sNTypeTab[ 27 ] = { sNType0, sNType1, sNType2, sNType3, sNType4, sNType5, sNType6, sNType7, sNType8, sNType9, sNType10, sNType11, sNType12, sNType13, sNType14, sNType15, sNType16, sNType17, sNType18, sNType19, sNType20, sNType21, sNType22, sNType23, sNType24, // diese sind mit doppelten HashIds sNType25, sNType26 }; static sal_uInt16 __READONLY_DATA aHashValue[ 27 ] = { 34, 38, 43, 7, 18, 32, 22, 29, 30, 33, 3, 28, 24, 40, 9, 11, 26, 45, 4, 23, 36, 44, 19, 5, 1, // diese sind mit doppelten HashIds 11, 38 }; static sal_uInt16 __READONLY_DATA aAdrToken[ 12 ] = { USER_OPT_COMPANY, USER_OPT_STREET, USER_OPT_COUNTRY, USER_OPT_ZIP, USER_OPT_CITY, USER_OPT_TITLE, USER_OPT_POSITION, USER_OPT_TELEPHONEWORK, USER_OPT_TELEPHONEHOME, USER_OPT_FAX, USER_OPT_EMAIL, USER_OPT_STATE }; static sal_uInt16 SwDocStat::* __READONLY_DATA aDocStat1[ 3 ] = { &SwDocStat::nTbl, &SwDocStat::nGrf, &SwDocStat::nOLE }; static sal_uLong SwDocStat::* __READONLY_DATA aDocStat2[ 4 ] = { &SwDocStat::nPage, &SwDocStat::nPara, &SwDocStat::nWord, &SwDocStat::nChar }; #if TBLSZ != 47 #error Alle Hashwerte angepasst? #endif const SwDocStat& rDocStat = rDoc.GetDocStat(); SwSbxValue nVal; String sTmpStr; sal_uInt16 n; for( n = 0; n < 25; ++n ) { sTmpStr.AssignAscii( sNTypeTab[ n ] ); VarTable[ aHashValue[ n ] ] = new SwCalcExp( sTmpStr, nVal, 0 ); } ((SwCalcExp*)VarTable[ aHashValue[ 0 ] ])->nValue.PutBool( sal_False ); ((SwCalcExp*)VarTable[ aHashValue[ 1 ] ])->nValue.PutBool( sal_True ); ((SwCalcExp*)VarTable[ aHashValue[ 2 ] ])->nValue.PutDouble( F_PI ); ((SwCalcExp*)VarTable[ aHashValue[ 3 ] ])->nValue.PutDouble( 2.7182818284590452354 ); for( n = 0; n < 3; ++n ) ((SwCalcExp*)VarTable[ aHashValue[ n + 4 ] ])->nValue.PutLong( rDocStat.*aDocStat1[ n ] ); for( n = 0; n < 4; ++n ) ((SwCalcExp*)VarTable[ aHashValue[ n + 7 ] ])->nValue.PutLong( rDocStat.*aDocStat2[ n ] ); SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions(); ((SwCalcExp*)VarTable[ aHashValue[ 11 ] ])->nValue.PutString( (String)rUserOptions.GetFirstName() ); ((SwCalcExp*)VarTable[ aHashValue[ 12 ] ])->nValue.PutString( (String)rUserOptions.GetLastName() ); ((SwCalcExp*)VarTable[ aHashValue[ 13 ] ])->nValue.PutString( (String)rUserOptions.GetID() ); for( n = 0; n < 11; ++n ) ((SwCalcExp*)VarTable[ aHashValue[ n + 14 ] ])->nValue.PutString( (String)rUserOptions.GetToken( aAdrToken[ n ] )); nVal.PutString( (String)rUserOptions.GetToken( aAdrToken[ 11 ] )); sTmpStr.AssignAscii( sNTypeTab[ 25 ] ); VarTable[ aHashValue[ 25 ] ]->pNext = new SwCalcExp( sTmpStr, nVal, 0 ); // at time its better not to use "graph", because then the im-/export have // to change in all formulas this name. // nVal.PutLong( rDocStat.*aDocStat1[ 1 ] ); // VarTable[ aHashValue[ 26 ] ]->pNext = new SwCalcExp( // sNTypeTab[ 26 ], nVal, 0 ); } /****************************************************************************** |* |* SwCalc::~SwCalc() |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung OK 12-02-93 11:04am |* |******************************************************************************/ SwCalc::~SwCalc() { for( sal_uInt16 n = 0; n < TBLSZ; ++n ) delete VarTable[n]; if( pLclData != m_aSysLocale.GetLocaleDataPtr() ) delete pLclData; if( pCharClass != &GetAppCharClass() ) delete pCharClass; } /****************************************************************************** |* |* SwSbxValue SwCalc::Calculate( const String& rStr ) |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung OK 12-02-93 11:04am |* |******************************************************************************/ SwSbxValue SwCalc::Calculate( const String& rStr ) { eError = CALC_NOERR; SwSbxValue nResult; if( !rStr.Len() ) return nResult; nListPor = 0; eCurrListOper = CALC_PLUS; // defaulten auf Summe sCommand = rStr; nCommandPos = 0; while( (eCurrOper = GetToken()) != CALC_ENDCALC && eError == CALC_NOERR ) nResult = Expr(); if( eError ) nResult.PutDouble( DBL_MAX ); return nResult; } /****************************************************************************** |* |* String SwCalc::GetStrResult( SwSbxValue nValue, sal_Bool bRound = sal_True ) |* Beschreibung Der Parameter bRound ist auf sal_True defaultet und darf |* nur beim errechnen von Tabellenzellen auf sal_False gesetzt |* werden, damit keine Rundungsfehler beim zusammenstellen |* der Formel entstehen. |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung JP 19.02.98 |* |******************************************************************************/ String SwCalc::GetStrResult( const SwSbxValue& rVal, sal_Bool bRound ) { if( !rVal.IsDouble() ) return rVal.GetString(); return GetStrResult( rVal.GetDouble(), bRound ); } String SwCalc::GetStrResult( double nValue, sal_Bool ) { if( nValue >= DBL_MAX ) switch( eError ) { case CALC_SYNTAX : return RESOURCE->aCalc_Syntax; case CALC_ZERODIV : return RESOURCE->aCalc_ZeroDiv; case CALC_BRACK : return RESOURCE->aCalc_Brack; case CALC_POWERR : return RESOURCE->aCalc_Pow; case CALC_VARNFND : return RESOURCE->aCalc_VarNFnd; case CALC_OVERFLOW : return RESOURCE->aCalc_Overflow; case CALC_WRONGTIME : return RESOURCE->aCalc_WrongTime; default : return RESOURCE->aCalc_Default; } sal_uInt16 nDec = 15; //pLclData->getNumDigits(); String aRetStr( ::rtl::math::doubleToUString( nValue, rtl_math_StringFormat_Automatic, nDec, pLclData->getNumDecimalSep().GetChar(0), true )); return aRetStr; } /****************************************************************************** |* |* SwCalcExp* SwCalc::VarLook( const String& ) |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung JP 15.11.99 |* |******************************************************************************/ SwCalcExp* SwCalc::VarInsert( const String &rStr ) { String aStr( rStr ); pCharClass->toLower( aStr ); return VarLook( aStr, 1 ); } /****************************************************************************** |* |* SwCalcExp* SwCalc::VarLook( const String& , sal_uInt16 ins ) |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung JP 15.11.99 |* |******************************************************************************/ SwCalcExp* SwCalc::VarLook( const String& rStr, sal_uInt16 ins ) { aErrExpr.nValue.SetVoidValue(false); sal_uInt16 ii = 0; String aStr( rStr ); pCharClass->toLower( aStr ); SwHash* pFnd = Find( aStr, VarTable, TBLSZ, &ii ); if( !pFnd ) { // dann sehen wir mal im Doc nach: SwHash** ppDocTbl = rDoc.GetUpdtFlds().GetFldTypeTable(); for( SwHash* pEntry = *(ppDocTbl+ii); pEntry; pEntry = pEntry->pNext ) if( aStr == pEntry->aStr ) { // dann hier zufuegen pFnd = new SwCalcExp( aStr, SwSbxValue(), ((SwCalcFldType*)pEntry)->pFldType ); pFnd->pNext = *(VarTable+ii); *(VarTable+ii) = pFnd; break; } } if( pFnd ) { SwCalcExp* pFndExp = (SwCalcExp*)pFnd; if( pFndExp->pFldType && pFndExp->pFldType->Which() == RES_USERFLD ) { SwUserFieldType* pUFld = (SwUserFieldType*)pFndExp->pFldType; if( nsSwGetSetExpType::GSE_STRING & pUFld->GetType() ) pFndExp->nValue.PutString( pUFld->GetContent() ); else if( !pUFld->IsValid() ) { // Die aktuellen Werte sichern . . . sal_uInt16 nOld_ListPor = nListPor; SwSbxValue nOld_LastLeft = nLastLeft; SwSbxValue nOld_NumberValue = nNumberValue; xub_StrLen nOld_CommandPos = nCommandPos; SwCalcOper eOld_CurrOper = eCurrOper; SwCalcOper eOld_CurrListOper = eCurrListOper; pFndExp->nValue.PutDouble( pUFld->GetValue( *this ) ); // . . . und zurueck damit. nListPor = nOld_ListPor; nLastLeft = nOld_LastLeft; nNumberValue = nOld_NumberValue; nCommandPos = nOld_CommandPos; eCurrOper = eOld_CurrOper; eCurrListOper = eOld_CurrListOper; } else pFndExp->nValue.PutDouble( pUFld->GetValue() ); } return pFndExp; } // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!") // #101436#: At this point the "real" case variable has to be used String sTmpName( rStr ); ::ReplacePoint( sTmpName ); if( !ins ) { SwNewDBMgr *pMgr = rDoc.GetNewDBMgr(); // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!") String sDBName(GetDBName( sTmpName )); String sSourceName(sDBName.GetToken(0, DB_DELIM)); String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM)); if( pMgr && sSourceName.Len() && sTableName.Len() && pMgr->OpenDataSource(sSourceName, sTableName, -1, false)) { String sColumnName( GetColumnName( sTmpName )); ASSERT (sColumnName.Len(), "DB-Spaltenname fehlt!"); String sDBNum( SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD) ); pCharClass->toLower(sDBNum); // Hier nochmal initialisieren, da das nicht mehr in docfld // fuer Felder != RES_DBFLD geschieht. Z.B. wenn ein Expressionfield // vor einem DB_Field in einem Dok vorkommt. VarChange( sDBNum, pMgr->GetSelectedRecordId(sSourceName, sTableName)); if( sDBNum.EqualsIgnoreCaseAscii(sColumnName) ) { aErrExpr.nValue.PutLong(long(pMgr->GetSelectedRecordId(sSourceName, sTableName))); return &aErrExpr; } sal_uLong nTmpRec = 0; if( 0 != ( pFnd = Find( sDBNum, VarTable, TBLSZ ) ) ) nTmpRec = ((SwCalcExp*)pFnd)->nValue.GetULong(); String sResult; double nNumber = DBL_MAX; long nLang = SvxLocaleToLanguage( pLclData->getLocale() ); if(pMgr->GetColumnCnt( sSourceName, sTableName, sColumnName, nTmpRec, nLang, sResult, &nNumber )) { if (nNumber != DBL_MAX) aErrExpr.nValue.PutDouble( nNumber ); else aErrExpr.nValue.PutString( sResult ); return &aErrExpr; } } else { //data source was not available - set return to "NoValue" aErrExpr.nValue.SetVoidValue(true); } // auf keinen fall eintragen!! return &aErrExpr; } SwCalcExp* pNewExp = new SwCalcExp( aStr, SwSbxValue(), 0 ); pNewExp->pNext = VarTable[ ii ]; VarTable[ ii ] = pNewExp; String sColumnName( GetColumnName( sTmpName )); ASSERT( sColumnName.Len(), "DB-Spaltenname fehlt!" ); if( sColumnName.EqualsIgnoreCaseAscii( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) )) { SwNewDBMgr *pMgr = rDoc.GetNewDBMgr(); String sDBName(GetDBName( sTmpName )); String sSourceName(sDBName.GetToken(0, DB_DELIM)); String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM)); if( pMgr && sSourceName.Len() && sTableName.Len() && pMgr->OpenDataSource(sSourceName, sTableName, -1, false) && !pMgr->IsInMerge()) pNewExp->nValue.PutULong( pMgr->GetSelectedRecordId(sSourceName, sTableName)); else pNewExp->nValue.SetVoidValue(true); } return pNewExp; } /****************************************************************************** |* |* sal_Bool SwCalc::VarChange( const String& rStr, const SwSbxValue nValue ) |* |* Erstellung OK 12-02-93 11:04am |* Letzte Aenderung OK 12-02-93 11:04am |* |******************************************************************************/ void SwCalc::VarChange( const String& rStr, double nValue ) { SwSbxValue aVal( nValue ); VarChange( rStr, aVal ); } void SwCalc::VarChange( const String& rStr, const SwSbxValue& rValue ) { String aStr( rStr ); pCharClass->toLower( aStr ); sal_uInt16 nPos = 0; SwCalcExp* pFnd = (SwCalcExp*)Find( aStr, VarTable, TBLSZ, &nPos ); if( !pFnd ) { pFnd = new SwCalcExp( aStr, SwSbxValue( rValue ), 0 ); pFnd->pNext = VarTable[ nPos ]; VarTable[ nPos ] = pFnd; } else pFnd->nValue = rValue; } /****************************************************************************** |* |* sal_Bool SwCalc::Push( const void* pPtr ) |* |* Erstellung OK 12-02-93 11:05am |* Letzte Aenderung OK 12-02-93 11:05am |* |******************************************************************************/ sal_Bool SwCalc::Push( const VoidPtr pPtr ) { if( USHRT_MAX != aRekurStk.GetPos( pPtr ) ) return sal_False; aRekurStk.Insert( pPtr, aRekurStk.Count() ); return sal_True; } /****************************************************************************** |* |* void SwCalc::Pop( const void* pPtr ) |* |* Erstellung OK 12-02-93 11:05am |* Letzte Aenderung OK 12-02-93 11:05am |* |******************************************************************************/ void SwCalc::Pop( const VoidPtr ) { ASSERT( aRekurStk.Count(), "SwCalc: Pop auf ungueltigen Ptr" ); aRekurStk.Remove( aRekurStk.Count() - 1 ); } /****************************************************************************** |* |* SwCalcOper SwCalc::GetToken() |* |* Erstellung OK 12-02-93 11:05am |* Letzte Aenderung JP 03.11.95 |* |******************************************************************************/ SwCalcOper SwCalc::GetToken() { #if OSL_DEBUG_LEVEL > 1 //JP 25.01.2001: static for switch back to the "old" implementation of the // calculator, which don't use the I18N routines. static int nUseOld = 0; if( !nUseOld ) { #endif if( nCommandPos >= sCommand.Len() ) return eCurrOper = CALC_ENDCALC; using namespace ::com::sun::star::i18n; { // Parse any token. ParseResult aRes = pCharClass->parseAnyToken( sCommand, nCommandPos, coStartFlags, aEmptyStr, coContFlags, aEmptyStr ); sal_Bool bSetError = sal_True; xub_StrLen nRealStt = nCommandPos + (xub_StrLen)aRes.LeadingWhiteSpace; if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) ) { nNumberValue.PutDouble( aRes.Value ); eCurrOper = CALC_NUMBER; bSetError = sal_False; } else if( aRes.TokenType & KParseType::IDENTNAME ) { String aName( sCommand.Copy( nRealStt, static_cast(aRes.EndPos) - nRealStt )); //#101436#: the variable may contain a database name it must not be converted to lower case // instead all further comparisons must be done case-insensitive //pCharClass->toLower( aName ); String sLowerCaseName(aName); pCharClass->toLower( sLowerCaseName ); // Currency-Symbol abfangen if( sLowerCaseName == sCurrSym ) { nCommandPos = (xub_StrLen)aRes.EndPos; return GetToken(); // also nochmal aufrufen } // Operations abfangen _CalcOp* pFnd = ::FindOperator( sLowerCaseName ); if( pFnd ) { switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) ) { case CALC_SUM: case CALC_MEAN: eCurrListOper = CALC_PLUS; break; case CALC_MIN: eCurrListOper = CALC_MIN_IN; break; case CALC_MAX: eCurrListOper = CALC_MAX_IN; break; case CALC_DATE: eCurrListOper = CALC_MONTH; break; default: break; } nCommandPos = (xub_StrLen)aRes.EndPos; return eCurrOper; } aVarName = aName; eCurrOper = CALC_NAME; bSetError = sal_False; } else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING ) { nNumberValue.PutString( String( aRes.DequotedNameOrString )); eCurrOper = CALC_NUMBER; bSetError = sal_False; } else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR ) { String aName( sCommand.Copy( nRealStt, static_cast(aRes.EndPos) - nRealStt )); if( 1 == aName.Len() ) { bSetError = sal_False; sal_Unicode ch = aName.GetChar( 0 ); switch( ch ) { case ';': if( CALC_MONTH == eCurrListOper || CALC_DAY == eCurrListOper ) { eCurrOper = eCurrListOper; break; } case '\n': eCurrOper = CALC_PRINT; break; case '%': case '^': case '*': case '/': case '+': case '-': case '(': case ')': eCurrOper = SwCalcOper(ch); break; case '=': case '!': { SwCalcOper eTmp2; if( '=' == ch ) eCurrOper = SwCalcOper('='), eTmp2 = CALC_EQ; else eCurrOper = CALC_NOT, eTmp2 = CALC_NEQ; if( aRes.EndPos < sCommand.Len() && '=' == sCommand.GetChar( (xub_StrLen)aRes.EndPos ) ) { eCurrOper = eTmp2; ++aRes.EndPos; } } break; case cListDelim : eCurrOper = eCurrListOper; break; case '[': if( aRes.EndPos < sCommand.Len() ) { aVarName.Erase(); xub_StrLen nFndPos = (xub_StrLen)aRes.EndPos, nSttPos = nFndPos; do{ if( STRING_NOTFOUND != ( nFndPos = sCommand.Search( ']', nFndPos )) ) { // ignore the ] if( '\\' == sCommand.GetChar(nFndPos-1)) { aVarName += sCommand.Copy( nSttPos, nFndPos - nSttPos - 1 ); nSttPos = ++nFndPos; } else break; } } while( STRING_NOTFOUND != nFndPos ); if( STRING_NOTFOUND != nFndPos ) { if( nSttPos != nFndPos ) aVarName += sCommand.Copy( nSttPos, nFndPos - nSttPos ); aRes.EndPos = nFndPos + 1; eCurrOper = CALC_NAME; } else bSetError = sal_True; } else bSetError = sal_True; break; default: bSetError = sal_True; break; } } } else if( aRes.TokenType & KParseType::BOOLEAN ) { String aName( sCommand.Copy( nRealStt, static_cast(aRes.EndPos) - nRealStt )); if( aName.Len() ) { sal_Unicode ch = aName.GetChar(0); bSetError = sal_True; if ('<' == ch || '>' == ch) { bSetError = sal_False; SwCalcOper eTmp2 = ('<' == ch) ? CALC_LEQ : CALC_GEQ; eCurrOper = ('<' == ch) ? CALC_LES : CALC_GRE; if( 2 == aName.Len() && '=' == aName.GetChar(1) ) eCurrOper = eTmp2; else if( 1 != aName.Len() ) bSetError = sal_True; } } } else if( nRealStt == sCommand.Len() ) { eCurrOper = CALC_ENDCALC; bSetError = sal_False; } if( bSetError ) { eError = CALC_SYNTAX; eCurrOper = CALC_PRINT; } nCommandPos = (xub_StrLen)aRes.EndPos; }; #if OSL_DEBUG_LEVEL > 1 #define NextCh( s, n ) (nCommandPos < sCommand.Len() ? sCommand.GetChar( nCommandPos++ ) : 0) } else { sal_Unicode ch; sal_Unicode cTSep = pLclData->getNumThousandSep().GetChar(0), cDSep = pLclData->getNumDecimalSep().GetChar(0); do { if( 0 == ( ch = NextCh( sCommand, nCommandPos ) ) ) return eCurrOper = CALC_ENDCALC; } while ( ch == '\t' || ch == ' ' || ch == cTSep ); if( ch == cDSep ) ch = '.'; switch( ch ) { case ';': if( CALC_MONTH == eCurrListOper || CALC_DAY == eCurrListOper ) { eCurrOper = eCurrListOper; break; } // else .. no break case '\n': { sal_Unicode c; while( nCommandPos < sCommand.Len() && ( ( c = sCommand.GetChar( nCommandPos ) ) == ' ' || c == '\t' || c == '\x0a' || c == '\x0d' )) ++nCommandPos; eCurrOper = CALC_PRINT; } break; case '%': case '^': case '*': case '/': case '+': case '-': case '(': case ')': eCurrOper = SwCalcOper(ch); break; case '=': if( '=' == sCommand.GetChar( nCommandPos ) ) { ++nCommandPos; eCurrOper = CALC_EQ; } else eCurrOper = SwCalcOper(ch); break; case '!': if( '=' == sCommand.GetChar( nCommandPos ) ) { ++nCommandPos; eCurrOper = CALC_NEQ; } else eCurrOper = CALC_NOT; break; case '>': case '<': eCurrOper = '>' == ch ? CALC_GRE : CALC_LES; if( '=' == (ch = sCommand.GetChar( nCommandPos ) ) ) { ++nCommandPos; eCurrOper = CALC_GRE == eCurrOper ? CALC_GEQ : CALC_LEQ; } else if( ' ' != ch ) { eError = CALC_SYNTAX; eCurrOper = CALC_PRINT; } break; case cListDelim : eCurrOper = eCurrListOper; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ',': case '.': { double nVal; --nCommandPos; // auf das 1. Zeichen zurueck if( Str2Double( sCommand, nCommandPos, nVal, pLclData )) { nNumberValue.PutDouble( nVal ); eCurrOper = CALC_NUMBER; } else { // fehlerhafte Zahl eError = CALC_SYNTAX; eCurrOper = CALC_PRINT; } } break; case '[': { String aStr; sal_Bool bIgnore = sal_False; do { while( 0 != ( ch = NextCh( sCommand, nCommandPos )) && ch != ']' ) { if( !bIgnore && '\\' == ch ) bIgnore = sal_True; else if( bIgnore ) bIgnore = sal_False; aStr += ch; } if( !bIgnore ) break; aStr.SetChar( aStr.Len() - 1, ch ); } while( ch ); aVarName = aStr; eCurrOper = CALC_NAME; } break; case '"': { xub_StrLen nStt = nCommandPos; while( 0 != ( ch = NextCh( sCommand, nCommandPos ) ) && '"' != ch ) ; xub_StrLen nLen = nCommandPos - nStt; if( '"' == ch ) --nLen; nNumberValue.PutString( sCommand.Copy( nStt, nLen )); eCurrOper = CALC_NUMBER; } break; default: if( ch && pCharClass->isLetter( sCommand, nCommandPos - 1) || '_' == ch ) { xub_StrLen nStt = nCommandPos-1; while( 0 != (ch = NextCh( sCommand, nCommandPos )) && (pCharClass->isLetterNumeric( sCommand, nCommandPos - 1) || ch == '_' || ch == '.' ) ) ; if( ch ) --nCommandPos; String aStr( sCommand.Copy( nStt, nCommandPos-nStt )); pCharClass->toLower( aStr ); // Currency-Symbol abfangen if( aStr == sCurrSym ) return GetToken(); // also nochmal aufrufen // Operations abfangen _CalcOp* pFnd = ::FindOperator( aStr ); if( pFnd ) { switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) ) { case CALC_SUM : case CALC_MEAN : eCurrListOper = CALC_PLUS; break; case CALC_MIN : eCurrListOper = CALC_MIN_IN; break; case CALC_MAX : eCurrListOper = CALC_MAX_IN; break; case CALC_DATE : eCurrListOper = CALC_MONTH; break; default : break; } return eCurrOper; } aVarName = aStr; eCurrOper = CALC_NAME; } else { eError = CALC_SYNTAX; eCurrOper = CALC_PRINT; } break; } } #endif return eCurrOper; } /****************************************************************************** |* |* SwSbxValue SwCalc::Term() |* |* Erstellung OK 12-02-93 11:05am |* Letzte Aenderung JP 16.01.96 |* |******************************************************************************/ SwSbxValue SwCalc::Term() { SwSbxValue left( Prim() ); nLastLeft = left; for(;;) { sal_uInt16 nSbxOper = USHRT_MAX; switch( eCurrOper ) { // wir haben kein Bitweises verodern, oder ? // case CALC_AND: eSbxOper = SbxAND; break; // case CALC_OR: eSbxOper = SbxOR; break; // case CALC_XOR: eSbxOper = SbxXOR; break; case CALC_AND: { GetToken(); sal_Bool bB = Prim().GetBool(); left.PutBool( left.GetBool() && bB ); } break; case CALC_OR: { GetToken(); sal_Bool bB = Prim().GetBool(); left.PutBool( left.GetBool() || bB ); } break; case CALC_XOR: { GetToken(); sal_Bool bR = Prim().GetBool(); sal_Bool bL = left.GetBool(); left.PutBool( (bL && !bR) || (!bL && bR) ); } break; case CALC_EQ: nSbxOper = SbxEQ; break; case CALC_NEQ: nSbxOper = SbxNE; break; case CALC_LEQ: nSbxOper = SbxLE; break; case CALC_GEQ: nSbxOper = SbxGE; break; case CALC_GRE: nSbxOper = SbxGT; break; case CALC_LES: nSbxOper = SbxLT; break; case CALC_MUL: nSbxOper = SbxMUL; break; case CALC_DIV: nSbxOper = SbxDIV; break; case CALC_MIN_IN: { GetToken(); SwSbxValue e = Prim(); left = left.GetDouble() < e.GetDouble() ? left : e; } break; case CALC_MAX_IN: { GetToken(); SwSbxValue e = Prim(); left = left.GetDouble() > e.GetDouble() ? left : e; } break; case CALC_MONTH: { GetToken(); SwSbxValue e = Prim(); sal_Int32 nYear = (sal_Int32) floor( left.GetDouble() ); nYear = nYear & 0x0000FFFF; sal_Int32 nMonth = (sal_Int32) floor( e.GetDouble() ); nMonth = ( nMonth & 0x000000FF ) << 16; left.PutLong( nMonth + nYear ); eCurrOper = CALC_DAY; } break; case CALC_DAY: { GetToken(); SwSbxValue e = Prim(); sal_Int32 nYearMonth = (sal_Int32) floor( left.GetDouble() ); nYearMonth = nYearMonth & 0x00FFFFFF; sal_Int32 nDay = (sal_Int32) floor( e.GetDouble() ); nDay = ( nDay & 0x000000FF ) << 24; left = lcl_ConvertToDateValue( rDoc, nDay + nYearMonth ); } break; case CALC_ROUND: { GetToken(); SwSbxValue e = Prim(); double fVal = 0; double fFac = 1; sal_Int32 nDec = (sal_Int32) floor( e.GetDouble() ); if( nDec < -20 || nDec > 20 ) { eError = CALC_OVERFLOW; left.Clear(); return left; } fVal = left.GetDouble(); sal_uInt16 i; if( nDec >= 0) for (i = 0; i < (sal_uInt16) nDec; ++i ) fFac *= 10.0; else for (i = 0; i < (sal_uInt16) -nDec; ++i ) fFac /= 10.0; fVal *= fFac; sal_Bool bSign; if (fVal < 0.0) { fVal *= -1.0; bSign = sal_True; } else bSign = sal_False; // runden double fNum = fVal; // find the exponent int nExp = 0; if( fNum > 0 ) { while( fNum < 1.0 ) fNum *= 10.0, --nExp; while( fNum >= 10.0 ) fNum /= 10.0, ++nExp; } nExp = 15 - nExp; if( nExp > 15 ) nExp = 15; else if( nExp <= 1 ) nExp = 0; fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] ); if (bSign) fVal *= -1.0; fVal /= fFac; left.PutDouble( fVal ); } break; /* // removed here because of #77448# (=2*3^2 != 18) case CALC_POW: { GetToken(); double fraction, integer; double right = Prim().GetDouble(), dleft = left.GetDouble(); fraction = modf( right, &integer ); if( ( dleft < 0.0 && 0.0 != fraction ) || ( 0.0 == dleft && right < 0.0 ) ) { eError = CALC_OVERFLOW; left.Clear(); return left; } dleft = pow(dleft, right ); if( dleft == HUGE_VAL ) { eError = CALC_POWERR; left.Clear(); return left; } left.PutDouble( dleft ); } break; */ default: return left; } if( USHRT_MAX != nSbxOper ) { // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX SbxOperator eSbxOper = (SbxOperator)nSbxOper; GetToken(); if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE ) left.PutBool( left.Compare( eSbxOper, Prim() )); else { SwSbxValue aRight( Prim() ); aRight.MakeDouble(); left.MakeDouble(); if( SbxDIV == eSbxOper && !aRight.GetDouble() ) eError = CALC_ZERODIV; else left.Compute( eSbxOper, aRight ); } } } } /****************************************************************************** |* |* SwSbxValue SwCalc::Prim() |* |* Erstellung OK 12-02-93 11:05am |* Letzte Aenderung JP 03.11.95 |* |******************************************************************************/ extern "C" typedef double (*pfCalc)( double ); SwSbxValue SwCalc::Prim() { SwSbxValue nErg; pfCalc pFnc = 0; sal_Bool bChkTrig = sal_False, bChkPow = sal_False; switch( eCurrOper ) { case CALC_SIN: pFnc = &sin; break; case CALC_COS: pFnc = &cos; break; case CALC_TAN: pFnc = &tan; break; case CALC_ATAN: pFnc = &atan; break; case CALC_ASIN: pFnc = &asin; bChkTrig = sal_True; break; case CALC_ACOS: pFnc = &acos; bChkTrig = sal_True; break; case CALC_NOT: { GetToken(); nErg = Prim(); if( SbxSTRING == nErg.GetType() ) nErg.PutBool( 0 == nErg.GetString().Len() ); else if(SbxBOOL == nErg.GetType() ) nErg.PutBool(!nErg.GetBool()); // evaluate arguments manually so that the binary NOT below // does not get called. // We want a BOOLEAN NOT. else if (nErg.IsNumeric()) nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 ); else { DBG_ERROR( "unexpected case. computing binary NOT" ); //!! computes a binary NOT nErg.Compute( SbxNOT, nErg ); } } break; case CALC_NUMBER: if( GetToken() == CALC_PHD ) { double aTmp = nNumberValue.GetDouble(); aTmp *= 0.01; nErg.PutDouble( aTmp ); GetToken(); } else if( eCurrOper == CALC_NAME ) eError = CALC_SYNTAX; else { nErg = nNumberValue; bChkPow = sal_True; } break; case CALC_NAME: if( GetToken() == CALC_ASSIGN ) { SwCalcExp* n = VarInsert( aVarName ); GetToken(); nErg = n->nValue = Expr(); } else { nErg = VarLook( aVarName )->nValue; bChkPow = sal_True; } break; case CALC_MINUS: GetToken(); nErg.PutDouble( -(Prim().GetDouble()) ); break; case CALC_LP: { GetToken(); nErg = Expr(); if( eCurrOper != CALC_RP ) eError = CALC_BRACK; else { GetToken(); bChkPow = sal_True; // in order for =(7)^2 to work } } break; case CALC_MEAN: { nListPor = 1; GetToken(); nErg = Expr(); double aTmp = nErg.GetDouble(); aTmp /= nListPor; nErg.PutDouble( aTmp ); } break; case CALC_SQRT: { GetToken(); nErg = Prim(); if( nErg.GetDouble() < 0 ) eError = CALC_OVERFLOW; else nErg.PutDouble( sqrt( nErg.GetDouble() )); } break; case CALC_SUM: case CALC_DATE: case CALC_MIN: case CALC_MAX: GetToken(); nErg = Expr(); break; case CALC_ENDCALC: nErg.Clear(); break; default: eError = CALC_SYNTAX; break; } if( pFnc ) { GetToken(); double nVal = Prim().GetDouble(); if( !bChkTrig || ( nVal > -1 && nVal < 1 ) ) nErg.PutDouble( (*pFnc)( nVal ) ); else eError = CALC_OVERFLOW; } // added here because of #77448# (=2*3^2 should be 18) if( bChkPow && eCurrOper == CALC_POW ) { double dleft = nErg.GetDouble(); GetToken(); double right = Prim().GetDouble(); double fraction, integer; fraction = modf( right, &integer ); if( ( dleft < 0.0 && 0.0 != fraction ) || ( 0.0 == dleft && right < 0.0 ) ) { eError = CALC_OVERFLOW; nErg.Clear(); } else { dleft = pow(dleft, right ); if( dleft == HUGE_VAL ) { eError = CALC_POWERR; nErg.Clear(); } else { nErg.PutDouble( dleft ); // GetToken(); } } } return nErg; } /****************************************************************************** |* |* SwSbxValue SwCalc::Expr() |* |* Erstellung OK 12-02-93 11:06am |* Letzte Aenderung JP 03.11.95 |* |******************************************************************************/ SwSbxValue SwCalc::Expr() { SwSbxValue left = Term(), right; nLastLeft = left; for(;;) switch(eCurrOper) { case CALC_PLUS: GetToken(); // erzeuge zum addieren auf jedenfall einen // Double-Wert left.MakeDouble(); ( right = Term() ).MakeDouble(); left.Compute( SbxPLUS, right ); nListPor++; break; case CALC_MINUS: GetToken(); // erzeuge zum addieren auf jedenfall einen // Double-Wert left.MakeDouble(); ( right = Term() ).MakeDouble(); left.Compute( SbxMINUS, right ); break; default: return left; } } //------------------------------------------------------------------------------ String SwCalc::GetColumnName(const String& rName) { xub_StrLen nPos = rName.Search(DB_DELIM); if( STRING_NOTFOUND != nPos ) { nPos = rName.Search(DB_DELIM, nPos + 1); if( STRING_NOTFOUND != nPos ) return rName.Copy(nPos + 1); } return rName; } //------------------------------------------------------------------------------ String SwCalc::GetDBName(const String& rName) { xub_StrLen nPos = rName.Search(DB_DELIM); if( STRING_NOTFOUND != nPos ) { nPos = rName.Search(DB_DELIM, nPos + 1); if( STRING_NOTFOUND != nPos ) return rName.Copy( 0, nPos ); } SwDBData aData = rDoc.GetDBData(); String sRet = aData.sDataSource; sRet += DB_DELIM; sRet += String(aData.sCommand); return sRet; } //------------------------------------------------------------------------------ namespace { static bool lcl_Str2Double( const String& rCommand, xub_StrLen& rCommandPos, double& rVal, const LocaleDataWrapper* const pLclData ) { OSL_ASSERT(pLclData); const xub_Unicode nCurrCmdPos = rCommandPos; rtl_math_ConversionStatus eStatus; const sal_Unicode* pEnd; rVal = rtl_math_uStringToDouble( rCommand.GetBuffer() + rCommandPos, rCommand.GetBuffer() + rCommand.Len(), pLclData->getNumDecimalSep().GetChar(0), pLclData->getNumThousandSep().GetChar(0), &eStatus, &pEnd ); rCommandPos = static_cast(pEnd - rCommand.GetBuffer()); return rtl_math_ConversionStatus_Ok == eStatus && nCurrCmdPos != rCommandPos; } } /****************************************************************************** * Methode : sal_Bool SwCalc::Str2Double( double& ) * Beschreibung: * Erstellt : OK 07.06.94 12:56 * Aenderung : JP 27.10.98 ******************************************************************************/ bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos, double& rVal, const LocaleDataWrapper* const pLclData ) { const SvtSysLocale aSysLocale; return lcl_Str2Double( rCommand, rCommandPos, rVal, pLclData ? pLclData : aSysLocale.GetLocaleDataPtr() ); } bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos, double& rVal, SwDoc* const pDoc ) { const SvtSysLocale aSysLocale; ::std::auto_ptr pLclD; if( pDoc ) { LanguageType eLang = GetDocAppScriptLang( *pDoc ); if (eLang != SvxLocaleToLanguage(aSysLocale.GetLocaleData().getLocale())) { pLclD.reset( new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), SvxCreateLocale( eLang ) ) ); } } bool const bRet = lcl_Str2Double( rCommand, rCommandPos, rVal, (pLclD.get()) ? pLclD.get() : aSysLocale.GetLocaleDataPtr() ); return bRet; } //------------------------------------------------------------------------------ sal_Bool SwCalc::IsValidVarName( const String& rStr, String* pValidName ) { sal_Bool bRet = sal_False; using namespace ::com::sun::star::i18n; { // Parse any token. ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0, coStartFlags, aEmptyStr, coContFlags, aEmptyStr ); if( aRes.TokenType & KParseType::IDENTNAME ) { bRet = aRes.EndPos == rStr.Len(); if( pValidName ) { xub_StrLen nRealStt = (xub_StrLen)aRes.LeadingWhiteSpace; *pValidName = rStr.Copy( nRealStt, static_cast(aRes.EndPos) - nRealStt ); } } else if( pValidName ) pValidName->Erase(); } return bRet; } //------------------------------------------------------------------------------ /****************************************************************************** |* |* CTOR DTOR der SwHash classes |* |* Ersterstellung OK 25.06.93 12:20 |* Letzte Aenderung OK 25.06.93 12:20 |* ******************************************************************************/ SwHash::SwHash( const String& rStr ) : aStr( rStr ), pNext( 0 ) {} SwHash::~SwHash() { if( pNext ) delete pNext; } void DeleteHashTable( SwHash **ppHashTable, sal_uInt16 nCount ) { for ( sal_uInt16 i = 0; i < nCount; ++i ) delete *(ppHashTable+i); delete [] ppHashTable; } SwCalcExp::SwCalcExp( const String& rStr, const SwSbxValue& rVal, const SwFieldType* pType ) : SwHash( rStr ), nValue( rVal ), pFldType( pType ) { } SwSbxValue::~SwSbxValue() { } sal_Bool SwSbxValue::GetBool() const { return SbxSTRING == GetType() ? 0 != GetString().Len() : 0 != SbxValue::GetBool(); } double SwSbxValue::GetDouble() const { double nRet; if( SbxSTRING == GetType() ) { xub_StrLen nStt = 0; SwCalc::Str2Double( GetString(), nStt, nRet ); } else if (IsBool()) { nRet = 0 != GetBool() ? 1.0 : 0.0; } else nRet = SbxValue::GetDouble(); return nRet; } SwSbxValue& SwSbxValue::MakeDouble() { if( SbxSTRING == GetType() || SbxBOOL == GetType() ) PutDouble( GetDouble() ); return *this; } #ifdef STANDALONE_HASHCALC // dies ist der Beispielcode zu erzeugen der HashValues im CTOR: #include void main() { static sal_Char sNType0[] = "false", sNType1[] = "true", sNType2[] = "pi", sNType3[] = "e", sNType4[] = "tables", sNType5[] = "graf", sNType6[] = "ole", sNType7[] = "page", sNType8[] = "para", sNType9[] = "word", sNType10[]= "char", sNType11[] = "user_company" , sNType12[] = "user_firstname" , sNType13[] = "user_lastname" , sNType14[] = "user_initials", sNType15[] = "user_street" , sNType16[] = "user_country" , sNType17[] = "user_zipcode" , sNType18[] = "user_city" , sNType19[] = "user_title" , sNType20[] = "user_position" , sNType21[] = "user_tel_home", sNType22[] = "user_tel_work", sNType23[] = "user_fax" , sNType24[] = "user_email" , sNType25[] = "user_state", sNType26[] = "graph" ; static const sal_Char* sNTypeTab[ 27 ] = { sNType0, sNType1, sNType2, sNType3, sNType4, sNType5, sNType6, sNType7, sNType8, sNType9, sNType10, sNType11, sNType12, sNType13, sNType14, sNType15, sNType16, sNType17, sNType18, sNType19, sNType20, sNType21, sNType22, sNType23, sNType24, sNType25, sNType26 }; const unsigned short nTblSize = 47; int aArr[ nTblSize ] = { 0 }; sal_Char ch; for( int n = 0; n < 27; ++n ) { unsigned long ii = 0; const sal_Char* pp = sNTypeTab[ n ]; while( *pp ) ii = ii << 1 ^ *pp++; ii %= nTblSize; ch = aArr[ ii ] ? 'X' : ' '; aArr[ ii ] = 1; printf( "%-20s -> %3d [%c]\n", sNTypeTab[ n ], ii, ch ); } } #endif