1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_linguistic.hxx"
26 
27 #include <tools/debug.hxx>
28 
29 #include <com/sun/star/linguistic2/LinguServiceEvent.hpp>
30 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
31 #include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <osl/mutex.hxx>
34 
35 #include <linguistic/misc.hxx>
36 #include <linguistic/lngprops.hxx>
37 
38 #include <linguistic/lngprophelp.hxx>
39 
40 
41 //using namespace utl;
42 using namespace osl;
43 using namespace rtl;
44 using namespace com::sun::star;
45 using namespace com::sun::star::beans;
46 using namespace com::sun::star::lang;
47 using namespace com::sun::star::uno;
48 using namespace com::sun::star::linguistic2;
49 using namespace linguistic;
50 
51 namespace linguistic
52 {
53 
54 ///////////////////////////////////////////////////////////////////////////
55 
56 static const char *aCH[] =
57 {
58 	UPN_IS_IGNORE_CONTROL_CHARACTERS,
59 	UPN_IS_USE_DICTIONARY_LIST,
60 };
61 
62 static int nCHCount = sizeof(aCH) / sizeof(aCH[0]);
63 
64 
65 PropertyChgHelper::PropertyChgHelper(
66 		const Reference< XInterface > &rxSource,
67 		Reference< XPropertySet > &rxPropSet,
68 		int nAllowedEvents ) :
69     PropertyChgHelperBase(),
70     aPropNames          (nCHCount),
71     xMyEvtObj           (rxSource),
72     aLngSvcEvtListeners (GetLinguMutex()),
73     xPropSet            (rxPropSet),
74     nEvtFlags           (nAllowedEvents)
75 {
76 	OUString *pName = aPropNames.getArray();
77 	for (sal_Int32 i = 0;  i < nCHCount;  ++i)
78 	{
79 		pName[i] = A2OU( aCH[i] );
80 	}
81 
82 	SetDefaultValues();
83 }
84 
85 
86 PropertyChgHelper::PropertyChgHelper( const PropertyChgHelper &rHelper ) :
87     PropertyChgHelperBase(),
88     aLngSvcEvtListeners (GetLinguMutex())
89 {
90 	RemoveAsPropListener();
91     aPropNames  = rHelper.aPropNames;
92     xMyEvtObj   = rHelper.xMyEvtObj;
93     xPropSet    = rHelper.xPropSet;
94     nEvtFlags   = rHelper.nEvtFlags;
95     AddAsPropListener();
96 
97 	SetDefaultValues();
98 	GetCurrentValues();
99 }
100 
101 
102 PropertyChgHelper::~PropertyChgHelper()
103 {
104 }
105 
106 
107 void PropertyChgHelper::AddPropNames( const char *pNewNames[], sal_Int32 nCount )
108 {
109 	if (pNewNames && nCount)
110 	{
111 		sal_Int32 nLen = GetPropNames().getLength();
112 		GetPropNames().realloc( nLen + nCount );
113 		OUString *pName = GetPropNames().getArray();
114 		for (sal_Int32 i = 0;  i < nCount;  ++i)
115 		{
116 			pName[ nLen + i ] = A2OU( pNewNames[ i ] );
117 		}
118 	}
119 }
120 
121 
122 void PropertyChgHelper::SetDefaultValues()
123 {
124 	bResIsIgnoreControlCharacters	= bIsIgnoreControlCharacters	= sal_True;
125 	bResIsUseDictionaryList			= bIsUseDictionaryList			= sal_True;
126 }
127 
128 
129 void PropertyChgHelper::GetCurrentValues()
130 {
131 	sal_Int32 nLen = GetPropNames().getLength();
132 	if (GetPropSet().is() && nLen)
133 	{
134 		const OUString *pPropName = GetPropNames().getConstArray();
135 		for (sal_Int32 i = 0;  i < nLen;  ++i)
136 		{
137 			sal_Bool *pbVal		= NULL,
138 				 *pbResVal	= NULL;
139 
140             if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_IS_IGNORE_CONTROL_CHARACTERS ) ))
141 			{
142 				pbVal	 = &bIsIgnoreControlCharacters;
143 				pbResVal = &bResIsIgnoreControlCharacters;
144 			}
145             else if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_IS_USE_DICTIONARY_LIST ) ))
146 			{
147 				pbVal	 = &bIsUseDictionaryList;
148 				pbResVal = &bResIsUseDictionaryList;
149 			}
150 
151 			if (pbVal && pbResVal)
152 			{
153 				GetPropSet()->getPropertyValue( pPropName[i] ) >>= *pbVal;
154 				*pbResVal = *pbVal;
155 			}
156 		}
157 	}
158 }
159 
160 
161 void PropertyChgHelper::SetTmpPropVals( const PropertyValues &rPropVals )
162 {
163 	// return value is default value unless there is an explicitly supplied
164 	// temporary value
165 	bResIsIgnoreControlCharacters	= bIsIgnoreControlCharacters;
166 	bResIsUseDictionaryList			= bIsUseDictionaryList;
167 	//
168 	sal_Int32 nLen = rPropVals.getLength();
169 	if (nLen)
170 	{
171 		const PropertyValue *pVal = rPropVals.getConstArray();
172 		for (sal_Int32 i = 0;  i < nLen;  ++i)
173 		{
174 			sal_Bool  *pbResVal = NULL;
175 			switch (pVal[i].Handle)
176 			{
177 				case UPH_IS_IGNORE_CONTROL_CHARACTERS :
178 						pbResVal = &bResIsIgnoreControlCharacters; break;
179 				case UPH_IS_USE_DICTIONARY_LIST		:
180 						pbResVal = &bResIsUseDictionaryList; break;
181 				default:
182 						;
183                     //DBG_ASSERT( 0, "unknown property" );
184 			}
185 			if (pbResVal)
186 				pVal[i].Value >>= *pbResVal;
187 		}
188 	}
189 }
190 
191 
192 sal_Bool PropertyChgHelper::propertyChange_Impl( const PropertyChangeEvent& rEvt )
193 {
194 	sal_Bool bRes = sal_False;
195 
196 	if (GetPropSet().is()  &&  rEvt.Source == GetPropSet())
197 	{
198 		sal_Int16 nLngSvcFlags = (nEvtFlags & AE_HYPHENATOR) ?
199 					LinguServiceEventFlags::HYPHENATE_AGAIN : 0;
200 		sal_Bool bSCWA = sal_False,	// SPELL_CORRECT_WORDS_AGAIN ?
201 			 bSWWA = sal_False;	// SPELL_WRONG_WORDS_AGAIN ?
202 
203 		sal_Bool  *pbVal = NULL;
204 		switch (rEvt.PropertyHandle)
205 		{
206 			case UPH_IS_IGNORE_CONTROL_CHARACTERS :
207 			{
208 				pbVal = &bIsIgnoreControlCharacters;
209 				nLngSvcFlags = 0;
210 				break;
211 			}
212 			case UPH_IS_USE_DICTIONARY_LIST		  :
213 			{
214 				pbVal = &bIsUseDictionaryList;
215 				bSCWA = bSWWA = sal_True;
216 				break;
217 			}
218 			default:
219 			{
220 				bRes = sal_False;
221                 //DBG_ASSERT( 0, "unknown property" );
222 			}
223 		}
224 		if (pbVal)
225 			rEvt.NewValue >>= *pbVal;
226 
227 		bRes = 0 != pbVal;	// sth changed?
228 		if (bRes)
229 		{
230 			sal_Bool bSpellEvts = (nEvtFlags & AE_SPELLCHECKER) ? sal_True : sal_False;
231 			if (bSCWA && bSpellEvts)
232 				nLngSvcFlags |= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
233 			if (bSWWA && bSpellEvts)
234 				nLngSvcFlags |= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
235 			if (nLngSvcFlags)
236 			{
237 				LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
238 				LaunchEvent( aEvt );
239 			}
240 		}
241 	}
242 
243 	return bRes;
244 }
245 
246 
247 void SAL_CALL
248 	PropertyChgHelper::propertyChange( const PropertyChangeEvent& rEvt )
249 		throw(RuntimeException)
250 {
251 	MutexGuard	aGuard( GetLinguMutex() );
252 	propertyChange_Impl( rEvt );
253 }
254 
255 
256 void PropertyChgHelper::AddAsPropListener()
257 {
258 	if (xPropSet.is())
259 	{
260 		sal_Int32 nLen = aPropNames.getLength();
261 		const OUString *pPropName = aPropNames.getConstArray();
262 		for (sal_Int32 i = 0;  i < nLen;  ++i)
263 		{
264 			if (pPropName[i].getLength())
265 				xPropSet->addPropertyChangeListener( pPropName[i], this );
266 		}
267 	}
268 }
269 
270 void PropertyChgHelper::RemoveAsPropListener()
271 {
272 	if (xPropSet.is())
273 	{
274 		sal_Int32 nLen = aPropNames.getLength();
275 		const OUString *pPropName = aPropNames.getConstArray();
276 		for (sal_Int32 i = 0;  i < nLen;  ++i)
277 		{
278 			if (pPropName[i].getLength())
279 				xPropSet->removePropertyChangeListener( pPropName[i], this );
280 		}
281 	}
282 }
283 
284 
285 void PropertyChgHelper::LaunchEvent( const LinguServiceEvent &rEvt )
286 {
287 	cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtListeners );
288 	while (aIt.hasMoreElements())
289 	{
290 		Reference< XLinguServiceEventListener > xRef( aIt.next(), UNO_QUERY );
291 		if (xRef.is())
292 			xRef->processLinguServiceEvent( rEvt );
293 	}
294 }
295 
296 
297 void SAL_CALL PropertyChgHelper::disposing( const EventObject& rSource )
298 		throw(RuntimeException)
299 {
300 	MutexGuard	aGuard( GetLinguMutex() );
301 	if (rSource.Source == xPropSet)
302 	{
303 		RemoveAsPropListener();
304 		xPropSet = NULL;
305 		aPropNames.realloc( 0 );
306 	}
307 }
308 
309 
310 sal_Bool SAL_CALL
311 	PropertyChgHelper::addLinguServiceEventListener(
312 			const Reference< XLinguServiceEventListener >& rxListener )
313 		throw(RuntimeException)
314 {
315 	MutexGuard	aGuard( GetLinguMutex() );
316 
317 	sal_Bool bRes = sal_False;
318 	if (rxListener.is())
319 	{
320 		sal_Int32	nCount = aLngSvcEvtListeners.getLength();
321 		bRes = aLngSvcEvtListeners.addInterface( rxListener ) != nCount;
322 	}
323 	return bRes;
324 }
325 
326 
327 sal_Bool SAL_CALL
328 	PropertyChgHelper::removeLinguServiceEventListener(
329 			const Reference< XLinguServiceEventListener >& rxListener )
330 		throw(RuntimeException)
331 {
332 	MutexGuard	aGuard( GetLinguMutex() );
333 
334 	sal_Bool bRes = sal_False;
335 	if (rxListener.is())
336 	{
337 		sal_Int32	nCount = aLngSvcEvtListeners.getLength();
338 		bRes = aLngSvcEvtListeners.removeInterface( rxListener ) != nCount;
339 	}
340 	return bRes;
341 }
342 
343 ///////////////////////////////////////////////////////////////////////////
344 
345 
346 PropertyHelper_Thes::PropertyHelper_Thes(
347 		const Reference< XInterface > &rxSource,
348 		Reference< XPropertySet > &rxPropSet ) :
349 	PropertyChgHelper	( rxSource, rxPropSet, 0 )
350 {
351 	SetDefaultValues();
352 	GetCurrentValues();
353 }
354 
355 
356 PropertyHelper_Thes::~PropertyHelper_Thes()
357 {
358 }
359 
360 
361 void SAL_CALL
362 	PropertyHelper_Thes::propertyChange( const PropertyChangeEvent& rEvt )
363 		throw(RuntimeException)
364 {
365 	MutexGuard	aGuard( GetLinguMutex() );
366     PropertyChgHelper::propertyChange_Impl( rEvt );
367 }
368 
369 
370 ///////////////////////////////////////////////////////////////////////////
371 
372 // list of properties from the property set to be used
373 // and listened to
374 static const char *aSP[] =
375 {
376 	UPN_IS_SPELL_UPPER_CASE,
377 	UPN_IS_SPELL_WITH_DIGITS,
378     UPN_IS_SPELL_CAPITALIZATION
379 };
380 
381 
382 PropertyHelper_Spell::PropertyHelper_Spell(
383 		const Reference< XInterface > & rxSource,
384 		Reference< XPropertySet > &rxPropSet ) :
385 	PropertyChgHelper	( rxSource, rxPropSet, AE_SPELLCHECKER )
386 {
387 	AddPropNames( aSP, sizeof(aSP) / sizeof(aSP[0]) );
388 	SetDefaultValues();
389 	GetCurrentValues();
390 
391     nResMaxNumberOfSuggestions = GetDefaultNumberOfSuggestions();
392 }
393 
394 
395 PropertyHelper_Spell::~PropertyHelper_Spell()
396 {
397 }
398 
399 
400 void PropertyHelper_Spell::SetDefaultValues()
401 {
402 	PropertyChgHelper::SetDefaultValues();
403 
404 	bResIsSpellUpperCase		= bIsSpellUpperCase			= sal_False;
405 	bResIsSpellWithDigits		= bIsSpellWithDigits		= sal_False;
406 	bResIsSpellCapitalization	= bIsSpellCapitalization	= sal_True;
407 }
408 
409 
410 void PropertyHelper_Spell::GetCurrentValues()
411 {
412 	PropertyChgHelper::GetCurrentValues();
413 
414 	sal_Int32 nLen = GetPropNames().getLength();
415 	if (GetPropSet().is() && nLen)
416 	{
417 		const OUString *pPropName = GetPropNames().getConstArray();
418 		for (sal_Int32 i = 0;  i < nLen;  ++i)
419 		{
420 			sal_Bool *pbVal		= NULL,
421 				 *pbResVal	= NULL;
422 
423             if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_IS_SPELL_UPPER_CASE ) ))
424 			{
425 				pbVal	 = &bIsSpellUpperCase;
426 				pbResVal = &bResIsSpellUpperCase;
427 			}
428             else if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_IS_SPELL_WITH_DIGITS ) ))
429 			{
430 				pbVal	 = &bIsSpellWithDigits;
431 				pbResVal = &bResIsSpellWithDigits;
432 			}
433             else if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_IS_SPELL_CAPITALIZATION ) ))
434 			{
435 				pbVal	 = &bIsSpellCapitalization;
436 				pbResVal = &bResIsSpellCapitalization;
437 			}
438 
439 			if (pbVal && pbResVal)
440 			{
441 				GetPropSet()->getPropertyValue( pPropName[i] ) >>= *pbVal;
442 				*pbResVal = *pbVal;
443 			}
444 		}
445 	}
446 }
447 
448 
449 sal_Bool PropertyHelper_Spell::propertyChange_Impl( const PropertyChangeEvent& rEvt )
450 {
451 	sal_Bool bRes = PropertyChgHelper::propertyChange_Impl( rEvt );
452 
453 	if (!bRes  &&  GetPropSet().is()  &&  rEvt.Source == GetPropSet())
454 	{
455 		sal_Int16 nLngSvcFlags = 0;
456 		sal_Bool bSCWA = sal_False,	// SPELL_CORRECT_WORDS_AGAIN ?
457 			 bSWWA = sal_False;	// SPELL_WRONG_WORDS_AGAIN ?
458 
459 		sal_Bool *pbVal = NULL;
460 		switch (rEvt.PropertyHandle)
461 		{
462 			case UPH_IS_SPELL_UPPER_CASE		  :
463 			{
464 				pbVal = &bIsSpellUpperCase;
465 				bSCWA = sal_False == *pbVal;	// sal_False->sal_True change?
466 				bSWWA = !bSCWA;				// sal_True->sal_False change?
467 				break;
468 			}
469 			case UPH_IS_SPELL_WITH_DIGITS		  :
470 			{
471 				pbVal = &bIsSpellWithDigits;
472 				bSCWA = sal_False == *pbVal;	// sal_False->sal_True change?
473 				bSWWA = !bSCWA;				// sal_True->sal_False change?
474 				break;
475 			}
476 			case UPH_IS_SPELL_CAPITALIZATION	  :
477 			{
478 				pbVal = &bIsSpellCapitalization;
479 				bSCWA = sal_False == *pbVal;	// sal_False->sal_True change?
480 				bSWWA = !bSCWA;				// sal_True->sal_False change?
481 				break;
482 			}
483 			default:
484                 DBG_ASSERT( 0, "unknown property" );
485 		}
486 		if (pbVal)
487 			rEvt.NewValue >>= *pbVal;
488 
489 		bRes = (pbVal != 0);
490 		if (bRes)
491 		{
492 			if (bSCWA)
493 				nLngSvcFlags |= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
494 			if (bSWWA)
495 				nLngSvcFlags |= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
496 			if (nLngSvcFlags)
497 			{
498 				LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
499 				LaunchEvent( aEvt );
500 			}
501 		}
502 	}
503 
504 	return bRes;
505 }
506 
507 
508 void SAL_CALL
509 	PropertyHelper_Spell::propertyChange( const PropertyChangeEvent& rEvt )
510 		throw(RuntimeException)
511 {
512 	MutexGuard	aGuard( GetLinguMutex() );
513 	propertyChange_Impl( rEvt );
514 }
515 
516 
517 void PropertyHelper_Spell::SetTmpPropVals( const PropertyValues &rPropVals )
518 {
519 	PropertyChgHelper::SetTmpPropVals( rPropVals );
520 
521 	// return value is default value unless there is an explicitly supplied
522 	// temporary value
523     nResMaxNumberOfSuggestions  = GetDefaultNumberOfSuggestions();
524 	bResIsSpellWithDigits		= bIsSpellWithDigits;
525 	bResIsSpellCapitalization	= bIsSpellCapitalization;
526 	//
527 	sal_Int32 nLen = rPropVals.getLength();
528 	if (nLen)
529 	{
530 		const PropertyValue *pVal = rPropVals.getConstArray();
531 		for (sal_Int32 i = 0;  i < nLen;  ++i)
532 		{
533             if (pVal[i].Name.equalsAscii( UPN_MAX_NUMBER_OF_SUGGESTIONS ))
534             {
535                 pVal[i].Value >>= nResMaxNumberOfSuggestions;
536             }
537             else
538             {
539                 sal_Bool *pbResVal = NULL;
540                 switch (pVal[i].Handle)
541                 {
542                     case UPH_IS_SPELL_UPPER_CASE     : pbResVal = &bResIsSpellUpperCase; break;
543                     case UPH_IS_SPELL_WITH_DIGITS    : pbResVal = &bResIsSpellWithDigits; break;
544                     case UPH_IS_SPELL_CAPITALIZATION : pbResVal = &bResIsSpellCapitalization; break;
545                     default:
546                         DBG_ASSERT( 0, "unknown property" );
547                 }
548                 if (pbResVal)
549                     pVal[i].Value >>= *pbResVal;
550             }
551 		}
552 	}
553 }
554 
555 sal_Int16 PropertyHelper_Spell::GetDefaultNumberOfSuggestions() const
556 {
557     return 16;
558 }
559 
560 ///////////////////////////////////////////////////////////////////////////
561 
562 static const char *aHP[] =
563 {
564 	UPN_HYPH_MIN_LEADING,
565 	UPN_HYPH_MIN_TRAILING,
566 	UPN_HYPH_MIN_WORD_LENGTH
567 };
568 
569 
570 PropertyHelper_Hyphen::PropertyHelper_Hyphen(
571 		const Reference< XInterface > & rxSource,
572 		Reference< XPropertySet > &rxPropSet ) :
573 	PropertyChgHelper	( rxSource, rxPropSet, AE_HYPHENATOR )
574 {
575 	AddPropNames( aHP, sizeof(aHP) / sizeof(aHP[0]) );
576 	SetDefaultValues();
577 	GetCurrentValues();
578 }
579 
580 
581 PropertyHelper_Hyphen::~PropertyHelper_Hyphen()
582 {
583 }
584 
585 
586 void PropertyHelper_Hyphen::SetDefaultValues()
587 {
588 	PropertyChgHelper::SetDefaultValues();
589 
590 	nResHyphMinLeading	 	= nHyphMinLeading		= 2;
591 	nResHyphMinTrailing	 	= nHyphMinTrailing		= 2;
592 	nResHyphMinWordLength	= nHyphMinWordLength	= 0;
593 }
594 
595 
596 void PropertyHelper_Hyphen::GetCurrentValues()
597 {
598 	PropertyChgHelper::GetCurrentValues();
599 
600 	sal_Int32 nLen = GetPropNames().getLength();
601 	if (GetPropSet().is() && nLen)
602 	{
603 		const OUString *pPropName = GetPropNames().getConstArray();
604 		for (sal_Int32 i = 0;  i < nLen;  ++i)
605 		{
606 			sal_Int16  *pnVal	 = NULL,
607 				   *pnResVal = NULL;
608 
609             if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_HYPH_MIN_LEADING ) ))
610 			{
611 				pnVal	 = &nHyphMinLeading;
612 				pnResVal = &nResHyphMinLeading;
613 			}
614             else if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_HYPH_MIN_TRAILING ) ))
615 			{
616 				pnVal	 = &nHyphMinTrailing;
617 				pnResVal = &nResHyphMinTrailing;
618 			}
619             else if (pPropName[i].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( UPN_HYPH_MIN_WORD_LENGTH ) ))
620 			{
621 				pnVal	 = &nHyphMinWordLength;
622 				pnResVal = &nResHyphMinWordLength;
623 			}
624 
625 			if (pnVal && pnResVal)
626 			{
627 				GetPropSet()->getPropertyValue( pPropName[i] ) >>= *pnVal;
628 				*pnResVal = *pnVal;
629 			}
630 		}
631 	}
632 }
633 
634 
635 sal_Bool PropertyHelper_Hyphen::propertyChange_Impl( const PropertyChangeEvent& rEvt )
636 {
637 	sal_Bool bRes = PropertyChgHelper::propertyChange_Impl( rEvt );
638 
639 	if (!bRes  &&  GetPropSet().is()  &&  rEvt.Source == GetPropSet())
640 	{
641 		sal_Int16 nLngSvcFlags = LinguServiceEventFlags::HYPHENATE_AGAIN;
642 
643 		sal_Int16	*pnVal = NULL;
644 		switch (rEvt.PropertyHandle)
645 		{
646 			case UPH_HYPH_MIN_LEADING	  : pnVal = &nHyphMinLeading; break;
647 			case UPH_HYPH_MIN_TRAILING	  : pnVal = &nHyphMinTrailing; break;
648 			case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &nHyphMinWordLength; break;
649 			default:
650                 DBG_ASSERT( 0, "unknown property" );
651 		}
652 		if (pnVal)
653 			rEvt.NewValue >>= *pnVal;
654 
655 		bRes = (pnVal != 0);
656 		if (bRes)
657 		{
658 			if (nLngSvcFlags)
659 			{
660 				LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
661 				LaunchEvent( aEvt );
662 			}
663 		}
664 	}
665 
666 	return bRes;
667 }
668 
669 
670 void SAL_CALL
671     PropertyHelper_Hyphen::propertyChange( const PropertyChangeEvent& rEvt )
672 		throw(RuntimeException)
673 {
674 	MutexGuard	aGuard( GetLinguMutex() );
675 	propertyChange_Impl( rEvt );
676 }
677 
678 
679 void PropertyHelper_Hyphen::SetTmpPropVals( const PropertyValues &rPropVals )
680 {
681 	PropertyChgHelper::SetTmpPropVals( rPropVals );
682 
683 	// return value is default value unless there is an explicitly supplied
684 	// temporary value
685 	nResHyphMinLeading	 	= nHyphMinLeading;
686 	nResHyphMinTrailing	 	= nHyphMinTrailing;
687 	nResHyphMinWordLength	= nHyphMinWordLength;
688 	//
689 	sal_Int32 nLen = rPropVals.getLength();
690 	if (nLen)
691 	{
692 		const PropertyValue *pVal = rPropVals.getConstArray();
693 		for (sal_Int32 i = 0;  i < nLen;  ++i)
694 		{
695 			sal_Int16	*pnResVal = NULL;
696 			switch (pVal[i].Handle)
697 			{
698 				case UPH_HYPH_MIN_LEADING	  : pnResVal = &nResHyphMinLeading; break;
699 				case UPH_HYPH_MIN_TRAILING	  : pnResVal = &nResHyphMinTrailing; break;
700 				case UPH_HYPH_MIN_WORD_LENGTH : pnResVal = &nResHyphMinWordLength; break;
701 				default:
702                     DBG_ASSERT( 0, "unknown property" );
703 			}
704 			if (pnResVal)
705 				pVal[i].Value >>= *pnResVal;
706 		}
707 	}
708 }
709 
710 ///////////////////////////////////////////////////////////////////////////
711 
712 }   // namespace linguistic
713 
714