diff options
Diffstat (limited to 'desktop/source/app/app.cxx')
-rw-r--r-- | desktop/source/app/app.cxx | 3338 |
1 files changed, 3338 insertions, 0 deletions
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx new file mode 100644 index 000000000000..cf5997ea3722 --- /dev/null +++ b/desktop/source/app/app.cxx @@ -0,0 +1,3338 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <cstdlib> +#include <vector> + +#include <memory> +#include <unistd.h> +#include "app.hxx" +#include "desktop.hrc" +#include "appinit.hxx" +#include "officeipcthread.hxx" +#include "cmdlineargs.hxx" +#include "desktopresid.hxx" +#include "dispatchwatcher.hxx" +#include "configinit.hxx" +#include "lockfile.hxx" +#include "checkinstall.hxx" +#include "cmdlinehelp.hxx" +#include "userinstall.hxx" +#include "desktopcontext.hxx" +#include "exithelper.hxx" +#include "../migration/pages.hxx" + +#include <svtools/javacontext.hxx> +#include <com/sun/star/frame/XSessionManagerListener.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <com/sun/star/configuration/CorruptedConfigurationException.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XFlushable.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/configuration/MissingBootstrapFileException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/InstallationIncompleteException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/BackendAccessException.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XRestartManager.hpp> +#ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_ +#include <com/sun/star/task/XJob.hpp> +#endif +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/ui/XUIElementFactoryRegistration.hpp> +#include <com/sun/star/frame/XUIControllerRegistration.hpp> + +#include <com/sun/star/java/XJavaVM.hpp> +#include <tools/testtoolloader.hxx> +#include <tools/solar.h> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <vos/security.hxx> +#include <vos/ref.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/configurationhelper.hxx> +#ifndef _UTL__HXX_ +#include <unotools/configmgr.hxx> +#endif +#include <unotools/configitem.hxx> +#include <unotools/confignode.hxx> +#include <unotools/ucbhelper.hxx> +#include <tools/tempfile.hxx> +#include <tools/urlobj.hxx> +#include <unotools/moduleoptions.hxx> +#include <osl/module.h> +#include <osl/file.hxx> +#include <osl/signal.h> +#include <rtl/uuid.h> +#include <rtl/uri.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/languageoptions.hxx> +#include <unotools/internaloptions.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <unotools/syslocale.hxx> +#include <svl/folderrestriction.hxx> +#include <unotools/tempfile.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/instance.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/help.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/sfx.hrc> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/bootstrap.hxx> +#include <cppuhelper/bootstrap.hxx> + +#include "vos/process.hxx" + +#include <svtools/fontsubstconfig.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <svtools/apearcfg.hxx> +#include <unotools/misccfg.hxx> +#include <svtools/filter.hxx> +#include <unotools/regoptions.hxx> + +#include "langselect.hxx" + +#if defined MACOSX +#include <errno.h> +#include <sys/wait.h> +#endif + +#define DEFINE_CONST_UNICODE(CONSTASCII) UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) +#define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8) + +using namespace vos; +using namespace rtl; + +//Gives an ICE with MSVC6 +//namespace css = ::com::sun::star; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +//using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::system; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::container; + +namespace css = ::com::sun::star; + +ResMgr* desktop::Desktop::pResMgr = 0; + +namespace desktop +{ + +static SalMainPipeExchangeSignalHandler* pSignalHandler = 0; +static sal_Bool _bCrashReporterEnabled = sal_True; + +static const ::rtl::OUString CFG_PACKAGE_COMMON_HELP ( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/Help")); +static const ::rtl::OUString CFG_PATH_REG ( RTL_CONSTASCII_USTRINGPARAM( "Registration" )); +static const ::rtl::OUString CFG_ENTRY_REGURL ( RTL_CONSTASCII_USTRINGPARAM( "URL" )); +static const ::rtl::OUString CFG_ENTRY_TEMPLATEREGURL ( RTL_CONSTASCII_USTRINGPARAM( "TemplateURL" )); + +// ---------------------------------------------------------------------------- + +ResMgr* Desktop::GetDesktopResManager() +{ + if ( !Desktop::pResMgr ) + { + String aMgrName = String::CreateFromAscii( "dkt" ); + + // Create desktop resource manager and bootstrap process + // was successful. Use default way to get language specific message. + if ( Application::IsInExecute() ) + Desktop::pResMgr = ResMgr::CreateResMgr( U2S( aMgrName )); + + if ( !Desktop::pResMgr ) + { + // Use VCL to get the correct language specific message as we + // are in the bootstrap process and not able to get the installed + // language!! +/* + LanguageType aLanguageType = LANGUAGE_DONTKNOW; + + Desktop::pResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLanguageType ); + AllSettings as = GetSettings(); + as.SetUILanguage(aLanguageType); + SetSettings(as); +*/ + // LanguageSelection langselect; + OUString aUILocaleString = LanguageSelection::getLanguageString(); + sal_Int32 nIndex = 0; + OUString aLanguage = aUILocaleString.getToken( 0, '-', nIndex); + OUString aCountry = aUILocaleString.getToken( 0, '-', nIndex); + OUString aVariant = aUILocaleString.getToken( 0, '-', nIndex); + + ::com::sun::star::lang::Locale aLocale( aLanguage, aCountry, aVariant ); + + Desktop::pResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale); + AllSettings as = GetSettings(); + as.SetUILocale(aLocale); + SetSettings(as); + } + } + + return Desktop::pResMgr; +} + +// ---------------------------------------------------------------------------- +// Get a message string securely. There is a fallback string if the resource +// is not available. + +OUString Desktop::GetMsgString( USHORT nId, const OUString& aFaultBackMsg ) +{ + ResMgr* resMgr = GetDesktopResManager(); + if ( !resMgr ) + return aFaultBackMsg; + else + return OUString( String( ResId( nId, *resMgr ))); +} + +OUString MakeStartupErrorMessage(OUString const & aErrorMessage) +{ + OUStringBuffer aDiagnosticMessage( 100 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CANNOT_START, *pResMgr))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + aDiagnosticMessage.appendAscii( "\n" ); + + aDiagnosticMessage.append( aErrorMessage ); + + return aDiagnosticMessage.makeStringAndClear(); +} + +OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg ) +{ + OUStringBuffer aDiagnosticMessage( 200 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + if ( aInternalErrMsg.getLength() > 0 ) + { + aDiagnosticMessage.appendAscii( "\n\n" ); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_INTERNAL_ERRMSG, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The following internal error has occured:\n\n" ); + aDiagnosticMessage.append( aInternalErrMsg ); + } + + return aDiagnosticMessage.makeStringAndClear(); +} + +//============================================================================= +// shows a simple error box with the given message ... but exits from these process ! +// +// Fatal errors cant be solved by the process ... nor any recovery can help. +// Mostly the installation was damaged and must be repaired manually .. or by calling +// setup again. +// +// On the other side we must make sure that no further actions will be possible within +// the current office process ! No pipe requests, no menu/toolbar/shortuct actions +// are allowed. Otherwise we will force a "crash inside a crash". +// +// Thats why we have to use a special native message box here which does not use yield :-) +//============================================================================= +void FatalError(const ::rtl::OUString& sMessage) +{ + ::rtl::OUString sProductKey = ::utl::Bootstrap::getProductKey(); + if ( ! sProductKey.getLength()) + { + ::vos::OStartupInfo aInfo; + aInfo.getExecutableFile( sProductKey ); + + ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/'); + if ( nLastIndex > 0 ) + sProductKey = sProductKey.copy( nLastIndex+1 ); + } + + ::rtl::OUStringBuffer sTitle (128); + sTitle.append (sProductKey ); + sTitle.appendAscii (" - Fatal Error"); + + Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage); + _exit(ExitHelper::E_FATAL_ERROR); +} + +static bool ShouldSuppressUI(CommandLineArgs* pCmdLine) +{ + return pCmdLine->IsInvisible() || + pCmdLine->IsHeadless() || + pCmdLine->IsQuickstart(); +} + +CommandLineArgs* Desktop::GetCommandLineArgs() +{ + static CommandLineArgs* pArgs = 0; + if ( !pArgs ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pArgs ) + { + pArgs = new CommandLineArgs; + } + } + + return pArgs; +} + +sal_Bool InitConfiguration() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jb99855) ::InitConfiguration" ); + + Reference< XMultiServiceFactory > xProvider( CreateApplicationConfigurationProvider( ) ); + return xProvider.is(); +} + +namespace +{ + struct BrandName + : public rtl::Static< String, BrandName > {}; + struct Version + : public rtl::Static< String, Version > {}; + struct AboutBoxVersion + : public rtl::Static< String, AboutBoxVersion > {}; + struct OOOVendor + : public rtl::Static< String, OOOVendor > {}; + struct Extension + : public rtl::Static< String, Extension > {}; + struct XMLFileFormatName + : public rtl::Static< String, XMLFileFormatName > {}; + struct XMLFileFormatVersion + : public rtl::Static< String, XMLFileFormatVersion > {}; + struct WriterCompatibilityVersionOOo11 + : public rtl::Static< String, WriterCompatibilityVersionOOo11 > {}; +} + +void ReplaceStringHookProc( UniString& rStr ) +{ + static int nAll = 0, nPro = 0; + + nAll++; + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + String &rBrandName = BrandName::get(); + String &rVersion = Version::get(); + String &rAboutBoxVersion = AboutBoxVersion::get(); + String &rExtension = Extension::get(); + String &rXMLFileFormatName = XMLFileFormatName::get(); + String &rXMLFileFormatVersion = XMLFileFormatVersion::get(); + + if ( !rBrandName.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aTmp; + rBrandName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATNAME ); + aRet >>= aTmp; + rXMLFileFormatName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATVERSION ); + aRet >>= aTmp; + rXMLFileFormatVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION ); + aRet >>= aTmp; + rVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION ); + aRet >>= aTmp; + rAboutBoxVersion = aTmp; + + if ( !rExtension.Len() ) + { + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION ); + aRet >>= aTmp; + rExtension = aTmp; + } + } + + nPro++; + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rBrandName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion ); + } + if ( rStr.SearchAscii( "%OOOVENDOR" ) != STRING_NOTFOUND ) + { + String &rOOOVendor = OOOVendor::get(); + + if ( !rOOOVendor.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::OOOVENDOR ); + aRet >>= aTmp; + rOOOVendor = aTmp; + + } + rStr.SearchAndReplaceAllAscii( "%OOOVENDOR" ,rOOOVendor ); + } + + if ( rStr.SearchAscii( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != STRING_NOTFOUND ) + { + String &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get(); + if ( !rWriterCompatibilityVersionOOo11.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::WRITERCOMPATIBILITYVERSIONOOO11 ); + aRet >>= aTmp; + rWriterCompatibilityVersionOOo11 = aTmp; + } + + rStr.SearchAndReplaceAllAscii( "%WRITERCOMPATIBILITYVERSIONOOO11", + rWriterCompatibilityVersionOOo11 ); + } +} + +static const char pLastSyncFileName[] = "lastsynchronized"; +static const sal_Int32 nStrLenLastSync = 16; + +static bool needsSynchronization( + ::rtl::OUString const & baseSynchronizedURL, ::rtl::OUString const & userSynchronizedURL ) +{ + bool bNeedsSync( false ); + + ::osl::DirectoryItem itemUserFile; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(userSynchronizedURL, itemUserFile); + + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return true; + } + else if (err1 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access lastsynchronized in user layer"); + return true; //sync just in case + } + + //If last synchronized does not exist in base layer, then do nothing + ::osl::DirectoryItem itemBaseFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(baseSynchronizedURL, itemBaseFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access file lastsynchronized in base layer"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + ::osl::FileStatus statUser(FileStatusMask_ModifyTime); + ::osl::FileStatus statBase(FileStatusMask_ModifyTime); + if (itemUserFile.getFileStatus(statUser) == ::osl::File::E_None) + { + if (itemBaseFile.getFileStatus(statBase) == ::osl::File::E_None) + { + TimeValue timeUser = statUser.getModifyTime(); + TimeValue timeBase = statBase.getModifyTime(); + + if (timeUser.Seconds < timeBase.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + + return bNeedsSync; +} + +static ::rtl::OUString getBrandSharePreregBundledPathURL() +{ + ::rtl::OUString url( + RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/prereg/bundled")); + + ::rtl::Bootstrap::expandMacros(url); + return url; +} + +static ::rtl::OUString getUserBundledExtPathURL() +{ + ::rtl::OUString folder( RTL_CONSTASCII_USTRINGPARAM( "$BUNDLED_EXTENSIONS_USER" )); + ::rtl::Bootstrap::expandMacros(folder); + + return folder; +} + +static ::rtl::OUString getLastSyncFileURLFromBrandInstallation() +{ + ::rtl::OUString aURL = getBrandSharePreregBundledPathURL(); + ::sal_Int32 nLastIndex = aURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aURL ); + + if ( nLastIndex != aURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} + +static ::rtl::OUString getLastSyncFileURLFromUserInstallation() +{ + ::rtl::OUString aUserBundledPathURL = getUserBundledExtPathURL(); + ::sal_Int32 nLastIndex = aUserBundledPathURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aUserBundledPathURL ); + + if ( nLastIndex != aUserBundledPathURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} + +static osl::FileBase::RC copy_bundled_recursive( + const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Int32 TypeToCopy ) +throw() +{ + osl::FileBase::RC err = osl::FileBase::E_None; + + if( TypeToCopy == -1 ) // Document + { + err = osl::File::copy( srcUnqPath,dstUnqPath ); + } + else if( TypeToCopy == +1 ) // Folder + { + osl::Directory aDir( srcUnqPath ); + aDir.open(); + + err = osl::Directory::create( dstUnqPath ); + osl::FileBase::RC next = err; + if( err == osl::FileBase::E_None || + err == osl::FileBase::E_EXIST ) + { + err = osl::FileBase::E_None; + sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type; + + osl::DirectoryItem aDirItem; + + while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) + { + sal_Bool IsDoc = false; + sal_Bool bFilter = false; + osl::FileStatus aFileStatus( n_Mask ); + aDirItem.getFileStatus( aFileStatus ); + if( aFileStatus.isValid( FileStatusMask_Type ) ) + IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; + + // Getting the information for the next recursive copy + sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; + + rtl::OUString newSrcUnqPath; + if( aFileStatus.isValid( FileStatusMask_FileURL ) ) + newSrcUnqPath = aFileStatus.getFileURL(); + + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString tit; + if( aFileStatus.isValid( FileStatusMask_FileName ) ) + { + ::rtl::OUString aFileName = aFileStatus.getFileName(); + tit = rtl::Uri::encode( aFileName, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + + // Special treatment for "lastsychronized" file. Must not be + // copied from the bundled folder! + if ( IsDoc && aFileName.equalsAscii( pLastSyncFileName )) + bFilter = true; + } + + if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) + newDstUnqPath += rtl::OUString::createFromAscii( "/" ); + + newDstUnqPath += tit; + + if (( newSrcUnqPath != dstUnqPath ) && !bFilter ) + err = copy_bundled_recursive( newSrcUnqPath,newDstUnqPath, newTypeToCopy ); + } + + if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) + err = next; + } + aDir.close(); + } + + return err; +} + +Desktop::Desktop() +: m_bServicesRegistered( false ) +, m_aBootstrapError( BE_OK ) +, m_pLockfile( NULL ) +{ + RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" ); +} + +Desktop::~Desktop() +{ +} + +void Desktop::Init() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" ); + SetBootstrapStatus(BS_OK); + + // Check for lastsynchronized file for bundled extensions in the user directory + // and test if synchronzation is necessary! + { + ::rtl::OUString aUserLastSyncFilePathURL = getLastSyncFileURLFromUserInstallation(); + ::rtl::OUString aPreregSyncFilePathURL = getLastSyncFileURLFromBrandInstallation(); + + if ( needsSynchronization( aPreregSyncFilePathURL, aUserLastSyncFilePathURL )) + { + rtl::OUString aUserPath = getUserBundledExtPathURL(); + rtl::OUString aPreregBundledPath = getBrandSharePreregBundledPathURL(); + + // copy bundled folder to the user directory + osl::FileBase::RC rc = osl::Directory::createPath(aUserPath); + (void) rc; + copy_bundled_recursive( aPreregBundledPath, aUserPath, +1 ); + } + } + + // create service factory... + Reference < XMultiServiceFactory > rSMgr = CreateApplicationServiceManager(); + if( rSMgr.is() ) + { + ::comphelper::setProcessServiceFactory( rSMgr ); + } + else + { + SetBootstrapError( BE_UNO_SERVICEMANAGER ); + } + + if ( GetBootstrapError() == BE_OK ) + { + // prepare language + if ( !LanguageSelection::prepareLanguage() ) + { + if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE ) + SetBootstrapError( BE_LANGUAGE_MISSING ); + else + SetBootstrapError( BE_OFFICECONFIG_BROKEN ); + } + } + + if ( GetBootstrapError() == BE_OK ) + { + CommandLineArgs* pCmdLineArgs = GetCommandLineArgs(); +#ifdef UNX + // check whether we need to print cmdline help + if ( pCmdLineArgs->IsHelp() ) { + displayCmdlineHelp(); + SetBootstrapStatus(BS_TERMINATE); + } +#endif + // start ipc thread only for non-remote offices + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" ); + OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread(); + if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR ) + { + SetBootstrapError( BE_PATHINFO_MISSING ); + } + else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE ) + { + // 2nd office startup should terminate after sending cmdlineargs through pipe + SetBootstrapStatus(BS_TERMINATE); + } + else if ( pCmdLineArgs->IsHelp() ) + { + // disable IPC thread in an instance that is just showing a help message + OfficeIPCThread::DisableOfficeIPCThread(); + } + pSignalHandler = new SalMainPipeExchangeSignalHandler; + } +} + +void Desktop::DeInit() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::DeInit" ); + + try { + // instead of removing of the configManager just let it commit all the changes + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + FlushConfiguration(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + + // close splashscreen if it's still open + CloseSplashScreen(); + Reference<XMultiServiceFactory> xXMultiServiceFactory(::comphelper::getProcessServiceFactory()); + DestroyApplicationServiceManager( xXMultiServiceFactory ); + // nobody should get a destroyd service factory... + ::comphelper::setProcessServiceFactory( NULL ); + + // clear lockfile + if (m_pLockfile != NULL) + m_pLockfile->clean(); + + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + DELETEZ( pSignalHandler ); + } catch (RuntimeException&) { + // someone threw an exception during shutdown + // this will leave some garbage behind.. + } + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::DeInit" ); +} + +BOOL Desktop::QueryExit() +{ + try + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + } + catch ( RuntimeException& ) + { + } + + const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto"; + + Reference< ::com::sun::star::frame::XDesktop > + xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + + Reference < ::com::sun::star::beans::XPropertySet > xPropertySet( xDesktop, UNO_QUERY ); + if ( xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_True; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + + BOOL bExit = ( !xDesktop.is() || xDesktop->terminate() ); + + + if ( !bExit && xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_False; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + else + { + FlushConfiguration(); + try + { + // it is no problem to call DisableOfficeIPCThread() more than once + // it also looks to be threadsafe + OfficeIPCThread::DisableOfficeIPCThread(); + } + catch ( RuntimeException& ) + { + } + + if (m_pLockfile != NULL) m_pLockfile->clean(); + } + + return bExit; +} + +void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage ) +{ + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + sal_Bool bWorkstationInstallation = sal_False; + ::rtl::OUString aBaseInstallURL; + ::rtl::OUString aUserInstallURL; + ::rtl::OUString aProductKey; + ::rtl::OUString aTemp; + ::vos::OStartupInfo aInfo; + + aInfo.getExecutableFile( aProductKey ); + sal_uInt32 lastIndex = aProductKey.lastIndexOf('/'); + if ( lastIndex > 0 ) + aProductKey = aProductKey.copy( lastIndex+1 ); + + aTemp = ::utl::Bootstrap::getProductKey( aProductKey ); + if ( aTemp.getLength() > 0 ) + aProductKey = aTemp; + + ::utl::Bootstrap::PathStatus aBaseInstallStatus = ::utl::Bootstrap::locateBaseInstallation( aBaseInstallURL ); + ::utl::Bootstrap::PathStatus aUserInstallStatus = ::utl::Bootstrap::locateUserInstallation( aUserInstallURL ); + + if (( aBaseInstallStatus == ::utl::Bootstrap::PATH_EXISTS && + aUserInstallStatus == ::utl::Bootstrap::PATH_EXISTS )) + { + if ( aBaseInstallURL != aUserInstallURL ) + bWorkstationInstallation = sal_True; + } + + OUString aMessage; + OUStringBuffer aBuffer( 100 ); + aBuffer.append( aDiagnosticMessage ); + + aBuffer.appendAscii( "\n" ); + + ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage ); + aBootstrapFailedBox.SetText( aProductKey ); + aBootstrapFailedBox.Execute(); + } +} + +// Create a error message depending on bootstrap failure code and an optional file url +::rtl::OUString Desktop::CreateErrorMsgString( + utl::Bootstrap::FailureCode nFailureCode, + const ::rtl::OUString& aFileURL ) +{ + OUString aMsg; + OUString aFilePath; + sal_Bool bFileInfo = sal_True; + + switch ( nFailureCode ) + { + /// the shared installation directory could not be located + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The installation path is not available." )) ); + bFileInfo = sal_False; + } + break; + + /// the bootstrap INI file could not be found or read + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is corrupt." )) ); + } + break; + + /// the version locator INI file could not be found or read + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the version locator INI has no entry for this version + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The main configuration file \"$1\" does not support the current version." )) ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration directory \"$1\" is missing." )) ); + } + break; + + /// some bootstrap data was invalid in unexpected ways + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "An internal failure occurred." )) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + { + // This needs to be improved, see #i67575#: + aMsg = OUString( + RTL_CONSTASCII_USTRINGPARAM( "Invalid version file entry" ) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + if ( bFileInfo ) + { + String aMsgString( aMsg ); + + osl::File::getSystemPathFromFileURL( aFileURL, aFilePath ); + + aMsgString.SearchAndReplaceAscii( "$1", aFilePath ); + aMsg = aMsgString; + } + + return MakeStartupErrorMessage( aMsg ); +} + +void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError ) +{ + if ( aBootstrapError == BE_PATHINFO_MISSING ) + { + OUString aErrorMsg; + OUString aBuffer; + utl::Bootstrap::Status aBootstrapStatus; + utl::Bootstrap::FailureCode nFailureCode; + + aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode ); + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + switch ( nFailureCode ) + { + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() ); + } + break; + + /// the bootstrap INI file could not be found or read + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + OUString aBootstrapFileURL; + + utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL ); + } + break; + + /// the version locator INI file could not be found or read + /// the version locator INI has no entry for this version + /// the version locator INI entry is not a valid directory URL + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + OUString aVersionFileURL; + + utl::Bootstrap::locateVersionFile( aVersionFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + OUString aUserInstallationURL; + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL ); + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg ); + } + } + else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING ) + { + // Uno service manager is not available. VCL needs a uno service manager to display a message box!!! + // Currently we are not able to display a message box with a service manager due to this limitations inside VCL. + + // When UNO is not properly initialized, all kinds of things can fail + // and cause the process to crash (e.g., a call to GetMsgString may + // crash when somewhere deep within that call Any::operator <= is used + // with a PropertyValue, and no binary UNO type description for + // PropertyValue is available). To give the user a hint even if + // generating and displaying a message box below crashes, print a + // hard-coded message on stderr first: + fputs( + aBootstrapError == BE_UNO_SERVICEMANAGER + ? ("The application cannot be started. " "\n" + "The component manager is not available." "\n") + // STR_BOOTSTRAP_ERR_CANNOT_START, STR_BOOTSTRAP_ERR_NO_SERVICE + : ("The application cannot be started. " "\n" + "The configuration service is not available." "\n"), + // STR_BOOTSTRAP_ERR_CANNOT_START, + // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE + stderr); + + // First sentence. We cannot bootstrap office further! + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + + OUString aErrorMsg; + + if ( aBootstrapError == BE_UNO_SERVICEMANAGER ) + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The service manager is not available." )) ); + else + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration service is not available." )) ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.appendAscii( "\n" ); + + // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to + // repair the installation with the setup executable besides the office executable. Now + // we have to ask the user to start the setup on CD/installation directory manually!! + OUString aStartSetupManually( GetMsgString( + STR_ASK_START_SETUP_MANUALLY, + OUString( RTL_CONSTASCII_USTRINGPARAM( "Start setup application to repair the installation from CD, or the folder containing the installation packages." )) )); + + aDiagnosticMessage.append( aStartSetupManually ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + + FatalError( aMessage); + } + else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "A general error occurred while accessing your central configuration." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_USERINSTALL_FAILED ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "User installation could not be completed" )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_LANGUAGE_MISSING ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( + //@@@ FIXME: should use an own resource string => #i36213# + STR_BOOTSTRAP_ERR_LANGUAGE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Language could not be determined." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) || + ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS )) + { + OUString aUserInstallationURL; + OUString aUserInstallationPath; + OUString aMessage; + OUString aErrorMsg; + OUStringBuffer aDiagnosticMessage( 100 ); + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + + if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be completed due to insufficient free disk space." )) ); + else + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOACCESSRIGHTS, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be processed due to missing access rights." )) ); + + osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.append( aUserInstallationPath ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + + return; +} + + +void Desktop::retrieveCrashReporterState() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_CRASHREPORTER = ::rtl::OUString::createFromAscii("CrashReporter" ); + static const ::rtl::OUString CFG_ENTRY_ENABLED = ::rtl::OUString::createFromAscii("Enabled" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bEnabled( sal_True ); + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_CRASHREPORTER, + CFG_ENTRY_ENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bEnabled; + } + _bCrashReporterEnabled = bEnabled; +} + +sal_Bool Desktop::isUIOnSessionShutdownAllowed() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_SESSION = ::rtl::OUString::createFromAscii("SessionShutdown" ); + static const ::rtl::OUString CFG_ENTRY_UIENABLED = ::rtl::OUString::createFromAscii("DocumentStoreUIEnabled" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bResult = sal_False; + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_SESSION, + CFG_ENTRY_UIENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bResult; + } + + return bResult; +} + +//----------------------------------------------- +/** @short check if crash reporter feature is enabled or + disabled. +*/ +sal_Bool Desktop::isCrashReporterEnabled() +{ + return _bCrashReporterEnabled; +} + +//----------------------------------------------- +/** @short check if recovery must be started or not. + + @param bCrashed [boolean ... out!] + the office crashed last times. + But may be there are no recovery data. + Usefull to trigger the error report tool without + showing the recovery UI. + + @param bRecoveryDataExists [boolean ... out!] + there exists some recovery data. + + @param bSessionDataExists [boolean ... out!] + there exists some session data. + Because the user may be logged out last time from it's + unix session... +*/ +void impl_checkRecoveryState(sal_Bool& bCrashed , + sal_Bool& bRecoveryDataExists, + sal_Bool& bSessionDataExists ) +{ + static const ::rtl::OUString SERVICENAME_RECOVERYCORE = ::rtl::OUString::createFromAscii("com.sun.star.frame.AutoRecovery"); + static const ::rtl::OUString PROP_CRASHED = ::rtl::OUString::createFromAscii("Crashed" ); + static const ::rtl::OUString PROP_EXISTSRECOVERY = ::rtl::OUString::createFromAscii("ExistsRecoveryData" ); + static const ::rtl::OUString PROP_EXISTSSESSION = ::rtl::OUString::createFromAscii("ExistsSessionData" ); + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_RECOVERYINFO = ::rtl::OUString::createFromAscii("RecoveryInfo" ); + + bCrashed = sal_False; + bRecoveryDataExists = sal_False; + bSessionDataExists = sal_False; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + try + { + css::uno::Reference< css::beans::XPropertySet > xRecovery( + xSMGR->createInstance(SERVICENAME_RECOVERYCORE), + css::uno::UNO_QUERY_THROW); + + xRecovery->getPropertyValue(PROP_CRASHED ) >>= bCrashed ; + xRecovery->getPropertyValue(PROP_EXISTSRECOVERY) >>= bRecoveryDataExists; + xRecovery->getPropertyValue(PROP_EXISTSSESSION ) >>= bSessionDataExists ; + } + catch(const css::uno::Exception&) {} +} + +//----------------------------------------------- +/* @short start the recovery wizard. + + @param bEmergencySave + differs between EMERGENCY_SAVE and RECOVERY +*/ +sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave , + sal_Bool bCrashed , + sal_Bool bExistsRecoveryData) +{ + static ::rtl::OUString SERVICENAME_RECOVERYUI = ::rtl::OUString::createFromAscii("com.sun.star.comp.svx.RecoveryUI" ); + static ::rtl::OUString SERVICENAME_URLPARSER = ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" ); + static ::rtl::OUString COMMAND_EMERGENCYSAVE = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doEmergencySave"); + static ::rtl::OUString COMMAND_RECOVERY = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doAutoRecovery" ); + static ::rtl::OUString COMMAND_CRASHREPORT = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doCrashReport" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + css::uno::Reference< css::frame::XSynchronousDispatch > xRecoveryUI( + xSMGR->createInstance(SERVICENAME_RECOVERYUI), + css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::util::XURLTransformer > xURLParser( + xSMGR->createInstance(SERVICENAME_URLPARSER), + css::uno::UNO_QUERY_THROW); + + css::util::URL aURL; + if (bEmergencySave) + aURL.Complete = COMMAND_EMERGENCYSAVE; + else + { + if (bExistsRecoveryData) + aURL.Complete = COMMAND_RECOVERY; + else + if (bCrashed && Desktop::isCrashReporterEnabled() ) + aURL.Complete = COMMAND_CRASHREPORT; + } + + sal_Bool bRet = sal_False; + if ( aURL.Complete.getLength() > 0 ) + { + xURLParser->parseStrict(aURL); + + css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >()); + aRet >>= bRet; + } + return bRet; +} + +/* + * Save all open documents so they will be reopened + * the next time the application ist started + * + * returns sal_True if at least one document could be saved... + * + */ + +sal_Bool Desktop::_bTasksSaved = sal_False; + +sal_Bool Desktop::SaveTasks() +{ + return impl_callRecoveryUI( + sal_True , // sal_True => force emergency save + sal_False, // 2. and 3. param not used if 1. = true! + sal_False); +} + +namespace { + +void restartOnMac(bool passArguments) { +#if defined MACOSX + OfficeIPCThread::DisableOfficeIPCThread(); + rtl::OUString execUrl; + OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None); + rtl::OUString execPath; + rtl::OString execPath8; + if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath) + != osl::FileBase::E_None) || + !execPath.convertToString( + &execPath8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + std::vector< rtl::OString > args; + args.push_back(execPath8); + bool wait = false; + if (passArguments) { + sal_uInt32 n = osl_getCommandArgCount(); + for (sal_uInt32 i = 0; i < n; ++i) { + rtl::OUString arg; + OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None); + if (arg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-accept="))) { + wait = true; + } + rtl::OString arg8; + if (!arg.convertToString( + &arg8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + args.push_back(arg8); + } + } + std::vector< char const * > argPtrs; + for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end(); + ++i) + { + argPtrs.push_back(i->getStr()); + } + argPtrs.push_back(0); + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6 + pid_t pid = fork(); + if (pid == 0) { + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + } else if (pid > 0) { + // Two simultaneously running soffice processes lead to two dock + // icons, so avoid waiting here unless it must be assumed that the + // process invoking soffice itself wants to wait for soffice to + // finish: + if (!wait) { + return; + } + int stat; + if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) { + _exit(WEXITSTATUS(stat)); + } + } + } + std::abort(); +#else + (void) passArguments; // avoid warnings +#endif +} + +} + +USHORT Desktop::Exception(USHORT nError) +{ + // protect against recursive calls + static BOOL bInException = FALSE; + + sal_uInt16 nOldMode = Application::GetSystemWindowMode(); + Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE ); + Application::SetDefDialogParent( NULL ); + + if ( bInException ) + { + String aDoubleExceptionString; + Application::Abort( aDoubleExceptionString ); + } + + bInException = TRUE; + CommandLineArgs* pArgs = GetCommandLineArgs(); + + // save all modified documents ... if it's allowed doing so. + sal_Bool bRestart = sal_False; + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !pArgs->IsNoRestore() ) && // some use cases of office must work without recovery + ( !pArgs->IsHeadless() ) && + ( !pArgs->IsServer() ) && + (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash + ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...) + ); + if ( bAllowRecoveryAndSessionManagement ) + bRestart = SaveTasks(); + + FlushConfiguration(); + + switch( nError & EXC_MAJORTYPE ) + { + case EXC_RSCNOTLOADED: + { + String aResExceptionString; + Application::Abort( aResExceptionString ); + break; + } + + case EXC_SYSOBJNOTCREATED: + { + String aSysResExceptionString; + Application::Abort( aSysResExceptionString ); + break; + } + + default: + { + if (m_pLockfile != NULL) { + m_pLockfile->clean(); + } + if( bRestart ) + { + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + DELETEZ( pSignalHandler ); + restartOnMac(false); + _exit( ExitHelper::E_CRASH_WITH_RESTART ); + } + else + { + Application::Abort( String() ); + } + + break; + } + } + + OSL_ASSERT(false); // unreachable + return 0; +} + +void Desktop::AppEvent( const ApplicationEvent& rAppEvent ) +{ + HandleAppEvent( rAppEvent ); +} + +void Desktop::Main() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Main" ); + + // Remember current context object + com::sun::star::uno::ContextLayer layer( + com::sun::star::uno::getCurrentContext() ); + + BootstrapError eError = GetBootstrapError(); + if ( eError != BE_OK ) + { + HandleBootstrapErrors( eError ); + return; + } + + BootstrapStatus eStatus = GetBootstrapStatus(); + if (eStatus == BS_TERMINATE) { + return; + } + + // Detect desktop environment - need to do this as early as possible + com::sun::star::uno::setCurrentContext( + new DesktopContext( com::sun::star::uno::getCurrentContext() ) ); + + CommandLineArgs* pCmdLineArgs = GetCommandLineArgs(); + + // setup configuration error handling + ConfigurationErrorHandler aConfigErrHandler; + if (!ShouldSuppressUI(pCmdLineArgs)) + aConfigErrHandler.activate(); + + ResMgr::SetReadStringHook( ReplaceStringHookProc ); + + // Startup screen + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main { OpenSplashScreen" ); + OpenSplashScreen(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" ); + + { + UserInstall::UserInstallError instErr_fin = UserInstall::finalize(); + if ( instErr_fin != UserInstall::E_None) + { + OSL_ENSURE(sal_False, "userinstall failed"); + if ( instErr_fin == UserInstall::E_NoDiskSpace ) + HandleBootstrapErrors( BE_USERINSTALL_NOTENOUGHDISKSPACE ); + else if ( instErr_fin == UserInstall::E_NoWriteAccess ) + HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS ); + else + HandleBootstrapErrors( BE_USERINSTALL_FAILED ); + return; + } + // refresh path information + utl::Bootstrap::reloadData(); + SetSplashScreenProgress(25); + } + + Reference< XMultiServiceFactory > xSMgr = + ::comphelper::getProcessServiceFactory(); + + std::auto_ptr<SvtLanguageOptions> pLanguageOptions; + std::auto_ptr<SvtPathOptions> pPathOptions; + + Reference< ::com::sun::star::task::XRestartManager > xRestartManager; + sal_Bool bRestartRequested( sal_False ); + sal_Bool bUseSystemFileDialog(sal_True); + int nAcquireCount( 0 ); + Reference < css::document::XEventListener > xGlobalBroadcaster; + try + { + RegisterServices( xSMgr ); + + //SetSplashScreenProgress(15); + +#ifndef UNX + if ( pCmdLineArgs->IsHelp() ) { + displayCmdlineHelp(); + return; + } +#endif + + // check user installation directory for lockfile so we can be sure + // there is no other instance using our data files from a remote host + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main -> Lockfile" ); + m_pLockfile = new Lockfile; + if ( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoLockcheck() && !m_pLockfile->check( Lockfile_execWarning )) { + // Lockfile exists, and user clicked 'no' + return; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main <- Lockfile" ); + + // check if accessibility is enabled but not working and allow to quit + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ GetEnableATToolSupport" ); + if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() ) + { + BOOL bQuitApp; + + if( !InitAccessBridge( true, bQuitApp ) ) + if( bQuitApp ) + return; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} GetEnableATToolSupport" ); + + // terminate if requested... + if( pCmdLineArgs->IsTerminateAfterInit() ) return; + + + // Read the common configuration items for optimization purpose + if ( !InitializeConfiguration() ) return; + + //SetSplashScreenProgress(20); + + // set static variable to enabled/disable crash reporter + retrieveCrashReporterState(); + if ( !isCrashReporterEnabled() ) + { + osl_setErrorReporting( sal_False ); + // disable stack trace feature + } + + // create title string + sal_Bool bCheckOk = sal_False; + ::com::sun::star::lang::Locale aLocale; + String aMgrName = String::CreateFromAscii( "iso" ); + ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale ); + if ( !pLabelResMgr ) + { + // no "iso" resource -> search for "ooo" resource + aMgrName = String::CreateFromAscii( "ooo" ); + pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale); + } + String aTitle = pLabelResMgr ? String( ResId( RID_APPTITLE, *pLabelResMgr ) ) : String(); + delete pLabelResMgr; +/* + // locale and UI locale in AppSettings are now retrieved from configuration or system directly via SvtSysLocale + // no reason to set while starting + // set UI language and locale + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ set locale settings" ); + //LanguageSelection langselect; + OUString aUILocaleString = LanguageSelection::getLanguageString(); + Locale aUILocale = LanguageSelection::IsoStringToLocale(aUILocaleString); + LanguageType eLanguage = SvtSysLocale().GetLanguage(); + + // #i39040#, do not call anything between GetSettings and SetSettings that might have + // a side effect on the settings (like, eg, SvtSysLocaleOptions().GetLocaleLanguageType(), + // which changes the MiscSettings !!! ) + AllSettings aSettings( Application::GetSettings() ); + aSettings.SetUILocale( aUILocale ); + aSettings.SetLanguage( eLanguage ); + Application::SetSettings( aSettings ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} set locale settings" ); +*/ + + // Check for StarOffice/Suite specific extensions runs also with OpenOffice installation sets + OUString aTitleString( aTitle ); + bCheckOk = CheckInstallation( aTitleString ); + if ( !bCheckOk ) + return; + else + aTitle = aTitleString; + +#ifdef DBG_UTIL + //include version ID in non product builds + ::rtl::OUString aDefault; + aTitle += DEFINE_CONST_UNICODE(" ["); + String aVerId( utl::Bootstrap::getBuildIdData( aDefault )); + aTitle += aVerId; + aTitle += ']'; +#endif + + SetDisplayName( aTitle ); +// SetSplashScreenProgress(30); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" ); + pPathOptions.reset( new SvtPathOptions); +// SetSplashScreenProgress(40); +// pLanguageOptions = new SvtLanguageOptions(sal_True); +// SetSplashScreenProgress(45); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" ); + + // Check special env variable #111015# + std::vector< String > aUnrestrictedFolders; + svt::getUnrestrictedFolders( aUnrestrictedFolders ); + + if ( aUnrestrictedFolders.size() > 0 ) + { + // Set different working directory. The first entry is + // the new work path. + String aWorkPath = aUnrestrictedFolders[0]; + SvtPathOptions().SetWorkPath( aWorkPath ); + } + + // create service for loadin SFX (still needed in startup) + xGlobalBroadcaster = Reference < css::document::XEventListener > + ( xSMgr->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.GlobalEventBroadcaster" ) ), UNO_QUERY ); + + /* ensure existance of a default window that messages can be dispatched to + This is for the benefit of testtool which uses PostUserEvent extensively + and else can deadlock while creating this window from another tread while + the main thread is not yet in the event loop. + */ + Application::GetDefaultDevice(); + + // initialize test-tool library (if available) + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ tools::InitTestToolLib" ); + tools::InitTestToolLib(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} tools::InitTestToolLib" ); + + // Check if bundled or shared extensions were added /removed + // and process those extensions (has to be done before checking + // the extension dependencies! + SynchronizeExtensionRepositories(); + bool bAbort = CheckExtensionDependencies(); + if ( bAbort ) + return; + // First Start Wizard allowed ? + if ( ! pCmdLineArgs->IsNoFirstStartWizard()) + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ FirstStartWizard" ); + + if (IsFirstStartWizardNeeded()) + { + ::utl::RegOptions().removeReminder(); // remove patch registration reminder + Reference< XJob > xFirstStartJob( xSMgr->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.comp.desktop.FirstStart" ) ), UNO_QUERY ); + if (xFirstStartJob.is()) + { + sal_Bool bDone = sal_False; + Sequence< NamedValue > lArgs(2); + lArgs[0].Name = ::rtl::OUString::createFromAscii("LicenseNeedsAcceptance"); + lArgs[0].Value <<= LicenseNeedsAcceptance(); + lArgs[1].Name = ::rtl::OUString::createFromAscii("LicensePath"); + lArgs[1].Value <<= GetLicensePath(); + + xFirstStartJob->execute(lArgs) >>= bDone; + if ( !bDone ) + { + return; + } + } + } + else if ( RegistrationPage::hasReminderDateCome() ) + RegistrationPage::executeSingleMode(); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} FirstStartWizard" ); + } + + // keep a language options instance... + pLanguageOptions.reset( new SvtLanguageOptions(sal_True)); + + if (xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString::createFromAscii("OnStartApp"); + xGlobalBroadcaster->notifyEvent(aEvent); + } + + SetSplashScreenProgress(50); + // Backing Component + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ impl_checkRecoveryState" ); + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} impl_checkRecoveryState" ); + + { + ::comphelper::ComponentContext aContext( xSMgr ); + xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY ); + } + + // check whether the shutdown is caused by restart + bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( pCmdLineArgs->IsHeadless() ) + { + // Ensure that we use not the system file dialogs as + // headless mode relies on Application::EnableHeadlessMode() + // which does only work for VCL dialogs!! + SvtMiscOptions aMiscOptions; + bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog(); + aMiscOptions.SetUseSystemFileDialog( sal_False ); + } + + if ( !bRestartRequested ) + { + if ( + (pCmdLineArgs->IsEmptyOrAcceptOnly() ) && + (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) && + (!bExistsRecoveryData ) && + (!bExistsSessionData ) && + (!Application::AnyInput( INPUT_APPEVENT ) ) + ) + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create BackingComponent" ); + Reference< XFrame > xDesktopFrame( xSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); + if (xDesktopFrame.is()) + { + // SetSplashScreenProgress(60); + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank" + // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior, + // otherwise documents loaded into this frame will later on miss functionality depending on the style. + Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ); + OSL_ENSURE( pContainerWindow, "Desktop::Main: no implementation access to the frame's container window!" ); + pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT ); + + SetSplashScreenProgress(75); + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + + Reference< XController > xBackingComp( + xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), + UNO_QUERY); + // SetSplashScreenProgress(80); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + SetSplashScreenProgress(100); + xBackingComp->attachFrame(xBackingFrame); + CloseSplashScreen(); + xContainerWindow->setVisible(sal_True); + } + } + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create BackingComponent" ); + } + } + } + catch ( com::sun::star::lang::WrappedTargetException& wte ) + { + com::sun::star::uno::Exception te; + wte.TargetException >>= te; + FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) ); + return; + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return; + } + /* + catch ( ... ) + { + FatalError( MakeStartupErrorMessage( + OUString::createFromAscii( + "Unknown error during startup (Office wrapper service).\nInstallation could be damaged."))); + return; + } + */ +// SetSplashScreenProgress(55); + + SvtFontSubstConfig().Apply(); + + SvtTabAppearanceCfg aAppearanceCfg; + aAppearanceCfg.SetInitialized(); + aAppearanceCfg.SetApplicationDefaults( this ); + SvtAccessibilityOptions aOptions; + aOptions.SetVCLSettings(); +// SetSplashScreenProgress(60); + + if ( !bRestartRequested ) + { + Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) ); + + sal_Bool bTerminateRequested = sal_False; + + // Preload function depends on an initialized sfx application! + SetSplashScreenProgress(75); + + // use system window dialogs + Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG ); + + // SetSplashScreenProgress(80); + + if ( !bTerminateRequested && !pCmdLineArgs->IsInvisible() && + !pCmdLineArgs->IsNoQuickstart() ) + InitializeQuickstartMode( xSMgr ); + + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" ); + try + { + Reference< XDesktop > xDesktop( xSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); + if ( xDesktop.is() ) + xDesktop->addTerminateListener( new OfficeIPCThreadController ); + SetSplashScreenProgress(100); + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return; + } + /* + catch ( ... ) + { + FatalError( MakeStartupErrorMessage( + OUString::createFromAscii( + "Unknown error during startup (TD/Desktop service).\nInstallation could be damaged."))); + return; + } + */ + + // Post user event to startup first application component window + // We have to send this OpenClients message short before execute() to + // minimize the risk that this message overtakes type detection contruction!! + Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) ); + + // Post event to enable acceptors + Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) ); + + // The configuration error handler currently is only for startup + aConfigErrHandler.deactivate(); + + // Acquire solar mutex just before we enter our message loop + if ( nAcquireCount ) + Application::AcquireSolarMutex( nAcquireCount ); + + // call Application::Execute to process messages in vcl message loop + RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" ); + + try + { + // The JavaContext contains an interaction handler which is used when + // the creation of a Java Virtual Machine fails + com::sun::star::uno::ContextLayer layer2( + new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) ); + + // check whether the shutdown is caused by restart just before entering the Execute + bRestartRequested = bRestartRequested || ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( !bRestartRequested ) + { + // if this run of the office is triggered by restart, some additional actions should be done + DoRestartActionsIfNecessary( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoQuickstart() ); + + Execute(); + } + } + catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exFilterCfg.Message) ); + } + catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exAnyCfg.Message) ); + } + } + + if ( bRestartRequested ) + SetRestartState(); + + if (xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString::createFromAscii("OnCloseApp"); + xGlobalBroadcaster->notifyEvent(aEvent); + } + + delete pResMgr; + // Restore old value + if ( pCmdLineArgs->IsHeadless() ) + SvtMiscOptions().SetUseSystemFileDialog( bUseSystemFileDialog ); + + // remove temp directory + RemoveTemporaryDirectory(); + FlushConfiguration(); + // The acceptors in the AcceptorMap must be released (in DeregisterServices) + // with the solar mutex unlocked, to avoid deadlock: + nAcquireCount = Application::ReleaseSolarMutex(); + DeregisterServices(); + Application::AcquireSolarMutex(nAcquireCount); + tools::DeInitTestToolLib(); + // be sure that path/language options gets destroyed before + // UCB is deinitialized + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> dispose path/language options" ); + pLanguageOptions.reset( 0 ); + pPathOptions.reset( 0 ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- dispose path/language options" ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> deinit ucb" ); + ::ucbhelper::ContentBroker::deinitialize(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- deinit ucb" ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::Main" ); + if ( bRestartRequested ) + { + restartOnMac(true); + // wouldn't the solution be more clean if SalMain returns the exit code to the system? + _exit( ExitHelper::E_NORMAL_RESTART ); + } +} + +IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData ) +{ + return GraphicFilter::GetGraphicFilter()->GetFilterCallback().Call( pData ); +} + +sal_Bool Desktop::InitializeConfiguration() +{ + sal_Bool bOk = sal_False; + + try + { + bOk = InitConfiguration(); + } + catch( ::com::sun::star::lang::ServiceNotRegisteredException& ) + { + this->HandleBootstrapErrors( Desktop::BE_UNO_SERVICE_CONFIG_MISSING ); + } + catch( ::com::sun::star::configuration::MissingBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InvalidBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InstallationIncompleteException& ) + { + OUString aVersionFileURL; + OUString aMsg; + utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL ); + if ( aPathStatus == utl::Bootstrap::PATH_EXISTS ) + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL ); + else + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL ); + + HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg ); + } + catch ( com::sun::star::configuration::backend::BackendAccessException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( com::sun::star::configuration::backend::BackendSetupException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( ::com::sun::star::configuration::CannotLoadConfigurationException& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::uno::Exception& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + + return bOk; +} + +void Desktop::FlushConfiguration() +{ + Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGFlush.is()) + { + xCFGFlush->flush(); + } + else + { + // because there is no method to flush the condiguration data, we must dispose the ConfigManager + Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGDispose.is()) + xCFGDispose->dispose(); + } +} + +sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr ) +{ + try + { + // the shutdown icon sits in the systray and allows the user to keep + // the office instance running for quicker restart + // this will only be activated if -quickstart was specified on cmdline + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" ); + + sal_Bool bQuickstart = GetCommandLineArgs()->IsQuickstart(); + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + + // Try to instanciate quickstart service. This service is not mandatory, so + // do nothing if service is not available + + // #i105753# the following if was invented for performance + // unfortunately this broke the QUARTZ behavior which is to always run + // in quickstart mode since Mac applications do not usually quit + // when the last document closes + #ifndef QUARTZ + if ( bQuickstart ) + #endif + { + Reference < XComponent > xQuickstart( rSMgr->createInstanceWithArguments( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ), + UNO_QUERY ); + } + return sal_True; + } + catch( ::com::sun::star::uno::Exception& ) + { + return sal_False; + } +} + +void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* ) +{ + if ( !SvtTabAppearanceCfg::IsInitialized () ) + return; + +# define DRAGFULL_OPTION_ALL \ + ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \ + | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \ + | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \ + | DRAGFULL_OPTION_SCROLL ) +# define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL) + + StyleSettings hStyleSettings = rSettings.GetStyleSettings(); + MouseSettings hMouseSettings = rSettings.GetMouseSettings(); + + sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions(); + + SvtTabAppearanceCfg aAppearanceCfg; + sal_uInt16 nGet = aAppearanceCfg.GetDragMode(); + switch ( nGet ) + { + case DragFullWindow: + nDragFullOptions |= DRAGFULL_OPTION_ALL; + break; + case DragFrame: + nDragFullOptions &= DRAGFULL_OPTION_NONE; + break; + case DragSystemDep: + default: + break; + } + + sal_uInt32 nFollow = hMouseSettings.GetFollow(); + hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU)); + rSettings.SetMouseSettings(hMouseSettings); + + BOOL bUseImagesInMenus = hStyleSettings.GetUseImagesInMenus(); + + SvtMenuOptions aMenuOpt; + nGet = aMenuOpt.GetMenuIconsState(); + switch ( nGet ) + { + case 0: + bUseImagesInMenus = FALSE; + break; + case 1: + bUseImagesInMenus = TRUE; + break; + case 2: + default: + break; + } + hStyleSettings.SetUseImagesInMenus(bUseImagesInMenus); + + sal_uInt16 nTabStyle = hStyleSettings.GetTabControlStyle(); + nTabStyle &= ~STYLE_TABCONTROL_SINGLELINE; + if( aAppearanceCfg.IsSingleLineTabCtrl() ) + nTabStyle |=STYLE_TABCONTROL_SINGLELINE; + + nTabStyle &= ~STYLE_TABCONTROL_COLOR; + if( aAppearanceCfg.IsColoredTabCtrl() ) + nTabStyle |= STYLE_TABCONTROL_COLOR; + + hStyleSettings.SetTabControlStyle(nTabStyle); + + hStyleSettings.SetDragFullOptions( nDragFullOptions ); + rSettings.SetStyleSettings ( hStyleSettings ); +} + +// ======================================================================== +IMPL_LINK( Desktop, AsyncInitFirstRun, void*, EMPTYARG ) +{ + DoFirstRunInitializations(); + return 0L; +} + +// ======================================================================== + +class ExitTimer : public Timer +{ + public: + ExitTimer() + { + SetTimeout(500); + Start(); + } + virtual void Timeout() + { + exit(42); + } +}; + +IMPL_LINK( Desktop, OpenClients_Impl, void*, EMPTYARG ) +{ + RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE - DesktopOpenClients_Impl()" ); + + OpenClients(); + + OfficeIPCThread::SetReady(); + + // CloseStartupScreen(); + CloseSplashScreen(); + + CheckFirstRun( ); + + // allow ipc interaction +// OfficeIPCThread::SetReady(); + + EnableOleAutomation(); + + if (getenv ("OOO_EXIT_POST_STARTUP")) + new ExitTimer(); + return 0; +} + +// enable acceptos +IMPL_LINK( Desktop, EnableAcceptors_Impl, void*, EMPTYARG ) +{ + enableAcceptors(); + return 0; +} + + +// Registers a COM class factory of the service manager with the windows operating system. +void Desktop::EnableOleAutomation() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jl97489) ::Desktop::EnableOleAutomation" ); +#ifdef WNT + Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory(); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.bridge.OleApplicationRegistration")); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.comp.ole.EmbedServer")); +#endif +} + +sal_Bool Desktop::CheckOEM() +{ + Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); + Reference<XJob> rOemJob(rFactory->createInstance( + OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")), + UNO_QUERY ); + Sequence<NamedValue> args; + sal_Bool bResult = sal_False; + if (rOemJob.is()) { + Any aResult = rOemJob->execute(args); + aResult >>= bResult; + return bResult; + } else { + return sal_True; + } +} + +void Desktop::PreloadModuleData( CommandLineArgs* pArgs ) +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + + Sequence < com::sun::star::beans::PropertyValue > args(1); + args[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + args[0].Value <<= sal_True; + Reference < XComponentLoader > xLoader( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), UNO_QUERY ); + + if ( !xLoader.is() ) + return; + + if ( pArgs->IsWriter() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/swriter"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsCalc() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/scalc"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsDraw() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/sdraw"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsImpress() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/simpress"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::PreloadConfigurationData() +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + Reference< XNameAccess > xNameAccess( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.UICommandDescription" )), UNO_QUERY ); + + rtl::OUString aWriterDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" )); + rtl::OUString aCalcDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" )); + rtl::OUString aDrawDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" )); + rtl::OUString aImpressDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" )); + + // preload commands configuration + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xCmdAccess; + + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + { + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:BasicShapes" )); + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:EditGlossary" )); + } + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:InsertObjectStarMath" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + // draw and impress share the same configuration file (DrawImpressCommands.xcu) + a = xNameAccess->getByName( aDrawDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:Polygon" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload window state configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.WindowStateConfiguration" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xWindowAccess; + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aDrawDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aImpressDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload user interface element factories + Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue; + Reference< ::com::sun::star::ui::XUIElementFactoryRegistration > xUIElementFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.UIElementFactoryManager" )), + UNO_QUERY ); + if ( xUIElementFactory.is() ) + { + try + { + aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload popup menu controller factories. As all controllers are in the same + // configuration file they also get preloaded! + Reference< ::com::sun::star::frame::XUIControllerRegistration > xPopupMenuControllerFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.PopupMenuControllerFactory" )), + UNO_QUERY ); + if ( xPopupMenuControllerFactory.is() ) + { + try + { + xPopupMenuControllerFactory->hasController( + DEFINE_CONST_UNICODE( ".uno:CharFontName" ), + OUString() ); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload filter configuration + Sequence< OUString > aSeq; + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload type detection configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); + static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ); + + // get configuration provider + Reference< XMultiServiceFactory > xConfigProvider; + xConfigProvider = Reference< XMultiServiceFactory > ( + rFactory->createInstance( sConfigSrvc ),UNO_QUERY ); + + if ( xConfigProvider.is() ) + { + // preload writer configuration + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Writer/MailMergeWizard" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // WriterWeb + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.WriterWeb/Content" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload compatibility + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Compatibility/WriterCompatibilityVersion" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload calc configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Calc/Content" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload impress configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI.Effects/UserInterface" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Impress/Layout" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload draw configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Draw/Layout" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload ui configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI/FilterClassification" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload addons configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Addons/AddonUI" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::OpenClients() +{ + + // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document + // should be created + Reference < XComponent > xFirst; + BOOL bLoaded = FALSE; + + CommandLineArgs* pArgs = GetCommandLineArgs(); + SvtInternalOptions aInternalOptions; + + Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); + + if (!pArgs->IsQuickstart()) { + sal_Bool bShowHelp = sal_False; + ::rtl::OUStringBuffer aHelpURLBuffer; + if (pArgs->IsHelpWriter()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start"); + } else if (pArgs->IsHelpCalc()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start"); + } else if (pArgs->IsHelpDraw()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start"); + } else if (pArgs->IsHelpImpress()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start"); + } else if (pArgs->IsHelpBase()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start"); + } else if (pArgs->IsHelpBasic()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start"); + } else if (pArgs->IsHelpMath()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start"); + } + if (bShowHelp) { + Help *pHelp = Application::GetHelp(); + + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ); + rtl::OUString aTmp; + aRet >>= aTmp; + aHelpURLBuffer.appendAscii("?Language="); + aHelpURLBuffer.append(aTmp); +#if defined UNX + aHelpURLBuffer.appendAscii("&System=UNX"); +#elif defined WNT + aHelpURLBuffer.appendAscii("&System=WIN"); +#elif defined MAC + aHelpURLBuffer.appendAscii("&System=MAC"); +#elif defined OS2 + aHelpURLBuffer.appendAscii("&System=OS2"); +#endif + pHelp->Start(aHelpURLBuffer.makeStringAndClear(), NULL); + return; + } + } + else + { + OUString aIniName; + ::vos::OStartupInfo aInfo; + + aInfo.getExecutableFile( aIniName ); + sal_uInt32 lastIndex = aIniName.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aIniName = aIniName.copy( 0, lastIndex+1 ); + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" )); +#if defined(WNT) || defined(OS2) + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" )); +#else + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" )); +#endif + } + + rtl::Bootstrap aPerfTuneIniFile( aIniName ); + + OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" )); + OUString aPreloadData; + + aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "QuickstartPreloadConfiguration" )), aPreloadData, aDefault ); + if ( aPreloadData.equalsAscii( "1" )) + { + if ( pArgs->IsWriter() || + pArgs->IsCalc() || + pArgs->IsDraw() || + pArgs->IsImpress() ) + { + PreloadModuleData( pArgs ); + } + + PreloadConfigurationData(); + } + } + + // Disable AutoSave feature in case "-norestore" or a similare command line switch is set on the command line. + // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data. + // But the require that all documents, which are saved as backup should exists inside + // memory. May be this mechanism will be inconsistent if the configuration exists ... + // but no document inside memory corrspond to this data. + // Furter it's not acceptable to recover such documents without any UI. It can + // need some time, where the user wont see any results and wait for finishing the office startup ... + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !pArgs->IsNoRestore() ) && + ( !pArgs->IsHeadless() ) && + ( !pArgs->IsServer() ) + ); + + if ( ! bAllowRecoveryAndSessionManagement ) + { + /* + ::comphelper::ConfigurationHelper::writeDirectKey( + ::comphelper::getProcessServiceFactory(), + ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery"), + ::rtl::OUString::createFromAscii("AutoSave"), + ::rtl::OUString::createFromAscii("Enabled"), + ::com::sun::star::uno::makeAny(sal_False), + ::comphelper::ConfigurationHelper::E_STANDARD); + + */ + try + { + Reference< XDispatch > xRecovery( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + Reference< XURLTransformer > xParser( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + css::util::URL aCmd; + aCmd.Complete = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/disableRecovery"); + xParser->parseStrict(aCmd); + + xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >()); + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Could not disable AutoRecovery.\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + else + { + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + + if ( !getenv ("OOO_DISABLE_RECOVERY") && + ( ! bLoaded ) && + ( + ( bExistsRecoveryData ) || // => crash with files => recovery + ( bCrashed ) // => crash without files => error report + ) + ) + { + try + { + impl_callRecoveryUI( + sal_False , // false => force recovery instead of emergency save + bCrashed , + bExistsRecoveryData); + /* TODO we cant be shure, that at least one document could be recovered here successfully + So we set bLoaded=TRUE to supress opening of the default document. + But we should make it more safe. Otherwhise we have an office without an UI ... + ... + May be we can check the desktop if some documents are existing there. + */ + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() ) + bLoaded = sal_True; + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Error during recovery\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + + Reference< XInitialization > xSessionListener; + try + { + xSessionListener = Reference< XInitialization >(::comphelper::getProcessServiceFactory()->createInstance( + OUString::createFromAscii("com.sun.star.frame.SessionListener")), UNO_QUERY_THROW); + + // specifies whether the UI-interaction on Session shutdown is allowed + sal_Bool bAllowUI = isUIOnSessionShutdownAllowed(); + css::beans::NamedValue aProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowUserInteractionOnQuit" ) ), + css::uno::makeAny( bAllowUI ) ); + css::uno::Sequence< css::uno::Any > aArgs( 1 ); + aArgs[0] <<= aProperty; + + xSessionListener->initialize( aArgs ); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Registration of session listener failed\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + + if ( + ( ! bLoaded ) && + ( bExistsSessionData ) + ) + { + // session management + try + { + Reference< XSessionManagerListener > r(xSessionListener, UNO_QUERY_THROW); + bLoaded = r->doRestore(); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Error in session management\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + } + + OfficeIPCThread::EnableRequests(); + + sal_Bool bShutdown( sal_False ); + if ( !pArgs->IsServer() ) + { + ProcessDocumentsRequest aRequest(pArgs->getCwdUrl()); + aRequest.pcProcessed = NULL; + + pArgs->GetOpenList( aRequest.aOpenList ); + pArgs->GetViewList( aRequest.aViewList ); + pArgs->GetStartList( aRequest.aStartList ); + pArgs->GetPrintList( aRequest.aPrintList ); + pArgs->GetPrintToList( aRequest.aPrintToList ); + pArgs->GetPrinterName( aRequest.aPrinterName ); + pArgs->GetForceOpenList( aRequest.aForceOpenList ); + pArgs->GetForceNewList( aRequest.aForceNewList ); + + if ( aRequest.aOpenList.getLength() > 0 || + aRequest.aViewList.getLength() > 0 || + aRequest.aStartList.getLength() > 0 || + aRequest.aPrintList.getLength() > 0 || + aRequest.aForceOpenList.getLength() > 0 || + aRequest.aForceNewList.getLength() > 0 || + ( aRequest.aPrintToList.getLength() > 0 && aRequest.aPrinterName.getLength() > 0 )) + { + bLoaded = sal_True; + + if ( pArgs->HasModuleParam() ) + { + SvtModuleOptions aOpt; + + // Support command line parameters to start a module (as preselection) + if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER ); + else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC ); + else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS ); + else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW ); + } + + // check for printing disabled + if( ( aRequest.aPrintList.getLength() || aRequest.aPrintToList.getLength() ) + && Application::GetSettings().GetMiscSettings().GetDisablePrinting() ) + { + aRequest.aPrintList = rtl::OUString(); + aRequest.aPrintToList = rtl::OUString(); + ResMgr* pDtResMgr = GetDesktopResManager(); + if( pDtResMgr ) + { + ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) ); + aBox.Execute(); + } + } + + // Process request + bShutdown = OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); + } + } + + // Don't do anything if we have successfully called terminate at desktop + if ( bShutdown ) + return; + + // no default document if a document was loaded by recovery or by command line or if soffice is used as server + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() || pArgs->IsServer() ) + return; + + if ( pArgs->IsQuickstart() || pArgs->IsInvisible() || pArgs->IsBean() || Application::AnyInput( INPUT_APPEVENT ) ) + // soffice was started as tray icon ... + return; + { + OpenDefault(); + } +} + +void Desktop::OpenDefault() +{ + + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::OpenDefault" ); + + ::rtl::OUString aName; + SvtModuleOptions aOpt; + + CommandLineArgs* pArgs = GetCommandLineArgs(); + if ( pArgs->IsNoDefault() ) return; + if ( pArgs->HasModuleParam() ) + { + // Support new command line parameters to start a module + if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( pArgs->IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else if ( pArgs->IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH ); + else if ( pArgs->IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL ); + else if ( pArgs->IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB ); + } + + if ( !aName.getLength() ) + { + // Old way to create a default document + if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else + return; + } + + ProcessDocumentsRequest aRequest(pArgs->getCwdUrl()); + aRequest.pcProcessed = NULL; + aRequest.aOpenList = aName; + OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); +} + + +String GetURL_Impl( + const String& rName, boost::optional< rtl::OUString > const & cwdUrl ) +{ + // if rName is a vnd.sun.star.script URL do not attempt to parse it + // as INetURLObj does not handle handle there URLs + if (rName.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL) + { + return rName; + } + + // dont touch file urls, those should already be in internal form + // they won't get better here (#112849#) + if (rName.CompareToAscii("file:" , 5) == COMPARE_EQUAL) + { + return rName; + } + + if ( rName.CompareToAscii("service:" , 8) == COMPARE_EQUAL ) + { + return rName; + } + + // Add path seperator to these directory and make given URL (rName) absolute by using of current working directory + // Attention: "setFianlSlash()" is neccessary for calling "smartRel2Abs()"!!! + // Otherwhise last part will be ignored and wrong result will be returned!!! + // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ... + // But if we add a seperator - he doesn't do it anymore. + INetURLObject aObj; + if (cwdUrl) { + aObj.SetURL(*cwdUrl); + aObj.setFinalSlash(); + } + + // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths. + // Otherwise this char won't get encoded and we are not able to load such files later, + // see #110156# + bool bWasAbsolute; + INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED, + RTL_TEXTENCODING_UTF8, true ); + String aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE); + + ::osl::FileStatus aStatus( FileStatusMask_FileURL ); + ::osl::DirectoryItem aItem; + if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) && + ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) ) + aFileURL = aStatus.getFileURL(); + + return aFileURL; +} + +void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent ) +{ + if ( rAppEvent.GetEvent() == "APPEAR" && !GetCommandLineArgs()->IsInvisible() ) + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + // find active task - the active task is always a visible task + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xTask = xDesktop->getActiveFrame(); + if ( !xTask.is() ) + { + // get any task if there is no active one + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY ); + if ( xList->getCount()>0 ) + xList->getByIndex(0) >>= xTask; + } + + if ( xTask.is() ) + { + Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY ); + xTop->toFront(); + } + else + { + // no visible task that could be activated found + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xDesktopFrame( xDesktop, UNO_QUERY ); + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + Reference< XController > xBackingComp( + xSMGR->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), + UNO_QUERY); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + xBackingComp->attachFrame(xBackingFrame); + xContainerWindow->setVisible(sal_True); + + Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow()); + if (pCompWindow) + pCompWindow->Update(); + } + } + } + } + else if ( rAppEvent.GetEvent() == "QUICKSTART" && !GetCommandLineArgs()->IsInvisible() ) + { + // If the office has been started the second time its command line arguments are sent through a pipe + // connection to the first office. We want to reuse the quickstart option for the first office. + // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the + // application events to do this (they are executed inside main thread)!!! + // Don't start quickstart service if the user specified "-invisible" on the command line! + sal_Bool bQuickstart( sal_True ); + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + + Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" )), + UNO_QUERY ); + if ( xQuickstart.is() ) + xQuickstart->initialize( aSeq ); + } + else if ( rAppEvent.GetEvent() == "ACCEPT" ) + { + // every time an accept parameter is used we create an acceptor + // with the corresponding accept-string + OUString aAcceptString(rAppEvent.GetData().GetBuffer()); + createAcceptor(aAcceptString); + } + else if ( rAppEvent.GetEvent() == "UNACCEPT" ) + { + // try to remove corresponding acceptor + OUString aUnAcceptString(rAppEvent.GetData().GetBuffer()); + destroyAcceptor(aUnAcceptString); + } + else if ( rAppEvent.GetEvent() == "SaveDocuments" ) + { + Desktop::_bTasksSaved = sal_False; + Desktop::_bTasksSaved = SaveTasks(); + } + else if ( rAppEvent.GetEvent() == "OPENHELPURL" ) + { + // start help for a specific URL + OUString aHelpURL(rAppEvent.GetData().GetBuffer()); + Help *pHelp = Application::GetHelp(); + pHelp->Start(aHelpURL, NULL); + } + else if ( rAppEvent.GetEvent() == APPEVENT_OPEN_STRING ) + { + OUString aOpenURL(rAppEvent.GetData().GetBuffer()); + + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + pCmdLine->getCwdUrl()); + pDocsRequest->aOpenList = aOpenURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } + else if ( rAppEvent.GetEvent() == APPEVENT_PRINT_STRING ) + { + OUString aPrintURL(rAppEvent.GetData().GetBuffer()); + + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + pCmdLine->getCwdUrl()); + pDocsRequest->aPrintList = aPrintURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } +#ifndef UNX + else if ( rAppEvent.GetEvent() == "HELP" ) + { + // in non unix version allow showing of cmdline help window + displayCmdlineHelp(); + } +#endif + else if ( rAppEvent.GetEvent() == "SHOWDIALOG" ) + { + // ignore all errors here. It's clicking a menu entry only ... + // The user will try it again, in case nothing happens .-) + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + + // check provider ... we know it's weak reference only + if ( ! xDesktop.is()) + return; + + css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), css::uno::UNO_QUERY_THROW); + css::util::URL aCommand; + if( rAppEvent.GetData().EqualsAscii( "PREFERENCES" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OptionsTreeDialog" ) ); + else if( rAppEvent.GetData().EqualsAscii( "ABOUT" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:About" ) ); + if( aCommand.Complete.getLength() ) + { + xParser->parseStrict(aCommand); + + css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0); + if (xDispatch.is()) + xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >()); + } + } + catch(const css::uno::Exception&) + {} + } +} + +void Desktop::OpenSplashScreen() +{ + ::rtl::OUString aTmpString; + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + sal_Bool bVisible = sal_False; + // Show intro only if this is normal start (e.g. no server, no quickstart, no printing ) + if ( !pCmdLine->IsInvisible() && + !pCmdLine->IsQuickstart() && + !pCmdLine->IsMinimized() && + !pCmdLine->IsNoLogo() && + !pCmdLine->IsTerminateAfterInit() && + !pCmdLine->GetPrintList( aTmpString ) && + !pCmdLine->GetPrintToList( aTmpString ) ) + { + // Determine application name from command line parameters + OUString aAppName; + if ( pCmdLine->IsWriter() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer" )); + else if ( pCmdLine->IsCalc() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc" )); + else if ( pCmdLine->IsDraw() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw" )); + else if ( pCmdLine->IsImpress() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress" )); + else if ( pCmdLine->IsBase() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "base" )); + else if ( pCmdLine->IsGlobal() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "global" )); + else if ( pCmdLine->IsMath() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math" )); + else if ( pCmdLine->IsWeb() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "web" )); + + bVisible = sal_True; + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= bVisible; + aSeq[1] <<= aAppName; + m_rSplashScreen = Reference<XStatusIndicator>( + comphelper::getProcessServiceFactory()->createInstanceWithArguments( + OUString::createFromAscii("com.sun.star.office.SplashScreen"), + aSeq), UNO_QUERY); + + if(m_rSplashScreen.is()) + m_rSplashScreen->start(OUString::createFromAscii("SplashScreen"), 100); + } + +} + +void Desktop::SetSplashScreenProgress(sal_Int32 iProgress) +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->setValue(iProgress); + } +} + +void Desktop::SetSplashScreenText( const ::rtl::OUString& rText ) +{ + if( m_rSplashScreen.is() ) + { + m_rSplashScreen->setText( rText ); + } +} + +void Desktop::CloseSplashScreen() +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->end(); + m_rSplashScreen = NULL; + } +} + +// ======================================================================== +void Desktop::DoFirstRunInitializations() +{ + try + { + Reference< XJobExecutor > xExecutor( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.task.JobExecutor" ) ), UNO_QUERY ); + if( xExecutor.is() ) + xExecutor->trigger( ::rtl::OUString::createFromAscii("onFirstRunInitialization") ); + } + catch(const ::com::sun::star::uno::Exception&) + { + OSL_ENSURE( sal_False, "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." ); + } +} + +// ======================================================================== +void Desktop::CheckFirstRun( ) +{ + const ::rtl::OUString sCommonMiscNodeName = ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Common/Misc" ); + const ::rtl::OUString sFirstRunNodeName = ::rtl::OUString::createFromAscii( "FirstRun" ); + + // -------------------------------------------------------------------- + // check if this is the first office start + + // for this, open the Common/Misc node where this info is stored + ::utl::OConfigurationTreeRoot aCommonMisc = ::utl::OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory( ), + sCommonMiscNodeName, + 2, + ::utl::OConfigurationTreeRoot::CM_UPDATABLE + ); + + // read the flag + OSL_ENSURE( aCommonMisc.isValid(), "Desktop::CheckFirstRun: could not open the config node needed!" ); + sal_Bool bIsFirstRun = sal_False; + aCommonMisc.getNodeValue( sFirstRunNodeName ) >>= bIsFirstRun; + + if ( !bIsFirstRun ) + // nothing to do .... + return; + + // -------------------------------------------------------------------- + // it is the first run + // this has once been done using a vos timer. this could lead to problems when + // the timer would trigger when the app is already going down again, since VCL would + // no longer be available. Since the old handler would do a postUserEvent to the main + // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#) + m_firstRunTimer.SetTimeout(3000); // 3 sec. + m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun)); + m_firstRunTimer.Start(); + + // -------------------------------------------------------------------- + // reset the config flag + + // set the value + aCommonMisc.setNodeValue( sFirstRunNodeName, makeAny( (sal_Bool)sal_False ) ); + // commit the changes + aCommonMisc.commit(); +} + +} |