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