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 <scitems.hxx> 21 #include <svx/algitem.hxx> 22 #include <editeng/brushitem.hxx> 23 #include <editeng/editobj.hxx> 24 #include <svl/srchitem.hxx> 25 #include <editeng/langitem.hxx> 26 #include <sfx2/docfile.hxx> 27 #include <sfx2/dispatch.hxx> 28 #include <sfx2/objsh.hxx> 29 #include <sfx2/sfxsids.hrc> 30 #include <sfx2/viewfrm.hxx> 31 #include <sfx2/viewsh.hxx> 32 #include <svl/intitem.hxx> 33 #include <svl/stritem.hxx> 34 #include <svl/zforlist.hxx> 35 #include <svl/zformat.hxx> 36 #include <vcl/keycodes.hxx> 37 #include <vcl/virdev.hxx> 38 #include <vcl/settings.hxx> 39 #include <vcl/svapp.hxx> 40 #include <unotools/charclass.hxx> 41 #include <unotools/securityoptions.hxx> 42 #include <osl/diagnose.h> 43 44 #include <i18nlangtag/mslangid.hxx> 45 #include <comphelper/doublecheckedinit.hxx> 46 #include <comphelper/processfactory.hxx> 47 #include <comphelper/string.hxx> 48 #include <unotools/calendarwrapper.hxx> 49 #include <unotools/collatorwrapper.hxx> 50 #include <unotools/syslocale.hxx> 51 #include <unotools/transliterationwrapper.hxx> 52 53 #include <comphelper/lok.hxx> 54 #include <vcl/opengl/OpenGLWrapper.hxx> 55 56 #include <global.hxx> 57 #include <scresid.hxx> 58 #include <autoform.hxx> 59 #include <patattr.hxx> 60 #include <addincol.hxx> 61 #include <adiasync.hxx> 62 #include <userlist.hxx> 63 #include <interpre.hxx> 64 #include <unitconv.hxx> 65 #include <compiler.hxx> 66 #include <parclass.hxx> 67 #include <funcdesc.hxx> 68 #include <globstr.hrc> 69 #include <strings.hrc> 70 #include <scmod.hxx> 71 #include <editutil.hxx> 72 #include <docsh.hxx> 73 74 tools::SvRef<ScDocShell> ScGlobal::xDrawClipDocShellRef; 75 SvxSearchItem* ScGlobal::pSearchItem = nullptr; 76 ScAutoFormat* ScGlobal::pAutoFormat = nullptr; 77 std::atomic<LegacyFuncCollection*> ScGlobal::pLegacyFuncCollection(nullptr); 78 std::atomic<ScUnoAddInCollection*> ScGlobal::pAddInCollection(nullptr); 79 ScUserList* ScGlobal::pUserList = nullptr; 80 LanguageType ScGlobal::eLnge = LANGUAGE_SYSTEM; 81 std::atomic<css::lang::Locale*> ScGlobal::pLocale(nullptr); 82 SvtSysLocale* ScGlobal::pSysLocale = nullptr; 83 CalendarWrapper* ScGlobal::pCalendar = nullptr; 84 std::atomic<CollatorWrapper*> ScGlobal::pCollator(nullptr); 85 std::atomic<CollatorWrapper*> ScGlobal::pCaseCollator(nullptr); 86 std::atomic<::utl::TransliterationWrapper*> ScGlobal::pTransliteration(nullptr); 87 std::atomic<::utl::TransliterationWrapper*> ScGlobal::pCaseTransliteration(nullptr); 88 css::uno::Reference< css::i18n::XOrdinalSuffix> ScGlobal::xOrdinalSuffix; 89 const OUString ScGlobal::aEmptyOUString; 90 OUString* ScGlobal::pStrClipDocName = nullptr; 91 92 SvxBrushItem* ScGlobal::pEmptyBrushItem = nullptr; 93 SvxBrushItem* ScGlobal::pButtonBrushItem = nullptr; 94 SvxBrushItem* ScGlobal::pEmbeddedBrushItem = nullptr; 95 96 ScFunctionList* ScGlobal::pStarCalcFunctionList = nullptr; 97 ScFunctionMgr* ScGlobal::pStarCalcFunctionMgr = nullptr; 98 99 std::atomic<ScUnitConverter*> ScGlobal::pUnitConverter(nullptr); 100 SvNumberFormatter* ScGlobal::pEnglishFormatter = nullptr; 101 ScFieldEditEngine* ScGlobal::pFieldEditEngine = nullptr; 102 103 double ScGlobal::nScreenPPTX = 96.0; 104 double ScGlobal::nScreenPPTY = 96.0; 105 106 sal_uInt16 ScGlobal::nDefFontHeight = 225; 107 sal_uInt16 ScGlobal::nStdRowHeight = 256; 108 109 long ScGlobal::nLastRowHeightExtra = 0; 110 long ScGlobal::nLastColWidthExtra = STD_EXTRA_WIDTH; 111 112 SfxViewShell* pScActiveViewShell = nullptr; //FIXME: Make this a member 113 sal_uInt16 nScClickMouseModifier = 0; //FIXME: This too 114 sal_uInt16 nScFillModeMouseModifier = 0; //FIXME: And this 115 116 bool ScGlobal::bThreadedGroupCalcInProgress = false; 117 118 // Static functions 119 120 bool ScGlobal::HasAttrChanged( const SfxItemSet& rNewAttrs, 121 const SfxItemSet& rOldAttrs, 122 const sal_uInt16 nWhich ) 123 { 124 bool bInvalidate = false; 125 const SfxPoolItem* pNewItem = nullptr; 126 const SfxItemState eNewState = rNewAttrs.GetItemState( nWhich, true, &pNewItem ); 127 const SfxPoolItem* pOldItem = nullptr; 128 const SfxItemState eOldState = rOldAttrs.GetItemState( nWhich, true, &pOldItem ); 129 130 if ( eNewState == eOldState ) 131 { 132 // Both Items set 133 // PoolItems, meaning comparing pointers is valid 134 if ( SfxItemState::SET == eOldState ) 135 bInvalidate = (pNewItem != pOldItem); 136 } 137 else 138 { 139 // Contains a Default Item 140 // PoolItems, meaning Item comparison necessary 141 if (!pOldItem) 142 pOldItem = &rOldAttrs.GetPool()->GetDefaultItem( nWhich ); 143 144 if (!pNewItem) 145 pNewItem = &rNewAttrs.GetPool()->GetDefaultItem( nWhich ); 146 147 bInvalidate = (*pNewItem != *pOldItem); 148 } 149 150 return bInvalidate; 151 } 152 153 sal_uInt32 ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter, 154 sal_uInt32 nFormat, SvNumFormatType nType ) 155 { 156 const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat ); 157 if ( pFormat ) 158 return rFormatter.GetStandardFormat( nFormat, nType, pFormat->GetLanguage() ); 159 return rFormatter.GetStandardFormat( nType, eLnge ); 160 } 161 162 sal_uInt16 ScGlobal::GetStandardRowHeight() 163 { 164 return nStdRowHeight; 165 } 166 167 SvNumberFormatter* ScGlobal::GetEnglishFormatter() 168 { 169 assert(!bThreadedGroupCalcInProgress); 170 if ( !pEnglishFormatter ) 171 { 172 pEnglishFormatter = new SvNumberFormatter( 173 ::comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US ); 174 pEnglishFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT ); 175 } 176 return pEnglishFormatter; 177 } 178 179 bool ScGlobal::CheckWidthInvalidate( bool& bNumFormatChanged, 180 const SfxItemSet& rNewAttrs, 181 const SfxItemSet& rOldAttrs ) 182 { 183 // Check whether attribute changes in rNewAttrs compared to rOldAttrs render 184 // the text width at a cell invalid 185 bNumFormatChanged = 186 HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_VALUE_FORMAT ); 187 return ( bNumFormatChanged 188 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LANGUAGE_FORMAT ) 189 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT ) 190 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT ) 191 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT ) 192 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_HEIGHT ) 193 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_HEIGHT ) 194 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_HEIGHT ) 195 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_WEIGHT ) 196 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_WEIGHT ) 197 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_WEIGHT ) 198 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_POSTURE ) 199 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_POSTURE ) 200 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_POSTURE ) 201 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_UNDERLINE ) 202 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_OVERLINE ) 203 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CROSSEDOUT ) 204 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CONTOUR ) 205 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_SHADOWED ) 206 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_STACKED ) 207 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_VALUE ) 208 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_MODE ) 209 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LINEBREAK ) 210 || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_MARGIN ) 211 ); 212 } 213 214 const SvxSearchItem& ScGlobal::GetSearchItem() 215 { 216 assert(!bThreadedGroupCalcInProgress); 217 if (!pSearchItem) 218 { 219 pSearchItem = new SvxSearchItem( SID_SEARCH_ITEM ); 220 pSearchItem->SetAppFlag( SvxSearchApp::CALC ); 221 } 222 return *pSearchItem; 223 } 224 225 void ScGlobal::SetSearchItem( const SvxSearchItem& rNew ) 226 { 227 assert(!bThreadedGroupCalcInProgress); 228 // FIXME: An assignment operator would be nice here 229 delete pSearchItem; 230 pSearchItem = rNew.Clone(); 231 232 pSearchItem->SetWhich( SID_SEARCH_ITEM ); 233 pSearchItem->SetAppFlag( SvxSearchApp::CALC ); 234 } 235 236 void ScGlobal::ClearAutoFormat() 237 { 238 assert(!bThreadedGroupCalcInProgress); 239 if (pAutoFormat) 240 { 241 // When modified via StarOne then only the SaveLater flag is set and no saving is done. 242 // If the flag is set then save now. 243 if (pAutoFormat->IsSaveLater()) 244 pAutoFormat->Save(); 245 delete pAutoFormat; 246 pAutoFormat = nullptr; 247 } 248 } 249 250 ScAutoFormat* ScGlobal::GetAutoFormat() 251 { 252 return pAutoFormat; 253 } 254 255 ScAutoFormat* ScGlobal::GetOrCreateAutoFormat() 256 { 257 assert(!bThreadedGroupCalcInProgress); 258 if ( !pAutoFormat ) 259 { 260 pAutoFormat = new ScAutoFormat; 261 pAutoFormat->Load(); 262 } 263 264 return pAutoFormat; 265 } 266 267 LegacyFuncCollection* ScGlobal::GetLegacyFuncCollection() 268 { 269 return comphelper::doubleCheckedInit( pLegacyFuncCollection, []() { return new LegacyFuncCollection(); }); 270 } 271 272 ScUnoAddInCollection* ScGlobal::GetAddInCollection() 273 { 274 return comphelper::doubleCheckedInit( pAddInCollection, []() { return new ScUnoAddInCollection(); }); 275 } 276 277 ScUserList* ScGlobal::GetUserList() 278 { 279 assert(!bThreadedGroupCalcInProgress); 280 // Hack: Load Cfg item at the App 281 global_InitAppOptions(); 282 283 if (!pUserList) 284 pUserList = new ScUserList(); 285 return pUserList; 286 } 287 288 void ScGlobal::SetUserList( const ScUserList* pNewList ) 289 { 290 assert(!bThreadedGroupCalcInProgress); 291 if ( pNewList ) 292 { 293 if ( !pUserList ) 294 pUserList = new ScUserList( *pNewList ); 295 else 296 *pUserList = *pNewList; 297 } 298 else 299 { 300 delete pUserList; 301 pUserList = nullptr; 302 } 303 } 304 305 OUString ScGlobal::GetErrorString(FormulaError nErr) 306 { 307 const char* pErrNumber; 308 switch (nErr) 309 { 310 case FormulaError::NoRef: 311 pErrNumber = STR_NO_REF_TABLE; 312 break; 313 case FormulaError::NoAddin: 314 pErrNumber = STR_NO_ADDIN; 315 break; 316 case FormulaError::NoMacro: 317 pErrNumber = STR_NO_MACRO; 318 break; 319 case FormulaError::NotAvailable: 320 return ScCompiler::GetNativeSymbol(ocErrNA); 321 case FormulaError::NoName: 322 return ScCompiler::GetNativeSymbol(ocErrName); 323 case FormulaError::NoValue: 324 return ScCompiler::GetNativeSymbol(ocErrValue); 325 case FormulaError::NoCode: 326 return ScCompiler::GetNativeSymbol(ocErrNull); 327 case FormulaError::DivisionByZero: 328 return ScCompiler::GetNativeSymbol(ocErrDivZero); 329 case FormulaError::IllegalFPOperation: 330 return ScCompiler::GetNativeSymbol(ocErrNum); 331 default: 332 return ScResId(STR_ERROR_STR) + OUString::number( static_cast<int>(nErr) ); 333 } 334 return ScResId(pErrNumber); 335 } 336 337 OUString ScGlobal::GetLongErrorString(FormulaError nErr) 338 { 339 const char* pErrNumber; 340 switch (nErr) 341 { 342 case FormulaError::NONE: 343 return OUString(); 344 case FormulaError::IllegalArgument: 345 pErrNumber = STR_LONG_ERR_ILL_ARG; 346 break; 347 case FormulaError::IllegalFPOperation: 348 pErrNumber = STR_LONG_ERR_ILL_FPO; 349 break; 350 case FormulaError::IllegalChar: 351 pErrNumber = STR_LONG_ERR_ILL_CHAR; 352 break; 353 case FormulaError::IllegalParameter: 354 pErrNumber = STR_LONG_ERR_ILL_PAR; 355 break; 356 case FormulaError::Pair: 357 case FormulaError::PairExpected: 358 pErrNumber = STR_LONG_ERR_PAIR; 359 break; 360 case FormulaError::OperatorExpected: 361 pErrNumber = STR_LONG_ERR_OP_EXP; 362 break; 363 case FormulaError::VariableExpected: 364 case FormulaError::ParameterExpected: 365 pErrNumber = STR_LONG_ERR_VAR_EXP; 366 break; 367 case FormulaError::CodeOverflow: 368 pErrNumber = STR_LONG_ERR_CODE_OVF; 369 break; 370 case FormulaError::StringOverflow: 371 pErrNumber = STR_LONG_ERR_STR_OVF; 372 break; 373 case FormulaError::StackOverflow: 374 pErrNumber = STR_LONG_ERR_STACK_OVF; 375 break; 376 case FormulaError::MatrixSize: 377 pErrNumber = STR_LONG_ERR_MATRIX_SIZE; 378 break; 379 case FormulaError::UnknownState: 380 case FormulaError::UnknownVariable: 381 case FormulaError::UnknownOpCode: 382 case FormulaError::UnknownStackVariable: 383 case FormulaError::UnknownToken: 384 case FormulaError::NoCode: 385 pErrNumber = STR_LONG_ERR_SYNTAX; 386 break; 387 case FormulaError::CircularReference: 388 pErrNumber = STR_LONG_ERR_CIRC_REF; 389 break; 390 case FormulaError::NoConvergence: 391 pErrNumber = STR_LONG_ERR_NO_CONV; 392 break; 393 case FormulaError::NoRef: 394 pErrNumber = STR_LONG_ERR_NO_REF; 395 break; 396 case FormulaError::NoName: 397 pErrNumber = STR_LONG_ERR_NO_NAME; 398 break; 399 case FormulaError::NoAddin: 400 pErrNumber = STR_LONG_ERR_NO_ADDIN; 401 break; 402 case FormulaError::NoMacro: 403 pErrNumber = STR_LONG_ERR_NO_MACRO; 404 break; 405 case FormulaError::DivisionByZero: 406 pErrNumber = STR_LONG_ERR_DIV_ZERO; 407 break; 408 case FormulaError::NestedArray: 409 pErrNumber = STR_ERR_LONG_NESTED_ARRAY; 410 break; 411 case FormulaError::BadArrayContent: 412 pErrNumber = STR_ERR_LONG_BAD_ARRAY_CONTENT; 413 break; 414 case FormulaError::LinkFormulaNeedingCheck: 415 pErrNumber = STR_ERR_LONG_LINK_FORMULA_NEEDING_CHECK; 416 break; 417 case FormulaError::NoValue: 418 pErrNumber = STR_LONG_ERR_NO_VALUE; 419 break; 420 case FormulaError::NotAvailable: 421 pErrNumber = STR_LONG_ERR_NV; 422 break; 423 default: 424 return ScResId(STR_ERROR_STR) + OUString::number( static_cast<int>(nErr) ); 425 break; 426 } 427 return ScResId(pErrNumber); 428 } 429 430 SvxBrushItem* ScGlobal::GetButtonBrushItem() 431 { 432 assert(!bThreadedGroupCalcInProgress); 433 pButtonBrushItem->SetColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); 434 return pButtonBrushItem; 435 } 436 437 void ScGlobal::Init() 438 { 439 // The default language for number formats (ScGlobal::eLnge) must 440 // always be LANGUAGE_SYSTEM 441 // FIXME: So remove this variable? 442 eLnge = LANGUAGE_SYSTEM; 443 444 // FIXME: If the sort-order etc. should depend the installed Office version 445 // use Application::GetSettings().GetUILanguage() here 446 pSysLocale = new SvtSysLocale; 447 448 pEmptyBrushItem = new SvxBrushItem( COL_TRANSPARENT, ATTR_BACKGROUND ); 449 pButtonBrushItem = new SvxBrushItem( Color(), ATTR_BACKGROUND ); 450 pEmbeddedBrushItem = new SvxBrushItem( COL_LIGHTCYAN, ATTR_BACKGROUND ); 451 452 InitPPT(); 453 //ScCompiler::InitSymbolsNative(); 454 // ScParameterClassification _after_ Compiler, needs function resources if 455 // arguments are to be merged in, which in turn need strings of function 456 // names from the compiler. 457 ScParameterClassification::Init(); 458 459 InitAddIns(); 460 461 pStrClipDocName = new OUString( ScResId( SCSTR_NONAME ) ); 462 *pStrClipDocName += "1"; 463 464 // ScDocumentPool::InitVersionMaps() has been called earlier already 465 } 466 467 void ScGlobal::InitPPT() 468 { 469 OutputDevice* pDev = Application::GetDefaultDevice(); 470 471 if (comphelper::LibreOfficeKit::isActive() || OpenGLWrapper::isVCLOpenGLEnabled()) 472 { 473 // LOK: the below limited precision is not enough for RowColumnHeader. 474 // OpenGL: limited precision breaks AA of text in charts. 475 nScreenPPTX = double(pDev->GetDPIX()) / double(TWIPS_PER_INCH); 476 nScreenPPTY = double(pDev->GetDPIY()) / double(TWIPS_PER_INCH); 477 } 478 else 479 { 480 // Avoid cumulative placement errors by intentionally limiting 481 // precision. 482 Point aPix1000 = pDev->LogicToPixel(Point(1000, 1000), MapMode(MapUnit::MapTwip)); 483 nScreenPPTX = aPix1000.X() / 1000.0; 484 nScreenPPTY = aPix1000.Y() / 1000.0; 485 } 486 } 487 488 const OUString& ScGlobal::GetClipDocName() 489 { 490 return *pStrClipDocName; 491 } 492 493 void ScGlobal::SetClipDocName( const OUString& rNew ) 494 { 495 assert(!bThreadedGroupCalcInProgress); 496 *pStrClipDocName = rNew; 497 } 498 499 void ScGlobal::InitTextHeight(const SfxItemPool* pPool) 500 { 501 if (!pPool) 502 { 503 OSL_FAIL("ScGlobal::InitTextHeight: No Pool"); 504 return; 505 } 506 507 const ScPatternAttr& rPattern = pPool->GetDefaultItem(ATTR_PATTERN); 508 509 OutputDevice* pDefaultDev = Application::GetDefaultDevice(); 510 ScopedVclPtrInstance< VirtualDevice > pVirtWindow( *pDefaultDev ); 511 pVirtWindow->SetMapMode(MapMode(MapUnit::MapPixel)); 512 vcl::Font aDefFont; 513 rPattern.GetFont(aDefFont, SC_AUTOCOL_BLACK, pVirtWindow); // Font color doesn't matter here 514 pVirtWindow->SetFont(aDefFont); 515 sal_uInt16 nTest = static_cast<sal_uInt16>( 516 pVirtWindow->PixelToLogic(Size(0, pVirtWindow->GetTextHeight()), MapMode(MapUnit::MapTwip)).Height()); 517 518 if (nTest > nDefFontHeight) 519 nDefFontHeight = nTest; 520 521 const SvxMarginItem& rMargin = rPattern.GetItem(ATTR_MARGIN); 522 523 nTest = static_cast<sal_uInt16>(nDefFontHeight + rMargin.GetTopMargin() 524 + rMargin.GetBottomMargin() - STD_ROWHEIGHT_DIFF); 525 526 if (nTest > nStdRowHeight) 527 nStdRowHeight = nTest; 528 } 529 530 void ScGlobal::Clear() 531 { 532 // Destroy asyncs _before_ ExitExternalFunc! 533 theAddInAsyncTbl.clear(); 534 ExitExternalFunc(); 535 ClearAutoFormat(); 536 DELETEZ(pSearchItem); 537 delete pLegacyFuncCollection.load(); pLegacyFuncCollection = nullptr; 538 delete pAddInCollection.load(); pAddInCollection = nullptr; 539 DELETEZ(pUserList); 540 DELETEZ(pStarCalcFunctionList); // Destroy before ResMgr! 541 DELETEZ(pStarCalcFunctionMgr); 542 ScParameterClassification::Exit(); 543 ScCompiler::DeInit(); 544 ScInterpreter::GlobalExit(); // Delete static Stack 545 546 DELETEZ(pEmptyBrushItem); 547 DELETEZ(pButtonBrushItem); 548 DELETEZ(pEmbeddedBrushItem); 549 DELETEZ(pEnglishFormatter); 550 delete pCaseTransliteration.load(); pCaseTransliteration = nullptr; 551 delete pTransliteration.load(); pTransliteration = nullptr; 552 delete pCaseCollator.load(); pCaseCollator = nullptr; 553 delete pCollator.load(); pCollator = nullptr; 554 DELETEZ(pCalendar); 555 DELETEZ(pSysLocale); 556 delete pLocale.load(); pLocale = nullptr; 557 DELETEZ(pStrClipDocName); 558 559 delete pUnitConverter.load(); pUnitConverter = nullptr; 560 DELETEZ(pFieldEditEngine); 561 562 xDrawClipDocShellRef.clear(); 563 } 564 565 rtl_TextEncoding ScGlobal::GetCharsetValue( const OUString& rCharSet ) 566 { 567 // new TextEncoding values 568 if ( CharClass::isAsciiNumeric( rCharSet ) ) 569 { 570 sal_Int32 nVal = rCharSet.toInt32(); 571 if ( nVal == RTL_TEXTENCODING_DONTKNOW ) 572 return osl_getThreadTextEncoding(); 573 return static_cast<rtl_TextEncoding>(nVal); 574 } 575 // old CharSet values for compatibility 576 else if (rCharSet.equalsIgnoreAsciiCase("ANSI") ) return RTL_TEXTENCODING_MS_1252; 577 else if (rCharSet.equalsIgnoreAsciiCase("MAC") ) return RTL_TEXTENCODING_APPLE_ROMAN; 578 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC") ) return RTL_TEXTENCODING_IBM_850; 579 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_437")) return RTL_TEXTENCODING_IBM_437; 580 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_850")) return RTL_TEXTENCODING_IBM_850; 581 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_860")) return RTL_TEXTENCODING_IBM_860; 582 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_861")) return RTL_TEXTENCODING_IBM_861; 583 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_863")) return RTL_TEXTENCODING_IBM_863; 584 else if (rCharSet.equalsIgnoreAsciiCase("IBMPC_865")) return RTL_TEXTENCODING_IBM_865; 585 // Some wrong "help" on the net mentions UTF8 and even unoconv uses it, 586 // which worked accidentally if the system encoding is UTF-8 anyway, so 587 // support it ;) but only when reading. 588 else if (rCharSet.equalsIgnoreAsciiCase("UTF8")) return RTL_TEXTENCODING_UTF8; 589 else if (rCharSet.equalsIgnoreAsciiCase("UTF-8")) return RTL_TEXTENCODING_UTF8; 590 else return osl_getThreadTextEncoding(); 591 } 592 593 OUString ScGlobal::GetCharsetString( rtl_TextEncoding eVal ) 594 { 595 const char* pChar; 596 switch ( eVal ) 597 { 598 // old CharSet strings for compatibility 599 case RTL_TEXTENCODING_MS_1252: pChar = "ANSI"; break; 600 case RTL_TEXTENCODING_APPLE_ROMAN: pChar = "MAC"; break; 601 // IBMPC == IBMPC_850 602 case RTL_TEXTENCODING_IBM_437: pChar = "IBMPC_437"; break; 603 case RTL_TEXTENCODING_IBM_850: pChar = "IBMPC_850"; break; 604 case RTL_TEXTENCODING_IBM_860: pChar = "IBMPC_860"; break; 605 case RTL_TEXTENCODING_IBM_861: pChar = "IBMPC_861"; break; 606 case RTL_TEXTENCODING_IBM_863: pChar = "IBMPC_863"; break; 607 case RTL_TEXTENCODING_IBM_865: pChar = "IBMPC_865"; break; 608 case RTL_TEXTENCODING_DONTKNOW: pChar = "SYSTEM"; break; 609 // new string of TextEncoding value 610 default: 611 return OUString::number( eVal ); 612 } 613 return OUString::createFromAscii(pChar); 614 } 615 616 bool ScGlobal::HasStarCalcFunctionList() 617 { 618 return ( pStarCalcFunctionList != nullptr ); 619 } 620 621 ScFunctionList* ScGlobal::GetStarCalcFunctionList() 622 { 623 assert(!bThreadedGroupCalcInProgress); 624 if ( !pStarCalcFunctionList ) 625 pStarCalcFunctionList = new ScFunctionList; 626 627 return pStarCalcFunctionList; 628 } 629 630 ScFunctionMgr* ScGlobal::GetStarCalcFunctionMgr() 631 { 632 assert(!bThreadedGroupCalcInProgress); 633 if ( !pStarCalcFunctionMgr ) 634 pStarCalcFunctionMgr = new ScFunctionMgr; 635 636 return pStarCalcFunctionMgr; 637 } 638 639 void ScGlobal::ResetFunctionList() 640 { 641 // FunctionMgr has pointers into FunctionList, must also be updated 642 DELETEZ( pStarCalcFunctionMgr ); 643 DELETEZ( pStarCalcFunctionList ); 644 } 645 646 ScUnitConverter* ScGlobal::GetUnitConverter() 647 { 648 return comphelper::doubleCheckedInit( pUnitConverter, 649 []() { return new ScUnitConverter; }); 650 } 651 652 const sal_Unicode* ScGlobal::UnicodeStrChr( const sal_Unicode* pStr, 653 sal_Unicode c ) 654 { 655 if ( !pStr ) 656 return nullptr; 657 while ( *pStr ) 658 { 659 if ( *pStr == c ) 660 return pStr; 661 pStr++; 662 } 663 return nullptr; 664 } 665 666 OUString ScGlobal::addToken(const OUString& rTokenList, const OUString& rToken, 667 sal_Unicode cSep, sal_Int32 nSepCount, bool bForceSep) 668 { 669 OUStringBuffer aBuf(rTokenList); 670 if( bForceSep || (!rToken.isEmpty() && !rTokenList.isEmpty()) ) 671 comphelper::string::padToLength(aBuf, aBuf.getLength() + nSepCount, cSep); 672 aBuf.append(rToken); 673 return aBuf.makeStringAndClear(); 674 } 675 676 bool ScGlobal::IsQuoted( const OUString& rString, sal_Unicode cQuote ) 677 { 678 return (rString.getLength() >= 2) && (rString[0] == cQuote) && (rString[ rString.getLength() - 1 ] == cQuote); 679 } 680 681 void ScGlobal::AddQuotes( OUString& rString, sal_Unicode cQuote, bool bEscapeEmbedded ) 682 { 683 if (bEscapeEmbedded) 684 { 685 sal_Unicode pQ[3]; 686 pQ[0] = pQ[1] = cQuote; 687 pQ[2] = 0; 688 OUString aQuotes( pQ ); 689 rString = rString.replaceAll( OUStringChar(cQuote), aQuotes); 690 } 691 rString = OUStringChar( cQuote ) + rString + OUStringChar( cQuote ); 692 } 693 694 void ScGlobal::EraseQuotes( OUString& rString, sal_Unicode cQuote, bool bUnescapeEmbedded ) 695 { 696 if ( IsQuoted( rString, cQuote ) ) 697 { 698 rString = rString.copy( 1, rString.getLength() - 2 ); 699 if (bUnescapeEmbedded) 700 { 701 sal_Unicode pQ[3]; 702 pQ[0] = pQ[1] = cQuote; 703 pQ[2] = 0; 704 OUString aQuotes( pQ ); 705 rString = rString.replaceAll( aQuotes, OUStringChar(cQuote)); 706 } 707 } 708 } 709 710 sal_Int32 ScGlobal::FindUnquoted( const OUString& rString, sal_Unicode cChar) 711 { 712 const sal_Unicode cQuote = '\''; 713 const sal_Unicode* const pStart = rString.getStr(); 714 const sal_Unicode* const pStop = pStart + rString.getLength(); 715 const sal_Unicode* p = pStart; 716 bool bQuoted = false; 717 while (p < pStop) 718 { 719 if (*p == cChar && !bQuoted) 720 return sal::static_int_cast< sal_Int32 >( p - pStart ); 721 else if (*p == cQuote) 722 { 723 if (!bQuoted) 724 bQuoted = true; 725 else if (p < pStop-1 && *(p+1) == cQuote) 726 ++p; 727 else 728 bQuoted = false; 729 } 730 ++p; 731 } 732 return -1; 733 } 734 735 const sal_Unicode* ScGlobal::FindUnquoted( const sal_Unicode* pString, sal_Unicode cChar ) 736 { 737 sal_Unicode cQuote = '\''; 738 const sal_Unicode* p = pString; 739 bool bQuoted = false; 740 while (*p) 741 { 742 if (*p == cChar && !bQuoted) 743 return p; 744 else if (*p == cQuote) 745 { 746 if (!bQuoted) 747 bQuoted = true; 748 else if (*(p+1) == cQuote) 749 ++p; 750 else 751 bQuoted = false; 752 } 753 ++p; 754 } 755 return nullptr; 756 } 757 758 bool ScGlobal::EETextObjEqual( const EditTextObject* pObj1, 759 const EditTextObject* pObj2 ) 760 { 761 if ( pObj1 == pObj2 ) // Both empty or the same object 762 return true; 763 764 if ( pObj1 && pObj2 ) 765 return pObj1->Equals( *pObj2); 766 767 return false; 768 } 769 770 void ScGlobal::OpenURL(const OUString& rURL, const OUString& rTarget, bool bIgnoreSettings) 771 { 772 // OpenURL is always called in the GridWindow by mouse clicks in some way or another. 773 // That's why pScActiveViewShell and nScClickMouseModifier are correct. 774 775 if (!bIgnoreSettings && !ShouldOpenURL()) 776 return; 777 778 SfxViewFrame* pViewFrm = SfxViewFrame::Current(); 779 if (!pViewFrm) 780 return; 781 782 OUString aUrlName( rURL ); 783 SfxViewFrame* pFrame = nullptr; 784 const SfxObjectShell* pObjShell = nullptr; 785 OUString aReferName; 786 if ( pScActiveViewShell ) 787 { 788 pFrame = pScActiveViewShell->GetViewFrame(); 789 pObjShell = pFrame->GetObjectShell(); 790 const SfxMedium* pMed = pObjShell->GetMedium(); 791 if (pMed) 792 aReferName = pMed->GetName(); 793 } 794 795 // Don't fiddle with fragments pointing into current document. 796 // Also don't mess around with a vnd.sun.star.script or service or other 797 // internal "URI". 798 if (!aUrlName.startsWith("#") 799 && !aUrlName.startsWithIgnoreAsciiCase("vnd.sun.star.script:") 800 && !aUrlName.startsWithIgnoreAsciiCase("macro:") 801 && !aUrlName.startsWithIgnoreAsciiCase("slot:") 802 && !aUrlName.startsWithIgnoreAsciiCase("service:") 803 && !aUrlName.startsWithIgnoreAsciiCase(".uno:")) 804 { 805 // Any relative reference would fail with "not an absolute URL" 806 // error, try to construct an absolute URI with the path relative 807 // to the current document's path or work path, as usual for all 808 // external references. 809 // This then also, as ScGlobal::GetAbsDocName() uses 810 // INetURLObject::smartRel2Abs(), supports "\\" UNC path names as 811 // smb:// Samba shares and DOS path separators converted to proper 812 // file:// URI. 813 const OUString aNewUrlName( ScGlobal::GetAbsDocName( aUrlName, pObjShell)); 814 if (!aNewUrlName.isEmpty()) 815 aUrlName = aNewUrlName; 816 } 817 818 SfxStringItem aUrl( SID_FILE_NAME, aUrlName ); 819 SfxStringItem aTarget( SID_TARGETNAME, rTarget ); 820 if ( nScClickMouseModifier & KEY_SHIFT ) // control-click -> into new window 821 aTarget.SetValue("_blank"); 822 823 SfxFrameItem aFrm( SID_DOCFRAME, pFrame ); 824 SfxStringItem aReferer( SID_REFERER, aReferName ); 825 826 SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, false ); 827 SfxBoolItem aBrowsing( SID_BROWSE, true ); 828 829 // No SID_SILENT anymore 830 pViewFrm->GetDispatcher()->ExecuteList(SID_OPENDOC, 831 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, 832 { &aUrl, &aTarget, &aFrm, &aReferer, &aNewView, &aBrowsing }); 833 } 834 835 bool ScGlobal::ShouldOpenURL() 836 { 837 SvtSecurityOptions aSecOpt; 838 bool bCtrlClickHappened = (nScClickMouseModifier & KEY_MOD1); 839 bool bCtrlClickSecOption = aSecOpt.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink ); 840 if( bCtrlClickHappened && ! bCtrlClickSecOption ) 841 { 842 // return since ctrl+click happened when the 843 // ctrl+click security option was disabled, link should not open 844 return false; 845 } 846 else if( ! bCtrlClickHappened && bCtrlClickSecOption ) 847 { 848 // ctrl+click did not happen; only click happened maybe with some 849 // other key combo. and security option is set, so return 850 return false; 851 } 852 return true; 853 } 854 855 bool ScGlobal::IsSystemRTL() 856 { 857 return MsLangId::isRightToLeft( Application::GetSettings().GetLanguageTag().getLanguageType() ); 858 } 859 860 SvtScriptType ScGlobal::GetDefaultScriptType() 861 { 862 // Used when text contains only WEAK characters. 863 // Script type of office language is used then (same as GetEditDefaultLanguage, 864 // to get consistent behavior of text in simple cells and EditEngine, 865 // also same as GetAppLanguage() in Writer) 866 return SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ); 867 } 868 869 LanguageType ScGlobal::GetEditDefaultLanguage() 870 { 871 // Used for EditEngine::SetDefaultLanguage 872 return Application::GetSettings().GetLanguageTag().getLanguageType(); 873 } 874 875 sal_uInt16 ScGlobal::GetScriptedWhichID( SvtScriptType nScriptType, sal_uInt16 nWhich ) 876 { 877 switch ( nScriptType ) 878 { 879 case SvtScriptType::LATIN: 880 case SvtScriptType::ASIAN: 881 case SvtScriptType::COMPLEX: 882 break; // take exact matches 883 default: // prefer one, first COMPLEX, then ASIAN 884 if ( nScriptType & SvtScriptType::COMPLEX ) 885 nScriptType = SvtScriptType::COMPLEX; 886 else if ( nScriptType & SvtScriptType::ASIAN ) 887 nScriptType = SvtScriptType::ASIAN; 888 } 889 switch ( nScriptType ) 890 { 891 case SvtScriptType::COMPLEX: 892 { 893 switch ( nWhich ) 894 { 895 case ATTR_FONT: 896 case ATTR_CJK_FONT: 897 nWhich = ATTR_CTL_FONT; 898 break; 899 case ATTR_FONT_HEIGHT: 900 case ATTR_CJK_FONT_HEIGHT: 901 nWhich = ATTR_CTL_FONT_HEIGHT; 902 break; 903 case ATTR_FONT_WEIGHT: 904 case ATTR_CJK_FONT_WEIGHT: 905 nWhich = ATTR_CTL_FONT_WEIGHT; 906 break; 907 case ATTR_FONT_POSTURE: 908 case ATTR_CJK_FONT_POSTURE: 909 nWhich = ATTR_CTL_FONT_POSTURE; 910 break; 911 } 912 } 913 break; 914 case SvtScriptType::ASIAN: 915 { 916 switch ( nWhich ) 917 { 918 case ATTR_FONT: 919 case ATTR_CTL_FONT: 920 nWhich = ATTR_CJK_FONT; 921 break; 922 case ATTR_FONT_HEIGHT: 923 case ATTR_CTL_FONT_HEIGHT: 924 nWhich = ATTR_CJK_FONT_HEIGHT; 925 break; 926 case ATTR_FONT_WEIGHT: 927 case ATTR_CTL_FONT_WEIGHT: 928 nWhich = ATTR_CJK_FONT_WEIGHT; 929 break; 930 case ATTR_FONT_POSTURE: 931 case ATTR_CTL_FONT_POSTURE: 932 nWhich = ATTR_CJK_FONT_POSTURE; 933 break; 934 } 935 } 936 break; 937 default: 938 { 939 switch ( nWhich ) 940 { 941 case ATTR_CTL_FONT: 942 case ATTR_CJK_FONT: 943 nWhich = ATTR_FONT; 944 break; 945 case ATTR_CTL_FONT_HEIGHT: 946 case ATTR_CJK_FONT_HEIGHT: 947 nWhich = ATTR_FONT_HEIGHT; 948 break; 949 case ATTR_CTL_FONT_WEIGHT: 950 case ATTR_CJK_FONT_WEIGHT: 951 nWhich = ATTR_FONT_WEIGHT; 952 break; 953 case ATTR_CTL_FONT_POSTURE: 954 case ATTR_CJK_FONT_POSTURE: 955 nWhich = ATTR_FONT_POSTURE; 956 break; 957 } 958 } 959 } 960 return nWhich; 961 } 962 963 void ScGlobal::AddLanguage( SfxItemSet& rSet, const SvNumberFormatter& rFormatter ) 964 { 965 OSL_ENSURE( rSet.GetItemState( ATTR_LANGUAGE_FORMAT, false ) == SfxItemState::DEFAULT, 966 "ScGlobal::AddLanguage - language already added"); 967 968 const SfxPoolItem* pHardItem; 969 if ( rSet.GetItemState( ATTR_VALUE_FORMAT, false, &pHardItem ) == SfxItemState::SET ) 970 { 971 const SvNumberformat* pHardFormat = rFormatter.GetEntry( 972 static_cast<const SfxUInt32Item*>(pHardItem)->GetValue() ); 973 974 sal_uInt32 nParentFmt = 0; // Pool default 975 const SfxItemSet* pParent = rSet.GetParent(); 976 if ( pParent ) 977 nParentFmt = pParent->Get( ATTR_VALUE_FORMAT ).GetValue(); 978 const SvNumberformat* pParFormat = rFormatter.GetEntry( nParentFmt ); 979 980 if ( pHardFormat && pParFormat && 981 (pHardFormat->GetLanguage() != pParFormat->GetLanguage()) ) 982 rSet.Put( SvxLanguageItem( pHardFormat->GetLanguage(), ATTR_LANGUAGE_FORMAT ) ); 983 } 984 } 985 986 utl::TransliterationWrapper* ScGlobal::GetpTransliteration() 987 { 988 return comphelper::doubleCheckedInit( pTransliteration, 989 []() 990 { 991 const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); 992 ::utl::TransliterationWrapper* p = new ::utl::TransliterationWrapper( 993 ::comphelper::getProcessComponentContext(), TransliterationFlags::IGNORE_CASE ); 994 p->loadModuleIfNeeded( eOfficeLanguage ); 995 return p; 996 }); 997 } 998 ::utl::TransliterationWrapper* ScGlobal::GetCaseTransliteration() 999 { 1000 return comphelper::doubleCheckedInit( pCaseTransliteration, 1001 []() 1002 { 1003 const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); 1004 ::utl::TransliterationWrapper* p = new ::utl::TransliterationWrapper( 1005 ::comphelper::getProcessComponentContext(), TransliterationFlags::NONE ); 1006 p->loadModuleIfNeeded( eOfficeLanguage ); 1007 return p; 1008 }); 1009 } 1010 1011 const LocaleDataWrapper* ScGlobal::getLocaleDataPtr() 1012 { 1013 OSL_ENSURE( 1014 pSysLocale, 1015 "ScGlobal::getLocaleDataPtr() called before ScGlobal::Init()"); 1016 1017 return pSysLocale->GetLocaleDataPtr(); 1018 } 1019 1020 const CharClass* ScGlobal::getCharClassPtr() 1021 { 1022 OSL_ENSURE( 1023 pSysLocale, 1024 "ScGlobal::getCharClassPtr() called before ScGlobal::Init()"); 1025 1026 return pSysLocale->GetCharClassPtr(); 1027 } 1028 1029 CalendarWrapper* ScGlobal::GetCalendar() 1030 { 1031 assert(!bThreadedGroupCalcInProgress); 1032 if ( !pCalendar ) 1033 { 1034 pCalendar = new CalendarWrapper( ::comphelper::getProcessComponentContext() ); 1035 pCalendar->loadDefaultCalendar( *GetLocale() ); 1036 } 1037 return pCalendar; 1038 } 1039 CollatorWrapper* ScGlobal::GetCollator() 1040 { 1041 return comphelper::doubleCheckedInit( pCollator, 1042 []() 1043 { 1044 CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); 1045 p->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES ); 1046 return p; 1047 }); 1048 } 1049 CollatorWrapper* ScGlobal::GetCaseCollator() 1050 { 1051 return comphelper::doubleCheckedInit( pCaseCollator, 1052 []() 1053 { 1054 CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); 1055 p->loadDefaultCollator( *GetLocale(), 0 ); 1056 return p; 1057 }); 1058 } 1059 css::lang::Locale* ScGlobal::GetLocale() 1060 { 1061 return comphelper::doubleCheckedInit( pLocale, 1062 []() { return new css::lang::Locale( Application::GetSettings().GetLanguageTag().getLocale()); }); 1063 } 1064 1065 ScFieldEditEngine& ScGlobal::GetStaticFieldEditEngine() 1066 { 1067 assert(!bThreadedGroupCalcInProgress); 1068 if (!pFieldEditEngine) 1069 { 1070 // Creating a ScFieldEditEngine with pDocument=NULL leads to document 1071 // specific fields not being resolvable! See 1072 // ScFieldEditEngine::CalcFieldValue(). pEnginePool=NULL lets 1073 // EditEngine internally create and delete a default pool. 1074 pFieldEditEngine = new ScFieldEditEngine( nullptr, nullptr); 1075 } 1076 return *pFieldEditEngine; 1077 } 1078 1079 OUString ScGlobal::ReplaceOrAppend( const OUString& rString, 1080 const OUString& rPlaceholder, const OUString& rReplacement ) 1081 { 1082 if (rString.isEmpty()) 1083 return rReplacement; 1084 sal_Int32 nFound = rString.indexOf( rPlaceholder); 1085 if (nFound < 0) 1086 { 1087 if (rString[rString.getLength()-1] == ' ') 1088 return rString + rReplacement; 1089 return rString + " " + rReplacement; 1090 } 1091 return rString.replaceFirst( rPlaceholder, rReplacement, &nFound); 1092 } 1093 1094 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1095
