Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
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>
29 :
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>
38 :
39 : #include <boost/checked_delete.hpp>
40 :
41 : #include "lngsvcmgr.hxx"
42 : #include "lngopt.hxx"
43 : #include "linguistic/misc.hxx"
44 : #include "spelldsp.hxx"
45 : #include "hyphdsp.hxx"
46 : #include "thesdsp.hxx"
47 : #include "gciterator.hxx"
48 :
49 :
50 : using namespace com::sun::star;
51 : using namespace linguistic;
52 : using ::rtl::OUString;
53 :
54 : // forward declarations
55 : uno::Sequence< OUString > static GetLangSvcList( const uno::Any &rVal );
56 : uno::Sequence< OUString > static GetLangSvc( const uno::Any &rVal );
57 :
58 :
59 0 : static sal_Bool lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText )
60 : {
61 0 : sal_Bool bRes = sal_False;
62 :
63 0 : sal_Int32 nLen = rSeq.getLength();
64 0 : if (nLen == 0 || rText.isEmpty())
65 0 : return bRes;
66 :
67 0 : const OUString *pSeq = rSeq.getConstArray();
68 0 : for (sal_Int32 i = 0; i < nLen && !bRes; ++i)
69 : {
70 0 : if (rText == pSeq[i])
71 0 : bRes = sal_True;
72 : }
73 0 : return bRes;
74 : }
75 :
76 :
77 44 : static uno::Sequence< lang::Locale > GetAvailLocales(
78 : const uno::Sequence< OUString > &rSvcImplNames )
79 : {
80 44 : uno::Sequence< lang::Locale > aRes;
81 :
82 44 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
83 44 : sal_Int32 nNames = rSvcImplNames.getLength();
84 44 : if (nNames && xFac.is())
85 : {
86 0 : std::set< LanguageType > aLanguages;
87 :
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 0 : uno::Sequence< uno::Any > aArgs(2);
91 0 : aArgs.getArray()[0] <<= GetLinguProperties();
92 :
93 : // check all services for the supported languages and new
94 : // languages to the result
95 0 : const OUString *pImplNames = rSvcImplNames.getConstArray();
96 : sal_Int32 i;
97 :
98 0 : for (i = 0; i < nNames; ++i)
99 : {
100 0 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc;
101 : try
102 : {
103 : xSuppLoc = uno::Reference< linguistic2::XSupportedLocales >(
104 0 : xFac->createInstanceWithArguments( pImplNames[i], aArgs ), uno::UNO_QUERY );
105 : }
106 0 : catch (uno::Exception &)
107 : {
108 : DBG_ASSERT( 0, "createInstanceWithArguments failed" );
109 : }
110 :
111 0 : if (xSuppLoc.is())
112 : {
113 0 : uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() );
114 0 : sal_Int32 nLoc = aLoc.getLength();
115 0 : for (sal_Int32 k = 0; k < nLoc; ++k)
116 : {
117 0 : const lang::Locale *pLoc = aLoc.getConstArray();
118 0 : LanguageType nLang = LanguageTag( pLoc[k] ).getLanguageType();
119 :
120 : // language not already added?
121 0 : if (aLanguages.find( nLang ) == aLanguages.end())
122 0 : aLanguages.insert( nLang );
123 0 : }
124 : }
125 : else
126 : {
127 : DBG_ASSERT( 0, "interface not supported by service" );
128 : }
129 0 : }
130 :
131 : // build return sequence
132 0 : sal_Int32 nLanguages = static_cast< sal_Int32 >(aLanguages.size());
133 0 : aRes.realloc( nLanguages );
134 0 : lang::Locale *pRes = aRes.getArray();
135 0 : std::set< LanguageType >::const_iterator aIt( aLanguages.begin() );
136 0 : for (i = 0; aIt != aLanguages.end(); ++aIt, ++i)
137 : {
138 0 : LanguageType nLang = *aIt;
139 0 : pRes[i] = LanguageTag( nLang ).getLocale();
140 0 : }
141 : }
142 :
143 44 : return aRes;
144 : }
145 :
146 :
147 0 : struct SvcInfo
148 : {
149 : const OUString aSvcImplName;
150 : const uno::Sequence< sal_Int16 > aSuppLanguages;
151 :
152 0 : SvcInfo( const OUString &rSvcImplName,
153 : const uno::Sequence< sal_Int16 > &rSuppLanguages ) :
154 : aSvcImplName (rSvcImplName),
155 0 : aSuppLanguages (rSuppLanguages)
156 : {
157 0 : }
158 :
159 : sal_Bool HasLanguage( sal_Int16 nLanguage ) const;
160 : };
161 :
162 :
163 0 : sal_Bool SvcInfo::HasLanguage( sal_Int16 nLanguage ) const
164 : {
165 0 : sal_Int32 nCnt = aSuppLanguages.getLength();
166 0 : const sal_Int16 *pLang = aSuppLanguages.getConstArray();
167 : sal_Int32 i;
168 :
169 0 : for ( i = 0; i < nCnt; ++i)
170 : {
171 0 : if (nLanguage == pLang[i])
172 0 : break;
173 : }
174 0 : return i < nCnt;
175 : }
176 :
177 14 : class LngSvcMgrListenerHelper :
178 : public cppu::WeakImplHelper2
179 : <
180 : linguistic2::XLinguServiceEventListener,
181 : linguistic2::XDictionaryListEventListener
182 : >
183 : {
184 : LngSvcMgr &rMyManager;
185 :
186 : ::cppu::OInterfaceContainerHelper aLngSvcMgrListeners;
187 : ::cppu::OInterfaceContainerHelper aLngSvcEvtBroadcasters;
188 : uno::Reference< linguistic2::XDictionaryList > xDicList;
189 :
190 : sal_Int16 nCombinedLngSvcEvt;
191 :
192 : // disallow copy-constructor and assignment-operator for now
193 : LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper &);
194 : LngSvcMgrListenerHelper & operator = (const LngSvcMgrListenerHelper &);
195 :
196 : void LaunchEvent( sal_Int16 nLngSvcEvtFlags );
197 :
198 : long Timeout();
199 :
200 : public:
201 : LngSvcMgrListenerHelper( LngSvcMgr &rLngSvcMgr,
202 : const uno::Reference< linguistic2::XDictionaryList > &rxDicList );
203 :
204 : // lang::XEventListener
205 : virtual void SAL_CALL
206 : disposing( const lang::EventObject& rSource )
207 : throw(uno::RuntimeException);
208 :
209 : // linguistic2::XLinguServiceEventListener
210 : virtual void SAL_CALL
211 : processLinguServiceEvent( const linguistic2::LinguServiceEvent& aLngSvcEvent )
212 : throw(uno::RuntimeException);
213 :
214 : // linguistic2::XDictionaryListEventListener
215 : virtual void SAL_CALL
216 : processDictionaryListEvent(
217 : const linguistic2::DictionaryListEvent& rDicListEvent )
218 : throw(uno::RuntimeException);
219 :
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 );
229 :
230 : void AddLngSvcEvt( sal_Int16 nLngSvcEvt );
231 : };
232 :
233 :
234 7 : LngSvcMgrListenerHelper::LngSvcMgrListenerHelper(
235 : LngSvcMgr &rLngSvcMgr,
236 : const uno::Reference< linguistic2::XDictionaryList > &rxDicList ) :
237 : rMyManager ( rLngSvcMgr ),
238 7 : aLngSvcMgrListeners ( GetLinguMutex() ),
239 7 : aLngSvcEvtBroadcasters ( GetLinguMutex() ),
240 21 : xDicList ( rxDicList )
241 : {
242 7 : if (xDicList.is())
243 : {
244 7 : xDicList->addDictionaryListEventListener(
245 7 : (linguistic2::XDictionaryListEventListener *) this, sal_False );
246 : }
247 :
248 7 : nCombinedLngSvcEvt = 0;
249 7 : }
250 :
251 :
252 0 : void SAL_CALL LngSvcMgrListenerHelper::disposing( const lang::EventObject& rSource )
253 : throw(uno::RuntimeException)
254 : {
255 0 : osl::MutexGuard aGuard( GetLinguMutex() );
256 :
257 0 : uno::Reference< uno::XInterface > xRef( rSource.Source );
258 0 : if ( xRef.is() )
259 : {
260 0 : aLngSvcMgrListeners .removeInterface( xRef );
261 0 : aLngSvcEvtBroadcasters.removeInterface( xRef );
262 0 : if (xDicList == xRef)
263 0 : xDicList = 0;
264 0 : }
265 0 : }
266 :
267 0 : long LngSvcMgrListenerHelper::Timeout()
268 : {
269 0 : osl::MutexGuard aGuard( GetLinguMutex() );
270 :
271 : {
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 0 : static_cast<com::sun::star::linguistic2::XLinguServiceManager*>(&rMyManager), nCombinedLngSvcEvt );
277 0 : nCombinedLngSvcEvt = 0;
278 :
279 0 : if (rMyManager.pSpellDsp)
280 0 : rMyManager.pSpellDsp->FlushSpellCache();
281 :
282 : // pass event on to linguistic2::XLinguServiceEventListener's
283 0 : cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
284 0 : while (aIt.hasMoreElements())
285 : {
286 0 : uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY );
287 0 : if (xRef.is())
288 0 : xRef->processLinguServiceEvent( aEvtObj );
289 0 : }
290 : }
291 0 : return 0;
292 : }
293 :
294 :
295 0 : void LngSvcMgrListenerHelper::AddLngSvcEvt( sal_Int16 nLngSvcEvt )
296 : {
297 0 : nCombinedLngSvcEvt |= nLngSvcEvt;
298 0 : Timeout();
299 0 : }
300 :
301 :
302 : void SAL_CALL
303 0 : LngSvcMgrListenerHelper::processLinguServiceEvent(
304 : const linguistic2::LinguServiceEvent& rLngSvcEvent )
305 : throw(uno::RuntimeException)
306 : {
307 0 : osl::MutexGuard aGuard( GetLinguMutex() );
308 0 : AddLngSvcEvt( rLngSvcEvent.nEvent );
309 0 : }
310 :
311 :
312 : void SAL_CALL
313 0 : LngSvcMgrListenerHelper::processDictionaryListEvent(
314 : const linguistic2::DictionaryListEvent& rDicListEvent )
315 : throw(uno::RuntimeException)
316 : {
317 0 : osl::MutexGuard aGuard( GetLinguMutex() );
318 :
319 0 : sal_Int16 nDlEvt = rDicListEvent.nCondensedEvent;
320 0 : if (0 == nDlEvt)
321 0 : return;
322 :
323 : // we do keep the original event source here though...
324 :
325 : // pass event on to linguistic2::XDictionaryListEventListener's
326 0 : cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
327 0 : while (aIt.hasMoreElements())
328 : {
329 0 : uno::Reference< linguistic2::XDictionaryListEventListener > xRef( aIt.next(), uno::UNO_QUERY );
330 0 : if (xRef.is())
331 0 : xRef->processDictionaryListEvent( rDicListEvent );
332 0 : }
333 :
334 : // "translate" DictionaryList event into linguistic2::LinguServiceEvent
335 0 : 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 0 : linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC;
341 0 : if (0 != (nDlEvt & nSpellCorrectFlags))
342 0 : nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
343 :
344 : sal_Int16 nSpellWrongFlags =
345 : linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
346 : linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY |
347 : linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
348 0 : linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC;
349 0 : if (0 != (nDlEvt & nSpellWrongFlags))
350 0 : nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
351 :
352 : sal_Int16 nHyphenateFlags =
353 : linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
354 : linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY |
355 : linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
356 0 : linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC;
357 0 : if (0 != (nDlEvt & nHyphenateFlags))
358 0 : nLngSvcEvt |= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN;
359 :
360 0 : if (rMyManager.pSpellDsp)
361 0 : rMyManager.pSpellDsp->FlushSpellCache();
362 0 : if (nLngSvcEvt)
363 0 : LaunchEvent( nLngSvcEvt );
364 : }
365 :
366 :
367 0 : void LngSvcMgrListenerHelper::LaunchEvent( sal_Int16 nLngSvcEvtFlags )
368 : {
369 : linguistic2::LinguServiceEvent aEvt(
370 0 : static_cast<com::sun::star::linguistic2::XLinguServiceManager*>(&rMyManager), nLngSvcEvtFlags );
371 :
372 : // pass event on to linguistic2::XLinguServiceEventListener's
373 0 : cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
374 0 : while (aIt.hasMoreElements())
375 : {
376 0 : uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY );
377 0 : if (xRef.is())
378 0 : xRef->processLinguServiceEvent( aEvt );
379 0 : }
380 0 : }
381 :
382 :
383 7 : inline sal_Bool LngSvcMgrListenerHelper::AddLngSvcMgrListener(
384 : const uno::Reference< lang::XEventListener >& rxListener )
385 : {
386 7 : aLngSvcMgrListeners.addInterface( rxListener );
387 7 : return sal_True;
388 : }
389 :
390 :
391 0 : inline sal_Bool LngSvcMgrListenerHelper::RemoveLngSvcMgrListener(
392 : const uno::Reference< lang::XEventListener >& rxListener )
393 : {
394 0 : aLngSvcMgrListeners.removeInterface( rxListener );
395 0 : return sal_True;
396 : }
397 :
398 :
399 7 : void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj )
400 : {
401 : // call "disposing" for all listeners and clear list
402 7 : aLngSvcMgrListeners .disposeAndClear( rEvtObj );
403 :
404 : // remove references to this object hold by the broadcasters
405 7 : cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtBroadcasters );
406 14 : while (aIt.hasMoreElements())
407 : {
408 0 : uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY );
409 0 : if (xRef.is())
410 0 : RemoveLngSvcEvtBroadcaster( xRef );
411 0 : }
412 :
413 : // remove refernce to this object hold by the dictionary-list
414 7 : if (xDicList.is())
415 : {
416 7 : xDicList->removeDictionaryListEventListener(
417 7 : (linguistic2::XDictionaryListEventListener *) this );
418 7 : xDicList = 0;
419 7 : }
420 7 : }
421 :
422 :
423 0 : sal_Bool LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster(
424 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
425 : {
426 0 : sal_Bool bRes = sal_False;
427 0 : if (rxBroadcaster.is())
428 : {
429 0 : aLngSvcEvtBroadcasters.addInterface( rxBroadcaster );
430 0 : rxBroadcaster->addLinguServiceEventListener(
431 0 : (linguistic2::XLinguServiceEventListener *) this );
432 : }
433 0 : return bRes;
434 : }
435 :
436 :
437 0 : sal_Bool LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster(
438 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
439 : {
440 0 : sal_Bool bRes = sal_False;
441 0 : if (rxBroadcaster.is())
442 : {
443 0 : aLngSvcEvtBroadcasters.removeInterface( rxBroadcaster );
444 0 : rxBroadcaster->removeLinguServiceEventListener(
445 0 : (linguistic2::XLinguServiceEventListener *) this );
446 : }
447 0 : return bRes;
448 : }
449 :
450 :
451 :
452 :
453 11 : LngSvcMgr::LngSvcMgr()
454 : : utl::ConfigItem("Office.Linguistic")
455 11 : , aEvtListeners(GetLinguMutex())
456 : {
457 11 : bDisposing = sal_False;
458 :
459 11 : pSpellDsp = 0;
460 11 : pGrammarDsp = 0;
461 11 : pHyphDsp = 0;
462 11 : pThesDsp = 0;
463 :
464 11 : pAvailSpellSvcs = 0;
465 11 : pAvailGrammarSvcs = 0;
466 11 : pAvailHyphSvcs = 0;
467 11 : pAvailThesSvcs = 0;
468 11 : pListenerHelper = 0;
469 :
470 : // request notify events when properties (i.e. something in the subtree) changes
471 11 : uno::Sequence< OUString > aNames(4);
472 11 : OUString *pNames = aNames.getArray();
473 11 : pNames[0] = "ServiceManager/SpellCheckerList";
474 11 : pNames[1] = "ServiceManager/GrammarCheckerList";
475 11 : pNames[2] = "ServiceManager/HyphenatorList";
476 11 : pNames[3] = "ServiceManager/ThesaurusList";
477 11 : EnableNotification( aNames );
478 :
479 11 : UpdateAll();
480 :
481 11 : aUpdateTimer.SetTimeout(500);
482 11 : aUpdateTimer.SetTimeoutHdl(LINK(this, LngSvcMgr, updateAndBroadcast));
483 :
484 : // request to be notified if an extension has been added/removed
485 11 : uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
486 :
487 11 : uno::Reference<deployment::XExtensionManager> xExtensionManager;
488 : try {
489 11 : xExtensionManager = deployment::ExtensionManager::get(xContext);
490 10 : } catch ( const uno::DeploymentException & ) {
491 : SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
492 0 : } catch ( const deployment::DeploymentException & ) {
493 : SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
494 : }
495 11 : if (xExtensionManager.is())
496 : {
497 1 : xMB = uno::Reference<util::XModifyBroadcaster>(xExtensionManager, uno::UNO_QUERY_THROW);
498 :
499 1 : uno::Reference<util::XModifyListener> xListener(this);
500 1 : xMB->addModifyListener( xListener );
501 11 : }
502 11 : }
503 :
504 : // ::com::sun::star::util::XModifyListener
505 0 : void LngSvcMgr::modified(const lang::EventObject&)
506 : throw(uno::RuntimeException)
507 : {
508 0 : 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
511 :
512 0 : clearSvcInfoArray(pAvailSpellSvcs);
513 0 : clearSvcInfoArray(pAvailGrammarSvcs);
514 0 : clearSvcInfoArray(pAvailHyphSvcs);
515 0 : clearSvcInfoArray(pAvailThesSvcs);
516 :
517 : //schedule in an update to execute in the main thread
518 0 : aUpdateTimer.Start();
519 0 : }
520 :
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 0 : IMPL_LINK_NOARG(LngSvcMgr, updateAndBroadcast)
526 : {
527 0 : osl::MutexGuard aGuard( GetLinguMutex() );
528 :
529 0 : UpdateAll();
530 :
531 0 : if (pListenerHelper)
532 : {
533 : pListenerHelper->AddLngSvcEvt(
534 : linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN |
535 : linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN |
536 : linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN |
537 0 : linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN );
538 : }
539 :
540 0 : return 0;
541 : }
542 :
543 12 : void LngSvcMgr::stopListening()
544 : {
545 12 : osl::MutexGuard aGuard(GetLinguMutex());
546 :
547 12 : if (xMB.is())
548 : {
549 : try
550 : {
551 1 : uno::Reference<util::XModifyListener> xListener(this);
552 2 : xMB->removeModifyListener(xListener);
553 : }
554 1 : catch (const uno::Exception&)
555 : {
556 : }
557 :
558 1 : xMB.clear();
559 12 : }
560 12 : }
561 :
562 1 : void LngSvcMgr::disposing(const lang::EventObject&)
563 : throw (uno::RuntimeException)
564 : {
565 1 : stopListening();
566 1 : }
567 :
568 44 : void LngSvcMgr::clearSvcInfoArray(SvcInfoArray* &rpInfo)
569 : {
570 44 : delete rpInfo;
571 44 : rpInfo = NULL;
572 44 : }
573 :
574 33 : LngSvcMgr::~LngSvcMgr()
575 : {
576 11 : stopListening();
577 :
578 : // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper
579 : // will be freed in the destructor of the respective Reference's
580 : // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp
581 :
582 11 : clearSvcInfoArray(pAvailSpellSvcs);
583 11 : clearSvcInfoArray(pAvailGrammarSvcs);
584 11 : clearSvcInfoArray(pAvailHyphSvcs);
585 11 : clearSvcInfoArray(pAvailThesSvcs);
586 22 : }
587 :
588 : namespace
589 : {
590 : using lang::Locale;
591 : using uno::Any;
592 : using uno::Sequence;
593 :
594 0 : sal_Bool lcl_FindEntry( const OUString &rEntry, const Sequence< OUString > &rCfgSvcs )
595 : {
596 0 : sal_Int32 nRes = -1;
597 0 : sal_Int32 nEntries = rCfgSvcs.getLength();
598 0 : const OUString *pEntry = rCfgSvcs.getConstArray();
599 0 : for (sal_Int32 i = 0; i < nEntries && nRes == -1; ++i)
600 : {
601 0 : if (rEntry == pEntry[i])
602 0 : nRes = i;
603 : }
604 0 : return nRes != -1;
605 : }
606 :
607 0 : Sequence< OUString > lcl_GetLastFoundSvcs(
608 : SvtLinguConfig &rCfg,
609 : const OUString &rLastFoundList ,
610 : const Locale &rAvailLocale )
611 : {
612 0 : Sequence< OUString > aRes;
613 :
614 0 : OUString aCfgLocaleStr( LanguageTag( rAvailLocale ).getBcp47() );
615 :
616 0 : Sequence< OUString > aNodeNames( rCfg.GetNodeNames(rLastFoundList) );
617 0 : sal_Bool bFound = lcl_FindEntry( aCfgLocaleStr, aNodeNames);
618 :
619 0 : if (bFound)
620 : {
621 0 : Sequence< OUString > aNames(1);
622 0 : OUString &rNodeName = aNames.getArray()[0];
623 0 : rNodeName = rLastFoundList;
624 0 : rNodeName += OUString::valueOf( (sal_Unicode)'/' );
625 0 : rNodeName += aCfgLocaleStr;
626 0 : Sequence< Any > aValues( rCfg.GetProperties( aNames ) );
627 0 : if (aValues.getLength())
628 : {
629 : OSL_ENSURE( aValues.getLength() == 1, "unexpected length of sequence" );
630 0 : Sequence< OUString > aSvcImplNames;
631 0 : if (aValues.getConstArray()[0] >>= aSvcImplNames)
632 0 : aRes = aSvcImplNames;
633 : else
634 : {
635 : OSL_FAIL( "type mismatch" );
636 0 : }
637 0 : }
638 : }
639 :
640 0 : return aRes;
641 : }
642 :
643 0 : Sequence< OUString > lcl_RemoveMissingEntries(
644 : const Sequence< OUString > &rCfgSvcs,
645 : const Sequence< OUString > &rAvailSvcs )
646 : {
647 0 : Sequence< OUString > aRes( rCfgSvcs.getLength() );
648 0 : OUString *pRes = aRes.getArray();
649 0 : sal_Int32 nCnt = 0;
650 :
651 0 : sal_Int32 nEntries = rCfgSvcs.getLength();
652 0 : const OUString *pEntry = rCfgSvcs.getConstArray();
653 0 : for (sal_Int32 i = 0; i < nEntries; ++i)
654 : {
655 0 : if (!pEntry[i].isEmpty() && lcl_FindEntry( pEntry[i], rAvailSvcs ))
656 0 : pRes[ nCnt++ ] = pEntry[i];
657 : }
658 :
659 0 : aRes.realloc( nCnt );
660 0 : return aRes;
661 : }
662 :
663 0 : Sequence< OUString > lcl_GetNewEntries(
664 : const Sequence< OUString > &rLastFoundSvcs,
665 : const Sequence< OUString > &rAvailSvcs )
666 : {
667 0 : sal_Int32 nLen = rAvailSvcs.getLength();
668 0 : Sequence< OUString > aRes( nLen );
669 0 : OUString *pRes = aRes.getArray();
670 0 : sal_Int32 nCnt = 0;
671 :
672 0 : const OUString *pEntry = rAvailSvcs.getConstArray();
673 0 : for (sal_Int32 i = 0; i < nLen; ++i)
674 : {
675 0 : if (!pEntry[i].isEmpty() && !lcl_FindEntry( pEntry[i], rLastFoundSvcs ))
676 0 : pRes[ nCnt++ ] = pEntry[i];
677 : }
678 :
679 0 : aRes.realloc( nCnt );
680 0 : return aRes;
681 : }
682 :
683 0 : Sequence< OUString > lcl_MergeSeq(
684 : const Sequence< OUString > &rCfgSvcs,
685 : const Sequence< OUString > &rNewSvcs )
686 : {
687 0 : Sequence< OUString > aRes( rCfgSvcs.getLength() + rNewSvcs.getLength() );
688 0 : OUString *pRes = aRes.getArray();
689 0 : sal_Int32 nCnt = 0;
690 :
691 0 : for (sal_Int32 k = 0; k < 2; ++k)
692 : {
693 : // add previously configuerd service first and append
694 : // new found services at the end
695 0 : const Sequence< OUString > &rSeq = k == 0 ? rCfgSvcs : rNewSvcs;
696 :
697 0 : sal_Int32 nLen = rSeq.getLength();
698 0 : const OUString *pEntry = rSeq.getConstArray();
699 0 : for (sal_Int32 i = 0; i < nLen; ++i)
700 : {
701 0 : if (!pEntry[i].isEmpty() && !lcl_FindEntry( pEntry[i], aRes ))
702 0 : pRes[ nCnt++ ] = pEntry[i];
703 : }
704 : }
705 :
706 0 : aRes.realloc( nCnt );
707 0 : return aRes;
708 : }
709 : }
710 :
711 11 : void LngSvcMgr::UpdateAll()
712 : {
713 : using beans::PropertyValue;
714 : using lang::Locale;
715 : using uno::Sequence;
716 :
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;
720 :
721 11 : SvtLinguConfig aCfg;
722 :
723 11 : const int nNumServices = 4;
724 11 : const sal_Char * apServices[nNumServices] = { SN_SPELLCHECKER, SN_GRAMMARCHECKER, SN_HYPHENATOR, SN_THESAURUS };
725 11 : const sal_Char * apCurLists[nNumServices] = { "ServiceManager/SpellCheckerList", "ServiceManager/GrammarCheckerList", "ServiceManager/HyphenatorList", "ServiceManager/ThesaurusList" };
726 11 : const sal_Char * apLastFoundLists[nNumServices] = { "ServiceManager/LastFoundSpellCheckers", "ServiceManager/LastFoundGrammarCheckers", "ServiceManager/LastFoundHyphenators", "ServiceManager/LastFoundThesauri" };
727 :
728 : // usage of indices as above: 0 = spell checker, 1 = grammar checker, 2 = hyphenator, 3 = thesaurus
729 11 : std::vector< list_entry_map_t > aLastFoundSvcs(nNumServices);
730 11 : std::vector< list_entry_map_t > aCurSvcs(nNumServices);
731 :
732 55 : for (int k = 0; k < nNumServices; ++k)
733 : {
734 44 : OUString aService( ::rtl::OUString::createFromAscii( apServices[k] ) );
735 44 : OUString aActiveList( ::rtl::OUString::createFromAscii( apCurLists[k] ) );
736 44 : OUString aLastFoundList( ::rtl::OUString::createFromAscii( apLastFoundLists[k] ) );
737 : sal_Int32 i;
738 :
739 : //
740 : // remove configured but not available language/services entries
741 : //
742 44 : Sequence< OUString > aNodeNames( aCfg.GetNodeNames( aActiveList ) ); // list of configured locales
743 44 : sal_Int32 nNodeNames = aNodeNames.getLength();
744 44 : const OUString *pNodeName = aNodeNames.getConstArray();
745 44 : for (i = 0; i < nNodeNames; ++i)
746 : {
747 0 : Locale aLocale( LanguageTag( pNodeName[i]).getLocale() );
748 0 : Sequence< OUString > aCfgSvcs( getConfiguredServices( aService, aLocale ));
749 0 : Sequence< OUString > aAvailSvcs( getAvailableServices( aService, aLocale ));
750 :
751 0 : aCfgSvcs = lcl_RemoveMissingEntries( aCfgSvcs, aAvailSvcs );
752 :
753 0 : aCurSvcs[k][ pNodeName[i] ] = aCfgSvcs;
754 0 : }
755 :
756 : //
757 : // add new available language/service entries
758 : // and
759 : // set last found services to currently available ones
760 : //
761 44 : Sequence< Locale > aAvailLocales( getAvailableLocales(aService) );
762 44 : sal_Int32 nAvailLocales = aAvailLocales.getLength();
763 44 : const Locale *pAvailLocale = aAvailLocales.getConstArray();
764 44 : for (i = 0; i < nAvailLocales; ++i)
765 : {
766 0 : OUString aCfgLocaleStr( LanguageTag( pAvailLocale[i] ).getBcp47() );
767 :
768 0 : Sequence< OUString > aAvailSvcs( getAvailableServices( aService, pAvailLocale[i] ));
769 :
770 0 : aLastFoundSvcs[k][ aCfgLocaleStr ] = aAvailSvcs;
771 :
772 : Sequence< OUString > aLastSvcs(
773 0 : lcl_GetLastFoundSvcs( aCfg, aLastFoundList , pAvailLocale[i] ));
774 : Sequence< OUString > aNewSvcs =
775 0 : lcl_GetNewEntries( aLastSvcs, aAvailSvcs );
776 :
777 0 : Sequence< OUString > aCfgSvcs( aCurSvcs[k][ aCfgLocaleStr ] );
778 :
779 : // merge services list (previously configured to be listed first).
780 0 : aCfgSvcs = lcl_MergeSeq( aCfgSvcs, aNewSvcs );
781 :
782 0 : aCurSvcs[k][ aCfgLocaleStr ] = aCfgSvcs;
783 0 : }
784 44 : }
785 :
786 : //
787 : // write new data back to configuration
788 : //
789 55 : for (int k = 0; k < nNumServices; ++k)
790 : {
791 132 : for (int i = 0; i < 2; ++i)
792 : {
793 88 : const sal_Char *pSubNodeName = (i == 0) ? apCurLists[k] : apLastFoundLists[k];
794 88 : OUString aSubNodeName( ::rtl::OUString::createFromAscii(pSubNodeName) );
795 :
796 88 : list_entry_map_t &rCurMap = (i == 0) ? aCurSvcs[k] : aLastFoundSvcs[k];
797 88 : list_entry_map_t::const_iterator aIt( rCurMap.begin() );
798 88 : sal_Int32 nVals = static_cast< sal_Int32 >( rCurMap.size() );
799 88 : Sequence< PropertyValue > aNewValues( nVals );
800 88 : PropertyValue *pNewValue = aNewValues.getArray();
801 176 : while (aIt != rCurMap.end())
802 : {
803 0 : OUString aCfgEntryName( aSubNodeName );
804 0 : aCfgEntryName += OUString::valueOf( (sal_Unicode) '/' );
805 0 : aCfgEntryName += (*aIt).first;
806 :
807 0 : pNewValue->Name = aCfgEntryName;
808 0 : pNewValue->Value <<= (*aIt).second;
809 0 : ++pNewValue;
810 0 : ++aIt;
811 0 : }
812 : OSL_ENSURE( pNewValue - aNewValues.getArray() == nVals,
813 : "possible mismatch of sequence size and property number" );
814 :
815 : {
816 : // add new or replace existing entries.
817 88 : sal_Bool bRes = aCfg.ReplaceSetProperties( aSubNodeName, aNewValues );
818 : if (!bRes)
819 : {
820 : #if OSL_DEBUG_LEVEL > 1
821 : OSL_FAIL( "failed to set new configuration values" );
822 : #endif
823 : }
824 : }
825 88 : }
826 11 : }
827 :
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.
831 11 : }
832 :
833 0 : void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames )
834 : {
835 0 : const OUString aSpellCheckerList( "ServiceManager/SpellCheckerList" );
836 0 : const OUString aGrammarCheckerList( "ServiceManager/GrammarCheckerList" );
837 0 : const OUString aHyphenatorList( "ServiceManager/HyphenatorList" );
838 0 : const OUString aThesaurusList( "ServiceManager/ThesaurusList" );
839 :
840 0 : const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) );
841 0 : const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) );
842 0 : const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) );
843 0 : const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) );
844 :
845 0 : uno::Sequence< uno::Any > aValues;
846 0 : uno::Sequence< OUString > aNames( 1 );
847 0 : OUString *pNames = aNames.getArray();
848 :
849 0 : sal_Int32 nLen = rPropertyNames.getLength();
850 0 : const OUString *pPropertyNames = rPropertyNames.getConstArray();
851 0 : for (sal_Int32 i = 0; i < nLen; ++i)
852 : {
853 : // property names look like
854 : // "ServiceManager/ThesaurusList/de-CH"
855 :
856 0 : const OUString &rName = pPropertyNames[i];
857 : sal_Int32 nKeyStart;
858 0 : nKeyStart = rName.lastIndexOf( '/' );
859 0 : OUString aKeyText;
860 0 : if (nKeyStart != -1)
861 0 : aKeyText = rName.copy( nKeyStart + 1 );
862 : DBG_ASSERT( !aKeyText.isEmpty(), "unexpected key (lang::Locale) string" );
863 0 : if (0 == rName.compareTo( aSpellCheckerList, aSpellCheckerList.getLength() ))
864 : {
865 : // delete old cached data, needs to be acquired new on demand
866 0 : clearSvcInfoArray(pAvailSpellSvcs);
867 :
868 0 : OUString aNode( aSpellCheckerList );
869 0 : if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText ))
870 : {
871 0 : OUString aPropName( aNode );
872 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
873 0 : aPropName += aKeyText;
874 0 : pNames[0] = aPropName;
875 0 : aValues = /*aCfg.*/GetProperties( aNames );
876 0 : uno::Sequence< OUString > aSvcImplNames;
877 0 : if (aValues.getLength())
878 0 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
879 :
880 0 : LanguageType nLang = LANGUAGE_NONE;
881 0 : if (!aKeyText.isEmpty())
882 0 : nLang = LanguageTag( aKeyText ).getLanguageType();
883 :
884 0 : GetSpellCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
885 0 : pSpellDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
886 0 : }
887 : }
888 0 : else if (0 == rName.compareTo( aGrammarCheckerList, aGrammarCheckerList.getLength() ))
889 : {
890 : // delete old cached data, needs to be acquired new on demand
891 0 : clearSvcInfoArray(pAvailGrammarSvcs);
892 :
893 0 : OUString aNode( aGrammarCheckerList );
894 0 : if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText ))
895 : {
896 0 : OUString aPropName( aNode );
897 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
898 0 : aPropName += aKeyText;
899 0 : pNames[0] = aPropName;
900 0 : aValues = /*aCfg.*/GetProperties( aNames );
901 0 : uno::Sequence< OUString > aSvcImplNames;
902 0 : if (aValues.getLength())
903 0 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
904 :
905 0 : LanguageType nLang = LANGUAGE_NONE;
906 0 : if (!aKeyText.isEmpty())
907 0 : nLang = LanguageTag( aKeyText ).getLanguageType();
908 :
909 0 : if (SvtLinguConfig().HasGrammarChecker())
910 : {
911 0 : GetGrammarCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
912 0 : pGrammarDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
913 0 : }
914 0 : }
915 : }
916 0 : else if (0 == rName.compareTo( aHyphenatorList, aHyphenatorList.getLength() ))
917 : {
918 : // delete old cached data, needs to be acquired new on demand
919 0 : clearSvcInfoArray(pAvailHyphSvcs);
920 :
921 0 : OUString aNode( aHyphenatorList );
922 0 : if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText ))
923 : {
924 0 : OUString aPropName( aNode );
925 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
926 0 : aPropName += aKeyText;
927 0 : pNames[0] = aPropName;
928 0 : aValues = /*aCfg.*/GetProperties( aNames );
929 0 : uno::Sequence< OUString > aSvcImplNames;
930 0 : if (aValues.getLength())
931 0 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
932 :
933 0 : LanguageType nLang = LANGUAGE_NONE;
934 0 : if (!aKeyText.isEmpty())
935 0 : nLang = LanguageTag( aKeyText ).getLanguageType();
936 :
937 0 : GetHyphenatorDsp_Impl( sal_False ); // don't set service list, it will be done below
938 0 : pHyphDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
939 0 : }
940 : }
941 0 : else if (0 == rName.compareTo( aThesaurusList, aThesaurusList.getLength() ))
942 : {
943 : // delete old cached data, needs to be acquired new on demand
944 0 : clearSvcInfoArray(pAvailThesSvcs);
945 :
946 0 : OUString aNode( aThesaurusList );
947 0 : if (lcl_SeqHasString( aThesaurusListEntries, aKeyText ))
948 : {
949 0 : OUString aPropName( aNode );
950 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
951 0 : aPropName += aKeyText;
952 0 : pNames[0] = aPropName;
953 0 : aValues = /*aCfg.*/GetProperties( aNames );
954 0 : uno::Sequence< OUString > aSvcImplNames;
955 0 : if (aValues.getLength())
956 0 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
957 :
958 0 : LanguageType nLang = LANGUAGE_NONE;
959 0 : if (!aKeyText.isEmpty())
960 0 : nLang = LanguageTag( aKeyText ).getLanguageType();
961 :
962 0 : GetThesaurusDsp_Impl( sal_False ); // don't set service list, it will be done below
963 0 : pThesDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
964 0 : }
965 : }
966 : else
967 : {
968 : DBG_ASSERT( 0, "nofified for unexpected property" );
969 : }
970 0 : }
971 0 : }
972 :
973 :
974 0 : void LngSvcMgr::Commit()
975 : {
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.
979 0 : }
980 :
981 :
982 7 : void LngSvcMgr::GetListenerHelper_Impl()
983 : {
984 7 : if (!pListenerHelper)
985 : {
986 7 : pListenerHelper = new LngSvcMgrListenerHelper( *this, linguistic::GetDictionaryList() );
987 7 : xListenerHelper = (linguistic2::XLinguServiceEventListener *) pListenerHelper;
988 : }
989 7 : }
990 :
991 :
992 6 : void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList )
993 : {
994 6 : if (!pSpellDsp)
995 : {
996 6 : pSpellDsp = new SpellCheckerDispatcher( *this );
997 6 : xSpellDsp = pSpellDsp;
998 6 : if (bSetSvcList)
999 6 : SetCfgServiceLists( *pSpellDsp );
1000 : }
1001 6 : }
1002 :
1003 :
1004 0 : void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList )
1005 : {
1006 0 : if (!pGrammarDsp && SvtLinguConfig().HasGrammarChecker())
1007 : {
1008 : //! since the grammar checking iterator needs to be a one instance service
1009 : //! we need to create it the correct way!
1010 0 : uno::Reference< linguistic2::XProofreadingIterator > xGCI;
1011 : try
1012 : {
1013 : uno::Reference< lang::XMultiServiceFactory > xMgr(
1014 0 : comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
1015 : xGCI = uno::Reference< linguistic2::XProofreadingIterator >(
1016 0 : xMgr->createInstance( SN_GRAMMARCHECKINGITERATOR ), uno::UNO_QUERY_THROW );
1017 : }
1018 0 : catch (uno::Exception &)
1019 : {
1020 : }
1021 : DBG_ASSERT( xGCI.is(), "instantiating grammar checking iterator failed" );
1022 :
1023 0 : if (xGCI.is())
1024 : {
1025 0 : pGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get());
1026 0 : xGrammarDsp = xGCI;
1027 : DBG_ASSERT( pGrammarDsp, "failed to get implementation" );
1028 0 : if (bSetSvcList)
1029 0 : SetCfgServiceLists( *pGrammarDsp );
1030 0 : }
1031 : }
1032 0 : }
1033 :
1034 :
1035 7 : void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList )
1036 : {
1037 7 : if (!pHyphDsp)
1038 : {
1039 7 : pHyphDsp = new HyphenatorDispatcher( *this );
1040 7 : xHyphDsp = pHyphDsp;
1041 7 : if (bSetSvcList)
1042 7 : SetCfgServiceLists( *pHyphDsp );
1043 : }
1044 7 : }
1045 :
1046 :
1047 0 : void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList )
1048 : {
1049 0 : if (!pThesDsp)
1050 : {
1051 0 : pThesDsp = new ThesaurusDispatcher;
1052 0 : xThesDsp = pThesDsp;
1053 0 : if (bSetSvcList)
1054 0 : SetCfgServiceLists( *pThesDsp );
1055 : }
1056 0 : }
1057 :
1058 :
1059 11 : void LngSvcMgr::GetAvailableSpellSvcs_Impl()
1060 : {
1061 11 : if (!pAvailSpellSvcs)
1062 : {
1063 11 : pAvailSpellSvcs = new SvcInfoArray;
1064 :
1065 11 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1066 11 : if (xFac.is())
1067 : {
1068 11 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1069 11 : uno::Reference< container::XEnumeration > xEnum;
1070 11 : if (xEnumAccess.is())
1071 11 : xEnum = xEnumAccess->createContentEnumeration( SN_SPELLCHECKER );
1072 :
1073 11 : if (xEnum.is())
1074 : {
1075 22 : while (xEnum->hasMoreElements())
1076 : {
1077 0 : uno::Any aCurrent = xEnum->nextElement();
1078 0 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1079 0 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1080 :
1081 0 : uno::Reference< linguistic2::XSpellChecker > xSvc;
1082 0 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1083 : {
1084 : try
1085 : {
1086 : uno::Reference < uno::XComponentContext > xContext(
1087 0 : comphelper::getComponentContext( xFac ) );
1088 0 : xSvc = uno::Reference< linguistic2::XSpellChecker >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1089 : }
1090 0 : catch (const uno::Exception &)
1091 : {
1092 : DBG_ASSERT( 0, "createInstance failed" );
1093 : }
1094 : }
1095 :
1096 0 : if (xSvc.is())
1097 : {
1098 0 : OUString aImplName;
1099 0 : uno::Sequence< sal_Int16 > aLanguages;
1100 0 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1101 0 : if (xInfo.is())
1102 0 : aImplName = xInfo->getImplementationName();
1103 : DBG_ASSERT( !aImplName.isEmpty(),
1104 : "empty implementation name" );
1105 0 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1106 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1107 0 : if (xSuppLoc.is()) {
1108 0 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1109 0 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1110 : }
1111 :
1112 0 : pAvailSpellSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1113 : }
1114 0 : }
1115 11 : }
1116 11 : }
1117 : }
1118 11 : }
1119 :
1120 :
1121 11 : void LngSvcMgr::GetAvailableGrammarSvcs_Impl()
1122 : {
1123 11 : if (!pAvailGrammarSvcs)
1124 : {
1125 11 : pAvailGrammarSvcs = new SvcInfoArray;
1126 :
1127 11 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1128 11 : if (xFac.is())
1129 : {
1130 11 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1131 11 : uno::Reference< container::XEnumeration > xEnum;
1132 11 : if (xEnumAccess.is())
1133 11 : xEnum = xEnumAccess->createContentEnumeration( SN_GRAMMARCHECKER );
1134 :
1135 11 : if (xEnum.is())
1136 : {
1137 22 : while (xEnum->hasMoreElements())
1138 : {
1139 0 : uno::Any aCurrent = xEnum->nextElement();
1140 0 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1141 0 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1142 :
1143 0 : uno::Reference< linguistic2::XProofreader > xSvc;
1144 0 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1145 : {
1146 : try
1147 : {
1148 : uno::Reference < uno::XComponentContext > xContext(
1149 0 : comphelper::getComponentContext( xFac ) );
1150 0 : xSvc = uno::Reference< linguistic2::XProofreader >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1151 : }
1152 0 : catch (const uno::Exception &)
1153 : {
1154 : DBG_ASSERT( 0, "createInstance failed" );
1155 : }
1156 : }
1157 :
1158 0 : if (xSvc.is())
1159 : {
1160 0 : OUString aImplName;
1161 0 : uno::Sequence< sal_Int16 > aLanguages;
1162 0 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1163 0 : if (xInfo.is())
1164 0 : aImplName = xInfo->getImplementationName();
1165 : DBG_ASSERT( !aImplName.isEmpty(),
1166 : "empty implementation name" );
1167 0 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1168 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1169 0 : if (xSuppLoc.is()) {
1170 0 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1171 0 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1172 : }
1173 :
1174 0 : pAvailGrammarSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1175 : }
1176 0 : }
1177 11 : }
1178 11 : }
1179 : }
1180 11 : }
1181 :
1182 :
1183 11 : void LngSvcMgr::GetAvailableHyphSvcs_Impl()
1184 : {
1185 11 : if (!pAvailHyphSvcs)
1186 : {
1187 11 : pAvailHyphSvcs = new SvcInfoArray;
1188 11 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1189 11 : if (xFac.is())
1190 : {
1191 11 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1192 11 : uno::Reference< container::XEnumeration > xEnum;
1193 11 : if (xEnumAccess.is())
1194 11 : xEnum = xEnumAccess->createContentEnumeration( SN_HYPHENATOR );
1195 :
1196 11 : if (xEnum.is())
1197 : {
1198 22 : while (xEnum->hasMoreElements())
1199 : {
1200 0 : uno::Any aCurrent = xEnum->nextElement();
1201 0 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1202 0 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1203 :
1204 0 : uno::Reference< linguistic2::XHyphenator > xSvc;
1205 0 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1206 : {
1207 : try
1208 : {
1209 : uno::Reference < uno::XComponentContext > xContext(
1210 0 : comphelper::getComponentContext( xFac ) );
1211 0 : xSvc = uno::Reference< linguistic2::XHyphenator >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1212 :
1213 : }
1214 0 : catch (const uno::Exception &)
1215 : {
1216 : DBG_ASSERT( 0, "createInstance failed" );
1217 : }
1218 : }
1219 :
1220 0 : if (xSvc.is())
1221 : {
1222 0 : OUString aImplName;
1223 0 : uno::Sequence< sal_Int16 > aLanguages;
1224 0 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1225 0 : if (xInfo.is())
1226 0 : aImplName = xInfo->getImplementationName();
1227 : DBG_ASSERT( !aImplName.isEmpty(),
1228 : "empty implementation name" );
1229 0 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1230 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1231 0 : if (xSuppLoc.is()) {
1232 0 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1233 0 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1234 : }
1235 :
1236 0 : pAvailHyphSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1237 : }
1238 0 : }
1239 11 : }
1240 11 : }
1241 : }
1242 11 : }
1243 :
1244 :
1245 11 : void LngSvcMgr::GetAvailableThesSvcs_Impl()
1246 : {
1247 11 : if (!pAvailThesSvcs)
1248 : {
1249 11 : pAvailThesSvcs = new SvcInfoArray;
1250 :
1251 11 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1252 11 : if (xFac.is())
1253 : {
1254 11 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1255 11 : uno::Reference< container::XEnumeration > xEnum;
1256 11 : if (xEnumAccess.is())
1257 11 : xEnum = xEnumAccess->createContentEnumeration( SN_THESAURUS );
1258 :
1259 11 : if (xEnum.is())
1260 : {
1261 22 : while (xEnum->hasMoreElements())
1262 : {
1263 0 : uno::Any aCurrent = xEnum->nextElement();
1264 :
1265 0 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1266 0 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1267 :
1268 0 : uno::Reference< linguistic2::XThesaurus > xSvc;
1269 0 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1270 : {
1271 : try
1272 : {
1273 : uno::Reference < uno::XComponentContext > xContext(
1274 0 : comphelper::getComponentContext( xFac ) );
1275 0 : xSvc = uno::Reference< linguistic2::XThesaurus >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1276 : }
1277 0 : catch (const uno::Exception &)
1278 : {
1279 : DBG_ASSERT( 0, "createInstance failed" );
1280 : }
1281 : }
1282 :
1283 0 : if (xSvc.is())
1284 : {
1285 0 : OUString aImplName;
1286 0 : uno::Sequence< sal_Int16 > aLanguages;
1287 0 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1288 0 : if (xInfo.is())
1289 0 : aImplName = xInfo->getImplementationName();
1290 : DBG_ASSERT( !aImplName.isEmpty(),
1291 : "empty implementation name" );
1292 0 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1293 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1294 0 : if (xSuppLoc.is()) {
1295 0 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1296 0 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1297 : }
1298 :
1299 0 : pAvailThesSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1300 : }
1301 0 : }
1302 11 : }
1303 11 : }
1304 : }
1305 11 : }
1306 :
1307 :
1308 6 : void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher &rSpellDsp )
1309 : {
1310 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" );
1311 :
1312 6 : rtl::OUString aNode("ServiceManager/SpellCheckerList");
1313 6 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1314 6 : OUString *pNames = aNames.getArray();
1315 6 : sal_Int32 nLen = aNames.getLength();
1316 :
1317 : // append path prefix need for 'GetProperties' call below
1318 6 : String aPrefix( aNode );
1319 6 : aPrefix.Append( (sal_Unicode) '/' );
1320 6 : for (int i = 0; i < nLen; ++i)
1321 : {
1322 0 : OUString aTmp( aPrefix );
1323 0 : aTmp += pNames[i];
1324 0 : pNames[i] = aTmp;
1325 0 : }
1326 :
1327 6 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1328 6 : if (nLen && nLen == aValues.getLength())
1329 : {
1330 0 : const uno::Any *pValues = aValues.getConstArray();
1331 0 : for (sal_Int32 i = 0; i < nLen; ++i)
1332 : {
1333 0 : uno::Sequence< OUString > aSvcImplNames;
1334 0 : if (pValues[i] >>= aSvcImplNames)
1335 : {
1336 0 : String aLocaleStr( pNames[i] );
1337 0 : xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1338 0 : aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1339 0 : rSpellDsp.SetServiceList( LanguageTag(aLocaleStr).getLocale(), aSvcImplNames );
1340 : }
1341 0 : }
1342 6 : }
1343 6 : }
1344 :
1345 :
1346 0 : void LngSvcMgr::SetCfgServiceLists( GrammarCheckingIterator &rGrammarDsp )
1347 : {
1348 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" );
1349 :
1350 0 : rtl::OUString aNode("ServiceManager/GrammarCheckerList");
1351 0 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1352 0 : OUString *pNames = aNames.getArray();
1353 0 : sal_Int32 nLen = aNames.getLength();
1354 :
1355 : // append path prefix need for 'GetProperties' call below
1356 0 : String aPrefix( aNode );
1357 0 : aPrefix.Append( (sal_Unicode) '/' );
1358 0 : for (int i = 0; i < nLen; ++i)
1359 : {
1360 0 : OUString aTmp( aPrefix );
1361 0 : aTmp += pNames[i];
1362 0 : pNames[i] = aTmp;
1363 0 : }
1364 :
1365 0 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1366 0 : if (nLen && nLen == aValues.getLength())
1367 : {
1368 0 : const uno::Any *pValues = aValues.getConstArray();
1369 0 : for (sal_Int32 i = 0; i < nLen; ++i)
1370 : {
1371 0 : uno::Sequence< OUString > aSvcImplNames;
1372 0 : if (pValues[i] >>= aSvcImplNames)
1373 : {
1374 : // there should only be one grammar checker in use per language...
1375 0 : if (aSvcImplNames.getLength() > 1)
1376 0 : aSvcImplNames.realloc(1);
1377 :
1378 0 : String aLocaleStr( pNames[i] );
1379 0 : xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1380 0 : aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1381 0 : rGrammarDsp.SetServiceList( LanguageTag(aLocaleStr).getLocale(), aSvcImplNames );
1382 : }
1383 0 : }
1384 0 : }
1385 0 : }
1386 :
1387 :
1388 7 : void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher &rHyphDsp )
1389 : {
1390 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" );
1391 :
1392 7 : rtl::OUString aNode("ServiceManager/HyphenatorList");
1393 7 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1394 7 : OUString *pNames = aNames.getArray();
1395 7 : sal_Int32 nLen = aNames.getLength();
1396 :
1397 : // append path prefix need for 'GetProperties' call below
1398 7 : String aPrefix( aNode );
1399 7 : aPrefix.Append( (sal_Unicode) '/' );
1400 7 : for (int i = 0; i < nLen; ++i)
1401 : {
1402 0 : OUString aTmp( aPrefix );
1403 0 : aTmp += pNames[i];
1404 0 : pNames[i] = aTmp;
1405 0 : }
1406 :
1407 7 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1408 7 : if (nLen && nLen == aValues.getLength())
1409 : {
1410 0 : const uno::Any *pValues = aValues.getConstArray();
1411 0 : for (sal_Int32 i = 0; i < nLen; ++i)
1412 : {
1413 0 : uno::Sequence< OUString > aSvcImplNames;
1414 0 : if (pValues[i] >>= aSvcImplNames)
1415 : {
1416 : // there should only be one hyphenator in use per language...
1417 0 : if (aSvcImplNames.getLength() > 1)
1418 0 : aSvcImplNames.realloc(1);
1419 :
1420 0 : String aLocaleStr( pNames[i] );
1421 0 : xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1422 0 : aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1423 0 : rHyphDsp.SetServiceList( LanguageTag(aLocaleStr).getLocale(), aSvcImplNames );
1424 : }
1425 0 : }
1426 7 : }
1427 7 : }
1428 :
1429 :
1430 0 : void LngSvcMgr::SetCfgServiceLists( ThesaurusDispatcher &rThesDsp )
1431 : {
1432 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" );
1433 :
1434 0 : rtl::OUString aNode("ServiceManager/ThesaurusList");
1435 0 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1436 0 : OUString *pNames = aNames.getArray();
1437 0 : sal_Int32 nLen = aNames.getLength();
1438 :
1439 : // append path prefix need for 'GetProperties' call below
1440 0 : String aPrefix( aNode );
1441 0 : aPrefix.Append( (sal_Unicode) '/' );
1442 0 : for (int i = 0; i < nLen; ++i)
1443 : {
1444 0 : OUString aTmp( aPrefix );
1445 0 : aTmp += pNames[i];
1446 0 : pNames[i] = aTmp;
1447 0 : }
1448 :
1449 0 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1450 0 : if (nLen && nLen == aValues.getLength())
1451 : {
1452 0 : const uno::Any *pValues = aValues.getConstArray();
1453 0 : for (sal_Int32 i = 0; i < nLen; ++i)
1454 : {
1455 0 : uno::Sequence< OUString > aSvcImplNames;
1456 0 : if (pValues[i] >>= aSvcImplNames)
1457 : {
1458 0 : String aLocaleStr( pNames[i] );
1459 0 : xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1460 0 : aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1461 0 : rThesDsp.SetServiceList( LanguageTag(aLocaleStr).getLocale(), aSvcImplNames );
1462 : }
1463 0 : }
1464 0 : }
1465 0 : }
1466 :
1467 :
1468 : uno::Reference< linguistic2::XSpellChecker > SAL_CALL
1469 6 : LngSvcMgr::getSpellChecker()
1470 : throw(uno::RuntimeException)
1471 : {
1472 6 : osl::MutexGuard aGuard( GetLinguMutex() );
1473 : #if OSL_DEBUG_LEVEL > 1
1474 : getAvailableLocales( SN_SPELLCHECKER );
1475 : #endif
1476 :
1477 6 : uno::Reference< linguistic2::XSpellChecker > xRes;
1478 6 : if (!bDisposing)
1479 : {
1480 6 : if (!xSpellDsp.is())
1481 6 : GetSpellCheckerDsp_Impl();
1482 6 : xRes = xSpellDsp;
1483 : }
1484 6 : return xRes;
1485 : }
1486 :
1487 :
1488 : uno::Reference< linguistic2::XHyphenator > SAL_CALL
1489 1135 : LngSvcMgr::getHyphenator()
1490 : throw(uno::RuntimeException)
1491 : {
1492 1135 : osl::MutexGuard aGuard( GetLinguMutex() );
1493 : #if OSL_DEBUG_LEVEL > 1
1494 : getAvailableLocales( SN_HYPHENATOR );
1495 : #endif
1496 :
1497 1135 : uno::Reference< linguistic2::XHyphenator > xRes;
1498 1135 : if (!bDisposing)
1499 : {
1500 1135 : if (!xHyphDsp.is())
1501 7 : GetHyphenatorDsp_Impl();
1502 1135 : xRes = xHyphDsp;
1503 : }
1504 1135 : return xRes;
1505 : }
1506 :
1507 :
1508 : uno::Reference< linguistic2::XThesaurus > SAL_CALL
1509 0 : LngSvcMgr::getThesaurus()
1510 : throw(uno::RuntimeException)
1511 : {
1512 0 : osl::MutexGuard aGuard( GetLinguMutex() );
1513 : #if OSL_DEBUG_LEVEL > 1
1514 : getAvailableLocales( SN_THESAURUS );
1515 : #endif
1516 :
1517 0 : uno::Reference< linguistic2::XThesaurus > xRes;
1518 0 : if (!bDisposing)
1519 : {
1520 0 : if (!xThesDsp.is())
1521 0 : GetThesaurusDsp_Impl();
1522 0 : xRes = xThesDsp;
1523 : }
1524 0 : return xRes;
1525 : }
1526 :
1527 :
1528 : sal_Bool SAL_CALL
1529 7 : LngSvcMgr::addLinguServiceManagerListener(
1530 : const uno::Reference< lang::XEventListener >& xListener )
1531 : throw(uno::RuntimeException)
1532 : {
1533 7 : osl::MutexGuard aGuard( GetLinguMutex() );
1534 :
1535 7 : sal_Bool bRes = sal_False;
1536 7 : if (!bDisposing && xListener.is())
1537 : {
1538 7 : if (!pListenerHelper)
1539 7 : GetListenerHelper_Impl();
1540 7 : bRes = pListenerHelper->AddLngSvcMgrListener( xListener );
1541 : }
1542 7 : return bRes;
1543 : }
1544 :
1545 :
1546 : sal_Bool SAL_CALL
1547 0 : LngSvcMgr::removeLinguServiceManagerListener(
1548 : const uno::Reference< lang::XEventListener >& xListener )
1549 : throw(uno::RuntimeException)
1550 : {
1551 0 : osl::MutexGuard aGuard( GetLinguMutex() );
1552 :
1553 0 : sal_Bool bRes = sal_False;
1554 0 : if (!bDisposing && xListener.is())
1555 : {
1556 : DBG_ASSERT( pListenerHelper, "listener removed without being added" );
1557 0 : if (!pListenerHelper)
1558 0 : GetListenerHelper_Impl();
1559 0 : bRes = pListenerHelper->RemoveLngSvcMgrListener( xListener );
1560 : }
1561 0 : return bRes;
1562 : }
1563 :
1564 :
1565 : uno::Sequence< OUString > SAL_CALL
1566 44 : LngSvcMgr::getAvailableServices(
1567 : const OUString& rServiceName,
1568 : const lang::Locale& rLocale )
1569 : throw(uno::RuntimeException)
1570 : {
1571 44 : osl::MutexGuard aGuard( GetLinguMutex() );
1572 :
1573 44 : uno::Sequence< OUString > aRes;
1574 44 : const SvcInfoArray *pInfoArray = 0;
1575 :
1576 44 : if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1577 : {
1578 11 : GetAvailableSpellSvcs_Impl();
1579 11 : pInfoArray = pAvailSpellSvcs;
1580 : }
1581 33 : else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1582 : {
1583 11 : GetAvailableGrammarSvcs_Impl();
1584 11 : pInfoArray = pAvailGrammarSvcs;
1585 : }
1586 22 : else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1587 : {
1588 11 : GetAvailableHyphSvcs_Impl();
1589 11 : pInfoArray = pAvailHyphSvcs;
1590 : }
1591 11 : else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1592 : {
1593 11 : GetAvailableThesSvcs_Impl();
1594 11 : pInfoArray = pAvailThesSvcs;
1595 : }
1596 :
1597 44 : if (pInfoArray)
1598 : {
1599 : // resize to max number of entries
1600 44 : size_t nMaxCnt = pInfoArray->size();
1601 44 : aRes.realloc( nMaxCnt );
1602 44 : OUString *pImplName = aRes.getArray();
1603 :
1604 44 : sal_uInt16 nCnt = 0;
1605 44 : LanguageType nLanguage = LanguageTag( rLocale ).getLanguageType();
1606 44 : for (size_t i = 0; i < nMaxCnt; ++i)
1607 : {
1608 0 : const SvcInfo &rInfo = (*pInfoArray)[i];
1609 0 : if (LANGUAGE_NONE == nLanguage
1610 0 : || rInfo.HasLanguage( nLanguage ))
1611 : {
1612 0 : pImplName[ nCnt++ ] = rInfo.aSvcImplName;
1613 : }
1614 : }
1615 :
1616 : // resize to actual number of entries
1617 44 : if (nCnt != nMaxCnt)
1618 0 : aRes.realloc( nCnt );
1619 : }
1620 :
1621 44 : return aRes;
1622 : }
1623 :
1624 :
1625 : uno::Sequence< lang::Locale > SAL_CALL
1626 44 : LngSvcMgr::getAvailableLocales(
1627 : const OUString& rServiceName )
1628 : throw(uno::RuntimeException)
1629 : {
1630 44 : osl::MutexGuard aGuard( GetLinguMutex() );
1631 :
1632 44 : uno::Sequence< lang::Locale > aRes;
1633 :
1634 44 : uno::Sequence< lang::Locale > *pAvailLocales = NULL;
1635 44 : if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1636 11 : pAvailLocales = &aAvailSpellLocales;
1637 33 : else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1638 11 : pAvailLocales = &aAvailGrammarLocales;
1639 22 : else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1640 11 : pAvailLocales = &aAvailHyphLocales;
1641 11 : else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1642 11 : pAvailLocales = &aAvailThesLocales;
1643 :
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.
1647 44 : if (pAvailLocales)
1648 : {
1649 44 : *pAvailLocales = GetAvailLocales(getAvailableServices(rServiceName, lang::Locale()));
1650 44 : aRes = *pAvailLocales;
1651 : }
1652 :
1653 44 : return aRes;
1654 : }
1655 :
1656 0 : static sal_Bool IsEqSvcList( const uno::Sequence< OUString > &rList1,
1657 : const uno::Sequence< OUString > &rList2 )
1658 : {
1659 : // returns sal_True iff both sequences are equal
1660 :
1661 0 : sal_Bool bRes = sal_False;
1662 0 : sal_Int32 nLen = rList1.getLength();
1663 0 : if (rList2.getLength() == nLen)
1664 : {
1665 0 : const OUString *pStr1 = rList1.getConstArray();
1666 0 : const OUString *pStr2 = rList2.getConstArray();
1667 0 : bRes = sal_True;
1668 0 : for (sal_Int32 i = 0; i < nLen && bRes; ++i)
1669 : {
1670 0 : if (*pStr1++ != *pStr2++)
1671 0 : bRes = sal_False;
1672 : }
1673 : }
1674 0 : return bRes;
1675 : }
1676 :
1677 :
1678 : void SAL_CALL
1679 0 : LngSvcMgr::setConfiguredServices(
1680 : const OUString& rServiceName,
1681 : const lang::Locale& rLocale,
1682 : const uno::Sequence< OUString >& rServiceImplNames )
1683 : throw(uno::RuntimeException)
1684 : {
1685 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::setConfiguredServices" );
1686 :
1687 0 : osl::MutexGuard aGuard( GetLinguMutex() );
1688 :
1689 : #if OSL_DEBUG_LEVEL > 1
1690 : #endif
1691 :
1692 0 : LanguageType nLanguage = LanguageTag( rLocale ).getLanguageType();
1693 0 : if (LANGUAGE_NONE != nLanguage)
1694 : {
1695 0 : if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1696 : {
1697 0 : if (!xSpellDsp.is())
1698 0 : GetSpellCheckerDsp_Impl();
1699 : sal_Bool bChanged = !IsEqSvcList( rServiceImplNames,
1700 0 : pSpellDsp->GetServiceList( rLocale ) );
1701 0 : if (bChanged)
1702 : {
1703 0 : pSpellDsp->SetServiceList( rLocale, rServiceImplNames );
1704 0 : SaveCfgSvcs( rtl::OUString(SN_SPELLCHECKER) );
1705 :
1706 0 : if (pListenerHelper && bChanged)
1707 : pListenerHelper->AddLngSvcEvt(
1708 : linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN |
1709 0 : linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN );
1710 : }
1711 : }
1712 0 : else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1713 : {
1714 0 : if (!xGrammarDsp.is())
1715 0 : GetGrammarCheckerDsp_Impl();
1716 : sal_Bool bChanged = !IsEqSvcList( rServiceImplNames,
1717 0 : pGrammarDsp->GetServiceList( rLocale ) );
1718 0 : if (bChanged)
1719 : {
1720 0 : pGrammarDsp->SetServiceList( rLocale, rServiceImplNames );
1721 0 : SaveCfgSvcs( rtl::OUString(SN_GRAMMARCHECKER) );
1722 :
1723 0 : if (pListenerHelper && bChanged)
1724 : pListenerHelper->AddLngSvcEvt(
1725 0 : linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN );
1726 : }
1727 : }
1728 0 : else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1729 : {
1730 0 : if (!xHyphDsp.is())
1731 0 : GetHyphenatorDsp_Impl();
1732 : sal_Bool bChanged = !IsEqSvcList( rServiceImplNames,
1733 0 : pHyphDsp->GetServiceList( rLocale ) );
1734 0 : if (bChanged)
1735 : {
1736 0 : pHyphDsp->SetServiceList( rLocale, rServiceImplNames );
1737 0 : SaveCfgSvcs( rtl::OUString(SN_HYPHENATOR) );
1738 :
1739 0 : if (pListenerHelper && bChanged)
1740 : pListenerHelper->AddLngSvcEvt(
1741 0 : linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN );
1742 : }
1743 : }
1744 0 : else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1745 : {
1746 0 : if (!xThesDsp.is())
1747 0 : GetThesaurusDsp_Impl();
1748 : sal_Bool bChanged = !IsEqSvcList( rServiceImplNames,
1749 0 : pThesDsp->GetServiceList( rLocale ) );
1750 0 : if (bChanged)
1751 : {
1752 0 : pThesDsp->SetServiceList( rLocale, rServiceImplNames );
1753 0 : SaveCfgSvcs( rtl::OUString(SN_THESAURUS) );
1754 : }
1755 : }
1756 0 : }
1757 0 : }
1758 :
1759 :
1760 0 : sal_Bool LngSvcMgr::SaveCfgSvcs( const String &rServiceName )
1761 : {
1762 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs" );
1763 :
1764 0 : sal_Bool bRes = sal_False;
1765 :
1766 0 : LinguDispatcher *pDsp = 0;
1767 0 : uno::Sequence< lang::Locale > aLocales;
1768 :
1769 0 : if (0 == rServiceName.CompareToAscii( SN_SPELLCHECKER ))
1770 : {
1771 0 : if (!pSpellDsp)
1772 0 : GetSpellCheckerDsp_Impl();
1773 0 : pDsp = pSpellDsp;
1774 0 : aLocales = getAvailableLocales( SN_SPELLCHECKER );
1775 : }
1776 0 : else if (0 == rServiceName.CompareToAscii( SN_GRAMMARCHECKER ))
1777 : {
1778 0 : if (!pGrammarDsp)
1779 0 : GetGrammarCheckerDsp_Impl();
1780 0 : pDsp = pGrammarDsp;
1781 0 : aLocales = getAvailableLocales( SN_GRAMMARCHECKER );
1782 : }
1783 0 : else if (0 == rServiceName.CompareToAscii( SN_HYPHENATOR ))
1784 : {
1785 0 : if (!pHyphDsp)
1786 0 : GetHyphenatorDsp_Impl();
1787 0 : pDsp = pHyphDsp;
1788 0 : aLocales = getAvailableLocales( SN_HYPHENATOR );
1789 : }
1790 0 : else if (0 == rServiceName.CompareToAscii( SN_THESAURUS ))
1791 : {
1792 0 : if (!pThesDsp)
1793 0 : GetThesaurusDsp_Impl();
1794 0 : pDsp = pThesDsp;
1795 0 : aLocales = getAvailableLocales( SN_THESAURUS );
1796 : }
1797 :
1798 0 : if (pDsp && aLocales.getLength())
1799 : {
1800 0 : sal_Int32 nLen = aLocales.getLength();
1801 0 : const lang::Locale *pLocale = aLocales.getConstArray();
1802 :
1803 0 : uno::Sequence< beans::PropertyValue > aValues( nLen );
1804 0 : beans::PropertyValue *pValues = aValues.getArray();
1805 0 : beans::PropertyValue *pValue = pValues;
1806 :
1807 : // get node name to be used
1808 0 : const char *pNodeName = NULL;
1809 0 : if (pDsp == pSpellDsp)
1810 0 : pNodeName = "ServiceManager/SpellCheckerList";
1811 0 : else if (pDsp == pGrammarDsp)
1812 0 : pNodeName = "ServiceManager/GrammarCheckerList";
1813 0 : else if (pDsp == pHyphDsp)
1814 0 : pNodeName = "ServiceManager/HyphenatorList";
1815 0 : else if (pDsp == pThesDsp)
1816 0 : pNodeName = "ServiceManager/ThesaurusList";
1817 : else
1818 : {
1819 : DBG_ASSERT( 0, "node name missing" );
1820 : }
1821 0 : OUString aNodeName( ::rtl::OUString::createFromAscii(pNodeName) );
1822 :
1823 0 : for (sal_Int32 i = 0; i < nLen; ++i)
1824 : {
1825 0 : uno::Sequence< OUString > aSvcImplNames;
1826 0 : aSvcImplNames = pDsp->GetServiceList( pLocale[i] );
1827 :
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)
1832 : {
1833 : OUString aImplName( pSvcImplName[j] );
1834 : }
1835 : #endif
1836 : // build value to be written back to configuration
1837 0 : uno::Any aCfgAny;
1838 0 : if ((pDsp == pHyphDsp || pDsp == pGrammarDsp) && aSvcImplNames.getLength() > 1)
1839 0 : aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained)
1840 0 : aCfgAny <<= aSvcImplNames;
1841 : DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" );
1842 :
1843 0 : OUString aCfgLocaleStr( LanguageTag( pLocale[i] ).getBcp47() );
1844 0 : pValue->Value = aCfgAny;
1845 0 : pValue->Name = aNodeName;
1846 0 : pValue->Name += OUString::valueOf( (sal_Unicode) '/' );
1847 0 : pValue->Name += aCfgLocaleStr;
1848 0 : pValue++;
1849 0 : }
1850 : {
1851 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" );
1852 : // change, add new or replace existing entries.
1853 0 : bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues );
1854 0 : }
1855 : }
1856 :
1857 0 : return bRes;
1858 : }
1859 :
1860 :
1861 0 : static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal )
1862 : {
1863 0 : uno::Sequence< OUString > aRes;
1864 :
1865 0 : if (rVal.hasValue())
1866 : {
1867 0 : rVal >>= aRes;
1868 : #if OSL_DEBUG_LEVEL > 1
1869 : sal_Int32 nSvcs = aRes.getLength();
1870 : if (nSvcs)
1871 : {
1872 : const OUString *pSvcName = aRes.getConstArray();
1873 : for (sal_Int32 j = 0; j < nSvcs; ++j)
1874 : {
1875 : OUString aImplName( pSvcName[j] );
1876 : DBG_ASSERT( !aImplName.isEmpty(), "service impl-name missing" );
1877 : }
1878 : }
1879 : #endif
1880 : }
1881 :
1882 0 : return aRes;
1883 : }
1884 :
1885 :
1886 0 : static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal )
1887 : {
1888 0 : uno::Sequence< OUString > aRes;
1889 0 : if (!rVal.hasValue())
1890 0 : return aRes;
1891 :
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.
1896 0 : if (rVal >>= aRes)
1897 : {
1898 : // but only the first string should be used.
1899 0 : if (aRes.getLength() > 1)
1900 0 : aRes.realloc(1);
1901 : }
1902 : else
1903 : {
1904 0 : OUString aImplName;
1905 0 : if ((rVal >>= aImplName) && !aImplName.isEmpty())
1906 : {
1907 0 : aRes.realloc(1);
1908 0 : aRes.getArray()[0] = aImplName;
1909 : }
1910 : else
1911 : {
1912 : DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" );
1913 0 : }
1914 : }
1915 :
1916 0 : return aRes;
1917 : }
1918 :
1919 :
1920 :
1921 : uno::Sequence< OUString > SAL_CALL
1922 0 : LngSvcMgr::getConfiguredServices(
1923 : const OUString& rServiceName,
1924 : const lang::Locale& rLocale )
1925 : throw(uno::RuntimeException)
1926 : {
1927 0 : osl::MutexGuard aGuard( GetLinguMutex() );
1928 :
1929 0 : uno::Sequence< OUString > aSvcImplNames;
1930 :
1931 0 : OUString aCfgLocale( LanguageTag( rLocale).getBcp47() );
1932 :
1933 0 : uno::Sequence< uno::Any > aValues;
1934 0 : uno::Sequence< OUString > aNames( 1 );
1935 0 : OUString *pNames = aNames.getArray();
1936 0 : if ( 0 == rServiceName.compareToAscii( SN_SPELLCHECKER ) )
1937 : {
1938 0 : OUString aNode( "ServiceManager/SpellCheckerList");
1939 0 : const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1940 0 : if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1941 : {
1942 0 : OUString aPropName( aNode );
1943 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
1944 0 : aPropName += aCfgLocale;
1945 0 : pNames[0] = aPropName;
1946 0 : aValues = /*aCfg.*/GetProperties( aNames );
1947 0 : if (aValues.getLength())
1948 0 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1949 0 : }
1950 : }
1951 0 : else if ( 0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ) )
1952 : {
1953 0 : OUString aNode( "ServiceManager/GrammarCheckerList");
1954 0 : const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1955 0 : if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1956 : {
1957 0 : OUString aPropName( aNode );
1958 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
1959 0 : aPropName += aCfgLocale;
1960 0 : pNames[0] = aPropName;
1961 0 : aValues = /*aCfg.*/GetProperties( aNames );
1962 0 : if (aValues.getLength())
1963 0 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1964 0 : }
1965 : }
1966 0 : else if ( 0 == rServiceName.compareToAscii( SN_HYPHENATOR ) )
1967 : {
1968 0 : OUString aNode( "ServiceManager/HyphenatorList");
1969 0 : const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1970 0 : if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1971 : {
1972 0 : OUString aPropName( aNode );
1973 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
1974 0 : aPropName += aCfgLocale;
1975 0 : pNames[0] = aPropName;
1976 0 : aValues = /*aCfg.*/GetProperties( aNames );
1977 0 : if (aValues.getLength())
1978 0 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1979 0 : }
1980 : }
1981 0 : else if ( 0 == rServiceName.compareToAscii( SN_THESAURUS ) )
1982 : {
1983 0 : OUString aNode( "ServiceManager/ThesaurusList");
1984 0 : const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1985 0 : if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1986 : {
1987 0 : OUString aPropName( aNode );
1988 0 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
1989 0 : aPropName += aCfgLocale;
1990 0 : pNames[0] = aPropName;
1991 0 : aValues = /*aCfg.*/GetProperties( aNames );
1992 0 : if (aValues.getLength())
1993 0 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1994 0 : }
1995 : }
1996 :
1997 : #if OSL_DEBUG_LEVEL > 1
1998 : const OUString *pImplNames = aSvcImplNames.getConstArray();
1999 : (void) pImplNames;
2000 : #endif
2001 0 : return aSvcImplNames;
2002 : }
2003 :
2004 :
2005 : void SAL_CALL
2006 11 : LngSvcMgr::dispose()
2007 : throw(uno::RuntimeException)
2008 : {
2009 11 : osl::MutexGuard aGuard( GetLinguMutex() );
2010 :
2011 11 : if (!bDisposing)
2012 : {
2013 11 : bDisposing = sal_True;
2014 :
2015 : // require listeners to release this object
2016 11 : lang::EventObject aEvtObj( static_cast<XLinguServiceManager*>(this) );
2017 11 : aEvtListeners.disposeAndClear( aEvtObj );
2018 :
2019 11 : if (pListenerHelper)
2020 7 : pListenerHelper->DisposeAndClear( aEvtObj );
2021 11 : }
2022 11 : }
2023 :
2024 :
2025 : void SAL_CALL
2026 0 : LngSvcMgr::addEventListener(
2027 : const uno::Reference< lang::XEventListener >& xListener )
2028 : throw(uno::RuntimeException)
2029 : {
2030 0 : osl::MutexGuard aGuard( GetLinguMutex() );
2031 :
2032 0 : if (!bDisposing && xListener.is())
2033 : {
2034 0 : aEvtListeners.addInterface( xListener );
2035 0 : }
2036 0 : }
2037 :
2038 :
2039 : void SAL_CALL
2040 0 : LngSvcMgr::removeEventListener(
2041 : const uno::Reference< lang::XEventListener >& xListener )
2042 : throw(uno::RuntimeException)
2043 : {
2044 0 : osl::MutexGuard aGuard( GetLinguMutex() );
2045 :
2046 0 : if (xListener.is())
2047 : {
2048 0 : aEvtListeners.removeInterface( xListener );
2049 0 : }
2050 0 : }
2051 :
2052 :
2053 0 : sal_Bool LngSvcMgr::AddLngSvcEvtBroadcaster(
2054 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
2055 : {
2056 0 : sal_Bool bRes = sal_False;
2057 0 : if (rxBroadcaster.is())
2058 : {
2059 0 : if (!pListenerHelper)
2060 0 : GetListenerHelper_Impl();
2061 0 : bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster );
2062 : }
2063 0 : return bRes;
2064 : }
2065 :
2066 :
2067 : OUString SAL_CALL
2068 0 : LngSvcMgr::getImplementationName()
2069 : throw(uno::RuntimeException)
2070 : {
2071 0 : osl::MutexGuard aGuard( GetLinguMutex() );
2072 0 : return getImplementationName_Static();
2073 : }
2074 :
2075 :
2076 : sal_Bool SAL_CALL
2077 0 : LngSvcMgr::supportsService( const OUString& ServiceName )
2078 : throw(uno::RuntimeException)
2079 : {
2080 0 : osl::MutexGuard aGuard( GetLinguMutex() );
2081 :
2082 0 : uno::Sequence< OUString > aSNL = getSupportedServiceNames();
2083 0 : const OUString * pArray = aSNL.getConstArray();
2084 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
2085 0 : if( pArray[i] == ServiceName )
2086 0 : return sal_True;
2087 0 : return sal_False;
2088 : }
2089 :
2090 :
2091 : uno::Sequence< OUString > SAL_CALL
2092 0 : LngSvcMgr::getSupportedServiceNames()
2093 : throw(uno::RuntimeException)
2094 : {
2095 0 : osl::MutexGuard aGuard( GetLinguMutex() );
2096 0 : return getSupportedServiceNames_Static();
2097 : }
2098 :
2099 :
2100 11 : uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static()
2101 : throw()
2102 : {
2103 11 : osl::MutexGuard aGuard( GetLinguMutex() );
2104 :
2105 11 : uno::Sequence< OUString > aSNS( 1 ); // more than 1 service possible
2106 11 : aSNS.getArray()[0] = "com.sun.star.linguistic2.LinguServiceManager";
2107 11 : return aSNS;
2108 : }
2109 :
2110 :
2111 11 : uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance(
2112 : const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ )
2113 : throw(uno::Exception)
2114 : {
2115 11 : uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr;
2116 11 : return xService;
2117 : }
2118 :
2119 21 : void * SAL_CALL LngSvcMgr_getFactory(
2120 : const sal_Char * pImplName,
2121 : lang::XMultiServiceFactory * pServiceManager,
2122 : void * /*pRegistryKey*/ )
2123 : {
2124 :
2125 21 : void * pRet = 0;
2126 21 : if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName ) )
2127 : {
2128 : uno::Reference< lang::XSingleServiceFactory > xFactory =
2129 : cppu::createOneInstanceFactory(
2130 : pServiceManager,
2131 : LngSvcMgr::getImplementationName_Static(),
2132 : LngSvcMgr_CreateInstance,
2133 11 : LngSvcMgr::getSupportedServiceNames_Static());
2134 : // acquire, because we return an interface pointer instead of a reference
2135 11 : xFactory->acquire();
2136 11 : pRet = xFactory.get();
2137 : }
2138 21 : return pRet;
2139 : }
2140 :
2141 :
2142 :
2143 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|