1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/deployment/ExtensionManager.hpp>
22 #include <com/sun/star/registry/XRegistryKey.hpp>
23 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
24 #include <com/sun/star/container/XEnumeration.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
27 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
28 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
30 #include <tools/solar.h>
31 #include <unotools/lingucfg.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <i18npool/lang.h>
34 #include <i18npool/languagetag.hxx>
35 #include <cppuhelper/factory.hxx>
36 #include <comphelper/extract.hxx>
37 #include <rtl/logfile.hxx>
39 #include <boost/checked_delete.hpp>
41 #include "lngsvcmgr.hxx"
43 #include "linguistic/misc.hxx"
44 #include "spelldsp.hxx"
45 #include "hyphdsp.hxx"
46 #include "thesdsp.hxx"
47 #include "gciterator.hxx"
50 using namespace com::sun::star
;
51 using namespace linguistic
;
52 using ::rtl::OUString
;
54 // forward declarations
55 uno::Sequence
< OUString
> static GetLangSvcList( const uno::Any
&rVal
);
56 uno::Sequence
< OUString
> static GetLangSvc( const uno::Any
&rVal
);
59 static sal_Bool
lcl_SeqHasString( const uno::Sequence
< OUString
> &rSeq
, const OUString
&rText
)
61 sal_Bool bRes
= sal_False
;
63 sal_Int32 nLen
= rSeq
.getLength();
64 if (nLen
== 0 || rText
.isEmpty())
67 const OUString
*pSeq
= rSeq
.getConstArray();
68 for (sal_Int32 i
= 0; i
< nLen
&& !bRes
; ++i
)
77 static uno::Sequence
< lang::Locale
> GetAvailLocales(
78 const uno::Sequence
< OUString
> &rSvcImplNames
)
80 uno::Sequence
< lang::Locale
> aRes
;
82 uno::Reference
< lang::XMultiServiceFactory
> xFac( comphelper::getProcessServiceFactory() );
83 sal_Int32 nNames
= rSvcImplNames
.getLength();
84 if (nNames
&& xFac
.is())
86 std::set
< LanguageType
> aLanguages
;
88 //! since we're going to create one-instance services we have to
89 //! supply their arguments even if we would not need them here...
90 uno::Sequence
< uno::Any
> aArgs(2);
91 aArgs
.getArray()[0] <<= GetLinguProperties();
93 // check all services for the supported languages and new
94 // languages to the result
95 const OUString
*pImplNames
= rSvcImplNames
.getConstArray();
98 for (i
= 0; i
< nNames
; ++i
)
100 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc
;
103 xSuppLoc
= uno::Reference
< linguistic2::XSupportedLocales
>(
104 xFac
->createInstanceWithArguments( pImplNames
[i
], aArgs
), uno::UNO_QUERY
);
106 catch (uno::Exception
&)
108 DBG_ASSERT( 0, "createInstanceWithArguments failed" );
113 uno::Sequence
< lang::Locale
> aLoc( xSuppLoc
->getLocales() );
114 sal_Int32 nLoc
= aLoc
.getLength();
115 for (sal_Int32 k
= 0; k
< nLoc
; ++k
)
117 const lang::Locale
*pLoc
= aLoc
.getConstArray();
118 LanguageType nLang
= LinguLocaleToLanguage( pLoc
[k
] );
120 // language not already added?
121 if (aLanguages
.find( nLang
) == aLanguages
.end())
122 aLanguages
.insert( nLang
);
127 DBG_ASSERT( 0, "interface not supported by service" );
131 // build return sequence
132 sal_Int32 nLanguages
= static_cast< sal_Int32
>(aLanguages
.size());
133 aRes
.realloc( nLanguages
);
134 lang::Locale
*pRes
= aRes
.getArray();
135 std::set
< LanguageType
>::const_iterator
aIt( aLanguages
.begin() );
136 for (i
= 0; aIt
!= aLanguages
.end(); ++aIt
, ++i
)
138 LanguageType nLang
= *aIt
;
139 pRes
[i
] = LanguageTag( nLang
).getLocale();
149 const OUString aSvcImplName
;
150 const uno::Sequence
< sal_Int16
> aSuppLanguages
;
152 SvcInfo( const OUString
&rSvcImplName
,
153 const uno::Sequence
< sal_Int16
> &rSuppLanguages
) :
154 aSvcImplName (rSvcImplName
),
155 aSuppLanguages (rSuppLanguages
)
159 sal_Bool
HasLanguage( sal_Int16 nLanguage
) const;
163 sal_Bool
SvcInfo::HasLanguage( sal_Int16 nLanguage
) const
165 sal_Int32 nCnt
= aSuppLanguages
.getLength();
166 const sal_Int16
*pLang
= aSuppLanguages
.getConstArray();
169 for ( i
= 0; i
< nCnt
; ++i
)
171 if (nLanguage
== pLang
[i
])
177 class LngSvcMgrListenerHelper
:
178 public cppu::WeakImplHelper2
180 linguistic2::XLinguServiceEventListener
,
181 linguistic2::XDictionaryListEventListener
184 LngSvcMgr
&rMyManager
;
186 ::cppu::OInterfaceContainerHelper aLngSvcMgrListeners
;
187 ::cppu::OInterfaceContainerHelper aLngSvcEvtBroadcasters
;
188 uno::Reference
< linguistic2::XDictionaryList
> xDicList
;
190 sal_Int16 nCombinedLngSvcEvt
;
192 // disallow copy-constructor and assignment-operator for now
193 LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper
&);
194 LngSvcMgrListenerHelper
& operator = (const LngSvcMgrListenerHelper
&);
196 void LaunchEvent( sal_Int16 nLngSvcEvtFlags
);
201 LngSvcMgrListenerHelper( LngSvcMgr
&rLngSvcMgr
,
202 const uno::Reference
< linguistic2::XDictionaryList
> &rxDicList
);
204 // lang::XEventListener
205 virtual void SAL_CALL
206 disposing( const lang::EventObject
& rSource
)
207 throw(uno::RuntimeException
);
209 // linguistic2::XLinguServiceEventListener
210 virtual void SAL_CALL
211 processLinguServiceEvent( const linguistic2::LinguServiceEvent
& aLngSvcEvent
)
212 throw(uno::RuntimeException
);
214 // linguistic2::XDictionaryListEventListener
215 virtual void SAL_CALL
216 processDictionaryListEvent(
217 const linguistic2::DictionaryListEvent
& rDicListEvent
)
218 throw(uno::RuntimeException
);
220 inline sal_Bool
AddLngSvcMgrListener(
221 const uno::Reference
< lang::XEventListener
>& rxListener
);
222 inline sal_Bool
RemoveLngSvcMgrListener(
223 const uno::Reference
< lang::XEventListener
>& rxListener
);
224 void DisposeAndClear( const lang::EventObject
&rEvtObj
);
225 sal_Bool
AddLngSvcEvtBroadcaster(
226 const uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> &rxBroadcaster
);
227 sal_Bool
RemoveLngSvcEvtBroadcaster(
228 const uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> &rxBroadcaster
);
230 void AddLngSvcEvt( sal_Int16 nLngSvcEvt
);
234 LngSvcMgrListenerHelper::LngSvcMgrListenerHelper(
235 LngSvcMgr
&rLngSvcMgr
,
236 const uno::Reference
< linguistic2::XDictionaryList
> &rxDicList
) :
237 rMyManager ( rLngSvcMgr
),
238 aLngSvcMgrListeners ( GetLinguMutex() ),
239 aLngSvcEvtBroadcasters ( GetLinguMutex() ),
240 xDicList ( rxDicList
)
244 xDicList
->addDictionaryListEventListener(
245 (linguistic2::XDictionaryListEventListener
*) this, sal_False
);
248 nCombinedLngSvcEvt
= 0;
252 void SAL_CALL
LngSvcMgrListenerHelper::disposing( const lang::EventObject
& rSource
)
253 throw(uno::RuntimeException
)
255 osl::MutexGuard
aGuard( GetLinguMutex() );
257 uno::Reference
< uno::XInterface
> xRef( rSource
.Source
);
260 aLngSvcMgrListeners
.removeInterface( xRef
);
261 aLngSvcEvtBroadcasters
.removeInterface( xRef
);
262 if (xDicList
== xRef
)
267 long LngSvcMgrListenerHelper::Timeout()
269 osl::MutexGuard
aGuard( GetLinguMutex() );
272 // change event source to LinguServiceManager since the listeners
273 // probably do not know (and need not to know) about the specific
274 // SpellChecker's or Hyphenator's.
275 linguistic2::LinguServiceEvent
aEvtObj(
276 static_cast<com::sun::star::linguistic2::XLinguServiceManager
*>(&rMyManager
), nCombinedLngSvcEvt
);
277 nCombinedLngSvcEvt
= 0;
279 if (rMyManager
.pSpellDsp
)
280 rMyManager
.pSpellDsp
->FlushSpellCache();
282 // pass event on to linguistic2::XLinguServiceEventListener's
283 cppu::OInterfaceIteratorHelper
aIt( aLngSvcMgrListeners
);
284 while (aIt
.hasMoreElements())
286 uno::Reference
< linguistic2::XLinguServiceEventListener
> xRef( aIt
.next(), uno::UNO_QUERY
);
288 xRef
->processLinguServiceEvent( aEvtObj
);
295 void LngSvcMgrListenerHelper::AddLngSvcEvt( sal_Int16 nLngSvcEvt
)
297 nCombinedLngSvcEvt
|= nLngSvcEvt
;
303 LngSvcMgrListenerHelper::processLinguServiceEvent(
304 const linguistic2::LinguServiceEvent
& rLngSvcEvent
)
305 throw(uno::RuntimeException
)
307 osl::MutexGuard
aGuard( GetLinguMutex() );
308 AddLngSvcEvt( rLngSvcEvent
.nEvent
);
313 LngSvcMgrListenerHelper::processDictionaryListEvent(
314 const linguistic2::DictionaryListEvent
& rDicListEvent
)
315 throw(uno::RuntimeException
)
317 osl::MutexGuard
aGuard( GetLinguMutex() );
319 sal_Int16 nDlEvt
= rDicListEvent
.nCondensedEvent
;
323 // we do keep the original event source here though...
325 // pass event on to linguistic2::XDictionaryListEventListener's
326 cppu::OInterfaceIteratorHelper
aIt( aLngSvcMgrListeners
);
327 while (aIt
.hasMoreElements())
329 uno::Reference
< linguistic2::XDictionaryListEventListener
> xRef( aIt
.next(), uno::UNO_QUERY
);
331 xRef
->processDictionaryListEvent( rDicListEvent
);
334 // "translate" DictionaryList event into linguistic2::LinguServiceEvent
335 sal_Int16 nLngSvcEvt
= 0;
336 sal_Int16 nSpellCorrectFlags
=
337 linguistic2::DictionaryListEventFlags::ADD_NEG_ENTRY
|
338 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY
|
339 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC
|
340 linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC
;
341 if (0 != (nDlEvt
& nSpellCorrectFlags
))
342 nLngSvcEvt
|= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN
;
344 sal_Int16 nSpellWrongFlags
=
345 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY
|
346 linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY
|
347 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC
|
348 linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC
;
349 if (0 != (nDlEvt
& nSpellWrongFlags
))
350 nLngSvcEvt
|= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN
;
352 sal_Int16 nHyphenateFlags
=
353 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY
|
354 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY
|
355 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC
|
356 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC
;
357 if (0 != (nDlEvt
& nHyphenateFlags
))
358 nLngSvcEvt
|= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN
;
360 if (rMyManager
.pSpellDsp
)
361 rMyManager
.pSpellDsp
->FlushSpellCache();
363 LaunchEvent( nLngSvcEvt
);
367 void LngSvcMgrListenerHelper::LaunchEvent( sal_Int16 nLngSvcEvtFlags
)
369 linguistic2::LinguServiceEvent
aEvt(
370 static_cast<com::sun::star::linguistic2::XLinguServiceManager
*>(&rMyManager
), nLngSvcEvtFlags
);
372 // pass event on to linguistic2::XLinguServiceEventListener's
373 cppu::OInterfaceIteratorHelper
aIt( aLngSvcMgrListeners
);
374 while (aIt
.hasMoreElements())
376 uno::Reference
< linguistic2::XLinguServiceEventListener
> xRef( aIt
.next(), uno::UNO_QUERY
);
378 xRef
->processLinguServiceEvent( aEvt
);
383 inline sal_Bool
LngSvcMgrListenerHelper::AddLngSvcMgrListener(
384 const uno::Reference
< lang::XEventListener
>& rxListener
)
386 aLngSvcMgrListeners
.addInterface( rxListener
);
391 inline sal_Bool
LngSvcMgrListenerHelper::RemoveLngSvcMgrListener(
392 const uno::Reference
< lang::XEventListener
>& rxListener
)
394 aLngSvcMgrListeners
.removeInterface( rxListener
);
399 void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject
&rEvtObj
)
401 // call "disposing" for all listeners and clear list
402 aLngSvcMgrListeners
.disposeAndClear( rEvtObj
);
404 // remove references to this object hold by the broadcasters
405 cppu::OInterfaceIteratorHelper
aIt( aLngSvcEvtBroadcasters
);
406 while (aIt
.hasMoreElements())
408 uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> xRef( aIt
.next(), uno::UNO_QUERY
);
410 RemoveLngSvcEvtBroadcaster( xRef
);
413 // remove refernce to this object hold by the dictionary-list
416 xDicList
->removeDictionaryListEventListener(
417 (linguistic2::XDictionaryListEventListener
*) this );
423 sal_Bool
LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster(
424 const uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> &rxBroadcaster
)
426 sal_Bool bRes
= sal_False
;
427 if (rxBroadcaster
.is())
429 aLngSvcEvtBroadcasters
.addInterface( rxBroadcaster
);
430 rxBroadcaster
->addLinguServiceEventListener(
431 (linguistic2::XLinguServiceEventListener
*) this );
437 sal_Bool
LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster(
438 const uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> &rxBroadcaster
)
440 sal_Bool bRes
= sal_False
;
441 if (rxBroadcaster
.is())
443 aLngSvcEvtBroadcasters
.removeInterface( rxBroadcaster
);
444 rxBroadcaster
->removeLinguServiceEventListener(
445 (linguistic2::XLinguServiceEventListener
*) this );
453 LngSvcMgr::LngSvcMgr()
454 : utl::ConfigItem("Office.Linguistic")
455 , aEvtListeners(GetLinguMutex())
457 bDisposing
= sal_False
;
465 pAvailGrammarSvcs
= 0;
470 // request notify events when properties (i.e. something in the subtree) changes
471 uno::Sequence
< OUString
> aNames(4);
472 OUString
*pNames
= aNames
.getArray();
473 pNames
[0] = "ServiceManager/SpellCheckerList";
474 pNames
[1] = "ServiceManager/GrammarCheckerList";
475 pNames
[2] = "ServiceManager/HyphenatorList";
476 pNames
[3] = "ServiceManager/ThesaurusList";
477 EnableNotification( aNames
);
481 aUpdateTimer
.SetTimeout(500);
482 aUpdateTimer
.SetTimeoutHdl(LINK(this, LngSvcMgr
, updateAndBroadcast
));
484 // request to be notified if an extension has been added/removed
485 uno::Reference
<uno::XComponentContext
> xContext(comphelper::getProcessComponentContext());
487 uno::Reference
<deployment::XExtensionManager
> xExtensionManager
;
489 xExtensionManager
= deployment::ExtensionManager::get(xContext
);
490 } catch ( const uno::DeploymentException
& ) {
491 SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
492 } catch ( const deployment::DeploymentException
& ) {
493 SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
495 if (xExtensionManager
.is())
497 xMB
= uno::Reference
<util::XModifyBroadcaster
>(xExtensionManager
, uno::UNO_QUERY_THROW
);
499 uno::Reference
<util::XModifyListener
> xListener(this);
500 xMB
->addModifyListener( xListener
);
504 // ::com::sun::star::util::XModifyListener
505 void LngSvcMgr::modified(const lang::EventObject
&)
506 throw(uno::RuntimeException
)
508 osl::MutexGuard
aGuard(GetLinguMutex());
509 //assume that if an extension has been added/removed that
510 //it might be a dictionary extension, so drop our cache
512 clearSvcInfoArray(pAvailSpellSvcs
);
513 clearSvcInfoArray(pAvailGrammarSvcs
);
514 clearSvcInfoArray(pAvailHyphSvcs
);
515 clearSvcInfoArray(pAvailThesSvcs
);
517 //schedule in an update to execute in the main thread
518 aUpdateTimer
.Start();
521 //run update, and inform everyone that dictionaries (may) have changed, this
522 //needs to be run in the main thread because
523 //utl::ConfigChangeListener_Impl::changesOccurred grabs the SolarMutex and we
524 //get notified that an extension was added from an extension manager thread
525 IMPL_LINK_NOARG(LngSvcMgr
, updateAndBroadcast
)
527 osl::MutexGuard
aGuard( GetLinguMutex() );
533 pListenerHelper
->AddLngSvcEvt(
534 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN
|
535 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN
|
536 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN
|
537 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN
);
543 void LngSvcMgr::stopListening()
545 osl::MutexGuard
aGuard(GetLinguMutex());
551 uno::Reference
<util::XModifyListener
> xListener(this);
552 xMB
->removeModifyListener(xListener
);
554 catch (const uno::Exception
&)
562 void LngSvcMgr::disposing(const lang::EventObject
&)
563 throw (uno::RuntimeException
)
568 void LngSvcMgr::clearSvcInfoArray(SvcInfoArray
* &rpInfo
)
574 LngSvcMgr::~LngSvcMgr()
578 // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper
579 // will be freed in the destructor of the respective Reference's
580 // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp
582 clearSvcInfoArray(pAvailSpellSvcs
);
583 clearSvcInfoArray(pAvailGrammarSvcs
);
584 clearSvcInfoArray(pAvailHyphSvcs
);
585 clearSvcInfoArray(pAvailThesSvcs
);
594 sal_Bool
lcl_FindEntry( const OUString
&rEntry
, const Sequence
< OUString
> &rCfgSvcs
)
597 sal_Int32 nEntries
= rCfgSvcs
.getLength();
598 const OUString
*pEntry
= rCfgSvcs
.getConstArray();
599 for (sal_Int32 i
= 0; i
< nEntries
&& nRes
== -1; ++i
)
601 if (rEntry
== pEntry
[i
])
607 Sequence
< OUString
> lcl_GetLastFoundSvcs(
608 SvtLinguConfig
&rCfg
,
609 const OUString
&rLastFoundList
,
610 const Locale
&rAvailLocale
)
612 Sequence
< OUString
> aRes
;
614 OUString
aCfgLocaleStr( LanguageTag( rAvailLocale
).getBcp47() );
616 Sequence
< OUString
> aNodeNames( rCfg
.GetNodeNames(rLastFoundList
) );
617 sal_Bool bFound
= lcl_FindEntry( aCfgLocaleStr
, aNodeNames
);
621 Sequence
< OUString
> aNames(1);
622 OUString
&rNodeName
= aNames
.getArray()[0];
623 rNodeName
= rLastFoundList
;
624 rNodeName
+= OUString::valueOf( (sal_Unicode
)'/' );
625 rNodeName
+= aCfgLocaleStr
;
626 Sequence
< Any
> aValues( rCfg
.GetProperties( aNames
) );
627 if (aValues
.getLength())
629 OSL_ENSURE( aValues
.getLength() == 1, "unexpected length of sequence" );
630 Sequence
< OUString
> aSvcImplNames
;
631 if (aValues
.getConstArray()[0] >>= aSvcImplNames
)
632 aRes
= aSvcImplNames
;
635 OSL_FAIL( "type mismatch" );
643 Sequence
< OUString
> lcl_RemoveMissingEntries(
644 const Sequence
< OUString
> &rCfgSvcs
,
645 const Sequence
< OUString
> &rAvailSvcs
)
647 Sequence
< OUString
> aRes( rCfgSvcs
.getLength() );
648 OUString
*pRes
= aRes
.getArray();
651 sal_Int32 nEntries
= rCfgSvcs
.getLength();
652 const OUString
*pEntry
= rCfgSvcs
.getConstArray();
653 for (sal_Int32 i
= 0; i
< nEntries
; ++i
)
655 if (!pEntry
[i
].isEmpty() && lcl_FindEntry( pEntry
[i
], rAvailSvcs
))
656 pRes
[ nCnt
++ ] = pEntry
[i
];
659 aRes
.realloc( nCnt
);
663 Sequence
< OUString
> lcl_GetNewEntries(
664 const Sequence
< OUString
> &rLastFoundSvcs
,
665 const Sequence
< OUString
> &rAvailSvcs
)
667 sal_Int32 nLen
= rAvailSvcs
.getLength();
668 Sequence
< OUString
> aRes( nLen
);
669 OUString
*pRes
= aRes
.getArray();
672 const OUString
*pEntry
= rAvailSvcs
.getConstArray();
673 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
675 if (!pEntry
[i
].isEmpty() && !lcl_FindEntry( pEntry
[i
], rLastFoundSvcs
))
676 pRes
[ nCnt
++ ] = pEntry
[i
];
679 aRes
.realloc( nCnt
);
683 Sequence
< OUString
> lcl_MergeSeq(
684 const Sequence
< OUString
> &rCfgSvcs
,
685 const Sequence
< OUString
> &rNewSvcs
)
687 Sequence
< OUString
> aRes( rCfgSvcs
.getLength() + rNewSvcs
.getLength() );
688 OUString
*pRes
= aRes
.getArray();
691 for (sal_Int32 k
= 0; k
< 2; ++k
)
693 // add previously configuerd service first and append
694 // new found services at the end
695 const Sequence
< OUString
> &rSeq
= k
== 0 ? rCfgSvcs
: rNewSvcs
;
697 sal_Int32 nLen
= rSeq
.getLength();
698 const OUString
*pEntry
= rSeq
.getConstArray();
699 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
701 if (!pEntry
[i
].isEmpty() && !lcl_FindEntry( pEntry
[i
], aRes
))
702 pRes
[ nCnt
++ ] = pEntry
[i
];
706 aRes
.realloc( nCnt
);
711 void LngSvcMgr::UpdateAll()
713 using beans::PropertyValue
;
717 typedef OUString OUstring_t
;
718 typedef Sequence
< OUString
> Sequence_OUString_t
;
719 typedef std::map
< OUstring_t
, Sequence_OUString_t
> list_entry_map_t
;
723 const int nNumServices
= 4;
724 const sal_Char
* apServices
[nNumServices
] = { SN_SPELLCHECKER
, SN_GRAMMARCHECKER
, SN_HYPHENATOR
, SN_THESAURUS
};
725 const sal_Char
* apCurLists
[nNumServices
] = { "ServiceManager/SpellCheckerList", "ServiceManager/GrammarCheckerList", "ServiceManager/HyphenatorList", "ServiceManager/ThesaurusList" };
726 const sal_Char
* apLastFoundLists
[nNumServices
] = { "ServiceManager/LastFoundSpellCheckers", "ServiceManager/LastFoundGrammarCheckers", "ServiceManager/LastFoundHyphenators", "ServiceManager/LastFoundThesauri" };
728 // usage of indices as above: 0 = spell checker, 1 = grammar checker, 2 = hyphenator, 3 = thesaurus
729 std::vector
< list_entry_map_t
> aLastFoundSvcs(nNumServices
);
730 std::vector
< list_entry_map_t
> aCurSvcs(nNumServices
);
732 for (int k
= 0; k
< nNumServices
; ++k
)
734 OUString
aService( ::rtl::OUString::createFromAscii( apServices
[k
] ) );
735 OUString
aActiveList( ::rtl::OUString::createFromAscii( apCurLists
[k
] ) );
736 OUString
aLastFoundList( ::rtl::OUString::createFromAscii( apLastFoundLists
[k
] ) );
740 // remove configured but not available language/services entries
742 Sequence
< OUString
> aNodeNames( aCfg
.GetNodeNames( aActiveList
) ); // list of configured locales
743 sal_Int32 nNodeNames
= aNodeNames
.getLength();
744 const OUString
*pNodeName
= aNodeNames
.getConstArray();
745 for (i
= 0; i
< nNodeNames
; ++i
)
747 Locale
aLocale( (LanguageTag(pNodeName
[i
])).getLocale() );
748 Sequence
< OUString
> aCfgSvcs( getConfiguredServices( aService
, aLocale
));
749 Sequence
< OUString
> aAvailSvcs( getAvailableServices( aService
, aLocale
));
751 aCfgSvcs
= lcl_RemoveMissingEntries( aCfgSvcs
, aAvailSvcs
);
753 aCurSvcs
[k
][ pNodeName
[i
] ] = aCfgSvcs
;
757 // add new available language/service entries
759 // set last found services to currently available ones
761 Sequence
< Locale
> aAvailLocales( getAvailableLocales(aService
) );
762 sal_Int32 nAvailLocales
= aAvailLocales
.getLength();
763 const Locale
*pAvailLocale
= aAvailLocales
.getConstArray();
764 for (i
= 0; i
< nAvailLocales
; ++i
)
766 OUString
aCfgLocaleStr( (LanguageTag(pAvailLocale
[i
])).getBcp47() );
768 Sequence
< OUString
> aAvailSvcs( getAvailableServices( aService
, pAvailLocale
[i
] ));
770 aLastFoundSvcs
[k
][ aCfgLocaleStr
] = aAvailSvcs
;
772 Sequence
< OUString
> aLastSvcs(
773 lcl_GetLastFoundSvcs( aCfg
, aLastFoundList
, pAvailLocale
[i
] ));
774 Sequence
< OUString
> aNewSvcs
=
775 lcl_GetNewEntries( aLastSvcs
, aAvailSvcs
);
777 Sequence
< OUString
> aCfgSvcs( aCurSvcs
[k
][ aCfgLocaleStr
] );
779 // merge services list (previously configured to be listed first).
780 aCfgSvcs
= lcl_MergeSeq( aCfgSvcs
, aNewSvcs
);
782 aCurSvcs
[k
][ aCfgLocaleStr
] = aCfgSvcs
;
787 // write new data back to configuration
789 for (int k
= 0; k
< nNumServices
; ++k
)
791 for (int i
= 0; i
< 2; ++i
)
793 const sal_Char
*pSubNodeName
= (i
== 0) ? apCurLists
[k
] : apLastFoundLists
[k
];
794 OUString
aSubNodeName( ::rtl::OUString::createFromAscii(pSubNodeName
) );
796 list_entry_map_t
&rCurMap
= (i
== 0) ? aCurSvcs
[k
] : aLastFoundSvcs
[k
];
797 list_entry_map_t::const_iterator
aIt( rCurMap
.begin() );
798 sal_Int32 nVals
= static_cast< sal_Int32
>( rCurMap
.size() );
799 Sequence
< PropertyValue
> aNewValues( nVals
);
800 PropertyValue
*pNewValue
= aNewValues
.getArray();
801 while (aIt
!= rCurMap
.end())
803 OUString
aCfgEntryName( aSubNodeName
);
804 aCfgEntryName
+= OUString::valueOf( (sal_Unicode
) '/' );
805 aCfgEntryName
+= (*aIt
).first
;
807 pNewValue
->Name
= aCfgEntryName
;
808 pNewValue
->Value
<<= (*aIt
).second
;
812 OSL_ENSURE( pNewValue
- aNewValues
.getArray() == nVals
,
813 "possible mismatch of sequence size and property number" );
816 // add new or replace existing entries.
817 sal_Bool bRes
= aCfg
.ReplaceSetProperties( aSubNodeName
, aNewValues
);
820 #if OSL_DEBUG_LEVEL > 1
821 OSL_FAIL( "failed to set new configuration values" );
828 //The new settings in the configuration get applied ! because we are
829 //listening to the configuration for changes of the relevant ! properties
830 //and Notify applies the new settings.
833 void LngSvcMgr::Notify( const uno::Sequence
< OUString
> &rPropertyNames
)
835 const OUString
aSpellCheckerList( "ServiceManager/SpellCheckerList" );
836 const OUString
aGrammarCheckerList( "ServiceManager/GrammarCheckerList" );
837 const OUString
aHyphenatorList( "ServiceManager/HyphenatorList" );
838 const OUString
aThesaurusList( "ServiceManager/ThesaurusList" );
840 const uno::Sequence
< OUString
> aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList
) );
841 const uno::Sequence
< OUString
> aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList
) );
842 const uno::Sequence
< OUString
> aHyphenatorListEntries( GetNodeNames( aHyphenatorList
) );
843 const uno::Sequence
< OUString
> aThesaurusListEntries( GetNodeNames( aThesaurusList
) );
845 uno::Sequence
< uno::Any
> aValues
;
846 uno::Sequence
< OUString
> aNames( 1 );
847 OUString
*pNames
= aNames
.getArray();
849 sal_Int32 nLen
= rPropertyNames
.getLength();
850 const OUString
*pPropertyNames
= rPropertyNames
.getConstArray();
851 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
853 // property names look like
854 // "ServiceManager/ThesaurusList/de-CH"
856 const OUString
&rName
= pPropertyNames
[i
];
858 nKeyStart
= rName
.lastIndexOf( '/' );
861 aKeyText
= rName
.copy( nKeyStart
+ 1 );
862 DBG_ASSERT( !aKeyText
.isEmpty(), "unexpected key (lang::Locale) string" );
863 if (0 == rName
.compareTo( aSpellCheckerList
, aSpellCheckerList
.getLength() ))
865 // delete old cached data, needs to be acquired new on demand
866 clearSvcInfoArray(pAvailSpellSvcs
);
868 OUString
aNode( aSpellCheckerList
);
869 if (lcl_SeqHasString( aSpellCheckerListEntries
, aKeyText
))
871 OUString
aPropName( aNode
);
872 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
873 aPropName
+= aKeyText
;
874 pNames
[0] = aPropName
;
875 aValues
= /*aCfg.*/GetProperties( aNames
);
876 uno::Sequence
< OUString
> aSvcImplNames
;
877 if (aValues
.getLength())
878 aSvcImplNames
= GetLangSvcList( aValues
.getConstArray()[0] );
880 LanguageType nLang
= LANGUAGE_NONE
;
881 if (!aKeyText
.isEmpty())
882 nLang
= LanguageTag( aKeyText
).getLanguageType();
884 GetSpellCheckerDsp_Impl( sal_False
); // don't set service list, it will be done below
885 pSpellDsp
->SetServiceList( LanguageTag(nLang
).getLocale(), aSvcImplNames
);
888 else if (0 == rName
.compareTo( aGrammarCheckerList
, aGrammarCheckerList
.getLength() ))
890 // delete old cached data, needs to be acquired new on demand
891 clearSvcInfoArray(pAvailGrammarSvcs
);
893 OUString
aNode( aGrammarCheckerList
);
894 if (lcl_SeqHasString( aGrammarCheckerListEntries
, aKeyText
))
896 OUString
aPropName( aNode
);
897 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
898 aPropName
+= aKeyText
;
899 pNames
[0] = aPropName
;
900 aValues
= /*aCfg.*/GetProperties( aNames
);
901 uno::Sequence
< OUString
> aSvcImplNames
;
902 if (aValues
.getLength())
903 aSvcImplNames
= GetLangSvc( aValues
.getConstArray()[0] );
905 LanguageType nLang
= LANGUAGE_NONE
;
906 if (!aKeyText
.isEmpty())
907 nLang
= LanguageTag( aKeyText
).getLanguageType();
909 if (SvtLinguConfig().HasGrammarChecker())
911 GetGrammarCheckerDsp_Impl( sal_False
); // don't set service list, it will be done below
912 pGrammarDsp
->SetServiceList( LanguageTag(nLang
).getLocale(), aSvcImplNames
);
916 else if (0 == rName
.compareTo( aHyphenatorList
, aHyphenatorList
.getLength() ))
918 // delete old cached data, needs to be acquired new on demand
919 clearSvcInfoArray(pAvailHyphSvcs
);
921 OUString
aNode( aHyphenatorList
);
922 if (lcl_SeqHasString( aHyphenatorListEntries
, aKeyText
))
924 OUString
aPropName( aNode
);
925 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
926 aPropName
+= aKeyText
;
927 pNames
[0] = aPropName
;
928 aValues
= /*aCfg.*/GetProperties( aNames
);
929 uno::Sequence
< OUString
> aSvcImplNames
;
930 if (aValues
.getLength())
931 aSvcImplNames
= GetLangSvc( aValues
.getConstArray()[0] );
933 LanguageType nLang
= LANGUAGE_NONE
;
934 if (!aKeyText
.isEmpty())
935 nLang
= LanguageTag( aKeyText
).getLanguageType();
937 GetHyphenatorDsp_Impl( sal_False
); // don't set service list, it will be done below
938 pHyphDsp
->SetServiceList( LanguageTag(nLang
).getLocale(), aSvcImplNames
);
941 else if (0 == rName
.compareTo( aThesaurusList
, aThesaurusList
.getLength() ))
943 // delete old cached data, needs to be acquired new on demand
944 clearSvcInfoArray(pAvailThesSvcs
);
946 OUString
aNode( aThesaurusList
);
947 if (lcl_SeqHasString( aThesaurusListEntries
, aKeyText
))
949 OUString
aPropName( aNode
);
950 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
951 aPropName
+= aKeyText
;
952 pNames
[0] = aPropName
;
953 aValues
= /*aCfg.*/GetProperties( aNames
);
954 uno::Sequence
< OUString
> aSvcImplNames
;
955 if (aValues
.getLength())
956 aSvcImplNames
= GetLangSvcList( aValues
.getConstArray()[0] );
958 LanguageType nLang
= LANGUAGE_NONE
;
959 if (!aKeyText
.isEmpty())
960 nLang
= LanguageTag( aKeyText
).getLanguageType();
962 GetThesaurusDsp_Impl( sal_False
); // don't set service list, it will be done below
963 pThesDsp
->SetServiceList( LanguageTag(nLang
).getLocale(), aSvcImplNames
);
968 DBG_ASSERT( 0, "nofified for unexpected property" );
974 void LngSvcMgr::Commit()
976 // everything necessary should have already been done by 'SaveCfgSvcs'
977 // called from within 'setConfiguredServices'.
978 // Also this class usually exits only when the Office i sbeing shutdown.
982 void LngSvcMgr::GetListenerHelper_Impl()
984 if (!pListenerHelper
)
986 pListenerHelper
= new LngSvcMgrListenerHelper( *this, linguistic::GetDictionaryList() );
987 xListenerHelper
= (linguistic2::XLinguServiceEventListener
*) pListenerHelper
;
992 void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList
)
996 pSpellDsp
= new SpellCheckerDispatcher( *this );
997 xSpellDsp
= pSpellDsp
;
999 SetCfgServiceLists( *pSpellDsp
);
1004 void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList
)
1006 if (!pGrammarDsp
&& SvtLinguConfig().HasGrammarChecker())
1008 //! since the grammar checking iterator needs to be a one instance service
1009 //! we need to create it the correct way!
1010 uno::Reference
< linguistic2::XProofreadingIterator
> xGCI
;
1013 uno::Reference
< lang::XMultiServiceFactory
> xMgr(
1014 comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
1015 xGCI
= uno::Reference
< linguistic2::XProofreadingIterator
>(
1016 xMgr
->createInstance( SN_GRAMMARCHECKINGITERATOR
), uno::UNO_QUERY_THROW
);
1018 catch (uno::Exception
&)
1021 DBG_ASSERT( xGCI
.is(), "instantiating grammar checking iterator failed" );
1025 pGrammarDsp
= dynamic_cast< GrammarCheckingIterator
* >(xGCI
.get());
1027 DBG_ASSERT( pGrammarDsp
, "failed to get implementation" );
1029 SetCfgServiceLists( *pGrammarDsp
);
1035 void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList
)
1039 pHyphDsp
= new HyphenatorDispatcher( *this );
1040 xHyphDsp
= pHyphDsp
;
1042 SetCfgServiceLists( *pHyphDsp
);
1047 void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList
)
1051 pThesDsp
= new ThesaurusDispatcher
;
1052 xThesDsp
= pThesDsp
;
1054 SetCfgServiceLists( *pThesDsp
);
1059 void LngSvcMgr::GetAvailableSpellSvcs_Impl()
1061 if (!pAvailSpellSvcs
)
1063 pAvailSpellSvcs
= new SvcInfoArray
;
1065 uno::Reference
< lang::XMultiServiceFactory
> xFac( comphelper::getProcessServiceFactory() );
1068 uno::Reference
< container::XContentEnumerationAccess
> xEnumAccess( xFac
, uno::UNO_QUERY
);
1069 uno::Reference
< container::XEnumeration
> xEnum
;
1070 if (xEnumAccess
.is())
1071 xEnum
= xEnumAccess
->createContentEnumeration( SN_SPELLCHECKER
);
1075 while (xEnum
->hasMoreElements())
1077 uno::Any aCurrent
= xEnum
->nextElement();
1078 uno::Reference
< lang::XSingleComponentFactory
> xCompFactory
;
1079 uno::Reference
< lang::XSingleServiceFactory
> xFactory
;
1081 uno::Reference
< linguistic2::XSpellChecker
> xSvc
;
1082 if ( cppu::extractInterface( xCompFactory
, aCurrent
) || ::cppu::extractInterface( xFactory
, aCurrent
) )
1086 uno::Reference
< uno::XComponentContext
> xContext(
1087 comphelper::getComponentContext( xFac
) );
1088 xSvc
= uno::Reference
< linguistic2::XSpellChecker
>( ( xCompFactory
.is() ? xCompFactory
->createInstanceWithContext( xContext
) : xFactory
->createInstance() ), uno::UNO_QUERY
);
1090 catch (const uno::Exception
&)
1092 DBG_ASSERT( 0, "createInstance failed" );
1099 uno::Sequence
< sal_Int16
> aLanguages
;
1100 uno::Reference
< XServiceInfo
> xInfo( xSvc
, uno::UNO_QUERY
);
1102 aImplName
= xInfo
->getImplementationName();
1103 DBG_ASSERT( !aImplName
.isEmpty(),
1104 "empty implementation name" );
1105 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc( xSvc
, uno::UNO_QUERY
);
1106 DBG_ASSERT( xSuppLoc
.is(), "interfaces not supported" );
1107 if (xSuppLoc
.is()) {
1108 uno::Sequence
<lang::Locale
> aLocaleSequence(xSuppLoc
->getLocales());
1109 aLanguages
= LocaleSeqToLangSeq( aLocaleSequence
);
1112 pAvailSpellSvcs
->push_back( new SvcInfo( aImplName
, aLanguages
) );
1121 void LngSvcMgr::GetAvailableGrammarSvcs_Impl()
1123 if (!pAvailGrammarSvcs
)
1125 pAvailGrammarSvcs
= new SvcInfoArray
;
1127 uno::Reference
< lang::XMultiServiceFactory
> xFac( comphelper::getProcessServiceFactory() );
1130 uno::Reference
< container::XContentEnumerationAccess
> xEnumAccess( xFac
, uno::UNO_QUERY
);
1131 uno::Reference
< container::XEnumeration
> xEnum
;
1132 if (xEnumAccess
.is())
1133 xEnum
= xEnumAccess
->createContentEnumeration( SN_GRAMMARCHECKER
);
1137 while (xEnum
->hasMoreElements())
1139 uno::Any aCurrent
= xEnum
->nextElement();
1140 uno::Reference
< lang::XSingleComponentFactory
> xCompFactory
;
1141 uno::Reference
< lang::XSingleServiceFactory
> xFactory
;
1143 uno::Reference
< linguistic2::XProofreader
> xSvc
;
1144 if ( cppu::extractInterface( xCompFactory
, aCurrent
) || ::cppu::extractInterface( xFactory
, aCurrent
) )
1148 uno::Reference
< uno::XComponentContext
> xContext(
1149 comphelper::getComponentContext( xFac
) );
1150 xSvc
= uno::Reference
< linguistic2::XProofreader
>( ( xCompFactory
.is() ? xCompFactory
->createInstanceWithContext( xContext
) : xFactory
->createInstance() ), uno::UNO_QUERY
);
1152 catch (const uno::Exception
&)
1154 DBG_ASSERT( 0, "createInstance failed" );
1161 uno::Sequence
< sal_Int16
> aLanguages
;
1162 uno::Reference
< XServiceInfo
> xInfo( xSvc
, uno::UNO_QUERY
);
1164 aImplName
= xInfo
->getImplementationName();
1165 DBG_ASSERT( !aImplName
.isEmpty(),
1166 "empty implementation name" );
1167 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc( xSvc
, uno::UNO_QUERY
);
1168 DBG_ASSERT( xSuppLoc
.is(), "interfaces not supported" );
1169 if (xSuppLoc
.is()) {
1170 uno::Sequence
<lang::Locale
> aLocaleSequence(xSuppLoc
->getLocales());
1171 aLanguages
= LocaleSeqToLangSeq( aLocaleSequence
);
1174 pAvailGrammarSvcs
->push_back( new SvcInfo( aImplName
, aLanguages
) );
1183 void LngSvcMgr::GetAvailableHyphSvcs_Impl()
1185 if (!pAvailHyphSvcs
)
1187 pAvailHyphSvcs
= new SvcInfoArray
;
1188 uno::Reference
< lang::XMultiServiceFactory
> xFac( comphelper::getProcessServiceFactory() );
1191 uno::Reference
< container::XContentEnumerationAccess
> xEnumAccess( xFac
, uno::UNO_QUERY
);
1192 uno::Reference
< container::XEnumeration
> xEnum
;
1193 if (xEnumAccess
.is())
1194 xEnum
= xEnumAccess
->createContentEnumeration( SN_HYPHENATOR
);
1198 while (xEnum
->hasMoreElements())
1200 uno::Any aCurrent
= xEnum
->nextElement();
1201 uno::Reference
< lang::XSingleComponentFactory
> xCompFactory
;
1202 uno::Reference
< lang::XSingleServiceFactory
> xFactory
;
1204 uno::Reference
< linguistic2::XHyphenator
> xSvc
;
1205 if ( cppu::extractInterface( xCompFactory
, aCurrent
) || ::cppu::extractInterface( xFactory
, aCurrent
) )
1209 uno::Reference
< uno::XComponentContext
> xContext(
1210 comphelper::getComponentContext( xFac
) );
1211 xSvc
= uno::Reference
< linguistic2::XHyphenator
>( ( xCompFactory
.is() ? xCompFactory
->createInstanceWithContext( xContext
) : xFactory
->createInstance() ), uno::UNO_QUERY
);
1214 catch (const uno::Exception
&)
1216 DBG_ASSERT( 0, "createInstance failed" );
1223 uno::Sequence
< sal_Int16
> aLanguages
;
1224 uno::Reference
< XServiceInfo
> xInfo( xSvc
, uno::UNO_QUERY
);
1226 aImplName
= xInfo
->getImplementationName();
1227 DBG_ASSERT( !aImplName
.isEmpty(),
1228 "empty implementation name" );
1229 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc( xSvc
, uno::UNO_QUERY
);
1230 DBG_ASSERT( xSuppLoc
.is(), "interfaces not supported" );
1231 if (xSuppLoc
.is()) {
1232 uno::Sequence
<lang::Locale
> aLocaleSequence(xSuppLoc
->getLocales());
1233 aLanguages
= LocaleSeqToLangSeq( aLocaleSequence
);
1236 pAvailHyphSvcs
->push_back( new SvcInfo( aImplName
, aLanguages
) );
1245 void LngSvcMgr::GetAvailableThesSvcs_Impl()
1247 if (!pAvailThesSvcs
)
1249 pAvailThesSvcs
= new SvcInfoArray
;
1251 uno::Reference
< lang::XMultiServiceFactory
> xFac( comphelper::getProcessServiceFactory() );
1254 uno::Reference
< container::XContentEnumerationAccess
> xEnumAccess( xFac
, uno::UNO_QUERY
);
1255 uno::Reference
< container::XEnumeration
> xEnum
;
1256 if (xEnumAccess
.is())
1257 xEnum
= xEnumAccess
->createContentEnumeration( SN_THESAURUS
);
1261 while (xEnum
->hasMoreElements())
1263 uno::Any aCurrent
= xEnum
->nextElement();
1265 uno::Reference
< lang::XSingleComponentFactory
> xCompFactory
;
1266 uno::Reference
< lang::XSingleServiceFactory
> xFactory
;
1268 uno::Reference
< linguistic2::XThesaurus
> xSvc
;
1269 if ( cppu::extractInterface( xCompFactory
, aCurrent
) || ::cppu::extractInterface( xFactory
, aCurrent
) )
1273 uno::Reference
< uno::XComponentContext
> xContext(
1274 comphelper::getComponentContext( xFac
) );
1275 xSvc
= uno::Reference
< linguistic2::XThesaurus
>( ( xCompFactory
.is() ? xCompFactory
->createInstanceWithContext( xContext
) : xFactory
->createInstance() ), uno::UNO_QUERY
);
1277 catch (const uno::Exception
&)
1279 DBG_ASSERT( 0, "createInstance failed" );
1286 uno::Sequence
< sal_Int16
> aLanguages
;
1287 uno::Reference
< XServiceInfo
> xInfo( xSvc
, uno::UNO_QUERY
);
1289 aImplName
= xInfo
->getImplementationName();
1290 DBG_ASSERT( !aImplName
.isEmpty(),
1291 "empty implementation name" );
1292 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc( xSvc
, uno::UNO_QUERY
);
1293 DBG_ASSERT( xSuppLoc
.is(), "interfaces not supported" );
1294 if (xSuppLoc
.is()) {
1295 uno::Sequence
<lang::Locale
> aLocaleSequence(xSuppLoc
->getLocales());
1296 aLanguages
= LocaleSeqToLangSeq( aLocaleSequence
);
1299 pAvailThesSvcs
->push_back( new SvcInfo( aImplName
, aLanguages
) );
1308 void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher
&rSpellDsp
)
1310 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" );
1312 rtl::OUString
aNode("ServiceManager/SpellCheckerList");
1313 uno::Sequence
< OUString
> aNames( /*aCfg.*/GetNodeNames( aNode
) );
1314 OUString
*pNames
= aNames
.getArray();
1315 sal_Int32 nLen
= aNames
.getLength();
1317 // append path prefix need for 'GetProperties' call below
1318 String
aPrefix( aNode
);
1319 aPrefix
.Append( (sal_Unicode
) '/' );
1320 for (int i
= 0; i
< nLen
; ++i
)
1322 OUString
aTmp( aPrefix
);
1327 uno::Sequence
< uno::Any
> aValues( /*aCfg.*/GetProperties( aNames
) );
1328 if (nLen
&& nLen
== aValues
.getLength())
1330 const uno::Any
*pValues
= aValues
.getConstArray();
1331 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1333 uno::Sequence
< OUString
> aSvcImplNames
;
1334 if (pValues
[i
] >>= aSvcImplNames
)
1336 String
aLocaleStr( pNames
[i
] );
1337 xub_StrLen nSeperatorPos
= aLocaleStr
.SearchBackward( sal_Unicode( '/' ) );
1338 aLocaleStr
= aLocaleStr
.Copy( nSeperatorPos
+ 1 );
1339 rSpellDsp
.SetServiceList( LanguageTag(aLocaleStr
).getLocale(), aSvcImplNames
);
1346 void LngSvcMgr::SetCfgServiceLists( GrammarCheckingIterator
&rGrammarDsp
)
1348 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" );
1350 rtl::OUString
aNode("ServiceManager/GrammarCheckerList");
1351 uno::Sequence
< OUString
> aNames( /*aCfg.*/GetNodeNames( aNode
) );
1352 OUString
*pNames
= aNames
.getArray();
1353 sal_Int32 nLen
= aNames
.getLength();
1355 // append path prefix need for 'GetProperties' call below
1356 String
aPrefix( aNode
);
1357 aPrefix
.Append( (sal_Unicode
) '/' );
1358 for (int i
= 0; i
< nLen
; ++i
)
1360 OUString
aTmp( aPrefix
);
1365 uno::Sequence
< uno::Any
> aValues( /*aCfg.*/GetProperties( aNames
) );
1366 if (nLen
&& nLen
== aValues
.getLength())
1368 const uno::Any
*pValues
= aValues
.getConstArray();
1369 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1371 uno::Sequence
< OUString
> aSvcImplNames
;
1372 if (pValues
[i
] >>= aSvcImplNames
)
1374 // there should only be one grammar checker in use per language...
1375 if (aSvcImplNames
.getLength() > 1)
1376 aSvcImplNames
.realloc(1);
1378 String
aLocaleStr( pNames
[i
] );
1379 xub_StrLen nSeperatorPos
= aLocaleStr
.SearchBackward( sal_Unicode( '/' ) );
1380 aLocaleStr
= aLocaleStr
.Copy( nSeperatorPos
+ 1 );
1381 rGrammarDsp
.SetServiceList( LanguageTag(aLocaleStr
).getLocale(), aSvcImplNames
);
1388 void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher
&rHyphDsp
)
1390 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" );
1392 rtl::OUString
aNode("ServiceManager/HyphenatorList");
1393 uno::Sequence
< OUString
> aNames( /*aCfg.*/GetNodeNames( aNode
) );
1394 OUString
*pNames
= aNames
.getArray();
1395 sal_Int32 nLen
= aNames
.getLength();
1397 // append path prefix need for 'GetProperties' call below
1398 String
aPrefix( aNode
);
1399 aPrefix
.Append( (sal_Unicode
) '/' );
1400 for (int i
= 0; i
< nLen
; ++i
)
1402 OUString
aTmp( aPrefix
);
1407 uno::Sequence
< uno::Any
> aValues( /*aCfg.*/GetProperties( aNames
) );
1408 if (nLen
&& nLen
== aValues
.getLength())
1410 const uno::Any
*pValues
= aValues
.getConstArray();
1411 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1413 uno::Sequence
< OUString
> aSvcImplNames
;
1414 if (pValues
[i
] >>= aSvcImplNames
)
1416 // there should only be one hyphenator in use per language...
1417 if (aSvcImplNames
.getLength() > 1)
1418 aSvcImplNames
.realloc(1);
1420 String
aLocaleStr( pNames
[i
] );
1421 xub_StrLen nSeperatorPos
= aLocaleStr
.SearchBackward( sal_Unicode( '/' ) );
1422 aLocaleStr
= aLocaleStr
.Copy( nSeperatorPos
+ 1 );
1423 rHyphDsp
.SetServiceList( LanguageTag(aLocaleStr
).getLocale(), aSvcImplNames
);
1430 void LngSvcMgr::SetCfgServiceLists( ThesaurusDispatcher
&rThesDsp
)
1432 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" );
1434 rtl::OUString
aNode("ServiceManager/ThesaurusList");
1435 uno::Sequence
< OUString
> aNames( /*aCfg.*/GetNodeNames( aNode
) );
1436 OUString
*pNames
= aNames
.getArray();
1437 sal_Int32 nLen
= aNames
.getLength();
1439 // append path prefix need for 'GetProperties' call below
1440 String
aPrefix( aNode
);
1441 aPrefix
.Append( (sal_Unicode
) '/' );
1442 for (int i
= 0; i
< nLen
; ++i
)
1444 OUString
aTmp( aPrefix
);
1449 uno::Sequence
< uno::Any
> aValues( /*aCfg.*/GetProperties( aNames
) );
1450 if (nLen
&& nLen
== aValues
.getLength())
1452 const uno::Any
*pValues
= aValues
.getConstArray();
1453 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1455 uno::Sequence
< OUString
> aSvcImplNames
;
1456 if (pValues
[i
] >>= aSvcImplNames
)
1458 String
aLocaleStr( pNames
[i
] );
1459 xub_StrLen nSeperatorPos
= aLocaleStr
.SearchBackward( sal_Unicode( '/' ) );
1460 aLocaleStr
= aLocaleStr
.Copy( nSeperatorPos
+ 1 );
1461 rThesDsp
.SetServiceList( LanguageTag(aLocaleStr
).getLocale(), aSvcImplNames
);
1468 uno::Reference
< linguistic2::XSpellChecker
> SAL_CALL
1469 LngSvcMgr::getSpellChecker()
1470 throw(uno::RuntimeException
)
1472 osl::MutexGuard
aGuard( GetLinguMutex() );
1473 #if OSL_DEBUG_LEVEL > 1
1474 getAvailableLocales( SN_SPELLCHECKER
);
1477 uno::Reference
< linguistic2::XSpellChecker
> xRes
;
1480 if (!xSpellDsp
.is())
1481 GetSpellCheckerDsp_Impl();
1488 uno::Reference
< linguistic2::XHyphenator
> SAL_CALL
1489 LngSvcMgr::getHyphenator()
1490 throw(uno::RuntimeException
)
1492 osl::MutexGuard
aGuard( GetLinguMutex() );
1493 #if OSL_DEBUG_LEVEL > 1
1494 getAvailableLocales( SN_HYPHENATOR
);
1497 uno::Reference
< linguistic2::XHyphenator
> xRes
;
1501 GetHyphenatorDsp_Impl();
1508 uno::Reference
< linguistic2::XThesaurus
> SAL_CALL
1509 LngSvcMgr::getThesaurus()
1510 throw(uno::RuntimeException
)
1512 osl::MutexGuard
aGuard( GetLinguMutex() );
1513 #if OSL_DEBUG_LEVEL > 1
1514 getAvailableLocales( SN_THESAURUS
);
1517 uno::Reference
< linguistic2::XThesaurus
> xRes
;
1521 GetThesaurusDsp_Impl();
1529 LngSvcMgr::addLinguServiceManagerListener(
1530 const uno::Reference
< lang::XEventListener
>& xListener
)
1531 throw(uno::RuntimeException
)
1533 osl::MutexGuard
aGuard( GetLinguMutex() );
1535 sal_Bool bRes
= sal_False
;
1536 if (!bDisposing
&& xListener
.is())
1538 if (!pListenerHelper
)
1539 GetListenerHelper_Impl();
1540 bRes
= pListenerHelper
->AddLngSvcMgrListener( xListener
);
1547 LngSvcMgr::removeLinguServiceManagerListener(
1548 const uno::Reference
< lang::XEventListener
>& xListener
)
1549 throw(uno::RuntimeException
)
1551 osl::MutexGuard
aGuard( GetLinguMutex() );
1553 sal_Bool bRes
= sal_False
;
1554 if (!bDisposing
&& xListener
.is())
1556 DBG_ASSERT( pListenerHelper
, "listener removed without being added" );
1557 if (!pListenerHelper
)
1558 GetListenerHelper_Impl();
1559 bRes
= pListenerHelper
->RemoveLngSvcMgrListener( xListener
);
1565 uno::Sequence
< OUString
> SAL_CALL
1566 LngSvcMgr::getAvailableServices(
1567 const OUString
& rServiceName
,
1568 const lang::Locale
& rLocale
)
1569 throw(uno::RuntimeException
)
1571 osl::MutexGuard
aGuard( GetLinguMutex() );
1573 uno::Sequence
< OUString
> aRes
;
1574 const SvcInfoArray
*pInfoArray
= 0;
1576 if (0 == rServiceName
.compareToAscii( SN_SPELLCHECKER
))
1578 GetAvailableSpellSvcs_Impl();
1579 pInfoArray
= pAvailSpellSvcs
;
1581 else if (0 == rServiceName
.compareToAscii( SN_GRAMMARCHECKER
))
1583 GetAvailableGrammarSvcs_Impl();
1584 pInfoArray
= pAvailGrammarSvcs
;
1586 else if (0 == rServiceName
.compareToAscii( SN_HYPHENATOR
))
1588 GetAvailableHyphSvcs_Impl();
1589 pInfoArray
= pAvailHyphSvcs
;
1591 else if (0 == rServiceName
.compareToAscii( SN_THESAURUS
))
1593 GetAvailableThesSvcs_Impl();
1594 pInfoArray
= pAvailThesSvcs
;
1599 // resize to max number of entries
1600 size_t nMaxCnt
= pInfoArray
->size();
1601 aRes
.realloc( nMaxCnt
);
1602 OUString
*pImplName
= aRes
.getArray();
1604 sal_uInt16 nCnt
= 0;
1605 LanguageType nLanguage
= LinguLocaleToLanguage( rLocale
);
1606 for (size_t i
= 0; i
< nMaxCnt
; ++i
)
1608 const SvcInfo
&rInfo
= (*pInfoArray
)[i
];
1609 if (LinguIsUnspecified( nLanguage
)
1610 || rInfo
.HasLanguage( nLanguage
))
1612 pImplName
[ nCnt
++ ] = rInfo
.aSvcImplName
;
1616 // resize to actual number of entries
1617 if (nCnt
!= nMaxCnt
)
1618 aRes
.realloc( nCnt
);
1625 uno::Sequence
< lang::Locale
> SAL_CALL
1626 LngSvcMgr::getAvailableLocales(
1627 const OUString
& rServiceName
)
1628 throw(uno::RuntimeException
)
1630 osl::MutexGuard
aGuard( GetLinguMutex() );
1632 uno::Sequence
< lang::Locale
> aRes
;
1634 uno::Sequence
< lang::Locale
> *pAvailLocales
= NULL
;
1635 if (0 == rServiceName
.compareToAscii( SN_SPELLCHECKER
))
1636 pAvailLocales
= &aAvailSpellLocales
;
1637 else if (0 == rServiceName
.compareToAscii( SN_GRAMMARCHECKER
))
1638 pAvailLocales
= &aAvailGrammarLocales
;
1639 else if (0 == rServiceName
.compareToAscii( SN_HYPHENATOR
))
1640 pAvailLocales
= &aAvailHyphLocales
;
1641 else if (0 == rServiceName
.compareToAscii( SN_THESAURUS
))
1642 pAvailLocales
= &aAvailThesLocales
;
1644 // Nowadays (with OOo lingu in SO) we want to know immediately about
1645 // new downloaded dictionaries and have them ready right away if the Tools/Options...
1646 // is used to activate them. Thus we can not rely anymore on buffered data.
1649 *pAvailLocales
= GetAvailLocales(getAvailableServices(rServiceName
, lang::Locale()));
1650 aRes
= *pAvailLocales
;
1656 static sal_Bool
IsEqSvcList( const uno::Sequence
< OUString
> &rList1
,
1657 const uno::Sequence
< OUString
> &rList2
)
1659 // returns sal_True iff both sequences are equal
1661 sal_Bool bRes
= sal_False
;
1662 sal_Int32 nLen
= rList1
.getLength();
1663 if (rList2
.getLength() == nLen
)
1665 const OUString
*pStr1
= rList1
.getConstArray();
1666 const OUString
*pStr2
= rList2
.getConstArray();
1668 for (sal_Int32 i
= 0; i
< nLen
&& bRes
; ++i
)
1670 if (*pStr1
++ != *pStr2
++)
1679 LngSvcMgr::setConfiguredServices(
1680 const OUString
& rServiceName
,
1681 const lang::Locale
& rLocale
,
1682 const uno::Sequence
< OUString
>& rServiceImplNames
)
1683 throw(uno::RuntimeException
)
1685 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::setConfiguredServices" );
1687 osl::MutexGuard
aGuard( GetLinguMutex() );
1689 #if OSL_DEBUG_LEVEL > 1
1692 LanguageType nLanguage
= LinguLocaleToLanguage( rLocale
);
1693 if (!LinguIsUnspecified( nLanguage
))
1695 if (0 == rServiceName
.compareToAscii( SN_SPELLCHECKER
))
1697 if (!xSpellDsp
.is())
1698 GetSpellCheckerDsp_Impl();
1699 sal_Bool bChanged
= !IsEqSvcList( rServiceImplNames
,
1700 pSpellDsp
->GetServiceList( rLocale
) );
1703 pSpellDsp
->SetServiceList( rLocale
, rServiceImplNames
);
1704 SaveCfgSvcs( rtl::OUString(SN_SPELLCHECKER
) );
1706 if (pListenerHelper
&& bChanged
)
1707 pListenerHelper
->AddLngSvcEvt(
1708 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN
|
1709 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN
);
1712 else if (0 == rServiceName
.compareToAscii( SN_GRAMMARCHECKER
))
1714 if (!xGrammarDsp
.is())
1715 GetGrammarCheckerDsp_Impl();
1716 sal_Bool bChanged
= !IsEqSvcList( rServiceImplNames
,
1717 pGrammarDsp
->GetServiceList( rLocale
) );
1720 pGrammarDsp
->SetServiceList( rLocale
, rServiceImplNames
);
1721 SaveCfgSvcs( rtl::OUString(SN_GRAMMARCHECKER
) );
1723 if (pListenerHelper
&& bChanged
)
1724 pListenerHelper
->AddLngSvcEvt(
1725 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN
);
1728 else if (0 == rServiceName
.compareToAscii( SN_HYPHENATOR
))
1731 GetHyphenatorDsp_Impl();
1732 sal_Bool bChanged
= !IsEqSvcList( rServiceImplNames
,
1733 pHyphDsp
->GetServiceList( rLocale
) );
1736 pHyphDsp
->SetServiceList( rLocale
, rServiceImplNames
);
1737 SaveCfgSvcs( rtl::OUString(SN_HYPHENATOR
) );
1739 if (pListenerHelper
&& bChanged
)
1740 pListenerHelper
->AddLngSvcEvt(
1741 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN
);
1744 else if (0 == rServiceName
.compareToAscii( SN_THESAURUS
))
1747 GetThesaurusDsp_Impl();
1748 sal_Bool bChanged
= !IsEqSvcList( rServiceImplNames
,
1749 pThesDsp
->GetServiceList( rLocale
) );
1752 pThesDsp
->SetServiceList( rLocale
, rServiceImplNames
);
1753 SaveCfgSvcs( rtl::OUString(SN_THESAURUS
) );
1760 sal_Bool
LngSvcMgr::SaveCfgSvcs( const String
&rServiceName
)
1762 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SaveCfgSvcs" );
1764 sal_Bool bRes
= sal_False
;
1766 LinguDispatcher
*pDsp
= 0;
1767 uno::Sequence
< lang::Locale
> aLocales
;
1769 if (0 == rServiceName
.CompareToAscii( SN_SPELLCHECKER
))
1772 GetSpellCheckerDsp_Impl();
1774 aLocales
= getAvailableLocales( SN_SPELLCHECKER
);
1776 else if (0 == rServiceName
.CompareToAscii( SN_GRAMMARCHECKER
))
1779 GetGrammarCheckerDsp_Impl();
1781 aLocales
= getAvailableLocales( SN_GRAMMARCHECKER
);
1783 else if (0 == rServiceName
.CompareToAscii( SN_HYPHENATOR
))
1786 GetHyphenatorDsp_Impl();
1788 aLocales
= getAvailableLocales( SN_HYPHENATOR
);
1790 else if (0 == rServiceName
.CompareToAscii( SN_THESAURUS
))
1793 GetThesaurusDsp_Impl();
1795 aLocales
= getAvailableLocales( SN_THESAURUS
);
1798 if (pDsp
&& aLocales
.getLength())
1800 sal_Int32 nLen
= aLocales
.getLength();
1801 const lang::Locale
*pLocale
= aLocales
.getConstArray();
1803 uno::Sequence
< beans::PropertyValue
> aValues( nLen
);
1804 beans::PropertyValue
*pValues
= aValues
.getArray();
1805 beans::PropertyValue
*pValue
= pValues
;
1807 // get node name to be used
1808 const char *pNodeName
= NULL
;
1809 if (pDsp
== pSpellDsp
)
1810 pNodeName
= "ServiceManager/SpellCheckerList";
1811 else if (pDsp
== pGrammarDsp
)
1812 pNodeName
= "ServiceManager/GrammarCheckerList";
1813 else if (pDsp
== pHyphDsp
)
1814 pNodeName
= "ServiceManager/HyphenatorList";
1815 else if (pDsp
== pThesDsp
)
1816 pNodeName
= "ServiceManager/ThesaurusList";
1819 DBG_ASSERT( 0, "node name missing" );
1821 OUString
aNodeName( ::rtl::OUString::createFromAscii(pNodeName
) );
1823 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1825 uno::Sequence
< OUString
> aSvcImplNames
;
1826 aSvcImplNames
= pDsp
->GetServiceList( pLocale
[i
] );
1828 #if OSL_DEBUG_LEVEL > 1
1829 sal_Int32 nSvcs
= aSvcImplNames
.getLength();
1830 const OUString
*pSvcImplName
= aSvcImplNames
.getConstArray();
1831 for (sal_Int32 j
= 0; j
< nSvcs
; ++j
)
1833 OUString
aImplName( pSvcImplName
[j
] );
1836 // build value to be written back to configuration
1838 if ((pDsp
== pHyphDsp
|| pDsp
== pGrammarDsp
) && aSvcImplNames
.getLength() > 1)
1839 aSvcImplNames
.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained)
1840 aCfgAny
<<= aSvcImplNames
;
1841 DBG_ASSERT( aCfgAny
.hasValue(), "missing value for 'Any' type" );
1843 OUString
aCfgLocaleStr( (LanguageTag(pLocale
[i
])).getBcp47() );
1844 pValue
->Value
= aCfgAny
;
1845 pValue
->Name
= aNodeName
;
1846 pValue
->Name
+= OUString::valueOf( (sal_Unicode
) '/' );
1847 pValue
->Name
+= aCfgLocaleStr
;
1851 RTL_LOGFILE_CONTEXT( aLog
, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" );
1852 // change, add new or replace existing entries.
1853 bRes
|= /*aCfg.*/ReplaceSetProperties( aNodeName
, aValues
);
1861 static uno::Sequence
< OUString
> GetLangSvcList( const uno::Any
&rVal
)
1863 uno::Sequence
< OUString
> aRes
;
1865 if (rVal
.hasValue())
1868 #if OSL_DEBUG_LEVEL > 1
1869 sal_Int32 nSvcs
= aRes
.getLength();
1872 const OUString
*pSvcName
= aRes
.getConstArray();
1873 for (sal_Int32 j
= 0; j
< nSvcs
; ++j
)
1875 OUString
aImplName( pSvcName
[j
] );
1876 DBG_ASSERT( !aImplName
.isEmpty(), "service impl-name missing" );
1886 static uno::Sequence
< OUString
> GetLangSvc( const uno::Any
&rVal
)
1888 uno::Sequence
< OUString
> aRes
;
1889 if (!rVal
.hasValue())
1892 // allowing for a sequence here as well (even though it should only
1893 // be a string) makes coding easier in other places since one needs
1894 // not make a special case for writing a string only and not a
1895 // sequence of strings.
1898 // but only the first string should be used.
1899 if (aRes
.getLength() > 1)
1905 if ((rVal
>>= aImplName
) && !aImplName
.isEmpty())
1908 aRes
.getArray()[0] = aImplName
;
1912 DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" );
1921 uno::Sequence
< OUString
> SAL_CALL
1922 LngSvcMgr::getConfiguredServices(
1923 const OUString
& rServiceName
,
1924 const lang::Locale
& rLocale
)
1925 throw(uno::RuntimeException
)
1927 osl::MutexGuard
aGuard( GetLinguMutex() );
1929 uno::Sequence
< OUString
> aSvcImplNames
;
1931 OUString
aCfgLocale( LanguageTag( rLocale
).getBcp47() );
1933 uno::Sequence
< uno::Any
> aValues
;
1934 uno::Sequence
< OUString
> aNames( 1 );
1935 OUString
*pNames
= aNames
.getArray();
1936 if ( 0 == rServiceName
.compareToAscii( SN_SPELLCHECKER
) )
1938 OUString
aNode( "ServiceManager/SpellCheckerList");
1939 const uno::Sequence
< OUString
> aNodeEntries( GetNodeNames( aNode
) );
1940 if (lcl_SeqHasString( aNodeEntries
, aCfgLocale
))
1942 OUString
aPropName( aNode
);
1943 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
1944 aPropName
+= aCfgLocale
;
1945 pNames
[0] = aPropName
;
1946 aValues
= /*aCfg.*/GetProperties( aNames
);
1947 if (aValues
.getLength())
1948 aSvcImplNames
= GetLangSvcList( aValues
.getConstArray()[0] );
1951 else if ( 0 == rServiceName
.compareToAscii( SN_GRAMMARCHECKER
) )
1953 OUString
aNode( "ServiceManager/GrammarCheckerList");
1954 const uno::Sequence
< OUString
> aNodeEntries( GetNodeNames( aNode
) );
1955 if (lcl_SeqHasString( aNodeEntries
, aCfgLocale
))
1957 OUString
aPropName( aNode
);
1958 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
1959 aPropName
+= aCfgLocale
;
1960 pNames
[0] = aPropName
;
1961 aValues
= /*aCfg.*/GetProperties( aNames
);
1962 if (aValues
.getLength())
1963 aSvcImplNames
= GetLangSvc( aValues
.getConstArray()[0] );
1966 else if ( 0 == rServiceName
.compareToAscii( SN_HYPHENATOR
) )
1968 OUString
aNode( "ServiceManager/HyphenatorList");
1969 const uno::Sequence
< OUString
> aNodeEntries( GetNodeNames( aNode
) );
1970 if (lcl_SeqHasString( aNodeEntries
, aCfgLocale
))
1972 OUString
aPropName( aNode
);
1973 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
1974 aPropName
+= aCfgLocale
;
1975 pNames
[0] = aPropName
;
1976 aValues
= /*aCfg.*/GetProperties( aNames
);
1977 if (aValues
.getLength())
1978 aSvcImplNames
= GetLangSvc( aValues
.getConstArray()[0] );
1981 else if ( 0 == rServiceName
.compareToAscii( SN_THESAURUS
) )
1983 OUString
aNode( "ServiceManager/ThesaurusList");
1984 const uno::Sequence
< OUString
> aNodeEntries( GetNodeNames( aNode
) );
1985 if (lcl_SeqHasString( aNodeEntries
, aCfgLocale
))
1987 OUString
aPropName( aNode
);
1988 aPropName
+= OUString::valueOf( (sal_Unicode
) '/' );
1989 aPropName
+= aCfgLocale
;
1990 pNames
[0] = aPropName
;
1991 aValues
= /*aCfg.*/GetProperties( aNames
);
1992 if (aValues
.getLength())
1993 aSvcImplNames
= GetLangSvcList( aValues
.getConstArray()[0] );
1997 #if OSL_DEBUG_LEVEL > 1
1998 const OUString
*pImplNames
= aSvcImplNames
.getConstArray();
2001 return aSvcImplNames
;
2006 LngSvcMgr::dispose()
2007 throw(uno::RuntimeException
)
2009 osl::MutexGuard
aGuard( GetLinguMutex() );
2013 bDisposing
= sal_True
;
2015 // require listeners to release this object
2016 lang::EventObject
aEvtObj( static_cast<XLinguServiceManager
*>(this) );
2017 aEvtListeners
.disposeAndClear( aEvtObj
);
2019 if (pListenerHelper
)
2020 pListenerHelper
->DisposeAndClear( aEvtObj
);
2026 LngSvcMgr::addEventListener(
2027 const uno::Reference
< lang::XEventListener
>& xListener
)
2028 throw(uno::RuntimeException
)
2030 osl::MutexGuard
aGuard( GetLinguMutex() );
2032 if (!bDisposing
&& xListener
.is())
2034 aEvtListeners
.addInterface( xListener
);
2040 LngSvcMgr::removeEventListener(
2041 const uno::Reference
< lang::XEventListener
>& xListener
)
2042 throw(uno::RuntimeException
)
2044 osl::MutexGuard
aGuard( GetLinguMutex() );
2048 aEvtListeners
.removeInterface( xListener
);
2053 sal_Bool
LngSvcMgr::AddLngSvcEvtBroadcaster(
2054 const uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> &rxBroadcaster
)
2056 sal_Bool bRes
= sal_False
;
2057 if (rxBroadcaster
.is())
2059 if (!pListenerHelper
)
2060 GetListenerHelper_Impl();
2061 bRes
= pListenerHelper
->AddLngSvcEvtBroadcaster( rxBroadcaster
);
2068 LngSvcMgr::getImplementationName()
2069 throw(uno::RuntimeException
)
2071 osl::MutexGuard
aGuard( GetLinguMutex() );
2072 return getImplementationName_Static();
2077 LngSvcMgr::supportsService( const OUString
& ServiceName
)
2078 throw(uno::RuntimeException
)
2080 osl::MutexGuard
aGuard( GetLinguMutex() );
2082 uno::Sequence
< OUString
> aSNL
= getSupportedServiceNames();
2083 const OUString
* pArray
= aSNL
.getConstArray();
2084 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
2085 if( pArray
[i
] == ServiceName
)
2091 uno::Sequence
< OUString
> SAL_CALL
2092 LngSvcMgr::getSupportedServiceNames()
2093 throw(uno::RuntimeException
)
2095 osl::MutexGuard
aGuard( GetLinguMutex() );
2096 return getSupportedServiceNames_Static();
2100 uno::Sequence
< OUString
> LngSvcMgr::getSupportedServiceNames_Static()
2103 osl::MutexGuard
aGuard( GetLinguMutex() );
2105 uno::Sequence
< OUString
> aSNS( 1 ); // more than 1 service possible
2106 aSNS
.getArray()[0] = "com.sun.star.linguistic2.LinguServiceManager";
2111 uno::Reference
< uno::XInterface
> SAL_CALL
LngSvcMgr_CreateInstance(
2112 const uno::Reference
< lang::XMultiServiceFactory
> & /*rSMgr*/ )
2113 throw(uno::Exception
)
2115 uno::Reference
< uno::XInterface
> xService
= (cppu::OWeakObject
*) new LngSvcMgr
;
2119 void * SAL_CALL
LngSvcMgr_getFactory(
2120 const sal_Char
* pImplName
,
2121 lang::XMultiServiceFactory
* pServiceManager
,
2122 void * /*pRegistryKey*/ )
2126 if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName
) )
2128 uno::Reference
< lang::XSingleServiceFactory
> xFactory
=
2129 cppu::createOneInstanceFactory(
2131 LngSvcMgr::getImplementationName_Static(),
2132 LngSvcMgr_CreateInstance
,
2133 LngSvcMgr::getSupportedServiceNames_Static());
2134 // acquire, because we return an interface pointer instead of a reference
2135 xFactory
->acquire();
2136 pRet
= xFactory
.get();
2143 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */