Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / linguistic / source / lngprophelp.cxx
blobed0006c8962b8a89cd5596a2c712c7296901dfc2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/debug.hxx>
22 #include <sal/macros.h>
23 #include <sal/log.hxx>
25 #include <com/sun/star/linguistic2/LinguServiceEvent.hpp>
26 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
27 #include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
28 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <osl/mutex.hxx>
31 #include <unotools/linguprops.hxx>
33 #include <linguistic/misc.hxx>
34 #include <linguistic/lngprops.hxx>
36 #include <linguistic/lngprophelp.hxx>
38 using namespace osl;
39 using namespace com::sun::star;
40 using namespace com::sun::star::beans;
41 using namespace com::sun::star::lang;
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::linguistic2;
44 using namespace linguistic;
47 namespace linguistic
51 static const char *aCH[] =
53 UPN_IS_IGNORE_CONTROL_CHARACTERS,
54 UPN_IS_USE_DICTIONARY_LIST,
57 static const int nCHCount = SAL_N_ELEMENTS(aCH);
60 PropertyChgHelper::PropertyChgHelper(
61 const Reference< XInterface > &rxSource,
62 Reference< XLinguProperties > const &rxPropSet,
63 int nAllowedEvents ) :
64 PropertyChgHelperBase(),
65 aPropNames (nCHCount),
66 xMyEvtObj (rxSource),
67 aLngSvcEvtListeners (GetLinguMutex()),
68 xPropSet (rxPropSet),
69 nEvtFlags (nAllowedEvents)
71 OUString *pName = aPropNames.getArray();
72 for (sal_Int32 i = 0; i < nCHCount; ++i)
74 pName[i] = OUString::createFromAscii( aCH[i] );
77 SetDefaultValues();
80 PropertyChgHelper::~PropertyChgHelper()
85 void PropertyChgHelper::AddPropNames( const char *pNewNames[], sal_Int32 nCount )
87 if (pNewNames && nCount)
89 sal_Int32 nLen = GetPropNames().getLength();
90 GetPropNames().realloc( nLen + nCount );
91 OUString *pName = GetPropNames().getArray();
92 for (sal_Int32 i = 0; i < nCount; ++i)
94 pName[ nLen + i ] = OUString::createFromAscii( pNewNames[ i ] );
101 void PropertyChgHelper::SetDefaultValues()
103 bResIsIgnoreControlCharacters = bIsIgnoreControlCharacters = true;
104 bResIsUseDictionaryList = bIsUseDictionaryList = true;
108 void PropertyChgHelper::GetCurrentValues()
110 const auto& rPropNames = GetPropNames();
111 if (GetPropSet().is() && rPropNames.hasElements())
113 for (const OUString& rPropName : rPropNames)
115 bool *pbVal = nullptr,
116 *pbResVal = nullptr;
118 if ( rPropName == UPN_IS_IGNORE_CONTROL_CHARACTERS )
120 pbVal = &bIsIgnoreControlCharacters;
121 pbResVal = &bResIsIgnoreControlCharacters;
123 else if ( rPropName == UPN_IS_USE_DICTIONARY_LIST )
125 pbVal = &bIsUseDictionaryList;
126 pbResVal = &bResIsUseDictionaryList;
129 if (pbVal && pbResVal)
131 GetPropSet()->getPropertyValue( rPropName ) >>= *pbVal;
132 *pbResVal = *pbVal;
139 void PropertyChgHelper::SetTmpPropVals( const PropertyValues &rPropVals )
141 // return value is default value unless there is an explicitly supplied
142 // temporary value
143 bResIsIgnoreControlCharacters = bIsIgnoreControlCharacters;
144 bResIsUseDictionaryList = bIsUseDictionaryList;
146 for (const PropertyValue& rVal : rPropVals)
148 bool *pbResVal = nullptr;
149 switch (rVal.Handle)
151 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
152 pbResVal = &bResIsIgnoreControlCharacters; break;
153 case UPH_IS_USE_DICTIONARY_LIST :
154 pbResVal = &bResIsUseDictionaryList; break;
155 default:
158 if (pbResVal)
159 rVal.Value >>= *pbResVal;
164 bool PropertyChgHelper::propertyChange_Impl( const PropertyChangeEvent& rEvt )
166 bool bRes = false;
168 if (GetPropSet().is() && rEvt.Source == GetPropSet())
170 sal_Int16 nLngSvcFlags = (nEvtFlags & AE_HYPHENATOR) ?
171 LinguServiceEventFlags::HYPHENATE_AGAIN : 0;
172 bool bSCWA = false, // SPELL_CORRECT_WORDS_AGAIN ?
173 bSWWA = false; // SPELL_WRONG_WORDS_AGAIN ?
175 bool *pbVal = nullptr;
176 switch (rEvt.PropertyHandle)
178 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
180 pbVal = &bIsIgnoreControlCharacters;
181 nLngSvcFlags = 0;
182 break;
184 case UPH_IS_USE_DICTIONARY_LIST :
186 pbVal = &bIsUseDictionaryList;
187 bSCWA = bSWWA = true;
188 break;
191 if (pbVal)
192 rEvt.NewValue >>= *pbVal;
194 bRes = nullptr != pbVal; // sth changed?
195 if (bRes)
197 bool bSpellEvts = (nEvtFlags & AE_SPELLCHECKER);
198 if (bSCWA && bSpellEvts)
199 nLngSvcFlags |= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
200 if (bSWWA && bSpellEvts)
201 nLngSvcFlags |= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
202 if (nLngSvcFlags)
204 LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
205 LaunchEvent( aEvt );
210 return bRes;
214 void SAL_CALL
215 PropertyChgHelper::propertyChange( const PropertyChangeEvent& rEvt )
217 MutexGuard aGuard( GetLinguMutex() );
218 propertyChange_Impl( rEvt );
222 void PropertyChgHelper::AddAsPropListener()
224 if (xPropSet.is())
226 for (const OUString& rPropName : std::as_const(aPropNames))
228 if (!rPropName.isEmpty())
229 xPropSet->addPropertyChangeListener( rPropName, this );
234 void PropertyChgHelper::RemoveAsPropListener()
236 if (xPropSet.is())
238 for (const OUString& rPropName : std::as_const(aPropNames))
240 if (!rPropName.isEmpty())
241 xPropSet->removePropertyChangeListener( rPropName, this );
247 void PropertyChgHelper::LaunchEvent( const LinguServiceEvent &rEvt )
249 aLngSvcEvtListeners.notifyEach( &XLinguServiceEventListener::processLinguServiceEvent, rEvt );
253 void SAL_CALL PropertyChgHelper::disposing( const EventObject& rSource )
255 MutexGuard aGuard( GetLinguMutex() );
256 if (rSource.Source == xPropSet)
258 RemoveAsPropListener();
259 xPropSet = nullptr;
260 aPropNames.realloc( 0 );
265 sal_Bool SAL_CALL
266 PropertyChgHelper::addLinguServiceEventListener(
267 const Reference< XLinguServiceEventListener >& rxListener )
269 MutexGuard aGuard( GetLinguMutex() );
271 bool bRes = false;
272 if (rxListener.is())
274 sal_Int32 nCount = aLngSvcEvtListeners.getLength();
275 bRes = aLngSvcEvtListeners.addInterface( rxListener ) != nCount;
277 return bRes;
281 sal_Bool SAL_CALL
282 PropertyChgHelper::removeLinguServiceEventListener(
283 const Reference< XLinguServiceEventListener >& rxListener )
285 MutexGuard aGuard( GetLinguMutex() );
287 bool bRes = false;
288 if (rxListener.is())
290 sal_Int32 nCount = aLngSvcEvtListeners.getLength();
291 bRes = aLngSvcEvtListeners.removeInterface( rxListener ) != nCount;
293 return bRes;
297 PropertyHelper_Thes::PropertyHelper_Thes(
298 const Reference< XInterface > &rxSource,
299 Reference< XLinguProperties > const &rxPropSet ) :
300 PropertyChgHelper ( rxSource, rxPropSet, 0 )
302 SetDefaultValues();
303 GetCurrentValues();
307 PropertyHelper_Thes::~PropertyHelper_Thes()
312 void SAL_CALL
313 PropertyHelper_Thes::propertyChange( const PropertyChangeEvent& rEvt )
315 MutexGuard aGuard( GetLinguMutex() );
316 PropertyChgHelper::propertyChange_Impl( rEvt );
320 // list of properties from the property set to be used
321 // and listened to
322 static const char *aSP[] =
324 UPN_IS_SPELL_UPPER_CASE,
325 UPN_IS_SPELL_WITH_DIGITS,
326 UPN_IS_SPELL_CAPITALIZATION
330 PropertyHelper_Spell::PropertyHelper_Spell(
331 const Reference< XInterface > & rxSource,
332 Reference< XLinguProperties > const &rxPropSet ) :
333 PropertyChgHelper ( rxSource, rxPropSet, AE_SPELLCHECKER )
335 AddPropNames( aSP, SAL_N_ELEMENTS(aSP) );
336 SetDefaultValues();
337 GetCurrentValues();
341 PropertyHelper_Spell::~PropertyHelper_Spell()
346 void PropertyHelper_Spell::SetDefaultValues()
348 PropertyChgHelper::SetDefaultValues();
350 bResIsSpellUpperCase = bIsSpellUpperCase = false;
351 bResIsSpellWithDigits = bIsSpellWithDigits = false;
352 bResIsSpellCapitalization = bIsSpellCapitalization = true;
356 void PropertyHelper_Spell::GetCurrentValues()
358 PropertyChgHelper::GetCurrentValues();
360 const auto& rPropNames = GetPropNames();
361 if (GetPropSet().is() && rPropNames.hasElements())
363 for (const OUString& rPropName : rPropNames)
365 bool *pbVal = nullptr,
366 *pbResVal = nullptr;
368 if ( rPropName == UPN_IS_SPELL_UPPER_CASE )
370 pbVal = &bIsSpellUpperCase;
371 pbResVal = &bResIsSpellUpperCase;
373 else if ( rPropName == UPN_IS_SPELL_WITH_DIGITS )
375 pbVal = &bIsSpellWithDigits;
376 pbResVal = &bResIsSpellWithDigits;
378 else if ( rPropName == UPN_IS_SPELL_CAPITALIZATION )
380 pbVal = &bIsSpellCapitalization;
381 pbResVal = &bResIsSpellCapitalization;
384 if (pbVal && pbResVal)
386 GetPropSet()->getPropertyValue( rPropName ) >>= *pbVal;
387 *pbResVal = *pbVal;
394 bool PropertyHelper_Spell::propertyChange_Impl( const PropertyChangeEvent& rEvt )
396 bool bRes = PropertyChgHelper::propertyChange_Impl( rEvt );
398 if (!bRes && GetPropSet().is() && rEvt.Source == GetPropSet())
400 bool bSCWA = false, // SPELL_CORRECT_WORDS_AGAIN ?
401 bSWWA = false; // SPELL_WRONG_WORDS_AGAIN ?
403 bool *pbVal = nullptr;
404 switch (rEvt.PropertyHandle)
406 case UPH_IS_SPELL_UPPER_CASE :
408 pbVal = &bIsSpellUpperCase;
409 bSCWA = ! *pbVal; // sal_False->sal_True change?
410 bSWWA = !bSCWA; // sal_True->sal_False change?
411 break;
413 case UPH_IS_SPELL_WITH_DIGITS :
415 pbVal = &bIsSpellWithDigits;
416 bSCWA = ! *pbVal; // sal_False->sal_True change?
417 bSWWA = !bSCWA; // sal_True->sal_False change?
418 break;
420 case UPH_IS_SPELL_CAPITALIZATION :
422 pbVal = &bIsSpellCapitalization;
423 bSCWA = ! *pbVal; // sal_False->sal_True change?
424 bSWWA = !bSCWA; // sal_True->sal_False change?
425 break;
427 default:
428 SAL_WARN( "linguistic", "unknown property" );
430 if (pbVal)
431 rEvt.NewValue >>= *pbVal;
433 bRes = (pbVal != nullptr);
434 if (bRes)
436 sal_Int16 nLngSvcFlags = 0;
437 if (bSCWA)
438 nLngSvcFlags |= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
439 if (bSWWA)
440 nLngSvcFlags |= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
441 if (nLngSvcFlags)
443 LinguServiceEvent aEvt( GetEvtObj(), nLngSvcFlags );
444 LaunchEvent( aEvt );
449 return bRes;
453 void SAL_CALL
454 PropertyHelper_Spell::propertyChange( const PropertyChangeEvent& rEvt )
456 MutexGuard aGuard( GetLinguMutex() );
457 propertyChange_Impl( rEvt );
461 void PropertyHelper_Spell::SetTmpPropVals( const PropertyValues &rPropVals )
463 PropertyChgHelper::SetTmpPropVals( rPropVals );
465 // return value is default value unless there is an explicitly supplied
466 // temporary value
467 bResIsSpellWithDigits = bIsSpellWithDigits;
468 bResIsSpellCapitalization = bIsSpellCapitalization;
469 bResIsSpellUpperCase = bIsSpellUpperCase;
471 for (const PropertyValue& rVal : rPropVals)
473 if ( rVal.Name == UPN_MAX_NUMBER_OF_SUGGESTIONS )
475 // special value that is not part of the property set and thus needs to be handled differently
477 else
479 bool *pbResVal = nullptr;
480 switch (rVal.Handle)
482 case UPH_IS_SPELL_UPPER_CASE : pbResVal = &bResIsSpellUpperCase; break;
483 case UPH_IS_SPELL_WITH_DIGITS : pbResVal = &bResIsSpellWithDigits; break;
484 case UPH_IS_SPELL_CAPITALIZATION : pbResVal = &bResIsSpellCapitalization; break;
485 default:
486 SAL_WARN( "linguistic", "unknown property" );
488 if (pbResVal)
489 rVal.Value >>= *pbResVal;
494 static const char *aHP[] =
496 UPN_HYPH_MIN_LEADING,
497 UPN_HYPH_MIN_TRAILING,
498 UPN_HYPH_MIN_WORD_LENGTH
502 PropertyHelper_Hyphen::PropertyHelper_Hyphen(
503 const Reference< XInterface > & rxSource,
504 Reference< XLinguProperties > const &rxPropSet ) :
505 PropertyChgHelper ( rxSource, rxPropSet, AE_HYPHENATOR )
507 AddPropNames( aHP, SAL_N_ELEMENTS(aHP) );
508 SetDefaultValues();
509 GetCurrentValues();
513 PropertyHelper_Hyphen::~PropertyHelper_Hyphen()
518 void PropertyHelper_Hyphen::SetDefaultValues()
520 PropertyChgHelper::SetDefaultValues();
522 nResHyphMinLeading = nHyphMinLeading = 2;
523 nResHyphMinTrailing = nHyphMinTrailing = 2;
524 nResHyphMinWordLength = nHyphMinWordLength = 0;
528 void PropertyHelper_Hyphen::GetCurrentValues()
530 PropertyChgHelper::GetCurrentValues();
532 const auto& rPropNames = GetPropNames();
533 if (GetPropSet().is() && rPropNames.hasElements())
535 for (const OUString& rPropName : rPropNames)
537 sal_Int16 *pnVal = nullptr,
538 *pnResVal = nullptr;
540 if ( rPropName == UPN_HYPH_MIN_LEADING )
542 pnVal = &nHyphMinLeading;
543 pnResVal = &nResHyphMinLeading;
545 else if ( rPropName == UPN_HYPH_MIN_TRAILING )
547 pnVal = &nHyphMinTrailing;
548 pnResVal = &nResHyphMinTrailing;
550 else if ( rPropName == UPN_HYPH_MIN_WORD_LENGTH )
552 pnVal = &nHyphMinWordLength;
553 pnResVal = &nResHyphMinWordLength;
556 if (pnVal && pnResVal)
558 GetPropSet()->getPropertyValue( rPropName ) >>= *pnVal;
559 *pnResVal = *pnVal;
566 bool PropertyHelper_Hyphen::propertyChange_Impl( const PropertyChangeEvent& rEvt )
568 bool bRes = PropertyChgHelper::propertyChange_Impl( rEvt );
570 if (!bRes && GetPropSet().is() && rEvt.Source == GetPropSet())
572 sal_Int16 *pnVal = nullptr;
573 switch (rEvt.PropertyHandle)
575 case UPH_HYPH_MIN_LEADING : pnVal = &nHyphMinLeading; break;
576 case UPH_HYPH_MIN_TRAILING : pnVal = &nHyphMinTrailing; break;
577 case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &nHyphMinWordLength; break;
578 default:
579 SAL_WARN( "linguistic", "unknown property" );
581 if (pnVal)
582 rEvt.NewValue >>= *pnVal;
584 bRes = (pnVal != nullptr);
585 if (bRes)
587 LinguServiceEvent aEvt(GetEvtObj(), LinguServiceEventFlags::HYPHENATE_AGAIN);
588 LaunchEvent(aEvt);
592 return bRes;
596 void SAL_CALL
597 PropertyHelper_Hyphen::propertyChange( const PropertyChangeEvent& rEvt )
599 MutexGuard aGuard( GetLinguMutex() );
600 propertyChange_Impl( rEvt );
604 void PropertyHelper_Hyphen::SetTmpPropVals( const PropertyValues &rPropVals )
606 PropertyChgHelper::SetTmpPropVals( rPropVals );
608 // return value is default value unless there is an explicitly supplied
609 // temporary value
610 nResHyphMinLeading = nHyphMinLeading;
611 nResHyphMinTrailing = nHyphMinTrailing;
612 nResHyphMinWordLength = nHyphMinWordLength;
614 for (const PropertyValue& rVal : rPropVals)
616 sal_Int16 *pnResVal = nullptr;
618 if ( rVal.Name == UPN_HYPH_MIN_LEADING )
619 pnResVal = &nResHyphMinLeading;
620 else if ( rVal.Name == UPN_HYPH_MIN_TRAILING )
621 pnResVal = &nResHyphMinTrailing;
622 else if ( rVal.Name == UPN_HYPH_MIN_WORD_LENGTH )
623 pnResVal = &nResHyphMinWordLength;
625 DBG_ASSERT( pnResVal, "unknown property" );
627 if (pnResVal)
628 rVal.Value >>= *pnResVal;
632 PropertyHelper_Thesaurus::PropertyHelper_Thesaurus(
633 const css::uno::Reference< css::uno::XInterface > &rxSource,
634 css::uno::Reference< css::linguistic2::XLinguProperties > const &rxPropSet )
636 mxPropHelper = new PropertyHelper_Thes( rxSource, rxPropSet );
639 PropertyHelper_Thesaurus::~PropertyHelper_Thesaurus()
643 void PropertyHelper_Thesaurus::AddAsPropListener()
645 mxPropHelper->AddAsPropListener();
648 void PropertyHelper_Thesaurus::RemoveAsPropListener()
650 mxPropHelper->RemoveAsPropListener();
653 void PropertyHelper_Thesaurus::SetTmpPropVals( const css::beans::PropertyValues &rPropVals )
655 mxPropHelper->SetTmpPropVals( rPropVals );
658 PropertyHelper_Hyphenation::PropertyHelper_Hyphenation(
659 const css::uno::Reference< css::uno::XInterface > &rxSource,
660 css::uno::Reference< css::linguistic2::XLinguProperties > const &rxPropSet)
662 mxPropHelper = new PropertyHelper_Hyphen( rxSource, rxPropSet );
665 PropertyHelper_Hyphenation::~PropertyHelper_Hyphenation()
669 void PropertyHelper_Hyphenation::AddAsPropListener()
671 mxPropHelper->AddAsPropListener();
674 void PropertyHelper_Hyphenation::RemoveAsPropListener()
676 mxPropHelper->RemoveAsPropListener();
679 void PropertyHelper_Hyphenation::SetTmpPropVals( const css::beans::PropertyValues &rPropVals )
681 mxPropHelper->SetTmpPropVals( rPropVals );
684 sal_Int16 PropertyHelper_Hyphenation::GetMinLeading() const
686 return mxPropHelper->GetMinLeading();
689 sal_Int16 PropertyHelper_Hyphenation::GetMinTrailing() const
691 return mxPropHelper->GetMinTrailing();
694 sal_Int16 PropertyHelper_Hyphenation::GetMinWordLength() const
696 return mxPropHelper->GetMinWordLength();
699 bool PropertyHelper_Hyphenation::addLinguServiceEventListener(
700 const css::uno::Reference< css::linguistic2::XLinguServiceEventListener >& rxListener )
702 return mxPropHelper->addLinguServiceEventListener( rxListener );
705 bool PropertyHelper_Hyphenation::removeLinguServiceEventListener(
706 const css::uno::Reference< css::linguistic2::XLinguServiceEventListener >& rxListener )
708 return mxPropHelper->removeLinguServiceEventListener( rxListener );
711 PropertyHelper_Spelling::PropertyHelper_Spelling(
712 const css::uno::Reference< css::uno::XInterface > &rxSource,
713 css::uno::Reference< css::linguistic2::XLinguProperties > const &rxPropSet )
715 mxPropHelper = new PropertyHelper_Spell( rxSource, rxPropSet );
718 PropertyHelper_Spelling::~PropertyHelper_Spelling()
722 void PropertyHelper_Spelling::AddAsPropListener()
724 mxPropHelper->AddAsPropListener();
727 void PropertyHelper_Spelling::RemoveAsPropListener()
729 mxPropHelper->RemoveAsPropListener();
732 void PropertyHelper_Spelling::SetTmpPropVals( const css::beans::PropertyValues &rPropVals )
734 mxPropHelper->SetTmpPropVals( rPropVals );
737 bool PropertyHelper_Spelling::IsSpellUpperCase() const
739 return mxPropHelper->IsSpellUpperCase();
742 bool PropertyHelper_Spelling::IsSpellWithDigits() const
744 return mxPropHelper->IsSpellWithDigits();
747 bool PropertyHelper_Spelling::IsSpellCapitalization() const
749 return mxPropHelper->IsSpellCapitalization();
752 bool PropertyHelper_Spelling::addLinguServiceEventListener(
753 const css::uno::Reference<
754 css::linguistic2::XLinguServiceEventListener >& rxListener )
756 return mxPropHelper->addLinguServiceEventListener( rxListener );
759 bool PropertyHelper_Spelling::removeLinguServiceEventListener(
760 const css::uno::Reference<
761 css::linguistic2::XLinguServiceEventListener >& rxListener )
763 return mxPropHelper->removeLinguServiceEventListener( rxListener );
766 } // namespace linguistic
768 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */