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 | i18n::KParseTokens::GROUP_SEPARATOR_IN_NUMBER)
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
198// static
200{
204 return rDoc.GetDefault(nWhich).GetLanguage();
205}
206
207static double lcl_ConvertToDateValue( SwDoc& rDoc, sal_Int32 nDate )
208{
209 double nRet = 0;
210 SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
211 if( pFormatter )
212 {
213 const Date& rNull = pFormatter->GetNullDate();
214 Date aDate( nDate >> 24, (nDate& 0x00FF0000) >> 16, nDate& 0x0000FFFF );
215 nRet = aDate - rNull;
216 }
217 return nRet;
218}
219
221 : m_aVarTable(TBLSZ)
222 , m_aErrExpr( OUString(), SwSbxValue(), nullptr )
223 , m_nCommandPos(0)
224 , m_rDoc( rD )
225 , m_pCharClass( &GetAppCharClass() )
226 , m_nListPor( 0 )
227 , m_bHasNumber( false )
228 , m_eCurrOper( CALC_NAME )
229 , m_eCurrListOper( CALC_NAME )
230 , m_eError( SwCalcError::NONE )
231{
232 m_aErrExpr.aStr = "~C_ERR~";
234 LanguageTag aLanguageTag( eLang );
235
237 {
238 m_pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), aLanguageTag );
239 }
240 m_xLocaleDataWrapper.reset(new LocaleDataWrapper( std::move(aLanguageTag) ));
241
244
245 static char const
246 sNType0[] = "false",
247 sNType1[] = "true",
248 sNType2[] = "pi",
249 sNType3[] = "e",
250 sNType4[] = "tables",
251 sNType5[] = "graf",
252 sNType6[] = "ole",
253 sNType7[] = "page",
254 sNType8[] = "para",
255 sNType9[] = "word",
256 sNType10[]= "char",
257
258 sNType11[] = "user_firstname" ,
259 sNType12[] = "user_lastname" ,
260 sNType13[] = "user_initials" ,
261 sNType14[] = "user_company" ,
262 sNType15[] = "user_street" ,
263 sNType16[] = "user_country" ,
264 sNType17[] = "user_zipcode" ,
265 sNType18[] = "user_city" ,
266 sNType19[] = "user_title" ,
267 sNType20[] = "user_position" ,
268 sNType21[] = "user_tel_work" ,
269 sNType22[] = "user_tel_home" ,
270 sNType23[] = "user_fax" ,
271 sNType24[] = "user_email" ,
272 sNType25[] = "user_state" ,
273 sNType26[] = "graph"
274 ;
275 static const char* const sNTypeTab[ 27 ] =
276 {
277 sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
278 sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
279 sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
280 sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
281 sNType24,
282
283 // those have two HashIds
284 sNType25, sNType26
285 };
286 static sal_uInt16 const aHashValue[ 27 ] =
287 {
288 34, 38, 43, 7, 18, 32, 22, 29, 30, 33, 3,
289 28, 24, 40, 9, 11, 26, 45, 4, 23, 36, 44, 19, 5, 1,
290 // those have two HashIds
291 11, 38
292 };
293 static UserOptToken const aAdrToken[ 12 ] =
294 {
295 UserOptToken::Company, UserOptToken::Street, UserOptToken::Country, UserOptToken::Zip,
296 UserOptToken::City, UserOptToken::Title, UserOptToken::Position, UserOptToken::TelephoneWork,
297 UserOptToken::TelephoneHome, UserOptToken::Fax, UserOptToken::Email, UserOptToken::State
298 };
299
300 static sal_uInt16 SwDocStat::* const aDocStat1[ 3 ] =
301 {
303 };
304 static sal_uLong SwDocStat::* const aDocStat2[ 4 ] =
305 {
308 };
309
310#if TBLSZ != 47
311#error Did you adjust all hash values?
312#endif
313
315
316 SwSbxValue nVal;
317 OUString sTmpStr;
318 sal_uInt16 n;
319
320 for( n = 0; n < 25; ++n )
321 {
322 sTmpStr = OUString::createFromAscii(sNTypeTab[n]);
323 m_aVarTable[ aHashValue[ n ] ].reset( new SwCalcExp( sTmpStr, nVal, nullptr ) );
324 }
325
326 m_aVarTable[ aHashValue[ 0 ] ]->nValue.PutBool( false );
327 m_aVarTable[ aHashValue[ 1 ] ]->nValue.PutBool( true );
328 m_aVarTable[ aHashValue[ 2 ] ]->nValue.PutDouble( M_PI );
329 m_aVarTable[ aHashValue[ 3 ] ]->nValue.PutDouble( M_E );
330
331 for( n = 0; n < 3; ++n )
332 m_aVarTable[ aHashValue[ n + 4 ] ]->nValue.PutLong( rDocStat.*aDocStat1[ n ] );
333 for( n = 0; n < 4; ++n )
334 m_aVarTable[ aHashValue[ n + 7 ] ]->nValue.PutLong( rDocStat.*aDocStat2[ n ] );
335
336 SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
337
338 m_aVarTable[ aHashValue[ 11 ] ]->nValue.PutString( rUserOptions.GetFirstName() );
339 m_aVarTable[ aHashValue[ 12 ] ]->nValue.PutString( rUserOptions.GetLastName() );
340 m_aVarTable[ aHashValue[ 13 ] ]->nValue.PutString( rUserOptions.GetID() );
341
342 for( n = 0; n < 11; ++n )
343 m_aVarTable[ aHashValue[ n + 14 ] ]->nValue.PutString(
344 rUserOptions.GetToken( aAdrToken[ n ] ));
345
346 nVal.PutString( rUserOptions.GetToken( aAdrToken[ 11 ] ));
347 sTmpStr = OUString::createFromAscii(sNTypeTab[25]);
348 m_aVarTable[ aHashValue[ 25 ] ]->pNext.reset( new SwCalcExp( sTmpStr, nVal, nullptr ) );
349
350} // SwCalc::SwCalc
351
353{
354 if( m_pCharClass != &GetAppCharClass() )
355 delete m_pCharClass;
356}
357
359{
361}
362
363SwSbxValue SwCalc::Calculate( const OUString& rStr )
364{
366 SwSbxValue nResult;
367
368 if( rStr.isEmpty() )
369 return nResult;
370
371 m_nListPor = 0;
372 m_eCurrListOper = CALC_PLUS; // default: sum
373
374 m_sCommand = rStr;
375 m_nCommandPos = 0;
376
377 for (;;)
378 {
381 break;
382 nResult = Expr();
383 }
384
386 nResult.PutDouble( DBL_MAX );
387
388 return nResult;
389}
390
391OUString SwCalc::GetStrResult( const SwSbxValue& rVal )
392{
393 if( !rVal.IsDouble() )
394 {
395 return rVal.GetOUString();
396 }
397 return GetStrResult( rVal.GetDouble() );
398}
399
400OUString SwCalc::GetStrResult( double nValue )
401{
402 if( nValue >= DBL_MAX )
403 switch( m_eError )
404 {
410 default : return SwViewShell::GetShellRes()->aCalc_Default;
411 }
412
413 const sal_Int32 nDecPlaces = 15;
414 OUString aRetStr( ::rtl::math::doubleToUString(
415 nValue,
416 rtl_math_StringFormat_Automatic,
417 nDecPlaces,
418 m_xLocaleDataWrapper->getNumDecimalSep()[0],
419 true ));
420 return aRetStr;
421}
422
423SwCalcExp* SwCalc::VarInsert( const OUString &rStr )
424{
425 OUString aStr = m_pCharClass->lowercase( rStr );
426 return VarLook( aStr, true );
427}
428
429SwCalcExp* SwCalc::VarLook( const OUString& rStr, bool bIns )
430{
432
433 sal_uInt32 ii = 0;
434 OUString aStr = m_pCharClass->lowercase( rStr );
435
436 SwCalcExp* pFnd = m_aVarTable.Find(aStr, &ii);
437
438 if( !pFnd )
439 {
440 // then check doc
442 for( SwHash* pEntry = rDocTable[ii].get(); pEntry; pEntry = pEntry->pNext.get() )
443 {
444 if( aStr == pEntry->aStr )
445 {
446 // then insert here
447 pFnd = new SwCalcExp( aStr, SwSbxValue(),
448 static_cast<SwCalcFieldType*>(pEntry)->pFieldType );
449 pFnd->pNext = std::move( m_aVarTable[ii] );
450 m_aVarTable[ii].reset(pFnd);
451 break;
452 }
453 }
454 }
455
456 if( pFnd )
457 {
458 if( pFnd->pFieldType && pFnd->pFieldType->Which() == SwFieldIds::User )
459 {
460 SwUserFieldType* pUField = const_cast<SwUserFieldType*>(static_cast<const SwUserFieldType*>(pFnd->pFieldType));
461 if( nsSwGetSetExpType::GSE_STRING & pUField->GetType() )
462 {
463 pFnd->nValue.PutString( pUField->GetContent() );
464 }
465 else if( !pUField->IsValid() )
466 {
467 // Save the current values...
468 sal_uInt16 nListPor = m_nListPor;
469 bool bHasNumber = m_bHasNumber;
470 SwSbxValue nLastLeft = m_nLastLeft;
471 SwSbxValue nNumberValue = m_nNumberValue;
472 sal_Int32 nCommandPos = m_nCommandPos;
473 SwCalcOper eCurrOper = m_eCurrOper;
474 SwCalcOper eCurrListOper = m_eCurrListOper;
475 OUString sCurrCommand = m_sCommand;
476
477 pFnd->nValue.PutDouble( pUField->GetValue( *this ) );
478
479 // ...and write them back.
480 m_nListPor = nListPor;
481 m_bHasNumber = bHasNumber;
482 m_nLastLeft = nLastLeft;
483 m_nNumberValue = nNumberValue;
484 m_nCommandPos = nCommandPos;
485 m_eCurrOper = eCurrOper;
486 m_eCurrListOper = eCurrListOper;
487 m_sCommand = sCurrCommand;
488 }
489 else
490 {
491 pFnd->nValue.PutDouble( pUField->GetValue() );
492 }
493 }
494 else if ( !pFnd->pFieldType && pFnd->nValue.IsDBvalue() )
495 {
496 if ( pFnd->nValue.IsString() )
498 else if ( pFnd->nValue.IsDouble() )
500 pFnd = &m_aErrExpr;
501 }
502 return pFnd;
503 }
504
505 // At this point the "real" case variable has to be used
506 OUString const sTmpName( ::ReplacePoint(rStr) );
507
508 if( !bIns )
509 {
510#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
512 OUString sDBName(GetDBName( sTmpName ));
513 OUString sSourceName(sDBName.getToken(0, DB_DELIM));
514 OUString sTableName(sDBName.getToken(0, ';').getToken(1, DB_DELIM));
515 if( pMgr && !sSourceName.isEmpty() && !sTableName.isEmpty() &&
516 pMgr->OpenDataSource(sSourceName, sTableName))
517 {
518 OUString sColumnName( GetColumnName( sTmpName ));
519 OSL_ENSURE(!sColumnName.isEmpty(), "Missing DB column name");
520
522 sDBNum = m_pCharClass->lowercase(sDBNum);
523
524 // Initialize again because this doesn't happen in docfld anymore for
525 // elements != SwFieldIds::Database. E.g. if there is an expression field before
526 // a DB_Field in a document.
527 const sal_uInt32 nTmpRec = pMgr->GetSelectedRecordId(sSourceName, sTableName);
528 VarChange(sDBNum, nTmpRec);
529
530 if( sDBNum.equalsIgnoreAsciiCase(sColumnName) )
531 {
532 m_aErrExpr.nValue.PutULong(nTmpRec);
533 return &m_aErrExpr;
534 }
535
536 OUString sResult;
537 double nNumber = DBL_MAX;
538
539 LanguageType nLang = m_xLocaleDataWrapper->getLanguageTag().getLanguageType();
540 if(pMgr->GetColumnCnt( sSourceName, sTableName, sColumnName,
541 nTmpRec, nLang, sResult, &nNumber ))
542 {
543 if (nNumber != DBL_MAX)
544 m_aErrExpr.nValue.PutDouble( nNumber );
545 else
546 m_aErrExpr.nValue.PutString( sResult );
547
548 return &m_aErrExpr;
549 }
550 }
551 else
552#endif
553 {
554 //data source was not available - set return to "NoValue"
556 }
557 // NEVER save!
558 return &m_aErrExpr;
559 }
560
561 SwCalcExp* pNewExp = new SwCalcExp( aStr, SwSbxValue(), nullptr );
562 pNewExp->pNext = std::move( m_aVarTable[ ii ] );
563 m_aVarTable[ ii ].reset( pNewExp );
564
565 OUString sColumnName( GetColumnName( sTmpName ));
566 OSL_ENSURE( !sColumnName.isEmpty(), "Missing DB column name" );
567 if( sColumnName.equalsIgnoreAsciiCase(
569 {
570#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
572 OUString sDBName(GetDBName( sTmpName ));
573 OUString sSourceName(sDBName.getToken(0, DB_DELIM));
574 OUString sTableName(sDBName.getToken(0, ';').getToken(1, DB_DELIM));
575 if( pMgr && !sSourceName.isEmpty() && !sTableName.isEmpty() &&
576 pMgr->OpenDataSource(sSourceName, sTableName) &&
577 !pMgr->IsInMerge())
578 {
579 pNewExp->nValue.PutULong( pMgr->GetSelectedRecordId(sSourceName, sTableName));
580 }
581 else
582#endif
583 {
584 pNewExp->nValue.SetVoidValue(true);
585 }
586 }
587
588 return pNewExp;
589}
590
591void SwCalc::VarChange( const OUString& rStr, double nValue )
592{
593 SwSbxValue aVal( nValue );
594 VarChange( rStr, aVal );
595}
596
597void SwCalc::VarChange( const OUString& rStr, const SwSbxValue& rValue )
598{
599 OUString aStr = m_pCharClass->lowercase( rStr );
600
601 sal_uInt32 nPos = 0;
602 SwCalcExp* pFnd = m_aVarTable.Find( aStr, &nPos );
603
604 if( !pFnd )
605 {
606 pFnd = new SwCalcExp( aStr, rValue, nullptr );
607 pFnd->pNext = std::move( m_aVarTable[ nPos ] );
608 m_aVarTable[ nPos ].reset( pFnd );
609 }
610 else
611 {
612 pFnd->nValue = rValue;
613 }
614}
615
616bool SwCalc::Push( const SwUserFieldType* pUserFieldType )
617{
618 if( m_aRekurStack.end() != std::find(m_aRekurStack.begin(), m_aRekurStack.end(), pUserFieldType ) )
619 return false;
620
621 m_aRekurStack.push_back( pUserFieldType );
622 return true;
623}
624
626{
627 OSL_ENSURE( m_aRekurStack.size(), "SwCalc: Pop on an invalid pointer" );
628
629 m_aRekurStack.pop_back();
630}
631
633{
634 return m_pCharClass;
635}
636
637void SwCalc::SetCharClass(const LanguageTag& rLanguageTag)
638{
639 m_pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), rLanguageTag );
640}
641
643{
644 if( m_nCommandPos >= m_sCommand.getLength() )
645 {
647 return m_eCurrOper;
648 }
649
650 using namespace ::com::sun::star::i18n;
651 {
652 // Parse any token.
654 coStartFlags, OUString(),
655 coContFlags, OUString());
656
657 bool bSetError = true;
658 sal_Int32 nRealStt = m_nCommandPos + aRes.LeadingWhiteSpace;
659 if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) )
660 {
661 m_nNumberValue.PutDouble( aRes.Value );
663 bSetError = false;
664 }
665 else if( aRes.TokenType & KParseType::IDENTNAME )
666 {
667 OUString aName( m_sCommand.copy( nRealStt,
668 aRes.EndPos - nRealStt ) );
669 //#101436#: The variable may contain a database name. It must not be
670 // converted to lower case! Instead all further comparisons must be
671 // done case-insensitive
672 OUString sLowerCaseName = m_pCharClass->lowercase( aName );
673 // catch currency symbol
674 if( sLowerCaseName == m_sCurrSym )
675 {
676 m_nCommandPos = aRes.EndPos;
677 return GetToken(); // call again
678 }
679
680 // catch operators
681 CalcOp* pFnd = ::FindOperator( sLowerCaseName );
682 if( pFnd )
683 {
684 m_eCurrOper = pFnd->eOp;
685 switch( m_eCurrOper )
686 {
687 case CALC_SUM:
688 case CALC_MEAN:
689 case CALC_AVERAGE:
690 case CALC_COUNT:
692 break;
693 case CALC_MIN:
695 break;
696 case CALC_MAX:
698 break;
699 case CALC_DATE:
701 break;
702 case CALC_PRODUCT:
704 break;
705 default:
706 break;
707 }
708 m_nCommandPos = aRes.EndPos;
709 return m_eCurrOper;
710 }
713 bSetError = false;
714 }
715 else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING )
716 {
717 m_nNumberValue.PutString( aRes.DequotedNameOrString );
719 bSetError = false;
720 }
721 else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR )
722 {
723 std::u16string_view aName( m_sCommand.subView( nRealStt,
724 aRes.EndPos - nRealStt ));
725 if( 1 == aName.size() )
726 {
727 bSetError = false;
728 sal_Unicode ch = aName[0];
729 switch( ch )
730 {
731 case ';':
733 {
735 break;
736 }
737 [[fallthrough]];
738 case '\n':
740 break;
741
742 case '%':
743 case '^':
744 case '*':
745 case '/':
746 case '+':
747 case '-':
748 case '(':
749 case ')':
751 break;
752
753 case '=':
754 case '!':
755 {
756 SwCalcOper eTmp2;
757 if( '=' == ch )
758 {
759 m_eCurrOper = SwCalcOper('=');
760 eTmp2 = CALC_EQ;
761 }
762 else
763 {
765 eTmp2 = CALC_NEQ;
766 }
767
768 if( aRes.EndPos < m_sCommand.getLength() &&
769 '=' == m_sCommand[aRes.EndPos] )
770 {
771 m_eCurrOper = eTmp2;
772 ++aRes.EndPos;
773 }
774 }
775 break;
776
777 case cListDelim:
779 break;
780
781 case '[':
782 if( aRes.EndPos < m_sCommand.getLength() )
783 {
784 m_aVarName.setLength(0);
785 sal_Int32 nFndPos = aRes.EndPos,
786 nSttPos = nFndPos;
787
788 do {
789 nFndPos = m_sCommand.indexOf( ']', nFndPos );
790 if( -1 != nFndPos )
791 {
792 // ignore the ]
793 if ('\\' == m_sCommand[nFndPos-1])
794 {
795 m_aVarName.append(m_sCommand.subView(nSttPos,
796 nFndPos - nSttPos - 1) );
797 nSttPos = ++nFndPos;
798 }
799 else
800 break;
801 }
802 } while( nFndPos != -1 );
803
804 if( nFndPos != -1 )
805 {
806 if( nSttPos != nFndPos )
807 m_aVarName.append(m_sCommand.subView(nSttPos,
808 nFndPos - nSttPos) );
809 aRes.EndPos = nFndPos + 1;
811 }
812 else
813 bSetError = true;
814 }
815 else
816 {
817 bSetError = true;
818 }
819 break;
820
821 default:
822 bSetError = true;
823 break;
824 }
825 }
826 }
827 else if( aRes.TokenType & KParseType::BOOLEAN )
828 {
829 std::u16string_view aName( m_sCommand.subView( nRealStt,
830 aRes.EndPos - nRealStt ));
831 if( !aName.empty() )
832 {
833 sal_Unicode ch = aName[0];
834
835 bSetError = true;
836 if ('<' == ch || '>' == ch)
837 {
838 bSetError = false;
839
840 SwCalcOper eTmp2 = ('<' == ch) ? CALC_LEQ : CALC_GEQ;
841 m_eCurrOper = ('<' == ch) ? CALC_LES : CALC_GRE;
842
843 if( 2 == aName.size() && '=' == aName[1] )
844 m_eCurrOper = eTmp2;
845 else if( 1 != aName.size() )
846 bSetError = true;
847 }
848 }
849 }
850 else if( nRealStt == m_sCommand.getLength() )
851 {
853 bSetError = false;
854 }
855
856 if( bSetError )
857 {
860 }
861 m_nCommandPos = aRes.EndPos;
862 };
863
864 return m_eCurrOper;
865}
866
868{
869 SwSbxValue left( Prim() );
871 for(;;)
872 {
873 sal_uInt16 nSbxOper = USHRT_MAX;
874
875 switch( m_eCurrOper )
876 {
877 case CALC_AND:
878 {
879 GetToken();
880 bool bB = Prim().GetBool();
881 left.PutBool( left.GetBool() && bB );
882 }
883 break;
884 case CALC_OR:
885 {
886 GetToken();
887 bool bB = Prim().GetBool();
888 left.PutBool( left.GetBool() || bB );
889 }
890 break;
891 case CALC_XOR:
892 {
893 GetToken();
894 bool bR = Prim().GetBool();
895 bool bL = left.GetBool();
896 left.PutBool(bL != bR);
897 }
898 break;
899
900 case CALC_EQ: nSbxOper = SbxEQ; break;
901 case CALC_NEQ: nSbxOper = SbxNE; break;
902 case CALC_LEQ: nSbxOper = SbxLE; break;
903 case CALC_GEQ: nSbxOper = SbxGE; break;
904 case CALC_GRE: nSbxOper = SbxGT; break;
905 case CALC_LES: nSbxOper = SbxLT; break;
906
907 case CALC_MUL: nSbxOper = SbxMUL; break;
908 case CALC_DIV: nSbxOper = SbxDIV; break;
909
910 case CALC_MIN_IN:
911 {
912 GetToken();
913 SwSbxValue e = Prim();
914 left = left.GetDouble() < e.GetDouble() ? left : e;
915 }
916 break;
917 case CALC_MAX_IN:
918 {
919 GetToken();
920 SwSbxValue e = Prim();
921 left = left.GetDouble() > e.GetDouble() ? left : e;
922 }
923 break;
924 case CALC_MONTH:
925 {
926 GetToken();
927 SwSbxValue e = Prim();
928 sal_Int32 nYear = static_cast<sal_Int32>(floor( left.GetDouble() ));
929 nYear = nYear & 0x0000FFFF;
930 sal_Int32 nMonth = static_cast<sal_Int32>(floor( e.GetDouble() ));
931 nMonth = ( nMonth & 0x000000FF ) << 16;
932 left.PutLong( nMonth + nYear );
934 }
935 break;
936 case CALC_DAY:
937 {
938 GetToken();
939 SwSbxValue e = Prim();
940 sal_Int32 nYearMonth = static_cast<sal_Int32>(floor( left.GetDouble() ));
941 nYearMonth = nYearMonth & 0x00FFFFFF;
942 sal_Int32 nDay = static_cast<sal_Int32>(floor( e.GetDouble() ));
943 nDay = ( nDay & 0x000000FF ) << 24;
944 left = lcl_ConvertToDateValue( m_rDoc, nDay + nYearMonth );
945 }
946 break;
947 case CALC_ROUND:
948 {
949 GetToken();
950 SwSbxValue e = Prim();
951
952 double fVal = 0;
953 double fFac = 1;
954 sal_Int32 nDec = static_cast<sal_Int32>(floor( e.GetDouble() ));
955 if( nDec < -20 || nDec > 20 )
956 {
958 left.Clear();
959 return left;
960 }
961 fVal = left.GetDouble();
962 if( nDec >= 0)
963 {
964 for (sal_Int32 i = 0; i < nDec; ++i )
965 fFac *= 10.0;
966 }
967 else
968 {
969 for (sal_Int32 i = 0; i < -nDec; ++i )
970 fFac /= 10.0;
971 }
972
973 fVal *= fFac;
974 bool bSign;
975 if (fVal < 0.0)
976 {
977 fVal *= -1.0;
978 bSign = true;
979 }
980 else
981 {
982 bSign = false;
983 }
984
985 // rounding
986 double fNum = fVal; // find the exponent
987 int nExp = 0;
988 if( fNum > 0 )
989 {
990 while( fNum < 1.0 )
991 {
992 fNum *= 10.0;
993 --nExp;
994 }
995 while( fNum >= 10.0 )
996 {
997 fNum /= 10.0;
998 ++nExp;
999 }
1000 }
1001 nExp = 15 - nExp;
1002 if( nExp > 15 )
1003 nExp = 15;
1004 else if( nExp <= 1 )
1005 nExp = 0;
1006 fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] );
1007
1008 if (bSign)
1009 fVal *= -1.0;
1010
1011 fVal /= fFac;
1012
1013 left.PutDouble( fVal );
1014 }
1015 break;
1016
1017//#77448# (=2*3^2 != 18)
1018
1019 default:
1020 return left;
1021 }
1022
1023 if( USHRT_MAX != nSbxOper )
1024 {
1025 // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
1026 SbxOperator eSbxOper = static_cast<SbxOperator>(nSbxOper);
1027
1028 GetToken();
1029 if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE )
1030 {
1031 left.PutBool( left.Compare( eSbxOper, Prim() ));
1032 }
1033 else
1034 {
1035 SwSbxValue aRight( Prim() );
1036 aRight.MakeDouble();
1037 left.MakeDouble();
1038
1039 if( SbxDIV == eSbxOper && !aRight.GetDouble() )
1041 else
1042 left.Compute( eSbxOper, aRight );
1043 }
1044 }
1045 }
1046}
1047
1049{
1050 SwSbxValue nErg;
1051 GetToken();
1052 double nVal = Prim().GetDouble();
1053 if( !bChkTrig || ( nVal > -1 && nVal < 1 ) )
1054 nErg.PutDouble( (*pFnc)( nVal ) );
1055 else
1057 return nErg;
1058}
1059
1061{
1062 rChkPow = false;
1063
1064 switch (m_eCurrOper)
1065 {
1066 case CALC_SIN:
1067 SAL_INFO("sw.calc", "sin");
1068 return StdFunc(&sin, false);
1069 case CALC_COS:
1070 SAL_INFO("sw.calc", "cos");
1071 return StdFunc(&cos, false);
1072 case CALC_TAN:
1073 SAL_INFO("sw.calc", "tan");
1074 return StdFunc(&tan, false);
1075 case CALC_ATAN:
1076 SAL_INFO("sw.calc", "atan");
1077 return StdFunc(&atan, false);
1078 case CALC_ASIN:
1079 SAL_INFO("sw.calc", "asin");
1080 return StdFunc(&asin, true);
1081 case CALC_ACOS:
1082 SAL_INFO("sw.calc", "acos");
1083 return StdFunc(&acos, true);
1084 case CALC_ABS:
1085 SAL_INFO("sw.calc", "abs");
1086 return StdFunc(&abs, false);
1087 case CALC_SIGN:
1088 {
1089 SAL_INFO("sw.calc", "sign");
1090 SwSbxValue nErg;
1091 GetToken();
1092 double nVal = Prim().GetDouble();
1093 nErg.PutDouble( int(0 < nVal) - int(nVal < 0) );
1094 return nErg;
1095 }
1096 case CALC_INT:
1097 {
1098 SAL_INFO("sw.calc", "int");
1099 SwSbxValue nErg;
1100 GetToken();
1101 sal_Int32 nVal = static_cast<sal_Int32>( Prim().GetDouble() );
1102 nErg.PutDouble( nVal );
1103 return nErg;
1104 }
1105 case CALC_NOT:
1106 {
1107 SAL_INFO("sw.calc", "not");
1108 GetToken();
1109 SwSbxValue nErg = Prim();
1110 if( SbxSTRING == nErg.GetType() )
1111 {
1112 nErg.PutBool( nErg.GetOUString().isEmpty() );
1113 }
1114 else if(SbxBOOL == nErg.GetType() )
1115 {
1116 nErg.PutBool(!nErg.GetBool());
1117 }
1118 // Evaluate arguments manually so that the binary NOT below does not
1119 // get called. We want a BOOLEAN NOT.
1120 else if (nErg.IsNumeric())
1121 {
1122 nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 );
1123 }
1124 else
1125 {
1126 OSL_FAIL( "unexpected case. computing binary NOT" );
1128 nErg.Compute( SbxNOT, nErg );
1129 }
1130 return nErg;
1131 }
1132 case CALC_NUMBER:
1133 {
1134 SAL_INFO("sw.calc", "number: " << m_nNumberValue.GetDouble());
1135 SwSbxValue nErg;
1136 m_bHasNumber = true;
1137 if( GetToken() == CALC_PHD )
1138 {
1139 double aTmp = m_nNumberValue.GetDouble();
1140 aTmp *= 0.01;
1141 nErg.PutDouble( aTmp );
1142 GetToken();
1143 }
1144 else if( m_eCurrOper == CALC_NAME )
1145 {
1147 }
1148 else
1149 {
1150 nErg = m_nNumberValue;
1151 rChkPow = true;
1152 }
1153 return nErg;
1154 }
1155 case CALC_NAME:
1156 {
1157 SAL_INFO("sw.calc", "name");
1158 SwSbxValue nErg;
1159 switch(SwCalcOper eOper = GetToken())
1160 {
1161 case CALC_ASSIGN:
1162 {
1163 SwCalcExp* n = VarInsert(m_aVarName.toString());
1164 GetToken();
1165 nErg = n->nValue = Expr();
1166 break;
1167 }
1168 default:
1169 nErg = VarLook(m_aVarName.toString())->nValue;
1170 // Explicitly disallow unknown function names (followed by "("),
1171 // allow unknown variable names (equal to zero)
1172 if (nErg.IsVoidValue() && (eOper == CALC_LP))
1174 else
1175 rChkPow = true;
1176 break;
1177 }
1178 return nErg;
1179 }
1180 case CALC_MINUS:
1181 {
1182 SAL_INFO("sw.calc", "-");
1183 SwSbxValue nErg;
1184 GetToken();
1185 nErg.PutDouble( -(Prim().GetDouble()) );
1186 return nErg;
1187 }
1188 case CALC_LP:
1189 {
1190 SAL_INFO("sw.calc", "(");
1191 GetToken();
1192 SwSbxValue nErg = Expr();
1193 if( m_eCurrOper != CALC_RP )
1194 {
1196 }
1197 else
1198 {
1199 GetToken();
1200 rChkPow = true; // in order for =(7)^2 to work
1201 }
1202 return nErg;
1203 }
1204 case CALC_RP:
1205 // ignore, see tdf#121962
1206 SAL_INFO("sw.calc", ")");
1207 break;
1208 case CALC_MEAN:
1209 case CALC_AVERAGE:
1210 {
1211 SAL_INFO("sw.calc", "mean");
1212 m_nListPor = 1;
1214 GetToken();
1215 SwSbxValue nErg = Expr();
1216 double aTmp = nErg.GetDouble();
1217 aTmp /= m_nListPor;
1218 if ( !m_bHasNumber )
1220 else
1221 nErg.PutDouble( aTmp );
1222 return nErg;
1223 }
1224 case CALC_COUNT:
1225 {
1226 SAL_INFO("sw.calc", "count");
1227 m_nListPor = 1;
1228 m_bHasNumber = false;
1229 GetToken();
1230 SwSbxValue nErg = Expr();
1231 nErg.PutDouble( m_bHasNumber ? m_nListPor : 0 );
1232 return nErg;
1233 }
1234 case CALC_SQRT:
1235 {
1236 SAL_INFO("sw.calc", "sqrt");
1237 GetToken();
1238 SwSbxValue nErg = Prim();
1239 if( nErg.GetDouble() < 0 )
1241 else
1242 nErg.PutDouble( sqrt( nErg.GetDouble() ));
1243 return nErg;
1244 }
1245 case CALC_SUM:
1246 case CALC_PRODUCT:
1247 case CALC_DATE:
1248 case CALC_MIN:
1249 case CALC_MAX:
1250 {
1251 SAL_INFO("sw.calc", "sum/product/date/min/max");
1252 GetToken();
1253 SwSbxValue nErg = Expr();
1254 return nErg;
1255 }
1256 case CALC_ENDCALC:
1257 {
1258 SAL_INFO("sw.calc", "endcalc");
1259 SwSbxValue nErg;
1260 nErg.Clear();
1261 return nErg;
1262 }
1263 default:
1264 SAL_INFO("sw.calc", "syntax error");
1266 break;
1267 }
1268
1269 return SwSbxValue();
1270}
1271
1273{
1274 bool bChkPow;
1275 SwSbxValue nErg = PrimFunc(bChkPow);
1276
1277 if (bChkPow && m_eCurrOper == CALC_POW)
1278 {
1279 double dleft = nErg.GetDouble();
1280 GetToken();
1281 double right = Prim().GetDouble();
1282
1283 double fraction;
1284 fraction = modf( right, &o3tl::temporary(double()) );
1285 if( ( dleft < 0.0 && 0.0 != fraction ) ||
1286 ( 0.0 == dleft && right < 0.0 ) )
1287 {
1289 nErg.Clear();
1290 }
1291 else
1292 {
1293 dleft = pow(dleft, right );
1294 if( dleft == HUGE_VAL )
1295 {
1297 nErg.Clear();
1298 }
1299 else
1300 {
1301 nErg.PutDouble( dleft );
1302 }
1303 }
1304 }
1305
1306 return nErg;
1307}
1308
1310{
1311 SwSbxValue left = Term();
1312 m_nLastLeft = left;
1313 for(;;)
1314 {
1315 switch(m_eCurrOper)
1316 {
1317 case CALC_PLUS:
1318 {
1319 GetToken();
1320 left.MakeDouble();
1322 right.MakeDouble();
1323 left.Compute(SbxPLUS, right);
1324 m_nListPor++;
1325 break;
1326 }
1327 case CALC_MINUS:
1328 {
1329 GetToken();
1330 left.MakeDouble();
1332 right.MakeDouble();
1333 left.Compute(SbxMINUS, right);
1334 break;
1335 }
1336 default:
1337 {
1338 return left;
1339 }
1340 }
1341 }
1342}
1343
1344OUString SwCalc::GetColumnName(const OUString& rName)
1345{
1346 sal_Int32 nPos = rName.indexOf(DB_DELIM);
1347 if( -1 != nPos )
1348 {
1349 nPos = rName.indexOf(DB_DELIM, nPos + 1);
1350
1351 if( -1 != nPos )
1352 return rName.copy(nPos + 1);
1353 }
1354 return rName;
1355}
1356
1357OUString SwCalc::GetDBName(std::u16string_view rName)
1358{
1359 size_t nPos = rName.find(DB_DELIM);
1360 if( std::u16string_view::npos != nPos )
1361 {
1362 nPos = rName.find(DB_DELIM, nPos + 1);
1363
1364 if( std::u16string_view::npos != nPos )
1365 return OUString(rName.substr( 0, nPos ));
1366 }
1368 return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
1369}
1370
1371namespace
1372{
1373 bool lcl_Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
1374 double& rVal,
1375 const LocaleDataWrapper* const pLclData )
1376 {
1377 assert(pLclData);
1378 const sal_Unicode nCurrCmdPos = rCommandPos;
1379 rtl_math_ConversionStatus eStatus;
1380 const sal_Unicode* pEnd;
1381 rVal = pLclData->stringToDouble( rCommand.getStr() + rCommandPos,
1382 rCommand.getStr() + rCommand.getLength(),
1383 true,
1384 &eStatus,
1385 &pEnd );
1386 rCommandPos = static_cast<sal_Int32>(pEnd - rCommand.getStr());
1387
1388 return rtl_math_ConversionStatus_Ok == eStatus &&
1389 nCurrCmdPos != rCommandPos;
1390 }
1391}
1392
1393bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
1394 double& rVal )
1395{
1396 const SvtSysLocale aSysLocale;
1397 return lcl_Str2Double( rCommand, rCommandPos, rVal, &aSysLocale.GetLocaleData() );
1398}
1399
1400bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
1401 double& rVal, SwDoc const * const pDoc )
1402{
1403 const SvtSysLocale aSysLocale;
1404 std::unique_ptr<const LocaleDataWrapper> pLclD;
1405 if( pDoc )
1406 {
1407 LanguageType eLang = GetDocAppScriptLang( *pDoc );
1408 if (eLang != aSysLocale.GetLanguageTag().getLanguageType())
1409 {
1410 pLclD.reset( new LocaleDataWrapper( LanguageTag( eLang )) );
1411 }
1412 }
1413
1414 bool const bRet = lcl_Str2Double(rCommand, rCommandPos, rVal,
1415 pLclD ? pLclD.get() : &aSysLocale.GetLocaleData());
1416
1417 return bRet;
1418}
1419
1420bool SwCalc::IsValidVarName( const OUString& rStr, OUString* pValidName )
1421{
1422 bool bRet = false;
1423 using namespace ::com::sun::star::i18n;
1424 {
1425 // Parse any token.
1426 ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0,
1427 coStartFlags, OUString(),
1428 coContFlags, OUString() );
1429
1430 if( aRes.TokenType & KParseType::IDENTNAME )
1431 {
1432 bRet = aRes.EndPos == rStr.getLength();
1433 if( pValidName )
1434 {
1435 *pValidName = rStr.copy( aRes.LeadingWhiteSpace,
1436 aRes.EndPos - aRes.LeadingWhiteSpace );
1437 }
1438 }
1439 else if( pValidName )
1440 pValidName->clear();
1441 }
1442 return bRet;
1443}
1444
1445SwHash::SwHash(OUString _aStr)
1446 : aStr(std::move(_aStr))
1447{
1448}
1449
1451{
1452}
1453
1454SwCalcExp::SwCalcExp(const OUString& rStr, SwSbxValue aVal,
1455 const SwFieldType* pType)
1456 : SwHash(rStr)
1457 , nValue(std::move(aVal))
1458 , pFieldType(pType)
1459{
1460}
1461
1463{
1464 return SbxSTRING == GetType() ? !GetOUString().isEmpty()
1466}
1467
1469{
1470 double nRet;
1471 if( SbxSTRING == GetType() )
1472 {
1473 sal_Int32 nStt = 0;
1474 SwCalc::Str2Double( GetOUString(), nStt, nRet );
1475 }
1476 else if (IsBool())
1477 {
1478 nRet = GetBool() ? 1.0 : 0.0;
1479 }
1480 else
1481 {
1482 nRet = SbxValue::GetDouble();
1483 }
1484 return nRet;
1485}
1486
1488{
1489 if( GetType() == SbxSTRING || GetType() == SbxBOOL )
1490 PutDouble( GetDouble() );
1491 return *this;
1492}
1493
1494#ifdef STANDALONE_HASHCALC
1495
1496// this is example code how to create hash values in the CTOR:
1497
1498#include <stdio.h>
1499void main()
1500{
1501 static char
1502 sNType0[] = "false", sNType1[] = "true", sNType2[] = "pi",
1503 sNType3[] = "e", sNType4[] = "tables", sNType5[] = "graf",
1504 sNType6[] = "ole", sNType7[] = "page", sNType8[] = "para",
1505 sNType9[] = "word", sNType10[]= "char",
1506 sNType11[] = "user_company" , sNType12[] = "user_firstname" ,
1507 sNType13[] = "user_lastname" , sNType14[] = "user_initials",
1508 sNType15[] = "user_street" , sNType16[] = "user_country" ,
1509 sNType17[] = "user_zipcode" , sNType18[] = "user_city" ,
1510 sNType19[] = "user_title" , sNType20[] = "user_position" ,
1511 sNType21[] = "user_tel_home", sNType22[] = "user_tel_work",
1512 sNType23[] = "user_fax" , sNType24[] = "user_email" ,
1513 sNType25[] = "user_state", sNType26[] = "graph"
1514 ;
1515
1516 static const char* sNTypeTab[ 27 ] =
1517 {
1518 sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
1519 sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
1520 sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
1521 sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
1522 sNType24, sNType25, sNType26
1523 };
1524
1525 const unsigned short nTableSize = 47;
1526 int aArr[ nTableSize ] = { 0 };
1527 char ch;
1528
1529 for( int n = 0; n < 27; ++n )
1530 {
1531 unsigned int ii = 0;
1532 const char* pp = sNTypeTab[ n ];
1533
1534 while( *pp )
1535 {
1536 ii = ii << 1 ^ *pp++;
1537 }
1538 ii %= nTableSize;
1539
1540 ch = aArr[ ii ] ? 'X' : ' ';
1541 aArr[ ii ] = 1;
1542 printf( "%-20s -> %3u [%c]\n", sNTypeTab[ n ], ii, ch );
1543 }
1544}
1545
1546#endif
1547
1548/* 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:207
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
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:197
const sal_Unicode cListDelim
Definition: calc.hxx:42
#define TBLSZ
Definition: calc.hxx:40
SwCalcError
Definition: calc.hxx:104
SwCalcOper
Definition: calc.hxx:45
@ CALC_SIN
Definition: calc.hxx:56
@ CALC_ACOS
Definition: calc.hxx:58
@ CALC_OR
Definition: calc.hxx:51
@ CALC_ENDCALC
Definition: calc.hxx:46
@ CALC_GEQ
Definition: calc.hxx:53
@ CALC_NOT
Definition: calc.hxx:51
@ CALC_DAY
Definition: calc.hxx:60
@ CALC_PRINT
Definition: calc.hxx:48
@ CALC_PRODUCT
Definition: calc.hxx:60
@ CALC_AND
Definition: calc.hxx:51
@ CALC_NEQ
Definition: calc.hxx:52
@ CALC_MUL
Definition: calc.hxx:47
@ CALC_MAX
Definition: calc.hxx:56
@ CALC_EQ
Definition: calc.hxx:52
@ CALC_ASSIGN
Definition: calc.hxx:48
@ CALC_ROUND
Definition: calc.hxx:59
@ CALC_ATAN
Definition: calc.hxx:58
@ CALC_RP
Definition: calc.hxx:49
@ CALC_XOR
Definition: calc.hxx:52
@ CALC_MIN_IN
Definition: calc.hxx:55
@ CALC_MONTH
Definition: calc.hxx:59
@ CALC_INT
Definition: calc.hxx:62
@ CALC_SIGN
Definition: calc.hxx:61
@ CALC_DATE
Definition: calc.hxx:59
@ CALC_COUNT
Definition: calc.hxx:61
@ CALC_MIN
Definition: calc.hxx:55
@ CALC_SUM
Definition: calc.hxx:54
@ CALC_NAME
Definition: calc.hxx:46
@ CALC_COS
Definition: calc.hxx:57
@ CALC_ASIN
Definition: calc.hxx:57
@ CALC_MAX_IN
Definition: calc.hxx:56
@ CALC_ABS
Definition: calc.hxx:61
@ CALC_GRE
Definition: calc.hxx:54
@ CALC_PHD
Definition: calc.hxx:49
@ CALC_LES
Definition: calc.hxx:53
@ CALC_PLUS
Definition: calc.hxx:47
@ CALC_POW
Definition: calc.hxx:50
@ CALC_AVERAGE
Definition: calc.hxx:60
@ CALC_LEQ
Definition: calc.hxx:53
@ CALC_DIV
Definition: calc.hxx:48
@ CALC_MINUS
Definition: calc.hxx:47
@ CALC_NUMBER
Definition: calc.hxx:46
@ CALC_MEAN
Definition: calc.hxx:54
@ CALC_SQRT
Definition: calc.hxx:55
@ CALC_TAN
Definition: calc.hxx:57
@ CALC_LP
Definition: calc.hxx:49
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:391
static SW_DLLPUBLIC bool IsValidVarName(const OUString &rStr, OUString *pValidName=nullptr)
Definition: calc.cxx:1420
OUStringBuffer m_aVarName
Definition: calc.hxx:202
void Pop()
Definition: calc.cxx:625
SwSbxValue Prim()
Definition: calc.cxx:1272
OUString m_sCurrSym
Definition: calc.hxx:203
const CharClass * GetCharClass() const
Definition: calc.cxx:632
SwCalcOper GetToken()
Definition: calc.cxx:642
std::vector< const SwUserFieldType * > m_aRekurStack
Definition: calc.hxx:205
~SwCalc()
Definition: calc.cxx:358
void VarChange(const OUString &rStr, const SwSbxValue &rValue)
Definition: calc.cxx:597
SwSbxValue StdFunc(pfCalc pFnc, bool bChkTrig)
Definition: calc.cxx:1048
SwDoc & m_rDoc
Definition: calc.hxx:211
SwCalcExp * VarInsert(const OUString &r)
Definition: calc.cxx:423
SwCalcError m_eError
Definition: calc.hxx:219
SwSbxValue Expr()
Definition: calc.cxx:1309
SwCalc(const SwCalc &)=delete
void SetCharClass(const LanguageTag &rLanguageTag)
Definition: calc.cxx:637
SwSbxValue Calculate(const OUString &rStr)
Definition: calc.cxx:363
SwSbxValue PrimFunc(bool &rChkPow)
Definition: calc.cxx:1060
OUString m_sCommand
Definition: calc.hxx:204
bool Push(const SwUserFieldType *pUserFieldType)
Definition: calc.cxx:616
SwCalcOper m_eCurrOper
Definition: calc.hxx:217
SwCalcExp * VarLook(const OUString &rStr, bool bIns=false)
Definition: calc.cxx:429
SwSbxValue m_nLastLeft
Definition: calc.hxx:206
static OUString GetColumnName(const OUString &rName)
Definition: calc.cxx:1344
static LanguageType GetDocAppScriptLang(SwDoc const &rDoc)
Definition: calc.cxx:199
bool m_bHasNumber
Definition: calc.hxx:216
SwHashTable< SwCalcExp > m_aVarTable
Definition: calc.hxx:201
OUString GetDBName(std::u16string_view rName)
Definition: calc.cxx:1357
static bool Str2Double(const OUString &rStr, sal_Int32 &rPos, double &rVal)
Definition: calc.cxx:1393
SwCalcExp m_aErrExpr
Definition: calc.hxx:208
SwSbxValue m_nNumberValue
Definition: calc.hxx:207
sal_Int32 m_nCommandPos
Definition: calc.hxx:209
CharClass * m_pCharClass
Definition: calc.hxx:213
SwSbxValue Term()
Definition: calc.cxx:867
sal_uInt16 m_nListPor
Definition: calc.hxx:215
std::unique_ptr< LocaleDataWrapper > m_xLocaleDataWrapper
Definition: calc.hxx:212
SwCalcOper m_eCurrListOper
Definition: calc.hxx:218
void ImplDestroy()
Definition: calc.cxx:352
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:2310
bool GetColumnCnt(const OUString &rSourceName, const OUString &rTableName, const OUString &rColumnName, sal_uInt32 nAbsRecordId, LanguageType nLanguage, OUString &rResult, double *pNumber)
Definition: dbmgr.cxx:2046
sal_uInt32 GetSelectedRecordId(const OUString &rDataSource, const OUString &rTableOrQuery, sal_Int32 nCommandType=-1)
Definition: dbmgr.cxx:2378
SwHashTable< SwCalcFieldType > const & GetFieldTypeTable() const
Definition: docfld.hxx:188
Definition: doc.hxx:197
SwDBData const & GetDBData()
Definition: docfld.cxx:386
SwDBManager * GetDBManager() const
Definition: doc.hxx:685
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:371
const SfxPoolItem & GetDefault(sal_uInt16 nFormatHint) const
Get the default attribute in this document.
Definition: docfmt.cxx:672
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1429
IDocumentStatistics const & getIDocumentStatistics() const
Definition: doc.cxx:387
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:247
SwFieldIds Which() const
Definition: fldbas.hxx:276
static const OUString & GetTypeStr(SwFieldTypesEnum nTypeId)
Definition: fldbas.cxx:124
T * Find(std::u16string_view aStr, sal_uInt32 *pPos=nullptr) const
Definition: calc.hxx:166
bool IsDBvalue() const
Definition: calc.hxx:130
bool IsVoidValue() const
Definition: calc.hxx:127
bool GetBool() const
Definition: calc.cxx:1462
void SetVoidValue(bool bSet)
Definition: calc.hxx:128
double GetDouble() const
Definition: calc.cxx:1468
SwSbxValue & MakeDouble()
Definition: calc.cxx:1487
The shared part of a user field.
Definition: usrfld.hxx:35
OUString GetContent(sal_uInt32 nFormat=0) const
Definition: usrfld.cxx:283
double GetValue(SwCalc &rCalc)
Definition: usrfld.cxx:236
sal_uInt16 GetType() const
Definition: usrfld.hxx:90
bool IsValid() const
Definition: usrfld.hxx:81
static ShellResource * GetShellRes()
Definition: viewsh.cxx:2664
#define suppress_fun_call_w_exception(expr)
SwDoc & m_rDoc
Definition: docbm.cxx:1228
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:184
CharClass & GetAppCharClass()
Definition: init.cxx:721
LanguageType GetAppLanguage()
Definition: init.cxx:741
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:207
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:145
SwCalcExp(const OUString &rStr, SwSbxValue aVal, const SwFieldType *pFieldType)
Definition: calc.cxx:1454
const SwFieldType * pFieldType
Definition: calc.hxx:146
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:136
SwHash(OUString aStr)
Definition: calc.cxx:1445
OUString aStr
Definition: calc.hxx:139
std::unique_ptr< SwHash > pNext
Definition: calc.hxx:140
virtual ~SwHash()
Definition: calc.cxx:1450
#define SW_MOD()
Definition: swmodule.hxx:254
#define DB_DELIM
Definition: swtypes.hxx:130
sal_uInt16 sal_Unicode
UserOptToken
sal_uInt64 left