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 <sal/macros.h>
24 #include <linguistic/lngprops.hxx>
25 #include <linguistic/misc.hxx>
26 #include <tools/debug.hxx>
27 #include <unotools/lingucfg.hxx>
29 #include <cppuhelper/factory.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <com/sun/star/container/XNameAccess.hpp>
32 #include <com/sun/star/registry/XSimpleRegistry.hpp>
33 #include <com/sun/star/registry/XRegistryKey.hpp>
34 #include <com/sun/star/lang/Locale.hpp>
35 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
36 #include <com/sun/star/i18n/ScriptType.hpp>
37 #include <i18nlangtag/mslangid.hxx>
41 using namespace com::sun::star
;
42 using namespace com::sun::star::container
;
43 using namespace com::sun::star::beans
;
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::uno
;
46 using namespace com::sun::star::linguistic2
;
47 using namespace linguistic
;
49 using namespace com::sun::star::registry
;
52 // static member initialization
53 SvtLinguOptions
* LinguOptions::pData
= nullptr;
54 oslInterlockedCount
LinguOptions::nRefCount
;
57 LinguOptions::LinguOptions()
61 pData
= new SvtLinguOptions
;
62 SvtLinguConfig aLinguCfg
;
63 aLinguCfg
.GetOptions( *pData
);
66 osl_atomic_increment( &nRefCount
);
70 LinguOptions::LinguOptions(const LinguOptions
& /*rOpt*/)
72 DBG_ASSERT( pData
, "lng : data missing" );
73 osl_atomic_increment( &nRefCount
);
77 LinguOptions::~LinguOptions()
79 MutexGuard
aGuard( GetLinguMutex() );
81 if ( osl_atomic_decrement( &nRefCount
) == 0 )
83 delete pData
; pData
= nullptr;
90 const char *pPropertyName
;
93 //! order of entries is import (see LinguOptions::GetName)
94 //! since the WID is used as index in this table!
95 WID_Name
const aWID_Name
[] =
98 { UPH_IS_USE_DICTIONARY_LIST
, UPN_IS_USE_DICTIONARY_LIST
},
99 { UPH_IS_IGNORE_CONTROL_CHARACTERS
, UPN_IS_IGNORE_CONTROL_CHARACTERS
},
100 { UPH_IS_SPELL_UPPER_CASE
, UPN_IS_SPELL_UPPER_CASE
},
101 { UPH_IS_SPELL_WITH_DIGITS
, UPN_IS_SPELL_WITH_DIGITS
},
102 { UPH_IS_SPELL_CAPITALIZATION
, UPN_IS_SPELL_CAPITALIZATION
},
103 { UPH_HYPH_MIN_LEADING
, UPN_HYPH_MIN_LEADING
},
104 { UPH_HYPH_MIN_TRAILING
, UPN_HYPH_MIN_TRAILING
},
105 { UPH_HYPH_MIN_WORD_LENGTH
, UPN_HYPH_MIN_WORD_LENGTH
},
106 { UPH_DEFAULT_LOCALE
, UPN_DEFAULT_LOCALE
},
107 { UPH_IS_SPELL_AUTO
, UPN_IS_SPELL_AUTO
},
110 { UPH_IS_SPELL_SPECIAL
, UPN_IS_SPELL_SPECIAL
},
111 { UPH_IS_HYPH_AUTO
, UPN_IS_HYPH_AUTO
},
112 { UPH_IS_HYPH_SPECIAL
, UPN_IS_HYPH_SPECIAL
},
113 { UPH_IS_WRAP_REVERSE
, UPN_IS_WRAP_REVERSE
},
118 { UPH_DEFAULT_LANGUAGE
, UPN_DEFAULT_LANGUAGE
},
119 { UPH_DEFAULT_LOCALE_CJK
, UPN_DEFAULT_LOCALE_CJK
},
120 { UPH_DEFAULT_LOCALE_CTL
, UPN_DEFAULT_LOCALE_CTL
}
124 OUString
LinguOptions::GetName( sal_Int32 nWID
)
126 MutexGuard
aGuard( GetLinguMutex() );
130 if (0 <= nWID
&& nWID
< sal_Int32(SAL_N_ELEMENTS(aWID_Name
)) && aWID_Name
[ nWID
].nWID
== nWID
)
131 aRes
= OUString::createFromAscii(aWID_Name
[nWID
].pPropertyName
);
133 OSL_FAIL("lng : unknown WID");
139 //! map must be sorted by first entry in alphabetical increasing order.
140 static const SfxItemPropertyMapEntry
* lcl_GetLinguProps()
142 static const SfxItemPropertyMapEntry aLinguProps
[] =
144 { OUString(UPN_DEFAULT_LANGUAGE
), UPH_DEFAULT_LANGUAGE
,
145 ::cppu::UnoType
<sal_Int16
>::get(), 0, 0 },
146 { OUString(UPN_DEFAULT_LOCALE
), UPH_DEFAULT_LOCALE
,
147 ::cppu::UnoType
<Locale
>::get(), 0, 0 },
148 { OUString(UPN_DEFAULT_LOCALE_CJK
), UPH_DEFAULT_LOCALE_CJK
,
149 ::cppu::UnoType
<Locale
>::get(), 0, 0 },
150 { OUString(UPN_DEFAULT_LOCALE_CTL
), UPH_DEFAULT_LOCALE_CTL
,
151 ::cppu::UnoType
<Locale
>::get(), 0, 0 },
152 { OUString(UPN_HYPH_MIN_LEADING
), UPH_HYPH_MIN_LEADING
,
153 ::cppu::UnoType
<sal_Int16
>::get(), 0, 0 },
154 { OUString(UPN_HYPH_MIN_TRAILING
), UPH_HYPH_MIN_TRAILING
,
155 ::cppu::UnoType
<sal_Int16
>::get(), 0, 0 },
156 { OUString(UPN_HYPH_MIN_WORD_LENGTH
), UPH_HYPH_MIN_WORD_LENGTH
,
157 ::cppu::UnoType
<sal_Int16
>::get(), 0, 0 },
158 { OUString(UPN_IS_GERMAN_PRE_REFORM
), UPH_IS_GERMAN_PRE_REFORM
, /*! deprecated !*/
159 cppu::UnoType
<bool>::get(), 0, 0 },
160 { OUString(UPN_IS_HYPH_AUTO
), UPH_IS_HYPH_AUTO
,
161 cppu::UnoType
<bool>::get(), 0, 0 },
162 { OUString(UPN_IS_HYPH_SPECIAL
), UPH_IS_HYPH_SPECIAL
,
163 cppu::UnoType
<bool>::get(), 0, 0 },
164 { OUString(UPN_IS_IGNORE_CONTROL_CHARACTERS
), UPH_IS_IGNORE_CONTROL_CHARACTERS
,
165 cppu::UnoType
<bool>::get(), 0, 0 },
166 { OUString(UPN_IS_SPELL_AUTO
), UPH_IS_SPELL_AUTO
,
167 cppu::UnoType
<bool>::get(), 0, 0 },
168 { OUString(UPN_IS_SPELL_CAPITALIZATION
), UPH_IS_SPELL_CAPITALIZATION
,
169 cppu::UnoType
<bool>::get(), 0, 0 },
170 { OUString(UPN_IS_SPELL_HIDE
), UPH_IS_SPELL_HIDE
, /*! deprecated !*/
171 cppu::UnoType
<bool>::get(), 0, 0 },
172 { OUString(UPN_IS_SPELL_IN_ALL_LANGUAGES
), UPH_IS_SPELL_IN_ALL_LANGUAGES
, /*! deprecated !*/
173 cppu::UnoType
<bool>::get(), 0, 0 },
174 { OUString(UPN_IS_SPELL_SPECIAL
), UPH_IS_SPELL_SPECIAL
,
175 cppu::UnoType
<bool>::get(), 0, 0 },
176 { OUString(UPN_IS_SPELL_UPPER_CASE
), UPH_IS_SPELL_UPPER_CASE
,
177 cppu::UnoType
<bool>::get(), 0, 0 },
178 { OUString(UPN_IS_SPELL_WITH_DIGITS
), UPH_IS_SPELL_WITH_DIGITS
,
179 cppu::UnoType
<bool>::get(), 0, 0 },
180 { OUString(UPN_IS_USE_DICTIONARY_LIST
), UPH_IS_USE_DICTIONARY_LIST
,
181 cppu::UnoType
<bool>::get(), 0, 0 },
182 { OUString(UPN_IS_WRAP_REVERSE
), UPH_IS_WRAP_REVERSE
,
183 cppu::UnoType
<bool>::get(), 0, 0 },
184 { OUString(), 0, css::uno::Type(), 0, 0 }
188 LinguProps::LinguProps() :
189 aEvtListeners (GetLinguMutex()),
190 aPropListeners (GetLinguMutex()),
191 aPropertyMap(lcl_GetLinguProps())
196 void LinguProps::launchEvent( const PropertyChangeEvent
&rEvt
) const
198 cppu::OInterfaceContainerHelper
*pContainer
=
199 aPropListeners
.getContainer( rEvt
.PropertyHandle
);
202 cppu::OInterfaceIteratorHelper
aIt( *pContainer
);
203 while (aIt
.hasMoreElements())
205 Reference
< XPropertyChangeListener
> xRef( aIt
.next(), UNO_QUERY
);
207 xRef
->propertyChange( rEvt
);
212 /// @throws Exception
213 static Reference
< XInterface
> LinguProps_CreateInstance(
214 const Reference
< XMultiServiceFactory
> & /*rSMgr*/ )
216 Reference
< XInterface
> xService
= static_cast<cppu::OWeakObject
*>(new LinguProps
);
220 Reference
< XPropertySetInfo
> SAL_CALL
LinguProps::getPropertySetInfo()
222 MutexGuard
aGuard( GetLinguMutex() );
224 static Reference
< XPropertySetInfo
> aRef
=
225 new SfxItemPropertySetInfo( aPropertyMap
);
229 void SAL_CALL
LinguProps::setPropertyValue(
230 const OUString
& rPropertyName
, const Any
& rValue
)
232 MutexGuard
aGuard( GetLinguMutex() );
234 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
237 Any
aOld( aConfig
.GetProperty( pCur
->nWID
) );
238 if (aOld
!= rValue
&& aConfig
.SetProperty( pCur
->nWID
, rValue
))
240 PropertyChangeEvent
aChgEvt( static_cast<XPropertySet
*>(this), rPropertyName
,
241 false, pCur
->nWID
, aOld
, rValue
);
242 launchEvent( aChgEvt
);
247 Any SAL_CALL
LinguProps::getPropertyValue( const OUString
& rPropertyName
)
249 MutexGuard
aGuard( GetLinguMutex() );
253 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
256 aRet
= aConfig
.GetProperty( pCur
->nWID
);
262 void SAL_CALL
LinguProps::addPropertyChangeListener(
263 const OUString
& rPropertyName
,
264 const Reference
< XPropertyChangeListener
>& rxListener
)
266 MutexGuard
aGuard( GetLinguMutex() );
268 if (!bDisposing
&& rxListener
.is())
270 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
272 aPropListeners
.addInterface( pCur
->nWID
, rxListener
);
276 void SAL_CALL
LinguProps::removePropertyChangeListener(
277 const OUString
& rPropertyName
,
278 const Reference
< XPropertyChangeListener
>& rxListener
)
280 MutexGuard
aGuard( GetLinguMutex() );
282 if (!bDisposing
&& rxListener
.is())
284 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
286 aPropListeners
.removeInterface( pCur
->nWID
, rxListener
);
290 void SAL_CALL
LinguProps::addVetoableChangeListener(
291 const OUString
& /*rPropertyName*/,
292 const Reference
< XVetoableChangeListener
>& /*xListener*/ )
296 void SAL_CALL
LinguProps::removeVetoableChangeListener(
297 const OUString
& /*rPropertyName*/,
298 const Reference
< XVetoableChangeListener
>& /*xListener*/ )
303 void SAL_CALL
LinguProps::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
305 MutexGuard
aGuard( GetLinguMutex() );
307 Any
aOld( aConfig
.GetProperty( nHandle
) );
308 if (aOld
!= rValue
&& aConfig
.SetProperty( nHandle
, rValue
))
310 PropertyChangeEvent
aChgEvt( static_cast<XPropertySet
*>(this),
311 LinguOptions::GetName( nHandle
), false, nHandle
, aOld
, rValue
);
312 launchEvent( aChgEvt
);
317 Any SAL_CALL
LinguProps::getFastPropertyValue( sal_Int32 nHandle
)
319 MutexGuard
aGuard( GetLinguMutex() );
321 Any
aRes( aConfig
.GetProperty( nHandle
) );
326 Sequence
< PropertyValue
> SAL_CALL
327 LinguProps::getPropertyValues()
329 MutexGuard
aGuard( GetLinguMutex() );
331 sal_Int32 nLen
= aPropertyMap
.getSize();
332 Sequence
< PropertyValue
> aProps( nLen
);
333 PropertyValue
*pProp
= aProps
.getArray();
334 PropertyEntryVector_t aPropEntries
= aPropertyMap
.getPropertyEntries();
335 PropertyEntryVector_t::const_iterator aIt
= aPropEntries
.begin();
336 for (sal_Int32 i
= 0; i
< nLen
; ++i
, ++aIt
)
338 PropertyValue
&rVal
= pProp
[i
];
339 Any
aAny( aConfig
.GetProperty( aIt
->nWID
) );
341 rVal
.Name
= aIt
->sName
;
342 rVal
.Handle
= aIt
->nWID
;
344 rVal
.State
= PropertyState_DIRECT_VALUE
;
350 LinguProps::setPropertyValues( const Sequence
< PropertyValue
>& rProps
)
352 MutexGuard
aGuard( GetLinguMutex() );
354 sal_Int32 nLen
= rProps
.getLength();
355 const PropertyValue
*pVal
= rProps
.getConstArray();
356 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
358 const PropertyValue
&rVal
= pVal
[i
];
359 setPropertyValue( rVal
.Name
, rVal
.Value
);
364 LinguProps::dispose()
366 MutexGuard
aGuard( GetLinguMutex() );
372 //! it's too late to save the options here!
373 // (see AppExitListener for saving)
374 //aOpt.Save(); // save (possible) changes before exiting
376 EventObject
aEvtObj( static_cast<XPropertySet
*>(this) );
377 aEvtListeners
.disposeAndClear( aEvtObj
);
378 aPropListeners
.disposeAndClear( aEvtObj
);
383 LinguProps::addEventListener( const Reference
< XEventListener
>& rxListener
)
385 MutexGuard
aGuard( GetLinguMutex() );
387 if (!bDisposing
&& rxListener
.is())
388 aEvtListeners
.addInterface( rxListener
);
392 LinguProps::removeEventListener( const Reference
< XEventListener
>& rxListener
)
394 MutexGuard
aGuard( GetLinguMutex() );
396 if (!bDisposing
&& rxListener
.is())
397 aEvtListeners
.removeInterface( rxListener
);
401 // Service specific part
404 OUString SAL_CALL
LinguProps::getImplementationName()
406 return getImplementationName_Static();
410 sal_Bool SAL_CALL
LinguProps::supportsService( const OUString
& ServiceName
)
412 return cppu::supportsService(this, ServiceName
);
416 uno::Sequence
< OUString
> SAL_CALL
LinguProps::getSupportedServiceNames()
418 return getSupportedServiceNames_Static();
421 // ORegistryServiceManager_Static
422 uno::Sequence
< OUString
> LinguProps::getSupportedServiceNames_Static()
425 uno::Sequence
< OUString
> aSNS
{ "com.sun.star.linguistic2.LinguProperties" };
429 bool LinguProps::getPropertyBool(const OUString
& aPropertyName
)
431 uno::Any any
= getPropertyValue(aPropertyName
);
437 sal_Int16
LinguProps::getPropertyInt16(const OUString
& aPropertyName
)
439 uno::Any any
= getPropertyValue(aPropertyName
);
445 Locale
LinguProps::getPropertyLocale(const OUString
& aPropertyName
)
447 uno::Any any
= getPropertyValue(aPropertyName
);
453 void * LinguProps_getFactory( const sal_Char
* pImplName
,
454 XMultiServiceFactory
*pServiceManager
)
456 void * pRet
= nullptr;
457 if ( LinguProps::getImplementationName_Static().equalsAscii( pImplName
) )
459 Reference
< XSingleServiceFactory
> xFactory
=
460 cppu::createOneInstanceFactory(
462 LinguProps::getImplementationName_Static(),
463 LinguProps_CreateInstance
,
464 LinguProps::getSupportedServiceNames_Static());
465 // acquire, because we return an interface pointer instead of a reference
467 pRet
= xFactory
.get();
473 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */