1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
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
),
67 aLngSvcEvtListeners (GetLinguMutex()),
69 nEvtFlags (nAllowedEvents
)
71 OUString
*pName
= aPropNames
.getArray();
72 for (sal_Int32 i
= 0; i
< nCHCount
; ++i
)
74 pName
[i
] = OUString::createFromAscii( aCH
[i
] );
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,
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
;
139 void PropertyChgHelper::SetTmpPropVals( const PropertyValues
&rPropVals
)
141 // return value is default value unless there is an explicitly supplied
143 bResIsIgnoreControlCharacters
= bIsIgnoreControlCharacters
;
144 bResIsUseDictionaryList
= bIsUseDictionaryList
;
146 for (const PropertyValue
& rVal
: rPropVals
)
148 bool *pbResVal
= nullptr;
151 case UPH_IS_IGNORE_CONTROL_CHARACTERS
:
152 pbResVal
= &bResIsIgnoreControlCharacters
; break;
153 case UPH_IS_USE_DICTIONARY_LIST
:
154 pbResVal
= &bResIsUseDictionaryList
; break;
159 rVal
.Value
>>= *pbResVal
;
164 bool PropertyChgHelper::propertyChange_Impl( const PropertyChangeEvent
& rEvt
)
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
;
184 case UPH_IS_USE_DICTIONARY_LIST
:
186 pbVal
= &bIsUseDictionaryList
;
187 bSCWA
= bSWWA
= true;
192 rEvt
.NewValue
>>= *pbVal
;
194 bRes
= nullptr != pbVal
; // sth changed?
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
;
204 LinguServiceEvent
aEvt( GetEvtObj(), nLngSvcFlags
);
215 PropertyChgHelper::propertyChange( const PropertyChangeEvent
& rEvt
)
217 MutexGuard
aGuard( GetLinguMutex() );
218 propertyChange_Impl( rEvt
);
222 void PropertyChgHelper::AddAsPropListener()
226 for (const OUString
& rPropName
: std::as_const(aPropNames
))
228 if (!rPropName
.isEmpty())
229 xPropSet
->addPropertyChangeListener( rPropName
, this );
234 void PropertyChgHelper::RemoveAsPropListener()
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();
260 aPropNames
.realloc( 0 );
266 PropertyChgHelper::addLinguServiceEventListener(
267 const Reference
< XLinguServiceEventListener
>& rxListener
)
269 MutexGuard
aGuard( GetLinguMutex() );
274 sal_Int32 nCount
= aLngSvcEvtListeners
.getLength();
275 bRes
= aLngSvcEvtListeners
.addInterface( rxListener
) != nCount
;
282 PropertyChgHelper::removeLinguServiceEventListener(
283 const Reference
< XLinguServiceEventListener
>& rxListener
)
285 MutexGuard
aGuard( GetLinguMutex() );
290 sal_Int32 nCount
= aLngSvcEvtListeners
.getLength();
291 bRes
= aLngSvcEvtListeners
.removeInterface( rxListener
) != nCount
;
297 PropertyHelper_Thes::PropertyHelper_Thes(
298 const Reference
< XInterface
> &rxSource
,
299 Reference
< XLinguProperties
> const &rxPropSet
) :
300 PropertyChgHelper ( rxSource
, rxPropSet
, 0 )
307 PropertyHelper_Thes::~PropertyHelper_Thes()
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
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
) );
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,
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
;
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?
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?
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?
428 SAL_WARN( "linguistic", "unknown property" );
431 rEvt
.NewValue
>>= *pbVal
;
433 bRes
= (pbVal
!= nullptr);
436 sal_Int16 nLngSvcFlags
= 0;
438 nLngSvcFlags
|= LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN
;
440 nLngSvcFlags
|= LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN
;
443 LinguServiceEvent
aEvt( GetEvtObj(), nLngSvcFlags
);
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
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
479 bool *pbResVal
= nullptr;
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;
486 SAL_WARN( "linguistic", "unknown property" );
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
) );
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,
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
;
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;
579 SAL_WARN( "linguistic", "unknown property" );
582 rEvt
.NewValue
>>= *pnVal
;
584 bRes
= (pnVal
!= nullptr);
587 LinguServiceEvent
aEvt(GetEvtObj(), LinguServiceEventFlags::HYPHENATE_AGAIN
);
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
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" );
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: */