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