xref: /AOO41X/main/framework/source/accelerators/acceleratorconfiguration.cxx (revision fa6c498df8a2a841cfab12bb1e38597050462477)
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 
lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping> & _rKeyMapping,const css::awt::KeyEvent & aKeyEvent)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
DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::ui::XAcceleratorConfiguration),DIRECT_INTERFACE (css::form::XReset),DIRECT_INTERFACE (css::ui::XUIConfigurationPersistence),DIRECT_INTERFACE (css::ui::XUIConfigurationStorage),DIRECT_INTERFACE (css::ui::XUIConfiguration))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 //-----------------------------------------------
~XMLBasedAcceleratorConfiguration()155 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
156 {
157     LOG_ASSERT(!m_pWriteCache, "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()\nChanges not flushed. Ignore it ...")
158 }
159 
160 //-----------------------------------------------
getAllKeyEvents()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 //-----------------------------------------------
getCommandByKeyEvent(const css::awt::KeyEvent & aKeyEvent)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 //-----------------------------------------------
setKeyEvent(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand)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 //-----------------------------------------------
removeKeyEvent(const css::awt::KeyEvent & aKeyEvent)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 //-----------------------------------------------
getKeyEventsByCommand(const::rtl::OUString & sCommand)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 //-----------------------------------------------
getPreferredKeyEventsForCommandList(const css::uno::Sequence<::rtl::OUString> & lCommandList)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 //-----------------------------------------------
removeCommandFromAllKeyEvents(const::rtl::OUString & sCommand)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 //-----------------------------------------------
reload()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 //-----------------------------------------------
store()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 //-----------------------------------------------
storeToStorage(const css::uno::Reference<css::embed::XStorage> & xStorage)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 //-----------------------------------------------
isModified()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 //-----------------------------------------------
isReadOnly()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 //-----------------------------------------------
setStorage(const css::uno::Reference<css::embed::XStorage> &)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 //-----------------------------------------------
hasStorage()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 //-----------------------------------------------
addConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)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 //-----------------------------------------------
removeConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)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 //-----------------------------------------------
reset()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 //-----------------------------------------------
addResetListener(const css::uno::Reference<css::form::XResetListener> &)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 //-----------------------------------------------
removeResetListener(const css::uno::Reference<css::form::XResetListener> &)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
changesOccured(const::rtl::OUString &)516 void XMLBasedAcceleratorConfiguration::changesOccured(const ::rtl::OUString& /*sPath*/)
517 {
518     reload();
519 }
520 
521 //-----------------------------------------------
impl_ts_load(const css::uno::Reference<css::io::XInputStream> & xStream)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 //-----------------------------------------------
impl_ts_save(const css::uno::Reference<css::io::XOutputStream> & xStream)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 //-----------------------------------------------
impl_getCFG(sal_Bool bWriteAccessRequested)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 //-----------------------------------------------
impl_ts_getLocale() const649 ::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
DEFINE_XINTERFACE_8(XCUBasedAcceleratorConfiguration,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::ui::XAcceleratorConfiguration),DIRECT_INTERFACE (css::util::XChangesListener),DIRECT_INTERFACE (css::form::XReset),DIRECT_INTERFACE (css::lang::XComponent),DIRECT_INTERFACE (css::ui::XUIConfigurationPersistence),DIRECT_INTERFACE (css::ui::XUIConfigurationStorage),DIRECT_INTERFACE (css::ui::XUIConfiguration))679 DEFINE_XINTERFACE_8(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::lang::XComponent                ),
686                     DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
687                     DIRECT_INTERFACE(css::ui::XUIConfigurationStorage    ),
688                     DIRECT_INTERFACE(css::ui::XUIConfiguration           ))
689 
690                     DEFINE_XTYPEPROVIDER_8(XCUBasedAcceleratorConfiguration ,
691                     css::lang::XTypeProvider             ,
692                     css::ui::XAcceleratorConfiguration  ,
693                     css::util::XChangesListener          ,
694                     css::form::XReset                    ,
695                     css::lang::XComponent                ,
696                     css::ui::XUIConfigurationPersistence,
697                     css::ui::XUIConfigurationStorage    ,
698                     css::ui::XUIConfiguration           )
699 
700 //-----------------------------------------------
701 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
702                                 : ThreadHelpBase  (&Application::GetSolarMutex())
703                                 , m_xSMGR         (xSMGR                        )
704                                 , m_pPrimaryWriteCache(0                        )
705                                 , m_pSecondaryWriteCache(0                      )
706 {
707     static const ::rtl::OUString CFG_ENTRY_ACCELERATORS(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Accelerators"));
708     m_xCfg = css::uno::Reference< css::container::XNameAccess > (
709              ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
710              css::uno::UNO_QUERY );
711 }
712 
713 //-----------------------------------------------
~XCUBasedAcceleratorConfiguration()714 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
715 {
716 }
717 
718 //-----------------------------------------------
getAllKeyEvents()719 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
720     throw(css::uno::RuntimeException)
721 {
722     // SAFE -> ----------------------------------
723     ReadGuard aReadLock(m_aLock);
724 
725     AcceleratorCache::TKeyList lKeys  = impl_getCFG(sal_True).getAllKeys(); //get keys from PrimaryKeys set
726 
727     AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(sal_False).getAllKeys(); //get keys from SecondaryKeys set
728     lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
729     AcceleratorCache::TKeyList::const_iterator pIt;
730     AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
731     for ( pIt  = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
732         lKeys.push_back(*pIt);
733 
734     return lKeys.getAsConstList();
735 
736     // <- SAFE ----------------------------------
737 }
738 
739 //-----------------------------------------------
getCommandByKeyEvent(const css::awt::KeyEvent & aKeyEvent)740 ::rtl::OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
741     throw(css::container::NoSuchElementException,
742           css::uno::RuntimeException            )
743 {
744     // SAFE -> ----------------------------------
745     ReadGuard aReadLock(m_aLock);
746 
747     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
748     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
749 
750     if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
751         throw css::container::NoSuchElementException(
752         ::rtl::OUString(),
753         static_cast< ::cppu::OWeakObject* >(this));
754 
755     if (rPrimaryCache.hasKey(aKeyEvent))
756         return rPrimaryCache.getCommandByKey(aKeyEvent);
757     else
758         return rSecondaryCache.getCommandByKey(aKeyEvent);
759 
760     // <- SAFE ----------------------------------
761 }
762 
763 //-----------------------------------------------
setKeyEvent(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand)764 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
765                                                     const ::rtl::OUString&    sCommand )
766                                                     throw(css::lang::IllegalArgumentException,
767                                                     css::uno::RuntimeException         )
768 {
769     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::setKeyEvent" );
770 
771     if (
772         (aKeyEvent.KeyCode   == 0) &&
773         (aKeyEvent.KeyChar   == 0) &&
774         (aKeyEvent.KeyFunc   == 0) &&
775         (aKeyEvent.Modifiers == 0)
776         )
777         throw css::lang::IllegalArgumentException(
778                 ::rtl::OUString::createFromAscii("Such key event seams not to be supported by any operating system."),
779                 static_cast< ::cppu::OWeakObject* >(this),
780                 0);
781 
782     if (!sCommand.getLength())
783                 throw css::lang::IllegalArgumentException(
784                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
785                 static_cast< ::cppu::OWeakObject* >(this),
786                 1);
787 
788     // SAFE -> ----------------------------------
789     WriteGuard aWriteLock(m_aLock);
790 
791     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True ); // sal_True => force getting of a writeable cache!
792     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True); // sal_True => force getting of a writeable cache!
793 
794     if ( rPrimaryCache.hasKey(aKeyEvent) )
795     {
796         ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
797         if ( sCommand != sOriginalCommand )
798         {
799             if (rSecondaryCache.hasCommand(sOriginalCommand))
800             {
801                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
802                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
803                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
804             }
805 
806             if (rPrimaryCache.hasCommand(sCommand))
807             {
808                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
809                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
810                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
811             }
812 
813             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
814         }
815     }
816 
817     else if ( rSecondaryCache.hasKey(aKeyEvent) )
818     {
819         ::rtl::OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
820         if (sCommand != sOriginalCommand)
821         {
822             if (rPrimaryCache.hasCommand(sCommand))
823             {
824                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
825                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
826                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
827             }
828 
829             rSecondaryCache.removeKey(aKeyEvent);
830             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
831         }
832     }
833 
834     else
835     {
836         if (rPrimaryCache.hasCommand(sCommand))
837         {
838             AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
839             rPrimaryCache.removeKey(lPrimaryKeys[0]);
840             rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
841         }
842 
843         rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
844     }
845 
846     aWriteLock.unlock();
847     // <- SAFE ----------------------------------
848 }
849 
850 //-----------------------------------------------
removeKeyEvent(const css::awt::KeyEvent & aKeyEvent)851 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
852     throw(css::container::NoSuchElementException,
853           css::uno::RuntimeException            )
854 {
855     // SAFE -> ----------------------------------
856     WriteGuard aWriteLock(m_aLock);
857 
858     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
859     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
860 
861     if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
862         throw css::container::NoSuchElementException(
863         ::rtl::OUString(),
864         static_cast< ::cppu::OWeakObject* >(this));
865 
866     if (rPrimaryCache.hasKey(aKeyEvent))
867     {
868         ::rtl::OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
869         if (sDelCommand.getLength() > 0)
870         {
871             ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
872             if (rSecondaryCache.hasCommand(sOriginalCommand))
873             {
874                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
875                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
876                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
877             }
878 
879             rPrimaryCache.removeKey(aKeyEvent);
880         }
881 
882     }
883     else
884     {
885         ::rtl::OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
886         if (sDelCommand.getLength() > 0)
887             rSecondaryCache.removeKey(aKeyEvent);
888     }
889 
890     // <- SAFE ----------------------------------
891 }
892 
893 //-----------------------------------------------
getKeyEventsByCommand(const::rtl::OUString & sCommand)894 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
895     throw(css::lang::IllegalArgumentException   ,
896         css::container::NoSuchElementException,
897         css::uno::RuntimeException            )
898 {
899     if (!sCommand.getLength())
900         throw css::lang::IllegalArgumentException(
901                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
902                 static_cast< ::cppu::OWeakObject* >(this),
903                 1);
904 
905     // SAFE -> ----------------------------------
906     ReadGuard aReadLock(m_aLock);
907 
908     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
909     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
910 
911     if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
912         throw css::container::NoSuchElementException(
913                 ::rtl::OUString(),
914                 static_cast< ::cppu::OWeakObject* >(this));
915 
916     AcceleratorCache::TKeyList lKeys  = rPrimaryCache.getKeysByCommand(sCommand);
917 
918     AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
919     AcceleratorCache::TKeyList::const_iterator pIt;
920     for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
921         lKeys.push_back(*pIt);
922 
923     return lKeys.getAsConstList();
924 
925     // <- SAFE ----------------------------------
926 }
927 
928 //-----------------------------------------------
lcl_getPreferredKey(const AcceleratorCache::TKeyList & lKeys)929 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
930 {
931     AcceleratorCache::TKeyList::const_iterator pIt;
932     for (  pIt  = lKeys.begin ();
933            pIt != lKeys.end   ();
934          ++pIt                  )
935     {
936         const css::awt::KeyEvent& rAWTKey = *pIt;
937         const KeyCode             aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
938         const String              sName   = aVCLKey.GetName();
939 
940         if (sName.Len () > 0)
941             return pIt;
942     }
943 
944     return lKeys.end ();
945 }
946 
947 //-----------------------------------------------
getPreferredKeyEventsForCommandList(const css::uno::Sequence<::rtl::OUString> & lCommandList)948 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
949     throw(css::lang::IllegalArgumentException   ,
950         css::uno::RuntimeException            )
951 {
952     // SAFE -> ----------------------------------
953     ReadGuard aReadLock(m_aLock);
954 
955     sal_Int32                           i              = 0;
956     sal_Int32                           c              = lCommandList.getLength();
957     css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
958     AcceleratorCache&                   rCache         = impl_getCFG(sal_True);
959 
960     for (i=0; i<c; ++i)
961     {
962         const ::rtl::OUString& rCommand = lCommandList[i];
963         if (!rCommand.getLength())
964             throw css::lang::IllegalArgumentException(
965                     ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
966                     static_cast< ::cppu::OWeakObject* >(this),
967                     (sal_Int16)i);
968 
969         if (!rCache.hasCommand(rCommand))
970             continue;
971 
972         AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
973         if ( lKeys.empty() )
974             continue;
975 
976         AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
977         if (pPreferredKey != lKeys.end ())
978         {
979             css::uno::Any& rAny = lPreferredOnes[i];
980             rAny <<= *(pPreferredKey);
981         }
982     }
983 
984     aReadLock.unlock();
985     // <- SAFE ----------------------------------
986 
987     return lPreferredOnes;
988 }
989 
990 //-----------------------------------------------
removeCommandFromAllKeyEvents(const::rtl::OUString & sCommand)991 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
992     throw(css::lang::IllegalArgumentException   ,
993         css::container::NoSuchElementException,
994         css::uno::RuntimeException            )
995 {
996     if (!sCommand.getLength())
997         throw css::lang::IllegalArgumentException(
998                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
999                 static_cast< ::cppu::OWeakObject* >(this),
1000                 0);
1001 
1002     // SAFE -> ----------------------------------
1003     WriteGuard aWriteLock(m_aLock);
1004 
1005     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
1006     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
1007 
1008     if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
1009         throw css::container::NoSuchElementException(
1010                 ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
1011                 static_cast< ::cppu::OWeakObject* >(this));
1012 
1013     if (rPrimaryCache.hasCommand(sCommand))
1014         rPrimaryCache.removeCommand(sCommand);
1015     if (rSecondaryCache.hasCommand(sCommand))
1016         rSecondaryCache.removeCommand(sCommand);
1017 
1018     aWriteLock.unlock();
1019     // <- SAFE ----------------------------------
1020 }
1021 
1022 //-----------------------------------------------
reload()1023 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
1024     throw(css::uno::Exception       ,
1025         css::uno::RuntimeException)
1026 {
1027     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::reload()" );
1028 
1029     // SAFE -> ----------------------------------
1030     WriteGuard aWriteLock(m_aLock);
1031 
1032     sal_Bool bPreferred;
1033     css::uno::Reference< css::container::XNameAccess > xAccess;
1034 
1035     bPreferred = sal_True;
1036     m_aPrimaryReadCache = AcceleratorCache();
1037     if (m_pPrimaryWriteCache)
1038     {
1039         // be aware of reentrance problems - use temp variable for calling delete ... :-)
1040         AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1041         m_pPrimaryWriteCache = 0;
1042         delete pTemp;
1043     }
1044     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1045     impl_ts_load(bPreferred, xAccess); // load the preferred keys
1046 
1047     bPreferred = sal_False;
1048     m_aSecondaryReadCache = AcceleratorCache();
1049     if (m_pSecondaryWriteCache)
1050     {
1051         // be aware of reentrance problems - use temp variable for calling delete ... :-)
1052         AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1053         m_pSecondaryWriteCache = 0;
1054         delete pTemp;
1055     }
1056     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1057     impl_ts_load(bPreferred, xAccess); // load the secondary keys
1058 
1059     aWriteLock.unlock();
1060     // <- SAFE ----------------------------------
1061 }
1062 
1063 //-----------------------------------------------
store()1064 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
1065     throw(css::uno::Exception       ,
1066           css::uno::RuntimeException)
1067 {
1068     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::store()" );
1069 
1070     // SAFE -> ----------------------------------
1071     ReadGuard aReadLock(m_aLock);
1072 
1073     sal_Bool bPreferred;
1074     css::uno::Reference< css::container::XNameAccess > xAccess;
1075 
1076     bPreferred = sal_True;
1077     // on-demand creation of the primary write cache
1078     impl_getCFG(bPreferred, sal_True);
1079     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1080     impl_ts_save(bPreferred, xAccess);
1081 
1082     bPreferred = sal_False;
1083     // on-demand creation of the secondary write cache
1084     impl_getCFG(bPreferred, sal_True);
1085     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1086     impl_ts_save(bPreferred, xAccess);
1087 
1088     aReadLock.unlock();
1089     // <- SAFE ----------------------------------
1090 }
1091 
1092 //-----------------------------------------------
storeToStorage(const css::uno::Reference<css::embed::XStorage> & xStorage)1093 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
1094     throw(css::uno::Exception       ,
1095       css::uno::RuntimeException)
1096 {
1097     // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
1098     if (!xStorage.is())
1099         return;
1100 
1101     long nOpenModes = css::embed::ElementModes::READWRITE;
1102     css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(::rtl::OUString::createFromAscii("accelerator"), nOpenModes);
1103     if (!xAcceleratorTypeStorage.is())
1104         return;
1105 
1106     css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(::rtl::OUString::createFromAscii("current"), nOpenModes);
1107     css::uno::Reference< css::io::XOutputStream > xOut;
1108     if (xStream.is())
1109         xOut = xStream->getOutputStream();
1110     if (!xOut.is())
1111         throw css::io::IOException(
1112         ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
1113         static_cast< ::cppu::OWeakObject* >(this));
1114 
1115     // the original m_aCache has been split into primay cache and secondary cache...
1116     // we should merge them before storing to storage
1117     // SAFE -> ----------------------------------
1118     WriteGuard aWriteLock(m_aLock);
1119 
1120     AcceleratorCache aCache;
1121     if (m_pPrimaryWriteCache != 0)
1122         aCache.takeOver(*m_pPrimaryWriteCache);
1123     else
1124         aCache.takeOver(m_aPrimaryReadCache);
1125 
1126     AcceleratorCache::TKeyList lKeys;
1127     AcceleratorCache::TKeyList::const_iterator pIt;
1128     if (m_pSecondaryWriteCache!=0)
1129     {
1130         lKeys = m_pSecondaryWriteCache->getAllKeys();
1131         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1132             aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
1133     }
1134     else
1135     {
1136         lKeys = m_aSecondaryReadCache.getAllKeys();
1137         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1138             aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
1139     }
1140 
1141     aWriteLock.unlock();
1142     // <- SAFE ----------------------------------
1143 
1144     css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
1145     xClearable->truncate();
1146     css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
1147     if (xSeek.is())
1148         xSeek->seek(0);
1149 
1150     css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter    (m_xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
1151     css::uno::Reference< css::io::XActiveDataSource>       xDataSource(xWriter                                     , css::uno::UNO_QUERY_THROW);
1152     xDataSource->setOutputStream(xOut);
1153 
1154     // write into the stream
1155     AcceleratorConfigurationWriter aWriter(aCache, xWriter);
1156     aWriter.flush();
1157 }
1158 
1159 //-----------------------------------------------
isModified()1160 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
1161     throw(css::uno::RuntimeException)
1162 {
1163     return sal_False;
1164 }
1165 
1166 //-----------------------------------------------
isReadOnly()1167 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
1168     throw(css::uno::RuntimeException)
1169 {
1170     return sal_False;
1171 }
1172 
1173 //-----------------------------------------------
setStorage(const css::uno::Reference<css::embed::XStorage> &)1174 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
1175     throw(css::uno::RuntimeException)
1176 {
1177     LOG_WARNING("XCUBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
1178 }
1179 
1180 //-----------------------------------------------
hasStorage()1181 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
1182     throw(css::uno::RuntimeException)
1183 {
1184     LOG_WARNING("XCUBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
1185         return sal_False;
1186 }
1187 
1188 //-----------------------------------------------
addConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)1189 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1190     throw(css::uno::RuntimeException)
1191 {
1192     LOG_WARNING("XCUBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
1193 }
1194 
1195 //-----------------------------------------------
removeConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)1196 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1197     throw(css::uno::RuntimeException)
1198 {
1199     LOG_WARNING("XCUBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
1200 }
1201 
1202 //-----------------------------------------------
reset()1203 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
1204     throw(css::uno::RuntimeException)
1205 {
1206     css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
1207     ::rtl::OUString sConfig = xNamed->getName();
1208     if ( sConfig.equalsAscii("Global") )
1209     {
1210         m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1211             ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1212             css::uno::UNO_QUERY );
1213         XCUBasedAcceleratorConfiguration::reload();
1214     }
1215     else if ( sConfig.equalsAscii("Modules") )
1216     {
1217         m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1218             ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1219             css::uno::UNO_QUERY );
1220         XCUBasedAcceleratorConfiguration::reload();
1221     }
1222 }
1223 
1224 //-----------------------------------------------
addResetListener(const css::uno::Reference<css::form::XResetListener> &)1225 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1226     throw(css::uno::RuntimeException)
1227 {
1228     LOG_WARNING("XCUBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
1229 }
1230 
1231 //-----------------------------------------------
removeResetListener(const css::uno::Reference<css::form::XResetListener> &)1232 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1233     throw(css::uno::RuntimeException)
1234 {
1235     LOG_WARNING("XCUBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
1236 }
1237 
1238 //-----------------------------------------------
changesOccurred(const css::util::ChangesEvent & aEvent)1239 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1240     throw(css::uno::RuntimeException)
1241 {
1242     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1243 
1244     css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1245     aEvent.Base >>= xHAccess;
1246     if (! xHAccess.is ())
1247         return;
1248 
1249     css::util::ChangesEvent aReceivedEvents( aEvent );
1250     const sal_Int32 c = aReceivedEvents.Changes.getLength();
1251           sal_Int32 i = 0;
1252     for (i=0; i<c; ++i)
1253     {
1254         const css::util::ElementChange& aChange  =   aReceivedEvents.Changes[i];
1255 
1256         // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1257         // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1258         // So we try to split the path into 3 parts (module isnt important here, because we already know it ... because
1259         // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1260 
1261         ::rtl::OUString sOrgPath ;
1262         ::rtl::OUString sPath    ;
1263         ::rtl::OUString sKey;
1264 
1265         aChange.Accessor >>= sOrgPath;
1266         sPath              = sOrgPath;
1267         ::rtl::OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1268         ::rtl::OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1269 
1270         if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1271         {
1272             ::rtl::OUString sModule;
1273             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1274             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1275                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1276         }
1277         else if ( sGlobalModules.equals(CFG_ENTRY_MODULES) )
1278         {
1279             ::rtl::OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1280             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1281 
1282             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1283             {
1284                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1285             }
1286         }
1287     }
1288 }
1289 
1290 //-----------------------------------------------
disposing(const css::lang::EventObject &)1291 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1292     throw(css::uno::RuntimeException)
1293 {
1294 }
1295 
1296 //-----------------------------------------------
dispose()1297 void SAL_CALL XCUBasedAcceleratorConfiguration::dispose()
1298     throw(css::uno::RuntimeException)
1299 {
1300     // nop
1301 }
1302 
1303 //-----------------------------------------------
addEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> &)1304 void SAL_CALL XCUBasedAcceleratorConfiguration::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /* xListener */ )
1305     throw(css::uno::RuntimeException)
1306 {
1307     // nop
1308 }
1309 
1310 //-----------------------------------------------
removeEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> &)1311 void SAL_CALL XCUBasedAcceleratorConfiguration::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /* aListener */ )
1312     throw(css::uno::RuntimeException)
1313 {
1314     // nop
1315 }
1316 
1317 //-----------------------------------------------
impl_ts_load(sal_Bool bPreferred,const css::uno::Reference<css::container::XNameAccess> & xCfg)1318 void XCUBasedAcceleratorConfiguration::impl_ts_load( sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1319 {
1320     AcceleratorCache aReadCache = AcceleratorCache();
1321     css::uno::Reference< css::container::XNameAccess > xAccess;
1322     if (m_sGlobalOrModules.equalsAscii("Global"))
1323         xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1324     else if (m_sGlobalOrModules.equalsAscii("Modules"))
1325     {
1326         css::uno::Reference< css::container::XNameAccess > xModules;
1327         xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1328         xModules->getByName(m_sModuleCFG) >>= xAccess;
1329     }
1330 
1331     const ::rtl::OUString sIsoLang       = impl_ts_getLocale().toISO();
1332     const ::rtl::OUString sDefaultLocale = ::rtl::OUString::createFromAscii("en-US");
1333 
1334     css::uno::Reference< css::container::XNameAccess > xKey;
1335     css::uno::Reference< css::container::XNameAccess > xCommand;
1336     if (xAccess.is())
1337     {
1338         css::uno::Sequence< ::rtl::OUString > lKeys = xAccess->getElementNames();
1339         sal_Int32 nKeys = lKeys.getLength();
1340         for ( sal_Int32 i=0; i<nKeys; ++i )
1341         {
1342             ::rtl::OUString sKey = lKeys[i];
1343             xAccess->getByName(sKey) >>= xKey;
1344             xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1345 
1346             css::uno::Sequence< ::rtl::OUString > lLocales = xCommand->getElementNames();
1347             sal_Int32 nLocales = lLocales.getLength();
1348             ::std::vector< ::rtl::OUString > aLocales;
1349             for ( sal_Int32 j=0; j<nLocales; ++j )
1350                 aLocales.push_back(lLocales[j]);
1351 
1352             ::std::vector< ::rtl::OUString >::const_iterator pFound;
1353             for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1354             {
1355                 if ( *pFound == sIsoLang )
1356                     break;
1357             }
1358 
1359             if ( pFound == aLocales.end() )
1360             {
1361                 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1362                 {
1363                     if ( *pFound == sDefaultLocale )
1364                         break;
1365                 }
1366 
1367                 if ( pFound == aLocales.end() )
1368                     continue;
1369             }
1370 
1371             ::rtl::OUString sLocale = *pFound;
1372             ::rtl::OUString sCommand;
1373             xCommand->getByName(sLocale) >>= sCommand;
1374             if (sCommand.getLength()<1)
1375                 continue;
1376 
1377             css::awt::KeyEvent aKeyEvent;
1378 
1379             sal_Int32 nIndex = 0;
1380             ::rtl::OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1381             ::rtl::OUString sPrefix = ::rtl::OUString::createFromAscii("KEY_");
1382             aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
1383 
1384             css::uno::Sequence< ::rtl::OUString > sToken(4);
1385             const sal_Int32 nToken = 4;
1386             sal_Bool bValid = sal_True;
1387             sal_Int32 k;
1388             for (k=0; k<nToken; ++k)
1389             {
1390                 if (nIndex < 0)
1391                     break;
1392 
1393                 sToken[k] = sKey.getToken(0, '_', nIndex);
1394                 ::rtl::OUString sTest = sToken[k];
1395                 if (sToken[k].getLength() < 1)
1396                 {
1397                     bValid = sal_False;
1398                     break;
1399                 }
1400 
1401                 if (sToken[k].equalsAscii("SHIFT"))
1402                     aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1403                 else if (sToken[k].equalsAscii("MOD1"))
1404                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1405                 else if (sToken[k].equalsAscii("MOD2"))
1406                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1407                 else if (sToken[k].equalsAscii("MOD3"))
1408                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1409                 else
1410                 {
1411                     bValid = sal_False;
1412                     break;
1413                 }
1414             }
1415 
1416             if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1417                 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1418         }
1419     }
1420 
1421     if (bPreferred)
1422         m_aPrimaryReadCache.takeOver(aReadCache);
1423     else
1424         m_aSecondaryReadCache.takeOver(aReadCache);
1425 }
1426 
1427 //-----------------------------------------------
impl_ts_save(sal_Bool bPreferred,const css::uno::Reference<css::container::XNameAccess> &)1428 void XCUBasedAcceleratorConfiguration::impl_ts_save(sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1429 {
1430     if (bPreferred)
1431     {
1432         AcceleratorCache::TKeyList::const_iterator pIt;
1433         AcceleratorCache::TKeyList lPrimaryReadKeys  = m_aPrimaryReadCache.getAllKeys();
1434         AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1435 
1436         for ( pIt  = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1437         {
1438             if (!m_pPrimaryWriteCache->hasKey(*pIt))
1439                 removeKeyFromConfiguration(*pIt, sal_True);
1440         }
1441 
1442         for ( pIt  = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1443         {
1444             ::rtl::OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1445             if (!m_aPrimaryReadCache.hasKey(*pIt))
1446             {
1447                 insertKeyToConfiguration(*pIt, sCommand, sal_True);
1448             }
1449             else
1450             {
1451                 ::rtl::OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1452                 if (sReadCommand != sCommand)
1453                     insertKeyToConfiguration(*pIt, sCommand, sal_True);
1454             }
1455         }
1456 
1457         // take over all changes into the original container
1458         // SAFE -> ----------------------------------
1459         WriteGuard aWriteLock(m_aLock);
1460 
1461         if (m_pPrimaryWriteCache)
1462         {
1463             m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1464             AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1465             m_pPrimaryWriteCache = 0;
1466             delete pTemp;
1467         }
1468 
1469         aWriteLock.unlock();
1470         // <- SAFE ----------------------------------
1471     }
1472 
1473     else
1474     {
1475         AcceleratorCache::TKeyList::const_iterator pIt;
1476         AcceleratorCache::TKeyList lSecondaryReadKeys  = m_aSecondaryReadCache.getAllKeys();
1477         AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1478 
1479         for ( pIt  = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1480         {
1481             if (!m_pSecondaryWriteCache->hasKey(*pIt))
1482                 removeKeyFromConfiguration(*pIt, sal_False);
1483         }
1484 
1485 
1486         for ( pIt  = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1487         {
1488             ::rtl::OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1489             if (!m_aSecondaryReadCache.hasKey(*pIt))
1490             {
1491                 insertKeyToConfiguration(*pIt, sCommand, sal_False);
1492             }
1493             else
1494             {
1495                 ::rtl::OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1496                 if (sReadCommand != sCommand)
1497                     insertKeyToConfiguration(*pIt, sCommand, sal_False);
1498             }
1499         }
1500 
1501         // take over all changes into the original container
1502         // SAFE -> ----------------------------------
1503         WriteGuard aWriteLock(m_aLock);
1504 
1505         if (m_pSecondaryWriteCache)
1506         {
1507             m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1508             AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1509             m_pSecondaryWriteCache = 0;
1510             delete pTemp;
1511         }
1512 
1513         aWriteLock.unlock();
1514         // <- SAFE ----------------------------------
1515     }
1516 
1517     ::comphelper::ConfigurationHelper::flush(m_xCfg);
1518 }
1519 
1520 //-----------------------------------------------
insertKeyToConfiguration(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand,const sal_Bool bPreferred)1521 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const ::rtl::OUString& sCommand, const sal_Bool bPreferred )
1522 {
1523     css::uno::Reference< css::container::XNameAccess > xAccess;
1524     css::uno::Reference< css::container::XNameContainer > xContainer;
1525     css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1526     css::uno::Reference< css::uno::XInterface > xInst;
1527 
1528     if ( bPreferred )
1529         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1530     else
1531         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1532 
1533     if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1534         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1535     else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1536     {
1537         css::uno::Reference< css::container::XNameContainer > xModules;
1538         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1539         if ( !xModules->hasByName(m_sModuleCFG) )
1540         {
1541             xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
1542             xInst = xFac->createInstance();
1543             xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1544         }
1545         xModules->getByName(m_sModuleCFG) >>= xContainer;
1546     }
1547 
1548     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1549     css::uno::Reference< css::container::XNameAccess > xKey;
1550     css::uno::Reference< css::container::XNameContainer > xCommand;
1551     if ( !xContainer->hasByName(sKey) )
1552     {
1553         xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
1554         xInst = xFac->createInstance();
1555         xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1556     }
1557     xContainer->getByName(sKey) >>= xKey;
1558 
1559     xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1560     ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1561     if ( !xCommand->hasByName(sLocale) )
1562         xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1563     else
1564         xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1565 }
1566 
1567 //-----------------------------------------------
removeKeyFromConfiguration(const css::awt::KeyEvent & aKeyEvent,const sal_Bool bPreferred)1568 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const sal_Bool bPreferred )
1569 {
1570     css::uno::Reference< css::container::XNameAccess > xAccess;
1571     css::uno::Reference< css::container::XNameContainer > xContainer;
1572 
1573     if ( bPreferred )
1574         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1575     else
1576         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1577 
1578     if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1579         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1580     else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1581     {
1582         css::uno::Reference< css::container::XNameAccess > xModules;
1583         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1584         if ( !xModules->hasByName(m_sModuleCFG) )
1585             return;
1586         xModules->getByName(m_sModuleCFG) >>= xContainer;
1587     }
1588 
1589     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1590     xContainer->removeByName(sKey);
1591 }
1592 
1593 //-----------------------------------------------
reloadChanged(const::rtl::OUString & sPrimarySecondary,const::rtl::OUString & sGlobalModules,const::rtl::OUString & sModule,const::rtl::OUString & sKey)1594 void XCUBasedAcceleratorConfiguration::reloadChanged( const ::rtl::OUString& sPrimarySecondary, const ::rtl::OUString& sGlobalModules, const ::rtl::OUString& sModule, const ::rtl::OUString& sKey )
1595 {
1596     css::uno::Reference< css::container::XNameAccess > xAccess;
1597     css::uno::Reference< css::container::XNameContainer > xContainer;
1598 
1599     m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1600     if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1601         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1602     else
1603     {
1604         css::uno::Reference< css::container::XNameAccess > xModules;
1605         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1606         if ( !xModules->hasByName(sModule) )
1607             return;
1608         xModules->getByName(sModule) >>= xContainer;
1609     }
1610 
1611     css::awt::KeyEvent aKeyEvent;
1612     ::rtl::OUString sKeyIdentifier;
1613 
1614     sal_Int32 nIndex = 0;
1615     sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1616     aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(::rtl::OUString::createFromAscii("KEY_")+sKeyIdentifier);
1617 
1618     css::uno::Sequence< ::rtl::OUString > sToken(3);
1619     const sal_Int32 nToken = 3;
1620     for (sal_Int32 i=0; i<nToken; ++i)
1621     {
1622         if ( nIndex < 0 )
1623             break;
1624 
1625         sToken[i] = sKey.getToken(0, '_', nIndex);
1626         if (sToken[i].equalsAscii("SHIFT"))
1627             aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1628         else if (sToken[i].equalsAscii("MOD1"))
1629             aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1630         else if (sToken[i].equalsAscii("MOD2"))
1631             aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1632                 else if (sToken[i].equalsAscii("MOD3"))
1633                         aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1634     }
1635 
1636     css::uno::Reference< css::container::XNameAccess > xKey;
1637     css::uno::Reference< css::container::XNameAccess > xCommand;
1638     ::rtl::OUString sCommand;
1639 
1640     if (xContainer->hasByName(sKey))
1641     {
1642         ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1643         xContainer->getByName(sKey)    >>= xKey;
1644         xKey->getByName(CFG_PROP_COMMAND)  >>= xCommand;
1645         xCommand->getByName(sLocale)       >>= sCommand;
1646     }
1647 
1648     if (sPrimarySecondary.equals(CFG_ENTRY_PRIMARY))
1649     {
1650         if (sCommand.getLength() ==0)
1651             m_aPrimaryReadCache.removeKey(aKeyEvent);
1652         else
1653             m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1654     }
1655     else if (sPrimarySecondary.equals(CFG_ENTRY_SECONDARY))
1656     {
1657         if (sCommand.getLength() ==0)
1658             m_aSecondaryReadCache.removeKey(aKeyEvent);
1659         else
1660             m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1661     }
1662 }
1663 
1664 //-----------------------------------------------
impl_getCFG(sal_Bool bPreferred,sal_Bool bWriteAccessRequested)1665 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bPreferred, sal_Bool bWriteAccessRequested)
1666 {
1667     // SAFE -> ----------------------------------
1668     WriteGuard aWriteLock(m_aLock);
1669 
1670     if (bPreferred)
1671     {
1672         //create copy of our readonly-cache, if write access is forced ... but
1673         //not still possible!
1674         if (
1675             (bWriteAccessRequested) &&
1676             (!m_pPrimaryWriteCache       )
1677             )
1678         {
1679             m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1680         }
1681 
1682         // in case, we have a writeable cache, we use it for reading too!
1683         // Otherwhise the API user cant find its own changes ...
1684         if (m_pPrimaryWriteCache)
1685             return *m_pPrimaryWriteCache;
1686         else
1687             return m_aPrimaryReadCache;
1688     }
1689 
1690     else
1691     {
1692         //create copy of our readonly-cache, if write access is forced ... but
1693         //not still possible!
1694         if (
1695             (bWriteAccessRequested) &&
1696             (!m_pSecondaryWriteCache       )
1697             )
1698         {
1699             m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1700         }
1701 
1702         // in case, we have a writeable cache, we use it for reading too!
1703         // Otherwhise the API user cant find its own changes ...
1704         if (m_pSecondaryWriteCache)
1705             return *m_pSecondaryWriteCache;
1706         else
1707             return m_aSecondaryReadCache;
1708     }
1709 
1710     // <- SAFE ----------------------------------
1711 }
1712 
1713 //-----------------------------------------------
impl_ts_getLocale() const1714 ::comphelper::Locale XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1715 {
1716     static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
1717     static ::rtl::OUString LOCALE_PATH    = ::rtl::OUString::createFromAscii("L10N"                 );
1718     static ::rtl::OUString LOCALE_KEY     = ::rtl::OUString::createFromAscii("ooLocale"             );
1719 
1720     // SAFE -> ----------------------------------
1721     ReadGuard aReadLock(m_aLock);
1722     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1723     aReadLock.unlock();
1724     // <- SAFE ----------------------------------
1725 
1726     css::uno::Reference< css::uno::XInterface >     xCFG      = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
1727     css::uno::Reference< css::beans::XPropertySet > xProp     (xCFG, css::uno::UNO_QUERY_THROW);
1728     ::rtl::OUString                                 sISOLocale;
1729     xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
1730 
1731     if (!sISOLocale.getLength())
1732         return ::comphelper::Locale::EN_US();
1733     return ::comphelper::Locale(sISOLocale);
1734 }
1735 
1736 } // namespace framework
1737