summaryrefslogtreecommitdiff
path: root/framework/source/services
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/services')
-rw-r--r--framework/source/services/autorecovery.cxx3747
-rw-r--r--framework/source/services/backingcomp.cxx874
-rw-r--r--framework/source/services/backingwindow.cxx1153
-rw-r--r--framework/source/services/backingwindow.hxx184
-rw-r--r--framework/source/services/desktop.cxx2038
-rw-r--r--framework/source/services/dispatchhelper.cxx227
-rw-r--r--framework/source/services/frame.cxx3311
-rw-r--r--framework/source/services/fwk_services.src227
-rw-r--r--framework/source/services/license.cxx631
-rw-r--r--framework/source/services/mediatypedetectionhelper.cxx111
-rwxr-xr-xframework/source/services/modelwinservice.cxx279
-rw-r--r--framework/source/services/modulemanager.cxx425
-rw-r--r--framework/source/services/pathsettings.cxx1187
-rw-r--r--framework/source/services/sessionlistener.cxx368
-rw-r--r--framework/source/services/substitutepathvars.cxx1249
-rw-r--r--framework/source/services/tabwindowservice.cxx485
-rw-r--r--framework/source/services/taskcreatorsrv.cxx404
-rw-r--r--framework/source/services/uriabbreviation.cxx90
-rw-r--r--framework/source/services/urltransformer.cxx372
19 files changed, 17362 insertions, 0 deletions
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
new file mode 100644
index 000000000000..564e26f2651b
--- /dev/null
+++ b/framework/source/services/autorecovery.cxx
@@ -0,0 +1,3747 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+#include "services/autorecovery.hxx"
+#include <loadenv/loadenv.hxx>
+
+//_______________________________________________
+// own includes
+#include <loadenv/targethelper.hxx>
+#include <pattern/frame.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+#include <classes/resource.hrc>
+#include <classes/fwkresid.hxx>
+#include <protocols.h>
+#include <properties.h>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/frame/XNotifyingDispatch.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XContainerQuery.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentRecovery.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
+
+//_______________________________________________
+// other includes
+#include <comphelper/configurationhelper.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/pathoptions.hxx>
+#include <tools/link.hxx>
+#include <tools/string.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/tempfile.hxx>
+#include <ucbhelper/content.hxx>
+
+#include <osl/time.h>
+#include <vcl/msgbox.hxx>
+#include <osl/file.hxx>
+#include <unotools/bootstrap.hxx>
+#include <unotools/configmgr.hxx>
+#include <svl/documentlockfile.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <tools/urlobj.hxx>
+
+#include <fwkdllapi.h>
+
+//_______________________________________________
+// namespaces
+
+#ifndef css
+namespace css = ::com::sun::star;
+#endif
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::container::XEnumeration;
+using ::com::sun::star::document::XDocumentRecovery;
+using ::com::sun::star::frame::XModel2;
+using ::com::sun::star::frame::XModel;
+using ::com::sun::star::frame::XFrame;
+using ::com::sun::star::frame::XController2;
+using ::com::sun::star::frame::XLoadable;
+using ::com::sun::star::frame::XStorable;
+using ::com::sun::star::lang::XComponent;
+
+namespace fpf = ::framework::pattern::frame;
+
+
+namespace framework
+{
+
+//-----------------------------------------------
+// recovery.xcu
+static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
+static const ::rtl::OUString CFG_ENTRY_RECOVERYLIST = ::rtl::OUString::createFromAscii("RecoveryList" );
+static const ::rtl::OUString CFG_PATH_RECOVERYINFO = ::rtl::OUString::createFromAscii("RecoveryInfo" );
+static const ::rtl::OUString CFG_ENTRY_ENABLED = ::rtl::OUString::createFromAscii("Enabled" );
+static const ::rtl::OUString CFG_ENTRY_CRASHED = ::rtl::OUString::createFromAscii("Crashed" );
+static const ::rtl::OUString CFG_ENTRY_SESSIONDATA = ::rtl::OUString::createFromAscii("SessionData" );
+
+static const ::rtl::OUString CFG_ENTRY_AUTOSAVE_ENABLED = ::rtl::OUString::createFromAscii("AutoSave/Enabled" );
+static const ::rtl::OUString CFG_ENTRY_AUTOSAVE_TIMEINTERVALL = ::rtl::OUString::createFromAscii("AutoSave/TimeIntervall" );
+
+static const ::rtl::OUString CFG_PATH_AUTOSAVE = ::rtl::OUString::createFromAscii("AutoSave" );
+static const ::rtl::OUString CFG_ENTRY_MINSPACE_DOCSAVE = ::rtl::OUString::createFromAscii("MinSpaceDocSave" );
+static const ::rtl::OUString CFG_ENTRY_MINSPACE_CONFIGSAVE = ::rtl::OUString::createFromAscii("MinSpaceConfigSave" );
+
+static const ::rtl::OUString CFG_PACKAGE_MODULES = ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office/Factories");
+static const ::rtl::OUString CFG_ENTRY_REALDEFAULTFILTER = ::rtl::OUString::createFromAscii("ooSetupFactoryActualFilter" );
+
+static const ::rtl::OUString CFG_ENTRY_PROP_TEMPURL = ::rtl::OUString::createFromAscii("TempURL" );
+static const ::rtl::OUString CFG_ENTRY_PROP_ORIGINALURL = ::rtl::OUString::createFromAscii("OriginalURL" );
+static const ::rtl::OUString CFG_ENTRY_PROP_TEMPLATEURL = ::rtl::OUString::createFromAscii("TemplateURL" );
+static const ::rtl::OUString CFG_ENTRY_PROP_FACTORYURL = ::rtl::OUString::createFromAscii("FactoryURL" );
+static const ::rtl::OUString CFG_ENTRY_PROP_MODULE = ::rtl::OUString::createFromAscii("Module" );
+static const ::rtl::OUString CFG_ENTRY_PROP_DOCUMENTSTATE = ::rtl::OUString::createFromAscii("DocumentState");
+static const ::rtl::OUString CFG_ENTRY_PROP_FILTER = ::rtl::OUString::createFromAscii("Filter" );
+static const ::rtl::OUString CFG_ENTRY_PROP_TITLE = ::rtl::OUString::createFromAscii("Title" );
+static const ::rtl::OUString CFG_ENTRY_PROP_ID = ::rtl::OUString::createFromAscii("ID" );
+static const ::rtl::OUString CFG_ENTRY_PROP_VIEWNAMES = ::rtl::OUString::createFromAscii("ViewNames" );
+
+static const ::rtl::OUString FILTER_PROP_TYPE = ::rtl::OUString::createFromAscii("Type" );
+static const ::rtl::OUString FILTER_PROP_NAME = ::rtl::OUString::createFromAscii("Name" );
+static const ::rtl::OUString TYPE_PROP_EXTENSIONS = ::rtl::OUString::createFromAscii("Extensions" );
+static const ::rtl::OUString DOCINFO_PROP_TEMPLATE = ::rtl::OUString::createFromAscii("TemplateFileName");
+
+// setup.xcu
+static const ::rtl::OUString CFG_ENTRY_PROP_EMPTYDOCUMENTURL = ::rtl::OUString::createFromAscii("ooSetupFactoryEmptyDocumentURL");
+static const ::rtl::OUString CFG_ENTRY_PROP_DEFAULTFILTER = ::rtl::OUString::createFromAscii("ooSetupFactoryDefaultFilter" );
+static const ::rtl::OUString CFG_ENTRY_PROP_FACTORYSERVICE = ::rtl::OUString::createFromAscii("ooSetupFactoryDocumentService" );
+
+static const ::rtl::OUString EVENT_ON_NEW = ::rtl::OUString::createFromAscii("OnNew" );
+static const ::rtl::OUString EVENT_ON_LOAD = ::rtl::OUString::createFromAscii("OnLoad" );
+static const ::rtl::OUString EVENT_ON_UNLOAD = ::rtl::OUString::createFromAscii("OnUnload" );
+static const ::rtl::OUString EVENT_ON_MODIFYCHANGED = ::rtl::OUString::createFromAscii("OnModifyChanged");
+static const ::rtl::OUString EVENT_ON_SAVE = ::rtl::OUString::createFromAscii("OnSave" );
+static const ::rtl::OUString EVENT_ON_SAVEAS = ::rtl::OUString::createFromAscii("OnSaveAs" );
+static const ::rtl::OUString EVENT_ON_SAVETO = ::rtl::OUString::createFromAscii("OnCopyTo" );
+static const ::rtl::OUString EVENT_ON_SAVEDONE = ::rtl::OUString::createFromAscii("OnSaveDone" );
+static const ::rtl::OUString EVENT_ON_SAVEASDONE = ::rtl::OUString::createFromAscii("OnSaveAsDone" );
+static const ::rtl::OUString EVENT_ON_SAVETODONE = ::rtl::OUString::createFromAscii("OnCopyToDone" );
+static const ::rtl::OUString EVENT_ON_SAVEFAILED = ::rtl::OUString::createFromAscii("OnSaveFailed" );
+static const ::rtl::OUString EVENT_ON_SAVEASFAILED = ::rtl::OUString::createFromAscii("OnSaveAsFailed" );
+static const ::rtl::OUString EVENT_ON_SAVETOFAILED = ::rtl::OUString::createFromAscii("OnCopyToFailed" );
+
+static const ::rtl::OUString RECOVERY_ITEM_BASE_IDENTIFIER = ::rtl::OUString::createFromAscii("recovery_item_" );
+
+static const ::rtl::OUString CMD_PROTOCOL = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:");
+
+static const ::rtl::OUString CMD_DO_AUTO_SAVE = ::rtl::OUString::createFromAscii("/doAutoSave" ); // force AutoSave ignoring the AutoSave timer
+static const ::rtl::OUString CMD_DO_PREPARE_EMERGENCY_SAVE = ::rtl::OUString::createFromAscii("/doPrepareEmergencySave" ); // prepare the office for the following EmergencySave step (hide windows etcpp.)
+static const ::rtl::OUString CMD_DO_EMERGENCY_SAVE = ::rtl::OUString::createFromAscii("/doEmergencySave" ); // do EmergencySave on crash
+static const ::rtl::OUString CMD_DO_RECOVERY = ::rtl::OUString::createFromAscii("/doAutoRecovery" ); // recover all crashed documents
+static const ::rtl::OUString CMD_DO_ENTRY_BACKUP = ::rtl::OUString::createFromAscii("/doEntryBackup" ); // try to store a temp or original file to a user defined location
+static const ::rtl::OUString CMD_DO_ENTRY_CLEANUP = ::rtl::OUString::createFromAscii("/doEntryCleanUp" ); // remove the specified entry from the recovery cache
+static const ::rtl::OUString CMD_DO_SESSION_SAVE = ::rtl::OUString::createFromAscii("/doSessionSave" ); // save all open documents if e.g. a window manager closes an user session
+static const ::rtl::OUString CMD_DO_SESSION_QUIET_QUIT = ::rtl::OUString::createFromAscii("/doSessionQuietQuit" ); // let the current session be quietly closed ( the saving should be done using doSessionSave previously ) if e.g. a window manager closes an user session
+static const ::rtl::OUString CMD_DO_SESSION_RESTORE = ::rtl::OUString::createFromAscii("/doSessionRestore" ); // restore a saved user session from disc
+static const ::rtl::OUString CMD_DO_DISABLE_RECOVERY = ::rtl::OUString::createFromAscii("/disableRecovery" ); // disable recovery and auto save (!) temp. for this office session
+static const ::rtl::OUString CMD_DO_SET_AUTOSAVE_STATE = ::rtl::OUString::createFromAscii("/setAutoSaveState" ); // disable/enable auto save (not crash save) for this office session
+
+static const ::rtl::OUString REFERRER_USER = ::rtl::OUString::createFromAscii("private:user");
+
+static const ::rtl::OUString PROP_DISPATCH_ASYNCHRON = ::rtl::OUString::createFromAscii("DispatchAsynchron");
+static const ::rtl::OUString PROP_PROGRESS = ::rtl::OUString::createFromAscii("StatusIndicator" );
+static const ::rtl::OUString PROP_SAVEPATH = ::rtl::OUString::createFromAscii("SavePath" );
+static const ::rtl::OUString PROP_ENTRY_ID = ::rtl::OUString::createFromAscii("EntryID" );
+static const ::rtl::OUString PROP_DBG_MAKE_IT_FASTER = ::rtl::OUString::createFromAscii("DBGMakeItFaster" );
+static const ::rtl::OUString PROP_AUTOSAVE_STATE = ::rtl::OUString::createFromAscii("AutoSaveState" );
+
+static const ::rtl::OUString OPERATION_START = ::rtl::OUString::createFromAscii("start" );
+static const ::rtl::OUString OPERATION_STOP = ::rtl::OUString::createFromAscii("stop" );
+static const ::rtl::OUString OPERATION_UPDATE = ::rtl::OUString::createFromAscii("update");
+
+static const sal_Int32 MIN_DISCSPACE_DOCSAVE = 5; // [MB]
+static const sal_Int32 MIN_DISCSPACE_CONFIGSAVE = 1; // [MB]
+static const sal_Int32 RETRY_STORE_ON_FULL_DISC_FOREVER = 300; // not forever ... but often enough .-)
+static const sal_Int32 RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL = 3; // in case FULL DISC does not seam the real problem
+static const sal_Int32 GIVE_UP_RETRY = 1; // in case FULL DISC does not seam the real problem
+
+#define SAVE_IN_PROGRESS sal_True
+#define SAVE_FINISHED sal_False
+
+#define LOCK_FOR_CACHE_ADD_REMOVE sal_True
+#define LOCK_FOR_CACHE_USE sal_False
+
+#define MIN_TIME_FOR_USER_IDLE 10000 // 10s user idle
+
+// enable the following defines in case you whish to simulate a full disc for debug purposes .-)
+
+// this define throws everytime a document is stored or a configuration change
+// should be flushed an exception ... so the special error handler for this scenario is triggered
+// #define TRIGGER_FULL_DISC_CHECK
+
+// force "return sal_False" for the method impl_enoughDiscSpace().
+// #define SIMULATE_FULL_DISC
+
+//-----------------------------------------------
+// #define ENABLE_RECOVERY_LOGGING
+#undef ENABLE_RECOVERY_LOGGING
+#ifdef ENABLE_RECOVERY_LOGGING
+ #define LOGFILE_RECOVERY "recovery.log"
+
+ #define LOG_RECOVERY(MSG) \
+ { \
+ WRITE_LOGFILE(LOGFILE_RECOVERY, MSG) \
+ WRITE_LOGFILE(LOGFILE_RECOVERY, "\n") \
+ }
+#else
+ #undef LOGFILE_RECOVERY
+ #define LOG_RECOVERY(MSG)
+#endif
+
+//-----------------------------------------------
+// TODO debug - remove it!
+class DbgListener : private ThreadHelpBase
+ , public ::cppu::OWeakObject
+ , public css::frame::XStatusListener
+{
+ public:
+
+ FWK_DECLARE_XINTERFACE
+
+ DbgListener()
+ {
+ WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::ctor()\n\n")
+ }
+
+ virtual ~DbgListener()
+ {
+ WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::dtor()\n\n")
+ }
+
+ void startListening(const css::uno::Reference< css::frame::XDispatch >& xBroadcaster)
+ {
+ ::rtl::OUStringBuffer sMsg1(256);
+ sMsg1.appendAscii("//**********************************************************************************\n");
+ sMsg1.appendAscii("start listening\n{\n");
+ WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg1.makeStringAndClear()))
+
+ ++m_refCount;
+
+ css::util::URL aURL;
+ aURL.Complete = ::rtl::OUString();
+ xBroadcaster->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
+
+ --m_refCount;
+
+ ::rtl::OUStringBuffer sMsg2(256);
+ sMsg2.appendAscii("}\nstart listening\n");
+ sMsg2.appendAscii("//**********************************************************************************\n");
+ WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg2.makeStringAndClear()))
+ }
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject&)
+ throw(css::uno::RuntimeException)
+ {
+ WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::dtor()\n\n")
+ }
+
+ virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& aEvent)
+ throw(css::uno::RuntimeException)
+ {
+ ::rtl::OUStringBuffer sMsg(256);
+
+ sMsg.appendAscii("//**********************************************************************************\n");
+
+ sMsg.appendAscii("FeatureURL = \"");
+ sMsg.append (aEvent.FeatureURL.Complete);
+ sMsg.appendAscii("\"\n");
+
+ sMsg.appendAscii("State = [");
+ sal_Int32 nState = -1;
+ aEvent.State >>= nState;
+ if (nState==-1)
+ {
+ sMsg.appendAscii("?-");
+ sMsg.append (::rtl::OUString::valueOf(nState));
+ sMsg.appendAscii("-? ");
+ }
+ if (nState==0)
+ sMsg.appendAscii("UNKNOWN ");
+ if ((nState & 1)==1)
+ sMsg.appendAscii("MODIFIED ");
+ if ((nState & 2)==2)
+ sMsg.appendAscii("TRYIT ");
+ if ((nState & 4)==4)
+ sMsg.appendAscii("HANDLED ");
+ if ((nState & 8)==8)
+ sMsg.appendAscii("POSTPONED ");
+ if ((nState & 16)==16)
+ sMsg.appendAscii("INCOMPLETE ");
+ if ((nState & 32)==32)
+ sMsg.appendAscii("DAMAGED ");
+ sMsg.appendAscii("]\n");
+/*
+ sMsg.appendAscii("IsEnabled = \"");
+ sMsg.append (::rtl::OUString::valueOf(aEvent.IsEnabled));
+ sMsg.appendAscii("\"\n");
+
+ sMsg.appendAscii("Requery = \"");
+ sMsg.append (::rtl::OUString::valueOf(aEvent.Requery));
+ sMsg.appendAscii("\"\n");
+*/
+ sMsg.appendAscii("\n");
+
+ WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg.makeStringAndClear()))
+ }
+};
+
+//-----------------------------------------------
+class CacheLockGuard
+{
+ private:
+
+ // holds the outside calli alive, so it's shared resources
+ // are valid everytimes
+ css::uno::Reference< css::uno::XInterface > m_xOwner;
+
+ // mutex shared with outside calli !
+ LockHelper& m_rSharedMutex;
+
+ // this variable knows the state of the "cache lock"
+ sal_Int32& m_rCacheLock;
+
+ // to prevent increasing/decreasing of m_rCacheLock more then ones
+ // we must know if THIS guard has an actual lock set there !
+ sal_Bool m_bLockedByThisGuard;
+
+ public:
+
+ CacheLockGuard(AutoRecovery* pOwner ,
+ LockHelper& rMutex ,
+ sal_Int32& rCacheLock ,
+ sal_Bool bLockForAddRemoveVectorItems);
+ ~CacheLockGuard();
+
+ void lock(sal_Bool bLockForAddRemoveVectorItems);
+ void unlock();
+};
+
+//-----------------------------------------------
+CacheLockGuard::CacheLockGuard(AutoRecovery* pOwner ,
+ LockHelper& rMutex ,
+ sal_Int32& rCacheLock ,
+ sal_Bool bLockForAddRemoveVectorItems)
+ : m_xOwner (static_cast< css::frame::XDispatch* >(pOwner))
+ , m_rSharedMutex (rMutex )
+ , m_rCacheLock (rCacheLock )
+ , m_bLockedByThisGuard(sal_False )
+{
+ lock(bLockForAddRemoveVectorItems);
+}
+
+//-----------------------------------------------
+CacheLockGuard::~CacheLockGuard()
+{
+ unlock();
+ m_xOwner.clear();
+}
+
+//-----------------------------------------------
+void CacheLockGuard::lock(sal_Bool bLockForAddRemoveVectorItems)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_rSharedMutex);
+
+ if (m_bLockedByThisGuard)
+ return;
+
+ // This cache lock is needed only to prevent us from removing/adding
+ // items from/into the recovery cache ... during it's used at another code place
+ // for iterating .-)
+
+ // Modifying of item properties is allowed and sometimes needed!
+ // So we should detect only the dangerous state of concurrent add/remove
+ // requests and throw an exception then ... which can of course break the whole
+ // operation. On the other side a crash reasoned by an invalid stl iterator
+ // will have the same effect .-)
+
+ if (
+ (m_rCacheLock > 0 ) &&
+ (bLockForAddRemoveVectorItems)
+ )
+ {
+ OSL_ENSURE(sal_False, "Re-entrance problem detected. Using of an stl structure in combination with iteration, adding, removing of elements etcpp.");
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Re-entrance problem detected. Using of an stl structure in combination with iteration, adding, removing of elements etcpp."),
+ m_xOwner);
+ }
+
+ ++m_rCacheLock;
+ m_bLockedByThisGuard = sal_True;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void CacheLockGuard::unlock()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_rSharedMutex);
+
+ if ( ! m_bLockedByThisGuard)
+ return;
+
+ --m_rCacheLock;
+ m_bLockedByThisGuard = sal_False;
+
+ if (m_rCacheLock < 0)
+ {
+ OSL_ENSURE(sal_False, "Wrong using of member m_nDocCacheLock detected. A ref counted value shouldn't reach values <0 .-)");
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Wrong using of member m_nDocCacheLock detected. A ref counted value shouldn't reach values <0 .-)"),
+ m_xOwner);
+ }
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+DispatchParams::DispatchParams()
+ : m_nWorkingEntryID(-1)
+{
+};
+
+//-----------------------------------------------
+DispatchParams::DispatchParams(const ::comphelper::SequenceAsHashMap& lArgs ,
+ const css::uno::Reference< css::uno::XInterface >& xOwner)
+{
+ m_nWorkingEntryID = lArgs.getUnpackedValueOrDefault(PROP_ENTRY_ID, (sal_Int32)-1 );
+ m_xProgress = lArgs.getUnpackedValueOrDefault(PROP_PROGRESS, css::uno::Reference< css::task::XStatusIndicator >());
+ m_sSavePath = lArgs.getUnpackedValueOrDefault(PROP_SAVEPATH, ::rtl::OUString() );
+ m_xHoldRefForAsyncOpAlive = xOwner;
+};
+
+//-----------------------------------------------
+DispatchParams::DispatchParams(const DispatchParams& rCopy)
+{
+ m_xProgress = rCopy.m_xProgress;
+ m_sSavePath = rCopy.m_sSavePath;
+ m_nWorkingEntryID = rCopy.m_nWorkingEntryID;
+ m_xHoldRefForAsyncOpAlive = rCopy.m_xHoldRefForAsyncOpAlive;
+};
+
+//-----------------------------------------------
+DispatchParams::~DispatchParams()
+{};
+
+//-----------------------------------------------
+DispatchParams& DispatchParams::operator=(const DispatchParams& rCopy)
+{
+ m_xProgress = rCopy.m_xProgress;
+ m_sSavePath = rCopy.m_sSavePath;
+ m_nWorkingEntryID = rCopy.m_nWorkingEntryID;
+ m_xHoldRefForAsyncOpAlive = rCopy.m_xHoldRefForAsyncOpAlive;
+ return *this;
+}
+
+//-----------------------------------------------
+void DispatchParams::forget()
+{
+ m_sSavePath = ::rtl::OUString();
+ m_nWorkingEntryID = -1;
+ m_xProgress.clear();
+ m_xHoldRefForAsyncOpAlive.clear();
+};
+
+//-----------------------------------------------
+DEFINE_XINTERFACE_1(DbgListener ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::frame::XStatusListener))
+
+//-----------------------------------------------
+DEFINE_XINTERFACE_10(AutoRecovery ,
+ OWeakObject ,
+ DIRECT_INTERFACE (css::lang::XTypeProvider ),
+ DIRECT_INTERFACE (css::lang::XServiceInfo ),
+ DIRECT_INTERFACE (css::frame::XDispatch ),
+ DIRECT_INTERFACE (css::beans::XMultiPropertySet ),
+ DIRECT_INTERFACE (css::beans::XFastPropertySet ),
+ DIRECT_INTERFACE (css::beans::XPropertySet ),
+ DIRECT_INTERFACE (css::document::XEventListener ),
+ DIRECT_INTERFACE (css::util::XChangesListener ),
+ DIRECT_INTERFACE (css::util::XModifyListener ),
+ DERIVED_INTERFACE(css::lang::XEventListener, css::document::XEventListener))
+
+//-----------------------------------------------
+DEFINE_XTYPEPROVIDER_6(AutoRecovery ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDispatch ,
+ css::beans::XMultiPropertySet,
+ css::beans::XFastPropertySet ,
+ css::beans::XPropertySet )
+
+//-----------------------------------------------
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(AutoRecovery ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_AUTORECOVERY ,
+ IMPLEMENTATIONNAME_AUTORECOVERY)
+
+//-----------------------------------------------
+DEFINE_INIT_SERVICE(
+ AutoRecovery,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+
+ // read configuration to know if autosave/recovery is on/off etcpp...
+ implts_readConfig();
+
+ implts_startListening();
+
+ // establish callback for our internal used timer.
+ // Note: Its only active, if the timer will be started ...
+ m_aTimer.SetTimeoutHdl(LINK(this, AutoRecovery, implts_timerExpired));
+/*
+ DbgListener* pListener = new DbgListener();
+ pListener->startListening(this);
+*/
+ }
+ )
+
+//-----------------------------------------------
+AutoRecovery::AutoRecovery(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+ , ::cppu::OBroadcastHelper ( m_aLock.getShareableOslMutex() )
+ , ::cppu::OPropertySetHelper( *(static_cast< ::cppu::OBroadcastHelper* >(this)) )
+ , ::cppu::OWeakObject ( )
+ , m_xSMGR (xSMGR )
+ , m_bListenForDocEvents (sal_False )
+ , m_bListenForConfigChanges (sal_False )
+ , m_nAutoSaveTimeIntervall (0 )
+ , m_eJob (AutoRecovery::E_NO_JOB )
+ , m_aAsyncDispatcher ( LINK( this, AutoRecovery, implts_asyncDispatch ) )
+ , m_eTimerType (E_DONT_START_TIMER )
+ , m_nIdPool (0 )
+ , m_lListener (m_aLock.getShareableOslMutex() )
+ , m_nDocCacheLock (0 )
+ , m_nMinSpaceDocSave (MIN_DISCSPACE_DOCSAVE )
+ , m_nMinSpaceConfigSave (MIN_DISCSPACE_CONFIGSAVE )
+
+ #if OSL_DEBUG_LEVEL > 1
+ , m_dbg_bMakeItFaster (sal_False )
+ #endif
+{
+}
+
+//-----------------------------------------------
+AutoRecovery::~AutoRecovery()
+{
+ implts_stopTimer();
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::dispatch(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
+ throw(css::uno::RuntimeException)
+{
+ LOG_RECOVERY("AutoRecovery::dispatch() starts ...")
+ LOG_RECOVERY(U2B(aURL.Complete).getStr())
+
+ // valid request ?
+ sal_Int32 eNewJob = AutoRecovery::implst_classifyJob(aURL);
+ if (eNewJob == AutoRecovery::E_NO_JOB)
+ return;
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // still running operation ... ignoring AUTO_SAVE.
+ // All other requests has higher prio!
+ if (
+ ( m_eJob != AutoRecovery::E_NO_JOB ) &&
+ ((m_eJob & AutoRecovery::E_AUTO_SAVE ) != AutoRecovery::E_AUTO_SAVE)
+ )
+ {
+ LOG_WARNING("AutoRecovery::dispatch()", "There is already an asynchronous dispatch() running. New request will be ignored!")
+ return;
+ }
+
+ ::comphelper::SequenceAsHashMap lArgs(lArguments);
+
+ // check if somewhere wish to disable recovery temp. for this office session
+ // This can be done immediatly ... must not been done asynchronous.
+ if ((eNewJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY)
+ {
+ // it's important to set a flag internaly, so AutoRecovery will be supressed - even if it's requested.
+ m_eJob |= eNewJob;
+ implts_stopTimer();
+ implts_stopListening();
+ return;
+ }
+
+ // disable/enable AutoSave for this office session only
+ // independend from the configuration entry.
+ if ((eNewJob & AutoRecovery::E_SET_AUTOSAVE_STATE) == AutoRecovery::E_SET_AUTOSAVE_STATE)
+ {
+ sal_Bool bOn = lArgs.getUnpackedValueOrDefault(PROP_AUTOSAVE_STATE, (sal_Bool)sal_True);
+ if (bOn)
+ {
+ // dont enable AutoSave hardly !
+ // reload configuration to know the current state.
+ implts_readAutoSaveConfig();
+ implts_updateTimer();
+ // can it happen that might be the listener was stopped ? .-)
+ // make sure it runs always ... even if AutoSave itself was disabled temporarly.
+ implts_startListening();
+ }
+ else
+ {
+ implts_stopTimer();
+ m_eJob &= ~AutoRecovery::E_AUTO_SAVE;
+ m_eTimerType = AutoRecovery::E_DONT_START_TIMER;
+ }
+ return;
+ }
+
+ m_eJob |= eNewJob;
+
+ sal_Bool bAsync = lArgs.getUnpackedValueOrDefault(PROP_DISPATCH_ASYNCHRON, (sal_Bool)sal_False);
+ DispatchParams aParams (lArgs, static_cast< css::frame::XDispatch* >(this));
+
+ // Hold this instance alive till the asynchronous operation will be finished.
+ if (bAsync)
+ m_aDispatchParams = aParams;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (bAsync)
+ m_aAsyncDispatcher.Post(0);
+ else
+ implts_dispatch(aParams);
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_dispatch(const DispatchParams& aParams)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ sal_Int32 eJob = m_eJob;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // in case a new dispatch overwrites a may ba active AutoSave session
+ // we must restore this session later. see below ...
+ sal_Bool bWasAutoSaveActive = ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE);
+
+ // On the other side it make no sense to reactivate the AutoSave operation
+ // if the new dispatch indicates a final decision ...
+ // E.g. an EmergencySave/SessionSave indicates the end of life of the current office session.
+ // It make no sense to reactivate an AutoSave then.
+ // But a Recovery or SessionRestore should reactivate a may be already active AutoSave.
+ sal_Bool bAllowAutoSaveReactivation = sal_True;
+
+ implts_stopTimer();
+ implts_stopListening();
+
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_START, NULL));
+
+ try
+ {
+ // if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE)
+ // Auto save is called from our internal timer ... not via dispatch() API !
+ // else
+ if (
+ ((eJob & AutoRecovery::E_PREPARE_EMERGENCY_SAVE) == AutoRecovery::E_PREPARE_EMERGENCY_SAVE) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY ) != AutoRecovery::E_DISABLE_AUTORECOVERY )
+ )
+ {
+ LOG_RECOVERY("... prepare emergency save ...")
+ bAllowAutoSaveReactivation = sal_False;
+ implts_prepareEmergencySave();
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_EMERGENCY_SAVE ) == AutoRecovery::E_EMERGENCY_SAVE ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do emergency save ...")
+ bAllowAutoSaveReactivation = sal_False;
+ implts_doEmergencySave(aParams);
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_RECOVERY ) == AutoRecovery::E_RECOVERY ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do recovery ...")
+ implts_doRecovery(aParams);
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_SESSION_SAVE ) == AutoRecovery::E_SESSION_SAVE ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do session save ...")
+ bAllowAutoSaveReactivation = sal_False;
+ implts_doSessionSave(aParams);
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT ) == AutoRecovery::E_SESSION_QUIET_QUIT ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do session quiet quit ...")
+ bAllowAutoSaveReactivation = sal_False;
+ implts_doSessionQuietQuit(aParams);
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_SESSION_RESTORE ) == AutoRecovery::E_SESSION_RESTORE ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do session restore ...")
+ implts_doSessionRestore(aParams);
+ }
+ else
+ if (
+ ((eJob & AutoRecovery::E_ENTRY_BACKUP ) == AutoRecovery::E_ENTRY_BACKUP ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ implts_backupWorkingEntry(aParams);
+ else
+ if (
+ ((eJob & AutoRecovery::E_ENTRY_CLEANUP ) == AutoRecovery::E_ENTRY_CLEANUP ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ implts_cleanUpWorkingEntry(aParams);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {} // TODO better error handling
+
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_STOP, NULL));
+
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+ m_eJob = E_NO_JOB;
+ if (
+ (bAllowAutoSaveReactivation) &&
+ (bWasAutoSaveActive )
+ )
+ {
+ m_eJob |= AutoRecovery::E_AUTO_SAVE;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // depends on bAllowAutoSaveReactivation implicitly by looking on m_eJob=E_AUTO_SAVE! see before ...
+ implts_updateTimer();
+
+ if (bAllowAutoSaveReactivation)
+ implts_startListening();
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener,
+ const css::util::URL& aURL )
+ throw(css::uno::RuntimeException)
+{
+ if (!xListener.is())
+ throw css::uno::RuntimeException(::rtl::OUString::createFromAscii("Invalid listener reference."), static_cast< css::frame::XDispatch* >(this));
+ // container is threadsafe by using a shared mutex!
+ m_lListener.addInterface(aURL.Complete, xListener);
+
+ // REENTRANT !? -> --------------------------------
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // THREAD SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ css::frame::FeatureStateEvent aEvent = AutoRecovery::implst_createFeatureStateEvent(m_eJob, OPERATION_UPDATE, &rInfo);
+
+ // <- SAFE ------------------------------
+ aReadLock.unlock();
+ xListener->statusChanged(aEvent);
+ aReadLock.lock();
+ // SAFE -> ------------------------------
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener,
+ const css::util::URL& aURL )
+ throw(css::uno::RuntimeException)
+{
+ if (!xListener.is())
+ throw css::uno::RuntimeException(::rtl::OUString::createFromAscii("Invalid listener reference."), static_cast< css::frame::XDispatch* >(this));
+ // container is threadsafe by using a shared mutex!
+ m_lListener.removeInterface(aURL.Complete, xListener);
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::notifyEvent(const css::document::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY);
+
+ // new document => put it into the internal list
+ if (
+ (aEvent.EventName.equals(EVENT_ON_NEW )) ||
+ (aEvent.EventName.equals(EVENT_ON_LOAD))
+ )
+ {
+ implts_registerDocument(xDocument);
+ }
+ // document modified => set its modify state new (means modified against the original file!)
+ else
+ if (aEvent.EventName.equals(EVENT_ON_MODIFYCHANGED))
+ {
+ implts_updateModifiedState(xDocument);
+ }
+ /* at least one document starts saving process =>
+ Our application code isnt ready for multiple save requests
+ at the same time. So we have to supress our AutoSave feature
+ for the moment, till this other save requests will be finished.
+ */
+ else
+ if (
+ (aEvent.EventName.equals(EVENT_ON_SAVE )) ||
+ (aEvent.EventName.equals(EVENT_ON_SAVEAS)) ||
+ (aEvent.EventName.equals(EVENT_ON_SAVETO))
+ )
+ {
+ implts_updateDocumentUsedForSavingState(xDocument, SAVE_IN_PROGRESS);
+ }
+ // document saved => remove tmp. files - but hold config entries alive!
+ else
+ if (
+ (aEvent.EventName.equals(EVENT_ON_SAVEDONE )) ||
+ (aEvent.EventName.equals(EVENT_ON_SAVEASDONE))
+ )
+ {
+ implts_markDocumentAsSaved(xDocument);
+ implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED);
+ }
+ /* document saved as copy => mark it as "non used by concurrent save operation".
+ so we can try to create a backup copy if next time AutoSave is started too.
+ Dont remove temp. files or change the modified state of the document!
+ It was not realy saved to the original file ...
+ */
+ else
+ if (aEvent.EventName.equals(EVENT_ON_SAVETODONE))
+ {
+ implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED);
+ }
+ // If saving of a document failed by an error ... we have to save this document
+ // by ourself next time AutoSave or EmergencySave is triggered.
+ // But we can reset the state "used for other save requests". Otherwhise
+ // these documents will never be saved!
+ else
+ if (
+ (aEvent.EventName.equals(EVENT_ON_SAVEFAILED )) ||
+ (aEvent.EventName.equals(EVENT_ON_SAVEASFAILED)) ||
+ (aEvent.EventName.equals(EVENT_ON_SAVETOFAILED))
+ )
+ {
+ implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED);
+ }
+ // document closed => remove temp. files and configuration entries
+ else
+ if (aEvent.EventName.equals(EVENT_ON_UNLOAD))
+ {
+ implts_deregisterDocument(xDocument, sal_True); // sal_True => stop listening for disposing() !
+ }
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::changesOccurred(const css::util::ChangesEvent& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ const css::uno::Sequence< css::util::ElementChange > lChanges (aEvent.Changes);
+ const css::util::ElementChange* pChanges = lChanges.getConstArray();
+
+ sal_Int32 c = lChanges.getLength();
+ sal_Int32 i = 0;
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // Changes of the configuration must be ignored if AutoSave/Recovery was disabled for this
+ // office session. That can happen if e.g. the command line arguments "-norestore" or "-headless"
+ // was set.
+ if ((m_eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY)
+ return;
+
+ for (i=0; i<c; ++i)
+ {
+ ::rtl::OUString sPath;
+ pChanges[i].Accessor >>= sPath;
+
+ if (sPath.equals(CFG_ENTRY_AUTOSAVE_ENABLED))
+ {
+ sal_Bool bEnabled = sal_False;
+ if (pChanges[i].Element >>= bEnabled)
+ {
+ if (bEnabled)
+ {
+ m_eJob |= AutoRecovery::E_AUTO_SAVE;
+ m_eTimerType = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL;
+ }
+ else
+ {
+ m_eJob &= ~AutoRecovery::E_AUTO_SAVE;
+ m_eTimerType = AutoRecovery::E_DONT_START_TIMER;
+ }
+ }
+ }
+ else
+ if (sPath.equals(CFG_ENTRY_AUTOSAVE_TIMEINTERVALL))
+ pChanges[i].Element >>= m_nAutoSaveTimeIntervall;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // Note: This call stops the timer and starts it again.
+ // But it checks the different timer states internaly and
+ // may be supress the restart!
+ implts_updateTimer();
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::modified(const css::lang::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY);
+ if (! xDocument.is())
+ return;
+
+ implts_markDocumentModifiedAgainstLastBackup(xDocument);
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::disposing(const css::lang::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (aEvent.Source == m_xNewDocBroadcaster)
+ {
+ m_xNewDocBroadcaster.clear();
+ return;
+ }
+
+ if (aEvent.Source == m_xRecoveryCFG)
+ {
+ m_xRecoveryCFG.clear();
+ return;
+ }
+
+ // dispose from one of our cached documents ?
+ // Normaly they should send a OnUnload message ...
+ // But some stacktraces shows another possible use case .-)
+ css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY);
+ if (xDocument.is())
+ {
+ implts_deregisterDocument(xDocument, sal_False); // sal_False => dont call removeEventListener() .. because it's not needed here
+ return;
+ }
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::container::XNameAccess > AutoRecovery::implts_openConfig()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_xRecoveryCFG.is())
+ return m_xRecoveryCFG;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // throws a RuntimeException if an error occure!
+ css::uno::Reference< css::container::XNameAccess > xCFG(
+ ::comphelper::ConfigurationHelper::openConfig(xSMGR, CFG_PACKAGE_RECOVERY, ::comphelper::ConfigurationHelper::E_STANDARD),
+ css::uno::UNO_QUERY);
+
+ sal_Int32 nMinSpaceDocSave = MIN_DISCSPACE_DOCSAVE;
+ sal_Int32 nMinSpaceConfigSave = MIN_DISCSPACE_CONFIGSAVE;
+
+ try
+ {
+ ::comphelper::ConfigurationHelper::readDirectKey(xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_AUTOSAVE,
+ CFG_ENTRY_MINSPACE_DOCSAVE,
+ ::comphelper::ConfigurationHelper::E_STANDARD) >>= nMinSpaceDocSave;
+
+ ::comphelper::ConfigurationHelper::readDirectKey(xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_AUTOSAVE,
+ CFG_ENTRY_MINSPACE_CONFIGSAVE,
+ ::comphelper::ConfigurationHelper::E_STANDARD) >>= nMinSpaceConfigSave;
+ }
+ catch(const css::uno::Exception&)
+ {
+ // These config keys are not sooooo important, that
+ // we are interested on errors here realy .-)
+ nMinSpaceDocSave = MIN_DISCSPACE_DOCSAVE;
+ nMinSpaceConfigSave = MIN_DISCSPACE_CONFIGSAVE;
+ }
+
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+ m_xRecoveryCFG = xCFG;
+ m_nMinSpaceDocSave = nMinSpaceDocSave;
+ m_nMinSpaceConfigSave = nMinSpaceConfigSave;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return xCFG;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_readAutoSaveConfig()
+{
+ css::uno::Reference< css::container::XHierarchicalNameAccess > xCommonRegistry(implts_openConfig(), css::uno::UNO_QUERY);
+
+ // AutoSave [bool]
+ sal_Bool bEnabled = sal_False;
+ xCommonRegistry->getByHierarchicalName(CFG_ENTRY_AUTOSAVE_ENABLED) >>= bEnabled;
+
+ // SAFE -> ------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ if (bEnabled)
+ {
+ m_eJob |= AutoRecovery::E_AUTO_SAVE;
+ m_eTimerType = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL;
+ }
+ else
+ {
+ m_eJob &= ~AutoRecovery::E_AUTO_SAVE;
+ m_eTimerType = AutoRecovery::E_DONT_START_TIMER;
+ }
+ aWriteLock.unlock();
+ // <- SAFE ------------------------------
+
+ // AutoSaveTimeIntervall [int] in min
+ sal_Int32 nTimeIntervall = 15;
+ xCommonRegistry->getByHierarchicalName(CFG_ENTRY_AUTOSAVE_TIMEINTERVALL) >>= nTimeIntervall;
+
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+ m_nAutoSaveTimeIntervall = nTimeIntervall;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_readConfig()
+{
+ implts_readAutoSaveConfig();
+
+ css::uno::Reference< css::container::XHierarchicalNameAccess > xCommonRegistry(implts_openConfig(), css::uno::UNO_QUERY);
+
+ // REENTRANT -> --------------------------------
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE);
+
+ // THREADSAFE -> -------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ // reset current cache load cache
+ m_lDocCache.clear();
+ m_nIdPool = 0;
+ aWriteLock.unlock();
+ // <- THREADSAFE -------------------------------
+
+ aCacheLock.unlock();
+ // <- REENTRANT --------------------------------
+
+ css::uno::Any aValue;
+
+ // RecoveryList [set]
+ aValue = xCommonRegistry->getByHierarchicalName(CFG_ENTRY_RECOVERYLIST);
+ css::uno::Reference< css::container::XNameAccess > xList;
+ aValue >>= xList;
+ if (xList.is())
+ {
+ const css::uno::Sequence< ::rtl::OUString > lItems = xList->getElementNames();
+ const ::rtl::OUString* pItems = lItems.getConstArray();
+ sal_Int32 c = lItems.getLength();
+ sal_Int32 i = 0;
+
+ // REENTRANT -> --------------------------
+ aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE);
+
+ for (i=0; i<c; ++i)
+ {
+ css::uno::Reference< css::beans::XPropertySet > xItem;
+ xList->getByName(pItems[i]) >>= xItem;
+ if (!xItem.is())
+ continue;
+
+ AutoRecovery::TDocumentInfo aInfo;
+ aInfo.NewTempURL = ::rtl::OUString();
+ aInfo.Document = css::uno::Reference< css::frame::XModel >();
+ xItem->getPropertyValue(CFG_ENTRY_PROP_ORIGINALURL ) >>= aInfo.OrgURL ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_TEMPURL ) >>= aInfo.OldTempURL ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_TEMPLATEURL ) >>= aInfo.TemplateURL ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_FILTER ) >>= aInfo.RealFilter ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE) >>= aInfo.DocumentState;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_MODULE ) >>= aInfo.AppModule ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_TITLE ) >>= aInfo.Title ;
+ xItem->getPropertyValue(CFG_ENTRY_PROP_VIEWNAMES ) >>= aInfo.ViewNames ;
+ implts_specifyAppModuleAndFactory(aInfo);
+ implts_specifyDefaultFilterAndExtension(aInfo);
+
+ if (pItems[i].indexOf(RECOVERY_ITEM_BASE_IDENTIFIER)==0)
+ {
+ ::rtl::OUString sID = pItems[i].copy(RECOVERY_ITEM_BASE_IDENTIFIER.getLength());
+ aInfo.ID = sID.toInt32();
+ // SAFE -> ----------------------
+ aWriteLock.lock();
+ if (aInfo.ID > m_nIdPool)
+ {
+ m_nIdPool = aInfo.ID+1;
+ LOG_ASSERT(m_nIdPool>=0, "AutoRecovery::implts_readConfig()\nOverflow of IDPool detected!")
+ }
+ aWriteLock.unlock();
+ // <- SAFE ----------------------
+ }
+ #ifdef ENABLE_WARNINGS
+ else
+ LOG_WARNING("AutoRecovery::implts_readConfig()", "Who changed numbering of recovery items? Cache will be inconsistent then! I do not know, what will happen next time .-)")
+ #endif
+
+ // THREADSAFE -> --------------------------
+ aWriteLock.lock();
+ m_lDocCache.push_back(aInfo);
+ aWriteLock.unlock();
+ // <- THREADSAFE --------------------------
+ }
+
+ aCacheLock.unlock();
+ // <- REENTRANT --------------------------
+ }
+
+ implts_updateTimer();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_specifyDefaultFilterAndExtension(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if (!rInfo.AppModule.getLength())
+ {
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Cant find out the default filter and its extension, if no application module is known!"),
+ static_cast< css::frame::XDispatch* >(this));
+ }
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::container::XNameAccess> xCFG = m_xModuleCFG;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ try
+ {
+ if (! xCFG.is())
+ {
+ // open module config on demand and cache the update access
+ xCFG = css::uno::Reference< css::container::XNameAccess >(
+ ::comphelper::ConfigurationHelper::openConfig(xSMGR, CFG_PACKAGE_MODULES, ::comphelper::ConfigurationHelper::E_STANDARD),
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_xModuleCFG = xCFG;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+ }
+
+ css::uno::Reference< css::container::XNameAccess > xModuleProps(
+ xCFG->getByName(rInfo.AppModule),
+ css::uno::UNO_QUERY_THROW);
+
+ xModuleProps->getByName(CFG_ENTRY_REALDEFAULTFILTER) >>= rInfo.DefaultFilter;
+
+ css::uno::Reference< css::container::XNameAccess > xFilterCFG(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xTypeCFG (xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY_THROW);
+
+ ::comphelper::SequenceAsHashMap lFilterProps (xFilterCFG->getByName(rInfo.DefaultFilter));
+ ::rtl::OUString sTypeRegistration = lFilterProps.getUnpackedValueOrDefault(FILTER_PROP_TYPE, ::rtl::OUString());
+ ::comphelper::SequenceAsHashMap lTypeProps (xTypeCFG->getByName(sTypeRegistration));
+ css::uno::Sequence< ::rtl::OUString > lExtensions = lTypeProps.getUnpackedValueOrDefault(TYPE_PROP_EXTENSIONS, css::uno::Sequence< ::rtl::OUString >());
+ if (lExtensions.getLength())
+ {
+ rInfo.Extension = ::rtl::OUString::createFromAscii(".");
+ rInfo.Extension += lExtensions[0];
+ }
+ else
+ rInfo.Extension = ::rtl::OUString::createFromAscii(".unknown");
+ }
+ catch(const css::uno::Exception&)
+ {
+ rInfo.DefaultFilter = ::rtl::OUString();
+ rInfo.Extension = ::rtl::OUString();
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_specifyAppModuleAndFactory(AutoRecovery::TDocumentInfo& rInfo)
+{
+ ENSURE_OR_THROW2(
+ rInfo.AppModule.getLength() || rInfo.Document.is(),
+ "Cant find out the application module nor its factory URL, if no application module (or a suitable) document is known!",
+ *this );
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XModuleManager > xManager (xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xModuleConfig(xManager , css::uno::UNO_QUERY_THROW);
+
+ if (!rInfo.AppModule.getLength())
+ rInfo.AppModule = xManager->identify(rInfo.Document);
+
+ ::comphelper::SequenceAsHashMap lModuleDescription(xModuleConfig->getByName(rInfo.AppModule));
+ lModuleDescription[CFG_ENTRY_PROP_EMPTYDOCUMENTURL] >>= rInfo.FactoryURL;
+ lModuleDescription[CFG_ENTRY_PROP_FACTORYSERVICE] >>= rInfo.FactoryService;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_collectActiveViewNames( AutoRecovery::TDocumentInfo& i_rInfo )
+{
+ ENSURE_OR_THROW2( i_rInfo.Document.is(), "need at document, at the very least", *this );
+
+ i_rInfo.ViewNames.realloc(0);
+
+ // obtain list of controllers of this document
+ ::std::vector< ::rtl::OUString > aViewNames;
+ const Reference< XModel2 > xModel( i_rInfo.Document, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ const Reference< XEnumeration > xEnumControllers( xModel->getControllers() );
+ while ( xEnumControllers->hasMoreElements() )
+ {
+ const Reference< XController2 > xController( xEnumControllers->nextElement(), UNO_QUERY );
+ ::rtl::OUString sViewName;
+ if ( xController.is() )
+ sViewName = xController->getViewControllerName();
+ OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" );
+
+ if ( sViewName.getLength() )
+ aViewNames.push_back( sViewName );
+ }
+ }
+ else
+ {
+ const Reference< XController2 > xController( xModel->getCurrentController(), UNO_QUERY );
+ ::rtl::OUString sViewName;
+ if ( xController.is() )
+ sViewName = xController->getViewControllerName();
+ OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" );
+
+ if ( sViewName.getLength() )
+ aViewNames.push_back( sViewName );
+ }
+
+ i_rInfo.ViewNames.realloc( aViewNames.size() );
+ ::std::copy( aViewNames.begin(), aViewNames.end(), i_rInfo.ViewNames.getArray() );
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_persistAllActiveViewNames()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // This list will be filled with every document
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ implts_collectActiveViewNames( *pIt );
+ implts_flushConfigItem( *pIt );
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_flushConfigItem(const AutoRecovery::TDocumentInfo& rInfo, sal_Bool bRemoveIt)
+{
+ css::uno::Reference< css::container::XHierarchicalNameAccess > xCFG;
+
+ try
+ {
+ xCFG = css::uno::Reference< css::container::XHierarchicalNameAccess >(implts_openConfig(), css::uno::UNO_QUERY_THROW);
+
+ css::uno::Reference< css::container::XNameAccess > xCheck;
+ xCFG->getByHierarchicalName(CFG_ENTRY_RECOVERYLIST) >>= xCheck;
+
+ css::uno::Reference< css::container::XNameContainer > xModify(xCheck, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::lang::XSingleServiceFactory > xCreate(xCheck, css::uno::UNO_QUERY_THROW);
+
+ ::rtl::OUStringBuffer sIDBuf;
+ sIDBuf.append(RECOVERY_ITEM_BASE_IDENTIFIER);
+ sIDBuf.append((sal_Int32)rInfo.ID);
+ ::rtl::OUString sID = sIDBuf.makeStringAndClear();
+
+ // remove
+ if (bRemoveIt)
+ {
+ // Catch NoSuchElementException.
+ // Its not a good idea inside multithreaded environments to call hasElement - removeElement.
+ // DO IT!
+ try
+ {
+ xModify->removeByName(sID);
+ }
+ catch(const css::container::NoSuchElementException&)
+ { return; }
+ }
+ else
+ {
+ // new/modify
+ css::uno::Reference< css::beans::XPropertySet > xSet;
+ sal_Bool bNew = (!xCheck->hasByName(sID));
+ if (bNew)
+ xSet = css::uno::Reference< css::beans::XPropertySet >(xCreate->createInstance(), css::uno::UNO_QUERY_THROW);
+ else
+ xCheck->getByName(sID) >>= xSet;
+
+ xSet->setPropertyValue(CFG_ENTRY_PROP_ORIGINALURL , css::uno::makeAny(rInfo.OrgURL ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_TEMPURL , css::uno::makeAny(rInfo.OldTempURL ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_TEMPLATEURL , css::uno::makeAny(rInfo.TemplateURL ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_FILTER , css::uno::makeAny(rInfo.RealFilter ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE, css::uno::makeAny(rInfo.DocumentState));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_MODULE , css::uno::makeAny(rInfo.AppModule ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_TITLE , css::uno::makeAny(rInfo.Title ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_VIEWNAMES , css::uno::makeAny(rInfo.ViewNames ));
+
+ if (bNew)
+ xModify->insertByName(sID, css::uno::makeAny(xSet));
+ }
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {} // ??? can it happen that a full disc let these set of operations fail too ???
+
+ sal_Int32 nRetry = RETRY_STORE_ON_FULL_DISC_FOREVER;
+ do
+ {
+ try
+ {
+ css::uno::Reference< css::util::XChangesBatch > xFlush(xCFG, css::uno::UNO_QUERY_THROW);
+ xFlush->commitChanges();
+
+ #ifdef TRIGGER_FULL_DISC_CHECK
+ throw css::uno::Exception();
+ #endif
+
+ nRetry = 0;
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ // a) FULL DISC seams to be the problem behind => show error and retry it forever (e.g. retry=300)
+ // b) unknown problem (may be locking problem) => reset RETRY value to more usefull value(!) (e.g. retry=3)
+ // c) unknown problem (may be locking problem) + 1..2 repeating operations => throw the original exception to force generation of a stacktrace !
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ sal_Int32 nMinSpaceConfigSave = m_nMinSpaceConfigSave;
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (! impl_enoughDiscSpace(nMinSpaceConfigSave))
+ AutoRecovery::impl_showFullDiscError();
+ else
+ if (nRetry > RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL)
+ nRetry = RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL;
+ else
+ if (nRetry <= GIVE_UP_RETRY)
+ throw ex; // force stacktrace to know if there exist might other reasons, why an AutoSave can fail !!!
+
+ --nRetry;
+ }
+ }
+ while(nRetry>0);
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_startListening()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::util::XChangesNotifier > xCFG (m_xRecoveryCFG, css::uno::UNO_QUERY);
+ css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster = m_xNewDocBroadcaster;
+ sal_Bool bListenForDocEvents = m_bListenForDocEvents;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (
+ ( xCFG.is() ) &&
+ (! m_bListenForConfigChanges)
+ )
+ {
+ xCFG->addChangesListener(static_cast< css::util::XChangesListener* >(this));
+ m_bListenForConfigChanges = sal_True;
+ }
+
+ if (!xBroadcaster.is())
+ {
+ xBroadcaster = css::uno::Reference< css::document::XEventBroadcaster >(xSMGR->createInstance(SERVICENAME_GLOBALEVENTBROADCASTER), css::uno::UNO_QUERY_THROW);
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_xNewDocBroadcaster = xBroadcaster;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+ }
+
+ if (
+ ( xBroadcaster.is() ) &&
+ (! bListenForDocEvents)
+ )
+ {
+ xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this));
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_bListenForDocEvents = sal_True;
+ aWriteLock.unlock();
+ // <- SAFE
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_stopListening()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ // Attention: Dont reset our internal members here too.
+ // May be we must work with our configuration, but dont wish to be informed
+ // about changes any longer. Needed e.g. during EMERGENCY_SAVE!
+ css::uno::Reference< css::util::XChangesNotifier > xCFG (m_xRecoveryCFG , css::uno::UNO_QUERY);
+ css::uno::Reference< css::document::XEventBroadcaster > xGlobalEventBroadcaster(m_xNewDocBroadcaster, css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (
+ (xGlobalEventBroadcaster.is()) &&
+ (m_bListenForDocEvents )
+ )
+ {
+ xGlobalEventBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this));
+ m_bListenForDocEvents = sal_False;
+ }
+
+ if (
+ (xCFG.is() ) &&
+ (m_bListenForConfigChanges)
+ )
+ {
+ xCFG->removeChangesListener(static_cast< css::util::XChangesListener* >(this));
+ m_bListenForConfigChanges = sal_False;
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_startModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if (rInfo.ListenForModify)
+ return;
+
+ css::uno::Reference< css::util::XModifyBroadcaster > xBroadcaster(rInfo.Document, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ {
+ css::uno::Reference< css::util::XModifyListener > xThis(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY);
+ xBroadcaster->addModifyListener(xThis);
+ rInfo.ListenForModify = sal_True;
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_stopModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if (! rInfo.ListenForModify)
+ return;
+
+ css::uno::Reference< css::util::XModifyBroadcaster > xBroadcaster(rInfo.Document, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ {
+ css::uno::Reference< css::util::XModifyListener > xThis(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY);
+ xBroadcaster->removeModifyListener(xThis);
+ rInfo.ListenForModify = sal_False;
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_updateTimer()
+{
+ implts_stopTimer();
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (
+ (m_eJob == AutoRecovery::E_NO_JOB ) || // TODO may be superflous - E_DONT_START_TIMER should be used only
+ (m_eTimerType == AutoRecovery::E_DONT_START_TIMER)
+ )
+ return;
+
+ sal_uLong nMilliSeconds = 0;
+ if (m_eTimerType == AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL)
+ {
+ nMilliSeconds = (m_nAutoSaveTimeIntervall*60000); // [min] => 60.000 ms
+ #if OSL_DEBUG_LEVEL > 1
+ if (m_dbg_bMakeItFaster)
+ nMilliSeconds = m_nAutoSaveTimeIntervall; // [ms]
+ #endif
+ }
+ else
+ if (m_eTimerType == AutoRecovery::E_POLL_FOR_USER_IDLE)
+ {
+ nMilliSeconds = MIN_TIME_FOR_USER_IDLE;
+ #if OSL_DEBUG_LEVEL > 1
+ if (m_dbg_bMakeItFaster)
+ nMilliSeconds = 300; // let us some time, to finish this method .-)
+ #endif
+ }
+ else
+ if (m_eTimerType == AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED)
+ nMilliSeconds = 300; // there is a minimum time frame, where the user can loose some key input data!
+
+ m_aTimer.SetTimeout(nMilliSeconds);
+ m_aTimer.Start();
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_stopTimer()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (!m_aTimer.IsActive())
+ return;
+ m_aTimer.Stop();
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+IMPL_LINK(AutoRecovery, implts_timerExpired, void*, EMPTYARG)
+{
+ try
+ {
+ // This method is called by using a pointer to us.
+ // But we must be aware that we can be destroyed hardly
+ // if our uno reference will be gone!
+ // => Hold this object alive till this method finish its work.
+ css::uno::Reference< css::uno::XInterface > xSelfHold(static_cast< css::lang::XTypeProvider* >(this));
+
+ // Needed! Otherwise every reschedule request allow a new triggered timer event :-(
+ implts_stopTimer();
+
+ // The timer must be ignored if AutoSave/Recovery was disabled for this
+ // office session. That can happen if e.g. the command line arguments "-norestore" or "-headless"
+ // was set. But normaly the timer was disabled if recovery was disabled ...
+ // But so we are more "safe" .-)
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ if ((m_eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY)
+ return 0;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // check some "states", where its not allowed (better: not a good idea) to
+ // start an AutoSave. (e.g. if the user makes drag & drop ...)
+ // Then we poll till this "disallowed" state is gone.
+ sal_Bool bAutoSaveNotAllowed = Application::IsUICaptured();
+ if (bAutoSaveNotAllowed)
+ {
+ // SAFE -> ------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_eTimerType = AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED;
+ aWriteLock.unlock();
+ // <- SAFE ------------------------------
+ implts_updateTimer();
+ return 0;
+ }
+
+ // analyze timer type.
+ // If we poll for an user idle period, may be we must
+ // do nothing here and start the timer again.
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_eTimerType == AutoRecovery::E_POLL_FOR_USER_IDLE)
+ {
+ sal_Bool bUserIdle = (Application::GetLastInputInterval()>MIN_TIME_FOR_USER_IDLE);
+ if (!bUserIdle)
+ {
+ implts_updateTimer();
+ return 0;
+ }
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ implts_informListener(AutoRecovery::E_AUTO_SAVE,
+ AutoRecovery::implst_createFeatureStateEvent(AutoRecovery::E_AUTO_SAVE, OPERATION_START, NULL));
+
+ // force save of all currently open documents
+ // The called method returns an info, if and how this
+ // timer must be restarted.
+ sal_Bool bAllowUserIdleLoop = sal_True;
+ AutoRecovery::ETimerType eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_False);
+
+ // If timer isnt used for "short callbacks" (means polling
+ // for special states) ... reset the handle state of all
+ // cache items. Such handle state indicates, that a document
+ // was already saved during the THIS(!) AutoSave session.
+ // Of course NEXT AutoSave session must be started without
+ // any "handle" state ...
+ if (
+ (eSuggestedTimer == AutoRecovery::E_DONT_START_TIMER ) ||
+ (eSuggestedTimer == AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL)
+ )
+ {
+ implts_resetHandleStates(sal_False);
+ }
+
+ implts_informListener(AutoRecovery::E_AUTO_SAVE,
+ AutoRecovery::implst_createFeatureStateEvent(AutoRecovery::E_AUTO_SAVE, OPERATION_STOP, NULL));
+
+ // restart timer - because it was disabled before ...
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+ m_eTimerType = eSuggestedTimer;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ implts_updateTimer();
+ }
+ catch(const css::uno::Exception&)
+ {
+ LOG_ASSERT(sal_False, "May be you found the reason for bug #125528#. Please report a test scenario to the right developer. THX.");
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------
+IMPL_LINK(AutoRecovery, implts_asyncDispatch, void*, EMPTYARG)
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ DispatchParams aParams = m_aDispatchParams;
+ css::uno::Reference< css::uno::XInterface > xHoldRefForMethodAlive = aParams.m_xHoldRefForAsyncOpAlive;
+ m_aDispatchParams.forget(); // clears all members ... including the ref-hold object .-)
+ aWriteLock.unlock();
+ // <- SAFE
+
+ implts_dispatch(aParams);
+ return 0;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame::XModel >& xDocument)
+{
+ // ignore corrupted events, where no document is given ... Runtime Error ?!
+ if (!xDocument.is())
+ return;
+
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // notification for already existing document !
+ // Can happen if events came in asynchronous on recovery time.
+ // Then our cache was filled from the configuration ... but now we get some
+ // asynchronous events from the global event broadcaster. We must be sure that
+ // we dont add the same document more then once.
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt != m_lDocCache.end())
+ {
+ // Normaly nothing must be done for this "late" notification.
+ // But may be the modified state was changed inbetween.
+ // Check it ...
+ implts_updateModifiedState(xDocument);
+ return;
+ }
+
+ aCacheLock.unlock();
+
+ ::comphelper::MediaDescriptor lDescriptor(xDocument->getArgs());
+
+ // check if this document must be ignored for recovery !
+ // Some use cases dont wish support for AutoSave/Recovery ... as e.g. OLE-Server / ActiveX Control etcpp.
+ sal_Bool bNoAutoSave = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_NOAUTOSAVE(), (sal_Bool)(sal_False));
+ if (bNoAutoSave)
+ return;
+
+ // Check if doc is well known on the desktop. Otherwhise ignore it!
+ // Other frames mostly are used from external programs - e.g. the bean ...
+ css::uno::Reference< css::frame::XController > xController = xDocument->getCurrentController();
+ if (!xController.is())
+ return;
+
+ css::uno::Reference< css::frame::XFrame > xFrame = xController->getFrame();
+ css::uno::Reference< css::frame::XDesktop > xDesktop (xFrame->getCreator(), css::uno::UNO_QUERY);
+ if (!xDesktop.is())
+ return;
+
+ // if the document doesn't support the XDocumentRecovery interface, we're not interested in it.
+ Reference< XDocumentRecovery > xDocRecovery( xDocument, UNO_QUERY );
+ if ( !xDocRecovery.is() )
+ return;
+
+ // get all needed informations of this document
+ // We need it to update our cache or to locate already existing elements there!
+ AutoRecovery::TDocumentInfo aNew;
+ aNew.Document = xDocument;
+
+ // TODO replace getLocation() with getURL() ... its a workaround currently only!
+ css::uno::Reference< css::frame::XStorable > xDoc(aNew.Document, css::uno::UNO_QUERY_THROW);
+ aNew.OrgURL = xDoc->getLocation();
+
+ css::uno::Reference< css::frame::XTitle > xTitle(aNew.Document, css::uno::UNO_QUERY_THROW);
+ aNew.Title = xTitle->getTitle ();
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // classify the used application module, which is used by this document.
+ implts_specifyAppModuleAndFactory(aNew);
+
+ // Hack! Check for "illegal office documents" ... as e.g. the Basic IDE
+ // Its not realy a full featured office document. It doesnt provide an URL, any filter, a factory URL etcpp.
+ // TODO file bug to Basci IDE developers. They must remove the office document API from its service.
+ if (
+ (!aNew.OrgURL.getLength() ) &&
+ (!aNew.FactoryURL.getLength())
+ )
+ {
+ OSL_ENSURE( false, "AutoRecovery::implts_registerDocument: this should not happen anymore!" );
+ // nowadays, the Basic IDE should already die on the "supports XDocumentRecovery" check. And no other known
+ // document type fits in here ...
+ return;
+ }
+
+ // By the way - get some information about the default format for saving!
+ // and save an information about the real used filter by this document.
+ // We save this document with DefaultFilter ... and load it with the RealFilter.
+ implts_specifyDefaultFilterAndExtension(aNew);
+ aNew.RealFilter = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME() , ::rtl::OUString());
+
+ // Further we must know, if this document base on a template.
+ // Then we must load it in a different way.
+ css::uno::Reference< css::document::XDocumentPropertiesSupplier > xSupplier(aNew.Document, css::uno::UNO_QUERY);
+ if (xSupplier.is()) // optional interface!
+ {
+ css::uno::Reference< css::document::XDocumentProperties > xDocProps(xSupplier->getDocumentProperties(), css::uno::UNO_QUERY_THROW);
+ aNew.TemplateURL = xDocProps->getTemplateURL();
+ }
+
+ css::uno::Reference< css::util::XModifiable > xModifyCheck(xDocument, css::uno::UNO_QUERY_THROW);
+ if (xModifyCheck->isModified())
+ {
+ aNew.DocumentState |= AutoRecovery::E_MODIFIED;
+ }
+
+ aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // create a new cache entry ... this document isn't known.
+ ++m_nIdPool;
+ aNew.ID = m_nIdPool;
+ LOG_ASSERT(m_nIdPool>=0, "AutoRecovery::implts_registerDocument()\nOverflow of ID pool detected.")
+ m_lDocCache.push_back(aNew);
+
+ AutoRecovery::TDocumentList::iterator pIt1 = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ AutoRecovery::TDocumentInfo& rInfo = *pIt1;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ implts_flushConfigItem(rInfo);
+ implts_startModifyListeningOnDoc(rInfo);
+
+ aCacheLock.unlock();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_deregisterDocument(const css::uno::Reference< css::frame::XModel >& xDocument ,
+ sal_Bool bStopListening)
+{
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // Attention: Dont leave SAFE section, if you work with pIt!
+ // Because it points directly into the m_lDocCache list ...
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt == m_lDocCache.end())
+ return; // unknown document => not a runtime error! Because we register only a few documents. see registration ...
+
+ AutoRecovery::TDocumentInfo aInfo = *pIt;
+
+ aCacheLock.unlock();
+
+ // Sometimes we close documents by ourself.
+ // And these documents cant be deregistered.
+ // Otherwhise we loos our configuration data ... but need it !
+ // see SessionSave !
+ if (aInfo.IgnoreClosing)
+ return;
+
+ CacheLockGuard aCacheLock2(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE);
+ pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt != m_lDocCache.end())
+ m_lDocCache.erase(pIt);
+ pIt = m_lDocCache.end(); // otherwhise its not specified what pIt means!
+ aCacheLock2.unlock();
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ /* This method is called within disposing() of the document too. But there it's not a good idea to
+ deregister us as listener. Furter it make no sense - because the broadcaster dies.
+ So we supress deregistration in such case ...
+ */
+ if (bStopListening)
+ implts_stopModifyListeningOnDoc(aInfo);
+
+ AutoRecovery::st_impl_removeFile(aInfo.OldTempURL);
+ AutoRecovery::st_impl_removeFile(aInfo.NewTempURL);
+ implts_flushConfigItem(aInfo, sal_True); // sal_True => remove it from config
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_markDocumentModifiedAgainstLastBackup(const css::uno::Reference< css::frame::XModel >& xDocument)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt != m_lDocCache.end())
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+
+ /* Now we know, that this document was modified again and must be saved next time.
+ But we dont need this information for every e.g. key input of the user.
+ So we stop listening here.
+ But if the document was saved as temp. file we start listening for this event again.
+ */
+ implts_stopModifyListeningOnDoc(rInfo);
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_updateModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt != m_lDocCache.end())
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+
+ // use sal_True as fallback ... so we recognize every document on EmergencySave/AutoRecovery!
+ sal_Bool bModified = sal_True;
+ css::uno::Reference< css::util::XModifiable > xModify(xDocument, css::uno::UNO_QUERY);
+ if (xModify.is())
+ bModified = xModify->isModified();
+ if (bModified)
+ {
+ rInfo.DocumentState |= AutoRecovery::E_MODIFIED;
+ }
+ else
+ {
+ rInfo.DocumentState &= ~AutoRecovery::E_MODIFIED;
+ }
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_updateDocumentUsedForSavingState(const css::uno::Reference< css::frame::XModel >& xDocument ,
+ sal_Bool bSaveInProgress)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt == m_lDocCache.end())
+ return;
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ rInfo.UsedForSaving = bSaveInProgress;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
+ if (pIt == m_lDocCache.end())
+ return;
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+
+ rInfo.DocumentState = AutoRecovery::E_UNKNOWN;
+ // TODO replace getLocation() with getURL() ... its a workaround currently only!
+ css::uno::Reference< css::frame::XStorable > xDoc(rInfo.Document, css::uno::UNO_QUERY);
+ rInfo.OrgURL = xDoc->getLocation();
+
+ ::rtl::OUString sRemoveURL1 = rInfo.OldTempURL;
+ ::rtl::OUString sRemoveURL2 = rInfo.NewTempURL;
+ rInfo.OldTempURL = ::rtl::OUString();
+ rInfo.NewTempURL = ::rtl::OUString();
+
+ ::comphelper::MediaDescriptor lDescriptor(rInfo.Document->getArgs());
+ rInfo.RealFilter = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString());
+
+ css::uno::Reference< css::frame::XTitle > xDocTitle(xDocument, css::uno::UNO_QUERY);
+ if (xDocTitle.is ())
+ rInfo.Title = xDocTitle->getTitle ();
+ else
+ {
+ rInfo.Title = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TITLE() , ::rtl::OUString());
+ if (!rInfo.Title.getLength())
+ rInfo.Title = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTTITLE(), ::rtl::OUString());
+ }
+
+ rInfo.UsedForSaving = sal_False;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ implts_flushConfigItem(rInfo);
+
+ aCacheLock.unlock();
+
+ AutoRecovery::st_impl_removeFile(sRemoveURL1);
+ AutoRecovery::st_impl_removeFile(sRemoveURL2);
+}
+
+//-----------------------------------------------
+AutoRecovery::TDocumentList::iterator AutoRecovery::impl_searchDocument( AutoRecovery::TDocumentList& rList ,
+ const css::uno::Reference< css::frame::XModel >& xDocument)
+{
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = rList.begin();
+ pIt != rList.end() ;
+ ++pIt )
+ {
+ const AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ if (rInfo.Document == xDocument)
+ break;
+ }
+ return pIt;
+}
+
+//-----------------------------------------------
+namespace
+{
+ void lcl_changeVisibility( const css::uno::Reference< css::frame::XFramesSupplier >& i_rFrames, sal_Bool i_bVisible )
+ {
+ css::uno::Reference< css::container::XIndexAccess > xFramesContainer( i_rFrames->getFrames(), css::uno::UNO_QUERY );
+ const sal_Int32 count = xFramesContainer->getCount();
+
+ Any aElement;
+ for ( sal_Int32 i=0; i < count; ++i )
+ {
+ aElement = xFramesContainer->getByIndex(i);
+ // check for sub frames
+ css::uno::Reference< css::frame::XFramesSupplier > xFramesSupp( aElement, css::uno::UNO_QUERY );
+ if ( xFramesSupp.is() )
+ lcl_changeVisibility( xFramesSupp, i_bVisible );
+
+ css::uno::Reference< css::frame::XFrame > xFrame( aElement, css::uno::UNO_QUERY );
+ if ( !xFrame.is() )
+ continue;
+
+ css::uno::Reference< css::awt::XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ xWindow->setVisible( i_bVisible );
+ }
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_changeAllDocVisibility(sal_Bool bVisible)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
+ lcl_changeVisibility( xDesktop, bVisible );
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+/* Currently the document is not closed in case of crash,
+ so the lock file must be removed explicitly
+*/
+void lc_removeLockFile(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if ( rInfo.Document.is() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XStorable > xStore(rInfo.Document, css::uno::UNO_QUERY_THROW);
+ ::rtl::OUString aURL = xStore->getLocation();
+ if ( aURL.getLength() )
+ {
+ ::svt::DocumentLockFile aLockFile( aURL );
+ aLockFile.RemoveFile();
+ }
+ }
+ catch( const css::uno::Exception& )
+ {}
+ }
+}
+
+
+//-----------------------------------------------
+void AutoRecovery::implts_prepareSessionShutdown()
+{
+ LOG_RECOVERY("AutoRecovery::implts_prepareSessionShutdown() starts ...")
+
+ // a) reset modified documents (of course the must be saved before this method is called!)
+ // b) close it without showing any UI!
+
+ // SAFE ->
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+
+ // WORKAROUND... Since the documents are not closed the lock file must be removed explicitly
+ // it is not done on documents saving since shutdown can be cancelled
+ lc_removeLockFile( rInfo );
+
+ // Prevent us from deregistration of these documents.
+ // Because we close these documents by ourself (see XClosable below) ...
+ // it's fact, that we reach our deregistration method. There we
+ // must not(!) update our configuration ... Otherwhise all
+ // session data are lost !!!
+ rInfo.IgnoreClosing = sal_True;
+
+ // reset modified flag of these documents (ignoring the notification about it!)
+ // Otherwise a message box is shown on closing these models.
+ implts_stopModifyListeningOnDoc(rInfo);
+
+ // if the session save is still running the documents should not be thrown away,
+ // actually that would be a bad sign, that means that the SessionManager tryes
+ // to kill the session before the saving is ready
+ if ((m_eJob & AutoRecovery::E_SESSION_SAVE) != AutoRecovery::E_SESSION_SAVE)
+ {
+ css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY);
+ if (xModify.is())
+ xModify->setModified(sal_False);
+
+ // close the model.
+ css::uno::Reference< css::util::XCloseable > xClose(rInfo.Document, css::uno::UNO_QUERY);
+ if (xClose.is())
+ {
+ try
+ {
+ xClose->close(sal_False);
+ }
+ /*
+ catch(const css::lang::DisposedException&)
+ {
+ // closed ... disposed ... always the same .-)
+ }
+ */
+ catch(const css::uno::Exception&)
+ {
+ // At least it's only a try to close these documents before anybody else it does.
+ // So it seams to be possible to ignore any error here .-)
+ }
+
+ rInfo.Document.clear();
+ }
+ }
+ }
+
+ aCacheLock.unlock();
+ // <- SAFE
+}
+
+//-----------------------------------------------
+/* TODO WORKAROUND:
+
+ #i64599#
+
+ Normaly the MediaDescriptor argument NoAutoSave indicates,
+ that a document must be ignored for AutoSave and Recovery.
+ But sometimes XModel->getArgs() does not contained this information
+ if implts_registerDocument() was called.
+ So we have to check a second time, if this property is set ....
+ Best place doing so is to check it immeditaly before saving
+ and supressingd saving the document then.
+ Of course removing the corresponding cache entry isnt an option.
+ Because it would disturb iteration over the cache !
+ So we ignore such documents only ...
+ Hopefully next time they are not inserted in our cache.
+*/
+sal_Bool lc_checkIfSaveForbiddenByArguments(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if (! rInfo.Document.is())
+ return sal_True;
+
+ ::comphelper::MediaDescriptor lDescriptor(rInfo.Document->getArgs());
+ sal_Bool bNoAutoSave = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_NOAUTOSAVE(), (sal_Bool)(sal_False));
+
+ return bNoAutoSave;
+}
+
+//-----------------------------------------------
+AutoRecovery::ETimerType AutoRecovery::implts_saveDocs( sal_Bool bAllowUserIdleLoop,
+ sal_Bool bRemoveLockFiles,
+ const DispatchParams* pParams )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::task::XStatusIndicator > xExternalProgress;
+ if (pParams)
+ xExternalProgress = pParams->m_xProgress;
+
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop (xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
+ ::rtl::OUString sBackupPath (SvtPathOptions().GetBackupPath());
+
+ css::uno::Reference< css::frame::XController > xActiveController;
+ css::uno::Reference< css::frame::XModel > xActiveModel ;
+ css::uno::Reference< css::frame::XFrame > xActiveFrame = xDesktop->getActiveFrame();
+ if (xActiveFrame.is())
+ xActiveController = xActiveFrame->getController();
+ if (xActiveController.is())
+ xActiveModel = xActiveController->getModel();
+
+ // Set the default timer action for our calli.
+ // Default = NORMAL_AUTOSAVE
+ // We return a suggestion for an active timer only.
+ // It will be ignored if the timer was disabled by the user ...
+ // Further this state can be set to USER_IDLE only later in this method.
+ // Its not allowed to reset such state then. Because we must know, if
+ // there exists POSTPONED documents. see below ...
+ AutoRecovery::ETimerType eTimer = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL;
+
+ sal_Int32 eJob = m_eJob;
+
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // This list will be filled with every document
+ // which should be saved as last one. E.g. if it was used
+ // already for an UI save operation => crashed ... and
+ // now we try to save it again ... which can fail again ( of course .-) ).
+ ::std::vector< AutoRecovery::TDocumentList::iterator > lDangerousDocs;
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo aInfo = *pIt;
+
+ // WORKAROUND... Since the documents are not closed the lock file must be removed explicitly
+ if ( bRemoveLockFiles )
+ lc_removeLockFile( aInfo );
+
+ // WORKAROUND ... see comment of this method
+ if (lc_checkIfSaveForbiddenByArguments(aInfo))
+ continue;
+
+ // already auto saved during this session :-)
+ // This state must be reset for all documents
+ // if timer is started with normnal AutoSaveTimerIntervall!
+ if ((aInfo.DocumentState & AutoRecovery::E_HANDLED) == AutoRecovery::E_HANDLED)
+ continue;
+
+ // Not modified documents are not saved.
+ // We safe an information about the URL only!
+ Reference< XDocumentRecovery > xDocRecover( aInfo.Document, UNO_QUERY_THROW );
+ if ( !xDocRecover->wasModifiedSinceLastSave() )
+ {
+ aInfo.DocumentState |= AutoRecovery::E_HANDLED;
+ continue;
+ }
+
+ // check if this document is still used by a concurrent save operation
+ // e.g. if the user tried to save via UI.
+ // Handle it in the following way:
+ // i) For an AutoSave ... ignore this document! It will be saved and next time we will (hopefully)
+ // get a notification about the state of this operation.
+ // And if a document was saved by the user we can remove our temp. file. But that will be done inside
+ // our callback for SaveDone notification.
+ // ii) For a CrashSave ... add it to the list of dangerous documents and
+ // save it after all other documents was saved successfully. That decrease
+ // the chance for a crash inside a crash.
+ // On the other side it's not neccessary for documents, which are not modified.
+ // They can be handled normaly - means we patch the corresponding configuration entry only.
+ // iii) For a SessionSave ... ignore it! There is no time to wait for this save operation.
+ // Because the WindowManager will kill the process if it doesnt react immediatly.
+ // On the other side we cant risk a concurrent save request ... because we know
+ // that it will produce a crash.
+
+ // Attention: Because eJob is used as a flag field, you have to check for the worst case first.
+ // E.g. a CrashSave can overwrite an AutoSave. So you have to check for a CrashSave before an AutoSave!
+ if (aInfo.UsedForSaving)
+ {
+ if ((eJob & AutoRecovery::E_EMERGENCY_SAVE) == AutoRecovery::E_EMERGENCY_SAVE)
+ {
+ lDangerousDocs.push_back(pIt);
+ continue;
+ }
+ else
+ if ((eJob & AutoRecovery::E_SESSION_SAVE) == AutoRecovery::E_SESSION_SAVE)
+ {
+ continue;
+ }
+ else
+ if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE)
+ {
+ eTimer = AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED;
+ aInfo.DocumentState |= AutoRecovery::E_POSTPONED;
+ continue;
+ }
+ }
+
+ // a) Document was not postponed - and is active now. => postpone it (restart timer, restart loop)
+ // b) Document was not postponed - and is not active now. => save it
+ // c) Document was postponed - and is not active now. => save it
+ // d) Document was postponed - and is active now. => save it (because user idle was checked already)
+ sal_Bool bActive = (xActiveModel == aInfo.Document);
+ sal_Bool bWasPostponed = ((aInfo.DocumentState & AutoRecovery::E_POSTPONED) == AutoRecovery::E_POSTPONED);
+
+ if (
+ ! bWasPostponed &&
+ bActive
+ )
+ {
+ aInfo.DocumentState |= AutoRecovery::E_POSTPONED;
+ *pIt = aInfo;
+ // postponed documents will be saved if this method is called again!
+ // That can be done by an outside started timer => E_POLL_FOR_USER_IDLE (if normal AutoSave is active)
+ // or it must be done directly without starting any timer => E_CALL_ME_BACK (if Emergency- or SessionSave is active and must be finished ASAP!)
+ eTimer = AutoRecovery::E_POLL_FOR_USER_IDLE;
+ if (!bAllowUserIdleLoop)
+ eTimer = AutoRecovery::E_CALL_ME_BACK;
+ continue;
+ }
+
+ // b, c, d)
+ // <- SAFE --------------------------
+ aWriteLock.unlock();
+ // changing of aInfo and flushing it is done inside implts_saveOneDoc!
+ implts_saveOneDoc(sBackupPath, aInfo, xExternalProgress);
+ implts_informListener(eJob, AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &aInfo));
+ aWriteLock.lock();
+ // SAFE -> --------------------------
+
+ *pIt = aInfo;
+ }
+
+ // Did we have some "dangerous candidates" ?
+ // Try to save it ... but may be it will fail !
+ ::std::vector< AutoRecovery::TDocumentList::iterator >::iterator pIt2;
+ for ( pIt2 = lDangerousDocs.begin();
+ pIt2 != lDangerousDocs.end() ;
+ ++pIt2 )
+ {
+ pIt = *pIt2;
+ AutoRecovery::TDocumentInfo aInfo = *pIt;
+
+ // <- SAFE --------------------------
+ aWriteLock.unlock();
+ // changing of aInfo and flushing it is done inside implts_saveOneDoc!
+ implts_saveOneDoc(sBackupPath, aInfo, xExternalProgress);
+ implts_informListener(eJob, AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &aInfo));
+ aWriteLock.lock();
+ // SAFE -> --------------------------
+
+ *pIt = aInfo;
+ }
+
+ return eTimer;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_saveOneDoc(const ::rtl::OUString& sBackupPath ,
+ AutoRecovery::TDocumentInfo& rInfo ,
+ const css::uno::Reference< css::task::XStatusIndicator >& xExternalProgress)
+{
+ // no document? => can occure if we loaded our configuration with files,
+ // which couldnt be recovered successfully. In such case we have all needed informations
+ // excepting the real document instance!
+
+ // TODO: search right place, where such "dead files" can be removed from the configuration!
+ if (!rInfo.Document.is())
+ return;
+
+ ::comphelper::MediaDescriptor lOldArgs(rInfo.Document->getArgs());
+ implts_generateNewTempURL(sBackupPath, lOldArgs, rInfo);
+
+ // if the document was loaded with a password, it should be
+ // stored with password
+ ::comphelper::MediaDescriptor lNewArgs;
+ ::rtl::OUString sPassword = lOldArgs.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PASSWORD(), ::rtl::OUString());
+ if (sPassword.getLength())
+ lNewArgs[::comphelper::MediaDescriptor::PROP_PASSWORD()] <<= sPassword;
+
+ // Further it must be saved using the default file format of that application.
+ // Otherwhise we will some data lost.
+ if (rInfo.DefaultFilter.getLength())
+ lNewArgs[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= rInfo.DefaultFilter;
+
+ // prepare frame/document/mediadescriptor in a way, that it uses OUR progress .-)
+ if (xExternalProgress.is())
+ lNewArgs[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xExternalProgress;
+ impl_establishProgress(rInfo, lNewArgs, css::uno::Reference< css::frame::XFrame >());
+
+ // #i66598# use special handling of property "DocumentBaseURL" (it must be an empty string!)
+ // for make hyperlinks working
+ lNewArgs[::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL()] <<= ::rtl::OUString();
+
+ // try to save this document as a new temp file everytimes.
+ // Mark AutoSave state as "INCOMPLETE" if it failed.
+ // Because the last temp file is to old and does not include all changes.
+ Reference< XDocumentRecovery > xDocRecover(rInfo.Document, css::uno::UNO_QUERY_THROW);
+
+ // safe the state about "trying to save"
+ // ... we need it for recovery if e.g. a crash occures inside next line!
+ rInfo.DocumentState |= AutoRecovery::E_TRY_SAVE;
+ implts_flushConfigItem(rInfo);
+
+ sal_Int32 nRetry = RETRY_STORE_ON_FULL_DISC_FOREVER;
+ sal_Bool bError = sal_False;
+ do
+ {
+ try
+ {
+ xDocRecover->storeToRecoveryFile( rInfo.NewTempURL, lNewArgs.getAsConstPropertyValueList() );
+
+ #ifdef TRIGGER_FULL_DISC_CHECK
+ throw css::uno::Exception();
+ #endif
+
+ bError = sal_False;
+ nRetry = 0;
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ bError = sal_True;
+
+ // a) FULL DISC seams to be the problem behind => show error and retry it forever (e.g. retry=300)
+ // b) unknown problem (may be locking problem) => reset RETRY value to more usefull value(!) (e.g. retry=3)
+ // c) unknown problem (may be locking problem) + 1..2 repeating operations => throw the original exception to force generation of a stacktrace !
+
+ // SAFE ->
+ ReadGuard aReadLock2(m_aLock);
+ sal_Int32 nMinSpaceDocSave = m_nMinSpaceDocSave;
+ aReadLock2.unlock();
+ // <- SAFE
+
+ if (! impl_enoughDiscSpace(nMinSpaceDocSave))
+ AutoRecovery::impl_showFullDiscError();
+ else
+ if (nRetry > RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL)
+ nRetry = RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL;
+ else
+ if (nRetry <= GIVE_UP_RETRY)
+ throw ex; // force stacktrace to know if there exist might other reasons, why an AutoSave can fail !!!
+
+ --nRetry;
+ }
+ }
+ while(nRetry>0);
+
+ if (! bError)
+ {
+ // safe the state about success
+ // ... you know the reason: to know it on recovery time if next line crash .-)
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_SAVE;
+ rInfo.DocumentState |= AutoRecovery::E_HANDLED;
+ rInfo.DocumentState |= AutoRecovery::E_SUCCEDED;
+ }
+ else
+ {
+ // safe the state about error ...
+ rInfo.NewTempURL = ::rtl::OUString();
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_SAVE;
+ rInfo.DocumentState |= AutoRecovery::E_HANDLED;
+ rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE;
+ }
+
+ // make sure the progress isnt referred any longer
+ impl_forgetProgress(rInfo, lNewArgs, css::uno::Reference< css::frame::XFrame >());
+
+ // try to remove the old temp file.
+ // Ignore any error here. We have a new temp file, which is up to date.
+ // The only thing is: we fill the disk with temp files, if we cant remove old ones :-)
+ ::rtl::OUString sRemoveFile = rInfo.OldTempURL;
+ rInfo.OldTempURL = rInfo.NewTempURL;
+ rInfo.NewTempURL = ::rtl::OUString();
+
+ implts_flushConfigItem(rInfo);
+
+ // We must know if the user modifies the document again ...
+ implts_startModifyListeningOnDoc(rInfo);
+
+ AutoRecovery::st_impl_removeFile(sRemoveFile);
+}
+
+//-----------------------------------------------
+AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aParams)
+{
+ AutoRecovery::ETimerType eTimer = AutoRecovery::E_DONT_START_TIMER;
+
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ sal_Int32 eJob = m_eJob;
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+
+ // Such documents are already loaded by the last loop.
+ // Dont check E_SUCCEDED here! Its may be the final state of an AutoSave
+ // operation before!!!
+ if ((rInfo.DocumentState & AutoRecovery::E_HANDLED) == AutoRecovery::E_HANDLED)
+ continue;
+
+ // a1,b1,c1,d2,e2,f2)
+ if ((rInfo.DocumentState & AutoRecovery::E_DAMAGED) == AutoRecovery::E_DAMAGED)
+ {
+ // dont forget to inform listener! May be this document was
+ // damaged on last saving time ...
+ // Then our listener need this notification.
+ // If it was damaged during last "try to open" ...
+ // it will be notified more then once. SH.. HAPPENS ...
+ // <- SAFE --------------------------
+ aWriteLock.unlock();
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo));
+ aWriteLock.lock();
+ // SAFE -> --------------------------
+ continue;
+ }
+
+ ::comphelper::MediaDescriptor lDescriptor;
+
+ // its an UI feature - so the "USER" itself must be set as referer
+ lDescriptor[::comphelper::MediaDescriptor::PROP_REFERRER()] <<= REFERRER_USER;
+ lDescriptor[::comphelper::MediaDescriptor::PROP_SALVAGEDFILE()] <<= ::rtl::OUString();
+
+ // recovered documents are loaded hidden, and shown all at once, later
+ lDescriptor[::comphelper::MediaDescriptor::PROP_HIDDEN()] <<= true;
+
+ if (aParams.m_xProgress.is())
+ lDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= aParams.m_xProgress;
+
+ sal_Bool bBackupWasTried = (
+ ((rInfo.DocumentState & AutoRecovery::E_TRY_LOAD_BACKUP ) == AutoRecovery::E_TRY_LOAD_BACKUP) || // temp. state!
+ ((rInfo.DocumentState & AutoRecovery::E_INCOMPLETE ) == AutoRecovery::E_INCOMPLETE ) // transport TRY_LOAD_BACKUP from last loop to this new one!
+ );
+ sal_Bool bOriginalWasTried = ((rInfo.DocumentState & AutoRecovery::E_TRY_LOAD_ORIGINAL) == AutoRecovery::E_TRY_LOAD_ORIGINAL);
+
+ if (bBackupWasTried)
+ {
+ if (!bOriginalWasTried)
+ {
+ rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE;
+ // try original URL ... ! dont continue with next item here ...
+ }
+ else
+ {
+ rInfo.DocumentState |= AutoRecovery::E_DAMAGED;
+ continue;
+ }
+ }
+
+ ::rtl::OUString sLoadOriginalURL;
+ ::rtl::OUString sLoadBackupURL ;
+
+ if (!bBackupWasTried)
+ sLoadBackupURL = rInfo.OldTempURL;
+
+ if (rInfo.OrgURL.getLength())
+ {
+ sLoadOriginalURL = rInfo.OrgURL;
+ }
+ else
+ if (rInfo.TemplateURL.getLength())
+ {
+ sLoadOriginalURL = rInfo.TemplateURL;
+ lDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True;
+ lDescriptor[::comphelper::MediaDescriptor::PROP_TEMPLATENAME()] <<= rInfo.TemplateURL;
+ }
+ else
+ if (rInfo.FactoryURL.getLength())
+ {
+ sLoadOriginalURL = rInfo.FactoryURL;
+ lDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True;
+ }
+
+ // A "Salvaged" item must exists every time. The core can make something special then for recovery.
+ // Of course it should be the real file name of the original file, in case we load the temp. backup here.
+ ::rtl::OUString sURL;
+ if (sLoadBackupURL.getLength())
+ {
+ sURL = sLoadBackupURL;
+ rInfo.DocumentState |= AutoRecovery::E_TRY_LOAD_BACKUP;
+ lDescriptor[::comphelper::MediaDescriptor::PROP_SALVAGEDFILE()] <<= sLoadOriginalURL;
+ }
+ else
+ if (sLoadOriginalURL.getLength())
+ {
+ sURL = sLoadOriginalURL;
+ rInfo.DocumentState |= AutoRecovery::E_TRY_LOAD_ORIGINAL;
+ }
+ else
+ continue; // TODO ERROR!
+
+ LoadEnv::initializeUIDefaults( m_xSMGR, lDescriptor, true, NULL );
+
+ // <- SAFE ------------------------------
+ aWriteLock.unlock();
+
+ implts_flushConfigItem(rInfo);
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo));
+
+ try
+ {
+ implts_openOneDoc(sURL, lDescriptor, rInfo);
+ }
+ catch(const css::uno::Exception&)
+ {
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_BACKUP;
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_ORIGINAL;
+ if (sLoadBackupURL.getLength())
+ {
+ rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE;
+ eTimer = AutoRecovery::E_CALL_ME_BACK;
+ }
+ else
+ {
+ rInfo.DocumentState |= AutoRecovery::E_HANDLED;
+ rInfo.DocumentState |= AutoRecovery::E_DAMAGED;
+ }
+
+ implts_flushConfigItem(rInfo, sal_True);
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo));
+
+ // SAFE -> ------------------------------
+ // Needed for next loop!
+ aWriteLock.lock();
+ continue;
+ }
+
+ if (rInfo.RealFilter.getLength())
+ {
+ ::comphelper::MediaDescriptor lPatchDescriptor(rInfo.Document->getArgs());
+ lPatchDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= rInfo.RealFilter;
+ rInfo.Document->attachResource(rInfo.Document->getURL(), lPatchDescriptor.getAsConstPropertyValueList());
+ // do *not* use sURL here. In case this points to the recovery file, it has already been passed
+ // to recoverFromFile. Also, passing it here is logically wrong, as attachResource is intended
+ // to take the logical file URL.
+ }
+
+ css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY);
+ if ( xModify.is() )
+ {
+ sal_Bool bModified = ((rInfo.DocumentState & AutoRecovery::E_MODIFIED) == AutoRecovery::E_MODIFIED);
+ xModify->setModified(bModified);
+ }
+
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_BACKUP;
+ rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_ORIGINAL;
+ rInfo.DocumentState |= AutoRecovery::E_HANDLED;
+ rInfo.DocumentState |= AutoRecovery::E_SUCCEDED;
+
+ implts_flushConfigItem(rInfo);
+ implts_informListener(eJob,
+ AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo));
+
+ /* Normaly we listen as XModifyListener on a document to know if a document was changed
+ since our last AutoSave. And we deregister us in case we know this state.
+ But directly after one document as recovered ... we must start listening.
+ Otherwhise the first "modify" doesnt reach us. Because we ourself called setModified()
+ on the document via API. And currently we dont listen for any events (not at the GlobalEventBroadcaster
+ nor at any document!).
+ */
+ implts_startModifyListeningOnDoc(rInfo);
+
+ // SAFE -> ------------------------------
+ // Needed for next loop. Dont unlock it again!
+ aWriteLock.lock();
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return eTimer;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_openOneDoc(const ::rtl::OUString& sURL ,
+ ::comphelper::MediaDescriptor& lDescriptor,
+ AutoRecovery::TDocumentInfo& rInfo )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XFrame > xDesktop( xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW );
+
+ ::std::vector< Reference< XComponent > > aCleanup;
+ try
+ {
+ // create a new document of the desired type
+ Reference< XModel2 > xModel( xSMGR->createInstance( rInfo.FactoryService ), UNO_QUERY_THROW );
+ aCleanup.push_back( xModel.get() );
+
+ // put the filter name into the descriptor - we're not going to involve any type detection, so
+ // the document might be lost without the FilterName property
+ lDescriptor[ ::comphelper::MediaDescriptor::PROP_FILTERNAME() ] <<= rInfo.RealFilter;
+
+ if ( sURL == rInfo.FactoryURL )
+ {
+ // if the document was a new, unmodified document, then there's nothing to recover, just to init
+ ENSURE_OR_THROW( ( rInfo.DocumentState & AutoRecovery::E_MODIFIED ) == 0,
+ "unexpected document state" );
+ Reference< XLoadable > xModelLoad( xModel, UNO_QUERY_THROW );
+ xModelLoad->initNew();
+
+ // TODO: remove load-process specific arguments from the descriptor, e.g. the status indicator
+ xModel->attachResource( sURL, lDescriptor.getAsConstPropertyValueList() );
+ }
+ else
+ {
+ // let it recover itself
+ Reference< XDocumentRecovery > xDocRecover( xModel, UNO_QUERY_THROW );
+ xDocRecover->recoverFromFile(
+ sURL,
+ lDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_SALVAGEDFILE(), ::rtl::OUString() ),
+ lDescriptor.getAsConstPropertyValueList()
+ );
+
+ // No attachResource needed here. By definition (of XDocumentRecovery), the implementation is responsible
+ // for completely initializing the model, which includes attachResource (or equivalent), if required.
+ }
+
+ // re-create all the views
+ ::std::vector< ::rtl::OUString > aViewsToRestore( rInfo.ViewNames.getLength() );
+ if ( rInfo.ViewNames.getLength() )
+ ::std::copy( rInfo.ViewNames.getConstArray(), rInfo.ViewNames.getConstArray() + rInfo.ViewNames.getLength(), aViewsToRestore.begin() );
+ // if we don't have views for whatever reason, then create a default-view, at least
+ if ( aViewsToRestore.empty() )
+ aViewsToRestore.push_back( ::rtl::OUString() );
+
+ for ( ::std::vector< ::rtl::OUString >::const_iterator viewName = aViewsToRestore.begin();
+ viewName != aViewsToRestore.end();
+ ++viewName
+ )
+ {
+ // create a frame
+ Reference< XFrame > xTargetFrame = xDesktop->findFrame( SPECIALTARGET_BLANK, 0 );
+ aCleanup.push_back( xTargetFrame.get() );
+
+ // create a view to the document
+ Reference< XController2 > xController;
+ if ( viewName->getLength() )
+ {
+ xController.set( xModel->createViewController( *viewName, Sequence< PropertyValue >(), xTargetFrame ), UNO_SET_THROW );
+ }
+ else
+ {
+ xController.set( xModel->createDefaultViewController( xTargetFrame ), UNO_SET_THROW );
+ }
+
+ // introduce model/view/controller to each other
+ xController->attachModel( xModel.get() );
+ xModel->connectController( xController.get() );
+ xTargetFrame->setComponent( xController->getComponentWindow(), xController.get() );
+ xController->attachFrame( xTargetFrame );
+ xModel->setCurrentController( xController.get() );
+ }
+
+ rInfo.Document = xModel.get();
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ {
+ Any aCaughtException( ::cppu::getCaughtException() );
+
+ // clean up
+ for ( ::std::vector< Reference< XComponent > >::const_iterator component = aCleanup.begin();
+ component != aCleanup.end();
+ ++component
+ )
+ {
+ css::uno::Reference< css::util::XCloseable > xClose( *component, css::uno::UNO_QUERY );
+ if ( xClose.is() )
+ xClose->close( sal_True );
+ else
+ (*component)->dispose();
+ }
+
+ // re-throw
+ ::rtl::OUStringBuffer sMsg(256);
+ sMsg.appendAscii("Recovery of \"");
+ sMsg.append (sURL );
+ sMsg.appendAscii("\" failed." );
+
+ throw css::lang::WrappedTargetException(
+ sMsg.makeStringAndClear(),
+ static_cast< css::frame::XDispatch* >(this),
+ aCaughtException
+ );
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_generateNewTempURL(const ::rtl::OUString& sBackupPath ,
+ ::comphelper::MediaDescriptor& /*rMediaDescriptor*/,
+ AutoRecovery::TDocumentInfo& rInfo )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // specify URL for saving (which points to a temp file inside backup directory)
+ // and define an unique name, so we can locate it later.
+ // This unique name must solve an optimization problem too!
+ // In case we are asked to save unmodified documents too - and one of them
+ // is an empty one (because it was new created using e.g. an URL private:factory/...)
+ // we should not save it realy. Then we put the information about such "empty document"
+ // into the configuration and dont create any recovery file on disk.
+ // We use the title of the document to make it unique.
+ ::rtl::OUStringBuffer sUniqueName;
+ if (rInfo.OrgURL.getLength())
+ {
+ css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
+ css::util::URL aURL;
+ aURL.Complete = rInfo.OrgURL;
+ xParser->parseStrict(aURL);
+ sUniqueName.append(aURL.Name);
+ }
+ else
+ if (rInfo.FactoryURL.getLength())
+ sUniqueName.appendAscii("untitled");
+ sUniqueName.appendAscii("_");
+
+ // TODO: Must we strip some illegal signes - if we use the title?
+
+ String sName (sUniqueName.makeStringAndClear());
+ String sExtension(rInfo.Extension );
+ String sPath (sBackupPath );
+ ::utl::TempFile aTempFile(sName, &sExtension, &sPath);
+
+ rInfo.NewTempURL = aTempFile.GetURL();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_informListener( sal_Int32 eJob ,
+ const css::frame::FeatureStateEvent& aEvent)
+{
+ // Helper shares mutex with us -> threadsafe!
+ ::cppu::OInterfaceContainerHelper* pListenerForURL = 0;
+ ::rtl::OUString sJob = AutoRecovery::implst_getJobDescription(eJob);
+
+ // inform listener, which are registered for any URLs(!)
+ pListenerForURL = m_lListener.getContainer(sJob);
+ if(pListenerForURL != 0)
+ {
+ ::cppu::OInterfaceIteratorHelper pIt(*pListenerForURL);
+ while(pIt.hasMoreElements())
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XStatusListener > xListener(((css::frame::XStatusListener*)pIt.next()), css::uno::UNO_QUERY);
+ xListener->statusChanged(aEvent);
+ }
+ catch(const css::uno::RuntimeException&)
+ { pIt.remove(); }
+ }
+ }
+}
+
+//-----------------------------------------------
+::rtl::OUString AutoRecovery::implst_getJobDescription(sal_Int32 eJob)
+{
+ // describe the current running operation
+ ::rtl::OUStringBuffer sFeature(256);
+ sFeature.append(CMD_PROTOCOL);
+
+ // Attention: Because "eJob" is used as a flag field the order of checking these
+ // flags is importent. We must preferr job with higher priorities!
+ // E.g. EmergencySave has an higher prio then AutoSave ...
+ // On the other side there exist a well defined order between two different jobs.
+ // e.g. PrepareEmergencySave must be done before EmergencySave is started of course.
+
+ if ((eJob & AutoRecovery::E_PREPARE_EMERGENCY_SAVE) == AutoRecovery::E_PREPARE_EMERGENCY_SAVE)
+ sFeature.append(CMD_DO_PREPARE_EMERGENCY_SAVE);
+ else
+ if ((eJob & AutoRecovery::E_EMERGENCY_SAVE) == AutoRecovery::E_EMERGENCY_SAVE)
+ sFeature.append(CMD_DO_EMERGENCY_SAVE);
+ else
+ if ((eJob & AutoRecovery::E_RECOVERY) == AutoRecovery::E_RECOVERY)
+ sFeature.append(CMD_DO_RECOVERY);
+ else
+ if ((eJob & AutoRecovery::E_SESSION_SAVE) == AutoRecovery::E_SESSION_SAVE)
+ sFeature.append(CMD_DO_SESSION_SAVE);
+ else
+ if ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT) == AutoRecovery::E_SESSION_QUIET_QUIT)
+ sFeature.append(CMD_DO_SESSION_QUIET_QUIT);
+ else
+ if ((eJob & AutoRecovery::E_SESSION_RESTORE) == AutoRecovery::E_SESSION_RESTORE)
+ sFeature.append(CMD_DO_SESSION_RESTORE);
+ else
+ if ((eJob & AutoRecovery::E_ENTRY_BACKUP) == AutoRecovery::E_ENTRY_BACKUP)
+ sFeature.append(CMD_DO_ENTRY_BACKUP);
+ else
+ if ((eJob & AutoRecovery::E_ENTRY_CLEANUP) == AutoRecovery::E_ENTRY_CLEANUP)
+ sFeature.append(CMD_DO_ENTRY_CLEANUP);
+ else
+ if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE)
+ sFeature.append(CMD_DO_AUTO_SAVE);
+ #ifdef ENABLE_WARNINGS
+ else if ( eJob != AutoRecovery::E_NO_JOB )
+ LOG_WARNING("AutoRecovery::implst_getJobDescription()", "Invalid job identifier detected.")
+ #endif
+
+ return sFeature.makeStringAndClear();
+}
+
+//-----------------------------------------------
+sal_Int32 AutoRecovery::implst_classifyJob(const css::util::URL& aURL)
+{
+ if (aURL.Protocol.equals(CMD_PROTOCOL))
+ {
+ if (aURL.Path.equals(CMD_DO_PREPARE_EMERGENCY_SAVE))
+ return AutoRecovery::E_PREPARE_EMERGENCY_SAVE;
+ else
+ if (aURL.Path.equals(CMD_DO_EMERGENCY_SAVE))
+ return AutoRecovery::E_EMERGENCY_SAVE;
+ else
+ if (aURL.Path.equals(CMD_DO_RECOVERY))
+ return AutoRecovery::E_RECOVERY;
+ else
+ if (aURL.Path.equals(CMD_DO_ENTRY_BACKUP))
+ return AutoRecovery::E_ENTRY_BACKUP;
+ else
+ if (aURL.Path.equals(CMD_DO_ENTRY_CLEANUP))
+ return AutoRecovery::E_ENTRY_CLEANUP;
+ else
+ if (aURL.Path.equals(CMD_DO_SESSION_SAVE))
+ return AutoRecovery::E_SESSION_SAVE;
+ else
+ if (aURL.Path.equals(CMD_DO_SESSION_QUIET_QUIT))
+ return AutoRecovery::E_SESSION_QUIET_QUIT;
+ else
+ if (aURL.Path.equals(CMD_DO_SESSION_RESTORE))
+ return AutoRecovery::E_SESSION_RESTORE;
+ else
+ if (aURL.Path.equals(CMD_DO_DISABLE_RECOVERY))
+ return AutoRecovery::E_DISABLE_AUTORECOVERY;
+ else
+ if (aURL.Path.equals(CMD_DO_SET_AUTOSAVE_STATE))
+ return AutoRecovery::E_SET_AUTOSAVE_STATE;
+ }
+
+ LOG_WARNING("AutoRecovery::implts_classifyJob()", "Invalid URL (protocol).")
+ return AutoRecovery::E_NO_JOB;
+}
+
+//-----------------------------------------------
+css::frame::FeatureStateEvent AutoRecovery::implst_createFeatureStateEvent( sal_Int32 eJob ,
+ const ::rtl::OUString& sEventType,
+ AutoRecovery::TDocumentInfo* pInfo )
+{
+ css::frame::FeatureStateEvent aEvent;
+ aEvent.FeatureURL.Complete = AutoRecovery::implst_getJobDescription(eJob);
+ aEvent.FeatureDescriptor = sEventType;
+
+ if (sEventType.equals(OPERATION_UPDATE) && pInfo)
+ {
+ // pack rInfo for transport via UNO
+ ::comphelper::NamedValueCollection aInfo;
+ aInfo.put( CFG_ENTRY_PROP_ID, pInfo->ID );
+ aInfo.put( CFG_ENTRY_PROP_ORIGINALURL, pInfo->OrgURL );
+ aInfo.put( CFG_ENTRY_PROP_FACTORYURL, pInfo->FactoryURL );
+ aInfo.put( CFG_ENTRY_PROP_TEMPLATEURL, pInfo->TemplateURL );
+ aInfo.put( CFG_ENTRY_PROP_TEMPURL, pInfo->OldTempURL.getLength() ? pInfo->OldTempURL : pInfo->NewTempURL );
+ aInfo.put( CFG_ENTRY_PROP_MODULE, pInfo->AppModule );
+ aInfo.put( CFG_ENTRY_PROP_TITLE, pInfo->Title );
+ aInfo.put( CFG_ENTRY_PROP_VIEWNAMES, pInfo->ViewNames );
+ aInfo.put( CFG_ENTRY_PROP_DOCUMENTSTATE, pInfo->DocumentState );
+
+ aEvent.State <<= aInfo.getPropertyValues();
+ }
+
+ return aEvent;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_resetHandleStates(sal_Bool /*bLoadCache*/)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ // SAFE -> ------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ rInfo.DocumentState &= ~AutoRecovery::E_HANDLED ;
+ rInfo.DocumentState &= ~AutoRecovery::E_POSTPONED;
+
+ // SAFE -> ------------------------------
+ aWriteLock.unlock();
+ implts_flushConfigItem(rInfo);
+ aWriteLock.lock();
+ // <- SAFE ------------------------------
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_prepareEmergencySave()
+{
+ // Be sure to know all open documents realy .-)
+ implts_verifyCacheAgainstDesktopDocumentList();
+
+ // hide all docs, so the user cant disturb our emergency save .-)
+ implts_changeAllDocVisibility(sal_False);
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_doEmergencySave(const DispatchParams& aParams)
+{
+ // Write a hint "we chrashed" into the configuration, so
+ // the error report tool is started too in case no recovery
+ // documents exists and was saved.
+ ::comphelper::ConfigurationHelper::writeDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_CRASHED,
+ css::uno::makeAny(sal_True),
+ ::comphelper::ConfigurationHelper::E_STANDARD);
+
+ // for all docs, store their current view/names in the configurtion
+ implts_persistAllActiveViewNames();
+
+ // The called method for saving documents runs
+ // during normal AutoSave more then once. Because
+ // it postpone active documents and save it later.
+ // That is normaly done by recalling it from a timer.
+ // Here we must do it immediatly!
+ // Of course this method returns the right state -
+ // because it knows, that we are running in ERMERGENCY SAVE mode .-)
+
+ sal_Bool bAllowUserIdleLoop = sal_False; // not allowed to change that .-)
+ AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER;
+ do
+ {
+ eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_True, &aParams);
+ }
+ while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK);
+
+ // reset the handle state of all
+ // cache items. Such handle state indicates, that a document
+ // was already saved during the THIS(!) EmergencySave session.
+ // Of course following recovery session must be started without
+ // any "handle" state ...
+ implts_resetHandleStates(sal_False);
+
+ // flush config cached back to disc.
+ impl_flushALLConfigChanges();
+
+ // try to make sure next time office will be started user wont be
+ // notified about any other might be running office instance
+ // remove ".lock" file from disc !
+ AutoRecovery::st_impl_removeLockFile();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_doRecovery(const DispatchParams& aParams)
+{
+ AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER;
+ do
+ {
+ eSuggestedTimer = implts_openDocs(aParams);
+ }
+ while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK);
+
+ // reset the handle state of all
+ // cache items. Such handle state indicates, that a document
+ // was already saved during the THIS(!) Recovery session.
+ // Of course a may be following EmergencySave session must be started without
+ // any "handle" state ...
+ implts_resetHandleStates(sal_True);
+
+ // Reset the configuration hint "we was crashed"!
+ ::comphelper::ConfigurationHelper::writeDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_CRASHED,
+ css::uno::makeAny(sal_False),
+ ::comphelper::ConfigurationHelper::E_STANDARD);
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
+{
+ LOG_RECOVERY("AutoRecovery::implts_doSessionSave()")
+
+ // Be sure to know all open documents realy .-)
+ implts_verifyCacheAgainstDesktopDocumentList();
+
+ // for all docs, store their current view/names in the configurtion
+ implts_persistAllActiveViewNames();
+
+ // The called method for saving documents runs
+ // during normal AutoSave more then once. Because
+ // it postpone active documents and save it later.
+ // That is normaly done by recalling it from a timer.
+ // Here we must do it immediatly!
+ // Of course this method returns the right state -
+ // because it knows, that we are running in SESSION SAVE mode .-)
+
+ sal_Bool bAllowUserIdleLoop = sal_False; // not allowed to change that .-)
+ AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER;
+ do
+ {
+ // do not remove lock files of the documents, it will be done on session quit
+ eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_False, &aParams);
+ }
+ while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK);
+
+ // reset the handle state of all
+ // cache items. Such handle state indicates, that a document
+ // was already saved during the THIS(!) save session.
+ // Of course following restore session must be started without
+ // any "handle" state ...
+ implts_resetHandleStates(sal_False);
+
+ // flush config cached back to disc.
+ impl_flushALLConfigChanges();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_doSessionQuietQuit(const DispatchParams& /*aParams*/)
+{
+ LOG_RECOVERY("AutoRecovery::implts_doSessionQuietQuit()")
+
+ // try to make sure next time office will be started user wont be
+ // notified about any other might be running office instance
+ // remove ".lock" file from disc !
+ // it is done as a first action for session save since Gnome sessions
+ // do not provide enough time for shutdown, and the dialog looks to be
+ // confusing for the user
+ AutoRecovery::st_impl_removeLockFile();
+
+ // reset all modified documents, so the dont show any UI on closing ...
+ // and close all documents, so we can shutdown the OS!
+ implts_prepareSessionShutdown();
+
+ // Write a hint for "stored session data" into the configuration, so
+ // the on next startup we know what's happen last time
+ ::comphelper::ConfigurationHelper::writeDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_SESSIONDATA,
+ css::uno::makeAny(sal_True),
+ ::comphelper::ConfigurationHelper::E_STANDARD);
+
+ // flush config cached back to disc.
+ impl_flushALLConfigChanges();
+}
+
+
+//-----------------------------------------------
+void AutoRecovery::implts_doSessionRestore(const DispatchParams& aParams)
+{
+ LOG_RECOVERY("AutoRecovery::implts_doSessionRestore() ...")
+
+ AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER;
+ do
+ {
+ eSuggestedTimer = implts_openDocs(aParams);
+ }
+ while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK);
+
+ // reset the handle state of all
+ // cache items. Such handle state indicates, that a document
+ // was already saved during the THIS(!) Restore session.
+ // Of course a may be following save session must be started without
+ // any "handle" state ...
+ implts_resetHandleStates(sal_True);
+
+ // make all opened documents visible
+ implts_changeAllDocVisibility(sal_True);
+
+ // Reset the configuration hint for "session save"!
+ LOG_RECOVERY("... reset config key 'SessionData'")
+ ::comphelper::ConfigurationHelper::writeDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_SESSIONDATA,
+ css::uno::makeAny(sal_False),
+ ::comphelper::ConfigurationHelper::E_STANDARD);
+
+ LOG_RECOVERY("... AutoRecovery::implts_doSessionRestore()")
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_backupWorkingEntry(const DispatchParams& aParams)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ const AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ if (rInfo.ID != aParams.m_nWorkingEntryID)
+ continue;
+
+ ::rtl::OUString sSourceURL;
+ // Prefer temp file. It contains the changes against the original document!
+ if (rInfo.OldTempURL.getLength())
+ sSourceURL = rInfo.OldTempURL;
+ else
+ if (rInfo.NewTempURL.getLength())
+ sSourceURL = rInfo.NewTempURL;
+ else
+ if (rInfo.OrgURL.getLength())
+ sSourceURL = rInfo.OrgURL;
+ else
+ continue; // nothing real to save! An unmodified but new created document.
+
+ INetURLObject aParser(sSourceURL);
+ // AutoRecovery::EFailureSafeResult eResult =
+ implts_copyFile(sSourceURL, aParams.m_sSavePath, aParser.getName());
+
+ // TODO: Check eResult and react for errors (InteractionHandler!?)
+ // Currently we ignore it ...
+ // DONT UPDATE THE CACHE OR REMOVE ANY TEMP. FILES FROM DISK.
+ // That has to be forced from outside explicitly.
+ // See implts_cleanUpWorkingEntry() for further details.
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_cleanUpWorkingEntry(const DispatchParams& aParams)
+{
+ CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE);
+
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ if (rInfo.ID != aParams.m_nWorkingEntryID)
+ continue;
+
+ AutoRecovery::st_impl_removeFile(rInfo.OldTempURL);
+ AutoRecovery::st_impl_removeFile(rInfo.NewTempURL);
+ implts_flushConfigItem(rInfo, sal_True); // sal_True => remove it from xml config!
+
+ m_lDocCache.erase(pIt);
+ break; /// !!! pIt is not defined any longer ... further this function has finished it's work
+ }
+}
+
+//-----------------------------------------------
+AutoRecovery::EFailureSafeResult AutoRecovery::implts_copyFile(const ::rtl::OUString& sSource ,
+ const ::rtl::OUString& sTargetPath,
+ const ::rtl::OUString& sTargetName)
+{
+ // create content for the parent folder and call transfer on that content with the source content
+ // and the destination file name as parameters
+
+ css::uno::Reference< css::ucb::XCommandEnvironment > xEnvironment;
+
+ ::ucbhelper::Content aSourceContent;
+ ::ucbhelper::Content aTargetContent;
+
+ try
+ {
+ aTargetContent = ::ucbhelper::Content(sTargetPath, xEnvironment);
+ }
+ catch(const css::uno::Exception&)
+ { return AutoRecovery::E_WRONG_TARGET_PATH; }
+
+ sal_Int32 nNameClash;
+// nNameClash = css::ucb::NameClash::ERROR;
+ nNameClash = css::ucb::NameClash::RENAME;
+// nNameClash = css::ucb::NameClash::OVERWRITE;
+
+ try
+ {
+ ::ucbhelper::Content::create(sSource, xEnvironment, aSourceContent);
+ aTargetContent.transferContent(aSourceContent, ::ucbhelper::InsertOperation_COPY, sTargetName, nNameClash);
+ }
+ catch(const css::uno::Exception&)
+ { return AutoRecovery::E_ORIGINAL_FILE_MISSING; }
+
+ return AutoRecovery::E_COPIED;
+}
+
+//-----------------------------------------------
+sal_Bool SAL_CALL AutoRecovery::convertFastPropertyValue( css::uno::Any& /*aConvertedValue*/,
+ css::uno::Any& /*aOldValue*/ ,
+ sal_Int32 /*nHandle*/ ,
+ const css::uno::Any& /*aValue*/ )
+ throw(css::lang::IllegalArgumentException)
+{
+ // not needed currently
+ return sal_False;
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/,
+ const css::uno::Any& /*aValue*/ )
+ throw(css::uno::Exception)
+{
+ // not needed currently
+}
+
+//-----------------------------------------------
+void SAL_CALL AutoRecovery::getFastPropertyValue(css::uno::Any& aValue ,
+ sal_Int32 nHandle) const
+{
+ switch(nHandle)
+ {
+ case AUTORECOVERY_PROPHANDLE_EXISTS_RECOVERYDATA :
+ {
+ sal_Bool bSessionData = sal_False;
+ ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_SESSIONDATA,
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= bSessionData;
+
+ sal_Bool bRecoveryData = ((sal_Bool)(m_lDocCache.size()>0));
+
+ // exists session data ... => then we cant say, that these
+ // data are valid for recovery. So we have to return sal_False then!
+ if (bSessionData)
+ bRecoveryData = sal_False;
+
+ aValue <<= bRecoveryData;
+ }
+ break;
+
+ case AUTORECOVERY_PROPHANDLE_CRASHED :
+ aValue = ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_CRASHED,
+ ::comphelper::ConfigurationHelper::E_READONLY);
+ break;
+
+ case AUTORECOVERY_PROPHANDLE_EXISTS_SESSIONDATA :
+ aValue = ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_RECOVERY,
+ CFG_PATH_RECOVERYINFO,
+ CFG_ENTRY_SESSIONDATA,
+ ::comphelper::ConfigurationHelper::E_READONLY);
+ break;
+ }
+}
+
+//-----------------------------------------------
+const css::uno::Sequence< css::beans::Property > impl_getStaticPropertyDescriptor()
+{
+ static const css::beans::Property pPropertys[] =
+ {
+ css::beans::Property( AUTORECOVERY_PROPNAME_CRASHED , AUTORECOVERY_PROPHANDLE_CRASHED , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( AUTORECOVERY_PROPNAME_EXISTS_RECOVERYDATA, AUTORECOVERY_PROPHANDLE_EXISTS_RECOVERYDATA, ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( AUTORECOVERY_PROPNAME_EXISTS_SESSIONDATA , AUTORECOVERY_PROPHANDLE_EXISTS_SESSIONDATA , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ };
+ static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor(pPropertys, AUTORECOVERY_PROPCOUNT);
+ return lPropertyDescriptor;
+}
+
+//-----------------------------------------------
+::cppu::IPropertyArrayHelper& SAL_CALL AutoRecovery::getInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper* pInfoHelper = 0;
+ if(!pInfoHelper)
+ {
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ if(!pInfoHelper)
+ {
+ static ::cppu::OPropertyArrayHelper aInfoHelper(impl_getStaticPropertyDescriptor(), sal_True);
+ pInfoHelper = &aInfoHelper;
+ }
+ }
+
+ return (*pInfoHelper);
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL AutoRecovery::getPropertySetInfo()
+ throw(css::uno::RuntimeException)
+{
+ static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = 0;
+ if(!pInfo)
+ {
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ if(!pInfo)
+ {
+ static css::uno::Reference< css::beans::XPropertySetInfo > xInfo(createPropertySetInfo(getInfoHelper()));
+ pInfo = &xInfo;
+ }
+ }
+
+ return (*pInfo);
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList()
+{
+ LOG_RECOVERY("AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList() ...")
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ try
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
+ xSMGR->createInstance(SERVICENAME_DESKTOP),
+ css::uno::UNO_QUERY_THROW);
+
+ css::uno::Reference< css::container::XIndexAccess > xContainer(
+ xDesktop->getFrames(),
+ css::uno::UNO_QUERY_THROW);
+
+ sal_Int32 i = 0;
+ sal_Int32 c = xContainer->getCount();
+
+ for (i=0; i<c; ++i)
+ {
+ css::uno::Reference< css::frame::XFrame > xFrame;
+ try
+ {
+ xContainer->getByIndex(i) >>= xFrame;
+ if (!xFrame.is())
+ continue;
+ }
+ // can happen in multithreaded environments, that frames was removed from the container during this loop runs!
+ // Ignore it.
+ catch(const css::lang::IndexOutOfBoundsException&)
+ { continue; }
+
+ // We are interested on visible documents only.
+ // Note: It's n optional interface .-(
+ css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(
+ xFrame->getContainerWindow(),
+ css::uno::UNO_QUERY);
+ if (
+ (!xVisibleCheck.is() ) ||
+ (!xVisibleCheck->isVisible())
+ )
+ {
+ continue;
+ }
+
+ // extract the model from the frame.
+ // Ignore "view only" frames, which does not have a model.
+ css::uno::Reference< css::frame::XController > xController;
+ css::uno::Reference< css::frame::XModel > xModel;
+
+ xController = xFrame->getController();
+ if (xController.is())
+ xModel = xController->getModel();
+ if (!xModel.is())
+ continue;
+
+ // insert model into cache ...
+ // If the model is already well known inside cache
+ // it's information set will be updated by asking the
+ // model again for it's new states.
+ implts_registerDocument(xModel);
+ }
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {}
+
+ LOG_RECOVERY("... AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList()")
+}
+
+//-----------------------------------------------
+sal_Bool AutoRecovery::impl_enoughDiscSpace(sal_Int32 nRequiredSpace)
+{
+ #ifdef SIMULATE_FULL_DISC
+ return sal_False;
+ #endif
+
+ // In case an error occures and we are not able to retrieve the needed information
+ // it's better to "disable" the feature ShowErrorOnFullDisc !
+ // Otherwhise we start a confusing process of error handling ...
+
+ sal_uInt64 nFreeSpace = SAL_MAX_UINT64;
+
+ ::rtl::OUString sBackupPath(SvtPathOptions().GetBackupPath());
+ ::osl::VolumeInfo aInfo (VolumeInfoMask_FreeSpace);
+ ::osl::FileBase::RC aRC = ::osl::Directory::getVolumeInfo(sBackupPath, aInfo);
+
+ if (
+ (aInfo.isValid(VolumeInfoMask_FreeSpace)) &&
+ (aRC == ::osl::FileBase::E_None )
+ )
+ {
+ nFreeSpace = aInfo.getFreeSpace();
+ }
+
+ sal_uInt64 nFreeMB = (nFreeSpace/1048576);
+ return (nFreeMB >= (sal_uInt64)nRequiredSpace);
+}
+
+//-----------------------------------------------
+void AutoRecovery::impl_showFullDiscError()
+{
+ static String PLACEHOLDER_PATH = String::CreateFromAscii("%PATH");
+
+ String sBtn(FwkResId(STR_FULL_DISC_RETRY_BUTTON));
+ String sMsg(FwkResId(STR_FULL_DISC_MSG ));
+
+ String sBackupURL(SvtPathOptions().GetBackupPath());
+ INetURLObject aConverter(sBackupURL);
+ sal_Unicode aDelimiter;
+ String sBackupPath = aConverter.getFSysPath(INetURLObject::FSYS_DETECT, &aDelimiter);
+ if (sBackupPath.Len()<1)
+ sBackupPath = sBackupURL;
+ sMsg.SearchAndReplace(PLACEHOLDER_PATH, sBackupPath);
+
+ ErrorBox dlgError(0, WB_OK, sMsg);
+ dlgError.SetButtonText(dlgError.GetButtonId(0), sBtn);
+ dlgError.Execute();
+}
+
+//-----------------------------------------------
+void AutoRecovery::impl_establishProgress(const AutoRecovery::TDocumentInfo& rInfo ,
+ ::comphelper::MediaDescriptor& rArgs ,
+ const css::uno::Reference< css::frame::XFrame >& xNewFrame)
+{
+ // external well known frame must be preferred (because it was created by ourself
+ // for loading documents into this frame)!
+ // But if no frame exists ... we can try to locate it using any frame bound to the provided
+ // document. Of course we must live without any frame in case the document does not exists at this
+ // point. But this state shouldnt occure. In such case xNewFrame should be valid ... hopefully .-)
+ css::uno::Reference< css::frame::XFrame > xFrame = xNewFrame;
+ if (
+ (!xFrame.is() ) &&
+ (rInfo.Document.is())
+ )
+ {
+ css::uno::Reference< css::frame::XController > xController = rInfo.Document->getCurrentController();
+ if (xController.is())
+ xFrame = xController->getFrame();
+ }
+
+ // Any outside progress must be used ...
+ // Only if there is no progress, we can create our own one.
+ css::uno::Reference< css::task::XStatusIndicator > xInternalProgress;
+ css::uno::Reference< css::task::XStatusIndicator > xExternalProgress = rArgs.getUnpackedValueOrDefault(
+ ::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(),
+ css::uno::Reference< css::task::XStatusIndicator >() );
+
+ // Normaly a progress is set from outside (e.g. by the CrashSave/Recovery dialog, which uses our dispatch API).
+ // But for a normal auto save we dont have such "external progress"... because this function is triggered by our own timer then.
+ // In such case we must create our own progress !
+ if (
+ (! xExternalProgress.is()) &&
+ (xFrame.is() )
+ )
+ {
+ css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xFrame, css::uno::UNO_QUERY);
+ if (xProgressFactory.is())
+ xInternalProgress = xProgressFactory->createStatusIndicator();
+ }
+
+ // HACK
+ // An external provided progress (most given by the CrashSave/Recovery dialog)
+ // must be preferred. But we know that some application filters query it's own progress instance
+ // at the frame method Frame::createStatusIndicator().
+ // So we use a two step mechanism:
+ // 1) we set the progress inside the MediaDescriptor, which will be provided to the filter
+ // 2) and we set a special Frame property, which overwrites the normal behaviour of Frame::createStatusIndicator .-)
+ // But we supress 2) in case we uses an internal progress. Because then it doesnt matter
+ // if our applications make it wrong. In such case the internal progress resists at the same frame
+ // and there is no need to forward progress activities to e.g. an outside dialog .-)
+ if (
+ (xExternalProgress.is()) &&
+ (xFrame.is() )
+ )
+ {
+ css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY);
+ if (xFrameProps.is())
+ xFrameProps->setPropertyValue(FRAME_PROPNAME_INDICATORINTERCEPTION, css::uno::makeAny(xExternalProgress));
+ }
+
+ // But inside the MediaDescriptor we must set our own create progress ...
+ // in case there is not already anothe rprogress set.
+ rArgs.createItemIfMissing(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), xInternalProgress);
+}
+
+//-----------------------------------------------
+void AutoRecovery::impl_forgetProgress(const AutoRecovery::TDocumentInfo& rInfo ,
+ ::comphelper::MediaDescriptor& rArgs ,
+ const css::uno::Reference< css::frame::XFrame >& xNewFrame)
+{
+ // external well known frame must be preferred (because it was created by ourself
+ // for loading documents into this frame)!
+ // But if no frame exists ... we can try to locate it using any frame bound to the provided
+ // document. Of course we must live without any frame in case the document does not exists at this
+ // point. But this state shouldnt occure. In such case xNewFrame should be valid ... hopefully .-)
+ css::uno::Reference< css::frame::XFrame > xFrame = xNewFrame;
+ if (
+ (!xFrame.is() ) &&
+ (rInfo.Document.is())
+ )
+ {
+ css::uno::Reference< css::frame::XController > xController = rInfo.Document->getCurrentController();
+ if (xController.is())
+ xFrame = xController->getFrame();
+ }
+
+ // stop progress interception on corresponding frame.
+ css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY);
+ if (xFrameProps.is())
+ xFrameProps->setPropertyValue(FRAME_PROPNAME_INDICATORINTERCEPTION, css::uno::makeAny(css::uno::Reference< css::task::XStatusIndicator >()));
+
+ // forget progress inside list of arguments.
+ ::comphelper::MediaDescriptor::iterator pArg = rArgs.find(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR());
+ if (pArg != rArgs.end())
+ {
+ rArgs.erase(pArg);
+ pArg = rArgs.end();
+ }
+}
+
+//-----------------------------------------------
+void AutoRecovery::impl_flushALLConfigChanges()
+{
+ try
+ {
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::uno::XInterface > xRecoveryCfg(m_xRecoveryCFG, css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (xRecoveryCfg.is())
+ ::comphelper::ConfigurationHelper::flush(xRecoveryCfg);
+
+ // SOLAR SAFE ->
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ ::utl::ConfigManager* pCfgMgr = ::utl::ConfigManager::GetConfigManager();
+ if (pCfgMgr)
+ pCfgMgr->StoreConfigItems();
+ }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+//-----------------------------------------------
+void AutoRecovery::st_impl_removeFile(const ::rtl::OUString& sURL)
+{
+ if ( ! sURL.getLength())
+ return;
+
+ try
+ {
+ ::ucbhelper::Content aContent = ::ucbhelper::Content(sURL, css::uno::Reference< css::ucb::XCommandEnvironment >());
+ aContent.executeCommand(::rtl::OUString::createFromAscii("delete"), css::uno::makeAny(sal_True));
+ }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+//-----------------------------------------------
+void AutoRecovery::st_impl_removeLockFile()
+{
+ try
+ {
+ ::rtl::OUString sUserURL;
+ ::utl::Bootstrap::locateUserInstallation( sUserURL );
+
+ ::rtl::OUStringBuffer sLockURLBuf;
+ sLockURLBuf.append (sUserURL);
+ sLockURLBuf.appendAscii("/.lock");
+ ::rtl::OUString sLockURL = sLockURLBuf.makeStringAndClear();
+
+ AutoRecovery::st_impl_removeFile(sLockURL);
+ }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+} // namespace framework
diff --git a/framework/source/services/backingcomp.cxx b/framework/source/services/backingcomp.cxx
new file mode 100644
index 000000000000..b8db175886d2
--- /dev/null
+++ b/framework/source/services/backingcomp.cxx
@@ -0,0 +1,874 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+#include "services/backingcomp.hxx"
+
+#include "backingwindow.hxx"
+
+//_______________________________________________
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <classes/droptargetlistener.hxx>
+#include <framework/acceleratorinfo.hxx>
+#include <targets.h>
+#include <properties.h>
+#include <services.h>
+
+#ifndef _FRAMEWORK_HELPID_HRC
+#include <helpid.hrc>
+#endif
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/XDataTransferProviderAccess.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+
+//_______________________________________________
+// other includes
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/factory.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/keycod.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/resmgr.hxx>
+#include <tools/urlobj.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#ifndef _SOLAR_HRC
+#include <svl/solar.hrc>
+#endif
+#include <svl/urihelper.hxx>
+#include <osl/file.hxx>
+#include <unotools/configmgr.hxx>
+
+#ifndef _UTL_BOOTSTRAP_HXX_
+#include <unotools/bootstrap.hxx>
+#endif
+
+namespace framework
+{
+
+//_______________________________________________
+
+//_______________________________________________
+
+BackingComp::BackingComp( const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR )
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+ , m_xSMGR (xSMGR )
+{
+}
+
+//_______________________________________________
+
+BackingComp::~BackingComp()
+{
+}
+
+//_______________________________________________
+
+/** return information about supported interfaces.
+
+ Some interfaces are supported by his class directly, but some other ones are
+ used by aggregation. An instance of this class must provide some window interfaces.
+ But it must represent a VCL window behind such interfaces too! So we use an internal
+ saved window member to ask it for it's interfaces and return it. But we must be aware then,
+ that it can be destroyed from outside too ...
+
+ @param aType
+ describe the required interface type
+
+ @return An Any holding the instance, which provides the queried interface.
+ Note: There exist two possible results ... this instance itself and her window member!
+ */
+
+css::uno::Any SAL_CALL BackingComp::queryInterface( /*IN*/ const css::uno::Type& aType )
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Any aResult;
+
+ // first look for own supported interfaces
+ aResult = ::cppu::queryInterface(
+ aType,
+ static_cast< css::lang::XTypeProvider* >(this),
+ static_cast< css::lang::XServiceInfo* >(this),
+ static_cast< css::lang::XInitialization* >(this),
+ static_cast< css::frame::XController* >(this),
+ static_cast< css::lang::XComponent* >(this),
+ static_cast< css::lang::XEventListener* >(this),
+ static_cast< css::awt::XKeyListener* >(static_cast< css::lang::XEventListener* >(this)));
+
+ // then look for supported window interfaces
+ // Note: They exist only, if this instance was initialized
+ // with a valid window reference. It's aggregation on demand ...
+ if (!aResult.hasValue())
+ {
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ if (m_xWindow.is())
+ aResult = m_xWindow->queryInterface(aType);
+ aReadLock.unlock();
+ /* } SAFE */
+ }
+
+ // look for XWeak and XInterface
+ if (!aResult.hasValue())
+ aResult = OWeakObject::queryInterface(aType);
+
+ return aResult;
+}
+
+//_______________________________________________
+
+/** increase ref count of this instance.
+ */
+
+void SAL_CALL BackingComp::acquire()
+ throw()
+{
+ OWeakObject::acquire();
+}
+
+//_______________________________________________
+
+/** decrease ref count of this instance.
+ */
+
+void SAL_CALL BackingComp::release()
+ throw()
+{
+ OWeakObject::release();
+}
+
+//_______________________________________________
+
+/** return collection about all supported interfaces.
+
+ Optimize this method !
+ We initialize a static variable only one time.
+ And we don't must use a mutex at every call!
+ For the first call; pTypeCollection is NULL -
+ for the second call pTypeCollection is different from NULL!
+
+ @return A list of all supported interface types.
+*/
+
+css::uno::Sequence< css::uno::Type > SAL_CALL BackingComp::getTypes()
+ throw(css::uno::RuntimeException)
+{
+ static ::cppu::OTypeCollection* pTypeCollection = NULL;
+ if (!pTypeCollection)
+ {
+ /* GLOBAL SAFE { */
+ ::osl::MutexGuard aGlobalLock(::osl::Mutex::getGlobalMutex());
+ // Control these pointer again ... it can be, that another instance will be faster then this one!
+ if (!pTypeCollection)
+ {
+ /* LOCAL SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XTypeProvider > xProvider(m_xWindow, css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ /* } LOCAL SAFE */
+
+ css::uno::Sequence< css::uno::Type > lWindowTypes;
+ if (xProvider.is())
+ lWindowTypes = xProvider->getTypes();
+
+ static ::cppu::OTypeCollection aTypeCollection(
+ ::getCppuType((const ::com::sun::star::uno::Reference< css::lang::XInitialization >*)NULL ),
+ ::getCppuType((const ::com::sun::star::uno::Reference< css::lang::XTypeProvider >*)NULL ),
+ ::getCppuType((const ::com::sun::star::uno::Reference< css::lang::XServiceInfo >*)NULL ),
+ ::getCppuType((const ::com::sun::star::uno::Reference< css::frame::XController >*)NULL ),
+ ::getCppuType((const ::com::sun::star::uno::Reference< css::lang::XComponent >*)NULL ),
+ lWindowTypes);
+
+ pTypeCollection = &aTypeCollection;
+ }
+ /* } GLOBAL SAFE */
+ }
+ return pTypeCollection->getTypes();
+}
+
+//_______________________________________________
+
+/** create one unique Id for all instances of this class.
+
+ Optimize this method
+ We initialize a static variable only one time. And we don't must use a mutex at every call!
+ For the first call; pID is NULL - for the second call pID is different from NULL!
+
+ @return A byte array, which represent the unique id.
+*/
+
+css::uno::Sequence< sal_Int8 > SAL_CALL BackingComp::getImplementationId()
+ throw(css::uno::RuntimeException)
+{
+ static ::cppu::OImplementationId* pID = NULL;
+ if (!pID)
+ {
+ /* GLOBAL SAFE { */
+ ::osl::MutexGuard aLock(::osl::Mutex::getGlobalMutex());
+ // Control these pointer again ... it can be, that another instance will be faster then this one!
+ if (!pID)
+ {
+ static ::cppu::OImplementationId aID(sal_False);
+ pID = &aID;
+ }
+ /* } GLOBAL SAFE */
+ }
+ return pID->getImplementationId();
+}
+
+//_______________________________________________
+
+/** returns a static implementation name for this UNO service.
+
+ Because this value is needed at different places and our class is used
+ by some generic macros too, we have to use a static impl method for that!
+
+ @see impl_getStaticImplementationName()
+ @see IMPLEMENTATIONNAME
+
+ @return The implementation name of this class.
+*/
+
+::rtl::OUString SAL_CALL BackingComp::getImplementationName()
+ throw(css::uno::RuntimeException)
+{
+ return impl_getStaticImplementationName();
+}
+
+//_______________________________________________
+
+/** returns information about supported services.
+
+ Because this value is needed at different places and our class is used
+ by some generic macros too, we have to use a static impl method for that!
+
+ @see impl_getStaticSupportedServiceNames()
+ @see SERVICENAME
+
+ @return <TRUE/> if the queried service is supported;
+ <br><FALSE/> otherwise.
+*/
+
+sal_Bool SAL_CALL BackingComp::supportsService( /*IN*/ const ::rtl::OUString& sServiceName )
+ throw(css::uno::RuntimeException)
+{
+ return (
+ sServiceName.equals(SERVICENAME_STARTMODULE ) ||
+ sServiceName.equals(SERVICENAME_FRAMECONTROLLER)
+ );
+}
+
+//_______________________________________________
+
+/** returns collection of supported services.
+
+ Because this value is needed at different places and our class is used
+ by some generic macros too, we have to use a static impl method for that!
+
+ @see impl_getStaticSupportedServiceNames()
+ @see SERVICENAME
+
+ @return A list of all supported uno service names.
+*/
+
+css::uno::Sequence< ::rtl::OUString > SAL_CALL BackingComp::getSupportedServiceNames()
+ throw(css::uno::RuntimeException)
+{
+ return impl_getStaticSupportedServiceNames();
+}
+
+//_______________________________________________
+
+/** returns static implementation name.
+
+ Because this value is needed at different places and our class is used
+ by some generic macros too, we have to use a static impl method for that!
+
+ @see impl_getStaticSupportedServiceNames()
+ @see SERVICENAME
+
+ @return The implementation name of this class.
+*/
+
+::rtl::OUString BackingComp::impl_getStaticImplementationName()
+{
+ return IMPLEMENTATIONNAME_STARTMODULE;
+}
+
+//_______________________________________________
+
+/** returns static list of supported service names.
+
+ Because this value is needed at different places and our class is used
+ by some generic macros too, we have to use a static impl method for that!
+
+ @see impl_getStaticSupportedServiceNames()
+ @see SERVICENAME
+
+ @return A list of all supported uno service names.
+*/
+
+css::uno::Sequence< ::rtl::OUString > BackingComp::impl_getStaticSupportedServiceNames()
+{
+ css::uno::Sequence< ::rtl::OUString > lNames(1);
+ lNames[0] = SERVICENAME_STARTMODULE;
+ return lNames;
+}
+
+//_______________________________________________
+
+/** returns a new instance of this class.
+
+ This factory method is registered inside the UNO runtime
+ and will be called for every createInstance() request from outside,
+ which wish to use this service.
+
+ @param xSMGR
+ reference to the uno service manager, which call us
+ We use it too, to set it at the new created instance.
+
+ @return A new instance as uno reference.
+*/
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL BackingComp::impl_createInstance( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
+ throw(css::uno::Exception)
+{
+ BackingComp* pObject = new BackingComp(xSMGR);
+ return css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(pObject), css::uno::UNO_QUERY);
+}
+
+//_______________________________________________
+
+/** returns a new factory instance for instances of this class.
+
+ It uses a helper class of the cppuhelper project as factory.
+ It will be initialized with all neccessary informations and
+ will be able afterwards to create instance of this class.
+ This factory call us back inside our method impl_createInstance().
+ So we can create and initialize ourself. Only filtering of creation
+ requests will be done by this factory.
+
+ @param xSMGR
+ reference to the uno service manager, which call us
+
+ @return A new instance of our factory.
+*/
+
+css::uno::Reference< css::lang::XSingleServiceFactory > BackingComp::impl_createFactory( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
+{
+ css::uno::Reference< css::lang::XSingleServiceFactory > xReturn(
+ cppu::createSingleFactory(
+ xSMGR,
+ BackingComp::impl_getStaticImplementationName(),
+ BackingComp::impl_createInstance,
+ BackingComp::impl_getStaticSupportedServiceNames()));
+ return xReturn;
+}
+
+//_______________________________________________
+
+/**
+ attach this component to a target frame.
+
+ We has to use the container window of this frame as parent window of our own component window.
+ But it's not allowed to work with it realy. May another component used it too.
+ Currently we need it only to create our child component window and support it's
+ interfaces inside our queryInterface() method. The user of us must have e.g. the
+ XWindow interface of it to be able to call setComponent(xWindow,xController) at the
+ frame!
+
+ May he will do the following things:
+
+ <listing>
+ XController xBackingComp = (XController)UnoRuntime.queryInterface(
+ XController.class,
+ xSMGR.createInstance(SERVICENAME_STARTMODULE));
+
+ // at this time XWindow isn't present at this instance!
+ XWindow xBackingComp = (XWindow)UnoRuntime.queryInterface(
+ XWindow.class,
+ xBackingComp);
+
+ // attach controller to the frame
+ // We will use it's container window, to create
+ // the component window. From now we offer the window interfaces!
+ xBackingComp.attachFrame(xFrame);
+
+ XWindow xBackingComp = (XWindow)UnoRuntime.queryInterface(
+ XWindow.class,
+ xBackingComp);
+
+ // Our user can set us at the frame as new component
+ xFrame.setComponent(xBackingWin, xBackingComp);
+
+ // But that had no effect to our view state.
+ // We must be started to create our UI elements like e.g. menu, title, background ...
+ XInitialization xBackingInit = (XInitialization)UnoRuntime.queryInterface(
+ XInitialization.class,
+ xBackingComp);
+
+ xBackingInit.initialize(lArgs);
+ </listing>
+
+ @param xFrame
+ reference to our new target frame
+
+ @throw com::sun::star::uno::RuntimeException
+ if the given frame reference is wrong or component window couldn't be created
+ successfully.
+ We throw it too, if we already attached to a frame. Because we don't support
+ reparenting of our component window on demand!
+*/
+
+void SAL_CALL BackingComp::attachFrame( /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame )
+ throw (css::uno::RuntimeException)
+{
+ /* SAFE */
+ WriteGuard aWriteLock(m_aLock);
+
+ // check some required states
+ if (m_xFrame.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("already attached"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ if (!xFrame.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("invalid frame reference"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ if (!m_xWindow.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("instance seams to be not or wrong initialized"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ // safe the frame reference
+ m_xFrame = xFrame;
+
+ // establish drag&drop mode
+ ::framework::DropTargetListener* pDropListener = new ::framework::DropTargetListener(m_xSMGR, m_xFrame);
+ m_xDropTargetListener = css::uno::Reference< css::datatransfer::dnd::XDropTargetListener >(static_cast< ::cppu::OWeakObject* >(pDropListener), css::uno::UNO_QUERY);
+
+ css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer(m_xSMGR->createInstance(SERVICENAME_VCLTOOLKIT), css::uno::UNO_QUERY);
+ if (xTransfer.is())
+ {
+ css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget(m_xWindow);
+ if (xDropTarget.is())
+ {
+ xDropTarget->addDropTargetListener(m_xDropTargetListener);
+ xDropTarget->setActive(sal_True);
+ }
+ }
+
+ // initialize the component and it's parent window
+ css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow();
+ WorkWindow* pParent = (WorkWindow*)VCLUnoHelper::GetWindow(xParentWindow);
+ Window* pWindow = VCLUnoHelper::GetWindow(m_xWindow);
+
+ // disable full screen mode of the frame!
+ if (pParent->IsFullScreenMode())
+ {
+ pParent->ShowFullScreenMode(sal_False);
+ pParent->SetMenuBarMode(MENUBAR_MODE_NORMAL);
+ }
+
+ // create the menu bar for the backing component
+ css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ xPropSet->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
+ if (xLayoutManager.is())
+ {
+ xLayoutManager->lock();
+ xLayoutManager->createElement( DECLARE_ASCII( "private:resource/menubar/menubar" ));
+ /* #i85963# new backing window comes withoud standard bar and statusbar
+ xLayoutManager->createElement( DECLARE_ASCII( "private:resource/toolbar/standardbar" ));
+ xLayoutManager->createElement( DECLARE_ASCII( "private:resource/statusbar/statusbar" ));
+ xLayoutManager->showElement ( DECLARE_ASCII( "private:resource/toolbar/standardbar" ));
+ xLayoutManager->showElement ( DECLARE_ASCII( "private:resource/statusbar/statusbar" ));
+ */
+ xLayoutManager->unlock();
+ }
+
+ // set help ID for our canvas
+ pWindow->SetHelpId(HID_BACKINGWINDOW);
+
+ // inform BackingWindow about frame
+ BackingWindow* pBack = dynamic_cast<BackingWindow*>(pWindow );
+ if( pBack )
+ pBack->setOwningFrame( m_xFrame );
+
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ This component does not know any model. It will be represented by a window and
+ it's controller only.
+
+ return <FALSE/> everytime.
+ */
+
+sal_Bool SAL_CALL BackingComp::attachModel( /*IN*/ const css::uno::Reference< css::frame::XModel >& )
+ throw (css::uno::RuntimeException)
+{
+ return sal_False;
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ This component does not know any model. It will be represented by a window and
+ it's controller only.
+
+ return An empty reference every time.
+ */
+
+css::uno::Reference< css::frame::XModel > SAL_CALL BackingComp::getModel()
+ throw (css::uno::RuntimeException)
+{
+ return css::uno::Reference< css::frame::XModel >();
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ return An empty value.
+ */
+
+css::uno::Any SAL_CALL BackingComp::getViewData()
+ throw (css::uno::RuntimeException)
+{
+ return css::uno::Any();
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ @param aData
+ not used.
+ */
+
+void SAL_CALL BackingComp::restoreViewData( /*IN*/ const css::uno::Any& )
+ throw (css::uno::RuntimeException)
+{
+}
+
+//_______________________________________________
+
+/** returns the attached frame for this component.
+
+ @see attachFrame()
+
+ @return The internaly saved frame reference.
+ Can be null, if attachFrame() was not called before.
+ */
+
+css::uno::Reference< css::frame::XFrame > SAL_CALL BackingComp::getFrame()
+ throw (css::uno::RuntimeException)
+{
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ return m_xFrame;
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/** ask controller for it's current working state.
+
+ If somehwere whish to close this component, it must suspend the controller before.
+ That will be a chance for it to disagree with that AND show any UI for a possible
+ UI user.
+
+ @param bSuspend
+ If its set to sal_True this controller should be suspended.
+ sal_False will resuspend it.
+
+ @return sal_True if the request could be finished successfully; sal_False otherwise.
+ */
+
+sal_Bool SAL_CALL BackingComp::suspend( /*IN*/ sal_Bool )
+ throw (css::uno::RuntimeException)
+{
+ /* FIXME ... implemented by using default :-( */
+ return sal_True;
+}
+
+//_______________________________________________
+
+/** callback from our window member.
+
+ Our internal saved window wish to die. It will be disposed from outside (may be the frame)
+ and inform us. We must release its reference only here. Of course we check the given reference
+ here and reject callback from unknown sources.
+
+ Note: deregistration as listener isnt neccessary here. The broadcaster do it automaticly.
+
+ @param aEvent
+ describe the broadcaster of this callback
+
+ @throw ::com::sun::star::uno::RuntimeException
+ if the broadcaster doesn't represent the expected window reference.
+*/
+
+void SAL_CALL BackingComp::disposing( /*IN*/ const css::lang::EventObject& aEvent )
+ throw(css::uno::RuntimeException)
+{
+ // Attention: dont free m_pAccExec here! see comments inside dtor and
+ // keyPressed() for further details.
+
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ if (!aEvent.Source.is() || aEvent.Source!=m_xWindow || !m_xWindow.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("unexpected source or called twice"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ m_xWindow = css::uno::Reference< css::awt::XWindow >();
+
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/** kill this instance.
+
+ It can be called from our owner frame only. But there is no possibility to check the calli.
+ We have to release all our internal used ressources and die. From this point we can throw
+ DisposedExceptions for every further interface request ... but current implementation doesn`t do so ...
+
+*/
+
+void SAL_CALL BackingComp::dispose()
+ throw(css::uno::RuntimeException)
+{
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ // kill the menu
+ css::util::URL aURL;
+ aURL.Complete = DECLARE_ASCII(".uno:close");
+ css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
+ if (xParser.is())
+ xParser->parseStrict(aURL);
+
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider(m_xFrame, css::uno::UNO_QUERY);
+ if (xProvider.is())
+ {
+ css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, SPECIALTARGET_MENUBAR, 0);
+ if (xDispatch.is())
+ xDispatch->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue>());
+ }
+
+ // deregister drag&drop helper
+ if (m_xDropTargetListener.is())
+ {
+ css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer(m_xSMGR->createInstance(SERVICENAME_VCLTOOLKIT), css::uno::UNO_QUERY);
+ if (xTransfer.is())
+ {
+ css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget(m_xWindow);
+ if (xDropTarget.is())
+ {
+ xDropTarget->removeDropTargetListener(m_xDropTargetListener);
+ xDropTarget->setActive(sal_False);
+ }
+ }
+ m_xDropTargetListener = css::uno::Reference< css::datatransfer::dnd::XDropTargetListener >();
+ }
+
+ // stop listening at the window
+ if (m_xWindow.is())
+ {
+ css::uno::Reference< css::lang::XComponent > xBroadcaster(m_xWindow, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ {
+ css::uno::Reference< css::lang::XEventListener > xEventThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ xBroadcaster->removeEventListener(xEventThis);
+ }
+ css::uno::Reference< css::awt::XKeyListener > xKeyThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ m_xWindow->removeKeyListener(xKeyThis);
+ m_xWindow = css::uno::Reference< css::awt::XWindow >();
+ }
+
+ // forget all other used references
+ m_xFrame = css::uno::Reference< css::frame::XFrame >();
+ m_xSMGR = css::uno::Reference< css::lang::XMultiServiceFactory >();
+
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ @param xListener
+ not used.
+
+ @throw ::com::sun::star::uno::RuntimeException
+ because the listener expect to be holded alive by this container.
+ We must inform it about this unsupported feature.
+ */
+
+void SAL_CALL BackingComp::addEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
+ throw(css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("not supported"),
+ static_cast< ::cppu::OWeakObject* >(this));
+}
+
+//_______________________________________________
+
+/** not supported.
+
+ Because registration is not supported too, we must do nothing here. Nobody can call this method realy.
+
+ @param xListener
+ not used.
+ */
+
+void SAL_CALL BackingComp::removeEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//_______________________________________________
+
+/**
+ force initialiation for this component.
+
+ Inside attachFrame() we created our component window. But it was not allowed there, to
+ initialitze it. E.g. the menu must be set at the container window of the frame, which
+ is our parent window. But may at that time another component used it.
+ That's why our creator has to inform us, when it's time to initialize us realy.
+ Currently only calling of this method must be done. But further implementatoins
+ can use special in parameter to configure this initialization ...
+
+ @param lArgs
+ currently not used
+
+ @throw com::sun::star::uno::RuntimeException
+ if some ressources are missing
+ Means if may be attachedFrame() wasn't called before.
+ */
+
+void SAL_CALL BackingComp::initialize( /*IN*/ const css::uno::Sequence< css::uno::Any >& lArgs )
+ throw(css::uno::Exception, css::uno::RuntimeException)
+{
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_xWindow.is())
+ throw css::uno::Exception(
+ ::rtl::OUString::createFromAscii("already initialized"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ css::uno::Reference< css::awt::XWindow > xParentWindow;
+ if (
+ (lArgs.getLength()!=1 ) ||
+ (!(lArgs[0] >>= xParentWindow)) ||
+ (!xParentWindow.is() )
+ )
+ {
+ throw css::uno::Exception(
+ ::rtl::OUString::createFromAscii("wrong or corrupt argument list"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ // create the component window
+ Window* pParent = VCLUnoHelper::GetWindow(xParentWindow);
+ Window* pWindow = new BackingWindow(pParent);
+ m_xWindow = VCLUnoHelper::GetInterface(pWindow);
+
+ if (!m_xWindow.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("couldn't create component window"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ // start listening for window disposing
+ // It's set at our owner frame as component window later too. So it will may be disposed there ...
+ css::uno::Reference< css::lang::XComponent > xBroadcaster(m_xWindow, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addEventListener(static_cast< css::lang::XEventListener* >(this));
+
+ m_xWindow->setVisible(sal_True);
+
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/**
+ */
+
+void SAL_CALL BackingComp::keyPressed( /*IN*/ const css::awt::KeyEvent& )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//_______________________________________________
+
+/**
+ */
+
+void SAL_CALL BackingComp::keyReleased( /*IN*/ const css::awt::KeyEvent& )
+ throw(css::uno::RuntimeException)
+{
+ /* Attention
+ Please use keyPressed() instead of this method. Otherwhise it would be possible, that
+ - a key input may be first switch to the backing mode
+ - and this component register itself as key listener too
+ - and it's first event will be a keyRealeased() for the already well known event, which switched to the backing mode!
+ So it will be handled twice! document => backing mode => exit app ...
+ */
+}
+
+} // namespace framework
diff --git a/framework/source/services/backingwindow.cxx b/framework/source/services/backingwindow.cxx
new file mode 100644
index 000000000000..1d1e877a5a86
--- /dev/null
+++ b/framework/source/services/backingwindow.cxx
@@ -0,0 +1,1153 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+#include "backingwindow.hxx"
+#include "classes/resource.hrc"
+#include "framework.hrc"
+#include "classes/fwkresid.hxx"
+#include <services.h>
+
+#include "vcl/metric.hxx"
+#include "vcl/mnemonic.hxx"
+#include "vcl/menu.hxx"
+#include "vcl/svapp.hxx"
+
+#include "tools/urlobj.hxx"
+
+#include "unotools/dynamicmenuoptions.hxx"
+#include "unotools/historyoptions.hxx"
+#include "svtools/imagemgr.hxx"
+#include "svtools/svtools.hrc"
+
+#include "comphelper/processfactory.hxx"
+#include "comphelper/sequenceashashmap.hxx"
+#include "comphelper/configurationhelper.hxx"
+
+#include "cppuhelper/implbase1.hxx"
+
+#include "rtl/strbuf.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "osl/file.h"
+
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/container/XNameAccess.hpp"
+#include "com/sun/star/system/XSystemShellExecute.hpp"
+#include "com/sun/star/system/SystemShellExecuteFlags.hpp"
+#include "com/sun/star/task/XJobExecutor.hpp"
+#include "com/sun/star/util/XStringWidth.hpp"
+
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace framework;
+
+#define WRITER_URL "private:factory/swriter"
+#define CALC_URL "private:factory/scalc"
+#define IMPRESS_WIZARD_URL "private:factory/simpress?slot=6686"
+#define DRAW_URL "private:factory/sdraw"
+#define BASE_URL "private:factory/sdatabase?Interactive"
+#define MATH_URL "private:factory/smath"
+#define TEMPLATE_URL "slot:5500"
+#define OPEN_URL ".uno:Open"
+
+DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
+ ToolBox( pParent, nStyle )
+{
+ SetBackground();
+ SetPaintTransparent( sal_True );
+}
+
+void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
+ {
+ calcMinSize();
+ SetBackground();
+ SetPaintTransparent( sal_True );
+ }
+}
+
+void DecoToolBox::calcMinSize()
+{
+ ToolBox aTbx( GetParent() );
+ sal_uInt16 nItems = GetItemCount();
+ for( sal_uInt16 i = 0; i < nItems; i++ )
+ {
+ sal_uInt16 nId = GetItemId( i );
+ aTbx.InsertItem( nId, GetItemImage( nId ) );
+ }
+ aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
+ maMinSize = aTbx.CalcWindowSizePixel();
+}
+
+Size DecoToolBox::getMinSize()
+{
+ return maMinSize;
+}
+
+class RecentFilesStringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth >
+{
+ public:
+ RecentFilesStringLength() {}
+ virtual ~RecentFilesStringLength() {}
+
+ // XStringWidth
+ sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
+ throw (::com::sun::star::uno::RuntimeException)
+ {
+ return aString.getLength();
+ }
+};
+
+#define STC_BUTTON_STYLE (WB_LEFT | WB_VCENTER | WB_FLATBUTTON | WB_BEVELBUTTON)
+
+BackingWindow::BackingWindow( Window* i_pParent ) :
+ Window( i_pParent, FwkResId( DLG_BACKING ) ),
+ maWelcome( this, WB_LEFT ),
+ maProduct( this, WB_LEFT ),
+ maWriterButton( this, STC_BUTTON_STYLE ),
+ maCalcButton( this, STC_BUTTON_STYLE ),
+ maImpressButton( this, STC_BUTTON_STYLE ),
+ maOpenButton( this, STC_BUTTON_STYLE ),
+ maDrawButton( this, STC_BUTTON_STYLE ),
+ maDBButton( this, STC_BUTTON_STYLE ),
+ maMathButton( this, STC_BUTTON_STYLE ),
+ maTemplateButton( this, STC_BUTTON_STYLE ),
+ maToolbox( this, WB_DIALOGCONTROL ),
+ maWelcomeString( FwkResId( STR_BACKING_WELCOME ) ),
+ maProductString( FwkResId( STR_BACKING_WELCOMEPRODUCT ) ),
+ maOpenString( FwkResId( STR_BACKING_FILE ) ),
+ maTemplateString( FwkResId( STR_BACKING_TEMPLATE ) ),
+ maButtonImageSize( 10, 10 ),
+ mbInitControls( false ),
+ mnLayoutStyle( 0 ),
+ mpAccExec( NULL ),
+ mnBtnPos( 120 ),
+ mnBtnTop( 150 ),
+ mpRecentMenu( NULL )
+{
+ mnColumnWidth[0] = mnColumnWidth[1] = 0;
+ mnTextColumnWidth[0] = mnTextColumnWidth[1] = 0;
+
+ try
+ {
+ Reference<lang::XMultiServiceFactory> xConfig( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY);
+ if( xConfig.is() )
+ {
+ Sequence<Any> args(1);
+ PropertyValue val(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath") ),
+ 0,
+ Any(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Common/Help/StartCenter"))),
+ PropertyState_DIRECT_VALUE);
+ args.getArray()[0] <<= val;
+ Reference<container::XNameAccess> xNameAccess(xConfig->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,args), UNO_QUERY);
+ if( xNameAccess.is() )
+ {
+ //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
+ Any value( xNameAccess->getByName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartCenterLayoutStyle"))) );
+ mnLayoutStyle = value.get<sal_Int32>();
+ }
+ }
+ }
+ catch (Exception& )
+ {
+ }
+
+ String aExtHelpText( FwkResId( STR_BACKING_EXTHELP ) );
+ String aRegHelpText( FwkResId( STR_BACKING_REGHELP ) );
+ String aInfoHelpText( FwkResId( STR_BACKING_INFOHELP ) );
+ String aTplRepHelpText( FwkResId( STR_BACKING_TPLREP ) );
+
+ // clean up resource stack
+ FreeResource();
+
+ maWelcome.SetPaintTransparent( sal_True );
+ maProduct.SetPaintTransparent( sal_True );
+ EnableChildTransparentMode();
+
+ SetStyle( GetStyle() | WB_DIALOGCONTROL );
+
+ // force tab cycling in toolbox
+ maToolbox.SetStyle( maToolbox.GetStyle() | WB_FORCETABCYCLE );
+
+ // insert toolbox items
+ maToolbox.InsertItem( nItemId_TplRep, Image() );
+ maToolbox.SetItemText( nItemId_TplRep, aTplRepHelpText );
+ maToolbox.SetQuickHelpText( nItemId_TplRep, aTplRepHelpText );
+ maToolbox.SetItemCommand( nItemId_TplRep, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:TemplateRepository" ) ) );
+ maToolbox.ShowItem( nItemId_TplRep );
+
+ maToolbox.InsertItem( nItemId_Extensions, Image() );
+ maToolbox.SetQuickHelpText( nItemId_Extensions, aExtHelpText );
+ maToolbox.SetItemText( nItemId_Extensions, aExtHelpText );
+ maToolbox.SetItemCommand( nItemId_Extensions, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Extensions" ) ) );
+ maToolbox.ShowItem( nItemId_Extensions );
+
+ maToolbox.InsertItem( nItemId_Reg, Image() );
+ maToolbox.SetQuickHelpText( nItemId_Reg, aRegHelpText );
+ maToolbox.SetItemText( nItemId_Reg, aRegHelpText );
+ maToolbox.SetItemCommand( nItemId_Reg, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Register" ) ) );
+ maToolbox.ShowItem( nItemId_Reg );
+
+ maToolbox.InsertItem( nItemId_Info, Image() );
+ maToolbox.SetItemText( nItemId_Info, aInfoHelpText );
+ maToolbox.SetQuickHelpText( nItemId_Info, aInfoHelpText );
+ maToolbox.SetItemCommand( nItemId_Info, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Info" ) ) );
+ maToolbox.ShowItem( nItemId_Info );
+
+ // get dispatch provider
+ mxDesktop = Reference<XDesktop>( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_DESKTOP ),UNO_QUERY );
+ if( mxDesktop.is() )
+ mxDesktopDispatchProvider = Reference< XDispatchProvider >( mxDesktop, UNO_QUERY );
+
+ maWriterButton.SetHelpId( ".HelpId:StartCenter:WriterButton" );
+ maCalcButton.SetHelpId( ".HelpId:StartCenter:CalcButton" );
+ maImpressButton.SetHelpId( ".HelpId:StartCenter:ImpressButton" );
+ maDrawButton.SetHelpId( ".HelpId:StartCenter:DrawButton" );
+ maDBButton.SetHelpId( ".HelpId:StartCenter:DBButton" );
+ maMathButton.SetHelpId( ".HelpId:StartCenter:MathButton" );
+ maTemplateButton.SetHelpId( ".HelpId:StartCenter:TemplateButton" );
+ maOpenButton.SetHelpId( ".HelpId:StartCenter:OpenButton" );
+ maToolbox.SetHelpId( ".HelpId:StartCenter:Toolbox" );
+
+ // init background
+ initBackground();
+
+ // add some breathing space for the images
+ maButtonImageSize.Width() += 12;
+ maButtonImageSize.Height() += 12;
+
+}
+
+
+BackingWindow::~BackingWindow()
+{
+ delete mpRecentMenu;
+ delete mpAccExec;
+}
+
+void BackingWindow::GetFocus()
+{
+ if( IsVisible() )
+ maWriterButton.GrabFocus();
+ Window::GetFocus();
+}
+
+class ImageContainerRes : public Resource
+{
+ public:
+ ImageContainerRes( const ResId& i_rId ) : Resource( i_rId ) {}
+ ~ImageContainerRes() { FreeResource(); }
+};
+
+void BackingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
+ {
+ initBackground();
+ Invalidate();
+ }
+}
+
+void BackingWindow::prepareRecentFileMenu()
+{
+ if( ! mpRecentMenu )
+ mpRecentMenu = new PopupMenu();
+ mpRecentMenu->Clear();
+ maRecentFiles.clear();
+
+ // get recent file list and dispatch arguments
+ Sequence< Sequence< PropertyValue > > aHistoryList( SvtHistoryOptions().GetList( ePICKLIST ) );
+
+ sal_Int32 nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
+
+ if( ( nPickListMenuItems > 0 ) )
+ {
+ maRecentFiles.reserve( nPickListMenuItems );
+ for ( sal_Int32 i = 0; i < nPickListMenuItems; i++ )
+ {
+ Sequence< PropertyValue >& rPickListEntry = aHistoryList[i];
+ rtl::OUString aURL, aFilter, aFilterOpt, aTitle;
+
+ for ( sal_Int32 j = 0; j < rPickListEntry.getLength(); j++ )
+ {
+ const Any& a = rPickListEntry[j].Value;
+
+ if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
+ a >>= aURL;
+ else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
+ {
+ a >>= aFilter;
+ sal_Int32 nPos = aFilter.indexOf( '|' );
+ if ( nPos >= 0 )
+ {
+ if ( nPos < ( aFilter.getLength() - 1 ) )
+ aFilterOpt = aFilter.copy( nPos+1 );
+ aFilter = aFilter.copy( 0, nPos-1 );
+ }
+ }
+ else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
+ a >>= aTitle;
+ }
+ maRecentFiles.push_back( LoadRecentFile() );
+ maRecentFiles.back().aTargetURL = aURL;
+
+ sal_Int32 nArgs = aFilterOpt.getLength() ? 4 : 3;
+ Sequence< PropertyValue >& rArgsList( maRecentFiles.back().aArgSeq );
+ rArgsList.realloc( nArgs );
+
+ nArgs--;
+ rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
+ rArgsList[nArgs].Value = makeAny( aFilter );
+
+ if( aFilterOpt.getLength() )
+ {
+ nArgs--;
+ rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" ));
+ rArgsList[nArgs].Value = makeAny( aFilterOpt );
+ }
+
+ // documents in the picklist will never be opened as templates
+ nArgs--;
+ rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate" ));
+ rArgsList[nArgs].Value = makeAny( (sal_Bool) sal_False );
+
+ nArgs--;
+ rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
+ rArgsList[nArgs].Value = makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:user" ) ) );
+
+ // and finally create an entry in the popupmenu
+ rtl::OUString aMenuTitle;
+ INetURLObject aURLObj( aURL );
+
+ if ( aURLObj.GetProtocol() == INET_PROT_FILE )
+ {
+ // Do handle file URL differently => convert it to a system
+ // path and abbreviate it with a special function:
+ String aFileSystemPath( aURLObj.getFSysPath( INetURLObject::FSYS_DETECT ) );
+
+ rtl::OUString aSystemPath( aFileSystemPath );
+ rtl::OUString aCompactedSystemPath;
+
+ oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
+ if ( !nError )
+ aMenuTitle = String( aCompactedSystemPath );
+ else
+ aMenuTitle = aSystemPath;
+ }
+ else
+ {
+ // Use INetURLObject to abbreviate all other URLs
+ Reference< util::XStringWidth > xStringLength( new RecentFilesStringLength() );
+ aMenuTitle = aURLObj.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
+ }
+ rtl::OUStringBuffer aBuf( aMenuTitle.getLength() + 5 );
+ if( i < 9 )
+ {
+ aBuf.append( sal_Unicode( '~' ) );
+ aBuf.append( i+1 );
+ }
+ else if( i == 9 )
+ aBuf.appendAscii( "1~0" );
+ else
+ aBuf.append( i+1 );
+ aBuf.appendAscii( ": " );
+ aBuf.append( aMenuTitle );
+ mpRecentMenu->InsertItem( static_cast<sal_uInt16>(i+1), aBuf.makeStringAndClear() );
+ }
+ }
+ else
+ {
+ String aNoDoc( FwkResId( STR_NODOCUMENT ) );
+ mpRecentMenu->InsertItem( 0xffff, aNoDoc );
+ }
+ maOpenButton.SetPopupMenu( mpRecentMenu );
+}
+
+void BackingWindow::initBackground()
+{
+ SetBackground( GetSettings().GetStyleSettings().GetWorkspaceGradient() );
+
+ bool bDark = GetSettings().GetStyleSettings().GetHighContrastMode();
+ if( bDark )
+ maWelcomeTextColor = maLabelTextColor = Color( COL_WHITE );
+ else if( mnLayoutStyle == 1 )
+ maWelcomeTextColor = maLabelTextColor = Color( COL_BLACK );
+ else
+ maWelcomeTextColor = maLabelTextColor = Color( 0x26, 0x35, 0x42 );
+
+ Color aTextBGColor( bDark ? COL_BLACK : COL_WHITE );
+
+ // select image set
+ ImageContainerRes aRes( FwkResId( bDark ? RES_BACKING_IMAGES_HC : RES_BACKING_IMAGES ) );
+
+ // scale middle segment
+ Size aMiddleSize;
+ if( !! maBackgroundMiddle )
+ aMiddleSize = maBackgroundMiddle.GetSizePixel();
+ // load middle segment
+ maBackgroundMiddle = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_MIDDLE ) );
+ // and scale it to previous size
+ if( aMiddleSize.Width() && aMiddleSize.Height() )
+ maBackgroundMiddle.Scale( aMiddleSize );
+
+ if( GetSettings().GetLayoutRTL() )
+ {
+ // replace images by RTL versions
+ maBackgroundLeft = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RTL_RIGHT ) );
+ maBackgroundRight = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RTL_LEFT) );
+ }
+ else
+ {
+ maBackgroundLeft = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_LEFT ) );
+ maBackgroundRight = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RIGHT ) );
+ }
+ maToolbox.SetItemImage( nItemId_Extensions, BitmapEx( FwkResId( BMP_BACKING_EXT ) ) );
+ maToolbox.SetItemImage( nItemId_Reg, BitmapEx( FwkResId( BMP_BACKING_REG ) ) );
+ maToolbox.SetItemImage( nItemId_Info, BitmapEx( FwkResId( BMP_BACKING_INFO ) ) );
+ maToolbox.SetItemImage( nItemId_TplRep, BitmapEx( FwkResId( BMP_BACKING_TPLREP ) ) );
+
+ maWelcome.SetControlForeground( maWelcomeTextColor );
+ maWelcome.SetBackground();
+ maProduct.SetControlForeground( maWelcomeTextColor );
+ maProduct.SetBackground();
+
+ if( mnLayoutStyle == 1 )
+ {
+ if( Application::GetSettings().GetLayoutRTL() )
+ mnBtnPos = maBackgroundRight.GetSizePixel().Width() + 40;
+ else
+ mnBtnPos = maBackgroundLeft.GetSizePixel().Width() + 40;
+ }
+
+ // get icon images from fwk resource and set them on the appropriate buttons
+ loadImage( FwkResId( BMP_BACKING_WRITER ), maWriterButton );
+ loadImage( FwkResId( BMP_BACKING_CALC ), maCalcButton );
+ loadImage( FwkResId( BMP_BACKING_IMPRESS ), maImpressButton );
+ loadImage( FwkResId( BMP_BACKING_DRAW ), maDrawButton );
+ loadImage( FwkResId( BMP_BACKING_DATABASE ), maDBButton );
+ loadImage( FwkResId( BMP_BACKING_FORMULA ), maMathButton );
+ loadImage( FwkResId( BMP_BACKING_OPENFILE ), maOpenButton );
+ loadImage( FwkResId( BMP_BACKING_OPENTEMPLATE ), maTemplateButton );
+
+ maOpenButton.SetMenuMode( MENUBUTTON_MENUMODE_TIMED );
+ maOpenButton.SetSelectHdl( LINK( this, BackingWindow, SelectHdl ) );
+ maOpenButton.SetActivateHdl( LINK( this, BackingWindow, ActivateHdl ) );
+}
+
+void BackingWindow::initControls()
+{
+ if( mbInitControls )
+ return;
+
+ mbInitControls = true;
+
+ // calculate dialog size
+ // begin with background bitmap
+ maControlRect = Rectangle( Point(), maBackgroundLeft.GetSizePixel() );
+ maControlRect.Left() += nShadowLeft;
+ maControlRect.Right() -= nShadowRight;
+ maControlRect.Top() += nShadowTop;
+ maControlRect.Bottom() -= nShadowBottom;
+
+ long nYPos = 0;
+ // set bigger welcome string
+ maWelcome.SetText( maWelcomeString );
+ maTextFont = GetSettings().GetStyleSettings().GetLabelFont();
+ maTextFont.SetSize( Size( 0, 18 ) );
+ maTextFont.SetWeight( WEIGHT_BOLD );
+ maWelcome.SetFont( maTextFont );
+ // get metric to get correct width factor and adjust
+ long nW = (maWelcome.GetFontMetric().GetWidth()*95)/100;
+ maTextFont.SetSize( Size( nW, 18 ) );
+
+ maWelcome.SetFont( maTextFont );
+ maWelcome.SetControlFont( maTextFont );
+ maWelcomeSize = Size( maWelcome.GetTextWidth( maWelcomeString ), maWelcome.GetTextHeight() );
+ maWelcomeSize.Width() = (maWelcomeSize.Width() * 20)/19;
+
+ nYPos += (maWelcomeSize.Height()*3)/2;
+
+ if( maControlRect.GetWidth() < mnBtnPos + maWelcomeSize.Width() + 20 )
+ maControlRect.Right() = maControlRect.Left() + maWelcomeSize.Width() + mnBtnPos + 20;
+
+ nYPos += maWelcomeSize.Height();
+
+ // set product string
+ maTextFont.SetSize( Size( 0, 30 ) );
+ maProduct.SetFont( maTextFont );
+
+ // get metric to get correct width factor and adjust
+ nW = (maProduct.GetFontMetric().GetWidth()*95)/100;
+ maTextFont.SetSize( Size( nW, 28 ) );
+
+ maProduct.SetFont( maTextFont );
+ maProduct.SetControlFont( maTextFont );
+ maProduct.SetText( maProductString );
+ maProductSize = Size( maProduct.GetTextWidth( maProductString ), maProduct.GetTextHeight() );
+ maProductSize.Width() = (maProductSize.Width() * 20)/19;
+
+ if( maControlRect.GetWidth() < maProductSize.Width() + mnBtnPos + 10 )
+ maControlRect.Right() = maControlRect.Left() + maProductSize.Width() + mnBtnPos + 10;
+
+ if( mnLayoutStyle == 1 )
+ {
+ maWelcome.Show();
+ maProduct.Show();
+ }
+
+ nYPos += (maProductSize.Height()*3)/2;
+
+ // set a slighly larger font than normal labels on the texts
+ maTextFont.SetSize( Size( 0, 11 ) );
+ maTextFont.SetWeight( WEIGHT_NORMAL );
+
+ // collect the URLs of the entries in the File/New menu
+ SvtModuleOptions aModuleOptions;
+ std::set< rtl::OUString > aFileNewAppsAvailable;
+ SvtDynamicMenuOptions aOpt;
+ Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
+ const rtl::OUString sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
+
+ const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
+ const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
+ for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
+ {
+ comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
+ rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, rtl::OUString() ) );
+ if ( sURL.getLength() )
+ aFileNewAppsAvailable.insert( sURL );
+ }
+
+ // create mnemonics on the fly, preregister the mnemonics of the menu
+ MnemonicGenerator aMnemns;
+ maTemplateString = MnemonicGenerator::EraseAllMnemonicChars( maTemplateString );
+ maOpenString = MnemonicGenerator::EraseAllMnemonicChars( maOpenString );
+
+ SystemWindow* pSysWin = GetSystemWindow();
+ if( pSysWin )
+ {
+ MenuBar* pMBar = pSysWin->GetMenuBar();
+ if( pMBar )
+ {
+ for( sal_uInt16 i = 0; i < pMBar->GetItemCount(); i++ )
+ {
+ sal_uInt16 nItemId = pMBar->GetItemId( i );
+ String aItemText( pMBar->GetItemText( nItemId ) );
+ if( aItemText.Len() )
+ aMnemns.RegisterMnemonic( aItemText );
+ }
+ }
+ }
+
+ // layout the buttons
+ layoutButton( WRITER_URL, 0, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SWRITER,
+ maWriterButton, aMnemns );
+ layoutButton( DRAW_URL, 1, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SDRAW,
+ maDrawButton, aMnemns );
+ nYPos += maButtonImageSize.Height() + 10;
+ layoutButton( CALC_URL, 0, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SCALC,
+ maCalcButton, aMnemns );
+ layoutButton( BASE_URL, 1, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SDATABASE,
+ maDBButton, aMnemns );
+ nYPos += maButtonImageSize.Height() + 10;
+ layoutButton( IMPRESS_WIZARD_URL, 0, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SIMPRESS,
+ maImpressButton, aMnemns );
+ layoutButton( MATH_URL, 1, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SMATH,
+ maMathButton, aMnemns );
+
+ nYPos += 3*maButtonImageSize.Height() / 2;
+
+ layoutButton( NULL, 0, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SWRITER,
+ maOpenButton, aMnemns, maOpenString );
+ layoutButton( NULL, 1, aFileNewAppsAvailable,
+ aModuleOptions, SvtModuleOptions::E_SWRITER,
+ maTemplateButton, aMnemns, maTemplateString );
+ nYPos += 10;
+
+ DBG_ASSERT( nYPos < maControlRect.GetHeight(), "misformatting !" );
+ if( mnColumnWidth[0] + mnColumnWidth[1] + mnBtnPos + 20 > maControlRect.GetWidth() )
+ maControlRect.Right() = maControlRect.Left() + mnColumnWidth[0] + mnColumnWidth[1] + mnBtnPos + 20;
+
+ mnTextColumnWidth[0] = mnColumnWidth[0];
+ mnTextColumnWidth[1] = mnColumnWidth[1];
+
+ if( mnTextColumnWidth[1] > mnTextColumnWidth[0] )
+ {
+ mnColumnWidth[0] = mnColumnWidth[1];
+ mnTextColumnWidth[0] = mnTextColumnWidth[1];
+ }
+ else
+ {
+ mnColumnWidth[1] = mnColumnWidth[0];
+ mnTextColumnWidth[1] = mnTextColumnWidth[0];
+ }
+ if( maControlRect.GetWidth() < maControlRect.GetHeight() * 3 / 2 )
+ {
+ maControlRect.Right() = maControlRect.Left() + maControlRect.GetHeight() * 3 / 2;
+ long nDelta = (maControlRect.GetWidth() - mnBtnPos - mnColumnWidth[1] - mnColumnWidth[0] - 20);
+ mnColumnWidth[0] += nDelta/2;
+ mnColumnWidth[1] += nDelta/2;
+ }
+
+ maToolbox.SetSelectHdl( LINK( this, BackingWindow, ToolboxHdl ) );
+ if( mnLayoutStyle == 0 )
+ maToolbox.Show();
+
+ // scale middle map to formatted width
+ Size aMiddleSegmentSize( maControlRect.GetSize().Width() + nShadowLeft + nShadowRight,
+ maBackgroundMiddle.GetSizePixel().Height() );
+
+ long nLW = maBackgroundLeft.GetSizePixel().Width();
+ long nRW = maBackgroundRight.GetSizePixel().Width();
+ if( aMiddleSegmentSize.Width() > nLW + nRW )
+ {
+ aMiddleSegmentSize.Width() -= nLW;
+ aMiddleSegmentSize.Width() -= nRW;
+ maBackgroundMiddle.Scale( aMiddleSegmentSize );
+ }
+ else
+ maBackgroundMiddle = BitmapEx();
+
+ Resize();
+
+ maWriterButton.GrabFocus();
+}
+
+void BackingWindow::loadImage( const ResId& i_rId, PushButton& i_rButton )
+{
+ BitmapEx aBmp( i_rId );
+ Size aImgSize( aBmp.GetSizePixel() );
+ if( aImgSize.Width() > maButtonImageSize.Width() )
+ maButtonImageSize.Width() = aImgSize.Width();
+ if( aImgSize.Height() > maButtonImageSize.Height() )
+ maButtonImageSize.Height() = aImgSize.Height();
+ i_rButton.SetModeImage( aBmp );
+}
+
+void BackingWindow::layoutButton(
+ const char* i_pURL, int nColumn,
+ const std::set<rtl::OUString>& i_rURLS,
+ SvtModuleOptions& i_rOpt, SvtModuleOptions::EModule i_eMod,
+ PushButton& i_rBtn,
+ MnemonicGenerator& i_rMnemns,
+ const String& i_rStr
+ )
+{
+ rtl::OUString aURL( rtl::OUString::createFromAscii( i_pURL ? i_pURL : "" ) );
+ // setup button
+ i_rBtn.SetPaintTransparent( sal_True );
+ i_rBtn.SetClickHdl( LINK( this, BackingWindow, ClickHdl ) );
+ if( i_pURL && (! i_rOpt.IsModuleInstalled( i_eMod ) || i_rURLS.find( aURL ) == i_rURLS.end()) )
+ {
+ i_rBtn.Enable( sal_False );
+ }
+
+ // setup text
+ i_rBtn.SetFont( maTextFont );
+ i_rBtn.SetControlFont( maTextFont );
+ String aText( i_rStr.Len() ? i_rStr : SvFileInformationManager::GetDescription( INetURLObject( aURL ) ) );
+ i_rMnemns.CreateMnemonic( aText );
+ i_rBtn.SetText( aText );
+
+ long nTextWidth = i_rBtn.GetTextWidth( i_rBtn.GetText() );
+
+ nTextWidth += maButtonImageSize.Width() + 8; // add some fuzz to be on the safe side
+ if( nColumn >= 0 && nColumn < static_cast<int>(sizeof(mnColumnWidth)/sizeof(mnColumnWidth[0])) )
+ {
+ if( nTextWidth > mnColumnWidth[nColumn] )
+ mnColumnWidth[nColumn] = nTextWidth;
+ }
+
+ i_rBtn.SetImageAlign( IMAGEALIGN_LEFT );
+ // show the controls
+ i_rBtn.Show();
+}
+
+void BackingWindow::Paint( const Rectangle& )
+{
+
+ // draw bitmap
+ if( GetSettings().GetLayoutRTL() )
+ {
+ Point aTL( maControlRect.TopLeft() );
+ aTL.X() -= nShadowRight;
+ aTL.Y() -= nShadowTop;
+ DrawBitmapEx( aTL, maBackgroundLeft );
+ aTL.X() += maBackgroundLeft.GetSizePixel().Width();
+ if( !!maBackgroundMiddle )
+ {
+ DrawBitmapEx( aTL, maBackgroundMiddle );
+ aTL.X() += maBackgroundMiddle.GetSizePixel().Width();
+ }
+ DrawBitmapEx( aTL, maBackgroundRight );
+ }
+ else
+ {
+ Point aTL( maControlRect.TopLeft() );
+ aTL.X() -= nShadowLeft;
+ aTL.Y() -= nShadowTop;
+ DrawBitmapEx( aTL, maBackgroundLeft );
+ aTL.X() += maBackgroundLeft.GetSizePixel().Width();
+ if( !!maBackgroundMiddle )
+ {
+ DrawBitmapEx( aTL, maBackgroundMiddle );
+ aTL.X() += maBackgroundMiddle.GetSizePixel().Width();
+ }
+ DrawBitmapEx( aTL, maBackgroundRight );
+ }
+}
+
+long BackingWindow::Notify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if( ! mpAccExec )
+ {
+ mpAccExec = svt::AcceleratorExecute::createAcceleratorHelper();
+ mpAccExec->init( comphelper::getProcessServiceFactory(), mxFrame);
+ }
+
+ const KeyEvent* pEvt = rNEvt.GetKeyEvent();
+ const KeyCode& rKeyCode(pEvt->GetKeyCode());
+ if( pEvt && mpAccExec->execute(rKeyCode) )
+ return 1;
+ // #i110344# extrawurst: specialized arrow key control
+ if( rKeyCode.GetModifier() == 0 )
+ {
+ if( rKeyCode.GetCode() == KEY_RIGHT )
+ {
+ if( maWriterButton.HasFocus() )
+ maDrawButton.GrabFocus();
+ else if( maCalcButton.HasFocus() )
+ maDBButton.GrabFocus();
+ else if( maImpressButton.HasFocus() )
+ maMathButton.GrabFocus();
+ else if( maOpenButton.HasFocus() )
+ maTemplateButton.GrabFocus();
+ return 1;
+ }
+ else if( rKeyCode.GetCode() == KEY_LEFT )
+ {
+ if( maDrawButton.HasFocus() )
+ maWriterButton.GrabFocus();
+ else if( maDBButton.HasFocus() )
+ maCalcButton.GrabFocus();
+ else if( maMathButton.HasFocus() )
+ maImpressButton.GrabFocus();
+ else if( maTemplateButton.HasFocus() )
+ maOpenButton.GrabFocus();
+ return 1;
+ }
+ else if( rKeyCode.GetCode() == KEY_UP )
+ {
+ // first column
+ if( maOpenButton.HasFocus() )
+ maImpressButton.GrabFocus();
+ else if( maImpressButton.HasFocus() )
+ maCalcButton.GrabFocus();
+ else if( maCalcButton.HasFocus() )
+ maWriterButton.GrabFocus();
+ // second column
+ else if( maTemplateButton.HasFocus() )
+ maMathButton.GrabFocus();
+ else if( maMathButton.HasFocus() )
+ maDBButton.GrabFocus();
+ else if( maDBButton.HasFocus() )
+ maDrawButton.GrabFocus();
+ return 1;
+ }
+ else if( rKeyCode.GetCode() == KEY_DOWN )
+ {
+ // first column
+ if( maWriterButton.HasFocus() )
+ maCalcButton.GrabFocus();
+ else if( maCalcButton.HasFocus() )
+ maImpressButton.GrabFocus();
+ else if( maImpressButton.HasFocus() )
+ maOpenButton.GrabFocus();
+ // second column
+ else if( maDrawButton.HasFocus() )
+ maDBButton.GrabFocus();
+ else if( maDBButton.HasFocus() )
+ maMathButton.GrabFocus();
+ else if( maMathButton.HasFocus() )
+ maTemplateButton.GrabFocus();
+ return 1;
+ }
+ }
+ }
+ return Window::Notify( rNEvt );
+}
+
+void BackingWindow::setOwningFrame( const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame )
+{
+ mxFrame = xFrame;
+ if( ! mbInitControls )
+ initControls();
+}
+
+void BackingWindow::Resize()
+{
+ Size aWindowSize( GetSizePixel() );
+ Size aControlSize = maControlRect.GetSize();
+ maControlRect = Rectangle( Point( (aWindowSize.Width() - aControlSize.Width()) / 2,
+ (aWindowSize.Height() - aControlSize.Height()) / 2 ),
+ aControlSize );
+
+ maToolbox.calcMinSize();
+ Size aTBSize( maToolbox.getMinSize() );
+ Point aTBPos( maControlRect.Left() + mnBtnPos,
+ maControlRect.Bottom() - aTBSize.Height() - 10 );
+ if( Application::GetSettings().GetLayoutRTL() )
+ aTBPos.X() = maControlRect.Right() - aTBSize.Width() - mnBtnPos;
+ maToolbox.SetPosSizePixel( aTBPos, aTBSize );
+
+ // #i93631# squeeze controls so they fit into the box
+ // this can be necessary due to application font height which has small deviations
+ // from the size set
+ const long nWDelta = maWelcomeSize.Height();
+ const long nW2Delta = (maWelcomeSize.Height()*3)/2;
+ const long nPDelta = (maProductSize.Height()*3)/2;
+ const long nBDelta = maButtonImageSize.Height() + 10;
+ const long nB2Delta = 3*maButtonImageSize.Height()/2;
+ const long nLastDelta = maButtonImageSize.Height();
+ long nDiff = 0;
+ while( ( maControlRect.Top() +
+ (nWDelta - nDiff) +
+ (nW2Delta- nDiff) +
+ (nPDelta - nDiff) +
+ 3 * (nBDelta - nDiff) +
+ (nB2Delta- nDiff) +
+ nLastDelta
+ ) > aTBPos.Y() )
+ {
+ nDiff++;
+ }
+
+ long nYPos = maControlRect.Top();
+ nYPos += nW2Delta - nDiff;
+ maWelcome.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ),
+ Size( maControlRect.GetWidth() - mnBtnPos - 5, (maWelcomeSize.Height()*20)/19 ) );
+ nYPos += nWDelta - nDiff;
+ maProduct.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( maControlRect.GetWidth() - mnBtnPos - 5, (maProductSize.Height()*20)/19 ) );
+ nYPos += nPDelta - nDiff;
+
+ nYPos += nWDelta/2 - nDiff;
+
+ if( mnLayoutStyle != 1 )
+ nYPos = maControlRect.Top() + mnBtnTop;
+
+ maWriterButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
+ maDrawButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
+ nYPos += nBDelta - nDiff;
+ maCalcButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
+ maDBButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
+ nYPos += nBDelta - nDiff;
+ maImpressButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
+ maMathButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
+
+ nYPos += nB2Delta - nDiff;
+ maOpenButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
+ maTemplateButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
+}
+
+IMPL_LINK( BackingWindow, ToolboxHdl, void*, EMPTYARG )
+{
+ const char* pNodePath = NULL;
+ const char* pNode = NULL;
+
+ switch( maToolbox.GetCurItemId() )
+ {
+ case nItemId_Extensions:
+ pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
+ pNode = "AddFeatureURL";
+ break;
+ case nItemId_Reg:
+ try
+ {
+ // create the Desktop component which can load components
+ Reference < lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+ if( xFactory.is() )
+ {
+ Reference< task::XJobExecutor > xProductRegistration(
+ xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.setup.ProductRegistration" ) ) ),
+ UNO_QUERY_THROW );
+
+ // tell it that the user wants to register
+ xProductRegistration->trigger( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RegistrationRequired" ) ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+ break;
+ case nItemId_Info:
+ pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
+ pNode = "InfoURL";
+ break;
+ case nItemId_TplRep:
+ pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
+ pNode = "TemplateRepositoryURL";
+ break;
+ default:
+ break;
+ }
+ if( pNodePath && pNode )
+ {
+ try
+ {
+ Reference<lang::XMultiServiceFactory> xConfig( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY);
+ if( xConfig.is() )
+ {
+ Sequence<Any> args(1);
+ PropertyValue val(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath") ),
+ 0,
+ Any(rtl::OUString::createFromAscii(pNodePath)),
+ PropertyState_DIRECT_VALUE);
+ args.getArray()[0] <<= val;
+ Reference<container::XNameAccess> xNameAccess(xConfig->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,args), UNO_QUERY);
+ if( xNameAccess.is() )
+ {
+ rtl::OUString sURL;
+ //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
+ Any value( xNameAccess->getByName(rtl::OUString::createFromAscii(pNode)) );
+ sURL = value.get<rtl::OUString> ();
+
+ // extend the URLs with Office locale argument
+ INetURLObject aURLObj( sURL );
+
+ rtl::OUString sParam = aURLObj.GetParam();
+ rtl::OUStringBuffer aURLBuf( sParam );
+ if ( sParam.getLength() > 0 )
+ aURLBuf.appendAscii( "&" );
+ aURLBuf.appendAscii( "lang=" );
+
+ // read locale from configuration
+ ::rtl::OUString sLocale;
+ ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup");
+ ::rtl::OUString sRelPath = ::rtl::OUString::createFromAscii("L10N");
+ ::rtl::OUString sKey = ::rtl::OUString::createFromAscii("ooLocale");
+
+ try
+ {
+ ::comphelper::ConfigurationHelper::readDirectKey(comphelper::getProcessServiceFactory(),
+ sPackage,
+ sRelPath,
+ sKey,
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= sLocale;
+ }
+ catch(const com::sun::star::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const com::sun::star::uno::Exception&)
+ { sLocale = ::rtl::OUString::createFromAscii("en-US"); }
+
+ aURLBuf.append(sLocale);
+
+ sParam = aURLBuf.makeStringAndClear();
+
+ aURLObj.SetParam( sParam );
+ sURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
+
+ Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
+ comphelper::getProcessServiceFactory()->createInstance(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ),
+ UNO_QUERY_THROW);
+ //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException
+ xSystemShellExecute->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS);
+ }
+ }
+ }
+ catch (Exception& )
+ {
+ }
+ }
+
+ return 0;
+}
+
+IMPL_LINK( BackingWindow, ClickHdl, Button*, pButton )
+{
+ // dispatch the appropriate URL and end the dialog
+ if( pButton == &maWriterButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(WRITER_URL) ) );
+ else if( pButton == &maCalcButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(CALC_URL) ) );
+ else if( pButton == &maImpressButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(IMPRESS_WIZARD_URL) ) );
+ else if( pButton == &maDrawButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(DRAW_URL) ) );
+ else if( pButton == &maDBButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(BASE_URL) ) );
+ else if( pButton == &maMathButton )
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(MATH_URL) ) );
+ else if( pButton == &maOpenButton )
+ {
+ Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
+
+ Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
+ PropertyValue* pArg = aArgs.getArray();
+ pArg[0].Name = rtl::OUString::createFromAscii("Referer");
+ pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
+
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(OPEN_URL) ), rtl::OUString(), xFrame, aArgs );
+ }
+ else if( pButton == &maTemplateButton )
+ {
+ Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
+
+ Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
+ PropertyValue* pArg = aArgs.getArray();
+ pArg[0].Name = rtl::OUString::createFromAscii("Referer");
+ pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
+
+ dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(TEMPLATE_URL) ), rtl::OUString(), xFrame, aArgs );
+ }
+ return 0;
+}
+
+IMPL_LINK( BackingWindow, SelectHdl, Button*, pButton )
+{
+ if( pButton == &maOpenButton )
+ {
+ sal_Int32 nItem = sal_Int32(maOpenButton.GetCurItemId())-1;
+ if( nItem >= 0 && nItem < sal_Int32(maRecentFiles.size()) )
+ {
+ Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
+ dispatchURL( maRecentFiles[nItem].aTargetURL, rtl::OUString(), xFrame, maRecentFiles[nItem].aArgSeq );
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( BackingWindow, ActivateHdl, Button*, pButton )
+{
+ if( pButton == &maOpenButton )
+ prepareRecentFileMenu();
+ return 0;
+}
+
+struct ImplDelayedDispatch
+{
+ Reference< XDispatch > xDispatch;
+ com::sun::star::util::URL aDispatchURL;
+ Sequence< PropertyValue > aArgs;
+
+ ImplDelayedDispatch( const Reference< XDispatch >& i_xDispatch,
+ const com::sun::star::util::URL& i_rURL,
+ const Sequence< PropertyValue >& i_rArgs )
+ : xDispatch( i_xDispatch ),
+ aDispatchURL( i_rURL ),
+ aArgs( i_rArgs )
+ {
+ }
+ ~ImplDelayedDispatch() {}
+};
+
+static long implDispatchDelayed( void*, void* pArg )
+{
+ struct ImplDelayedDispatch* pDispatch = reinterpret_cast<ImplDelayedDispatch*>(pArg);
+ try
+ {
+ pDispatch->xDispatch->dispatch( pDispatch->aDispatchURL, pDispatch->aArgs );
+ }
+ catch( Exception )
+ {
+ }
+
+ // clean up
+ delete pDispatch;
+
+ return 0;
+}
+
+void BackingWindow::dispatchURL( const rtl::OUString& i_rURL,
+ const rtl::OUString& rTarget,
+ const Reference< XDispatchProvider >& i_xProv,
+ const Sequence< PropertyValue >& i_rArgs )
+{
+ // if no special dispatch provider is given, get the desktop
+ Reference< XDispatchProvider > xProvider( i_xProv.is() ? i_xProv : mxDesktopDispatchProvider );
+
+ // check for dispatch provider
+ if( !xProvider.is())
+ return;
+
+ // get an URL transformer to clean up the URL
+ com::sun::star::util::URL aDispatchURL;
+ aDispatchURL.Complete = i_rURL;
+
+ Reference < com::sun::star::util::XURLTransformer > xURLTransformer(
+ comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer") ),
+ com::sun::star::uno::UNO_QUERY );
+ if ( xURLTransformer.is() )
+ {
+ try
+ {
+ // clean up the URL
+ xURLTransformer->parseStrict( aDispatchURL );
+ // get a Dispatch for the URL and target
+ Reference< XDispatch > xDispatch(
+ xProvider->queryDispatch( aDispatchURL, rTarget, 0 )
+ );
+ // dispatch the URL
+ if ( xDispatch.is() )
+ {
+ ImplDelayedDispatch* pDisp = new ImplDelayedDispatch( xDispatch, aDispatchURL, i_rArgs );
+ sal_uLong nEventId = 0;
+ if( ! Application::PostUserEvent( nEventId, Link( NULL, implDispatchDelayed ), pDisp ) )
+ delete pDisp; // event could not be posted for unknown reason, at least don't leak
+ }
+ }
+ catch ( com::sun::star::uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch ( com::sun::star::uno::Exception& )
+ {
+ }
+ }
+}
+
diff --git a/framework/source/services/backingwindow.hxx b/framework/source/services/backingwindow.hxx
new file mode 100644
index 000000000000..958ebfbb243e
--- /dev/null
+++ b/framework/source/services/backingwindow.hxx
@@ -0,0 +1,184 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef FRAMEWORK_BACKINGWINDOW_HXX
+#define FRAMEWORK_BACKINGWINDOW_HXX
+
+#include "rtl/ustring.hxx"
+
+#include "vcl/button.hxx"
+#include "vcl/menubtn.hxx"
+#include "vcl/fixed.hxx"
+#include "vcl/bitmapex.hxx"
+#include "vcl/toolbox.hxx"
+
+#include "unotools/moduleoptions.hxx"
+#include "svtools/acceleratorexecute.hxx"
+
+#include "com/sun/star/frame/XDispatchProvider.hpp"
+#include "com/sun/star/frame/XDesktop.hpp"
+#include "com/sun/star/frame/XFrame.hpp"
+#include "com/sun/star/frame/XTerminateListener.hpp"
+#include "com/sun/star/document/XEventListener.hpp"
+#include "com/sun/star/document/XEventBroadcaster.hpp"
+#include "com/sun/star/util/XURLTransformer.hpp"
+#include "com/sun/star/ui/dialogs/XFilePicker.hpp"
+#include "com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp"
+#include "com/sun/star/ui/dialogs/XFilterManager.hpp"
+#include "com/sun/star/ui/dialogs/XFolderPicker.hpp"
+#include "com/sun/star/ui/dialogs/TemplateDescription.hpp"
+#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
+
+#include <set>
+
+class MnemonicGenerator;
+
+namespace framework
+{
+ // To get the transparent mouse-over look, the closer is actually a toolbox
+ // overload DataChange to handle style changes correctly
+ class DecoToolBox : public ToolBox
+ {
+ Size maMinSize;
+
+ using Window::ImplInit;
+ public:
+ DecoToolBox( Window* pParent, WinBits nStyle = 0 );
+ DecoToolBox( Window* pParent, const ResId& rResId );
+
+ void DataChanged( const DataChangedEvent& rDCEvt );
+
+ void calcMinSize();
+ Size getMinSize();
+ };
+
+ class BackingWindow : public Window
+ {
+ struct LoadRecentFile
+ {
+ rtl::OUString aTargetURL;
+ com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aArgSeq;
+ };
+
+ com::sun::star::uno::Reference<com::sun::star::frame::XDesktop> mxDesktop;
+ com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider > mxDesktopDispatchProvider;
+ com::sun::star::uno::Reference<com::sun::star::frame::XFrame> mxFrame;
+ com::sun::star::uno::Reference<com::sun::star::document::XEventBroadcaster> mxBroadcaster;
+
+ FixedText maWelcome;
+ Size maWelcomeSize;
+ FixedText maProduct;
+ Size maProductSize;
+ ImageButton maWriterButton;
+ ImageButton maCalcButton;
+ ImageButton maImpressButton;
+ MenuButton maOpenButton;
+ ImageButton maDrawButton;
+ ImageButton maDBButton;
+ ImageButton maMathButton;
+ ImageButton maTemplateButton;
+
+ DecoToolBox maToolbox;
+
+ BitmapEx maBackgroundLeft;
+ BitmapEx maBackgroundMiddle;
+ BitmapEx maBackgroundRight;
+
+ String maWelcomeString;
+ String maProductString;
+ String maCreateString;
+ String maOpenString;
+ String maTemplateString;
+
+ Font maTextFont;
+ Rectangle maControlRect;
+
+ long mnColumnWidth[2];
+ long mnTextColumnWidth[2];
+ Color maLabelTextColor;
+ Color maWelcomeTextColor;
+
+ Size maButtonImageSize;
+
+ bool mbInitControls;
+ sal_Int32 mnLayoutStyle;
+ svt::AcceleratorExecute* mpAccExec;
+ long mnBtnPos;
+ long mnBtnTop;
+
+ PopupMenu* mpRecentMenu;
+ std::vector< LoadRecentFile > maRecentFiles;
+
+ static const int nItemId_Extensions = 1;
+ static const int nItemId_Reg = 2;
+ static const int nItemId_Info = 3;
+ static const int nItemId_TplRep = 4;
+ static const int nShadowTop = 32;
+ static const int nShadowLeft = 35;
+ static const int nShadowRight = 45;
+ static const int nShadowBottom = 50;
+
+ void loadImage( const ResId& i_rId, PushButton& i_rButton );
+
+ void layoutButton( const char* i_pURL, int nColumn, const std::set<rtl::OUString>& i_rURLS,
+ SvtModuleOptions& i_rOpt, SvtModuleOptions::EModule i_eMod,
+ PushButton& i_rBtn,
+ MnemonicGenerator& i_rMnemonicGen,
+ const String& i_rStr = String()
+ );
+
+ void dispatchURL( const rtl::OUString& i_rURL,
+ const rtl::OUString& i_rTarget = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ),
+ const com::sun::star::uno::Reference< com::sun::star::frame::XDispatchProvider >& i_xProv = com::sun::star::uno::Reference< com::sun::star::frame::XDispatchProvider >(),
+ const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& = com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >()
+ );
+
+ DECL_LINK( ClickHdl, Button* );
+ DECL_LINK( SelectHdl, Button* );
+ DECL_LINK( ActivateHdl, Button* );
+ DECL_LINK( ToolboxHdl, void* );
+
+ void initControls();
+ void initBackground();
+ void prepareRecentFileMenu();
+ public:
+ BackingWindow( Window* pParent );
+ ~BackingWindow();
+
+ virtual void Paint( const Rectangle& rRect );
+ virtual void Resize();
+ virtual long Notify( NotifyEvent& rNEvt );
+ virtual void DataChanged( const DataChangedEvent& rDCEvt );
+ virtual void GetFocus();
+
+ void setOwningFrame( const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame );
+ };
+
+}
+
+#endif
+
diff --git a/framework/source/services/desktop.cxx b/framework/source/services/desktop.cxx
new file mode 100644
index 000000000000..3c89661af599
--- /dev/null
+++ b/framework/source/services/desktop.cxx
@@ -0,0 +1,2038 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <loadenv/loadenv.hxx>
+
+#ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_
+#include <loadenv/targethelper.hxx>
+#endif
+
+#ifndef __FRAMEWORK_DESKTOP_HXX_
+#include <services/desktop.hxx>
+#endif
+#include <helper/ocomponentaccess.hxx>
+#include <dispatch/dispatchprovider.hxx>
+
+#ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_
+#include <dispatch/interceptionhelper.hxx>
+#endif
+#include <classes/taskcreator.hxx>
+#include <threadhelp/transactionguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <threadhelp/readguard.hxx>
+#include <services.h>
+#include <general.h>
+#include <properties.h>
+
+#include <classes/resource.hrc>
+#include <classes/fwkresid.hxx>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/task/XInteractionAbort.hpp>
+#include <com/sun/star/task/XInteractionApprove.hpp>
+#include <com/sun/star/document/XInteractionFilterSelect.hpp>
+#include <com/sun/star/document/AmbigousFilterRequest.hpp>
+#include <com/sun/star/task/ErrorCodeRequest.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/frame/XNotifyingDispatch.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <com/sun/star/frame/XTerminateListener2.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/proptypehlp.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/logfile.hxx>
+#include <vcl/svapp.hxx>
+
+#ifndef __RSC
+#include <tools/errinf.hxx>
+#endif
+#include <comphelper/extract.hxx>
+
+#include <fwkdllapi.h>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_15 ( Desktop ,
+ OWeakObject ,
+ DIRECT_INTERFACE( css::lang::XTypeProvider ),
+ DIRECT_INTERFACE( css::lang::XServiceInfo ),
+ DIRECT_INTERFACE( css::frame::XDesktop ),
+ DIRECT_INTERFACE( css::frame::XComponentLoader ),
+ DIRECT_INTERFACE( css::frame::XTasksSupplier ),
+ DIRECT_INTERFACE( css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE( css::frame::XDispatchProviderInterception),
+ DIRECT_INTERFACE( css::frame::XFramesSupplier ),
+ DIRECT_INTERFACE( css::frame::XFrame ),
+ DIRECT_INTERFACE( css::lang::XComponent ),
+ DIRECT_INTERFACE( css::frame::XDispatchResultListener ),
+ DIRECT_INTERFACE( css::lang::XEventListener ),
+ DIRECT_INTERFACE( css::task::XInteractionHandler ),
+ DIRECT_INTERFACE( css::beans::XPropertySet ),
+ DIRECT_INTERFACE( css::frame::XUntitledNumbers )
+ )
+
+DEFINE_XTYPEPROVIDER_15 ( Desktop ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDesktop ,
+ css::frame::XComponentLoader ,
+ css::frame::XTasksSupplier ,
+ css::frame::XDispatchProvider ,
+ css::frame::XDispatchProviderInterception ,
+ css::frame::XFramesSupplier ,
+ css::frame::XFrame ,
+ css::lang::XComponent ,
+ css::frame::XDispatchResultListener ,
+ css::lang::XEventListener ,
+ css::task::XInteractionHandler ,
+ css::beans::XPropertySet ,
+ css::frame::XUntitledNumbers
+ )
+
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( Desktop ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_DESKTOP ,
+ IMPLEMENTATIONNAME_DESKTOP
+ )
+
+DEFINE_INIT_SERVICE ( Desktop,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
+ // We hold member as reference ... not as pointer too!
+ // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
+ // But look on dispose() for right order of deinitialization.
+ OFrames* pFramesHelper = new OFrames( m_xFactory, this, &m_aChildTaskContainer );
+ m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new dispatchhelper-object to handle dispatches.
+ // We use these helper as slave for our interceptor helper ... not directly!
+ // But he is event listener on THIS instance!
+ DispatchProvider* pDispatchHelper = new DispatchProvider( m_xFactory, this );
+ css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( static_cast< ::cppu::OWeakObject* >(pDispatchHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
+ // Set created dispatch provider as slowest slave of it.
+ // Hold interception helper by reference only - not by pointer!
+ // So it's easiear to destroy it.
+ InterceptionHelper* pInterceptionHelper = new InterceptionHelper( this, xDispatchProvider );
+ m_xDispatchHelper = css::uno::Reference< css::frame::XDispatchProvider >( static_cast< ::cppu::OWeakObject* >(pInterceptionHelper), css::uno::UNO_QUERY );
+
+ ::rtl::OUStringBuffer sUntitledPrefix (256);
+ sUntitledPrefix.append (::rtl::OUString( String( FwkResId( STR_UNTITLED_DOCUMENT ))));
+ sUntitledPrefix.appendAscii (" ");
+
+ ::comphelper::NumberedCollection* pNumbers = new ::comphelper::NumberedCollection ();
+ m_xTitleNumberGenerator = css::uno::Reference< css::frame::XUntitledNumbers >(static_cast< ::cppu::OWeakObject* >(pNumbers), css::uno::UNO_QUERY_THROW);
+ pNumbers->setOwner ( static_cast< ::cppu::OWeakObject* >(this) );
+ pNumbers->setUntitledPrefix ( sUntitledPrefix.makeStringAndClear () );
+
+ // Safe impossible cases
+ // We can't work without this helper!
+ LOG_ASSERT2( m_xFramesHelper.is ()==sal_False, "Desktop::Desktop()", "Frames helper is not valid. XFrames, XIndexAccess and XElementAcces are not supported!\n")
+ LOG_ASSERT2( m_xDispatchHelper.is()==sal_False, "Desktop::Desktop()", "Dispatch helper is not valid. XDispatch will not work correctly!\n" )
+
+ // Enable object for real working!
+ // Otherwise all calls will be rejected ...
+ m_aTransactionManager.setWorkingMode( E_WORK );
+ }
+ )
+
+/*-************************************************************************************************************//**
+ @short standard constructor to create instance by factory
+ @descr This constructor initialize a new instance of this class by valid factory,
+ and will be set valid values on his member and baseclasses.
+
+ @attention a) Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you
+ will get over this. (e.g. using of your reference as parameter to initialize some member)
+ Do such things in DEFINE_INIT_SERVICE() method, which is called automaticly after your ctor!!!
+ b) Baseclass OBroadcastHelper is a typedef in namespace cppu!
+ The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
+ If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!?
+ I don't know why! (other compiler not tested .. but it works!)
+
+ @seealso method DEFINE_INIT_SERVICE()
+
+ @param "xFactory" is the multi service manager, which create this instance.
+ The value must be different from NULL!
+ @return -
+
+ @onerror We throw an ASSERT in debug version or do nothing in relaese version.
+*//*-*************************************************************************************************************/
+Desktop::Desktop( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ // Attention: Don't change order of initialization!
+ // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
+ // We must garant right initialization and a valid value of this to initialize other baseclasses!
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , TransactionBase ( )
+ , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType > ( m_aLock.getShareableOslMutex() )
+ , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) )
+ , ::cppu::OWeakObject ( )
+ // Init member
+ #ifdef ENABLE_ASSERTIONS
+ , m_bIsTerminated ( sal_False ) // see dispose() for further informations!
+ #endif
+ , m_xFactory ( xFactory )
+ , m_aChildTaskContainer ( )
+ , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
+ , m_xFramesHelper ( )
+ , m_xDispatchHelper ( )
+ , m_eLoadState ( E_NOTSET )
+ , m_xLastFrame ( )
+ , m_aInteractionRequest ( )
+ , m_bSuspendQuickstartVeto( sal_False )
+ , m_aCommandOptions ( )
+ , m_sName ( )
+ , m_sTitle ( )
+ , m_xDispatchRecorderSupplier( )
+ , m_xPipeTerminator ( )
+ , m_xQuickLauncher ( )
+ , m_xSWThreadManager ( )
+ , m_xSfxTerminator ( )
+ , m_xTitleNumberGenerator ( )
+{
+ // Safe impossible cases
+ // We don't accept all incoming parameter.
+ LOG_ASSERT2( implcp_ctor( xFactory ), "Desktop::Desktop()", "Invalid parameter detected!")
+}
+
+/*-************************************************************************************************************//**
+ @short standard destructor
+ @descr This one do NOTHING! Use dispose() instaed of this.
+
+ @seealso method dispose()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+Desktop::~Desktop()
+{
+ LOG_ASSERT2( m_bIsTerminated ==sal_False, "Desktop::~Desktop()", "Who forgot to terminate the desktop service?" )
+ LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE , "Desktop::~Desktop()", "Who forgot to dispose this service?" )
+}
+
+//=============================================================================
+sal_Bool SAL_CALL Desktop::terminate()
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ SYNCHRONIZED_START
+ ReadGuard aReadLock( m_aLock );
+
+ css::uno::Reference< css::frame::XTerminateListener > xPipeTerminator = m_xPipeTerminator;
+ css::uno::Reference< css::frame::XTerminateListener > xQuickLauncher = m_xQuickLauncher;
+ css::uno::Reference< css::frame::XTerminateListener > xSWThreadManager = m_xSWThreadManager;
+ css::uno::Reference< css::frame::XTerminateListener > xSfxTerminator = m_xSfxTerminator;
+
+ css::lang::EventObject aEvent ( static_cast< ::cppu::OWeakObject* >(this) );
+ ::sal_Bool bAskQuickStart = !m_bSuspendQuickstartVeto ;
+
+ aReadLock.unlock();
+ SYNCHRONIZED_END
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Ask normal terminate listener. They could stop terminate without closing any open document.
+ Desktop::TTerminateListenerList lCalledTerminationListener;
+ ::sal_Bool bVeto = sal_False;
+ impl_sendQueryTerminationEvent(lCalledTerminationListener, bVeto);
+ if ( bVeto )
+ {
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // try to close all open frames.
+ // Allow using of any UI ... because Desktop.terminate() was designed as UI functionality in the past.
+ ::sal_Bool bAllowUI = sal_True;
+ ::sal_Bool bFramesClosed = impl_closeFrames(bAllowUI);
+ if ( ! bFramesClosed )
+ {
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Normal listener had no problem ...
+ // all frames was closed ...
+ // now it's time to ask our specialized listener.
+ // They are handled these way because they wish to hinder the office on termination
+ // but they wish also closing of all frames.
+
+ // Note further:
+ // We shouldn't ask quicklauncher in case it was allowed from outside only.
+ // This is special trick to "ignore existing quick starter" for debug purposes.
+
+ // Attention:
+ // Order of alled listener is important !
+ // some of them are harmless .-)
+ // But some of them can be dangerous. E.g. it would be dangerous if we close our pipe
+ // and dont terminate in real because another listener throws a veto exception .-)
+
+ ::sal_Bool bTerminate = sal_False;
+ try
+ {
+ if(
+ ( bAskQuickStart ) &&
+ ( xQuickLauncher.is() )
+ )
+ {
+ xQuickLauncher->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xQuickLauncher );
+ }
+
+ if ( xSWThreadManager.is() )
+ {
+ xSWThreadManager->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xSWThreadManager );
+ }
+
+ if ( xPipeTerminator.is() )
+ {
+ xPipeTerminator->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xPipeTerminator );
+ }
+
+ if ( xSfxTerminator.is() )
+ {
+ xSfxTerminator->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xSfxTerminator );
+ }
+
+ bTerminate = sal_True;
+ }
+ catch(const css::frame::TerminationVetoException&)
+ {
+ bTerminate = sal_False;
+ }
+
+ if ( ! bTerminate )
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ else
+ {
+ #ifdef ENABLE_ASSERTIONS
+ // "Protect" us against dispose before terminate calls!
+ // see dispose() for further informations.
+ /* SAFE AREA --------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ m_bIsTerminated = sal_True;
+ aWriteLock.unlock();
+ /* UNSAFE AREA ------------------------------------------------------------------------------------- */
+ #endif
+
+ impl_sendNotifyTerminationEvent();
+
+ if(
+ ( bAskQuickStart ) &&
+ ( xQuickLauncher.is() )
+ )
+ {
+ xQuickLauncher->notifyTermination( aEvent );
+ }
+
+ if ( xSWThreadManager.is() )
+ xSWThreadManager->notifyTermination( aEvent );
+
+ if ( xPipeTerminator.is() )
+ xPipeTerminator->notifyTermination( aEvent );
+
+ // Must be realy the last listener to be called.
+ // Because it shutdown the whole process asynchronous !
+ if ( xSfxTerminator.is() )
+ xSfxTerminator->notifyTermination( aEvent );
+ }
+
+ return bTerminate;
+}
+
+
+//=============================================================================
+void SAL_CALL Desktop::addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ ::rtl::OUString sImplementationName = xInfo->getImplementationName();
+
+ // SYCNHRONIZED ->
+ WriteGuard aWriteLock( m_aLock );
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
+ {
+ m_xSfxTerminator = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
+ {
+ m_xPipeTerminator = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
+ {
+ m_xQuickLauncher = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
+ {
+ m_xSWThreadManager = xListener;
+ return;
+ }
+
+ aWriteLock.unlock();
+ // <- SYCNHRONIZED
+ }
+
+ // No lock required ... container is threadsafe by itself.
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
+}
+
+//=============================================================================
+void SAL_CALL Desktop::removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ ::rtl::OUString sImplementationName = xInfo->getImplementationName();
+
+ // SYCNHRONIZED ->
+ WriteGuard aWriteLock( m_aLock );
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
+ {
+ m_xSfxTerminator.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
+ {
+ m_xPipeTerminator.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
+ {
+ m_xQuickLauncher.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
+ {
+ m_xSWThreadManager.clear();
+ return;
+ }
+
+ aWriteLock.unlock();
+ // <- SYCNHRONIZED
+ }
+
+ // No lock required ... container is threadsafe by itself.
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short get access to create enumerations of all current components
+ @descr You will be the owner of the returned object and must delete it if you don't use it again.
+
+ @seealso class TasksAccess
+ @seealso class TasksEnumeration
+
+ @param -
+ @return A reference to an XEnumerationAccess-object.
+
+ @onerror We return a null-reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getComponents() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // We use a helper class OComponentAccess to have access on all child components.
+ // Create it on demand and return it as a reference.
+ OComponentAccess* pAccess = new OComponentAccess( this );
+ css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pAccess), css::uno::UNO_QUERY );
+ return xAccess;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short return the current active component
+ @descr The most current component is the window, model or the controller of the current active frame.
+
+ @seealso method getCurrentFrame()
+ @seealso method impl_getFrameComponent()
+
+ @param -
+ @return A reference to the component.
+
+ @onerror We return a null-reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::getCurrentComponent() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Set return value if method failed.
+ css::uno::Reference< css::lang::XComponent > xComponent;
+
+ // Get reference to current frame ...
+ // ... get component of this frame ... (It can be the window, the model or the controller.)
+ // ... and return the result.
+ css::uno::Reference< css::frame::XFrame > xCurrentFrame = getCurrentFrame();
+ if( xCurrentFrame.is() == sal_True )
+ {
+ xComponent = impl_getFrameComponent( xCurrentFrame );
+ }
+ return xComponent;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short return the current active frame in hierarchy
+ @descr There can be more then one different active pathes in our frame hierarchy. But only one of them
+ could be the most active frame (normal he has the focus).
+ Don't mix it with getActiveFrame()! That will return our current active frame, which must be
+ a direct child of us and should be a part(!) of an active path.
+
+ @seealso method getActiveFrame()
+
+ @param -
+ @return A valid reference, if there is an active frame.
+ A null reference , otherwise.
+
+ @onerror We return a null reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getCurrentFrame() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Start search with ouer direct active frame (if it exist!).
+ // Search on his children for other active frames too.
+ // Stop if no one could be found and return last of found ones.
+ css::uno::Reference< css::frame::XFramesSupplier > xLast = css::uno::Reference< css::frame::XFramesSupplier >( getActiveFrame(), css::uno::UNO_QUERY );
+ if( xLast.is() == sal_True )
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xNext = css::uno::Reference< css::frame::XFramesSupplier >( xLast->getActiveFrame(), css::uno::UNO_QUERY );
+ while( xNext.is() == sal_True )
+ {
+ xLast = xNext;
+ xNext = css::uno::Reference< css::frame::XFramesSupplier >( xNext->getActiveFrame(), css::uno::UNO_QUERY );
+ }
+ }
+ return css::uno::Reference< css::frame::XFrame >( xLast, css::uno::UNO_QUERY );
+}
+
+/*-************************************************************************************************************//**
+ @interface XComponentLoader
+ @short try to load given URL into a task
+ @descr You can give us some informations about the content, which you will load into a frame.
+ We search or create this target for you, make a type detection of given URL and try to load it.
+ As result of this operation we return the new created component or nothing, if loading failed.
+
+ @seealso -
+
+ @param "sURL" , URL, which represant the content
+ @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ...
+ @param "nSearchFlags" , optional arguments for frame search, if target isn't a special one
+ @param "lArguments" , optional arguments for loading
+ @return A valid component reference, if loading was successfully.
+ A null reference otherwise.
+
+ @onerror We return a null reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::loadComponentFromURL( const ::rtl::OUString& sURL ,
+ const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::io::IOException ,
+ css::lang::IllegalArgumentException ,
+ css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::Desktop::loadComponentFromURL" );
+
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XComponentLoader > xThis(static_cast< css::frame::XComponentLoader* >(this), css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory;
+ aReadLock.unlock();
+
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog2, "PERFORMANCE - Desktop::loadComponentFromURL()" );
+ return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments);
+}
+
+/*-************************************************************************************************************//**
+ @interface XTasksSupplier
+ @short get access to create enumerations of ouer taskchilds
+ @descr Direct childs of desktop are tasks everytime.
+ Call these method to could create enumerations of it.
+
+But; Don't forget - you will be the owner of returned object and must release it!
+ We use a helper class to implement the access interface. They hold a weakreference to us.
+ It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing!
+ You can't create enumerations then.
+
+ @attention Normaly we don't need any lock here. We don't work on internal member!
+
+ @seealso class TasksAccess
+
+ @param -
+ @return A reference to an accessobject, which can create enumerations of ouer childtasks.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getTasks() throw( css::uno::RuntimeException )
+{
+ LOG_WARNING("Desktop::getTasks()", "Use of obsolete interface XTaskSupplier")
+ return NULL;
+ /*
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ OTasksAccess* pTasksAccess = new OTasksAccess( this, &m_aChildTaskContainer );
+ css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pTasksAccess), css::uno::UNO_QUERY );
+ return xAccess;
+ */
+}
+
+/*-************************************************************************************************************//**
+ @interface XTasksSupplier
+ @short return current active task of ouer direct childs
+ @descr Desktop childs are tasks only ! If we have an active path from desktop
+ as top to any frame on bottom, we must have an active direct child. His reference is returned here.
+
+ @attention a) Do not confuse it with getCurrentFrame()! The current frame don't must one of ouer direct childs.
+ It can be every frame in subtree and must have the focus (Is the last one of an active path!).
+ b) We don't need any lock here. Our container is threadsafe himself and live, if we live!
+
+ @seealso method getCurrentFrame()
+
+ @param -
+ @return A reference to ouer current active taskchild.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XTask > SAL_CALL Desktop::getActiveTask() throw( css::uno::RuntimeException )
+{
+ /*
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return css::uno::Reference< css::frame::XTask >( m_aChildTaskContainer.getActive(), css::uno::UNO_QUERY );
+ */
+ LOG_WARNING("Desktop::getActiveTask()", "Use of obsolete interface XTaskSupplier")
+ return NULL;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDispatchProvider
+ @short search a dispatcher for given URL
+ @descr We use a helper implementation (class DispatchProvider) to do so.
+ So we don't must implement this algorithm twice!
+
+ @attention We don't need any lock here. Our helper is threadsafe himself and live, if we live!
+
+ @seealso class DispatchProvider
+
+ @param "aURL" , URL to dispatch
+ @param "sTargetFrameName" , name of target frame, who should dispatch these URL
+ @param "nSearchFlags" , flags to regulate the search
+ @param "lQueries" , list of queryDispatch() calls!
+ @return A reference or list of founded dispatch objects for these URL.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL Desktop::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ const char UNO_PROTOCOL[] = ".uno:";
+
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
+ // in our hash map. All other protocols are stored with the protocol part.
+ String aCommand( aURL.Main );
+ if ( aURL.Protocol.equalsIgnoreAsciiCaseAsciiL( UNO_PROTOCOL, sizeof( UNO_PROTOCOL )-1 ))
+ aCommand = aURL.Path;
+
+ // Make hash_map lookup if the current URL is in the disabled list
+ if ( m_aCommandOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aCommand ) )
+ return css::uno::Reference< css::frame::XDispatch >();
+ else
+ {
+ // We use a helper to support these interface and an interceptor mechanism.
+ // Our helper is threadsafe by himself!
+ return m_xDispatchHelper->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
+ }
+}
+
+//*****************************************************************************************************************
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Desktop::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lQueries ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_xDispatchHelper->queryDispatches( lQueries );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDipsatchProviderInterception
+ @short supports registration/deregistration of interception objects, which
+ are interested on special dispatches.
+
+ @descr Its realy provided by an internal helper, which is used inside the dispatch api too.
+ @param xInterceptor
+ the interceptor object, which wish to be (de)registered.
+
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw( css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw( css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
+}
+
+/*-************************************************************************************************************//**
+ @interface XFramesSupplier
+ @short return access to append or remove childs on desktop
+ @descr We don't implement these interface directly. We use a helper class to do this.
+ If you wish to add or delete childs to/from the container, call these method to get
+ a reference to the helper.
+
+ @attention Helper is threadsafe himself. So we don't need any lock here.
+
+ @seealso class OFrames
+
+ @param -
+ @return A reference to the helper.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrames > SAL_CALL Desktop::getFrames() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_xFramesHelper;
+}
+
+/*-************************************************************************************************************//**
+ @interface XFramesSupplier
+ @short set/get the current active child frame
+ @descr It must be a task. Direct childs of desktop are tasks only! No frames are accepted.
+ We don't save this information directly in this class. We use ouer container-helper
+ to do that.
+
+ @attention Helper is threadsafe himself. So we don't need any lock here.
+
+ @seealso class OFrameContainer
+
+ @param "xFrame", new active frame (must be valid!)
+ @return A reference to ouer current active childtask, if anyone exist.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Get old active frame first.
+ // If nothing will change - do nothing!
+ // Otherwise set new active frame ...
+ // and deactivate last frame.
+ // It's neccessary for our FrameActionEvent listener on a frame!
+ css::uno::Reference< css::frame::XFrame > xLastActiveChild = m_aChildTaskContainer.getActive();
+ if( xLastActiveChild != xFrame )
+ {
+ m_aChildTaskContainer.setActive( xFrame );
+ if( xLastActiveChild.is() == sal_True )
+ {
+ xLastActiveChild->deactivate();
+ }
+ }
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getActiveFrame() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_aChildTaskContainer.getActive();
+}
+
+/*-************************************************************************************************************//**
+ @interface XFrame
+ @short non implemented methods!
+ @descr Some method make no sense for our desktop! He has no window or parent or ...
+ So we should implement it empty and warn programmer, if he use it!
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+ @threadsafe -
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::initialize( const css::uno::Reference< css::awt::XWindow >& ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getContainerWindow() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::awt::XWindow >();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& /*xCreator*/ ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Desktop::getCreator() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::frame::XFramesSupplier >();
+}
+
+//*****************************************************************************************************************
+::rtl::OUString SAL_CALL Desktop::getName() throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ return m_sName;
+ /* } SAFE */
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_sName = sName;
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::isTop() throw( css::uno::RuntimeException )
+{
+ return sal_True;
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::activate() throw( css::uno::RuntimeException )
+{
+ // Desktop is activae always ... but sometimes our frames try to activate
+ // the complete path from bottom to top ... And our desktop is the topest frame :-(
+ // So - please don't show any assertions here. Do nothing!
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::deactivate() throw( css::uno::RuntimeException )
+{
+ // Desktop is activae always ... but sometimes our frames try to deactivate
+ // the complete path from bottom to top ... And our desktop is the topest frame :-(
+ // So - please don't show any assertions here. Do nothing!
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::isActive() throw( css::uno::RuntimeException )
+{
+ return sal_True;
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::setComponent( const css::uno::Reference< css::awt::XWindow >& /*xComponentWindow*/ ,
+ const css::uno::Reference< css::frame::XController >& /*xController*/ ) throw( css::uno::RuntimeException )
+{
+ return sal_False;
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getComponentWindow() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::awt::XWindow >();
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XController > SAL_CALL Desktop::getController() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::frame::XController >();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::contextChanged() throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+// css::frame::XFrame
+//*****************************************************************************************************************
+void SAL_CALL Desktop::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
+{
+}
+
+/*-************************************************************************************************************//**
+ @interface XFrame
+ @short try to find a frame with special parameters
+ @descr This method searches for a frame with the specified name.
+ Frames may contain other frames (e.g. a frameset) and may
+ be contained in other frames. This hierarchie ist searched by
+ this method.
+ First some special names are taken into account, i.e. "",
+ "_self", "_top", "_parent" etc. The FrameSearchFlags are ignored
+ when comparing these names with aTargetFrameName, further steps are
+ controlled by the FrameSearchFlags. If allowed, the name of the frame
+ itself is compared with the desired one, then ( again if allowed )
+ the method findFrame is called for all children of the frame.
+ If no Frame with the given name is found until the top frames container,
+ a new top Frame is created, if this is allowed by a special
+ FrameSearchFlag. The new Frame also gets the desired name.
+ We use a helper to get right search direction and react in a right manner.
+
+ @seealso class TargetFinder
+
+ @param "sTargetFrameName" , name of searched frame
+ @param "nSearchFlags" , flags to regulate search
+ @return A reference to an existing frame in hierarchy, if it exist.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::findFrame( const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XFrame > xTarget;
+
+ //-----------------------------------------------------------------------------------------------------
+ // 0) Ignore wrong parameter!
+ // We doesn't support search for following special targets.
+ // If we reject this requests - we mustnt check for such names
+ // in following code again and again. If we do not so -wrong
+ // search results can occure!
+ //-----------------------------------------------------------------------------------------------------
+ if (
+ (sTargetFrameName==SPECIALTARGET_DEFAULT ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition
+ (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only -
+ // and they exist more then ones. We have no idea which our sub tasks is the right one
+ )
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I) check for special defined targets first which must be handled exclusive.
+ // force using of "if() else if() ..."
+ //-----------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.I) "_blank"
+ // create a new task as child of this desktop instance
+ // Note: Used helper TaskCreator use us automaticly ...
+ //-----------------------------------------------------------------------------------------------------
+ if ( sTargetFrameName==SPECIALTARGET_BLANK )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.II) "_top"
+ // We are top by definition
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if ( sTargetFrameName==SPECIALTARGET_TOP )
+ {
+ xTarget = this;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.III) "_self", ""
+ // This mean this "frame" in every case.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (
+ ( sTargetFrameName==SPECIALTARGET_SELF ) ||
+ ( sTargetFrameName.getLength()<1 )
+ )
+ {
+ xTarget = this;
+ }
+
+ else
+ {
+ //-------------------------------------------------------------------------------------------------
+ // II) otherwhise use optional given search flags
+ // force using of combinations of such flags. means no "else" part of use if() statements.
+ // But we ust break further searches if target was already found.
+ // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
+ // TASK and CREATE are handled special.
+ // But note: Such flags are not valid for the desktop - especialy SIBLINGS or PARENT.
+ //-------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ aReadLock.lock();
+ ::rtl::OUString sOwnName = m_sName;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-------------------------------------------------------------------------------------------------
+ // II.I) SELF
+ // Check for right name. If it's the searched one return ourself - otherwhise
+ // ignore this flag.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ (nSearchFlags & css::frame::FrameSearchFlag::SELF) &&
+ (sOwnName == sTargetFrameName )
+ )
+ {
+ xTarget = this;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.II) TASKS
+ // This is a special flag. Normaly it regulate search inside tasks and forbid access to parent trees.
+ // But the desktop exists outside such task trees. They are our sub trees. So the desktop implement
+ // a special feature: We use it to start search on our direct childrens only. That means we supress
+ // search on ALL child frames. May that can be usefull to get access on opened document tasks
+ // only without filter out all non realy required sub frames ...
+ // Used helper method on our container doesn't create any frame - its a search only.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::TASKS)
+ )
+ {
+ xTarget = m_aChildTaskContainer.searchOnDirectChildrens(sTargetFrameName);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.III) CHILDREN
+ // Search on all children for the given target name.
+ // An empty name value can't occure here - because it must be already handled as "_self"
+ // before. Used helper function of container doesn't create any frame.
+ // It makes a deep search only.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
+ )
+ {
+ xTarget = m_aChildTaskContainer.searchOnAllChildrens(sTargetFrameName);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.IV) CREATE
+ // If we haven't found any valid target frame by using normal flags - but user allowed us to create
+ // a new one ... we should do that. Used TaskCreator use us automaticly as parent!
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
+ )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+ }
+
+ return xTarget;
+}
+
+//=============================================================================
+void SAL_CALL Desktop::dispose()
+ throw( css::uno::RuntimeException )
+{
+ // Safe impossible cases
+ // It's an programming error if dispose is called before terminate!
+ LOG_ASSERT2( m_bIsTerminated==sal_False, "Desktop::dispose()", "It's not allowed to dispose the desktop before terminate() is called!" )
+
+ SYNCHRONIZED_START
+ WriteGuard aWriteLock( m_aLock );
+
+ // Look for multiple calls of this method!
+ // If somewhere call dispose() twice - he will be stopped here realy!!!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Now - we are alone and its the first call of this method ...
+ // otherwise call before had thrown a DisposedException / hopefully .-)
+ // But we dont use the transaction object created before ... we reset it immediatly ...
+ // two lines of code ... for what ?
+ // The answer: We wished to synchronize concurrent dispose() calls -> OK
+ // But next line will wait for all currently running transaction (even if they
+ // are running within the same thread!) So we would block ourself there if aTransaction
+ // will stay registered .-)
+ aTransaction.stop();
+
+ // Disable this instance for further work.
+ // This will wait for all current running transactions ...
+ // and reject all new incoming requests!
+ m_aTransactionManager.setWorkingMode( E_BEFORECLOSE );
+
+ aWriteLock.unlock();
+ SYNCHRONIZED_END
+
+ // Following lines of code can be called outside a synchronized block ...
+ // Because our transaction manager will block all new requests to this object.
+ // So nobody can use us any longer.
+ // Exception: Only removing of listener will work ... and this code cant be dangerous.
+
+ // First we has to kill all listener connections.
+ // They might rely on our member and can hinder us on releasing them.
+ css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::lang::EventObject aEvent( xThis );
+ m_aListenerContainer.disposeAndClear( aEvent );
+
+ // Clear our child task container and forget all task references hardly.
+ // Normaly all open document was already closed by our terminate() function before ...
+ // New opened frames will have a problem now .-)
+ m_aChildTaskContainer.clear();
+
+ // Dispose our helper too.
+ css::uno::Reference< css::lang::XEventListener > xFramesHelper( m_xFramesHelper, css::uno::UNO_QUERY );
+ if( xFramesHelper.is() )
+ xFramesHelper->disposing( aEvent );
+
+ // At least clean up other member references.
+ m_xDispatchHelper.clear();
+ m_xFramesHelper.clear();
+ m_xLastFrame.clear();
+ m_xFactory.clear();
+
+ m_xPipeTerminator.clear();
+ m_xQuickLauncher.clear();
+ m_xSWThreadManager.clear();
+ m_xSfxTerminator.clear();
+
+ // From this point nothing will work further on this object ...
+ // excepting our dtor() .-)
+ m_aTransactionManager.setWorkingMode( E_CLOSE );
+}
+
+/*-************************************************************************************************************//**
+ @interface XComponent
+ @short add/remove listener for dispose events
+ @descr Add an event listener to this object, if you whish to get informations
+ about our dieing!
+ You must releas ethis listener reference during your own disposing() method.
+
+ @attention Our container is threadsafe himeslf. So we doesn't need any lock here.
+
+ @seealso -
+
+ @param "xListener", reference to valid listener. We don't accept invalid values!
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Safe impossible cases
+ // Method not defined for all incoming parameter.
+ LOG_ASSERT2( implcp_addEventListener( xListener ), "Desktop::addEventListener()", "Invalid parameter detected!" )
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Safe impossible cases
+ // Method not defined for all incoming parameter.
+ LOG_ASSERT2( implcp_removeEventListener( xListener ), "Desktop::removeEventListener()", "Invalid parameter detected!" )
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDispatchResultListener
+ @short callback for dispatches
+ @descr To support our method "loadComponentFromURL()" we are listener on temp. created dispatcher.
+ They call us back in this method "statusChanged()". As source of given state event, they give us a
+ reference to the target frame, in which dispatch was loaded! So we can use it to return his component
+ to caller! If no target exist ... ??!!
+
+ @seealso method loadComponentFromURL()
+
+ @param "aEvent", state event which (hopefully) valid informations
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::dispatchFinished( const css::frame::DispatchResultEvent& aEvent ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ if( m_eLoadState != E_INTERACTION )
+ {
+ m_xLastFrame = css::uno::Reference< css::frame::XFrame >();
+ m_eLoadState = E_FAILED ;
+ if( aEvent.State == css::frame::DispatchResultState::SUCCESS )
+ {
+ css::uno::Reference < css::frame::XFrame > xFrame;
+ if ( aEvent.Result >>= m_xLastFrame )
+ m_eLoadState = E_SUCCESSFUL;
+ }
+ }
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+}
+
+/*-************************************************************************************************************//**
+ @interface XEventListener
+ @short not implemented!
+ @descr We are a status listener ... and so we must be an event listener too ... But we doesn't need it realy!
+ We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher.
+
+ @seealso method loadComponentFromURL()
+
+ @param -
+ @return -
+
+ @onerror -
+ @threadsafe -
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::disposing( const css::lang::EventObject& ) throw( css::uno::RuntimeException )
+{
+ LOG_ERROR( "Desktop::disposing()", "Algorithm error! Normaly desktop is temp. listener ... not all the time. So this method shouldn't be called." )
+}
+
+/*-************************************************************************************************************//**
+ @interface XInteractionHandler
+ @short callback for loadComponentFromURL for detected exceptions during load proccess
+ @descr In this case we must cancel loading and throw these detected exception again as result
+ of our own called method.
+
+ @attention a)
+ Normal loop in loadComponentFromURL() breaks on setted member m_eLoadState during callback statusChanged().
+ But these interaction feature implements second way to do so! So we must look on different callbacks
+ for same operation ... and live with it.
+ b)
+ Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations
+ for currently running operation!
+
+ @seealso method loadComponentFromURL()
+ @seealso member m_eLoadState
+
+ @param "xRequest", request for interaction - normal a wrapped target exception from bottom services
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::handle( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Don't check incoming request!
+ // If somewhere starts interaction without right parameter - he maked something wrong.
+ // loadComponentFromURL() waits for thjese event - otherwise it yield for ever!
+
+ // get packed request and work on it first
+ // Attention: Don't set it on internal member BEFORE interaction is finished - because
+ // "loadComponentFromURL()" yield tills this member is changed. If we do it before
+ // interaction finish we can't guarantee right functionality. May be we cancel load process to erliear ...
+ css::uno::Any aRequest = xRequest->getRequest();
+
+ // extract continuations from request
+ css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
+ css::uno::Reference< css::task::XInteractionAbort > xAbort ;
+ css::uno::Reference< css::task::XInteractionApprove > xApprove ;
+ css::uno::Reference< css::document::XInteractionFilterSelect > xFilterSelect ;
+ sal_Bool bAbort = sal_False;
+
+ sal_Int32 nCount=lContinuations.getLength();
+ for( sal_Int32 nStep=0; nStep<nCount; ++nStep )
+ {
+ if( ! xAbort.is() )
+ xAbort = css::uno::Reference< css::task::XInteractionAbort >( lContinuations[nStep], css::uno::UNO_QUERY );
+
+ if( ! xApprove.is() )
+ xApprove = css::uno::Reference< css::task::XInteractionApprove >( lContinuations[nStep], css::uno::UNO_QUERY );
+
+ if( ! xFilterSelect.is() )
+ xFilterSelect = css::uno::Reference< css::document::XInteractionFilterSelect >( lContinuations[nStep], css::uno::UNO_QUERY );
+ }
+
+ // differ between abortable interactions (error, unknown filter ...)
+ // and other ones (ambigous but not unknown filter ...)
+ css::task::ErrorCodeRequest aErrorCodeRequest ;
+ css::document::AmbigousFilterRequest aAmbigousFilterRequest;
+ if( aRequest >>= aAmbigousFilterRequest )
+ {
+ if( xFilterSelect.is() )
+ {
+ xFilterSelect->setFilter( aAmbigousFilterRequest.SelectedFilter ); // user selected filter wins!
+ xFilterSelect->select();
+ }
+ }
+ else
+ if( aRequest >>= aErrorCodeRequest )
+ {
+ sal_Bool bWarning = ((aErrorCodeRequest.ErrCode & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
+ if (xApprove.is() && bWarning)
+ xApprove->select();
+ else
+ if (xAbort.is())
+ {
+ xAbort->select();
+ bAbort = sal_True;
+ }
+ }
+ else
+ if( xAbort.is() )
+ {
+ xAbort->select();
+ bAbort = sal_True;
+ }
+
+ /* SAFE AREA ------------------------------------------------------------------------------------------- */
+ // Ok now it's time to break yield loop of loadComponentFromURL().
+ // But only for realy aborted requests!
+ // For example warnings will be approved and we wait for any success story ...
+ if (bAbort)
+ {
+ WriteGuard aWriteLock( m_aLock );
+ m_eLoadState = E_INTERACTION;
+ m_aInteractionRequest = aRequest ;
+ aWriteLock.unlock();
+ }
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+}
+
+//-----------------------------------------------------------------------------
+::sal_Int32 SAL_CALL Desktop::leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ return m_xTitleNumberGenerator->leaseNumber (xComponent);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL Desktop::releaseNumber( ::sal_Int32 nNumber )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ m_xTitleNumberGenerator->releaseNumber (nNumber);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL Desktop::releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ m_xTitleNumberGenerator->releaseNumberForComponent (xComponent);
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OUString SAL_CALL Desktop::getUntitledPrefix()
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ return m_xTitleNumberGenerator->getUntitledPrefix ();
+}
+
+/*-************************************************************************************************************//**
+ @short try to convert a property value
+ @descr This method is called from helperclass "OPropertySetHelper".
+ Don't use this directly!
+ You must try to convert the value of given DESKTOP_PROPHANDLE and
+ return results of this operation. This will be used to ask vetoable
+ listener. If no listener has a veto, we will change value realy!
+ ( in method setFastPropertyValue_NoBroadcast(...) )
+
+ @attention Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!)
+ So we must use different locks to make our implementation threadsafe.
+
+ @seealso class OPropertySetHelper
+ @seealso method setFastPropertyValue_NoBroadcast()
+
+ @param "aConvertedValue" new converted value of property
+ @param "aOldValue" old value of property
+ @param "nHandle" handle of property
+ @param "aValue" new value of property
+ @return sal_True if value will be changed, sal_FALSE otherway
+
+ @onerror IllegalArgumentException, if you call this with an invalid argument
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+sal_Bool SAL_CALL Desktop::convertFastPropertyValue( css::uno::Any& aConvertedValue ,
+ css::uno::Any& aOldValue ,
+ sal_Int32 nHandle ,
+ const css::uno::Any& aValue ) throw( css::lang::IllegalArgumentException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Initialize state with sal_False !!!
+ // (Handle can be invalid)
+ sal_Bool bReturn = sal_False;
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO:
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_bSuspendQuickstartVeto),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_xDispatchRecorderSupplier),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ case DESKTOP_PROPHANDLE_TITLE :
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_sTitle),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ }
+
+ // Return state of operation.
+ return bReturn ;
+}
+
+/*-************************************************************************************************************//**
+ @short set value of a transient property
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+ Handle and value are valid everyway! You must set the new value only.
+ After this, baseclass send messages to all listener automaticly.
+
+ @seealso class OPropertySetHelper
+
+ @param "nHandle" handle of property to change
+ @param "aValue" new value of property
+ @return -
+
+ @onerror An exception is thrown.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle ,
+ const css::uno::Any& aValue ) throw( css::uno::Exception )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue >>= m_bSuspendQuickstartVeto;
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue >>= m_xDispatchRecorderSupplier;
+ break;
+ case DESKTOP_PROPHANDLE_TITLE: aValue >>= m_sTitle;
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short get value of a transient property
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+
+ @attention We don't need any mutex or lock here ... We use threadsafe container or methods here only!
+
+ @seealso class OPropertySetHelper
+
+ @param "nHandle" handle of property to change
+ @param "aValue" current value of property
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::getFastPropertyValue( css::uno::Any& aValue ,
+ sal_Int32 nHandle ) const
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_ACTIVEFRAME : aValue <<= m_aChildTaskContainer.getActive();
+ break;
+ case DESKTOP_PROPHANDLE_ISPLUGGED : aValue <<= sal_False;
+ break;
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue <<= m_bSuspendQuickstartVeto;
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue <<= m_xDispatchRecorderSupplier;
+ break;
+ case DESKTOP_PROPHANDLE_TITLE: aValue <<= m_sTitle;
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short return structure and information about transient properties
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+
+ @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
+ Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
+ So we could have two different mutex/lock mechanism at the same object.
+
+ @seealso class OPropertySetHelper
+
+ @param -
+ @return structure with property-informations
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+::cppu::IPropertyArrayHelper& SAL_CALL Desktop::getInfoHelper()
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Optimize this method !
+ // We initialize a static variable only one time. And we don't must use a mutex at every call!
+ // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL!
+ static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL;
+
+ if( pInfoHelper == NULL )
+ {
+ // Ready for multithreading
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ // Control this pointer again, another instance can be faster then these!
+ if( pInfoHelper == NULL )
+ {
+ // Define static member to give structure of properties to baseclass "OPropertySetHelper".
+ // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable.
+ // "sal_True" say: Table is sorted by name.
+ static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True );
+ pInfoHelper = &aInfoHelper;
+ }
+ }
+
+ return(*pInfoHelper);
+}
+
+/*-************************************************************************************************************//**
+ @short return propertysetinfo
+ @descr You can call this method to get information about transient properties
+ of this object.
+
+ @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
+ Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
+ So we could have two different mutex/lock mechanism at the same object.
+
+ @seealso class OPropertySetHelper
+ @seealso interface XPropertySet
+ @seealso interface XMultiPropertySet
+
+ @param -
+ @return reference to object with information [XPropertySetInfo]
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL Desktop::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException)
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Optimize this method !
+ // We initialize a static variable only one time. And we don't must use a mutex at every call!
+ // For the first call; pInfo is NULL - for the second call pInfo is different from NULL!
+ static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = NULL;
+
+ if( pInfo == NULL )
+ {
+ // Ready for multithreading
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ // Control this pointer again, another instance can be faster then these!
+ if( pInfo == NULL )
+ {
+ // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
+ // (Use method "getInfoHelper()".)
+ static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ pInfo = &xInfo;
+ }
+ }
+
+ return (*pInfo);
+}
+
+/*-************************************************************************************************************//**
+ @short return current component of current frame
+ @descr The desktop himself has no component. But every frame in subtree.
+ If somewhere call getCurrentComponent() at this class, we try to find the right frame and
+ then we try to become his component. It can be a VCL-component, the model or the controller
+ of founded frame.
+
+ @attention We don't work on internal member ... so we doesn't need any lock here.
+
+ @seealso method getCurrentComponent();
+
+ @param "xFrame", reference to valid frame in hierarchy. Method is not defined for invalid values.
+ But we don't check these. Its an IMPL-method and caller must use it right!
+ @return A reference to found component.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > Desktop::impl_getFrameComponent( const css::uno::Reference< css::frame::XFrame >& xFrame ) const
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Set default return value, if method failed.
+ css::uno::Reference< css::lang::XComponent > xComponent;
+ // Does no controller exists?
+ css::uno::Reference< css::frame::XController > xController = xFrame->getController();
+ if( xController.is() == sal_False )
+ {
+ // Controller not exist - use the VCL-component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xFrame->getComponentWindow(), css::uno::UNO_QUERY );
+ }
+ else
+ {
+ // Does no model exists?
+ css::uno::Reference< css::frame::XModel > xModel( xController->getModel(), css::uno::UNO_QUERY );
+ if( xModel.is() == sal_True )
+ {
+ // Model exist - use the model as component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xModel, css::uno::UNO_QUERY );
+ }
+ else
+ {
+ // Model not exist - use the controller as component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xController, css::uno::UNO_QUERY );
+ }
+ }
+
+ return xComponent;
+}
+
+/*-************************************************************************************************************//**
+ @short create table with information about properties
+ @descr We use a helper class to support properties. These class need some information about this.
+ These method create a new static description table with name, type, r/w-flags and so on ...
+
+ @seealso class OPropertySetHelper
+ @seealso method getInfoHelper()
+
+ @param -
+ @return Static table with information about properties.
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+const css::uno::Sequence< css::beans::Property > Desktop::impl_getStaticPropertyDescriptor()
+{
+ // Create a new static property array to initialize sequence!
+ // Table of all predefined properties of this class. Its used from OPropertySetHelper-class!
+ // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!!
+ // It's necessary for methods of OPropertySetHelper.
+ // ATTENTION:
+ // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!!
+
+ static const css::beans::Property pProperties[] =
+ {
+ css::beans::Property( DESKTOP_PROPNAME_ACTIVEFRAME , DESKTOP_PROPHANDLE_ACTIVEFRAME , ::getCppuType((const css::uno::Reference< css::lang::XComponent >*)NULL) , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( DESKTOP_PROPNAME_DISPATCHRECORDERSUPPLIER , DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER, ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL), css::beans::PropertyAttribute::TRANSIENT ),
+ css::beans::Property( DESKTOP_PROPNAME_ISPLUGGED , DESKTOP_PROPHANDLE_ISPLUGGED , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( DESKTOP_PROPNAME_SUSPENDQUICKSTARTVETO , DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT ),
+ css::beans::Property( DESKTOP_PROPNAME_TITLE , DESKTOP_PROPHANDLE_TITLE , ::getCppuType((const ::rtl::OUString*)NULL) , css::beans::PropertyAttribute::TRANSIENT ),
+ };
+ // Use it to initialize sequence!
+ static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor( pProperties, DESKTOP_PROPCOUNT );
+ // Return static "PropertyDescriptor"
+ return lPropertyDescriptor;
+}
+
+//=============================================================================
+void Desktop::impl_sendQueryTerminationEvent(Desktop::TTerminateListenerList& lCalledListener,
+ ::sal_Bool& bVeto )
+{
+ bVeto = sal_False;
+
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
+ if ( ! pContainer )
+ return;
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+
+ ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
+ while ( aIterator.hasMoreElements() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
+ if ( ! xListener.is() )
+ continue;
+ xListener->queryTermination( aEvent );
+ lCalledListener.push_back(xListener);
+ }
+ catch( const css::frame::TerminationVetoException& )
+ {
+ // first veto will stop notification loop.
+ bVeto = sal_True;
+ return;
+ }
+ catch( const css::uno::Exception& )
+ {
+ // clean up container.
+ // E.g. dead remote listener objects can make trouble otherwise.
+ // Iterator implementation allows removing objects during it's used !
+ aIterator.remove();
+ }
+ }
+}
+
+//=============================================================================
+void Desktop::impl_sendCancelTerminationEvent(const Desktop::TTerminateListenerList& lCalledListener)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+ Desktop::TTerminateListenerList::const_iterator pIt;
+ for ( pIt = lCalledListener.begin();
+ pIt != lCalledListener.end ();
+ ++pIt )
+ {
+ try
+ {
+ // Note: cancelTermination() is a new and optional interface method !
+ css::uno::Reference< css::frame::XTerminateListener > xListener = *pIt;
+ css::uno::Reference< css::frame::XTerminateListener2 > xListenerGeneration2(xListener, css::uno::UNO_QUERY);
+ if ( ! xListenerGeneration2.is() )
+ continue;
+ xListenerGeneration2->cancelTermination( aEvent );
+ }
+ catch( const css::uno::Exception& )
+ {}
+ }
+}
+
+//=============================================================================
+void Desktop::impl_sendNotifyTerminationEvent()
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
+ if ( ! pContainer )
+ return;
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+
+ ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
+ while ( aIterator.hasMoreElements() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
+ if ( ! xListener.is() )
+ continue;
+ xListener->notifyTermination( aEvent );
+ }
+ catch( const css::uno::Exception& )
+ {
+ // clean up container.
+ // E.g. dead remote listener objects can make trouble otherwise.
+ // Iterator implementation allows removing objects during it's used !
+ aIterator.remove();
+ }
+ }
+}
+
+//=============================================================================
+::sal_Bool Desktop::impl_closeFrames(::sal_Bool bAllowUI)
+{
+ SYNCHRONIZED_START
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > lFrames = m_aChildTaskContainer.getAllElements();
+ aReadLock.unlock();
+ SYNCHRONIZED_END
+
+ ::sal_Int32 c = lFrames.getLength();
+ ::sal_Int32 i = 0;
+ ::sal_Int32 nNonClosedFrames = 0;
+
+ for( i=0; i<c; ++i )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XFrame > xFrame = lFrames[i];
+
+ // XController.suspend() will show an UI ...
+ // Use it in case it was allowed from outside only.
+ sal_Bool bSuspended = sal_False;
+ css::uno::Reference< css::frame::XController > xController( xFrame->getController(), css::uno::UNO_QUERY );
+ if (
+ ( bAllowUI ) &&
+ ( xController.is() )
+ )
+ {
+ bSuspended = xController->suspend( sal_True );
+ if ( ! bSuspended )
+ {
+ ++nNonClosedFrames;
+ continue;
+ }
+ }
+
+ // Try to close frame (in case no UI was allowed without calling XController->suspend() before!)
+ // But don't deliver ownership to any other one!
+ // This method can be called again.
+ css::uno::Reference< css::util::XCloseable > xClose( xFrame, css::uno::UNO_QUERY );
+ if ( xClose.is() )
+ {
+ try
+ {
+ xClose->close(sal_False);
+ }
+ catch(const css::util::CloseVetoException&)
+ {
+ // Any internal process of this frame disagree with our request.
+ // Safe this state but dont break these loop. Other frames has to be closed!
+ ++nNonClosedFrames;
+
+ // Reactivate controller.
+ // It can happen that XController.suspend() returned true ... but a registered close listener
+ // throwed these veto exception. Then the controller has to be reactivated. Otherwise
+ // these document doesnt work any more.
+ if (
+ (bSuspended ) &&
+ (xController.is())
+ )
+ xController->suspend(sal_False);
+ }
+
+ // If interface XClosable interface exists and was used ...
+ // it's not allowed to use XComponent->dispose() also !
+ continue;
+ }
+
+ // XClosable not supported ?
+ // Then we have to dispose these frame hardly.
+ css::uno::Reference< css::lang::XComponent > xDispose( xFrame, css::uno::UNO_QUERY );
+ if ( xDispose.is() )
+ xDispose->dispose();
+
+ // Don't remove these frame from our child container!
+ // A frame do it by itself inside close()/dispose() method.
+ }
+ catch(const css::lang::DisposedException&)
+ {
+ // Dispose frames are closed frames.
+ // So we can count it here .-)
+ }
+ }
+
+ return (nNonClosedFrames < 1);
+}
+
+//_________________________________________________________________________________________________________________
+// debug methods
+//_________________________________________________________________________________________________________________
+
+/*-----------------------------------------------------------------------------------------------------------------
+ The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
+ we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT!
+-----------------------------------------------------------------------------------------------------------------*/
+
+#ifdef ENABLE_ASSERTIONS
+
+//*****************************************************************************************************************
+// We work with valid servicemanager only.
+sal_Bool Desktop::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+{
+ return(
+ ( &xFactory == NULL ) ||
+ ( xFactory.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+// We work with valid listener only.
+sal_Bool Desktop::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return(
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+// We work with valid listener only.
+sal_Bool Desktop::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return(
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+#endif // #ifdef ENABLE_ASSERTIONS
+
+} // namespace framework
diff --git a/framework/source/services/dispatchhelper.cxx b/framework/source/services/dispatchhelper.cxx
new file mode 100644
index 000000000000..be8e666ee9db
--- /dev/null
+++ b/framework/source/services/dispatchhelper.cxx
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_______________________________________________
+// my own includes
+#include <services/dispatchhelper.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/frame/XNotifyingDispatch.hpp>
+
+//_______________________________________________
+// includes of other projects
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+//_______________________________________________
+// non exported const
+
+//_______________________________________________
+// non exported definitions
+
+//_______________________________________________
+// declarations
+
+//_______________________________________________
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XSERVICEINFO_MULTISERVICE(DispatchHelper ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_DISPATCHHELPER ,
+ IMPLEMENTATIONNAME_DISPATCHHELPER)
+
+DEFINE_INIT_SERVICE( DispatchHelper, {} )
+
+//_______________________________________________
+
+/** ctor.
+
+ @param xSMGR the global uno service manager, which can be used to create own needed services.
+*/
+DispatchHelper::DispatchHelper( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
+ : ThreadHelpBase( )
+ // Init member
+ , m_xSMGR (xSMGR)
+{
+}
+
+//_______________________________________________
+
+/** dtor.
+*/
+DispatchHelper::~DispatchHelper()
+{
+}
+
+//_______________________________________________
+
+/** capsulate all steps of a dispatch request and provide so an easy way for dispatches.
+
+ @param xDispatchProvider
+ identifies the object, which provides may be valid dispatch objects for this execute.
+
+ @param sURL
+ describes the requested feature.
+
+ @param sTargetFrameName
+ points to the frame, which must be used (or may be created) for this dispatch.
+
+ @param nSearchFlags
+ in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.
+
+ @param lArguments
+ optional arguments for this request.
+
+ @return An Any which capsulate a possible result of the internal wrapped dispatch.
+ */
+css::uno::Any SAL_CALL DispatchHelper::executeDispatch(
+ const css::uno::Reference< css::frame::XDispatchProvider >& xDispatchProvider ,
+ const ::rtl::OUString& sURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::uno::XInterface > xTHIS(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+
+ // check for valid parameters
+ if (
+ (!xDispatchProvider.is()) ||
+ (sURL.getLength()<1 )
+ )
+ {
+ return css::uno::Any();
+ }
+
+ // parse given URL
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ /* } SAFE */
+
+ css::util::URL aURL;
+ aURL.Complete = sURL;
+ xParser->parseStrict(aURL);
+
+ // search dispatcher
+ css::uno::Reference< css::frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
+ css::uno::Reference< css::frame::XNotifyingDispatch > xNotifyDispatch (xDispatch, css::uno::UNO_QUERY);
+
+ // make sure that synchronous execution is used (if possible)
+ css::uno::Sequence< css::beans::PropertyValue > aArguments( lArguments );
+ sal_Int32 nLength = lArguments.getLength();
+ aArguments.realloc( nLength + 1 );
+ aArguments[ nLength ].Name = ::rtl::OUString::createFromAscii("SynchronMode");
+ aArguments[ nLength ].Value <<= (sal_Bool) sal_True;
+
+ css::uno::Any aResult;
+ if (xNotifyDispatch.is())
+ {
+ // dispatch it with guaranteed notification
+ // Here we can hope for a result ... instead of the normal dispatch.
+ css::uno::Reference< css::frame::XDispatchResultListener > xListener(xTHIS, css::uno::UNO_QUERY);
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+ m_xBroadcaster = css::uno::Reference< css::uno::XInterface >(xNotifyDispatch, css::uno::UNO_QUERY);
+ m_aResult = css::uno::Any();
+ m_aBlock.reset();
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ // dispatch it and wait for a notification
+ // TODO/MBA: waiting in main thread?!
+ xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
+ //m_aBlock.wait();
+ aResult = m_aResult;
+ }
+ else
+ if (xDispatch.is())
+ {
+ // dispatch it without any chance to get a result
+ xDispatch->dispatch( aURL, aArguments );
+ }
+
+ return aResult;
+}
+
+//_______________________________________________
+
+/** callback for started dispatch with guaranteed notifications.
+
+ We must save the result, so the method executeDispatch() can return it.
+ Further we must release the broadcaster (otherwhise it can't die)
+ and unblock the waiting executeDispatch() request.
+
+ @param aResult
+ describes the result of the dispatch operation
+ */
+void SAL_CALL DispatchHelper::dispatchFinished( const css::frame::DispatchResultEvent& aResult )
+ throw(css::uno::RuntimeException)
+{
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ m_aResult <<= aResult;
+ m_aBlock.set();
+ m_xBroadcaster.clear();
+
+ /* } SAFE */
+}
+
+//_______________________________________________
+
+/** we has to realease our broadcaster reference.
+
+ @param aEvent
+ describe the source of this event and MUST be our save broadcaster!
+ */
+void SAL_CALL DispatchHelper::disposing( const css::lang::EventObject& )
+ throw(css::uno::RuntimeException)
+{
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ m_aResult.clear();
+ m_aBlock.set();
+ m_xBroadcaster.clear();
+
+ /* } SAFE */
+}
+
+}
diff --git a/framework/source/services/frame.cxx b/framework/source/services/frame.cxx
new file mode 100644
index 000000000000..b9dd626cf06d
--- /dev/null
+++ b/framework/source/services/frame.cxx
@@ -0,0 +1,3311 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <services/frame.hxx>
+#include <dispatch/dispatchprovider.hxx>
+
+#ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_
+#include <dispatch/interceptionhelper.hxx>
+#endif
+#include <dispatch/closedispatcher.hxx>
+#include <dispatch/windowcommanddispatch.hxx>
+#include <loadenv/loadenv.hxx>
+#include <helper/oframes.hxx>
+#include <helper/statusindicatorfactory.hxx>
+#include <framework/titlehelper.hxx>
+#include <classes/droptargetlistener.hxx>
+#include <classes/taskcreator.hxx>
+#include <loadenv/targethelper.hxx>
+#include <framework/framelistanalyzer.hxx>
+#include <helper/dockingareadefaultacceptor.hxx>
+#include <dispatch/dispatchinformationprovider.hxx>
+#include <threadhelp/transactionguard.hxx>
+#include <pattern/window.hxx>
+#include <services.h>
+#include <properties.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/task/XStatusIndicatorSupplier.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/awt/XDataTransferProviderAccess.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+
+#ifndef _COM_SUN_STAR_FRAME_XTITLECHANGEBROADCASTER_HPP_
+#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
+#endif
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <comphelper/sequenceashashmap.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/proptypehlp.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/window.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/svapp.hxx>
+
+#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
+#include <toolkit/unohlp.hxx>
+#endif
+#include <toolkit/awt/vclxwindow.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/moduleoptions.hxx>
+
+#ifdef ENABLE_ASSERTIONS
+ #ifndef _RTL_STRBUF_HXX_
+ #include <rtl/strbuf.hxx>
+ #endif
+#endif
+
+#include <vcl/menu.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+css::uno::WeakReference< css::frame::XFrame > Frame::m_xCloserFrame = css::uno::WeakReference< css::frame::XFrame >();
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_21 ( Frame ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::frame::XFramesSupplier ),
+ DIRECT_INTERFACE(css::frame::XFrame ),
+ DIRECT_INTERFACE(css::lang::XComponent ),
+ DIRECT_INTERFACE(css::task::XStatusIndicatorFactory ),
+ DIRECT_INTERFACE(css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE(css::frame::XDispatchInformationProvider ),
+ DIRECT_INTERFACE(css::frame::XDispatchProviderInterception ),
+ DIRECT_INTERFACE(css::beans::XPropertySet ),
+ DIRECT_INTERFACE(css::beans::XPropertySetInfo ),
+ DIRECT_INTERFACE(css::awt::XWindowListener ),
+ DIRECT_INTERFACE(css::awt::XTopWindowListener ),
+ DIRECT_INTERFACE(css::awt::XFocusListener ),
+ DERIVED_INTERFACE(css::lang::XEventListener, css::awt::XWindowListener ),
+ DIRECT_INTERFACE(css::document::XActionLockable ),
+ DIRECT_INTERFACE(css::util::XCloseable ),
+ DIRECT_INTERFACE(css::util::XCloseBroadcaster ),
+ DIRECT_INTERFACE(css::frame::XComponentLoader ),
+ DIRECT_INTERFACE(css::frame::XTitle ),
+ DIRECT_INTERFACE(css::frame::XTitleChangeBroadcaster )
+ )
+
+DEFINE_XTYPEPROVIDER_20 ( Frame ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XFramesSupplier ,
+ css::frame::XFrame ,
+ css::lang::XComponent ,
+ css::task::XStatusIndicatorFactory ,
+ css::beans::XPropertySet ,
+ css::beans::XPropertySetInfo ,
+ css::frame::XDispatchProvider ,
+ css::frame::XDispatchInformationProvider ,
+ css::frame::XDispatchProviderInterception ,
+ css::awt::XWindowListener ,
+ css::awt::XTopWindowListener ,
+ css::awt::XFocusListener ,
+ css::lang::XEventListener ,
+ css::util::XCloseable ,
+ css::util::XCloseBroadcaster ,
+ css::frame::XComponentLoader ,
+ css::frame::XTitle ,
+ css::frame::XTitleChangeBroadcaster
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( Frame ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_FRAME ,
+ IMPLEMENTATIONNAME_FRAME
+ )
+
+DEFINE_INIT_SERVICE ( Frame,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW);
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new dispatchhelper-object to handle dispatches.
+ // We use these helper as slave for our interceptor helper ... not directly!
+ // But he is event listener on THIS instance!
+ DispatchProvider* pDispatchHelper = new DispatchProvider( m_xFactory, this );
+ css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( static_cast< ::cppu::OWeakObject* >(pDispatchHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ DispatchInformationProvider* pInfoHelper = new DispatchInformationProvider(m_xFactory, this);
+ m_xDispatchInfoHelper = css::uno::Reference< css::frame::XDispatchInformationProvider >( static_cast< ::cppu::OWeakObject* >(pInfoHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
+ // Set created dispatch provider as slowest slave of it.
+ // Hold interception helper by reference only - not by pointer!
+ // So it's easiear to destroy it.
+ InterceptionHelper* pInterceptionHelper = new InterceptionHelper( this, xDispatchProvider );
+ m_xDispatchHelper = css::uno::Reference< css::frame::XDispatchProvider >( static_cast< ::cppu::OWeakObject* >(pInterceptionHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
+ // We hold member as reference ... not as pointer too!
+ // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
+ // But look on dispose() for right order of deinitialization.
+ OFrames* pFramesHelper = new OFrames( m_xFactory, this, &m_aChildFrameContainer );
+ m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a the drop target listener.
+ // We hold member as reference ... not as pointer too!
+ DropTargetListener* pDropListener = new DropTargetListener( m_xFactory, this );
+ m_xDropTargetListener = css::uno::Reference< css::datatransfer::dnd::XDropTargetListener >( static_cast< ::cppu::OWeakObject* >(pDropListener), css::uno::UNO_QUERY );
+
+ // Safe impossible cases
+ // We can't work without these helpers!
+ LOG_ASSERT2( xDispatchProvider.is ()==sal_False, "Frame::impl_initService()", "Slowest slave for dispatch- and interception helper isn't valid. XDispatchProvider, XDispatch, XDispatchProviderInterception are not full supported!" )
+ LOG_ASSERT2( m_xDispatchHelper.is ()==sal_False, "Frame::impl_initService()", "Interception helper isn't valid. XDispatchProvider, XDispatch, XDispatchProviderInterception are not full supported!" )
+ LOG_ASSERT2( m_xFramesHelper.is ()==sal_False, "Frame::impl_initService()", "Frames helper isn't valid. XFrames, XIndexAccess and XElementAcces are not supported!" )
+ LOG_ASSERT2( m_xDropTargetListener.is()==sal_False, "Frame::impl_initService()", "DropTarget helper isn't valid. Drag and drop without functionality!" )
+
+ //-------------------------------------------------------------------------------------------------------------
+ // establish notifies for changing of "disabled commands" configuration during runtime
+ m_aCommandOptions.EstablisFrameCallback(this);
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Create an initial layout manager
+ // Create layout manager and connect it to the newly created frame
+ m_xLayoutManager = css::uno::Reference< css::frame::XLayoutManager >(m_xFactory->createInstance(SERVICENAME_LAYOUTMANAGER), css::uno::UNO_QUERY);
+
+ //-------------------------------------------------------------------------------------------------------------
+ // set information about all supported properties at the base class helper PropertySetHelper
+ impl_initializePropInfo();
+ }
+ )
+
+/*-****************************************************************************************************//**
+ @short standard constructor to create instance by factory
+ @descr This constructor initialize a new instance of this class by valid factory,
+ and will be set valid values on his member and baseclasses.
+
+ @attention a) Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you
+ will get over this. (e.g. using of your reference as parameter to initialize some member)
+ Do such things in DEFINE_INIT_SERVICE() method, which is called automaticly after your ctor!!!
+ b) Baseclass OBroadcastHelper is a typedef in namespace cppu!
+ The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
+ If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!?
+ I don't know why! (other compiler not tested .. but it works!)
+
+ @seealso method DEFINE_INIT_SERVICE()
+
+ @param "xFactory" is the multi service manager, which create this instance.
+ The value must be different from NULL!
+ @return -
+
+ @onerror ASSERT in debug version or nothing in relaese version.
+*//*-*****************************************************************************************************/
+Frame::Frame( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , TransactionBase ( )
+ , PropertySetHelper ( xFactory,
+ &m_aLock,
+ &m_aTransactionManager,
+ sal_False) // sal_False => dont release shared mutex on calling us!
+ , ::cppu::OWeakObject ( )
+ // init member
+ , m_xFactory ( xFactory )
+ , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
+ , m_xParent ( )
+ , m_xContainerWindow ( )
+ , m_xComponentWindow ( )
+ , m_xController ( )
+ , m_eActiveState ( E_INACTIVE )
+ , m_sName ( )
+ , m_bIsFrameTop ( sal_True ) // I think we are top without a parent ... and there is no parent yet!
+ , m_bConnected ( sal_False ) // There exist no component inside of use => sal_False, we are not connected!
+ , m_nExternalLockCount ( 0 )
+ , m_bSelfClose ( sal_False ) // Important!
+ , m_bIsHidden ( sal_True )
+ , m_xTitleHelper ( )
+ , m_aChildFrameContainer ( )
+{
+ // Check incoming parameter to avoid against wrong initialization.
+ LOG_ASSERT2( implcp_ctor( xFactory ), "Frame::Frame()", "Invalid parameter detected!" )
+
+ /* Please have a look on "@attentions" of description before! */
+}
+
+/*-****************************************************************************************************//**
+ @short standard destructor
+ @descr This one do NOTHING! Use dispose() instaed of this.
+
+ @seealso method dispose()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+Frame::~Frame()
+{
+ LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE, "Frame::~Frame()", "Who forgot to dispose this service?" )
+}
+
+/*-************************************************************************************************************//**
+ @interface XComponentLoader
+ @short try to load given URL into a task
+ @descr You can give us some informations about the content, which you will load into a frame.
+ We search or create this target for you, make a type detection of given URL and try to load it.
+ As result of this operation we return the new created component or nothing, if loading failed.
+
+ @seealso -
+
+ @param "sURL" , URL, which represant the content
+ @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ...
+ @param "nSearchFlags" , optional arguments for frame search, if target isn't a special one
+ @param "lArguments" , optional arguments for loading
+ @return A valid component reference, if loading was successfully.
+ A null reference otherwise.
+
+ @onerror We return a null reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > SAL_CALL Frame::loadComponentFromURL( const ::rtl::OUString& sURL ,
+ const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::io::IOException ,
+ css::lang::IllegalArgumentException ,
+ css::uno::RuntimeException )
+{
+ {
+ // If the frame is closed the call might lead to crash even with target "_blank",
+ // so the DisposedException should be thrown in this case
+ // It still looks to be too dangerous to set the transaction for the whole loading process
+ // so the guard is used in scopes to let the standard check be used
+
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ }
+
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XComponentLoader > xThis(static_cast< css::frame::XComponentLoader* >(this), css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory;
+ aReadLock.unlock();
+
+ return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments);
+}
+
+/*-****************************************************************************************************//**
+ @short return access to append or remove childs on desktop
+ @descr We don't implement these interface directly. We use a helper class to do this.
+ If you wish to add or delete childs to/from the container, call these method to get
+ a reference to the helper.
+
+ @seealso class OFrames
+
+ @param -
+ @return A reference to the helper which answer your queries.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XFrames > SAL_CALL Frame::getFrames() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+
+/*TODO
+ This is a temp. HACK!
+ Our parent (a Task!) stand in close/dispose and set working mode to E_BEFOERECLOSE
+ and call dispose on us! We tra to get this xFramesHelper and are reject by an "already closed" pranet instance ....
+ => We use SOFTEXCEPTIONS here ... but we should make it right in further times ....
+ */
+
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ // Return access to all child frames to caller.
+ // Ouer childframe container is implemented in helper class OFrames and used as a reference m_xFramesHelper!
+ return m_xFramesHelper;
+}
+
+/*-****************************************************************************************************//**
+ @short get the current active child frame
+ @descr It must be a frameto. Direct childs of a frame are frames only! No task or desktop is accepted.
+ We don't save this information directly in this class. We use ouer container-helper
+ to do that.
+
+ @seealso class OFrameContainer
+ @seealso method setActiveFrame()
+
+ @param -
+ @return A reference to ouer current active childframe, if anyone exist.
+ @return A null reference, if nobody is active.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Frame::getActiveFrame() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ // Return current active frame.
+ // This information is avaliable on the container.
+ return m_aChildFrameContainer.getActive();
+}
+
+/*-****************************************************************************************************//**
+ @short set the new active direct child frame
+ @descr It must be a frame to. Direct childs of frame are frames only! No task or desktop is accepted.
+ We don't save this information directly in this class. We use ouer container-helper
+ to do that.
+
+ @seealso class OFrameContainer
+ @seealso method getActiveFrame()
+
+ @param "xFrame", reference to new active child. It must be an already existing child!
+ @return -
+
+ @onerror An assertion is thrown and element is ignored, if given frame is'nt already a child of us.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameters.
+ LOG_ASSERT2( implcp_setActiveFrame( xFrame ), "Frame::setActiveFrame()", "Invalid parameter detected!" )
+ // Look for rejected calls!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+
+ // Copy neccessary member for threadsafe access!
+ // m_aChildFrameContainer is threadsafe himself and he live if we live!!!
+ // ...and our transaction is non breakable too ...
+ css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
+ EActiveState eActiveState = m_eActiveState ;
+
+ aWriteLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ // Don't work, if "new" active frame is'nt different from current one!
+ // (xFrame==NULL is allowed to UNSET it!)
+ if( xActiveChild != xFrame )
+ {
+ // ... otherwise set new and deactivate old one.
+ m_aChildFrameContainer.setActive( xFrame );
+ if (
+ ( eActiveState != E_INACTIVE ) &&
+ ( xActiveChild.is() == sal_True )
+ )
+ {
+ xActiveChild->deactivate();
+ }
+ }
+
+ if( xFrame.is() == sal_True )
+ {
+ // If last active frame had focus ...
+ // ... reset state to ACTIVE and send right FrameActionEvent for focus lost.
+ if( eActiveState == E_FOCUS )
+ {
+ aWriteLock.lock();
+ eActiveState = E_ACTIVE ;
+ m_eActiveState = eActiveState;
+ aWriteLock.unlock();
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING );
+ }
+
+ // If last active frame was active ...
+ // but new one isn't it ...
+ // ... set it as active one.
+ if (
+ ( eActiveState == E_ACTIVE ) &&
+ ( xFrame->isActive() == sal_False )
+ )
+ {
+ xFrame->activate();
+ }
+ }
+ else
+ // If this frame is active and has no active subframe anymore it is UI active too
+ if( eActiveState == E_ACTIVE )
+ {
+ aWriteLock.lock();
+ eActiveState = E_FOCUS ;
+ m_eActiveState = eActiveState;
+ aWriteLock.unlock();
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED );
+ }
+}
+
+/*-****************************************************************************************************//**
+ initialize new created layout manager
+**/
+void lcl_enableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager >& xLayoutManager,
+ const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ // Provide container window to our layout manager implementation
+ xLayoutManager->attachFrame(xFrame);
+
+ css::uno::Reference< css::frame::XFrameActionListener > xListen(xLayoutManager, css::uno::UNO_QUERY_THROW);
+ xFrame->addFrameActionListener(xListen);
+
+ DockingAreaDefaultAcceptor* pAcceptor = new DockingAreaDefaultAcceptor(xFrame);
+ css::uno::Reference< css::ui::XDockingAreaAcceptor > xDockingAreaAcceptor( static_cast< ::cppu::OWeakObject* >(pAcceptor), css::uno::UNO_QUERY_THROW);
+ xLayoutManager->setDockingAreaAcceptor(xDockingAreaAcceptor);
+}
+
+/*-****************************************************************************************************//**
+ deinitialize layout manager
+**/
+void lcl_disableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager >& xLayoutManager,
+ const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ css::uno::Reference< css::frame::XFrameActionListener > xListen(xLayoutManager, css::uno::UNO_QUERY_THROW);
+ xFrame->removeFrameActionListener(xListen);
+ xLayoutManager->setDockingAreaAcceptor(css::uno::Reference< css::ui::XDockingAreaAcceptor >());
+ xLayoutManager->attachFrame(css::uno::Reference< css::frame::XFrame >());
+}
+
+/*-****************************************************************************************************//**
+ @short initialize frame instance
+ @descr A frame needs a window. This method set a new one ... but should called one times only!
+ We use this window to listen for window events and forward it to our set component.
+ Its used as parent of component window too.
+
+ @seealso method getContainerWindow()
+ @seealso method setComponent()
+ @seealso member m_xContainerWindow
+
+ @param "xWindow", reference to new container window - must be valid!
+ @return -
+
+ @onerror We do nothing.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::initialize( const css::uno::Reference< css::awt::XWindow >& xWindow ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ if (!xWindow.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Frame::initialize() called without a valid container window reference."),
+ static_cast< css::frame::XFrame* >(this));
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+
+ if ( m_xContainerWindow.is() )
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Frame::initialized() is called more then once, which isnt usefull nor allowed."),
+ static_cast< css::frame::XFrame* >(this));
+
+ // Look for rejected calls first!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ // Enable object for real working ... so follow impl methods don't must handle it special! (e.g. E_SOFTEXCEPTIONS for rejected calls)
+ m_aTransactionManager.setWorkingMode( E_WORK );
+
+ // This must be the first call of this method!
+ // We should initialize our object and open it for working.
+ // Set the new window.
+ LOG_ASSERT2( m_xContainerWindow.is()==sal_True, "Frame::initialize()", "Leak detected! This state should never occure ..." )
+ m_xContainerWindow = xWindow;
+
+ // if window is initially visible, we will never get a windowShowing event
+ Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
+ if (pWindow && pWindow->IsVisible())
+ m_bIsHidden = sal_False;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory;
+ css::uno::Reference< css::frame::XLayoutManager > xLayoutManager = m_xLayoutManager;
+
+ // Release lock ... because we call some impl methods, which are threadsafe by himself.
+ // If we hold this lock - we will produce our own deadlock!
+ aWriteLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ if (xLayoutManager.is())
+ lcl_enableLayoutManager(xLayoutManager, this);
+
+ // create progress helper
+ css::uno::Reference< css::frame::XFrame > xThis (static_cast< css::frame::XFrame* >(this) , css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::task::XStatusIndicatorFactory > xIndicatorFactory(xSMGR->createInstance(IMPLEMENTATIONNAME_STATUSINDICATORFACTORY), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::lang::XInitialization > xIndicatorInit (xIndicatorFactory , css::uno::UNO_QUERY_THROW);
+ css::uno::Sequence< css::uno::Any > lArgs(2);
+ css::beans::NamedValue aArg;
+ aArg.Name = STATUSINDICATORFACTORY_PROPNAME_FRAME;
+ aArg.Value <<= xThis;
+ lArgs[0] <<= aArg;
+ aArg.Name = STATUSINDICATORFACTORY_PROPNAME_ALLOWPARENTSHOW;
+ aArg.Value <<= sal_True;
+ lArgs[1] <<= aArg;
+ xIndicatorInit->initialize(lArgs);
+
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+ m_xIndicatorFactoryHelper = xIndicatorFactory;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // Start listening for events after setting it on helper class ...
+ // So superflous messages are filtered to NULL :-)
+ implts_startWindowListening();
+
+ impl_enablePropertySet();
+
+ // create WindowCommandDispatch; it is supposed to release itself at frame destruction
+ (void)new WindowCommandDispatch(xSMGR, this);
+
+ // Initialize title functionality
+ TitleHelper* pTitleHelper = new TitleHelper(xSMGR);
+ m_xTitleHelper = css::uno::Reference< css::frame::XTitle >(static_cast< ::cppu::OWeakObject* >(pTitleHelper), css::uno::UNO_QUERY_THROW);
+ pTitleHelper->setOwner(xThis);
+}
+
+/*-****************************************************************************************************//**
+ @short returns current set container window
+ @descr The ContainerWindow property is used as a container for the component
+ in this frame. So this object implements a container interface too.
+ The instantiation of the container window is done by the user of this class.
+ The frame is the owner of its container window.
+
+ @seealso method initialize()
+
+ @param -
+ @return A reference to current set containerwindow.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::awt::XWindow > SAL_CALL Frame::getContainerWindow() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ return m_xContainerWindow;
+}
+
+/*-****************************************************************************************************//**
+ @short set parent frame
+ @descr We need a parent to support some functionality! e.g. findFrame()
+ By the way we use the chance to set an internal information about our top state.
+ So we must not check this information during every isTop() call.
+ We are top, if our parent is the desktop instance or we havent any parent.
+
+ @seealso getCreator()
+ @seealso findFrame()
+ @seealso isTop()
+ @seealos m_bIsFrameTop
+
+ @param xCreator
+ valid reference to our new owner frame, which should implement a supplier interface
+
+ @threadsafe yes
+ @modified 08.05.2002 09:35, as96863
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& xCreator ) throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_xParent = xCreator;
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ css::uno::Reference< css::frame::XDesktop > xIsDesktop( xCreator, css::uno::UNO_QUERY );
+ m_bIsFrameTop = ( xIsDesktop.is() || ! xCreator.is() );
+}
+
+/*-****************************************************************************************************//**
+ @short returns current parent frame
+ @descr The Creator is the parent frame container. If it is NULL, the frame is the uppermost one.
+
+ @seealso method setCreator()
+
+ @param -
+ @return A reference to current set parent frame container.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Frame::getCreator() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ return m_xParent;
+}
+
+/*-****************************************************************************************************//**
+ @short returns current set name of frame
+ @descr This name is used to find target of findFrame() or queryDispatch() calls.
+
+ @seealso method setName()
+
+ @param -
+ @return Current set name of frame.
+
+ @onerror An empty string is returned.
+*//*-*****************************************************************************************************/
+::rtl::OUString SAL_CALL Frame::getName() throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ return m_sName;
+ /* } SAFE */
+}
+
+/*-****************************************************************************************************//**
+ @short set new name for frame
+ @descr This name is used to find target of findFrame() or queryDispatch() calls.
+
+ @attention Special names like "_blank", "_self" aren't allowed ...
+ "_beamer" or "_menubar" excepts this rule!
+
+ @seealso method getName()
+
+ @param "sName", new frame name.
+ @return -
+
+ @onerror We do nothing.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ // Set new name ... but look for invalid special target names!
+ // They are not allowed to set.
+ if (TargetHelper::isValidNameForFrame(sName))
+ m_sName = sName;
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+/*-****************************************************************************************************//**
+ @short search for frames
+ @descr This method searches for a frame with the specified name.
+ Frames may contain other frames (e.g. a frameset) and may
+ be contained in other frames. This hierarchie ist searched by
+ this method.
+ First some special names are taken into account, i.e. "",
+ "_self", "_top", "_blank" etc. The nSearchFlags are ignored
+ when comparing these names with sTargetFrameName, further steps are
+ controlled by the search flags. If allowed, the name of the frame
+ itself is compared with the desired one, then ( again if allowed )
+ the method findFrame() is called for all children, for siblings
+ and as last for the parent frame.
+ If no frame with the given name is found until the top frames container,
+ a new top one is created, if this is allowed by a special
+ flag. The new frame also gets the desired name.
+
+ @param sTargetFrameName
+ special names (_blank, _self) or real name of target frame
+ @param nSearchFlags
+ optional flags which regulate search for non special target frames
+
+ @return A reference to found or may be new created frame.
+ @threadsafe yes
+ @modified 16.05.2002 11:08, as96863
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Frame::findFrame( const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XFrame > xTarget;
+
+ //-----------------------------------------------------------------------------------------------------
+ // 0) Ignore wrong parameter!
+ // We doesn't support search for following special targets.
+ // If we reject this requests - we mustnt check for such names
+ // in following code again and again. If we do not so -wrong
+ // search results can occure!
+ //-----------------------------------------------------------------------------------------------------
+ if (
+ (sTargetFrameName==SPECIALTARGET_DEFAULT ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_HELPAGENT) // valid for dispatches - not for findFrame()!
+ )
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I) check for special defined targets first which must be handled exclusive.
+ // force using of "if() else if() ..."
+ //-----------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::frame::XFrame > xParent ( m_xParent, css::uno::UNO_QUERY );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ sal_Bool bIsTopFrame = m_bIsFrameTop;
+ sal_Bool bIsTopWindow = WindowHelper::isTopWindow(m_xContainerWindow);
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.I) "_blank"
+ // Not allowed for a normal frame - but for the desktop.
+ // Use helper class to do so. It use the desktop automaticly.
+ //-----------------------------------------------------------------------------------------------------
+ if ( sTargetFrameName==SPECIALTARGET_BLANK )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.II) "_parent"
+ // It doesn't matter if we have a valid parent or not. User ask for him and get it.
+ // An empty result is a valid result too.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if ( sTargetFrameName==SPECIALTARGET_PARENT )
+ {
+ xTarget = xParent;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.III) "_top"
+ // If we are not the top frame in this hierarchy, we must forward request to our parent.
+ // Otherwhise we must return ourself.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if ( sTargetFrameName==SPECIALTARGET_TOP )
+ {
+ if (bIsTopFrame)
+ xTarget = this;
+ else
+ if (xParent.is()) // If we are not top - the parent MUST exist. But may it's better to check it again .-)
+ xTarget = xParent->findFrame(SPECIALTARGET_TOP,0);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.IV) "_self", ""
+ // This mean this frame in every case.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (
+ ( sTargetFrameName==SPECIALTARGET_SELF ) ||
+ ( sTargetFrameName.getLength()<1 )
+ )
+ {
+ xTarget = this;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.V) "_beamer"
+ // This is a special sub frame of any task. We must return it if we found it on our direct childrens
+ // or create it there if it not already exists.
+ // Note: Such beamer exists for task(top) frames only!
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if ( sTargetFrameName==SPECIALTARGET_BEAMER )
+ {
+ // We are a task => search or create the beamer
+ if (bIsTopWindow)
+ {
+ xTarget = m_aChildFrameContainer.searchOnDirectChildrens(SPECIALTARGET_BEAMER);
+ if ( ! xTarget.is() )
+ {
+ /* TODO
+ Creation not supported yet!
+ Wait for new layout manager service because we can't plug it
+ inside already opened document of this frame ...
+ */
+ }
+ }
+ // We arent a task => forward request to our parent or ignore it.
+ else
+ if (xParent.is())
+ xTarget = xParent->findFrame(SPECIALTARGET_BEAMER,0);
+ }
+
+ else
+ {
+ //-------------------------------------------------------------------------------------------------
+ // II) otherwhise use optional given search flags
+ // force using of combinations of such flags. means no "else" part of use if() statements.
+ // But we ust break further searches if target was already found.
+ // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
+ // TASK and CREATE are handled special.
+ //-------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ aReadLock.lock();
+ ::rtl::OUString sOwnName = m_sName;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-------------------------------------------------------------------------------------------------
+ // II.I) SELF
+ // Check for right name. If it's the searched one return ourself - otherwhise
+ // ignore this flag.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ (nSearchFlags & css::frame::FrameSearchFlag::SELF) &&
+ (sOwnName == sTargetFrameName )
+ )
+ {
+ xTarget = this;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.II) CHILDREN
+ // Search on all children for the given target name.
+ // An empty name value can't occure here - because it must be already handled as "_self"
+ // before. Used helper function of container doesn't create any frame.
+ // It makes a deep search only.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
+ )
+ {
+ xTarget = m_aChildFrameContainer.searchOnAllChildrens(sTargetFrameName);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.III) TASKS
+ // This is a special flag. It regulate search on this task tree only or allow search on
+ // all other ones (which are sibling trees of us) too.
+ // Upper search must stop at this frame if we are the topest one and the TASK flag isn't set
+ // or we can ignore it if we have no valid parent.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( bIsTopFrame && (nSearchFlags & css::frame::FrameSearchFlag::TASKS) ) ||
+ ( ! bIsTopFrame )
+ )
+ {
+ //-------------------------------------------------------------------------------------------------
+ // II.III.I) SIBLINGS
+ // Search on all our direct siblings - means all childrens of our parent.
+ // Use this flag in combination with TASK. We must supress such upper search if
+ // user has not set it and if we are a top frame.
+ //
+ // Attention: Don't forward this request to our parent as a findFrame() call.
+ // In such case we must protect us against recursive calls.
+ // Use snapshot of our parent. But don't use queryFrames() of XFrames interface.
+ // Because it's return all siblings and all her childrens including our children too
+ // if we call it with the CHILDREN flag. We doesn't need that - we need the direct container
+ // items of our parent only to start searches there. So we must use the container interface
+ // XIndexAccess instead of XFrames.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::SIBLINGS) &&
+ ( xParent.is() ) // search on siblings is impossible without a parent
+ )
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
+ if (xSupplier.is())
+ {
+ css::uno::Reference< css::container::XIndexAccess > xContainer( xSupplier->getFrames(), css::uno::UNO_QUERY );
+ if (xContainer.is())
+ {
+ sal_Int32 nCount = xContainer->getCount();
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ css::uno::Reference< css::frame::XFrame > xSibling;
+ if (
+ ( !(xContainer->getByIndex(i)>>=xSibling) ) || // control unpacking
+ ( ! xSibling.is() ) || // check for valid items
+ ( xSibling==static_cast< ::cppu::OWeakObject* >(this) ) // ignore ourself! (We are a part of this container too - but search on our children was already done.)
+ )
+ {
+ continue;
+ }
+
+ // Don't allow upper search here! Use rigth flags to regulate it.
+ // And allow deep search on children only - if it was allowed for us too.
+ sal_Int32 nRightFlags = css::frame::FrameSearchFlag::SELF;
+ if (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
+ nRightFlags |= css::frame::FrameSearchFlag::CHILDREN;
+ xTarget = xSibling->findFrame(sTargetFrameName, nRightFlags );
+ // perform search be breaking further search if a result exist.
+ if (xTarget.is())
+ break;
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.III.II) PARENT
+ // Forward search to our parent (if he exists.)
+ // To prevent us against recursive and superflous calls (which can occure if we allow him
+ // to search on his childrens too) we must change used search flags.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::PARENT) &&
+ ( xParent.is() )
+ )
+ {
+ if (xParent->getName() == sTargetFrameName)
+ xTarget = xParent;
+ else
+ {
+ sal_Int32 nRightFlags = nSearchFlags;
+ nRightFlags &= ~css::frame::FrameSearchFlag::CHILDREN;
+ xTarget = xParent->findFrame(sTargetFrameName, nRightFlags);
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.IV) CREATE
+ // If we haven't found any valid target frame by using normal flags - but user allowed us to create
+ // a new one ... we should do that. Used TaskCreator use Desktop instance automaticly as parent!
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
+ )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+ }
+
+ return xTarget;
+}
+
+/*-****************************************************************************************************//**
+ @short -
+ @descr Returns sal_True, if this frame is a "top frame", otherwise sal_False.
+ The "m_bIsFrameTop" member must be set in the ctor or setCreator() method.
+ A top frame is a member of the top frame container or a member of the
+ task frame container. Both containers can create new frames if the findFrame()
+ method of their css::frame::XFrame interface is called with a frame name not yet known.
+
+ @seealso ctor
+ @seealso method setCreator()
+ @seealso method findFrame()
+
+ @param -
+ @return true, if is it a top frame ... false otherwise.
+
+ @onerror No error should occure!
+*//*-*****************************************************************************************************/
+sal_Bool SAL_CALL Frame::isTop() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ // This information is set in setCreator().
+ // We are top, if ouer parent is a task or the desktop or if no parent exist!
+ return m_bIsFrameTop;
+}
+
+/*-****************************************************************************************************//**
+ @short activate frame in hierarchy
+ @descr This feature is used to mark active pathes in our frame hierarchy.
+ You can be a listener for this event to react for it ... change some internal states or something else.
+
+ @seealso method deactivate()
+ @seealso method isActivate()
+ @seealso enum EActiveState
+ @seealso listener mechanism
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::activate() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+
+ // Copy neccessary member and free the lock.
+ // It's not neccessary for m_aChildFrameContainer ... because
+ // he is threadsafe himself and live if we live.
+ // We use a registered transaction to prevent us against
+ // breaks during this operation!
+ css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive() ;
+ css::uno::Reference< css::frame::XFramesSupplier > xParent ( m_xParent, css::uno::UNO_QUERY ) ;
+ css::uno::Reference< css::frame::XFrame > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XWindow > xComponentWindow( m_xComponentWindow, css::uno::UNO_QUERY ) ;
+ EActiveState eState = m_eActiveState ;
+
+ aWriteLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ //_________________________________________________________________________________________________________
+ // 1) If I'am not active before ...
+ if( eState == E_INACTIVE )
+ {
+ // ... do it then.
+ aWriteLock.lock();
+ eState = E_ACTIVE;
+ m_eActiveState = eState;
+ aWriteLock.unlock();
+ // Deactivate sibling path and forward activation to parent ... if any parent exist!
+ if( xParent.is() == sal_True )
+ {
+ // Everytime set THIS frame as active child of parent and activate it.
+ // We MUST have a valid path from bottom to top as active path!
+ // But we must deactivate the old active sibling path first.
+
+ // Attention: Deactivation of an active path, deactivate the whole path ... from bottom to top!
+ // But we wish to deactivate founded sibling-tree only.
+ // [ see deactivate() / step 4) for further informations! ]
+
+ xParent->setActiveFrame( xThis );
+
+ // Then we can activate from here to top.
+ // Attention: We are ACTIVE now. And the parent will call activate() at us!
+ // But we do nothing then! We are already activated.
+ xParent->activate();
+ }
+ // Its neccessary to send event NOW - not before.
+ // Activation goes from bottom to top!
+ // Thats the reason to activate parent first and send event now.
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_ACTIVATED );
+ }
+
+ //_________________________________________________________________________________________________________
+ // 2) I was active before or current activated and there is a path from here to bottom, who CAN be active.
+ // But ouer direct child of path is not active yet.
+ // (It can be, if activation occur in the middle of a current path!)
+ // In these case we activate path to bottom to set focus on right frame!
+ if (
+ ( eState == E_ACTIVE ) &&
+ ( xActiveChild.is() == sal_True ) &&
+ ( xActiveChild->isActive() == sal_False )
+ )
+ {
+ xActiveChild->activate();
+ }
+
+ //_________________________________________________________________________________________________________
+ // 3) I was active before or current activated. But if I have no active child => I will get the focus!
+ if (
+ ( eState == E_ACTIVE ) &&
+ ( xActiveChild.is() == sal_False )
+ )
+ {
+ aWriteLock.lock();
+ eState = E_FOCUS;
+ m_eActiveState = eState;
+ aWriteLock.unlock();
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED );
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short deactivate frame in hierarchy
+ @descr This feature is used to deactive pathes in our frame hierarchy.
+ You can be a listener for this event to react for it ... change some internal states or something else.
+
+ @seealso method activate()
+ @seealso method isActivate()
+ @seealso enum EActiveState
+ @seealso listener mechanism
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::deactivate() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+
+ // Copy neccessary member and free the lock.
+ css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive() ;
+ css::uno::Reference< css::frame::XFramesSupplier > xParent ( m_xParent, css::uno::UNO_QUERY ) ;
+ css::uno::Reference< css::frame::XFrame > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ EActiveState eState = m_eActiveState ;
+
+ aWriteLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ // Work only, if there something to do!
+ if( eState != E_INACTIVE )
+ {
+ //_____________________________________________________________________________________________________
+ // 1) Deactivate all active childs.
+ if (
+ ( xActiveChild.is() == sal_True ) &&
+ ( xActiveChild->isActive() == sal_True )
+ )
+ {
+ xActiveChild->deactivate();
+ }
+
+ //_____________________________________________________________________________________________________
+ // 2) If I have the focus - I will lost it now.
+ if( eState == E_FOCUS )
+ {
+ // Set new state INACTIVE(!) and send message to all listener.
+ // Don't set ACTIVE as new state. This frame is deactivated for next time - due to activate().
+ aWriteLock.lock();
+ eState = E_ACTIVE;
+ m_eActiveState = eState ;
+ aWriteLock.unlock();
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING );
+ }
+
+ //_____________________________________________________________________________________________________
+ // 3) If I'am active - I will be deactivated now.
+ if( eState == E_ACTIVE )
+ {
+ // Set new state and send message to all listener.
+ aWriteLock.lock();
+ eState = E_INACTIVE;
+ m_eActiveState = eState ;
+ aWriteLock.unlock();
+ implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_DEACTIVATING );
+ }
+
+ //_____________________________________________________________________________________________________
+ // 4) If there is a path from here to my parent ...
+ // ... I'am on the top or in the middle of deactivated subtree and action was started here.
+ // I must deactivate all frames from here to top, which are members of current path.
+ // Stop, if THESE frame not the active frame of ouer parent!
+ if (
+ ( xParent.is() == sal_True ) &&
+ ( xParent->getActiveFrame() == xThis )
+ )
+ {
+ // We MUST break the path - otherwise we will get the focus - not ouer parent! ...
+ // Attention: Ouer parent don't call us again - WE ARE NOT ACTIVE YET!
+ // [ see step 3 and condition "if ( m_eActiveState!=INACTIVE ) ..." in this method! ]
+ xParent->deactivate();
+ }
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short returns active state
+ @descr Call it to get informations about current active state of this frame.
+
+ @seealso method activate()
+ @seealso method deactivate()
+ @seealso enum EActiveState
+
+ @param -
+ @return true if active, false otherwise.
+
+ @onerror No error should occure.
+*//*-*****************************************************************************************************/
+sal_Bool SAL_CALL Frame::isActive() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ return (
+ ( m_eActiveState == E_ACTIVE ) ||
+ ( m_eActiveState == E_FOCUS )
+ );
+}
+
+/*-****************************************************************************************************//**
+ @short ???
+ @descr -
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::contextChanged() throw( css::uno::RuntimeException )
+{
+ // Look for rejected calls!
+ // Sometimes called during closing object... => soft exceptions
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+ // Impl-method is threadsafe himself!
+ // Send event to all listener for frame actions.
+ implts_sendFrameActionEvent( css::frame::FrameAction_CONTEXT_CHANGED );
+}
+
+/*-****************************************************************************************************//**
+ @short set new component inside the frame
+ @descr A frame is a container for a component. Use this method to set, change or realease it!
+ We accept null references! The xComponentWindow will be a child of our container window
+ and get all window events from us.
+
+ @attention (a) A current set component can disagree with the suspend() request!
+ We don't set the new one and return with false then.
+ (b) It's possible to set:
+ (b1) a simple component here which supports the window only - no controller;
+ (b2) a full featured component which supports window and controller;
+ (b3) or both to NULL if outside code which to forget this component.
+
+ @seealso method getComponentWindow()
+ @seealso method getController()
+
+ @param xComponentWindow
+ valid reference to new component window which will be a child of internal container window
+ May <NULL/> for releasing.
+ @param xController
+ reference to new component controller
+ (may <NULL/> for relasing or setting of a simple component)
+
+ @return <TRUE/> if operation was successful, <FALSE/> otherwise.
+
+ @onerror We return <FALSE/>.
+ @threadsafe yes
+ @modified 06.05.2002 11:39, as96863
+*//*-*****************************************************************************************************/
+sal_Bool SAL_CALL Frame::setComponent( const css::uno::Reference< css::awt::XWindow >& xComponentWindow ,
+ const css::uno::Reference< css::frame::XController >& xController ) throw( css::uno::RuntimeException )
+{
+ //_____________________________________________________________________________________________________
+ // Ignore this HACK of sfx2!
+ // He call us with an valid controller without a valid window ... Thats not allowed!
+ if ( xController.is() && ! xComponentWindow.is() )
+ return sal_True;
+
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ //_____________________________________________________________________________________________________
+ // Get threadsafe some copies of used members.
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
+ css::uno::Reference< css::awt::XWindow > xOldComponentWindow = m_xComponentWindow;
+ css::uno::Reference< css::frame::XController > xOldController = m_xController;
+ Window* pOwnWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+ sal_Bool bHadFocus = pOwnWindow->HasChildPathFocus();
+ sal_Bool bWasConnected = m_bConnected;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //_____________________________________________________________________________________________________
+ // stop listening on old window
+ // May it produce some trouble.
+ // But don't forget to listen on new window again ... or reactivate listening
+ // if we reject this setComponent() request and leave this method without changing the old window.
+ implts_stopWindowListening();
+
+ // Notify all listener, that this component (if current one exist) will be unloaded.
+ if (bWasConnected)
+ implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_DETACHING );
+
+ //_____________________________________________________________________________________________________
+ // otherwhise release old component first
+ // Always release controller before releasing window,
+ // because controller may want to access its window!
+ // But check for real changes - may the new controller is the old one.
+ if (
+ (xOldController.is() ) &&
+ (xOldController != xController)
+ )
+ {
+ /* ATTENTION
+ Don't suspend the old controller here. Because the outside caller must do that
+ by definition. We have to dispose it here only.
+ */
+
+ // Before we dispose this controller we should hide it inside this frame instance.
+ // We hold it alive for next calls by using xOldController!
+ /* SAFE {*/
+ WriteGuard aWriteLock( m_aLock );
+ m_xController = NULL;
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ css::uno::Reference< css::lang::XComponent > xDisposable( xOldController, css::uno::UNO_QUERY );
+ if (xDisposable.is())
+ {
+ try
+ {
+ xDisposable->dispose();
+ }
+ catch(const css::lang::DisposedException&)
+ {}
+ }
+ xOldController = NULL;
+ }
+
+ //_____________________________________________________________________________________________________
+ // Now it's time to release the component window.
+ // If controller wasn't released successfully - this code line shouldn't be reached.
+ // Because in case of "suspend()==false" we return immediately with false ...
+ // see before
+ // Check for real changes too.
+ if (
+ (xOldComponentWindow.is() ) &&
+ (xOldComponentWindow != xComponentWindow)
+ )
+ {
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_xComponentWindow = NULL;
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ css::uno::Reference< css::lang::XComponent > xDisposable( xOldComponentWindow, css::uno::UNO_QUERY );
+ if (xDisposable.is())
+ {
+ try
+ {
+ xDisposable->dispose();
+ }
+ catch(const css::lang::DisposedException&)
+ {}
+ }
+ xOldComponentWindow = NULL;
+ }
+
+ //_____________________________________________________________________________________________________
+ // Now it's time to set the new component ...
+ // By the way - find out our new "load state" - means if we have a valid component inside.
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_xComponentWindow = xComponentWindow;
+ m_xController = xController ;
+ m_bConnected = (m_xComponentWindow.is() || m_xController.is());
+ sal_Bool bIsConnected = m_bConnected;
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ //_____________________________________________________________________________________________________
+ // notifies all interest listener, that current component was changed or a new one was loaded
+ if (bIsConnected && bWasConnected)
+ implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_REATTACHED );
+ else
+ if (bIsConnected && !bWasConnected)
+ implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_ATTACHED );
+
+ //_____________________________________________________________________________________________________
+ // A new component window doesn't know anything about current active/focus states.
+ // Set this information on it!
+ if (
+ (bHadFocus ) &&
+ (xComponentWindow.is())
+ )
+ {
+ xComponentWindow->setFocus();
+ }
+
+ // If it was a new component window - we must resize it to fill out
+ // our container window.
+ implts_resizeComponentWindow();
+ // New component should change our current icon ...
+ implts_setIconOnWindow();
+ // OK - start listening on new window again - or do nothing if it is an empty one.
+ implts_startWindowListening();
+
+ /* SAFE { */
+ aWriteLock.lock();
+ impl_checkMenuCloser();
+ aWriteLock.unlock();
+ /* } SAFE */
+
+ return sal_True;
+}
+
+/*-****************************************************************************************************//**
+ @short returns current set component window
+ @descr Frames are used to display components. The actual displayed component is
+ held by the m_xComponentWindow property. If the component implements only a
+ XComponent interface, the communication between the frame and the
+ component is very restricted. Better integration is achievable through a
+ XController interface.
+ If the component wants other objects to be able to get information about its
+ ResourceDescriptor it has to implement a XModel interface.
+ This frame is the owner of the component window.
+
+ @seealso method setComponent()
+
+ @param -
+ @return css::uno::Reference to current set component window.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::awt::XWindow > SAL_CALL Frame::getComponentWindow() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ return m_xComponentWindow;
+}
+
+/*-****************************************************************************************************//**
+ @short returns current set controller
+ @descr Frames are used to display components. The actual displayed component is
+ held by the m_xComponentWindow property. If the component implements only a
+ XComponent interface, the communication between the frame and the
+ component is very restricted. Better integration is achievable through a
+ XController interface.
+ If the component wants other objects to be able to get information about its
+ ResourceDescriptor it has to implement a XModel interface.
+ This frame is the owner of the component window.
+
+ @seealso method setComponent()
+
+ @param -
+ @return css::uno::Reference to current set controller.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XController > SAL_CALL Frame::getController() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // It seems to be unavoidable that disposed frames allow to ask for a Controller (#111452)
+ // Register transaction and reject wrong calls.
+ // TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ return m_xController;
+}
+
+/*-****************************************************************************************************//**
+ @short add/remove listener for activate/deactivate/contextChanged events
+ @descr -
+
+ @seealso method activate()
+ @seealso method deactivate()
+ @seealso method contextChanged()
+
+ @param "xListener" reference to your listener object
+ @return -
+
+ @onerror Listener is ignored.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_addFrameActionListener( xListener ), "Frame::addFrameActionListener()", "Invalid parameter detected." )
+ // Listener container is threadsafe by himself ... but we must look for rejected calls!
+ // Our OMenuDispatch-helper (is a member of ODispatchProvider!) is create at startup of this frame BEFORE initialize!
+ // => soft exceptions!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ m_aListenerContainer.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XFrameActionListener >*)NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_removeFrameActionListener( xListener ), "Frame::removeFrameActionListener()", "Invalid parameter detected." )
+ // Listener container is threadsafe by himself ... but we must look for rejected calls after disposing!
+ // But we must work with E_SOFTEXCEPTIONS ... because sometimes we are called from our listeners
+ // during dispose! Our work mode is E_BEFORECLOSE then ... and E_HARDEXCEPTIONS whould throw a DisposedException.
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ m_aListenerContainer.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XFrameActionListener >*)NULL ), xListener );
+}
+
+/*-****************************************************************************************************//**
+ @short support two way mechanism to release a frame
+ @descr This method ask internal component (controller) if he accept this close request.
+ In case of <TRUE/> nothing will be happen (from point of caller of this close method).
+ In case of <FALSE/> a CloseVetoException is thrown. After such exception given parameter
+ <var>bDeliverOwnerShip</var> regulate which will be the new owner of this instance.
+
+ @attention It's the replacement for XTask::close() which is marked as obsolete method.
+
+ @param bDeliverOwnerShip
+ If parameter is set to <FALSE/> the original caller will be the owner after thrown
+ veto exception and must try to close this frame at later time again. Otherwhise the
+ source of throwed exception is the right one. May it will be the frame himself.
+
+ @thrown CloseVetoException
+ if any internal things willn't be closed
+
+ @threadsafe yes
+ @modified 06.05.2002 08:33, as96863
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::close( sal_Bool bDeliverOwnerShip ) throw( css::util::CloseVetoException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // At the end of this method may we must dispose ourself ...
+ // and may nobody from outside hold a reference to us ...
+ // then it's a good idea to do that by ourself.
+ css::uno::Reference< css::uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
+
+ // Check any close listener before we look for currently running internal processes.
+ // Because if a listener disagree with this close() request - we hace time to finish this
+ // internal operations too ...
+ // Note: container is threadsafe himself.
+ css::lang::EventObject aSource (static_cast< ::cppu::OWeakObject*>(this));
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >*) NULL ) );
+ if (pContainer!=NULL)
+ {
+ ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ ((css::util::XCloseListener*)pIterator.next())->queryClosing( aSource, bDeliverOwnerShip );
+ }
+ catch( css::uno::RuntimeException& )
+ {
+ pIterator.remove();
+ }
+ }
+ }
+
+ // Ok - no listener disagreed with this close() request
+ // check if this frame is used for any load process currently
+ if (isActionLocked())
+ {
+ if (bDeliverOwnerShip)
+ {
+ /* SAFE */
+ WriteGuard aWriteLock( m_aLock );
+ m_bSelfClose = sal_True;
+ aWriteLock.unlock();
+ /* SAFE */
+ }
+
+ throw css::util::CloseVetoException(DECLARE_ASCII("Frame in use for loading document ..."),static_cast< ::cppu::OWeakObject*>(this));
+ }
+
+ if ( ! setComponent(NULL,NULL) )
+ throw css::util::CloseVetoException(DECLARE_ASCII("Component couldn't be deattached ..."),static_cast< ::cppu::OWeakObject*>(this));
+
+ // If closing is allowed ... inform all istener and dispose this frame!
+ pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >*) NULL ) );
+ if (pContainer!=NULL)
+ {
+ ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ ((css::util::XCloseListener*)pIterator.next())->notifyClosing( aSource );
+ }
+ catch( css::uno::RuntimeException& )
+ {
+ pIterator.remove();
+ }
+ }
+ }
+
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_bIsHidden = sal_True;
+ aWriteLock.unlock();
+ /* } SAFE */
+ impl_checkMenuCloser();
+
+ // Attention: We must release our own registered transaction here. Otherwhise following dispose() call
+ // wait for us too ....
+ aTransaction.stop();
+ dispose();
+}
+
+/*-****************************************************************************************************//**
+ @short be a listener for close events!
+ @descr Adds/remove a CloseListener at this frame instance. If the close() method is called on
+ this object, the such listener are informed and can disagree with that by throwing
+ a CloseVetoException.
+
+ @seealso Frame::close()
+
+ @param xListener
+ reference to your listener object
+
+ @onerror Listener is ignored.
+
+ @threadsafe yes
+ @modified 06.05.2002 10:03, as96863
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::addCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener ) throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ // We doesn't need any lock here ...
+ // Container lives if we live and is threadsafe by himself.
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >* ) NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::removeCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener ) throw (css::uno::RuntimeException)
+{
+ // Use soft exception mode - moslty this method is called during disposing of this frame ...
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+ // We doesn't need any lock here ...
+ // Container lives if we live and is threadsafe by himself.
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >* ) NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+::rtl::OUString SAL_CALL Frame::getTitle()
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ return xTitle->getTitle();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::setTitle( const ::rtl::OUString& sTitle )
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ xTitle->setTitle(sTitle);
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::addTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ xTitle->addTitleChangeListener(xListener);
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::removeTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener )
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ xTitle->removeTitleChangeListener(xListener);
+}
+
+/*-****************************************************************************************************/
+void Frame::implts_forgetSubFrames()
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::container::XIndexAccess > xContainer(m_xFramesHelper, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ sal_Int32 c = xContainer->getCount();
+ sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XFrame > xFrame;
+ xContainer->getByIndex(i) >>= xFrame;
+ if (xFrame.is())
+ xFrame->setCreator(css::uno::Reference< css::frame::XFramesSupplier >());
+ }
+ catch(const css::uno::Exception&)
+ {
+ // Ignore errors here.
+ // Nobody can guarantee a stable index in multi threaded environments .-)
+ }
+ }
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xFramesHelper.clear(); // clear uno reference
+ m_aChildFrameContainer.clear(); // clear container content
+ aWriteLock.unlock();
+ // <- SAFE
+}
+
+/*-****************************************************************************************************//**
+ @short destroy instance
+ @descr The owner of this object calles the dispose method if the object
+ should be destroyed. All other objects and components, that are registered
+ as an EventListener are forced to release their references to this object.
+ Furthermore this frame is removed from its parent frame container to release
+ this reference. The reference attributes are disposed and released also.
+
+ @attention Look for globale description at beginning of file too!
+ (DisposedException, FairRWLock ..., initialize, dispose)
+
+ @seealso method initialize()
+ @seealso baseclass FairRWLockBase!
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::dispose() throw( css::uno::RuntimeException )
+{
+ // We should hold a reference to ourself ...
+ // because our owner dispose us and release our reference ...
+ // May be we will die before we could finish this method ...
+ css::uno::Reference< css::frame::XFrame > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+
+ LOG_DISPOSEEVENT( "Frame", sName )
+
+ // First operation should be ... "stopp all listening for window events on our container window".
+ // These events are superflous but can make trouble!
+ // We will die, die and die ...
+ implts_stopWindowListening();
+
+ // Send message to all listener and forget her references.
+ css::lang::EventObject aEvent( xThis );
+ m_aListenerContainer.disposeAndClear( aEvent );
+
+ // set "end of live" for our property set helper
+ impl_disablePropertySet();
+
+ // interception/dispatch chain must be destructed explicitly
+ // Otherwhise some dispatches and/or interception objects wont die.
+ css::uno::Reference< css::lang::XEventListener > xDispatchHelper(m_xDispatchHelper, css::uno::UNO_QUERY_THROW);
+ xDispatchHelper->disposing(aEvent);
+ xDispatchHelper.clear();
+
+ // Disable this instance for further work.
+ // This will wait for all current running ones ...
+ // and reject all further requests!
+ m_aTransactionManager.setWorkingMode( E_BEFORECLOSE );
+
+ // Don't show any dialogs, errors or something else any more!
+ // If somewhere called dispose() whitout close() before - normaly no dialogs
+ // should exist. Otherwhise it's the problem of the outside caller.
+ // Note:
+ // (a) Do it after stopWindowListening(). May that force some active/deactive
+ // notifications which we doesn't need here realy.
+ // (b) Don't forget to save the old value of IsDialogCancelEnabled() to
+ // restore it afterwards. We cannot call EnableDialogCancel( sal_False )
+ // as we would kill the headless mode!
+ sal_Bool bCancelDialogs( Application::IsDialogCancelEnabled() );
+ Application::EnableDialogCancel( sal_True );
+
+ // We should be alone for ever and further dispose calls are rejected by lines before ...
+ // I hope it :-)
+
+ // Free references of our frame tree.
+ // Force parent container to forget this frame too ...
+ // ( It's contained in m_xParent and so no css::lang::XEventListener for m_xParent! )
+ // It's important to do that before we free some other internal structures.
+ // Because if our parent gets an activate and found us as last possible active frame
+ // he try to deactivate us ... and we run into some trouble (DisposedExceptions!).
+ if( m_xParent.is() == sal_True )
+ {
+ m_xParent->getFrames()->remove( xThis );
+ m_xParent = css::uno::Reference< css::frame::XFramesSupplier >();
+ }
+
+ /* } SAFE */
+ // Forget our internal component and her window first.
+ // So we can release our container window later without problems.
+ // Because this container window is the parent of the component window ...
+ // Note: Dispose it hard - because suspending must be done inside close() call!
+ // But try to dispose the controller first befor you destroy the window.
+ // Because the window is used by the controller too ...
+ if (m_xController.is())
+ {
+ css::uno::Reference< css::lang::XComponent > xDisposable( m_xController, css::uno::UNO_QUERY );
+ if (xDisposable.is())
+ xDisposable->dispose();
+ }
+
+ if (m_xComponentWindow.is())
+ {
+ css::uno::Reference< css::lang::XComponent > xDisposable( m_xComponentWindow, css::uno::UNO_QUERY );
+ if (xDisposable.is())
+ xDisposable->dispose();
+ }
+
+ impl_checkMenuCloser();
+
+ impl_disposeContainerWindow( m_xContainerWindow );
+
+ /*ATTENTION
+ Clear container after successful removing from parent container ...
+ because our parent could be the desktop which stand in dispose too!
+ If we have already cleared our own container we lost our child before this could be
+ remove himself at this instance ...
+ Release m_xFramesHelper after that ... it's the same problem between parent and child!
+ "m_xParent->getFrames()->remove( xThis );" needs this helper ...
+ Otherwise we get a null reference and could finish removing successfuly.
+ => You see: Order of calling operations is important!!!
+ */
+ implts_forgetSubFrames();
+
+ // Release some other references.
+ // This calls should be easy ... I hope it :-)
+ m_xDispatchHelper.clear();
+ m_xFactory.clear();
+ m_xDropTargetListener.clear();
+ m_xDispatchRecorderSupplier.clear();
+ m_xLayoutManager.clear();
+ m_xIndicatorFactoryHelper.clear();
+
+ // It's important to set default values here!
+ // If may be later somewhere change the disposed-behaviour of this implementation
+ // and doesn't throw any DisposedExceptions we must guarantee best matching default values ...
+ m_eActiveState = E_INACTIVE;
+ m_sName = ::rtl::OUString();
+ m_bIsFrameTop = sal_False;
+ m_bConnected = sal_False;
+ m_nExternalLockCount = 0;
+ m_bSelfClose = sal_False;
+ m_bIsHidden = sal_True;
+
+ // Disable this instance for further working realy!
+ m_aTransactionManager.setWorkingMode( E_CLOSE );
+
+ // Don't forget it restore old value -
+ // otherwhise no dialogs can be shown anymore in other frames.
+ Application::EnableDialogCancel( bCancelDialogs );
+}
+
+/*-****************************************************************************************************//**
+ @short Be a listener for dispose events!
+ @descr Adds/remove an EventListener to this object. If the dispose method is called on
+ this object, the disposing method of the listener is called.
+
+ @seealso -
+
+ @param "xListener" reference to your listener object.
+ @return -
+
+ @onerror Listener is ignored.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_addEventListener( xListener ), "Frame::addEventListener()", "Invalid parameter detected." )
+ // Look for rejected calls only!
+ // Container is threadsafe.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_removeEventListener( xListener ), "Frame::removeEventListener()", "Invalid parameter detected." )
+ // Look for rejected calls only!
+ // Container is threadsafe.
+ // Use E_SOFTEXCEPTIONS to allow removing listeners during dispose call!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener );
+}
+
+/*-****************************************************************************************************//**
+ @short create new status indicator
+ @descr Use returned status indicator to show progresses and some text informations.
+ All created objects share the same dialog! Only the last one can show his information.
+
+ @seealso class StatusIndicatorFactory
+ @seealso class StatusIndicator
+
+ @param -
+ @return A reference to created object.
+
+ @onerror We return a null reference.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::task::XStatusIndicator > SAL_CALL Frame::createStatusIndicator() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+ // Look for rejected calls!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ // Make snapshot of neccessary member and define default return value.
+ css::uno::Reference< css::task::XStatusIndicator > xExternal(m_xIndicatorInterception.get(), css::uno::UNO_QUERY);
+ css::uno::Reference< css::task::XStatusIndicatorFactory > xFactory = m_xIndicatorFactoryHelper;
+
+ aReadLock.unlock();
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+
+ // Was set from outside to intercept any progress activities!
+ if (xExternal.is())
+ return xExternal;
+
+ // Or use our own factory as fallback, to create such progress.
+ if (xFactory.is())
+ return xFactory->createStatusIndicator();
+
+ return css::uno::Reference< css::task::XStatusIndicator >();
+}
+
+/*-****************************************************************************************************//**
+ @short search for target to load URL
+ @descr This method searches for a dispatch for the specified DispatchDescriptor.
+ The FrameSearchFlags and the FrameName of the DispatchDescriptor are
+ treated as described for findFrame.
+
+ @seealso method findFrame()
+ @seealso method queryDispatches()
+ @seealso method set/getName()
+ @seealso class TargetFinder
+
+ @param "aURL" , URL for loading
+ @param "sTargetFrameName" , name of target frame
+ @param "nSearchFlags" , additional flags to regulate search if sTargetFrameName isn't clear
+ @return css::uno::Reference to dispatch handler.
+
+ @onerror A null reference is returned.
+*//*-*****************************************************************************************************/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL Frame::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ const char UNO_PROTOCOL[] = ".uno:";
+
+ // Don't check incoming parameter here! Our helper do it for us and it isn't a good idea to do it more then ones!
+ // But look for rejected calls!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
+ // in our hash map. All other protocols are stored with the protocol part.
+ String aCommand( aURL.Main );
+ if ( aURL.Protocol.equalsIgnoreAsciiCaseAsciiL( UNO_PROTOCOL, sizeof( UNO_PROTOCOL )-1 ))
+ aCommand = aURL.Path;
+
+ // Make hash_map lookup if the current URL is in the disabled list
+ if ( m_aCommandOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aCommand ) )
+ return css::uno::Reference< css::frame::XDispatch >();
+ else
+ {
+ // We use a helper to support these interface and an interceptor mechanism.
+ // Our helper is threadsafe by himself!
+ return m_xDispatchHelper->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short handle more then ones dispatches at same call
+ @descr Returns a sequence of dispatches. For details see the queryDispatch method.
+ For failed dispatches we return empty items in list!
+
+ @seealso method queryDispatch()
+
+ @param "lDescriptor" list of dispatch arguments for queryDispatch()!
+ @return List of dispatch references. Some elements can be NULL!
+
+ @onerror An empty list is returned.
+*//*-*****************************************************************************************************/
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Frame::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
+{
+ // Don't check incoming parameter here! Our helper do it for us and it isn't a good idea to do it more then ones!
+ // But look for rejected calls!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // We use a helper to support these interface and an interceptor mechanism.
+ // Our helper is threadsafe by himself!
+ return m_xDispatchHelper->queryDispatches( lDescriptor );
+}
+
+/*-****************************************************************************************************//**
+ @short register/unregister interceptor for dispatch calls
+ @descr If you whish to handle some dispatches by himself ... you should be
+ an interceptor for it. Please see class OInterceptionHelper for further informations.
+
+ @seealso class OInterceptionHelper
+
+ @param "xInterceptor", reference to your interceptor implementation.
+ @return -
+
+ @onerror Interceptor is ignored.
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor ) throw( css::uno::RuntimeException )
+{
+ // We use a helper to support these interface and an interceptor mechanism.
+ // This helper is threadsafe himself and check incoming parameter too.
+ // I think we don't need any lock here!
+ // But we must look for rejected calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::releaseDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor ) throw( css::uno::RuntimeException )
+{
+ // We use a helper to support these interface and an interceptor mechanism.
+ // This helper is threadsafe himself and check incoming parameter too.
+ // I think we don't need any lock here!
+ // But we must look for rejected calls ...
+ // Sometimes we are called during our dispose() method ... => soft exceptions!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
+}
+
+/*-****************************************************************************************************//**
+ @short provides information about all possible dispatch functions
+ inside the currnt frame environment
+*//*-*****************************************************************************************************/
+css::uno::Sequence< sal_Int16 > SAL_CALL Frame::getSupportedCommandGroups()
+ throw(css::uno::RuntimeException)
+{
+ return m_xDispatchInfoHelper->getSupportedCommandGroups();
+}
+
+//*****************************************************************************************************************
+css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL Frame::getConfigurableDispatchInformation(sal_Int16 nCommandGroup)
+ throw(css::uno::RuntimeException)
+{
+ return m_xDispatchInfoHelper->getConfigurableDispatchInformation(nCommandGroup);
+}
+
+/*-****************************************************************************************************//**
+ @short notifications for window events
+ @descr We are a listener on our container window to forward it to our component window.
+
+ @seealso method setComponent()
+ @seealso member m_xContainerWindow
+ @seealso member m_xComponentWindow
+
+ @param "aEvent" describe source of detected event
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::windowResized( const css::awt::WindowEvent&
+#if OSL_DEBUG_LEVEL > 0
+aEvent
+#endif
+) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_windowResized( aEvent ), "Frame::windowResized()", "Invalid parameter detected." )
+ // Look for rejected calls.
+ // Part of dispose-mechanism => soft exceptions
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ // Impl-method is threadsafe!
+ // If we have a current component window - we must resize it!
+ implts_resizeComponentWindow();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::focusGained( const css::awt::FocusEvent&
+#if OSL_DEBUG_LEVEL > 0
+aEvent
+#endif
+) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_focusGained( aEvent ), "Frame::focusGained()", "Invalid parameter detected." )
+ // Look for rejected calls.
+ // Part of dispose() mechanism ... => soft exceptions!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+ // Make snapshot of member!
+ css::uno::Reference< css::awt::XWindow > xComponentWindow = m_xComponentWindow;
+ aReadLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ if( xComponentWindow.is() == sal_True )
+ {
+ xComponentWindow->setFocus();
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short notifications for window events
+ @descr We are a listener on our container window to forward it to our component window ...
+ but a XTopWindowListener we are only if we are a top frame!
+
+ @seealso method setComponent()
+ @seealso member m_xContainerWindow
+ @seealso member m_xComponentWindow
+
+ @param "aEvent" describe source of detected event
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::windowActivated( const css::lang::EventObject&
+#if OSL_DEBUG_LEVEL > 0
+aEvent
+#endif
+) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_windowActivated( aEvent ), "Frame::windowActivated()", "Invalid parameter detected." )
+ // Look for rejected calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+ // Make snapshot of member!
+ EActiveState eState = m_eActiveState;
+ aReadLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Activate the new active path from here to top.
+ if( eState == E_INACTIVE )
+ {
+// CheckMenuCloser_Impl();
+ setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
+ activate();
+ }
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::windowDeactivated( const css::lang::EventObject&
+#if OSL_DEBUG_LEVEL > 0
+aEvent
+#endif
+) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_windowDeactivated( aEvent ), "Frame::windowDeactivated()", "Invalid parameter detected." )
+ // Look for rejected calls.
+ // Sometimes called during dispose() => soft exceptions
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+
+ css::uno::Reference< css::frame::XFrame > xParent ( m_xParent, css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
+ EActiveState eActiveState = m_eActiveState ;
+
+ aReadLock.unlock();
+
+ if( eActiveState != E_INACTIVE )
+ {
+ // Deactivation is always done implicitely by activation of another frame.
+ // Only if no activation is done, deactivations have to be processed if the activated window
+ // is a parent window of the last active Window!
+ ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+// CheckMenuCloser_Impl();
+ Window* pFocusWindow = Application::GetFocusWindow();
+ if (
+ ( xContainerWindow.is() == sal_True ) &&
+ ( xParent.is() == sal_True ) &&
+ ( (css::uno::Reference< css::frame::XDesktop >( xParent, css::uno::UNO_QUERY )).is() == sal_False )
+ )
+ {
+ css::uno::Reference< css::awt::XWindow > xParentWindow = xParent->getContainerWindow() ;
+ Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
+ //#i70261#: dialogs opend from an OLE object will cause a deactivate on the frame of the OLE object
+ // on Solaris/Linux at that time pFocusWindow is still NULL because the focus handling is different; right after
+ // the deactivation the focus will be set into the dialog!
+ // currently I see no case where a sub frame could get a deactivate with pFocusWindow being NULL permanently
+ // so for now this case is omitted from handled deactivations
+ if( pFocusWindow && pParentWindow->IsChild( pFocusWindow ) )
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
+ if( xSupplier.is() == sal_True )
+ {
+ aSolarGuard.clear();
+ xSupplier->setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
+ }
+ }
+ }
+ }
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::windowClosing( const css::lang::EventObject& ) throw( css::uno::RuntimeException )
+{
+ /* #i62088#
+ Some interceptor objects intercept our "internaly asynchronoues implemented" dispatch call.
+ And they close this frame directly (means synchronous then).
+ Means: Frame::windowClosing()->Frame::close()
+ In such situation its not a good idea to hold this transaction count alive .-)
+ */
+ {
+ // Look for rejected calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ // deactivate this frame ...
+ deactivate();
+ }
+
+ // ... and try to close it
+ // But do it asynchron inside the main thread.
+ // VCL has no fun to do such things outside his main thread :-(
+ // Note: The used dispatch make it asynchronous for us .-)
+
+ /*ATTENTION!
+ Don't try to suspend the controller here! Because it's done inside used dispatch().
+ Otherwhise the dialog "would you save your changes?" will be shown more then once ...
+ */
+
+ /* SAFE */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ /* SAFE */
+
+ css::util::URL aURL;
+ aURL.Complete = DECLARE_ASCII(".uno:CloseFrame");
+ css::uno::Reference< css::util::XURLTransformer > xParser(xFactory->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
+ xParser->parseStrict(aURL);
+
+ css::uno::Reference< css::frame::XDispatch > xCloser = queryDispatch(aURL, SPECIALTARGET_SELF, 0);
+ if (xCloser.is())
+ xCloser->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >());
+
+ // Attention: If this dispatch works synchronous ... and full fill its job ...
+ // this line of code will never be reached ...
+ // Or if it will be reached it will be for sure that all your member are gone .-)
+}
+
+/*-****************************************************************************************************//**
+ @short react for a show event for the internal container window
+ @descr Normaly we doesn't need this information realy. But we can use it to
+ implement the special feature "trigger first visible task".
+
+ Algorithm: - first we have to check if we are a top (task) frame
+ It's not enough to be a top frame! Because we MUST have the desktop as parent.
+ But frames without a parent are top too. So it's not possible to check isTop() here!
+ We have to look for the type of our parent.
+ - if we are a task frame, then we have to check if we are the first one.
+ We use a static variable to do so. They will be reset to afterwards be shure
+ that further calls of this method doesn't do anything then.
+ - Then we have to trigger the right event string on the global job executor.
+
+ @seealso css::task::JobExecutor
+
+ @param aEvent
+ describes the source of this event
+ We are not interested on this information. We are interested on the visible state only.
+
+ @threadsafe yes
+ @modified 31.07.2002 07:56, as96863
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::windowShown( const css::lang::EventObject& ) throw(css::uno::RuntimeException)
+{
+ static sal_Bool bFirstVisibleTask = sal_True;
+
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XDesktop > xDesktopCheck( m_xParent, css::uno::UNO_QUERY );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ m_bIsHidden = sal_False;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ impl_checkMenuCloser();
+
+ if (xDesktopCheck.is())
+ {
+ /* STATIC SAFE { */
+ WriteGuard aStaticWriteLock( LockHelper::getGlobalLock() );
+ sal_Bool bMustBeTriggered = bFirstVisibleTask;
+ bFirstVisibleTask = sal_False;
+ aStaticWriteLock.unlock();
+ /* } STATIC SAFE */
+
+ if (bMustBeTriggered)
+ {
+ css::uno::Reference< css::task::XJobExecutor > xExecutor( xFactory->createInstance( SERVICENAME_JOBEXECUTOR ), css::uno::UNO_QUERY );
+ if (xExecutor.is())
+ {
+ xExecutor->trigger( DECLARE_ASCII("onFirstVisibleTask") );
+ }
+ }
+ }
+}
+
+void SAL_CALL Frame::windowHidden( const css::lang::EventObject& ) throw(css::uno::RuntimeException)
+{
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+ m_bIsHidden = sal_True;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ impl_checkMenuCloser();
+}
+
+/*-****************************************************************************************************//**
+ @short called by dispose of our windows!
+ @descr This object is forced to release all references to the interfaces given
+ by the parameter source. We are a listener at our container window and
+ should listen for his diposing.
+
+ @seealso XWindowListener
+ @seealso XTopWindowListener
+ @seealso XFocusListener
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void SAL_CALL Frame::disposing( const css::lang::EventObject& aEvent ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Check incoming parameter.
+ LOG_ASSERT2( implcp_disposing( aEvent ), "Frame::disposing()", "Invalid parameter detected." )
+ // Look for rejected calls.
+ // May be we are called during releasing our windows in our in dispose call!? => soft exceptions
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+
+ if( aEvent.Source == m_xContainerWindow )
+ {
+ // NECCESSARY: Impl-method is threadsafe by himself!
+ aWriteLock.unlock();
+ implts_stopWindowListening();
+ aWriteLock.lock();
+ m_xContainerWindow = css::uno::Reference< css::awt::XWindow >();
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface com.sun.star.document.XActionLockable
+ @short implement locking of frame/task from outside
+ @descr Sometimes we have problems to decide if closing of task is allowed. Because; frame/task
+ could be used for pending loading jobs. So you can lock this object from outside and
+ prevent instance against closing during using! But - don't do it in a wrong or expensive manner.
+ Otherwise task couldn't die anymore!!!
+
+ @seealso interface XActionLockable
+ @seeelso method BaseDispatcher::implts_loadIt()
+ @seeelso method Desktop::loadComponentFromURL()
+
+ @param -
+ @return true if frame/task is locked
+ false otherwise
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+sal_Bool SAL_CALL Frame::isActionLocked() throw( css::uno::RuntimeException )
+{
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ReadGuard aReadLock( m_aLock );
+ return( m_nExternalLockCount!=0);
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::addActionLock() throw( css::uno::RuntimeException )
+{
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ ++m_nExternalLockCount;
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::removeActionLock() throw( css::uno::RuntimeException )
+{
+ // Register no transaction here! Otherwhise we wait for ever inside possible
+ // implts_checkSuicide()/dispose() request ...
+
+ /* SAFE AREA */{
+ WriteGuard aWriteLock( m_aLock );
+ LOG_ASSERT2( m_nExternalLockCount<=0, "Frame::removeActionLock()", "Frame isn't locked! Possible multithreading problem detected." )
+ --m_nExternalLockCount;
+ }/* SAFE */
+
+ implts_checkSuicide();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::setActionLocks( sal_Int16 nLock ) throw( css::uno::RuntimeException )
+{
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ // Attention: If somewhere called resetActionLocks() before and get e.g. 5 locks ...
+ // and tried to set these 5 ones here after his operations ...
+ // we can't ignore setted requests during these two calls!
+ // So we must add(!) these 5 locks here.
+ m_nExternalLockCount = m_nExternalLockCount + nLock;
+}
+
+//*****************************************************************************************************************
+sal_Int16 SAL_CALL Frame::resetActionLocks() throw( css::uno::RuntimeException )
+{
+ // Register no transaction here! Otherwhise we wait for ever inside possible
+ // implts_checkSuicide()/dispose() request ...
+
+ sal_Int16 nCurrentLocks = 0;
+ /* SAFE */{
+ WriteGuard aWriteLock( m_aLock );
+ nCurrentLocks = m_nExternalLockCount;
+ m_nExternalLockCount = 0;
+ }/* SAFE */
+
+ // Attention:
+ // external lock count is 0 here every time ... but if
+ // member m_bSelfClose is set to true too .... we call our own close()/dispose().
+ // See close() for further informations
+ implts_checkSuicide();
+
+ return nCurrentLocks;
+}
+
+//*****************************************************************************************************************
+void Frame::impl_initializePropInfo()
+{
+ impl_setPropertyChangeBroadcaster(static_cast< css::frame::XFrame* >(this));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ FRAME_PROPNAME_DISPATCHRECORDERSUPPLIER,
+ FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER,
+ ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL),
+ css::beans::PropertyAttribute::TRANSIENT));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ FRAME_PROPNAME_INDICATORINTERCEPTION,
+ FRAME_PROPHANDLE_INDICATORINTERCEPTION,
+ ::getCppuType((const css::uno::Reference< css::task::XStatusIndicator >*)NULL),
+ css::beans::PropertyAttribute::TRANSIENT));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ FRAME_PROPNAME_ISHIDDEN,
+ FRAME_PROPHANDLE_ISHIDDEN,
+ ::getBooleanCppuType(),
+ css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ FRAME_PROPNAME_LAYOUTMANAGER,
+ FRAME_PROPHANDLE_LAYOUTMANAGER,
+ ::getCppuType((const css::uno::Reference< ::com::sun::star::frame::XLayoutManager >*)NULL),
+ css::beans::PropertyAttribute::TRANSIENT));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ FRAME_PROPNAME_TITLE,
+ FRAME_PROPHANDLE_TITLE,
+ ::getCppuType((const ::rtl::OUString*)NULL),
+ css::beans::PropertyAttribute::TRANSIENT));
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Frame::impl_setPropertyValue(const ::rtl::OUString& /*sProperty*/,
+ sal_Int32 nHandle ,
+ const css::uno::Any& aValue )
+
+{
+ static ::rtl::OUString MATERIALPROP_TITLE = ::rtl::OUString::createFromAscii("title");
+
+ /* There is no need to lock any mutex here. Because we share the
+ solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-)
+ see ctor of PropertySetHelper for further informations.
+ */
+
+ /* Attention: You can use nHandle only, if you are sure that all supported
+ properties has an unique handle. That must be guaranteed
+ inside method impl_initializePropInfo()!
+ */
+ switch (nHandle)
+ {
+ case FRAME_PROPHANDLE_TITLE :
+ {
+ ::rtl::OUString sExternalTitle;
+ aValue >>= sExternalTitle;
+ setTitle (sExternalTitle);
+ }
+ break;
+
+ case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
+ aValue >>= m_xDispatchRecorderSupplier;
+ break;
+
+ case FRAME_PROPHANDLE_LAYOUTMANAGER :
+ {
+ css::uno::Reference< css::frame::XLayoutManager > xOldLayoutManager = m_xLayoutManager;
+ css::uno::Reference< css::frame::XLayoutManager > xNewLayoutManager;
+ aValue >>= xNewLayoutManager;
+
+ if (xOldLayoutManager != xNewLayoutManager)
+ {
+ m_xLayoutManager = xNewLayoutManager;
+ if (xOldLayoutManager.is())
+ lcl_disableLayoutManager(xOldLayoutManager, this);
+ if (xNewLayoutManager.is())
+ lcl_enableLayoutManager(xNewLayoutManager, this);
+ }
+ }
+ break;
+
+ case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
+ {
+ css::uno::Reference< css::task::XStatusIndicator > xProgress;
+ aValue >>= xProgress;
+ m_xIndicatorInterception = xProgress;
+ }
+ break;
+
+ #ifdef ENABLE_WARNINGS
+ default :
+ LOG_WARNING( "Frame::setFastPropertyValue_NoBroadcast()", "Invalid handle detected!" )
+ break;
+ #endif
+ }
+}
+
+//*****************************************************************************************************************
+css::uno::Any SAL_CALL Frame::impl_getPropertyValue(const ::rtl::OUString& /*sProperty*/,
+ sal_Int32 nHandle )
+{
+ /* There is no need to lock any mutex here. Because we share the
+ solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-)
+ see ctor of PropertySetHelper for further informations.
+ */
+
+ /* Attention: You can use nHandle only, if you are sure that all supported
+ properties has an unique handle. That must be guaranteed
+ inside method impl_initializePropInfo()!
+ */
+ css::uno::Any aValue;
+ switch (nHandle)
+ {
+ case FRAME_PROPHANDLE_TITLE :
+ aValue <<= getTitle ();
+ break;
+
+ case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
+ aValue <<= m_xDispatchRecorderSupplier;
+ break;
+
+ case FRAME_PROPHANDLE_ISHIDDEN :
+ aValue <<= m_bIsHidden;
+ break;
+
+ case FRAME_PROPHANDLE_LAYOUTMANAGER :
+ aValue <<= m_xLayoutManager;
+ break;
+
+ case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
+ {
+ css::uno::Reference< css::task::XStatusIndicator > xProgress(m_xIndicatorInterception.get(), css::uno::UNO_QUERY);
+ aValue = css::uno::makeAny(xProgress);
+ }
+ break;
+
+ #ifdef ENABLE_WARNINGS
+ default :
+ LOG_WARNING( "Frame::getFastPropertyValue()", "Invalid handle detected!" )
+ break;
+ #endif
+ }
+
+ return aValue;
+}
+
+/*-****************************************************************************************************//**
+ @short dispose old container window and forget his reference
+ @descr Sometimes we must repair our "modal dialog parent mechanism" too!
+
+ @seealso -
+
+ @param "xWindow", reference to old container window to dispose it
+ @return An empty reference.
+
+ @onerror -
+ @threadsafe NO!
+*//*-*****************************************************************************************************/
+void Frame::impl_disposeContainerWindow( css::uno::Reference< css::awt::XWindow >& xWindow )
+{
+ if( xWindow.is() == sal_True )
+ {
+ xWindow->setVisible( sal_False );
+ // All VclComponents are XComponents; so call dispose before discarding
+ // a css::uno::Reference< XVclComponent >, because this frame is the owner of the window
+ xWindow->dispose();
+ xWindow = css::uno::Reference< css::awt::XWindow >();
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short send frame action event to our listener
+ @descr This method is threadsafe AND can be called by our dispose method too!
+
+ @seealso -
+
+ @param "aAction", describe the event for sending
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void Frame::implts_sendFrameActionEvent( const css::frame::FrameAction& aAction )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Sometimes used by dispose() => soft exceptions!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ // Log informations about order of events to file!
+ // (only activated in debug version!)
+ LOG_FRAMEACTIONEVENT( "Frame", m_sName, aAction )
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ // Send css::frame::FrameAction event to all listener.
+ // Get container for right listener.
+ // FOLLOW LINES ARE THREADSAFE!!!
+ // ( OInterfaceContainerHelper is synchronized with m_aListenerContainer! )
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XFrameActionListener >*) NULL ) );
+
+ if( pContainer != NULL )
+ {
+ // Build action event.
+ css::frame::FrameActionEvent aFrameActionEvent( static_cast< ::cppu::OWeakObject* >(this), this, aAction );
+
+ // Get iterator for access to listener.
+ ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
+ // Send message to all listener.
+ while( aIterator.hasMoreElements() == sal_True )
+ {
+ try
+ {
+ ((css::frame::XFrameActionListener*)aIterator.next())->frameAction( aFrameActionEvent );
+ }
+ catch( css::uno::RuntimeException& )
+ {
+ aIterator.remove();
+ }
+ }
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short helper to resize our component window
+ @descr A frame contains 2 windows - a container ~ and a component window.
+ This method resize inner component window to full size of outer container window.
+ This method is threadsafe AND can be called by our dispose method too!
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*****************************************************************************************************/
+void Frame::implts_resizeComponentWindow()
+{
+ // usually the LayoutManager does the resizing
+ // in case there is no LayoutManager resizing has to be done here
+ if ( !m_xLayoutManager.is() )
+ {
+ css::uno::Reference< css::awt::XWindow > xComponentWindow( getComponentWindow() );
+ if( xComponentWindow.is() == sal_True )
+ {
+ css::uno::Reference< css::awt::XDevice > xDevice( getContainerWindow(), css::uno::UNO_QUERY );
+
+ // Convert relativ size to output size.
+ css::awt::Rectangle aRectangle = getContainerWindow()->getPosSize();
+ css::awt::DeviceInfo aInfo = xDevice->getInfo();
+ css::awt::Size aSize ( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
+ aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
+
+ // Resize our component window.
+ xComponentWindow->setPosSize( 0, 0, aSize.Width, aSize.Height, css::awt::PosSize::POSSIZE );
+ }
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short helper to set icon on our container window (if it is a system window!)
+ @descr We use our internal set controller (if it exist) to specify which factory he represanted.
+ These information can be used to find right icon. But our controller can say it us directly
+ too ... we should ask his optional property set first ...
+
+ @seealso method Window::SetIcon()
+
+ @param -
+ @return -
+
+ @onerror We do nothing.
+*//*-*****************************************************************************************************/
+void Frame::implts_setIconOnWindow()
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Look for rejected calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ // Make snapshot of neccessary members and release lock.
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow( m_xContainerWindow, css::uno::UNO_QUERY );
+ css::uno::Reference< css::frame::XController > xController ( m_xController , css::uno::UNO_QUERY );
+ aReadLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ if(
+ ( xContainerWindow.is() == sal_True ) &&
+ ( xController.is() == sal_True )
+ )
+ {
+ //-------------------------------------------------------------------------------------------------------------
+ // a) set default value to an invalid one. So we can start further searches for right icon id, if
+ // first steps failed!
+ // We must reset it to any fallback value - if no search step returns a valid result.
+ sal_Int32 nIcon = -1;
+
+ //-------------------------------------------------------------------------------------------------------------
+ // b) try to find information on controller propertyset directly
+ // Don't forget to catch possible exceptions - because these property is an optional one!
+ css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
+ if( xSet.is() == sal_True )
+ {
+ try
+ {
+ xSet->getPropertyValue( DECLARE_ASCII("IconId") )>>= nIcon;
+ }
+ catch( css::beans::UnknownPropertyException& )
+ {
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // c) if b) failed ... analyze argument list of currently loaded document insde the frame to find the filter.
+ // He can be used to detect right factory - and these can be used to match factory to icon ...
+ if( nIcon == -1 )
+ {
+ css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
+ if( xModel.is() == sal_True )
+ {
+ SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByModel(xModel);
+ if (eFactory != SvtModuleOptions::E_UNKNOWN_FACTORY)
+ nIcon = SvtModuleOptions().GetFactoryIcon( eFactory );
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // d) if all steps failed - use fallback!
+ if( nIcon == -1 )
+ {
+ nIcon = 0;
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // e) set icon on container window now
+ // Don't forget SolarMutex! We use vcl directly :-(
+ // Check window pointer for right WorkWindow class too!!!
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+ Window* pWindow = (VCLUnoHelper::GetWindow( xContainerWindow ));
+ if(
+ ( pWindow != NULL ) &&
+ ( pWindow->GetType() == WINDOW_WORKWINDOW )
+ )
+ {
+ WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
+ pWorkWindow->SetIcon( (sal_uInt16)nIcon );
+ }
+ aSolarGuard.clear();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short helper to start/stop listeneing for window events on container window
+ @descr If we get a new container window, we must set it on internal memeber ...
+ and stop listening at old one ... and start listening on new one!
+ But sometimes (in dispose() call!) it's neccessary to stop listeneing without starting
+ on new connections. So we split this functionality to make it easier at use.
+
+ @seealso method initialize()
+ @seealso method dispose()
+
+ @param -
+ @return -
+
+ @onerror We do nothing!
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void Frame::implts_startWindowListening()
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ // Make snapshot of neccessary member!
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow ;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory ;
+ css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
+ css::uno::Reference< css::awt::XWindowListener > xWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XFocusListener > xFocusListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ aReadLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ if( xContainerWindow.is() == sal_True )
+ {
+ xContainerWindow->addWindowListener( xWindowListener);
+ xContainerWindow->addFocusListener ( xFocusListener );
+
+ css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
+ if( xTopWindow.is() == sal_True )
+ {
+ xTopWindow->addTopWindowListener( xTopWindowListener );
+
+ css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer( xFactory->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY );
+ if( xTransfer.is() == sal_True )
+ {
+ css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget( xContainerWindow );
+ if( xDropTarget.is() == sal_True )
+ {
+ xDropTarget->addDropTargetListener( xDragDropListener );
+ xDropTarget->setActive( sal_True );
+ }
+ }
+ }
+ }
+}
+
+//*****************************************************************************************************************
+void Frame::implts_stopWindowListening()
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Sometimes used by dispose() => soft exceptions!
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ // Make snapshot of neccessary member!
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow ;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory ;
+ css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
+ css::uno::Reference< css::awt::XWindowListener > xWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XFocusListener > xFocusListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ aReadLock.unlock();
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+
+ if( xContainerWindow.is() == sal_True )
+ {
+ xContainerWindow->removeWindowListener( xWindowListener);
+ xContainerWindow->removeFocusListener ( xFocusListener );
+
+ css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
+ if( xTopWindow.is() == sal_True )
+ {
+ xTopWindow->removeTopWindowListener( xTopWindowListener );
+
+ css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer( xFactory->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY );
+ if( xTransfer.is() == sal_True )
+ {
+ css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget( xContainerWindow );
+ if( xDropTarget.is() == sal_True )
+ {
+ xDropTarget->removeDropTargetListener( xDragDropListener );
+ xDropTarget->setActive( sal_False );
+ }
+ }
+ }
+ }
+}
+
+/*-****************************************************************************************************//**
+ @short helper to force breaked close() request again
+ @descr If we self disagree with a close() request, and detect that all external locks are gone ...
+ then we must try to close this frame again.
+
+ @seealso XCloseable::close()
+ @seealso Frame::close()
+ @seealso Frame::removeActionLock()
+ @seealso Frame::resetActionLock()
+ @seealso m_bSelfClose
+ @seealso m_nExternalLockCount
+
+ @threadsafe yes
+ @modified 06.05.2002 09:31, as96863
+*//*-*****************************************************************************************************/
+void Frame::implts_checkSuicide()
+{
+ /* SAFE */
+ ReadGuard aReadLock(m_aLock);
+ // in case of lock==0 and safed state of previous close() request m_bSelfClose
+ // we must force close() again. Because we had disagreed with that before.
+ sal_Bool bSuicide = (m_nExternalLockCount==0 && m_bSelfClose);
+ m_bSelfClose = sal_False;
+ aReadLock.unlock();
+ /* } SAFE */
+ // force close and deliver owner ship to source of possible throwed veto exception
+ // Attention: Because this method isn't designed to throw such exception we must supress
+ // it for outside code!
+ try
+ {
+ if (bSuicide)
+ close(sal_True);
+ }
+ catch(const css::util::CloseVetoException&)
+ {}
+ catch(const css::lang::DisposedException&)
+ {}
+}
+
+//_______________________________________________________________
+
+/** little helper to enable/disable the menu closer at the menubar of the given frame.
+
+ @param xFrame
+ we use its layout manager to set/reset a special callback.
+ Its existence regulate visibility of this closer item.
+
+ @param bState
+ <TRUE/> enable; <FALSE/> disable this state
+ */
+
+void Frame::impl_setCloser( /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame ,
+ /*IN*/ sal_Bool bState )
+{
+ // Note: If start module isnt installed - no closer has to be shown!
+ if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE))
+ return;
+
+ try
+ {
+ css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ xFrameProps->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
+ css::uno::Reference< css::beans::XPropertySet > xLayoutProps(xLayoutManager, css::uno::UNO_QUERY_THROW);
+ xLayoutProps->setPropertyValue(LAYOUTMANAGER_PROPNAME_MENUBARCLOSER, css::uno::makeAny(bState));
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+//_______________________________________________________________
+
+/** it checks, which of the top level task frames must have the special menu closer for
+ switching to the backing window mode.
+
+ It analyze the current list of visible top level frames. Only the last real document
+ frame can have this symbol. Not the help frame nor the backing task itself.
+ Here we do anything related to this closer. We remove it from the old frame and set it
+ for the new one.
+ */
+
+void Frame::impl_checkMenuCloser()
+{
+ /* SAFE { */
+ ReadGuard aReadLock(m_aLock);
+
+ // only top frames, which are part of our desktop hierarchy, can
+ // do so! By the way - we need the desktop instance to have acess
+ // to all other top level frames too.
+ css::uno::Reference< css::frame::XDesktop > xDesktop (m_xParent, css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XFramesSupplier > xTaskSupplier(xDesktop , css::uno::UNO_QUERY);
+ if ( !xDesktop.is() || !xTaskSupplier.is() )
+ return;
+
+ aReadLock.unlock();
+ /* } SAFE */
+
+ // analyze the list of current open tasks
+ // Suppress search for other views to the same model ...
+ // It's not needed here and can be very expensive.
+ FrameListAnalyzer aAnalyzer(
+ xTaskSupplier,
+ this,
+ FrameListAnalyzer::E_HIDDEN | FrameListAnalyzer::E_HELP | FrameListAnalyzer::E_BACKINGCOMPONENT);
+
+ // specify the new frame, which must have this special state ...
+ css::uno::Reference< css::frame::XFrame > xNewCloserFrame;
+
+ // -----------------------------
+ // a)
+ // If there exist ate least one other frame - there are two frames currently open.
+ // But we can enable this closer only, if one of these two tasks includes the help module.
+ // The "other frame" couldn't be the help. Because then it wouldn't be part of this "other list".
+ // In such case it will be seperated to the reference aAnalyzer.m_xHelp!
+ // But we must check, if weself includes the help ...
+ // Check aAnalyzer.m_bReferenceIsHelp!
+ if (
+ (aAnalyzer.m_lOtherVisibleFrames.getLength()==1) &&
+ (
+ (aAnalyzer.m_bReferenceIsHelp ) ||
+ (aAnalyzer.m_bReferenceIsHidden)
+ )
+ )
+ {
+ // others[0] can't be the backing component!
+ // Because it's set at the special member aAnalyzer.m_xBackingComponent ... :-)
+ xNewCloserFrame = aAnalyzer.m_lOtherVisibleFrames[0];
+ }
+ else
+ // -----------------------------
+ // b)
+ // There is no other frame ... means no other document frame. The help module
+ // will be handled seperatly and must(!) be ignored here ... excepting weself includes the help.
+ if (
+ (aAnalyzer.m_lOtherVisibleFrames.getLength()==0) &&
+ (!aAnalyzer.m_bReferenceIsHelp ) &&
+ (!aAnalyzer.m_bReferenceIsHidden ) &&
+ (!aAnalyzer.m_bReferenceIsBacking )
+ )
+ {
+ xNewCloserFrame = this;
+ }
+
+ // Look for neccessary actions ...
+ // Only if the closer state must be moved from one frame to another one
+ // or must be enabled/disabled at all.
+ /* STATIC SAFE { */
+ WriteGuard aStaticWriteLock(LockHelper::getGlobalLock());
+ css::uno::Reference< css::frame::XFrame > xCloserFrame (m_xCloserFrame.get(), css::uno::UNO_QUERY);
+ if (xCloserFrame!=xNewCloserFrame)
+ {
+ if (xCloserFrame.is())
+ impl_setCloser(xCloserFrame, sal_False);
+ if (xNewCloserFrame.is())
+ impl_setCloser(xNewCloserFrame, sal_True);
+ m_xCloserFrame = xNewCloserFrame;
+ }
+ aStaticWriteLock.unlock();
+ /* } STATIC SAFE */
+}
+
+//_________________________________________________________________________________________________________________
+// debug methods
+//_________________________________________________________________________________________________________________
+
+/*-----------------------------------------------------------------------------------------------------------------
+ The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
+ we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT!
+-----------------------------------------------------------------------------------------------------------------*/
+
+#ifdef ENABLE_ASSERTIONS
+
+//*****************************************************************************************************************
+// We don't accept null pointer or references!
+sal_Bool Frame::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+{
+ return (
+ ( &xFactory == NULL ) ||
+ ( xFactory.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+// Its allowed to reset the active frame membervariable with a NULL-css::uno::Reference but not with a NULL-pointer!
+// And we accept frames only! No tasks and desktops!
+sal_Bool Frame::implcp_setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ return (
+ ( &xFrame == NULL ) ||
+ ( css::uno::Reference< css::frame::XDesktop >( xFrame, css::uno::UNO_QUERY ).is() == sal_True )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
+{
+ return (
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
+{
+ return (
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return (
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return (
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_windowResized( const css::awt::WindowEvent& aEvent )
+{
+ return (
+ ( &aEvent == NULL ) ||
+ ( aEvent.Source.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_focusGained( const css::awt::FocusEvent& aEvent )
+{
+ return (
+ ( &aEvent == NULL ) ||
+ ( aEvent.Source.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_windowActivated( const css::lang::EventObject& aEvent )
+{
+ return (
+ ( &aEvent == NULL ) ||
+ ( aEvent.Source.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_windowDeactivated( const css::lang::EventObject& aEvent )
+{
+ return (
+ ( &aEvent == NULL ) ||
+ ( aEvent.Source.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+sal_Bool Frame::implcp_disposing( const css::lang::EventObject& aEvent )
+{
+ return (
+ ( &aEvent == NULL ) ||
+ ( aEvent.Source.is() == sal_False )
+ );
+}
+
+#endif // #ifdef ENABLE_ASSERTIONS
+
+} // namespace framework
diff --git a/framework/source/services/fwk_services.src b/framework/source/services/fwk_services.src
new file mode 100644
index 000000000000..ef037c75778a
--- /dev/null
+++ b/framework/source/services/fwk_services.src
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "framework.hrc"
+
+Window DLG_BACKING
+{
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Border = FALSE;
+
+ String STR_BACKING_WELCOME
+ {
+ Text [ en-US ] = "Welcome to";
+ };
+ String STR_BACKING_WELCOMEPRODUCT
+ {
+ Text [ en-US ] = "%PRODUCTNAME";
+ };
+ String STR_BACKING_CREATE
+ {
+ Text [ en-US ] = "Create a new document";
+ };
+ String STR_BACKING_TEMPLATE
+ {
+ Text [ en-US ] = "~Templates...";
+ };
+ String STR_BACKING_FILE
+ {
+ Text [ en-US ] = "~Open...";
+ };
+ String STR_BACKING_EXTHELP
+ {
+ Text [ en-US ] = "Add new features to %PRODUCTNAME";
+ };
+ String STR_BACKING_REGHELP
+ {
+ Text [ en-US ] = "Register your %PRODUCTNAME";
+ };
+ String STR_BACKING_INFOHELP
+ {
+ Text [ en-US ] = "Get more information about %PRODUCTNAME";
+ };
+ String STR_BACKING_TPLREP
+ {
+ Text [ en-US ] = "Get more templates for %PRODUCTNAME";
+ };
+};
+
+Resource RES_BACKING_IMAGES
+{
+ Bitmap BMP_BACKING_BACKGROUND_LEFT
+ {
+ File = "backing.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_MIDDLE
+ {
+ File = "backing_space.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RIGHT
+ {
+ File = "backing_right.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RTL_LEFT
+ {
+ File = "backing_rtl_left.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RTL_RIGHT
+ {
+ File = "backing_rtl_right.png";
+ };
+ Bitmap BMP_BACKING_EXT
+ {
+ File = "extension.png";
+ };
+ Bitmap BMP_BACKING_REG
+ {
+ File = "register_32.png";
+ };
+ Bitmap BMP_BACKING_INFO
+ {
+ File = "info_26.png";
+ };
+ Bitmap BMP_BACKING_TPLREP
+ {
+ File = "addtemplate_32.png";
+ };
+ Bitmap BMP_BACKING_WRITER
+ {
+ File = "odt_32.png";
+ };
+ Bitmap BMP_BACKING_CALC
+ {
+ File = "ods_32.png";
+ };
+ Bitmap BMP_BACKING_IMPRESS
+ {
+ File = "odp_32.png";
+ };
+ Bitmap BMP_BACKING_DRAW
+ {
+ File = "odg_32.png";
+ };
+ Bitmap BMP_BACKING_DATABASE
+ {
+ File = "odb_32.png";
+ };
+ Bitmap BMP_BACKING_FORMULA
+ {
+ File = "odf_32.png";
+ };
+ Bitmap BMP_BACKING_OPENFILE
+ {
+ File = "folder_32.png";
+ };
+ Bitmap BMP_BACKING_OPENTEMPLATE
+ {
+ File = "templates_32.png";
+ };
+};
+
+Resource RES_BACKING_IMAGES_HC
+{
+ Bitmap BMP_BACKING_BACKGROUND_LEFT
+ {
+ File = "backing_hc.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_MIDDLE
+ {
+ File = "backing_space_hc.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RIGHT
+ {
+ File = "backing_right_hc.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RTL_LEFT
+ {
+ File = "backing_rtl_left_hc.png";
+ };
+ Bitmap BMP_BACKING_BACKGROUND_RTL_RIGHT
+ {
+ File = "backing_rtl_right_hc.png";
+ };
+ Bitmap BMP_BACKING_EXT
+ {
+ File = "extension_hc.png";
+ };
+ Bitmap BMP_BACKING_REG
+ {
+ File = "register_hc.png";
+ };
+ Bitmap BMP_BACKING_INFO
+ {
+ File = "info_hc.png";
+ };
+ Bitmap BMP_BACKING_TPLREP
+ {
+ File = "template_hc.png";
+ };
+ Bitmap BMP_BACKING_WRITER
+ {
+ File = "odt_32_hc.png";
+ };
+ Bitmap BMP_BACKING_CALC
+ {
+ File = "ods_32_hc.png";
+ };
+ Bitmap BMP_BACKING_IMPRESS
+ {
+ File = "odp_32_hc.png";
+ };
+ Bitmap BMP_BACKING_DRAW
+ {
+ File = "odg_32_hc.png";
+ };
+ Bitmap BMP_BACKING_DATABASE
+ {
+ File = "odb_32_hc.png";
+ };
+ Bitmap BMP_BACKING_FORMULA
+ {
+ File = "odf_32_hc.png";
+ };
+ Bitmap BMP_BACKING_OPENFILE
+ {
+ File = "folder_32_hc.png";
+ };
+ Bitmap BMP_BACKING_OPENTEMPLATE
+ {
+ File = "templates_32_hc.png";
+ };
+};
+
+Window WIN_TABWINDOW
+{
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ TabControl TC_TABCONTROL
+ {
+ OutputSize = TRUE ;
+ };
+};
+
diff --git a/framework/source/services/license.cxx b/framework/source/services/license.cxx
new file mode 100644
index 000000000000..f140b8e22886
--- /dev/null
+++ b/framework/source/services/license.cxx
@@ -0,0 +1,631 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <services/license.hxx>
+#include <threadhelp/resetableguard.hxx>
+#include <macros/debug.hxx>
+#include <services.h>
+
+// local header for UI implementation
+#include "services/licensedlg.hxx"
+#include "classes/resource.hrc"
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <rtl/ustrbuf.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/string.hxx>
+#include <unotools/bootstrap.hxx>
+#include <osl/file.hxx>
+#include <svtools/xtextedt.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/processfactory.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <tools/datetime.hxx>
+#include <osl/file.hxx>
+#include <osl/time.h>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+using namespace utl;
+using namespace ::osl ;
+using namespace ::cppu ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::beans ;
+using namespace ::com::sun::star::lang ;
+using namespace ::com::sun::star::util ;
+using namespace ::com::sun::star::frame ;
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+// license file name
+static const char *szLicensePath = "/share/readme";
+#ifdef UNX
+static const char *szUNXLicenseName = "/LICENSE";
+static const char *szUNXLicenseExt = "";
+#elif defined(WNT) || defined(OS2)
+static const char *szWNTLicenseName = "/license";
+static const char *szWNTLicenseExt = ".txt";
+#endif
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+License::License( const Reference< XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ // Attention:
+ // Don't change order of initialization!
+ // ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
+ // we must garant right initialization and a valid value of this! First initialize
+ // baseclasses and then members. And we need the mutex for other baseclasses !!!
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+ , m_bTerminate ( sal_False )
+{
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+License::~License()
+{
+}
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+
+DEFINE_XINTERFACE_4 ( License ,
+ OWeakObject ,
+ DIRECT_INTERFACE(XTypeProvider ),
+ DIRECT_INTERFACE(XServiceInfo ),
+ DIRECT_INTERFACE(XJob ),
+ DIRECT_INTERFACE(XCloseable )
+ )
+
+DEFINE_XTYPEPROVIDER_4 ( License ,
+ XTypeProvider ,
+ XServiceInfo ,
+ XJob ,
+ XCloseable
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( License,
+ OWeakObject ,
+ SERVICENAME_LICENSE ,
+ IMPLEMENTATIONNAME_LICENSE
+ )
+
+DEFINE_INIT_SERVICE ( License,
+ {
+ }
+ )
+
+
+#if 0
+IMPL_STATIC_LINK_NOINSTANCE( License, Terminate, void*, EMPTYARG )
+{
+ /*
+ Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ Reference< XDesktop > xDesktop(xFactory->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
+ if (xDesktop.is())
+ xDesktop->terminate();
+ */
+ /*
+ _exit(0);
+ */
+ return 0;
+}
+#endif
+
+static DateTime _oslDateTimeToDateTime(const oslDateTime& aDateTime)
+{
+ return DateTime(
+ Date(aDateTime.Day, aDateTime.Month, aDateTime.Year),
+ Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds));
+}
+
+static ::rtl::OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
+{
+ ::rtl::OStringBuffer aDateTimeString;
+ aDateTimeString.append((sal_Int32)aDateTime.GetYear());
+ aDateTimeString.append("-");
+ if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
+ aDateTimeString.append("-");
+ if (aDateTime.GetDay()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetDay());
+ aDateTimeString.append("T");
+ if (aDateTime.GetHour()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetHour());
+ aDateTimeString.append(":");
+ if (aDateTime.GetMin()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetMin());
+ aDateTimeString.append(":");
+ if (aDateTime.GetSec()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetSec());
+ if (bUTC) aDateTimeString.append("Z");
+
+ return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
+}
+
+static sal_Bool _parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
+{
+ // take apart a canonical literal xsd:dateTime string
+ //CCYY-MM-DDThh:mm:ss(Z)
+
+ ::rtl::OUString aDateTimeString = aString.trim();
+
+ // check length
+ if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
+ return sal_False;
+
+ sal_Int32 nDateLength = 10;
+ sal_Int32 nTimeLength = 8;
+
+ ::rtl::OUString aDateTimeSep = ::rtl::OUString::createFromAscii("T");
+ ::rtl::OUString aDateSep = ::rtl::OUString::createFromAscii("-");
+ ::rtl::OUString aTimeSep = ::rtl::OUString::createFromAscii(":");
+ ::rtl::OUString aUTCString = ::rtl::OUString::createFromAscii("Z");
+
+ ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
+ ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
+
+ sal_Int32 nIndex = 0;
+ sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
+ sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
+ sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
+ nIndex = 0;
+ sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
+ sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
+ sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
+
+ Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
+ Time tmpTime(nHour, nMinute, nSecond);
+ DateTime tmpDateTime(tmpDate, tmpTime);
+ if (aString.indexOf(aUTCString) < 0)
+ tmpDateTime.ConvertToUTC();
+
+ aDateTime = tmpDateTime;
+ return sal_True;
+}
+
+static ::rtl::OUString _getCurrentDateString()
+{
+ ::rtl::OUString aString;
+ return _makeDateTimeString(DateTime());
+}
+
+// execution of license check...
+css::uno::Any SAL_CALL License::execute(const css::uno::Sequence< css::beans::NamedValue >& )
+ throw( css::lang::IllegalArgumentException, css::uno::Exception)
+{
+ // return value
+ Any aRet; aRet <<= sal_False;
+
+ try
+ {
+ ::rtl::OUString aBaseInstallPath;
+ Bootstrap::PathStatus aBaseLocateResult =
+ Bootstrap::locateBaseInstallation(aBaseInstallPath);
+ if (aBaseLocateResult != Bootstrap::PATH_EXISTS)
+ {
+ // base install noit found
+ // prepare termination
+ // m_bTerminate = sal_True;
+ // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
+ aRet <<= sal_False;
+ return aRet;
+ }
+ // determine the filename of the license to show
+ ::rtl::OUString aLangString;
+ ::com::sun::star::lang::Locale aLocale;
+ ::rtl::OString aMgrName = ::rtl::OString("fwe");
+ AllSettings aSettings(Application::GetSettings());
+ aLocale = aSettings.GetUILocale();
+ ResMgr* pResMgr = ResMgr::SearchCreateResMgr(aMgrName, aLocale);
+
+ aLangString = aLocale.Language;
+ if ( aLocale.Country.getLength() != 0 )
+ {
+ aLangString += ::rtl::OUString::createFromAscii("-");
+ aLangString += aLocale.Country;
+ if ( aLocale.Variant.getLength() != 0 )
+ {
+ aLangString += ::rtl::OUString::createFromAscii("-");
+ aLangString += aLocale.Variant;
+ }
+ }
+#if defined(WNT) || defined(OS2)
+ ::rtl::OUString aLicensePath =
+ aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
+ + ::rtl::OUString::createFromAscii(szWNTLicenseName)
+ + ::rtl::OUString::createFromAscii("_")
+ + aLangString
+ + ::rtl::OUString::createFromAscii(szWNTLicenseExt);
+#else
+ ::rtl::OUString aLicensePath =
+ aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
+ + ::rtl::OUString::createFromAscii(szUNXLicenseName)
+ + ::rtl::OUString::createFromAscii("_")
+ + aLangString
+ + ::rtl::OUString::createFromAscii(szUNXLicenseExt);
+#endif
+ // check if we need to show the license at all
+ // open org.openoffice.Setup/Office/ooLicenseAcceptDate
+ ::rtl::OUString sConfigSrvc = SERVICENAME_CFGPROVIDER;
+ ::rtl::OUString sAccessSrvc = ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
+ ::rtl::OUString sReadSrvc = SERVICENAME_CFGREADACCESS;
+
+ // get configuration provider
+ Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
+ m_xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
+ Sequence< Any > theArgs(1);
+ NamedValue v;
+ v.Name = ::rtl::OUString::createFromAscii("NodePath");
+ v.Value <<= ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office");
+ theArgs[0] <<= v;
+ Reference< XPropertySet > pset = Reference< XPropertySet >(
+ theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
+
+ // if we find a date there, compare it to baseinstall license date
+ ::rtl::OUString aAcceptDate;
+ if (pset->getPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate")) >>= aAcceptDate)
+ {
+ // get LicenseFileDate from base install
+ ::rtl::OUString aLicenseURL = aLicensePath;
+ /*
+ if (FileBase::getFileURLFromSystemPath(aLicensePath, aLicenseURL) != FileBase::E_None)
+ return makeAny(sal_False);
+ */
+ DirectoryItem aDirItem;
+ if (DirectoryItem::get(aLicenseURL, aDirItem) != FileBase::E_None)
+ return makeAny(sal_False);
+ FileStatus aStatus(FileStatusMask_All);
+ if (aDirItem.getFileStatus(aStatus) != FileBase::E_None)
+ return makeAny(sal_False);
+ TimeValue aTimeVal = aStatus.getModifyTime();
+ oslDateTime aDateTimeVal;
+ if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
+ return makeAny(sal_False);
+
+ // compare dates
+ DateTime aLicenseDateTime = _oslDateTimeToDateTime(aDateTimeVal);
+ DateTime aAcceptDateTime;
+ if (!_parseDateTime(aAcceptDate, aAcceptDateTime))
+ return makeAny(sal_False);
+
+ if ( aAcceptDateTime > aLicenseDateTime )
+ return makeAny(sal_True);
+ }
+ // prepare to show
+ // display license dialog
+ LicenseDialog* pDialog = new LicenseDialog(aLicensePath, pResMgr);
+ sal_Bool bAgreed = (pDialog->Execute() == 1);
+ delete pDialog;
+
+ if (bAgreed) {
+
+ // write org.openoffice.Setup/ooLicenseAcceptDate
+ aAcceptDate = _getCurrentDateString();
+ pset->setPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate"), makeAny(aAcceptDate));
+ Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
+
+ // enable quickstarter
+ sal_Bool bQuickstart( sal_True );
+ sal_Bool bAutostart( sal_True );
+ Sequence< Any > aSeq( 2 );
+ aSeq[0] <<= bQuickstart;
+ aSeq[1] <<= bAutostart;
+
+ Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii( "com.sun.star.office.Quickstart" )),UNO_QUERY );
+ if ( xQuickstart.is() )
+ xQuickstart->initialize( aSeq );
+
+ aRet <<= sal_True;
+ }
+ else
+ {
+ // license was not accepted
+ // prepare termination
+ // m_bTerminate = sal_True;
+ // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
+ aRet <<= sal_False;
+ }
+ }
+ catch (RuntimeException&)
+ {
+ // license could not be verified
+ aRet <<= sal_False;
+ }
+ return aRet;
+}
+
+void SAL_CALL License::close(sal_Bool /*bDeliverOwnership*/) throw (css::util::CloseVetoException)
+{
+ if (!m_bTerminate)
+ throw CloseVetoException();
+}
+void SAL_CALL License::addCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
+ throw (css::uno::RuntimeException)
+{
+}
+void SAL_CALL License::removeCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
+ throw (css::uno::RuntimeException)
+{
+}
+
+
+//************************************************************************
+// License Dialog
+//************************************************************************
+
+LicenseDialog::LicenseDialog(const ::rtl::OUString & aLicensePath, ResMgr *pResMgr) :
+ ModalDialog(NULL, ResId(DLG_LICENSE, *pResMgr)),
+ aLicenseML(this, ResId(ML_LICENSE, *pResMgr)),
+ aInfo1FT(this, ResId(FT_INFO1, *pResMgr)),
+ aInfo2FT(this, ResId(FT_INFO2, *pResMgr)),
+ aInfo3FT(this, ResId(FT_INFO3, *pResMgr)),
+ aInfo2_1FT(this, ResId(FT_INFO2_1, *pResMgr)),
+ aInfo3_1FT(this, ResId(FT_INFO3_1, *pResMgr)),
+ aFixedLine(this, ResId(FL_DIVIDE, *pResMgr)),
+ aPBPageDown(this, ResId(PB_PAGEDOWN, *pResMgr)),
+ aPBDecline( this, ResId(PB_DECLINE, *pResMgr) ),
+ aPBAccept( this, ResId(PB_ACCEPT, *pResMgr) ),
+ aArrow(this, ResId(IMG_ARROW, *pResMgr)),
+ aStrAccept( ResId(LICENSE_ACCEPT, *pResMgr) ),
+ aStrNotAccept( ResId(LICENSE_NOTACCEPT, *pResMgr) ),
+ bEndReached(sal_False)
+{
+ FreeResource();
+
+ aLicenseML.SetEndReachedHdl( LINK(this, LicenseDialog, EndReachedHdl) );
+ aLicenseML.SetScrolledHdl( LINK(this, LicenseDialog, ScrolledHdl) );
+
+ aPBPageDown.SetClickHdl( LINK(this, LicenseDialog, PageDownHdl) );
+ aPBDecline.SetClickHdl( LINK(this, LicenseDialog, DeclineBtnHdl) );
+ aPBAccept.SetClickHdl( LINK(this, LicenseDialog, AcceptBtnHdl) );
+
+ // We want a automatic repeating page down button
+ WinBits aStyle = aPBPageDown.GetStyle();
+ aStyle |= WB_REPEAT;
+ aPBPageDown.SetStyle( aStyle );
+
+ String aText = aInfo2FT.GetText();
+ aText.SearchAndReplaceAll( UniString::CreateFromAscii("%PAGEDOWN"), aPBPageDown.GetText() );
+ aInfo2FT.SetText( aText );
+
+ aPBDecline.SetText( aStrNotAccept );
+ aPBAccept.SetText( aStrAccept );
+
+ aPBAccept.Disable();
+
+ // load license text
+ File aLicenseFile(aLicensePath);
+ if ( aLicenseFile.open(OpenFlag_Read) == FileBase::E_None)
+ {
+ DirectoryItem d;
+ DirectoryItem::get(aLicensePath, d);
+ FileStatus fs(FileStatusMask_FileSize);
+ d.getFileStatus(fs);
+ sal_uInt64 nBytesRead = 0;
+ sal_uInt64 nPosition = 0;
+ sal_uInt32 nBytes = (sal_uInt32)fs.getFileSize();
+ sal_Char *pBuffer = new sal_Char[nBytes];
+ // FileBase RC r = FileBase::E_None;
+ while (aLicenseFile.read(pBuffer+nPosition, nBytes-nPosition, nBytesRead) == FileBase::E_None
+ && nPosition + nBytesRead < nBytes)
+ {
+ nPosition += nBytesRead;
+ }
+ ::rtl::OUString aLicenseString(pBuffer, nBytes, RTL_TEXTENCODING_UTF8,
+ OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
+ delete[] pBuffer;
+ aLicenseML.SetText(aLicenseString);
+ }
+
+}
+
+LicenseDialog::~LicenseDialog()
+{
+}
+
+IMPL_LINK( LicenseDialog, PageDownHdl, PushButton *, EMPTYARG )
+{
+ aLicenseML.ScrollDown( SCROLL_PAGEDOWN );
+ return 0;
+}
+
+IMPL_LINK( LicenseDialog, EndReachedHdl, LicenseView *, EMPTYARG )
+{
+ bEndReached = sal_True;
+
+ EnableControls();
+
+ return 0;
+}
+
+IMPL_LINK( LicenseDialog, ScrolledHdl, LicenseView *, EMPTYARG )
+{
+ EnableControls();
+
+ return 0;
+}
+
+IMPL_LINK( LicenseDialog, DeclineBtnHdl, PushButton *, EMPTYARG )
+{
+ EndDialog(0);
+ return 0;
+}
+IMPL_LINK( LicenseDialog, AcceptBtnHdl, PushButton *, EMPTYARG )
+{
+ EndDialog(1);
+ return 0;
+}
+
+
+void LicenseDialog::EnableControls()
+{
+ if( !bEndReached &&
+ ( aLicenseML.IsEndReached() || !aLicenseML.GetText().Len() ) )
+ bEndReached = sal_True;
+
+ if ( bEndReached )
+ {
+ Point aPos( aInfo1FT.GetPosPixel().X(),
+ aInfo3_1FT.GetPosPixel().Y() );
+ aArrow.SetPosPixel( aPos );
+ aPBAccept.Enable();
+ }
+ else
+ {
+ Point aPos( aInfo1FT.GetPosPixel().X(),
+ aInfo2_1FT.GetPosPixel().Y() );
+ aArrow.SetPosPixel( aPos );
+ aPBAccept.Disable();
+ }
+
+ if ( aLicenseML.IsEndReached() )
+ aPBPageDown.Disable();
+ else
+ aPBPageDown.Enable();
+
+}
+
+
+LicenseView::LicenseView( Window* pParent, const ResId& rResId )
+ : MultiLineEdit( pParent, rResId )
+{
+ SetLeftMargin( 5 );
+
+ mbEndReached = IsEndReached();
+
+ StartListening( *GetTextEngine() );
+}
+
+LicenseView::~LicenseView()
+{
+ maEndReachedHdl = Link();
+ maScrolledHdl = Link();
+
+ EndListeningAll();
+}
+
+void LicenseView::ScrollDown( ScrollType eScroll )
+{
+ ScrollBar* pScroll = GetVScrollBar();
+
+ if ( pScroll )
+ pScroll->DoScrollAction( eScroll );
+}
+
+sal_Bool LicenseView::IsEndReached() const
+{
+ sal_Bool bEndReached;
+
+ ExtTextView* pView = GetTextView();
+ ExtTextEngine* pEdit = GetTextEngine();
+ sal_uLong nHeight = pEdit->GetTextHeight();
+ Size aOutSize = pView->GetWindow()->GetOutputSizePixel();
+ Point aBottom( 0, aOutSize.Height() );
+
+ if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
+ bEndReached = sal_True;
+ else
+ bEndReached = sal_False;
+
+ return bEndReached;
+}
+
+void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( rHint.IsA( TYPE(TextHint) ) )
+ {
+ sal_Bool bLastVal = EndReached();
+ sal_uLong nId = ((const TextHint&)rHint).GetId();
+
+ if ( nId == TEXT_HINT_PARAINSERTED )
+ {
+ if ( bLastVal )
+ mbEndReached = IsEndReached();
+ }
+ else if ( nId == TEXT_HINT_VIEWSCROLLED )
+ {
+ if ( ! mbEndReached )
+ mbEndReached = IsEndReached();
+ maScrolledHdl.Call( this );
+ }
+
+ if ( EndReached() && !bLastVal )
+ {
+ maEndReachedHdl.Call( this );
+ }
+ }
+}
+
+} // namespace framework
+
diff --git a/framework/source/services/mediatypedetectionhelper.cxx b/framework/source/services/mediatypedetectionhelper.cxx
new file mode 100644
index 000000000000..1033cbda7913
--- /dev/null
+++ b/framework/source/services/mediatypedetectionhelper.cxx
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <services/mediatypedetectionhelper.hxx>
+#include <services.h>
+#include <svl/inettype.hxx>
+#include <tools/string.hxx>
+#include <rtl/logfile.hxx>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework
+{
+
+using namespace ::com::sun::star ;
+using namespace ::rtl ;
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+MediaTypeDetectionHelper::MediaTypeDetectionHelper( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
+ : m_xFactory( xFactory )
+{
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+MediaTypeDetectionHelper::~MediaTypeDetectionHelper()
+{
+}
+
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( MediaTypeDetectionHelper
+ , ::cppu::OWeakObject
+ , SERVICENAME_MEDIATYPEDETECTIONHELPER
+ , IMPLEMENTATIONNAME_MEDIATYPEDETECTIONHELPER
+ )
+
+DEFINE_INIT_SERVICE ( MediaTypeDetectionHelper,
+ {
+ }
+ )
+
+//*****************************************************************************************************************
+// XStringMapping
+//*****************************************************************************************************************
+
+//virtual
+sal_Bool SAL_CALL MediaTypeDetectionHelper::mapStrings(
+ uno::Sequence< OUString >& rSeq )
+ throw(uno::RuntimeException)
+{
+ sal_Bool bModified = sal_False;
+ for( sal_Int32 i = rSeq.getLength(); i--; )
+ {
+
+ OUString& rUrl = rSeq[i];
+ INetContentType eType = INetContentTypes::GetContentTypeFromURL( rUrl );
+
+ UniString aType( INetContentTypes::GetContentType( eType ) );
+ if( aType.Len() )
+ {
+ rUrl = aType;
+ bModified = sal_True;
+ }
+ }
+ return bModified;
+}
+
+} // namespace framework
+
diff --git a/framework/source/services/modelwinservice.cxx b/framework/source/services/modelwinservice.cxx
new file mode 100755
index 000000000000..d50fe7dcc653
--- /dev/null
+++ b/framework/source/services/modelwinservice.cxx
@@ -0,0 +1,279 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: urltransformer.cxx,v $
+ * $Revision: 1.17 $
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+
+#include "services.h"
+#include "services/modelwinservice.hxx"
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+#include <com/sun/star/awt/XControlModel.hpp>
+
+using namespace ::com::sun::star;
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+class Impl_ModelWinService
+{
+ public:
+ ~Impl_ModelWinService();
+
+ static Impl_ModelWinService* getSingleInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager );
+
+ uno::Any getByName( const ::rtl::OUString& sName )
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException );
+
+ uno::Sequence< ::rtl::OUString > getElementNames()
+ throw( uno::RuntimeException );
+
+ sal_Bool hasByName( const ::rtl::OUString& sName )
+ throw( uno::RuntimeException );
+
+ uno::Type getElementType()
+ throw( css::uno::RuntimeException );
+
+ sal_Bool hasElements()
+ throw( css::uno::RuntimeException );
+
+ void registerModelForXWindow( const uno::Reference< awt::XWindow >& rWindow, const uno::Reference< awt::XControlModel >& rModel );
+
+ void deregisterModelForXWindow( const uno::Reference< awt::XWindow >& rWindow );
+
+ private:
+ typedef BaseHash< uno::WeakReference< awt::XControlModel > > ModelWinMap;
+
+ Impl_ModelWinService();
+ Impl_ModelWinService( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager );
+
+ static Impl_ModelWinService* m_pModelWinService;
+
+ ::com::sun::star::uno::WeakReference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager;
+ ModelWinMap m_aModelMap;
+};
+
+Impl_ModelWinService* Impl_ModelWinService::m_pModelWinService = 0;
+
+Impl_ModelWinService* Impl_ModelWinService::getSingleInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager )
+{
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+ if ( !m_pModelWinService )
+ m_pModelWinService = new Impl_ModelWinService( rServiceManager );
+ return m_pModelWinService;
+}
+
+Impl_ModelWinService::Impl_ModelWinService( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager ) :
+ m_xServiceManager( rServiceManager )
+{
+}
+
+Impl_ModelWinService::Impl_ModelWinService()
+{
+}
+
+Impl_ModelWinService::~Impl_ModelWinService()
+{
+}
+
+void Impl_ModelWinService::registerModelForXWindow( const uno::Reference< awt::XWindow >& rWindow, const uno::Reference< awt::XControlModel >& rModel )
+{
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+
+ ::rtl::OUString sName = rtl::OUString::valueOf( reinterpret_cast< sal_Int64 >((void*)rWindow.get()));
+ ModelWinMap::iterator pIter = m_aModelMap.find( sName );
+ if ( pIter != m_aModelMap.end() )
+ pIter->second = rModel;
+ else
+ m_aModelMap[sName] = rModel;
+}
+
+void Impl_ModelWinService::deregisterModelForXWindow( const uno::Reference< awt::XWindow >& /*rWindow*/ )
+{
+}
+
+uno::Any Impl_ModelWinService::getByName( const ::rtl::OUString& sName )
+throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ uno::Any aAny;
+
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+ ModelWinMap::iterator pIter = m_aModelMap.find( sName );
+ if ( pIter != m_aModelMap.end())
+ {
+ uno::Reference< awt::XControlModel > xModel( pIter->second );
+ aAny = uno::makeAny(xModel);
+ }
+
+ return aAny;
+}
+
+uno::Sequence< ::rtl::OUString > Impl_ModelWinService::getElementNames()
+throw( uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+ uno::Sequence< ::rtl::OUString > aResult( m_aModelMap.size() );
+
+ sal_Int32 i = 0;
+ ModelWinMap::const_iterator pIter = m_aModelMap.begin();
+ while ( pIter != m_aModelMap.end())
+ aResult[i++] = pIter->first;
+
+ return aResult;
+}
+
+sal_Bool Impl_ModelWinService::hasByName( const ::rtl::OUString& sName )
+throw( uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+ ModelWinMap::iterator pIter = m_aModelMap.find( sName );
+ if ( pIter != m_aModelMap.end())
+ return true;
+ else
+ return false;
+}
+
+uno::Type Impl_ModelWinService::getElementType()
+throw( css::uno::RuntimeException )
+{
+ return ::getCppuType(( const uno::Reference< awt::XControlModel >*)NULL );
+}
+
+sal_Bool Impl_ModelWinService::hasElements()
+throw( css::uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
+ return (m_aModelMap.size() > 0);
+}
+
+//*****************************************************************************************************************
+// css::uno::XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+
+DEFINE_XINTERFACE_4 ( ModelWinService ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::container::XNameAccess ),
+ DIRECT_INTERFACE(css::container::XElementAccess )
+ )
+
+DEFINE_XTYPEPROVIDER_4 ( ModelWinService ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::container::XNameAccess ,
+ css::container::XElementAccess
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( ModelWinService ,
+ OWeakObject ,
+ SERVICENAME_MODELWINSERVICE ,
+ IMPLEMENTATIONNAME_MODELWINSERVICE
+ )
+
+DEFINE_INIT_SERVICE ( ModelWinService,
+ {
+ }
+ )
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+ModelWinService::ModelWinService(const uno::Reference< lang::XMultiServiceFactory >& rServiceManager ) :
+ m_xServiceManager( rServiceManager )
+{
+}
+
+ModelWinService::~ModelWinService()
+{
+}
+
+void ModelWinService::registerModelForXWindow( const uno::Reference< awt::XWindow >& rWindow, const uno::Reference< awt::XControlModel >& rModel )
+{
+ Impl_ModelWinService::getSingleInstance(m_xServiceManager)->registerModelForXWindow( rWindow, rModel );
+}
+
+void ModelWinService::deregisterModelForXWindow( const uno::Reference< awt::XWindow >& rWindow )
+{
+ Impl_ModelWinService::getSingleInstance(m_xServiceManager)->deregisterModelForXWindow( rWindow );
+}
+
+uno::Any SAL_CALL ModelWinService::getByName( const ::rtl::OUString& sName )
+throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ return Impl_ModelWinService::getSingleInstance(m_xServiceManager)->getByName( sName );
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL ModelWinService::getElementNames()
+throw( uno::RuntimeException )
+{
+ return Impl_ModelWinService::getSingleInstance(m_xServiceManager)->getElementNames( );
+}
+
+sal_Bool SAL_CALL ModelWinService::hasByName( const ::rtl::OUString& sName )
+throw( uno::RuntimeException )
+{
+ return Impl_ModelWinService::getSingleInstance(m_xServiceManager)->hasByName( sName );
+}
+
+//---------------------------------------------------------------------------------------------------------
+// XElementAccess
+//---------------------------------------------------------------------------------------------------------
+uno::Type SAL_CALL ModelWinService::getElementType()
+throw( uno::RuntimeException )
+{
+ return ::getCppuType( (const uno::Reference< awt::XControlModel > *)NULL );
+}
+
+sal_Bool SAL_CALL ModelWinService::hasElements()
+throw( uno::RuntimeException )
+{
+ return Impl_ModelWinService::getSingleInstance(m_xServiceManager)->hasElements();
+}
+
+}
diff --git a/framework/source/services/modulemanager.cxx b/framework/source/services/modulemanager.cxx
new file mode 100644
index 000000000000..396a9650e3f7
--- /dev/null
+++ b/framework/source/services/modulemanager.cxx
@@ -0,0 +1,425 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+#include "services/modulemanager.hxx"
+#include "services/frame.hxx"
+
+//_______________________________________________
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+#include <comphelper/configurationhelper.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/sequenceasvector.hxx>
+#include <comphelper/enumhelper.hxx>
+
+//_______________________________________________
+// other includes
+#include <rtl/logfile.hxx>
+
+namespace framework
+{
+
+static const ::rtl::OUString CFGPATH_FACTORIES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
+static const ::rtl::OUString MODULEPROP_IDENTIFIER = ::rtl::OUString::createFromAscii("ooSetupFactoryModuleIdentifier" );
+
+/*-----------------------------------------------
+ 04.12.2003 09:32
+-----------------------------------------------*/
+DEFINE_XINTERFACE_7(ModuleManager ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::container::XNameReplace ),
+ DIRECT_INTERFACE(css::container::XNameAccess ),
+ DIRECT_INTERFACE(css::container::XElementAccess ),
+ DIRECT_INTERFACE(css::container::XContainerQuery),
+ DIRECT_INTERFACE(css::frame::XModuleManager ))
+
+/*-----------------------------------------------
+ 04.12.2003 09:32
+-----------------------------------------------*/
+DEFINE_XTYPEPROVIDER_7(ModuleManager ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::container::XNameReplace ,
+ css::container::XNameAccess ,
+ css::container::XElementAccess ,
+ css::container::XContainerQuery,
+ css::frame::XModuleManager )
+
+/*-----------------------------------------------
+ 04.12.2003 09:35
+-----------------------------------------------*/
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(ModuleManager ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_MODULEMANAGER ,
+ IMPLEMENTATIONNAME_MODULEMANAGER)
+
+/*-----------------------------------------------
+ 04.12.2003 09:35
+-----------------------------------------------*/
+DEFINE_INIT_SERVICE(
+ ModuleManager,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ }
+ )
+
+/*-----------------------------------------------
+ 04.12.2003 09:30
+-----------------------------------------------*/
+ModuleManager::ModuleManager(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase( )
+ , m_xSMGR (xSMGR)
+{
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:59
+-----------------------------------------------*/
+ModuleManager::~ModuleManager()
+{
+ if (m_xCFG.is())
+ m_xCFG.clear();
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:02
+-----------------------------------------------*/
+::rtl::OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule)
+ throw(css::lang::IllegalArgumentException,
+ css::frame::UnknownModuleException,
+ css::uno::RuntimeException )
+{
+ // valid parameter?
+ css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY);
+ css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY);
+
+ if (
+ (!xFrame.is() ) &&
+ (!xWindow.is() ) &&
+ (!xController.is()) &&
+ (!xModel.is() )
+ )
+ {
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Given module is not a frame nor a window, controller or model."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1);
+ }
+
+ if (xFrame.is())
+ {
+ xController = xFrame->getController();
+ xWindow = xFrame->getComponentWindow();
+ }
+ if (xController.is())
+ xModel = xController->getModel();
+
+ // modules are implemented by the deepest component in hierarchy ...
+ // Means: model -> controller -> window
+ // No fallbacks to higher components are allowed !
+ // Note : A frame provides access to module components only ... but it's not a module by himself.
+
+ ::rtl::OUString sModule;
+ if (xModel.is())
+ sModule = implts_identify(xModel);
+ else
+ if (xController.is())
+ sModule = implts_identify(xController);
+ else
+ if (xWindow.is())
+ sModule = implts_identify(xWindow);
+
+ if (sModule.getLength() < 1)
+ throw css::frame::UnknownModuleException(
+ ::rtl::OUString::createFromAscii("Cant find suitable module for the given component."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ return sModule;
+}
+
+/*-----------------------------------------------
+ 08.03.2007 09:55
+-----------------------------------------------*/
+void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName ,
+ const css::uno::Any& aValue)
+ throw (css::lang::IllegalArgumentException ,
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException ,
+ css::uno::RuntimeException )
+{
+ ::comphelper::SequenceAsHashMap lProps(aValue);
+ if (lProps.empty() )
+ {
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("No properties given to replace part of module."),
+ static_cast< css::container::XNameAccess* >(this),
+ 2);
+ }
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // get access to the element
+ // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further
+ // it cache it as a member of this module manager instance. If we change some props there ... but dont
+ // flush changes (because an error occured) we will read them later. If we use a different config access
+ // we can close it without a flush ... and our read data wont be affected .-)
+ css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig(
+ xSMGR,
+ CFGPATH_FACTORIES,
+ ::comphelper::ConfigurationHelper::E_STANDARD);
+ css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameReplace > xModule ;
+
+ xModules->getByName(sName) >>= xModule;
+ if (!xModule.is())
+ {
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."),
+ static_cast< css::container::XNameAccess* >(this));
+ }
+
+ ::comphelper::SequenceAsHashMap::const_iterator pProp;
+ for ( pProp = lProps.begin();
+ pProp != lProps.end() ;
+ ++pProp )
+ {
+ const ::rtl::OUString& sPropName = pProp->first;
+ const css::uno::Any& aPropValue = pProp->second;
+
+ // let "NoSuchElementException" out ! We support the same API ...
+ // and without a flush() at the end all changed data before will be ignored !
+ xModule->replaceByName(sPropName, aPropValue);
+ }
+
+ ::comphelper::ConfigurationHelper::flush(xCfg);
+}
+
+/*-----------------------------------------------
+ 10.12.2003 12:05
+-----------------------------------------------*/
+css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName)
+ throw(css::container::NoSuchElementException,
+ css::lang::WrappedTargetException ,
+ css::uno::RuntimeException )
+{
+ // get access to the element
+ css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
+ css::uno::Reference< css::container::XNameAccess > xModule;
+ xCFG->getByName(sName) >>= xModule;
+ if (!xModule.is())
+ {
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."),
+ static_cast< css::container::XNameAccess* >(this));
+ }
+
+ // convert it to seq< PropertyValue >
+ const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames();
+ ::comphelper::SequenceAsHashMap lProps ;
+ sal_Int32 c = lPropNames.getLength();
+ sal_Int32 i = 0;
+
+ lProps[MODULEPROP_IDENTIFIER] <<= sName;
+ for (i=0; i<c; ++i)
+ {
+ const ::rtl::OUString& sPropName = lPropNames[i];
+ lProps[sPropName] = xModule->getByName(sPropName);
+ }
+
+ return css::uno::makeAny(lProps.getAsConstPropertyValueList());
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:58
+-----------------------------------------------*/
+css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames()
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
+ return xCFG->getElementNames();
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:57
+-----------------------------------------------*/
+sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName)
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
+ return xCFG->hasByName(sName);
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:35
+-----------------------------------------------*/
+css::uno::Type SAL_CALL ModuleManager::getElementType()
+ throw(css::uno::RuntimeException)
+{
+ return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0);
+}
+
+/*-----------------------------------------------
+ 10.12.2003 11:56
+-----------------------------------------------*/
+sal_Bool SAL_CALL ModuleManager::hasElements()
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
+ return xCFG->hasElements();
+}
+
+/*-----------------------------------------------
+ 07.03.2007 12:55
+-----------------------------------------------*/
+css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&)
+ throw(css::uno::RuntimeException)
+{
+ return css::uno::Reference< css::container::XEnumeration >();
+}
+
+/*-----------------------------------------------
+ 07.03.2007 12:55
+-----------------------------------------------*/
+css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
+ throw(css::uno::RuntimeException)
+{
+ ::comphelper::SequenceAsHashMap lSearchProps (lProperties);
+ css::uno::Sequence< ::rtl::OUString > lModules = getElementNames();
+ sal_Int32 c = lModules.getLength();
+ sal_Int32 i = 0;
+ ::comphelper::SequenceAsVector< css::uno::Any > lResult ;
+
+ for (i=0; i<c; ++i)
+ {
+ try
+ {
+ const ::rtl::OUString& sModule = lModules[i];
+ ::comphelper::SequenceAsHashMap lModuleProps = getByName(sModule);
+
+ if (lModuleProps.match(lSearchProps))
+ lResult.push_back(css::uno::makeAny(lModuleProps.getAsConstPropertyValueList()));
+ }
+ catch(const css::uno::Exception&)
+ {}
+ }
+
+ ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lResult.getAsConstList());
+ css::uno::Reference< css::container::XEnumeration > xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW);
+ return xEnum;
+}
+
+/*-----------------------------------------------
+ 14.12.2003 09:45
+-----------------------------------------------*/
+css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ if (m_xCFG.is())
+ return m_xCFG;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::uno::XInterface > xCfg;
+ try
+ {
+ xCfg = ::comphelper::ConfigurationHelper::openConfig(
+ xSMGR,
+ CFGPATH_FACTORIES,
+ ::comphelper::ConfigurationHelper::E_READONLY);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { xCfg.clear(); }
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW);
+ return m_xCFG;
+ // <- SAFE ----------------------------------
+}
+
+/*-----------------------------------------------
+ 30.01.2004 07:54
+-----------------------------------------------*/
+::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent)
+{
+ // Search for an optional (!) interface XModule first.
+ // Its used to overrule an existing service name. Used e.g. by our database form designer
+ // which uses a writer module internaly.
+ css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY);
+ if (xModule.is())
+ return xModule->getIdentifier();
+
+ // detect modules in a generic way ...
+ // comparing service names with configured entries ...
+ css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY);
+ if (!xInfo.is())
+ return ::rtl::OUString();
+
+ const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames();
+ const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray();
+ sal_Int32 c = lKnownModules.getLength();
+ sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ if (xInfo->supportsService(pKnownModules[i]))
+ return pKnownModules[i];
+ }
+
+ return ::rtl::OUString();
+}
+
+} // namespace framework
diff --git a/framework/source/services/pathsettings.cxx b/framework/source/services/pathsettings.cxx
new file mode 100644
index 000000000000..baf3a785c5e6
--- /dev/null
+++ b/framework/source/services/pathsettings.cxx
@@ -0,0 +1,1187 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+// ______________________________________________
+// my own includes
+
+/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble
+ with solaris headers ...
+*/
+#include <vector>
+#include <services/pathsettings.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <services.h>
+
+// ______________________________________________
+// interface includes
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XProperty.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XChangesNotifier.hpp>
+
+// ______________________________________________
+// includes of other projects
+#include <tools/urlobj.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/logfile.hxx>
+
+#include <comphelper/configurationhelper.hxx>
+#include <unotools/configpathes.hxx>
+
+#include <fwkdllapi.h>
+
+// ______________________________________________
+// non exported const
+
+#define CFG_READONLY_DEFAULT sal_False
+
+const ::rtl::OUString CFGPROP_INTERNALPATHES = ::rtl::OUString::createFromAscii("InternalPaths");
+const ::rtl::OUString CFGPROP_USERPATHES = ::rtl::OUString::createFromAscii("UserPaths" );
+const ::rtl::OUString CFGPROP_WRITEPATH = ::rtl::OUString::createFromAscii("WritePath" );
+const ::rtl::OUString CFGPROP_ISSINGLEPATH = ::rtl::OUString::createFromAscii("IsSinglePath" );
+
+/*
+ 0 : old style "Template" string using ";" as seperator
+ 1 : internal paths "Template_internal" string list
+ 2 : user paths "Template_user" string list
+ 3 : write path "Template_write" string
+ */
+
+const ::rtl::OUString POSTFIX_INTERNAL_PATHES = ::rtl::OUString::createFromAscii("_internal");
+const ::rtl::OUString POSTFIX_USER_PATHES = ::rtl::OUString::createFromAscii("_user" );
+const ::rtl::OUString POSTFIX_WRITE_PATH = ::rtl::OUString::createFromAscii("_writable");
+
+const sal_Int32 IDGROUP_OLDSTYLE = 0;
+const sal_Int32 IDGROUP_INTERNAL_PATHES = 1;
+const sal_Int32 IDGROUP_USER_PATHES = 2;
+const sal_Int32 IDGROUP_WRITE_PATH = 3;
+
+const sal_Int32 IDGROUP_COUNT = 4;
+
+sal_Int32 impl_getPropGroup(sal_Int32 nID)
+{
+ return (nID % IDGROUP_COUNT);
+}
+
+// ______________________________________________
+// namespace
+
+namespace framework
+{
+
+//-----------------------------------------------------------------------------
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XINTERFACE_7 ( PathSettings ,
+ OWeakObject ,
+ DIRECT_INTERFACE ( css::lang::XTypeProvider ),
+ DIRECT_INTERFACE ( css::lang::XServiceInfo ),
+ DERIVED_INTERFACE( css::lang::XEventListener, css::util::XChangesListener),
+ DIRECT_INTERFACE ( css::util::XChangesListener ),
+ DIRECT_INTERFACE ( css::beans::XPropertySet ),
+ DIRECT_INTERFACE ( css::beans::XFastPropertySet ),
+ DIRECT_INTERFACE ( css::beans::XMultiPropertySet )
+ )
+
+DEFINE_XTYPEPROVIDER_7 ( PathSettings ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::lang::XEventListener ,
+ css::util::XChangesListener ,
+ css::beans::XPropertySet ,
+ css::beans::XFastPropertySet ,
+ css::beans::XMultiPropertySet
+ )
+
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( PathSettings ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_PATHSETTINGS ,
+ IMPLEMENTATIONNAME_PATHSETTINGS
+ )
+
+DEFINE_INIT_SERVICE ( PathSettings,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+
+ // fill cache
+ impl_readAll();
+ }
+ )
+
+//-----------------------------------------------------------------------------
+PathSettings::PathSettings( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
+ // Init baseclasses first
+ // Attention: Don't change order of initialization!
+ // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
+ // We must garant right initialization and a valid value of this to initialize other baseclasses!
+ : ThreadHelpBase()
+ , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >(m_aLock.getShareableOslMutex())
+ , ::cppu::OPropertySetHelper(*(static_cast< ::cppu::OBroadcastHelper* >(this)))
+ , ::cppu::OWeakObject()
+ // Init member
+ , m_xSMGR (xSMGR)
+ , m_pPropHelp(0 )
+ , m_bIgnoreEvents(sal_False)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::PathSettings" );
+}
+
+//-----------------------------------------------------------------------------
+PathSettings::~PathSettings()
+{
+ if (m_pPropHelp)
+ delete m_pPropHelp;
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL PathSettings::changesOccurred(const css::util::ChangesEvent& aEvent)
+ throw (css::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::changesOccurred" );
+ /*
+ if (m_bIgnoreEvents)
+ return;
+ */
+
+ sal_Int32 c = aEvent.Changes.getLength();
+ sal_Int32 i = 0;
+ sal_Bool bUpdateDescriptor = sal_False;
+
+ for (i=0; i<c; ++i)
+ {
+ const css::util::ElementChange& aChange = aEvent.Changes[i];
+
+ ::rtl::OUString sChanged;
+ aChange.Accessor >>= sChanged;
+
+ ::rtl::OUString sPath = ::utl::extractFirstFromConfigurationPath(sChanged);
+ if (sPath.getLength())
+ {
+ PathSettings::EChangeOp eOp = impl_updatePath(sPath, sal_True);
+ if (
+ (eOp == PathSettings::E_ADDED ) ||
+ (eOp == PathSettings::E_REMOVED)
+ )
+ bUpdateDescriptor = sal_True;
+ }
+ }
+
+ if (bUpdateDescriptor)
+ impl_rebuildPropertyDescriptor();
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL PathSettings::disposing(const css::lang::EventObject& aSource)
+ throw(css::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::disposing" );
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ if (aSource.Source == m_xCfgNew)
+ m_xCfgNew.clear();
+
+ aWriteLock.unlock();
+ // <- SAFE
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_readAll()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_readAll" );
+ RTL_LOGFILE_CONTEXT(aLog, "framework (as96863) ::PathSettings::load config (all)");
+
+ // TODO think about me
+ css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
+ css::uno::Sequence< ::rtl::OUString > lPaths = xCfg->getElementNames();
+
+ sal_Int32 c = lPaths.getLength();
+ sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ const ::rtl::OUString& sPath = lPaths[i];
+ impl_updatePath(sPath, sal_False);
+ }
+
+ impl_rebuildPropertyDescriptor();
+}
+
+//-----------------------------------------------------------------------------
+// NO substitution here ! It's done outside ...
+OUStringList PathSettings::impl_readOldFormat(const ::rtl::OUString& sPath)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_readOldFormat" );
+ css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
+ OUStringList aPathVal;
+
+ if( xCfg->hasByName(sPath) )
+ {
+ css::uno::Any aVal( xCfg->getByName(sPath) );
+
+ ::rtl::OUString sStringVal;
+ css::uno::Sequence< ::rtl::OUString > lStringListVal;
+
+ if (aVal >>= sStringVal)
+ {
+ aPathVal.push_back(sStringVal);
+ }
+ else if (aVal >>= lStringListVal)
+ {
+ aPathVal << lStringListVal;
+ }
+ }
+
+ return aPathVal;
+}
+
+//-----------------------------------------------------------------------------
+// NO substitution here ! It's done outside ...
+PathSettings::PathInfo PathSettings::impl_readNewFormat(const ::rtl::OUString& sPath)
+{
+ css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
+
+ // get access to the "queried" path
+ css::uno::Reference< css::container::XNameAccess > xPath;
+ xCfg->getByName(sPath) >>= xPath;
+
+ PathSettings::PathInfo aPathVal;
+
+ // read internal path list
+ css::uno::Reference< css::container::XNameAccess > xIPath;
+ xPath->getByName(CFGPROP_INTERNALPATHES) >>= xIPath;
+ aPathVal.lInternalPaths << xIPath->getElementNames();
+
+ // read user defined path list
+ aPathVal.lUserPaths << xPath->getByName(CFGPROP_USERPATHES);
+
+ // read the writeable path
+ xPath->getByName(CFGPROP_WRITEPATH) >>= aPathVal.sWritePath;
+
+ // read state props
+ xPath->getByName(CFGPROP_ISSINGLEPATH) >>= aPathVal.bIsSinglePath;
+
+ // analyze finalized/mandatory states
+ aPathVal.bIsReadonly = sal_False;
+ css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
+ if (xInfo.is())
+ {
+ css::beans::Property aInfo = xInfo->getAsProperty();
+ sal_Bool bFinalized = ((aInfo.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
+ //sal_Bool bMandatory = ((aInfo.Attributes & css::beans::PropertyAttribute::REMOVEABLE) != css::beans::PropertyAttribute::REMOVEABLE);
+
+ // Note: Till we support finalized / mandatory on our API more in detail we handle
+ // all states simple as READONLY ! But because all realy needed pathes are "mandatory" by default
+ // we have to handle "finalized" as the real "readonly" indicator .
+ aPathVal.bIsReadonly = bFinalized;
+ }
+
+ return aPathVal;
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_storePath(const PathSettings::PathInfo& aPath)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_storePath" );
+ m_bIgnoreEvents = sal_True;
+
+ css::uno::Reference< css::container::XNameAccess > xCfgNew = fa_getCfgNew();
+ css::uno::Reference< css::container::XNameAccess > xCfgOld = fa_getCfgOld();
+
+ // try to replace path-parts with well known and uspported variables.
+ // So an office can be moved easialy to another location without loosing
+ // it's related pathes.
+ PathInfo aResubstPath(aPath);
+ impl_subst(aResubstPath, sal_True);
+
+ // update new configuration
+ if (! aResubstPath.bIsSinglePath)
+ {
+ ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
+ aResubstPath.sPathName,
+ CFGPROP_USERPATHES,
+ css::uno::makeAny(aResubstPath.lUserPaths.getAsConstList()));
+ }
+
+ ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
+ aResubstPath.sPathName,
+ CFGPROP_WRITEPATH,
+ css::uno::makeAny(aResubstPath.sWritePath));
+
+ ::comphelper::ConfigurationHelper::flush(xCfgNew);
+
+ // remove the whole path from the old configuration !
+ // Otherwise we cant make sure that the diff between new and old configuration
+ // on loading time realy represent an user setting !!!
+
+ // Check if the given path exists inside the old configuration.
+ // Because our new configuration knows more then the list of old pathes ... !
+ if (xCfgOld->hasByName(aResubstPath.sPathName))
+ {
+ css::uno::Reference< css::beans::XPropertySet > xProps(xCfgOld, css::uno::UNO_QUERY_THROW);
+ xProps->setPropertyValue(aResubstPath.sPathName, css::uno::Any());
+ ::comphelper::ConfigurationHelper::flush(xCfgOld);
+ }
+
+ m_bIgnoreEvents = sal_False;
+}
+
+//-----------------------------------------------------------------------------
+#ifdef MIGRATE_OLD_USER_PATHES
+void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
+ const OUStringList& lOld )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_mergeOldUserPaths" );
+ OUStringList::const_iterator pIt;
+ for ( pIt = lOld.begin();
+ pIt != lOld.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& sOld = *pIt;
+
+ if (rPath.bIsSinglePath)
+ {
+ LOG_ASSERT2(lOld.size()>1, "PathSettings::impl_mergeOldUserPaths()", "Single path has more then one path value inside old configuration (Common.xcu)!")
+ if (! rPath.sWritePath.equals(sOld))
+ rPath.sWritePath = sOld;
+ }
+ else
+ {
+ if (
+ ( rPath.lInternalPaths.findConst(sOld) == rPath.lInternalPaths.end()) &&
+ ( rPath.lUserPaths.findConst(sOld) == rPath.lUserPaths.end() ) &&
+ (! rPath.sWritePath.equals(sOld) )
+ )
+ rPath.lUserPaths.push_back(sOld);
+ }
+ }
+}
+#endif // MIGRATE_OLD_USER_PATHES
+
+//-----------------------------------------------------------------------------
+PathSettings::EChangeOp PathSettings::impl_updatePath(const ::rtl::OUString& sPath ,
+ sal_Bool bNotifyListener)
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ PathSettings::PathInfo* pPathOld = 0;
+ PathSettings::PathInfo* pPathNew = 0;
+ PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
+ PathSettings::PathInfo aPath;
+
+ try
+ {
+ aPath = impl_readNewFormat(sPath);
+ aPath.sPathName = sPath;
+ // replace all might existing variables with real values
+ // Do it before these old pathes will be compared against the
+ // new path configuration. Otherwise some striungs uses different variables ... but substitution
+ // will produce strings with same content (because some variables are redundant!)
+ impl_subst(aPath, sal_False);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::container::NoSuchElementException&)
+ { eOp = PathSettings::E_REMOVED; }
+ catch(const css::uno::Exception& exAny)
+ { throw exAny; }
+
+ #ifdef MIGRATE_OLD_USER_PATHES
+ try
+ {
+ // migration of old user defined values on demand
+ // can be disabled for a new major
+ OUStringList lOldVals = impl_readOldFormat(sPath);
+ // replace all might existing variables with real values
+ // Do it before these old pathes will be compared against the
+ // new path configuration. Otherwise some striungs uses different variables ... but substitution
+ // will produce strings with same content (because some variables are redundant!)
+ impl_subst(lOldVals, fa_getSubstitution(), sal_False);
+ impl_mergeOldUserPaths(aPath, lOldVals);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ // Normal(!) exceptions can be ignored!
+ // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
+ // we cant find a value for it inside the "old" configuration. So a NoSuchElementException
+ // will be normal .-)
+ catch(const css::uno::Exception&)
+ {}
+ #endif // MIGRATE_OLD_USER_PATHES
+
+ PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
+ if (eOp == PathSettings::E_UNDEFINED)
+ {
+ if (pPath != m_lPaths.end())
+ eOp = PathSettings::E_CHANGED;
+ else
+ eOp = PathSettings::E_ADDED;
+ }
+
+ switch(eOp)
+ {
+ case PathSettings::E_ADDED :
+ {
+ if (bNotifyListener)
+ {
+ pPathOld = 0;
+ pPathNew = &aPath;
+ impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
+ }
+ m_lPaths[sPath] = aPath;
+ }
+ break;
+
+ case PathSettings::E_CHANGED :
+ {
+ if (bNotifyListener)
+ {
+ pPathOld = &(pPath->second);
+ pPathNew = &aPath;
+ impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
+ }
+ m_lPaths[sPath] = aPath;
+ }
+ break;
+
+ case PathSettings::E_REMOVED :
+ {
+ if (pPath != m_lPaths.end())
+ {
+ if (bNotifyListener)
+ {
+ pPathOld = &(pPath->second);
+ pPathNew = 0;
+ impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
+ }
+ m_lPaths.erase(pPath);
+ }
+ }
+ break;
+
+ default: // to let compiler be happy
+ break;
+ }
+
+ return eOp;
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Sequence< sal_Int32 > PathSettings::impl_mapPathName2IDList(const ::rtl::OUString& sPath)
+{
+ ::rtl::OUString sOldStyleProp = sPath;
+ ::rtl::OUString sInternalProp = sPath+POSTFIX_INTERNAL_PATHES;
+ ::rtl::OUString sUserProp = sPath+POSTFIX_USER_PATHES;
+ ::rtl::OUString sWriteProp = sPath+POSTFIX_WRITE_PATH;
+
+ // Attention: The default set of IDs is fix and must follow these schema.
+ // Otherwhise the outside code ant work for new added properties.
+ // Why ?
+ // The outside code must fire N events for every changed property.
+ // And the knowing about packaging of variables of the structure PathInfo
+ // follow these group IDs ! But if such ID isnt in the range of [0..IDGROUP_COUNT]
+ // the outside cant determine the right group ... and cant fire the right events .-)
+
+ css::uno::Sequence< sal_Int32 > lIDs(IDGROUP_COUNT);
+ lIDs[0] = IDGROUP_OLDSTYLE ;
+ lIDs[1] = IDGROUP_INTERNAL_PATHES;
+ lIDs[2] = IDGROUP_USER_PATHES ;
+ lIDs[3] = IDGROUP_WRITE_PATH ;
+
+ sal_Int32 c = m_lPropDesc.getLength();
+ sal_Int32 i = 0;
+ for (i=0; i<c; ++i)
+ {
+ const css::beans::Property& rProp = m_lPropDesc[i];
+
+ if (rProp.Name.equals(sOldStyleProp))
+ lIDs[IDGROUP_OLDSTYLE] = rProp.Handle;
+ else
+ if (rProp.Name.equals(sInternalProp))
+ lIDs[IDGROUP_INTERNAL_PATHES] = rProp.Handle;
+ else
+ if (rProp.Name.equals(sUserProp))
+ lIDs[IDGROUP_USER_PATHES] = rProp.Handle;
+ else
+ if (rProp.Name.equals(sWriteProp))
+ lIDs[IDGROUP_WRITE_PATH] = rProp.Handle;
+ }
+
+ return lIDs;
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp /*eOp*/ ,
+ const ::rtl::OUString& sPath ,
+ const PathSettings::PathInfo* pPathOld,
+ const PathSettings::PathInfo* pPathNew)
+{
+ css::uno::Sequence< sal_Int32 > lHandles(1);
+ css::uno::Sequence< css::uno::Any > lOldVals(1);
+ css::uno::Sequence< css::uno::Any > lNewVals(1);
+
+ css::uno::Sequence< sal_Int32 > lIDs = impl_mapPathName2IDList(sPath);
+ sal_Int32 c = lIDs.getLength();
+ sal_Int32 i = 0;
+ sal_Int32 nMaxID = m_lPropDesc.getLength()-1;
+ for (i=0; i<c; ++i)
+ {
+ sal_Int32 nID = lIDs[i];
+
+ if (
+ (nID < 0 ) ||
+ (nID > nMaxID)
+ )
+ continue;
+
+ lHandles[0] = nID;
+ switch(impl_getPropGroup(nID))
+ {
+ case IDGROUP_OLDSTYLE :
+ {
+ if (pPathOld)
+ {
+ ::rtl::OUString sVal = impl_convertPath2OldStyle(*pPathOld);
+ lOldVals[0] <<= sVal;
+ }
+ if (pPathNew)
+ {
+ ::rtl::OUString sVal = impl_convertPath2OldStyle(*pPathNew);
+ lNewVals[0] <<= sVal;
+ }
+ }
+ break;
+
+ case IDGROUP_INTERNAL_PATHES :
+ {
+ if (pPathOld)
+ lOldVals[0] <<= pPathOld->lInternalPaths.getAsConstList();
+ if (pPathNew)
+ lNewVals[0] <<= pPathNew->lInternalPaths.getAsConstList();
+ }
+ break;
+
+ case IDGROUP_USER_PATHES :
+ {
+ if (pPathOld)
+ lOldVals[0] <<= pPathOld->lUserPaths.getAsConstList();
+ if (pPathNew)
+ lNewVals[0] <<= pPathNew->lUserPaths.getAsConstList();
+ }
+ break;
+
+ case IDGROUP_WRITE_PATH :
+ {
+ if (pPathOld)
+ lOldVals[0] <<= pPathOld->sWritePath;
+ if (pPathNew)
+ lNewVals[0] <<= pPathNew->sWritePath;
+ }
+ break;
+ }
+
+ fire(lHandles.getArray(),
+ lNewVals.getArray(),
+ lOldVals.getArray(),
+ 1,
+ sal_False);
+ }
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_subst( OUStringList& lVals ,
+ const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
+ sal_Bool bReSubst)
+{
+ OUStringList::iterator pIt;
+
+ for ( pIt = lVals.begin();
+ pIt != lVals.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& sOld = *pIt;
+ ::rtl::OUString sNew ;
+ if (bReSubst)
+ sNew = xSubst->reSubstituteVariables(sOld);
+ else
+ sNew = xSubst->substituteVariables(sOld, sal_False);
+
+ *pIt = sNew;
+ }
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
+ sal_Bool bReSubst)
+{
+ css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
+
+ impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
+ impl_subst(aPath.lUserPaths , xSubst, bReSubst);
+ if (bReSubst)
+ aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
+ else
+ aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, sal_False);
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
+{
+ OUStringList::const_iterator pIt;
+ OUStringList lTemp;
+ lTemp.reserve(rPath.lInternalPaths.size() + rPath.lUserPaths.size() + 1);
+
+ for ( pIt = rPath.lInternalPaths.begin();
+ pIt != rPath.lInternalPaths.end() ;
+ ++pIt )
+ {
+ lTemp.push_back(*pIt);
+ }
+ for ( pIt = rPath.lUserPaths.begin();
+ pIt != rPath.lUserPaths.end() ;
+ ++pIt )
+ {
+ lTemp.push_back(*pIt);
+ }
+
+ if (rPath.sWritePath.getLength() > 0)
+ lTemp.push_back(rPath.sWritePath);
+
+ ::rtl::OUStringBuffer sPathVal(256);
+ for ( pIt = lTemp.begin();
+ pIt != lTemp.end() ;
+ )
+ {
+ sPathVal.append(*pIt);
+ ++pIt;
+ if (pIt != lTemp.end())
+ sPathVal.appendAscii(";");
+ }
+
+ return sPathVal.makeStringAndClear();
+}
+
+//-----------------------------------------------------------------------------
+OUStringList PathSettings::impl_convertOldStyle2Path(const ::rtl::OUString& sOldStylePath) const
+{
+ OUStringList lList;
+ sal_Int32 nToken = 0;
+ do
+ {
+ ::rtl::OUString sToken = sOldStylePath.getToken(0, ';', nToken);
+ if (sToken.getLength())
+ lList.push_back(sToken);
+ }
+ while(nToken >= 0);
+
+ return lList;
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
+ OUStringList& lList)
+{
+ OUStringList::const_iterator pIt;
+ for ( pIt = rPath.lInternalPaths.begin();
+ pIt != rPath.lInternalPaths.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& rItem = *pIt;
+ OUStringList::iterator pItem = lList.find(rItem);
+ if (pItem != lList.end())
+ lList.erase(pItem);
+ }
+ for ( pIt = rPath.lUserPaths.begin();
+ pIt != rPath.lUserPaths.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& rItem = *pIt;
+ OUStringList::iterator pItem = lList.find(rItem);
+ if (pItem != lList.end())
+ lList.erase(pItem);
+ }
+
+ OUStringList::iterator pItem = lList.find(rPath.sWritePath);
+ if (pItem != lList.end())
+ lList.erase(pItem);
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_rebuildPropertyDescriptor()
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ sal_Int32 c = (sal_Int32)m_lPaths.size();
+ sal_Int32 i = 0;
+ m_lPropDesc.realloc(c*IDGROUP_COUNT);
+
+ PathHash::const_iterator pIt;
+ for ( pIt = m_lPaths.begin();
+ pIt != m_lPaths.end() ;
+ ++pIt )
+ {
+ const PathSettings::PathInfo& rPath = pIt->second;
+ css::beans::Property* pProp = 0;
+
+ pProp = &(m_lPropDesc[i]);
+ pProp->Name = rPath.sPathName;
+ pProp->Handle = i;
+ pProp->Type = ::getCppuType((::rtl::OUString*)0);
+ pProp->Attributes = css::beans::PropertyAttribute::BOUND;
+ if (rPath.bIsReadonly)
+ pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
+ ++i;
+
+ pProp = &(m_lPropDesc[i]);
+ pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHES;
+ pProp->Handle = i;
+ pProp->Type = ::getCppuType((css::uno::Sequence< ::rtl::OUString >*)0);
+ pProp->Attributes = css::beans::PropertyAttribute::BOUND |
+ css::beans::PropertyAttribute::READONLY;
+ ++i;
+
+ pProp = &(m_lPropDesc[i]);
+ pProp->Name = rPath.sPathName+POSTFIX_USER_PATHES;
+ pProp->Handle = i;
+ pProp->Type = ::getCppuType((css::uno::Sequence< ::rtl::OUString >*)0);
+ pProp->Attributes = css::beans::PropertyAttribute::BOUND;
+ if (rPath.bIsReadonly)
+ pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
+ ++i;
+
+ pProp = &(m_lPropDesc[i]);
+ pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
+ pProp->Handle = i;
+ pProp->Type = ::getCppuType((::rtl::OUString*)0);
+ pProp->Attributes = css::beans::PropertyAttribute::BOUND;
+ if (rPath.bIsReadonly)
+ pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
+ ++i;
+ }
+
+ if (m_pPropHelp)
+ delete m_pPropHelp;
+ m_pPropHelp = new ::cppu::OPropertyArrayHelper(m_lPropDesc, sal_False); // false => not sorted ... must be done inside helper
+
+ aWriteLock.unlock();
+ // <- SAFE
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
+{
+ const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
+ if (! pPath)
+ throw css::container::NoSuchElementException();
+
+ css::uno::Any aVal;
+ switch(impl_getPropGroup(nID))
+ {
+ case IDGROUP_OLDSTYLE :
+ {
+ ::rtl::OUString sVal = impl_convertPath2OldStyle(*pPath);
+ aVal <<= sVal;
+ }
+ break;
+
+ case IDGROUP_INTERNAL_PATHES :
+ {
+ aVal <<= pPath->lInternalPaths.getAsConstList();
+ }
+ break;
+
+ case IDGROUP_USER_PATHES :
+ {
+ aVal <<= pPath->lUserPaths.getAsConstList();
+ }
+ break;
+
+ case IDGROUP_WRITE_PATH :
+ {
+ aVal <<= pPath->sWritePath;
+ }
+ break;
+ }
+
+ return aVal;
+}
+
+//-----------------------------------------------------------------------------
+void PathSettings::impl_setPathValue( sal_Int32 nID ,
+ const css::uno::Any& aVal)
+{
+ PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
+ if (! pOrgPath)
+ throw css::container::NoSuchElementException();
+
+ // We work on a copied path ... so we can be sure that errors during this operation
+ // does not make our internal cache invalid .-)
+ PathSettings::PathInfo aChangePath(*pOrgPath);
+
+ switch(impl_getPropGroup(nID))
+ {
+ case IDGROUP_OLDSTYLE :
+ {
+ ::rtl::OUString sVal;
+ aVal >>= sVal;
+ OUStringList lList = impl_convertOldStyle2Path(sVal);
+ impl_subst(lList, fa_getSubstitution(), sal_False);
+ impl_purgeKnownPaths(aChangePath, lList);
+ if (! impl_isValidPath(lList))
+ throw css::lang::IllegalArgumentException();
+
+ if (aChangePath.bIsSinglePath)
+ {
+ LOG_ASSERT2(lList.size()>1, "PathSettings::impl_setPathValue()", "You try to set more then path value for a defined SINGLE_PATH!")
+ if ( !lList.empty() )
+ aChangePath.sWritePath = *(lList.begin());
+ else
+ aChangePath.sWritePath = ::rtl::OUString();
+ }
+ else
+ {
+ OUStringList::const_iterator pIt;
+ for ( pIt = lList.begin();
+ pIt != lList.end() ;
+ ++pIt )
+ {
+ aChangePath.lUserPaths.push_back(*pIt);
+ }
+ }
+ }
+ break;
+
+ case IDGROUP_INTERNAL_PATHES :
+ {
+ if (aChangePath.bIsSinglePath)
+ {
+ ::rtl::OUStringBuffer sMsg(256);
+ sMsg.appendAscii("The path '" );
+ sMsg.append (aChangePath.sPathName);
+ sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
+ throw css::uno::Exception(sMsg.makeStringAndClear(),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ OUStringList lList;
+ lList << aVal;
+ if (! impl_isValidPath(lList))
+ throw css::lang::IllegalArgumentException();
+ aChangePath.lInternalPaths = lList;
+ }
+ break;
+
+ case IDGROUP_USER_PATHES :
+ {
+ if (aChangePath.bIsSinglePath)
+ {
+ ::rtl::OUStringBuffer sMsg(256);
+ sMsg.appendAscii("The path '" );
+ sMsg.append (aChangePath.sPathName);
+ sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
+ throw css::uno::Exception(sMsg.makeStringAndClear(),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ OUStringList lList;
+ lList << aVal;
+ if (! impl_isValidPath(lList))
+ throw css::lang::IllegalArgumentException();
+ aChangePath.lUserPaths = lList;
+ }
+ break;
+
+ case IDGROUP_WRITE_PATH :
+ {
+ ::rtl::OUString sVal;
+ aVal >>= sVal;
+ if (! impl_isValidPath(sVal))
+ throw css::lang::IllegalArgumentException();
+ aChangePath.sWritePath = sVal;
+ }
+ break;
+ }
+
+ // TODO check if path has at least one path value set
+ // At least it depends from the feature using this path, if an empty path list is allowed.
+ /*
+ if (impl_isPathEmpty(aChangePath))
+ {
+ ::rtl::OUStringBuffer sMsg(256);
+ sMsg.appendAscii("The path '" );
+ sMsg.append (aChangePath.sPathName);
+ sMsg.appendAscii("' is empty now ... Not a real good idea.");
+ throw css::uno::Exception(sMsg.makeStringAndClear(),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+ */
+
+ // first we should try to store the changed (copied!) path ...
+ // In case an error occure on saving time an exception is thrown ...
+ // If no exception occures we can update our internal cache (means
+ // we can overwrite pOrgPath !
+ impl_storePath(aChangePath);
+ pOrgPath->takeOver(aChangePath);
+}
+
+//-----------------------------------------------------------------------------
+sal_Bool PathSettings::impl_isValidPath(const OUStringList& lPath) const
+{
+ OUStringList::const_iterator pIt;
+ for ( pIt = lPath.begin();
+ pIt != lPath.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& rVal = *pIt;
+ if (! impl_isValidPath(rVal))
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+//-----------------------------------------------------------------------------
+sal_Bool PathSettings::impl_isValidPath(const ::rtl::OUString& sPath) const
+{
+ // allow empty path to reset a path.
+// idea by LLA to support empty pathes
+// if (sPath.getLength() == 0)
+// {
+// return sal_True;
+// }
+
+ return (! INetURLObject(sPath).HasError());
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OUString impl_extractBaseFromPropName(const ::rtl::OUString& sPropName)
+{
+ sal_Int32 i = -1;
+
+ i = sPropName.indexOf(POSTFIX_INTERNAL_PATHES);
+ if (i > -1)
+ return sPropName.copy(0, i);
+ i = sPropName.indexOf(POSTFIX_USER_PATHES);
+ if (i > -1)
+ return sPropName.copy(0, i);
+ i = sPropName.indexOf(POSTFIX_WRITE_PATH);
+ if (i > -1)
+ return sPropName.copy(0, i);
+
+ return sPropName;
+}
+
+//-----------------------------------------------------------------------------
+PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+
+ if (nHandle > (m_lPropDesc.getLength()-1))
+ return 0;
+
+ const css::beans::Property& rProp = m_lPropDesc[nHandle];
+ ::rtl::OUString sProp = impl_extractBaseFromPropName(rProp.Name);
+ PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
+
+ if (rPath != m_lPaths.end())
+ return &(rPath->second);
+
+ return 0;
+ // <- SAFE
+}
+
+//-----------------------------------------------------------------------------
+const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+
+ if (nHandle > (m_lPropDesc.getLength()-1))
+ return 0;
+
+ const css::beans::Property& rProp = m_lPropDesc[nHandle];
+ ::rtl::OUString sProp = impl_extractBaseFromPropName(rProp.Name);
+ PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
+
+ if (rPath != m_lPaths.end())
+ return &(rPath->second);
+
+ return 0;
+ // <- SAFE
+}
+
+//-----------------------------------------------------------------------------
+sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
+ css::uno::Any& aOldValue ,
+ sal_Int32 nHandle ,
+ const css::uno::Any& aValue )
+ throw(css::lang::IllegalArgumentException)
+{
+ // throws NoSuchElementException !
+ css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
+
+ return PropHelper::willPropertyBeChanged(
+ aCurrentVal,
+ aValue,
+ aOldValue,
+ aConvertedValue);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
+ const css::uno::Any& aValue )
+ throw(css::uno::Exception)
+{
+ // throws NoSuchElement- and IllegalArgumentException !
+ impl_setPathValue(nHandle, aValue);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
+ sal_Int32 nHandle) const
+{
+ aValue = impl_getPathValue(nHandle);
+}
+
+//-----------------------------------------------------------------------------
+::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
+{
+ return *m_pPropHelp;
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
+ throw(css::uno::RuntimeException)
+{
+ return css::uno::Reference< css::beans::XPropertySetInfo >(createPropertySetInfo(getInfoHelper()));
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::util::XStringSubstitution > xSubst = m_xSubstitution;
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (! xSubst.is())
+ {
+ // create the needed substitution service.
+ // We must replace all used variables inside readed path values.
+ // In case we can't do so ... the whole office can't work realy.
+ // That's why it seams to be OK to throw a RuntimeException then.
+ xSubst = css::uno::Reference< css::util::XStringSubstitution >(
+ xSMGR->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES),
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xSubstitution = xSubst;
+ aWriteLock.unlock();
+ }
+
+ return xSubst;
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
+{
+ const static ::rtl::OUString CFG_NODE_OLD = ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/Path/Current");
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::container::XNameAccess > xCfg = m_xCfgOld;
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (! xCfg.is())
+ {
+ xCfg = css::uno::Reference< css::container::XNameAccess >(
+ ::comphelper::ConfigurationHelper::openConfig(
+ xSMGR,
+ CFG_NODE_OLD,
+ ::comphelper::ConfigurationHelper::E_STANDARD), // not readonly! Somtimes we need write access there !!!
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xCfgOld = xCfg;
+ aWriteLock.unlock();
+ }
+
+ return xCfg;
+}
+
+//-----------------------------------------------------------------------------
+css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
+{
+ const static ::rtl::OUString CFG_NODE_NEW = ::rtl::OUString::createFromAscii("org.openoffice.Office.Paths/Paths");
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::container::XNameAccess > xCfg = m_xCfgNew;
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (! xCfg.is())
+ {
+ xCfg = css::uno::Reference< css::container::XNameAccess >(
+ ::comphelper::ConfigurationHelper::openConfig(
+ xSMGR,
+ CFG_NODE_NEW,
+ ::comphelper::ConfigurationHelper::E_STANDARD),
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xCfgNew = xCfg;
+ aWriteLock.unlock();
+
+ css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
+ xBroadcaster->addChangesListener(static_cast< css::util::XChangesListener* >(this));
+ }
+
+ return xCfg;
+}
+
+} // namespace framework
diff --git a/framework/source/services/sessionlistener.cxx b/framework/source/services/sessionlistener.cxx
new file mode 100644
index 000000000000..42a2637f823e
--- /dev/null
+++ b/framework/source/services/sessionlistener.cxx
@@ -0,0 +1,368 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+//_______________________________________________
+// my own includes
+
+#ifndef __FRAMEWORK_SERVICES_TYPEDETECTION_HXX_
+#include <services/sessionlistener.hxx>
+#endif
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/resetableguard.hxx>
+#include <protocols.h>
+#include <services.h>
+
+#include <osl/thread.h>
+
+
+#include <vcl/svapp.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/tempfile.hxx>
+#include <unotools/tempfile.hxx>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <osl/time.h>
+#include <comphelper/processfactory.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/internaloptions.hxx>
+#include <stdio.h>
+//_______________________________________________
+// interface includes
+#include <com/sun/star/uno/Any.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+//_______________________________________________
+// includes of other projects
+
+//_______________________________________________
+// namespace
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+
+using namespace rtl;
+
+namespace framework{
+
+//_______________________________________________
+// non exported const
+
+//_______________________________________________
+// non exported definitions
+
+//_______________________________________________
+// declarations
+
+//***********************************************
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XINTERFACE_6(
+ SessionListener,
+ OWeakObject,
+ DIRECT_INTERFACE(css::lang::XTypeProvider),
+ DIRECT_INTERFACE(css::lang::XInitialization),
+ DIRECT_INTERFACE(css::frame::XSessionManagerListener),
+ DIRECT_INTERFACE(css::frame::XSessionManagerListener2),
+ DIRECT_INTERFACE(css::frame::XStatusListener),
+ DIRECT_INTERFACE(css::lang::XServiceInfo))
+
+DEFINE_XTYPEPROVIDER_5(
+ SessionListener,
+ css::lang::XTypeProvider,
+ css::lang::XInitialization,
+ css::frame::XSessionManagerListener2,
+ css::frame::XStatusListener,
+ css::lang::XServiceInfo)
+
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(
+ SessionListener,
+ cppu::OWeakObject,
+ SERVICENAME_SESSIONLISTENER,
+ IMPLEMENTATIONNAME_SESSIONLISTENER)
+
+DEFINE_INIT_SERVICE(SessionListener,
+ {
+ /* Add special code for initialization here, if you have to use your own instance
+ during your ctor is still in progress! */
+ }
+ )
+
+SessionListener::SessionListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
+ : ThreadHelpBase (&Application::GetSolarMutex())
+ , OWeakObject ( )
+ , m_xSMGR (xSMGR )
+ , m_bRestored( sal_False )
+ , m_bSessionStoreRequested( sal_False )
+ , m_bAllowUserInteractionOnQuit( sal_False )
+ , m_bTerminated( sal_False )
+{
+}
+
+SessionListener::~SessionListener()
+{
+ if (m_rSessionManager.is())
+ {
+ css::uno::Reference< XSessionManagerListener> me(this);
+ m_rSessionManager->removeSessionManagerListener(me);
+ }
+}
+
+void SessionListener::StoreSession( sal_Bool bAsync )
+{
+ ResetableGuard aGuard(m_aLock);
+ try
+ {
+ // xd create SERVICENAME_AUTORECOVERY -> XDispatch
+ // xd->dispatch("vnd.sun.star.autorecovery:/doSessionSave, async=bAsync
+ // on stop event m_rSessionManager->saveDone(this); in case of asynchronous call
+ // in case of synchronous call the caller should do saveDone() call himself!
+
+ css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
+ css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionSave");
+ xURLTransformer->parseStrict(aURL);
+
+ // in case of asynchronous call the notification will trigger saveDone()
+ if ( bAsync )
+ xDispatch->addStatusListener(this, aURL);
+
+ Sequence< PropertyValue > args(1);
+ args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(bAsync),PropertyState_DIRECT_VALUE);
+ xDispatch->dispatch(aURL, args);
+ } catch (com::sun::star::uno::Exception& e) {
+ OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ // save failed, but tell manager to go on if we havent yet dispatched the request
+ // in case of synchronous saving the notification is done by the caller
+ if ( bAsync && m_rSessionManager.is() )
+ m_rSessionManager->saveDone(this);
+ }
+}
+
+void SessionListener::QuitSessionQuietly()
+{
+ ResetableGuard aGuard(m_aLock);
+ try
+ {
+ // xd create SERVICENAME_AUTORECOVERY -> XDispatch
+ // xd->dispatch("vnd.sun.star.autorecovery:/doSessionQuietQuit, async=false
+ // it is done synchronously to avoid conflict with normal quit process
+
+ css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
+ css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionQuietQuit");
+ xURLTransformer->parseStrict(aURL);
+
+ Sequence< PropertyValue > args(1);
+ args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(sal_False),PropertyState_DIRECT_VALUE);
+ xDispatch->dispatch(aURL, args);
+ } catch (com::sun::star::uno::Exception& e) {
+ OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ }
+}
+
+void SAL_CALL SessionListener::disposing(const com::sun::star::lang::EventObject&) throw (RuntimeException)
+{
+}
+
+void SAL_CALL SessionListener::initialize(const Sequence< Any >& args)
+ throw (RuntimeException)
+{
+
+ OUString aSMgr = OUString::createFromAscii("com.sun.star.frame.SessionManagerClient");
+ if (args.getLength() > 0)
+ {
+ NamedValue v;
+ for (int i = 0; i < args.getLength(); i++)
+ {
+ if (args[i] >>= v)
+ {
+ if (v.Name.equalsAscii("SessionManagerName"))
+ v.Value >>= aSMgr;
+ else if (v.Name.equalsAscii("SessionManager"))
+ v.Value >>= m_rSessionManager;
+ else if (v.Name.equalsAscii("AllowUserInteractionOnQuit"))
+ v.Value >>= m_bAllowUserInteractionOnQuit;
+ }
+ }
+ }
+ if (!m_rSessionManager.is())
+ m_rSessionManager = css::uno::Reference< XSessionManagerClient >
+ (m_xSMGR->createInstance(aSMgr), UNO_QUERY);
+
+ if (m_rSessionManager.is())
+ {
+ m_rSessionManager->addSessionManagerListener(this);
+ }
+}
+
+void SAL_CALL SessionListener::statusChanged(const FeatureStateEvent& event)
+ throw (css::uno::RuntimeException)
+{
+ if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionRestore"))
+ {
+ if (event.FeatureDescriptor.compareToAscii("update")==0)
+ m_bRestored = sal_True; // a document was restored
+ // if (event.FeatureDescriptor.compareToAscii("stop")==0)
+
+ }
+ else if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionSave"))
+ {
+ if (event.FeatureDescriptor.compareToAscii("stop")==0)
+ {
+ if (m_rSessionManager.is())
+ m_rSessionManager->saveDone(this); // done with save
+ }
+ }
+}
+
+
+sal_Bool SAL_CALL SessionListener::doRestore()
+ throw (RuntimeException)
+{
+ ResetableGuard aGuard(m_aLock);
+ m_bRestored = sal_False;
+ try {
+ css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
+
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionRestore");
+ css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
+ xURLTransformer->parseStrict(aURL);
+ Sequence< PropertyValue > args;
+ xDispatch->addStatusListener(this, aURL);
+ xDispatch->dispatch(aURL, args);
+ m_bRestored = sal_True;
+
+ } catch (com::sun::star::uno::Exception& e) {
+ OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ }
+
+ return m_bRestored;
+}
+
+
+void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelable*/ )
+ throw (RuntimeException)
+{
+ if (bShutdown)
+ {
+ m_bSessionStoreRequested = sal_True; // there is no need to protect it with mutex
+ if ( m_bAllowUserInteractionOnQuit && m_rSessionManager.is() )
+ m_rSessionManager->queryInteraction( static_cast< css::frame::XSessionManagerListener* >( this ) );
+ else
+ StoreSession( sal_True );
+ }
+ // we don't have anything to do so tell the session manager we're done
+ else if( m_rSessionManager.is() )
+ m_rSessionManager->saveDone( this );
+}
+
+void SAL_CALL SessionListener::approveInteraction( sal_Bool bInteractionGranted )
+ throw (RuntimeException)
+{
+ // do AutoSave as the first step
+ ResetableGuard aGuard(m_aLock);
+
+ if ( bInteractionGranted )
+ {
+ // close the office documents in normal way
+ try
+ {
+ // first of all let the session be stored to be sure that we lose no information
+ StoreSession( sal_False );
+
+ css::uno::Reference< css::frame::XDesktop > xDesktop( m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
+ m_bTerminated = xDesktop->terminate();
+
+ if ( m_rSessionManager.is() )
+ {
+ // false means that the application closing has been cancelled
+ if ( !m_bTerminated )
+ m_rSessionManager->cancelShutdown();
+ else
+ m_rSessionManager->interactionDone( this );
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ StoreSession( sal_True );
+ m_rSessionManager->interactionDone( this );
+ }
+
+ if ( m_rSessionManager.is() )
+ m_rSessionManager->saveDone(this);
+ }
+ else
+ {
+ StoreSession( sal_True );
+ }
+}
+
+void SessionListener::shutdownCanceled()
+ throw (RuntimeException)
+{
+ // set the state back
+ m_bSessionStoreRequested = sal_False; // there is no need to protect it with mutex
+}
+
+void SessionListener::doQuit()
+ throw (RuntimeException)
+{
+ if ( m_bSessionStoreRequested && !m_bTerminated )
+ {
+ // let the session be closed quietly in this case
+ QuitSessionQuietly();
+ }
+}
+
+}
diff --git a/framework/source/services/substitutepathvars.cxx b/framework/source/services/substitutepathvars.cxx
new file mode 100644
index 000000000000..90c460b74298
--- /dev/null
+++ b/framework/source/services/substitutepathvars.cxx
@@ -0,0 +1,1249 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include "services/substitutepathvars.hxx"
+#include <threadhelp/resetableguard.hxx>
+#include <helper/networkdomain.hxx>
+#include "services.h"
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <unotools/configitem.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <unotools/configmgr.hxx>
+
+#ifndef _UTL_BOOTSTRAP_HXX_
+#include <unotools/bootstrap.hxx>
+#endif
+#include <osl/mutex.hxx>
+#include <osl/file.hxx>
+#include <osl/security.hxx>
+#include <osl/socket.hxx>
+#include <vos/process.hxx>
+#include <i18npool/mslangid.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/resmgr.hxx>
+#include <tools/debug.hxx>
+#include <tools/wldcrd.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/bootstrap.hxx>
+
+#include <comphelper/configurationhelper.hxx>
+
+#include <string.h>
+
+//_________________________________________________________________________________________________________________
+// Defines
+//_________________________________________________________________________________________________________________
+//
+
+#define STRPOS_NOTFOUND (sal_Int32)-1
+
+#define ASCII_STR( val ) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( val ))
+
+#define SEARCHPATH_DELIMITER ';'
+
+// Variable start/end characters
+#define SIGN_STARTVARIABLE ASCII_STR("$(")
+#define SIGN_ENDVARIABLE ASCII_STR(")")
+
+// Length of SUBSTITUTE_... to replace it with real values.
+#define REPLACELENGTH_INST 7
+#define REPLACELENGTH_PROG 7
+#define REPLACELENGTH_USER 7
+#define REPLACELENGTH_WORK 7
+#define REPLACELENGTH_HOME 7
+#define REPLACELENGTH_TEMP 7
+#define REPLACELENGTH_PATH 7
+#define REPLACELENGTH_INSTPATH 11
+#define REPLACELENGTH_PROGPATH 11
+#define REPLACELENGTH_USERPATH 11
+#define REPLACELENGTH_INSTURL 10
+#define REPLACELENGTH_PROGURL 10
+#define REPLACELENGTH_USERURL 10
+#define REPLACELENGTH_PATH 7
+#define REPLACELENGTH_LANG 7
+#define REPLACELENGTH_LANGID 9
+#define REPLACELENGTH_VLANG 8
+#define REPLACELENGTH_WORKDIRURL 13
+// --> PB 2004-10-27 #i32656# - new variable of hierachy service
+#define REPLACELENGTH_BASEINSTURL 14
+#define REPLACELENGTH_USERDATAURL 14
+// <--
+
+// Name of the pre defined path variables
+#define VARIABLE_INST "$(inst)"
+#define VARIABLE_PROG "$(prog)"
+#define VARIABLE_USER "$(user)"
+#define VARIABLE_WORK "$(work)"
+#define VARIABLE_HOME "$(home)"
+#define VARIABLE_TEMP "$(temp)"
+#define VARIABLE_PATH "$(path)"
+#define VARIABLE_LANG "$(lang)"
+#define VARIABLE_LANGID "$(langid)"
+#define VARIABLE_VLANG "$(vlang)"
+#define VARIABLE_INSTPATH "$(instpath)"
+#define VARIABLE_PROGPATH "$(progpath)"
+#define VARIABLE_USERPATH "$(userpath)"
+#define VARIABLE_INSTURL "$(insturl)"
+#define VARIABLE_PROGURL "$(progurl)"
+#define VARIABLE_USERURL "$(userurl)"
+#define VARIABLE_WORKDIRURL "$(workdirurl)"
+// --> PB 2004-10-27 #i32656# - new variable of hierachy service
+#define VARIABLE_BASEINSTURL "$(baseinsturl)"
+#define VARIABLE_USERDATAURL "$(userdataurl)"
+// <--
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::util;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::container;
+
+//_________________________________________________________________________________________________________________
+// Namespace
+//_________________________________________________________________________________________________________________
+//
+
+namespace framework
+{
+
+struct FixedVariable
+{
+ const char* pVarName;
+ PreDefVariable nEnumValue;
+ int nStrLen;
+};
+
+struct TableEntry
+{
+ const char* pOSString;
+ int nStrLen;
+};
+
+// Table with valid operating system strings
+// Name of the os as char* and the length
+// of the string
+static TableEntry aOSTable[OS_COUNT] =
+{
+ { "WINDOWS" , 7 },
+ { "UNIX" , 4 },
+ { "SOLARIS" , 7 },
+ { "LINUX" , 5 },
+ { "" , 0 } // unknown
+};
+
+// Table with valid environment variables
+// Name of the environment type as a char* and
+// the length of the string.
+static TableEntry aEnvTable[ET_COUNT] =
+{
+ { "HOST" , 4 },
+ { "YPDOMAIN" , 8 },
+ { "DNSDOMAIN" , 9 },
+ { "NTDOMAIN" , 8 },
+ { "OS" , 2 },
+ { "" , 0 } // unknown
+};
+
+// Priority table for the environment types. Lower numbers define
+// a higher priority. Equal numbers has the same priority that means
+// that the first match wins!!
+static sal_Int16 aEnvPrioTable[ET_COUNT] =
+{
+ 1, // ET_HOST
+ 2, // ET_IPDOMAIN
+ 2, // ET_DNSDOMAIN
+ 2, // ET_NTDOMAIN
+ 3, // ET_OS
+ 99, // ET_UNKNOWN
+};
+
+// Table with all fixed/predefined variables supported.
+static FixedVariable aFixedVarTable[] =
+{
+ { VARIABLE_INST, PREDEFVAR_INST, REPLACELENGTH_INST },
+ { VARIABLE_PROG, PREDEFVAR_PROG, REPLACELENGTH_PROG },
+ { VARIABLE_USER, PREDEFVAR_USER, REPLACELENGTH_USER },
+ { VARIABLE_WORK, PREDEFVAR_WORK, REPLACELENGTH_WORK }, // Special variable (transient)!
+ { VARIABLE_HOME, PREDEFVAR_HOME, REPLACELENGTH_HOME },
+ { VARIABLE_TEMP, PREDEFVAR_TEMP, REPLACELENGTH_TEMP },
+ { VARIABLE_PATH, PREDEFVAR_PATH, REPLACELENGTH_PATH },
+ { VARIABLE_LANG, PREDEFVAR_LANG, REPLACELENGTH_LANG },
+ { VARIABLE_LANGID, PREDEFVAR_LANGID, REPLACELENGTH_LANGID },
+ { VARIABLE_VLANG, PREDEFVAR_VLANG, REPLACELENGTH_VLANG },
+ { VARIABLE_INSTPATH, PREDEFVAR_INSTPATH, REPLACELENGTH_INSTPATH },
+ { VARIABLE_PROGPATH, PREDEFVAR_PROGPATH, REPLACELENGTH_PROGPATH },
+ { VARIABLE_USERPATH, PREDEFVAR_USERPATH, REPLACELENGTH_USERPATH },
+ { VARIABLE_INSTURL, PREDEFVAR_INSTURL, REPLACELENGTH_INSTURL },
+ { VARIABLE_PROGURL, PREDEFVAR_PROGURL, REPLACELENGTH_PROGURL },
+ { VARIABLE_USERURL, PREDEFVAR_USERURL, REPLACELENGTH_USERURL },
+ { VARIABLE_WORKDIRURL, PREDEFVAR_WORKDIRURL, REPLACELENGTH_WORKDIRURL }, // Special variable (transient) and don't use for resubstitution!
+ // --> PB 2004-10-27 #i32656# - new variable of hierachy service
+ { VARIABLE_BASEINSTURL, PREDEFVAR_BASEINSTURL, REPLACELENGTH_BASEINSTURL },
+ { VARIABLE_USERDATAURL, PREDEFVAR_USERDATAURL, REPLACELENGTH_USERDATAURL },
+ // <--
+ { "$(brandbaseurl)", PREDEFVAR_BRANDBASEURL,
+ RTL_CONSTASCII_LENGTH("$(brandbaseurl)") }
+};
+
+//_________________________________________________________________________________________________________________
+// Implementation helper classes
+//_________________________________________________________________________________________________________________
+//
+
+OperatingSystem SubstitutePathVariables_Impl::GetOperatingSystemFromString( const rtl::OUString& aOSString )
+{
+ for ( int i = 0; i < OS_COUNT; i++ )
+ {
+ if ( aOSString.equalsIgnoreAsciiCaseAsciiL( aOSTable[i].pOSString, aOSTable[i].nStrLen ))
+ return (OperatingSystem)i;
+ }
+
+ return OS_UNKNOWN;
+}
+
+EnvironmentType SubstitutePathVariables_Impl::GetEnvTypeFromString( const rtl::OUString& aEnvTypeString )
+{
+ for ( int i = 0; i < ET_COUNT; i++ )
+ {
+ if ( aEnvTypeString.equalsIgnoreAsciiCaseAsciiL( aEnvTable[i].pOSString, aEnvTable[i].nStrLen ))
+ return (EnvironmentType)i;
+ }
+
+ return ET_UNKNOWN;
+}
+
+SubstitutePathVariables_Impl::SubstitutePathVariables_Impl( const Link& aNotifyLink ) :
+ utl::ConfigItem( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Office.Substitution" ))),
+ m_bYPDomainRetrieved( sal_False ),
+ m_bDNSDomainRetrieved( sal_False ),
+ m_bNTDomainRetrieved( sal_False ),
+ m_bHostRetrieved( sal_False ),
+ m_bOSRetrieved( sal_False ),
+ m_aListenerNotify( aNotifyLink ),
+ m_aSharePointsNodeName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SharePoints" ))),
+ m_aDirPropertyName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/Directory" ))),
+ m_aEnvPropertyName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/Environment" ))),
+ m_aLevelSep( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" )))
+{
+ // Enable notification mechanism
+ // We need it to get information about changes outside these class on our configuration branch
+ Sequence< rtl::OUString > aNotifySeq( 1 );
+ aNotifySeq[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SharePoints" ));
+ EnableNotification( aNotifySeq, sal_True );
+}
+
+SubstitutePathVariables_Impl::~SubstitutePathVariables_Impl()
+{
+}
+
+void SubstitutePathVariables_Impl::GetSharePointsRules( SubstituteVariables& aSubstVarMap )
+{
+ Sequence< rtl::OUString > aSharePointNames;
+ ReadSharePointsFromConfiguration( aSharePointNames );
+
+ if ( aSharePointNames.getLength() > 0 )
+ {
+ sal_Int32 nSharePoints = 0;
+
+ // Read SharePoints container from configuration
+ while ( nSharePoints < aSharePointNames.getLength() )
+ {
+ rtl::OUString aSharePointNodeName( m_aSharePointsNodeName );
+ aSharePointNodeName += rtl::OUString::createFromAscii( "/" );
+ aSharePointNodeName += aSharePointNames[ nSharePoints ];
+
+ SubstituteRuleVector aRuleSet;
+ ReadSharePointRuleSetFromConfiguration( aSharePointNames[ nSharePoints ], aSharePointNodeName, aRuleSet );
+ if ( !aRuleSet.empty() )
+ {
+ // We have at minimum one rule. Filter the correct rule out of the rule set
+ // and put into our SubstituteVariable map
+ SubstituteRule aActiveRule;
+ if ( FilterRuleSet( aRuleSet, aActiveRule ))
+ {
+ // We have found an active rule
+ aActiveRule.aSubstVariable = aSharePointNames[ nSharePoints ];
+ aSubstVarMap.insert( SubstituteVariables::value_type(
+ aActiveRule.aSubstVariable, aActiveRule ));
+ }
+ }
+
+ ++nSharePoints;
+ }
+ }
+}
+
+void SubstitutePathVariables_Impl::Notify( const com::sun::star::uno::Sequence< rtl::OUString >& /*aPropertyNames*/ )
+{
+ // NOT implemented yet!
+}
+
+void SubstitutePathVariables_Impl::Commit()
+{
+}
+
+
+//_________________________________________________________________________________________________________________
+// private methods
+//_________________________________________________________________________________________________________________
+//
+
+OperatingSystem SubstitutePathVariables_Impl::GetOperatingSystem()
+{
+ if ( !m_bOSRetrieved )
+ {
+#ifdef SOLARIS
+ m_eOSType = OS_SOLARIS;
+#elif defined LINUX
+ m_eOSType = OS_LINUX;
+#elif defined WIN32
+ m_eOSType = OS_WINDOWS;
+#elif defined UNIX
+ m_eOSType = OS_UNIX;
+#else
+ m_eOSType = OS_UNKNOWN;
+#endif
+ m_bOSRetrieved = sal_True;
+ }
+
+ return m_eOSType;
+}
+
+const rtl::OUString& SubstitutePathVariables_Impl::GetYPDomainName()
+{
+ if ( !m_bYPDomainRetrieved )
+ {
+ m_aYPDomain = NetworkDomain::GetYPDomainName().toAsciiLowerCase();
+ m_bYPDomainRetrieved = sal_True;
+ }
+
+ return m_aYPDomain;
+}
+
+const rtl::OUString& SubstitutePathVariables_Impl::GetDNSDomainName()
+{
+ if ( !m_bDNSDomainRetrieved )
+ {
+ rtl::OUString aTemp;
+ osl::SocketAddr aSockAddr;
+ oslSocketResult aResult;
+
+ rtl::OUString aHostName = GetHostName();
+ osl::SocketAddr::resolveHostname( aHostName, aSockAddr );
+ aTemp = aSockAddr.getHostname( &aResult );
+
+ // DNS domain name begins after the first "."
+ sal_Int32 nIndex = aTemp.indexOf( '.' );
+ if ( nIndex >= 0 && aTemp.getLength() > nIndex+1 )
+ m_aDNSDomain = aTemp.copy( nIndex+1 ).toAsciiLowerCase();
+ else
+ m_aDNSDomain = rtl::OUString();
+
+ m_bDNSDomainRetrieved = sal_True;
+ }
+
+ return m_aDNSDomain;
+}
+
+const rtl::OUString& SubstitutePathVariables_Impl::GetNTDomainName()
+{
+ if ( !m_bNTDomainRetrieved )
+ {
+ m_aNTDomain = NetworkDomain::GetNTDomainName().toAsciiLowerCase();
+ m_bNTDomainRetrieved = sal_True;
+ }
+
+ return m_aNTDomain;
+}
+
+const rtl::OUString& SubstitutePathVariables_Impl::GetHostName()
+{
+ if ( !m_bHostRetrieved )
+ {
+ rtl::OUString aHostName;
+ oslSocketResult aSocketResult;
+
+ m_aHost = osl::SocketAddr::getLocalHostname( &aSocketResult ).toAsciiLowerCase();
+ }
+
+ return m_aHost;
+}
+
+sal_Bool SubstitutePathVariables_Impl::FilterRuleSet( const SubstituteRuleVector& aRuleSet, SubstituteRule& aActiveRule )
+{
+ sal_Bool bResult = sal_False;
+
+ if ( !aRuleSet.empty() )
+ {
+ sal_Int16 nPrioCurrentRule = aEnvPrioTable[ ET_UNKNOWN ];
+ const sal_uInt32 nCount = aRuleSet.size();
+ for ( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ const SubstituteRule& aRule = aRuleSet[nIndex];
+ EnvironmentType eEnvType = aRule.aEnvType;
+
+ // Check if environment type has a higher priority than current one!
+ if ( nPrioCurrentRule > aEnvPrioTable[eEnvType] )
+ {
+ switch ( eEnvType )
+ {
+ case ET_HOST:
+ {
+ rtl::OUString aHost = GetHostName();
+ rtl::OUString aHostStr;
+ aRule.aEnvValue >>= aHostStr;
+ aHostStr = aHostStr.toAsciiLowerCase();
+
+ // Pattern match if domain environment match
+ WildCard aPattern(aHostStr);
+ sal_Bool bMatch = aPattern.Matches(aHost);
+ if ( bMatch )
+ {
+ aActiveRule = aRule;
+ bResult = sal_True;
+ nPrioCurrentRule = aEnvPrioTable[eEnvType];
+ }
+ }
+ break;
+
+ case ET_YPDOMAIN:
+ case ET_DNSDOMAIN:
+ case ET_NTDOMAIN:
+ {
+ rtl::OUString aDomain;
+ rtl::OUString aDomainStr;
+ aRule.aEnvValue >>= aDomainStr;
+ aDomainStr = aDomainStr.toAsciiLowerCase();
+
+ // Retrieve the correct domain value
+ if ( eEnvType == ET_YPDOMAIN )
+ aDomain = GetYPDomainName();
+ else if ( eEnvType == ET_DNSDOMAIN )
+ aDomain = GetDNSDomainName();
+ else
+ aDomain = GetNTDomainName();
+
+ // Pattern match if domain environment match
+ WildCard aPattern(aDomainStr);
+ sal_Bool bMatch = aPattern.Matches(aDomain);
+ if ( bMatch )
+ {
+ aActiveRule = aRule;
+ bResult = sal_True;
+ nPrioCurrentRule = aEnvPrioTable[eEnvType];
+ }
+ }
+ break;
+
+ case ET_OS:
+ {
+ // No pattern matching for OS type
+ OperatingSystem eOSType = GetOperatingSystem();
+
+ sal_Int16 nValue = 0;
+ aRule.aEnvValue >>= nValue;
+
+ sal_Bool bUnix = ( eOSType == OS_LINUX ) || ( eOSType == OS_SOLARIS );
+ OperatingSystem eRuleOSType = (OperatingSystem)nValue;
+
+ // Match if OS identical or rule is set to UNIX and OS is LINUX/SOLARIS!
+ if (( eRuleOSType == eOSType ) || ( eRuleOSType == OS_UNIX && bUnix ))
+ {
+ aActiveRule = aRule;
+ bResult = sal_True;
+ nPrioCurrentRule = aEnvPrioTable[eEnvType];
+ }
+ }
+ break;
+
+ case ET_UNKNOWN: // nothing to do
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return bResult;
+}
+
+void SubstitutePathVariables_Impl::ReadSharePointsFromConfiguration( Sequence< rtl::OUString >& aSharePointsSeq )
+{
+ //returns all the names of all share point nodes
+ aSharePointsSeq = GetNodeNames( m_aSharePointsNodeName );
+}
+
+void SubstitutePathVariables_Impl::ReadSharePointRuleSetFromConfiguration(
+ const rtl::OUString& aSharePointName,
+ const rtl::OUString& aSharePointNodeName,
+ SubstituteRuleVector& rRuleSet )
+{
+ Sequence< rtl::OUString > aSharePointMappingsNodeNames = GetNodeNames( aSharePointNodeName, utl::CONFIG_NAME_LOCAL_PATH );
+
+ sal_Int32 nSharePointMapping = 0;
+ while ( nSharePointMapping < aSharePointMappingsNodeNames.getLength() )
+ {
+ rtl::OUString aSharePointMapping( aSharePointNodeName );
+ aSharePointMapping += m_aLevelSep;
+ aSharePointMapping += aSharePointMappingsNodeNames[ nSharePointMapping ];
+
+ // Read SharePointMapping
+ rtl::OUString aDirValue;
+ rtl::OUString aDirProperty( aSharePointMapping );
+ aDirProperty += m_aDirPropertyName;
+
+ // Read only the directory property
+ Sequence< rtl::OUString > aDirPropertySeq( 1 );
+ aDirPropertySeq[0] = aDirProperty;
+
+ Sequence< Any > aValueSeq = GetProperties( aDirPropertySeq );
+ if ( aValueSeq.getLength() == 1 )
+ aValueSeq[0] >>= aDirValue;
+
+ // Read the environment setting
+ rtl::OUString aEnvUsed;
+ rtl::OUString aEnvProperty( aSharePointMapping );
+ aEnvProperty += m_aEnvPropertyName;
+ Sequence< rtl::OUString > aEnvironmentVariable = GetNodeNames( aEnvProperty );
+
+ // Filter the property which has a value set
+ Sequence< rtl::OUString > aEnvUsedPropertySeq( aEnvironmentVariable.getLength() );
+
+ rtl::OUString aEnvUsePropNameTemplate( aEnvProperty );
+ aEnvUsePropNameTemplate += m_aLevelSep;
+
+ for ( sal_Int32 nProperty = 0; nProperty < aEnvironmentVariable.getLength(); nProperty++ )
+ aEnvUsedPropertySeq[nProperty] = rtl::OUString( aEnvUsePropNameTemplate + aEnvironmentVariable[nProperty] );
+
+ Sequence< Any > aEnvUsedValueSeq;
+ aEnvUsedValueSeq = GetProperties( aEnvUsedPropertySeq );
+
+ rtl::OUString aEnvUsedValue;
+ for ( sal_Int32 nIndex = 0; nIndex < aEnvironmentVariable.getLength(); nIndex++ )
+ {
+ if ( aEnvUsedValueSeq[nIndex] >>= aEnvUsedValue )
+ {
+ aEnvUsed = aEnvironmentVariable[nIndex];
+ break;
+ }
+ }
+
+ // Decode the environment and optional the operatng system settings
+ Any aEnvValue;
+ EnvironmentType eEnvType = GetEnvTypeFromString( aEnvUsed );
+ if ( eEnvType == ET_OS )
+ {
+ OperatingSystem eOSType = GetOperatingSystemFromString( aEnvUsedValue );
+ aEnvValue <<= (sal_Int16)eOSType;
+ }
+ else
+ aEnvValue <<= aEnvUsedValue;
+
+ // Create rule struct and push it into the rule set
+ SubstituteRule aRule( aSharePointName, aDirValue, aEnvValue, eEnvType );
+ rRuleSet.push_back( aRule );
+
+ ++nSharePointMapping;
+ }
+}
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( SubstitutePathVariables ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_SUBSTITUTEPATHVARIABLES ,
+ IMPLEMENTATIONNAME_SUBSTITUTEPATHVARIABLES
+ )
+
+DEFINE_INIT_SERVICE ( SubstitutePathVariables, {} )
+
+
+SubstitutePathVariables::SubstitutePathVariables( const Reference< XMultiServiceFactory >& xServiceManager ) :
+ ThreadHelpBase(),
+ m_aVarStart( SIGN_STARTVARIABLE ),
+ m_aVarEnd( SIGN_ENDVARIABLE ),
+ m_aImpl( LINK( this, SubstitutePathVariables, implts_ConfigurationNotify )),
+ m_xServiceManager( xServiceManager )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::SubstitutePathVariables" );
+ int i;
+
+ SetPredefinedPathVariables( m_aPreDefVars );
+ m_aImpl.GetSharePointsRules( m_aSubstVarMap );
+
+ // Init the predefined/fixed variable to index hash map
+ for ( i = 0; i < PREDEFVAR_COUNT; i++ )
+ {
+ // Store variable name into struct of predefined/fixed variables
+ m_aPreDefVars.m_FixedVarNames[i] = rtl::OUString::createFromAscii( aFixedVarTable[i].pVarName );
+
+ // Create hash map entry
+ m_aPreDefVarMap.insert( VarNameToIndexMap::value_type(
+ m_aPreDefVars.m_FixedVarNames[i], aFixedVarTable[i].nEnumValue ) );
+ }
+
+ // Sort predefined/fixed variable to path length
+ for ( i = 0; i < PREDEFVAR_COUNT; i++ )
+ {
+ if (( i != PREDEFVAR_WORKDIRURL ) &&
+ ( i != PREDEFVAR_PATH ))
+ {
+ // Special path variables, don't include into automatic resubstituion search!
+ // $(workdirurl) is not allowed to resubstitute! This variable is the value of path settings entry
+ // and it could be possible that it will be resubstituted by itself!!
+ // Example: WORK_PATH=c:\test, $(workdirurl)=WORK_PATH => WORK_PATH=$(workdirurl) and this cannot be substituted!
+ ReSubstFixedVarOrder aFixedVar;
+ aFixedVar.eVariable = aFixedVarTable[i].nEnumValue;
+ aFixedVar.nVarValueLength = m_aPreDefVars.m_FixedVar[(sal_Int32)aFixedVar.eVariable].getLength();
+ m_aReSubstFixedVarOrder.push_back( aFixedVar );
+ }
+ }
+ m_aReSubstFixedVarOrder.sort();
+
+ // Sort user variables to path length
+ SubstituteVariables::const_iterator pIter;
+ for ( pIter = m_aSubstVarMap.begin(); pIter != m_aSubstVarMap.end(); pIter++ )
+ {
+ ReSubstUserVarOrder aUserOrderVar;
+ rtl::OUStringBuffer aStrBuffer( pIter->second.aSubstVariable.getLength() );
+ aStrBuffer.append( m_aVarStart );
+ aStrBuffer.append( pIter->second.aSubstVariable );
+ aStrBuffer.append( m_aVarEnd );
+ aUserOrderVar.aVarName = aStrBuffer.makeStringAndClear();
+ aUserOrderVar.nVarValueLength = pIter->second.aSubstVariable.getLength();
+ m_aReSubstUserVarOrder.push_back( aUserOrderVar );
+ }
+ m_aReSubstUserVarOrder.sort();
+}
+
+SubstitutePathVariables::~SubstitutePathVariables()
+{
+}
+
+// XStringSubstitution
+rtl::OUString SAL_CALL SubstitutePathVariables::substituteVariables( const ::rtl::OUString& aText, sal_Bool bSubstRequired )
+throw ( NoSuchElementException, RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::substituteVariables" );
+ ResetableGuard aLock( m_aLock );
+ return impl_substituteVariable( aText, bSubstRequired );
+}
+
+rtl::OUString SAL_CALL SubstitutePathVariables::reSubstituteVariables( const ::rtl::OUString& aText )
+throw ( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::reSubstituteVariables" );
+ ResetableGuard aLock( m_aLock );
+ return impl_reSubstituteVariables( aText );
+}
+
+rtl::OUString SAL_CALL SubstitutePathVariables::getSubstituteVariableValue( const ::rtl::OUString& aVariable )
+throw ( NoSuchElementException, RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::getSubstituteVariableValue" );
+ ResetableGuard aLock( m_aLock );
+ return impl_getSubstituteVariableValue( aVariable );
+}
+
+//_________________________________________________________________________________________________________________
+// protected methods
+//_________________________________________________________________________________________________________________
+//
+
+IMPL_LINK( SubstitutePathVariables, implts_ConfigurationNotify, SubstitutePathNotify*, EMPTYARG )
+{
+ /* SAFE AREA ----------------------------------------------------------------------------------------------- */
+ ResetableGuard aLock( m_aLock );
+
+ return 0;
+}
+
+rtl::OUString SubstitutePathVariables::ConvertOSLtoUCBURL( const rtl::OUString& aOSLCompliantURL ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::ConvertOSLtoUCBURL" );
+ String aResult;
+ rtl::OUString aTemp;
+
+ osl::FileBase::getSystemPathFromFileURL( aOSLCompliantURL, aTemp );
+ utl::LocalFileHelper::ConvertPhysicalNameToURL( aTemp, aResult );
+
+ // Not all OSL URL's can be mapped to UCB URL's!
+ if ( aResult.Len() == 0 )
+ return aOSLCompliantURL;
+ else
+ return rtl::OUString( aResult );
+}
+
+rtl::OUString SubstitutePathVariables::GetWorkPath() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::GetWorkPath" );
+ rtl::OUString aWorkPath;
+ ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xServiceManager,
+ ::rtl::OUString::createFromAscii("org.openoffice.Office.Paths"),
+ ::rtl::OUString::createFromAscii("Paths/Work"),
+ ::rtl::OUString::createFromAscii("WritePath"),
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= aWorkPath;
+ return aWorkPath;
+}
+
+rtl::OUString SubstitutePathVariables::GetWorkVariableValue() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::GetWorkVariableValue" );
+ ::rtl::OUString aWorkPath;
+ ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xServiceManager,
+ ::rtl::OUString::createFromAscii("org.openoffice.Office.Paths"),
+ ::rtl::OUString::createFromAscii("Variables"),
+ ::rtl::OUString::createFromAscii("Work"),
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= aWorkPath;
+
+ // fallback to $HOME in case platform dependend config layer does not return
+ // an usuable work dir value.
+ if (aWorkPath.getLength() < 1)
+ {
+ osl::Security aSecurity;
+ aSecurity.getHomeDir( aWorkPath );
+ }
+ return ConvertOSLtoUCBURL( aWorkPath );
+}
+
+rtl::OUString SubstitutePathVariables::GetHomeVariableValue() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::GetHomeVariableValue" );
+ osl::Security aSecurity;
+ rtl::OUString aHomePath;
+
+ aSecurity.getHomeDir( aHomePath );
+ return ConvertOSLtoUCBURL( aHomePath );
+}
+
+rtl::OUString SubstitutePathVariables::GetPathVariableValue() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::GetPathVariableValue" );
+ const int PATH_EXTEND_FACTOR = 120;
+
+ rtl::OUString aRetStr;
+ const char* pEnv = getenv( "PATH" );
+
+ if ( pEnv )
+ {
+ rtl::OUString aTmp;
+ rtl::OUString aPathList( pEnv, strlen( pEnv ), gsl_getSystemTextEncoding() );
+ rtl::OUStringBuffer aPathStrBuffer( aPathList.getLength() * PATH_EXTEND_FACTOR / 100 );
+
+ sal_Bool bAppendSep = sal_False;
+ sal_Int32 nToken = 0;
+ do
+ {
+ ::rtl::OUString sToken = aPathList.getToken(0, SAL_PATHSEPARATOR, nToken);
+ if (sToken.getLength())
+ {
+ osl::FileBase::getFileURLFromSystemPath( sToken, aTmp );
+ if ( bAppendSep )
+ aPathStrBuffer.appendAscii( ";" ); // Office uses ';' as path separator
+ aPathStrBuffer.append( aTmp );
+ bAppendSep = sal_True;
+ }
+ }
+ while(nToken>=0);
+
+ aRetStr = aPathStrBuffer.makeStringAndClear();
+ }
+
+ return aRetStr;
+}
+
+rtl::OUString SubstitutePathVariables::impl_substituteVariable( const ::rtl::OUString& rText, sal_Bool bSubstRequired )
+throw ( NoSuchElementException, RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::impl_substituteVariable" );
+ // This is maximal recursive depth supported!
+ const sal_Int32 nMaxRecursiveDepth = 8;
+
+ rtl::OUString aWorkText = rText;
+ rtl::OUString aResult;
+
+ // Use vector with strings to detect endless recursions!
+ std::vector< rtl::OUString > aEndlessRecursiveDetector;
+
+ // Search for first occure of "$(...".
+ sal_Int32 nDepth = 0;
+ sal_Int32 bSubstitutionCompleted = sal_False;
+ sal_Int32 nPosition = aWorkText.indexOf( m_aVarStart ); // = first position of "$(" in string
+ sal_Int32 nLength = 0; // = count of letters from "$(" to ")" in string
+ sal_Bool bVarNotSubstituted = sal_False;
+
+ // Have we found any variable like "$(...)"?
+ if ( nPosition != STRPOS_NOTFOUND )
+ {
+ // Yes; Get length of found variable.
+ // If no ")" was found - nLength is set to 0 by default! see before.
+ sal_Int32 nEndPosition = aWorkText.indexOf( m_aVarEnd, nPosition );
+ if ( nEndPosition != STRPOS_NOTFOUND )
+ nLength = nEndPosition - nPosition + 1;
+ }
+
+ // Is there something to replace ?
+ sal_Bool bWorkRetrieved = sal_False;
+ sal_Bool bWorkDirURLRetrieved = sal_False;
+ while ( !bSubstitutionCompleted && nDepth < nMaxRecursiveDepth )
+ {
+ while ( ( nPosition != STRPOS_NOTFOUND ) && ( nLength > 3 ) ) // "$(" ")"
+ {
+ // YES; Get the next variable for replace.
+ sal_Int32 nReplaceLength = 0;
+ rtl::OUString aReplacement;
+ rtl::OUString aSubString = aWorkText.copy( nPosition, nLength );
+ rtl::OUString aSubVarString;
+
+ // Path variables are not case sensitive!
+ aSubVarString = aSubString.toAsciiLowerCase();
+ VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( aSubVarString );
+ if ( pNTOIIter != m_aPreDefVarMap.end() )
+ {
+ // Fixed/Predefined variable found
+ PreDefVariable nIndex = (PreDefVariable)pNTOIIter->second;
+
+ // Determine variable value and length from array/table
+ if ( nIndex == PREDEFVAR_WORK && !bWorkRetrieved )
+ {
+ // Transient value, retrieve it again
+ m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ] = GetWorkVariableValue();
+ bWorkRetrieved = sal_True;
+ }
+ else if ( nIndex == PREDEFVAR_WORKDIRURL && !bWorkDirURLRetrieved )
+ {
+ // Transient value, retrieve it again
+ m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ] = GetWorkPath();
+ bWorkDirURLRetrieved = sal_True;
+ }
+
+ aReplacement = m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ];
+ nReplaceLength = nLength;
+ }
+ else
+ {
+ // Extract the variable name and try to find in the user defined variable set
+ rtl::OUString aVarName = aSubString.copy( 2, nLength-3 );
+ SubstituteVariables::const_iterator pIter = m_aSubstVarMap.find( aVarName );
+ if ( pIter != m_aSubstVarMap.end() )
+ {
+ // found!
+ aReplacement = pIter->second.aSubstValue;
+ nReplaceLength = nLength;
+ }
+ }
+
+ // Have we found something to replace?
+ if ( nReplaceLength > 0 )
+ {
+ // Yes ... then do it.
+ aWorkText = aWorkText.replaceAt( nPosition, nReplaceLength, aReplacement );
+ }
+ else
+ {
+ // Variable not known
+ bVarNotSubstituted = sal_False;
+ nPosition += nLength;
+ }
+
+ // Step after replaced text! If no text was replaced (unknown variable!),
+ // length of aReplacement is 0 ... and we don't step then.
+ nPosition += aReplacement.getLength();
+
+ // We must control index in string before call something at OUString!
+ // The OUString-implementation don't do it for us :-( but the result is not defined otherwise.
+ if ( nPosition + 1 > aWorkText.getLength() )
+ {
+ // Position is out of range. Break loop!
+ nPosition = STRPOS_NOTFOUND;
+ nLength = 0;
+ }
+ else
+ {
+ // Else; Position is valid. Search for next variable to replace.
+ nPosition = aWorkText.indexOf( m_aVarStart, nPosition );
+ // Have we found any variable like "$(...)"?
+ if ( nPosition != STRPOS_NOTFOUND )
+ {
+ // Yes; Get length of found variable. If no ")" was found - nLength must set to 0!
+ nLength = 0;
+ sal_Int32 nEndPosition = aWorkText.indexOf( m_aVarEnd, nPosition );
+ if ( nEndPosition != STRPOS_NOTFOUND )
+ nLength = nEndPosition - nPosition + 1;
+ }
+ }
+ }
+
+ nPosition = aWorkText.indexOf( m_aVarStart );
+ if ( nPosition == -1 )
+ {
+ bSubstitutionCompleted = sal_True;
+ break; // All variables are substituted
+ }
+ else
+ {
+ // Check for recursion
+ const sal_uInt32 nCount = aEndlessRecursiveDetector.size();
+ for ( sal_uInt32 i=0; i < nCount; i++ )
+ {
+ if ( aEndlessRecursiveDetector[i] == aWorkText )
+ {
+ if ( bVarNotSubstituted )
+ break; // Not all variables could be substituted!
+ else
+ {
+ nDepth = nMaxRecursiveDepth;
+ break; // Recursion detected!
+ }
+ }
+ }
+
+ aEndlessRecursiveDetector.push_back( aWorkText );
+
+ // Initialize values for next
+ sal_Int32 nEndPosition = aWorkText.indexOf( m_aVarEnd, nPosition );
+ if ( nEndPosition != STRPOS_NOTFOUND )
+ nLength = nEndPosition - nPosition + 1;
+ bVarNotSubstituted = sal_False;
+ ++nDepth;
+ }
+ }
+
+ // Fill return value with result
+ if ( bSubstitutionCompleted )
+ {
+ // Substitution successfull!
+ aResult = aWorkText;
+ }
+ else
+ {
+ // Substitution not successfull!
+ if ( nDepth == nMaxRecursiveDepth )
+ {
+ // recursion depth reached!
+ if ( bSubstRequired )
+ {
+ rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM( "Endless recursion detected. Cannot substitute variables!" ));
+ throw NoSuchElementException( aMsg, (cppu::OWeakObject *)this );
+ }
+ else
+ aResult = rText;
+ }
+ else
+ {
+ // variable in text but unknwon!
+ if ( bSubstRequired )
+ {
+ rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM( "Unknown variable found!" ));
+ throw NoSuchElementException( aMsg, (cppu::OWeakObject *)this );
+ }
+ else
+ aResult = aWorkText;
+ }
+ }
+
+ return aResult;
+}
+
+rtl::OUString SubstitutePathVariables::impl_reSubstituteVariables( const ::rtl::OUString& rURL )
+throw ( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::impl_reSubstituteVariables" );
+ rtl::OUString aURL;
+
+ INetURLObject aUrl( rURL );
+ if ( !aUrl.HasError() )
+ aURL = aUrl.GetMainURL( INetURLObject::NO_DECODE );
+ else
+ {
+ // Convert a system path to a UCB compliant URL before resubstitution
+ rtl::OUString aTemp;
+ if ( osl::FileBase::getFileURLFromSystemPath( rURL, aTemp ) == osl::FileBase::E_None )
+ {
+ aTemp = ConvertOSLtoUCBURL( aTemp );
+ if ( aTemp.getLength() )
+ aURL = INetURLObject( aTemp ).GetMainURL( INetURLObject::NO_DECODE );
+ else
+ return rURL;
+ }
+ else
+ {
+ // rURL is not a valid URL nor a osl system path. Give up and return error!
+ return rURL;
+ }
+ }
+
+ // Due to a recursive definition this code must exchange variables with variables!
+ sal_Bool bResubstitutionCompleted = sal_False;
+ sal_Bool bVariableFound = sal_False;
+
+ // Get transient predefined path variable $(work) value before starting resubstitution
+ m_aPreDefVars.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
+
+ while ( !bResubstitutionCompleted )
+ {
+ ReSubstFixedVarOrderVector::const_iterator pIterFixed;
+ for ( pIterFixed = m_aReSubstFixedVarOrder.begin(); pIterFixed != m_aReSubstFixedVarOrder.end(); pIterFixed++ )
+ {
+ rtl::OUString aValue = m_aPreDefVars.m_FixedVar[ (sal_Int32)pIterFixed->eVariable ];
+ sal_Int32 nPos = aURL.indexOf( aValue );
+ if ( nPos >= 0 )
+ {
+ sal_Bool bMatch = sal_True;
+ if ( pIterFixed->eVariable == PREDEFVAR_LANG ||
+ pIterFixed->eVariable == PREDEFVAR_LANGID ||
+ pIterFixed->eVariable == PREDEFVAR_VLANG )
+ {
+ // Special path variables as they can occur in the middle of a path. Only match if they
+ // describe a whole directory and not only a substring of a directory!
+ const sal_Unicode* pStr = aURL.getStr();
+
+ if ( nPos > 0 )
+ bMatch = ( aURL[ nPos-1 ] == '/' );
+
+ if ( bMatch )
+ {
+ if ( nPos + aValue.getLength() < aURL.getLength() )
+ bMatch = ( pStr[ nPos + aValue.getLength() ] == '/' );
+ }
+ }
+
+ if ( bMatch )
+ {
+ rtl::OUStringBuffer aStrBuffer( aURL.getLength() );
+ aStrBuffer.append( aURL.copy( 0, nPos ) );
+ aStrBuffer.append( m_aPreDefVars.m_FixedVarNames[ (sal_Int32)pIterFixed->eVariable ] ); // Get the variable name for struct var name array!
+ aStrBuffer.append( aURL.copy( nPos + aValue.getLength(), ( aURL.getLength() - ( nPos + aValue.getLength() )) ));
+ aURL = aStrBuffer.makeStringAndClear();
+ bVariableFound = sal_True; // Resubstitution not finished yet!
+ break;
+ }
+ }
+ }
+
+ // This part can be iteratered more than one time as variables can contain variables again!
+ ReSubstUserVarOrderVector::const_iterator pIterUser;
+ for ( pIterUser = m_aReSubstUserVarOrder.begin(); pIterUser != m_aReSubstUserVarOrder.end(); pIterUser++ )
+ {
+ rtl::OUString aVarValue = pIterUser->aVarName;
+ sal_Int32 nPos = aURL.indexOf( aVarValue );
+ if ( nPos >= 0 )
+ {
+ rtl::OUStringBuffer aStrBuffer( aURL.getLength() );
+ aStrBuffer.append( aURL.copy( 0, nPos ) );
+ aStrBuffer.append( m_aVarStart );
+ aStrBuffer.append( aVarValue );
+ aStrBuffer.append( m_aVarEnd );
+ aStrBuffer.append( aURL.copy( nPos + aVarValue.getLength(), ( aURL.getLength() - ( nPos + aVarValue.getLength() )) ));
+ aURL = aStrBuffer.makeStringAndClear();
+ bVariableFound = sal_True; // Resubstitution not finished yet!
+ }
+ }
+
+ if ( !bVariableFound )
+ bResubstitutionCompleted = sal_True;
+ else
+ bVariableFound = sal_False; // Next resubstitution
+ }
+
+ return aURL;
+}
+
+// This method support both request schemes "$("<varname>")" or "<varname>".
+::rtl::OUString SubstitutePathVariables::impl_getSubstituteVariableValue( const ::rtl::OUString& rVariable )
+throw ( NoSuchElementException, RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::impl_getSubstituteVariableValue" );
+ rtl::OUString aVariable;
+
+ sal_Int32 nPos = rVariable.indexOf( m_aVarStart );
+ if ( nPos == -1 )
+ {
+ // Prepare variable name before hash map access
+ rtl::OUStringBuffer aStrBuffer( rVariable.getLength() + m_aVarStart.getLength() + m_aVarEnd.getLength() );
+ aStrBuffer.append( m_aVarStart );
+ aStrBuffer.append( rVariable );
+ aStrBuffer.append( m_aVarEnd );
+ aVariable = aStrBuffer.makeStringAndClear();
+ }
+
+ VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( ( nPos == -1 ) ? aVariable : rVariable );
+
+ // Fixed/Predefined variable
+ if ( pNTOIIter != m_aPreDefVarMap.end() )
+ {
+ PreDefVariable nIndex = (PreDefVariable)pNTOIIter->second;
+ return m_aPreDefVars.m_FixedVar[(sal_Int32)nIndex];
+ }
+ else
+ {
+ // Prepare variable name before hash map access
+ if ( nPos >= 0 )
+ {
+ if ( rVariable.getLength() > 3 )
+ aVariable = rVariable.copy( 2, rVariable.getLength() - 3 );
+ else
+ {
+ rtl::OUString aExceptionText( RTL_CONSTASCII_USTRINGPARAM( "Unknown variable!" ));
+ throw NoSuchElementException();
+ }
+ }
+ else
+ aVariable = rVariable;
+
+ // User defined variable
+ SubstituteVariables::const_iterator pIter = m_aSubstVarMap.find( aVariable );
+ if ( pIter != m_aSubstVarMap.end() )
+ {
+ // found!
+ return pIter->second.aSubstValue;
+ }
+
+ rtl::OUString aExceptionText( RTL_CONSTASCII_USTRINGPARAM( "Unknown variable!" ));
+ throw NoSuchElementException( aExceptionText, (cppu::OWeakObject *)this );
+ }
+}
+
+void SubstitutePathVariables::SetPredefinedPathVariables( PredefinedPathVariables& aPreDefPathVariables )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "SubstitutePathVariables::SetPredefinedPathVariables" );
+ Any aAny;
+ ::rtl::OUString aOfficePath;
+ ::rtl::OUString aUserPath;
+ ::rtl::OUString aTmp;
+ ::rtl::OUString aTmp2;
+ String aResult;
+
+ // Get inspath and userpath from bootstrap mechanism in every case as file URL
+ ::utl::Bootstrap::PathStatus aState;
+ ::rtl::OUString sVal ;
+
+ aState = utl::Bootstrap::locateBaseInstallation( sVal );
+ if( aState==::utl::Bootstrap::PATH_EXISTS ) {
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ] = ConvertOSLtoUCBURL( sVal );
+ }
+ else {
+ LOG_ERROR( "SubstitutePathVariables::SetPredefinedPathVariables", "Bootstrap code has no value for instpath!");
+ }
+
+ aState = utl::Bootstrap::locateUserData( sVal );
+ if( aState == ::utl::Bootstrap::PATH_EXISTS ) {
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ] = ConvertOSLtoUCBURL( sVal );
+ }
+ else {
+ LOG_ERROR( "SubstitutePathVariables::SetPredefinedPathVariables", "Bootstrap code has no value for userpath");
+ }
+
+ // Set $(inst), $(instpath), $(insturl)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTURL ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INST ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
+ // --> PB 2004-10-27 #i32656# - new variable of hierachy service
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_BASEINSTURL ]= aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
+ // <--
+
+ // Set $(user), $(userpath), $(userurl)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERURL ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USER ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
+ // --> PB 2004-11-11 #i32656# - new variable of hierachy service
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERDATAURL ]= aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
+ // <--
+
+ // Detect the program directory
+ // Set $(prog), $(progpath), $(progurl)
+ INetURLObject aProgObj(
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ] );
+ if ( !aProgObj.HasError() &&
+ aProgObj.insertName(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("program")) ) )
+ {
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ] = aProgObj.GetMainURL(INetURLObject::NO_DECODE);
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGURL ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ];
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROG ] = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ];
+ }
+
+ // Detect the language type of the current office
+ aPreDefPathVariables.m_eLanguageType = LANGUAGE_ENGLISH_US;
+ rtl::OUString aLocaleStr;
+ if ( utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty( utl::ConfigManager::LOCALE ) >>= aLocaleStr )
+ aPreDefPathVariables.m_eLanguageType = MsLangId::convertIsoStringToLanguage( aLocaleStr );
+ else
+ {
+ LOG_ERROR( "SubstitutePathVariables::SetPredefinedPathVariables", "Wrong Any type for language!" );
+ }
+
+ // Set $(lang)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_LANG ] = ConvertOSLtoUCBURL(
+ rtl::OUString::createFromAscii( ResMgr::GetLang( aPreDefPathVariables.m_eLanguageType, 0 ) ));
+ // Set $(vlang)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_VLANG ] = aLocaleStr;
+
+ // Set $(langid)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_LANGID ] = rtl::OUString::valueOf( (sal_Int32)aPreDefPathVariables.m_eLanguageType );
+
+ // Set the other pre defined path variables
+ // Set $(work)
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_HOME ] = GetHomeVariableValue();
+
+ // Set $(workdirurl) this is the value of the path PATH_WORK which doesn't make sense
+ // anymore because the path settings service has this value! It can deliver this value more
+ // quickly than the substitution service!
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_WORKDIRURL ] = GetWorkPath();
+
+ // Set $(path) variable
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PATH ] = GetPathVariableValue();
+
+ // Set $(temp)
+ osl::FileBase::getTempDirURL( aTmp );
+ aPreDefPathVariables.m_FixedVar[ PREDEFVAR_TEMP ] = ConvertOSLtoUCBURL( aTmp );
+
+ aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL] = rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR"));
+ rtl::Bootstrap::expandMacros(
+ aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL]);
+}
+
+} // namespace framework
diff --git a/framework/source/services/tabwindowservice.cxx b/framework/source/services/tabwindowservice.cxx
new file mode 100644
index 000000000000..ef29214bc229
--- /dev/null
+++ b/framework/source/services/tabwindowservice.cxx
@@ -0,0 +1,485 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+
+#include <services/tabwindowservice.hxx>
+#include <classes/fwktabwindow.hxx>
+#include <threadhelp/resetableguard.hxx>
+#include <services.h>
+#include <properties.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/urlobj.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// css::uno::XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+
+DEFINE_XINTERFACE_6 ( TabWindowService ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::lang::XComponent),
+ DIRECT_INTERFACE(css::awt::XSimpleTabController),
+ DIRECT_INTERFACE(css::beans::XPropertySet ),
+ DIRECT_INTERFACE(css::beans::XPropertySetInfo )
+ )
+
+DEFINE_XTYPEPROVIDER_6 ( TabWindowService ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::lang::XComponent ,
+ css::awt::XSimpleTabController ,
+ css::beans::XPropertySet ,
+ css::beans::XPropertySetInfo
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( TabWindowService ,
+ OWeakObject ,
+ SERVICENAME_TABWINDOWSERVICE ,
+ IMPLEMENTATIONNAME_TABWINDOWSERVICE
+ )
+
+DEFINE_INIT_SERVICE ( TabWindowService,
+ {
+ impl_initializePropInfo();
+ m_aTransactionManager.setWorkingMode( E_WORK );
+ }
+ )
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+TabWindowService::TabWindowService( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ // Attention:
+ // Don't change order of initialization!
+ // ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
+ // we must garant right initialization and a valid value of this! First initialize
+ // baseclasses and then members. And we need the mutex for other baseclasses !!!
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , TransactionBase ( )
+ , PropertySetHelper ( xFactory ,
+ &m_aLock ,
+ &m_aTransactionManager ,
+ sal_False ) // sal_False => dont release shared mutex on calling us!
+ , OWeakObject ( )
+
+ // Init member
+ , m_xFactory ( xFactory )
+ , m_xTabWin ( )
+ , m_pTabWin ( NULL )
+ , m_lTabPageInfos ( )
+ , m_lListener ( m_aLock.getShareableOslMutex())
+ , m_nPageIndexCounter ( 1 )
+ , m_nCurrentPageIndex ( 0 )
+{
+ // Safe impossible cases.
+ // Method not defined for all incoming parameter.
+ LOG_ASSERT( xFactory.is(), "TabWindowService::TabWindowService()\nInvalid parameter detected!\n" )
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+TabWindowService::~TabWindowService()
+{
+ // SAFE->
+ ResetableGuard aGuard(m_aLock);
+
+ if (m_pTabWin)
+ m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+::sal_Int32 SAL_CALL TabWindowService::insertTab()
+ throw ( css::uno::RuntimeException )
+{
+ // SAFE ->
+ ResetableGuard aGuard( m_aLock );
+
+ ::sal_Int32 nID = m_nPageIndexCounter++;
+ TTabPageInfo aInfo(nID);
+
+ m_lTabPageInfos[nID] = aInfo;
+
+ return nID;
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::removeTab(::sal_Int32 nID)
+ throw (css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException )
+{
+ // SAFE ->
+ ResetableGuard aGuard(m_aLock);
+
+ // throws suitable IndexOutOfBoundsException .-)
+ TTabPageInfoHash::iterator pIt = impl_getTabPageInfo (nID);
+ m_lTabPageInfos.erase(pIt);
+
+ FwkTabWindow* pTabWin = mem_TabWin ();
+ if (pTabWin)
+ pTabWin->RemovePage(nID);
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::setTabProps( ::sal_Int32 nID ,
+ const css::uno::Sequence< css::beans::NamedValue >& lProperties)
+ throw (css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException )
+{
+ // SAFE ->
+ ResetableGuard aGuard(m_aLock);
+
+ // throws suitable IndexOutOfBoundsException .-)
+ TTabPageInfoHash::iterator pIt = impl_getTabPageInfo (nID);
+ TTabPageInfo& rInfo = pIt->second;
+ rInfo.m_lProperties = lProperties;
+
+ if ( ! rInfo.m_bCreated)
+ {
+ FwkTabWindow* pTabWin = mem_TabWin ();
+ if (pTabWin)
+ {
+ pTabWin->AddTabPage(rInfo.m_nIndex, rInfo.m_lProperties);
+ rInfo.m_bCreated = sal_True;
+ }
+ }
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+css::uno::Sequence< css::beans::NamedValue > SAL_CALL TabWindowService::getTabProps(::sal_Int32 nID)
+ throw (css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException )
+{
+ // SAFE ->
+ ResetableGuard aGuard(m_aLock);
+
+ // throws suitable IndexOutOfBoundsException .-)
+ TTabPageInfoHash::const_iterator pIt = impl_getTabPageInfo (nID);
+ const TTabPageInfo& rInfo = pIt->second;
+
+ return rInfo.m_lProperties;
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::activateTab(::sal_Int32 nID)
+ throw (css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException )
+{
+ // SAFE ->
+ ResetableGuard aGuard(m_aLock);
+
+ // throws suitable IndexOutOfBoundsException .-)
+ impl_checkTabIndex (nID);
+ m_nCurrentPageIndex = nID;
+
+ FwkTabWindow* pTabWin = mem_TabWin ();
+ if (pTabWin)
+ pTabWin->ActivatePage(nID);
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+::sal_Int32 SAL_CALL TabWindowService::getActiveTabID()
+ throw (css::uno::RuntimeException)
+{
+ // SAFE->
+ ResetableGuard aGuard( m_aLock );
+ return m_nCurrentPageIndex;
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::addTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
+ throw (css::uno::RuntimeException)
+{
+ m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
+}
+
+//*****************************************************************************************************************
+// XSimpleTabController
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::removeTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
+ throw (css::uno::RuntimeException)
+{
+ m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
+}
+
+//*****************************************************************************************************************
+// XComponent
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::dispose()
+ throw (css::uno::RuntimeException)
+{
+ // SAFE->
+ ResetableGuard aGuard(m_aLock);
+
+ css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ css::lang::EventObject aEvent(xThis);
+
+ m_lListener.disposeAndClear (aEvent);
+
+ if (m_pTabWin)
+ m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
+
+ m_pTabWin = NULL;
+ m_xTabWin.clear();
+}
+
+//*****************************************************************************************************************
+// XComponent
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::addEventListener(const css::uno::Reference< css::lang::XEventListener >& xListener)
+ throw (css::uno::RuntimeException)
+{
+ m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
+}
+
+//*****************************************************************************************************************
+// XComponent
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener)
+ throw (css::uno::RuntimeException)
+{
+ m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
+}
+
+//*****************************************************************************************************************
+void TabWindowService::impl_initializePropInfo()
+{
+ impl_setPropertyChangeBroadcaster(static_cast< css::awt::XSimpleTabController* >(this));
+
+ impl_addPropertyInfo(
+ css::beans::Property(
+ TABWINDOWSERVICE_PROPNAME_WINDOW,
+ TABWINDOWSERVICE_PROPHANDLE_WINDOW,
+ ::getCppuType((const css::uno::Reference< css::awt::XWindow >*)NULL),
+ css::beans::PropertyAttribute::TRANSIENT));
+}
+
+//*****************************************************************************************************************
+void SAL_CALL TabWindowService::impl_setPropertyValue(const ::rtl::OUString& /*sProperty*/,
+ sal_Int32 /*nHandle */,
+ const css::uno::Any& /*aValue */)
+
+{
+}
+
+//*****************************************************************************************************************
+css::uno::Any SAL_CALL TabWindowService::impl_getPropertyValue(const ::rtl::OUString& /*sProperty*/,
+ sal_Int32 nHandle )
+{
+ /* There is no need to lock any mutex here. Because we share the
+ solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-)
+ see ctor of PropertySetHelper for further informations.
+ */
+ css::uno::Any aValue;
+
+ switch (nHandle)
+ {
+ case TABWINDOWSERVICE_PROPHANDLE_WINDOW:
+ {
+ mem_TabWin (); // force "creation on demand" of m_xTabWin :-)
+ aValue <<= m_xTabWin;
+ }
+ break;
+ }
+
+ return aValue;
+}
+
+//*****************************************************************************************************************
+// TabWindowService
+//*****************************************************************************************************************
+IMPL_LINK( TabWindowService, EventListener, VclSimpleEvent*, pEvent )
+{
+
+ if ( !pEvent && !pEvent->ISA(VclWindowEvent))
+ return 0;
+
+ sal_uLong nEventId = pEvent->GetId();
+ VclWindowEvent* pWinEvt = static_cast< VclWindowEvent* >(pEvent);
+
+ css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::lang::EventObject aEvent( xThis );
+
+ if (nEventId == VCLEVENT_OBJECT_DYING)
+ {
+ m_lListener.disposeAndClear (aEvent);
+
+ m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
+ m_pTabWin = NULL;
+ m_xTabWin.clear();
+
+ return 0;
+ }
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*) NULL));
+ if ( ! pContainer)
+ return 0;
+
+ ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ css::awt::XTabListener* pListener = (css::awt::XTabListener*)pIterator.next();
+
+ switch (nEventId)
+ {
+ case VCLEVENT_TABPAGE_ACTIVATE :
+ pListener->activated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
+ break;
+
+ case VCLEVENT_TABPAGE_DEACTIVATE :
+ pListener->deactivated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
+ break;
+
+ case VCLEVENT_TABPAGE_INSERTED :
+ pListener->inserted( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
+ break;
+
+ case VCLEVENT_TABPAGE_REMOVED :
+ pListener->removed( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
+ break;
+
+ case VCLEVENT_TABPAGE_PAGETEXTCHANGED :
+ case VCLEVENT_TABPAGE_REMOVEDALL :
+ break;
+ }
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ pIterator.remove();
+ }
+ }
+
+ return 0;
+}
+
+//*****************************************************************************************************************
+// TabWindowService
+//*****************************************************************************************************************
+void TabWindowService::impl_checkTabIndex (::sal_Int32 nID)
+ throw (css::lang::IndexOutOfBoundsException)
+{
+ if (
+ (nID <= 0 ) ||
+ (nID > m_nPageIndexCounter)
+ )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ ::rtl::OUString::createFromAscii("Tab index out of bounds."),
+ css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
+ }
+}
+
+//*****************************************************************************************************************
+// TabWindowService
+//*****************************************************************************************************************
+TTabPageInfoHash::iterator TabWindowService::impl_getTabPageInfo(::sal_Int32 nID)
+ throw (css::lang::IndexOutOfBoundsException)
+{
+ TTabPageInfoHash::iterator pIt = m_lTabPageInfos.find(nID);
+ if (pIt == m_lTabPageInfos.end ())
+ throw css::lang::IndexOutOfBoundsException(
+ ::rtl::OUString::createFromAscii("Tab index out of bounds."),
+ css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
+ return pIt;
+}
+
+//*****************************************************************************************************************
+// TabWindowService
+//*****************************************************************************************************************
+FwkTabWindow* TabWindowService::mem_TabWin ()
+{
+ FwkTabWindow* pWin = NULL;
+
+ if ( ! m_xTabWin.is ())
+ {
+ Window* pFakeParent = dynamic_cast< Window* >(Application::GetDefaultDevice ());
+
+ m_pTabWin = new FwkTabWindow (pFakeParent);
+ m_xTabWin = VCLUnoHelper::GetInterface (m_pTabWin);
+
+ m_pTabWin->AddEventListener( LINK( this, TabWindowService, EventListener ) );
+ }
+
+ if (m_xTabWin.is ())
+ pWin = m_pTabWin;
+
+ return pWin;
+}
+
+} // namespace framework
diff --git a/framework/source/services/taskcreatorsrv.cxx b/framework/source/services/taskcreatorsrv.cxx
new file mode 100644
index 000000000000..90bcdb93efbf
--- /dev/null
+++ b/framework/source/services/taskcreatorsrv.cxx
@@ -0,0 +1,404 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+#include "services/taskcreatorsrv.hxx"
+
+//_______________________________________________
+// own includes
+#include <helper/persistentwindowstate.hxx>
+#include <helper/tagwindowasmodified.hxx>
+#include <helper/titlebarupdate.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <loadenv/targethelper.hxx>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+
+//_______________________________________________
+// other includes
+#include <svtools/colorcfg.hxx>
+#include <vcl/svapp.hxx>
+
+#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
+#include <toolkit/unohlp.hxx>
+#endif
+#include <vcl/window.hxx>
+
+//_______________________________________________
+// namespaces
+
+namespace framework
+{
+
+//-----------------------------------------------
+const ::rtl::OUString TaskCreatorService::ARGUMENT_PARENTFRAME = ::rtl::OUString::createFromAscii("ParentFrame" ); // XFrame
+const ::rtl::OUString TaskCreatorService::ARGUMENT_FRAMENAME = ::rtl::OUString::createFromAscii("FrameName" ); // OUString
+const ::rtl::OUString TaskCreatorService::ARGUMENT_MAKEVISIBLE = ::rtl::OUString::createFromAscii("MakeVisible" ); // sal_Bool
+const ::rtl::OUString TaskCreatorService::ARGUMENT_CREATETOPWINDOW = ::rtl::OUString::createFromAscii("CreateTopWindow" ); // sal_Bool
+const ::rtl::OUString TaskCreatorService::ARGUMENT_POSSIZE = ::rtl::OUString::createFromAscii("PosSize" ); // Rectangle
+const ::rtl::OUString TaskCreatorService::ARGUMENT_CONTAINERWINDOW = ::rtl::OUString::createFromAscii("ContainerWindow" ); // XWindow
+const ::rtl::OUString TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE = ::rtl::OUString::createFromAscii("SupportPersistentWindowState" ); // sal_Bool
+const ::rtl::OUString TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE = ::rtl::OUString::createFromAscii("EnableTitleBarUpdate" ); // sal_Bool
+
+//-----------------------------------------------
+DEFINE_XINTERFACE_3(TaskCreatorService ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::lang::XSingleServiceFactory))
+
+//-----------------------------------------------
+DEFINE_XTYPEPROVIDER_3(TaskCreatorService ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::lang::XSingleServiceFactory)
+
+//-----------------------------------------------
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(TaskCreatorService ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_TASKCREATOR ,
+ IMPLEMENTATIONNAME_FWK_TASKCREATOR)
+
+//-----------------------------------------------
+DEFINE_INIT_SERVICE(
+ TaskCreatorService,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ }
+ )
+
+//-----------------------------------------------
+TaskCreatorService::TaskCreatorService(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase (&Application::GetSolarMutex())
+ , ::cppu::OWeakObject( )
+ , m_xSMGR (xSMGR )
+{
+}
+
+//-----------------------------------------------
+TaskCreatorService::~TaskCreatorService()
+{
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstance()
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ return createInstanceWithArguments(css::uno::Sequence< css::uno::Any >());
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ static ::rtl::OUString DEFAULTVAL_FRAMENAME = ::rtl::OUString();
+ static sal_Bool DEFAULTVAL_MAKEVISIBLE = sal_False;
+ static sal_Bool DEFAULTVAL_CREATETOPWINDOW = sal_True;
+ static css::awt::Rectangle DEFAULTVAL_POSSIZE = css::awt::Rectangle(0, 0, 0, 0); // only possize=[0,0,0,0] triggers default handling of vcl !
+ static sal_Bool DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE = sal_False;
+ static sal_Bool DEFAULTVAL_ENABLE_TITLEBARUPDATE = sal_True;
+
+ ::comphelper::SequenceAsHashMap lArgs(lArguments);
+
+ css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_PARENTFRAME , css::uno::Reference< css::frame::XFrame >());
+ ::rtl::OUString sFrameName = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_FRAMENAME , DEFAULTVAL_FRAMENAME );
+ sal_Bool bVisible = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_MAKEVISIBLE , DEFAULTVAL_MAKEVISIBLE );
+ sal_Bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CREATETOPWINDOW , DEFAULTVAL_CREATETOPWINDOW );
+ css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_POSSIZE , DEFAULTVAL_POSSIZE );
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CONTAINERWINDOW , css::uno::Reference< css::awt::XWindow >() );
+ sal_Bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE , DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE );
+ sal_Bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE , DEFAULTVAL_ENABLE_TITLEBARUPDATE );
+
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ // We use FrameName property to set it as API name of the new created frame later.
+ // But those frame names must be different from the set of special target names as e.g. _blank, _self etcpp !
+ ::rtl::OUString sRightName = impl_filterNames(sFrameName);
+
+ // if no external frame window was given ... create a new one.
+ if ( ! xContainerWindow.is())
+ {
+ css::uno::Reference< css::awt::XWindow > xParentWindow;
+ if (xParentFrame.is())
+ xParentWindow = xParentFrame->getContainerWindow();
+
+ // Parent has no own window ...
+ // So we have to create a top level window always !
+ if ( ! xParentWindow.is())
+ bCreateTopWindow = sal_True;
+
+ xContainerWindow = implts_createContainerWindow(xParentWindow, aPosSize, bCreateTopWindow);
+ }
+
+ //------------------->
+ // HACK #125187# + #i53630#
+ // Mark all document windows as "special ones", so VCL can bind
+ // special features to it. Because VCL doesnt know anything about documents ...
+ // Note: Doing so it's no longer supported, that e.g. our wizards can use findFrame(_blank)
+ // to create it's previes frames. They must do it manually by using WindowDescriptor+Toolkit!
+ css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY);
+ ::sal_Bool bTopLevelDocumentWindow = (
+ (sRightName.getLength () < 1) &&
+ (
+ (! xParentFrame.is() ) ||
+ ( xDesktop.is() )
+ )
+ );
+ if (bTopLevelDocumentWindow)
+ implts_applyDocStyleToWindow(xContainerWindow);
+ //------------------->
+
+ // create the new frame
+ css::uno::Reference< css::frame::XFrame > xFrame = implts_createFrame(xParentFrame, xContainerWindow, sRightName);
+
+ // special freature:
+ // A special listener will restore pos/size states in case
+ // a component was loaded into the frame first time.
+ if (bSupportPersistentWindowState)
+ implts_establishWindowStateListener(xFrame);
+
+ // special feature: On Mac we need tagging the window in case
+ // the underlying model was modified.
+ // VCL will ignore our calls in case different platform then Mac
+ // is used ...
+ if (bTopLevelDocumentWindow)
+ implts_establishDocModifyListener (xFrame);
+
+ // special freature:
+ // A special listener will update title bar (text and icon)
+ // if component of frame will be changed.
+ if (bEnableTitleBarUpdate)
+ implts_establishTitleBarUpdate(xFrame);
+
+ // Make it visible directly here ...
+ // if its required from outside.
+ if (bVisible)
+ xContainerWindow->setVisible(bVisible);
+
+ return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW);
+}
+
+//-----------------------------------------------
+void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const
+{
+ // SYNCHRONIZED ->
+ ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
+ Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow);
+ if (pVCLWindow)
+ pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT);
+ aSolarGuard.clear();
+ // <- SYNCHRONIZED
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::awt::XWindow > TaskCreatorService::implts_createContainerWindow( const css::uno::Reference< css::awt::XWindow >& xParentWindow ,
+ const css::awt::Rectangle& aPosSize ,
+ sal_Bool bTopWindow )
+{
+ // SAFE ->
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE
+
+ // get toolkit to create task container window
+ css::uno::Reference< css::awt::XToolkit > xToolkit( xSMGR->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY_THROW);
+
+ // Check if child frames can be created realy. We need at least a valid window at the parent frame ...
+ css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer;
+ if ( ! bTopWindow)
+ {
+ if ( ! xParentWindow.is())
+ bTopWindow = sal_False;
+ else
+ xParentWindowPeer = css::uno::Reference< css::awt::XWindowPeer >(xParentWindow, css::uno::UNO_QUERY_THROW);
+ }
+
+ // describe window properties.
+ css::awt::WindowDescriptor aDescriptor;
+ if (bTopWindow)
+ {
+ aDescriptor.Type = css::awt::WindowClass_TOP ;
+ aDescriptor.WindowServiceName = DECLARE_ASCII("window") ;
+ aDescriptor.ParentIndex = -1 ;
+ aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >() ;
+ aDescriptor.Bounds = aPosSize ;
+ aDescriptor.WindowAttributes = css::awt::WindowAttribute::BORDER |
+ css::awt::WindowAttribute::MOVEABLE |
+ css::awt::WindowAttribute::SIZEABLE |
+ css::awt::WindowAttribute::CLOSEABLE |
+ css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
+ }
+ else
+ {
+ aDescriptor.Type = css::awt::WindowClass_TOP ;
+ aDescriptor.WindowServiceName = DECLARE_ASCII("dockingwindow") ;
+ aDescriptor.ParentIndex = 1 ;
+ aDescriptor.Parent = xParentWindowPeer ;
+ aDescriptor.Bounds = aPosSize ;
+ aDescriptor.WindowAttributes = css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
+ }
+
+ // create a new blank container window and get access to parent container to append new created task.
+ css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor );
+ css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY );
+ if ( ! xWindow.is())
+ throw css::uno::Exception(::rtl::OUString::createFromAscii("TaskCreator service was not able to create suitable frame window."),
+ static_cast< ::cppu::OWeakObject* >(this));
+ if (bTopWindow)
+ xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor);
+ else
+ xPeer->setBackground(0xffffffff);
+
+ return xWindow;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::frame::XFrame > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame ,
+ const css::uno::Reference< css::awt::XWindow >& xContainerWindow,
+ const ::rtl::OUString& sName )
+{
+ // SAFE ->
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE
+
+ // create new frame.
+ css::uno::Reference< css::frame::XFrame > xNewFrame( xSMGR->createInstance( SERVICENAME_FRAME ), css::uno::UNO_QUERY_THROW );
+
+ // Set window on frame.
+ // Do it before calling any other interface methods ...
+ // The new created frame must be initialized before you can do anything else there.
+ xNewFrame->initialize( xContainerWindow );
+
+ // Put frame to the frame tree.
+ // Note: The property creator/parent will be set on the new putted frame automaticly ... by the parent container.
+ if (xParentFrame.is())
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames();
+ xContainer->append( xNewFrame );
+ }
+
+ // Set it's API name (if there is one from outside)
+ if (sName.getLength())
+ xNewFrame->setName( sName );
+
+ return xNewFrame;
+}
+
+//-----------------------------------------------
+void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ // SAFE ->
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE
+
+ // Special feature: It's allowed for frames using a top level window only!
+ // We must create a special listener service and couple it with the new created task frame.
+ // He will restore or save the window state of it ...
+ // See used classes for further informations too.
+ PersistentWindowState* pPersistentStateHandler = new PersistentWindowState(xSMGR);
+ css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW);
+
+ css::uno::Sequence< css::uno::Any > lInitData(1);
+ lInitData[0] <<= xFrame;
+ xInit->initialize(lInitData);
+}
+
+//-----------------------------------------------
+void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ // SAFE ->
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE
+
+ // Special feature: It's allowed for frames using a top level window only!
+ // We must create a special listener service and couple it with the new created task frame.
+ // It will tag the window as modified if the underlying model was modified ...
+ TagWindowAsModified* pTag = new TagWindowAsModified(xSMGR);
+ css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW);
+
+ css::uno::Sequence< css::uno::Any > lInitData(1);
+ lInitData[0] <<= xFrame;
+ xInit->initialize(lInitData);
+}
+
+//-----------------------------------------------
+void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ // SAFE ->
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE
+
+ TitleBarUpdate* pHelper = new TitleBarUpdate (xSMGR);
+ css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW);
+
+ css::uno::Sequence< css::uno::Any > lInitData(1);
+ lInitData[0] <<= xFrame;
+ xInit->initialize(lInitData);
+}
+
+//-----------------------------------------------
+::rtl::OUString TaskCreatorService::impl_filterNames( const ::rtl::OUString& sName )
+{
+ ::rtl::OUString sFiltered;
+ if (TargetHelper::isValidNameForFrame(sName))
+ sFiltered = sName;
+ return sFiltered;
+}
+
+} // namespace framework
diff --git a/framework/source/services/uriabbreviation.cxx b/framework/source/services/uriabbreviation.cxx
new file mode 100644
index 000000000000..1c89870c429d
--- /dev/null
+++ b/framework/source/services/uriabbreviation.cxx
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+#include "services/uriabbreviation.hxx"
+#include "services.h"
+
+#include "sal/config.h"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implementationentry.hxx"
+
+#include "tools/urlobj.hxx"
+
+// component helper namespace
+namespace css = ::com::sun::star;
+
+// framework namespace
+namespace framework
+{
+
+namespace css = ::com::sun::star;
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XSERVICEINFO_MULTISERVICE_2 ( UriAbbreviation ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_STRINGABBREVIATION ,
+ IMPLEMENTATIONNAME_URIABBREVIATION
+ )
+
+DEFINE_INIT_SERVICE ( UriAbbreviation,
+ {
+ }
+ )
+
+UriAbbreviation::UriAbbreviation(css::uno::Reference< css::uno::XComponentContext > const & context) :
+ m_xContext(context)
+{
+}
+
+// ::com::sun::star::util::XStringAbbreviation:
+::rtl::OUString SAL_CALL UriAbbreviation::abbreviateString(const css::uno::Reference< css::util::XStringWidth > & xStringWidth, ::sal_Int32 nWidth, const ::rtl::OUString & aString) throw (css::uno::RuntimeException)
+{
+ ::rtl::OUString aResult( aString );
+ if ( xStringWidth.is() )
+ {
+ // Use INetURLObject to abbreviate URLs
+ INetURLObject aURL( aString );
+ aResult = aURL.getAbbreviated( xStringWidth, nWidth, INetURLObject::DECODE_UNAMBIGUOUS );
+ }
+
+ return aResult;
+}
+
+} // namespace framework
+
+
+
+
+
diff --git a/framework/source/services/urltransformer.cxx b/framework/source/services/urltransformer.cxx
new file mode 100644
index 000000000000..cac8e7e359ca
--- /dev/null
+++ b/framework/source/services/urltransformer.cxx
@@ -0,0 +1,372 @@
+/*************************************************************************
+ *
+ * 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_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <services/urltransformer.hxx>
+#include <threadhelp/resetableguard.hxx>
+#include <macros/debug.hxx>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <tools/urlobj.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+using namespace ::osl ;
+using namespace ::cppu ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+using namespace ::com::sun::star::util ;
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+URLTransformer::URLTransformer( const Reference< XMultiServiceFactory >& /*xFactory*/ )
+{
+ // Safe impossible cases.
+ // Method not defined for all incoming parameter.
+ //LOG_ASSERT( xFactory.is(), "URLTransformer::URLTransformer()\nInvalid parameter detected!\n" )
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+URLTransformer::~URLTransformer()
+{
+}
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( URLTransformer ,
+ OWeakObject ,
+ SERVICENAME_URLTRANSFORMER ,
+ IMPLEMENTATIONNAME_URLTRANSFORMER
+ )
+
+DEFINE_INIT_SERVICE ( URLTransformer,
+ {
+ }
+ )
+
+namespace
+{
+ void lcl_ParserHelper(INetURLObject& _rParser,URL& _rURL,bool _bUseIntern)
+ {
+ // Get all information about this URL.
+ _rURL.Protocol = INetURLObject::GetScheme( _rParser.GetProtocol() );
+ _rURL.User = _rParser.GetUser ( INetURLObject::DECODE_WITH_CHARSET );
+ _rURL.Password = _rParser.GetPass ( INetURLObject::DECODE_WITH_CHARSET );
+ _rURL.Server = _rParser.GetHost ( INetURLObject::DECODE_WITH_CHARSET );
+ _rURL.Port = (sal_Int16)_rParser.GetPort();
+
+ sal_Int32 nCount = _rParser.getSegmentCount( false );
+ if ( nCount > 0 )
+ {
+ // Don't add last segment as it is the name!
+ --nCount;
+
+ rtl::OUStringBuffer aPath;
+ for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ aPath.append( sal_Unicode( '/' ));
+ aPath.append( _rParser.getName( nIndex, false, INetURLObject::NO_DECODE ));
+ }
+
+ if ( nCount > 0 )
+ aPath.append( sal_Unicode( '/' )); // final slash!
+
+ _rURL.Path = aPath.makeStringAndClear();
+ _rURL.Name = _rParser.getName( INetURLObject::LAST_SEGMENT, false, INetURLObject::NO_DECODE );
+ }
+ else
+ {
+ _rURL.Path = _rParser.GetURLPath( INetURLObject::NO_DECODE );
+ _rURL.Name = _rParser.GetName ( );
+ }
+
+ _rURL.Arguments = _rParser.GetParam ( INetURLObject::NO_DECODE );
+ _rURL.Mark = _rParser.GetMark ( INetURLObject::DECODE_WITH_CHARSET );
+
+ // INetURLObject supports only an intelligent method of parsing URL's. So write
+ // back Complete to have a valid encoded URL in all cases!
+ _rURL.Complete = _rParser.GetMainURL( INetURLObject::NO_DECODE );
+ if ( _bUseIntern )
+ _rURL.Complete = _rURL.Complete.intern();
+
+ _rParser.SetMark ( ::rtl::OUString() );
+ _rParser.SetParam( ::rtl::OUString() );
+
+ _rURL.Main = _rParser.GetMainURL( INetURLObject::NO_DECODE );
+ }
+}
+//*****************************************************************************************************************
+// XURLTransformer
+//*****************************************************************************************************************
+sal_Bool SAL_CALL URLTransformer::parseStrict( URL& aURL ) throw( RuntimeException )
+{
+ // Safe impossible cases.
+ if (( &aURL == NULL ) ||
+ ( aURL.Complete.getLength() < 1 ) )
+ {
+ return sal_False;
+ }
+ // Try to extract the protocol
+ sal_Int32 nURLIndex = aURL.Complete.indexOf( sal_Unicode( ':' ));
+ ::rtl::OUString aProtocol;
+ if ( nURLIndex > 1 )
+ {
+ aProtocol = aURL.Complete.copy( 0, nURLIndex+1 );
+
+ // If INetURLObject knows this protocol let it parse
+ if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
+ {
+ // Initialize parser with given URL.
+ INetURLObject aParser( aURL.Complete );
+
+ // Get all information about this URL.
+ INetProtocol eINetProt = aParser.GetProtocol();
+ if ( eINetProt == INET_PROT_NOT_VALID )
+ {
+ return sal_False;
+ }
+ else if ( !aParser.HasError() )
+ {
+ lcl_ParserHelper(aParser,aURL,false);
+ // Return "URL is parsed".
+ return sal_True;
+ }
+ }
+ else
+ {
+ // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
+ // in framework!
+ aURL.Protocol = aProtocol;
+ aURL.Main = aURL.Complete;
+ aURL.Path = aURL.Complete.copy( nURLIndex+1 );;
+
+ // Return "URL is parsed".
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//*****************************************************************************************************************
+// XURLTransformer
+//*****************************************************************************************************************
+sal_Bool SAL_CALL URLTransformer::parseSmart( URL& aURL ,
+ const ::rtl::OUString& sSmartProtocol ) throw( RuntimeException )
+{
+ // Safe impossible cases.
+ if (( &aURL == NULL ) ||
+ ( aURL.Complete.getLength() < 1 ) )
+ {
+ return sal_False;
+ }
+
+ // Initialize parser with given URL.
+ INetURLObject aParser;
+
+ aParser.SetSmartProtocol( INetURLObject::CompareProtocolScheme( sSmartProtocol ));
+ bool bOk = aParser.SetSmartURL( aURL.Complete );
+ if ( bOk )
+ {
+ lcl_ParserHelper(aParser,aURL,true);
+ // Return "URL is parsed".
+ return sal_True;
+ }
+ else
+ {
+ // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
+ // in framework!
+ if ( INetURLObject::CompareProtocolScheme( sSmartProtocol ) == INET_PROT_NOT_VALID )
+ {
+ // Try to extract the protocol
+ sal_Int32 nIndex = aURL.Complete.indexOf( sal_Unicode( ':' ));
+ ::rtl::OUString aProtocol;
+ if ( nIndex > 1 )
+ {
+ aProtocol = aURL.Complete.copy( 0, nIndex+1 );
+
+ // If INetURLObject knows this protocol something is wrong as detected before =>
+ // give up and return false!
+ if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
+ return sal_False;
+ else
+ aURL.Protocol = aProtocol;
+ }
+ else
+ return sal_False;
+
+ aURL.Main = aURL.Complete;
+ aURL.Path = aURL.Complete.copy( nIndex+1 );
+ return sal_True;
+ }
+ else
+ return sal_False;
+ }
+}
+
+//*****************************************************************************************************************
+// XURLTransformer
+//*****************************************************************************************************************
+sal_Bool SAL_CALL URLTransformer::assemble( URL& aURL ) throw( RuntimeException )
+{
+ // Safe impossible cases.
+ if ( &aURL == NULL )
+ return sal_False ;
+
+ // Initialize parser.
+ INetURLObject aParser;
+
+ if ( INetURLObject::CompareProtocolScheme( aURL.Protocol ) != INET_PROT_NOT_VALID )
+ {
+ ::rtl::OUStringBuffer aCompletePath( aURL.Path );
+
+ // Concat the name if it is provided, just support a final slash
+ if ( aURL.Name.getLength() > 0 )
+ {
+ sal_Int32 nIndex = aURL.Path.lastIndexOf( sal_Unicode('/') );
+ if ( nIndex == ( aURL.Path.getLength() -1 ))
+ aCompletePath.append( aURL.Name );
+ else
+ {
+ aCompletePath.append( sal_Unicode( '/' ) );
+ aCompletePath.append( aURL.Name );
+ }
+ }
+
+ bool bResult = aParser.ConcatData(
+ INetURLObject::CompareProtocolScheme( aURL.Protocol ) ,
+ aURL.User ,
+ aURL.Password ,
+ aURL.Server ,
+ aURL.Port ,
+ aCompletePath.makeStringAndClear() );
+
+ if ( !bResult )
+ return sal_False;
+
+ // First parse URL WITHOUT ...
+ aURL.Main = aParser.GetMainURL( INetURLObject::NO_DECODE );
+ // ...and then WITH parameter and mark.
+ aParser.SetParam( aURL.Arguments);
+ aParser.SetMark ( aURL.Mark, INetURLObject::ENCODE_ALL );
+ aURL.Complete = aParser.GetMainURL( INetURLObject::NO_DECODE );
+
+ // Return "URL is assembled".
+ return sal_True;
+ }
+ else if ( aURL.Protocol.getLength() > 0 )
+ {
+ // Minimal support for unknown protocols
+ ::rtl::OUStringBuffer aBuffer( aURL.Protocol );
+ aBuffer.append( aURL.Path );
+ aURL.Complete = aBuffer.makeStringAndClear();
+ aURL.Main = aURL.Complete;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+//*****************************************************************************************************************
+// XURLTransformer
+//*****************************************************************************************************************
+::rtl::OUString SAL_CALL URLTransformer::getPresentation( const URL& aURL ,
+ sal_Bool bWithPassword ) throw( RuntimeException )
+{
+ // Safe impossible cases.
+ if (( &aURL == NULL ) ||
+ ( aURL.Complete.getLength() < 1 ) ||
+ (( bWithPassword != sal_True ) &&
+ ( bWithPassword != sal_False ) ) )
+ {
+ return ::rtl::OUString();
+ }
+
+ // Check given URL
+ URL aTestURL = aURL;
+ sal_Bool bParseResult = parseSmart( aTestURL, aTestURL.Protocol );
+ if ( bParseResult )
+ {
+ if ( !bWithPassword && aTestURL.Password.getLength() > 0 )
+ {
+ // Exchange password text with other placeholder string
+ aTestURL.Password = ::rtl::OUString::createFromAscii( "<******>" );
+ assemble( aTestURL );
+ }
+
+ // Convert internal URLs to "praesentation"-URLs!
+ rtl::OUString sPraesentationURL;
+ INetURLObject::translateToExternal( aTestURL.Complete, sPraesentationURL, INetURLObject::DECODE_UNAMBIGUOUS );
+
+ return sPraesentationURL;
+ }
+ else
+ return ::rtl::OUString();
+}
+
+//_________________________________________________________________________________________________________________
+// debug methods
+//_________________________________________________________________________________________________________________
+
+
+} // namespace framework
+