bump product version to 7.2.5.1
[LibreOffice.git] / linguistic / source / hyphdsp.cxx
blob4036d0c2d5b02360639006112c7bb9bcbb480c22
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>
25 #include <cppuhelper/factory.hxx>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/uno/XComponentContext.hpp>
28 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
29 #include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>
30 #include <rtl/ustrbuf.hxx>
31 #include <i18nlangtag/lang.h>
32 #include <unotools/localedatawrapper.hxx>
33 #include <tools/debug.hxx>
34 #include <svl/lngmisc.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/sequence.hxx>
37 #include <osl/mutex.hxx>
39 #include "hyphdsp.hxx"
40 #include <linguistic/hyphdta.hxx>
41 #include <linguistic/misc.hxx>
42 #include "lngsvcmgr.hxx"
44 using namespace osl;
45 using namespace com::sun::star;
46 using namespace com::sun::star::beans;
47 using namespace com::sun::star::lang;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::linguistic2;
50 using namespace linguistic;
53 HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
54 rMgr (rLngSvcMgr)
59 HyphenatorDispatcher::~HyphenatorDispatcher()
61 ClearSvcList();
65 void HyphenatorDispatcher::ClearSvcList()
67 // release memory for each table entry
68 HyphSvcByLangMap_t().swap(aSvcMap);
72 Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord(
73 const OUString& rOrigWord,
74 const Reference<XDictionaryEntry> &xEntry,
75 LanguageType nLang, sal_Int16 nMaxLeading )
77 MutexGuard aGuard( GetLinguMutex() );
79 Reference< XHyphenatedWord > xRes;
81 if (xEntry.is())
83 OUString aText( xEntry->getDictionaryWord() );
84 sal_Int32 nTextLen = aText.getLength();
86 // trailing '=' means "hyphenation should not be possible"
87 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
89 sal_Int16 nHyphenationPos = -1;
90 sal_Int16 nOrigHyphPos = -1;
92 OUStringBuffer aTmp( nTextLen );
93 bool bSkip = false;
94 bool bSkip2 = false;
95 sal_Int32 nHyphIdx = -1;
96 sal_Int32 nLeading = 0;
97 for (sal_Int32 i = 0; i < nTextLen; i++)
99 sal_Unicode cTmp = aText[i];
100 if (cTmp == '[' || cTmp == ']')
101 bSkip2 = !bSkip2;
102 if (cTmp != '=' && !bSkip2 && cTmp != ']')
104 aTmp.append( cTmp );
105 nLeading++;
106 bSkip = false;
107 nHyphIdx++;
109 else
111 if (!bSkip && nHyphIdx >= 0)
113 if (nLeading <= nMaxLeading) {
114 nHyphenationPos = static_cast<sal_Int16>(nHyphIdx);
115 nOrigHyphPos = i;
118 bSkip = true; //! multiple '=' should count as one only
122 if (nHyphenationPos > 0)
124 #if OSL_DEBUG_LEVEL > 0
126 if (aTmp.toString() != rOrigWord)
128 // both words should only differ by a having a trailing '.'
129 // character or not...
130 OUString aShorter, aLonger;
131 if (aTmp.getLength() <= rOrigWord.getLength())
133 aShorter = aTmp.toString();
134 aLonger = rOrigWord;
136 else
138 aShorter = rOrigWord;
139 aLonger = aTmp.toString();
141 sal_Int32 nS = aShorter.getLength();
142 sal_Int32 nL = aLonger.getLength();
143 if (nS > 0 && nL > 0)
145 assert( ((nS + 1 == nL) && aLonger[nL-1] == '.') && "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
149 #endif
150 sal_Int32 nHyphenPos = -1;
151 if (aText[ nOrigHyphPos ] == '[') // alternative hyphenation
153 sal_Int16 split = 0;
154 sal_Unicode c = aText [ nOrigHyphPos + 1 ];
155 sal_Int32 endhyphpat = aText.indexOf( ']', nOrigHyphPos );
156 if ('0' <= c && c <= '9')
158 split = c - '0';
159 nOrigHyphPos++;
161 if (endhyphpat > -1)
163 OUStringBuffer aTmp2 ( aTmp.copy(0, std::max (nHyphenationPos + 1 - split, 0) ) );
164 aTmp2.append( aText.subView( nOrigHyphPos + 1, endhyphpat - nOrigHyphPos - 1) );
165 nHyphenPos = aTmp2.getLength();
166 aTmp2.append( aTmp.copy( nHyphenationPos + 1 ) );
167 //! take care of #i22591#
168 if (rOrigWord[ rOrigWord.getLength() - 1 ] == '.')
169 aTmp2.append( '.' );
170 aText = aTmp2.makeStringAndClear();
173 if (nHyphenPos == -1)
174 aText = rOrigWord;
176 xRes = new HyphenatedWord( rOrigWord, nLang, nHyphenationPos,
177 aText, (nHyphenPos > -1) ? nHyphenPos - 1 : nHyphenationPos);
182 return xRes;
186 Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
187 const Reference< XDictionaryEntry > &xEntry, LanguageType nLanguage )
189 MutexGuard aGuard( GetLinguMutex() );
191 Reference<XPossibleHyphens> xRes;
193 if (xEntry.is())
195 // text with hyphenation info
196 OUString aText( xEntry->getDictionaryWord() );
197 sal_Int32 nTextLen = aText.getLength();
199 // trailing '=' means "hyphenation should not be possible"
200 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
202 // sequence to hold hyphenation positions
203 Sequence< sal_Int16 > aHyphPos( nTextLen );
204 sal_Int16 *pPos = aHyphPos.getArray();
205 sal_Int32 nHyphCount = 0;
207 OUStringBuffer aTmp( nTextLen );
208 bool bSkip = false;
209 bool bSkip2 = false;
210 sal_Int32 nHyphIdx = -1;
211 for (sal_Int32 i = 0; i < nTextLen; i++)
213 sal_Unicode cTmp = aText[i];
214 if (cTmp == '[' || cTmp == ']')
215 bSkip2 = !bSkip2;
216 if (cTmp != '=' && !bSkip2 && cTmp != ']')
218 aTmp.append( cTmp );
219 bSkip = false;
220 nHyphIdx++;
222 else
224 if (!bSkip && nHyphIdx >= 0)
225 pPos[ nHyphCount++ ] = static_cast<sal_Int16>(nHyphIdx);
226 bSkip = true; //! multiple '=' should count as one only
230 // ignore (multiple) trailing '='
231 if (bSkip && nHyphIdx >= 0)
233 nHyphCount--;
235 DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
237 if (nHyphCount > 0)
239 aHyphPos.realloc( nHyphCount );
240 xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
241 aText, aHyphPos );
246 return xRes;
250 Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
252 MutexGuard aGuard( GetLinguMutex() );
254 std::vector<Locale> aLocales;
255 aLocales.reserve(aSvcMap.size());
257 std::transform(aSvcMap.begin(), aSvcMap.end(), std::back_inserter(aLocales),
258 [](HyphSvcByLangMap_t::const_reference elem) { return LanguageTag::convertToLocale(elem.first); });
260 return comphelper::containerToSequence(aLocales);
264 sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
266 MutexGuard aGuard( GetLinguMutex() );
267 HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LinguLocaleToLanguage( rLocale ) ) );
268 return aIt != aSvcMap.end();
272 Reference< XHyphenatedWord > SAL_CALL
273 HyphenatorDispatcher::hyphenate(
274 const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
275 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
277 MutexGuard aGuard( GetLinguMutex() );
279 Reference< XHyphenatedWord > xRes;
281 sal_Int32 nWordLen = rWord.getLength();
282 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
283 if (LinguIsUnspecified(nLanguage) || !nWordLen ||
284 nMaxLeading == 0 || nMaxLeading == nWordLen)
285 return xRes;
287 // search for entry with that language
288 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
289 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
291 bool bWordModified = false;
292 if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
294 return nullptr;
296 else
298 OUString aChkWord( rWord );
300 // replace typographical apostroph by ascii apostroph
301 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
302 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
303 if (!aSingleQuote.isEmpty())
304 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
306 bWordModified |= RemoveHyphens( aChkWord );
307 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
308 bWordModified |= RemoveControlChars( aChkWord );
309 sal_Int16 nChkMaxLeading = static_cast<sal_Int16>(GetPosInWordToCheck( rWord, nMaxLeading ));
311 // check for results from (positive) dictionaries which have precedence!
312 Reference< XDictionaryEntry > xEntry;
314 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
316 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
317 true, false );
320 if (xEntry.is())
322 //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
323 //! does not distinguish between "XYZ" and "XYZ." in order to avoid
324 //! to require them as different entry we have to supply the
325 //! original word here as well so it can be used in th result
326 //! otherwise a strange effect may occur (see #i22591#)
327 xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
329 else
331 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
332 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
333 "lng : index out of range");
335 sal_Int32 i = 0;
336 Reference< XHyphenator > xHyph;
337 if (pEntry->aSvcRefs.hasElements())
338 xHyph = pEntry->aSvcRefs[0];
340 // try already instantiated service
341 if (i <= pEntry->nLastTriedSvcIndex)
343 if (xHyph.is() && xHyph->hasLocale( rLocale ))
344 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
345 rProperties );
346 ++i;
348 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
349 // instantiate services and try it
351 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
353 Reference< XComponentContext > xContext(
354 comphelper::getProcessComponentContext() );
356 // build service initialization argument
357 Sequence< Any > aArgs(2);
358 aArgs.getArray()[0] <<= GetPropSet();
360 // create specific service via it's implementation name
363 xHyph = Reference< XHyphenator >(
364 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
365 pEntry->aSvcImplNames[0], aArgs, xContext ),
366 UNO_QUERY );
368 catch (uno::Exception &)
370 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
372 pRef [i] = xHyph;
374 Reference< XLinguServiceEventBroadcaster >
375 xBroadcaster( xHyph, UNO_QUERY );
376 if (xBroadcaster.is())
377 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
379 if (xHyph.is() && xHyph->hasLocale( rLocale ))
380 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
381 rProperties );
383 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
384 ++i;
386 // if language is not supported by the services
387 // remove it from the list.
388 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
389 aSvcMap.erase( nLanguage );
391 } // if (xEntry.is())
394 if (bWordModified && xRes.is())
395 xRes = RebuildHyphensAndControlChars( rWord, xRes );
397 if (xRes.is() && xRes->getWord() != rWord)
399 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
400 xRes->getHyphenatedWord(),
401 xRes->getHyphenPos() );
404 return xRes;
408 Reference< XHyphenatedWord > SAL_CALL
409 HyphenatorDispatcher::queryAlternativeSpelling(
410 const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
411 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
413 MutexGuard aGuard( GetLinguMutex() );
415 Reference< XHyphenatedWord > xRes;
417 sal_Int32 nWordLen = rWord.getLength();
418 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
419 if (LinguIsUnspecified(nLanguage) || !nWordLen)
420 return xRes;
422 // search for entry with that language
423 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
424 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
426 bool bWordModified = false;
427 if (!pEntry || 0 > nIndex || nIndex > nWordLen - 2)
429 return nullptr;
431 else
433 OUString aChkWord( rWord );
435 // replace typographical apostroph by ascii apostroph
436 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
437 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
438 if (!aSingleQuote.isEmpty())
439 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
441 bWordModified |= RemoveHyphens( aChkWord );
442 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
443 bWordModified |= RemoveControlChars( aChkWord );
444 sal_Int16 nChkIndex = static_cast<sal_Int16>(GetPosInWordToCheck( rWord, nIndex ));
446 // check for results from (positive) dictionaries which have precedence!
447 Reference< XDictionaryEntry > xEntry;
449 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
451 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
452 true, false );
455 if (xEntry.is())
457 xRes = buildHyphWord(aChkWord, xEntry, nLanguage, nIndex + 1);
458 if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() == nIndex)
459 return xRes;
461 else
463 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
464 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
465 "lng : index out of range");
467 sal_Int32 i = 0;
468 Reference< XHyphenator > xHyph;
469 if (pEntry->aSvcRefs.hasElements())
470 xHyph = pEntry->aSvcRefs[0];
472 // try already instantiated service
473 if (i <= pEntry->nLastTriedSvcIndex)
475 if (xHyph.is() && xHyph->hasLocale( rLocale ))
476 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
477 nChkIndex, rProperties );
478 ++i;
480 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
481 // instantiate services and try it
483 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
485 Reference< XComponentContext > xContext(
486 comphelper::getProcessComponentContext() );
488 // build service initialization argument
489 Sequence< Any > aArgs(2);
490 aArgs.getArray()[0] <<= GetPropSet();
492 // create specific service via it's implementation name
495 xHyph = Reference< XHyphenator >(
496 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
497 pEntry->aSvcImplNames[0], aArgs, xContext ), UNO_QUERY );
499 catch (uno::Exception &)
501 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
503 pRef [i] = xHyph;
505 Reference< XLinguServiceEventBroadcaster >
506 xBroadcaster( xHyph, UNO_QUERY );
507 if (xBroadcaster.is())
508 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
510 if (xHyph.is() && xHyph->hasLocale( rLocale ))
511 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
512 nChkIndex, rProperties );
514 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
515 ++i;
517 // if language is not supported by the services
518 // remove it from the list.
519 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
520 aSvcMap.erase( nLanguage );
522 } // if (xEntry.is())
525 if (bWordModified && xRes.is())
526 xRes = RebuildHyphensAndControlChars( rWord, xRes );
528 if (xRes.is() && xRes->getWord() != rWord)
530 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
531 xRes->getHyphenatedWord(),
532 xRes->getHyphenPos() );
535 return xRes;
539 Reference< XPossibleHyphens > SAL_CALL
540 HyphenatorDispatcher::createPossibleHyphens(
541 const OUString& rWord, const Locale& rLocale,
542 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
544 MutexGuard aGuard( GetLinguMutex() );
546 Reference< XPossibleHyphens > xRes;
548 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
549 if (LinguIsUnspecified(nLanguage) || rWord.isEmpty())
550 return xRes;
552 // search for entry with that language
553 HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
554 LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
556 if (pEntry)
558 OUString aChkWord( rWord );
560 // replace typographical apostroph by ascii apostroph
561 OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
562 DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" );
563 if (!aSingleQuote.isEmpty())
564 aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
566 RemoveHyphens( aChkWord );
567 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
568 RemoveControlChars( aChkWord );
570 // check for results from (positive) dictionaries which have precedence!
571 Reference< XDictionaryEntry > xEntry;
573 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
575 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
576 true, false );
579 if (xEntry.is())
581 xRes = buildPossHyphens( xEntry, nLanguage );
583 else
585 sal_Int32 nLen = pEntry->aSvcImplNames.hasElements() ? 1 : 0;
586 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
587 "lng : index out of range");
589 sal_Int32 i = 0;
590 Reference< XHyphenator > xHyph;
591 if (pEntry->aSvcRefs.hasElements())
592 xHyph = pEntry->aSvcRefs[0];
594 // try already instantiated service
595 if (i <= pEntry->nLastTriedSvcIndex)
597 if (xHyph.is() && xHyph->hasLocale( rLocale ))
598 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
599 rProperties );
600 ++i;
602 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
603 // instantiate services and try it
605 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
607 Reference< XComponentContext > xContext(
608 comphelper::getProcessComponentContext() );
610 // build service initialization argument
611 Sequence< Any > aArgs(2);
612 aArgs.getArray()[0] <<= GetPropSet();
614 // create specific service via it's implementation name
617 xHyph.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
618 pEntry->aSvcImplNames[0], aArgs, xContext ),
619 UNO_QUERY );
621 catch (uno::Exception &)
623 SAL_WARN( "linguistic", "createWithArguments failed" );
625 pRef [i] = xHyph;
627 Reference< XLinguServiceEventBroadcaster >
628 xBroadcaster( xHyph, UNO_QUERY );
629 if (xBroadcaster.is())
630 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
632 if (xHyph.is() && xHyph->hasLocale( rLocale ))
633 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale, rProperties );
635 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
636 ++i;
638 // if language is not supported by the services
639 // remove it from the list.
640 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
641 aSvcMap.erase( nLanguage );
643 } // if (xEntry.is())
646 if (xRes.is() && xRes->getWord() != rWord)
648 xRes = new PossibleHyphens( rWord, nLanguage,
649 xRes->getPossibleHyphens(),
650 xRes->getHyphenationPositions() );
653 return xRes;
657 void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
658 const Sequence< OUString > &rSvcImplNames )
660 MutexGuard aGuard( GetLinguMutex() );
662 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
664 if (!rSvcImplNames.hasElements())
665 // remove entry
666 aSvcMap.erase( nLanguage );
667 else
669 // modify/add entry
670 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
671 if (pEntry)
673 pEntry->Clear();
674 pEntry->aSvcImplNames = rSvcImplNames;
675 pEntry->aSvcImplNames.realloc(1);
676 pEntry->aSvcRefs = Sequence< Reference < XHyphenator > > ( 1 );
678 else
680 auto pTmpEntry = std::make_shared<LangSvcEntries_Hyph>( rSvcImplNames[0] );
681 pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
682 aSvcMap[ nLanguage ] = pTmpEntry;
688 Sequence< OUString >
689 HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
691 MutexGuard aGuard( GetLinguMutex() );
693 Sequence< OUString > aRes;
695 // search for entry with that language and use data from that
696 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
697 const HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( nLanguage ) );
698 const LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
699 if (pEntry)
701 aRes = pEntry->aSvcImplNames;
702 if (aRes.hasElements())
703 aRes.realloc(1);
706 return aRes;
710 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */