xref: /core/sfx2/source/appl/appserv.cxx (revision 94d6fa11)
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 
22 #include <com/sun/star/document/XEmbeddedScripts.hpp>
23 #include <com/sun/star/drawing/ModuleDispatcher.hpp>
24 #include <com/sun/star/embed/XStorage.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/frame/Desktop.hpp>
27 #include <com/sun/star/frame/DispatchResultEvent.hpp>
28 #include <com/sun/star/frame/DispatchResultState.hpp>
29 #include <com/sun/star/frame/DispatchHelper.hpp>
30 #include <com/sun/star/frame/UnknownModuleException.hpp>
31 #include <com/sun/star/frame/XLayoutManager.hpp>
32 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
33 #include <com/sun/star/sdbc/DriverManager.hpp>
34 #include <com/sun/star/system/SystemShellExecute.hpp>
35 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
36 #include <com/sun/star/system/SystemShellExecuteException.hpp>
37 #include <com/sun/star/task/XJobExecutor.hpp>
38 #include <com/sun/star/text/ModuleDispatcher.hpp>
39 #include <com/sun/star/task/OfficeRestartManager.hpp>
40 #include <com/sun/star/task/XInteractionHandler.hpp>
41 #include <com/sun/star/ui/dialogs/AddressBookSourcePilot.hpp>
42 #include <com/sun/star/ui/UIElementType.hpp>
43 #include <com/sun/star/ui/XUIElement.hpp>
44 #include <com/sun/star/uno/Reference.hxx>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <com/sun/star/util/CloseVetoException.hpp>
47 #include <org/freedesktop/PackageKit/SyncDbusSessionHelper.hpp>
48 
49 #include <comphelper/namedvaluecollection.hxx>
50 #include <comphelper/processfactory.hxx>
51 #include <comphelper/propertysequence.hxx>
52 #include <comphelper/sequence.hxx>
53 
54 #include <svtools/addresstemplate.hxx>
55 #include <svtools/miscopt.hxx>
56 #include <svtools/restartdialog.hxx>
57 #include <svl/visitem.hxx>
58 #include <unotools/intlwrapper.hxx>
59 
60 #include <unotools/configmgr.hxx>
61 #include <tools/svlibrary.h>
62 #include <tools/diagnose_ex.h>
63 #include <vcl/sysdata.hxx>
64 #include <vcl/weld.hxx>
65 #include <svl/intitem.hxx>
66 #include <svl/eitem.hxx>
67 #include <svl/stritem.hxx>
68 #include <basic/sbstar.hxx>
69 #include <basic/basmgr.hxx>
70 #include <basic/basrdll.hxx>
71 #include <basic/sberrors.hxx>
72 #include <svtools/sfxecode.hxx>
73 #include <svtools/ehdl.hxx>
74 #include <vcl/help.hxx>
75 #include <vcl/stdtext.hxx>
76 #include <rtl/ustrbuf.hxx>
77 #include <sal/log.hxx>
78 #include <osl/file.hxx>
79 #include <osl/module.hxx>
80 #include <vcl/EnumContext.hxx>
81 
82 #include <unotools/pathoptions.hxx>
83 #include <unotools/moduleoptions.hxx>
84 #include <unotools/viewoptions.hxx>
85 #include <svtools/helpopt.hxx>
86 #include <toolkit/helper/vclunohelper.hxx>
87 #include <unotools/bootstrap.hxx>
88 #include <rtl/bootstrap.hxx>
89 #include <cppuhelper/exc_hlp.hxx>
90 
91 #include <com/sun/star/frame/ModuleManager.hpp>
92 #include <com/sun/star/beans/XPropertySet.hpp>
93 
94 #include <sfx2/app.hxx>
95 #include <sfx2/request.hxx>
96 #include <sfx2/dispatch.hxx>
97 #include <sfx2/bindings.hxx>
98 #include <sfx2/msg.hxx>
99 #include <sfx2/objface.hxx>
100 #include <sfx2/objitem.hxx>
101 #include <sfx2/objsh.hxx>
102 #include <sfx2/hintpost.hxx>
103 #include <sfx2/viewsh.hxx>
104 #include <sfx2/docfac.hxx>
105 #include <sfx2/docfile.hxx>
106 #include <sfx2/docfilt.hxx>
107 #include <sfx2/new.hxx>
108 #include <sfxtypes.hxx>
109 #include <sfx2/tabdlg.hxx>
110 #include <arrdecl.hxx>
111 #include <sfx2/strings.hrc>
112 #include <sfx2/passwd.hxx>
113 #include <sfx2/sfxresid.hxx>
114 #include <sfx2/childwin.hxx>
115 #include <appdata.hxx>
116 #include <sfx2/minfitem.hxx>
117 #include <sfx2/event.hxx>
118 #include <sfx2/module.hxx>
119 #include <sfx2/viewfrm.hxx>
120 #include <sfxpicklist.hxx>
121 #include <sfx2/sfxdlg.hxx>
122 #include <sfx2/sfxsids.hrc>
123 #include <sorgitm.hxx>
124 #include <sfx2/sfxhelp.hxx>
125 #include <sfx2/zoomitem.hxx>
126 #include <sfx2/templatedlg.hxx>
127 #include <sfx2/sidebar/Sidebar.hxx>
128 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
129 #include <sfx2/sidebar/SidebarController.hxx>
130 #include <sfx2/safemode.hxx>
131 #include <sfx2/sfxuno.hxx>
132 
133 #include <comphelper/types.hxx>
134 #include <officecfg/Office/Common.hxx>
135 #include <officecfg/Office/UI/ToolbarMode.hxx>
136 #include <unotools/confignode.hxx>
137 #include <officecfg/Setup.hxx>
138 #include <memory>
139 
140 #include <openuriexternally.hxx>
141 
142 using namespace ::com::sun::star;
143 using namespace ::com::sun::star::beans;
144 using namespace ::com::sun::star::uno;
145 using namespace ::com::sun::star::frame;
146 using namespace ::com::sun::star::container;
147 using namespace ::com::sun::star::util;
148 using namespace ::com::sun::star::script;
149 using namespace ::com::sun::star::system;
150 using namespace ::com::sun::star::lang;
151 using namespace ::com::sun::star::document;
152 using namespace ::com::sun::star::ui;
153 
154 namespace
155 {
156     OUString lcl_getAppName( vcl::EnumContext::Application eApp )
157     {
158         switch ( eApp )
159         {
160             case vcl::EnumContext::Application::Writer:
161                 return "Writer";
162                 break;
163             case vcl::EnumContext::Application::Calc:
164                 return "Calc";
165                 break;
166             case vcl::EnumContext::Application::Impress:
167                 return "Impress";
168                 break;
169             case vcl::EnumContext::Application::Draw:
170                 return "Draw";
171                 break;
172             case vcl::EnumContext::Application::Formula:
173                 return "Formula";
174                 break;
175             case vcl::EnumContext::Application::Base:
176                 return "Base";
177                 break;
178             default:
179                 return OUString();
180                 break;
181         }
182     }
183 
184     // lp#527938, debian#602953, fdo#33266, i#105408
185     bool lcl_isBaseAvailable()
186     {
187         try
188         {
189             // if we get css::sdbc::DriverManager, libsdbc2 is there
190             // and the bibliography is assumed to work
191             return css::sdbc::DriverManager::create(comphelper::getProcessComponentContext()).is();
192         }
193         catch (const Exception &)
194         {
195             TOOLS_INFO_EXCEPTION("sfx.appl", "assuming Base to be missing");
196             return false;
197         }
198     }
199     void lcl_tryLoadBibliography()
200     {
201         // lp#527938, debian#602953, fdo#33266, i#105408
202         // make sure we actually can instantiate services from base first
203         if(!lcl_isBaseAvailable())
204         {
205             try
206             {
207                 using namespace org::freedesktop::PackageKit;
208                 using namespace svtools;
209                 Reference< XSyncDbusSessionHelper > xSyncDbusSessionHelper(SyncDbusSessionHelper::create(comphelper::getProcessComponentContext()));
210                 Sequence< OUString > vPackages { "libreoffice-base" };
211                 xSyncDbusSessionHelper->InstallPackageNames(vPackages, OUString());
212                 // Ill be back (hopefully)!
213                 SolarMutexGuard aGuard;
214                 executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, RESTART_REASON_BIBLIOGRAPHY_INSTALL);
215             }
216             catch (const Exception &)
217             {
218                 TOOLS_INFO_EXCEPTION("sfx.appl", "trying to install LibreOffice Base");
219             }
220             return;
221         }
222 
223         try // fdo#48775
224         {
225             SfxStringItem aURL(SID_FILE_NAME, ".component:Bibliography/View1");
226             SfxStringItem aRef(SID_REFERER, "private:user");
227             SfxStringItem aTarget(SID_TARGETNAME, "_blank");
228             SfxViewFrame::Current()->GetDispatcher()->ExecuteList(SID_OPENDOC,
229                 SfxCallMode::ASYNCHRON, { &aURL, &aRef, &aTarget });
230         }
231         catch (const Exception &)
232         {
233             TOOLS_INFO_EXCEPTION( "sfx.appl", "trying to load bibliography database");
234         }
235     }
236 }
237 /// Find the correct location of the document (CREDITS.fodt, etc.), and return
238 /// it in rURL if found.
239 static bool checkURL( const char *pName, const char *pExt, OUString &rURL )
240 {
241     using namespace osl;
242     DirectoryItem aDirItem;
243 
244 #ifdef MACOSX
245     rURL = "$BRAND_BASE_DIR/Resources/" + OUString::createFromAscii( pName ) +
246            OUString::createFromAscii( pExt );
247 #else
248     rURL = "$BRAND_BASE_DIR/" + OUString::createFromAscii( pName ) +
249            OUString::createFromAscii( pExt );
250 #endif
251     rtl::Bootstrap::expandMacros( rURL );
252 
253     if (!rURL.isEmpty())
254         return DirectoryItem::get( rURL, aDirItem ) == DirectoryItem::E_None;
255     else
256         return false;
257 }
258 
259 /// Displays CREDITS or LICENSE in any of the available version
260 static void showDocument( const char* pBaseName )
261 {
262     try {
263         Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
264         auto args(::comphelper::InitPropertySequence({
265             {"ViewOnly",    makeAny(true)},
266             {"ReadOnly",    makeAny(true)}
267         }));
268 
269         OUString aURL;
270         if ( checkURL ( pBaseName, ".fodt", aURL ) ||
271              checkURL ( pBaseName, ".html", aURL ) ||
272              checkURL ( pBaseName, "", aURL ) ) {
273             xDesktop->loadComponentFromURL( aURL, "_blank", 0, args );
274         }
275     } catch (const css::uno::Exception &) {
276     }
277 }
278 
279 namespace
280 {
281     Reference<XFrame> GetRequestFrame(const SfxRequest& rReq)
282     {
283         const SfxItemSet* pArgs = rReq.GetInternalArgs_Impl();
284         const SfxPoolItem* pItem = nullptr;
285         Reference <XFrame> xFrame;
286         if (pArgs && pArgs->GetItemState(SID_FILLFRAME, false, &pItem) == SfxItemState::SET)
287         {
288             OSL_ENSURE( dynamic_cast< const SfxUnoFrameItem *>( pItem ) !=  nullptr, "SfxApplication::OfaExec_Impl: XFrames are to be transported via SfxUnoFrameItem by now!" );
289             xFrame = static_cast< const SfxUnoFrameItem*>( pItem )->GetFrame();
290         }
291         return xFrame;
292     }
293 
294     vcl::Window* getFrameWindow(const Reference<XFrame>& rFrame)
295     {
296         if (rFrame.is())
297         {
298             try
299             {
300                 Reference< awt::XWindow > xContainerWindow(rFrame->getContainerWindow(), UNO_SET_THROW);
301                 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xContainerWindow);
302                 return pWindow;
303             }
304             catch (const Exception&)
305             {
306                 DBG_UNHANDLED_EXCEPTION("sfx.appl");
307             }
308         }
309 
310         SAL_WARN( "sfx.appl", "no parent for dialogs" );
311         return nullptr;
312     }
313 
314     class LicenseDialog : public weld::GenericDialogController
315     {
316     public:
317         LicenseDialog(weld::Window* pParent)
318             : GenericDialogController(pParent, "sfx/ui/licensedialog.ui",  "LicenseDialog")
319         {
320         }
321 
322         virtual short run() override
323         {
324             short nRet = GenericDialogController::run();
325             if (nRet == RET_OK)
326                 showDocument("LICENSE");
327             return nRet;
328         }
329     };
330 
331     class SafeModeQueryDialog : public weld::MessageDialogController
332     {
333     public:
334         SafeModeQueryDialog(weld::Window* pParent)
335             : MessageDialogController(pParent, "sfx/ui/safemodequerydialog.ui", "SafeModeQueryDialog")
336         {
337         }
338 
339         virtual short run() override
340         {
341             short nRet = MessageDialogController::run();
342             if (nRet == RET_OK)
343             {
344                 sfx2::SafeMode::putFlag();
345                 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
346                 css::task::OfficeRestartManager::get(xContext)->requestRestart(
347                     css::uno::Reference< css::task::XInteractionHandler >());
348             }
349             return nRet;
350         }
351     };
352 }
353 
354 vcl::Window* SfxRequest::GetFrameWindow() const
355 {
356     return getFrameWindow(GetRequestFrame(*this));
357 }
358 
359 weld::Window* SfxRequest::GetFrameWeld() const
360 {
361     const SfxItemSet* pIntArgs = GetInternalArgs_Impl();
362     const SfxPoolItem* pItem = nullptr;
363     if (pIntArgs && pIntArgs->GetItemState(SID_DIALOG_PARENT, false, &pItem) == SfxItemState::SET)
364     {
365         assert(dynamic_cast<const SfxUnoAnyItem*>(pItem));
366         auto aAny = static_cast<const SfxUnoAnyItem*>(pItem)->GetValue();
367         Reference<awt::XWindow> xWindow;
368         aAny >>= xWindow;
369         return Application::GetFrameWeld(xWindow);
370     }
371 
372     vcl::Window* pWin = GetFrameWindow();
373     return pWin ? pWin->GetFrameWeld() : nullptr;
374 }
375 
376 void SfxApplication::MiscExec_Impl( SfxRequest& rReq )
377 {
378     bool bDone = false;
379     switch ( rReq.GetSlot() )
380     {
381         case SID_SETOPTIONS:
382         {
383             if( rReq.GetArgs() )
384                 SetOptions_Impl( *rReq.GetArgs() );
385             break;
386         }
387 
388         case SID_QUITAPP:
389         case SID_LOGOUT:
390         {
391             // protect against reentrant calls
392             if ( pImpl->bInQuit )
393                 return;
394 
395             if ( rReq.GetSlot() == SID_LOGOUT )
396             {
397                 for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
398                     pObjSh; pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
399                 {
400                     if ( !pObjSh->IsModified() )
401                         continue;
402 
403                     SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pObjSh );
404                     if ( !pFrame || !pFrame->GetWindow().IsReallyVisible() )
405                         continue;
406 
407                     if (pObjSh->PrepareClose())
408                         pObjSh->SetModified( false );
409                     else
410                         return;
411                 }
412 
413                 SfxStringItem aNameItem( SID_FILE_NAME, "vnd.sun.star.cmd:logout" );
414                 SfxStringItem aReferer( SID_REFERER, "private/user" );
415                 pImpl->pAppDispat->ExecuteList(SID_OPENDOC,
416                         SfxCallMode::SLOT, { &aNameItem, &aReferer });
417                 return;
418             }
419 
420             // try from nested requests again after 100ms
421             if( Application::GetDispatchLevel() > 1 )
422             {
423                 /* Don't save the request for closing the application and try it later
424                    again. This is an UI bound functionality ... and the user will  try it again
425                    if the dialog is closed. But we should not close the application automatically
426                    if this dialog is closed by the user ...
427                    So we ignore this request now and wait for a new user decision.
428                 */
429                 SAL_INFO("sfx.appl", "QueryExit => sal_False, DispatchLevel == " << Application::GetDispatchLevel() );
430                 return;
431             }
432 
433             // block reentrant calls
434             pImpl->bInQuit = true;
435             Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
436 
437             rReq.ForgetAllArgs();
438 
439             // if terminate() failed, pImpl->bInQuit will now be sal_False, allowing further calls of SID_QUITAPP
440             bool bTerminated = xDesktop->terminate();
441             if (!bTerminated)
442                 // if terminate() was successful, SfxApplication is now dead!
443                 pImpl->bInQuit = false;
444 
445             // Set return value, terminate if possible
446             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bTerminated ) );
447             return;
448         }
449 
450         case SID_CONFIG:
451         case SID_TOOLBOXOPTIONS:
452         case SID_CONFIGSTATUSBAR:
453         case SID_CONFIGMENU:
454         case SID_CONFIGACCEL:
455         case SID_CONFIGEVENT:
456         {
457             SfxAbstractDialogFactory* pFact =
458                 SfxAbstractDialogFactory::Create();
459 
460             const SfxStringItem* pStringItem = rReq.GetArg<SfxStringItem>(SID_CONFIG);
461 
462             SfxItemSet aSet(
463                 GetPool(), svl::Items<SID_CONFIG, SID_CONFIG>{} );
464 
465             if ( pStringItem )
466             {
467                 aSet.Put( SfxStringItem(
468                     SID_CONFIG, pStringItem->GetValue() ) );
469             }
470 
471             Reference <XFrame> xFrame(GetRequestFrame(rReq));
472             ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateCustomizeTabDialog(rReq.GetFrameWeld(),
473                 &aSet, xFrame ));
474 
475             const short nRet = pDlg->Execute();
476 
477             if ( nRet )
478                 bDone = true;
479             break;
480         }
481 
482         case SID_CLOSEDOCS:
483         {
484 
485             Reference < XDesktop2 > xDesktop  = Desktop::create( ::comphelper::getProcessComponentContext() );
486             Reference< XIndexAccess > xTasks = xDesktop->getFrames();
487             if ( !xTasks.is() )
488                 break;
489 
490             sal_Int32 n=0;
491             do
492             {
493                 if ( xTasks->getCount() <= n )
494                     break;
495 
496                 Any aAny = xTasks->getByIndex(n);
497                 Reference < XCloseable > xTask;
498                 aAny >>= xTask;
499                 try
500                 {
501                     xTask->close(true);
502                     n++;
503                 }
504                 catch( CloseVetoException& )
505                 {
506                 }
507             }
508             while( true );
509 
510             bool bOk = ( n == 0);
511             rReq.SetReturnValue( SfxBoolItem( 0, bOk ) );
512             bDone = true;
513             break;
514         }
515 
516         case SID_SAVEDOCS:
517         {
518             bool bOK = true;
519             for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
520                   pObjSh;
521                   pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
522             {
523                 SfxRequest aReq( SID_SAVEDOC, SfxCallMode::SLOT, pObjSh->GetPool() );
524                 if ( pObjSh->IsModified() )
525                 {
526                     pObjSh->ExecuteSlot( aReq );
527                     const SfxBoolItem *pItem = dynamic_cast<const SfxBoolItem*>( aReq.GetReturnValue()  );
528                     if ( !pItem || !pItem->GetValue() )
529                         bOK = false;
530                 }
531             }
532 
533             rReq.SetReturnValue( SfxBoolItem( 0, bOK ) );
534             rReq.Done();
535             break;
536         }
537 
538         case SID_SEND_FEEDBACK:
539         {
540             OUString module = SfxHelp::GetCurrentModuleIdentifier();
541             OUString sURL(officecfg::Office::Common::Menus::SendFeedbackURL::get() + //officecfg/registry/data/org/openoffice/Office/Common.xcu => https://hub.libreoffice.org/send-feedback/
542                 "?LOversion=" + utl::ConfigManager::getAboutBoxProductVersion() +
543                 "&LOlocale=" + utl::ConfigManager::getUILocale() +
544                 "&LOmodule=" + module.copy(module.lastIndexOf('.') + 1 )  );
545             sfx2::openUriExternally(sURL, false);
546             break;
547         }
548 
549         case SID_Q_AND_A:
550         {
551             // Askbot has URL's normalized to languages, not locales
552             // Get language from locale: ll or lll or ll-CC or lll-CC
553 
554             OUString sURL(officecfg::Office::Common::Menus::QA_URL::get() + //https://hub.libreoffice.org/forum/
555                 "?LOlocale=" + utl::ConfigManager::getUILocale());
556             sfx2::openUriExternally(sURL, false);
557             break;
558         }
559         case SID_DOCUMENTATION:
560         {
561             // Open documentation page based on locales
562             OUString sURL(officecfg::Office::Common::Menus::DocumentationURL::get() + //https://hub.libreoffice.org/documentation/
563                 "?LOlocale=" + utl::ConfigManager::getUILocale());
564             sfx2::openUriExternally(sURL, false);
565             break;
566         }
567         case SID_GETINVOLVED:
568         {
569             // Open get involved/join us page based on locales
570             OUString sURL(officecfg::Office::Common::Menus::GetInvolvedURL::get() + //https://hub.libreoffice.org/joinus/
571                 "?LOlocale=" + utl::ConfigManager::getUILocale());
572             sfx2::openUriExternally(sURL, false);
573             break;
574         }
575         case SID_DONATION:
576         {
577             // Open donation page based on language + script (BCP47) with language as fall back.
578             OUString aLang = LanguageTag(utl::ConfigManager::getUILocale()).getLanguage();
579             OUString aBcp47 = LanguageTag(utl::ConfigManager::getUILocale()).getBcp47();
580             OUString sURL(officecfg::Office::Common::Menus::DonationURL::get() + //https://hub.libreoffice.org/donation/
581                 "?BCP47=" + aBcp47 + "&LOlang=" + aLang );
582             sfx2::openUriExternally(sURL, false);
583             break;
584         }
585         case SID_WHATSNEW:
586         {
587             // Open release notes depending on version and locale
588             OUString sURL(officecfg::Office::Common::Menus::ReleaseNotesURL::get() + //https://hub.libreoffice.org/ReleaseNotes/
589                 "?LOvers=" + utl::ConfigManager::getProductVersion() +
590                 "&LOlocale=" + LanguageTag(utl::ConfigManager::getUILocale()).getLanguage() );
591             sfx2::openUriExternally(sURL, false);
592             break;
593         }
594         case SID_SHOW_LICENSE:
595         {
596             LicenseDialog aDialog(rReq.GetFrameWeld());
597             aDialog.run();
598             break;
599         }
600 
601         case SID_SHOW_CREDITS:
602         {
603             showDocument( "CREDITS" );
604             break;
605         }
606 
607         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
608         case SID_HELPINDEX:
609         {
610             Help* pHelp = Application::GetHelp();
611             if ( pHelp )
612             {
613                 pHelp->Start(".uno:HelpIndex", Application::GetDefDialogParent()); // show start page
614                 bDone = true;
615             }
616             break;
617         }
618 
619         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
620         case SID_HELPTIPS:
621         {
622             // Evaluate Parameter
623             const SfxBoolItem* pOnItem = rReq.GetArg<SfxBoolItem>(SID_HELPTIPS);
624             bool bOn = pOnItem
625                             ? pOnItem->GetValue()
626                             : !Help::IsQuickHelpEnabled();
627 
628             if ( bOn )
629                 Help::EnableQuickHelp();
630             else
631                 Help::DisableQuickHelp();
632             SvtHelpOptions().SetHelpTips( bOn );
633             Invalidate(SID_HELPTIPS);
634             bDone = true;
635 
636             // Record if possible
637             if ( !rReq.IsAPI() )
638                 rReq.AppendItem( SfxBoolItem( SID_HELPTIPS, bOn) );
639             break;
640         }
641         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
642         case SID_EXTENDEDHELP:
643         {
644             Help::StartExtHelp();
645             break;
646         }
647         case SID_HELPBALLOONS:
648         {
649             // Evaluate Parameter
650             const SfxBoolItem* pOnItem = rReq.GetArg<SfxBoolItem>(SID_HELPBALLOONS);
651             bool bOn = pOnItem
652                             ? pOnItem->GetValue()
653                             : !Help::IsBalloonHelpEnabled();
654 
655             if ( bOn )
656                 Help::EnableBalloonHelp();
657             else
658                 Help::DisableBalloonHelp();
659             SvtHelpOptions().SetExtendedHelp( bOn );
660             Invalidate(SID_HELPBALLOONS);
661             bDone = true;
662 
663             // Record if possible
664             if ( !rReq.IsAPI() )
665                 rReq.AppendItem( SfxBoolItem( SID_HELPBALLOONS, bOn) );
666             break;
667         }
668 
669         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
670         case SID_ABOUT:
671         {
672             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
673             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateAboutDialog(rReq.GetFrameWeld()));
674             pDlg->Execute();
675             bDone = true;
676             break;
677         }
678 
679         case SID_TEMPLATE_MANAGER:
680         {
681             SfxTemplateManagerDlg aDialog(rReq.GetFrameWeld());
682             aDialog.run();
683             bDone = true;
684             break;
685         }
686 
687         case SID_TEMPLATE_ADDRESSBOKSOURCE:
688         {
689             svt::AddressBookSourceDialog aDialog(rReq.GetFrameWeld(), ::comphelper::getProcessComponentContext());
690             aDialog.run();
691             bDone = true;
692             break;
693         }
694 
695 #if HAVE_FEATURE_SCRIPTING
696         case SID_BASICSTOP:
697             StarBASIC::Stop();
698             break;
699 
700         case SID_BASICBREAK :
701             BasicDLL::BasicBreak();
702             break;
703 #endif
704 
705         case SID_ZOOM_50_PERCENT:
706         case SID_ZOOM_75_PERCENT:
707         case SID_ZOOM_100_PERCENT:
708         case SID_ZOOM_150_PERCENT:
709         case SID_ZOOM_200_PERCENT:
710         case SID_ZOOM_OPTIMAL:
711         case SID_ZOOM_ENTIRE_PAGE:
712         case SID_ZOOM_PAGE_WIDTH:
713         {
714             SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
715             if (!pCurrentShell)
716                 return;
717 
718             // make sure aZoom is initialized with a proper value if SetType
719             // doesn't work
720             SvxZoomItem aZoom( SvxZoomType::PERCENT, 100 );
721 
722             switch (rReq.GetSlot())
723             {
724                 case SID_ZOOM_50_PERCENT:
725                     aZoom.SetValue(50);
726                     break;
727                 case SID_ZOOM_75_PERCENT:
728                     aZoom.SetValue(75);
729                     break;
730                 case SID_ZOOM_100_PERCENT:
731                     aZoom.SetValue(100);
732                     break;
733                 case SID_ZOOM_150_PERCENT:
734                     aZoom.SetValue(150);
735                     break;
736                 case SID_ZOOM_200_PERCENT:
737                     aZoom.SetValue(200);
738                     break;
739                 case SID_ZOOM_OPTIMAL:
740                     aZoom.SetType( SvxZoomType::OPTIMAL );
741                     break;
742                 case SID_ZOOM_ENTIRE_PAGE:
743                     aZoom.SetType( SvxZoomType::WHOLEPAGE );
744                     break;
745                 case SID_ZOOM_PAGE_WIDTH:
746                     aZoom.SetType( SvxZoomType::PAGEWIDTH );
747                     break;
748             }
749 
750             pCurrentShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM, SfxCallMode::ASYNCHRON, { &aZoom });
751 
752             break;
753         }
754         case SID_TOOLBAR_MODE:
755         {
756             const SfxStringItem* pModeName = rReq.GetArg<SfxStringItem>( SID_TOOLBAR_MODE );
757 
758             if ( !pModeName )
759             {
760                 bDone = true;
761                 break;
762             }
763 
764             OUString aNewName(pModeName->GetValue());
765             uno::Reference< uno::XComponentContext > xContext =
766                     ::comphelper::getProcessComponentContext();
767 
768             // Get information about current frame and module
769             Reference<XFrame> xCurrentFrame;
770             vcl::EnumContext::Application eCurrentApp = vcl::EnumContext::Application::NONE;
771             OUString aCurrentMode;
772 
773             SfxViewFrame* pViewFrame = SfxViewFrame::Current();
774             if( pViewFrame )
775             {
776                 xCurrentFrame = pViewFrame->GetFrame().GetFrameInterface();
777 
778                 const Reference<frame::XModuleManager> xModuleManager  = frame::ModuleManager::create( xContext );
779                 eCurrentApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xCurrentFrame ) );
780 
781                 OUStringBuffer aPath("org.openoffice.Office.UI.ToolbarMode/Applications/");
782                 aPath.append( lcl_getAppName( eCurrentApp ) );
783 
784                 const utl::OConfigurationTreeRoot aAppNode(
785                                                     xContext,
786                                                     aPath.makeStringAndClear(),
787                                                     true);
788                 if ( !aAppNode.isValid() )
789                 {
790                     bDone = true;
791                     break;
792                 }
793 
794                 aCurrentMode = comphelper::getString( aAppNode.getNodeValue( "Active" ) );
795 
796                 if ( aCurrentMode == aNewName )
797                 {
798                     bDone = true;
799                     break;
800                 }
801 
802                 // Save new toolbar mode for a current module
803                 aAppNode.setNodeValue( "Active", makeAny( aNewName ) );
804                 aAppNode.commit();
805             }
806 
807             // Apply settings for all frames
808             pViewFrame = SfxViewFrame::GetFirst();
809             while( pViewFrame )
810             {
811                 Reference<XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
812 
813                 // We want to change mode only for a current app module, ignore other apps
814                 const Reference<frame::XModuleManager> xModuleManager  = frame::ModuleManager::create( xContext );
815                 vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
816                 if ( eApp != eCurrentApp )
817                 {
818                     pViewFrame = SfxViewFrame::GetNext( *pViewFrame );
819                     continue;
820                 }
821 
822                 Reference<css::beans::XPropertySet> xPropSet( xFrame, UNO_QUERY );
823                 Reference<css::frame::XLayoutManager> xLayoutManager;
824                 if ( xPropSet.is() )
825                 {
826                     try
827                     {
828                         Any aValue = xPropSet->getPropertyValue( "LayoutManager" );
829                         aValue >>= xLayoutManager;
830                     }
831                     catch ( const css::uno::RuntimeException& )
832                     {
833                         throw;
834                     }
835                     catch ( css::uno::Exception& )
836                     {
837                     }
838                 }
839 
840                 if ( xLayoutManager.is() )
841                 {
842                     css::uno::Sequence<OUString> aMandatoryToolbars;
843                     css::uno::Sequence<OUString> aUserToolbars;
844                     std::vector<OUString> aBackupList;
845                     OUString aSidebarMode;
846 
847                     OUStringBuffer aPath( "org.openoffice.Office.UI.ToolbarMode/Applications/" );
848                     aPath.append( lcl_getAppName( eApp ) );
849                     aPath.append( "/Modes" );
850 
851                     // Read mode settings
852                     const utl::OConfigurationTreeRoot aModesNode(
853                                             xContext,
854                                             aPath.makeStringAndClear(),
855                                             true);
856                     if ( !aModesNode.isValid() )
857                     {
858                         bDone = true;
859                         break;
860                     }
861 
862                     const Sequence<OUString> aModeNodeNames( aModesNode.getNodeNames() );
863 
864                     for ( const auto& rModeNodeName : aModeNodeNames )
865                     {
866                         const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
867                         if ( !aModeNode.isValid() )
868                             continue;
869 
870                         OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
871 
872                         if ( aCommandArg == aNewName )
873                         {
874                             aMandatoryToolbars = aModeNode.getNodeValue( "Toolbars" ).get< uno::Sequence<OUString> >();
875                             aUserToolbars = aModeNode.getNodeValue( "UserToolbars" ).get< uno::Sequence<OUString> >();
876                             aSidebarMode = comphelper::getString( aModeNode.getNodeValue( "Sidebar" ) );
877                             break;
878                         }
879                     }
880 
881                     // Backup visible toolbar list and hide all toolbars
882                     const Sequence<Reference<XUIElement>> aUIElements = xLayoutManager->getElements();
883                     for ( const Reference< XUIElement >& xUIElement : aUIElements )
884                     {
885                         Reference< XPropertySet > xPropertySet( xUIElement, UNO_QUERY );
886                         if ( xPropertySet.is() && xUIElement.is() )
887                         {
888                             try
889                             {
890                                 OUString aResName;
891                                 sal_Int16 nType( -1 );
892                                 xPropertySet->getPropertyValue( "Type" ) >>= nType;
893                                 xPropertySet->getPropertyValue( "ResourceURL" ) >>= aResName;
894 
895                                 if (( nType == css::ui::UIElementType::TOOLBAR ) &&
896                                     !aResName.isEmpty() )
897                                 {
898                                     if ( xLayoutManager->isElementVisible( aResName ) )
899                                     {
900                                         aBackupList.push_back( aResName );
901                                     }
902                                     xLayoutManager->hideElement( aResName );
903                                 }
904                             }
905                             catch ( const Exception& )
906                             {
907                             }
908                         }
909                     }
910 
911                     // Show toolbars
912                     for ( const OUString& rName : std::as_const(aMandatoryToolbars) )
913                     {
914                         xLayoutManager->createElement( rName );
915                         xLayoutManager->showElement( rName );
916                     }
917 
918                     for ( const OUString& rName : std::as_const(aUserToolbars) )
919                     {
920                         xLayoutManager->createElement( rName );
921                         xLayoutManager->showElement( rName );
922                     }
923 
924                     // Sidebar
925                     pViewFrame->ShowChildWindow( SID_SIDEBAR );
926 
927                     sfx2::sidebar::SidebarController* pSidebar =
928                             sfx2::sidebar::SidebarController::GetSidebarControllerForFrame( xFrame );
929                     if ( pSidebar )
930                     {
931                         if ( aSidebarMode == "Arrow" )
932                         {
933                             pSidebar->FadeOut();
934                         }
935                         else if ( aSidebarMode == "Tabs" )
936                         {
937                             pSidebar->FadeIn();
938                             pSidebar->RequestOpenDeck();
939                             pSidebar->RequestCloseDeck();
940                         }
941                         else if ( aSidebarMode == "Opened" )
942                         {
943                             pSidebar->FadeIn();
944                             pSidebar->RequestOpenDeck();
945                         }
946                     }
947 
948                     // Show/Hide the Notebookbar
949                     const SfxPoolItem* pItem;
950                     pViewFrame->GetDispatcher()->QueryState( SID_NOTEBOOKBAR, pItem );
951 
952                     // Save settings
953                     if ( pViewFrame == SfxViewFrame::Current() )
954                     {
955                         css::uno::Sequence<OUString> aBackup( comphelper::containerToSequence(aBackupList) );
956 
957                         for ( const auto& rModeNodeName : aModeNodeNames )
958                         {
959                             const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
960                             if ( !aModeNode.isValid() )
961                                 continue;
962 
963                             OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
964 
965                             if ( aCommandArg == aCurrentMode )
966                             {
967                                 aModeNode.setNodeValue( "UserToolbars", makeAny( aBackup ) );
968                                 break;
969                             }
970                         }
971                         aModesNode.commit();
972                     }
973                 }
974 
975                 pViewFrame = SfxViewFrame::GetNext(*pViewFrame);
976             }
977 
978             bDone = true;
979             break;
980         }
981         case SID_AVAILABLE_TOOLBARS:
982         {
983             const SfxStringItem* pToolbarName = rReq.GetArg<SfxStringItem>(SID_AVAILABLE_TOOLBARS);
984 
985             if ( pToolbarName )
986             {
987                 Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
988                 Reference< XFrame > xFrame = xDesktop->getActiveFrame();
989 
990                 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
991                 Reference< css::frame::XLayoutManager > xLayoutManager;
992                 if ( xPropSet.is() )
993                 {
994                     try
995                     {
996                         Any aValue = xPropSet->getPropertyValue("LayoutManager");
997                         aValue >>= xLayoutManager;
998                     }
999                     catch ( const css::uno::RuntimeException& )
1000                     {
1001                         throw;
1002                     }
1003                     catch ( css::uno::Exception& )
1004                     {
1005                     }
1006                 }
1007 
1008                 if ( xLayoutManager.is() )
1009                 {
1010                     OUStringBuffer aBuf( "private:resource/toolbar/" );
1011                     aBuf.append( pToolbarName->GetValue() );
1012 
1013                     // Evaluate Parameter
1014                     OUString aToolbarName( aBuf.makeStringAndClear() );
1015                     bool bShow( !xLayoutManager->isElementVisible( aToolbarName ));
1016 
1017                     if ( bShow )
1018                     {
1019                         xLayoutManager->createElement( aToolbarName );
1020                         xLayoutManager->showElement( aToolbarName );
1021                     }
1022                     else
1023                         xLayoutManager->hideElement( aToolbarName );
1024                 }
1025             }
1026 
1027             bDone = true;
1028             break;
1029         }
1030         case SID_MENUBAR:
1031         {
1032             sfx2::SfxNotebookBar::ToggleMenubar();
1033             bDone = true;
1034             break;
1035         }
1036         case SID_SAFE_MODE:
1037         {
1038             SafeModeQueryDialog aDialog(rReq.GetFrameWeld());
1039             aDialog.run();
1040             break;
1041         }
1042 
1043         default:
1044             break;
1045     }
1046 
1047     if ( bDone )
1048         rReq.Done();
1049 }
1050 
1051 void SfxApplication::MiscState_Impl(SfxItemSet &rSet)
1052 {
1053     const sal_uInt16 *pRanges = rSet.GetRanges();
1054     DBG_ASSERT(pRanges && *pRanges, "Set without range");
1055     while ( *pRanges )
1056     {
1057         for(sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich)
1058         {
1059             switch(nWhich)
1060             {
1061                 case SID_TEMPLATE_ADDRESSBOKSOURCE:
1062                     if ( !SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE) )
1063                         rSet.Put(SfxVisibilityItem(nWhich, false));
1064                     break;
1065                 case SID_QUITAPP:
1066                 {
1067                     if ( pImpl->nDocModalMode )
1068                         rSet.DisableItem(nWhich);
1069                     else
1070                         rSet.Put(SfxStringItem(nWhich, SfxResId(STR_QUITAPP)));
1071                     break;
1072                 }
1073 
1074                 case SID_CONFIG:
1075                 case SID_TOOLBOXOPTIONS:
1076                 case SID_CONFIGSTATUSBAR:
1077                 case SID_CONFIGMENU:
1078                 case SID_CONFIGACCEL:
1079                 case SID_CONFIGEVENT:
1080                 {
1081                     if( SvtMiscOptions().DisableUICustomization() )
1082                         rSet.DisableItem(nWhich);
1083                     break;
1084                 }
1085 
1086 #if HAVE_FEATURE_SCRIPTING
1087                 case SID_BASICSTOP:
1088                     if ( !StarBASIC::IsRunning() )
1089                         rSet.DisableItem(nWhich);
1090                     break;
1091 #endif
1092 
1093                 case SID_HELPTIPS:
1094                 {
1095                     rSet.Put( SfxBoolItem( SID_HELPTIPS, Help::IsQuickHelpEnabled() ) );
1096                 }
1097                 break;
1098                 case SID_HELPBALLOONS:
1099                 {
1100                     rSet.Put( SfxBoolItem( SID_HELPBALLOONS, Help::IsBalloonHelpEnabled() ) );
1101                 }
1102                 break;
1103 
1104                 case SID_EXTENDEDHELP:
1105                 {
1106                 }
1107                 break;
1108 
1109                 case SID_CLOSEDOCS:
1110                 {
1111                     Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1112                     Reference< XIndexAccess > xTasks = xDesktop->getFrames();
1113                     if ( !xTasks.is() || !xTasks->getCount() )
1114                         rSet.DisableItem(nWhich);
1115                     break;
1116                 }
1117 
1118                 case SID_SAVEDOCS:
1119                 {
1120                     bool bModified = false;
1121                     for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
1122                           pObjSh;
1123                           pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
1124                     {
1125                         if ( pObjSh->IsModified() )
1126                         {
1127                             bModified = true;
1128                             break;
1129                         }
1130                     }
1131 
1132                     if ( !bModified )
1133                         rSet.DisableItem( nWhich );
1134                     break;
1135                 }
1136 
1137                 case SID_TEMPLATE_MANAGER:
1138                     {
1139                         SvtMiscOptions aMiscOptions;
1140                         if ( !aMiscOptions.IsExperimentalMode() )
1141                         {
1142                            rSet.DisableItem( nWhich );
1143                            rSet.Put( SfxVisibilityItem( nWhich, false ) );
1144                         }
1145                     }
1146                     break;
1147 
1148                 case SID_ZOOM_50_PERCENT:
1149                 case SID_ZOOM_75_PERCENT:
1150                 case SID_ZOOM_100_PERCENT:
1151                 case SID_ZOOM_150_PERCENT:
1152                 case SID_ZOOM_200_PERCENT:
1153                 case SID_ZOOM_OPTIMAL:
1154                 case SID_ZOOM_ENTIRE_PAGE:
1155                 case SID_ZOOM_PAGE_WIDTH:
1156                     {
1157                         SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
1158 
1159                         const SfxPoolItem *pItem;
1160                         SfxItemState aState = pCurrentShell ?
1161                             pCurrentShell->GetDispatcher()->QueryState(SID_ATTR_ZOOM, pItem) : SfxItemState::DISABLED;
1162                         if ( aState == SfxItemState::DISABLED )
1163                             rSet.DisableItem( nWhich );
1164                     }
1165                     break;
1166 
1167                 case SID_MENUBAR:
1168                 {
1169                     Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
1170                     Reference< XFrame > xFrame = xDesktop->getActiveFrame();
1171 
1172                     Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
1173                     Reference< css::frame::XLayoutManager > xLayoutManager;
1174                     if ( xPropSet.is() )
1175                     {
1176                         try
1177                         {
1178                             Any aValue = xPropSet->getPropertyValue("LayoutManager");
1179                             aValue >>= xLayoutManager;
1180                         }
1181                         catch ( const css::uno::RuntimeException& )
1182                         {
1183                             throw;
1184                         }
1185                         catch ( css::uno::Exception& )
1186                         {
1187                         }
1188                     }
1189 
1190                     if ( xLayoutManager.is() )
1191                     {
1192                         const bool bState
1193                             = xLayoutManager->getElement("private:resource/menubar/menubar").is()
1194                               && xLayoutManager->isElementVisible(
1195                                      "private:resource/menubar/menubar");
1196 
1197                         SfxBoolItem aItem( SID_MENUBAR, bState );
1198                         rSet.Put( aItem );
1199                     }
1200                     break;
1201                 }
1202                 case SID_SAFE_MODE:
1203                 {
1204                     // no restart in safe mode when already in safe mode
1205                     if ( Application::IsSafeModeEnabled() )
1206                        rSet.DisableItem( SID_SAFE_MODE );
1207                     break;
1208                 }
1209 
1210                 default:
1211                     break;
1212             }
1213         }
1214 
1215         ++pRanges;
1216     }
1217 }
1218 
1219 #if HAVE_FEATURE_SCRIPTING
1220 
1221 #ifndef DISABLE_DYNLOADING
1222 
1223 typedef rtl_uString* (*basicide_choose_macro)(void*, void*, void*, sal_Bool);
1224 
1225 extern "C" { static void thisModule() {} }
1226 
1227 #else
1228 
1229 extern "C" rtl_uString* basicide_choose_macro(void*, void*, void*, sal_Bool);
1230 
1231 #endif
1232 
1233 static OUString ChooseMacro(weld::Window* pParent, const Reference<XModel>& rxLimitToDocument, const Reference<XFrame>& xDocFrame, bool bChooseOnly)
1234 {
1235 #ifndef DISABLE_DYNLOADING
1236     osl::Module aMod;
1237 
1238     // load basctl module
1239     aMod.loadRelative(&thisModule, SVLIBRARY("basctl"));
1240 
1241     // get symbol
1242     basicide_choose_macro pSymbol = reinterpret_cast<basicide_choose_macro>(aMod.getFunctionSymbol("basicide_choose_macro"));
1243     SAL_WARN_IF(!pSymbol, "sfx.appl", "SfxApplication::MacroOrganizer, no symbol!");
1244     if (!pSymbol)
1245         return OUString();
1246     aMod.release();
1247 #else
1248 #define pSymbol basicide_choose_macro
1249 #endif
1250 
1251     // call basicide_choose_macro in basctl
1252     rtl_uString* pScriptURL = pSymbol(pParent, rxLimitToDocument.get(), xDocFrame.get(), bChooseOnly);
1253     OUString aScriptURL( pScriptURL );
1254     rtl_uString_release( pScriptURL );
1255     return aScriptURL;
1256 
1257 #ifdef DISABLE_DYNLOADING
1258 #undef pSymbol
1259 #endif
1260 }
1261 
1262 #endif
1263 
1264 namespace
1265 {
1266 #if HAVE_FEATURE_SCRIPTING
1267     weld::Window* lcl_getDialogParent(const Reference<XFrame>& rxFrame)
1268     {
1269         Reference<awt::XWindow> xContainerWindow;
1270         if (rxFrame.is())
1271             xContainerWindow = rxFrame->getContainerWindow();
1272         return Application::GetFrameWeld(xContainerWindow);
1273     }
1274 
1275     SfxViewFrame* lcl_getBasicIDEViewFrame( SfxObjectShell const * i_pBasicIDE )
1276     {
1277         SfxViewFrame* pView = SfxViewFrame::GetFirst( i_pBasicIDE );
1278         while ( pView )
1279         {
1280             if ( pView->GetObjectShell()->GetFactory().GetDocumentServiceName() == "com.sun.star.script.BasicIDE" )
1281                 break;
1282             pView = SfxViewFrame::GetNext( *pView, i_pBasicIDE );
1283         }
1284         return pView;
1285     }
1286     Reference< XFrame > lcl_findStartModuleFrame( const Reference<XComponentContext> & rxContext )
1287     {
1288         try
1289         {
1290             Reference < XDesktop2 > xDesktop = Desktop::create( rxContext );
1291             Reference < XIndexAccess > xContainer( xDesktop->getFrames(), UNO_QUERY_THROW );
1292 
1293             Reference< XModuleManager2 > xCheck = ModuleManager::create(rxContext);
1294 
1295             sal_Int32 nCount = xContainer->getCount();
1296             for ( sal_Int32 i=0; i<nCount; ++i )
1297             {
1298                 try
1299                 {
1300                     Reference < XFrame > xFrame( xContainer->getByIndex(i), UNO_QUERY_THROW );
1301                     OUString sModule = xCheck->identify( xFrame );
1302                     if ( sModule == "com.sun.star.frame.StartModule" )
1303                         return xFrame;
1304                 }
1305                 catch( const UnknownModuleException& )
1306                 {
1307                     // silence
1308                 }
1309                 catch(const Exception&)
1310                 {
1311                     // re-throw, caught below
1312                     throw;
1313                 }
1314             }
1315         }
1316         catch( const Exception& )
1317         {
1318                DBG_UNHANDLED_EXCEPTION("sfx.appl");
1319         }
1320         return nullptr;
1321     }
1322 #endif // HAVE_FEATURE_SCRIPTING
1323 }
1324 
1325 void SfxApplication::OfaExec_Impl( SfxRequest& rReq )
1326 {
1327     switch ( rReq.GetSlot() )
1328     {
1329         case SID_OPTIONS_TREEDIALOG:
1330         {
1331             OUString sPageURL;
1332             const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_OPTIONS_PAGEURL);
1333             if ( pURLItem )
1334                 sPageURL = pURLItem->GetValue();
1335             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1336             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1337             VclPtr<VclAbstractDialog> pDlg =
1338                 pFact->CreateFrameDialog(rReq.GetFrameWeld(), xFrame, rReq.GetSlot(), sPageURL );
1339             short nRet = pDlg->Execute();
1340             pDlg.disposeAndClear();
1341             SfxViewFrame* pView = SfxViewFrame::GetFirst();
1342             while ( pView )
1343             {
1344                 if (nRet == RET_OK)
1345                 {
1346                     SfxObjectShell* pObjSh = pView->GetObjectShell();
1347                     if (pObjSh)
1348                         pObjSh->SetConfigOptionsChecked(false);
1349                 }
1350                 pView->GetBindings().InvalidateAll(false);
1351                 pView = SfxViewFrame::GetNext( *pView );
1352             }
1353             break;
1354         }
1355 
1356         case SID_MORE_DICTIONARIES:
1357         {
1358             try
1359             {
1360                 uno::Reference< uno::XComponentContext > xContext =
1361                     ::comphelper::getProcessComponentContext();
1362                 uno::Reference< css::system::XSystemShellExecute > xSystemShell(
1363                     css::system::SystemShellExecute::create(xContext) );
1364 
1365                 // read repository URL from configuration
1366                 OUString sTemplRepoURL(officecfg::Office::Common::Dictionaries::RepositoryURL::get());
1367 
1368                 if ( xSystemShell.is() && !sTemplRepoURL.isEmpty() )
1369                 {
1370                     OUStringBuffer aURLBuf( sTemplRepoURL );
1371                     aURLBuf.append("?lang=");
1372 
1373                     // read locale from configuration
1374                     OUString sLocale(officecfg::Setup::L10N::ooLocale::get());
1375                     if (sLocale.isEmpty())
1376                         sLocale = "en-US";
1377 
1378                     aURLBuf.append( sLocale );
1379                     xSystemShell->execute(
1380                         aURLBuf.makeStringAndClear(),
1381                         OUString(),
1382                         css::system::SystemShellExecuteFlags::URIS_ONLY );
1383                 }
1384             }
1385             catch( const css::uno::Exception& )
1386             {
1387                 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxApplication::OfaExec_Impl(SID_MORE_DICTIONARIES)" );
1388             }
1389             break;
1390         }
1391 #if HAVE_FEATURE_SCRIPTING
1392         case SID_BASICIDE_APPEAR:
1393         {
1394             SfxViewFrame* pView = lcl_getBasicIDEViewFrame( nullptr );
1395             if ( !pView )
1396             {
1397                 SfxObjectShell* pBasicIDE = SfxObjectShell::CreateObject( "com.sun.star.script.BasicIDE" );
1398                 pBasicIDE->DoInitNew();
1399                 pBasicIDE->SetModified( false );
1400                 try
1401                 {
1402                     // load the Basic IDE via direct access to the SFX frame loader. A generic loadComponentFromURL
1403                     // (which could be done via SfxViewFrame::LoadDocumentIntoFrame) is not feasible here, since the Basic IDE
1404                     // does not really play nice with the framework's concept. For instance, it is a "singleton document",
1405                     // which conflicts, at the latest, with the framework's concept of loading into _blank frames.
1406                     // So, since we know that our frame loader can handle it, we skip the generic framework loader
1407                     // mechanism, and the type detection (which doesn't know about the Basic IDE).
1408                     Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1409                     Reference< XSynchronousFrameLoader > xLoader(
1410                         xContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.office.FrameLoader", xContext),
1411                         UNO_QUERY_THROW );
1412                     ::comphelper::NamedValueCollection aLoadArgs;
1413                     aLoadArgs.put( "Model", pBasicIDE->GetModel() );
1414                     aLoadArgs.put( "URL", OUString( "private:factory/sbasic"  ) );
1415 
1416                     Reference< XFrame > xTargetFrame( lcl_findStartModuleFrame( xContext ) );
1417                     if ( !xTargetFrame.is() )
1418                         xTargetFrame = SfxFrame::CreateBlankFrame();
1419                     ENSURE_OR_THROW( xTargetFrame.is(), "could not obtain a frameto load the Basic IDE into!" );
1420 
1421                     xLoader->load( aLoadArgs.getPropertyValues(), xTargetFrame );
1422                 }
1423                 catch( const Exception& )
1424                 {
1425                     DBG_UNHANDLED_EXCEPTION("sfx.appl");
1426                 }
1427 
1428                 pView = lcl_getBasicIDEViewFrame( pBasicIDE );
1429                 if ( pView )
1430                     pView->SetName( "BASIC:1" );
1431             }
1432 
1433             if ( pView )
1434                 pView->GetFrame().Appear();
1435 
1436             const SfxItemSet* pArgs = rReq.GetArgs();
1437             if ( pArgs && pView )
1438             {
1439                 SfxViewShell* pViewShell = pView->GetViewShell();
1440                 SfxObjectShell* pObjShell = pView->GetObjectShell();
1441                 if ( pViewShell && pObjShell )
1442                 {
1443                     SfxRequest aReq( SID_BASICIDE_SHOWWINDOW, SfxCallMode::SYNCHRON, pObjShell->GetPool() );
1444                     aReq.SetArgs( *pArgs );
1445                     pViewShell->ExecuteSlot( aReq );
1446                 }
1447             }
1448 
1449             rReq.Done();
1450         }
1451         break;
1452 
1453         case SID_BASICCHOOSER:
1454         {
1455             const SfxItemSet* pArgs = rReq.GetArgs();
1456             const SfxPoolItem* pItem;
1457             bool bChooseOnly = false;
1458             Reference< XModel > xLimitToModel;
1459             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_RECORDMACRO, false, &pItem) )
1460             {
1461                 bool bRecord = static_cast<const SfxBoolItem*>(pItem)->GetValue();
1462                 if ( bRecord )
1463                 {
1464                     // !Hack
1465                     bChooseOnly = false;
1466                     SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
1467                     OSL_ENSURE( pCurrentShell, "macro recording outside an SFX document?" );
1468                     if ( pCurrentShell )
1469                         xLimitToModel = pCurrentShell->GetModel();
1470                 }
1471             }
1472 
1473             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1474             rReq.SetReturnValue(SfxStringItem(rReq.GetSlot(), ChooseMacro(rReq.GetFrameWeld(), xLimitToModel, xFrame, bChooseOnly)));
1475             rReq.Done();
1476         }
1477         break;
1478 
1479         case SID_MACROORGANIZER:
1480         {
1481             SAL_INFO("sfx.appl", "handling SID_MACROORGANIZER");
1482             const SfxItemSet* pArgs = rReq.GetArgs();
1483             const SfxPoolItem* pItem;
1484             sal_Int16 nTabId = 0;
1485             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_MACROORGANIZER, false, &pItem) )
1486             {
1487                 nTabId = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1488             }
1489 
1490             SfxApplication::MacroOrganizer(rReq.GetFrameWeld(), nTabId);
1491             rReq.Done();
1492         }
1493         break;
1494 
1495         case SID_RUNMACRO:
1496         {
1497             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1498             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: case ScriptOrg");
1499 
1500             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1501             if ( !xFrame.is() )
1502             {
1503                 const SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1504                 if ( pViewFrame )
1505                     xFrame = pViewFrame->GetFrame().GetFrameInterface();
1506             }
1507 
1508             do  // artificial loop for flow control
1509             {
1510                 ScopedVclPtr<AbstractScriptSelectorDialog> pDlg(pFact->CreateScriptSelectorDialog(lcl_getDialogParent(xFrame), xFrame));
1511                 OSL_ENSURE( pDlg, "SfxApplication::OfaExec_Impl( SID_RUNMACRO ): no dialog!" );
1512                 if ( !pDlg )
1513                     break;
1514                 pDlg->SetRunLabel();
1515 
1516                 short nDialogResult = pDlg->Execute();
1517                 if ( !nDialogResult )
1518                     break;
1519 
1520                 Sequence< Any > args;
1521                 Sequence< sal_Int16 > outIndex;
1522                 Sequence< Any > outArgs;
1523                 Any ret;
1524 
1525                 Reference< XInterface > xScriptContext;
1526 
1527                 Reference< XController > xController;
1528                 if ( xFrame.is() )
1529                     xController = xFrame->getController();
1530                 if ( xController.is() )
1531                     xScriptContext = xController->getModel();
1532                 if ( !xScriptContext.is() )
1533                     xScriptContext = xController;
1534 
1535                 SfxObjectShell::CallXScript( xScriptContext, pDlg->GetScriptURL(), args, ret, outIndex, outArgs );
1536             }
1537             while ( false );
1538             rReq.Done();
1539         }
1540         break;
1541 
1542         case SID_SCRIPTORGANIZER:
1543         {
1544             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1545             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: case ScriptOrg");
1546             const SfxItemSet* pArgs = rReq.GetArgs();
1547             const SfxPoolItem* pItem;
1548             OUString aLanguage;
1549             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SCRIPTORGANIZER, false, &pItem) )
1550             {
1551                 aLanguage = static_cast<const SfxScriptOrganizerItem*>(pItem)->getLanguage();
1552             }
1553 
1554             OUString aLang( aLanguage );
1555             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: about to create dialog for: " << aLang);
1556             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSvxScriptOrgDialog(rReq.GetFrameWeld(), aLanguage));
1557             if( pDlg )
1558             {
1559                 pDlg->Execute();
1560             }
1561             else
1562             {
1563                 SAL_WARN("sfx.appl", "no dialog!!!");
1564             }
1565             rReq.Done();
1566         }
1567         break;
1568 #endif // HAVE_FEATURE_SCRIPTING
1569 
1570         case SID_OFFICE_CHECK_PLZ:
1571         {
1572             bool bRet = false;
1573             const SfxStringItem* pStringItem = rReq.GetArg<SfxStringItem>(rReq.GetSlot());
1574 
1575             if ( pStringItem )
1576             {
1577                 bRet = true /*!!!SfxIniManager::CheckPLZ( aPLZ )*/;
1578             }
1579 #if HAVE_FEATURE_SCRIPTING
1580             else
1581                 SbxBase::SetError( ERRCODE_BASIC_WRONG_ARGS );
1582 #endif
1583             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bRet ) );
1584         }
1585         break;
1586 
1587         case SID_AUTO_CORRECT_DLG:
1588         {
1589             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1590             SfxItemSet aSet(GetPool(), svl::Items<SID_AUTO_CORRECT_DLG, SID_AUTO_CORRECT_DLG>{});
1591             const SfxPoolItem* pItem=nullptr;
1592             const SfxItemSet* pSet = rReq.GetArgs();
1593             SfxItemPool* pSetPool = pSet ? pSet->GetPool() : nullptr;
1594             if ( pSet && pSet->GetItemState( pSetPool->GetWhich( SID_AUTO_CORRECT_DLG ), false, &pItem ) == SfxItemState::SET )
1595                 aSet.Put( *pItem );
1596 
1597             const SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1598             ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateAutoCorrTabDialog(pViewFrame ? pViewFrame->GetWindow().GetFrameWeld() : nullptr, &aSet));
1599             pDlg->Execute();
1600 
1601             break;
1602         }
1603 
1604         case SID_NEWSD :
1605         {
1606             SvtModuleOptions aModuleOpt;
1607             if ( !aModuleOpt.IsImpress() )
1608             {
1609                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
1610                                                                          VclMessageType::Warning, VclButtonsType::Ok,
1611                                                                          SfxResId(STR_MODULENOTINSTALLED)));
1612                 xBox->run();
1613                 return;
1614             }
1615 
1616             Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1617             Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext );
1618 
1619             OUString aCmd = OUString::createFromAscii( GetInterface()->GetSlot( rReq.GetSlot() )->GetUnoName() );
1620             Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
1621             Sequence < beans::PropertyValue > aSeq;
1622             if ( rReq.GetArgs() )
1623                 TransformItems( rReq.GetSlot(), *rReq.GetArgs(), aSeq );
1624             Any aResult = xHelper->executeDispatch( xProv, aCmd, OUString(), 0, aSeq );
1625             frame::DispatchResultEvent aEvent;
1626             bool bSuccess = (aResult >>= aEvent) &&
1627                                 (aEvent.State == frame::DispatchResultState::SUCCESS);
1628             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bSuccess ) );
1629         }
1630         break;
1631 
1632         case FN_LABEL :
1633         case FN_BUSINESS_CARD :
1634         case FN_XFORMS_INIT :
1635         {
1636             Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1637             Reference< frame::XDispatchProvider > xProv = text::ModuleDispatcher::create( xContext );
1638 
1639             OUString aCmd = OUString::createFromAscii( GetInterface()->GetSlot( rReq.GetSlot() )->GetUnoName() );
1640             Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
1641             Sequence < beans::PropertyValue > aSeq;
1642             if ( rReq.GetArgs() )
1643                 TransformItems( rReq.GetSlot(), *rReq.GetArgs(), aSeq );
1644             Any aResult = xHelper->executeDispatch( xProv, aCmd, OUString(), 0, aSeq );
1645             frame::DispatchResultEvent aEvent;
1646             bool bSuccess = (aResult >>= aEvent) &&
1647                                 (aEvent.State == frame::DispatchResultState::SUCCESS);
1648             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bSuccess ) );
1649         }
1650         break;
1651 
1652         case SID_ADDRESS_DATA_SOURCE:
1653         {
1654             try
1655             {
1656                 Reference< uno::XComponentContext > xORB = ::comphelper::getProcessComponentContext();
1657                 Reference< ui::dialogs::XExecutableDialog > xDialog = ui::dialogs::AddressBookSourcePilot::createWithParent(xORB, nullptr);
1658                 xDialog->execute();
1659             }
1660             catch(const css::uno::Exception&)
1661             {
1662                 DBG_UNHANDLED_EXCEPTION("sfx.appl");
1663             }
1664         }
1665         break;
1666 
1667         case SID_COMP_BIBLIOGRAPHY:
1668             lcl_tryLoadBibliography();
1669         break;
1670     }
1671 }
1672 
1673 void SfxApplication::OfaState_Impl(SfxItemSet &rSet)
1674 {
1675     SvtModuleOptions aModuleOpt;
1676 
1677     if( !aModuleOpt.IsWriter())
1678     {
1679         rSet.DisableItem( FN_LABEL );
1680         rSet.DisableItem( FN_BUSINESS_CARD );
1681         rSet.DisableItem( FN_XFORMS_INIT );
1682     }
1683 
1684 }
1685 
1686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1687