1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include <accelerators/acceleratorconfiguration.hxx>
31 
32 //_______________________________________________
33 // own includes
34 #include <pattern/configuration.hxx>
35 #include <accelerators/presethandler.hxx>
36 
37 #include <xml/saxnamespacefilter.hxx>
38 #include <xml/acceleratorconfigurationreader.hxx>
39 #include <xml/acceleratorconfigurationwriter.hxx>
40 
41 #include <threadhelp/readguard.hxx>
42 #include <threadhelp/writeguard.hxx>
43 
44 #include <acceleratorconst.h>
45 #include <services.h>
46 
47 //_______________________________________________
48 // interface includes
49 #include <com/sun/star/xml/sax/XParser.hpp>
50 #include <com/sun/star/xml/sax/InputSource.hpp>
51 #include <com/sun/star/io/XActiveDataSource.hpp>
52 #include <com/sun/star/embed/ElementModes.hpp>
53 #include <com/sun/star/io/XSeekable.hpp>
54 #include <com/sun/star/io/XTruncate.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 
57 //_______________________________________________
58 // other includes
59 #include <vcl/svapp.hxx>
60 
61 #ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
62 #include <com/sun/star/container/XNamed.hpp>
63 #endif
64 
65 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
66 #include <com/sun/star/container/XNameContainer.hpp>
67 #endif
68 
69 #ifndef __COM_SUN_STAR_AWT_KEYEVENT_HPP_
70 #include <com/sun/star/awt/KeyEvent.hpp>
71 #endif
72 
73 #ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
74 #include <com/sun/star/awt/KeyModifier.hpp>
75 #endif
76 
77 #ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
78 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
79 #endif
80 
81 #ifndef _COM_SUN_STAR_UTIL_XCHANGESNOTIFIER_HPP_
82 #include <com/sun/star/util/XChangesNotifier.hpp>
83 #endif
84 
85 #ifndef _COMPHELPER_CONFIGURATIONHELPER_HXX_
86 #include <comphelper/configurationhelper.hxx>
87 #endif
88 
89 #ifndef UNOTOOLS_CONFIGPATHES_HXX_INCLUDED
90 #include <unotools/configpathes.hxx>
91 #endif
92 
93 #ifndef _RTL_LOGFILE_HXX_
94 #include <rtl/logfile.hxx>
95 #endif
96 
97 #include <svtools/acceleratorexecute.hxx>
98 
99 #include <stdio.h>
100 
101 //_______________________________________________
102 // const
103 
104 namespace framework
105 {
106 
107 #ifdef fpc
108     #error "Who exports this define? I use it as namespace alias ..."
109 #else
110     namespace fpc = ::framework::pattern::configuration;
111 #endif
112 
113     ::rtl::OUString lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping>& _rKeyMapping, const css::awt::KeyEvent& aKeyEvent)
114     {
115 	    const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
116 	    ::rtl::OUStringBuffer sKeyBuffer((_rKeyMapping->mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
117 
118 	    if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
119 		    sKeyBuffer.appendAscii("_SHIFT");
120 	    if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1  )
121 		    sKeyBuffer.appendAscii("_MOD1");
122 	    if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2  )
123 		    sKeyBuffer.appendAscii("_MOD2");
124         if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3  )
125             sKeyBuffer.appendAscii("_MOD3");
126 
127         return sKeyBuffer.makeStringAndClear();
128     }
129 
130 //-----------------------------------------------
131 //	XInterface, XTypeProvider
132 DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration                       ,
133                     OWeakObject                                            ,
134                     DIRECT_INTERFACE(css::lang::XTypeProvider             ),
135                     DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration  ),
136                     DIRECT_INTERFACE(css::form::XReset                    ),
137                     DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
138                     DIRECT_INTERFACE(css::ui::XUIConfigurationStorage    ),
139                     DIRECT_INTERFACE(css::ui::XUIConfiguration           ))
140 
141 DEFINE_XTYPEPROVIDER_6(XMLBasedAcceleratorConfiguration     ,
142                        css::lang::XTypeProvider             ,
143                        css::ui::XAcceleratorConfiguration  ,
144                        css::form::XReset                    ,
145                        css::ui::XUIConfigurationPersistence,
146                        css::ui::XUIConfigurationStorage    ,
147                        css::ui::XUIConfiguration           )
148 
149 //-----------------------------------------------
150 XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
151     : ThreadHelpBase  (&Application::GetSolarMutex())
152     , m_xSMGR         (xSMGR                        )
153     , m_aPresetHandler(xSMGR                        )
154     , m_pWriteCache   (0                            )
155 {
156 }
157 
158 //-----------------------------------------------
159 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
160 {
161     LOG_ASSERT(!m_pWriteCache, "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()\nChanges not flushed. Ignore it ...")
162 }
163 
164 //-----------------------------------------------
165 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
166     throw(css::uno::RuntimeException)
167 {
168     // SAFE -> ----------------------------------
169     ReadGuard aReadLock(m_aLock);
170 
171     AcceleratorCache&          rCache = impl_getCFG();
172     AcceleratorCache::TKeyList lKeys  = rCache.getAllKeys();
173     return lKeys.getAsConstList();
174 
175     // <- SAFE ----------------------------------
176 }
177 
178 //-----------------------------------------------
179 ::rtl::OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
180     throw(css::container::NoSuchElementException,
181           css::uno::RuntimeException            )
182 {
183     // SAFE -> ----------------------------------
184     ReadGuard aReadLock(m_aLock);
185 
186     AcceleratorCache& rCache = impl_getCFG();
187     if (!rCache.hasKey(aKeyEvent))
188         throw css::container::NoSuchElementException(
189                 ::rtl::OUString(),
190                 static_cast< ::cppu::OWeakObject* >(this));
191     return rCache.getCommandByKey(aKeyEvent);
192 
193     // <- SAFE ----------------------------------
194 }
195 
196 //-----------------------------------------------
197 void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
198 													const ::rtl::OUString&    sCommand )
199 													throw(css::lang::IllegalArgumentException,
200 													css::uno::RuntimeException         )
201 {
202 	if (
203 		(aKeyEvent.KeyCode   == 0) &&
204 		(aKeyEvent.KeyChar   == 0) &&
205 		(aKeyEvent.KeyFunc   == 0) &&
206 		(aKeyEvent.Modifiers == 0)
207 		)
208 		throw css::lang::IllegalArgumentException(
209 		::rtl::OUString::createFromAscii("Such key event seams not to be supported by any operating system."),
210 		static_cast< ::cppu::OWeakObject* >(this),
211 		0);
212 
213 	if (!sCommand.getLength())
214 		throw css::lang::IllegalArgumentException(
215 		::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
216 		static_cast< ::cppu::OWeakObject* >(this),
217 		1);
218 
219 	// SAFE -> ----------------------------------
220 	WriteGuard aWriteLock(m_aLock);
221 
222 	AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
223 	rCache.setKeyCommandPair(aKeyEvent, sCommand);
224 
225 	aWriteLock.unlock();
226 	// <- SAFE ----------------------------------
227 }
228 
229 //-----------------------------------------------
230 void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
231 throw(css::container::NoSuchElementException,
232 	  css::uno::RuntimeException            )
233 {
234 	// SAFE -> ----------------------------------
235 	WriteGuard aWriteLock(m_aLock);
236 
237 	AcceleratorCache& rCache = impl_getCFG(sal_True); // true => force using of a writeable cache
238 	if (!rCache.hasKey(aKeyEvent))
239 		throw css::container::NoSuchElementException(
240 		::rtl::OUString(),
241 		static_cast< ::cppu::OWeakObject* >(this));
242 	rCache.removeKey(aKeyEvent);
243 
244 	// <- SAFE ----------------------------------
245 }
246 
247 //-----------------------------------------------
248 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
249     throw(css::lang::IllegalArgumentException   ,
250           css::container::NoSuchElementException,
251           css::uno::RuntimeException            )
252 {
253     if (!sCommand.getLength())
254         throw css::lang::IllegalArgumentException(
255                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
256                 static_cast< ::cppu::OWeakObject* >(this),
257                 1);
258 
259     // SAFE -> ----------------------------------
260     ReadGuard aReadLock(m_aLock);
261 
262     AcceleratorCache& rCache = impl_getCFG();
263     if (!rCache.hasCommand(sCommand))
264         throw css::container::NoSuchElementException(
265                 ::rtl::OUString(),
266                 static_cast< ::cppu::OWeakObject* >(this));
267 
268     AcceleratorCache::TKeyList lKeys  = rCache.getKeysByCommand(sCommand);
269     return lKeys.getAsConstList();
270 
271     // <- SAFE ----------------------------------
272 }
273 
274 //-----------------------------------------------
275 css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
276     throw(css::lang::IllegalArgumentException   ,
277           css::uno::RuntimeException            )
278 {
279     // SAFE -> ----------------------------------
280     ReadGuard aReadLock(m_aLock);
281 
282     sal_Int32                           i              = 0;
283     sal_Int32                           c              = lCommandList.getLength();
284     css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
285     AcceleratorCache&                   rCache         = impl_getCFG();
286 
287     for (i=0; i<c; ++i)
288     {
289         const ::rtl::OUString& rCommand = lCommandList[i];
290         if (!rCommand.getLength())
291             throw css::lang::IllegalArgumentException(
292                     ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
293                     static_cast< ::cppu::OWeakObject* >(this),
294                     (sal_Int16)i);
295 
296         if (!rCache.hasCommand(rCommand))
297             continue;
298 
299         AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
300         if ( lKeys.empty() )
301             continue;
302 
303         css::uno::Any& rAny = lPreferredOnes[i];
304         rAny <<= *(lKeys.begin());
305     }
306 
307     aReadLock.unlock();
308     // <- SAFE ----------------------------------
309 
310     return lPreferredOnes;
311 }
312 
313 //-----------------------------------------------
314 void SAL_CALL XMLBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
315     throw(css::lang::IllegalArgumentException   ,
316           css::container::NoSuchElementException,
317           css::uno::RuntimeException            )
318 {
319     if (!sCommand.getLength())
320         throw css::lang::IllegalArgumentException(
321                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
322                 static_cast< ::cppu::OWeakObject* >(this),
323                 0);
324 
325     // SAFE -> ----------------------------------
326     WriteGuard aWriteLock(m_aLock);
327 
328     AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
329     if (!rCache.hasCommand(sCommand))
330         throw css::container::NoSuchElementException(
331                 ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
332                 static_cast< ::cppu::OWeakObject* >(this));
333     rCache.removeCommand(sCommand);
334 
335     aWriteLock.unlock();
336     // <- SAFE ----------------------------------
337 }
338 
339 //-----------------------------------------------
340 void SAL_CALL XMLBasedAcceleratorConfiguration::reload()
341 	throw(css::uno::Exception       ,
342 		css::uno::RuntimeException)
343 {
344 	css::uno::Reference< css::io::XStream > xStreamNoLang;
345 
346 	// SAFE -> ----------------------------------
347 	ReadGuard aReadLock(m_aLock);
348 	css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
349 	try
350 	{
351 		xStreamNoLang = m_aPresetHandler.openPreset(PresetHandler::PRESET_DEFAULT(), sal_True);
352 	}
353 	catch(const css::io::IOException&) {} // does not have to exist
354 	aReadLock.unlock();
355 	// <- SAFE ----------------------------------
356 
357 	css::uno::Reference< css::io::XInputStream > xIn;
358 	if (xStream.is())
359 		xIn = xStream->getInputStream();
360 	if (!xIn.is())
361 		throw css::io::IOException(
362 		::rtl::OUString::createFromAscii("Could not open accelerator configuration for reading."),
363 		static_cast< ::cppu::OWeakObject* >(this));
364 
365 	// impl_ts_load() does not clear the cache
366 	// SAFE -> ----------------------------------
367 	WriteGuard aWriteLock(m_aLock);
368 	m_aReadCache = AcceleratorCache();
369 	aWriteLock.unlock();
370 	// <- SAFE ----------------------------------
371 
372 	impl_ts_load(xIn);
373 
374 	// Load also the general language independent default accelerators
375 	// (ignoring the already defined accelerators)
376 	if (xStreamNoLang.is())
377 	{
378 		xIn = xStreamNoLang->getInputStream();
379 		if (xIn.is())
380 			impl_ts_load(xIn);
381 	}
382 }
383 
384 //-----------------------------------------------
385 void SAL_CALL XMLBasedAcceleratorConfiguration::store()
386 	throw(css::uno::Exception       ,
387 		css::uno::RuntimeException)
388 {
389 	// SAFE -> ----------------------------------
390 	ReadGuard aReadLock(m_aLock);
391 	css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
392 	aReadLock.unlock();
393 	// <- SAFE ----------------------------------
394 
395 	css::uno::Reference< css::io::XOutputStream > xOut;
396 	if (xStream.is())
397 		xOut = xStream->getOutputStream();
398 
399 	if (!xOut.is())
400 		throw css::io::IOException(
401 		::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
402 		static_cast< ::cppu::OWeakObject* >(this));
403 
404 	impl_ts_save(xOut);
405 
406 	xOut.clear();
407 	xStream.clear();
408 
409 	m_aPresetHandler.commitUserChanges();
410 }
411 
412 //-----------------------------------------------
413 void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
414     throw(css::uno::Exception       ,
415           css::uno::RuntimeException)
416 {
417     css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
418                                                             xStorage,
419                                                             PresetHandler::TARGET_CURRENT(),
420                                                             css::embed::ElementModes::READWRITE,
421                                                             sal_False); // False => no fallback from read/write to readonly!
422     css::uno::Reference< css::io::XOutputStream > xOut;
423     if (xStream.is())
424         xOut = xStream->getOutputStream();
425 
426     if (!xOut.is())
427         throw css::io::IOException(
428                 ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
429                 static_cast< ::cppu::OWeakObject* >(this));
430 
431     impl_ts_save(xOut);
432 
433     // TODO inform listener about success, so it can flush the root and sub storage of this stream!
434 }
435 
436 //-----------------------------------------------
437 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
438     throw(css::uno::RuntimeException)
439 {
440     // SAFE -> ----------------------------------
441     ReadGuard aReadLock(m_aLock);
442     return (m_pWriteCache != 0);
443     // <- SAFE ----------------------------------
444 }
445 
446 //-----------------------------------------------
447 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
448     throw(css::uno::RuntimeException)
449 {
450 	// SAFE -> ----------------------------------
451 	ReadGuard aReadLock(m_aLock);
452 	css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
453 	aReadLock.unlock();
454 	// <- SAFE ----------------------------------
455 
456 	css::uno::Reference< css::io::XOutputStream > xOut;
457 	if (xStream.is())
458 		xOut = xStream->getOutputStream();
459 	return !(xOut.is());
460 }
461 
462 //-----------------------------------------------
463 void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
464     throw(css::uno::RuntimeException)
465 {
466     LOG_WARNING("XMLBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
467 }
468 
469 //-----------------------------------------------
470 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
471     throw(css::uno::RuntimeException)
472 {
473     LOG_WARNING("XMLBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
474     return sal_False;
475 }
476 
477 //-----------------------------------------------
478 void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
479     throw(css::uno::RuntimeException)
480 {
481     LOG_WARNING("XMLBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
482 }
483 
484 //-----------------------------------------------
485 void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
486     throw(css::uno::RuntimeException)
487 {
488     LOG_WARNING("XMLBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
489 }
490 
491 //-----------------------------------------------
492 void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
493 throw(css::uno::RuntimeException)
494 {
495 	// SAFE -> ----------------------------------
496 	WriteGuard aWriteLock(m_aLock);
497 	m_aPresetHandler.copyPresetToTarget(PresetHandler::PRESET_DEFAULT(), PresetHandler::TARGET_CURRENT());
498 	aWriteLock.unlock();
499 	// <- SAFE ----------------------------------
500 
501 	reload();
502 }
503 
504 //-----------------------------------------------
505 void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
506     throw(css::uno::RuntimeException)
507 {
508     LOG_WARNING("XMLBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
509 }
510 
511 //-----------------------------------------------
512 void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
513     throw(css::uno::RuntimeException)
514 {
515     LOG_WARNING("XMLBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
516 }
517 
518 //-----------------------------------------------
519 // IStorageListener
520 void XMLBasedAcceleratorConfiguration::changesOccured(const ::rtl::OUString& /*sPath*/)
521 {
522     reload();
523 }
524 
525 //-----------------------------------------------
526 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
527 {
528     // SAFE -> ----------------------------------
529     WriteGuard aWriteLock(m_aLock);
530 
531     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
532     if (m_pWriteCache)
533     {
534         // be aware of reentrance problems - use temp variable for calling delete ... :-)
535         AcceleratorCache* pTemp = m_pWriteCache;
536         m_pWriteCache = 0;
537         delete pTemp;
538     }
539 
540     aWriteLock.unlock();
541     // <- SAFE ----------------------------------
542 
543     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
544     if (xSeek.is())
545         xSeek->seek(0);
546 
547     // add accelerators to the cache (the cache is not cleared)
548     // SAFE -> ----------------------------------
549     aWriteLock.lock();
550 
551     // create the parser queue
552     // Note: Use special filter object between parser and reader
553     // to get filtered xml with right namespaces ...
554     // Use further a temp cache for reading!
555     AcceleratorConfigurationReader*                        pReader = new AcceleratorConfigurationReader(m_aReadCache);
556     css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
557     SaxNamespaceFilter*                                    pFilter = new SaxNamespaceFilter(xReader);
558     css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
559 
560 	// connect parser, filter and stream
561 	css::uno::Reference< css::xml::sax::XParser > xParser(xSMGR->createInstance(SERVICENAME_SAXPARSER), css::uno::UNO_QUERY_THROW);
562 	xParser->setDocumentHandler(xFilter);
563 
564     css::xml::sax::InputSource aSource;
565     aSource.aInputStream = xStream;
566 
567     // TODO think about error handling
568     xParser->parseStream(aSource);
569 
570     aWriteLock.unlock();
571     // <- SAFE ----------------------------------
572 }
573 
574 //-----------------------------------------------
575 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
576 {
577     // SAFE -> ----------------------------------
578     ReadGuard aReadLock(m_aLock);
579 
580     AcceleratorCache aCache;
581     sal_Bool bChanged = (m_pWriteCache != 0);
582     if (bChanged)
583         aCache.takeOver(*m_pWriteCache);
584     else
585         aCache.takeOver(m_aReadCache);
586     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
587 
588     aReadLock.unlock();
589     // <- SAFE ----------------------------------
590 
591     css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
592     xClearable->truncate();
593 
594     // TODO can be removed if seek(0) is done by truncate() automaticly!
595     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
596     if (xSeek.is())
597         xSeek->seek(0);
598 
599     // combine writer/cache/stream etcpp.
600     css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter    (xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
601 	css::uno::Reference< css::io::XActiveDataSource>       xDataSource(xWriter                                     , css::uno::UNO_QUERY_THROW);
602     xDataSource->setOutputStream(xStream);
603 
604     // write into the stream
605     AcceleratorConfigurationWriter aWriter(aCache, xWriter);
606     aWriter.flush();
607 
608     // take over all changes into the original container
609     // SAFE -> ----------------------------------
610     WriteGuard aWriteLock(m_aLock);
611 
612     // take over all changes into the readonly cache ...
613     // and forget the copy-on-write copied cache
614     if (bChanged)
615     {
616         m_aReadCache.takeOver(*m_pWriteCache);
617         // live with reentrance .-)
618         AcceleratorCache* pTemp = m_pWriteCache;
619         m_pWriteCache = 0;
620         delete pTemp;
621     }
622 
623     aWriteLock.unlock();
624     // <- SAFE ----------------------------------
625 }
626 
627 //-----------------------------------------------
628 AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bWriteAccessRequested)
629 {
630     // SAFE -> ----------------------------------
631     WriteGuard aWriteLock(m_aLock);
632 
633     //create copy of our readonly-cache, if write access is forced ... but
634     //not still possible!
635     if (
636         (bWriteAccessRequested) &&
637         (!m_pWriteCache       )
638        )
639     {
640         m_pWriteCache = new AcceleratorCache(m_aReadCache);
641     }
642 
643     // in case, we have a writeable cache, we use it for reading too!
644     // Otherwhise the API user cant find its own changes ...
645     if (m_pWriteCache)
646         return *m_pWriteCache;
647     else
648         return m_aReadCache;
649     // <- SAFE ----------------------------------
650 }
651 
652 //-----------------------------------------------
653 ::comphelper::Locale XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
654 {
655     static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
656     static ::rtl::OUString LOCALE_PATH    = ::rtl::OUString::createFromAscii("L10N"                 );
657     static ::rtl::OUString LOCALE_KEY     = ::rtl::OUString::createFromAscii("ooLocale"             );
658 
659     // SAFE -> ----------------------------------
660     ReadGuard aReadLock(m_aLock);
661     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
662     aReadLock.unlock();
663     // <- SAFE ----------------------------------
664 
665     css::uno::Reference< css::uno::XInterface >     xCFG      = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
666     css::uno::Reference< css::beans::XPropertySet > xProp     (xCFG, css::uno::UNO_QUERY_THROW);
667     ::rtl::OUString                                 sISOLocale;
668     xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
669 
670     if (!sISOLocale.getLength())
671         return ::comphelper::Locale::EN_US();
672     return ::comphelper::Locale(sISOLocale);
673 }
674 
675 /*******************************************************************************
676 *
677 * XCU based accelerator configuration
678 *
679 *******************************************************************************/
680 
681 //-----------------------------------------------
682 //	XInterface, XTypeProvider
683 DEFINE_XINTERFACE_7(XCUBasedAcceleratorConfiguration                       ,
684 					OWeakObject                                            ,
685 					DIRECT_INTERFACE(css::lang::XTypeProvider             ),
686 					DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration  ),
687 					DIRECT_INTERFACE(css::util::XChangesListener          ),
688 					DIRECT_INTERFACE(css::form::XReset                    ),
689 					DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
690 					DIRECT_INTERFACE(css::ui::XUIConfigurationStorage    ),
691 					DIRECT_INTERFACE(css::ui::XUIConfiguration           ))
692 
693 					DEFINE_XTYPEPROVIDER_7(XCUBasedAcceleratorConfiguration ,
694 					css::lang::XTypeProvider             ,
695 					css::ui::XAcceleratorConfiguration  ,
696 					css::util::XChangesListener          ,
697 					css::form::XReset                    ,
698 					css::ui::XUIConfigurationPersistence,
699 					css::ui::XUIConfigurationStorage    ,
700 					css::ui::XUIConfiguration           )
701 
702 //-----------------------------------------------
703 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
704 								: ThreadHelpBase  (&Application::GetSolarMutex())
705 								, m_xSMGR         (xSMGR                        )
706                                 , m_pPrimaryWriteCache(0                        )
707                                 , m_pSecondaryWriteCache(0                      )
708 {
709     static const ::rtl::OUString CFG_ENTRY_ACCELERATORS(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Accelerators"));
710     m_xCfg = css::uno::Reference< css::container::XNameAccess > (
711 			 ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
712 			 css::uno::UNO_QUERY );
713 }
714 
715 //-----------------------------------------------
716 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
717 {
718 }
719 
720 //-----------------------------------------------
721 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
722 	throw(css::uno::RuntimeException)
723 {
724 	// SAFE -> ----------------------------------
725 	ReadGuard aReadLock(m_aLock);
726 
727 	AcceleratorCache::TKeyList lKeys  = impl_getCFG(sal_True).getAllKeys(); //get keys from PrimaryKeys set
728 
729     AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(sal_False).getAllKeys(); //get keys from SecondaryKeys set
730     lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
731     AcceleratorCache::TKeyList::const_iterator pIt;
732     AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
733     for ( pIt  = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
734         lKeys.push_back(*pIt);
735 
736     return lKeys.getAsConstList();
737 
738 	// <- SAFE ----------------------------------
739 }
740 
741 //-----------------------------------------------
742 ::rtl::OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
743 	throw(css::container::NoSuchElementException,
744 		  css::uno::RuntimeException            )
745 {
746 	// SAFE -> ----------------------------------
747 	ReadGuard aReadLock(m_aLock);
748 
749     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
750     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
751 
752 	if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
753 		throw css::container::NoSuchElementException(
754 		::rtl::OUString(),
755 		static_cast< ::cppu::OWeakObject* >(this));
756 
757     if (rPrimaryCache.hasKey(aKeyEvent))
758 	    return rPrimaryCache.getCommandByKey(aKeyEvent);
759     else
760         return rSecondaryCache.getCommandByKey(aKeyEvent);
761 
762 	// <- SAFE ----------------------------------
763 }
764 
765 //-----------------------------------------------
766 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
767 													const ::rtl::OUString&    sCommand )
768 													throw(css::lang::IllegalArgumentException,
769 													css::uno::RuntimeException         )
770 {
771 	RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::setKeyEvent" );
772 
773 	if (
774 		(aKeyEvent.KeyCode   == 0) &&
775 		(aKeyEvent.KeyChar   == 0) &&
776 		(aKeyEvent.KeyFunc   == 0) &&
777 		(aKeyEvent.Modifiers == 0)
778 		)
779 		throw css::lang::IllegalArgumentException(
780 				::rtl::OUString::createFromAscii("Such key event seams not to be supported by any operating system."),
781 				static_cast< ::cppu::OWeakObject* >(this),
782 				0);
783 
784 	if (!sCommand.getLength())
785 				throw css::lang::IllegalArgumentException(
786 				::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
787 				static_cast< ::cppu::OWeakObject* >(this),
788 				1);
789 
790 	// SAFE -> ----------------------------------
791 	WriteGuard aWriteLock(m_aLock);
792 
793     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True ); // sal_True => force getting of a writeable cache!
794     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True); // sal_True => force getting of a writeable cache!
795 
796     if ( rPrimaryCache.hasKey(aKeyEvent) )
797     {
798         ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
799         if ( sCommand != sOriginalCommand )
800         {
801             if (rSecondaryCache.hasCommand(sOriginalCommand))
802             {
803                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
804                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
805                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
806             }
807 
808             if (rPrimaryCache.hasCommand(sCommand))
809             {
810                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
811                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
812                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
813             }
814 
815             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
816         }
817     }
818 
819     else if ( rSecondaryCache.hasKey(aKeyEvent) )
820     {
821         ::rtl::OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
822         if (sCommand != sOriginalCommand)
823         {
824             if (rPrimaryCache.hasCommand(sCommand))
825             {
826                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
827                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
828                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
829             }
830 
831             rSecondaryCache.removeKey(aKeyEvent);
832             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
833         }
834     }
835 
836     else
837     {
838         if (rPrimaryCache.hasCommand(sCommand))
839         {
840             AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
841             rPrimaryCache.removeKey(lPrimaryKeys[0]);
842             rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
843         }
844 
845         rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
846     }
847 
848 	aWriteLock.unlock();
849 	// <- SAFE ----------------------------------
850 }
851 
852 //-----------------------------------------------
853 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
854 	throw(css::container::NoSuchElementException,
855 		  css::uno::RuntimeException            )
856 {
857 	// SAFE -> ----------------------------------
858 	WriteGuard aWriteLock(m_aLock);
859 
860     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
861     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
862 
863 	if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
864 		throw css::container::NoSuchElementException(
865 		::rtl::OUString(),
866 		static_cast< ::cppu::OWeakObject* >(this));
867 
868     if (rPrimaryCache.hasKey(aKeyEvent))
869     {
870         ::rtl::OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
871         if (sDelCommand.getLength() > 0)
872         {
873             ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
874             if (rSecondaryCache.hasCommand(sOriginalCommand))
875             {
876                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
877                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
878                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
879             }
880 
881             rPrimaryCache.removeKey(aKeyEvent);
882         }
883 
884     }
885     else
886     {
887         ::rtl::OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
888         if (sDelCommand.getLength() > 0)
889             rSecondaryCache.removeKey(aKeyEvent);
890     }
891 
892 	// <- SAFE ----------------------------------
893 }
894 
895 //-----------------------------------------------
896 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
897 	throw(css::lang::IllegalArgumentException   ,
898 		css::container::NoSuchElementException,
899 		css::uno::RuntimeException            )
900 {
901 	if (!sCommand.getLength())
902 		throw css::lang::IllegalArgumentException(
903 				::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
904 				static_cast< ::cppu::OWeakObject* >(this),
905 				1);
906 
907 	// SAFE -> ----------------------------------
908 	ReadGuard aReadLock(m_aLock);
909 
910     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
911     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
912 
913 	if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
914 		throw css::container::NoSuchElementException(
915 				::rtl::OUString(),
916 				static_cast< ::cppu::OWeakObject* >(this));
917 
918 	AcceleratorCache::TKeyList lKeys  = rPrimaryCache.getKeysByCommand(sCommand);
919 
920     AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
921     AcceleratorCache::TKeyList::const_iterator pIt;
922     for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
923         lKeys.push_back(*pIt);
924 
925 	return lKeys.getAsConstList();
926 
927 	// <- SAFE ----------------------------------
928 }
929 
930 //-----------------------------------------------
931 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
932 {
933     AcceleratorCache::TKeyList::const_iterator pIt;
934     for (  pIt  = lKeys.begin ();
935            pIt != lKeys.end   ();
936          ++pIt                  )
937     {
938         const css::awt::KeyEvent& rAWTKey = *pIt;
939         const KeyCode             aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
940         const String              sName   = aVCLKey.GetName();
941 
942         if (sName.Len () > 0)
943             return pIt;
944     }
945 
946     return lKeys.end ();
947 }
948 
949 //-----------------------------------------------
950 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
951 	throw(css::lang::IllegalArgumentException   ,
952 		css::uno::RuntimeException            )
953 {
954     // SAFE -> ----------------------------------
955 	ReadGuard aReadLock(m_aLock);
956 
957 	sal_Int32                           i              = 0;
958 	sal_Int32                           c              = lCommandList.getLength();
959 	css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
960     AcceleratorCache&                   rCache         = impl_getCFG(sal_True);
961 
962 	for (i=0; i<c; ++i)
963 	{
964 		const ::rtl::OUString& rCommand = lCommandList[i];
965 		if (!rCommand.getLength())
966 			throw css::lang::IllegalArgumentException(
967 					::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
968 					static_cast< ::cppu::OWeakObject* >(this),
969 					(sal_Int16)i);
970 
971 		if (!rCache.hasCommand(rCommand))
972 			continue;
973 
974 		AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
975 		if ( lKeys.empty() )
976 			continue;
977 
978 		AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
979 		if (pPreferredKey != lKeys.end ())
980 		{
981 			css::uno::Any& rAny = lPreferredOnes[i];
982 			rAny <<= *(pPreferredKey);
983 		}
984 	}
985 
986 	aReadLock.unlock();
987 	// <- SAFE ----------------------------------
988 
989 	return lPreferredOnes;
990 }
991 
992 //-----------------------------------------------
993 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
994 	throw(css::lang::IllegalArgumentException   ,
995 		css::container::NoSuchElementException,
996 		css::uno::RuntimeException            )
997 {
998 	if (!sCommand.getLength())
999 		throw css::lang::IllegalArgumentException(
1000 				::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
1001 				static_cast< ::cppu::OWeakObject* >(this),
1002 				0);
1003 
1004 	// SAFE -> ----------------------------------
1005 	WriteGuard aWriteLock(m_aLock);
1006 
1007     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
1008     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
1009 
1010 	if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
1011 		throw css::container::NoSuchElementException(
1012 				::rtl::OUString::createFromAscii("Command does not exists inside this container."),
1013 				static_cast< ::cppu::OWeakObject* >(this));
1014 
1015     if (rPrimaryCache.hasCommand(sCommand))
1016 	    rPrimaryCache.removeCommand(sCommand);
1017     if (rSecondaryCache.hasCommand(sCommand))
1018         rSecondaryCache.removeCommand(sCommand);
1019 
1020 	aWriteLock.unlock();
1021 	// <- SAFE ----------------------------------
1022 }
1023 
1024 //-----------------------------------------------
1025 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
1026 	throw(css::uno::Exception       ,
1027 		css::uno::RuntimeException)
1028 {
1029     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::reload()" );
1030 
1031 	// SAFE -> ----------------------------------
1032 	WriteGuard aWriteLock(m_aLock);
1033 
1034     sal_Bool bPreferred;
1035     css::uno::Reference< css::container::XNameAccess > xAccess;
1036 
1037     bPreferred = sal_True;
1038 	m_aPrimaryReadCache = AcceleratorCache();
1039     if (m_pPrimaryWriteCache)
1040     {
1041         // be aware of reentrance problems - use temp variable for calling delete ... :-)
1042         AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1043         m_pPrimaryWriteCache = 0;
1044         delete pTemp;
1045     }
1046     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1047     impl_ts_load(bPreferred, xAccess); // load the preferred keys
1048 
1049     bPreferred = sal_False;
1050 	m_aSecondaryReadCache = AcceleratorCache();
1051     if (m_pSecondaryWriteCache)
1052     {
1053         // be aware of reentrance problems - use temp variable for calling delete ... :-)
1054         AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1055         m_pSecondaryWriteCache = 0;
1056         delete pTemp;
1057     }
1058     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1059     impl_ts_load(bPreferred, xAccess); // load the secondary keys
1060 
1061 	aWriteLock.unlock();
1062 	// <- SAFE ----------------------------------
1063 }
1064 
1065 //-----------------------------------------------
1066 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
1067 	throw(css::uno::Exception       ,
1068 		  css::uno::RuntimeException)
1069 {
1070     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::store()" );
1071 
1072     // SAFE -> ----------------------------------
1073     ReadGuard aReadLock(m_aLock);
1074 
1075     sal_Bool bPreferred;
1076     css::uno::Reference< css::container::XNameAccess > xAccess;
1077 
1078     bPreferred = sal_True;
1079     // on-demand creation of the primary write cache
1080     impl_getCFG(bPreferred, sal_True);
1081     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1082     impl_ts_save(bPreferred, xAccess);
1083 
1084     bPreferred = sal_False;
1085     // on-demand creation of the secondary write cache
1086     impl_getCFG(bPreferred, sal_True);
1087     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1088     impl_ts_save(bPreferred, xAccess);
1089 
1090     aReadLock.unlock();
1091     // <- SAFE ----------------------------------
1092 }
1093 
1094 //-----------------------------------------------
1095 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
1096 	throw(css::uno::Exception       ,
1097 	  css::uno::RuntimeException)
1098 {
1099     // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
1100     if (!xStorage.is())
1101         return;
1102 
1103     long nOpenModes = css::embed::ElementModes::READWRITE;
1104     css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(::rtl::OUString::createFromAscii("accelerator"), nOpenModes);
1105     if (!xAcceleratorTypeStorage.is())
1106         return;
1107 
1108     css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(::rtl::OUString::createFromAscii("current"), nOpenModes);
1109     css::uno::Reference< css::io::XOutputStream > xOut;
1110     if (xStream.is())
1111         xOut = xStream->getOutputStream();
1112     if (!xOut.is())
1113         throw css::io::IOException(
1114         ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
1115         static_cast< ::cppu::OWeakObject* >(this));
1116 
1117     // the original m_aCache has been split into primay cache and secondary cache...
1118     // we should merge them before storing to storage
1119     // SAFE -> ----------------------------------
1120     WriteGuard aWriteLock(m_aLock);
1121 
1122     AcceleratorCache aCache;
1123     if (m_pPrimaryWriteCache != 0)
1124         aCache.takeOver(*m_pPrimaryWriteCache);
1125     else
1126         aCache.takeOver(m_aPrimaryReadCache);
1127 
1128     AcceleratorCache::TKeyList lKeys;
1129     AcceleratorCache::TKeyList::const_iterator pIt;
1130     if (m_pSecondaryWriteCache!=0)
1131     {
1132         lKeys = m_pSecondaryWriteCache->getAllKeys();
1133         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1134             aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
1135     }
1136     else
1137     {
1138         lKeys = m_aSecondaryReadCache.getAllKeys();
1139         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1140             aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
1141     }
1142 
1143     aWriteLock.unlock();
1144     // <- SAFE ----------------------------------
1145 
1146     css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
1147     xClearable->truncate();
1148     css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
1149     if (xSeek.is())
1150         xSeek->seek(0);
1151 
1152     css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter    (m_xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
1153     css::uno::Reference< css::io::XActiveDataSource>       xDataSource(xWriter                                     , css::uno::UNO_QUERY_THROW);
1154     xDataSource->setOutputStream(xOut);
1155 
1156     // write into the stream
1157     AcceleratorConfigurationWriter aWriter(aCache, xWriter);
1158     aWriter.flush();
1159 }
1160 
1161 //-----------------------------------------------
1162 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
1163 	throw(css::uno::RuntimeException)
1164 {
1165 	return sal_False;
1166 }
1167 
1168 //-----------------------------------------------
1169 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
1170 	throw(css::uno::RuntimeException)
1171 {
1172 	return sal_False;
1173 }
1174 
1175 //-----------------------------------------------
1176 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
1177 	throw(css::uno::RuntimeException)
1178 {
1179 	LOG_WARNING("XCUBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
1180 }
1181 
1182 //-----------------------------------------------
1183 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
1184 	throw(css::uno::RuntimeException)
1185 {
1186 	LOG_WARNING("XCUBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
1187 		return sal_False;
1188 }
1189 
1190 //-----------------------------------------------
1191 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1192 	throw(css::uno::RuntimeException)
1193 {
1194 	LOG_WARNING("XCUBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
1195 }
1196 
1197 //-----------------------------------------------
1198 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1199 	throw(css::uno::RuntimeException)
1200 {
1201 	LOG_WARNING("XCUBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
1202 }
1203 
1204 //-----------------------------------------------
1205 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
1206 	throw(css::uno::RuntimeException)
1207 {
1208 	css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
1209 	::rtl::OUString sConfig = xNamed->getName();
1210 	if ( sConfig.equalsAscii("Global") )
1211 	{
1212 		m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1213 			::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1214 			css::uno::UNO_QUERY );
1215 		XCUBasedAcceleratorConfiguration::reload();
1216 	}
1217 	else if ( sConfig.equalsAscii("Modules") )
1218 	{
1219 		m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1220 			::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1221 			css::uno::UNO_QUERY );
1222 		XCUBasedAcceleratorConfiguration::reload();
1223 	}
1224 }
1225 
1226 //-----------------------------------------------
1227 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1228 	throw(css::uno::RuntimeException)
1229 {
1230 	LOG_WARNING("XCUBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
1231 }
1232 
1233 //-----------------------------------------------
1234 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1235 	throw(css::uno::RuntimeException)
1236 {
1237 	LOG_WARNING("XCUBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
1238 }
1239 
1240 //-----------------------------------------------
1241 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1242 	throw(css::uno::RuntimeException)
1243 {
1244 	RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1245 
1246 	css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1247 	aEvent.Base >>= xHAccess;
1248 	if (! xHAccess.is ())
1249 		return;
1250 
1251     css::util::ChangesEvent aReceivedEvents( aEvent );
1252     const sal_Int32 c = aReceivedEvents.Changes.getLength();
1253 	      sal_Int32 i = 0;
1254     for (i=0; i<c; ++i)
1255 	{
1256 		const css::util::ElementChange& aChange  =   aReceivedEvents.Changes[i];
1257 
1258         // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1259         // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1260         // So we try to split the path into 3 parts (module isnt important here, because we already know it ... because
1261         // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1262 
1263         ::rtl::OUString sOrgPath ;
1264         ::rtl::OUString sPath    ;
1265         ::rtl::OUString sKey;
1266 
1267         aChange.Accessor >>= sOrgPath;
1268         sPath              = sOrgPath;
1269         ::rtl::OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1270         ::rtl::OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1271 
1272         if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1273         {
1274             ::rtl::OUString sModule;
1275             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1276             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1277                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1278         }
1279         else if ( sGlobalModules.equals(CFG_ENTRY_MODULES) )
1280         {
1281             ::rtl::OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1282             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1283 
1284             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1285             {
1286                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1287             }
1288         }
1289 	}
1290 }
1291 
1292 //-----------------------------------------------
1293 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1294 	throw(css::uno::RuntimeException)
1295 {
1296 }
1297 
1298 //-----------------------------------------------
1299 void XCUBasedAcceleratorConfiguration::impl_ts_load( sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1300 {
1301     AcceleratorCache aReadCache = AcceleratorCache();
1302     css::uno::Reference< css::container::XNameAccess > xAccess;
1303     if (m_sGlobalOrModules.equalsAscii("Global"))
1304         xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1305     else if (m_sGlobalOrModules.equalsAscii("Modules"))
1306     {
1307         css::uno::Reference< css::container::XNameAccess > xModules;
1308         xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1309         xModules->getByName(m_sModuleCFG) >>= xAccess;
1310     }
1311 
1312     const ::rtl::OUString sIsoLang       = impl_ts_getLocale().toISO();
1313 	const ::rtl::OUString sDefaultLocale = ::rtl::OUString::createFromAscii("en-US");
1314 
1315     css::uno::Reference< css::container::XNameAccess > xKey;
1316     css::uno::Reference< css::container::XNameAccess > xCommand;
1317     if (xAccess.is())
1318     {
1319         css::uno::Sequence< ::rtl::OUString > lKeys = xAccess->getElementNames();
1320         sal_Int32 nKeys = lKeys.getLength();
1321         for ( sal_Int32 i=0; i<nKeys; ++i )
1322         {
1323             ::rtl::OUString sKey = lKeys[i];
1324             xAccess->getByName(sKey) >>= xKey;
1325             xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1326 
1327             css::uno::Sequence< ::rtl::OUString > lLocales = xCommand->getElementNames();
1328             sal_Int32 nLocales = lLocales.getLength();
1329             ::std::vector< ::rtl::OUString > aLocales;
1330             for ( sal_Int32 j=0; j<nLocales; ++j )
1331                 aLocales.push_back(lLocales[j]);
1332 
1333             ::std::vector< ::rtl::OUString >::const_iterator pFound;
1334             for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1335             {
1336                 if ( *pFound == sIsoLang )
1337                     break;
1338             }
1339 
1340             if ( pFound == aLocales.end() )
1341             {
1342                 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1343                 {
1344                     if ( *pFound == sDefaultLocale )
1345                         break;
1346                 }
1347 
1348                 if ( pFound == aLocales.end() )
1349                     continue;
1350             }
1351 
1352             ::rtl::OUString sLocale = *pFound;
1353             ::rtl::OUString sCommand;
1354             xCommand->getByName(sLocale) >>= sCommand;
1355             if (sCommand.getLength()<1)
1356                 continue;
1357 
1358             css::awt::KeyEvent aKeyEvent;
1359 
1360             sal_Int32 nIndex = 0;
1361             ::rtl::OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1362             ::rtl::OUString sPrefix = ::rtl::OUString::createFromAscii("KEY_");
1363             aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
1364 
1365             css::uno::Sequence< ::rtl::OUString > sToken(4);
1366             const sal_Int32 nToken = 4;
1367             sal_Bool bValid = sal_True;
1368             sal_Int32 k;
1369             for (k=0; k<nToken; ++k)
1370             {
1371                 if (nIndex < 0)
1372                     break;
1373 
1374                 sToken[k] = sKey.getToken(0, '_', nIndex);
1375                 ::rtl::OUString sTest = sToken[k];
1376                 if (sToken[k].getLength() < 1)
1377                 {
1378                     bValid = sal_False;
1379                     break;
1380                 }
1381 
1382                 if (sToken[k].equalsAscii("SHIFT"))
1383                     aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1384                 else if (sToken[k].equalsAscii("MOD1"))
1385                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1386                 else if (sToken[k].equalsAscii("MOD2"))
1387                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1388                 else if (sToken[k].equalsAscii("MOD3"))
1389 		            aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1390                 else
1391                 {
1392                     bValid = sal_False;
1393                     break;
1394                 }
1395             }
1396 
1397             if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1398                 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1399         }
1400     }
1401 
1402     if (bPreferred)
1403         m_aPrimaryReadCache.takeOver(aReadCache);
1404     else
1405         m_aSecondaryReadCache.takeOver(aReadCache);
1406 }
1407 
1408 //-----------------------------------------------
1409 void XCUBasedAcceleratorConfiguration::impl_ts_save(sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1410 {
1411     if (bPreferred)
1412     {
1413         AcceleratorCache::TKeyList::const_iterator pIt;
1414         AcceleratorCache::TKeyList lPrimaryReadKeys  = m_aPrimaryReadCache.getAllKeys();
1415         AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1416 
1417         for ( pIt  = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1418         {
1419             if (!m_pPrimaryWriteCache->hasKey(*pIt))
1420                 removeKeyFromConfiguration(*pIt, sal_True);
1421         }
1422 
1423         for ( pIt  = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1424         {
1425             ::rtl::OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1426             if (!m_aPrimaryReadCache.hasKey(*pIt))
1427             {
1428                 insertKeyToConfiguration(*pIt, sCommand, sal_True);
1429             }
1430             else
1431             {
1432                 ::rtl::OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1433                 if (sReadCommand != sCommand)
1434                     insertKeyToConfiguration(*pIt, sCommand, sal_True);
1435             }
1436         }
1437 
1438         // take over all changes into the original container
1439         // SAFE -> ----------------------------------
1440         WriteGuard aWriteLock(m_aLock);
1441 
1442         if (m_pPrimaryWriteCache)
1443         {
1444             m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1445             AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1446             m_pPrimaryWriteCache = 0;
1447             delete pTemp;
1448         }
1449 
1450         aWriteLock.unlock();
1451         // <- SAFE ----------------------------------
1452     }
1453 
1454     else
1455     {
1456         AcceleratorCache::TKeyList::const_iterator pIt;
1457         AcceleratorCache::TKeyList lSecondaryReadKeys  = m_aSecondaryReadCache.getAllKeys();
1458         AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1459 
1460         for ( pIt  = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1461         {
1462             if (!m_pSecondaryWriteCache->hasKey(*pIt))
1463                 removeKeyFromConfiguration(*pIt, sal_False);
1464         }
1465 
1466 
1467         for ( pIt  = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1468         {
1469             ::rtl::OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1470             if (!m_aSecondaryReadCache.hasKey(*pIt))
1471             {
1472                 insertKeyToConfiguration(*pIt, sCommand, sal_False);
1473             }
1474             else
1475             {
1476                 ::rtl::OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1477                 if (sReadCommand != sCommand)
1478                     insertKeyToConfiguration(*pIt, sCommand, sal_False);
1479             }
1480         }
1481 
1482         // take over all changes into the original container
1483         // SAFE -> ----------------------------------
1484         WriteGuard aWriteLock(m_aLock);
1485 
1486         if (m_pSecondaryWriteCache)
1487         {
1488             m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1489             AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1490             m_pSecondaryWriteCache = 0;
1491             delete pTemp;
1492         }
1493 
1494         aWriteLock.unlock();
1495         // <- SAFE ----------------------------------
1496     }
1497 
1498     ::comphelper::ConfigurationHelper::flush(m_xCfg);
1499 }
1500 
1501 //-----------------------------------------------
1502 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const ::rtl::OUString& sCommand, const sal_Bool bPreferred )
1503 {
1504     css::uno::Reference< css::container::XNameAccess > xAccess;
1505     css::uno::Reference< css::container::XNameContainer > xContainer;
1506     css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1507 	css::uno::Reference< css::uno::XInterface > xInst;
1508 
1509     if ( bPreferred )
1510         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1511     else
1512         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1513 
1514 	if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1515 		xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1516 	else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1517     {
1518         css::uno::Reference< css::container::XNameContainer > xModules;
1519 		xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1520         if ( !xModules->hasByName(m_sModuleCFG) )
1521         {
1522             xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
1523             xInst = xFac->createInstance();
1524             xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1525         }
1526         xModules->getByName(m_sModuleCFG) >>= xContainer;
1527     }
1528 
1529     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1530 	css::uno::Reference< css::container::XNameAccess > xKey;
1531 	css::uno::Reference< css::container::XNameContainer > xCommand;
1532 	if ( !xContainer->hasByName(sKey) )
1533 	{
1534 		xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
1535 		xInst = xFac->createInstance();
1536 		xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1537 	}
1538 	xContainer->getByName(sKey) >>= xKey;
1539 
1540     xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1541 	::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1542 	if ( !xCommand->hasByName(sLocale) )
1543 		xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1544 	else
1545 		xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1546 }
1547 
1548 //-----------------------------------------------
1549 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const sal_Bool bPreferred )
1550 {
1551     css::uno::Reference< css::container::XNameAccess > xAccess;
1552     css::uno::Reference< css::container::XNameContainer > xContainer;
1553 
1554     if ( bPreferred )
1555         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1556     else
1557         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1558 
1559 	if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1560 		xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1561 	else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1562     {
1563         css::uno::Reference< css::container::XNameAccess > xModules;
1564 		xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1565         if ( !xModules->hasByName(m_sModuleCFG) )
1566             return;
1567         xModules->getByName(m_sModuleCFG) >>= xContainer;
1568     }
1569 
1570     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1571 	xContainer->removeByName(sKey);
1572 }
1573 
1574 //-----------------------------------------------
1575 void XCUBasedAcceleratorConfiguration::reloadChanged( const ::rtl::OUString& sPrimarySecondary, const ::rtl::OUString& sGlobalModules, const ::rtl::OUString& sModule, const ::rtl::OUString& sKey )
1576 {
1577     css::uno::Reference< css::container::XNameAccess > xAccess;
1578     css::uno::Reference< css::container::XNameContainer > xContainer;
1579 
1580     m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1581 	if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1582 		xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1583 	else
1584     {
1585         css::uno::Reference< css::container::XNameAccess > xModules;
1586 		xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1587         if ( !xModules->hasByName(sModule) )
1588             return;
1589         xModules->getByName(sModule) >>= xContainer;
1590     }
1591 
1592 	css::awt::KeyEvent aKeyEvent;
1593 	::rtl::OUString sKeyIdentifier;
1594 
1595 	sal_Int32 nIndex = 0;
1596 	sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1597 	aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(::rtl::OUString::createFromAscii("KEY_")+sKeyIdentifier);
1598 
1599 	css::uno::Sequence< ::rtl::OUString > sToken(3);
1600 	const sal_Int32 nToken = 3;
1601 	for (sal_Int32 i=0; i<nToken; ++i)
1602 	{
1603 		if ( nIndex < 0 )
1604 			break;
1605 
1606 		sToken[i] = sKey.getToken(0, '_', nIndex);
1607 		if (sToken[i].equalsAscii("SHIFT"))
1608 			aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1609 		else if (sToken[i].equalsAscii("MOD1"))
1610 			aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1611 		else if (sToken[i].equalsAscii("MOD2"))
1612 			aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1613                 else if (sToken[i].equalsAscii("MOD3"))
1614                         aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1615 	}
1616 
1617 	css::uno::Reference< css::container::XNameAccess > xKey;
1618 	css::uno::Reference< css::container::XNameAccess > xCommand;
1619 	::rtl::OUString sCommand;
1620 
1621 	if (xContainer->hasByName(sKey))
1622 	{
1623 		::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1624 		xContainer->getByName(sKey)    >>= xKey;
1625 		xKey->getByName(CFG_PROP_COMMAND)  >>= xCommand;
1626 		xCommand->getByName(sLocale)       >>= sCommand;
1627 	}
1628 
1629     if (sPrimarySecondary.equals(CFG_ENTRY_PRIMARY))
1630     {
1631         if (sCommand.getLength() ==0)
1632             m_aPrimaryReadCache.removeKey(aKeyEvent);
1633         else
1634 	        m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1635     }
1636     else if (sPrimarySecondary.equals(CFG_ENTRY_SECONDARY))
1637     {
1638         if (sCommand.getLength() ==0)
1639             m_aSecondaryReadCache.removeKey(aKeyEvent);
1640         else
1641             m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1642     }
1643 }
1644 
1645 //-----------------------------------------------
1646 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bPreferred, sal_Bool bWriteAccessRequested)
1647 {
1648     // SAFE -> ----------------------------------
1649     WriteGuard aWriteLock(m_aLock);
1650 
1651     if (bPreferred)
1652     {
1653         //create copy of our readonly-cache, if write access is forced ... but
1654         //not still possible!
1655         if (
1656             (bWriteAccessRequested) &&
1657             (!m_pPrimaryWriteCache       )
1658             )
1659         {
1660             m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1661         }
1662 
1663         // in case, we have a writeable cache, we use it for reading too!
1664         // Otherwhise the API user cant find its own changes ...
1665         if (m_pPrimaryWriteCache)
1666             return *m_pPrimaryWriteCache;
1667         else
1668             return m_aPrimaryReadCache;
1669     }
1670 
1671     else
1672     {
1673         //create copy of our readonly-cache, if write access is forced ... but
1674         //not still possible!
1675         if (
1676             (bWriteAccessRequested) &&
1677             (!m_pSecondaryWriteCache       )
1678             )
1679         {
1680             m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1681         }
1682 
1683         // in case, we have a writeable cache, we use it for reading too!
1684         // Otherwhise the API user cant find its own changes ...
1685         if (m_pSecondaryWriteCache)
1686             return *m_pSecondaryWriteCache;
1687         else
1688             return m_aSecondaryReadCache;
1689     }
1690 
1691 	// <- SAFE ----------------------------------
1692 }
1693 
1694 //-----------------------------------------------
1695 ::comphelper::Locale XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1696 {
1697 	static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
1698 	static ::rtl::OUString LOCALE_PATH    = ::rtl::OUString::createFromAscii("L10N"                 );
1699 	static ::rtl::OUString LOCALE_KEY     = ::rtl::OUString::createFromAscii("ooLocale"             );
1700 
1701 	// SAFE -> ----------------------------------
1702 	ReadGuard aReadLock(m_aLock);
1703 	css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1704 	aReadLock.unlock();
1705 	// <- SAFE ----------------------------------
1706 
1707 	css::uno::Reference< css::uno::XInterface >     xCFG      = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
1708 	css::uno::Reference< css::beans::XPropertySet > xProp     (xCFG, css::uno::UNO_QUERY_THROW);
1709 	::rtl::OUString                                 sISOLocale;
1710 	xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
1711 
1712 	if (!sISOLocale.getLength())
1713 		return ::comphelper::Locale::EN_US();
1714 	return ::comphelper::Locale(sISOLocale);
1715 }
1716 
1717 } // namespace framework
1718