Update ooo320-m1
[ooovba.git] / linguistic / source / hyphdsp.cxx
blob7bc8c343af9dda4e21425f5a2c29deb0afcdff64
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * Copyright 2008 by Sun Microsystems, Inc.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * $RCSfile: hyphdsp.cxx,v $
11 * $Revision: 1.24 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_linguistic.hxx"
36 #include <cppuhelper/factory.hxx> // helper for factories
37 #include <com/sun/star/registry/XRegistryKey.hpp>
38 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
39 #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
40 #include <rtl/ustrbuf.hxx>
41 #include <i18npool/lang.h>
42 #include <unotools/localedatawrapper.hxx>
43 #include <tools/debug.hxx>
44 #include <svtools/lngmisc.hxx>
45 #include <unotools/processfactory.hxx>
46 #include <osl/mutex.hxx>
48 #include "hyphdsp.hxx"
49 #include "hyphdta.hxx"
50 #include "lngprops.hxx"
51 #include "lngsvcmgr.hxx"
54 using namespace utl;
55 using namespace osl;
56 using namespace rtl;
57 using namespace com::sun::star;
58 using namespace com::sun::star::beans;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::linguistic2;
62 using namespace linguistic;
64 ///////////////////////////////////////////////////////////////////////////
66 HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
67 rMgr (rLngSvcMgr)
72 HyphenatorDispatcher::~HyphenatorDispatcher()
74 ClearSvcList();
78 void HyphenatorDispatcher::ClearSvcList()
80 // release memory for each table entry
81 HyphSvcByLangMap_t aTmp;
82 aSvcMap.swap( aTmp );
86 Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord(
87 const OUString rOrigWord,
88 const Reference<XDictionaryEntry> &xEntry,
89 INT16 nLang, INT16 nMaxLeading )
91 MutexGuard aGuard( GetLinguMutex() );
93 Reference< XHyphenatedWord > xRes;
95 if (xEntry.is())
97 OUString aText( xEntry->getDictionaryWord() );
98 INT32 nTextLen = aText.getLength();
100 // trailing '=' means "hyphenation should not be possible"
101 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=')
103 INT16 nHyphenationPos = -1;
105 OUStringBuffer aTmp( nTextLen );
106 BOOL bSkip = FALSE;
107 INT32 nHyphIdx = -1;
108 INT32 nLeading = 0;
109 for (INT32 i = 0; i < nTextLen; i++)
111 sal_Unicode cTmp = aText[i];
112 if (cTmp != '=')
114 aTmp.append( cTmp );
115 nLeading++;
116 bSkip = FALSE;
117 nHyphIdx++;
119 else
121 if (!bSkip && nHyphIdx >= 0)
123 if (nLeading <= nMaxLeading)
124 nHyphenationPos = (INT16) nHyphIdx;
126 bSkip = TRUE; //! multiple '=' should count as one only
130 if (nHyphenationPos > 0)
132 aText = aTmp.makeStringAndClear();
134 #if OSL_DEBUG_LEVEL > 1
136 if (aText != rOrigWord)
138 // both words should only differ by a having a trailing '.'
139 // character or not...
140 OUString aShorter, aLonger;
141 if (aText.getLength() <= rOrigWord.getLength())
143 aShorter = aText;
144 aLonger = rOrigWord;
146 else
148 aShorter = rOrigWord;
149 aLonger = aText;
151 xub_StrLen nS = sal::static_int_cast< xub_StrLen >( aShorter.getLength() );
152 xub_StrLen nL = sal::static_int_cast< xub_StrLen >( aLonger.getLength() );
153 if (nS > 0 && nL > 0)
155 DBG_ASSERT( (nS + 1 == nL) && aLonger[nL-1] == (sal_Unicode) '.',
156 "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
160 #endif
161 //! take care of #i22591#
162 aText = rOrigWord;
164 DBG_ASSERT( aText == rOrigWord, "failed to " );
165 xRes = new HyphenatedWord( aText, nLang, nHyphenationPos,
166 aText, nHyphenationPos );
171 return xRes;
175 Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
176 const Reference< XDictionaryEntry > &xEntry, INT16 nLanguage )
178 MutexGuard aGuard( GetLinguMutex() );
180 Reference<XPossibleHyphens> xRes;
182 if (xEntry.is())
184 // text with hyphenation info
185 OUString aText( xEntry->getDictionaryWord() );
186 INT32 nTextLen = aText.getLength();
188 // trailing '=' means "hyphenation should not be possible"
189 if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=')
191 // sequence to hold hyphenation positions
192 Sequence< INT16 > aHyphPos( nTextLen );
193 INT16 *pPos = aHyphPos.getArray();
194 INT32 nHyphCount = 0;
196 OUStringBuffer aTmp( nTextLen );
197 BOOL bSkip = FALSE;
198 INT32 nHyphIdx = -1;
199 for (INT32 i = 0; i < nTextLen; i++)
201 sal_Unicode cTmp = aText[i];
202 if (cTmp != '=')
204 aTmp.append( cTmp );
205 bSkip = FALSE;
206 nHyphIdx++;
208 else
210 if (!bSkip && nHyphIdx >= 0)
211 pPos[ nHyphCount++ ] = (INT16) nHyphIdx;
212 bSkip = TRUE; //! multiple '=' should count as one only
216 // ignore (multiple) trailing '='
217 if (bSkip && nHyphIdx >= 0)
219 nHyphCount--;
221 DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
223 if (nHyphCount > 0)
225 aHyphPos.realloc( nHyphCount );
226 xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
227 aText, aHyphPos );
232 return xRes;
236 Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
237 throw(RuntimeException)
239 MutexGuard aGuard( GetLinguMutex() );
241 Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
242 Locale *pLocales = aLocales.getArray();
243 HyphSvcByLangMap_t::const_iterator aIt;
244 for (aIt = aSvcMap.begin(); aIt != aSvcMap.end(); ++aIt)
246 *pLocales++ = CreateLocale( aIt->first );
248 return aLocales;
252 BOOL SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
253 throw(RuntimeException)
255 MutexGuard aGuard( GetLinguMutex() );
256 HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LocaleToLanguage( rLocale ) ) );
257 return aIt != aSvcMap.end();
261 Reference< XHyphenatedWord > SAL_CALL
262 HyphenatorDispatcher::hyphenate(
263 const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
264 const PropertyValues& rProperties )
265 throw(IllegalArgumentException, RuntimeException)
267 MutexGuard aGuard( GetLinguMutex() );
269 Reference< XHyphenatedWord > xRes;
271 INT32 nWordLen = rWord.getLength();
272 INT16 nLanguage = LocaleToLanguage( rLocale );
273 if (nLanguage == LANGUAGE_NONE || !nWordLen ||
274 nMaxLeading == 0 || nMaxLeading == nWordLen)
275 return xRes;
277 // search for entry with that language
278 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
280 BOOL bWordModified = FALSE;
281 if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
283 #ifdef LINGU_EXCEPTIONS
284 throw IllegalArgumentException();
285 #else
286 return NULL;
287 #endif
289 else
291 OUString aChkWord( rWord );
293 // replace typographical apostroph by ascii apostroph
294 String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
295 DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
296 if (aSingleQuote.Len())
297 aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
299 bWordModified |= RemoveHyphens( aChkWord );
300 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
301 bWordModified |= RemoveControlChars( aChkWord );
302 INT16 nChkMaxLeading = (INT16) GetPosInWordToCheck( rWord, nMaxLeading );
304 // check for results from (positive) dictionaries which have precedence!
305 Reference< XDictionaryEntry > xEntry;
307 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
309 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
310 TRUE, FALSE );
313 if (xEntry.is())
315 //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
316 //! does not distinguish betwee "XYZ" and "XYZ." in order to avoid
317 //! to require them as different entry we have to supply the
318 //! original word here as well so it can be used in th result
319 //! otherwise a strange effect may occur (see #i22591#)
320 xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
322 else
324 INT32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
325 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
326 "lng : index out of range");
328 INT32 i = 0;
329 Reference< XHyphenator > xHyph;
330 if (pEntry->aSvcRefs.getLength() > 0)
331 xHyph = pEntry->aSvcRefs[0];
333 // try already instantiated service
334 if (i <= pEntry->nLastTriedSvcIndex)
336 if (xHyph.is() && xHyph->hasLocale( rLocale ))
337 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
338 rProperties );
339 ++i;
341 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
342 // instantiate services and try it
344 // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
345 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
347 Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() );
348 if (xMgr.is())
350 // build service initialization argument
351 Sequence< Any > aArgs(2);
352 aArgs.getArray()[0] <<= GetPropSet();
353 //! The dispatcher searches the dictionary-list
354 //! thus the service needs not to now about it
355 //aArgs.getArray()[1] <<= GetDicList();
357 // create specific service via it's implementation name
360 xHyph = Reference< XHyphenator >(
361 xMgr->createInstanceWithArguments(
362 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
364 catch (uno::Exception &)
366 DBG_ASSERT( 0, "createInstanceWithArguments failed" );
368 pRef [i] = xHyph;
370 Reference< XLinguServiceEventBroadcaster >
371 xBroadcaster( xHyph, UNO_QUERY );
372 if (xBroadcaster.is())
373 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
375 if (xHyph.is() && xHyph->hasLocale( rLocale ))
376 xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
377 rProperties );
379 pEntry->nLastTriedSvcIndex = (INT16) i;
380 ++i;
382 // if language is not supported by the services
383 // remove it from the list.
384 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
385 aSvcMap.erase( nLanguage );
388 } // if (xEntry.is())
391 if (bWordModified && xRes.is())
392 xRes = RebuildHyphensAndControlChars( rWord, xRes );
394 if (xRes.is() && xRes->getWord() != rWord)
396 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
397 xRes->getHyphenatedWord(),
398 xRes->getHyphenPos() );
401 return xRes;
405 Reference< XHyphenatedWord > SAL_CALL
406 HyphenatorDispatcher::queryAlternativeSpelling(
407 const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
408 const PropertyValues& rProperties )
409 throw(IllegalArgumentException, RuntimeException)
411 MutexGuard aGuard( GetLinguMutex() );
413 Reference< XHyphenatedWord > xRes;
415 INT32 nWordLen = rWord.getLength();
416 INT16 nLanguage = LocaleToLanguage( rLocale );
417 if (nLanguage == LANGUAGE_NONE || !nWordLen)
418 return xRes;
420 // search for entry with that language
421 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
423 BOOL bWordModified = FALSE;
424 if (!pEntry || !(0 <= nIndex && nIndex <= nWordLen - 2))
426 #ifdef LINGU_EXCEPTIONS
427 throw IllegalArgumentException();
428 #else
429 return NULL;
430 #endif
432 else
434 OUString aChkWord( rWord );
436 // replace typographical apostroph by ascii apostroph
437 String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
438 DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
439 if (aSingleQuote.Len())
440 aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
442 bWordModified |= RemoveHyphens( aChkWord );
443 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
444 bWordModified |= RemoveControlChars( aChkWord );
445 INT16 nChkIndex = (INT16) GetPosInWordToCheck( rWord, nIndex );
447 // check for results from (positive) dictionaries which have precedence!
448 Reference< XDictionaryEntry > xEntry;
450 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
452 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
453 TRUE, FALSE );
456 if (xEntry.is())
458 //! alternative spellings not yet supported by dictionaries
460 else
462 INT32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
463 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
464 "lng : index out of range");
466 INT32 i = 0;
467 Reference< XHyphenator > xHyph;
468 if (pEntry->aSvcRefs.getLength() > 0)
469 xHyph = pEntry->aSvcRefs[0];
471 // try already instantiated service
472 if (i <= pEntry->nLastTriedSvcIndex)
474 if (xHyph.is() && xHyph->hasLocale( rLocale ))
475 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
476 nChkIndex, rProperties );
477 ++i;
479 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
480 // instantiate services and try it
482 // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
483 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
485 Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() );
486 if (xMgr.is())
488 // build service initialization argument
489 Sequence< Any > aArgs(2);
490 aArgs.getArray()[0] <<= GetPropSet();
491 //! The dispatcher searches the dictionary-list
492 //! thus the service needs not to now about it
493 //aArgs.getArray()[1] <<= GetDicList();
495 // create specific service via it's implementation name
498 xHyph = Reference< XHyphenator >(
499 xMgr->createInstanceWithArguments(
500 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
502 catch (uno::Exception &)
504 DBG_ASSERT( 0, "createInstanceWithArguments failed" );
506 pRef [i] = xHyph;
508 Reference< XLinguServiceEventBroadcaster >
509 xBroadcaster( xHyph, UNO_QUERY );
510 if (xBroadcaster.is())
511 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
513 if (xHyph.is() && xHyph->hasLocale( rLocale ))
514 xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
515 nChkIndex, rProperties );
517 pEntry->nLastTriedSvcIndex = (INT16) i;
518 ++i;
520 // if language is not supported by the services
521 // remove it from the list.
522 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
523 aSvcMap.erase( nLanguage );
526 } // if (xEntry.is())
529 if (bWordModified && xRes.is())
530 xRes = RebuildHyphensAndControlChars( rWord, xRes );
532 if (xRes.is() && xRes->getWord() != rWord)
534 xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
535 xRes->getHyphenatedWord(),
536 xRes->getHyphenPos() );
539 return xRes;
543 Reference< XPossibleHyphens > SAL_CALL
544 HyphenatorDispatcher::createPossibleHyphens(
545 const OUString& rWord, const Locale& rLocale,
546 const PropertyValues& rProperties )
547 throw(IllegalArgumentException, RuntimeException)
549 MutexGuard aGuard( GetLinguMutex() );
551 Reference< XPossibleHyphens > xRes;
553 INT16 nLanguage = LocaleToLanguage( rLocale );
554 if (nLanguage == LANGUAGE_NONE || !rWord.getLength())
555 return xRes;
557 // search for entry with that language
558 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
560 if (!pEntry)
562 #ifdef LINGU_EXCEPTIONS
563 throw IllegalArgumentException();
564 #endif
566 else
568 OUString aChkWord( rWord );
570 // replace typographical apostroph by ascii apostroph
571 String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
572 DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
573 if (aSingleQuote.Len())
574 aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
576 RemoveHyphens( aChkWord );
577 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
578 RemoveControlChars( aChkWord );
580 // check for results from (positive) dictionaries which have precedence!
581 Reference< XDictionaryEntry > xEntry;
583 if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
585 xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
586 TRUE, FALSE );
589 if (xEntry.is())
591 xRes = buildPossHyphens( xEntry, nLanguage );
593 else
595 INT32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
596 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
597 "lng : index out of range");
599 INT32 i = 0;
600 Reference< XHyphenator > xHyph;
601 if (pEntry->aSvcRefs.getLength() > 0)
602 xHyph = pEntry->aSvcRefs[0];
604 // try already instantiated service
605 if (i <= pEntry->nLastTriedSvcIndex)
607 if (xHyph.is() && xHyph->hasLocale( rLocale ))
608 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
609 rProperties );
610 ++i;
612 else if (pEntry->nLastTriedSvcIndex < nLen - 1)
613 // instantiate services and try it
615 // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
616 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
618 Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() );
619 if (xMgr.is())
621 // build service initialization argument
622 Sequence< Any > aArgs(2);
623 aArgs.getArray()[0] <<= GetPropSet();
624 //! The dispatcher searches the dictionary-list
625 //! thus the service needs not to now about it
626 //aArgs.getArray()[1] <<= GetDicList();
628 // create specific service via it's implementation name
631 xHyph = Reference< XHyphenator >(
632 xMgr->createInstanceWithArguments(
633 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
635 catch (uno::Exception &)
637 DBG_ASSERT( 0, "createWithArguments failed" );
639 pRef [i] = xHyph;
641 Reference< XLinguServiceEventBroadcaster >
642 xBroadcaster( xHyph, UNO_QUERY );
643 if (xBroadcaster.is())
644 rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
646 if (xHyph.is() && xHyph->hasLocale( rLocale ))
647 xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
648 rProperties );
650 pEntry->nLastTriedSvcIndex = (INT16) i;
651 ++i;
653 // if language is not supported by the services
654 // remove it from the list.
655 if (xHyph.is() && !xHyph->hasLocale( rLocale ))
656 aSvcMap.erase( nLanguage );
659 } // if (xEntry.is())
662 if (xRes.is() && xRes->getWord() != rWord)
664 xRes = new PossibleHyphens( rWord, nLanguage,
665 xRes->getPossibleHyphens(),
666 xRes->getHyphenationPositions() );
669 return xRes;
673 void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
674 const Sequence< OUString > &rSvcImplNames )
676 MutexGuard aGuard( GetLinguMutex() );
678 INT16 nLanguage = LocaleToLanguage( rLocale );
680 INT32 nLen = rSvcImplNames.getLength();
681 if (0 == nLen)
682 // remove entry
683 aSvcMap.erase( nLanguage );
684 else
686 // modify/add entry
687 LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
688 // only one hypenator can be in use for a language...
689 //const OUString &rSvcImplName = rSvcImplNames.getConstArray()[0];
690 if (pEntry)
692 pEntry->Clear();
693 pEntry->aSvcImplNames = rSvcImplNames;
694 pEntry->aSvcImplNames.realloc(1);
695 pEntry->aSvcRefs = Sequence< Reference < XHyphenator > > ( 1 );
697 else
699 boost::shared_ptr< LangSvcEntries_Hyph > pTmpEntry( new LangSvcEntries_Hyph( rSvcImplNames[0] ) );
700 pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
701 aSvcMap[ nLanguage ] = pTmpEntry;
707 Sequence< OUString >
708 HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
710 MutexGuard aGuard( GetLinguMutex() );
712 Sequence< OUString > aRes;
714 // search for entry with that language and use data from that
715 INT16 nLanguage = LocaleToLanguage( rLocale );
716 HyphenatorDispatcher *pThis = (HyphenatorDispatcher *) this;
717 const LangSvcEntries_Hyph *pEntry = pThis->aSvcMap[ nLanguage ].get();
718 if (pEntry)
720 aRes = pEntry->aSvcImplNames;
721 if (aRes.getLength() > 0)
722 aRes.realloc(1);
725 return aRes;
729 LinguDispatcher::DspType HyphenatorDispatcher::GetDspType() const
731 return DSP_HYPH;
735 ///////////////////////////////////////////////////////////////////////////