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>
23 #include "linguistic/lngprops.hxx"
24 #include "linguistic/misc.hxx"
25 #include <tools/debug.hxx>
26 #include <unotools/lingucfg.hxx>
28 #include <uno/lbnames.h> // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
29 #include <cppuhelper/implbase1.hxx> // helper for implementations
31 #include <cppuhelper/factory.hxx> // helper for factories
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/registry/XSimpleRegistry.hpp>
34 #include <com/sun/star/registry/XRegistryKey.hpp>
35 #include <com/sun/star/lang/Locale.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
;
54 // static member intialization
55 SvtLinguOptions
* LinguOptions::pData
= NULL
;
56 oslInterlockedCount
LinguOptions::nRefCount
;
59 LinguOptions::LinguOptions()
63 pData
= new SvtLinguOptions
;
64 SvtLinguConfig aLinguCfg
;
65 aLinguCfg
.GetOptions( *pData
);
68 osl_atomic_increment( &nRefCount
);
72 LinguOptions::LinguOptions(const LinguOptions
& /*rOpt*/)
74 DBG_ASSERT( pData
, "lng : data missing" );
75 osl_atomic_increment( &nRefCount
);
79 LinguOptions::~LinguOptions()
81 MutexGuard
aGuard( GetLinguMutex() );
83 if ( osl_atomic_decrement( &nRefCount
) == 0 )
85 delete pData
; pData
= NULL
;
92 const char *pPropertyName
;
95 //! order of entries is import (see LinguOptions::GetName)
96 //! since the WID is used as index in this table!
97 WID_Name aWID_Name
[] =
100 { WID_IS_USE_DICTIONARY_LIST
, UPN_IS_USE_DICTIONARY_LIST
},
101 { WID_IS_IGNORE_CONTROL_CHARACTERS
, UPN_IS_IGNORE_CONTROL_CHARACTERS
},
102 { WID_IS_SPELL_UPPER_CASE
, UPN_IS_SPELL_UPPER_CASE
},
103 { WID_IS_SPELL_WITH_DIGITS
, UPN_IS_SPELL_WITH_DIGITS
},
104 { WID_IS_SPELL_CAPITALIZATION
, UPN_IS_SPELL_CAPITALIZATION
},
105 { WID_HYPH_MIN_LEADING
, UPN_HYPH_MIN_LEADING
},
106 { WID_HYPH_MIN_TRAILING
, UPN_HYPH_MIN_TRAILING
},
107 { WID_HYPH_MIN_WORD_LENGTH
, UPN_HYPH_MIN_WORD_LENGTH
},
108 { WID_DEFAULT_LOCALE
, UPN_DEFAULT_LOCALE
},
109 { WID_IS_SPELL_AUTO
, UPN_IS_SPELL_AUTO
},
112 { WID_IS_SPELL_SPECIAL
, UPN_IS_SPELL_SPECIAL
},
113 { WID_IS_HYPH_AUTO
, UPN_IS_HYPH_AUTO
},
114 { WID_IS_HYPH_SPECIAL
, UPN_IS_HYPH_SPECIAL
},
115 { WID_IS_WRAP_REVERSE
, UPN_IS_WRAP_REVERSE
},
120 { WID_DEFAULT_LANGUAGE
, UPN_DEFAULT_LANGUAGE
},
121 { WID_DEFAULT_LOCALE_CJK
, UPN_DEFAULT_LOCALE_CJK
},
122 { WID_DEFAULT_LOCALE_CTL
, UPN_DEFAULT_LOCALE_CTL
}
126 OUString
LinguOptions::GetName( sal_Int32 nWID
)
128 MutexGuard
aGuard( GetLinguMutex() );
132 sal_Int32 nLen
= sizeof (aWID_Name
) / sizeof (aWID_Name
[0]);
133 if (0 <= nWID
&& nWID
< nLen
&& aWID_Name
[ nWID
].nWID
== nWID
)
134 aRes
= OUString::createFromAscii(aWID_Name
[nWID
].pPropertyName
);
136 OSL_FAIL("lng : unknown WID");
143 //! map must be sorted by first entry in alphabetical increasing order.
144 static const SfxItemPropertyMapEntry
* lcl_GetLinguProps()
146 static const SfxItemPropertyMapEntry aLinguProps
[] =
148 { MAP_CHAR_LEN(UPN_DEFAULT_LANGUAGE
), WID_DEFAULT_LANGUAGE
,
149 &::getCppuType( (sal_Int16
*)0 ), 0, 0 },
150 { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE
), WID_DEFAULT_LOCALE
,
151 &::getCppuType( (Locale
* )0), 0, 0 },
152 { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CJK
), WID_DEFAULT_LOCALE_CJK
,
153 &::getCppuType( (Locale
* )0), 0, 0 },
154 { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CTL
), WID_DEFAULT_LOCALE_CTL
,
155 &::getCppuType( (Locale
* )0), 0, 0 },
156 { MAP_CHAR_LEN(UPN_HYPH_MIN_LEADING
), WID_HYPH_MIN_LEADING
,
157 &::getCppuType( (sal_Int16
*)0 ), 0, 0 },
158 { MAP_CHAR_LEN(UPN_HYPH_MIN_TRAILING
), WID_HYPH_MIN_TRAILING
,
159 &::getCppuType( (sal_Int16
*)0 ), 0, 0 },
160 { MAP_CHAR_LEN(UPN_HYPH_MIN_WORD_LENGTH
), WID_HYPH_MIN_WORD_LENGTH
,
161 &::getCppuType( (sal_Int16
*)0 ), 0, 0 },
162 { MAP_CHAR_LEN(UPN_IS_GERMAN_PRE_REFORM
), WID_IS_GERMAN_PRE_REFORM
, /*! deprecated !*/
163 &::getBooleanCppuType(), 0, 0 },
164 { MAP_CHAR_LEN(UPN_IS_HYPH_AUTO
), WID_IS_HYPH_AUTO
,
165 &::getBooleanCppuType(), 0, 0 },
166 { MAP_CHAR_LEN(UPN_IS_HYPH_SPECIAL
), WID_IS_HYPH_SPECIAL
,
167 &::getBooleanCppuType(), 0, 0 },
168 { MAP_CHAR_LEN(UPN_IS_IGNORE_CONTROL_CHARACTERS
), WID_IS_IGNORE_CONTROL_CHARACTERS
,
169 &::getBooleanCppuType(), 0, 0 },
170 { MAP_CHAR_LEN(UPN_IS_SPELL_AUTO
), WID_IS_SPELL_AUTO
,
171 &::getBooleanCppuType(), 0, 0 },
172 { MAP_CHAR_LEN(UPN_IS_SPELL_CAPITALIZATION
), WID_IS_SPELL_CAPITALIZATION
,
173 &::getBooleanCppuType(), 0, 0 },
174 { MAP_CHAR_LEN(UPN_IS_SPELL_HIDE
), WID_IS_SPELL_HIDE
, /*! deprecated !*/
175 &::getBooleanCppuType(), 0, 0 },
176 { MAP_CHAR_LEN(UPN_IS_SPELL_IN_ALL_LANGUAGES
), WID_IS_SPELL_IN_ALL_LANGUAGES
, /*! deprecated !*/
177 &::getBooleanCppuType(), 0, 0 },
178 { MAP_CHAR_LEN(UPN_IS_SPELL_SPECIAL
), WID_IS_SPELL_SPECIAL
,
179 &::getBooleanCppuType(), 0, 0 },
180 { MAP_CHAR_LEN(UPN_IS_SPELL_UPPER_CASE
), WID_IS_SPELL_UPPER_CASE
,
181 &::getBooleanCppuType(), 0, 0 },
182 { MAP_CHAR_LEN(UPN_IS_SPELL_WITH_DIGITS
), WID_IS_SPELL_WITH_DIGITS
,
183 &::getBooleanCppuType(), 0, 0 },
184 { MAP_CHAR_LEN(UPN_IS_USE_DICTIONARY_LIST
), WID_IS_USE_DICTIONARY_LIST
,
185 &::getBooleanCppuType(), 0, 0 },
186 { MAP_CHAR_LEN(UPN_IS_WRAP_REVERSE
), WID_IS_WRAP_REVERSE
,
187 &::getBooleanCppuType(), 0, 0 },
192 LinguProps::LinguProps() :
193 aEvtListeners (GetLinguMutex()),
194 aPropListeners (GetLinguMutex()),
195 aPropertyMap(lcl_GetLinguProps())
197 bDisposing
= sal_False
;
200 void LinguProps::launchEvent( const PropertyChangeEvent
&rEvt
) const
202 cppu::OInterfaceContainerHelper
*pContainer
=
203 aPropListeners
.getContainer( rEvt
.PropertyHandle
);
206 cppu::OInterfaceIteratorHelper
aIt( *pContainer
);
207 while (aIt
.hasMoreElements())
209 Reference
< XPropertyChangeListener
> xRef( aIt
.next(), UNO_QUERY
);
211 xRef
->propertyChange( rEvt
);
216 Reference
< XInterface
> SAL_CALL
LinguProps_CreateInstance(
217 const Reference
< XMultiServiceFactory
> & /*rSMgr*/ )
220 Reference
< XInterface
> xService
= (cppu::OWeakObject
*)new LinguProps
;
224 Reference
< XPropertySetInfo
> SAL_CALL
LinguProps::getPropertySetInfo()
225 throw(RuntimeException
)
227 MutexGuard
aGuard( GetLinguMutex() );
229 static Reference
< XPropertySetInfo
> aRef
=
230 new SfxItemPropertySetInfo( aPropertyMap
);
234 void SAL_CALL
LinguProps::setPropertyValue(
235 const OUString
& rPropertyName
, const Any
& rValue
)
236 throw(UnknownPropertyException
, PropertyVetoException
,
237 IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
239 MutexGuard
aGuard( GetLinguMutex() );
241 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
244 Any
aOld( aConfig
.GetProperty( pCur
->nWID
) );
245 if (aOld
!= rValue
&& aConfig
.SetProperty( pCur
->nWID
, rValue
))
247 PropertyChangeEvent
aChgEvt( (XPropertySet
*) this, rPropertyName
,
248 sal_False
, pCur
->nWID
, aOld
, rValue
);
249 launchEvent( aChgEvt
);
254 Any SAL_CALL
LinguProps::getPropertyValue( const OUString
& rPropertyName
)
255 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
257 MutexGuard
aGuard( GetLinguMutex() );
261 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
264 aRet
= aConfig
.GetProperty( pCur
->nWID
);
270 void SAL_CALL
LinguProps::addPropertyChangeListener(
271 const OUString
& rPropertyName
,
272 const Reference
< XPropertyChangeListener
>& rxListener
)
273 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
275 MutexGuard
aGuard( GetLinguMutex() );
277 if (!bDisposing
&& rxListener
.is())
279 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
281 aPropListeners
.addInterface( pCur
->nWID
, rxListener
);
285 void SAL_CALL
LinguProps::removePropertyChangeListener(
286 const OUString
& rPropertyName
,
287 const Reference
< XPropertyChangeListener
>& rxListener
)
288 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
290 MutexGuard
aGuard( GetLinguMutex() );
292 if (!bDisposing
&& rxListener
.is())
294 const SfxItemPropertySimpleEntry
* pCur
= aPropertyMap
.getByName( rPropertyName
);
296 aPropListeners
.removeInterface( pCur
->nWID
, rxListener
);
300 void SAL_CALL
LinguProps::addVetoableChangeListener(
301 const OUString
& /*rPropertyName*/,
302 const Reference
< XVetoableChangeListener
>& /*xListener*/ )
303 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
307 void SAL_CALL
LinguProps::removeVetoableChangeListener(
308 const OUString
& /*rPropertyName*/,
309 const Reference
< XVetoableChangeListener
>& /*xListener*/ )
310 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
315 void SAL_CALL
LinguProps::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
316 throw(UnknownPropertyException
, PropertyVetoException
,
317 IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
319 MutexGuard
aGuard( GetLinguMutex() );
321 Any
aOld( aConfig
.GetProperty( nHandle
) );
322 if (aOld
!= rValue
&& aConfig
.SetProperty( nHandle
, rValue
))
324 PropertyChangeEvent
aChgEvt( (XPropertySet
*) this,
325 LinguOptions::GetName( nHandle
), sal_False
, nHandle
, aOld
, rValue
);
326 launchEvent( aChgEvt
);
331 Any SAL_CALL
LinguProps::getFastPropertyValue( sal_Int32 nHandle
)
332 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
334 MutexGuard
aGuard( GetLinguMutex() );
336 Any
aRes( aConfig
.GetProperty( nHandle
) );
341 Sequence
< PropertyValue
> SAL_CALL
342 LinguProps::getPropertyValues()
343 throw(RuntimeException
)
345 MutexGuard
aGuard( GetLinguMutex() );
347 sal_Int32 nLen
= aPropertyMap
.getSize();
348 Sequence
< PropertyValue
> aProps( nLen
);
349 PropertyValue
*pProp
= aProps
.getArray();
350 PropertyEntryVector_t aPropEntries
= aPropertyMap
.getPropertyEntries();
351 PropertyEntryVector_t::const_iterator aIt
= aPropEntries
.begin();
352 for (sal_Int32 i
= 0; i
< nLen
; ++i
, ++aIt
)
354 PropertyValue
&rVal
= pProp
[i
];
355 Any
aAny( aConfig
.GetProperty( aIt
->nWID
) );
357 rVal
.Name
= aIt
->sName
;
358 rVal
.Handle
= aIt
->nWID
;
360 rVal
.State
= PropertyState_DIRECT_VALUE
;
366 LinguProps::setPropertyValues( const Sequence
< PropertyValue
>& rProps
)
367 throw(UnknownPropertyException
, PropertyVetoException
,
368 IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
370 MutexGuard
aGuard( GetLinguMutex() );
372 sal_Int32 nLen
= rProps
.getLength();
373 const PropertyValue
*pVal
= rProps
.getConstArray();
374 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
376 const PropertyValue
&rVal
= pVal
[i
];
377 setPropertyValue( rVal
.Name
, rVal
.Value
);
382 LinguProps::dispose()
383 throw(RuntimeException
)
385 MutexGuard
aGuard( GetLinguMutex() );
389 bDisposing
= sal_True
;
391 //! its too late to save the options here!
392 // (see AppExitListener for saving)
393 //aOpt.Save(); // save (possible) changes before exiting
395 EventObject
aEvtObj( (XPropertySet
*) this );
396 aEvtListeners
.disposeAndClear( aEvtObj
);
397 aPropListeners
.disposeAndClear( aEvtObj
);
402 LinguProps::addEventListener( const Reference
< XEventListener
>& rxListener
)
403 throw(RuntimeException
)
405 MutexGuard
aGuard( GetLinguMutex() );
407 if (!bDisposing
&& rxListener
.is())
408 aEvtListeners
.addInterface( rxListener
);
412 LinguProps::removeEventListener( const Reference
< XEventListener
>& rxListener
)
413 throw(RuntimeException
)
415 MutexGuard
aGuard( GetLinguMutex() );
417 if (!bDisposing
&& rxListener
.is())
418 aEvtListeners
.removeInterface( rxListener
);
422 // Service specific part
425 OUString SAL_CALL
LinguProps::getImplementationName()
426 throw(RuntimeException
)
428 MutexGuard
aGuard( GetLinguMutex() );
429 return getImplementationName_Static();
433 sal_Bool SAL_CALL
LinguProps::supportsService( const OUString
& ServiceName
)
434 throw(RuntimeException
)
436 MutexGuard
aGuard( GetLinguMutex() );
438 uno::Sequence
< OUString
> aSNL
= getSupportedServiceNames();
439 const OUString
* pArray
= aSNL
.getConstArray();
440 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
441 if( pArray
[i
] == ServiceName
)
447 uno::Sequence
< OUString
> SAL_CALL
LinguProps::getSupportedServiceNames()
448 throw(RuntimeException
)
450 MutexGuard
aGuard( GetLinguMutex() );
451 return getSupportedServiceNames_Static();
454 // ORegistryServiceManager_Static
455 uno::Sequence
< OUString
> LinguProps::getSupportedServiceNames_Static()
458 MutexGuard
aGuard( GetLinguMutex() );
460 uno::Sequence
< OUString
> aSNS( 1 ); // more than 1 service possible
461 aSNS
.getArray()[0] = "com.sun.star.linguistic2.LinguProperties";
465 sal_Bool
LinguProps::getPropertyBool(const OUString
& aPropertyName
) throw (css::uno::RuntimeException
)
467 uno::Any any
= getPropertyValue(aPropertyName
);
468 sal_Bool b
= sal_False
;
473 sal_Int16
LinguProps::getPropertyInt16(const OUString
& aPropertyName
) throw (css::uno::RuntimeException
)
475 uno::Any any
= getPropertyValue(aPropertyName
);
476 sal_Int16 b
= sal_False
;
481 Locale
LinguProps::getPropertyLocale(const OUString
& aPropertyName
) throw (css::uno::RuntimeException
)
483 uno::Any any
= getPropertyValue(aPropertyName
);
489 void * SAL_CALL
LinguProps_getFactory( const sal_Char
* pImplName
,
490 XMultiServiceFactory
*pServiceManager
, void * )
493 if ( !LinguProps::getImplementationName_Static().compareToAscii( pImplName
) )
495 Reference
< XSingleServiceFactory
> xFactory
=
496 cppu::createOneInstanceFactory(
498 LinguProps::getImplementationName_Static(),
499 LinguProps_CreateInstance
,
500 LinguProps::getSupportedServiceNames_Static());
501 // acquire, because we return an interface pointer instead of a reference
503 pRet
= xFactory
.get();
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */