look for java, javac and javadoc with the .exe suffix on windows
[LibreOffice.git] / linguistic / source / hyphdsp.cxx
blob6113960d4c9ee2fbede2a62048a08a860bc3b5c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <algorithm>
24 #if OSL_DEBUG_LEVEL > 0
25 #include <utility>
26 #endif
28 #include <cppuhelper/factory.hxx>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/uno/XComponentContext.hpp>
31 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
32 #include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>
33 #include <rtl/ustrbuf.hxx>
34 #include <i18nlangtag/lang.h>
35 #include <unotools/localedatawrapper.hxx>
36 #include <tools/debug.hxx>
37 #include <svl/lngmisc.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/sequence.hxx>
40 #include <osl/mutex.hxx>
42 #include "hyphdsp.hxx"
43 #include <linguistic/hyphdta.hxx>
44 #include <linguistic/misc.hxx>
45 #include "lngsvcmgr.hxx"
47 using namespace osl;
48 using namespace com::sun::star;
49 using namespace com::sun::star::beans;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::linguistic2;
53 using namespace linguistic;
56 HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
57 rMgr (rLngSvcMgr)
62 HyphenatorDispatcher::~HyphenatorDispatcher()
64 ClearSvcList();
68 void HyphenatorDispatcher::ClearSvcList()
70 // release memory for each table entry
71 HyphSvcByLangMap_t().swap(aSvcMap);
75 Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord(
76 const OUString& rOrigWord,
77 const Reference<XDictionaryEntry> &xEntry,
78 LanguageType nLang, sal_Int16 nMaxLeading )
80 MutexGuard aGuard( GetLinguMutex() );
82 Reference< XHyphenatedWord > xRes;
84 if (xEntry.is())
86 OUString aText( xEntry->getDictionaryWord() );
87 sal_Int32 nTextLen = aText.getLength();
89 // trailing '=' means "hyphenation should not be possible"
90 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
92 sal_Int16 nHyphenationPos = -1;
93 sal_Int16 nOrigHyphPos = -1;
95 OUStringBuffer aTmp( nTextLen );
96 bool bSkip = false;
97 bool bSkip2 = false;
98 sal_Int32 nHyphIdx = -1;
99 sal_Int32 nLeading = 0;
100 for (sal_Int32 i = 0; i < nTextLen; i++)
102 sal_Unicode cTmp = aText[i];
103 if (cTmp == '[' || cTmp == ']')
104 bSkip2 = !bSkip2;
105 if (cTmp != '=' && !bSkip2 && cTmp != ']')
107 aTmp.append( cTmp );
108 nLeading++;
109 bSkip = false;
110 nHyphIdx++;
112 else
114 if (!bSkip && nHyphIdx >= 0)
116 if (nLeading <= nMaxLeading) {
117 nHyphenationPos = static_cast<sal_Int16>(nHyphIdx);
118 nOrigHyphPos = i;
121 bSkip = true; //! multiple '=' should count as one only
125 if (nHyphenationPos > 0)
127 #if OSL_DEBUG_LEVEL > 0
129 if (std::u16string_view(aTmp) != rOrigWord)
131 // both words should only differ by a having a trailing '.'
132 // character or not...
133 std::u16string_view aShorter(aTmp), aLonger(rOrigWord);
134 if (aTmp.getLength() > rOrigWord.getLength())
135 std::swap(aShorter, aLonger);
136 sal_Int32 nS = aShorter.size();
137 sal_Int32 nL = aLonger.size();
138 if (nS > 0 && nL > 0)
140 assert( ((nS + 1 == nL) && aLonger[nL-1] == '.') && "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
144 #endif
145 sal_Int32 nHyphenPos = -1;
146 if (aText[ nOrigHyphPos ] == '[') // alternative hyphenation
148 sal_Int16 split = 0;
149 sal_Unicode c = aText [ nOrigHyphPos + 1 ];
150 sal_Int32 endhyphpat = aText.indexOf( ']', nOrigHyphPos );
151 if ('0' <= c && c <= '9')
153 split = c - '0';
154 nOrigHyphPos++;
156 if (endhyphpat > -1)
158 OUStringBuffer aTmp2 ( aTmp.copy(0, std::max (nHyphenationPos + 1 - split, 0) ) );
159 aTmp2.append( aText.subView( nOrigHyphPos + 1, endhyphpat - nOrigHyphPos - 1) );
160 nHyphenPos = aTmp2.getLength();
161 aTmp2.append( aTmp.subView( nHyphenationPos + 1 ) );
162 //! take care of #i22591#
163 if (rOrigWord[ rOrigWord.getLength() - 1 ] == '.')
164 aTmp2.append( '.' );
165 aText = aTmp2.makeStringAndClear();
168 if (nHyphenPos == -1)
169 aText = rOrigWord;
171 xRes = new HyphenatedWord( rOrigWord, nLang, nHyphenationPos,
172 aText, (nHyphenPos > -1) ? nHyphenPos - 1 : nHyphenationPos);
177 return xRes;
181 Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
182 const Reference< XDictionaryEntry > &xEntry, LanguageType nLanguage )
184 MutexGuard aGuard( GetLinguMutex() );
186 Reference<XPossibleHyphens> xRes;
188 if (xEntry.is())
190 // text with hyphenation info
191 OUString aText( xEntry->getDictionaryWord() );
192 sal_Int32 nTextLen = aText.getLength();
194 // trailing '=' means "hyphenation should not be possible"
195 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
197 // sequence to hold hyphenation positions
198 Sequence< sal_Int16 > aHyphPos( nTextLen );
199 sal_Int16 *pPos = aHyphPos.getArray();
200 sal_Int32 nHyphCount = 0;
202 OUStringBuffer aTmp( nTextLen );
203 bool bSkip = false;
204 bool bSkip2 = false;
205 sal_Int32 nHyphIdx = -1;
206 for (sal_Int32 i = 0; i < nTextLen; i++)
208 sal_Unicode cTmp = aText[i];
209 if (cTmp == '[' || cTmp == ']')
210 bSkip2 = !bSkip2;
211 if (cTmp != '=' && !bSkip2 && cTmp != ']')
213 aTmp.append( cTmp );
214 bSkip = false;
215 nHyphIdx++;
217 else
219 if (!bSkip && nHyphIdx >= 0)
220 pPos[ nHyphCount++ ] = static_cast<sal_Int16>(nHyphIdx);
221 bSkip = true; //! multiple '=' should count as one only
225 // ignore (multiple) trailing '='
226 if (bSkip && nHyphIdx >= 0)
228 nHyphCount--;
230 DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
232 if (nHyphCount > 0)
234 aHyphPos.realloc( nHyphCount );
235 xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
236 aText, aHyphPos );
241 return xRes;
245 Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
247 MutexGuard aGuard( GetLinguMutex() );
249 std::vector<Locale> aLocales;
250 aLocales.reserve(aSvcMap.size());
252 std::transform(aSvcMap.begin(), aSvcMap.end(), std::back_inserter(aLocales),
253 [](HyphSvcByLangMap_t::const_reference elem) { return LanguageTag::convertToLocale(elem.first); });
255 return comphelper::containerToSequence(aLocales);
259 sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
261 MutexGuard aGuard( GetLinguMutex() );
262 HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LinguLocaleToLanguage( rLocale ) ) );
263 return aIt != aSvcMap.end();
267 Reference< XHyphenatedWord > SAL_CALL
268 HyphenatorDispatcher::hyphenate(
269 const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
270 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
272 MutexGuard aGuard( GetLinguMutex() );
274 Reference< XHyphenatedWord > xRes;
276 sal_Int32 nWordLen = rWord.getLength();
277 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
278 if (LinguIsUnspecified(nLanguage) || !nWordLen ||
279 nMaxLeading == 0 || nMaxLeading == nWordLen)
280 return xRes;
282 // search for entry with that language
283 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
284 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
286 bool bWordModified = false;
287 if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
289 return nullptr;
291 else
293 OUString aChkWord( rWord );
295 // replace typographical apostroph by ascii apostroph
296 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
297 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
298 if (!aSingleQuote.isEmpty())
299 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
301 bWordModified |= RemoveHyphens( aChkWord );
302 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
303 bWordModified |= RemoveControlChars( aChkWord );
304 sal_Int16 nChkMaxLeading = static_cast<sal_Int16>(GetPosInWordToCheck( rWord, nMaxLeading ));
306 // check for results from (positive) dictionaries which have precedence!
307 Reference< XDictionaryEntry > xEntry;
309 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
311 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
312 true, false );
315 if (xEntry.is())
317 //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
318 //! does not distinguish between "XYZ" and "XYZ." in order to avoid
319 //! to require them as different entry we have to supply the
320 //! original word here as well so it can be used in th result
321 //! otherwise a strange effect may occur (see #i22591#)
322 xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
324 else
326 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
327 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
328 "lng : index out of range");
330 sal_Int32 i = 0;
331 Reference< XHyphenator > xHyph;
332 if (pEntry->aSvcRefs.hasElements())
333 xHyph = pEntry->aSvcRefs[0];
335 // try already instantiated service
336 if (i <= pEntry->nLastTriedSvcIndex)
338 if (xHyph.is() && xHyph->hasLocale( rLocale ))
339 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
340 rProperties );
341 ++i;
343 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
344 // instantiate services and try it
346 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
348 Reference< XComponentContext > xContext(
349 comphelper::getProcessComponentContext() );
351 // build service initialization argument
352 Sequence< Any > aArgs(2);
353 aArgs.getArray()[0] <<= GetPropSet();
355 // create specific service via it's implementation name
358 xHyph = Reference< XHyphenator >(
359 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
360 pEntry->aSvcImplNames[0], aArgs, xContext ),
361 UNO_QUERY );
363 catch (uno::Exception &)
365 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
367 pRef [i] = xHyph;
369 Reference< XLinguServiceEventBroadcaster >
370 xBroadcaster( xHyph, UNO_QUERY );
371 if (xBroadcaster.is())
372 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
374 if (xHyph.is() && xHyph->hasLocale( rLocale ))
375 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
376 rProperties );
378 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
379 ++i;
381 // if language is not supported by the services
382 // remove it from the list.
383 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
384 aSvcMap.erase( nLanguage );
386 } // if (xEntry.is())
389 if (bWordModified && xRes.is())
390 xRes = RebuildHyphensAndControlChars( rWord, xRes );
392 if (xRes.is() && xRes->getWord() != rWord)
394 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
395 xRes->getHyphenatedWord(),
396 xRes->getHyphenPos() );
399 return xRes;
403 Reference< XHyphenatedWord > SAL_CALL
404 HyphenatorDispatcher::queryAlternativeSpelling(
405 const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
406 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
408 MutexGuard aGuard( GetLinguMutex() );
410 Reference< XHyphenatedWord > xRes;
412 sal_Int32 nWordLen = rWord.getLength();
413 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
414 if (LinguIsUnspecified(nLanguage) || !nWordLen)
415 return xRes;
417 // search for entry with that language
418 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
419 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
421 bool bWordModified = false;
422 if (!pEntry || 0 > nIndex || nIndex > nWordLen - 2)
424 return nullptr;
426 else
428 OUString aChkWord( rWord );
430 // replace typographical apostroph by ascii apostroph
431 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
432 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
433 if (!aSingleQuote.isEmpty())
434 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
436 bWordModified |= RemoveHyphens( aChkWord );
437 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
438 bWordModified |= RemoveControlChars( aChkWord );
439 sal_Int16 nChkIndex = static_cast<sal_Int16>(GetPosInWordToCheck( rWord, nIndex ));
441 // check for results from (positive) dictionaries which have precedence!
442 Reference< XDictionaryEntry > xEntry;
444 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
446 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
447 true, false );
450 if (xEntry.is())
452 xRes = buildHyphWord(aChkWord, xEntry, nLanguage, nIndex + 1);
453 if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() == nIndex)
454 return xRes;
456 else
458 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
459 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
460 "lng : index out of range");
462 sal_Int32 i = 0;
463 Reference< XHyphenator > xHyph;
464 if (pEntry->aSvcRefs.hasElements())
465 xHyph = pEntry->aSvcRefs[0];
467 // try already instantiated service
468 if (i <= pEntry->nLastTriedSvcIndex)
470 if (xHyph.is() && xHyph->hasLocale( rLocale ))
471 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
472 nChkIndex, rProperties );
473 ++i;
475 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
476 // instantiate services and try it
478 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
480 Reference< XComponentContext > xContext(
481 comphelper::getProcessComponentContext() );
483 // build service initialization argument
484 Sequence< Any > aArgs(2);
485 aArgs.getArray()[0] <<= GetPropSet();
487 // create specific service via it's implementation name
490 xHyph = Reference< XHyphenator >(
491 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
492 pEntry->aSvcImplNames[0], aArgs, xContext ), UNO_QUERY );
494 catch (uno::Exception &)
496 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
498 pRef [i] = xHyph;
500 Reference< XLinguServiceEventBroadcaster >
501 xBroadcaster( xHyph, UNO_QUERY );
502 if (xBroadcaster.is())
503 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
505 if (xHyph.is() && xHyph->hasLocale( rLocale ))
506 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
507 nChkIndex, rProperties );
509 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
510 ++i;
512 // if language is not supported by the services
513 // remove it from the list.
514 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
515 aSvcMap.erase( nLanguage );
517 } // if (xEntry.is())
520 if (bWordModified && xRes.is())
521 xRes = RebuildHyphensAndControlChars( rWord, xRes );
523 if (xRes.is() && xRes->getWord() != rWord)
525 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
526 xRes->getHyphenatedWord(),
527 xRes->getHyphenPos() );
530 return xRes;
534 Reference< XPossibleHyphens > SAL_CALL
535 HyphenatorDispatcher::createPossibleHyphens(
536 const OUString& rWord, const Locale& rLocale,
537 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
539 MutexGuard aGuard( GetLinguMutex() );
541 Reference< XPossibleHyphens > xRes;
543 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
544 if (LinguIsUnspecified(nLanguage) || rWord.isEmpty())
545 return xRes;
547 // search for entry with that language
548 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
549 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
551 if (pEntry)
553 OUString aChkWord( rWord );
555 // replace typographical apostroph by ascii apostroph
556 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
557 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
558 if (!aSingleQuote.isEmpty())
559 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
561 RemoveHyphens( aChkWord );
562 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
563 RemoveControlChars( aChkWord );
565 // check for results from (positive) dictionaries which have precedence!
566 Reference< XDictionaryEntry > xEntry;
568 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
570 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
571 true, false );
574 if (xEntry.is())
576 xRes = buildPossHyphens( xEntry, nLanguage );
578 else
580 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
581 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
582 "lng : index out of range");
584 sal_Int32 i = 0;
585 Reference< XHyphenator > xHyph;
586 if (pEntry->aSvcRefs.hasElements())
587 xHyph = pEntry->aSvcRefs[0];
589 // try already instantiated service
590 if (i <= pEntry->nLastTriedSvcIndex)
592 if (xHyph.is() && xHyph->hasLocale( rLocale ))
593 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
594 rProperties );
595 ++i;
597 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
598 // instantiate services and try it
600 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
602 Reference< XComponentContext > xContext(
603 comphelper::getProcessComponentContext() );
605 // build service initialization argument
606 Sequence< Any > aArgs(2);
607 aArgs.getArray()[0] <<= GetPropSet();
609 // create specific service via it's implementation name
612 xHyph.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
613 pEntry->aSvcImplNames[0], aArgs, xContext ),
614 UNO_QUERY );
616 catch (uno::Exception &)
618 SAL_WARN( "linguistic", "createWithArguments failed" );
620 pRef [i] = xHyph;
622 Reference< XLinguServiceEventBroadcaster >
623 xBroadcaster( xHyph, UNO_QUERY );
624 if (xBroadcaster.is())
625 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
627 if (xHyph.is() && xHyph->hasLocale( rLocale ))
628 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale, rProperties );
630 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
631 ++i;
633 // if language is not supported by the services
634 // remove it from the list.
635 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
636 aSvcMap.erase( nLanguage );
638 } // if (xEntry.is())
641 if (xRes.is() && xRes->getWord() != rWord)
643 xRes = new PossibleHyphens( rWord, nLanguage,
644 xRes->getPossibleHyphens(),
645 xRes->getHyphenationPositions() );
648 return xRes;
652 void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
653 const Sequence< OUString > &rSvcImplNames )
655 MutexGuard aGuard( GetLinguMutex() );
657 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
659 if (!rSvcImplNames.hasElements())
660 // remove entry
661 aSvcMap.erase( nLanguage );
662 else
664 // modify/add entry
665 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
666 if (pEntry)
668 pEntry->Clear();
669 pEntry->aSvcImplNames = rSvcImplNames;
670 pEntry->aSvcImplNames.realloc(1);
671 pEntry->aSvcRefs = Sequence< Reference < XHyphenator > > ( 1 );
673 else
675 auto pTmpEntry = std::make_shared<LangSvcEntries_Hyph>( rSvcImplNames[0] );
676 pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
677 aSvcMap[ nLanguage ] = pTmpEntry;
683 Sequence< OUString >
684 HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
686 MutexGuard aGuard( GetLinguMutex() );
688 Sequence< OUString > aRes;
690 // search for entry with that language and use data from that
691 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
692 const HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( nLanguage ) );
693 const LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
694 if (pEntry)
696 aRes = pEntry->aSvcImplNames;
697 if (aRes.hasElements())
698 aRes.realloc(1);
701 return aRes;
705 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */