LibreOffice Module linguistic (master) 1
lngsvcmgr.cxx
Go to the documentation of this file.
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#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <com/sun/star/deployment/DeploymentException.hpp>
24#include <com/sun/star/deployment/ExtensionManager.hpp>
25#include <com/sun/star/container/XContentEnumerationAccess.hpp>
26#include <com/sun/star/container/XEnumeration.hpp>
27#include <com/sun/star/lang/XSingleComponentFactory.hpp>
28#include <com/sun/star/lang/XSingleServiceFactory.hpp>
29#include <com/sun/star/linguistic2/XSupportedLocales.hpp>
30#include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
31#include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
32#include <com/sun/star/linguistic2/ProofreadingIterator.hpp>
33
34#include <tools/debug.hxx>
35#include <unotools/lingucfg.hxx>
36#include <utility>
37#include <vcl/svapp.hxx>
41#include <i18nlangtag/lang.h>
46#include <cppuhelper/weak.hxx>
47
48#include "lngsvcmgr.hxx"
49#include <linguistic/misc.hxx>
50#include "spelldsp.hxx"
51#include "hyphdsp.hxx"
52#include "thesdsp.hxx"
53#include "gciterator.hxx"
54
55using namespace com::sun::star;
56using namespace linguistic;
57
58uno::Sequence< OUString > static GetLangSvcList( const uno::Any &rVal );
59uno::Sequence< OUString > static GetLangSvc( const uno::Any &rVal );
60
61static bool lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText )
62{
63 return !rText.isEmpty()
64 && comphelper::findValue(rSeq, rText) != -1;
65}
66
67
68static uno::Sequence< lang::Locale > GetAvailLocales(
69 const uno::Sequence< OUString > &rSvcImplNames )
70{
71 uno::Sequence< lang::Locale > aRes;
72
73 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
74 if( rSvcImplNames.hasElements() )
75 {
76 std::set< LanguageType > aLanguages;
77
78 // All of these services only use one arg, but need two args for compat reasons
79 uno::Sequence< uno::Any > aArgs(2);
80 aArgs.getArray()[0] <<= GetLinguProperties();
81
82 // check all services for the supported languages and new
83 // languages to the result
84
85 for (const OUString& rImplName : rSvcImplNames)
86 {
87 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc;
88 try
89 {
90 xSuppLoc.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
91 rImplName, aArgs, xContext ),
92 uno::UNO_QUERY );
93 }
94 catch (uno::Exception &)
95 {
96 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
97 }
98
99 if (xSuppLoc.is())
100 {
101 const uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() );
102 for (const lang::Locale& rLoc : aLoc)
103 {
104 LanguageType nLang = LinguLocaleToLanguage( rLoc );
105
106 // It's a set, so insertion fails if language was already added.
107 aLanguages.insert( nLang );
108 }
109 }
110 else
111 {
112 SAL_WARN( "linguistic", "interface not supported by service" );
113 }
114 }
115
116 // build return sequence
117 std::vector<lang::Locale> aVec;
118 aVec.reserve(aLanguages.size());
119
120 std::transform(aLanguages.begin(), aLanguages.end(), std::back_inserter(aVec),
121 [](const LanguageType& rLang) -> lang::Locale { return LanguageTag::convertToLocale(rLang); });
122
124 }
125
126 return aRes;
127}
128
129
131{
132 const OUString aSvcImplName;
133 const std::vector< LanguageType > aSuppLanguages;
134
135 SvcInfo( OUString aSvcImplName_,
136 std::vector< LanguageType >&& rSuppLanguages ) :
137 aSvcImplName (std::move(aSvcImplName_)),
138 aSuppLanguages (std::move(rSuppLanguages))
139 {
140 }
141
142 bool HasLanguage( LanguageType nLanguage ) const;
143};
144
145
146bool SvcInfo::HasLanguage( LanguageType nLanguage ) const
147{
148 for ( auto const & i : aSuppLanguages)
149 {
150 if (nLanguage == i)
151 return true;
152 }
153 return false;
154}
155
157 public cppu::WeakImplHelper
158 <
159 linguistic2::XLinguServiceEventListener,
160 linguistic2::XDictionaryListEventListener
161 >
162{
164
167 uno::Reference< linguistic2::XSearchableDictionaryList > xDicList;
168
170
171 void LaunchEvent( sal_Int16 nLngSvcEvtFlags );
172
173 void Timeout();
174
175public:
177 uno::Reference< linguistic2::XSearchableDictionaryList > xDicList );
178
181
182 // lang::XEventListener
183 virtual void SAL_CALL
184 disposing( const lang::EventObject& rSource ) override;
185
186 // linguistic2::XLinguServiceEventListener
187 virtual void SAL_CALL
188 processLinguServiceEvent( const linguistic2::LinguServiceEvent& aLngSvcEvent ) override;
189
190 // linguistic2::XDictionaryListEventListener
191 virtual void SAL_CALL
193 const linguistic2::DictionaryListEvent& rDicListEvent ) override;
194
195 inline void AddLngSvcMgrListener(
196 const uno::Reference< lang::XEventListener >& rxListener );
197 inline void RemoveLngSvcMgrListener(
198 const uno::Reference< lang::XEventListener >& rxListener );
199 void DisposeAndClear( const lang::EventObject &rEvtObj );
201 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster );
203 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster );
204
205 void AddLngSvcEvt( sal_Int16 nLngSvcEvt );
206};
207
208
210 LngSvcMgr &rLngSvcMgr,
211 uno::Reference< linguistic2::XSearchableDictionaryList > xDicList_ ) :
212 rMyManager ( rLngSvcMgr ),
213 aLngSvcMgrListeners ( GetLinguMutex() ),
214 aLngSvcEvtBroadcasters ( GetLinguMutex() ),
215 xDicList (std::move( xDicList_ ))
216{
217 if (xDicList.is())
218 {
219 xDicList->addDictionaryListEventListener(
220 static_cast<linguistic2::XDictionaryListEventListener *>(this), false );
221 }
222
224}
225
226
227void SAL_CALL LngSvcMgrListenerHelper::disposing( const lang::EventObject& rSource )
228{
229 osl::MutexGuard aGuard( GetLinguMutex() );
230
231 uno::Reference< uno::XInterface > xRef( rSource.Source );
232 if ( xRef.is() )
233 {
236 if (xDicList == xRef)
237 xDicList = nullptr;
238 }
239}
240
242{
243 osl::MutexGuard aGuard( GetLinguMutex() );
244
245 {
246 // change event source to LinguServiceManager since the listeners
247 // probably do not know (and need not to know) about the specific
248 // SpellChecker's or Hyphenator's.
249 linguistic2::LinguServiceEvent aEvtObj(
250 static_cast<css::linguistic2::XLinguServiceManager*>(&rMyManager), nCombinedLngSvcEvt );
252
253 if (rMyManager.mxSpellDsp.is())
254 rMyManager.mxSpellDsp->FlushSpellCache();
255
256 // pass event on to linguistic2::XLinguServiceEventListener's
257 aLngSvcMgrListeners.notifyEach( &linguistic2::XLinguServiceEventListener::processLinguServiceEvent, aEvtObj );
258 }
259}
260
261
262void LngSvcMgrListenerHelper::AddLngSvcEvt( sal_Int16 nLngSvcEvt )
263{
264 nCombinedLngSvcEvt |= nLngSvcEvt;
265 Timeout();
266}
267
268
269void SAL_CALL
271 const linguistic2::LinguServiceEvent& rLngSvcEvent )
272{
273 osl::MutexGuard aGuard( GetLinguMutex() );
274 AddLngSvcEvt( rLngSvcEvent.nEvent );
275}
276
277
278void SAL_CALL
280 const linguistic2::DictionaryListEvent& rDicListEvent )
281{
282 osl::MutexGuard aGuard( GetLinguMutex() );
283
284 sal_Int16 nDlEvt = rDicListEvent.nCondensedEvent;
285 if (0 == nDlEvt)
286 return;
287
288 // we do keep the original event source here though...
289
290 // pass event on to linguistic2::XDictionaryListEventListener's
291 aLngSvcMgrListeners.notifyEach( &linguistic2::XDictionaryListEventListener::processDictionaryListEvent, rDicListEvent );
292
293 // "translate" DictionaryList event into linguistic2::LinguServiceEvent
294 sal_Int16 nLngSvcEvt = 0;
295 sal_Int16 const nSpellCorrectFlags =
296 linguistic2::DictionaryListEventFlags::ADD_NEG_ENTRY |
297 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY |
298 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC |
299 linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC;
300 if (0 != (nDlEvt & nSpellCorrectFlags))
301 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
302
303 sal_Int16 const nSpellWrongFlags =
304 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
305 linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY |
306 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
307 linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC;
308 if (0 != (nDlEvt & nSpellWrongFlags))
309 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
310
311 sal_Int16 const nHyphenateFlags =
312 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
313 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY |
314 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
315 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC;
316 if (0 != (nDlEvt & nHyphenateFlags))
317 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN;
318
319 if (rMyManager.mxSpellDsp.is())
320 rMyManager.mxSpellDsp->FlushSpellCache();
321 if (nLngSvcEvt)
322 LaunchEvent( nLngSvcEvt );
323}
324
325
326void LngSvcMgrListenerHelper::LaunchEvent( sal_Int16 nLngSvcEvtFlags )
327{
328 linguistic2::LinguServiceEvent aEvt(
329 static_cast<css::linguistic2::XLinguServiceManager*>(&rMyManager), nLngSvcEvtFlags );
330
331 // pass event on to linguistic2::XLinguServiceEventListener's
332 aLngSvcMgrListeners.notifyEach( &linguistic2::XLinguServiceEventListener::processLinguServiceEvent, aEvt );
333}
334
335
337 const uno::Reference< lang::XEventListener >& rxListener )
338{
339 aLngSvcMgrListeners.addInterface( rxListener );
340}
341
342
344 const uno::Reference< lang::XEventListener >& rxListener )
345{
347}
348
349
350void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj )
351{
352 // call "disposing" for all listeners and clear list
354
355 // remove references to this object hold by the broadcasters
357 while (aIt.hasMoreElements())
358 {
359 uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY );
360 if (xRef.is())
362 }
363
364 // remove reference to this object hold by the dictionary-list
365 if (xDicList.is())
366 {
367 xDicList->removeDictionaryListEventListener(
368 static_cast<linguistic2::XDictionaryListEventListener *>(this) );
369 xDicList = nullptr;
370 }
371}
372
373
375 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
376{
377 if (rxBroadcaster.is())
378 {
379 aLngSvcEvtBroadcasters.addInterface( rxBroadcaster );
380 rxBroadcaster->addLinguServiceEventListener(
381 static_cast<linguistic2::XLinguServiceEventListener *>(this) );
382 }
383}
384
385
387 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
388{
389 if (rxBroadcaster.is())
390 {
392 rxBroadcaster->removeLinguServiceEventListener(
393 static_cast<linguistic2::XLinguServiceEventListener *>(this) );
394 }
395}
396
397
399 : utl::ConfigItem("Office.Linguistic")
400 , aEvtListeners(GetLinguMutex())
401 , aUpdateIdle("LngSvcMgr aUpdateIdle")
402{
403 bDisposing = false;
404
405 // request notify events when properties (i.e. something in the subtree) changes
406 uno::Sequence< OUString > aNames{
407 "ServiceManager/SpellCheckerList",
408 "ServiceManager/GrammarCheckerList",
409 "ServiceManager/HyphenatorList",
410 "ServiceManager/ThesaurusList"
411 };
412 EnableNotification( aNames );
413
414 UpdateAll();
415
416 aUpdateIdle.SetPriority(TaskPriority::LOWEST);
417 aUpdateIdle.SetInvokeHandler(LINK(this, LngSvcMgr, updateAndBroadcast));
418
419 // request to be notified if an extension has been added/removed
420 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
421
422 uno::Reference<deployment::XExtensionManager> xExtensionManager;
423 try {
424 xExtensionManager = deployment::ExtensionManager::get(xContext);
425 } catch ( const uno::DeploymentException & ) {
426 SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
427 } catch ( const deployment::DeploymentException & ) {
428 SAL_WARN( "linguistic", "no extension manager - should fire on mobile only" );
429 }
430 if (xExtensionManager.is())
431 {
432 xMB.set(xExtensionManager, uno::UNO_QUERY_THROW);
433
434 uno::Reference<util::XModifyListener> xListener(this);
435 xMB->addModifyListener( xListener );
436 }
437}
438
439// css::util::XModifyListener
440void LngSvcMgr::modified(const lang::EventObject&)
441{
442 osl::MutexGuard aGuard(GetLinguMutex());
443 //assume that if an extension has been added/removed that
444 //it might be a dictionary extension, so drop our cache
445
446 pAvailSpellSvcs.reset();
447 pAvailGrammarSvcs.reset();
448 pAvailHyphSvcs.reset();
449 pAvailThesSvcs.reset();
450
451 //schedule in an update to execute in the main thread
453}
454
455//run update, and inform everyone that dictionaries (may) have changed, this
456//needs to be run in the main thread because
457//utl::ConfigChangeListener_Impl::changesOccurred grabs the SolarMutex and we
458//get notified that an extension was added from an extension manager thread
459IMPL_LINK_NOARG(LngSvcMgr, updateAndBroadcast, Timer *, void)
460{
461 osl::MutexGuard aGuard( GetLinguMutex() );
462
463 UpdateAll();
464
465 if (mxListenerHelper.is())
466 {
467 mxListenerHelper->AddLngSvcEvt(
468 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN |
469 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN |
470 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN |
471 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN );
472 }
473}
474
476{
477 osl::MutexGuard aGuard(GetLinguMutex());
478
479 if (!xMB.is())
480 return;
481
482 try
483 {
484 uno::Reference<util::XModifyListener> xListener(this);
485 xMB->removeModifyListener(xListener);
486 }
487 catch (const uno::Exception&)
488 {
489 }
490
491 xMB.clear();
492}
493
494void LngSvcMgr::disposing(const lang::EventObject&)
495{
497}
498
500{
502
503 // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper
504 // will be freed in the destructor of the respective Reference's
505 // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp
506
507 pAvailSpellSvcs.reset();
508 pAvailGrammarSvcs.reset();
509 pAvailHyphSvcs.reset();
510 pAvailThesSvcs.reset();
511}
512
513namespace
514{
515 using lang::Locale;
516 using uno::Any;
517 using uno::Sequence;
518
519 bool lcl_FindEntry( const OUString &rEntry, const Sequence< OUString > &rCfgSvcs )
520 {
521 return comphelper::findValue(rCfgSvcs, rEntry) != -1;
522 }
523
524 bool lcl_FindEntry( const OUString &rEntry, const std::vector< OUString > &rCfgSvcs )
525 {
526 return std::find(rCfgSvcs.begin(), rCfgSvcs.end(), rEntry) != rCfgSvcs.end();
527 }
528
529 Sequence< OUString > lcl_GetLastFoundSvcs(
530 SvtLinguConfig const &rCfg,
531 const OUString &rLastFoundList ,
532 const OUString& rCfgLocaleStr )
533 {
534 Sequence< OUString > aRes;
535
536 Sequence< OUString > aNodeNames( rCfg.GetNodeNames(rLastFoundList) );
537 bool bFound = lcl_FindEntry( rCfgLocaleStr, aNodeNames);
538
539 if (bFound)
540 {
541 Sequence< OUString > aNames { rLastFoundList + "/" + rCfgLocaleStr };
542 Sequence< Any > aValues( rCfg.GetProperties( aNames ) );
543 if (aValues.hasElements())
544 {
545 SAL_WARN_IF( aValues.getLength() != 1, "linguistic", "unexpected length of sequence" );
546 Sequence< OUString > aSvcImplNames;
547 if (aValues.getConstArray()[0] >>= aSvcImplNames)
548 aRes = aSvcImplNames;
549 else
550 {
551 SAL_WARN( "linguistic", "type mismatch" );
552 }
553 }
554 }
555
556 return aRes;
557 }
558
559 Sequence< OUString > lcl_RemoveMissingEntries(
560 const Sequence< OUString > &rCfgSvcs,
561 const Sequence< OUString > &rAvailSvcs )
562 {
563 std::vector<OUString> aRes;
564 aRes.reserve(rCfgSvcs.getLength());
565
566 std::copy_if(rCfgSvcs.begin(), rCfgSvcs.end(), std::back_inserter(aRes),
567 [&rAvailSvcs](const OUString& entry) { return lcl_SeqHasString(rAvailSvcs, entry); });
568
570 }
571
572 Sequence< OUString > lcl_GetNewEntries(
573 const Sequence< OUString > &rLastFoundSvcs,
574 const Sequence< OUString > &rAvailSvcs )
575 {
576 std::vector<OUString> aRes;
577 aRes.reserve(rAvailSvcs.getLength());
578
579 std::copy_if(rAvailSvcs.begin(), rAvailSvcs.end(), std::back_inserter(aRes),
580 [&rLastFoundSvcs](const OUString& rEntry) {
581 return !rEntry.isEmpty() && !lcl_FindEntry( rEntry, rLastFoundSvcs ); });
582
584 }
585
586 Sequence< OUString > lcl_MergeSeq(
587 const Sequence< OUString > &rCfgSvcs,
588 const Sequence< OUString > &rNewSvcs )
589 {
590 std::vector<OUString> aRes;
591 aRes.reserve(rCfgSvcs.getLength() + rNewSvcs.getLength());
592
593 auto lVecNotHasString = [&aRes](const OUString& rEntry)
594 { return !rEntry.isEmpty() && !lcl_FindEntry(rEntry, aRes); };
595
596 // add previously configured service first and append
597 // new found services at the end
598 for (const Sequence< OUString > &rSeq : { rCfgSvcs, rNewSvcs })
599 {
600 std::copy_if(rSeq.begin(), rSeq.end(), std::back_inserter(aRes), lVecNotHasString);
601 }
602
604 }
605}
606
608{
609 using beans::PropertyValue;
610 using lang::Locale;
611 using uno::Sequence;
612
613 typedef std::map< OUString, Sequence< OUString > > list_entry_map_t;
614
615 SvtLinguConfig aCfg;
616
617 const int nNumServices = 4;
618 static constexpr rtl::OUStringConstExpr apServices[nNumServices] = { SN_SPELLCHECKER, SN_GRAMMARCHECKER, SN_HYPHENATOR, SN_THESAURUS };
619 const char * const apCurLists[nNumServices] = { "ServiceManager/SpellCheckerList", "ServiceManager/GrammarCheckerList", "ServiceManager/HyphenatorList", "ServiceManager/ThesaurusList" };
620 const char * const apLastFoundLists[nNumServices] = { "ServiceManager/LastFoundSpellCheckers", "ServiceManager/LastFoundGrammarCheckers", "ServiceManager/LastFoundHyphenators", "ServiceManager/LastFoundThesauri" };
621
622 // usage of indices as above: 0 = spell checker, 1 = grammar checker, 2 = hyphenator, 3 = thesaurus
623 std::vector< list_entry_map_t > aLastFoundSvcs(nNumServices);
624 std::vector< list_entry_map_t > aCurSvcs(nNumServices);
625
626 for (int k = 0; k < nNumServices; ++k)
627 {
628 OUString aService( apServices[k] );
629 OUString aActiveList( OUString::createFromAscii( apCurLists[k] ) );
630 OUString aLastFoundList( OUString::createFromAscii( apLastFoundLists[k] ) );
631
632
633 // remove configured but not available language/services entries
634
635 const Sequence< OUString > aNodeNames( aCfg.GetNodeNames( aActiveList ) ); // list of configured locales
636 for (const OUString& rNodeName : aNodeNames)
637 {
638 Locale aLocale( LanguageTag::convertToLocale( rNodeName));
639 Sequence< OUString > aCfgSvcs( getConfiguredServices( aService, aLocale ));
640 Sequence< OUString > aAvailSvcs( getAvailableServices( aService, aLocale ));
641
642 aCfgSvcs = lcl_RemoveMissingEntries( aCfgSvcs, aAvailSvcs );
643
644 aCurSvcs[k][ rNodeName ] = aCfgSvcs;
645 }
646
647
648 // add new available language/service entries
649 // and
650 // set last found services to currently available ones
651
652 const Sequence< Locale > aAvailLocales( getAvailableLocales(aService) );
653 for (const Locale& rAvailLocale : aAvailLocales)
654 {
655 OUString aCfgLocaleStr( LanguageTag::convertToBcp47( rAvailLocale));
656
657 Sequence< OUString > aAvailSvcs( getAvailableServices( aService, rAvailLocale ));
658
659 aLastFoundSvcs[k][ aCfgLocaleStr ] = aAvailSvcs;
660
661 Sequence< OUString > aLastSvcs(
662 lcl_GetLastFoundSvcs( aCfg, aLastFoundList , aCfgLocaleStr ));
663 Sequence< OUString > aNewSvcs =
664 lcl_GetNewEntries( aLastSvcs, aAvailSvcs );
665
666 Sequence< OUString > aCfgSvcs( aCurSvcs[k][ aCfgLocaleStr ] );
667
668 // merge services list (previously configured to be listed first).
669 aCfgSvcs = lcl_MergeSeq( aCfgSvcs, aNewSvcs );
670
671 aCurSvcs[k][ aCfgLocaleStr ] = aCfgSvcs;
672 }
673 }
674
675
676 // write new data back to configuration
677
678 for (int k = 0; k < nNumServices; ++k)
679 {
680 for (int i = 0; i < 2; ++i)
681 {
682 const char *pSubNodeName = (i == 0) ? apCurLists[k] : apLastFoundLists[k];
683 OUString aSubNodeName( OUString::createFromAscii(pSubNodeName) );
684
685 list_entry_map_t &rCurMap = (i == 0) ? aCurSvcs[k] : aLastFoundSvcs[k];
686 sal_Int32 nVals = static_cast< sal_Int32 >( rCurMap.size() );
687 Sequence< PropertyValue > aNewValues( nVals );
688 PropertyValue *pNewValue = aNewValues.getArray();
689 for (auto const& elem : rCurMap)
690 {
691 pNewValue->Name = aSubNodeName + "/" + elem.first;
692 pNewValue->Value <<= elem.second;
693 ++pNewValue;
694 }
695 OSL_ENSURE( pNewValue - aNewValues.getConstArray() == nVals,
696 "possible mismatch of sequence size and property number" );
697
698 {
699 // add new or replace existing entries.
700 bool bRes = aCfg.ReplaceSetProperties( aSubNodeName, aNewValues );
701 SAL_WARN_IF(!bRes, "linguistic", "failed to set new configuration values");
702 }
703 }
704 }
705
706 //The new settings in the configuration get applied ! because we are
707 //listening to the configuration for changes of the relevant ! properties
708 //and Notify applies the new settings.
709}
710
711void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames )
712{
713 static constexpr OUStringLiteral aSpellCheckerList( u"ServiceManager/SpellCheckerList" );
714 static constexpr OUStringLiteral aGrammarCheckerList( u"ServiceManager/GrammarCheckerList" );
715 static constexpr OUStringLiteral aHyphenatorList( u"ServiceManager/HyphenatorList" );
716 static constexpr OUStringLiteral aThesaurusList( u"ServiceManager/ThesaurusList" );
717
718 const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) );
719 const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) );
720 const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) );
721 const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) );
722
723 uno::Sequence< uno::Any > aValues;
724 uno::Sequence< OUString > aNames( 1 );
725 OUString *pNames = aNames.getArray();
726
727 for (const OUString& rName : rPropertyNames)
728 {
729 // property names look like
730 // "ServiceManager/ThesaurusList/de-CH"
731
732 sal_Int32 nKeyStart;
733 nKeyStart = rName.lastIndexOf( '/' );
734 OUString aKeyText;
735 if (nKeyStart != -1)
736 aKeyText = rName.copy( nKeyStart + 1 );
737 SAL_WARN_IF( aKeyText.isEmpty(), "linguistic", "unexpected key (lang::Locale) string" );
738 if (rName.startsWith( aSpellCheckerList ))
739 {
740 osl::MutexGuard aGuard(GetLinguMutex());
741
742 // delete old cached data, needs to be acquired new on demand
743 pAvailSpellSvcs.reset();
744
745 if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText ))
746 {
747 pNames[0] = aSpellCheckerList + "/" + aKeyText;
748 aValues = /*aCfg.*/GetProperties( aNames );
749 uno::Sequence< OUString > aSvcImplNames;
750 if (aValues.hasElements())
751 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
752
754 if (!aKeyText.isEmpty())
755 nLang = LanguageTag::convertToLanguageType( aKeyText );
756
757 GetSpellCheckerDsp_Impl( false ); // don't set service list, it will be done below
758 mxSpellDsp->SetServiceList( LanguageTag::convertToLocale(nLang), aSvcImplNames );
759 }
760 }
761 else if (rName.startsWith( aGrammarCheckerList ))
762 {
763 osl::MutexGuard aGuard(GetLinguMutex());
764
765 // delete old cached data, needs to be acquired new on demand
766 pAvailGrammarSvcs.reset();
767
768 if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText ))
769 {
770 pNames[0] = aGrammarCheckerList + "/" + aKeyText;
771 aValues = /*aCfg.*/GetProperties( aNames );
772 uno::Sequence< OUString > aSvcImplNames;
773 if (aValues.hasElements())
774 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
775
777 if (!aKeyText.isEmpty())
778 nLang = LanguageTag::convertToLanguageType( aKeyText );
779
780 if (SvtLinguConfig().HasGrammarChecker())
781 {
782 GetGrammarCheckerDsp_Impl( false ); // don't set service list, it will be done below
783 mxGrammarDsp->SetServiceList( LanguageTag::convertToLocale(nLang), aSvcImplNames );
784 }
785 }
786 }
787 else if (rName.startsWith( aHyphenatorList ))
788 {
789 osl::MutexGuard aGuard(GetLinguMutex());
790
791 // delete old cached data, needs to be acquired new on demand
792 pAvailHyphSvcs.reset();
793
794 if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText ))
795 {
796 pNames[0] = aHyphenatorList + "/" + aKeyText;
797 aValues = /*aCfg.*/GetProperties( aNames );
798 uno::Sequence< OUString > aSvcImplNames;
799 if (aValues.hasElements())
800 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
801
803 if (!aKeyText.isEmpty())
804 nLang = LanguageTag::convertToLanguageType( aKeyText );
805
806 GetHyphenatorDsp_Impl( false ); // don't set service list, it will be done below
807 mxHyphDsp->SetServiceList( LanguageTag::convertToLocale(nLang), aSvcImplNames );
808 }
809 }
810 else if (rName.startsWith( aThesaurusList ))
811 {
812 osl::MutexGuard aGuard(GetLinguMutex());
813
814 // delete old cached data, needs to be acquired new on demand
815 pAvailThesSvcs.reset();
816
817 if (lcl_SeqHasString( aThesaurusListEntries, aKeyText ))
818 {
819 pNames[0] = aThesaurusList + "/" + aKeyText;
820 aValues = /*aCfg.*/GetProperties( aNames );
821 uno::Sequence< OUString > aSvcImplNames;
822 if (aValues.hasElements())
823 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
824
826 if (!aKeyText.isEmpty())
827 nLang = LanguageTag::convertToLanguageType( aKeyText );
828
829 GetThesaurusDsp_Impl( false ); // don't set service list, it will be done below
830 mxThesDsp->SetServiceList( LanguageTag::convertToLocale(nLang), aSvcImplNames );
831 }
832 }
833 else
834 {
835 SAL_WARN( "linguistic", "notified for unexpected property" );
836 }
837 }
838}
839
840
842{
843 // everything necessary should have already been done by 'SaveCfgSvcs'
844 // called from within 'setConfiguredServices'.
845 // Also this class usually exits only when the Office is being shutdown.
846}
847
848
850{
851 if (!mxListenerHelper.is())
852 {
854 }
855}
856
857
859{
860 if (!mxSpellDsp.is())
861 {
862 mxSpellDsp = new SpellCheckerDispatcher( *this );
863 if (bSetSvcList)
865 }
866}
867
868
870{
871 if (mxGrammarDsp.is() || !SvtLinguConfig().HasGrammarChecker())
872 return;
873
876 uno::Reference< linguistic2::XProofreadingIterator > xGCI;
877 try
878 {
879 xGCI = linguistic2::ProofreadingIterator::create( comphelper::getProcessComponentContext() );
880 }
881 catch (const uno::Exception &)
882 {
883 }
884 SAL_WARN_IF( !xGCI.is(), "linguistic", "instantiating grammar checking iterator failed" );
885
886 if (xGCI.is())
887 {
888 mxGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get());
889 SAL_WARN_IF( mxGrammarDsp == nullptr, "linguistic", "failed to get implementation" );
890 if (bSetSvcList && mxGrammarDsp.is())
892 }
893}
894
895
896void LngSvcMgr::GetHyphenatorDsp_Impl( bool bSetSvcList )
897{
898 if (!mxHyphDsp.is())
899 {
900 mxHyphDsp = new HyphenatorDispatcher( *this );
901 if (bSetSvcList)
903 }
904}
905
906
907void LngSvcMgr::GetThesaurusDsp_Impl( bool bSetSvcList )
908{
909 if (!mxThesDsp.is())
910 {
912 if (bSetSvcList)
914 }
915}
916
917
919{
920 if (pAvailSpellSvcs)
921 return;
922
923 pAvailSpellSvcs.emplace();
924
925 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
926
927 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xContext->getServiceManager(), uno::UNO_QUERY );
928 uno::Reference< container::XEnumeration > xEnum;
929 if (xEnumAccess.is())
930 xEnum = xEnumAccess->createContentEnumeration( SN_SPELLCHECKER );
931
932 if (!xEnum.is())
933 return;
934
935 while (xEnum->hasMoreElements())
936 {
937 uno::Any aCurrent = xEnum->nextElement();
938 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
939 uno::Reference< lang::XSingleServiceFactory > xFactory;
940
941 xCompFactory.set(aCurrent, css::uno::UNO_QUERY);
942 if (!xCompFactory.is())
943 {
944 xFactory.set(aCurrent, css::uno::UNO_QUERY);
945 }
946 if ( xCompFactory.is() || xFactory.is() )
947 {
948 try
949 {
950 uno::Reference< linguistic2::XSpellChecker > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY_THROW );
951
952 OUString aImplName;
953 std::vector< LanguageType > aLanguages;
954 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
955 if (xInfo.is())
956 aImplName = xInfo->getImplementationName();
957 SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" );
958 uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales());
959 aLanguages = LocaleSeqToLangVec( aLocaleSequence );
960
961 pAvailSpellSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) );
962 }
963 catch (const uno::Exception &)
964 {
965 SAL_WARN( "linguistic", "createInstance failed" );
966 }
967 }
968 }
969}
970
971
973{
975 return;
976
977 pAvailGrammarSvcs.emplace();
978
979 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
980
981 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xContext->getServiceManager(), uno::UNO_QUERY );
982 uno::Reference< container::XEnumeration > xEnum;
983 if (xEnumAccess.is())
984 xEnum = xEnumAccess->createContentEnumeration( SN_GRAMMARCHECKER );
985
986 if (!xEnum.is())
987 return;
988
989 while (xEnum->hasMoreElements())
990 {
991 uno::Any aCurrent = xEnum->nextElement();
992 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
993 uno::Reference< lang::XSingleServiceFactory > xFactory;
994
995 xCompFactory.set(aCurrent, css::uno::UNO_QUERY);
996 if (!xCompFactory.is())
997 {
998 xFactory.set(aCurrent, css::uno::UNO_QUERY);
999 }
1000 if ( xCompFactory.is() || xFactory.is() )
1001 {
1002 try
1003 {
1004 uno::Reference< linguistic2::XProofreader > xSvc(
1005 xCompFactory.is()
1006 ? xCompFactory->createInstanceWithContext(xContext)
1007 : xFactory->createInstance(),
1008 uno::UNO_QUERY_THROW);
1009
1010 OUString aImplName;
1011 std::vector< LanguageType > aLanguages;
1012 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1013 if (xInfo.is())
1014 aImplName = xInfo->getImplementationName();
1015 SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" );
1016 uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales());
1017 aLanguages = LocaleSeqToLangVec( aLocaleSequence );
1018
1019 pAvailGrammarSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) );
1020 }
1021 catch (const uno::Exception &)
1022 {
1023 SAL_WARN( "linguistic", "createInstance failed" );
1024 }
1025 }
1026
1027 }
1028}
1029
1030
1032{
1033 if (pAvailHyphSvcs)
1034 return;
1035
1036 pAvailHyphSvcs.emplace();
1037 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
1038
1039 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xContext->getServiceManager(), uno::UNO_QUERY );
1040 uno::Reference< container::XEnumeration > xEnum;
1041 if (xEnumAccess.is())
1042 xEnum = xEnumAccess->createContentEnumeration( SN_HYPHENATOR );
1043
1044 if (!xEnum.is())
1045 return;
1046
1047 while (xEnum->hasMoreElements())
1048 {
1049 uno::Any aCurrent = xEnum->nextElement();
1050 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1051 uno::Reference< lang::XSingleServiceFactory > xFactory;
1052
1053 xCompFactory.set(aCurrent, css::uno::UNO_QUERY);
1054 if (!xCompFactory.is())
1055 {
1056 xFactory.set(aCurrent, css::uno::UNO_QUERY);
1057 }
1058 if ( xCompFactory.is() || xFactory.is() )
1059 {
1060 try
1061 {
1062 uno::Reference< linguistic2::XHyphenator > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY_THROW );
1063 OUString aImplName;
1064 std::vector< LanguageType > aLanguages;
1065 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1066 if (xInfo.is())
1067 aImplName = xInfo->getImplementationName();
1068 SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" );
1069 uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales());
1070 aLanguages = LocaleSeqToLangVec( aLocaleSequence );
1071 pAvailHyphSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) );
1072 }
1073 catch (const uno::Exception &)
1074 {
1075 SAL_WARN( "linguistic", "createInstance failed" );
1076 }
1077 }
1078 }
1079}
1080
1081
1083{
1084 if (pAvailThesSvcs)
1085 return;
1086
1087 pAvailThesSvcs.emplace();
1088
1089 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
1090
1091 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xContext->getServiceManager(), uno::UNO_QUERY );
1092 uno::Reference< container::XEnumeration > xEnum;
1093 if (xEnumAccess.is())
1094 xEnum = xEnumAccess->createContentEnumeration( SN_THESAURUS );
1095
1096 if (!xEnum.is())
1097 return;
1098
1099 while (xEnum->hasMoreElements())
1100 {
1101 uno::Any aCurrent = xEnum->nextElement();
1102 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1103 uno::Reference< lang::XSingleServiceFactory > xFactory;
1104
1105 xCompFactory.set(aCurrent, css::uno::UNO_QUERY);
1106 if (!xCompFactory.is())
1107 {
1108 xFactory.set(aCurrent, css::uno::UNO_QUERY);
1109 }
1110 if ( xCompFactory.is() || xFactory.is() )
1111 {
1112 try
1113 {
1114 uno::Reference< linguistic2::XThesaurus > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY_THROW );
1115
1116 OUString aImplName;
1117 std::vector< LanguageType > aLanguages;
1118 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1119 if (xInfo.is())
1120 aImplName = xInfo->getImplementationName();
1121 SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" );
1122 uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales());
1123 aLanguages = LocaleSeqToLangVec( aLocaleSequence );
1124
1125 pAvailThesSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) );
1126 }
1127 catch (const uno::Exception &)
1128 {
1129 SAL_WARN( "linguistic", "createInstance failed" );
1130 }
1131 }
1132 }
1133}
1134
1135
1137{
1138 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" );
1139
1140 OUString aNode("ServiceManager/SpellCheckerList");
1141 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1142
1143 // append path prefix need for 'GetProperties' call below
1144 OUString aPrefix = aNode + "/";
1145 for (OUString & name : asNonConstRange(aNames))
1146 {
1147 name = aPrefix + name;
1148 }
1149
1150 const uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1151 if (!(aNames.hasElements() && aNames.getLength() == aValues.getLength()))
1152 return;
1153
1154 const OUString *pNames = aNames.getConstArray();
1155 for (const uno::Any& rValue : aValues)
1156 {
1157 uno::Sequence< OUString > aSvcImplNames;
1158 if (rValue >>= aSvcImplNames)
1159 {
1160 OUString aLocaleStr( *pNames++ );
1161 sal_Int32 nSeparatorPos = aLocaleStr.lastIndexOf( '/' );
1162 aLocaleStr = aLocaleStr.copy( nSeparatorPos + 1 );
1163 rSpellDsp.SetServiceList( LanguageTag::convertToLocale(aLocaleStr), aSvcImplNames );
1164 }
1165 }
1166}
1167
1168
1170{
1171 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" );
1172
1173 OUString aNode("ServiceManager/GrammarCheckerList");
1174 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1175
1176 // append path prefix need for 'GetProperties' call below
1177 OUString aPrefix = aNode + "/";
1178 for (OUString & name : asNonConstRange(aNames))
1179 {
1180 name = aPrefix + name;
1181 }
1182
1183 const uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1184 if (!(aNames.hasElements() && aNames.getLength() == aValues.getLength()))
1185 return;
1186
1187 const OUString *pNames = aNames.getConstArray();
1188 for (const uno::Any& rValue : aValues)
1189 {
1190 uno::Sequence< OUString > aSvcImplNames;
1191 if (rValue >>= aSvcImplNames)
1192 {
1193 // there should only be one grammar checker in use per language...
1194 if (aSvcImplNames.getLength() > 1)
1195 aSvcImplNames.realloc(1);
1196
1197 OUString aLocaleStr( *pNames++ );
1198 sal_Int32 nSeparatorPos = aLocaleStr.lastIndexOf( '/' );
1199 aLocaleStr = aLocaleStr.copy( nSeparatorPos + 1 );
1200 rGrammarDsp.SetServiceList( LanguageTag::convertToLocale(aLocaleStr), aSvcImplNames );
1201 }
1202 }
1203}
1204
1205
1207{
1208 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" );
1209
1210 OUString aNode("ServiceManager/HyphenatorList");
1211 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1212
1213 // append path prefix need for 'GetProperties' call below
1214 OUString aPrefix = aNode + "/";
1215 for (OUString & name : asNonConstRange(aNames))
1216 {
1217 name = aPrefix + name;
1218 }
1219
1220 const uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1221 if (!(aNames.hasElements() && aNames.getLength() == aValues.getLength()))
1222 return;
1223
1224 const OUString *pNames = aNames.getConstArray();
1225 for (const uno::Any& rValue : aValues)
1226 {
1227 uno::Sequence< OUString > aSvcImplNames;
1228 if (rValue >>= aSvcImplNames)
1229 {
1230 // there should only be one hyphenator in use per language...
1231 if (aSvcImplNames.getLength() > 1)
1232 aSvcImplNames.realloc(1);
1233
1234 OUString aLocaleStr( *pNames++ );
1235 sal_Int32 nSeparatorPos = aLocaleStr.lastIndexOf( '/' );
1236 aLocaleStr = aLocaleStr.copy( nSeparatorPos + 1 );
1237 rHyphDsp.SetServiceList( LanguageTag::convertToLocale(aLocaleStr), aSvcImplNames );
1238 }
1239 }
1240}
1241
1242
1244{
1245 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" );
1246
1247 OUString aNode("ServiceManager/ThesaurusList");
1248 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1249
1250 // append path prefix need for 'GetProperties' call below
1251 OUString aPrefix = aNode + "/";
1252 for (OUString & name : asNonConstRange(aNames))
1253 {
1254 name = aPrefix + name;
1255 }
1256
1257 const uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1258 if (!(aNames.hasElements() && aNames.getLength() == aValues.getLength()))
1259 return;
1260
1261 const OUString *pNames = aNames.getConstArray();
1262 for (const uno::Any& rValue : aValues)
1263 {
1264 uno::Sequence< OUString > aSvcImplNames;
1265 if (rValue >>= aSvcImplNames)
1266 {
1267 OUString aLocaleStr( *pNames++ );
1268 sal_Int32 nSeparatorPos = aLocaleStr.lastIndexOf( '/' );
1269 aLocaleStr = aLocaleStr.copy( nSeparatorPos + 1 );
1270 rThesDsp.SetServiceList( LanguageTag::convertToLocale(aLocaleStr), aSvcImplNames );
1271 }
1272 }
1273}
1274
1275
1276uno::Reference< linguistic2::XSpellChecker > SAL_CALL
1278{
1279 osl::MutexGuard aGuard( GetLinguMutex() );
1280#if OSL_DEBUG_LEVEL > 0
1282#endif
1283
1284 uno::Reference< linguistic2::XSpellChecker > xRes;
1285 if (!bDisposing)
1286 {
1287 if (!mxSpellDsp.is())
1289 xRes = mxSpellDsp.get();
1290 }
1291 return xRes;
1292}
1293
1294
1295uno::Reference< linguistic2::XHyphenator > SAL_CALL
1297{
1298 osl::MutexGuard aGuard( GetLinguMutex() );
1299#if OSL_DEBUG_LEVEL > 0
1301#endif
1302 uno::Reference< linguistic2::XHyphenator > xRes;
1303 if (!bDisposing)
1304 {
1305 if (!mxHyphDsp.is())
1307 xRes = mxHyphDsp.get();
1308 }
1309 return xRes;
1310}
1311
1312
1313uno::Reference< linguistic2::XThesaurus > SAL_CALL
1315{
1316 osl::MutexGuard aGuard( GetLinguMutex() );
1317#if OSL_DEBUG_LEVEL > 0
1319#endif
1320 uno::Reference< linguistic2::XThesaurus > xRes;
1321 if (!bDisposing)
1322 {
1323 if (!mxThesDsp.is())
1325 xRes = mxThesDsp.get();
1326 }
1327 return xRes;
1328}
1329
1330
1331sal_Bool SAL_CALL
1333 const uno::Reference< lang::XEventListener >& xListener )
1334{
1335 osl::MutexGuard aGuard( GetLinguMutex() );
1336
1337 if (bDisposing || !xListener.is())
1338 return false;
1339
1340 if (!mxListenerHelper.is())
1342 mxListenerHelper->AddLngSvcMgrListener( xListener );
1343 return true;
1344}
1345
1346
1347sal_Bool SAL_CALL
1349 const uno::Reference< lang::XEventListener >& xListener )
1350{
1351 osl::MutexGuard aGuard( GetLinguMutex() );
1352
1353 if (bDisposing || !xListener.is())
1354 return false;
1355
1356 DBG_ASSERT( mxListenerHelper.is(), "listener removed without being added" );
1357 if (!mxListenerHelper.is())
1359 mxListenerHelper->RemoveLngSvcMgrListener( xListener );
1360 return true;
1361}
1362
1363
1364uno::Sequence< OUString > SAL_CALL
1366 const OUString& rServiceName,
1367 const lang::Locale& rLocale )
1368{
1369 osl::MutexGuard aGuard( GetLinguMutex() );
1370
1371 uno::Sequence< OUString > aRes;
1372 const SvcInfoArray *pInfoArray = nullptr;
1373
1374 if (rServiceName == SN_SPELLCHECKER)
1375 {
1377 pInfoArray = &*pAvailSpellSvcs;
1378 }
1379 else if (rServiceName == SN_GRAMMARCHECKER)
1380 {
1382 pInfoArray = &*pAvailGrammarSvcs;
1383 }
1384 else if (rServiceName == SN_HYPHENATOR)
1385 {
1387 pInfoArray = &*pAvailHyphSvcs;
1388 }
1389 else if (rServiceName == SN_THESAURUS)
1390 {
1392 pInfoArray = &*pAvailThesSvcs;
1393 }
1394
1395 if (pInfoArray)
1396 {
1397 std::vector<OUString> aVec;
1398 aVec.reserve(pInfoArray->size());
1399
1400 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
1401 for (const auto& rInfo : *pInfoArray)
1402 {
1403 if (LinguIsUnspecified( nLanguage )
1404 || rInfo.HasLanguage( nLanguage ))
1405 {
1406 aVec.push_back(rInfo.aSvcImplName);
1407 }
1408 }
1409
1411 }
1412
1413 return aRes;
1414}
1415
1416
1417uno::Sequence< lang::Locale > SAL_CALL
1419 const OUString& rServiceName )
1420{
1421 osl::MutexGuard aGuard( GetLinguMutex() );
1422
1423 uno::Sequence< lang::Locale > aRes;
1424
1425 uno::Sequence< lang::Locale > *pAvailLocales = nullptr;
1426 if (rServiceName == SN_SPELLCHECKER)
1427 pAvailLocales = &aAvailSpellLocales;
1428 else if (rServiceName == SN_GRAMMARCHECKER)
1429 pAvailLocales = &aAvailGrammarLocales;
1430 else if (rServiceName == SN_HYPHENATOR)
1431 pAvailLocales = &aAvailHyphLocales;
1432 else if (rServiceName == SN_THESAURUS)
1433 pAvailLocales = &aAvailThesLocales;
1434
1435 // Nowadays (with OOo lingu in SO) we want to know immediately about
1436 // new downloaded dictionaries and have them ready right away if the Tools/Options...
1437 // is used to activate them. Thus we can not rely anymore on buffered data.
1438 if (pAvailLocales)
1439 {
1440 *pAvailLocales = GetAvailLocales(getAvailableServices(rServiceName, lang::Locale()));
1441 aRes = *pAvailLocales;
1442 }
1443
1444 return aRes;
1445}
1446
1447static bool IsEqSvcList( const uno::Sequence< OUString > &rList1,
1448 const uno::Sequence< OUString > &rList2 )
1449{
1450 // returns true if both sequences are equal
1451 return rList1.getLength() == rList2.getLength()
1452 && std::equal(rList1.begin(), rList1.end(), rList2.begin(), rList2.end());
1453}
1454
1455
1456void SAL_CALL
1458 const OUString& rServiceName,
1459 const lang::Locale& rLocale,
1460 const uno::Sequence< OUString >& rServiceImplNames )
1461{
1462 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::setConfiguredServices" );
1463
1464 osl::MutexGuard aGuard( GetLinguMutex() );
1465
1466 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
1467 if (LinguIsUnspecified( nLanguage))
1468 return;
1469
1470 if (rServiceName == SN_SPELLCHECKER)
1471 {
1472 if (!mxSpellDsp.is())
1474 bool bChanged = !IsEqSvcList( rServiceImplNames,
1475 mxSpellDsp->GetServiceList( rLocale ) );
1476 if (bChanged)
1477 {
1478 mxSpellDsp->SetServiceList( rLocale, rServiceImplNames );
1480
1481 if (mxListenerHelper)
1482 mxListenerHelper->AddLngSvcEvt(
1483 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN |
1484 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN );
1485 }
1486 }
1487 else if (rServiceName == SN_GRAMMARCHECKER)
1488 {
1489 if (!mxGrammarDsp.is())
1491 if (!mxGrammarDsp) // e.g., when !SvtLinguConfig().HasGrammarChecker()
1492 return;
1493 bool bChanged = !IsEqSvcList( rServiceImplNames,
1494 mxGrammarDsp->GetServiceList( rLocale ) );
1495 if (bChanged)
1496 {
1497 mxGrammarDsp->SetServiceList( rLocale, rServiceImplNames );
1499
1500 if (mxListenerHelper)
1501 mxListenerHelper->AddLngSvcEvt(
1502 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN );
1503 }
1504 }
1505 else if (rServiceName == SN_HYPHENATOR)
1506 {
1507 if (!mxHyphDsp.is())
1509 bool bChanged = !IsEqSvcList( rServiceImplNames,
1510 mxHyphDsp->GetServiceList( rLocale ) );
1511 if (bChanged)
1512 {
1513 mxHyphDsp->SetServiceList( rLocale, rServiceImplNames );
1515
1516 if (mxListenerHelper)
1517 mxListenerHelper->AddLngSvcEvt(
1518 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN );
1519 }
1520 }
1521 else if (rServiceName == SN_THESAURUS)
1522 {
1523 if (!mxThesDsp.is())
1525 bool bChanged = !IsEqSvcList( rServiceImplNames,
1526 mxThesDsp->GetServiceList( rLocale ) );
1527 if (bChanged)
1528 {
1529 mxThesDsp->SetServiceList( rLocale, rServiceImplNames );
1531 }
1532 }
1533}
1534
1535
1536bool LngSvcMgr::SaveCfgSvcs( std::u16string_view rServiceName )
1537{
1538 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SaveCfgSvcs" );
1539
1540 bool bRes = false;
1541
1542 LinguDispatcher *pDsp = nullptr;
1543 uno::Sequence< lang::Locale > aLocales;
1544
1545 if (rServiceName == SN_SPELLCHECKER)
1546 {
1547 if (!mxSpellDsp)
1549 pDsp = mxSpellDsp.get();
1551 }
1552 else if (rServiceName == SN_GRAMMARCHECKER)
1553 {
1554 if (!mxGrammarDsp.is())
1556 pDsp = mxGrammarDsp.get();
1558 }
1559 else if (rServiceName == SN_HYPHENATOR)
1560 {
1561 if (!mxHyphDsp.is())
1563 pDsp = mxHyphDsp.get();
1564 aLocales = getAvailableLocales( SN_HYPHENATOR );
1565 }
1566 else if (rServiceName == SN_THESAURUS)
1567 {
1568 if (!mxThesDsp.is())
1570 pDsp = mxThesDsp.get();
1571 aLocales = getAvailableLocales( SN_THESAURUS );
1572 }
1573
1574 if (pDsp && aLocales.hasElements())
1575 {
1576 uno::Sequence< beans::PropertyValue > aValues( aLocales.getLength() );
1577 beans::PropertyValue *pValue = aValues.getArray();
1578
1579 // get node name to be used
1580 const char *pNodeName = nullptr;
1581 if (pDsp == mxSpellDsp.get())
1582 pNodeName = "ServiceManager/SpellCheckerList";
1583 else if (pDsp == mxGrammarDsp.get())
1584 pNodeName = "ServiceManager/GrammarCheckerList";
1585 else if (pDsp == mxHyphDsp.get())
1586 pNodeName = "ServiceManager/HyphenatorList";
1587 else if (pDsp == mxThesDsp.get())
1588 pNodeName = "ServiceManager/ThesaurusList";
1589 else
1590 {
1591 SAL_WARN( "linguistic", "node name missing" );
1592 }
1593 OUString aNodeName( OUString::createFromAscii(pNodeName) );
1594
1595 for (const lang::Locale& rLocale : std::as_const(aLocales))
1596 {
1597 uno::Sequence< OUString > aSvcImplNames = pDsp->GetServiceList( rLocale );
1598
1599 // build value to be written back to configuration
1600 uno::Any aCfgAny;
1601 if ((pDsp == mxHyphDsp.get() || pDsp == mxGrammarDsp.get()) && aSvcImplNames.getLength() > 1)
1602 aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained)
1603 aCfgAny <<= aSvcImplNames;
1604 DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" );
1605
1606 OUString aCfgLocaleStr( LanguageTag::convertToBcp47( rLocale));
1607 pValue->Value = aCfgAny;
1608 pValue->Name = aNodeName + "/" + aCfgLocaleStr;
1609 pValue++;
1610 }
1611 {
1612 SAL_INFO( "linguistic", "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" );
1613 // change, add new or replace existing entries.
1614 bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues );
1615 }
1616 }
1617
1618 return bRes;
1619}
1620
1621
1622static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal )
1623{
1624 uno::Sequence< OUString > aRes;
1625
1626 if (rVal.hasValue())
1627 {
1628 rVal >>= aRes;
1629#if OSL_DEBUG_LEVEL > 0
1630 for (const OUString& rSvcName : std::as_const(aRes))
1631 {
1632 SAL_WARN_IF( rSvcName.isEmpty(), "linguistic", "service impl-name missing" );
1633 }
1634#endif
1635 }
1636
1637 return aRes;
1638}
1639
1640
1641static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal )
1642{
1643 uno::Sequence< OUString > aRes;
1644 if (!rVal.hasValue())
1645 return aRes;
1646
1647 // allowing for a sequence here as well (even though it should only
1648 // be a string) makes coding easier in other places since one needs
1649 // not make a special case for writing a string only and not a
1650 // sequence of strings.
1651 if (rVal >>= aRes)
1652 {
1653 // but only the first string should be used.
1654 if (aRes.getLength() > 1)
1655 aRes.realloc(1);
1656 }
1657 else
1658 {
1659 OUString aImplName;
1660 if ((rVal >>= aImplName) && !aImplName.isEmpty())
1661 {
1662 aRes.realloc(1);
1663 aRes.getArray()[0] = aImplName;
1664 }
1665 else
1666 {
1667 SAL_WARN( "linguistic", "GetLangSvc: unexpected type encountered" );
1668 }
1669 }
1670
1671 return aRes;
1672}
1673
1674
1675uno::Sequence< OUString > SAL_CALL
1677 const OUString& rServiceName,
1678 const lang::Locale& rLocale )
1679{
1680 osl::MutexGuard aGuard( GetLinguMutex() );
1681
1682 uno::Sequence< OUString > aSvcImplNames;
1683
1684 OUString aCfgLocale( LanguageTag::convertToBcp47( rLocale) );
1685
1686 uno::Sequence< uno::Any > aValues;
1687 uno::Sequence< OUString > aNames( 1 );
1688 OUString *pNames = aNames.getArray();
1689 if ( rServiceName == SN_SPELLCHECKER )
1690 {
1691 OUString aNode( "ServiceManager/SpellCheckerList");
1692 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1693 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1694 {
1695 pNames[0] = aNode + "/" + aCfgLocale;
1696 aValues = /*aCfg.*/GetProperties( aNames );
1697 if (aValues.hasElements())
1698 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1699 }
1700 }
1701 else if ( rServiceName == SN_GRAMMARCHECKER )
1702 {
1703 OUString aNode( "ServiceManager/GrammarCheckerList");
1704 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1705 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1706 {
1707 pNames[0] = aNode + "/" + aCfgLocale;
1708 aValues = /*aCfg.*/GetProperties( aNames );
1709 if (aValues.hasElements())
1710 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1711 }
1712 }
1713 else if ( rServiceName == SN_HYPHENATOR )
1714 {
1715 OUString aNode( "ServiceManager/HyphenatorList");
1716 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1717 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1718 {
1719 pNames[0] = aNode + "/" + aCfgLocale;
1720 aValues = /*aCfg.*/GetProperties( aNames );
1721 if (aValues.hasElements())
1722 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1723 }
1724 }
1725 else if ( rServiceName == SN_THESAURUS )
1726 {
1727 OUString aNode( "ServiceManager/ThesaurusList");
1728 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1729 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1730 {
1731 pNames[0] = aNode + "/" + aCfgLocale;
1732 aValues = /*aCfg.*/GetProperties( aNames );
1733 if (aValues.hasElements())
1734 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1735 }
1736 }
1737
1738 return aSvcImplNames;
1739}
1740
1741
1742void SAL_CALL
1744{
1745 osl::MutexGuard aGuard( GetLinguMutex() );
1746
1747 if (!bDisposing)
1748 {
1749 bDisposing = true;
1750
1751 // require listeners to release this object
1752 lang::EventObject aEvtObj( static_cast<XLinguServiceManager*>(this) );
1753 aEvtListeners.disposeAndClear( aEvtObj );
1754
1755 if (mxListenerHelper.is())
1756 mxListenerHelper->DisposeAndClear( aEvtObj );
1757 }
1758}
1759
1760
1761void SAL_CALL
1763 const uno::Reference< lang::XEventListener >& xListener )
1764{
1765 osl::MutexGuard aGuard( GetLinguMutex() );
1766
1767 if (!bDisposing && xListener.is())
1768 {
1769 aEvtListeners.addInterface( xListener );
1770 }
1771}
1772
1773
1774void SAL_CALL
1776 const uno::Reference< lang::XEventListener >& xListener )
1777{
1778 osl::MutexGuard aGuard( GetLinguMutex() );
1779
1780 if (xListener.is())
1781 {
1782 aEvtListeners.removeInterface( xListener );
1783 }
1784}
1785
1786
1788 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
1789{
1790 if (!rxBroadcaster.is())
1791 return false;
1792 if (!mxListenerHelper.is())
1794 mxListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster );
1795 return true;
1796}
1797
1798
1799OUString SAL_CALL
1801{
1802 return "com.sun.star.lingu2.LngSvcMgr";
1803}
1804
1805
1806sal_Bool SAL_CALL
1807 LngSvcMgr::supportsService( const OUString& ServiceName )
1808{
1809 return cppu::supportsService(this, ServiceName);
1810}
1811
1812
1813uno::Sequence< OUString > SAL_CALL
1815{
1816 return { "com.sun.star.linguistic2.LinguServiceManager" };
1817}
1818
1819extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1821 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
1822{
1823 return cppu::acquire(new LngSvcMgr());
1824}
1825
1826
1827/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SetServiceList(const css::lang::Locale &rLocale, const css::uno::Sequence< OUString > &rSvcImplNames) override
virtual void SetServiceList(const css::lang::Locale &rLocale, const css::uno::Sequence< OUString > &rSvcImplNames) override
Definition: hyphdsp.cxx:652
virtual void Start(bool bStartTimer=true) override
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
static OUString convertToBcp47(LanguageType nLangID)
static LanguageType convertToLanguageType(const css::lang::Locale &rLocale, bool bResolveSystem=true)
virtual css::uno::Sequence< OUString > GetServiceList(const css::lang::Locale &rLocale) const =0
void AddLngSvcEvt(sal_Int16 nLngSvcEvt)
Definition: lngsvcmgr.cxx:262
::comphelper::OInterfaceContainerHelper2 aLngSvcMgrListeners
Definition: lngsvcmgr.cxx:165
void RemoveLngSvcMgrListener(const uno::Reference< lang::XEventListener > &rxListener)
Definition: lngsvcmgr.cxx:343
uno::Reference< linguistic2::XSearchableDictionaryList > xDicList
Definition: lngsvcmgr.cxx:167
sal_Int16 nCombinedLngSvcEvt
Definition: lngsvcmgr.cxx:169
virtual void SAL_CALL processDictionaryListEvent(const linguistic2::DictionaryListEvent &rDicListEvent) override
Definition: lngsvcmgr.cxx:279
void AddLngSvcMgrListener(const uno::Reference< lang::XEventListener > &rxListener)
Definition: lngsvcmgr.cxx:336
void DisposeAndClear(const lang::EventObject &rEvtObj)
Definition: lngsvcmgr.cxx:350
LngSvcMgrListenerHelper & operator=(const LngSvcMgrListenerHelper &)=delete
LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper &)=delete
virtual void SAL_CALL disposing(const lang::EventObject &rSource) override
Definition: lngsvcmgr.cxx:227
void LaunchEvent(sal_Int16 nLngSvcEvtFlags)
Definition: lngsvcmgr.cxx:326
void AddLngSvcEvtBroadcaster(const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster)
Definition: lngsvcmgr.cxx:374
void RemoveLngSvcEvtBroadcaster(const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster)
Definition: lngsvcmgr.cxx:386
::comphelper::OInterfaceContainerHelper2 aLngSvcEvtBroadcasters
Definition: lngsvcmgr.cxx:166
virtual void SAL_CALL processLinguServiceEvent(const linguistic2::LinguServiceEvent &aLngSvcEvent) override
Definition: lngsvcmgr.cxx:270
LngSvcMgrListenerHelper(LngSvcMgr &rLngSvcMgr, uno::Reference< linguistic2::XSearchableDictionaryList > xDicList)
Definition: lngsvcmgr.cxx:209
std::optional< SvcInfoArray > pAvailHyphSvcs
Definition: lngsvcmgr.hxx:92
virtual css::uno::Reference< css::linguistic2::XHyphenator > SAL_CALL getHyphenator() override
Definition: lngsvcmgr.cxx:1296
virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServices(const OUString &aServiceName, const css::lang::Locale &aLocale) override
Definition: lngsvcmgr.cxx:1365
virtual void Notify(const css::uno::Sequence< OUString > &rPropertyNames) override
Definition: lngsvcmgr.cxx:711
virtual void SAL_CALL setConfiguredServices(const OUString &aServiceName, const css::lang::Locale &aLocale, const css::uno::Sequence< OUString > &aServiceImplNames) override
Definition: lngsvcmgr.cxx:1457
void GetAvailableSpellSvcs_Impl()
Definition: lngsvcmgr.cxx:918
bool AddLngSvcEvtBroadcaster(const css::uno::Reference< css::linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster)
Definition: lngsvcmgr.cxx:1787
void GetAvailableHyphSvcs_Impl()
Definition: lngsvcmgr.cxx:1031
css::uno::Sequence< css::lang::Locale > aAvailGrammarLocales
Definition: lngsvcmgr.hxx:76
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: lngsvcmgr.cxx:1762
virtual void SAL_CALL modified(const css::lang::EventObject &rEvent) override
Definition: lngsvcmgr.cxx:440
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: lngsvcmgr.cxx:1775
virtual css::uno::Reference< css::linguistic2::XThesaurus > SAL_CALL getThesaurus() override
Definition: lngsvcmgr.cxx:1314
css::uno::Sequence< css::lang::Locale > aAvailThesLocales
Definition: lngsvcmgr.hxx:80
void GetAvailableGrammarSvcs_Impl()
Definition: lngsvcmgr.cxx:972
virtual css::uno::Reference< css::linguistic2::XSpellChecker > SAL_CALL getSpellChecker() override
Definition: lngsvcmgr.cxx:1277
virtual css::uno::Sequence< OUString > SAL_CALL getConfiguredServices(const OUString &aServiceName, const css::lang::Locale &aLocale) override
Definition: lngsvcmgr.cxx:1676
rtl::Reference< ThesaurusDispatcher > mxThesDsp
Definition: lngsvcmgr.hxx:85
virtual sal_Bool SAL_CALL removeLinguServiceManagerListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: lngsvcmgr.cxx:1348
void GetThesaurusDsp_Impl(bool bSetSvcList=true)
Definition: lngsvcmgr.cxx:907
std::optional< SvcInfoArray > pAvailGrammarSvcs
Definition: lngsvcmgr.hxx:91
bool SaveCfgSvcs(std::u16string_view rServiceName)
Definition: lngsvcmgr.cxx:1536
void GetHyphenatorDsp_Impl(bool bSetSvcList=true)
Definition: lngsvcmgr.cxx:896
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getAvailableLocales(const OUString &aServiceName) override
Definition: lngsvcmgr.cxx:1418
virtual ~LngSvcMgr() override
Definition: lngsvcmgr.cxx:499
rtl::Reference< LngSvcMgrListenerHelper > mxListenerHelper
Definition: lngsvcmgr.hxx:87
::comphelper::OInterfaceContainerHelper3< css::lang::XEventListener > aEvtListeners
Definition: lngsvcmgr.hxx:65
Idle aUpdateIdle
Definition: lngsvcmgr.hxx:70
bool bDisposing
Definition: lngsvcmgr.hxx:95
virtual sal_Bool SAL_CALL addLinguServiceManagerListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: lngsvcmgr.cxx:1332
css::uno::Sequence< css::lang::Locale > aAvailSpellLocales
Definition: lngsvcmgr.hxx:74
virtual void SAL_CALL dispose() override
Definition: lngsvcmgr.cxx:1743
friend class LngSvcMgrListenerHelper
Definition: lngsvcmgr.hxx:63
void stopListening()
Definition: lngsvcmgr.cxx:475
void GetGrammarCheckerDsp_Impl(bool bSetSvcList=true)
Definition: lngsvcmgr.cxx:869
css::uno::Sequence< css::lang::Locale > aAvailHyphLocales
Definition: lngsvcmgr.hxx:78
rtl::Reference< HyphenatorDispatcher > mxHyphDsp
Definition: lngsvcmgr.hxx:84
void SetCfgServiceLists(SpellCheckerDispatcher &rSpellDsp)
Definition: lngsvcmgr.cxx:1136
void UpdateAll()
Definition: lngsvcmgr.cxx:607
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: lngsvcmgr.cxx:1807
std::optional< SvcInfoArray > pAvailSpellSvcs
Definition: lngsvcmgr.hxx:90
virtual void SAL_CALL disposing(const css::lang::EventObject &rSource) override
Definition: lngsvcmgr.cxx:494
rtl::Reference< SpellCheckerDispatcher > mxSpellDsp
Definition: lngsvcmgr.hxx:82
void GetListenerHelper_Impl()
Definition: lngsvcmgr.cxx:849
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: lngsvcmgr.cxx:1814
css::uno::Reference< css::util::XModifyBroadcaster > xMB
Definition: lngsvcmgr.hxx:68
std::vector< SvcInfo > SvcInfoArray
Definition: lngsvcmgr.hxx:89
rtl::Reference< GrammarCheckingIterator > mxGrammarDsp
Definition: lngsvcmgr.hxx:83
void GetSpellCheckerDsp_Impl(bool bSetSvcList=true)
Definition: lngsvcmgr.cxx:858
void GetAvailableThesSvcs_Impl()
Definition: lngsvcmgr.cxx:1082
virtual void ImplCommit() override
Definition: lngsvcmgr.cxx:841
virtual OUString SAL_CALL getImplementationName() override
Definition: lngsvcmgr.cxx:1800
std::optional< SvcInfoArray > pAvailThesSvcs
Definition: lngsvcmgr.hxx:93
virtual void SetServiceList(const css::lang::Locale &rLocale, const css::uno::Sequence< OUString > &rSvcImplNames) override
Definition: spelldsp.cxx:756
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode) const
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames) const
bool ReplaceSetProperties(const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
void SetPriority(TaskPriority ePriority)
virtual void SetServiceList(const css::lang::Locale &rLocale, const css::uno::Sequence< OUString > &rSvcImplNames) override
Definition: thesdsp.cxx:191
void SetInvokeHandler(const Link< Timer *, void > &rLink)
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
sal_Int32 addInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
css::uno::XInterface * next()
bool EnableNotification(const css::uno::Sequence< OUString > &rNames, bool bEnableInternalNotification=false)
static css::uno::Sequence< css::uno::Any > GetProperties(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const css::uno::Sequence< OUString > &rNames, bool bAllLocales)
static bool ReplaceSetProperties(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues, bool bAllLocales)
static css::uno::Sequence< OUString > GetNodeNames(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const OUString &rNode, ConfigNameFormat eFormat)
#define DBG_ASSERT(sCon, aError)
float u
Reference< XSingleServiceFactory > xFactory
const char * name
#define LANGUAGE_NONE
static bool lcl_SeqHasString(const uno::Sequence< OUString > &rSeq, const OUString &rText)
Definition: lngsvcmgr.cxx:61
static uno::Sequence< OUString > GetLangSvcList(const uno::Any &rVal)
Definition: lngsvcmgr.cxx:1622
static uno::Sequence< OUString > GetLangSvc(const uno::Any &rVal)
Definition: lngsvcmgr.cxx:1641
static uno::Sequence< lang::Locale > GetAvailLocales(const uno::Sequence< OUString > &rSvcImplNames)
Definition: lngsvcmgr.cxx:68
IMPL_LINK_NOARG(LngSvcMgr, updateAndBroadcast, Timer *, void)
Definition: lngsvcmgr.cxx:459
static bool IsEqSvcList(const uno::Sequence< OUString > &rList1, const uno::Sequence< OUString > &rList2)
Definition: lngsvcmgr.cxx:1447
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * linguistic_LngSvcMgr_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: lngsvcmgr.cxx:1820
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
constexpr OUStringLiteral SN_SPELLCHECKER
Definition: misc.hxx:50
constexpr OUStringLiteral SN_HYPHENATOR
Definition: misc.hxx:51
constexpr OUStringLiteral SN_GRAMMARCHECKER
Definition: misc.hxx:49
constexpr OUStringLiteral SN_THESAURUS
Definition: misc.hxx:52
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
std::vector< LanguageType > LocaleSeqToLangVec(uno::Sequence< Locale > const &rLocaleSeq)
Definition: misc.cxx:363
bool LinguIsUnspecified(LanguageType nLanguage)
Checks if a LanguageType is one of the values that denote absence of language or undetermined languag...
Definition: misc.cxx:88
uno::Reference< XSearchableDictionaryList > GetDictionaryList()
Definition: misc.cxx:671
uno::Reference< XLinguProperties > GetLinguProperties()
Definition: misc.cxx:666
osl::Mutex & GetLinguMutex()
! multi-thread safe mutex for all platforms !!
Definition: misc.cxx:60
LanguageType LinguLocaleToLanguage(const css::lang::Locale &rLocale)
Convert Locale to LanguageType for legacy handling.
Definition: misc.cxx:74
bool HasLanguage(LanguageType nLanguage) const
Definition: lngsvcmgr.cxx:146
const OUString aSvcImplName
Definition: lngsvcmgr.cxx:132
SvcInfo(OUString aSvcImplName_, std::vector< LanguageType > &&rSuppLanguages)
Definition: lngsvcmgr.cxx:135
const std::vector< LanguageType > aSuppLanguages
Definition: lngsvcmgr.cxx:133
bool hasValue()
unsigned char sal_Bool