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 145 : static sal_Bool lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText )
60 : {
61 145 : sal_Bool bRes = sal_False;
62 :
63 145 : sal_Int32 nLen = rSeq.getLength();
64 145 : if (nLen == 0 || rText.isEmpty())
65 0 : return bRes;
66 :
67 145 : const OUString *pSeq = rSeq.getConstArray();
68 3119 : for (sal_Int32 i = 0; i < nLen && !bRes; ++i)
69 : {
70 2974 : if (rText == pSeq[i])
71 145 : bRes = sal_True;
72 : }
73 145 : return bRes;
74 : }
75 :
76 :
77 108 : static uno::Sequence< lang::Locale > GetAvailLocales(
78 : const uno::Sequence< OUString > &rSvcImplNames )
79 : {
80 108 : uno::Sequence< lang::Locale > aRes;
81 :
82 108 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
83 108 : sal_Int32 nNames = rSvcImplNames.getLength();
84 108 : if (nNames && xFac.is())
85 : {
86 4 : 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 4 : uno::Sequence< uno::Any > aArgs(2);
91 4 : aArgs.getArray()[0] <<= GetLinguProperties();
92 :
93 : // check all services for the supported languages and new
94 : // languages to the result
95 4 : const OUString *pImplNames = rSvcImplNames.getConstArray();
96 : sal_Int32 i;
97 :
98 8 : for (i = 0; i < nNames; ++i)
99 : {
100 4 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc;
101 : try
102 : {
103 : xSuppLoc = uno::Reference< linguistic2::XSupportedLocales >(
104 4 : xFac->createInstanceWithArguments( pImplNames[i], aArgs ), uno::UNO_QUERY );
105 : }
106 0 : catch (uno::Exception &)
107 : {
108 : DBG_ASSERT( 0, "createInstanceWithArguments failed" );
109 : }
110 :
111 4 : if (xSuppLoc.is())
112 : {
113 4 : uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() );
114 4 : sal_Int32 nLoc = aLoc.getLength();
115 149 : for (sal_Int32 k = 0; k < nLoc; ++k)
116 : {
117 145 : const lang::Locale *pLoc = aLoc.getConstArray();
118 145 : LanguageType nLang = LanguageTag( pLoc[k] ).getLanguageType();
119 :
120 : // language not already added?
121 145 : if (aLanguages.find( nLang ) == aLanguages.end())
122 145 : aLanguages.insert( nLang );
123 4 : }
124 : }
125 : else
126 : {
127 : DBG_ASSERT( 0, "interface not supported by service" );
128 : }
129 4 : }
130 :
131 : // build return sequence
132 4 : sal_Int32 nLanguages = static_cast< sal_Int32 >(aLanguages.size());
133 4 : aRes.realloc( nLanguages );
134 4 : lang::Locale *pRes = aRes.getArray();
135 4 : std::set< LanguageType >::const_iterator aIt( aLanguages.begin() );
136 149 : for (i = 0; aIt != aLanguages.end(); ++aIt, ++i)
137 : {
138 145 : LanguageType nLang = *aIt;
139 145 : pRes[i] = LanguageTag( nLang ).getLocale();
140 4 : }
141 : }
142 :
143 108 : return aRes;
144 : }
145 :
146 :
147 4 : struct SvcInfo
148 : {
149 : const OUString aSvcImplName;
150 : const uno::Sequence< sal_Int16 > aSuppLanguages;
151 :
152 4 : SvcInfo( const OUString &rSvcImplName,
153 : const uno::Sequence< sal_Int16 > &rSuppLanguages ) :
154 : aSvcImplName (rSvcImplName),
155 4 : aSuppLanguages (rSuppLanguages)
156 : {
157 4 : }
158 :
159 : sal_Bool HasLanguage( sal_Int16 nLanguage ) const;
160 : };
161 :
162 :
163 149 : sal_Bool SvcInfo::HasLanguage( sal_Int16 nLanguage ) const
164 : {
165 149 : sal_Int32 nCnt = aSuppLanguages.getLength();
166 149 : const sal_Int16 *pLang = aSuppLanguages.getConstArray();
167 : sal_Int32 i;
168 :
169 3022 : for ( i = 0; i < nCnt; ++i)
170 : {
171 3022 : if (nLanguage == pLang[i])
172 149 : break;
173 : }
174 149 : return i < nCnt;
175 : }
176 :
177 34 : 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 17 : LngSvcMgrListenerHelper::LngSvcMgrListenerHelper(
235 : LngSvcMgr &rLngSvcMgr,
236 : const uno::Reference< linguistic2::XDictionaryList > &rxDicList ) :
237 : rMyManager ( rLngSvcMgr ),
238 17 : aLngSvcMgrListeners ( GetLinguMutex() ),
239 17 : aLngSvcEvtBroadcasters ( GetLinguMutex() ),
240 51 : xDicList ( rxDicList )
241 : {
242 17 : if (xDicList.is())
243 : {
244 17 : xDicList->addDictionaryListEventListener(
245 17 : (linguistic2::XDictionaryListEventListener *) this, sal_False );
246 : }
247 :
248 17 : nCombinedLngSvcEvt = 0;
249 17 : }
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 17 : inline sal_Bool LngSvcMgrListenerHelper::AddLngSvcMgrListener(
384 : const uno::Reference< lang::XEventListener >& rxListener )
385 : {
386 17 : aLngSvcMgrListeners.addInterface( rxListener );
387 17 : 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 17 : void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj )
400 : {
401 : // call "disposing" for all listeners and clear list
402 17 : aLngSvcMgrListeners .disposeAndClear( rEvtObj );
403 :
404 : // remove references to this object hold by the broadcasters
405 17 : cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtBroadcasters );
406 35 : while (aIt.hasMoreElements())
407 : {
408 1 : uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY );
409 1 : if (xRef.is())
410 1 : RemoveLngSvcEvtBroadcaster( xRef );
411 1 : }
412 :
413 : // remove refernce to this object hold by the dictionary-list
414 17 : if (xDicList.is())
415 : {
416 17 : xDicList->removeDictionaryListEventListener(
417 17 : (linguistic2::XDictionaryListEventListener *) this );
418 17 : xDicList = 0;
419 17 : }
420 17 : }
421 :
422 :
423 1 : sal_Bool LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster(
424 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
425 : {
426 1 : sal_Bool bRes = sal_False;
427 1 : if (rxBroadcaster.is())
428 : {
429 1 : aLngSvcEvtBroadcasters.addInterface( rxBroadcaster );
430 1 : rxBroadcaster->addLinguServiceEventListener(
431 1 : (linguistic2::XLinguServiceEventListener *) this );
432 : }
433 1 : return bRes;
434 : }
435 :
436 :
437 1 : sal_Bool LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster(
438 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
439 : {
440 1 : sal_Bool bRes = sal_False;
441 1 : if (rxBroadcaster.is())
442 : {
443 1 : aLngSvcEvtBroadcasters.removeInterface( rxBroadcaster );
444 1 : rxBroadcaster->removeLinguServiceEventListener(
445 1 : (linguistic2::XLinguServiceEventListener *) this );
446 : }
447 1 : return bRes;
448 : }
449 :
450 :
451 :
452 :
453 27 : LngSvcMgr::LngSvcMgr()
454 : : utl::ConfigItem("Office.Linguistic")
455 27 : , aEvtListeners(GetLinguMutex())
456 : {
457 27 : bDisposing = sal_False;
458 :
459 27 : pSpellDsp = 0;
460 27 : pGrammarDsp = 0;
461 27 : pHyphDsp = 0;
462 27 : pThesDsp = 0;
463 :
464 27 : pAvailSpellSvcs = 0;
465 27 : pAvailGrammarSvcs = 0;
466 27 : pAvailHyphSvcs = 0;
467 27 : pAvailThesSvcs = 0;
468 27 : pListenerHelper = 0;
469 :
470 : // request notify events when properties (i.e. something in the subtree) changes
471 27 : uno::Sequence< OUString > aNames(4);
472 27 : OUString *pNames = aNames.getArray();
473 27 : pNames[0] = "ServiceManager/SpellCheckerList";
474 27 : pNames[1] = "ServiceManager/GrammarCheckerList";
475 27 : pNames[2] = "ServiceManager/HyphenatorList";
476 27 : pNames[3] = "ServiceManager/ThesaurusList";
477 27 : EnableNotification( aNames );
478 :
479 27 : UpdateAll();
480 :
481 27 : aUpdateTimer.SetTimeout(500);
482 27 : aUpdateTimer.SetTimeoutHdl(LINK(this, LngSvcMgr, updateAndBroadcast));
483 :
484 : // request to be notified if an extension has been added/removed
485 27 : uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
486 :
487 27 : uno::Reference<deployment::XExtensionManager> xExtensionManager;
488 : try {
489 27 : xExtensionManager = deployment::ExtensionManager::get(xContext);
490 24 : } 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 27 : if (xExtensionManager.is())
496 : {
497 3 : xMB = uno::Reference<util::XModifyBroadcaster>(xExtensionManager, uno::UNO_QUERY_THROW);
498 :
499 3 : uno::Reference<util::XModifyListener> xListener(this);
500 3 : xMB->addModifyListener( xListener );
501 27 : }
502 27 : }
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 30 : void LngSvcMgr::stopListening()
544 : {
545 30 : osl::MutexGuard aGuard(GetLinguMutex());
546 :
547 30 : if (xMB.is())
548 : {
549 : try
550 : {
551 3 : uno::Reference<util::XModifyListener> xListener(this);
552 6 : xMB->removeModifyListener(xListener);
553 : }
554 3 : catch (const uno::Exception&)
555 : {
556 : }
557 :
558 3 : xMB.clear();
559 30 : }
560 30 : }
561 :
562 3 : void LngSvcMgr::disposing(const lang::EventObject&)
563 : throw (uno::RuntimeException)
564 : {
565 3 : stopListening();
566 3 : }
567 :
568 253 : void LngSvcMgr::clearSvcInfoArray(SvcInfoArray* &rpInfo)
569 : {
570 253 : delete rpInfo;
571 253 : rpInfo = NULL;
572 253 : }
573 :
574 81 : LngSvcMgr::~LngSvcMgr()
575 : {
576 27 : 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 27 : clearSvcInfoArray(pAvailSpellSvcs);
583 27 : clearSvcInfoArray(pAvailGrammarSvcs);
584 27 : clearSvcInfoArray(pAvailHyphSvcs);
585 27 : clearSvcInfoArray(pAvailThesSvcs);
586 54 : }
587 :
588 : namespace
589 : {
590 : using lang::Locale;
591 : using uno::Any;
592 : using uno::Sequence;
593 :
594 435 : sal_Bool lcl_FindEntry( const OUString &rEntry, const Sequence< OUString > &rCfgSvcs )
595 : {
596 435 : sal_Int32 nRes = -1;
597 435 : sal_Int32 nEntries = rCfgSvcs.getLength();
598 435 : const OUString *pEntry = rCfgSvcs.getConstArray();
599 580 : for (sal_Int32 i = 0; i < nEntries && nRes == -1; ++i)
600 : {
601 145 : if (rEntry == pEntry[i])
602 0 : nRes = i;
603 : }
604 435 : return nRes != -1;
605 : }
606 :
607 145 : Sequence< OUString > lcl_GetLastFoundSvcs(
608 : SvtLinguConfig &rCfg,
609 : const OUString &rLastFoundList ,
610 : const Locale &rAvailLocale )
611 : {
612 145 : Sequence< OUString > aRes;
613 :
614 145 : OUString aCfgLocaleStr( LanguageTag( rAvailLocale ).getBcp47() );
615 :
616 145 : Sequence< OUString > aNodeNames( rCfg.GetNodeNames(rLastFoundList) );
617 145 : sal_Bool bFound = lcl_FindEntry( aCfgLocaleStr, aNodeNames);
618 :
619 145 : 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 145 : 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 145 : Sequence< OUString > lcl_GetNewEntries(
664 : const Sequence< OUString > &rLastFoundSvcs,
665 : const Sequence< OUString > &rAvailSvcs )
666 : {
667 145 : sal_Int32 nLen = rAvailSvcs.getLength();
668 145 : Sequence< OUString > aRes( nLen );
669 145 : OUString *pRes = aRes.getArray();
670 145 : sal_Int32 nCnt = 0;
671 :
672 145 : const OUString *pEntry = rAvailSvcs.getConstArray();
673 290 : for (sal_Int32 i = 0; i < nLen; ++i)
674 : {
675 145 : if (!pEntry[i].isEmpty() && !lcl_FindEntry( pEntry[i], rLastFoundSvcs ))
676 145 : pRes[ nCnt++ ] = pEntry[i];
677 : }
678 :
679 145 : aRes.realloc( nCnt );
680 145 : return aRes;
681 : }
682 :
683 145 : Sequence< OUString > lcl_MergeSeq(
684 : const Sequence< OUString > &rCfgSvcs,
685 : const Sequence< OUString > &rNewSvcs )
686 : {
687 145 : Sequence< OUString > aRes( rCfgSvcs.getLength() + rNewSvcs.getLength() );
688 145 : OUString *pRes = aRes.getArray();
689 145 : sal_Int32 nCnt = 0;
690 :
691 435 : 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 290 : const Sequence< OUString > &rSeq = k == 0 ? rCfgSvcs : rNewSvcs;
696 :
697 290 : sal_Int32 nLen = rSeq.getLength();
698 290 : const OUString *pEntry = rSeq.getConstArray();
699 435 : for (sal_Int32 i = 0; i < nLen; ++i)
700 : {
701 145 : if (!pEntry[i].isEmpty() && !lcl_FindEntry( pEntry[i], aRes ))
702 145 : pRes[ nCnt++ ] = pEntry[i];
703 : }
704 : }
705 :
706 145 : aRes.realloc( nCnt );
707 145 : return aRes;
708 : }
709 : }
710 :
711 27 : 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 27 : SvtLinguConfig aCfg;
722 :
723 27 : const int nNumServices = 4;
724 27 : const sal_Char * apServices[nNumServices] = { SN_SPELLCHECKER, SN_GRAMMARCHECKER, SN_HYPHENATOR, SN_THESAURUS };
725 27 : const sal_Char * apCurLists[nNumServices] = { "ServiceManager/SpellCheckerList", "ServiceManager/GrammarCheckerList", "ServiceManager/HyphenatorList", "ServiceManager/ThesaurusList" };
726 27 : 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 27 : std::vector< list_entry_map_t > aLastFoundSvcs(nNumServices);
730 27 : std::vector< list_entry_map_t > aCurSvcs(nNumServices);
731 :
732 135 : for (int k = 0; k < nNumServices; ++k)
733 : {
734 108 : OUString aService( ::rtl::OUString::createFromAscii( apServices[k] ) );
735 108 : OUString aActiveList( ::rtl::OUString::createFromAscii( apCurLists[k] ) );
736 108 : OUString aLastFoundList( ::rtl::OUString::createFromAscii( apLastFoundLists[k] ) );
737 : sal_Int32 i;
738 :
739 : //
740 : // remove configured but not available language/services entries
741 : //
742 108 : Sequence< OUString > aNodeNames( aCfg.GetNodeNames( aActiveList ) ); // list of configured locales
743 108 : sal_Int32 nNodeNames = aNodeNames.getLength();
744 108 : const OUString *pNodeName = aNodeNames.getConstArray();
745 108 : 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 108 : Sequence< Locale > aAvailLocales( getAvailableLocales(aService) );
762 108 : sal_Int32 nAvailLocales = aAvailLocales.getLength();
763 108 : const Locale *pAvailLocale = aAvailLocales.getConstArray();
764 253 : for (i = 0; i < nAvailLocales; ++i)
765 : {
766 145 : OUString aCfgLocaleStr( LanguageTag( pAvailLocale[i] ).getBcp47() );
767 :
768 145 : Sequence< OUString > aAvailSvcs( getAvailableServices( aService, pAvailLocale[i] ));
769 :
770 145 : aLastFoundSvcs[k][ aCfgLocaleStr ] = aAvailSvcs;
771 :
772 : Sequence< OUString > aLastSvcs(
773 145 : lcl_GetLastFoundSvcs( aCfg, aLastFoundList , pAvailLocale[i] ));
774 : Sequence< OUString > aNewSvcs =
775 145 : lcl_GetNewEntries( aLastSvcs, aAvailSvcs );
776 :
777 145 : Sequence< OUString > aCfgSvcs( aCurSvcs[k][ aCfgLocaleStr ] );
778 :
779 : // merge services list (previously configured to be listed first).
780 145 : aCfgSvcs = lcl_MergeSeq( aCfgSvcs, aNewSvcs );
781 :
782 145 : aCurSvcs[k][ aCfgLocaleStr ] = aCfgSvcs;
783 145 : }
784 108 : }
785 :
786 : //
787 : // write new data back to configuration
788 : //
789 135 : for (int k = 0; k < nNumServices; ++k)
790 : {
791 324 : for (int i = 0; i < 2; ++i)
792 : {
793 216 : const sal_Char *pSubNodeName = (i == 0) ? apCurLists[k] : apLastFoundLists[k];
794 216 : OUString aSubNodeName( ::rtl::OUString::createFromAscii(pSubNodeName) );
795 :
796 216 : list_entry_map_t &rCurMap = (i == 0) ? aCurSvcs[k] : aLastFoundSvcs[k];
797 216 : list_entry_map_t::const_iterator aIt( rCurMap.begin() );
798 216 : sal_Int32 nVals = static_cast< sal_Int32 >( rCurMap.size() );
799 216 : Sequence< PropertyValue > aNewValues( nVals );
800 216 : PropertyValue *pNewValue = aNewValues.getArray();
801 722 : while (aIt != rCurMap.end())
802 : {
803 290 : OUString aCfgEntryName( aSubNodeName );
804 290 : aCfgEntryName += OUString::valueOf( (sal_Unicode) '/' );
805 290 : aCfgEntryName += (*aIt).first;
806 :
807 290 : pNewValue->Name = aCfgEntryName;
808 290 : pNewValue->Value <<= (*aIt).second;
809 290 : ++pNewValue;
810 290 : ++aIt;
811 290 : }
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 216 : 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 216 : }
826 27 : }
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 27 : }
832 :
833 4 : void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames )
834 : {
835 4 : const OUString aSpellCheckerList( "ServiceManager/SpellCheckerList" );
836 4 : const OUString aGrammarCheckerList( "ServiceManager/GrammarCheckerList" );
837 4 : const OUString aHyphenatorList( "ServiceManager/HyphenatorList" );
838 4 : const OUString aThesaurusList( "ServiceManager/ThesaurusList" );
839 :
840 4 : const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) );
841 4 : const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) );
842 4 : const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) );
843 4 : const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) );
844 :
845 4 : uno::Sequence< uno::Any > aValues;
846 4 : uno::Sequence< OUString > aNames( 1 );
847 4 : OUString *pNames = aNames.getArray();
848 :
849 4 : sal_Int32 nLen = rPropertyNames.getLength();
850 4 : const OUString *pPropertyNames = rPropertyNames.getConstArray();
851 149 : for (sal_Int32 i = 0; i < nLen; ++i)
852 : {
853 : // property names look like
854 : // "ServiceManager/ThesaurusList/de-CH"
855 :
856 145 : const OUString &rName = pPropertyNames[i];
857 : sal_Int32 nKeyStart;
858 145 : nKeyStart = rName.lastIndexOf( '/' );
859 145 : OUString aKeyText;
860 145 : if (nKeyStart != -1)
861 145 : aKeyText = rName.copy( nKeyStart + 1 );
862 : DBG_ASSERT( !aKeyText.isEmpty(), "unexpected key (lang::Locale) string" );
863 145 : if (0 == rName.compareTo( aSpellCheckerList, aSpellCheckerList.getLength() ))
864 : {
865 : // delete old cached data, needs to be acquired new on demand
866 43 : clearSvcInfoArray(pAvailSpellSvcs);
867 :
868 43 : OUString aNode( aSpellCheckerList );
869 43 : if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText ))
870 : {
871 43 : OUString aPropName( aNode );
872 43 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
873 43 : aPropName += aKeyText;
874 43 : pNames[0] = aPropName;
875 43 : aValues = /*aCfg.*/GetProperties( aNames );
876 43 : uno::Sequence< OUString > aSvcImplNames;
877 43 : if (aValues.getLength())
878 43 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
879 :
880 43 : LanguageType nLang = LANGUAGE_NONE;
881 43 : if (!aKeyText.isEmpty())
882 43 : nLang = LanguageTag( aKeyText ).getLanguageType();
883 :
884 43 : GetSpellCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
885 43 : pSpellDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
886 43 : }
887 : }
888 102 : else if (0 == rName.compareTo( aGrammarCheckerList, aGrammarCheckerList.getLength() ))
889 : {
890 : // delete old cached data, needs to be acquired new on demand
891 16 : clearSvcInfoArray(pAvailGrammarSvcs);
892 :
893 16 : OUString aNode( aGrammarCheckerList );
894 16 : if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText ))
895 : {
896 16 : OUString aPropName( aNode );
897 16 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
898 16 : aPropName += aKeyText;
899 16 : pNames[0] = aPropName;
900 16 : aValues = /*aCfg.*/GetProperties( aNames );
901 16 : uno::Sequence< OUString > aSvcImplNames;
902 16 : if (aValues.getLength())
903 16 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
904 :
905 16 : LanguageType nLang = LANGUAGE_NONE;
906 16 : if (!aKeyText.isEmpty())
907 16 : nLang = LanguageTag( aKeyText ).getLanguageType();
908 :
909 16 : if (SvtLinguConfig().HasGrammarChecker())
910 : {
911 16 : GetGrammarCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
912 16 : pGrammarDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
913 16 : }
914 16 : }
915 : }
916 86 : else if (0 == rName.compareTo( aHyphenatorList, aHyphenatorList.getLength() ))
917 : {
918 : // delete old cached data, needs to be acquired new on demand
919 43 : clearSvcInfoArray(pAvailHyphSvcs);
920 :
921 43 : OUString aNode( aHyphenatorList );
922 43 : if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText ))
923 : {
924 43 : OUString aPropName( aNode );
925 43 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
926 43 : aPropName += aKeyText;
927 43 : pNames[0] = aPropName;
928 43 : aValues = /*aCfg.*/GetProperties( aNames );
929 43 : uno::Sequence< OUString > aSvcImplNames;
930 43 : if (aValues.getLength())
931 43 : aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
932 :
933 43 : LanguageType nLang = LANGUAGE_NONE;
934 43 : if (!aKeyText.isEmpty())
935 43 : nLang = LanguageTag( aKeyText ).getLanguageType();
936 :
937 43 : GetHyphenatorDsp_Impl( sal_False ); // don't set service list, it will be done below
938 43 : pHyphDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
939 43 : }
940 : }
941 43 : else if (0 == rName.compareTo( aThesaurusList, aThesaurusList.getLength() ))
942 : {
943 : // delete old cached data, needs to be acquired new on demand
944 43 : clearSvcInfoArray(pAvailThesSvcs);
945 :
946 43 : OUString aNode( aThesaurusList );
947 43 : if (lcl_SeqHasString( aThesaurusListEntries, aKeyText ))
948 : {
949 43 : OUString aPropName( aNode );
950 43 : aPropName += OUString::valueOf( (sal_Unicode) '/' );
951 43 : aPropName += aKeyText;
952 43 : pNames[0] = aPropName;
953 43 : aValues = /*aCfg.*/GetProperties( aNames );
954 43 : uno::Sequence< OUString > aSvcImplNames;
955 43 : if (aValues.getLength())
956 43 : aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
957 :
958 43 : LanguageType nLang = LANGUAGE_NONE;
959 43 : if (!aKeyText.isEmpty())
960 43 : nLang = LanguageTag( aKeyText ).getLanguageType();
961 :
962 43 : GetThesaurusDsp_Impl( sal_False ); // don't set service list, it will be done below
963 43 : pThesDsp->SetServiceList( LanguageTag(nLang).getLocale(), aSvcImplNames );
964 43 : }
965 : }
966 : else
967 : {
968 : DBG_ASSERT( 0, "nofified for unexpected property" );
969 : }
970 149 : }
971 4 : }
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 17 : void LngSvcMgr::GetListenerHelper_Impl()
983 : {
984 17 : if (!pListenerHelper)
985 : {
986 17 : pListenerHelper = new LngSvcMgrListenerHelper( *this, linguistic::GetDictionaryList() );
987 17 : xListenerHelper = (linguistic2::XLinguServiceEventListener *) pListenerHelper;
988 : }
989 17 : }
990 :
991 :
992 59 : void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList )
993 : {
994 59 : if (!pSpellDsp)
995 : {
996 17 : pSpellDsp = new SpellCheckerDispatcher( *this );
997 17 : xSpellDsp = pSpellDsp;
998 17 : if (bSetSvcList)
999 16 : SetCfgServiceLists( *pSpellDsp );
1000 : }
1001 59 : }
1002 :
1003 :
1004 16 : void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList )
1005 : {
1006 16 : 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 1 : uno::Reference< linguistic2::XProofreadingIterator > xGCI;
1011 : try
1012 : {
1013 : uno::Reference< lang::XMultiServiceFactory > xMgr(
1014 1 : comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
1015 : xGCI = uno::Reference< linguistic2::XProofreadingIterator >(
1016 1 : 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 1 : if (xGCI.is())
1024 : {
1025 1 : pGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get());
1026 1 : xGrammarDsp = xGCI;
1027 : DBG_ASSERT( pGrammarDsp, "failed to get implementation" );
1028 1 : if (bSetSvcList)
1029 0 : SetCfgServiceLists( *pGrammarDsp );
1030 1 : }
1031 : }
1032 16 : }
1033 :
1034 :
1035 59 : void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList )
1036 : {
1037 59 : if (!pHyphDsp)
1038 : {
1039 17 : pHyphDsp = new HyphenatorDispatcher( *this );
1040 17 : xHyphDsp = pHyphDsp;
1041 17 : if (bSetSvcList)
1042 16 : SetCfgServiceLists( *pHyphDsp );
1043 : }
1044 59 : }
1045 :
1046 :
1047 43 : void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList )
1048 : {
1049 43 : if (!pThesDsp)
1050 : {
1051 1 : pThesDsp = new ThesaurusDispatcher;
1052 1 : xThesDsp = pThesDsp;
1053 1 : if (bSetSvcList)
1054 0 : SetCfgServiceLists( *pThesDsp );
1055 : }
1056 43 : }
1057 :
1058 :
1059 70 : void LngSvcMgr::GetAvailableSpellSvcs_Impl()
1060 : {
1061 70 : if (!pAvailSpellSvcs)
1062 : {
1063 27 : pAvailSpellSvcs = new SvcInfoArray;
1064 :
1065 27 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1066 27 : if (xFac.is())
1067 : {
1068 27 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1069 27 : uno::Reference< container::XEnumeration > xEnum;
1070 27 : if (xEnumAccess.is())
1071 27 : xEnum = xEnumAccess->createContentEnumeration( SN_SPELLCHECKER );
1072 :
1073 27 : if (xEnum.is())
1074 : {
1075 55 : while (xEnum->hasMoreElements())
1076 : {
1077 1 : uno::Any aCurrent = xEnum->nextElement();
1078 1 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1079 1 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1080 :
1081 1 : uno::Reference< linguistic2::XSpellChecker > xSvc;
1082 1 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1083 : {
1084 : try
1085 : {
1086 : uno::Reference < uno::XComponentContext > xContext(
1087 1 : comphelper::getComponentContext( xFac ) );
1088 1 : 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 1 : if (xSvc.is())
1097 : {
1098 1 : OUString aImplName;
1099 1 : uno::Sequence< sal_Int16 > aLanguages;
1100 1 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1101 1 : if (xInfo.is())
1102 1 : aImplName = xInfo->getImplementationName();
1103 : DBG_ASSERT( !aImplName.isEmpty(),
1104 : "empty implementation name" );
1105 1 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1106 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1107 1 : if (xSuppLoc.is()) {
1108 1 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1109 1 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1110 : }
1111 :
1112 1 : pAvailSpellSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1113 : }
1114 1 : }
1115 27 : }
1116 27 : }
1117 : }
1118 70 : }
1119 :
1120 :
1121 43 : void LngSvcMgr::GetAvailableGrammarSvcs_Impl()
1122 : {
1123 43 : if (!pAvailGrammarSvcs)
1124 : {
1125 27 : pAvailGrammarSvcs = new SvcInfoArray;
1126 :
1127 27 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1128 27 : if (xFac.is())
1129 : {
1130 27 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1131 27 : uno::Reference< container::XEnumeration > xEnum;
1132 27 : if (xEnumAccess.is())
1133 27 : xEnum = xEnumAccess->createContentEnumeration( SN_GRAMMARCHECKER );
1134 :
1135 27 : if (xEnum.is())
1136 : {
1137 55 : while (xEnum->hasMoreElements())
1138 : {
1139 1 : uno::Any aCurrent = xEnum->nextElement();
1140 1 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1141 1 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1142 :
1143 1 : uno::Reference< linguistic2::XProofreader > xSvc;
1144 1 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1145 : {
1146 : try
1147 : {
1148 : uno::Reference < uno::XComponentContext > xContext(
1149 1 : comphelper::getComponentContext( xFac ) );
1150 1 : 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 1 : if (xSvc.is())
1159 : {
1160 1 : OUString aImplName;
1161 1 : uno::Sequence< sal_Int16 > aLanguages;
1162 1 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1163 1 : if (xInfo.is())
1164 1 : aImplName = xInfo->getImplementationName();
1165 : DBG_ASSERT( !aImplName.isEmpty(),
1166 : "empty implementation name" );
1167 1 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1168 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1169 1 : if (xSuppLoc.is()) {
1170 1 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1171 1 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1172 : }
1173 :
1174 1 : pAvailGrammarSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1175 : }
1176 1 : }
1177 27 : }
1178 27 : }
1179 : }
1180 43 : }
1181 :
1182 :
1183 70 : void LngSvcMgr::GetAvailableHyphSvcs_Impl()
1184 : {
1185 70 : if (!pAvailHyphSvcs)
1186 : {
1187 27 : pAvailHyphSvcs = new SvcInfoArray;
1188 27 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1189 27 : if (xFac.is())
1190 : {
1191 27 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1192 27 : uno::Reference< container::XEnumeration > xEnum;
1193 27 : if (xEnumAccess.is())
1194 27 : xEnum = xEnumAccess->createContentEnumeration( SN_HYPHENATOR );
1195 :
1196 27 : if (xEnum.is())
1197 : {
1198 55 : while (xEnum->hasMoreElements())
1199 : {
1200 1 : uno::Any aCurrent = xEnum->nextElement();
1201 1 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1202 1 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1203 :
1204 1 : uno::Reference< linguistic2::XHyphenator > xSvc;
1205 1 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1206 : {
1207 : try
1208 : {
1209 : uno::Reference < uno::XComponentContext > xContext(
1210 1 : comphelper::getComponentContext( xFac ) );
1211 1 : 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 1 : if (xSvc.is())
1221 : {
1222 1 : OUString aImplName;
1223 1 : uno::Sequence< sal_Int16 > aLanguages;
1224 1 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1225 1 : if (xInfo.is())
1226 1 : aImplName = xInfo->getImplementationName();
1227 : DBG_ASSERT( !aImplName.isEmpty(),
1228 : "empty implementation name" );
1229 1 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1230 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1231 1 : if (xSuppLoc.is()) {
1232 1 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1233 1 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1234 : }
1235 :
1236 1 : pAvailHyphSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1237 : }
1238 1 : }
1239 27 : }
1240 27 : }
1241 : }
1242 70 : }
1243 :
1244 :
1245 70 : void LngSvcMgr::GetAvailableThesSvcs_Impl()
1246 : {
1247 70 : if (!pAvailThesSvcs)
1248 : {
1249 27 : pAvailThesSvcs = new SvcInfoArray;
1250 :
1251 27 : uno::Reference< lang::XMultiServiceFactory > xFac( comphelper::getProcessServiceFactory() );
1252 27 : if (xFac.is())
1253 : {
1254 27 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1255 27 : uno::Reference< container::XEnumeration > xEnum;
1256 27 : if (xEnumAccess.is())
1257 27 : xEnum = xEnumAccess->createContentEnumeration( SN_THESAURUS );
1258 :
1259 27 : if (xEnum.is())
1260 : {
1261 55 : while (xEnum->hasMoreElements())
1262 : {
1263 1 : uno::Any aCurrent = xEnum->nextElement();
1264 :
1265 1 : uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1266 1 : uno::Reference< lang::XSingleServiceFactory > xFactory;
1267 :
1268 1 : uno::Reference< linguistic2::XThesaurus > xSvc;
1269 1 : if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1270 : {
1271 : try
1272 : {
1273 : uno::Reference < uno::XComponentContext > xContext(
1274 1 : comphelper::getComponentContext( xFac ) );
1275 1 : 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 1 : if (xSvc.is())
1284 : {
1285 1 : OUString aImplName;
1286 1 : uno::Sequence< sal_Int16 > aLanguages;
1287 1 : uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1288 1 : if (xInfo.is())
1289 1 : aImplName = xInfo->getImplementationName();
1290 : DBG_ASSERT( !aImplName.isEmpty(),
1291 : "empty implementation name" );
1292 1 : uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1293 : DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1294 1 : if (xSuppLoc.is()) {
1295 1 : uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1296 1 : aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1297 : }
1298 :
1299 1 : pAvailThesSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1300 : }
1301 1 : }
1302 27 : }
1303 27 : }
1304 : }
1305 70 : }
1306 :
1307 :
1308 16 : void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher &rSpellDsp )
1309 : {
1310 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" );
1311 :
1312 16 : rtl::OUString aNode("ServiceManager/SpellCheckerList");
1313 16 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1314 16 : OUString *pNames = aNames.getArray();
1315 16 : sal_Int32 nLen = aNames.getLength();
1316 :
1317 : // append path prefix need for 'GetProperties' call below
1318 16 : String aPrefix( aNode );
1319 16 : aPrefix.Append( (sal_Unicode) '/' );
1320 16 : 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 16 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1328 16 : 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 16 : }
1343 16 : }
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 16 : void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher &rHyphDsp )
1389 : {
1390 : RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" );
1391 :
1392 16 : rtl::OUString aNode("ServiceManager/HyphenatorList");
1393 16 : uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1394 16 : OUString *pNames = aNames.getArray();
1395 16 : sal_Int32 nLen = aNames.getLength();
1396 :
1397 : // append path prefix need for 'GetProperties' call below
1398 16 : String aPrefix( aNode );
1399 16 : aPrefix.Append( (sal_Unicode) '/' );
1400 16 : 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 16 : uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1408 16 : 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 16 : }
1427 16 : }
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 17 : LngSvcMgr::getSpellChecker()
1470 : throw(uno::RuntimeException)
1471 : {
1472 17 : osl::MutexGuard aGuard( GetLinguMutex() );
1473 : #if OSL_DEBUG_LEVEL > 1
1474 : getAvailableLocales( SN_SPELLCHECKER );
1475 : #endif
1476 :
1477 17 : uno::Reference< linguistic2::XSpellChecker > xRes;
1478 17 : if (!bDisposing)
1479 : {
1480 17 : if (!xSpellDsp.is())
1481 16 : GetSpellCheckerDsp_Impl();
1482 17 : xRes = xSpellDsp;
1483 : }
1484 17 : return xRes;
1485 : }
1486 :
1487 :
1488 : uno::Reference< linguistic2::XHyphenator > SAL_CALL
1489 2272 : LngSvcMgr::getHyphenator()
1490 : throw(uno::RuntimeException)
1491 : {
1492 2272 : osl::MutexGuard aGuard( GetLinguMutex() );
1493 : #if OSL_DEBUG_LEVEL > 1
1494 : getAvailableLocales( SN_HYPHENATOR );
1495 : #endif
1496 :
1497 2272 : uno::Reference< linguistic2::XHyphenator > xRes;
1498 2272 : if (!bDisposing)
1499 : {
1500 2272 : if (!xHyphDsp.is())
1501 16 : GetHyphenatorDsp_Impl();
1502 2272 : xRes = xHyphDsp;
1503 : }
1504 2272 : 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 17 : LngSvcMgr::addLinguServiceManagerListener(
1530 : const uno::Reference< lang::XEventListener >& xListener )
1531 : throw(uno::RuntimeException)
1532 : {
1533 17 : osl::MutexGuard aGuard( GetLinguMutex() );
1534 :
1535 17 : sal_Bool bRes = sal_False;
1536 17 : if (!bDisposing && xListener.is())
1537 : {
1538 17 : if (!pListenerHelper)
1539 17 : GetListenerHelper_Impl();
1540 17 : bRes = pListenerHelper->AddLngSvcMgrListener( xListener );
1541 : }
1542 17 : 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 253 : LngSvcMgr::getAvailableServices(
1567 : const OUString& rServiceName,
1568 : const lang::Locale& rLocale )
1569 : throw(uno::RuntimeException)
1570 : {
1571 253 : osl::MutexGuard aGuard( GetLinguMutex() );
1572 :
1573 253 : uno::Sequence< OUString > aRes;
1574 253 : const SvcInfoArray *pInfoArray = 0;
1575 :
1576 253 : if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1577 : {
1578 70 : GetAvailableSpellSvcs_Impl();
1579 70 : pInfoArray = pAvailSpellSvcs;
1580 : }
1581 183 : else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1582 : {
1583 43 : GetAvailableGrammarSvcs_Impl();
1584 43 : pInfoArray = pAvailGrammarSvcs;
1585 : }
1586 140 : else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1587 : {
1588 70 : GetAvailableHyphSvcs_Impl();
1589 70 : pInfoArray = pAvailHyphSvcs;
1590 : }
1591 70 : else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1592 : {
1593 70 : GetAvailableThesSvcs_Impl();
1594 70 : pInfoArray = pAvailThesSvcs;
1595 : }
1596 :
1597 253 : if (pInfoArray)
1598 : {
1599 : // resize to max number of entries
1600 253 : size_t nMaxCnt = pInfoArray->size();
1601 253 : aRes.realloc( nMaxCnt );
1602 253 : OUString *pImplName = aRes.getArray();
1603 :
1604 253 : sal_uInt16 nCnt = 0;
1605 253 : LanguageType nLanguage = LanguageTag( rLocale ).getLanguageType();
1606 402 : for (size_t i = 0; i < nMaxCnt; ++i)
1607 : {
1608 149 : const SvcInfo &rInfo = (*pInfoArray)[i];
1609 298 : if (LANGUAGE_NONE == nLanguage
1610 149 : || rInfo.HasLanguage( nLanguage ))
1611 : {
1612 149 : pImplName[ nCnt++ ] = rInfo.aSvcImplName;
1613 : }
1614 : }
1615 :
1616 : // resize to actual number of entries
1617 253 : if (nCnt != nMaxCnt)
1618 0 : aRes.realloc( nCnt );
1619 : }
1620 :
1621 253 : return aRes;
1622 : }
1623 :
1624 :
1625 : uno::Sequence< lang::Locale > SAL_CALL
1626 108 : LngSvcMgr::getAvailableLocales(
1627 : const OUString& rServiceName )
1628 : throw(uno::RuntimeException)
1629 : {
1630 108 : osl::MutexGuard aGuard( GetLinguMutex() );
1631 :
1632 108 : uno::Sequence< lang::Locale > aRes;
1633 :
1634 108 : uno::Sequence< lang::Locale > *pAvailLocales = NULL;
1635 108 : if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1636 27 : pAvailLocales = &aAvailSpellLocales;
1637 81 : else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1638 27 : pAvailLocales = &aAvailGrammarLocales;
1639 54 : else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1640 27 : pAvailLocales = &aAvailHyphLocales;
1641 27 : else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1642 27 : 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 108 : if (pAvailLocales)
1648 : {
1649 108 : *pAvailLocales = GetAvailLocales(getAvailableServices(rServiceName, lang::Locale()));
1650 108 : aRes = *pAvailLocales;
1651 : }
1652 :
1653 108 : 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 86 : static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal )
1862 : {
1863 86 : uno::Sequence< OUString > aRes;
1864 :
1865 86 : if (rVal.hasValue())
1866 : {
1867 86 : 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 86 : return aRes;
1883 : }
1884 :
1885 :
1886 59 : static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal )
1887 : {
1888 59 : uno::Sequence< OUString > aRes;
1889 59 : 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 59 : if (rVal >>= aRes)
1897 : {
1898 : // but only the first string should be used.
1899 59 : 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 59 : 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 27 : LngSvcMgr::dispose()
2007 : throw(uno::RuntimeException)
2008 : {
2009 27 : osl::MutexGuard aGuard( GetLinguMutex() );
2010 :
2011 27 : if (!bDisposing)
2012 : {
2013 27 : bDisposing = sal_True;
2014 :
2015 : // require listeners to release this object
2016 27 : lang::EventObject aEvtObj( static_cast<XLinguServiceManager*>(this) );
2017 27 : aEvtListeners.disposeAndClear( aEvtObj );
2018 :
2019 27 : if (pListenerHelper)
2020 17 : pListenerHelper->DisposeAndClear( aEvtObj );
2021 27 : }
2022 27 : }
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 1 : sal_Bool LngSvcMgr::AddLngSvcEvtBroadcaster(
2054 : const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
2055 : {
2056 1 : sal_Bool bRes = sal_False;
2057 1 : if (rxBroadcaster.is())
2058 : {
2059 1 : if (!pListenerHelper)
2060 0 : GetListenerHelper_Impl();
2061 1 : bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster );
2062 : }
2063 1 : 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 27 : uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static()
2101 : throw()
2102 : {
2103 27 : osl::MutexGuard aGuard( GetLinguMutex() );
2104 :
2105 27 : uno::Sequence< OUString > aSNS( 1 ); // more than 1 service possible
2106 27 : aSNS.getArray()[0] = "com.sun.star.linguistic2.LinguServiceManager";
2107 27 : return aSNS;
2108 : }
2109 :
2110 :
2111 27 : uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance(
2112 : const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ )
2113 : throw(uno::Exception)
2114 : {
2115 27 : uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr;
2116 27 : return xService;
2117 : }
2118 :
2119 52 : void * SAL_CALL LngSvcMgr_getFactory(
2120 : const sal_Char * pImplName,
2121 : lang::XMultiServiceFactory * pServiceManager,
2122 : void * /*pRegistryKey*/ )
2123 : {
2124 :
2125 52 : void * pRet = 0;
2126 52 : 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 27 : LngSvcMgr::getSupportedServiceNames_Static());
2134 : // acquire, because we return an interface pointer instead of a reference
2135 27 : xFactory->acquire();
2136 27 : pRet = xFactory.get();
2137 : }
2138 52 : return pRet;
2139 : }
2140 :
2141 :
2142 :
2143 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|