1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_linguistic.hxx"
30 
31 #include "linguistic/misc.hxx"
32 
33 #include "sprophelp.hxx"
34 #include "linguistic/lngprops.hxx"
35 #include <tools/debug.hxx>
36 
37 #include <com/sun/star/linguistic2/LinguServiceEvent.hpp>
38 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
39 #include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <osl/mutex.hxx>
42 
43 //using namespace utl;
44 using namespace osl;
45 using namespace rtl;
46 using namespace com::sun::star;
47 using namespace com::sun::star::beans;
48 using namespace com::sun::star::lang;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::linguistic2;
51 using namespace linguistic;
52 
53 
54 #define A2OU(x)	::rtl::OUString::createFromAscii( x )
55 
56 ///////////////////////////////////////////////////////////////////////////
57 
58 
59 PropertyChgHelper::PropertyChgHelper(
60 		const Reference< XInterface > & rxSource,
61 		Reference< XPropertySet > &rxPropSet,
62 		const char *pPropNames[], USHORT nPropCount ) :
63 	xMyEvtObj			(rxSource),
64 	xPropSet			(rxPropSet),
65 	aPropNames			(nPropCount),
66 	aLngSvcEvtListeners	(GetLinguMutex())
67 {
68 	OUString *pName = aPropNames.getArray();
69 	for (INT32 i = 0;  i < nPropCount;  ++i)
70 	{
71 		pName[i] = A2OU( pPropNames[i] );
72 	}
73 }
74 
75 
76 PropertyChgHelper::PropertyChgHelper( const PropertyChgHelper &rHelper ) :
77 	aLngSvcEvtListeners	(GetLinguMutex())
78 {
79 	xPropSet	= rHelper.xPropSet;
80 	aPropNames	= rHelper.aPropNames;
81 	AddAsPropListener();
82 
83 	xMyEvtObj	= rHelper.xMyEvtObj;
84 }
85 
86 
87 PropertyChgHelper::~PropertyChgHelper()
88 {
89 }
90 
91 
92 void PropertyChgHelper::AddAsPropListener()
93 {
94 	if (xPropSet.is())
95 	{
96 		INT32 nLen = aPropNames.getLength();
97 		const OUString *pPropName = aPropNames.getConstArray();
98 		for (INT32 i = 0;  i < nLen;  ++i)
99 		{
100 			if (pPropName[i].getLength())
101 				xPropSet->addPropertyChangeListener( pPropName[i], this );
102 		}
103 	}
104 }
105 
106 void PropertyChgHelper::RemoveAsPropListener()
107 {
108 	if (xPropSet.is())
109 	{
110 		INT32 nLen = aPropNames.getLength();
111 		const OUString *pPropName = aPropNames.getConstArray();
112 		for (INT32 i = 0;  i < nLen;  ++i)
113 		{
114 			if (pPropName[i].getLength())
115 				xPropSet->removePropertyChangeListener( pPropName[i], this );
116 		}
117 	}
118 }
119 
120 
121 void PropertyChgHelper::LaunchEvent( const LinguServiceEvent &rEvt )
122 {
123 	cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtListeners );
124 	while (aIt.hasMoreElements())
125 	{
126 		Reference< XLinguServiceEventListener > xRef( aIt.next(), UNO_QUERY );
127 		if (xRef.is())
128 			xRef->processLinguServiceEvent( rEvt );
129 	}
130 }
131 
132 
133 void SAL_CALL PropertyChgHelper::disposing( const EventObject& rSource )
134 		throw(RuntimeException)
135 {
136 	MutexGuard	aGuard( GetLinguMutex() );
137 	if (rSource.Source == xPropSet)
138 	{
139 		RemoveAsPropListener();
140 		xPropSet = NULL;
141 		aPropNames.realloc( 0 );
142 	}
143 }
144 
145 
146 sal_Bool SAL_CALL
147 	PropertyChgHelper::addLinguServiceEventListener(
148 			const Reference< XLinguServiceEventListener >& rxListener )
149 		throw(RuntimeException)
150 {
151 	MutexGuard	aGuard( GetLinguMutex() );
152 
153 	BOOL bRes = FALSE;
154 	if (rxListener.is())
155 	{
156 		INT32	nCount = aLngSvcEvtListeners.getLength();
157 		bRes = aLngSvcEvtListeners.addInterface( rxListener ) != nCount;
158 	}
159 	return bRes;
160 }
161 
162 
163 sal_Bool SAL_CALL
164 	PropertyChgHelper::removeLinguServiceEventListener(
165 			const Reference< XLinguServiceEventListener >& rxListener )
166 		throw(RuntimeException)
167 {
168 	MutexGuard	aGuard( GetLinguMutex() );
169 
170 	BOOL bRes = FALSE;
171 	if (rxListener.is())
172 	{
173 		INT32	nCount = aLngSvcEvtListeners.getLength();
174 		bRes = aLngSvcEvtListeners.removeInterface( rxListener ) != nCount;
175 	}
176 	return bRes;
177 }
178 
179 ///////////////////////////////////////////////////////////////////////////
180 
181 static const char *aSP[] =
182 {
183 	UPN_IS_GERMAN_PRE_REFORM,
184 	UPN_IS_IGNORE_CONTROL_CHARACTERS,
185 	UPN_IS_USE_DICTIONARY_LIST,
186 	UPN_IS_SPELL_UPPER_CASE,
187 	UPN_IS_SPELL_WITH_DIGITS,
188 	UPN_IS_SPELL_CAPITALIZATION
189 };
190 
191 
192 PropertyHelper_Spell::PropertyHelper_Spell(
193 		const Reference< XInterface > & rxSource,
194 		Reference< XPropertySet > &rxPropSet ) :
195 	PropertyChgHelper	( rxSource, rxPropSet, aSP, sizeof(aSP) / sizeof(aSP[0]) )
196 {
197 	SetDefault();
198 	INT32 nLen = GetPropNames().getLength();
199 	if (rxPropSet.is() && nLen)
200 	{
201 		const OUString *pPropName = GetPropNames().getConstArray();
202 		for (INT32 i = 0;  i < nLen;  ++i)
203 		{
204 			BOOL *pbVal		= NULL,
205 				 *pbResVal	= NULL;
206 
207 			if (A2OU( UPN_IS_GERMAN_PRE_REFORM ) == pPropName[i])
208 			{
209 				pbVal	 = &bIsGermanPreReform;
210 				pbResVal = &bResIsGermanPreReform;
211 			}
212 			else if (A2OU( UPN_IS_IGNORE_CONTROL_CHARACTERS ) == pPropName[i])
213 			{
214 				pbVal	 = &bIsIgnoreControlCharacters;
215 				pbResVal = &bResIsIgnoreControlCharacters;
216 			}
217 			else if (A2OU( UPN_IS_USE_DICTIONARY_LIST ) == pPropName[i])
218 			{
219 				pbVal	 = &bIsUseDictionaryList;
220 				pbResVal = &bResIsUseDictionaryList;
221 			}
222 			else if (A2OU( UPN_IS_SPELL_UPPER_CASE ) == pPropName[i])
223 			{
224 				pbVal	 = &bIsSpellUpperCase;
225 				pbResVal = &bResIsSpellUpperCase;
226 			}
227 			else if (A2OU( UPN_IS_SPELL_WITH_DIGITS ) == pPropName[i])
228 			{
229 				pbVal	 = &bIsSpellWithDigits;
230 				pbResVal = &bResIsSpellWithDigits;
231 			}
232 			else if (A2OU( UPN_IS_SPELL_CAPITALIZATION ) == pPropName[i])
233 			{
234 				pbVal	 = &bIsSpellCapitalization;
235 				pbResVal = &bResIsSpellCapitalization;
236 			}
237 
238 			if (pbVal && pbResVal)
239 			{
240 				rxPropSet->getPropertyValue( pPropName[i] ) >>= *pbVal;
241 				*pbResVal = *pbVal;
242 			}
243 		}
244 	}
245 }
246 
247 
248 PropertyHelper_Spell::~PropertyHelper_Spell()
249 {
250 }
251 
252 
253 void PropertyHelper_Spell::SetDefault()
254 {
255 	bResIsGermanPreReform			= bIsGermanPreReform			= FALSE;
256 	bResIsIgnoreControlCharacters	= bIsIgnoreControlCharacters	= TRUE;
257 	bResIsUseDictionaryList			= bIsUseDictionaryList			= TRUE;
258 	bResIsSpellUpperCase			= bIsSpellUpperCase				= FALSE;
259 	bResIsSpellWithDigits			= bIsSpellWithDigits			= FALSE;
260 	bResIsSpellCapitalization		= bIsSpellCapitalization		= TRUE;
261 }
262 
263 
264 void SAL_CALL
265 	PropertyHelper_Spell::propertyChange( const PropertyChangeEvent& rEvt )
266 		throw(RuntimeException)
267 {
268 	MutexGuard	aGuard( GetLinguMutex() );
269 
270 	if (GetPropSet().is()  &&  rEvt.Source == GetPropSet())
271 	{
272 		INT16 nLngSvcFlags = 0;
273 		BOOL bSCWA = FALSE,	// SPELL_CORRECT_WORDS_AGAIN ?
274 			 bSWWA = FALSE;	// SPELL_WRONG_WORDS_AGAIN ?
275 
276 		BOOL *pbVal = NULL;
277 		switch (rEvt.PropertyHandle)
278 		{
279 			case UPH_IS_IGNORE_CONTROL_CHARACTERS :
280 			{
281 				pbVal = &bIsIgnoreControlCharacters;
282 				break;
283 			}
284 			case UPH_IS_GERMAN_PRE_REFORM		  :
285 			{
286 				pbVal = &bIsGermanPreReform;
287 				bSCWA = bSWWA = TRUE;
288 				break;
289 			}
290 			case UPH_IS_USE_DICTIONARY_LIST		  :
291 			{
292 				pbVal = &bIsUseDictionaryList;
293 				bSCWA = bSWWA = TRUE;
294 				break;
295 			}
296 			case UPH_IS_SPELL_UPPER_CASE		  :
297 			{
298 				pbVal = &bIsSpellUpperCase;
299 				bSCWA = FALSE == *pbVal;	// FALSE->TRUE change?
300 				bSWWA = !bSCWA;				// TRUE->FALSE change?
301 				break;
302 			}
303 			case UPH_IS_SPELL_WITH_DIGITS		  :
304 			{
305 				pbVal = &bIsSpellWithDigits;
306 				bSCWA = FALSE == *pbVal;	// FALSE->TRUE change?
307 				bSWWA = !bSCWA;				// TRUE->FALSE change?
308 				break;
309 			}
310 			case UPH_IS_SPELL_CAPITALIZATION	  :
311 			{
312 				pbVal = &bIsSpellCapitalization;
313 				bSCWA = FALSE == *pbVal;	// FALSE->TRUE change?
314 				bSWWA = !bSCWA;				// TRUE->FALSE change?
315 				break;
316 			}
317 			default:
318 				DBG_ERROR( "unknown property" );
319 		}
320 		if (pbVal)
321 			rEvt.NewValue >>= *pbVal;
322 
323 		if (bSCWA)
324 			nLngSvcFlags |= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
325 		if (bSWWA)
326 			nLngSvcFlags |= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
327 		if (nLngSvcFlags)
328 		{
329 			LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
330 			LaunchEvent( aEvt );
331 		}
332 	}
333 }
334 
335 
336 void PropertyHelper_Spell::SetTmpPropVals( const PropertyValues &rPropVals )
337 {
338 	// set return value to default value unless there is an
339 	// explicitly supplied temporary value
340 	bResIsGermanPreReform			= bIsGermanPreReform;
341 	bResIsIgnoreControlCharacters	= bIsIgnoreControlCharacters;
342 	bResIsUseDictionaryList			= bIsUseDictionaryList;
343 	bResIsSpellUpperCase			= bIsSpellUpperCase;
344 	bResIsSpellWithDigits			= bIsSpellWithDigits;
345 	bResIsSpellCapitalization		= bIsSpellCapitalization;
346 	//
347 	INT32 nLen = rPropVals.getLength();
348 	if (nLen)
349 	{
350 		const PropertyValue *pVal = rPropVals.getConstArray();
351 		for (INT32 i = 0;  i < nLen;  ++i)
352 		{
353 			BOOL *pbResVal = NULL;
354 			switch (pVal[i].Handle)
355 			{
356 				case UPH_IS_GERMAN_PRE_REFORM		  : pbResVal = &bResIsGermanPreReform; break;
357 				case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbResVal = &bResIsIgnoreControlCharacters; break;
358 				case UPH_IS_USE_DICTIONARY_LIST		  : pbResVal = &bResIsUseDictionaryList; break;
359 				case UPH_IS_SPELL_UPPER_CASE		  : pbResVal = &bResIsSpellUpperCase; break;
360 				case UPH_IS_SPELL_WITH_DIGITS		  : pbResVal = &bResIsSpellWithDigits; break;
361 				case UPH_IS_SPELL_CAPITALIZATION	  : pbResVal = &bResIsSpellCapitalization; break;
362 				default:
363 					DBG_ERROR( "unknown property" );
364 			}
365 			if (pbResVal)
366 				pVal[i].Value >>= *pbResVal;
367 		}
368 	}
369 }
370 
371 ///////////////////////////////////////////////////////////////////////////
372 
373