1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: calc.cxx,v $
10 * $Revision: 1.44.174.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
43 #include <hintids.hxx>
44 #include <rtl/math.hxx>
45 #include <svx/langitem.hxx>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <comphelper/processfactory.hxx>
48 #include <unotools/localedatawrapper.hxx>
49 #include <unotools/charclass.hxx>
50 #include <svx/unolingu.hxx>
51 #include <svx/scripttypeitem.hxx>
52 #include <svtools/useroptions.hxx>
53 #include <tools/datetime.hxx>
54 #include <svtools/zforlist.hxx>
55 #include <swmodule.hxx>
58 #include <docstat.hxx>
60 #include <shellres.hxx>
68 #include <swunodef.hxx>
69 #include <swtypes.hxx>
71 using namespace ::com::sun::star
;
73 // tippt sich schneller
74 #define RESOURCE ViewShell::GetShellRes()
76 const sal_Char __FAR_DATA sCalc_Add
[] = "add";
77 const sal_Char __FAR_DATA sCalc_Sub
[] = "sub";
78 const sal_Char __FAR_DATA sCalc_Mul
[] = "mul";
79 const sal_Char __FAR_DATA sCalc_Div
[] = "div";
80 const sal_Char __FAR_DATA sCalc_Phd
[] = "phd";
81 const sal_Char __FAR_DATA sCalc_Sqrt
[] = "sqrt";
82 const sal_Char __FAR_DATA sCalc_Pow
[] = "pow";
83 const sal_Char __FAR_DATA sCalc_Or
[] = "or";
84 const sal_Char __FAR_DATA sCalc_Xor
[] = "xor";
85 const sal_Char __FAR_DATA sCalc_And
[] = "and";
86 const sal_Char __FAR_DATA sCalc_Not
[] = "not";
87 const sal_Char __FAR_DATA sCalc_Eq
[] = "eq";
88 const sal_Char __FAR_DATA sCalc_Neq
[] = "neq";
89 const sal_Char __FAR_DATA sCalc_Leq
[] = "leq";
90 const sal_Char __FAR_DATA sCalc_Geq
[] = "geq";
91 const sal_Char __FAR_DATA sCalc_L
[] = "l";
92 const sal_Char __FAR_DATA sCalc_G
[] = "g";
93 const sal_Char __FAR_DATA sCalc_Sum
[] = "sum";
94 const sal_Char __FAR_DATA sCalc_Mean
[] = "mean";
95 const sal_Char __FAR_DATA sCalc_Min
[] = "min";
96 const sal_Char __FAR_DATA sCalc_Max
[] = "max";
97 const sal_Char __FAR_DATA sCalc_Sin
[] = "sin";
98 const sal_Char __FAR_DATA sCalc_Cos
[] = "cos";
99 const sal_Char __FAR_DATA sCalc_Tan
[] = "tan";
100 const sal_Char __FAR_DATA sCalc_Asin
[] = "asin";
101 const sal_Char __FAR_DATA sCalc_Acos
[] = "acos";
102 const sal_Char __FAR_DATA sCalc_Atan
[] = "atan";
103 const sal_Char __FAR_DATA sCalc_Round
[] = "round";
104 const sal_Char __FAR_DATA sCalc_Date
[] = "date";
108 //!!!!! ACHTUNG - Sortierte Liste aller Operatoren !!!!!
112 const sal_Char
* pName
;
113 const String
* pUName
;
118 _CalcOp __READONLY_DATA aOpTable
[] = {
119 /* ACOS */ {{sCalc_Acos
}, CALC_ACOS
}, // Arcuscosinus
120 /* ADD */ {{sCalc_Add
}, CALC_PLUS
}, // Addition
121 /* AND */ {{sCalc_And
}, CALC_AND
}, // log. und
122 /* ASIN */ {{sCalc_Asin
}, CALC_ASIN
}, // Arcussinus
123 /* ATAN */ {{sCalc_Atan
}, CALC_ATAN
}, // Arcustangens
124 /* COS */ {{sCalc_Cos
}, CALC_COS
}, // Cosinus
125 /* DATE */ {{sCalc_Date
}, CALC_DATE
}, // Date
126 /* DIV */ {{sCalc_Div
}, CALC_DIV
}, // Dividieren
127 /* EQ */ {{sCalc_Eq
}, CALC_EQ
}, // gleich
128 /* G */ {{sCalc_G
}, CALC_GRE
}, // groesser
129 /* GEQ */ {{sCalc_Geq
}, CALC_GEQ
}, // groesser gleich
130 /* L */ {{sCalc_L
}, CALC_LES
}, // kleiner
131 /* LEQ */ {{sCalc_Leq
}, CALC_LEQ
}, // kleiner gleich
132 /* MAX */ {{sCalc_Max
}, CALC_MAX
}, // Maximalwert
133 /* MEAN */ {{sCalc_Mean
}, CALC_MEAN
}, // Mittelwert
134 /* MIN */ {{sCalc_Min
}, CALC_MIN
}, // Minimalwert
135 /* MUL */ {{sCalc_Mul
}, CALC_MUL
}, // Multiplizieren
136 /* NEQ */ {{sCalc_Neq
}, CALC_NEQ
}, // nicht gleich
137 /* NOT */ {{sCalc_Not
}, CALC_NOT
}, // log. nicht
138 /* OR */ {{sCalc_Or
}, CALC_OR
}, // log. oder
139 /* PHD */ {{sCalc_Phd
}, CALC_PHD
}, // Prozent
140 /* POW */ {{sCalc_Pow
}, CALC_POW
}, // Potenzieren
141 /* ROUND */ {{sCalc_Round
}, CALC_ROUND
}, // Runden
142 /* SIN */ {{sCalc_Sin
}, CALC_SIN
}, // Sinus
143 /* SQRT */ {{sCalc_Sqrt
}, CALC_SQRT
}, // Wurzel
144 /* SUB */ {{sCalc_Sub
}, CALC_MINUS
}, // Subtraktion
145 /* SUM */ {{sCalc_Sum
}, CALC_SUM
}, // Summe
146 /* TAN */ {{sCalc_Tan
}, CALC_TAN
}, // Tangens
147 /* XOR */ {{sCalc_Xor
}, CALC_XOR
} // log. xoder
150 double __READONLY_DATA nRoundVal
[] = {
151 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
152 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,
156 double __READONLY_DATA nKorrVal
[] = {
157 9, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
158 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14
161 // First character may be any alphabetic or underscore.
162 const sal_Int32 coStartFlags
=
163 i18n::KParseTokens::ANY_LETTER_OR_NUMBER
|
164 i18n::KParseTokens::ASC_UNDERSCORE
|
165 i18n::KParseTokens::IGNORE_LEADING_WS
;
167 // Continuing characters may be any alphanumeric or underscore or dot.
168 const sal_Int32 coContFlags
=
169 ( coStartFlags
| i18n::KParseTokens::ASC_DOT
)
170 & ~i18n::KParseTokens::IGNORE_LEADING_WS
;
181 OperatorCompare( const void *pFirst
, const void *pSecond
)
184 if( CALC_NAME
== ((_CalcOp
*)pFirst
)->eOp
)
186 if( CALC_NAME
== ((_CalcOp
*)pSecond
)->eOp
)
187 nRet
= ((_CalcOp
*)pFirst
)->pUName
->CompareTo(
188 *((_CalcOp
*)pSecond
)->pUName
);
190 nRet
= ((_CalcOp
*)pFirst
)->pUName
->CompareToAscii(
191 ((_CalcOp
*)pSecond
)->pName
);
195 if( CALC_NAME
== ((_CalcOp
*)pSecond
)->eOp
)
196 nRet
= -1 * ((_CalcOp
*)pSecond
)->pUName
->CompareToAscii(
197 ((_CalcOp
*)pFirst
)->pName
);
199 nRet
= strcmp( ((_CalcOp
*)pFirst
)->pName
,
200 ((_CalcOp
*)pSecond
)->pName
);
207 _CalcOp
* FindOperator( const String
& rSrch
)
210 aSrch
.pUName
= &rSrch
;
211 aSrch
.eOp
= CALC_NAME
;
213 return (_CalcOp
*)bsearch( (void*) &aSrch
,
215 sizeof( aOpTable
) / sizeof( _CalcOp
),
221 //-----------------------------------------------------------------------------
223 SwHash
* Find( const String
& rStr
, SwHash
** ppTable
, USHORT nTblSize
,
227 for( xub_StrLen n
= 0; n
< rStr
.Len(); ++n
)
228 ii
= ii
<< 1 ^ rStr
.GetChar( n
);
234 for( SwHash
* pEntry
= *(ppTable
+ii
); pEntry
; pEntry
= pEntry
->pNext
)
235 if( rStr
== pEntry
->aStr
)
240 inline LanguageType
GetDocAppScriptLang( SwDoc
& rDoc
)
242 return ((SvxLanguageItem
&)rDoc
.GetDefault(
243 GetWhichOfScript( RES_CHRATR_LANGUAGE
,
244 GetI18NScriptTypeOfLanguage( (USHORT
)GetAppLanguage() ))
248 double lcl_ConvertToDateValue( SwDoc
& rDoc
, sal_Int32 nDate
)
251 SvNumberFormatter
* pFormatter
= rDoc
.GetNumberFormatter();
254 Date
* pNull
= pFormatter
->GetNullDate();
255 Date
aDate( nDate
>> 24, (nDate
& 0x00FF0000) >> 16, nDate
& 0x0000FFFF );
256 nRet
= aDate
- *pNull
;
261 //-----------------------------------------------------------------------------
263 /******************************************************************************
265 |* SwCalc::SwCalc( SwDoc* pD ) :
267 |* Erstellung OK 12-02-93 11:04am
268 |* Letzte Aenderung JP 03.11.95
270 |******************************************************************************/
272 SwCalc::SwCalc( SwDoc
& rD
)
274 aErrExpr( aEmptyStr
, SwSbxValue(), 0 ),
276 pLclData( &SvtSysLocale().GetLocaleData() ),
277 pCharClass( &GetAppCharClass() ),
281 aErrExpr
.aStr
.AssignAscii( "~C_ERR~" );
282 memset( VarTable
, 0, sizeof(VarTable
) );
283 LanguageType eLang
= GetDocAppScriptLang( rDoc
);
285 if( eLang
!= SvxLocaleToLanguage( pLclData
->getLocale() ) ||
286 eLang
!= SvxLocaleToLanguage( pCharClass
->getLocale() ) )
288 STAR_NMSPC::lang::Locale
aLocale( SvxCreateLocale( eLang
));
289 STAR_REFERENCE( lang::XMultiServiceFactory
) xMSF(
290 ::comphelper::getProcessServiceFactory() );
291 pCharClass
= new CharClass( xMSF
, aLocale
);
292 pLclData
= new LocaleDataWrapper( xMSF
, aLocale
);
295 sCurrSym
= pLclData
->getCurrSymbol();
296 sCurrSym
.EraseLeadingChars().EraseTrailingChars();
297 pCharClass
->toLower( sCurrSym
);
299 static sal_Char __READONLY_DATA
304 sNType4
[] = "tables",
312 sNType11
[] = "user_firstname" ,
313 sNType12
[] = "user_lastname" ,
314 sNType13
[] = "user_initials" ,
315 sNType14
[] = "user_company" ,
316 sNType15
[] = "user_street" ,
317 sNType16
[] = "user_country" ,
318 sNType17
[] = "user_zipcode" ,
319 sNType18
[] = "user_city" ,
320 sNType19
[] = "user_title" ,
321 sNType20
[] = "user_position" ,
322 sNType21
[] = "user_tel_work" ,
323 sNType22
[] = "user_tel_home" ,
324 sNType23
[] = "user_fax" ,
325 sNType24
[] = "user_email" ,
326 sNType25
[] = "user_state" ,
330 static const sal_Char
* __READONLY_DATA sNTypeTab
[ 27 ] =
332 sNType0
, sNType1
, sNType2
, sNType3
, sNType4
, sNType5
,
333 sNType6
, sNType7
, sNType8
, sNType9
, sNType10
, sNType11
,
334 sNType12
, sNType13
, sNType14
, sNType15
, sNType16
, sNType17
,
335 sNType18
, sNType19
, sNType20
, sNType21
, sNType22
, sNType23
,
338 // diese sind mit doppelten HashIds
341 static USHORT __READONLY_DATA aHashValue
[ 27 ] =
343 34, 38, 43, 7, 18, 32, 22, 29, 30, 33, 3,
344 28, 24, 40, 9, 11, 26, 45, 4, 23, 36, 44, 19, 5, 1,
345 // diese sind mit doppelten HashIds
348 static USHORT __READONLY_DATA aAdrToken
[ 12 ] =
350 USER_OPT_COMPANY
, USER_OPT_STREET
, USER_OPT_COUNTRY
, USER_OPT_ZIP
,
351 USER_OPT_CITY
, USER_OPT_TITLE
, USER_OPT_POSITION
, USER_OPT_TELEPHONEWORK
,
352 USER_OPT_TELEPHONEHOME
, USER_OPT_FAX
, USER_OPT_EMAIL
, USER_OPT_STATE
355 static USHORT
SwDocStat::* __READONLY_DATA aDocStat1
[ 3 ] =
357 &SwDocStat::nTbl
, &SwDocStat::nGrf
, &SwDocStat::nOLE
359 static ULONG
SwDocStat::* __READONLY_DATA aDocStat2
[ 4 ] =
361 &SwDocStat::nPage
, &SwDocStat::nPara
,
362 &SwDocStat::nWord
, &SwDocStat::nChar
366 #error Alle Hashwerte angepasst?
369 const SwDocStat
& rDocStat
= rDoc
.GetDocStat();
375 for( n
= 0; n
< 25; ++n
)
377 sTmpStr
.AssignAscii( sNTypeTab
[ n
] );
378 VarTable
[ aHashValue
[ n
] ] = new SwCalcExp( sTmpStr
, nVal
, 0 );
381 ((SwCalcExp
*)VarTable
[ aHashValue
[ 0 ] ])->nValue
.PutBool( FALSE
);
382 ((SwCalcExp
*)VarTable
[ aHashValue
[ 1 ] ])->nValue
.PutBool( TRUE
);
383 ((SwCalcExp
*)VarTable
[ aHashValue
[ 2 ] ])->nValue
.PutDouble( F_PI
);
384 ((SwCalcExp
*)VarTable
[ aHashValue
[ 3 ] ])->nValue
.PutDouble( 2.7182818284590452354 );
386 for( n
= 0; n
< 3; ++n
)
387 ((SwCalcExp
*)VarTable
[ aHashValue
[ n
+ 4 ] ])->nValue
.PutLong( rDocStat
.*aDocStat1
[ n
] );
388 for( n
= 0; n
< 4; ++n
)
389 ((SwCalcExp
*)VarTable
[ aHashValue
[ n
+ 7 ] ])->nValue
.PutLong( rDocStat
.*aDocStat2
[ n
] );
391 SvtUserOptions
& rUserOptions
= SW_MOD()->GetUserOptions();
393 ((SwCalcExp
*)VarTable
[ aHashValue
[ 11 ] ])->nValue
.PutString( (String
)rUserOptions
.GetFirstName() );
394 ((SwCalcExp
*)VarTable
[ aHashValue
[ 12 ] ])->nValue
.PutString( (String
)rUserOptions
.GetLastName() );
395 ((SwCalcExp
*)VarTable
[ aHashValue
[ 13 ] ])->nValue
.PutString( (String
)rUserOptions
.GetID() );
397 for( n
= 0; n
< 11; ++n
)
398 ((SwCalcExp
*)VarTable
[ aHashValue
[ n
+ 14 ] ])->nValue
.PutString(
399 (String
)rUserOptions
.GetToken( aAdrToken
[ n
] ));
401 nVal
.PutString( (String
)rUserOptions
.GetToken( aAdrToken
[ 11 ] ));
402 sTmpStr
.AssignAscii( sNTypeTab
[ 25 ] );
403 VarTable
[ aHashValue
[ 25 ] ]->pNext
= new SwCalcExp( sTmpStr
, nVal
, 0 );
405 // at time its better not to use "graph", because then the im-/export have
406 // to change in all formulas this name.
407 // nVal.PutLong( rDocStat.*aDocStat1[ 1 ] );
408 // VarTable[ aHashValue[ 26 ] ]->pNext = new SwCalcExp(
409 // sNTypeTab[ 26 ], nVal, 0 );
412 /******************************************************************************
416 |* Erstellung OK 12-02-93 11:04am
417 |* Letzte Aenderung OK 12-02-93 11:04am
419 |******************************************************************************/
423 for( USHORT n
= 0; n
< TBLSZ
; ++n
)
425 if( pLclData
!= &SvtSysLocale().GetLocaleData() )
427 if( pCharClass
!= &GetAppCharClass() )
431 /******************************************************************************
433 |* SwSbxValue SwCalc::Calculate( const String& rStr )
435 |* Erstellung OK 12-02-93 11:04am
436 |* Letzte Aenderung OK 12-02-93 11:04am
438 |******************************************************************************/
440 SwSbxValue
SwCalc::Calculate( const String
& rStr
)
449 eCurrListOper
= CALC_PLUS
; // defaulten auf Summe
454 while( (eCurrOper
= GetToken()) != CALC_ENDCALC
&& eError
== CALC_NOERR
)
458 nResult
.PutDouble( DBL_MAX
);
463 /******************************************************************************
465 |* String SwCalc::GetStrResult( SwSbxValue nValue, BOOL bRound = TRUE )
466 |* Beschreibung Der Parameter bRound ist auf TRUE defaultet und darf
467 |* nur beim errechnen von Tabellenzellen auf FALSE gesetzt
468 |* werden, damit keine Rundungsfehler beim zusammenstellen
469 |* der Formel entstehen.
470 |* Erstellung OK 12-02-93 11:04am
471 |* Letzte Aenderung JP 19.02.98
473 |******************************************************************************/
475 String
SwCalc::GetStrResult( const SwSbxValue
& rVal
, BOOL bRound
)
477 if( !rVal
.IsDouble() )
478 return rVal
.GetString();
480 return GetStrResult( rVal
.GetDouble(), bRound
);
484 String
SwCalc::GetStrResult( double nValue
, BOOL
)
486 if( nValue
>= DBL_MAX
)
489 case CALC_SYNTAX
: return RESOURCE
->aCalc_Syntax
;
490 case CALC_ZERODIV
: return RESOURCE
->aCalc_ZeroDiv
;
491 case CALC_BRACK
: return RESOURCE
->aCalc_Brack
;
492 case CALC_POWERR
: return RESOURCE
->aCalc_Pow
;
493 case CALC_VARNFND
: return RESOURCE
->aCalc_VarNFnd
;
494 case CALC_OVERFLOW
: return RESOURCE
->aCalc_Overflow
;
495 case CALC_WRONGTIME
: return RESOURCE
->aCalc_WrongTime
;
496 default : return RESOURCE
->aCalc_Default
;
499 USHORT nDec
= 15; //pLclData->getNumDigits();
500 String
aRetStr( ::rtl::math::doubleToUString( nValue
,
501 rtl_math_StringFormat_Automatic
,
503 pLclData
->getNumDecimalSep().GetChar(0),
509 /******************************************************************************
511 |* SwCalcExp* SwCalc::VarLook( const String& )
513 |* Erstellung OK 12-02-93 11:04am
514 |* Letzte Aenderung JP 15.11.99
516 |******************************************************************************/
518 SwCalcExp
* SwCalc::VarInsert( const String
&rStr
)
521 pCharClass
->toLower( aStr
);
522 return VarLook( aStr
, 1 );
525 /******************************************************************************
527 |* SwCalcExp* SwCalc::VarLook( const String& , USHORT ins )
529 |* Erstellung OK 12-02-93 11:04am
530 |* Letzte Aenderung JP 15.11.99
532 |******************************************************************************/
533 SwCalcExp
* SwCalc::VarLook( const String
& rStr
, USHORT ins
)
535 aErrExpr
.nValue
.SetVoidValue(false);
539 pCharClass
->toLower( aStr
);
541 SwHash
* pFnd
= Find( aStr
, VarTable
, TBLSZ
, &ii
);
545 // dann sehen wir mal im Doc nach:
546 SwHash
** ppDocTbl
= rDoc
.GetUpdtFlds().GetFldTypeTable();
547 for( SwHash
* pEntry
= *(ppDocTbl
+ii
); pEntry
; pEntry
= pEntry
->pNext
)
548 if( aStr
== pEntry
->aStr
)
550 // dann hier zufuegen
551 pFnd
= new SwCalcExp( aStr
, SwSbxValue(),
552 ((SwCalcFldType
*)pEntry
)->pFldType
);
553 pFnd
->pNext
= *(VarTable
+ii
);
554 *(VarTable
+ii
) = pFnd
;
561 SwCalcExp
* pFndExp
= (SwCalcExp
*)pFnd
;
563 if( pFndExp
->pFldType
&& pFndExp
->pFldType
->Which() == RES_USERFLD
)
565 SwUserFieldType
* pUFld
= (SwUserFieldType
*)pFndExp
->pFldType
;
566 if( nsSwGetSetExpType::GSE_STRING
& pUFld
->GetType() )
567 pFndExp
->nValue
.PutString( pUFld
->GetContent() );
568 else if( !pUFld
->IsValid() )
570 // Die aktuellen Werte sichern . . .
571 USHORT nOld_ListPor
= nListPor
;
572 SwSbxValue nOld_LastLeft
= nLastLeft
;
573 SwSbxValue nOld_NumberValue
= nNumberValue
;
574 xub_StrLen nOld_CommandPos
= nCommandPos
;
575 SwCalcOper eOld_CurrOper
= eCurrOper
;
576 SwCalcOper eOld_CurrListOper
= eCurrListOper
;
578 pFndExp
->nValue
.PutDouble( pUFld
->GetValue( *this ) );
580 // . . . und zurueck damit.
581 nListPor
= nOld_ListPor
;
582 nLastLeft
= nOld_LastLeft
;
583 nNumberValue
= nOld_NumberValue
;
584 nCommandPos
= nOld_CommandPos
;
585 eCurrOper
= eOld_CurrOper
;
586 eCurrListOper
= eOld_CurrListOper
;
589 pFndExp
->nValue
.PutDouble( pUFld
->GetValue() );
594 // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER
595 // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!")
596 // #101436#: At this point the "real" case variable has to be used
597 String
sTmpName( rStr
);
598 ::ReplacePoint( sTmpName
);
602 SwNewDBMgr
*pMgr
= rDoc
.GetNewDBMgr();
604 // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER
605 // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!")
606 String
sDBName(GetDBName( sTmpName
));
607 String
sSourceName(sDBName
.GetToken(0, DB_DELIM
));
608 String
sTableName(sDBName
.GetToken(0).GetToken(1, DB_DELIM
));
609 if( pMgr
&& sSourceName
.Len() && sTableName
.Len() &&
610 pMgr
->OpenDataSource(sSourceName
, sTableName
, -1, false))
612 String
sColumnName( GetColumnName( sTmpName
));
613 ASSERT (sColumnName
.Len(), "DB-Spaltenname fehlt!");
615 String
sDBNum( SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD
) );
616 pCharClass
->toLower(sDBNum
);
618 // Hier nochmal initialisieren, da das nicht mehr in docfld
619 // fuer Felder != RES_DBFLD geschieht. Z.B. wenn ein Expressionfield
620 // vor einem DB_Field in einem Dok vorkommt.
621 VarChange( sDBNum
, pMgr
->GetSelectedRecordId(sSourceName
, sTableName
));
623 if( sDBNum
.EqualsIgnoreCaseAscii(sColumnName
) )
625 aErrExpr
.nValue
.PutLong(long(pMgr
->GetSelectedRecordId(sSourceName
, sTableName
)));
630 if( 0 != ( pFnd
= Find( sDBNum
, VarTable
, TBLSZ
) ) )
631 nTmpRec
= ((SwCalcExp
*)pFnd
)->nValue
.GetULong();
634 double nNumber
= DBL_MAX
;
636 long nLang
= SvxLocaleToLanguage( pLclData
->getLocale() );
637 if(pMgr
->GetColumnCnt( sSourceName
, sTableName
, sColumnName
,
638 nTmpRec
, nLang
, sResult
, &nNumber
))
640 if (nNumber
!= DBL_MAX
)
641 aErrExpr
.nValue
.PutDouble( nNumber
);
643 aErrExpr
.nValue
.PutString( sResult
);
650 //data source was not available - set return to "NoValue"
651 aErrExpr
.nValue
.SetVoidValue(true);
653 // auf keinen fall eintragen!!
658 SwCalcExp
* pNewExp
= new SwCalcExp( aStr
, SwSbxValue(), 0 );
659 pNewExp
->pNext
= VarTable
[ ii
];
660 VarTable
[ ii
] = pNewExp
;
662 String
sColumnName( GetColumnName( sTmpName
));
663 ASSERT( sColumnName
.Len(), "DB-Spaltenname fehlt!" );
664 if( sColumnName
.EqualsIgnoreCaseAscii(
665 SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD
) ))
667 SwNewDBMgr
*pMgr
= rDoc
.GetNewDBMgr();
668 String
sDBName(GetDBName( sTmpName
));
669 String
sSourceName(sDBName
.GetToken(0, DB_DELIM
));
670 String
sTableName(sDBName
.GetToken(0).GetToken(1, DB_DELIM
));
671 if( pMgr
&& sSourceName
.Len() && sTableName
.Len() &&
672 pMgr
->OpenDataSource(sSourceName
, sTableName
, -1, false) &&
674 pNewExp
->nValue
.PutULong( pMgr
->GetSelectedRecordId(sSourceName
, sTableName
));
676 pNewExp
->nValue
.SetVoidValue(true);
682 /******************************************************************************
684 |* BOOL SwCalc::VarChange( const String& rStr, const SwSbxValue nValue )
686 |* Erstellung OK 12-02-93 11:04am
687 |* Letzte Aenderung OK 12-02-93 11:04am
689 |******************************************************************************/
691 void SwCalc::VarChange( const String
& rStr
, double nValue
)
693 SwSbxValue
aVal( nValue
);
694 VarChange( rStr
, aVal
);
697 void SwCalc::VarChange( const String
& rStr
, const SwSbxValue
& rValue
)
700 pCharClass
->toLower( aStr
);
703 SwCalcExp
* pFnd
= (SwCalcExp
*)Find( aStr
, VarTable
, TBLSZ
, &nPos
);
707 pFnd
= new SwCalcExp( aStr
, SwSbxValue( rValue
), 0 );
708 pFnd
->pNext
= VarTable
[ nPos
];
709 VarTable
[ nPos
] = pFnd
;
712 pFnd
->nValue
= rValue
;
715 /******************************************************************************
717 |* BOOL SwCalc::Push( const void* pPtr )
719 |* Erstellung OK 12-02-93 11:05am
720 |* Letzte Aenderung OK 12-02-93 11:05am
722 |******************************************************************************/
724 BOOL
SwCalc::Push( const VoidPtr pPtr
)
726 if( USHRT_MAX
!= aRekurStk
.GetPos( pPtr
) )
729 aRekurStk
.Insert( pPtr
, aRekurStk
.Count() );
733 /******************************************************************************
735 |* void SwCalc::Pop( const void* pPtr )
737 |* Erstellung OK 12-02-93 11:05am
738 |* Letzte Aenderung OK 12-02-93 11:05am
740 |******************************************************************************/
742 void SwCalc::Pop( const VoidPtr
)
744 ASSERT( aRekurStk
.Count(), "SwCalc: Pop auf ungueltigen Ptr" );
746 aRekurStk
.Remove( aRekurStk
.Count() - 1 );
750 /******************************************************************************
752 |* SwCalcOper SwCalc::GetToken()
754 |* Erstellung OK 12-02-93 11:05am
755 |* Letzte Aenderung JP 03.11.95
757 |******************************************************************************/
759 SwCalcOper
SwCalc::GetToken()
761 #if OSL_DEBUG_LEVEL > 1
762 //JP 25.01.2001: static for switch back to the "old" implementation of the
763 // calculator, which don't use the I18N routines.
764 static int nUseOld
= 0;
769 if( nCommandPos
>= sCommand
.Len() )
770 return eCurrOper
= CALC_ENDCALC
;
772 using namespace ::com::sun::star::i18n
;
775 ParseResult aRes
= pCharClass
->parseAnyToken( sCommand
, nCommandPos
,
776 coStartFlags
, aEmptyStr
,
777 coContFlags
, aEmptyStr
);
779 BOOL bSetError
= TRUE
;
780 xub_StrLen nRealStt
= nCommandPos
+ (xub_StrLen
)aRes
.LeadingWhiteSpace
;
781 if( aRes
.TokenType
& (KParseType::ASC_NUMBER
| KParseType::UNI_NUMBER
) )
783 nNumberValue
.PutDouble( aRes
.Value
);
784 eCurrOper
= CALC_NUMBER
;
787 else if( aRes
.TokenType
& KParseType::IDENTNAME
)
789 String
aName( sCommand
.Copy( nRealStt
, static_cast<xub_StrLen
>(aRes
.EndPos
) - nRealStt
));
790 //#101436#: the variable may contain a database name it must not be converted to lower case
791 // instead all further comparisons must be done case-insensitive
792 //pCharClass->toLower( aName );
793 String
sLowerCaseName(aName
);
794 pCharClass
->toLower( sLowerCaseName
);
795 // Currency-Symbol abfangen
796 if( sLowerCaseName
== sCurrSym
)
798 nCommandPos
= (xub_StrLen
)aRes
.EndPos
;
799 return GetToken(); // also nochmal aufrufen
802 // Operations abfangen
803 _CalcOp
* pFnd
= ::FindOperator( sLowerCaseName
);
806 switch( ( eCurrOper
= ((_CalcOp
*)pFnd
)->eOp
) )
810 eCurrListOper
= CALC_PLUS
;
813 eCurrListOper
= CALC_MIN_IN
;
816 eCurrListOper
= CALC_MAX_IN
;
819 eCurrListOper
= CALC_MONTH
;
824 nCommandPos
= (xub_StrLen
)aRes
.EndPos
;
828 eCurrOper
= CALC_NAME
;
831 else if ( aRes
.TokenType
& KParseType::DOUBLE_QUOTE_STRING
)
833 nNumberValue
.PutString( String( aRes
.DequotedNameOrString
));
834 eCurrOper
= CALC_NUMBER
;
837 else if( aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
839 String
aName( sCommand
.Copy( nRealStt
, static_cast<xub_StrLen
>(aRes
.EndPos
) - nRealStt
));
840 if( 1 == aName
.Len() )
843 sal_Unicode ch
= aName
.GetChar( 0 );
846 case ';': if( CALC_MONTH
== eCurrListOper
||
847 CALC_DAY
== eCurrListOper
)
849 eCurrOper
= eCurrListOper
;
853 eCurrOper
= CALC_PRINT
;
862 case ')': eCurrOper
= SwCalcOper(ch
);
870 eCurrOper
= SwCalcOper('='), eTmp2
= CALC_EQ
;
872 eCurrOper
= CALC_NOT
, eTmp2
= CALC_NEQ
;
874 if( aRes
.EndPos
< sCommand
.Len() &&
875 '=' == sCommand
.GetChar( (xub_StrLen
)aRes
.EndPos
) )
884 eCurrOper
= eCurrListOper
;
888 if( aRes
.EndPos
< sCommand
.Len() )
891 xub_StrLen nFndPos
= (xub_StrLen
)aRes
.EndPos
,
895 if( STRING_NOTFOUND
!= ( nFndPos
=
896 sCommand
.Search( ']', nFndPos
)) )
899 if( '\\' == sCommand
.GetChar(nFndPos
-1))
901 aVarName
+= sCommand
.Copy( nSttPos
,
902 nFndPos
- nSttPos
- 1 );
908 } while( STRING_NOTFOUND
!= nFndPos
);
910 if( STRING_NOTFOUND
!= nFndPos
)
912 if( nSttPos
!= nFndPos
)
913 aVarName
+= sCommand
.Copy( nSttPos
,
915 aRes
.EndPos
= nFndPos
+ 1;
916 eCurrOper
= CALC_NAME
;
931 else if( aRes
.TokenType
& KParseType::BOOLEAN
)
933 String
aName( sCommand
.Copy( nRealStt
, static_cast<xub_StrLen
>(aRes
.EndPos
) - nRealStt
));
936 sal_Unicode ch
= aName
.GetChar(0);
939 if ('<' == ch
|| '>' == ch
)
943 SwCalcOper eTmp2
= ('<' == ch
) ? CALC_LEQ
: CALC_GEQ
;
944 eCurrOper
= ('<' == ch
) ? CALC_LES
: CALC_GRE
;
946 if( 2 == aName
.Len() && '=' == aName
.GetChar(1) )
948 else if( 1 != aName
.Len() )
953 else if( nRealStt
== sCommand
.Len() )
955 eCurrOper
= CALC_ENDCALC
;
961 eError
= CALC_SYNTAX
;
962 eCurrOper
= CALC_PRINT
;
964 nCommandPos
= (xub_StrLen
)aRes
.EndPos
;
967 #if OSL_DEBUG_LEVEL > 1
969 #define NextCh( s, n ) (nCommandPos < sCommand.Len() ? sCommand.GetChar( nCommandPos++ ) : 0)
975 sal_Unicode cTSep
= pLclData
->getNumThousandSep().GetChar(0),
976 cDSep
= pLclData
->getNumDecimalSep().GetChar(0);
979 if( 0 == ( ch
= NextCh( sCommand
, nCommandPos
) ) )
980 return eCurrOper
= CALC_ENDCALC
;
981 } while ( ch
== '\t' || ch
== ' ' || ch
== cTSep
);
988 case ';': if( CALC_MONTH
== eCurrListOper
|| CALC_DAY
== eCurrListOper
)
990 eCurrOper
= eCurrListOper
;
992 } // else .. no break
996 while( nCommandPos
< sCommand
.Len() && ( ( c
=
997 sCommand
.GetChar( nCommandPos
) ) == ' ' ||
998 c
== '\t' || c
== '\x0a' || c
== '\x0d' ))
1000 eCurrOper
= CALC_PRINT
;
1010 case ')': eCurrOper
= SwCalcOper(ch
);
1013 case '=': if( '=' == sCommand
.GetChar( nCommandPos
) )
1016 eCurrOper
= CALC_EQ
;
1019 eCurrOper
= SwCalcOper(ch
);
1022 case '!': if( '=' == sCommand
.GetChar( nCommandPos
) )
1025 eCurrOper
= CALC_NEQ
;
1028 eCurrOper
= CALC_NOT
;
1032 case '<': eCurrOper
= '>' == ch
? CALC_GRE
: CALC_LES
;
1033 if( '=' == (ch
= sCommand
.GetChar( nCommandPos
) ) )
1036 eCurrOper
= CALC_GRE
== eCurrOper
? CALC_GEQ
: CALC_LEQ
;
1038 else if( ' ' != ch
)
1040 eError
= CALC_SYNTAX
;
1041 eCurrOper
= CALC_PRINT
;
1046 eCurrOper
= eCurrListOper
;
1049 case '0': case '1': case '2': case '3': case '4':
1050 case '5': case '6': case '7': case '8': case '9':
1054 --nCommandPos
; // auf das 1. Zeichen zurueck
1055 if( Str2Double( sCommand
, nCommandPos
, nVal
, pLclData
))
1057 nNumberValue
.PutDouble( nVal
);
1058 eCurrOper
= CALC_NUMBER
;
1063 eError
= CALC_SYNTAX
;
1064 eCurrOper
= CALC_PRINT
;
1071 BOOL bIgnore
= FALSE
;
1073 while( 0 != ( ch
= NextCh( sCommand
, nCommandPos
))
1076 if( !bIgnore
&& '\\' == ch
)
1086 aStr
.SetChar( aStr
.Len() - 1, ch
);
1090 eCurrOper
= CALC_NAME
;
1095 xub_StrLen nStt
= nCommandPos
;
1096 while( 0 != ( ch
= NextCh( sCommand
, nCommandPos
) )
1100 xub_StrLen nLen
= nCommandPos
- nStt
;
1103 nNumberValue
.PutString( sCommand
.Copy( nStt
, nLen
));
1104 eCurrOper
= CALC_NUMBER
;
1108 default: if( ch
&& pCharClass
->isLetter( sCommand
, nCommandPos
- 1)
1111 xub_StrLen nStt
= nCommandPos
-1;
1112 while( 0 != (ch
= NextCh( sCommand
, nCommandPos
)) &&
1113 (pCharClass
->isLetterNumeric(
1114 sCommand
, nCommandPos
- 1) ||
1115 ch
== '_' || ch
== '.' ) )
1121 String
aStr( sCommand
.Copy( nStt
, nCommandPos
-nStt
));
1122 pCharClass
->toLower( aStr
);
1125 // Currency-Symbol abfangen
1126 if( aStr
== sCurrSym
)
1127 return GetToken(); // also nochmal aufrufen
1129 // Operations abfangen
1130 _CalcOp
* pFnd
= ::FindOperator( aStr
);
1133 switch( ( eCurrOper
= ((_CalcOp
*)pFnd
)->eOp
) )
1136 case CALC_MEAN
: eCurrListOper
= CALC_PLUS
;
1138 case CALC_MIN
: eCurrListOper
= CALC_MIN_IN
;
1140 case CALC_MAX
: eCurrListOper
= CALC_MAX_IN
;
1142 case CALC_DATE
: eCurrListOper
= CALC_MONTH
;
1150 eCurrOper
= CALC_NAME
;
1154 eError
= CALC_SYNTAX
;
1155 eCurrOper
= CALC_PRINT
;
1165 /******************************************************************************
1167 |* SwSbxValue SwCalc::Term()
1169 |* Erstellung OK 12-02-93 11:05am
1170 |* Letzte Aenderung JP 16.01.96
1172 |******************************************************************************/
1174 SwSbxValue
SwCalc::Term()
1176 SwSbxValue
left( Prim() );
1180 USHORT nSbxOper
= USHRT_MAX
;
1184 // wir haben kein Bitweises verodern, oder ?
1185 // case CALC_AND: eSbxOper = SbxAND; break;
1186 // case CALC_OR: eSbxOper = SbxOR; break;
1187 // case CALC_XOR: eSbxOper = SbxXOR; break;
1190 BOOL bB
= Prim().GetBool();
1191 left
.PutBool( left
.GetBool() && bB
);
1196 BOOL bB
= Prim().GetBool();
1197 left
.PutBool( left
.GetBool() || bB
);
1202 BOOL bR
= Prim().GetBool();
1203 BOOL bL
= left
.GetBool();
1204 left
.PutBool( (bL
&& !bR
) || (!bL
&& bR
) );
1208 case CALC_EQ
: nSbxOper
= SbxEQ
; break;
1209 case CALC_NEQ
: nSbxOper
= SbxNE
; break;
1210 case CALC_LEQ
: nSbxOper
= SbxLE
; break;
1211 case CALC_GEQ
: nSbxOper
= SbxGE
; break;
1212 case CALC_GRE
: nSbxOper
= SbxGT
; break;
1213 case CALC_LES
: nSbxOper
= SbxLT
; break;
1215 case CALC_MUL
: nSbxOper
= SbxMUL
; break;
1216 case CALC_DIV
: nSbxOper
= SbxDIV
; break;
1221 SwSbxValue e
= Prim();
1222 left
= left
.GetDouble() < e
.GetDouble()
1229 SwSbxValue e
= Prim();
1230 left
= left
.GetDouble() > e
.GetDouble()
1237 SwSbxValue e
= Prim();
1238 sal_Int32 nYear
= (sal_Int32
) floor( left
.GetDouble() );
1239 nYear
= nYear
& 0x0000FFFF;
1240 sal_Int32 nMonth
= (INT32
) floor( e
.GetDouble() );
1241 nMonth
= ( nMonth
& 0x000000FF ) << 16;
1242 left
.PutLong( nMonth
+ nYear
);
1243 eCurrOper
= CALC_DAY
;
1249 SwSbxValue e
= Prim();
1250 sal_Int32 nYearMonth
= (sal_Int32
) floor( left
.GetDouble() );
1251 nYearMonth
= nYearMonth
& 0x00FFFFFF;
1252 sal_Int32 nDay
= (sal_Int32
) floor( e
.GetDouble() );
1253 nDay
= ( nDay
& 0x000000FF ) << 24;
1254 left
= lcl_ConvertToDateValue( rDoc
, nDay
+ nYearMonth
);
1260 SwSbxValue e
= Prim();
1264 INT32 nDec
= (INT32
) floor( e
.GetDouble() );
1265 if( nDec
< -20 || nDec
> 20 )
1267 eError
= CALC_OVERFLOW
;
1271 fVal
= left
.GetDouble();
1274 for (i
= 0; i
< (USHORT
) nDec
; ++i
)
1277 for (i
= 0; i
< (USHORT
) -nDec
; ++i
)
1292 double fNum
= fVal
; // find the exponent
1296 while( fNum
< 1.0 ) fNum
*= 10.0, --nExp
;
1297 while( fNum
>= 10.0 ) fNum
/= 10.0, ++nExp
;
1302 else if( nExp
<= 1 )
1304 fVal
= floor( fVal
+ 0.5 + nRoundVal
[ nExp
] );
1311 left
.PutDouble( fVal
);
1316 // removed here because of #77448# (=2*3^2 != 18)
1319 double fraction, integer;
1320 double right = Prim().GetDouble(),
1321 dleft = left.GetDouble();
1323 fraction = modf( right, &integer );
1324 if( ( dleft < 0.0 && 0.0 != fraction ) ||
1325 ( 0.0 == dleft && right < 0.0 ) )
1327 eError = CALC_OVERFLOW;
1331 dleft = pow(dleft, right );
1332 if( dleft == HUGE_VAL )
1334 eError = CALC_POWERR;
1338 left.PutDouble( dleft );
1342 default: return left
;
1345 if( USHRT_MAX
!= nSbxOper
)
1347 // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
1348 SbxOperator eSbxOper
= (SbxOperator
)nSbxOper
;
1351 if( SbxEQ
<= eSbxOper
&& eSbxOper
<= SbxGE
)
1352 left
.PutBool( left
.Compare( eSbxOper
, Prim() ));
1355 SwSbxValue
aRight( Prim() );
1356 aRight
.MakeDouble();
1359 if( SbxDIV
== eSbxOper
&& !aRight
.GetDouble() )
1360 eError
= CALC_ZERODIV
;
1362 left
.Compute( eSbxOper
, aRight
);
1368 /******************************************************************************
1370 |* SwSbxValue SwCalc::Prim()
1372 |* Erstellung OK 12-02-93 11:05am
1373 |* Letzte Aenderung JP 03.11.95
1375 |******************************************************************************/
1377 extern "C" typedef double (*pfCalc
)( double );
1379 SwSbxValue
SwCalc::Prim()
1385 BOOL bChkTrig
= FALSE
, bChkPow
= FALSE
;
1389 case CALC_SIN
: pFnc
= &sin
; break;
1390 case CALC_COS
: pFnc
= &cos
; break;
1391 case CALC_TAN
: pFnc
= &tan
; break;
1392 case CALC_ATAN
: pFnc
= &atan
; break;
1393 case CALC_ASIN
: pFnc
= &asin
; bChkTrig
= TRUE
; break;
1394 case CALC_ACOS
: pFnc
= &acos
; bChkTrig
= TRUE
; break;
1399 if( SbxSTRING
== nErg
.GetType() )
1400 nErg
.PutBool( 0 == nErg
.GetString().Len() );
1401 else if(SbxBOOL
== nErg
.GetType() )
1402 nErg
.PutBool(!nErg
.GetBool());
1403 // evaluate arguments manually so that the binary NOT below
1404 // does not get called.
1405 // We want a BOOLEAN NOT.
1406 else if (nErg
.IsNumeric())
1407 nErg
.PutLong( nErg
.GetDouble() == 0.0 ? 1 : 0 );
1410 DBG_ERROR( "unexpected case. computing binary NOT" );
1411 //!! computes a binary NOT
1412 nErg
.Compute( SbxNOT
, nErg
);
1417 case CALC_NUMBER
: if( GetToken() == CALC_PHD
)
1419 double aTmp
= nNumberValue
.GetDouble();
1421 nErg
.PutDouble( aTmp
);
1424 else if( eCurrOper
== CALC_NAME
)
1425 eError
= CALC_SYNTAX
;
1428 nErg
= nNumberValue
;
1433 case CALC_NAME
: if( GetToken() == CALC_ASSIGN
)
1435 SwCalcExp
* n
= VarInsert( aVarName
);
1437 nErg
= n
->nValue
= Expr();
1441 nErg
= VarLook( aVarName
)->nValue
;
1446 case CALC_MINUS
: GetToken();
1447 nErg
.PutDouble( -(Prim().GetDouble()) );
1453 if( eCurrOper
!= CALC_RP
)
1454 eError
= CALC_BRACK
;
1458 bChkPow
= TRUE
; // in order for =(7)^2 to work
1467 double aTmp
= nErg
.GetDouble();
1469 nErg
.PutDouble( aTmp
);
1476 if( nErg
.GetDouble() < 0 )
1477 eError
= CALC_OVERFLOW
;
1479 nErg
.PutDouble( sqrt( nErg
.GetDouble() ));
1486 case CALC_MAX
: GetToken();
1490 case CALC_ENDCALC
: nErg
.Clear();
1493 default: eError
= CALC_SYNTAX
;
1500 double nVal
= Prim().GetDouble();
1501 if( !bChkTrig
|| ( nVal
> -1 && nVal
< 1 ) )
1502 nErg
.PutDouble( (*pFnc
)( nVal
) );
1504 eError
= CALC_OVERFLOW
;
1507 // added here because of #77448# (=2*3^2 should be 18)
1508 if( bChkPow
&& eCurrOper
== CALC_POW
)
1510 double dleft
= nErg
.GetDouble();
1512 double right
= Prim().GetDouble();
1514 double fraction
, integer
;
1515 fraction
= modf( right
, &integer
);
1516 if( ( dleft
< 0.0 && 0.0 != fraction
) ||
1517 ( 0.0 == dleft
&& right
< 0.0 ) )
1519 eError
= CALC_OVERFLOW
;
1524 dleft
= pow(dleft
, right
);
1525 if( dleft
== HUGE_VAL
)
1527 eError
= CALC_POWERR
;
1532 nErg
.PutDouble( dleft
);
1541 /******************************************************************************
1543 |* SwSbxValue SwCalc::Expr()
1545 |* Erstellung OK 12-02-93 11:06am
1546 |* Letzte Aenderung JP 03.11.95
1548 |******************************************************************************/
1550 SwSbxValue
SwCalc::Expr()
1552 SwSbxValue left
= Term(), right
;
1557 case CALC_PLUS
: GetToken();
1558 // erzeuge zum addieren auf jedenfall einen
1561 ( right
= Term() ).MakeDouble();
1562 left
.Compute( SbxPLUS
, right
);
1566 case CALC_MINUS
: GetToken();
1567 // erzeuge zum addieren auf jedenfall einen
1570 ( right
= Term() ).MakeDouble();
1571 left
.Compute( SbxMINUS
, right
);
1574 default: return left
;
1578 //------------------------------------------------------------------------------
1580 String
SwCalc::GetColumnName(const String
& rName
)
1582 xub_StrLen nPos
= rName
.Search(DB_DELIM
);
1583 if( STRING_NOTFOUND
!= nPos
)
1585 nPos
= rName
.Search(DB_DELIM
, nPos
+ 1);
1587 if( STRING_NOTFOUND
!= nPos
)
1588 return rName
.Copy(nPos
+ 1);
1593 //------------------------------------------------------------------------------
1595 String
SwCalc::GetDBName(const String
& rName
)
1597 xub_StrLen nPos
= rName
.Search(DB_DELIM
);
1598 if( STRING_NOTFOUND
!= nPos
)
1600 nPos
= rName
.Search(DB_DELIM
, nPos
+ 1);
1602 if( STRING_NOTFOUND
!= nPos
)
1603 return rName
.Copy( 0, nPos
);
1605 SwDBData aData
= rDoc
.GetDBData();
1606 String sRet
= aData
.sDataSource
;
1608 sRet
+= String(aData
.sCommand
);
1612 //------------------------------------------------------------------------------
1614 /******************************************************************************
1615 * Methode : BOOL SwCalc::Str2Double( double& )
1617 * Erstellt : OK 07.06.94 12:56
1618 * Aenderung : JP 27.10.98
1619 ******************************************************************************/
1620 BOOL
SwCalc::Str2Double( const String
& rCommand
, xub_StrLen
& rCommandPos
,
1621 double& rVal
, const LocaleDataWrapper
* pLclData
)
1623 const LocaleDataWrapper
* pLclD
= pLclData
;
1625 pLclD
= &SvtSysLocale().GetLocaleData();
1627 const xub_Unicode nCurrCmdPos
= rCommandPos
;
1628 rtl_math_ConversionStatus eStatus
;
1629 const sal_Unicode
* pEnd
;
1630 rVal
= rtl_math_uStringToDouble( rCommand
.GetBuffer() + rCommandPos
,
1631 rCommand
.GetBuffer() + rCommand
.Len(),
1632 pLclD
->getNumDecimalSep().GetChar(0),
1633 pLclD
->getNumThousandSep().GetChar(0),
1635 rCommandPos
= static_cast<xub_StrLen
>(pEnd
- rCommand
.GetBuffer());
1637 if( !pLclData
&& pLclD
!= &SvtSysLocale().GetLocaleData() )
1638 delete (LocaleDataWrapper
*)pLclD
;
1640 return rtl_math_ConversionStatus_Ok
== eStatus
&& nCurrCmdPos
!= rCommandPos
;
1643 BOOL
SwCalc::Str2Double( const String
& rCommand
, xub_StrLen
& rCommandPos
,
1644 double& rVal
, SwDoc
* pDoc
)
1646 const LocaleDataWrapper
* pLclD
= &SvtSysLocale().GetLocaleData();
1650 LanguageType eLang
= GetDocAppScriptLang( *pDoc
);
1651 if( eLang
!= SvxLocaleToLanguage( pLclD
->getLocale() ) )
1652 pLclD
= new LocaleDataWrapper(
1653 ::comphelper::getProcessServiceFactory(),
1654 SvxCreateLocale( eLang
) );
1657 const xub_Unicode nCurrCmdPos
= rCommandPos
;
1658 rtl_math_ConversionStatus eStatus
;
1659 const sal_Unicode
* pEnd
;
1660 rVal
= rtl_math_uStringToDouble( rCommand
.GetBuffer() + rCommandPos
,
1661 rCommand
.GetBuffer() + rCommand
.Len(),
1662 pLclD
->getNumDecimalSep().GetChar(0),
1663 pLclD
->getNumThousandSep().GetChar(0),
1665 rCommandPos
= static_cast<xub_StrLen
>(pEnd
- rCommand
.GetBuffer());
1667 if( pLclD
!= &SvtSysLocale().GetLocaleData() )
1668 delete (LocaleDataWrapper
*)pLclD
;
1670 return rtl_math_ConversionStatus_Ok
== eStatus
&& nCurrCmdPos
!= rCommandPos
;
1673 //------------------------------------------------------------------------------
1675 BOOL
SwCalc::IsValidVarName( const String
& rStr
,
1676 String
* pValidName
)
1679 using namespace ::com::sun::star::i18n
;
1682 ParseResult aRes
= GetAppCharClass().parseAnyToken( rStr
, 0,
1683 coStartFlags
, aEmptyStr
,
1684 coContFlags
, aEmptyStr
);
1686 if( aRes
.TokenType
& KParseType::IDENTNAME
)
1688 bRet
= aRes
.EndPos
== rStr
.Len();
1691 xub_StrLen nRealStt
= (xub_StrLen
)aRes
.LeadingWhiteSpace
;
1692 *pValidName
= rStr
.Copy( nRealStt
, static_cast<xub_StrLen
>(aRes
.EndPos
) - nRealStt
);
1695 else if( pValidName
)
1696 pValidName
->Erase();
1701 //------------------------------------------------------------------------------
1703 /******************************************************************************
1705 |* CTOR DTOR der SwHash classes
1707 |* Ersterstellung OK 25.06.93 12:20
1708 |* Letzte Aenderung OK 25.06.93 12:20
1710 ******************************************************************************/
1712 SwHash::SwHash( const String
& rStr
) :
1723 void DeleteHashTable( SwHash
**ppHashTable
, USHORT nCount
)
1725 for ( USHORT i
= 0; i
< nCount
; ++i
)
1726 delete *(ppHashTable
+i
);
1727 delete [] ppHashTable
;
1730 SwCalcExp::SwCalcExp( const String
& rStr
, const SwSbxValue
& rVal
,
1731 const SwFieldType
* pType
)
1739 SwSbxValue::~SwSbxValue()
1743 BOOL
SwSbxValue::GetBool() const
1745 return SbxSTRING
== GetType() ? 0 != GetString().Len()
1746 : 0 != SbxValue::GetBool();
1749 double SwSbxValue::GetDouble() const
1752 if( SbxSTRING
== GetType() )
1754 xub_StrLen nStt
= 0;
1755 SwCalc::Str2Double( GetString(), nStt
, nRet
);
1759 nRet
= 0 != GetBool() ? 1.0 : 0.0;
1762 nRet
= SbxValue::GetDouble();
1766 SwSbxValue
& SwSbxValue::MakeDouble()
1768 if( SbxSTRING
== GetType() )
1769 PutDouble( GetDouble() );
1773 #ifdef STANDALONE_HASHCALC
1775 // dies ist der Beispielcode zu erzeugen der HashValues im CTOR:
1782 sNType0
[] = "false", sNType1
[] = "true", sNType2
[] = "pi",
1783 sNType3
[] = "e", sNType4
[] = "tables", sNType5
[] = "graf",
1784 sNType6
[] = "ole", sNType7
[] = "page", sNType8
[] = "para",
1785 sNType9
[] = "word", sNType10
[]= "char",
1786 sNType11
[] = "user_company" , sNType12
[] = "user_firstname" ,
1787 sNType13
[] = "user_lastname" , sNType14
[] = "user_initials",
1788 sNType15
[] = "user_street" , sNType16
[] = "user_country" ,
1789 sNType17
[] = "user_zipcode" , sNType18
[] = "user_city" ,
1790 sNType19
[] = "user_title" , sNType20
[] = "user_position" ,
1791 sNType21
[] = "user_tel_home", sNType22
[] = "user_tel_work",
1792 sNType23
[] = "user_fax" , sNType24
[] = "user_email" ,
1793 sNType25
[] = "user_state", sNType26
[] = "graph"
1796 static const sal_Char
* sNTypeTab
[ 27 ] =
1798 sNType0
, sNType1
, sNType2
, sNType3
, sNType4
, sNType5
,
1799 sNType6
, sNType7
, sNType8
, sNType9
, sNType10
, sNType11
,
1800 sNType12
, sNType13
, sNType14
, sNType15
, sNType16
, sNType17
,
1801 sNType18
, sNType19
, sNType20
, sNType21
, sNType22
, sNType23
,
1802 sNType24
, sNType25
, sNType26
1805 const unsigned short nTblSize
= 47;
1806 int aArr
[ nTblSize
] = { 0 };
1809 for( int n
= 0; n
< 27; ++n
)
1811 unsigned long ii
= 0;
1812 const sal_Char
* pp
= sNTypeTab
[ n
];
1815 ii
= ii
<< 1 ^ *pp
++;
1818 ch
= aArr
[ ii
] ? 'X' : ' ';
1820 printf( "%-20s -> %3d [%c]\n", sNTypeTab
[ n
], ii
, ch
);