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_feature_desktop.h> 21 #include <sal/log.hxx> 22 #include <osl/module.hxx> 23 #include <tools/debug.hxx> 24 25 #include <sfx2/app.hxx> 26 #include <sfx2/frame.hxx> 27 #include <basic/sberrors.hxx> 28 #include <tools/svlibrary.h> 29 30 #include <svl/svdde.hxx> 31 #include <unotools/configmgr.hxx> 32 #include <com/sun/star/frame/XFrame.hpp> 33 #include <comphelper/processfactory.hxx> 34 #include <com/sun/star/uri/UriReferenceFactory.hpp> 35 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> 36 #include <basic/basmgr.hxx> 37 #include <vcl/svapp.hxx> 38 #include <sfx2/sfxhelp.hxx> 39 #include <sfx2/progress.hxx> 40 #include <sfx2/objsh.hxx> 41 #include <sfx2/dispatch.hxx> 42 #include <sfx2/viewsh.hxx> 43 #include <sfx2/viewfrm.hxx> 44 #include <appdata.hxx> 45 #include <sfx2/module.hxx> 46 #include <sfx2/event.hxx> 47 #include <workwin.hxx> 48 #include <sfx2/sidebar/Theme.hxx> 49 #include <sfx2/tbxctrl.hxx> 50 #include <sfx2/sfxdlg.hxx> 51 #include <sfx2/stbitem.hxx> 52 #include <sfx2/dockwin.hxx> 53 #include <shellimpl.hxx> 54 55 #include <svtools/helpopt.hxx> 56 #include <unotools/viewoptions.hxx> 57 #include <rtl/instance.hxx> 58 #include <rtl/strbuf.hxx> 59 #include <memory> 60 #include <framework/sfxhelperfunctions.hxx> 61 #include <fwkhelper.hxx> 62 63 using namespace ::com::sun::star; 64 65 static SfxApplication* g_pSfxApplication = nullptr; 66 67 #if HAVE_FEATURE_DESKTOP 68 static SfxHelp* pSfxHelp = nullptr; 69 #endif 70 71 namespace 72 { 73 class theApplicationMutex 74 : public rtl::Static<osl::Mutex, theApplicationMutex> {}; 75 } 76 77 SfxApplication* SfxApplication::Get() 78 { 79 return g_pSfxApplication; 80 } 81 82 void SfxApplication::SetModule(SfxToolsModule nSharedLib, std::unique_ptr<SfxModule> pModule) 83 { 84 assert(g_pSfxApplication != nullptr); 85 86 g_pSfxApplication->pImpl->aModules[nSharedLib] = std::move(pModule); 87 } 88 89 SfxModule* SfxApplication::GetModule(SfxToolsModule nSharedLib) 90 { 91 if (!g_pSfxApplication) // It is possible GetModule is called before SfxApplication is initialised via GetOrCreate() 92 return nullptr; 93 return g_pSfxApplication->pImpl->aModules[nSharedLib].get(); 94 } 95 96 SfxApplication* SfxApplication::GetOrCreate() 97 { 98 // SFX on demand 99 ::osl::MutexGuard aGuard(theApplicationMutex::get()); 100 if (!g_pSfxApplication) 101 { 102 SAL_INFO( "sfx.appl", "SfxApplication::SetApp" ); 103 104 g_pSfxApplication = new SfxApplication; 105 106 // at the moment a bug may occur when Initialize_Impl returns FALSE, 107 // but this is only temporary because all code that may cause such 108 // a fault will be moved outside the SFX 109 g_pSfxApplication->Initialize_Impl(); 110 111 ::framework::SetRefreshToolbars( RefreshToolbars ); 112 ::framework::SetToolBoxControllerCreator( SfxToolBoxControllerFactory ); 113 ::framework::SetStatusBarControllerCreator( SfxStatusBarControllerFactory ); 114 ::framework::SetDockingWindowCreator( SfxDockingWindowFactory ); 115 ::framework::SetIsDockingWindowVisible( IsDockingWindowVisible ); 116 #if HAVE_FEATURE_DESKTOP 117 Application::SetHelp( pSfxHelp ); 118 if (!utl::ConfigManager::IsFuzzing() && SvtHelpOptions().IsHelpTips()) 119 Help::EnableQuickHelp(); 120 else 121 Help::DisableQuickHelp(); 122 if (!utl::ConfigManager::IsFuzzing() && SvtHelpOptions().IsHelpTips() && SvtHelpOptions().IsExtendedHelp()) 123 Help::EnableBalloonHelp(); 124 else 125 Help::DisableBalloonHelp(); 126 #endif 127 } 128 return g_pSfxApplication; 129 } 130 131 SfxApplication::SfxApplication() 132 : pImpl( new SfxAppData_Impl ) 133 { 134 SetName( "StarOffice" ); 135 if (!utl::ConfigManager::IsFuzzing()) 136 SvtViewOptions::AcquireOptions(); 137 138 SAL_INFO( "sfx.appl", "{ initialize DDE" ); 139 140 bool bOk = InitializeDde(); 141 142 #ifdef DBG_UTIL 143 if( !bOk ) 144 { 145 OStringBuffer aStr("No DDE-Service possible. Error: "); 146 if( GetDdeService() ) 147 aStr.append(static_cast<sal_Int32>(GetDdeService()->GetError())); 148 else 149 aStr.append('?'); 150 SAL_WARN( "sfx.appl", aStr.getStr() ); 151 } 152 #else 153 (void)bOk; 154 #endif 155 156 #if HAVE_FEATURE_DESKTOP 157 pSfxHelp = new SfxHelp; 158 #endif 159 160 #if HAVE_FEATURE_SCRIPTING 161 StarBASIC::SetGlobalErrorHdl( LINK( this, SfxApplication, GlobalBasicErrorHdl_Impl ) ); 162 #endif 163 164 SAL_INFO( "sfx.appl", "} initialize DDE" ); 165 } 166 167 SfxApplication::~SfxApplication() 168 { 169 SAL_WARN_IF(GetObjectShells_Impl().size() != 0, "sfx.appl", "Memory leak: some object shells were not removed!"); 170 171 Broadcast( SfxHint(SfxHintId::Dying) ); 172 173 for (auto &module : pImpl->aModules) // Clear modules 174 module.reset(); 175 176 #if HAVE_FEATURE_DESKTOP 177 delete pSfxHelp; 178 Application::SetHelp(); 179 #endif 180 181 // delete global options 182 if (!utl::ConfigManager::IsFuzzing()) 183 SvtViewOptions::ReleaseOptions(); 184 185 if ( !pImpl->bDowning ) 186 Deinitialize(); 187 188 g_pSfxApplication = nullptr; 189 } 190 191 192 const OUString& SfxApplication::GetLastDir_Impl() const 193 194 /* [Description] 195 196 Internal method by which the last set directory with the method 197 <SfxApplication::SetLastDir_Impl()> in SFX is returned. 198 199 This is usually the most recently addressed by the 200 SfxFileDialog directory. 201 202 [Cross-reference] 203 <SfxApplication::SetLastDir_Impl()> 204 */ 205 206 { 207 return pImpl->aLastDir; 208 } 209 210 void SfxApplication::SetLastDir_Impl 211 ( 212 const OUString& rNewDir /* Complete directory path as a string */ 213 ) 214 215 /* [Description] 216 217 Internal Method, by which a directory path is set that was last addressed 218 (eg by the SfxFileDialog). 219 220 [Cross-reference] 221 <SfxApplication::GetLastDir_Impl()> 222 */ 223 224 { 225 pImpl->aLastDir = rNewDir; 226 } 227 228 229 void SfxApplication::ResetLastDir() 230 { 231 pImpl->aLastDir.clear(); 232 } 233 234 235 SfxDispatcher* SfxApplication::GetDispatcher_Impl() 236 { 237 return pImpl->pViewFrame? pImpl->pViewFrame->GetDispatcher(): pImpl->pAppDispat; 238 } 239 240 241 void SfxApplication::SetViewFrame_Impl( SfxViewFrame *pFrame ) 242 { 243 if ( pFrame != pImpl->pViewFrame ) 244 { 245 SfxViewFrame *pOldFrame = pImpl->pViewFrame; 246 247 // DocWinActivate : both frames belong to the same TopWindow 248 // TopWinActivate : both frames belong to different TopWindows 249 250 bool bTaskActivate = pOldFrame != pFrame; 251 252 if ( pOldFrame ) 253 { 254 if ( bTaskActivate ) 255 NotifyEvent( SfxViewEventHint( SfxEventHintId::DeactivateDoc, GlobalEventConfig::GetEventName(GlobalEventId::DEACTIVATEDOC), pOldFrame->GetObjectShell(), pOldFrame->GetFrame().GetController() ) ); 256 pOldFrame->DoDeactivate( bTaskActivate, pFrame ); 257 258 if( pOldFrame->GetProgress() ) 259 pOldFrame->GetProgress()->Suspend(); 260 } 261 262 pImpl->pViewFrame = pFrame; 263 264 if( pFrame ) 265 { 266 pFrame->DoActivate( bTaskActivate ); 267 if ( bTaskActivate && pFrame->GetObjectShell() ) 268 { 269 pFrame->GetObjectShell()->PostActivateEvent_Impl( pFrame ); 270 NotifyEvent(SfxViewEventHint(SfxEventHintId::ActivateDoc, GlobalEventConfig::GetEventName(GlobalEventId::ACTIVATEDOC), pFrame->GetObjectShell(), pFrame->GetFrame().GetController() ) ); 271 } 272 273 SfxProgress *pProgress = pFrame->GetProgress(); 274 if ( pProgress ) 275 { 276 if( pProgress->IsSuspended() ) 277 pProgress->Resume(); 278 else 279 pProgress->SetState( pProgress->GetState() ); 280 } 281 282 if ( pImpl->pViewFrame->GetViewShell() ) 283 { 284 SfxDispatcher* pDisp = pImpl->pViewFrame->GetDispatcher(); 285 pDisp->Flush(); 286 pDisp->Update_Impl(true); 287 } 288 } 289 } 290 291 // even if the frame actually didn't change, ensure its document is forwarded 292 // to SfxObjectShell::SetCurrentComponent. 293 // Otherwise, the CurrentComponent might not be correct, in case it has meanwhile 294 // been reset to some other document, by some non-SFX component. #i49133# 295 if ( pFrame && pFrame->GetViewShell() ) 296 pFrame->GetViewShell()->SetCurrentDocument(); 297 } 298 299 void SfxApplication::SetProgress_Impl 300 ( 301 SfxProgress *pProgress 302 ) 303 { 304 DBG_ASSERT( ( !pImpl->pProgress && pProgress ) || 305 ( pImpl->pProgress && !pProgress ), 306 "Progress activation/deactivation mismatch" ); 307 308 if ( pImpl->pProgress && pProgress ) 309 { 310 pImpl->pProgress->Suspend(); 311 delete pImpl->pProgress; 312 } 313 314 pImpl->pProgress = pProgress; 315 } 316 317 318 sal_uInt16 SfxApplication::GetFreeIndex() 319 { 320 return pImpl->aIndexBitSet.GetFreeIndex()+1; 321 } 322 323 324 void SfxApplication::ReleaseIndex(sal_uInt16 i) 325 { 326 pImpl->aIndexBitSet.ReleaseIndex(i-1); 327 } 328 329 330 vcl::Window* SfxApplication::GetTopWindow() const 331 { 332 SfxWorkWindow* pWork = GetWorkWindow_Impl( SfxViewFrame::Current() ); 333 return pWork ? pWork->GetWindow() : nullptr; 334 } 335 336 SfxTbxCtrlFactArr_Impl& SfxApplication::GetTbxCtrlFactories_Impl() const 337 { 338 return *pImpl->pTbxCtrlFac; 339 } 340 341 SfxStbCtrlFactArr_Impl& SfxApplication::GetStbCtrlFactories_Impl() const 342 { 343 return *pImpl->pStbCtrlFac; 344 } 345 346 SfxViewFrameArr_Impl& SfxApplication::GetViewFrames_Impl() const 347 { 348 return *pImpl->pViewFrames; 349 } 350 351 SfxViewShellArr_Impl& SfxApplication::GetViewShells_Impl() const 352 { 353 return *pImpl->pViewShells; 354 } 355 356 SfxObjectShellArr_Impl& SfxApplication::GetObjectShells_Impl() const 357 { 358 return *pImpl->pObjShells; 359 } 360 361 void SfxApplication::Invalidate( sal_uInt16 nId ) 362 { 363 for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame ) ) 364 Invalidate_Impl( pFrame->GetBindings(), nId ); 365 } 366 367 #if HAVE_FEATURE_SCRIPTING 368 369 #ifndef DISABLE_DYNLOADING 370 371 typedef long (*basicide_handle_basic_error)(void const *); 372 typedef void (*basicide_macro_organizer)(void *, sal_Int16); 373 374 extern "C" { static void thisModule() {} } 375 376 #else 377 378 extern "C" long basicide_handle_basic_error(void const*); 379 extern "C" void basicide_macro_organizer(void*, sal_Int16); 380 381 #endif 382 383 #endif 384 385 IMPL_STATIC_LINK( SfxApplication, GlobalBasicErrorHdl_Impl, StarBASIC*, pStarBasic, bool ) 386 { 387 #if !HAVE_FEATURE_SCRIPTING 388 (void) pStarBasic; 389 return false; 390 #else 391 392 #ifndef DISABLE_DYNLOADING 393 // load basctl module 394 osl::Module aMod; 395 aMod.loadRelative(&thisModule, SVLIBRARY("basctl")); 396 397 // get symbol 398 basicide_handle_basic_error pSymbol = reinterpret_cast<basicide_handle_basic_error>(aMod.getFunctionSymbol("basicide_handle_basic_error")); 399 400 aMod.release(); 401 402 // call basicide_handle_basic_error in basctl 403 bool bRet = pSymbol && pSymbol( pStarBasic ); 404 405 #else 406 407 bool bRet = basicide_handle_basic_error( pStarBasic ); 408 409 #endif 410 411 return bRet; 412 413 #endif 414 } 415 416 bool SfxApplication::IsXScriptURL( const OUString& rScriptURL ) 417 { 418 bool result = false; 419 420 #if !HAVE_FEATURE_SCRIPTING 421 (void) rScriptURL; 422 #else 423 css::uno::Reference< css::uno::XComponentContext > xContext = 424 ::comphelper::getProcessComponentContext(); 425 426 css::uno::Reference< css::uri::XUriReferenceFactory > 427 xFactory = css::uri::UriReferenceFactory::create( xContext ); 428 429 try 430 { 431 css::uno::Reference< css::uri::XVndSunStarScriptUrl > 432 xUrl( xFactory->parse( rScriptURL ), css::uno::UNO_QUERY ); 433 434 if ( xUrl.is() ) 435 { 436 result = true; 437 } 438 } 439 catch (const css::uno::RuntimeException&) 440 { 441 // ignore, will just return FALSE 442 } 443 #endif 444 return result; 445 } 446 447 OUString 448 SfxApplication::ChooseScript(weld::Window *pParent) 449 { 450 OUString aScriptURL; 451 452 #if HAVE_FEATURE_SCRIPTING 453 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); 454 SAL_INFO( "sfx.appl", "create selector dialog"); 455 456 const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); 457 const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; 458 uno::Reference< frame::XFrame > xFrame( pFrame ? pFrame->GetFrameInterface() : uno::Reference< frame::XFrame >() ); 459 460 ScopedVclPtr<AbstractScriptSelectorDialog> pDlg(pFact->CreateScriptSelectorDialog(pParent, xFrame)); 461 462 SAL_INFO( "sfx.appl", "done, now exec it"); 463 464 sal_uInt16 nRet = pDlg->Execute(); 465 466 SAL_INFO( "sfx.appl", "has returned"); 467 468 if ( nRet == RET_OK ) 469 { 470 aScriptURL = pDlg->GetScriptURL(); 471 } 472 #else 473 (void) pParent; 474 #endif 475 return aScriptURL; 476 } 477 478 void SfxApplication::MacroOrganizer(weld::Window* pParent, sal_Int16 nTabId) 479 { 480 #if !HAVE_FEATURE_SCRIPTING 481 (void) pParent; 482 (void) nTabId; 483 #else 484 485 #ifndef DISABLE_DYNLOADING 486 // load basctl module 487 osl::Module aMod; 488 aMod.loadRelative(&thisModule, SVLIBRARY("basctl")); 489 490 // get symbol 491 basicide_macro_organizer pSymbol = reinterpret_cast<basicide_macro_organizer>(aMod.getFunctionSymbol("basicide_macro_organizer")); 492 493 aMod.release(); 494 495 SAL_WARN_IF(!pSymbol, "sfx.appl", "SfxApplication::MacroOrganizer, no symbol!"); 496 if (!pSymbol) 497 return; 498 499 // call basicide_macro_organizer in basctl 500 pSymbol(pParent, nTabId); 501 502 #else 503 504 basicide_macro_organizer(pParent, nTabId); 505 506 #endif 507 508 #endif 509 } 510 511 ErrCode SfxApplication::CallBasic( const OUString& rCode, BasicManager* pMgr, SbxArray* pArgs, SbxValue* pRet ) 512 { 513 #if !HAVE_FEATURE_SCRIPTING 514 (void) rCode; 515 (void) pMgr; 516 (void) pArgs; 517 (void) pRet; 518 return ERRCODE_BASIC_CANNOT_LOAD; 519 #else 520 (void) ERRCODE_BASIC_CANNOT_LOAD; // So that the !HAVE_FEATURE_SCRIPTING case isn't broken again by IWYU 521 return pMgr->ExecuteMacro( rCode, pArgs, pRet); 522 #endif 523 } 524 525 sfx2::sidebar::Theme & SfxApplication::GetSidebarTheme() 526 { 527 if (!pImpl->m_pSidebarTheme.is()) 528 { 529 pImpl->m_pSidebarTheme.set(new sfx2::sidebar::Theme); 530 pImpl->m_pSidebarTheme->InitializeTheme(); 531 } 532 return *pImpl->m_pSidebarTheme; 533 } 534 535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 536
