xref: /aoo41x/main/linguistic/source/hyphdsp.cxx (revision 3b8558fd)
1*3b8558fdSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*3b8558fdSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*3b8558fdSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*3b8558fdSAndrew Rist  * distributed with this work for additional information
6*3b8558fdSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*3b8558fdSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*3b8558fdSAndrew Rist  * "License"); you may not use this file except in compliance
9*3b8558fdSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*3b8558fdSAndrew Rist  *
11*3b8558fdSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*3b8558fdSAndrew Rist  *
13*3b8558fdSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*3b8558fdSAndrew Rist  * software distributed under the License is distributed on an
15*3b8558fdSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*3b8558fdSAndrew Rist  * KIND, either express or implied.  See the License for the
17*3b8558fdSAndrew Rist  * specific language governing permissions and limitations
18*3b8558fdSAndrew Rist  * under the License.
19*3b8558fdSAndrew Rist  *
20*3b8558fdSAndrew Rist  *************************************************************/
21*3b8558fdSAndrew Rist 
22*3b8558fdSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_linguistic.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <cppuhelper/factory.hxx>	// helper for factories
29cdf0e10cSrcweir #include <com/sun/star/registry/XRegistryKey.hpp>
30cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
31cdf0e10cSrcweir #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
32cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
33cdf0e10cSrcweir #include <i18npool/lang.h>
34cdf0e10cSrcweir #include <unotools/localedatawrapper.hxx>
35cdf0e10cSrcweir #include <tools/debug.hxx>
36cdf0e10cSrcweir #include <svl/lngmisc.hxx>
37cdf0e10cSrcweir #include <unotools/processfactory.hxx>
38cdf0e10cSrcweir #include <osl/mutex.hxx>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "hyphdsp.hxx"
41cdf0e10cSrcweir #include "linguistic/hyphdta.hxx"
42cdf0e10cSrcweir #include "linguistic/lngprops.hxx"
43cdf0e10cSrcweir #include "lngsvcmgr.hxx"
44cdf0e10cSrcweir 
45cdf0e10cSrcweir 
46cdf0e10cSrcweir using namespace utl;
47cdf0e10cSrcweir using namespace osl;
48cdf0e10cSrcweir using namespace rtl;
49cdf0e10cSrcweir using namespace com::sun::star;
50cdf0e10cSrcweir using namespace com::sun::star::beans;
51cdf0e10cSrcweir using namespace com::sun::star::lang;
52cdf0e10cSrcweir using namespace com::sun::star::uno;
53cdf0e10cSrcweir using namespace com::sun::star::linguistic2;
54cdf0e10cSrcweir using namespace linguistic;
55cdf0e10cSrcweir 
56cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
57cdf0e10cSrcweir 
HyphenatorDispatcher(LngSvcMgr & rLngSvcMgr)58cdf0e10cSrcweir HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
59cdf0e10cSrcweir 	rMgr	(rLngSvcMgr)
60cdf0e10cSrcweir {
61cdf0e10cSrcweir }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir 
~HyphenatorDispatcher()64cdf0e10cSrcweir HyphenatorDispatcher::~HyphenatorDispatcher()
65cdf0e10cSrcweir {
66cdf0e10cSrcweir 	ClearSvcList();
67cdf0e10cSrcweir }
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 
ClearSvcList()70cdf0e10cSrcweir void HyphenatorDispatcher::ClearSvcList()
71cdf0e10cSrcweir {
72cdf0e10cSrcweir 	// release memory for each table entry
73cdf0e10cSrcweir     HyphSvcByLangMap_t aTmp;
74cdf0e10cSrcweir     aSvcMap.swap( aTmp );
75cdf0e10cSrcweir }
76cdf0e10cSrcweir 
77cdf0e10cSrcweir 
buildHyphWord(const OUString rOrigWord,const Reference<XDictionaryEntry> & xEntry,sal_Int16 nLang,sal_Int16 nMaxLeading)78cdf0e10cSrcweir Reference<XHyphenatedWord>	HyphenatorDispatcher::buildHyphWord(
79cdf0e10cSrcweir             const OUString rOrigWord,
80cdf0e10cSrcweir 			const Reference<XDictionaryEntry> &xEntry,
81cdf0e10cSrcweir 			sal_Int16 nLang, sal_Int16 nMaxLeading )
82cdf0e10cSrcweir {
83cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
84cdf0e10cSrcweir 
85cdf0e10cSrcweir 	Reference< XHyphenatedWord > xRes;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 	if (xEntry.is())
88cdf0e10cSrcweir 	{
89cdf0e10cSrcweir 		OUString aText( xEntry->getDictionaryWord() );
90cdf0e10cSrcweir 		sal_Int32 nTextLen = aText.getLength();
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 		// trailing '=' means "hyphenation should not be possible"
93cdf0e10cSrcweir 		if (nTextLen > 0  &&  aText[ nTextLen - 1 ] != '=')
94cdf0e10cSrcweir 		{
95cdf0e10cSrcweir 			sal_Int16 nHyphenationPos = -1;
96cdf0e10cSrcweir 
97cdf0e10cSrcweir 			OUStringBuffer aTmp( nTextLen );
98cdf0e10cSrcweir 			sal_Bool  bSkip = sal_False;
99cdf0e10cSrcweir 			sal_Int32 nHyphIdx = -1;
100cdf0e10cSrcweir 			sal_Int32 nLeading = 0;
101cdf0e10cSrcweir 			for (sal_Int32 i = 0;  i < nTextLen;  i++)
102cdf0e10cSrcweir 			{
103cdf0e10cSrcweir 				sal_Unicode cTmp = aText[i];
104cdf0e10cSrcweir 				if (cTmp != '=')
105cdf0e10cSrcweir 				{
106cdf0e10cSrcweir 					aTmp.append( cTmp );
107cdf0e10cSrcweir 					nLeading++;
108cdf0e10cSrcweir 					bSkip = sal_False;
109cdf0e10cSrcweir 					nHyphIdx++;
110cdf0e10cSrcweir 				}
111cdf0e10cSrcweir 				else
112cdf0e10cSrcweir 				{
113cdf0e10cSrcweir 					if (!bSkip  &&  nHyphIdx >= 0)
114cdf0e10cSrcweir 					{
115cdf0e10cSrcweir 						if (nLeading <= nMaxLeading)
116cdf0e10cSrcweir                             nHyphenationPos = (sal_Int16) nHyphIdx;
117cdf0e10cSrcweir 					}
118cdf0e10cSrcweir 					bSkip = sal_True;	//! multiple '=' should count as one only
119cdf0e10cSrcweir 				}
120cdf0e10cSrcweir 			}
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 			if (nHyphenationPos > 0)
123cdf0e10cSrcweir 			{
124cdf0e10cSrcweir 				aText = aTmp.makeStringAndClear();
125cdf0e10cSrcweir 
126cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
127cdf0e10cSrcweir                 {
128cdf0e10cSrcweir                     if (aText != rOrigWord)
129cdf0e10cSrcweir                     {
130cdf0e10cSrcweir                         // both words should only differ by a having a trailing '.'
131cdf0e10cSrcweir                         // character or not...
132cdf0e10cSrcweir                         OUString aShorter, aLonger;
133cdf0e10cSrcweir                         if (aText.getLength() <= rOrigWord.getLength())
134cdf0e10cSrcweir                         {
135cdf0e10cSrcweir                             aShorter = aText;
136cdf0e10cSrcweir                             aLonger  = rOrigWord;
137cdf0e10cSrcweir                         }
138cdf0e10cSrcweir                         else
139cdf0e10cSrcweir                         {
140cdf0e10cSrcweir                             aShorter = rOrigWord;
141cdf0e10cSrcweir                             aLonger  = aText;
142cdf0e10cSrcweir                         }
143cdf0e10cSrcweir                         xub_StrLen nS = sal::static_int_cast< xub_StrLen >( aShorter.getLength() );
144cdf0e10cSrcweir                         xub_StrLen nL = sal::static_int_cast< xub_StrLen >( aLonger.getLength() );
145cdf0e10cSrcweir                         if (nS > 0 && nL > 0)
146cdf0e10cSrcweir                         {
147cdf0e10cSrcweir                             DBG_ASSERT( (nS + 1 == nL) && aLonger[nL-1] == (sal_Unicode) '.',
148cdf0e10cSrcweir                                 "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
149cdf0e10cSrcweir                         }
150cdf0e10cSrcweir                     }
151cdf0e10cSrcweir                 }
152cdf0e10cSrcweir #endif
153cdf0e10cSrcweir                 //! take care of #i22591#
154cdf0e10cSrcweir                 aText = rOrigWord;
155cdf0e10cSrcweir 
156cdf0e10cSrcweir                 DBG_ASSERT( aText == rOrigWord, "failed to " );
157cdf0e10cSrcweir                 xRes = new HyphenatedWord( aText, nLang, nHyphenationPos,
158cdf0e10cSrcweir 								aText, nHyphenationPos );
159cdf0e10cSrcweir 			}
160cdf0e10cSrcweir 		}
161cdf0e10cSrcweir 	}
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 	return xRes;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
166cdf0e10cSrcweir 
buildPossHyphens(const Reference<XDictionaryEntry> & xEntry,sal_Int16 nLanguage)167cdf0e10cSrcweir Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
168cdf0e10cSrcweir 			const Reference< XDictionaryEntry > &xEntry, sal_Int16 nLanguage )
169cdf0e10cSrcweir {
170cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	Reference<XPossibleHyphens> xRes;
173cdf0e10cSrcweir 
174cdf0e10cSrcweir 	if (xEntry.is())
175cdf0e10cSrcweir 	{
176cdf0e10cSrcweir 		// text with hyphenation info
177cdf0e10cSrcweir 		OUString aText( xEntry->getDictionaryWord() );
178cdf0e10cSrcweir 		sal_Int32 nTextLen = aText.getLength();
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 		// trailing '=' means "hyphenation should not be possible"
181cdf0e10cSrcweir 		if (nTextLen > 0  &&  aText[ nTextLen - 1 ] != '=')
182cdf0e10cSrcweir 		{
183cdf0e10cSrcweir 			// sequence to hold hyphenation positions
184cdf0e10cSrcweir 			Sequence< sal_Int16 > aHyphPos( nTextLen );
185cdf0e10cSrcweir 			sal_Int16 *pPos = aHyphPos.getArray();
186cdf0e10cSrcweir 			sal_Int32 nHyphCount = 0;
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 			OUStringBuffer aTmp( nTextLen );
189cdf0e10cSrcweir 			sal_Bool  bSkip = sal_False;
190cdf0e10cSrcweir 			sal_Int32 nHyphIdx = -1;
191cdf0e10cSrcweir 			for (sal_Int32 i = 0;  i < nTextLen;  i++)
192cdf0e10cSrcweir 			{
193cdf0e10cSrcweir 				sal_Unicode cTmp = aText[i];
194cdf0e10cSrcweir 				if (cTmp != '=')
195cdf0e10cSrcweir 				{
196cdf0e10cSrcweir 					aTmp.append( cTmp );
197cdf0e10cSrcweir 					bSkip = sal_False;
198cdf0e10cSrcweir 					nHyphIdx++;
199cdf0e10cSrcweir 				}
200cdf0e10cSrcweir 				else
201cdf0e10cSrcweir 				{
202cdf0e10cSrcweir 					if (!bSkip  &&  nHyphIdx >= 0)
203cdf0e10cSrcweir                         pPos[ nHyphCount++ ] = (sal_Int16) nHyphIdx;
204cdf0e10cSrcweir 					bSkip = sal_True;	//! multiple '=' should count as one only
205cdf0e10cSrcweir 				}
206cdf0e10cSrcweir 			}
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 			// ignore (multiple) trailing '='
209cdf0e10cSrcweir 			if (bSkip  &&  nHyphIdx >= 0)
210cdf0e10cSrcweir 			{
211cdf0e10cSrcweir 				nHyphCount--;
212cdf0e10cSrcweir 			}
213cdf0e10cSrcweir 			DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
214cdf0e10cSrcweir 
215cdf0e10cSrcweir 			if (nHyphCount > 0)
216cdf0e10cSrcweir 			{
217cdf0e10cSrcweir 				aHyphPos.realloc( nHyphCount );
218cdf0e10cSrcweir 				xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
219cdf0e10cSrcweir 								aText, aHyphPos );
220cdf0e10cSrcweir 			}
221cdf0e10cSrcweir 		}
222cdf0e10cSrcweir 	}
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 	return xRes;
225cdf0e10cSrcweir }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 
getLocales()228cdf0e10cSrcweir Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
229cdf0e10cSrcweir 		throw(RuntimeException)
230cdf0e10cSrcweir {
231cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir     Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
234cdf0e10cSrcweir     Locale *pLocales = aLocales.getArray();
235cdf0e10cSrcweir     HyphSvcByLangMap_t::const_iterator aIt;
236cdf0e10cSrcweir     for (aIt = aSvcMap.begin();  aIt != aSvcMap.end();  ++aIt)
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         *pLocales++ = CreateLocale( aIt->first );
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir 	return aLocales;
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 
hasLocale(const Locale & rLocale)244cdf0e10cSrcweir sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
245cdf0e10cSrcweir 		throw(RuntimeException)
246cdf0e10cSrcweir {
247cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
248cdf0e10cSrcweir     HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LocaleToLanguage( rLocale ) ) );
249cdf0e10cSrcweir     return aIt != aSvcMap.end();
250cdf0e10cSrcweir }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 
253cdf0e10cSrcweir Reference< XHyphenatedWord > SAL_CALL
hyphenate(const OUString & rWord,const Locale & rLocale,sal_Int16 nMaxLeading,const PropertyValues & rProperties)254cdf0e10cSrcweir 	HyphenatorDispatcher::hyphenate(
255cdf0e10cSrcweir 			const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
256cdf0e10cSrcweir 			const PropertyValues& rProperties )
257cdf0e10cSrcweir 		throw(IllegalArgumentException, RuntimeException)
258cdf0e10cSrcweir {
259cdf0e10cSrcweir     MutexGuard	aGuard( GetLinguMutex() );
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 	Reference< XHyphenatedWord >	xRes;
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     sal_Int32 nWordLen = rWord.getLength();
264cdf0e10cSrcweir 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
265cdf0e10cSrcweir     if (nLanguage == LANGUAGE_NONE  || !nWordLen ||
266cdf0e10cSrcweir         nMaxLeading == 0 || nMaxLeading == nWordLen)
267cdf0e10cSrcweir 		return xRes;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 	// search for entry with that language
270cdf0e10cSrcweir     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
271cdf0e10cSrcweir     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 	sal_Bool bWordModified = sal_False;
274cdf0e10cSrcweir     if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
275cdf0e10cSrcweir 	{
276cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS
277cdf0e10cSrcweir 		throw IllegalArgumentException();
278cdf0e10cSrcweir #else
279cdf0e10cSrcweir         return NULL;
280cdf0e10cSrcweir #endif
281cdf0e10cSrcweir 	}
282cdf0e10cSrcweir 	else
283cdf0e10cSrcweir 	{
284cdf0e10cSrcweir 		OUString aChkWord( rWord );
285cdf0e10cSrcweir 
286cdf0e10cSrcweir         // replace typographical apostroph by ascii apostroph
287cdf0e10cSrcweir         String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
288cdf0e10cSrcweir         DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
289cdf0e10cSrcweir         if (aSingleQuote.Len())
290cdf0e10cSrcweir             aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
291cdf0e10cSrcweir 
292cdf0e10cSrcweir 		bWordModified |= RemoveHyphens( aChkWord );
293cdf0e10cSrcweir 		if (IsIgnoreControlChars( rProperties, GetPropSet() ))
294cdf0e10cSrcweir 			bWordModified |= RemoveControlChars( aChkWord );
295cdf0e10cSrcweir         sal_Int16 nChkMaxLeading = (sal_Int16) GetPosInWordToCheck( rWord, nMaxLeading );
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 		// check for results from (positive) dictionaries which have precedence!
298cdf0e10cSrcweir 		Reference< XDictionaryEntry > xEntry;
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 		if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
301cdf0e10cSrcweir 		{
302cdf0e10cSrcweir 			xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
303cdf0e10cSrcweir 						sal_True, sal_False );
304cdf0e10cSrcweir 		}
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 		if (xEntry.is())
307cdf0e10cSrcweir 		{
308cdf0e10cSrcweir             //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
309cdf0e10cSrcweir             //! does not distinguish betwee "XYZ" and "XYZ." in order to avoid
310cdf0e10cSrcweir             //! to require them as different entry we have to supply the
311cdf0e10cSrcweir             //! original word here as well so it can be used in th result
312cdf0e10cSrcweir             //! otherwise a strange effect may occur (see #i22591#)
313cdf0e10cSrcweir             xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
314cdf0e10cSrcweir 		}
315cdf0e10cSrcweir 		else
316cdf0e10cSrcweir 		{
317cdf0e10cSrcweir             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
318cdf0e10cSrcweir             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
319cdf0e10cSrcweir 					"lng : index out of range");
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 			sal_Int32 i = 0;
322cdf0e10cSrcweir             Reference< XHyphenator > xHyph;
323cdf0e10cSrcweir             if (pEntry->aSvcRefs.getLength() > 0)
324cdf0e10cSrcweir                 xHyph = pEntry->aSvcRefs[0];
325cdf0e10cSrcweir 
326cdf0e10cSrcweir 			// try already instantiated service
327cdf0e10cSrcweir             if (i <= pEntry->nLastTriedSvcIndex)
328cdf0e10cSrcweir 			{
329cdf0e10cSrcweir                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
330cdf0e10cSrcweir                     xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
331cdf0e10cSrcweir 											rProperties );
332cdf0e10cSrcweir 				++i;
333cdf0e10cSrcweir 			}
334cdf0e10cSrcweir             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
335cdf0e10cSrcweir 			// instantiate services and try it
336cdf0e10cSrcweir 			{
337cdf0e10cSrcweir //                const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
338cdf0e10cSrcweir                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
339cdf0e10cSrcweir 
340cdf0e10cSrcweir 				Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
341cdf0e10cSrcweir 				if (xMgr.is())
342cdf0e10cSrcweir 				{
343cdf0e10cSrcweir 					// build service initialization argument
344cdf0e10cSrcweir 					Sequence< Any > aArgs(2);
345cdf0e10cSrcweir 					aArgs.getArray()[0] <<= GetPropSet();
346cdf0e10cSrcweir 					//! The dispatcher searches the dictionary-list
347cdf0e10cSrcweir 					//! thus the service needs not to now about it
348cdf0e10cSrcweir 					//aArgs.getArray()[1] <<= GetDicList();
349cdf0e10cSrcweir 
350cdf0e10cSrcweir 					// create specific service via it's implementation name
351cdf0e10cSrcweir 					try
352cdf0e10cSrcweir 					{
353cdf0e10cSrcweir 						xHyph = Reference< XHyphenator >(
354cdf0e10cSrcweir 								xMgr->createInstanceWithArguments(
355cdf0e10cSrcweir                                 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
356cdf0e10cSrcweir 					}
357cdf0e10cSrcweir 					catch (uno::Exception &)
358cdf0e10cSrcweir 					{
359cdf0e10cSrcweir                         DBG_ASSERT( 0, "createInstanceWithArguments failed" );
360cdf0e10cSrcweir 					}
361cdf0e10cSrcweir                     pRef [i] = xHyph;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 					Reference< XLinguServiceEventBroadcaster >
364cdf0e10cSrcweir 							xBroadcaster( xHyph, UNO_QUERY );
365cdf0e10cSrcweir 					if (xBroadcaster.is())
366cdf0e10cSrcweir 						rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
367cdf0e10cSrcweir 
368cdf0e10cSrcweir                     if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
369cdf0e10cSrcweir                         xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
370cdf0e10cSrcweir 												rProperties );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
373cdf0e10cSrcweir 					++i;
374cdf0e10cSrcweir 
375cdf0e10cSrcweir                     // if language is not supported by the services
376cdf0e10cSrcweir                     // remove it from the list.
377cdf0e10cSrcweir                     if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
378cdf0e10cSrcweir                         aSvcMap.erase( nLanguage );
379cdf0e10cSrcweir                 }
380cdf0e10cSrcweir 			}
381cdf0e10cSrcweir 		}	// if (xEntry.is())
382cdf0e10cSrcweir 	}
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 	if (bWordModified  &&  xRes.is())
385cdf0e10cSrcweir 		xRes = RebuildHyphensAndControlChars( rWord, xRes );
386cdf0e10cSrcweir 
387cdf0e10cSrcweir     if (xRes.is()  &&  xRes->getWord() != rWord)
388cdf0e10cSrcweir     {
389cdf0e10cSrcweir         xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
390cdf0e10cSrcweir                                    xRes->getHyphenatedWord(),
391cdf0e10cSrcweir                                    xRes->getHyphenPos() );
392cdf0e10cSrcweir     }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 	return xRes;
395cdf0e10cSrcweir }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir 
398cdf0e10cSrcweir Reference< XHyphenatedWord > SAL_CALL
queryAlternativeSpelling(const OUString & rWord,const Locale & rLocale,sal_Int16 nIndex,const PropertyValues & rProperties)399cdf0e10cSrcweir 	HyphenatorDispatcher::queryAlternativeSpelling(
400cdf0e10cSrcweir 			const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
401cdf0e10cSrcweir 			const PropertyValues& rProperties )
402cdf0e10cSrcweir 		throw(IllegalArgumentException, RuntimeException)
403cdf0e10cSrcweir {
404cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 	Reference< XHyphenatedWord >	xRes;
407cdf0e10cSrcweir 
408cdf0e10cSrcweir     sal_Int32 nWordLen = rWord.getLength();
409cdf0e10cSrcweir 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
410cdf0e10cSrcweir     if (nLanguage == LANGUAGE_NONE  || !nWordLen)
411cdf0e10cSrcweir 		return xRes;
412cdf0e10cSrcweir 
413cdf0e10cSrcweir 	// search for entry with that language
414cdf0e10cSrcweir     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
415cdf0e10cSrcweir     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 	sal_Bool bWordModified = sal_False;
418cdf0e10cSrcweir     if (!pEntry || !(0 <= nIndex && nIndex <= nWordLen - 2))
419cdf0e10cSrcweir 	{
420cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS
421cdf0e10cSrcweir 		throw IllegalArgumentException();
422cdf0e10cSrcweir #else
423cdf0e10cSrcweir         return NULL;
424cdf0e10cSrcweir #endif
425cdf0e10cSrcweir 	}
426cdf0e10cSrcweir 	else
427cdf0e10cSrcweir 	{
428cdf0e10cSrcweir         OUString aChkWord( rWord );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir         // replace typographical apostroph by ascii apostroph
431cdf0e10cSrcweir         String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
432cdf0e10cSrcweir         DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
433cdf0e10cSrcweir         if (aSingleQuote.Len())
434cdf0e10cSrcweir             aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir 		bWordModified |= RemoveHyphens( aChkWord );
437cdf0e10cSrcweir 		if (IsIgnoreControlChars( rProperties, GetPropSet() ))
438cdf0e10cSrcweir 			bWordModified |= RemoveControlChars( aChkWord );
439cdf0e10cSrcweir         sal_Int16 nChkIndex = (sal_Int16) GetPosInWordToCheck( rWord, nIndex );
440cdf0e10cSrcweir 
441cdf0e10cSrcweir 		// check for results from (positive) dictionaries which have precedence!
442cdf0e10cSrcweir 		Reference< XDictionaryEntry > xEntry;
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 		if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
445cdf0e10cSrcweir 		{
446cdf0e10cSrcweir 			xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
447cdf0e10cSrcweir 						sal_True, sal_False );
448cdf0e10cSrcweir 		}
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 		if (xEntry.is())
451cdf0e10cSrcweir 		{
452cdf0e10cSrcweir 			//! alternative spellings not yet supported by dictionaries
453cdf0e10cSrcweir 		}
454cdf0e10cSrcweir 		else
455cdf0e10cSrcweir 		{
456cdf0e10cSrcweir             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
457cdf0e10cSrcweir             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
458cdf0e10cSrcweir 					"lng : index out of range");
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 			sal_Int32 i = 0;
461cdf0e10cSrcweir             Reference< XHyphenator > xHyph;
462cdf0e10cSrcweir             if (pEntry->aSvcRefs.getLength() > 0)
463cdf0e10cSrcweir                 xHyph = pEntry->aSvcRefs[0];
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 			// try already instantiated service
466cdf0e10cSrcweir             if (i <= pEntry->nLastTriedSvcIndex)
467cdf0e10cSrcweir 			{
468cdf0e10cSrcweir                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
469cdf0e10cSrcweir                     xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
470cdf0e10cSrcweir 								nChkIndex, rProperties );
471cdf0e10cSrcweir 				++i;
472cdf0e10cSrcweir 			}
473cdf0e10cSrcweir             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
474cdf0e10cSrcweir 			// instantiate services and try it
475cdf0e10cSrcweir 			{
476cdf0e10cSrcweir //                const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
477cdf0e10cSrcweir                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
478cdf0e10cSrcweir 
479cdf0e10cSrcweir 				Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
480cdf0e10cSrcweir 				if (xMgr.is())
481cdf0e10cSrcweir 				{
482cdf0e10cSrcweir 					// build service initialization argument
483cdf0e10cSrcweir 					Sequence< Any > aArgs(2);
484cdf0e10cSrcweir 					aArgs.getArray()[0] <<= GetPropSet();
485cdf0e10cSrcweir 					//! The dispatcher searches the dictionary-list
486cdf0e10cSrcweir 					//! thus the service needs not to now about it
487cdf0e10cSrcweir 					//aArgs.getArray()[1] <<= GetDicList();
488cdf0e10cSrcweir 
489cdf0e10cSrcweir 					// create specific service via it's implementation name
490cdf0e10cSrcweir 					try
491cdf0e10cSrcweir 					{
492cdf0e10cSrcweir 						xHyph = Reference< XHyphenator >(
493cdf0e10cSrcweir 								xMgr->createInstanceWithArguments(
494cdf0e10cSrcweir                                 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
495cdf0e10cSrcweir 					}
496cdf0e10cSrcweir 					catch (uno::Exception &)
497cdf0e10cSrcweir 					{
498cdf0e10cSrcweir                         DBG_ASSERT( 0, "createInstanceWithArguments failed" );
499cdf0e10cSrcweir 					}
500cdf0e10cSrcweir                     pRef [i] = xHyph;
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 					Reference< XLinguServiceEventBroadcaster >
503cdf0e10cSrcweir 							xBroadcaster( xHyph, UNO_QUERY );
504cdf0e10cSrcweir 					if (xBroadcaster.is())
505cdf0e10cSrcweir 						rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
506cdf0e10cSrcweir 
507cdf0e10cSrcweir                     if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
508cdf0e10cSrcweir                         xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
509cdf0e10cSrcweir 									nChkIndex, rProperties );
510cdf0e10cSrcweir 
511cdf0e10cSrcweir                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
512cdf0e10cSrcweir 					++i;
513cdf0e10cSrcweir 
514cdf0e10cSrcweir                     // if language is not supported by the services
515cdf0e10cSrcweir                     // remove it from the list.
516cdf0e10cSrcweir                     if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
517cdf0e10cSrcweir                         aSvcMap.erase( nLanguage );
518cdf0e10cSrcweir 				}
519cdf0e10cSrcweir 			}
520cdf0e10cSrcweir 		}	// if (xEntry.is())
521cdf0e10cSrcweir 	}
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 	if (bWordModified  &&  xRes.is())
524cdf0e10cSrcweir 		xRes = RebuildHyphensAndControlChars( rWord, xRes );
525cdf0e10cSrcweir 
526cdf0e10cSrcweir     if (xRes.is()  &&  xRes->getWord() != rWord)
527cdf0e10cSrcweir     {
528cdf0e10cSrcweir         xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
529cdf0e10cSrcweir                                    xRes->getHyphenatedWord(),
530cdf0e10cSrcweir                                    xRes->getHyphenPos() );
531cdf0e10cSrcweir     }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir 	return xRes;
534cdf0e10cSrcweir }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 
537cdf0e10cSrcweir Reference< XPossibleHyphens > SAL_CALL
createPossibleHyphens(const OUString & rWord,const Locale & rLocale,const PropertyValues & rProperties)538cdf0e10cSrcweir 	HyphenatorDispatcher::createPossibleHyphens(
539cdf0e10cSrcweir 			const OUString& rWord, const Locale& rLocale,
540cdf0e10cSrcweir 			const PropertyValues& rProperties )
541cdf0e10cSrcweir 		throw(IllegalArgumentException, RuntimeException)
542cdf0e10cSrcweir {
543cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
544cdf0e10cSrcweir 
545cdf0e10cSrcweir 	Reference< XPossibleHyphens >	xRes;
546cdf0e10cSrcweir 
547cdf0e10cSrcweir 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
548cdf0e10cSrcweir 	if (nLanguage == LANGUAGE_NONE  || !rWord.getLength())
549cdf0e10cSrcweir 		return xRes;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 	// search for entry with that language
552cdf0e10cSrcweir     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
553cdf0e10cSrcweir     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 	if (!pEntry)
556cdf0e10cSrcweir 	{
557cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS
558cdf0e10cSrcweir 		throw IllegalArgumentException();
559cdf0e10cSrcweir #endif
560cdf0e10cSrcweir 	}
561cdf0e10cSrcweir 	else
562cdf0e10cSrcweir 	{
563cdf0e10cSrcweir 		OUString aChkWord( rWord );
564cdf0e10cSrcweir 
565cdf0e10cSrcweir         // replace typographical apostroph by ascii apostroph
566cdf0e10cSrcweir         String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
567cdf0e10cSrcweir         DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
568cdf0e10cSrcweir         if (aSingleQuote.Len())
569cdf0e10cSrcweir             aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
570cdf0e10cSrcweir 
571cdf0e10cSrcweir         RemoveHyphens( aChkWord );
572cdf0e10cSrcweir 		if (IsIgnoreControlChars( rProperties, GetPropSet() ))
573cdf0e10cSrcweir 			RemoveControlChars( aChkWord );
574cdf0e10cSrcweir 
575cdf0e10cSrcweir 		// check for results from (positive) dictionaries which have precedence!
576cdf0e10cSrcweir 		Reference< XDictionaryEntry > xEntry;
577cdf0e10cSrcweir 
578cdf0e10cSrcweir 		if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
579cdf0e10cSrcweir 		{
580cdf0e10cSrcweir 			xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
581cdf0e10cSrcweir 						sal_True, sal_False );
582cdf0e10cSrcweir 		}
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 		if (xEntry.is())
585cdf0e10cSrcweir 		{
586cdf0e10cSrcweir 			xRes = buildPossHyphens( xEntry, nLanguage );
587cdf0e10cSrcweir 		}
588cdf0e10cSrcweir 		else
589cdf0e10cSrcweir 		{
590cdf0e10cSrcweir             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
591cdf0e10cSrcweir             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
592cdf0e10cSrcweir 					"lng : index out of range");
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 			sal_Int32 i = 0;
595cdf0e10cSrcweir             Reference< XHyphenator > xHyph;
596cdf0e10cSrcweir             if (pEntry->aSvcRefs.getLength() > 0)
597cdf0e10cSrcweir                 xHyph = pEntry->aSvcRefs[0];
598cdf0e10cSrcweir 
599cdf0e10cSrcweir 			// try already instantiated service
600cdf0e10cSrcweir             if (i <= pEntry->nLastTriedSvcIndex)
601cdf0e10cSrcweir 			{
602cdf0e10cSrcweir                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
603cdf0e10cSrcweir                     xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
604cdf0e10cSrcweir 								rProperties );
605cdf0e10cSrcweir 				++i;
606cdf0e10cSrcweir 			}
607cdf0e10cSrcweir             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
608cdf0e10cSrcweir 			// instantiate services and try it
609cdf0e10cSrcweir 			{
610cdf0e10cSrcweir //                const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
611cdf0e10cSrcweir                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 				Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
614cdf0e10cSrcweir 				if (xMgr.is())
615cdf0e10cSrcweir 				{
616cdf0e10cSrcweir 					// build service initialization argument
617cdf0e10cSrcweir 					Sequence< Any > aArgs(2);
618cdf0e10cSrcweir 					aArgs.getArray()[0] <<= GetPropSet();
619cdf0e10cSrcweir 					//! The dispatcher searches the dictionary-list
620cdf0e10cSrcweir 					//! thus the service needs not to now about it
621cdf0e10cSrcweir 					//aArgs.getArray()[1] <<= GetDicList();
622cdf0e10cSrcweir 
623cdf0e10cSrcweir 					// create specific service via it's implementation name
624cdf0e10cSrcweir 					try
625cdf0e10cSrcweir 					{
626cdf0e10cSrcweir 						xHyph = Reference< XHyphenator >(
627cdf0e10cSrcweir 								xMgr->createInstanceWithArguments(
628cdf0e10cSrcweir                                 pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
629cdf0e10cSrcweir 					}
630cdf0e10cSrcweir 					catch (uno::Exception &)
631cdf0e10cSrcweir 					{
632cdf0e10cSrcweir                         DBG_ASSERT( 0, "createWithArguments failed" );
633cdf0e10cSrcweir 					}
634cdf0e10cSrcweir                     pRef [i] = xHyph;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 					Reference< XLinguServiceEventBroadcaster >
637cdf0e10cSrcweir 							xBroadcaster( xHyph, UNO_QUERY );
638cdf0e10cSrcweir 					if (xBroadcaster.is())
639cdf0e10cSrcweir 						rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
640cdf0e10cSrcweir 
641cdf0e10cSrcweir                     if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
642cdf0e10cSrcweir                     xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
643cdf0e10cSrcweir 								rProperties );
644cdf0e10cSrcweir 
645cdf0e10cSrcweir                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
646cdf0e10cSrcweir 					++i;
647cdf0e10cSrcweir 
648cdf0e10cSrcweir                     // if language is not supported by the services
649cdf0e10cSrcweir                     // remove it from the list.
650cdf0e10cSrcweir                     if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
651cdf0e10cSrcweir                         aSvcMap.erase( nLanguage );
652cdf0e10cSrcweir 				}
653cdf0e10cSrcweir 			}
654cdf0e10cSrcweir 		}	// if (xEntry.is())
655cdf0e10cSrcweir 	}
656cdf0e10cSrcweir 
657cdf0e10cSrcweir     if (xRes.is()  &&  xRes->getWord() != rWord)
658cdf0e10cSrcweir     {
659cdf0e10cSrcweir         xRes = new PossibleHyphens( rWord, nLanguage,
660cdf0e10cSrcweir                                     xRes->getPossibleHyphens(),
661cdf0e10cSrcweir                                     xRes->getHyphenationPositions() );
662cdf0e10cSrcweir     }
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 	return xRes;
665cdf0e10cSrcweir }
666cdf0e10cSrcweir 
667cdf0e10cSrcweir 
SetServiceList(const Locale & rLocale,const Sequence<OUString> & rSvcImplNames)668cdf0e10cSrcweir void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
669cdf0e10cSrcweir 		const Sequence< OUString > &rSvcImplNames )
670cdf0e10cSrcweir {
671cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
672cdf0e10cSrcweir 
673cdf0e10cSrcweir 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
674cdf0e10cSrcweir 
675cdf0e10cSrcweir     sal_Int32 nLen = rSvcImplNames.getLength();
676cdf0e10cSrcweir     if (0 == nLen)
677cdf0e10cSrcweir         // remove entry
678cdf0e10cSrcweir         aSvcMap.erase( nLanguage );
679cdf0e10cSrcweir     else
680cdf0e10cSrcweir     {
681cdf0e10cSrcweir         // modify/add entry
682cdf0e10cSrcweir         LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
683cdf0e10cSrcweir 		// only one hypenator can be in use for a language...
684cdf0e10cSrcweir         //const OUString &rSvcImplName = rSvcImplNames.getConstArray()[0];
685cdf0e10cSrcweir         if (pEntry)
686cdf0e10cSrcweir         {
687cdf0e10cSrcweir             pEntry->Clear();
688cdf0e10cSrcweir             pEntry->aSvcImplNames = rSvcImplNames;
689cdf0e10cSrcweir             pEntry->aSvcImplNames.realloc(1);
690cdf0e10cSrcweir             pEntry->aSvcRefs  = Sequence< Reference < XHyphenator > > ( 1 );
691cdf0e10cSrcweir         }
692cdf0e10cSrcweir         else
693cdf0e10cSrcweir         {
694cdf0e10cSrcweir             boost::shared_ptr< LangSvcEntries_Hyph > pTmpEntry( new LangSvcEntries_Hyph( rSvcImplNames[0] ) );
695cdf0e10cSrcweir             pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
696cdf0e10cSrcweir             aSvcMap[ nLanguage ] = pTmpEntry;
697cdf0e10cSrcweir         }
698cdf0e10cSrcweir     }
699cdf0e10cSrcweir }
700cdf0e10cSrcweir 
701cdf0e10cSrcweir 
702cdf0e10cSrcweir Sequence< OUString >
GetServiceList(const Locale & rLocale) const703cdf0e10cSrcweir 	HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
704cdf0e10cSrcweir {
705cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     Sequence< OUString > aRes;
708cdf0e10cSrcweir 
709cdf0e10cSrcweir 	// search for entry with that language and use data from that
710cdf0e10cSrcweir 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
711cdf0e10cSrcweir     HyphenatorDispatcher            *pThis = (HyphenatorDispatcher *) this;
712cdf0e10cSrcweir     const HyphSvcByLangMap_t::iterator  aIt( pThis->aSvcMap.find( nLanguage ) );
713cdf0e10cSrcweir     const LangSvcEntries_Hyph       *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
714cdf0e10cSrcweir 	if (pEntry)
715cdf0e10cSrcweir     {
716cdf0e10cSrcweir         aRes = pEntry->aSvcImplNames;
717cdf0e10cSrcweir         if (aRes.getLength() > 0)
718cdf0e10cSrcweir             aRes.realloc(1);
719cdf0e10cSrcweir     }
720cdf0e10cSrcweir 
721cdf0e10cSrcweir 	return aRes;
722cdf0e10cSrcweir }
723cdf0e10cSrcweir 
724cdf0e10cSrcweir 
GetDspType() const725cdf0e10cSrcweir LinguDispatcher::DspType HyphenatorDispatcher::GetDspType() const
726cdf0e10cSrcweir {
727cdf0e10cSrcweir     return DSP_HYPH;
728cdf0e10cSrcweir }
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 
731cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
732cdf0e10cSrcweir 
733