xref: /trunk/main/sfx2/source/appl/shutdownicon.cxx (revision ac203367)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <shutdownicon.hxx>
32 #include <app.hrc>
33 #include <sfx2/app.hxx>
34 #include <vos/mutex.hxx>
35 #include <svtools/imagemgr.hxx>
36 #include <svtools/miscopt.hxx>
37 // #include <cmdlineargs.hxx>
38 #include <com/sun/star/task/XInteractionHandler.hpp>
39 #include <com/sun/star/frame/XDispatchResultListener.hpp>
40 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
41 #include <com/sun/star/frame/XFramesSupplier.hpp>
42 #include <com/sun/star/frame/XComponentLoader.hpp>
43 #include <com/sun/star/frame/XFrame.hpp>
44 #include <com/sun/star/util/XURLTransformer.hpp>
45 #include <com/sun/star/frame/XFramesSupplier.hpp>
46 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
47 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
48 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
49 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
50 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
51 #include <com/sun/star/document/MacroExecMode.hpp>
52 #include <com/sun/star/document/UpdateDocMode.hpp>
53 #include <sfx2/filedlghelper.hxx>
54 #include <sfx2/fcontnr.hxx>
55 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
56 #include <comphelper/processfactory.hxx>
57 #endif
58 #include <cppuhelper/compbase1.hxx>
59 #include <sfx2/dispatch.hxx>
60 #include <comphelper/extract.hxx>
61 #include <tools/urlobj.hxx>
62 #include <osl/security.hxx>
63 #include <osl/file.hxx>
64 #include <rtl/bootstrap.hxx>
65 #include <tools/link.hxx>
66 #ifdef UNX // need symlink
67 #include <unistd.h>
68 #include <errno.h>
69 #endif
70 #include <vcl/timer.hxx>
71 
72 #include "sfx2/sfxresid.hxx"
73 
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star::frame;
76 using namespace ::com::sun::star::container;
77 using namespace ::com::sun::star::io;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::beans;
80 using namespace ::com::sun::star::util;
81 using namespace ::com::sun::star::ui::dialogs;
82 using namespace ::vos;
83 #ifdef WNT
84 using ::rtl::OUString;
85 #else
86 using namespace ::rtl;
87 #endif
88 using namespace ::sfx2;
89 
90 #ifdef ENABLE_QUICKSTART_APPLET
91 # if !defined(WIN32) && !defined(QUARTZ)
92 extern "C" { static void SAL_CALL thisModule() {} }
93 # endif
94 #endif
95 
96 #if defined(UNX) && defined(ENABLE_SYSTRAY_GTK)
97 #define PLUGIN_NAME libqstart_gtk.so
98 #endif
99 
100 class SfxNotificationListener_Impl : public cppu::WeakImplHelper1< XDispatchResultListener >
101 {
102 public:
103     virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) throw( RuntimeException );
104     virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException );
105 };
106 
107 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException )
108 {
109 	ShutdownIcon::LeaveModalMode();
110 }
111 
112 void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) throw( RuntimeException )
113 {
114 }
115 
116 SFX_IMPL_XSERVICEINFO( ShutdownIcon, "com.sun.star.office.Quickstart", "com.sun.star.comp.desktop.QuickstartWrapper" )	\
117 SFX_IMPL_ONEINSTANCEFACTORY( ShutdownIcon );
118 
119 bool ShutdownIcon::bModalMode = false;
120 ShutdownIcon* ShutdownIcon::pShutdownIcon = NULL;
121 
122 // To remove conditionals
123 extern "C" {
124 	static void disabled_initSystray() { }
125 	static void disabled_deInitSystray() { }
126 }
127 #define DOSTRING( x )			   			#x
128 #define STRING( x )				   			DOSTRING( x )
129 
130 bool ShutdownIcon::LoadModule( osl::Module **pModule,
131 							   oslGenericFunction *pInit,
132 							   oslGenericFunction *pDeInit )
133 {
134 	if ( pModule )
135 	{
136 		OSL_ASSERT ( pInit && pDeInit );
137 		*pInit = *pDeInit = NULL;
138 		*pModule = NULL;
139 	}
140 
141 #ifdef ENABLE_QUICKSTART_APPLET
142 #  ifdef WIN32
143 	if ( pModule )
144 	{
145 		*pInit = win32_init_sys_tray;
146 		*pDeInit = win32_shutdown_sys_tray;
147 	}
148 	return true;
149 #  elif defined QUARTZ
150     *pInit = aqua_init_systray;
151     *pDeInit = aqua_shutdown_systray;
152     return true;
153 #  else // UNX
154 	osl::Module *pPlugin;
155 	pPlugin = new osl::Module();
156 
157 	oslGenericFunction pTmpInit = NULL;
158 	oslGenericFunction pTmpDeInit = NULL;
159 	if ( pPlugin->loadRelative( &thisModule, OUString( RTL_CONSTASCII_USTRINGPARAM( STRING( PLUGIN_NAME ) ) ) ) )
160 	{
161 		pTmpInit = pPlugin->getFunctionSymbol(
162 			OUString( RTL_CONSTASCII_USTRINGPARAM( "plugin_init_sys_tray" ) ) );
163 		pTmpDeInit = pPlugin->getFunctionSymbol(
164 			OUString( RTL_CONSTASCII_USTRINGPARAM( "plugin_shutdown_sys_tray" ) ) );
165 	}
166 	if ( !pTmpInit || !pTmpDeInit )
167 	{
168 		delete pPlugin;
169 		pPlugin = NULL;
170 	}
171 	if ( pModule )
172 	{
173 		*pModule = pPlugin;
174 		*pInit = pTmpInit;
175 		*pDeInit = pTmpDeInit;
176 	}
177 	else
178 	{
179 		bool bRet = pPlugin != NULL;
180 		delete pPlugin;
181 		return bRet;
182 	}
183 #  endif // UNX
184 #endif // ENABLE_QUICKSTART_APPLET
185 	if ( pModule )
186 	{
187 		if ( !*pInit )
188 			*pInit = disabled_initSystray;
189 		if ( !*pDeInit )
190 			*pDeInit = disabled_deInitSystray;
191 	}
192 
193 	return true;
194 }
195 
196 class IdleUnloader : Timer
197 {
198     ::osl::Module *m_pModule;
199 public:
200     IdleUnloader (::osl::Module **pModule) :
201         m_pModule (*pModule)
202     {
203         *pModule = NULL;
204         Start();
205     }
206     virtual void Timeout()
207     {
208         delete m_pModule;
209         delete this;
210     }
211 };
212 
213 void ShutdownIcon::initSystray()
214 {
215 	if (m_bInitialized)
216 		return;
217 	m_bInitialized = true;
218 
219 	(void) LoadModule( &m_pPlugin, &m_pInitSystray, &m_pDeInitSystray );
220 	m_bVeto = true;
221 	m_pInitSystray();
222 }
223 
224 void ShutdownIcon::deInitSystray()
225 {
226 	if (!m_bInitialized)
227 		return;
228 
229     if (m_pDeInitSystray)
230 		m_pDeInitSystray();
231 
232 	m_bVeto = false;
233 	m_pInitSystray = 0;
234 	m_pDeInitSystray = 0;
235     new IdleUnloader (&m_pPlugin);
236 
237     delete m_pFileDlg;
238 	m_pFileDlg = NULL;
239 	m_bInitialized = false;
240 }
241 
242 
243 ShutdownIcon::ShutdownIcon( Reference< XMultiServiceFactory > aSMgr ) :
244 	ShutdownIconServiceBase( m_aMutex ),
245 	m_bVeto ( false ),
246     m_bListenForTermination ( false ),
247     m_bSystemDialogs( false ),
248 	m_pResMgr( NULL ),
249     m_pFileDlg( NULL ),
250 	m_xServiceManager( aSMgr ),
251 	m_pInitSystray( 0 ),
252 	m_pDeInitSystray( 0 ),
253 	m_pPlugin( 0 ),
254 	m_bInitialized( false )
255 {
256     m_bSystemDialogs = SvtMiscOptions().UseSystemFileDialog();
257 }
258 
259 ShutdownIcon::~ShutdownIcon()
260 {
261 	deInitSystray();
262     new IdleUnloader (&m_pPlugin);
263 }
264 
265 // ---------------------------------------------------------------------------
266 
267 void ShutdownIcon::OpenURL( const ::rtl::OUString& aURL, const ::rtl::OUString& rTarget, const Sequence< PropertyValue >& aArgs )
268 {
269     if ( getInstance() && getInstance()->m_xDesktop.is() )
270     {
271         Reference < XDispatchProvider > xDispatchProvider( getInstance()->m_xDesktop, UNO_QUERY );
272         if ( xDispatchProvider.is() )
273         {
274             com::sun::star::util::URL aDispatchURL;
275             aDispatchURL.Complete = aURL;
276 
277             Reference < com::sun::star::util::XURLTransformer > xURLTransformer(
278                 ::comphelper::getProcessServiceFactory()->createInstance( OUString::createFromAscii("com.sun.star.util.URLTransformer") ),
279                 com::sun::star::uno::UNO_QUERY );
280             if ( xURLTransformer.is() )
281             {
282                 try
283                 {
284                     Reference< com::sun::star::frame::XDispatch > xDispatch;
285 
286                     xURLTransformer->parseStrict( aDispatchURL );
287                     xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
288                     if ( xDispatch.is() )
289                         xDispatch->dispatch( aDispatchURL, aArgs );
290                 }
291                 catch ( com::sun::star::uno::RuntimeException& )
292                 {
293                     throw;
294                 }
295                 catch ( com::sun::star::uno::Exception& )
296                 {
297                 }
298             }
299         }
300     }
301 }
302 
303 // ---------------------------------------------------------------------------
304 
305 void ShutdownIcon::FileOpen()
306 {
307     if ( getInstance() && getInstance()->m_xDesktop.is() )
308     {
309         ::vos::OGuard aGuard( Application::GetSolarMutex() );
310 		EnterModalMode();
311         getInstance()->StartFileDialog();
312     }
313 }
314 
315 // ---------------------------------------------------------------------------
316 
317 void ShutdownIcon::FromTemplate()
318 {
319     if ( getInstance() && getInstance()->m_xDesktop.is() )
320     {
321         Reference < ::com::sun::star::frame::XFramesSupplier > xDesktop ( getInstance()->m_xDesktop, UNO_QUERY);
322         Reference < ::com::sun::star::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
323         if ( !xFrame.is() )
324             xFrame = Reference < ::com::sun::star::frame::XFrame >( xDesktop, UNO_QUERY );
325 
326         URL aTargetURL;
327         aTargetURL.Complete = OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:5500" ) );
328         Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
329         xTrans->parseStrict( aTargetURL );
330 
331         Reference < ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
332         Reference < ::com::sun::star::frame::XDispatch > xDisp;
333 	    if ( xProv.is() )
334 	    {
335             if ( aTargetURL.Protocol.compareToAscii("slot:") == COMPARE_EQUAL )
336                 xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
337             else
338                 xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString::createFromAscii("_blank"), 0 );
339 	    }
340         if ( xDisp.is() )
341 	    {
342 		    Sequence<PropertyValue> aArgs(1);
343 		    PropertyValue* pArg = aArgs.getArray();
344 		    pArg[0].Name = rtl::OUString::createFromAscii("Referer");
345             pArg[0].Value <<= ::rtl::OUString::createFromAscii("private:user");
346             Reference< ::com::sun::star::frame::XNotifyingDispatch > xNotifyer( xDisp, UNO_QUERY );
347             if ( xNotifyer.is() )
348 			{
349 				EnterModalMode();
350                 xNotifyer->dispatchWithNotification( aTargetURL, aArgs, new SfxNotificationListener_Impl() );
351 			}
352             else
353                 xDisp->dispatch( aTargetURL, aArgs );
354 	    }
355     }
356 }
357 
358 // ---------------------------------------------------------------------------
359 #include <tools/rcid.h>
360 OUString ShutdownIcon::GetResString( int id )
361 {
362     ::vos::OGuard aGuard( Application::GetSolarMutex() );
363 
364     if( ! m_pResMgr )
365         m_pResMgr = SfxResId::GetResMgr();
366 	ResId aResId( id, *m_pResMgr );
367 	aResId.SetRT( RSC_STRING );
368 	if( !m_pResMgr || !m_pResMgr->IsAvailable( aResId ) )
369         return OUString();
370 
371     UniString aRes( ResId(id, *m_pResMgr) );
372     return OUString( aRes );
373 }
374 
375 // ---------------------------------------------------------------------------
376 
377 OUString ShutdownIcon::GetUrlDescription( const OUString& aUrl )
378 {
379     ::vos::OGuard aGuard( Application::GetSolarMutex() );
380 
381     return OUString( SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ) );
382 }
383 
384 // ---------------------------------------------------------------------------
385 
386 void ShutdownIcon::StartFileDialog()
387 {
388     ::vos::OGuard aGuard( Application::GetSolarMutex() );
389 
390     bool bDirty = ( m_bSystemDialogs != static_cast<bool>(SvtMiscOptions().UseSystemFileDialog()) );
391 
392     if ( m_pFileDlg && bDirty )
393     {
394         // Destroy instance as changing the system file dialog setting
395         // forces us to create a new FileDialogHelper instance!
396         delete m_pFileDlg;
397         m_pFileDlg = NULL;
398     }
399 
400     if ( !m_pFileDlg )
401         m_pFileDlg = new FileDialogHelper( WB_OPEN | SFXWB_MULTISELECTION, String() );
402     m_pFileDlg->StartExecuteModal( STATIC_LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
403 }
404 
405 // ---------------------------------------------------------------------------
406 
407 IMPL_STATIC_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, EMPTYARG )
408 {
409     DBG_ASSERT( pThis->m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
410 
411     // use ctor for filling up filters automatically! #89169#
412     if ( ERRCODE_NONE == pThis->m_pFileDlg->GetError() )
413     {
414         Reference< XFilePicker >    xPicker = pThis->m_pFileDlg->GetFilePicker();
415 
416         try
417         {
418 
419             if ( xPicker.is() )
420             {
421 
422                 Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
423                 Reference < XFilterManager > xFilterManager ( xPicker, UNO_QUERY );
424 
425                 Sequence< OUString >        sFiles = xPicker->getFiles();
426                 int                         nFiles = sFiles.getLength();
427 
428                 int                         nArgs=3;
429                 Sequence< PropertyValue >   aArgs(3);
430 
431                 Reference < com::sun::star::task::XInteractionHandler > xInteraction(
432                     ::comphelper::getProcessServiceFactory()->createInstance( OUString::createFromAscii("com.sun.star.task.InteractionHandler") ),
433                     com::sun::star::uno::UNO_QUERY );
434 
435                 aArgs[0].Name = OUString::createFromAscii( "InteractionHandler" );
436                 aArgs[0].Value <<= xInteraction;
437 
438                 sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
439                 aArgs[1].Name = OUString::createFromAscii( "MacroExecutionMode" );
440                 aArgs[1].Value <<= nMacroExecMode;
441 
442                 sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
443                 aArgs[2].Name = OUString::createFromAscii( "UpdateDocMode" );
444                 aArgs[2].Value <<= nUpdateDoc;
445 
446                 // pb: #102643# use the filedlghelper to get the current filter name,
447                 // because it removes the extensions before you get the filter name.
448                 OUString aFilterName( pThis->m_pFileDlg->GetCurrentFilter() );
449 
450                 if ( xPickerControls.is() )
451                 {
452 
453                     // Set readonly flag
454 
455                     sal_Bool    bReadOnly = sal_False;
456 
457 
458                     xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
459 
460                     // #95239#: Only set porperty if readonly is set to TRUE
461 
462                     if ( bReadOnly )
463                     {
464                         aArgs.realloc( ++nArgs );
465                         aArgs[nArgs-1].Name  = OUString::createFromAscii( "ReadOnly" );
466                         aArgs[nArgs-1].Value <<= bReadOnly;
467                     }
468 
469                     // Get version string
470 
471                     sal_Int32   iVersion = -1;
472 
473                     xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
474 
475                     if ( iVersion >= 0 )
476                     {
477                         sal_Int16   uVersion = (sal_Int16)iVersion;
478 
479                         aArgs.realloc( ++nArgs );
480                         aArgs[nArgs-1].Name  = OUString::createFromAscii( "Version" );
481                         aArgs[nArgs-1].Value <<= uVersion;
482                     }
483 
484                     // Retrieve the current filter
485 
486                     if ( !aFilterName.getLength() )
487                         xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
488 
489                 }
490 
491 
492                 // Convert UI filter name to internal filter name
493 
494                 if ( aFilterName.getLength() )
495                 {
496                     const SfxFilter* pFilter = SFX_APP()->GetFilterMatcher().GetFilter4UIName( aFilterName, 0, SFX_FILTER_NOTINFILEDLG );
497 
498                     if ( pFilter )
499                     {
500                         aFilterName = pFilter->GetFilterName();
501 
502                         if ( aFilterName.getLength() )
503                         {
504                             aArgs.realloc( ++nArgs );
505                             aArgs[nArgs-1].Name  = OUString::createFromAscii( "FilterName" );
506                             aArgs[nArgs-1].Value <<= aFilterName;
507                         }
508                     }
509                 }
510 
511                 if ( 1 == nFiles )
512                     OpenURL( sFiles[0], OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ), aArgs );
513                 else
514                 {
515                     OUString    aBaseDirURL = sFiles[0];
516                     if ( aBaseDirURL.getLength() > 0 && aBaseDirURL[aBaseDirURL.getLength()-1] != '/' )
517                         aBaseDirURL += OUString::createFromAscii("/");
518 
519                     int iFiles;
520                     for ( iFiles = 1; iFiles < nFiles; iFiles++ )
521                     {
522                         OUString    aURL = aBaseDirURL;
523                         aURL += sFiles[iFiles];
524                         OpenURL( aURL, OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ), aArgs );
525                     }
526                 }
527             }
528         }
529         catch ( ... )
530         {
531         }
532     }
533 
534 #ifdef WNT
535     // #103346 Destroy dialog to prevent problems with custom controls
536     // This fix is dependent on the dialog settings. Destroying the dialog here will
537     // crash the non-native dialog implementation! Therefore make this dependent on
538     // the settings.
539     if ( SvtMiscOptions().UseSystemFileDialog() )
540     {
541         delete pThis->m_pFileDlg;
542         pThis->m_pFileDlg = NULL;
543     }
544 #endif
545 
546     LeaveModalMode();
547     return 0;
548 }
549 
550 // ---------------------------------------------------------------------------
551 
552 void ShutdownIcon::addTerminateListener()
553 {
554     ShutdownIcon* pInst = getInstance();
555     if ( ! pInst)
556         return;
557 
558     if (pInst->m_bListenForTermination)
559         return;
560 
561     Reference< XDesktop > xDesktop = pInst->m_xDesktop;
562     if ( ! xDesktop.is())
563         return;
564 
565 	xDesktop->addTerminateListener( pInst );
566     pInst->m_bListenForTermination = true;
567 }
568 
569 // ---------------------------------------------------------------------------
570 
571 void ShutdownIcon::terminateDesktop()
572 {
573     ShutdownIcon* pInst = getInstance();
574     if ( ! pInst)
575         return;
576 
577     Reference< XDesktop > xDesktop = pInst->m_xDesktop;
578     if ( ! xDesktop.is())
579         return;
580 
581     // always remove ourselves as listener
582     xDesktop->removeTerminateListener( pInst );
583     pInst->m_bListenForTermination = true;
584 
585     // terminate desktop only if no tasks exist
586     Reference< XFramesSupplier > xSupplier( xDesktop, UNO_QUERY );
587     if ( xSupplier.is() )
588     {
589         Reference< XIndexAccess > xTasks ( xSupplier->getFrames(), UNO_QUERY );
590         if( xTasks.is() )
591         {
592             if( xTasks->getCount() < 1 )
593                 xDesktop->terminate();
594         }
595     }
596 
597     // remove the instance pointer
598     ShutdownIcon::pShutdownIcon = 0;
599 }
600 
601 // ---------------------------------------------------------------------------
602 
603 ShutdownIcon* ShutdownIcon::getInstance()
604 {
605 	OSL_ASSERT( pShutdownIcon );
606 	return pShutdownIcon;
607 }
608 
609 // ---------------------------------------------------------------------------
610 
611 ShutdownIcon* ShutdownIcon::createInstance()
612 {
613 	if (pShutdownIcon)
614         return pShutdownIcon;
615 
616 	ShutdownIcon *pIcon = NULL;
617 	try {
618 		Reference< XMultiServiceFactory > xSMgr( comphelper::getProcessServiceFactory() );
619 		pIcon = new ShutdownIcon( xSMgr );
620 		pIcon->init ();
621 		pShutdownIcon = pIcon;
622 	} catch (...) {
623 		delete pIcon;
624 	}
625 
626 	return pShutdownIcon;
627 }
628 
629 void ShutdownIcon::init() throw( ::com::sun::star::uno::Exception )
630 {
631 	// access resource system and sfx only protected by solarmutex
632 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
633 	ResMgr *pResMgr = SfxResId::GetResMgr();
634 
635 	::osl::ResettableMutexGuard	aGuard(	m_aMutex );
636 	m_pResMgr = pResMgr;
637 	aGuard.clear();
638 	Reference < XDesktop > xDesktop( m_xServiceManager->createInstance(
639 											 DEFINE_CONST_UNICODE( "com.sun.star.frame.Desktop" )),
640 									 UNO_QUERY );
641 	aGuard.reset();
642 	m_xDesktop = xDesktop;
643 }
644 
645 // ---------------------------------------------------------------------------
646 
647 void SAL_CALL ShutdownIcon::disposing()
648 {
649 	m_xServiceManager = Reference< XMultiServiceFactory >();
650 	m_xDesktop = Reference< XDesktop >();
651 }
652 
653 // ---------------------------------------------------------------------------
654 
655 // XEventListener
656 void SAL_CALL ShutdownIcon::disposing( const ::com::sun::star::lang::EventObject& )
657 	throw(::com::sun::star::uno::RuntimeException)
658 {
659 }
660 
661 // ---------------------------------------------------------------------------
662 
663 // XTerminateListener
664 void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
665 throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException)
666 {
667 	::osl::ClearableMutexGuard	aGuard(	m_aMutex );
668 
669 	if ( m_bVeto )
670 		throw ::com::sun::star::frame::TerminationVetoException();
671 }
672 
673 
674 // ---------------------------------------------------------------------------
675 
676 void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
677 throw(::com::sun::star::uno::RuntimeException)
678 {
679 }
680 
681 
682 // ---------------------------------------------------------------------------
683 
684 void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
685 	throw( ::com::sun::star::uno::Exception )
686 {
687 	::osl::ResettableMutexGuard	aGuard(	m_aMutex );
688 
689     // third argument only sets veto, everything else will be ignored!
690     if (aArguments.getLength() > 2)
691     {
692         sal_Bool bVeto = sal_True;
693         bVeto = ::cppu::any2bool(aArguments[2]);
694         m_bVeto = bVeto;
695         return;
696     }
697 
698 	if ( aArguments.getLength() > 0 )
699 	{
700 		if ( !ShutdownIcon::pShutdownIcon )
701 		{
702 			try
703 			{
704 				sal_Bool bQuickstart = sal_False;
705 				bQuickstart = ::cppu::any2bool( aArguments[0] );
706 				if( !bQuickstart && !GetAutostart() )
707 					return;
708                 aGuard.clear();
709 				init ();
710                 aGuard.reset();
711 				if ( !m_xDesktop.is() )
712 					return;
713 
714 				/* Create a sub-classed instance - foo */
715 				ShutdownIcon::pShutdownIcon = this;
716 				initSystray();
717 #ifdef OS2
718 				// above win32 starts the quickstart thread, but we have
719 				// quickstart running only when -quickstart is specified
720 				// on command line (next boot).
721 				// so if -quickstart was not specified, we cannot issue
722 				// quickstart veto on shutdown.
723 				if (bQuickstart)
724 				{
725 					// disable shutdown
726 					ShutdownIcon::getInstance()->SetVeto( true );
727 					ShutdownIcon::getInstance()->addTerminateListener();
728 				}
729 #endif
730 			}
731 			catch(const ::com::sun::star::lang::IllegalArgumentException&)
732 			{
733 			}
734 		}
735 	}
736     if ( aArguments.getLength() > 1 )
737     {
738 			sal_Bool bAutostart = sal_False;
739 			bAutostart = ::cppu::any2bool( aArguments[1] );
740             if (bAutostart && !GetAutostart())
741                 SetAutostart( sal_True );
742             if (!bAutostart && GetAutostart())
743                 SetAutostart( sal_False );
744     }
745 
746 }
747 
748 // -------------------------------
749 
750 void ShutdownIcon::EnterModalMode()
751 {
752 	bModalMode = sal_True;
753 }
754 
755 // -------------------------------
756 
757 void ShutdownIcon::LeaveModalMode()
758 {
759 	bModalMode = sal_False;
760 }
761 
762 #ifdef WNT
763 // defined in shutdowniconw32.cxx
764 #elif defined(OS2)
765 // defined in shutdowniconOs2.cxx
766 #elif defined QUARTZ
767 // defined in shutdowniconaqua.cxx
768 #else
769 bool ShutdownIcon::IsQuickstarterInstalled()
770 {
771 #ifndef ENABLE_QUICKSTART_APPLET
772 	return false;
773 #else // !ENABLE_QUICKSTART_APPLET
774 #ifdef UNX
775 	return LoadModule( NULL, NULL, NULL);
776 #endif // UNX
777 #endif // !ENABLE_QUICKSTART_APPLET
778 }
779 #endif // !WNT
780 
781 // ---------------------------------------------------------------------------
782 
783 #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
784 static OUString getDotAutostart( bool bCreate = false )
785 {
786 	OUString aShortcut;
787 	const char *pConfigHome;
788 	if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
789 		aShortcut = OStringToOUString( OString( pConfigHome ), RTL_TEXTENCODING_UTF8 );
790 	else
791 	{
792 		OUString aHomeURL;
793 		osl::Security().getHomeDir( aHomeURL );
794 		::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
795 		aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "/.config" ) );
796 	}
797 	aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "/autostart" ) );
798 	if (bCreate)
799 	{
800 		OUString aShortcutUrl;
801 		osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
802 		osl::Directory::createPath( aShortcutUrl );
803 	}
804 	return aShortcut;
805 }
806 #endif
807 
808 rtl::OUString ShutdownIcon::getShortcutName()
809 {
810 #ifndef ENABLE_QUICKSTART_APPLET
811 	return OUString();
812 #else
813 
814     OUString aShortcutName( RTL_CONSTASCII_USTRINGPARAM( "StarOffice 6.0" ) );
815 	ResMgr* pMgr = SfxResId::GetResMgr();
816     if( pMgr )
817     {
818         ::vos::OGuard aGuard( Application::GetSolarMutex() );
819         UniString aRes( SfxResId( STR_QUICKSTART_LNKNAME ) );
820         aShortcutName = OUString( aRes );
821     }
822 #ifdef WNT
823     aShortcutName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".lnk" ) );
824 
825 	OUString aShortcut(GetAutostartFolderNameW32());
826 	aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\" ) );
827 	aShortcut += aShortcutName;
828 #else // UNX
829 	OUString aShortcut = getDotAutostart();
830 	aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "/qstart.desktop" ) );
831 #endif // UNX
832 	return aShortcut;
833 #endif // ENABLE_QUICKSTART_APPLET
834 }
835 
836 bool ShutdownIcon::GetAutostart( )
837 {
838 #if defined(OS2)
839     return GetAutostartOs2( );
840 #elif defined QUARTZ
841     return true;
842 #else
843 	bool bRet = false;
844 #ifdef ENABLE_QUICKSTART_APPLET
845 	OUString aShortcut( getShortcutName() );
846 	OUString aShortcutUrl;
847 	osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
848 	osl::File f( aShortcutUrl );
849 	osl::File::RC error = f.open( OpenFlag_Read );
850 	if( error == osl::File::E_None )
851 	{
852 		f.close();
853 		bRet = true;
854 	}
855 #endif // ENABLE_QUICKSTART_APPLET
856     return bRet;
857 #endif
858 }
859 
860 void ShutdownIcon::SetAutostart( bool bActivate )
861 {
862 #ifdef ENABLE_QUICKSTART_APPLET
863 	OUString aShortcut( getShortcutName() );
864 
865     if( bActivate && IsQuickstarterInstalled() )
866     {
867 #ifdef WNT
868 		EnableAutostartW32( aShortcut );
869 #else // UNX
870 		getDotAutostart( true );
871 
872 		OUString aPath( RTL_CONSTASCII_USTRINGPARAM("${BRAND_BASE_DIR}/share/xdg/qstart.desktop" ) );
873 		Bootstrap::expandMacros( aPath );
874 
875 		OUString aDesktopFile;
876 		::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
877 
878 		OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
879 													 osl_getThreadTextEncoding() );
880 		OString aShortcutUnx = OUStringToOString( aShortcut,
881 												  osl_getThreadTextEncoding() );
882 		if ((0 != symlink(aDesktopFileUnx, aShortcutUnx)) && (errno == EEXIST))
883 		{
884 		unlink(aShortcutUnx);
885 		symlink(aDesktopFileUnx, aShortcutUnx);
886 		}
887 
888 		ShutdownIcon *pIcon = ShutdownIcon::createInstance();
889 		if( pIcon )
890 			pIcon->initSystray();
891 #endif // UNX
892     }
893     else
894     {
895         OUString aShortcutUrl;
896         ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
897         ::osl::File::remove( aShortcutUrl );
898 #ifdef UNX
899 		if (pShutdownIcon)
900 		{
901 		    ShutdownIcon *pIcon = getInstance();
902 			pIcon->deInitSystray();
903 		}
904 #endif
905     }
906 #elif defined OS2
907     SetAutostartOs2( bActivate );
908 #else
909     (void)bActivate; // unused variable
910 #endif // ENABLE_QUICKSTART_APPLET
911 }
912 
913 static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
914 
915 // XFastPropertySet
916 void SAL_CALL ShutdownIcon::setFastPropertyValue(       ::sal_Int32                  nHandle,
917                                                   const ::com::sun::star::uno::Any& aValue )
918     throw (::com::sun::star::beans::UnknownPropertyException,
919             ::com::sun::star::beans::PropertyVetoException,
920             ::com::sun::star::lang::IllegalArgumentException,
921             ::com::sun::star::lang::WrappedTargetException,
922             ::com::sun::star::uno::RuntimeException)
923 {
924     switch(nHandle)
925     {
926         case PROPHANDLE_TERMINATEVETOSTATE :
927              {
928                 // use new value in case it's a valid information only
929                 ::sal_Bool bState( sal_False );
930                 if (! (aValue >>= bState))
931                     return;
932 
933                 m_bVeto = bState;
934                 if (m_bVeto && ! m_bListenForTermination)
935                     addTerminateListener();
936              }
937              break;
938 
939         default :
940             throw ::com::sun::star::beans::UnknownPropertyException();
941     }
942 }
943 
944 // XFastPropertySet
945 ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
946     throw (::com::sun::star::beans::UnknownPropertyException,
947             ::com::sun::star::lang::WrappedTargetException,
948             ::com::sun::star::uno::RuntimeException)
949 {
950     ::com::sun::star::uno::Any aValue;
951     switch(nHandle)
952     {
953         case PROPHANDLE_TERMINATEVETOSTATE :
954              {
955                 bool bState   = (m_bListenForTermination && m_bVeto);
956                      aValue <<= bState;
957              }
958              break;
959 
960         default :
961             throw ::com::sun::star::beans::UnknownPropertyException();
962     }
963 
964     return aValue;
965 }
966