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 seems 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() automatically!
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     // Otherwise the API user can't 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 seems 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 isn't 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         // Otherwise the API user can't 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         // Otherwise the API user can't 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