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