summaryrefslogtreecommitdiff
path: root/framework/source/accelerators
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/accelerators')
-rw-r--r--framework/source/accelerators/acceleratorcache.cxx250
-rw-r--r--framework/source/accelerators/acceleratorconfiguration.cxx1717
-rw-r--r--framework/source/accelerators/acceleratorexecute.cxx382
-rw-r--r--framework/source/accelerators/acceleratorexecute.hxx255
-rw-r--r--framework/source/accelerators/documentacceleratorconfiguration.cxx240
-rw-r--r--framework/source/accelerators/globalacceleratorconfiguration.cxx127
-rw-r--r--framework/source/accelerators/keymapping.cxx229
-rw-r--r--framework/source/accelerators/makefile.mk52
-rw-r--r--framework/source/accelerators/moduleacceleratorconfiguration.cxx175
-rw-r--r--framework/source/accelerators/presethandler.cxx937
-rw-r--r--framework/source/accelerators/storageholder.cxx637
11 files changed, 5001 insertions, 0 deletions
diff --git a/framework/source/accelerators/acceleratorcache.cxx b/framework/source/accelerators/acceleratorcache.cxx
new file mode 100644
index 000000000000..96a266818d31
--- /dev/null
+++ b/framework/source/accelerators/acceleratorcache.cxx
@@ -0,0 +1,250 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/acceleratorcache.hxx>
+
+//_______________________________________________
+// own includes
+
+#ifndef __FRAMEWORK_XML_ACCELERATORCONFIGURATIONREADER_HXX_
+#include <xml/acceleratorconfigurationreader.hxx>
+#endif
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+//_______________________________________________
+// interface includes
+
+#ifndef __COM_SUN_STAR_CONTAINER_ELEMENTEXISTEXCEPTION_HPP_
+#include <com/sun/star/container/ElementExistException.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#endif
+
+//_______________________________________________
+// other includes
+#include <vcl/svapp.hxx>
+
+namespace framework
+{
+
+//-----------------------------------------------
+AcceleratorCache::AcceleratorCache()
+ : ThreadHelpBase(&Application::GetSolarMutex())
+{
+}
+
+//-----------------------------------------------
+AcceleratorCache::AcceleratorCache(const AcceleratorCache& rCopy)
+ : ThreadHelpBase(&Application::GetSolarMutex())
+{
+ m_lCommand2Keys = rCopy.m_lCommand2Keys;
+ m_lKey2Commands = rCopy.m_lKey2Commands;
+}
+
+//-----------------------------------------------
+AcceleratorCache::~AcceleratorCache()
+{
+ // Dont save anything automaticly here.
+ // The user has to do that explicitly!
+}
+
+//-----------------------------------------------
+void AcceleratorCache::takeOver(const AcceleratorCache& rCopy)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ m_lCommand2Keys = rCopy.m_lCommand2Keys;
+ m_lKey2Commands = rCopy.m_lKey2Commands;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+AcceleratorCache& AcceleratorCache::operator=(const AcceleratorCache& rCopy)
+{
+ takeOver(rCopy);
+ return *this;
+}
+
+//-----------------------------------------------
+sal_Bool AcceleratorCache::hasKey(const css::awt::KeyEvent& aKey) const
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ return (m_lKey2Commands.find(aKey) != m_lKey2Commands.end());
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+sal_Bool AcceleratorCache::hasCommand(const ::rtl::OUString& sCommand) const
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ return (m_lCommand2Keys.find(sCommand) != m_lCommand2Keys.end());
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+AcceleratorCache::TKeyList AcceleratorCache::getAllKeys() const
+{
+ TKeyList lKeys;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ lKeys.reserve(m_lKey2Commands.size());
+
+ TKey2Commands::const_iterator pIt;
+ TKey2Commands::const_iterator pEnd = m_lKey2Commands.end();
+ for ( pIt = m_lKey2Commands.begin();
+ pIt != pEnd ;
+ ++pIt )
+ {
+ lKeys.push_back(pIt->first);
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return lKeys;
+}
+
+//-----------------------------------------------
+void AcceleratorCache::setKeyCommandPair(const css::awt::KeyEvent& aKey ,
+ const ::rtl::OUString& sCommand)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // register command for the specified key
+ m_lKey2Commands[aKey] = sCommand;
+
+ // update optimized structure to bind multiple keys to one command
+ TKeyList& rKeyList = m_lCommand2Keys[sCommand];
+ rKeyList.push_back(aKey);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+AcceleratorCache::TKeyList AcceleratorCache::getKeysByCommand(const ::rtl::OUString& sCommand) const
+{
+ TKeyList lKeys;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TCommand2Keys::const_iterator pCommand = m_lCommand2Keys.find(sCommand);
+ if (pCommand == m_lCommand2Keys.end())
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(), css::uno::Reference< css::uno::XInterface >());
+ lKeys = pCommand->second;
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return lKeys;
+}
+
+//-----------------------------------------------
+::rtl::OUString AcceleratorCache::getCommandByKey(const css::awt::KeyEvent& aKey) const
+{
+ ::rtl::OUString sCommand;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TKey2Commands::const_iterator pKey = m_lKey2Commands.find(aKey);
+ if (pKey == m_lKey2Commands.end())
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(), css::uno::Reference< css::uno::XInterface >());
+ sCommand = pKey->second;
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return sCommand;
+}
+
+//-----------------------------------------------
+void AcceleratorCache::removeKey(const css::awt::KeyEvent& aKey)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // check if key exists
+ TKey2Commands::const_iterator pKey = m_lKey2Commands.find(aKey);
+ if (pKey == m_lKey2Commands.end())
+ return;
+
+ // get its registered command
+ // Because we must know its place inside the optimized
+ // structure, which bind keys to commands, too!
+ ::rtl::OUString sCommand = pKey->second;
+ pKey = m_lKey2Commands.end(); // nobody should use an undefined value .-)
+
+ // remove key from primary list
+ m_lKey2Commands.erase(aKey);
+
+ // remove key from optimized command list
+ m_lCommand2Keys.erase(sCommand);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AcceleratorCache::removeCommand(const ::rtl::OUString& sCommand)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ const TKeyList& lKeys = getKeysByCommand(sCommand);
+ AcceleratorCache::TKeyList::const_iterator pKey ;
+ for ( pKey = lKeys.begin();
+ pKey != lKeys.end() ;
+ ++pKey )
+ {
+ const css::awt::KeyEvent& rKey = *pKey;
+ removeKey(rKey);
+ }
+ m_lCommand2Keys.erase(sCommand);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+} // namespace framework
diff --git a/framework/source/accelerators/acceleratorconfiguration.cxx b/framework/source/accelerators/acceleratorconfiguration.cxx
new file mode 100644
index 000000000000..43772f5c4273
--- /dev/null
+++ b/framework/source/accelerators/acceleratorconfiguration.cxx
@@ -0,0 +1,1717 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/acceleratorconfiguration.hxx>
+
+//_______________________________________________
+// own includes
+#include <pattern/configuration.hxx>
+#include <accelerators/presethandler.hxx>
+
+#include <xml/saxnamespacefilter.hxx>
+#include <xml/acceleratorconfigurationreader.hxx>
+#include <xml/acceleratorconfigurationwriter.hxx>
+
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+#include <acceleratorconst.h>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+//_______________________________________________
+// other includes
+#include <vcl/svapp.hxx>
+
+#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
+#include <com/sun/star/container/XNamed.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
+#include <com/sun/star/container/XNameContainer.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_AWT_KEYEVENT_HPP_
+#include <com/sun/star/awt/KeyEvent.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
+#include <com/sun/star/awt/KeyModifier.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_UTIL_XCHANGESNOTIFIER_HPP_
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#endif
+
+#ifndef _COMPHELPER_CONFIGURATIONHELPER_HXX_
+#include <comphelper/configurationhelper.hxx>
+#endif
+
+#ifndef UNOTOOLS_CONFIGPATHES_HXX_INCLUDED
+#include <unotools/configpathes.hxx>
+#endif
+
+#ifndef _RTL_LOGFILE_HXX_
+#include <rtl/logfile.hxx>
+#endif
+
+#include <svtools/acceleratorexecute.hxx>
+
+#include <stdio.h>
+
+//_______________________________________________
+// const
+
+namespace framework
+{
+
+#ifdef fpc
+ #error "Who exports this define? I use it as namespace alias ..."
+#else
+ namespace fpc = ::framework::pattern::configuration;
+#endif
+
+ ::rtl::OUString lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping>& _rKeyMapping, const css::awt::KeyEvent& aKeyEvent)
+ {
+ const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
+ ::rtl::OUStringBuffer sKeyBuffer((_rKeyMapping->mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
+
+ if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
+ sKeyBuffer.appendAscii("_SHIFT");
+ if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 )
+ sKeyBuffer.appendAscii("_MOD1");
+ if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 )
+ sKeyBuffer.appendAscii("_MOD2");
+ if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 )
+ sKeyBuffer.appendAscii("_MOD3");
+
+ return sKeyBuffer.makeStringAndClear();
+ }
+
+//-----------------------------------------------
+// XInterface, XTypeProvider
+DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration ),
+ DIRECT_INTERFACE(css::form::XReset ),
+ DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
+ DIRECT_INTERFACE(css::ui::XUIConfigurationStorage ),
+ DIRECT_INTERFACE(css::ui::XUIConfiguration ))
+
+DEFINE_XTYPEPROVIDER_6(XMLBasedAcceleratorConfiguration ,
+ css::lang::XTypeProvider ,
+ css::ui::XAcceleratorConfiguration ,
+ css::form::XReset ,
+ css::ui::XUIConfigurationPersistence,
+ css::ui::XUIConfigurationStorage ,
+ css::ui::XUIConfiguration )
+
+//-----------------------------------------------
+XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
+ : ThreadHelpBase (&Application::GetSolarMutex())
+ , m_xSMGR (xSMGR )
+ , m_aPresetHandler(xSMGR )
+ , m_pWriteCache (0 )
+{
+}
+
+//-----------------------------------------------
+XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
+{
+ LOG_ASSERT(!m_pWriteCache, "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()\nChanges not flushed. Ignore it ...")
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG();
+ AcceleratorCache::TKeyList lKeys = rCache.getAllKeys();
+ return lKeys.getAsConstList();
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::rtl::OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
+ throw(css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG();
+ if (!rCache.hasKey(aKeyEvent))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+ return rCache.getCommandByKey(aKeyEvent);
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
+ const ::rtl::OUString& sCommand )
+ throw(css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ if (
+ (aKeyEvent.KeyCode == 0) &&
+ (aKeyEvent.KeyChar == 0) &&
+ (aKeyEvent.KeyFunc == 0) &&
+ (aKeyEvent.Modifiers == 0)
+ )
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Such key event seams not to be supported by any operating system."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 0);
+
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG(sal_True); // TRUE => force getting of a writeable cache!
+ rCache.setKeyCommandPair(aKeyEvent, sCommand);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
+throw(css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG(sal_True); // true => force using of a writeable cache
+ if (!rCache.hasKey(aKeyEvent))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+ rCache.removeKey(aKeyEvent);
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
+ throw(css::lang::IllegalArgumentException ,
+ css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1);
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG();
+ if (!rCache.hasCommand(sCommand))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(sCommand);
+ return lKeys.getAsConstList();
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
+ throw(css::lang::IllegalArgumentException ,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ sal_Int32 i = 0;
+ sal_Int32 c = lCommandList.getLength();
+ css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
+ AcceleratorCache& rCache = impl_getCFG();
+
+ for (i=0; i<c; ++i)
+ {
+ const ::rtl::OUString& rCommand = lCommandList[i];
+ if (!rCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ (sal_Int16)i);
+
+ if (!rCache.hasCommand(rCommand))
+ continue;
+
+ AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
+ if ( lKeys.empty() )
+ continue;
+
+ css::uno::Any& rAny = lPreferredOnes[i];
+ rAny <<= *(lKeys.begin());
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return lPreferredOnes;
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
+ throw(css::lang::IllegalArgumentException ,
+ css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 0);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rCache = impl_getCFG(sal_True); // TRUE => force getting of a writeable cache!
+ if (!rCache.hasCommand(sCommand))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
+ static_cast< ::cppu::OWeakObject* >(this));
+ rCache.removeCommand(sCommand);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::reload()
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ css::uno::Reference< css::io::XStream > xStreamNoLang;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // TRUE => open or create!
+ try
+ {
+ xStreamNoLang = m_aPresetHandler.openPreset(PresetHandler::PRESET_DEFAULT(), sal_True);
+ }
+ catch(const css::io::IOException&) {} // does not have to exist
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XInputStream > xIn;
+ if (xStream.is())
+ xIn = xStream->getInputStream();
+ if (!xIn.is())
+ throw css::io::IOException(
+ ::rtl::OUString::createFromAscii("Could not open accelerator configuration for reading."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ // impl_ts_load() does not clear the cache
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_aReadCache = AcceleratorCache();
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ impl_ts_load(xIn);
+
+ // Load also the general language independent default accelerators
+ // (ignoring the already defined accelerators)
+ if (xStreamNoLang.is())
+ {
+ xIn = xStreamNoLang->getInputStream();
+ if (xIn.is())
+ impl_ts_load(xIn);
+ }
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::store()
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // TRUE => open or create!
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XOutputStream > xOut;
+ if (xStream.is())
+ xOut = xStream->getOutputStream();
+
+ if (!xOut.is())
+ throw css::io::IOException(
+ ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ impl_ts_save(xOut);
+
+ xOut.clear();
+ xStream.clear();
+
+ m_aPresetHandler.commitUserChanges();
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
+ xStorage,
+ PresetHandler::TARGET_CURRENT(),
+ css::embed::ElementModes::READWRITE,
+ sal_False); // False => no fallback from read/write to readonly!
+ css::uno::Reference< css::io::XOutputStream > xOut;
+ if (xStream.is())
+ xOut = xStream->getOutputStream();
+
+ if (!xOut.is())
+ throw css::io::IOException(
+ ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ impl_ts_save(xOut);
+
+ // TODO inform listener about success, so it can flush the root and sub storage of this stream!
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ return (m_pWriteCache != 0);
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // TRUE => open or create!
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XOutputStream > xOut;
+ if (xStream.is())
+ xOut = xStream->getOutputStream();
+ return !(xOut.is());
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
+ return sal_False;
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
+throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_aPresetHandler.copyPresetToTarget(PresetHandler::PRESET_DEFAULT(), PresetHandler::TARGET_CURRENT());
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ reload();
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XMLBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+// IStorageListener
+void XMLBasedAcceleratorConfiguration::changesOccured(const ::rtl::OUString& /*sPath*/)
+{
+ reload();
+}
+
+//-----------------------------------------------
+void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ if (m_pWriteCache)
+ {
+ // be aware of reentrance problems - use temp variable for calling delete ... :-)
+ AcceleratorCache* pTemp = m_pWriteCache;
+ m_pWriteCache = 0;
+ delete pTemp;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
+ if (xSeek.is())
+ xSeek->seek(0);
+
+ // add accelerators to the cache (the cache is not cleared)
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+
+ // create the parser queue
+ // Note: Use special filter object between parser and reader
+ // to get filtered xml with right namespaces ...
+ // Use further a temp cache for reading!
+ AcceleratorConfigurationReader* pReader = new AcceleratorConfigurationReader(m_aReadCache);
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
+ SaxNamespaceFilter* pFilter = new SaxNamespaceFilter(xReader);
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
+
+ // connect parser, filter and stream
+ css::uno::Reference< css::xml::sax::XParser > xParser(xSMGR->createInstance(SERVICENAME_SAXPARSER), css::uno::UNO_QUERY_THROW);
+ xParser->setDocumentHandler(xFilter);
+
+ css::xml::sax::InputSource aSource;
+ aSource.aInputStream = xStream;
+
+ // TODO think about error handling
+ xParser->parseStream(aSource);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache aCache;
+ sal_Bool bChanged = (m_pWriteCache != 0);
+ if (bChanged)
+ aCache.takeOver(*m_pWriteCache);
+ else
+ aCache.takeOver(m_aReadCache);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
+ xClearable->truncate();
+
+ // TODO can be removed if seek(0) is done by truncate() automaticly!
+ css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
+ if (xSeek.is())
+ xSeek->seek(0);
+
+ // combine writer/cache/stream etcpp.
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter (xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::io::XActiveDataSource> xDataSource(xWriter , css::uno::UNO_QUERY_THROW);
+ xDataSource->setOutputStream(xStream);
+
+ // write into the stream
+ AcceleratorConfigurationWriter aWriter(aCache, xWriter);
+ aWriter.flush();
+
+ // take over all changes into the original container
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // take over all changes into the readonly cache ...
+ // and forget the copy-on-write copied cache
+ if (bChanged)
+ {
+ m_aReadCache.takeOver(*m_pWriteCache);
+ // live with reentrance .-)
+ AcceleratorCache* pTemp = m_pWriteCache;
+ m_pWriteCache = 0;
+ delete pTemp;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bWriteAccessRequested)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ //create copy of our readonly-cache, if write access is forced ... but
+ //not still possible!
+ if (
+ (bWriteAccessRequested) &&
+ (!m_pWriteCache )
+ )
+ {
+ m_pWriteCache = new AcceleratorCache(m_aReadCache);
+ }
+
+ // in case, we have a writeable cache, we use it for reading too!
+ // Otherwhise the API user cant find its own changes ...
+ if (m_pWriteCache)
+ return *m_pWriteCache;
+ else
+ return m_aReadCache;
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::comphelper::Locale XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
+{
+ static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
+ static ::rtl::OUString LOCALE_PATH = ::rtl::OUString::createFromAscii("L10N" );
+ static ::rtl::OUString LOCALE_KEY = ::rtl::OUString::createFromAscii("ooLocale" );
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::uno::XInterface > xCFG = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
+ css::uno::Reference< css::beans::XPropertySet > xProp (xCFG, css::uno::UNO_QUERY_THROW);
+ ::rtl::OUString sISOLocale;
+ xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
+
+ if (!sISOLocale.getLength())
+ return ::comphelper::Locale::EN_US();
+ return ::comphelper::Locale(sISOLocale);
+}
+
+/*******************************************************************************
+*
+* XCU based accelerator configuration
+*
+*******************************************************************************/
+
+//-----------------------------------------------
+// XInterface, XTypeProvider
+DEFINE_XINTERFACE_7(XCUBasedAcceleratorConfiguration ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration ),
+ DIRECT_INTERFACE(css::util::XChangesListener ),
+ DIRECT_INTERFACE(css::form::XReset ),
+ DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
+ DIRECT_INTERFACE(css::ui::XUIConfigurationStorage ),
+ DIRECT_INTERFACE(css::ui::XUIConfiguration ))
+
+ DEFINE_XTYPEPROVIDER_7(XCUBasedAcceleratorConfiguration ,
+ css::lang::XTypeProvider ,
+ css::ui::XAcceleratorConfiguration ,
+ css::util::XChangesListener ,
+ css::form::XReset ,
+ css::ui::XUIConfigurationPersistence,
+ css::ui::XUIConfigurationStorage ,
+ css::ui::XUIConfiguration )
+
+//-----------------------------------------------
+XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
+ : ThreadHelpBase (&Application::GetSolarMutex())
+ , m_xSMGR (xSMGR )
+ , m_pPrimaryWriteCache(0 )
+ , m_pSecondaryWriteCache(0 )
+{
+ static const ::rtl::OUString CFG_ENTRY_ACCELERATORS(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Accelerators"));
+ m_xCfg = css::uno::Reference< css::container::XNameAccess > (
+ ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
+ css::uno::UNO_QUERY );
+}
+
+//-----------------------------------------------
+XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
+{
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache::TKeyList lKeys = impl_getCFG(sal_True).getAllKeys(); //get keys from PrimaryKeys set
+
+ AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(sal_False).getAllKeys(); //get keys from SecondaryKeys set
+ lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
+ for ( pIt = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
+ lKeys.push_back(*pIt);
+
+ return lKeys.getAsConstList();
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::rtl::OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
+ throw(css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True );
+ AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
+
+ if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ if (rPrimaryCache.hasKey(aKeyEvent))
+ return rPrimaryCache.getCommandByKey(aKeyEvent);
+ else
+ return rSecondaryCache.getCommandByKey(aKeyEvent);
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
+ const ::rtl::OUString& sCommand )
+ throw(css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::setKeyEvent" );
+
+ if (
+ (aKeyEvent.KeyCode == 0) &&
+ (aKeyEvent.KeyChar == 0) &&
+ (aKeyEvent.KeyFunc == 0) &&
+ (aKeyEvent.Modifiers == 0)
+ )
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Such key event seams not to be supported by any operating system."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 0);
+
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True ); // TRUE => force getting of a writeable cache!
+ AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True); // TRUE => force getting of a writeable cache!
+
+ if ( rPrimaryCache.hasKey(aKeyEvent) )
+ {
+ ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
+ if ( sCommand != sOriginalCommand )
+ {
+ if (rSecondaryCache.hasCommand(sOriginalCommand))
+ {
+ AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
+ rSecondaryCache.removeKey(lSecondaryKeys[0]);
+ rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
+ }
+
+ if (rPrimaryCache.hasCommand(sCommand))
+ {
+ AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
+ rPrimaryCache.removeKey(lPrimaryKeys[0]);
+ rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
+ }
+
+ rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+ }
+
+ else if ( rSecondaryCache.hasKey(aKeyEvent) )
+ {
+ ::rtl::OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
+ if (sCommand != sOriginalCommand)
+ {
+ if (rPrimaryCache.hasCommand(sCommand))
+ {
+ AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
+ rPrimaryCache.removeKey(lPrimaryKeys[0]);
+ rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
+ }
+
+ rSecondaryCache.removeKey(aKeyEvent);
+ rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+ }
+
+ else
+ {
+ if (rPrimaryCache.hasCommand(sCommand))
+ {
+ AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
+ rPrimaryCache.removeKey(lPrimaryKeys[0]);
+ rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
+ }
+
+ rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
+ throw(css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True );
+ AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
+
+ if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ if (rPrimaryCache.hasKey(aKeyEvent))
+ {
+ ::rtl::OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
+ if (sDelCommand.getLength() > 0)
+ {
+ ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
+ if (rSecondaryCache.hasCommand(sOriginalCommand))
+ {
+ AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
+ rSecondaryCache.removeKey(lSecondaryKeys[0]);
+ rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
+ }
+
+ rPrimaryCache.removeKey(aKeyEvent);
+ }
+
+ }
+ else
+ {
+ ::rtl::OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
+ if (sDelCommand.getLength() > 0)
+ rSecondaryCache.removeKey(aKeyEvent);
+ }
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
+ throw(css::lang::IllegalArgumentException ,
+ css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1);
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True );
+ AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
+
+ if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString(),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ AcceleratorCache::TKeyList lKeys = rPrimaryCache.getKeysByCommand(sCommand);
+
+ AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
+ lKeys.push_back(*pIt);
+
+ return lKeys.getAsConstList();
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
+{
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ for ( pIt = lKeys.begin ();
+ pIt != lKeys.end ();
+ ++pIt )
+ {
+ const css::awt::KeyEvent& rAWTKey = *pIt;
+ const KeyCode aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
+ const String sName = aVCLKey.GetName();
+
+ if (sName.Len () > 0)
+ return pIt;
+ }
+
+ return lKeys.end ();
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
+ throw(css::lang::IllegalArgumentException ,
+ css::uno::RuntimeException )
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ sal_Int32 i = 0;
+ sal_Int32 c = lCommandList.getLength();
+ css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
+ AcceleratorCache& rCache = impl_getCFG(sal_True);
+
+ for (i=0; i<c; ++i)
+ {
+ const ::rtl::OUString& rCommand = lCommandList[i];
+ if (!rCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ (sal_Int16)i);
+
+ if (!rCache.hasCommand(rCommand))
+ continue;
+
+ AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
+ if ( lKeys.empty() )
+ continue;
+
+ AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
+ if (pPreferredKey != lKeys.end ())
+ {
+ css::uno::Any& rAny = lPreferredOnes[i];
+ rAny <<= *(pPreferredKey);
+ }
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return lPreferredOnes;
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
+ throw(css::lang::IllegalArgumentException ,
+ css::container::NoSuchElementException,
+ css::uno::RuntimeException )
+{
+ if (!sCommand.getLength())
+ throw css::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
+ static_cast< ::cppu::OWeakObject* >(this),
+ 0);
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True );
+ AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
+
+ if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
+ throw css::container::NoSuchElementException(
+ ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ if (rPrimaryCache.hasCommand(sCommand))
+ rPrimaryCache.removeCommand(sCommand);
+ if (rSecondaryCache.hasCommand(sCommand))
+ rSecondaryCache.removeCommand(sCommand);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::reload()" );
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ sal_Bool bPreferred;
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+
+ bPreferred = sal_True;
+ m_aPrimaryReadCache = AcceleratorCache();
+ if (m_pPrimaryWriteCache)
+ {
+ // be aware of reentrance problems - use temp variable for calling delete ... :-)
+ AcceleratorCache* pTemp = m_pPrimaryWriteCache;
+ m_pPrimaryWriteCache = 0;
+ delete pTemp;
+ }
+ m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
+ impl_ts_load(bPreferred, xAccess); // load the preferred keys
+
+ bPreferred = sal_False;
+ m_aSecondaryReadCache = AcceleratorCache();
+ if (m_pSecondaryWriteCache)
+ {
+ // be aware of reentrance problems - use temp variable for calling delete ... :-)
+ AcceleratorCache* pTemp = m_pSecondaryWriteCache;
+ m_pSecondaryWriteCache = 0;
+ delete pTemp;
+ }
+ m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
+ impl_ts_load(bPreferred, xAccess); // load the secondary keys
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::store()
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::store()" );
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ sal_Bool bPreferred;
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+
+ bPreferred = sal_True;
+ // on-demand creation of the primary write cache
+ impl_getCFG(bPreferred, sal_True);
+ m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
+ impl_ts_save(bPreferred, xAccess);
+
+ bPreferred = sal_False;
+ // on-demand creation of the secondary write cache
+ impl_getCFG(bPreferred, sal_True);
+ m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
+ impl_ts_save(bPreferred, xAccess);
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
+ if (!xStorage.is())
+ return;
+
+ long nOpenModes = css::embed::ElementModes::READWRITE;
+ css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(::rtl::OUString::createFromAscii("accelerator"), nOpenModes);
+ if (!xAcceleratorTypeStorage.is())
+ return;
+
+ css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(::rtl::OUString::createFromAscii("current"), nOpenModes);
+ css::uno::Reference< css::io::XOutputStream > xOut;
+ if (xStream.is())
+ xOut = xStream->getOutputStream();
+ if (!xOut.is())
+ throw css::io::IOException(
+ ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ // the original m_aCache has been split into primay cache and secondary cache...
+ // we should merge them before storing to storage
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ AcceleratorCache aCache;
+ if (m_pPrimaryWriteCache != 0)
+ aCache.takeOver(*m_pPrimaryWriteCache);
+ else
+ aCache.takeOver(m_aPrimaryReadCache);
+
+ AcceleratorCache::TKeyList lKeys;
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ if (m_pSecondaryWriteCache!=0)
+ {
+ lKeys = m_pSecondaryWriteCache->getAllKeys();
+ for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
+ aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
+ }
+ else
+ {
+ lKeys = m_aSecondaryReadCache.getAllKeys();
+ for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
+ aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
+ xClearable->truncate();
+ css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
+ if (xSeek.is())
+ xSeek->seek(0);
+
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter (m_xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::io::XActiveDataSource> xDataSource(xWriter , css::uno::UNO_QUERY_THROW);
+ xDataSource->setOutputStream(xOut);
+
+ // write into the stream
+ AcceleratorConfigurationWriter aWriter(aCache, xWriter);
+ aWriter.flush();
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
+ throw(css::uno::RuntimeException)
+{
+ return sal_False;
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
+ throw(css::uno::RuntimeException)
+{
+ return sal_False;
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
+}
+
+//-----------------------------------------------
+::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
+ return sal_False;
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
+ ::rtl::OUString sConfig = xNamed->getName();
+ if ( sConfig.equalsAscii("Global") )
+ {
+ m_xCfg = css::uno::Reference< css::container::XNameAccess > (
+ ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
+ css::uno::UNO_QUERY );
+ XCUBasedAcceleratorConfiguration::reload();
+ }
+ else if ( sConfig.equalsAscii("Modules") )
+ {
+ m_xCfg = css::uno::Reference< css::container::XNameAccess > (
+ ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
+ css::uno::UNO_QUERY );
+ XCUBasedAcceleratorConfiguration::reload();
+ }
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
+ throw(css::uno::RuntimeException)
+{
+ LOG_WARNING("XCUBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::changesOccurred()" );
+
+ css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
+ aEvent.Base >>= xHAccess;
+ if (! xHAccess.is ())
+ return;
+
+ css::util::ChangesEvent aReceivedEvents( aEvent );
+ const sal_Int32 c = aReceivedEvents.Changes.getLength();
+ sal_Int32 i = 0;
+ for (i=0; i<c; ++i)
+ {
+ const css::util::ElementChange& aChange = aReceivedEvents.Changes[i];
+
+ // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
+ // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
+ // So we try to split the path into 3 parts (module isnt important here, because we already know it ... because
+ // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
+
+ ::rtl::OUString sOrgPath ;
+ ::rtl::OUString sPath ;
+ ::rtl::OUString sKey;
+
+ aChange.Accessor >>= sOrgPath;
+ sPath = sOrgPath;
+ ::rtl::OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
+ ::rtl::OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
+
+ if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
+ {
+ ::rtl::OUString sModule;
+ sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
+ if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
+ reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
+ }
+ else if ( sGlobalModules.equals(CFG_ENTRY_MODULES) )
+ {
+ ::rtl::OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
+ sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
+
+ if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
+ {
+ reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------
+void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
+ throw(css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+void XCUBasedAcceleratorConfiguration::impl_ts_load( sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
+{
+ AcceleratorCache aReadCache = AcceleratorCache();
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+ if (m_sGlobalOrModules.equalsAscii("Global"))
+ xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
+ else if (m_sGlobalOrModules.equalsAscii("Modules"))
+ {
+ css::uno::Reference< css::container::XNameAccess > xModules;
+ xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
+ xModules->getByName(m_sModuleCFG) >>= xAccess;
+ }
+
+ const ::rtl::OUString sIsoLang = impl_ts_getLocale().toISO();
+ const ::rtl::OUString sDefaultLocale = ::rtl::OUString::createFromAscii("en-US");
+
+ css::uno::Reference< css::container::XNameAccess > xKey;
+ css::uno::Reference< css::container::XNameAccess > xCommand;
+ if (xAccess.is())
+ {
+ css::uno::Sequence< ::rtl::OUString > lKeys = xAccess->getElementNames();
+ sal_Int32 nKeys = lKeys.getLength();
+ for ( sal_Int32 i=0; i<nKeys; ++i )
+ {
+ ::rtl::OUString sKey = lKeys[i];
+ xAccess->getByName(sKey) >>= xKey;
+ xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
+
+ css::uno::Sequence< ::rtl::OUString > lLocales = xCommand->getElementNames();
+ sal_Int32 nLocales = lLocales.getLength();
+ ::std::vector< ::rtl::OUString > aLocales;
+ for ( sal_Int32 j=0; j<nLocales; ++j )
+ aLocales.push_back(lLocales[j]);
+
+ ::std::vector< ::rtl::OUString >::const_iterator pFound;
+ for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
+ {
+ if ( *pFound == sIsoLang )
+ break;
+ }
+
+ if ( pFound == aLocales.end() )
+ {
+ for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
+ {
+ if ( *pFound == sDefaultLocale )
+ break;
+ }
+
+ if ( pFound == aLocales.end() )
+ continue;
+ }
+
+ ::rtl::OUString sLocale = *pFound;
+ ::rtl::OUString sCommand;
+ xCommand->getByName(sLocale) >>= sCommand;
+ if (sCommand.getLength()<1)
+ continue;
+
+ css::awt::KeyEvent aKeyEvent;
+
+ sal_Int32 nIndex = 0;
+ ::rtl::OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
+ ::rtl::OUString sPrefix = ::rtl::OUString::createFromAscii("KEY_");
+ aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
+
+ css::uno::Sequence< ::rtl::OUString > sToken(4);
+ const sal_Int32 nToken = 4;
+ sal_Bool bValid = sal_True;
+ sal_Int32 k;
+ for (k=0; k<nToken; ++k)
+ {
+ if (nIndex < 0)
+ break;
+
+ sToken[k] = sKey.getToken(0, '_', nIndex);
+ ::rtl::OUString sTest = sToken[k];
+ if (sToken[k].getLength() < 1)
+ {
+ bValid = sal_False;
+ break;
+ }
+
+ if (sToken[k].equalsAscii("SHIFT"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
+ else if (sToken[k].equalsAscii("MOD1"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
+ else if (sToken[k].equalsAscii("MOD2"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
+ else if (sToken[k].equalsAscii("MOD3"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
+ else
+ {
+ bValid = sal_False;
+ break;
+ }
+ }
+
+ if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
+ aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+ }
+
+ if (bPreferred)
+ m_aPrimaryReadCache.takeOver(aReadCache);
+ else
+ m_aSecondaryReadCache.takeOver(aReadCache);
+}
+
+//-----------------------------------------------
+void XCUBasedAcceleratorConfiguration::impl_ts_save(sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
+{
+ if (bPreferred)
+ {
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ AcceleratorCache::TKeyList lPrimaryReadKeys = m_aPrimaryReadCache.getAllKeys();
+ AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
+
+ for ( pIt = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
+ {
+ if (!m_pPrimaryWriteCache->hasKey(*pIt))
+ removeKeyFromConfiguration(*pIt, sal_True);
+ }
+
+ for ( pIt = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
+ {
+ ::rtl::OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
+ if (!m_aPrimaryReadCache.hasKey(*pIt))
+ {
+ insertKeyToConfiguration(*pIt, sCommand, sal_True);
+ }
+ else
+ {
+ ::rtl::OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
+ if (sReadCommand != sCommand)
+ insertKeyToConfiguration(*pIt, sCommand, sal_True);
+ }
+ }
+
+ // take over all changes into the original container
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_pPrimaryWriteCache)
+ {
+ m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
+ AcceleratorCache* pTemp = m_pPrimaryWriteCache;
+ m_pPrimaryWriteCache = 0;
+ delete pTemp;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+ }
+
+ else
+ {
+ AcceleratorCache::TKeyList::const_iterator pIt;
+ AcceleratorCache::TKeyList lSecondaryReadKeys = m_aSecondaryReadCache.getAllKeys();
+ AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
+
+ for ( pIt = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
+ {
+ if (!m_pSecondaryWriteCache->hasKey(*pIt))
+ removeKeyFromConfiguration(*pIt, sal_False);
+ }
+
+
+ for ( pIt = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
+ {
+ ::rtl::OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
+ if (!m_aSecondaryReadCache.hasKey(*pIt))
+ {
+ insertKeyToConfiguration(*pIt, sCommand, sal_False);
+ }
+ else
+ {
+ ::rtl::OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
+ if (sReadCommand != sCommand)
+ insertKeyToConfiguration(*pIt, sCommand, sal_False);
+ }
+ }
+
+ // take over all changes into the original container
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_pSecondaryWriteCache)
+ {
+ m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
+ AcceleratorCache* pTemp = m_pSecondaryWriteCache;
+ m_pSecondaryWriteCache = 0;
+ delete pTemp;
+ }
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+ }
+
+ ::comphelper::ConfigurationHelper::flush(m_xCfg);
+}
+
+//-----------------------------------------------
+void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const ::rtl::OUString& sCommand, const sal_Bool bPreferred )
+{
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+ css::uno::Reference< css::container::XNameContainer > xContainer;
+ css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
+ css::uno::Reference< css::uno::XInterface > xInst;
+
+ if ( bPreferred )
+ m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
+ else
+ m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
+
+ if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
+ xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
+ else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
+ {
+ css::uno::Reference< css::container::XNameContainer > xModules;
+ xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
+ if ( !xModules->hasByName(m_sModuleCFG) )
+ {
+ xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
+ xInst = xFac->createInstance();
+ xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
+ }
+ xModules->getByName(m_sModuleCFG) >>= xContainer;
+ }
+
+ const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
+ css::uno::Reference< css::container::XNameAccess > xKey;
+ css::uno::Reference< css::container::XNameContainer > xCommand;
+ if ( !xContainer->hasByName(sKey) )
+ {
+ xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
+ xInst = xFac->createInstance();
+ xContainer->insertByName(sKey, css::uno::makeAny(xInst));
+ }
+ xContainer->getByName(sKey) >>= xKey;
+
+ xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
+ ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
+ if ( !xCommand->hasByName(sLocale) )
+ xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
+ else
+ xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
+}
+
+//-----------------------------------------------
+void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const sal_Bool bPreferred )
+{
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+ css::uno::Reference< css::container::XNameContainer > xContainer;
+
+ if ( bPreferred )
+ m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
+ else
+ m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
+
+ if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
+ xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
+ else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
+ {
+ css::uno::Reference< css::container::XNameAccess > xModules;
+ xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
+ if ( !xModules->hasByName(m_sModuleCFG) )
+ return;
+ xModules->getByName(m_sModuleCFG) >>= xContainer;
+ }
+
+ const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
+ xContainer->removeByName(sKey);
+}
+
+//-----------------------------------------------
+void XCUBasedAcceleratorConfiguration::reloadChanged( const ::rtl::OUString& sPrimarySecondary, const ::rtl::OUString& sGlobalModules, const ::rtl::OUString& sModule, const ::rtl::OUString& sKey )
+{
+ css::uno::Reference< css::container::XNameAccess > xAccess;
+ css::uno::Reference< css::container::XNameContainer > xContainer;
+
+ m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
+ if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
+ xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
+ else
+ {
+ css::uno::Reference< css::container::XNameAccess > xModules;
+ xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
+ if ( !xModules->hasByName(sModule) )
+ return;
+ xModules->getByName(sModule) >>= xContainer;
+ }
+
+ css::awt::KeyEvent aKeyEvent;
+ ::rtl::OUString sKeyIdentifier;
+
+ sal_Int32 nIndex = 0;
+ sKeyIdentifier = sKey.getToken(0, '_', nIndex);
+ aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(::rtl::OUString::createFromAscii("KEY_")+sKeyIdentifier);
+
+ css::uno::Sequence< ::rtl::OUString > sToken(3);
+ const sal_Int32 nToken = 3;
+ for (sal_Int32 i=0; i<nToken; ++i)
+ {
+ if ( nIndex < 0 )
+ break;
+
+ sToken[i] = sKey.getToken(0, '_', nIndex);
+ if (sToken[i].equalsAscii("SHIFT"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
+ else if (sToken[i].equalsAscii("MOD1"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
+ else if (sToken[i].equalsAscii("MOD2"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
+ else if (sToken[i].equalsAscii("MOD3"))
+ aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
+ }
+
+ css::uno::Reference< css::container::XNameAccess > xKey;
+ css::uno::Reference< css::container::XNameAccess > xCommand;
+ ::rtl::OUString sCommand;
+
+ if (xContainer->hasByName(sKey))
+ {
+ ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
+ xContainer->getByName(sKey) >>= xKey;
+ xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
+ xCommand->getByName(sLocale) >>= sCommand;
+ }
+
+ if (sPrimarySecondary.equals(CFG_ENTRY_PRIMARY))
+ {
+ if (sCommand.getLength() ==0)
+ m_aPrimaryReadCache.removeKey(aKeyEvent);
+ else
+ m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+ else if (sPrimarySecondary.equals(CFG_ENTRY_SECONDARY))
+ {
+ if (sCommand.getLength() ==0)
+ m_aSecondaryReadCache.removeKey(aKeyEvent);
+ else
+ m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
+ }
+}
+
+//-----------------------------------------------
+AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bPreferred, sal_Bool bWriteAccessRequested)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (bPreferred)
+ {
+ //create copy of our readonly-cache, if write access is forced ... but
+ //not still possible!
+ if (
+ (bWriteAccessRequested) &&
+ (!m_pPrimaryWriteCache )
+ )
+ {
+ m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
+ }
+
+ // in case, we have a writeable cache, we use it for reading too!
+ // Otherwhise the API user cant find its own changes ...
+ if (m_pPrimaryWriteCache)
+ return *m_pPrimaryWriteCache;
+ else
+ return m_aPrimaryReadCache;
+ }
+
+ else
+ {
+ //create copy of our readonly-cache, if write access is forced ... but
+ //not still possible!
+ if (
+ (bWriteAccessRequested) &&
+ (!m_pSecondaryWriteCache )
+ )
+ {
+ m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
+ }
+
+ // in case, we have a writeable cache, we use it for reading too!
+ // Otherwhise the API user cant find its own changes ...
+ if (m_pSecondaryWriteCache)
+ return *m_pSecondaryWriteCache;
+ else
+ return m_aSecondaryReadCache;
+ }
+
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::comphelper::Locale XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
+{
+ static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
+ static ::rtl::OUString LOCALE_PATH = ::rtl::OUString::createFromAscii("L10N" );
+ static ::rtl::OUString LOCALE_KEY = ::rtl::OUString::createFromAscii("ooLocale" );
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::uno::XInterface > xCFG = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
+ css::uno::Reference< css::beans::XPropertySet > xProp (xCFG, css::uno::UNO_QUERY_THROW);
+ ::rtl::OUString sISOLocale;
+ xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
+
+ if (!sISOLocale.getLength())
+ return ::comphelper::Locale::EN_US();
+ return ::comphelper::Locale(sISOLocale);
+}
+
+} // namespace framework
diff --git a/framework/source/accelerators/acceleratorexecute.cxx b/framework/source/accelerators/acceleratorexecute.cxx
new file mode 100644
index 000000000000..98fe7bb7630b
--- /dev/null
+++ b/framework/source/accelerators/acceleratorexecute.cxx
@@ -0,0 +1,382 @@
+/*************************************************************************
+ *
+ * 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 "acceleratorexecute.hxx"
+
+//===============================================
+// includes
+
+#ifndef __COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
+#include <com/sun/star/frame/XModuleManager.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGER_HPP_
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UI_XMODULEUICONFIGURATIONMANAGERSUPPLIER_HPP_
+#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGERSUPPLIER_HPP_
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
+#include <com/sun/star/awt/KeyModifier.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UNO_SEQUENCE_HXX_
+#include <com/sun/star/uno/Sequence.hxx>
+#endif
+
+#ifndef __COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
+#include <com/sun/star/beans/PropertyValue.hpp>
+#endif
+
+//===============================================
+// namespace
+
+namespace svt
+{
+
+namespace css = ::com::sun::star;
+
+//===============================================
+// definitions
+
+//-----------------------------------------------
+AcceleratorExecute::AcceleratorExecute()
+ : TMutexInit ( )
+ , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
+{
+}
+
+//-----------------------------------------------
+AcceleratorExecute::AcceleratorExecute(const AcceleratorExecute& rCopy)
+ : TMutexInit ( )
+ , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
+{
+ // copy construction sint supported in real ...
+ // but we need this ctor to init our async callback ...
+}
+
+//-----------------------------------------------
+AcceleratorExecute::~AcceleratorExecute()
+{
+ // does nothing real
+}
+
+//-----------------------------------------------
+AcceleratorExecute* AcceleratorExecute::createAcceleratorHelper()
+{
+ AcceleratorExecute* pNew = new AcceleratorExecute();
+ return pNew;
+}
+
+//-----------------------------------------------
+void AcceleratorExecute::init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR,
+ const css::uno::Reference< css::frame::XFrame >& xEnv )
+{
+ // SAFE -> ----------------------------------
+ ::osl::ResettableMutexGuard aLock(m_aLock);
+
+ // take over the uno service manager
+ m_xSMGR = xSMGR;
+
+ // specify our internal dispatch provider
+ // frame or desktop?! => document or global config.
+ sal_Bool bDesktopIsUsed = sal_False;
+ m_xDispatcher = css::uno::Reference< css::frame::XDispatchProvider >(xEnv, css::uno::UNO_QUERY);
+ if (!m_xDispatcher.is())
+ {
+ aLock.clear();
+ // <- SAFE ------------------------------
+
+ css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(
+ xSMGR->createInstance(SERVICENAME_DESKTOP),
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE -> ------------------------------
+ aLock.reset();
+
+ m_xDispatcher = xDispatcher;
+ bDesktopIsUsed = sal_True;
+ }
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ // open all needed configuration objects
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg ;
+
+ // global cfg
+ xGlobalCfg = AcceleratorExecute::impl_st_openGlobalConfig(xSMGR);
+ if (!bDesktopIsUsed)
+ {
+ // module cfg
+ xModuleCfg = AcceleratorExecute::impl_st_openModuleConfig(xSMGR, xEnv);
+
+ // doc cfg
+ css::uno::Reference< css::frame::XController > xController;
+ css::uno::Reference< css::frame::XModel > xModel;
+ xController = xEnv->getController();
+ if (xController.is())
+ xModel = xController->getModel();
+ if (xModel.is())
+ xDocCfg = AcceleratorExecute::impl_st_openDocConfig(xModel);
+ }
+
+ // SAFE -> ------------------------------
+ aLock.reset();
+
+ m_xGlobalCfg = xGlobalCfg;
+ m_xModuleCfg = xModuleCfg;
+ m_xDocCfg = xDocCfg ;
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void AcceleratorExecute::execute(const KeyCode& aVCLKey)
+{
+ css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
+ execute(aAWTKey);
+}
+
+//-----------------------------------------------
+void AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
+{
+ ::rtl::OUString sCommand = impl_ts_findCommand(aAWTKey);
+
+ // No Command found? Do nothing! User isnt interested on any error handling .-)
+ if (!sCommand.getLength())
+ return;
+
+ // SAFE -> ----------------------------------
+ ::osl::ResettableMutexGuard aLock(m_aLock);
+
+ m_lCommandQueue.push_back(sCommand);
+ m_aAsyncCallback.Post(0);
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const KeyCode& aVCLKey)
+{
+ css::awt::KeyEvent aAWTKey;
+ aAWTKey.Modifiers = 0;
+ aAWTKey.KeyCode = (sal_Int16)aVCLKey.GetCode();
+
+ if (aVCLKey.IsShift())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
+ if (aVCLKey.IsMod1())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
+ if (aVCLKey.IsMod2())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
+ if (aVCLKey.IsMod3())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
+
+ return aAWTKey;
+}
+
+/*
+ViewFrame->GetObjectShell
+ObjectShell->GetStyleSheetPool
+*/
+
+//-----------------------------------------------
+KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
+{
+ sal_Bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
+ sal_Bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
+ sal_Bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
+ sal_Bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
+ USHORT nKey = (USHORT)aAWTKey.KeyCode;
+
+ return KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
+}
+
+//-----------------------------------------------
+::rtl::OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
+{
+ // SAFE -> ----------------------------------
+ ::osl::ResettableMutexGuard aLock(m_aLock);
+
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg = m_xDocCfg ;
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ ::rtl::OUString sCommand;
+ try
+ {
+ if (xDocCfg.is())
+ sCommand = xDocCfg->getCommandByKeyEvent(aKey);
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ try
+ {
+ if (xModuleCfg.is())
+ sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ try
+ {
+ if (xGlobalCfg.is())
+ sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
+ }
+ catch(const css::container::NoSuchElementException&)
+ {}
+ }
+ }
+
+ return sCommand;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openGlobalConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+{
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg(
+ xSMGR->createInstance(SERVICENAME_GLOBALACCELERATORCONFIGURATION),
+ css::uno::UNO_QUERY_THROW);
+ return xAccCfg;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openModuleConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame)
+{
+ css::uno::Reference< css::frame::XModuleManager > xModuleDetection(
+ xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
+ css::uno::UNO_QUERY_THROW);
+
+ ::rtl::OUString sModule;
+ try
+ {
+ sModule = xModuleDetection->identify(xFrame);
+ }
+ catch(const css::uno::RuntimeException& exRuntime)
+ { throw exRuntime; }
+ catch(const css::uno::Exception&)
+ { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
+
+ css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
+ xSMGR->createInstance(SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER),
+ css::uno::UNO_QUERY_THROW);
+
+ css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager(sModule);
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg (xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
+ return xAccCfg;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
+{
+ css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager();
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg (xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
+ return xAccCfg;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
+{
+ // SAFE -> ----------------------------------
+ ::osl::ResettableMutexGuard aLock(m_aLock);
+
+ if (m_xURLParser.is())
+ return m_xURLParser;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::util::XURLTransformer > xParser(
+ xSMGR->createInstance(SERVICENAME_URLTRANSFORMER),
+ css::uno::UNO_QUERY_THROW);
+
+ // SAFE -> ----------------------------------
+ aLock.reset();
+ m_xURLParser = xParser;
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ return xParser;
+}
+
+//-----------------------------------------------
+IMPL_LINK(AcceleratorExecute, impl_ts_asyncCallback, void*, pVoid)
+{
+ // SAFE -> ----------------------------------
+ ::osl::ResettableMutexGuard aLock(m_aLock);
+
+ TCommandQueue::iterator pIt = m_lCommandQueue.begin();
+ if (pIt == m_lCommandQueue.end())
+ return 0;
+ ::rtl::OUString sCommand = *pIt;
+ m_lCommandQueue.erase(pIt);
+
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ // convert command in URL structure
+ css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
+ css::util::URL aURL;
+ aURL.Complete = sCommand;
+ xParser->parseStrict(aURL);
+
+ // ask for dispatch object
+ css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, ::rtl::OUString(), 0);
+ css::uno::Sequence< css::beans::PropertyValue> aArgs;
+ if (xDispatch.is())
+ {
+ if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
+ {
+ Sequence<css::beans::PropertyValue> source;
+ ::comphelper::UiEventsLogger::appendDispatchOrigin(OUString::createFromAscii("AcceleratorExecute"));
+ ::comphelper::UiEventsLogger::logDispatch(aURL, source);
+ }
+ xDispatch->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >());
+ }
+ return 0;
+}
+
+} // namespace svt
diff --git a/framework/source/accelerators/acceleratorexecute.hxx b/framework/source/accelerators/acceleratorexecute.hxx
new file mode 100644
index 000000000000..07f6348184e2
--- /dev/null
+++ b/framework/source/accelerators/acceleratorexecute.hxx
@@ -0,0 +1,255 @@
+/*************************************************************************
+ *
+ * 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 INCLUDED_SVTOOLS_ACCELERATOREXECUTE_HXX
+#define INCLUDED_SVTOOLS_ACCELERATOREXECUTE_HXX
+
+//===============================================
+// includes
+
+#include <vector>
+
+#ifndef __COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_FRAME_XFRAME_HPP_
+#include <com/sun/star/frame/XFrame.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UI_XACCELERATORCONFIGURATION_HPP_
+#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
+#include <com/sun/star/util/XURLTransformer.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_AWT_KEYEVENT_HPP_
+#include <com/sun/star/awt/KeyEvent.hpp>
+#endif
+#include <vcl/keycod.hxx>
+#include <vcl/evntpost.hxx>
+#include <osl/mutex.h>
+
+//===============================================
+// namespace
+
+namespace svt
+{
+
+#ifdef css
+ #error "Who define css? I need it as namespace alias."
+#else
+ #define css ::com::sun::star
+#endif
+
+//===============================================
+// definitions
+
+struct TMutexInit
+{
+ ::osl::Mutex m_aLock;
+};
+
+//===============================================
+/**
+ @descr implements a helper, which can be used to
+ convert vcl key codes into awt key codes ...
+ and reverse.
+
+ Further such key code can be triggered.
+ Doing so different accelerator
+ configurations are merged together; a suitable
+ command registered for the given key code is searched
+ and will be dispatched.
+
+ @attention
+
+ Because exceution of an accelerator command can be dangerous
+ (in case it force an office shutdown for key "ALT+F4"!)
+ all internal dispatches are done asynchronous.
+ Menas that the trigger call doesnt wait till the dispatch
+ is finished. You can call very often. All requests will be
+ queued internal and dispatched ASAP.
+
+ Of course this queue will be stopped if the environment
+ will be destructed ...
+ */
+class AcceleratorExecute : private TMutexInit
+{
+ //-------------------------------------------
+ // const, types
+ private:
+
+ /** TODO document me */
+ typedef ::std::vector< ::rtl::OUString > TCommandQueue;
+
+ //-------------------------------------------
+ // member
+ private:
+
+ /** TODO document me */
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
+
+ /** TODO document me */
+ css::uno::Reference< css::util::XURLTransformer > m_xURLParser;
+
+ /** TODO document me */
+ css::uno::Reference< css::frame::XDispatchProvider > m_xDispatcher;
+
+ /** TODO document me */
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xGlobalCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xModuleCfg;
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xDocCfg;
+
+ /** TODO document me */
+ TCommandQueue m_lCommandQueue;
+
+ /** TODO document me */
+ ::vcl::EventPoster m_aAsyncCallback;
+
+ //-------------------------------------------
+ // interface
+ public:
+
+ //---------------------------------------
+ /** @short factory method to create new accelerator
+ helper instance.
+
+ @descr Such helper instance must be initialized at first.
+ So it can know its environment (global/module or
+ document specific).
+
+ Afterwards it can be used to execute incoming
+ accelerator requests.
+
+ The "end of life" of such helper can be reached as follow:
+
+ - delete the object
+ => If it stands currently in its execute method, they will
+ be finished. All further queued requests will be removed
+ and further not executed!
+
+ Other modes are possible and will be implemented ASAP :-)
+ */
+ static AcceleratorExecute* createAcceleratorHelper();
+
+ //---------------------------------------
+ /** @short fight against inlining ... */
+ virtual ~AcceleratorExecute();
+
+ //---------------------------------------
+ /** @short init this instance.
+
+ @descr It must be called as first method after creation.
+ And further it can be called more then once ...
+ but at least its should be used one times only.
+ Otherwhise nobody can say, which asynchronous
+ executions will be used inside the old and which one
+ will be used inside the new environment.
+
+ @param xSMGR
+ reference to an uno service manager.
+
+ @param xEnv
+ if it points to a valid frame it will be used
+ to execute the dispatch there. Further the frame
+ is used to locate the right module configuration
+ and use it merged together with the document and
+ the global configuration.
+
+ If this parameter is set to NULL, the global configuration
+ is used only. Further the global Desktop instance is
+ used for dispatch.
+ */
+ virtual void init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR,
+ const css::uno::Reference< css::frame::XFrame >& xEnv );
+
+ //---------------------------------------
+ /** @short trigger this accelerator.
+
+ @descr The internal configuartions are used to find
+ as suitable command for this key code.
+ This command will be queued and executed later
+ asynchronous.
+
+ @param aKey
+ specify the accelerator for execute.
+ */
+ virtual void execute(const KeyCode& aKey);
+ virtual void execute(const css::awt::KeyEvent& aKey);
+
+ //---------------------------------------
+ /** TODO document me */
+ static css::awt::KeyEvent st_VCLKey2AWTKey(const KeyCode& aKey);
+ static KeyCode st_AWTKey2VCLKey(const css::awt::KeyEvent& aKey);
+
+ //-------------------------------------------
+ // internal
+ private:
+
+ //---------------------------------------
+ /** @short allow creation of instances of this class
+ by using our factory only!
+ */
+ AcceleratorExecute();
+ AcceleratorExecute(const AcceleratorExecute& rCopy);
+ void operator=(const AcceleratorExecute& rCopy) {};
+
+ //---------------------------------------
+ /** TODO document me */
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > impl_st_openGlobalConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR);
+
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > impl_st_openModuleConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame);
+
+ css::uno::Reference< css::ui::XAcceleratorConfiguration > impl_st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel);
+
+ //---------------------------------------
+ /** TODO document me */
+ ::rtl::OUString impl_ts_findCommand(const css::awt::KeyEvent& aKey);
+
+ //---------------------------------------
+ /** TODO document me */
+ css::uno::Reference< css::util::XURLTransformer > impl_ts_getURLParser();
+
+ //---------------------------------------
+ /** TODO document me */
+ DECL_LINK(impl_ts_asyncCallback, void*);
+};
+
+#undef css
+#undef css
+
+} // namespace svt
+
+#endif // INCLUDED_SVTOOLS_ACCELERATOREXECUTE_HXX
diff --git a/framework/source/accelerators/documentacceleratorconfiguration.cxx b/framework/source/accelerators/documentacceleratorconfiguration.cxx
new file mode 100644
index 000000000000..81edb165653c
--- /dev/null
+++ b/framework/source/accelerators/documentacceleratorconfiguration.cxx
@@ -0,0 +1,240 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/documentacceleratorconfiguration.hxx>
+
+#ifndef __FRAMEWORK_XML_ACCELERATORCONFIGURATIONREADER_HXX_
+#include <xml/acceleratorconfigurationreader.hxx>
+#endif
+
+#ifndef __FRAMEWORK_XML_ACCELERATORCONFIGURATIONWRITER_HXX_
+#include <xml/acceleratorconfigurationwriter.hxx>
+#endif
+
+#ifndef __FRAMEWORK_XML_SAXNAMESPACEFILTER_HXX_
+#include <xml/saxnamespacefilter.hxx>
+#endif
+
+//_______________________________________________
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+#ifndef __FRAMEWORK_ACCELERATORCONST_H_
+#include <acceleratorconst.h>
+#endif
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+
+#ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_
+#include <com/sun/star/io/XSeekable.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_IO_XTRUNCATE_HPP_
+#include <com/sun/star/io/XTruncate.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_
+#include <com/sun/star/embed/ElementModes.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_XML_SAX_INPUTSOURCE_HPP_
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_XML_SAX_XPARSER_HPP_
+#include <com/sun/star/xml/sax/XParser.hpp>
+#endif
+
+//_______________________________________________
+// other includes
+
+#ifndef _COMPHELPER_SEQUENCEASHASHMAP_HXX
+#include <comphelper/sequenceashashmap.hxx>
+#endif
+
+//_______________________________________________
+// const
+
+namespace framework
+{
+
+//-----------------------------------------------
+// XInterface, XTypeProvider, XServiceInfo
+DEFINE_XINTERFACE_2(DocumentAcceleratorConfiguration ,
+ XMLBasedAcceleratorConfiguration ,
+ DIRECT_INTERFACE(css::lang::XServiceInfo) ,
+ DIRECT_INTERFACE(css::lang::XInitialization))
+// DIRECT_INTERFACE(css::ui::XUIConfigurationStorage))
+
+DEFINE_XTYPEPROVIDER_2_WITH_BASECLASS(DocumentAcceleratorConfiguration ,
+ XMLBasedAcceleratorConfiguration ,
+ css::lang::XServiceInfo ,
+ css::lang::XInitialization)
+// css::ui::XUIConfigurationStorage)
+
+DEFINE_XSERVICEINFO_MULTISERVICE(DocumentAcceleratorConfiguration ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_DOCUMENTACCELERATORCONFIGURATION ,
+ IMPLEMENTATIONNAME_DOCUMENTACCELERATORCONFIGURATION)
+
+DEFINE_INIT_SERVICE(DocumentAcceleratorConfiguration,
+ {
+ /*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!
+ */
+ }
+ )
+
+//-----------------------------------------------
+DocumentAcceleratorConfiguration::DocumentAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
+ : XMLBasedAcceleratorConfiguration(xSMGR)
+{
+}
+
+//-----------------------------------------------
+DocumentAcceleratorConfiguration::~DocumentAcceleratorConfiguration()
+{
+ m_aPresetHandler.removeStorageListener(this);
+}
+
+//-----------------------------------------------
+void SAL_CALL DocumentAcceleratorConfiguration::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ ::comphelper::SequenceAsHashMap lArgs(lArguments);
+ m_xDocumentRoot = lArgs.getUnpackedValueOrDefault(
+ ::rtl::OUString::createFromAscii("DocumentRoot"),
+ css::uno::Reference< css::embed::XStorage >());
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ impl_ts_fillCache();
+}
+
+//-----------------------------------------------
+void SAL_CALL DocumentAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
+ throw(css::uno::RuntimeException)
+{
+ // Attention! xStorage must be accepted too, if it's NULL !
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ sal_Bool bForgetOldStorages = m_xDocumentRoot.is();
+ m_xDocumentRoot = xStorage;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (bForgetOldStorages)
+ impl_ts_clearCache();
+
+ if (xStorage.is())
+ impl_ts_fillCache();
+}
+
+//-----------------------------------------------
+sal_Bool SAL_CALL DocumentAcceleratorConfiguration::hasStorage()
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ return m_xDocumentRoot.is();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void DocumentAcceleratorConfiguration::impl_ts_fillCache()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xDocumentRoot = m_xDocumentRoot;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // Sometimes we must live without a document root.
+ // E.g. if the document is readonly ...
+ if (!xDocumentRoot.is())
+ return;
+
+ // get current office locale ... but dont cache it.
+ // Otherwise we must be listener on the configuration layer
+ // which seems to superflous for this small implementation .-)
+ ::comphelper::Locale aLocale = impl_ts_getLocale();
+
+ // May be the current document does not contain any
+ // accelerator config? Handle it gracefully :-)
+ try
+ {
+ // Note: The used preset class is threadsafe by itself ... and live if we live!
+ // We do not need any mutex here.
+
+ // open the folder, where the configuration exists
+ m_aPresetHandler.connectToResource(
+ PresetHandler::E_DOCUMENT,
+ PresetHandler::RESOURCETYPE_ACCELERATOR(),
+ ::rtl::OUString(),
+ xDocumentRoot,
+ aLocale);
+
+ DocumentAcceleratorConfiguration::reload();
+ m_aPresetHandler.addStorageListener(this);
+ }
+ /*
+
+ Sometimes the configuration seams to be corrupted ..
+ So it would be nice if we dont crash the office then .-)
+ #121559#
+
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ */
+ catch(const css::uno::Exception&)
+ {}
+}
+
+//-----------------------------------------------
+void DocumentAcceleratorConfiguration::impl_ts_clearCache()
+{
+ m_aPresetHandler.forgetCachedStorages();
+}
+
+} // namespace framework
diff --git a/framework/source/accelerators/globalacceleratorconfiguration.cxx b/framework/source/accelerators/globalacceleratorconfiguration.cxx
new file mode 100644
index 000000000000..dc040479d854
--- /dev/null
+++ b/framework/source/accelerators/globalacceleratorconfiguration.cxx
@@ -0,0 +1,127 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/globalacceleratorconfiguration.hxx>
+
+//_______________________________________________
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+#include <acceleratorconst.h>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/util/XChangesNotifier.hpp>
+
+//_______________________________________________
+// other includes
+#include <vcl/svapp.hxx>
+#include <comphelper/locale.hxx>
+#include <comphelper/configurationhelper.hxx>
+
+//_______________________________________________
+// const
+
+namespace framework
+{
+
+//-----------------------------------------------
+// XInterface, XTypeProvider, XServiceInfo
+DEFINE_XINTERFACE_2(GlobalAcceleratorConfiguration ,
+ XCUBasedAcceleratorConfiguration ,
+ DIRECT_INTERFACE(css::lang::XServiceInfo),
+ DIRECT_INTERFACE(css::lang::XInitialization))
+DEFINE_XTYPEPROVIDER_2_WITH_BASECLASS(GlobalAcceleratorConfiguration,
+ XCUBasedAcceleratorConfiguration ,
+ css::lang::XServiceInfo ,
+ css::lang::XInitialization)
+
+DEFINE_XSERVICEINFO_MULTISERVICE(GlobalAcceleratorConfiguration ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_GLOBALACCELERATORCONFIGURATION ,
+ IMPLEMENTATIONNAME_GLOBALACCELERATORCONFIGURATION)
+
+DEFINE_INIT_SERVICE(GlobalAcceleratorConfiguration,
+ {
+ /*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!
+ */
+ impl_ts_fillCache();
+ }
+ )
+
+//-----------------------------------------------
+GlobalAcceleratorConfiguration::GlobalAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
+ : XCUBasedAcceleratorConfiguration(xSMGR)
+{
+}
+
+//-----------------------------------------------
+GlobalAcceleratorConfiguration::~GlobalAcceleratorConfiguration()
+{
+}
+
+void SAL_CALL GlobalAcceleratorConfiguration::initialize(const css::uno::Sequence< css::uno::Any >& /*lArguments*/)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+void GlobalAcceleratorConfiguration::impl_ts_fillCache()
+{
+ // get current office locale ... but dont cache it.
+ // Otherwise we must be listener on the configuration layer
+ // which seems to superflous for this small implementation .-)
+ ::comphelper::Locale aLocale = ::comphelper::Locale(m_sLocale);
+
+ // May be there exists no accelerator config? Handle it gracefully :-)
+ try
+ {
+ m_sGlobalOrModules = CFG_ENTRY_GLOBAL;
+ XCUBasedAcceleratorConfiguration::reload();
+
+ css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(m_xCfg, css::uno::UNO_QUERY_THROW);
+ xBroadcaster->addChangesListener(static_cast< css::util::XChangesListener* >(this));
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+} // namespace framework
diff --git a/framework/source/accelerators/keymapping.cxx b/framework/source/accelerators/keymapping.cxx
new file mode 100644
index 000000000000..7d4054014524
--- /dev/null
+++ b/framework/source/accelerators/keymapping.cxx
@@ -0,0 +1,229 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/keymapping.hxx>
+
+//_______________________________________________
+// own includes
+
+#include <macros/generic.hxx>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/awt/Key.hpp>
+
+//_______________________________________________
+// other includes
+
+//_______________________________________________
+// namespace
+
+namespace framework
+{
+
+//_______________________________________________
+// helper
+
+KeyMapping::KeyIdentifierInfo KeyMapping::KeyIdentifierMap[] =
+{
+ {css::awt::Key::NUM0 , "KEY_0" },
+ {css::awt::Key::NUM1 , "KEY_1" },
+ {css::awt::Key::NUM2 , "KEY_2" },
+ {css::awt::Key::NUM3 , "KEY_3" },
+ {css::awt::Key::NUM4 , "KEY_4" },
+ {css::awt::Key::NUM5 , "KEY_5" },
+ {css::awt::Key::NUM6 , "KEY_6" },
+ {css::awt::Key::NUM7 , "KEY_7" },
+ {css::awt::Key::NUM8 , "KEY_8" },
+ {css::awt::Key::NUM9 , "KEY_9" },
+ {css::awt::Key::A , "KEY_A" },
+ {css::awt::Key::B , "KEY_B" },
+ {css::awt::Key::C , "KEY_C" },
+ {css::awt::Key::D , "KEY_D" },
+ {css::awt::Key::E , "KEY_E" },
+ {css::awt::Key::F , "KEY_F" },
+ {css::awt::Key::G , "KEY_G" },
+ {css::awt::Key::H , "KEY_H" },
+ {css::awt::Key::I , "KEY_I" },
+ {css::awt::Key::J , "KEY_J" },
+ {css::awt::Key::K , "KEY_K" },
+ {css::awt::Key::L , "KEY_L" },
+ {css::awt::Key::M , "KEY_M" },
+ {css::awt::Key::N , "KEY_N" },
+ {css::awt::Key::O , "KEY_O" },
+ {css::awt::Key::P , "KEY_P" },
+ {css::awt::Key::Q , "KEY_Q" },
+ {css::awt::Key::R , "KEY_R" },
+ {css::awt::Key::S , "KEY_S" },
+ {css::awt::Key::T , "KEY_T" },
+ {css::awt::Key::U , "KEY_U" },
+ {css::awt::Key::V , "KEY_V" },
+ {css::awt::Key::W , "KEY_W" },
+ {css::awt::Key::X , "KEY_X" },
+ {css::awt::Key::Y , "KEY_Y" },
+ {css::awt::Key::Z , "KEY_Z" },
+ {css::awt::Key::F1 , "KEY_F1" },
+ {css::awt::Key::F2 , "KEY_F2" },
+ {css::awt::Key::F3 , "KEY_F3" },
+ {css::awt::Key::F4 , "KEY_F4" },
+ {css::awt::Key::F5 , "KEY_F5" },
+ {css::awt::Key::F6 , "KEY_F6" },
+ {css::awt::Key::F7 , "KEY_F7" },
+ {css::awt::Key::F8 , "KEY_F8" },
+ {css::awt::Key::F9 , "KEY_F9" },
+ {css::awt::Key::F10 , "KEY_F10" },
+ {css::awt::Key::F11 , "KEY_F11" },
+ {css::awt::Key::F12 , "KEY_F12" },
+ {css::awt::Key::F13 , "KEY_F13" },
+ {css::awt::Key::F14 , "KEY_F14" },
+ {css::awt::Key::F15 , "KEY_F15" },
+ {css::awt::Key::F16 , "KEY_F16" },
+ {css::awt::Key::F17 , "KEY_F17" },
+ {css::awt::Key::F18 , "KEY_F18" },
+ {css::awt::Key::F19 , "KEY_F19" },
+ {css::awt::Key::F20 , "KEY_F20" },
+ {css::awt::Key::F21 , "KEY_F21" },
+ {css::awt::Key::F22 , "KEY_F22" },
+ {css::awt::Key::F23 , "KEY_F23" },
+ {css::awt::Key::F24 , "KEY_F24" },
+ {css::awt::Key::F25 , "KEY_F25" },
+ {css::awt::Key::F26 , "KEY_F26" },
+ {css::awt::Key::DOWN , "KEY_DOWN" },
+ {css::awt::Key::UP , "KEY_UP" },
+ {css::awt::Key::LEFT , "KEY_LEFT" },
+ {css::awt::Key::RIGHT , "KEY_RIGHT" },
+ {css::awt::Key::HOME , "KEY_HOME" },
+ {css::awt::Key::END , "KEY_END" },
+ {css::awt::Key::PAGEUP , "KEY_PAGEUP" },
+ {css::awt::Key::PAGEDOWN , "KEY_PAGEDOWN" },
+ {css::awt::Key::RETURN , "KEY_RETURN" },
+ {css::awt::Key::ESCAPE , "KEY_ESCAPE" },
+ {css::awt::Key::TAB , "KEY_TAB" },
+ {css::awt::Key::BACKSPACE , "KEY_BACKSPACE" },
+ {css::awt::Key::SPACE , "KEY_SPACE" },
+ {css::awt::Key::INSERT , "KEY_INSERT" },
+ {css::awt::Key::DELETE , "KEY_DELETE" },
+ {css::awt::Key::ADD , "KEY_ADD" },
+ {css::awt::Key::SUBTRACT , "KEY_SUBTRACT" },
+ {css::awt::Key::MULTIPLY , "KEY_MULTIPLY" },
+ {css::awt::Key::DIVIDE , "KEY_DIVIDE" },
+ {css::awt::Key::POINT , "KEY_POINT" },
+ {css::awt::Key::COMMA , "KEY_COMMA" },
+ {css::awt::Key::LESS , "KEY_LESS" },
+ {css::awt::Key::GREATER , "KEY_GREATER" },
+ {css::awt::Key::EQUAL , "KEY_EQUAL" },
+ {css::awt::Key::OPEN , "KEY_OPEN" },
+ {css::awt::Key::CUT , "KEY_CUT" },
+ {css::awt::Key::COPY , "KEY_COPY" },
+ {css::awt::Key::PASTE , "KEY_PASTE" },
+ {css::awt::Key::UNDO , "KEY_UNDO" },
+ {css::awt::Key::REPEAT , "KEY_REPEAT" },
+ {css::awt::Key::FIND , "KEY_FIND" },
+ {css::awt::Key::PROPERTIES , "KEY_PROPERTIES" },
+ {css::awt::Key::FRONT , "KEY_FRONT" },
+ {css::awt::Key::CONTEXTMENU , "KEY_CONTEXTMENU"},
+ {css::awt::Key::HELP , "KEY_HELP" },
+ {css::awt::Key::MENU , "KEY_MENU" },
+ {css::awt::Key::HANGUL_HANJA , "KEY_HANGUL_HANJA"},
+ {css::awt::Key::DECIMAL , "KEY_DECIMAL" },
+ {css::awt::Key::TILDE , "KEY_TILDE" },
+ {css::awt::Key::QUOTELEFT , "KEY_QUOTELEFT" },
+ {0 , "" } // mark the end of this array!
+};
+
+//-----------------------------------------------
+KeyMapping::KeyMapping()
+{
+ sal_Int32 i = 0;
+ while(KeyIdentifierMap[i].Code != 0)
+ {
+ ::rtl::OUString sIdentifier = ::rtl::OUString::createFromAscii(KeyIdentifierMap[i].Identifier);
+ sal_Int16 nCode = KeyIdentifierMap[i].Code;
+
+ m_lIdentifierHash[sIdentifier] = nCode ;
+ m_lCodeHash [nCode] = sIdentifier;
+
+ ++i;
+ }
+}
+
+//-----------------------------------------------
+KeyMapping::~KeyMapping()
+{
+}
+
+//-----------------------------------------------
+sal_uInt16 KeyMapping::mapIdentifierToCode(const ::rtl::OUString& sIdentifier)
+ throw(css::lang::IllegalArgumentException)
+{
+ Identifier2CodeHash::const_iterator pIt = m_lIdentifierHash.find(sIdentifier);
+ if (pIt != m_lIdentifierHash.end())
+ return pIt->second;
+
+ // Its not well known identifier - but may be a pure key code formated as string ...
+ // Check and convert it!
+ sal_uInt16 nCode = 0;
+ if (!KeyMapping::impl_st_interpretIdentifierAsPureKeyCode(sIdentifier, nCode))
+ throw css::lang::IllegalArgumentException(
+ DECLARE_ASCII("Cant map given identifier to a valid key code value."),
+ css::uno::Reference< css::uno::XInterface >(),
+ 0);
+
+ return (sal_uInt16)nCode;
+}
+
+//-----------------------------------------------
+::rtl::OUString KeyMapping::mapCodeToIdentifier(sal_uInt16 nCode)
+{
+ Code2IdentifierHash::const_iterator pIt = m_lCodeHash.find(nCode);
+ if (pIt != m_lCodeHash.end())
+ return pIt->second;
+
+ // If we have no well known identifier - use the pure code value!
+ return ::rtl::OUString::valueOf((sal_Int32)nCode);
+}
+
+//-----------------------------------------------
+sal_Bool KeyMapping::impl_st_interpretIdentifierAsPureKeyCode(const ::rtl::OUString& sIdentifier,
+ sal_uInt16& rCode )
+{
+ sal_Int32 nCode = sIdentifier.toInt32();
+ if (nCode > 0)
+ {
+ rCode = (sal_uInt16)nCode;
+ return sal_True;
+ }
+
+ // 0 is normaly an error of the called method toInt32() ...
+ // But we must be aware, that the identifier is "0"!
+ rCode = 0;
+ return sIdentifier.equalsAscii("0");
+}
+
+} // namespace framework
diff --git a/framework/source/accelerators/makefile.mk b/framework/source/accelerators/makefile.mk
new file mode 100644
index 000000000000..23a60dd1870e
--- /dev/null
+++ b/framework/source/accelerators/makefile.mk
@@ -0,0 +1,52 @@
+#*************************************************************************
+#
+# 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.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME= framework
+TARGET= fwk_accelerators
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Generate -----------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/keymapping.obj \
+ $(SLO)$/storageholder.obj \
+ $(SLO)$/presethandler.obj \
+ $(SLO)$/acceleratorcache.obj \
+ $(SLO)$/acceleratorconfiguration.obj \
+ $(SLO)$/globalacceleratorconfiguration.obj \
+ $(SLO)$/moduleacceleratorconfiguration.obj \
+ $(SLO)$/documentacceleratorconfiguration.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/framework/source/accelerators/moduleacceleratorconfiguration.cxx b/framework/source/accelerators/moduleacceleratorconfiguration.cxx
new file mode 100644
index 000000000000..566311d6f5be
--- /dev/null
+++ b/framework/source/accelerators/moduleacceleratorconfiguration.cxx
@@ -0,0 +1,175 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/moduleacceleratorconfiguration.hxx>
+
+//_______________________________________________
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+#ifndef __FRAMEWORK_ACCELERATORCONST_H_
+#include <acceleratorconst.h>
+#endif
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+
+//_______________________________________________
+// other includes
+
+#ifndef _COMPHELPER_SEQUENCEASHASHMAP_HXX
+#include <comphelper/sequenceashashmap.hxx>
+#endif
+#include <vcl/svapp.hxx>
+
+#ifndef _COMPHELPER_CONFIGURATIONHELPER_HXX_
+#include <comphelper/configurationhelper.hxx>
+#endif
+
+#ifndef _COM_SUN_STAR_UTIL_XCHANGESNOTIFIER_HPP_
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#endif
+
+#ifndef _RTL_LOGFILE_HXX_
+#include <rtl/logfile.hxx>
+#endif
+
+#ifndef _RTL_LOGFILE_HXX_
+#include <rtl/logfile.h>
+#endif
+
+//_______________________________________________
+// const
+
+namespace framework
+{
+
+//-----------------------------------------------
+// XInterface, XTypeProvider, XServiceInfo
+DEFINE_XINTERFACE_2(ModuleAcceleratorConfiguration ,
+ XCUBasedAcceleratorConfiguration ,
+ DIRECT_INTERFACE(css::lang::XServiceInfo) ,
+ DIRECT_INTERFACE(css::lang::XInitialization))
+
+DEFINE_XTYPEPROVIDER_2_WITH_BASECLASS(ModuleAcceleratorConfiguration,
+ XCUBasedAcceleratorConfiguration ,
+ css::lang::XServiceInfo ,
+ css::lang::XInitialization )
+
+DEFINE_XSERVICEINFO_MULTISERVICE(ModuleAcceleratorConfiguration ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_MODULEACCELERATORCONFIGURATION ,
+ IMPLEMENTATIONNAME_MODULEACCELERATORCONFIGURATION)
+
+DEFINE_INIT_SERVICE(ModuleAcceleratorConfiguration,
+ {
+ /*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!
+ */
+ }
+ )
+
+//-----------------------------------------------
+ModuleAcceleratorConfiguration::ModuleAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
+ : XCUBasedAcceleratorConfiguration(xSMGR)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleAcceleratorConfiguration::ModuleAcceleratorConfiguration" );
+}
+
+//-----------------------------------------------
+ModuleAcceleratorConfiguration::~ModuleAcceleratorConfiguration()
+{
+ // m_aPresetHandler.removeStorageListener(this);
+}
+
+//-----------------------------------------------
+void SAL_CALL ModuleAcceleratorConfiguration::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
+ throw(css::uno::Exception ,
+ css::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleAcceleratorConfiguration::initialize" );
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ ::comphelper::SequenceAsHashMap lArgs(lArguments);
+ m_sModule = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString());
+ m_sLocale = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("Locale") , ::rtl::OUString::createFromAscii("x-default"));
+
+ if (!m_sModule.getLength())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("The module dependend accelerator configuration service was initialized with an empty module identifier!"),
+ static_cast< ::cppu::OWeakObject* >(this));
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ impl_ts_fillCache();
+}
+
+//-----------------------------------------------
+void ModuleAcceleratorConfiguration::impl_ts_fillCache()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleAcceleratorConfiguration::impl_ts_fillCache" );
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ ::rtl::OUString sModule = m_sModule;
+ m_sModuleCFG = m_sModule;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // get current office locale ... but dont cache it.
+ // Otherwise we must be listener on the configuration layer
+ // which seems to superflous for this small implementation .-)
+ ::comphelper::Locale aLocale = ::comphelper::Locale(m_sLocale);
+
+ // May be the current app module does not have any
+ // accelerator config? Handle it gracefully :-)
+ try
+ {
+ m_sGlobalOrModules = CFG_ENTRY_MODULES;
+ XCUBasedAcceleratorConfiguration::reload();
+
+ css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(m_xCfg, css::uno::UNO_QUERY_THROW);
+ xBroadcaster->addChangesListener(static_cast< css::util::XChangesListener* >(this));
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+} // namespace framework
+
diff --git a/framework/source/accelerators/presethandler.cxx b/framework/source/accelerators/presethandler.cxx
new file mode 100644
index 000000000000..ecfe6d2a0a5f
--- /dev/null
+++ b/framework/source/accelerators/presethandler.cxx
@@ -0,0 +1,937 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/presethandler.hxx>
+
+//_______________________________________________
+// own includes
+#include <classes/fwkresid.hxx>
+
+#include "classes/resource.hrc"
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+
+#ifndef __COM_SUN_STAR_CONFIGURATION_CORRUPTEDUICONFIGURATIONEXCEPTION_HPP_
+#include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
+#include <com/sun/star/container/XNameAccess.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
+#include <com/sun/star/beans/XPropertySet.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_
+#include <com/sun/star/embed/ElementModes.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+//_______________________________________________
+// other includes
+#include <vcl/svapp.hxx>
+
+#ifndef _RTL_USTRBUF_HXX
+#include <rtl/ustrbuf.hxx>
+#endif
+
+//_______________________________________________
+// const
+
+#define SUBSTORAGE_GLOBAL DECLARE_ASCII("global" )
+#define SUBSTORAGE_MODULES DECLARE_ASCII("modules")
+
+#define BASEPATH_SHARE_LAYER DECLARE_ASCII("UIConfig" )
+#define BASEPATH_USER_LAYER DECLARE_ASCII("UserConfig")
+
+#define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg")
+#define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg")
+// #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
+// #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
+
+#define FILE_EXTENSION DECLARE_ASCII(".xml")
+
+#define PATH_SEPERATOR DECLARE_ASCII("/")
+
+static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1;
+static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2;
+static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3;
+
+//_______________________________________________
+// namespace
+
+namespace framework
+{
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::PRESET_DEFAULT()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("default");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::TARGET_CURRENT()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("current");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::RESOURCETYPE_MENUBAR()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("menubar");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::RESOURCETYPE_TOOLBAR()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("toolbar");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::RESOURCETYPE_ACCELERATOR()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("accelerator");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+::rtl::OUString PresetHandler::RESOURCETYPE_STATUSBAR()
+{
+ static ::rtl::OUString RSTYPE = DECLARE_ASCII("statusbar");
+ return RSTYPE;
+}
+
+//-----------------------------------------------
+PresetHandler::PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+ , m_xSMGR (xSMGR )
+ , m_aSharedStorages ( )
+ , m_lDocumentStorages(xSMGR )
+ , m_aLocale (::comphelper::Locale::X_NOTRANSLATE())
+{
+}
+
+//-----------------------------------------------
+PresetHandler::PresetHandler(const PresetHandler& rCopy)
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+{
+ m_xSMGR = rCopy.m_xSMGR;
+ m_eConfigType = rCopy.m_eConfigType;
+ m_sResourceType = rCopy.m_sResourceType;
+ m_sModule = rCopy.m_sModule;
+ m_aSharedStorages = rCopy.m_aSharedStorages;
+ m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare;
+ m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang;
+ m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser;
+ m_lPresets = rCopy.m_lPresets;
+ m_lTargets = rCopy.m_lTargets;
+ m_aLocale = rCopy.m_aLocale;
+ m_lDocumentStorages = rCopy.m_lDocumentStorages;
+ m_sRelPathShare = rCopy.m_sRelPathShare;
+ m_sRelPathNoLang = rCopy.m_sRelPathNoLang;
+ m_sRelPathUser = rCopy.m_sRelPathUser;
+}
+
+//-----------------------------------------------
+PresetHandler::~PresetHandler()
+{
+ m_xWorkingStorageShare.clear();
+ m_xWorkingStorageNoLang.clear();
+ m_xWorkingStorageUser.clear();
+
+ /* #i46497#
+ Dont call forgetCachedStorages() here for shared storages.
+ Because we opened different sub storages by using openPath().
+ And every already open path was reused and referenced (means it's
+ ref count was increased!)
+ So now we have to release our ref counts to these shared storages
+ only ... and not to free all used storages.
+ Otherwise we will disconnect all other open configuration access
+ objects which base on these storages.
+ */
+ m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare);
+ m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser );
+
+ /* On the other side closePath() is not needed for our special handled
+ document storage. Because it's not shared with others ... so we can
+ free it.
+ */
+ m_lDocumentStorages.forgetCachedStorages();
+}
+
+//-----------------------------------------------
+void PresetHandler::forgetCachedStorages()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ if (m_eConfigType == E_DOCUMENT)
+ {
+ m_xWorkingStorageShare.clear();
+ m_xWorkingStorageNoLang.clear();
+ m_xWorkingStorageUser.clear();
+ }
+
+ m_lDocumentStorages.forgetCachedStorages();
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+::rtl::OUString lcl_getLocalizedMessage(::sal_Int32 nID)
+{
+ ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("Unknown error.");
+
+ switch(nID)
+ {
+ case ID_CORRUPT_UICONFIG_SHARE :
+ sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_SHARE )));
+ break;
+
+ case ID_CORRUPT_UICONFIG_USER :
+ sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_USER )));
+ break;
+
+ case ID_CORRUPT_UICONFIG_GENERAL :
+ sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_GENERAL )));
+ break;
+ }
+
+ return sMessage;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare()
+{
+ css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage();
+ if (xRoot.is())
+ return xRoot;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::beans::XPropertySet > xPathSettings(
+ xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
+ css::uno::UNO_QUERY_THROW);
+
+ ::rtl::OUString sShareLayer;
+ xPathSettings->getPropertyValue(BASEPATH_SHARE_LAYER) >>= sShareLayer;
+
+ // "UIConfig" is a "multi path" ... use first part only here!
+ sal_Int32 nPos = sShareLayer.indexOf(';');
+ if (nPos > 0)
+ sShareLayer = sShareLayer.copy(0, nPos);
+
+ // Note: May be an user uses URLs without a final slash! Check it ...
+ nPos = sShareLayer.lastIndexOf('/');
+ if (nPos != sShareLayer.getLength()-1)
+ sShareLayer += ::rtl::OUString::createFromAscii("/");
+
+ sShareLayer += RELPATH_SHARE_LAYER; // folder
+ /*
+ // TODO remove me!
+ // Attention: This is temp. workaround ... We create a temp. storage file
+ // based of a sytem directory. This must be used so, till the storage implementation
+ // can work on directories too.
+ */
+ css::uno::Sequence< css::uno::Any > lArgs(2);
+ lArgs[0] <<= sShareLayer;
+ lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE;
+
+ css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::embed::XStorage > xStorage;
+
+ try
+ {
+ xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::configuration::CorruptedUIConfigurationException(
+ lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_SHARE),
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+
+ m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage);
+
+ return xStorage;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser()
+{
+ css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage();
+ if (xRoot.is())
+ return xRoot;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::beans::XPropertySet > xPathSettings(
+ xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
+ css::uno::UNO_QUERY_THROW);
+
+ ::rtl::OUString sUserLayer;
+ xPathSettings->getPropertyValue(BASEPATH_USER_LAYER) >>= sUserLayer ;
+
+ // Note: May be an user uses URLs without a final slash! Check it ...
+ sal_Int32 nPos = sUserLayer.lastIndexOf('/');
+ if (nPos != sUserLayer.getLength()-1)
+ sUserLayer += ::rtl::OUString::createFromAscii("/");
+
+ sUserLayer += RELPATH_USER_LAYER; // storage file
+
+ css::uno::Sequence< css::uno::Any > lArgs(2);
+ lArgs[0] <<= sUserLayer;
+ lArgs[1] <<= css::embed::ElementModes::READWRITE;
+
+ css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::embed::XStorage > xStorage;
+
+ try
+ {
+ xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::configuration::CorruptedUIConfigurationException(
+ lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_USER),
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+
+ m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage);
+
+ return xStorage;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ return m_xWorkingStorageShare;
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ return m_xWorkingStorageUser;
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageShare;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking);
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking);
+}
+
+//-----------------------------------------------
+void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType ,
+ const ::rtl::OUString& sResource ,
+ const ::rtl::OUString& sModule ,
+ const css::uno::Reference< css::embed::XStorage >& xDocumentRoot,
+ const ::comphelper::Locale& aLocale )
+{
+ // TODO free all current open storages!
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ m_eConfigType = eConfigType ;
+ m_sResourceType = sResource ;
+ m_sModule = sModule ;
+ m_aLocale = aLocale ;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::embed::XStorage > xShare;
+ css::uno::Reference< css::embed::XStorage > xNoLang;
+ css::uno::Reference< css::embed::XStorage > xUser;
+
+ // special case for documents
+ // use outside root storage, if we run in E_DOCUMENT mode!
+ if (eConfigType == E_DOCUMENT)
+ {
+ if (!xDocumentRoot.is())
+ throw css::uno::RuntimeException(
+ ::rtl::OUString::createFromAscii("There is valid root storage, where the UI configuration can work on."),
+ css::uno::Reference< css::uno::XInterface >());
+ m_lDocumentStorages.setRootStorage(xDocumentRoot);
+ xShare = xDocumentRoot;
+ xUser = xDocumentRoot;
+ }
+ else
+ {
+ xShare = getOrCreateRootStorageShare();
+ xUser = getOrCreateRootStorageUser();
+ }
+
+ // #...#
+ try
+ {
+
+ // a) inside share layer we should not create any new structures ... We jave to use
+ // existing ones only!
+ // b) inside user layer we can (SOFT mode!) but sometimes we shouldnt (HARD mode!)
+ // create new empty structures. We should preferr using of any existing structure.
+ sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE);
+ sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE );
+
+ ::rtl::OUStringBuffer sRelPathBuf(1024);
+ ::rtl::OUString sRelPathShare;
+ ::rtl::OUString sRelPathNoLang;
+ ::rtl::OUString sRelPathUser;
+ switch(eConfigType)
+ {
+ case E_GLOBAL :
+ {
+ sRelPathBuf.append(SUBSTORAGE_GLOBAL);
+ sRelPathBuf.append(PATH_SEPERATOR );
+ sRelPathBuf.append(sResource );
+ sRelPathShare = sRelPathBuf.makeStringAndClear();
+ sRelPathUser = sRelPathShare;
+
+ xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
+ xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
+ }
+ break;
+
+ case E_MODULES :
+ {
+ sRelPathBuf.append(SUBSTORAGE_MODULES);
+ sRelPathBuf.append(PATH_SEPERATOR );
+ sRelPathBuf.append(sModule );
+ sRelPathBuf.append(PATH_SEPERATOR );
+ sRelPathBuf.append(sResource );
+ sRelPathShare = sRelPathBuf.makeStringAndClear();
+ sRelPathUser = sRelPathShare;
+
+ xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
+ xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
+ }
+ break;
+
+ case E_DOCUMENT :
+ {
+ // A document does not have a share layer in real.
+ // It has one layer only, and this one should be opened READ_WRITE.
+ // So we open the user layer here only and set the share layer equals to it .-)
+
+ sRelPathBuf.append(sResource);
+ sRelPathUser = sRelPathBuf.makeStringAndClear();
+ sRelPathShare = sRelPathUser;
+
+ try
+ {
+ xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode );
+ xShare = xUser;
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { xShare.clear(); xUser.clear(); }
+ }
+ break;
+ }
+
+ // Non-localized global share
+ xNoLang = xShare;
+ sRelPathNoLang = sRelPathShare;
+
+ if (
+ (aLocale != ::comphelper::Locale::X_NOTRANSLATE()) && // localized level?
+ (eConfigType != E_DOCUMENT ) // no localization in document mode!
+ )
+ {
+ // First try to find the right localized set inside share layer.
+ // Fallbacks are allowed there.
+ ::comphelper::Locale aShareLocale = aLocale ;
+ ::rtl::OUString sLocalizedSharePath(sRelPathShare);
+ sal_Bool bAllowFallbacks = sal_True ;
+ xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, sal_True , aShareLocale, bAllowFallbacks);
+
+ // The try to locate the right sub dir inside user layer ... without using fallbacks!
+ // Normaly the corresponding sub dir should be created matching the specified locale.
+ // Because we allow creation of storages inside user layer by default.
+ ::comphelper::Locale aUserLocale = aLocale ;
+ ::rtl::OUString sLocalizedUserPath(sRelPathUser);
+ bAllowFallbacks = sal_False ;
+ xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode , sal_False, aUserLocale, bAllowFallbacks);
+
+ sRelPathShare = sLocalizedSharePath;
+ sRelPathUser = sLocalizedUserPath ;
+ }
+
+ // read content of level 3 (presets, targets)
+ css::uno::Reference< css::container::XNameAccess > xAccess ;
+ css::uno::Sequence< ::rtl::OUString > lNames ;
+ const ::rtl::OUString* pNames ;
+ sal_Int32 c ;
+ sal_Int32 i ;
+ OUStringList lPresets;
+ OUStringList lTargets;
+
+ // read preset names of share layer
+ xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY);
+ if (xAccess.is())
+ {
+ lNames = xAccess->getElementNames();
+ pNames = lNames.getConstArray();
+ c = lNames.getLength();
+
+ for (i=0; i<c; ++i)
+ {
+ ::rtl::OUString sTemp = pNames[i];
+ sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
+ if (nPos > -1)
+ sTemp = sTemp.copy(0,nPos);
+ lPresets.push_back(sTemp);
+ }
+ }
+
+ // read preset names of user layer
+ xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY);
+ if (xAccess.is())
+ {
+ lNames = xAccess->getElementNames();
+ pNames = lNames.getConstArray();
+ c = lNames.getLength();
+
+ for (i=0; i<c; ++i)
+ {
+ ::rtl::OUString sTemp = pNames[i];
+ sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
+ if (nPos > -1)
+ sTemp = sTemp.copy(0,nPos);
+ lTargets.push_back(sTemp);
+ }
+ }
+
+ // SAFE -> ----------------------------------
+ aWriteLock.lock();
+
+ m_xWorkingStorageShare = xShare ;
+ m_xWorkingStorageNoLang= xNoLang;
+ m_xWorkingStorageUser = xUser ;
+ m_lPresets = lPresets;
+ m_lTargets = lTargets;
+ m_sRelPathShare = sRelPathShare;
+ m_sRelPathNoLang = sRelPathNoLang;
+ m_sRelPathUser = sRelPathUser;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::configuration::CorruptedUIConfigurationException(
+ lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_GENERAL),
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+}
+
+//-----------------------------------------------
+void PresetHandler::copyPresetToTarget(const ::rtl::OUString& sPreset,
+ const ::rtl::OUString& sTarget)
+{
+ // dont check our preset list, if element exists
+ // We try to open it and forward all errors to the user!
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xWorkingShare = m_xWorkingStorageShare;
+ css::uno::Reference< css::embed::XStorage > xWorkingNoLang= m_xWorkingStorageNoLang;
+ css::uno::Reference< css::embed::XStorage > xWorkingUser = m_xWorkingStorageUser ;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // e.g. module without any config data ?!
+ if (
+ (!xWorkingShare.is()) ||
+ (!xWorkingUser.is() )
+ )
+ {
+ return;
+ }
+
+ ::rtl::OUString sPresetFile(sPreset);
+ sPresetFile += FILE_EXTENSION;
+
+ ::rtl::OUString sTargetFile(sTarget);
+ sTargetFile += FILE_EXTENSION;
+
+ // remove existing elements before you try to copy the preset to that location ...
+ // Otherwise w will get an ElementExistException inside copyElementTo()!
+ css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW);
+ if (xCheckingUser->hasByName(sTargetFile))
+ xWorkingUser->removeElement(sTargetFile);
+
+ xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile);
+
+ // If our storages work in transacted mode, we have
+ // to commit all changes from bottom to top!
+ commitUserChanges();
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const ::rtl::OUString& sPreset,
+ sal_Bool bUseNoLangGlobal)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // e.g. module without any config data ?!
+ if (!xFolder.is())
+ return css::uno::Reference< css::io::XStream >();
+
+ ::rtl::OUString sFile(sPreset);
+ sFile += FILE_EXTENSION;
+
+ // inform user about errors (use original exceptions!)
+ css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ);
+ return xStream;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const ::rtl::OUString& sTarget ,
+ sal_Bool bCreateIfMissing)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xFolder = m_xWorkingStorageUser;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // e.g. module without any config data ?!
+ if (!xFolder.is())
+ return css::uno::Reference< css::io::XStream >();
+
+ ::rtl::OUString sFile(sTarget);
+ sFile += FILE_EXTENSION;
+
+ sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE;
+ if (!bCreateIfMissing)
+ nOpenMode |= css::embed::ElementModes::NOCREATE;
+
+ // try it in read/write mode first and ignore errors.
+ css::uno::Reference< css::io::XStream > xStream;
+ try
+ {
+ xStream = xFolder->openStreamElement(sFile, nOpenMode);
+ return xStream;
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ { xStream.clear(); }
+
+ // try it readonly if it failed before.
+ // inform user about errors (use original exceptions!)
+ nOpenMode &= ~css::embed::ElementModes::WRITE;
+ xStream = xFolder->openStreamElement(sFile, nOpenMode);
+
+ return xStream;
+}
+
+//-----------------------------------------------
+void PresetHandler::commitUserChanges()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
+ EConfigType eCfgType = m_eConfigType;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // e.g. module without any config data ?!
+ if (!xWorking.is())
+ return;
+
+ ::rtl::OUString sPath;
+
+ switch(eCfgType)
+ {
+ case E_GLOBAL :
+ case E_MODULES :
+ {
+ sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking);
+ m_aSharedStorages->m_lStoragesUser.commitPath(sPath);
+ m_aSharedStorages->m_lStoragesUser.notifyPath(sPath);
+ }
+ break;
+
+ case E_DOCUMENT :
+ {
+ sPath = m_lDocumentStorages.getPathOfStorage(xWorking);
+ m_lDocumentStorages.commitPath(sPath);
+ m_lDocumentStorages.notifyPath(sPath);
+ }
+ break;
+ }
+}
+
+//-----------------------------------------------
+void PresetHandler::addStorageListener(IStorageListener* pListener)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
+ EConfigType eCfgType = m_eConfigType;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (!sRelPath.getLength())
+ return;
+
+ switch(eCfgType)
+ {
+ case E_GLOBAL :
+ case E_MODULES :
+ {
+ m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath);
+ }
+ break;
+
+ case E_DOCUMENT :
+ {
+ m_lDocumentStorages.addStorageListener(pListener, sRelPath);
+ }
+ break;
+ }
+}
+
+//-----------------------------------------------
+void PresetHandler::removeStorageListener(IStorageListener* pListener)
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
+ EConfigType eCfgType = m_eConfigType;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (!sRelPath.getLength())
+ return;
+
+ switch(eCfgType)
+ {
+ case E_GLOBAL :
+ case E_MODULES :
+ {
+ m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath);
+ }
+ break;
+
+ case E_DOCUMENT :
+ {
+ m_lDocumentStorages.removeStorageListener(pListener, sRelPath);
+ }
+ break;
+ }
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const ::rtl::OUString& sPath ,
+ sal_Int32 eMode ,
+ sal_Bool bShare)
+{
+ css::uno::Reference< css::embed::XStorage > xPath;
+ try
+ {
+ if (bShare)
+ xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode);
+ else
+ xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { xPath.clear(); }
+ return xPath;
+}
+
+//-----------------------------------------------
+::std::vector< ::rtl::OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(const ::std::vector< ::rtl::OUString >& lLocalizedValues,
+ ::comphelper::Locale& aLocale ,
+ sal_Bool bAllowFallbacks )
+{
+ ::std::vector< ::rtl::OUString >::const_iterator pFound = lLocalizedValues.end();
+ if (bAllowFallbacks)
+ {
+ pFound = ::comphelper::Locale::getFallback(lLocalizedValues, aLocale.toISO());
+ }
+ else
+ {
+ for ( pFound = lLocalizedValues.begin();
+ pFound != lLocalizedValues.end() ;
+ ++pFound )
+ {
+ const ::rtl::OUString& sCheckISO = *pFound;
+ ::comphelper::Locale aCheckLocale(sCheckISO);
+ if (aCheckLocale.equals(aLocale))
+ break;
+ }
+ }
+
+ // if we found a valid locale ... take it over to our in/out parameter aLocale
+ if (pFound != lLocalizedValues.end())
+ {
+ const ::rtl::OUString& sISOLocale = *pFound;
+ aLocale.fromISO(sISOLocale);
+ }
+
+ return pFound;
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(::rtl::OUString& sPath ,
+ sal_Int32 eMode ,
+ sal_Bool bShare ,
+ ::comphelper::Locale& aLocale ,
+ sal_Bool bAllowFallback)
+{
+ css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare);
+ ::std::vector< ::rtl::OUString > lSubFolders = impl_getSubFolderNames(xPath);
+ ::std::vector< ::rtl::OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, aLocale, bAllowFallback);
+
+ // no fallback ... creation not allowed => no storage
+ if (
+ (pLocaleFolder == lSubFolders.end() ) &&
+ ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE)
+ )
+ return css::uno::Reference< css::embed::XStorage >();
+
+ // it doesnt matter, if there is a locale fallback or not
+ // If creation of storages is allowed, we do it anyway.
+ // Otherwhise we have no acc config at all, which can make other trouble.
+ ::rtl::OUString sLocalizedPath;
+ sLocalizedPath = sPath;
+ sLocalizedPath += PATH_SEPERATOR;
+ if (pLocaleFolder != lSubFolders.end())
+ sLocalizedPath += *pLocaleFolder;
+ else
+ sLocalizedPath += aLocale.toISO();
+
+ css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare);
+
+ if (xLocalePath.is())
+ sPath = sLocalizedPath;
+ else
+ sPath = ::rtl::OUString();
+
+ return xLocalePath;
+}
+
+//-----------------------------------------------
+::std::vector< ::rtl::OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder)
+{
+ css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY);
+ if (!xAccess.is())
+ return ::std::vector< ::rtl::OUString >();
+
+ ::std::vector< ::rtl::OUString > lSubFolders;
+ const css::uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
+ const ::rtl::OUString* pNames = lNames.getConstArray();
+ sal_Int32 c = lNames.getLength();
+ sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ try
+ {
+ if (xFolder->isStorageElement(pNames[i]))
+ lSubFolders.push_back(pNames[i]);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {}
+ }
+
+ return lSubFolders;
+}
+
+//-----------------------------------------------
+} // namespace framework
diff --git a/framework/source/accelerators/storageholder.cxx b/framework/source/accelerators/storageholder.cxx
new file mode 100644
index 000000000000..33776d8c7fc1
--- /dev/null
+++ b/framework/source/accelerators/storageholder.cxx
@@ -0,0 +1,637 @@
+/*************************************************************************
+ *
+ * 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 <accelerators/storageholder.hxx>
+
+//===============================================
+// own includes
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <services.h>
+
+//===============================================
+// interface includes
+
+#ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
+#include <com/sun/star/container/XNameAccess.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
+#include <com/sun/star/beans/XPropertySet.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_
+#include <com/sun/star/embed/ElementModes.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_EMBED_XPACKAGESTRUCTURECREATOR_HPP_
+#include <com/sun/star/embed/XPackageStructureCreator.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+#ifndef __COM_SUN_STAR_IO_XSEEKABLE_HPP_
+#include <com/sun/star/io/XSeekable.hpp>
+#endif
+
+//===============================================
+// other includes
+#include <comphelper/processfactory.hxx>
+
+//===============================================
+// const
+
+#define PATH_SEPERATOR_ASCII "/"
+#define PATH_SEPERATOR_UNICODE ((sal_Unicode)'/')
+#define PATH_SEPERATOR ::rtl::OUString::createFromAscii(PATH_SEPERATOR_ASCII)
+
+//===============================================
+// namespace
+
+namespace framework
+{
+
+namespace css = ::com::sun::star;
+
+//-----------------------------------------------
+StorageHolder::StorageHolder()
+ : ThreadHelpBase( )
+ , m_xSMGR (::comphelper::getProcessServiceFactory())
+{
+}
+
+//-----------------------------------------------
+StorageHolder::StorageHolder(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase( )
+ , m_xSMGR (xSMGR)
+{
+}
+
+//-----------------------------------------------
+StorageHolder::~StorageHolder()
+{
+ // TODO implement me
+ // dispose/clear etcpp.
+}
+
+//-----------------------------------------------
+void StorageHolder::forgetCachedStorages()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ TPath2StorageInfo::iterator pIt;
+ for ( pIt = m_lStorages.begin();
+ pIt != m_lStorages.end() ;
+ ++pIt )
+ {
+ TStorageInfo& rInfo = pIt->second;
+ // TODO think about listener !
+ rInfo.Storage.clear();
+ }
+ m_lStorages.clear();
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+void StorageHolder::setRootStorage(const css::uno::Reference< css::embed::XStorage >& xRoot)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_xRoot = xRoot;
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > StorageHolder::getRootStorage() const
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ return m_xRoot;
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > StorageHolder::openPath(const ::rtl::OUString& sPath ,
+ sal_Int32 nOpenMode)
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
+ OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath);
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::embed::XStorage > xParent = m_xRoot;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::embed::XStorage > xChild ;
+ ::rtl::OUString sRelPath;
+ OUStringList::const_iterator pIt ;
+
+ for ( pIt = lFolders.begin();
+ pIt != lFolders.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& sChild = *pIt;
+ ::rtl::OUString sCheckPath (sRelPath);
+ sCheckPath += sChild;
+ sCheckPath += PATH_SEPERATOR;
+
+ // SAFE -> ------------------------------
+ aReadLock.lock();
+
+ // If we found an already open storage ... we must increase
+ // its use count. Otherwhise it will may be closed to early :-)
+ TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath);
+ TStorageInfo* pInfo = 0;
+ if (pCheck != m_lStorages.end())
+ {
+ pInfo = &(pCheck->second);
+ ++(pInfo->UseCount);
+ xChild = pInfo->Storage;
+ }
+ else
+ {
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+
+ try
+ {
+ xChild = StorageHolder::openSubStorageWithFallback(xParent, sChild, nOpenMode, sal_True); // TODO think about delegating fallback decision to our own calli!
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception& exAny)
+ {
+ /* TODO URGENT!
+ in case we found some "already existing storages" on the path before and increased its UseCount ...
+ and now we will get an exception on creating a new sub storage ...
+ we must decrease all UseCounts, which was touched before. Otherwise these storages cant be closed!
+
+ Idea: Using of another structure member "PossibleUseCount" as vector of unique numbers.
+ Every thread use another unique number to identify all "owned candidates".
+ A flush method with the same unique number force increasing of the "UseCount" variable then
+ inside a synchronized block ...
+ */
+ throw exAny;
+ }
+
+ // SAFE -> ------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ pInfo = &(m_lStorages[sCheckPath]);
+ pInfo->Storage = xChild;
+ pInfo->UseCount = 1;
+ aWriteLock.unlock();
+ // <- SAFE ------------------------------
+ }
+
+ xParent = xChild;
+ sRelPath += sChild;
+ sRelPath += PATH_SEPERATOR;
+ }
+
+ // TODO think about return last storage as working storage ... but dont caching it inside this holder!
+ // => otherwhise the same storage is may be commit more then once.
+
+ return xChild;
+}
+
+//-----------------------------------------------
+StorageHolder::TStorageList StorageHolder::getAllPathStorages(const ::rtl::OUString& sPath)
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
+ OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath);
+
+ StorageHolder::TStorageList lStoragesOfPath;
+ ::rtl::OUString sRelPath ;
+ OUStringList::const_iterator pIt ;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ for ( pIt = lFolders.begin();
+ pIt != lFolders.end() ;
+ ++pIt )
+ {
+ const ::rtl::OUString& sChild = *pIt;
+ ::rtl::OUString sCheckPath (sRelPath);
+ sCheckPath += sChild;
+ sCheckPath += PATH_SEPERATOR;
+
+ TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath);
+ if (pCheck == m_lStorages.end())
+ {
+ // at least one path element was not found
+ // Seems that this path isnt open ...
+ lStoragesOfPath.clear();
+ return lStoragesOfPath;
+ }
+
+ TStorageInfo& rInfo = pCheck->second;
+ lStoragesOfPath.push_back(rInfo.Storage);
+
+ sRelPath += sChild;
+ sRelPath += PATH_SEPERATOR;
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return lStoragesOfPath;
+}
+
+//-----------------------------------------------
+void StorageHolder::commitPath(const ::rtl::OUString& sPath)
+{
+ StorageHolder::TStorageList lStorages = getAllPathStorages(sPath);
+
+ css::uno::Reference< css::embed::XTransactedObject > xCommit;
+ StorageHolder::TStorageList::reverse_iterator pIt;
+ for ( pIt = lStorages.rbegin(); // order of commit is important ... otherwhise changes are not recognized!
+ pIt != lStorages.rend() ;
+ ++pIt )
+ {
+ xCommit = css::uno::Reference< css::embed::XTransactedObject >(*pIt, css::uno::UNO_QUERY);
+ if (!xCommit.is())
+ continue;
+ xCommit->commit();
+ }
+
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+ xCommit = css::uno::Reference< css::embed::XTransactedObject >(m_xRoot, css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+
+ if (xCommit.is())
+ xCommit->commit();
+}
+
+//-----------------------------------------------
+void StorageHolder::closePath(const ::rtl::OUString& rPath)
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(rPath);
+ OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath);
+
+ /* convert list of pathes in the following way:
+ [0] = "path_1" => "path_1
+ [1] = "path_2" => "path_1/path_2"
+ [2] = "path_3" => "path_1/path_2/path_3"
+ */
+ OUStringList::iterator pIt1 ;
+ ::rtl::OUString sParentPath;
+ for ( pIt1 = lFolders.begin();
+ pIt1 != lFolders.end() ;
+ ++pIt1 )
+ {
+ ::rtl::OUString sCurrentRelPath = sParentPath;
+ sCurrentRelPath += *pIt1;
+ sCurrentRelPath += PATH_SEPERATOR;
+ *pIt1 = sCurrentRelPath;
+ sParentPath = sCurrentRelPath;
+ }
+
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ OUStringList::reverse_iterator pIt2;
+ for ( pIt2 = lFolders.rbegin();
+ pIt2 != lFolders.rend() ;
+ ++pIt2 )
+ {
+ ::rtl::OUString sPath = *pIt2;
+ TPath2StorageInfo::iterator pPath = m_lStorages.find(sPath);
+ if (pPath == m_lStorages.end())
+ continue; // ???
+
+ TStorageInfo& rInfo = pPath->second;
+ --rInfo.UseCount;
+ if (rInfo.UseCount < 1)
+ {
+ rInfo.Storage.clear();
+ m_lStorages.erase(pPath);
+ }
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+}
+
+//-----------------------------------------------
+void StorageHolder::notifyPath(const ::rtl::OUString& sPath)
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
+
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
+ if (pIt1 == m_lStorages.end())
+ return;
+
+ TStorageInfo& rInfo = pIt1->second;
+ TStorageListenerList::iterator pIt2;
+ for ( pIt2 = rInfo.Listener.begin();
+ pIt2 != rInfo.Listener.end() ;
+ ++pIt2 )
+ {
+ IStorageListener* pListener = *pIt2;
+ if (pListener)
+ pListener->changesOccured(sNormedPath);
+ }
+
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+}
+
+//-----------------------------------------------
+void StorageHolder::addStorageListener( IStorageListener* pListener,
+ const ::rtl::OUString& sPath )
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
+
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
+ if (pIt1 == m_lStorages.end())
+ return;
+
+ TStorageInfo& rInfo = pIt1->second;
+ TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener);
+ if (pIt2 == rInfo.Listener.end())
+ rInfo.Listener.push_back(pListener);
+
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+}
+
+//-----------------------------------------------
+void StorageHolder::removeStorageListener( IStorageListener* pListener,
+ const ::rtl::OUString& sPath )
+{
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
+
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
+ if (pIt1 == m_lStorages.end())
+ return;
+
+ TStorageInfo& rInfo = pIt1->second;
+ TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener);
+ if (pIt2 != rInfo.Listener.end())
+ rInfo.Listener.erase(pIt2);
+
+ aReadLock.unlock();
+ // <- SAFE ------------------------------
+}
+
+//-----------------------------------------------
+::rtl::OUString StorageHolder::getPathOfStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
+{
+ // SAFE -> ------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ TPath2StorageInfo::const_iterator pIt;
+ for ( pIt = m_lStorages.begin();
+ pIt != m_lStorages.end() ;
+ ++pIt )
+ {
+ const TStorageInfo& rInfo = pIt->second;
+ if (rInfo.Storage == xStorage)
+ break;
+ }
+
+ if (pIt == m_lStorages.end())
+ return ::rtl::OUString();
+
+ return pIt->first;
+
+ // <- SAFE ------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const css::uno::Reference< css::embed::XStorage >& xChild)
+{
+ ::rtl::OUString sChildPath = getPathOfStorage(xChild);
+ return getParentStorage(sChildPath);
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const ::rtl::OUString& sChildPath)
+{
+ // normed path = "a/b/c/" ... we search for "a/b/"
+ ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sChildPath);
+ OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath);
+ sal_Int32 c = lFolders.size();
+
+ // a) "" => - => no parent
+ // b) "a/b/c/" => "a/b/" => return storage "a/b/"
+ // c) "a/" => "" => return root !
+
+ // a)
+ if (c < 1)
+ return css::uno::Reference< css::embed::XStorage >();
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ // b)
+ if (c < 2)
+ return m_xRoot;
+
+ // c)
+ ::rtl::OUString sParentPath;
+ sal_Int32 i = 0;
+ for (i=0; i<c-1; ++i)
+ {
+ sParentPath += lFolders[i];
+ sParentPath += PATH_SEPERATOR;
+ }
+
+ TPath2StorageInfo::const_iterator pParent = m_lStorages.find(sParentPath);
+ if (pParent != m_lStorages.end())
+ return pParent->second.Storage;
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // ?
+ LOG_WARNING("StorageHolder::getParentStorage()", "Unexpected situation. Cached storage item seems to be wrong.")
+ return css::uno::Reference< css::embed::XStorage >();
+}
+
+//-----------------------------------------------
+void StorageHolder::operator=(const StorageHolder& rCopy)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ m_xSMGR = rCopy.m_xSMGR; // ???
+ m_xRoot = rCopy.m_xRoot;
+ m_lStorages = rCopy.m_lStorages;
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::embed::XStorage > StorageHolder::openSubStorageWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage ,
+ const ::rtl::OUString& sSubStorage ,
+ sal_Int32 eOpenMode ,
+ sal_Bool bAllowFallback)
+{
+ // a) try it first with user specified open mode
+ // ignore errors ... but save it for later use!
+ css::uno::Exception exResult;
+ try
+ {
+ css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eOpenMode);
+ if (xSubStorage.is())
+ return xSubStorage;
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception& ex)
+ { exResult = ex; }
+
+ // b) readonly already tried? => forward last error!
+ if (
+ (!bAllowFallback ) || // fallback allowed ?
+ ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE) // fallback possible ?
+ )
+ throw exResult;
+
+ // c) try it readonly
+ // dont catch exception here! Outside code whish to know, if operation failed or not.
+ // Otherwhise they work on NULL references ...
+ sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE);
+ css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eNewMode);
+ if (xSubStorage.is())
+ return xSubStorage;
+
+ // d) no chance!
+ LOG_WARNING("openSubStorageWithFallback()", "Unexpected situation! Got no exception for missing storage ...")
+ return css::uno::Reference< css::embed::XStorage >();
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::io::XStream > StorageHolder::openSubStreamWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage ,
+ const ::rtl::OUString& sSubStream ,
+ sal_Int32 eOpenMode ,
+ sal_Bool bAllowFallback)
+{
+ // a) try it first with user specified open mode
+ // ignore errors ... but save it for later use!
+ css::uno::Exception exResult;
+ try
+ {
+ css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eOpenMode);
+ if (xSubStream.is())
+ return xSubStream;
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception& ex)
+ { exResult = ex; }
+
+ // b) readonly already tried? => forward last error!
+ if (
+ (!bAllowFallback ) || // fallback allowed ?
+ ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE) // fallback possible ?
+ )
+ throw exResult;
+
+ // c) try it readonly
+ // dont catch exception here! Outside code whish to know, if operation failed or not.
+ // Otherwhise they work on NULL references ...
+ sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE);
+ css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eNewMode);
+ if (xSubStream.is())
+ return xSubStream;
+
+ // d) no chance!
+ LOG_WARNING("openSubStreamWithFallbacks()", "Unexpected situation! Got no exception for missing stream ...")
+ return css::uno::Reference< css::io::XStream >();
+}
+
+//-----------------------------------------------
+::rtl::OUString StorageHolder::impl_st_normPath(const ::rtl::OUString& sPath)
+{
+ // path must start without "/" but end with "/"!
+
+ ::rtl::OUString sNormedPath = sPath;
+
+ // "/bla" => "bla" && "/" => "" (!)
+ if (sNormedPath.indexOf(PATH_SEPERATOR) == 0)
+ sNormedPath += sNormedPath.copy(1);
+
+ // "/" => "" || "" => "" ?
+ if (sNormedPath.getLength() < 1)
+ return ::rtl::OUString();
+
+ // "bla" => "bla/"
+ if (sNormedPath.lastIndexOf(PATH_SEPERATOR) != (sNormedPath.getLength()-1))
+ sNormedPath += PATH_SEPERATOR;
+
+ return sNormedPath;
+}
+
+//-----------------------------------------------
+OUStringList StorageHolder::impl_st_parsePath(const ::rtl::OUString& sPath)
+{
+ OUStringList lToken;
+ sal_Int32 i = 0;
+ while (sal_True)
+ {
+ ::rtl::OUString sToken = sPath.getToken(0, PATH_SEPERATOR_UNICODE, i);
+ if (i < 0)
+ break;
+ lToken.push_back(sToken);
+ }
+ return lToken;
+}
+
+//===============================================
+} // namespace framework