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