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 #include <com/sun/star/uno/Reference.h>
27cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <com/sun/star/linguistic2/SpellFailure.hpp>
30cdf0e10cSrcweir #include <cppuhelper/factory.hxx>	// helper for factories
31cdf0e10cSrcweir #include <com/sun/star/registry/XRegistryKey.hpp>
32cdf0e10cSrcweir #include <tools/debug.hxx>
33cdf0e10cSrcweir #include <unotools/processfactory.hxx>
34cdf0e10cSrcweir #include <osl/mutex.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #ifndef _SPELLIMP_HXX
37cdf0e10cSrcweir #include <sspellimp.hxx>
38cdf0e10cSrcweir #endif
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "linguistic/lngprops.hxx"
41cdf0e10cSrcweir #include "linguistic/spelldta.hxx"
42cdf0e10cSrcweir 
43cdf0e10cSrcweir using namespace utl;
44cdf0e10cSrcweir using namespace osl;
45cdf0e10cSrcweir using namespace rtl;
46cdf0e10cSrcweir using namespace com::sun::star;
47cdf0e10cSrcweir using namespace com::sun::star::beans;
48cdf0e10cSrcweir using namespace com::sun::star::lang;
49cdf0e10cSrcweir using namespace com::sun::star::uno;
50cdf0e10cSrcweir using namespace com::sun::star::linguistic2;
51cdf0e10cSrcweir using namespace linguistic;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir 
54cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
55cdf0e10cSrcweir 
operator ==(const Locale & rL1,const Locale & rL2)56cdf0e10cSrcweir BOOL operator == ( const Locale &rL1, const Locale &rL2 )
57cdf0e10cSrcweir {
58cdf0e10cSrcweir 	return	rL1.Language ==  rL2.Language	&&
59cdf0e10cSrcweir 			rL1.Country  ==  rL2.Country	&&
60cdf0e10cSrcweir 			rL1.Variant  ==  rL2.Variant;
61cdf0e10cSrcweir }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
64cdf0e10cSrcweir 
65cdf0e10cSrcweir 
SpellChecker()66cdf0e10cSrcweir SpellChecker::SpellChecker() :
67cdf0e10cSrcweir 	aEvtListeners	( GetLinguMutex() )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir 	bDisposing = FALSE;
70cdf0e10cSrcweir 	pPropHelper = NULL;
71cdf0e10cSrcweir }
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
~SpellChecker()74cdf0e10cSrcweir SpellChecker::~SpellChecker()
75cdf0e10cSrcweir {
76cdf0e10cSrcweir 	if (pPropHelper)
77cdf0e10cSrcweir 		pPropHelper->RemoveAsPropListener();
78cdf0e10cSrcweir }
79cdf0e10cSrcweir 
80cdf0e10cSrcweir 
GetPropHelper_Impl()81cdf0e10cSrcweir PropertyHelper_Spell & SpellChecker::GetPropHelper_Impl()
82cdf0e10cSrcweir {
83cdf0e10cSrcweir 	if (!pPropHelper)
84cdf0e10cSrcweir 	{
85cdf0e10cSrcweir 		Reference< XPropertySet	>	xPropSet( GetLinguProperties(), UNO_QUERY );
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 		pPropHelper	= new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet );
88cdf0e10cSrcweir 		xPropHelper = pPropHelper;
89cdf0e10cSrcweir 		pPropHelper->AddAsPropListener();	//! after a reference is established
90cdf0e10cSrcweir 	}
91cdf0e10cSrcweir 	return *pPropHelper;
92cdf0e10cSrcweir }
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 
getLocales()95cdf0e10cSrcweir Sequence< Locale > SAL_CALL SpellChecker::getLocales()
96cdf0e10cSrcweir 		throw(RuntimeException)
97cdf0e10cSrcweir {
98cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 	if (!aSuppLocales.getLength())
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir 		aSuppLocales.realloc( 3 );
103cdf0e10cSrcweir 		Locale *pLocale = aSuppLocales.getArray();
104cdf0e10cSrcweir 		pLocale[0] = Locale( A2OU("en"), A2OU("US"), OUString() );
105cdf0e10cSrcweir 		pLocale[1] = Locale( A2OU("de"), A2OU("DE"), OUString() );
106cdf0e10cSrcweir 		pLocale[2] = Locale( A2OU("de"), A2OU("CH"), OUString() );
107cdf0e10cSrcweir 	}
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 	return aSuppLocales;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 
hasLocale(const Locale & rLocale)113cdf0e10cSrcweir sal_Bool SAL_CALL SpellChecker::hasLocale(const Locale& rLocale)
114cdf0e10cSrcweir 		throw(RuntimeException)
115cdf0e10cSrcweir {
116cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
117cdf0e10cSrcweir 
118cdf0e10cSrcweir 	BOOL bRes = FALSE;
119cdf0e10cSrcweir 	if (!aSuppLocales.getLength())
120cdf0e10cSrcweir 		getLocales();
121cdf0e10cSrcweir 	INT32 nLen = aSuppLocales.getLength();
122cdf0e10cSrcweir 	for (INT32 i = 0;  i < nLen;  ++i)
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		const Locale *pLocale = aSuppLocales.getConstArray();
125cdf0e10cSrcweir 		if (rLocale == pLocale[i])
126cdf0e10cSrcweir 		{
127cdf0e10cSrcweir 			bRes = TRUE;
128cdf0e10cSrcweir 			break;
129cdf0e10cSrcweir 		}
130cdf0e10cSrcweir 	}
131cdf0e10cSrcweir 	return bRes;
132cdf0e10cSrcweir }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 
GetSpellFailure(const OUString & rWord,const Locale & rLocale)135cdf0e10cSrcweir INT16 SpellChecker::GetSpellFailure( const OUString &rWord, const Locale &rLocale )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir 	// Checks wether a word is OK in a given language (Locale) or not, and
138cdf0e10cSrcweir 	// provides a failure type for the incorrect ones.
139cdf0e10cSrcweir 	// - words with "liss" (case sensitiv) as substring will be negative.
140cdf0e10cSrcweir 	// - words with 'x' or 'X' will have incorrect spelling.
141cdf0e10cSrcweir 	// - words with 's' or 'S' as first letter will have the wrong caption.
142cdf0e10cSrcweir 	// - all other words will be OK.
143cdf0e10cSrcweir 
144cdf0e10cSrcweir 	INT16 nRes = -1;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir 	String aTmp( rWord );
147cdf0e10cSrcweir 	if (aTmp.Len())
148cdf0e10cSrcweir 	{
149cdf0e10cSrcweir 		if (STRING_NOTFOUND != aTmp.SearchAscii( "liss" ))
150cdf0e10cSrcweir 		{
151cdf0e10cSrcweir 			nRes = SpellFailure::IS_NEGATIVE_WORD;
152cdf0e10cSrcweir 		}
153cdf0e10cSrcweir 		else if (STRING_NOTFOUND != aTmp.Search( (sal_Unicode) 'x' )  ||
154cdf0e10cSrcweir 				 STRING_NOTFOUND != aTmp.Search( (sal_Unicode) 'X' ))
155cdf0e10cSrcweir 		{
156cdf0e10cSrcweir 			nRes = SpellFailure::SPELLING_ERROR;
157cdf0e10cSrcweir 		}
158cdf0e10cSrcweir 		else
159cdf0e10cSrcweir 		{
160cdf0e10cSrcweir 			sal_Unicode cChar = aTmp.GetChar( 0 );
161cdf0e10cSrcweir 			if (cChar == (sal_Unicode) 's'  ||  cChar == (sal_Unicode) 'S')
162cdf0e10cSrcweir 				nRes = SpellFailure::CAPTION_ERROR;
163cdf0e10cSrcweir 		}
164cdf0e10cSrcweir 	}
165cdf0e10cSrcweir 
166cdf0e10cSrcweir 	return nRes;
167cdf0e10cSrcweir }
168cdf0e10cSrcweir 
169cdf0e10cSrcweir 
170cdf0e10cSrcweir sal_Bool SAL_CALL
isValid(const OUString & rWord,const Locale & rLocale,const PropertyValues & rProperties)171cdf0e10cSrcweir 	SpellChecker::isValid( const OUString& rWord, const Locale& rLocale,
172cdf0e10cSrcweir 			const PropertyValues& rProperties )
173cdf0e10cSrcweir 		throw(IllegalArgumentException, RuntimeException)
174cdf0e10cSrcweir {
175cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir  	if (rLocale == Locale()  ||  !rWord.getLength())
178cdf0e10cSrcweir 		return TRUE;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 	if (!hasLocale( rLocale ))
181cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS
182cdf0e10cSrcweir 		throw( IllegalArgumentException() );
183cdf0e10cSrcweir #else
184cdf0e10cSrcweir 		return TRUE;
185cdf0e10cSrcweir #endif
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 	// Get property values to be used.
188cdf0e10cSrcweir 	// These are be the default values set in the SN_LINGU_PROPERTIES
189cdf0e10cSrcweir 	// PropertySet which are overridden by the supplied ones from the
190cdf0e10cSrcweir 	// last argument.
191cdf0e10cSrcweir 	// You'll probably like to use a simplier solution than the provided
192cdf0e10cSrcweir 	// one using the PropertyHelper_Spell.
193cdf0e10cSrcweir 	PropertyHelper_Spell &rHelper = GetPropHelper();
194cdf0e10cSrcweir 	rHelper.SetTmpPropVals( rProperties );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir 	INT16 nFailure = GetSpellFailure( rWord, rLocale );
197cdf0e10cSrcweir 	if (nFailure != -1)
198cdf0e10cSrcweir 	{
199cdf0e10cSrcweir 		INT16 nLang = LocaleToLanguage( rLocale );
200cdf0e10cSrcweir 		// postprocess result for errors that should be ignored
201cdf0e10cSrcweir 		if (   (!rHelper.IsSpellUpperCase()  && IsUpper( rWord, nLang ))
202cdf0e10cSrcweir 			|| (!rHelper.IsSpellWithDigits() && HasDigits( rWord ))
203cdf0e10cSrcweir 			|| (!rHelper.IsSpellCapitalization()
204cdf0e10cSrcweir 				&&  nFailure == SpellFailure::CAPTION_ERROR)
205cdf0e10cSrcweir 		)
206cdf0e10cSrcweir 			nFailure = -1;
207cdf0e10cSrcweir 	}
208cdf0e10cSrcweir 	return nFailure == -1;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 
212cdf0e10cSrcweir Reference< XSpellAlternatives >
GetProposals(const OUString & rWord,const Locale & rLocale)213cdf0e10cSrcweir 	SpellChecker::GetProposals( const OUString &rWord, const Locale &rLocale )
214cdf0e10cSrcweir {
215cdf0e10cSrcweir 	// Retrieves the return values for the 'spell' function call in case
216cdf0e10cSrcweir 	// of a misspelled word.
217cdf0e10cSrcweir 	// Especially it may give a list of suggested (correct) words:
218cdf0e10cSrcweir 	// - a "liss" substring will be replaced by "liz".
219cdf0e10cSrcweir 	// - 'x' or 'X' will be replaced by 'u' or 'U' for the first proposal
220cdf0e10cSrcweir 	//   and they will be removed from the word for the second proposal.
221cdf0e10cSrcweir 	// - 's' or 'S' as first letter will be changed to the other caption.
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 	Reference< XSpellAlternatives > xRes;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 	String aTmp( rWord );
226cdf0e10cSrcweir 	if (aTmp.Len())
227cdf0e10cSrcweir 	{
228cdf0e10cSrcweir 		INT16 nLang = LocaleToLanguage( rLocale );
229cdf0e10cSrcweir 
230cdf0e10cSrcweir 		if (STRING_NOTFOUND != aTmp.SearchAscii( "liss" ))
231cdf0e10cSrcweir 		{
232cdf0e10cSrcweir 			aTmp.SearchAndReplaceAllAscii( "liss", A2OU("liz") );
233cdf0e10cSrcweir 			xRes = new SpellAlternatives( aTmp, nLang,
234cdf0e10cSrcweir 						SpellFailure::IS_NEGATIVE_WORD, aTmp );
235cdf0e10cSrcweir 		}
236cdf0e10cSrcweir 		else if (STRING_NOTFOUND != aTmp.Search( (sal_Unicode) 'x' )  ||
237cdf0e10cSrcweir 				 STRING_NOTFOUND != aTmp.Search( (sal_Unicode) 'X' ))
238cdf0e10cSrcweir 		{
239cdf0e10cSrcweir 			Sequence< OUString > aStr( 2 );
240cdf0e10cSrcweir 			OUString *pStr = aStr.getArray();
241cdf0e10cSrcweir 			String  aAlt1( aTmp ),
242cdf0e10cSrcweir 					aAlt2( aTmp );
243cdf0e10cSrcweir 			aAlt1.SearchAndReplaceAll( (sal_Unicode) 'x', (sal_Unicode) 'u');
244cdf0e10cSrcweir 			aAlt1.SearchAndReplaceAll( (sal_Unicode) 'X', (sal_Unicode) 'U');
245cdf0e10cSrcweir 			aAlt2.EraseAllChars( (sal_Unicode) 'x' );
246cdf0e10cSrcweir 			aAlt2.EraseAllChars( (sal_Unicode) 'X' );
247cdf0e10cSrcweir 			pStr[0] = aAlt1;
248cdf0e10cSrcweir 			pStr[1] = aAlt2;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 			SpellAlternatives *pAlt = new SpellAlternatives;
251cdf0e10cSrcweir 			pAlt->SetWordLanguage( aTmp, nLang );
252cdf0e10cSrcweir 			pAlt->SetFailureType( SpellFailure::SPELLING_ERROR );
253cdf0e10cSrcweir 			pAlt->SetAlternatives( aStr );
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 			xRes = pAlt;
256cdf0e10cSrcweir 		}
257cdf0e10cSrcweir 		else
258cdf0e10cSrcweir 		{
259cdf0e10cSrcweir 			sal_Unicode cChar = aTmp.GetChar( 0 );
260cdf0e10cSrcweir 			if (cChar == (sal_Unicode) 's'  ||  cChar == (sal_Unicode) 'S')
261cdf0e10cSrcweir 			{
262cdf0e10cSrcweir 				sal_Unicode cNewChar = cChar == (sal_Unicode) 's' ?
263cdf0e10cSrcweir 						(sal_Unicode) 'S': (sal_Unicode) 's';
264cdf0e10cSrcweir 				aTmp.GetBufferAccess()[0] = cNewChar;
265cdf0e10cSrcweir 				xRes = new SpellAlternatives( aTmp, nLang,
266cdf0e10cSrcweir 						SpellFailure::CAPTION_ERROR, aTmp );
267cdf0e10cSrcweir 			}
268cdf0e10cSrcweir 		}
269cdf0e10cSrcweir 	}
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 	return xRes;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir 
275cdf0e10cSrcweir Reference< XSpellAlternatives > SAL_CALL
spell(const OUString & rWord,const Locale & rLocale,const PropertyValues & rProperties)276cdf0e10cSrcweir 	SpellChecker::spell( const OUString& rWord, const Locale& rLocale,
277cdf0e10cSrcweir 			const PropertyValues& rProperties )
278cdf0e10cSrcweir 		throw(IllegalArgumentException, RuntimeException)
279cdf0e10cSrcweir {
280cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
281cdf0e10cSrcweir 
282cdf0e10cSrcweir  	if (rLocale == Locale()  ||  !rWord.getLength())
283cdf0e10cSrcweir 		return NULL;
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 	if (!hasLocale( rLocale ))
286cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS
287cdf0e10cSrcweir 		throw( IllegalArgumentException() );
288cdf0e10cSrcweir #else
289cdf0e10cSrcweir 		return NULL;
290cdf0e10cSrcweir #endif
291cdf0e10cSrcweir 
292cdf0e10cSrcweir 	Reference< XSpellAlternatives > xAlt;
293cdf0e10cSrcweir 	if (!isValid( rWord, rLocale, rProperties ))
294cdf0e10cSrcweir 	{
295cdf0e10cSrcweir 		xAlt =  GetProposals( rWord, rLocale );
296cdf0e10cSrcweir 	}
297cdf0e10cSrcweir 	return xAlt;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 
SpellChecker_CreateInstance(const Reference<XMultiServiceFactory> & rSMgr)301cdf0e10cSrcweir Reference< XInterface > SAL_CALL SpellChecker_CreateInstance(
302cdf0e10cSrcweir 			const Reference< XMultiServiceFactory > & rSMgr )
303cdf0e10cSrcweir 		throw(Exception)
304cdf0e10cSrcweir {
305cdf0e10cSrcweir 	Reference< XInterface > xService = (cppu::OWeakObject*) new SpellChecker;
306cdf0e10cSrcweir 	return xService;
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 
310cdf0e10cSrcweir sal_Bool SAL_CALL
addLinguServiceEventListener(const Reference<XLinguServiceEventListener> & rxLstnr)311cdf0e10cSrcweir 	SpellChecker::addLinguServiceEventListener(
312cdf0e10cSrcweir 			const Reference< XLinguServiceEventListener >& rxLstnr )
313cdf0e10cSrcweir 		throw(RuntimeException)
314cdf0e10cSrcweir {
315cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 	BOOL bRes = FALSE;
318cdf0e10cSrcweir 	if (!bDisposing && rxLstnr.is())
319cdf0e10cSrcweir 	{
320cdf0e10cSrcweir 		bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
321cdf0e10cSrcweir 	}
322cdf0e10cSrcweir 	return bRes;
323cdf0e10cSrcweir }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 
326cdf0e10cSrcweir sal_Bool SAL_CALL
removeLinguServiceEventListener(const Reference<XLinguServiceEventListener> & rxLstnr)327cdf0e10cSrcweir 	SpellChecker::removeLinguServiceEventListener(
328cdf0e10cSrcweir 			const Reference< XLinguServiceEventListener >& rxLstnr )
329cdf0e10cSrcweir 		throw(RuntimeException)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
332cdf0e10cSrcweir 
333cdf0e10cSrcweir 	BOOL bRes = FALSE;
334cdf0e10cSrcweir 	if (!bDisposing && rxLstnr.is())
335cdf0e10cSrcweir 	{
336cdf0e10cSrcweir 		DBG_ASSERT( xPropHelper.is(), "xPropHelper non existent" );
337cdf0e10cSrcweir 		bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
338cdf0e10cSrcweir 	}
339cdf0e10cSrcweir 	return bRes;
340cdf0e10cSrcweir }
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 
343cdf0e10cSrcweir OUString SAL_CALL
getServiceDisplayName(const Locale & rLocale)344cdf0e10cSrcweir 	SpellChecker::getServiceDisplayName( const Locale& rLocale )
345cdf0e10cSrcweir 		throw(RuntimeException)
346cdf0e10cSrcweir {
347cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
348cdf0e10cSrcweir 	return A2OU( "OpenOffice example spellchecker" );
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 
352cdf0e10cSrcweir void SAL_CALL
initialize(const Sequence<Any> & rArguments)353cdf0e10cSrcweir 	SpellChecker::initialize( const Sequence< Any >& rArguments )
354cdf0e10cSrcweir 		throw(Exception, RuntimeException)
355cdf0e10cSrcweir {
356cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
357cdf0e10cSrcweir 
358cdf0e10cSrcweir 	if (!pPropHelper)
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		INT32 nLen = rArguments.getLength();
361cdf0e10cSrcweir 		if (2 == nLen)
362cdf0e10cSrcweir 		{
363cdf0e10cSrcweir 			Reference< XPropertySet	>	xPropSet;
364cdf0e10cSrcweir 			rArguments.getConstArray()[0] >>= xPropSet;
365cdf0e10cSrcweir 			//rArguments.getConstArray()[1] >>= xDicList;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir 			//! Pointer allows for access of the non-UNO functions.
368cdf0e10cSrcweir 			//! And the reference to the UNO-functions while increasing
369cdf0e10cSrcweir 			//! the ref-count and will implicitly free the memory
370cdf0e10cSrcweir 			//! when the object is not longer used.
371cdf0e10cSrcweir 			pPropHelper = new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet );
372cdf0e10cSrcweir 			xPropHelper = pPropHelper;
373cdf0e10cSrcweir 			pPropHelper->AddAsPropListener();	//! after a reference is established
374cdf0e10cSrcweir 		}
375cdf0e10cSrcweir 		else
376cdf0e10cSrcweir 			DBG_ERROR( "wrong number of arguments in sequence" );
377cdf0e10cSrcweir 	}
378cdf0e10cSrcweir }
379cdf0e10cSrcweir 
380cdf0e10cSrcweir 
381cdf0e10cSrcweir void SAL_CALL
dispose()382cdf0e10cSrcweir 	SpellChecker::dispose()
383cdf0e10cSrcweir 		throw(RuntimeException)
384cdf0e10cSrcweir {
385cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
386cdf0e10cSrcweir 
387cdf0e10cSrcweir 	if (!bDisposing)
388cdf0e10cSrcweir 	{
389cdf0e10cSrcweir 		bDisposing = TRUE;
390cdf0e10cSrcweir 		EventObject	aEvtObj( (XSpellChecker *) this );
391cdf0e10cSrcweir 		aEvtListeners.disposeAndClear( aEvtObj );
392cdf0e10cSrcweir 	}
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
395cdf0e10cSrcweir 
396cdf0e10cSrcweir void SAL_CALL
addEventListener(const Reference<XEventListener> & rxListener)397cdf0e10cSrcweir 	SpellChecker::addEventListener( const Reference< XEventListener >& rxListener )
398cdf0e10cSrcweir 		throw(RuntimeException)
399cdf0e10cSrcweir {
400cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 	if (!bDisposing && rxListener.is())
403cdf0e10cSrcweir 		aEvtListeners.addInterface( rxListener );
404cdf0e10cSrcweir }
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 
407cdf0e10cSrcweir void SAL_CALL
removeEventListener(const Reference<XEventListener> & rxListener)408cdf0e10cSrcweir 	SpellChecker::removeEventListener( const Reference< XEventListener >& rxListener )
409cdf0e10cSrcweir 		throw(RuntimeException)
410cdf0e10cSrcweir {
411cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
412cdf0e10cSrcweir 
413cdf0e10cSrcweir 	if (!bDisposing && rxListener.is())
414cdf0e10cSrcweir 		aEvtListeners.removeInterface( rxListener );
415cdf0e10cSrcweir }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 
418cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
419cdf0e10cSrcweir // Service specific part
420cdf0e10cSrcweir //
421cdf0e10cSrcweir 
getImplementationName()422cdf0e10cSrcweir OUString SAL_CALL SpellChecker::getImplementationName()
423cdf0e10cSrcweir 		throw(RuntimeException)
424cdf0e10cSrcweir {
425cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
426cdf0e10cSrcweir 	return getImplementationName_Static();
427cdf0e10cSrcweir }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 
supportsService(const OUString & ServiceName)430cdf0e10cSrcweir sal_Bool SAL_CALL SpellChecker::supportsService( const OUString& ServiceName )
431cdf0e10cSrcweir 		throw(RuntimeException)
432cdf0e10cSrcweir {
433cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 	Sequence< OUString > aSNL = getSupportedServiceNames();
436cdf0e10cSrcweir 	const OUString * pArray = aSNL.getConstArray();
437cdf0e10cSrcweir 	for( INT32 i = 0; i < aSNL.getLength(); i++ )
438cdf0e10cSrcweir 		if( pArray[i] == ServiceName )
439cdf0e10cSrcweir 			return TRUE;
440cdf0e10cSrcweir 	return FALSE;
441cdf0e10cSrcweir }
442cdf0e10cSrcweir 
443cdf0e10cSrcweir 
getSupportedServiceNames()444cdf0e10cSrcweir Sequence< OUString > SAL_CALL SpellChecker::getSupportedServiceNames()
445cdf0e10cSrcweir 		throw(RuntimeException)
446cdf0e10cSrcweir {
447cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
448cdf0e10cSrcweir 	return getSupportedServiceNames_Static();
449cdf0e10cSrcweir }
450cdf0e10cSrcweir 
451cdf0e10cSrcweir 
getSupportedServiceNames_Static()452cdf0e10cSrcweir Sequence< OUString > SpellChecker::getSupportedServiceNames_Static()
453cdf0e10cSrcweir 		throw()
454cdf0e10cSrcweir {
455cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 	Sequence< OUString > aSNS( 1 );	// auch mehr als 1 Service moeglich
458cdf0e10cSrcweir 	aSNS.getArray()[0] = A2OU( SN_SPELLCHECKER );
459cdf0e10cSrcweir 	return aSNS;
460cdf0e10cSrcweir }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir 
SpellChecker_writeInfo(void *,registry::XRegistryKey * pRegistryKey)463cdf0e10cSrcweir sal_Bool SAL_CALL SpellChecker_writeInfo(
464cdf0e10cSrcweir 			void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
465cdf0e10cSrcweir {
466cdf0e10cSrcweir 	try
467cdf0e10cSrcweir 	{
468cdf0e10cSrcweir 		String aImpl( '/' );
469cdf0e10cSrcweir 		aImpl += SpellChecker::getImplementationName_Static().getStr();
470cdf0e10cSrcweir 		aImpl.AppendAscii( "/UNO/SERVICES" );
471cdf0e10cSrcweir 		Reference< registry::XRegistryKey > xNewKey =
472cdf0e10cSrcweir 				pRegistryKey->createKey( aImpl );
473cdf0e10cSrcweir 		Sequence< OUString > aServices =
474cdf0e10cSrcweir 				SpellChecker::getSupportedServiceNames_Static();
475cdf0e10cSrcweir 		for( INT32 i = 0; i < aServices.getLength(); i++ )
476cdf0e10cSrcweir 			xNewKey->createKey( aServices.getConstArray()[i] );
477cdf0e10cSrcweir 
478cdf0e10cSrcweir 		return sal_True;
479cdf0e10cSrcweir 	}
480cdf0e10cSrcweir 	catch(Exception &)
481cdf0e10cSrcweir 	{
482cdf0e10cSrcweir 		return sal_False;
483cdf0e10cSrcweir 	}
484cdf0e10cSrcweir }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 
SpellChecker_getFactory(const sal_Char * pImplName,XMultiServiceFactory * pServiceManager,void *)487cdf0e10cSrcweir void * SAL_CALL SpellChecker_getFactory( const sal_Char * pImplName,
488cdf0e10cSrcweir 			XMultiServiceFactory * pServiceManager, void *  )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir 	void * pRet = 0;
491cdf0e10cSrcweir 	if ( !SpellChecker::getImplementationName_Static().compareToAscii( pImplName ) )
492cdf0e10cSrcweir 	{
493cdf0e10cSrcweir 		Reference< XSingleServiceFactory > xFactory =
494cdf0e10cSrcweir 			cppu::createOneInstanceFactory(
495cdf0e10cSrcweir 				pServiceManager,
496cdf0e10cSrcweir 				SpellChecker::getImplementationName_Static(),
497cdf0e10cSrcweir 				SpellChecker_CreateInstance,
498cdf0e10cSrcweir 				SpellChecker::getSupportedServiceNames_Static());
499cdf0e10cSrcweir 		// acquire, because we return an interface pointer instead of a reference
500cdf0e10cSrcweir 		xFactory->acquire();
501cdf0e10cSrcweir 		pRet = xFactory.get();
502cdf0e10cSrcweir 	}
503cdf0e10cSrcweir 	return pRet;
504cdf0e10cSrcweir }
505cdf0e10cSrcweir 
506cdf0e10cSrcweir 
507cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
508cdf0e10cSrcweir 
509