1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: syslocaleoptions.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #ifdef SVL_DLLIMPLEMENTATION
35 #undef SVL_DLLIMPLEMENTATION
37 #define SVT_DLLIMPLEMENTATION
39 #include <svtools/syslocaleoptions.hxx>
40 #include <broadcast.hxx>
41 #include <listener.hxx>
42 #include <svtools/smplhint.hxx>
43 #include <i18npool/mslangid.hxx>
44 #include <tools/string.hxx>
45 #include <rtl/ustrbuf.hxx>
46 #include <rtl/instance.hxx>
47 #include <unotools/configmgr.hxx>
48 #include <unotools/configitem.hxx>
49 #include <tools/debug.hxx>
50 #include <com/sun/star/uno/Any.hxx>
51 #include <com/sun/star/uno/Sequence.hxx>
52 #include <vcl/settings.hxx>
53 #include <vcl/svapp.hxx>
55 #include <rtl/logfile.hxx>
57 #include "itemholder2.hxx"
60 #define CFG_READONLY_DEFAULT sal_False
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::lang
;
69 SvtSysLocaleOptions_Impl
* SvtSysLocaleOptions::pOptions
= NULL
;
70 sal_Int32
SvtSysLocaleOptions::nRefCount
= 0;
73 struct CurrencyChangeLink
74 : public rtl::Static
<Link
, CurrencyChangeLink
> {};
77 class SvtSysLocaleOptions_Impl
: public utl::ConfigItem
79 OUString m_aLocaleString
; // en-US or de-DE or empty for SYSTEM
80 LanguageType m_eLocaleLanguageType
; // same for convenience access
81 OUString m_aCurrencyString
; // USD-en-US or EUR-de-DE
82 SvtBroadcaster m_aBroadcaster
;
83 ULONG m_nBlockedHint
; // pending hints
84 sal_Int32 m_nBroadcastBlocked
; // broadcast only if this is 0
85 sal_Bool m_bDecimalSeparator
; //use decimal separator same as locale
89 sal_Bool m_bROCurrency
;
90 sal_Bool m_bRODecimalSeparator
;
92 static const Sequence
< /* const */ OUString
> GetPropertyNames();
94 void UpdateMiscSettings_Impl();
95 ULONG
ChangeLocaleSettings();
96 void ChangeDefaultCurrency() const;
97 void Broadcast( ULONG nHint
);
100 SvtSysLocaleOptions_Impl();
101 virtual ~SvtSysLocaleOptions_Impl();
103 virtual void Notify( const com::sun::star::uno::Sequence
< rtl::OUString
>& aPropertyNames
);
104 virtual void Commit();
106 const OUString
& GetLocaleString() const
107 { return m_aLocaleString
; }
108 void SetLocaleString( const OUString
& rStr
);
109 LanguageType
GetLocaleLanguageType() const
110 { return m_eLocaleLanguageType
; }
112 const OUString
& GetCurrencyString() const
113 { return m_aCurrencyString
; }
114 void SetCurrencyString( const OUString
& rStr
);
116 sal_Bool
IsDecimalSeparatorAsLocale() const { return m_bDecimalSeparator
;}
117 void SetDecimalSeparatorAsLocale( sal_Bool bSet
);
119 SvtBroadcaster
& GetBroadcaster()
120 { return m_aBroadcaster
; }
121 void BlockBroadcasts( BOOL bBlock
);
122 sal_Bool
IsReadOnly( SvtSysLocaleOptions::EOption eOption
) const;
126 #define ROOTNODE_SYSLOCALE OUString(RTL_CONSTASCII_USTRINGPARAM("Setup/L10N"))
128 #define PROPERTYNAME_LOCALE OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupSystemLocale"))
129 #define PROPERTYNAME_CURRENCY OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupCurrency"))
130 #define PROPERTYNAME_DECIMALSEPARATOR OUString(RTL_CONSTASCII_USTRINGPARAM("DecimalSeparatorAsLocale"))
132 #define PROPERTYHANDLE_LOCALE 0
133 #define PROPERTYHANDLE_CURRENCY 1
134 #define PROPERTYHANDLE_DECIMALSEPARATOR 2
136 #define PROPERTYCOUNT 3
138 const Sequence
< OUString
> SvtSysLocaleOptions_Impl::GetPropertyNames()
140 static const OUString pProperties
[] =
143 PROPERTYNAME_CURRENCY
,
144 PROPERTYNAME_DECIMALSEPARATOR
146 static const Sequence
< OUString
> seqPropertyNames( pProperties
, PROPERTYCOUNT
);
147 return seqPropertyNames
;
151 // -----------------------------------------------------------------------
153 SvtSysLocaleOptions_Impl::SvtSysLocaleOptions_Impl()
154 : ConfigItem( ROOTNODE_SYSLOCALE
)
155 , m_nBlockedHint( 0 )
156 , m_nBroadcastBlocked( 0 )
157 , m_bDecimalSeparator( sal_True
)
158 , m_bROLocale(CFG_READONLY_DEFAULT
)
159 , m_bROCurrency(CFG_READONLY_DEFAULT
)
160 , m_bRODecimalSeparator(sal_False
)
163 if ( !IsValidConfigMgr() )
164 ChangeLocaleSettings(); // assume SYSTEM defaults during Setup
167 const Sequence
< OUString
> aNames
= GetPropertyNames();
168 Sequence
< Any
> aValues
= GetProperties( aNames
);
169 Sequence
< sal_Bool
> aROStates
= GetReadOnlyStates( aNames
);
170 const Any
* pValues
= aValues
.getConstArray();
171 const sal_Bool
* pROStates
= aROStates
.getConstArray();
172 DBG_ASSERT( aValues
.getLength() == aNames
.getLength(), "GetProperties failed" );
173 DBG_ASSERT( aROStates
.getLength() == aNames
.getLength(), "GetReadOnlyStates failed" );
174 if ( aValues
.getLength() == aNames
.getLength() && aROStates
.getLength() == aNames
.getLength() )
176 for ( sal_Int32 nProp
= 0; nProp
< aNames
.getLength(); nProp
++ )
178 DBG_ASSERT( pValues
[nProp
].hasValue(), "property value missing" );
179 if ( pValues
[nProp
].hasValue() )
183 case PROPERTYHANDLE_LOCALE
:
186 if ( pValues
[nProp
] >>= aStr
)
187 m_aLocaleString
= aStr
;
190 DBG_ERRORFILE( "Wrong property type!" );
192 m_bROLocale
= pROStates
[nProp
];
195 case PROPERTYHANDLE_CURRENCY
:
198 if ( pValues
[nProp
] >>= aStr
)
199 m_aCurrencyString
= aStr
;
202 DBG_ERRORFILE( "Wrong property type!" );
204 m_bROCurrency
= pROStates
[nProp
];
207 case PROPERTYHANDLE_DECIMALSEPARATOR
:
209 sal_Bool bValue
= sal_Bool();
210 if ( pValues
[nProp
] >>= bValue
)
211 m_bDecimalSeparator
= bValue
;
214 DBG_ERRORFILE( "Wrong property type!" );
216 m_bRODecimalSeparator
= pROStates
[nProp
];
220 DBG_ERRORFILE( "Wrong property type!" );
225 UpdateMiscSettings_Impl();
226 ChangeLocaleSettings();
227 EnableNotification( aNames
);
232 SvtSysLocaleOptions_Impl::~SvtSysLocaleOptions_Impl()
239 void SvtSysLocaleOptions_Impl::BlockBroadcasts( BOOL bBlock
)
242 ++m_nBroadcastBlocked
;
243 else if ( m_nBroadcastBlocked
)
245 if ( --m_nBroadcastBlocked
== 0 )
250 sal_Bool
SvtSysLocaleOptions_Impl::IsReadOnly( SvtSysLocaleOptions::EOption eOption
) const
252 sal_Bool bReadOnly
= CFG_READONLY_DEFAULT
;
255 case SvtSysLocaleOptions::E_LOCALE
:
257 bReadOnly
= m_bROLocale
;
260 case SvtSysLocaleOptions::E_CURRENCY
:
262 bReadOnly
= m_bROCurrency
;
270 void SvtSysLocaleOptions_Impl::Broadcast( ULONG nHint
)
272 if ( m_nBroadcastBlocked
)
273 m_nBlockedHint
|= nHint
;
276 nHint
|= m_nBlockedHint
;
280 if ( nHint
& SYSLOCALEOPTIONS_HINT_CURRENCY
)
281 ChangeDefaultCurrency();
282 SfxSimpleHint
aHint( nHint
);
283 GetBroadcaster().Broadcast( aHint
);
289 void SvtSysLocaleOptions_Impl::Commit()
291 const Sequence
< OUString
> aOrgNames
= GetPropertyNames();
292 sal_Int32 nOrgCount
= aOrgNames
.getLength();
294 Sequence
< OUString
> aNames( nOrgCount
);
295 Sequence
< Any
> aValues( nOrgCount
);
297 OUString
* pNames
= aNames
.getArray();
298 Any
* pValues
= aValues
.getArray();
299 sal_Int32 nRealCount
= 0;
301 for ( sal_Int32 nProp
= 0; nProp
< nOrgCount
; nProp
++ )
305 case PROPERTYHANDLE_LOCALE
:
309 pNames
[nRealCount
] = aOrgNames
[nProp
];
310 pValues
[nRealCount
] <<= m_aLocaleString
;
315 case PROPERTYHANDLE_CURRENCY
:
319 pNames
[nRealCount
] = aOrgNames
[nProp
];
320 pValues
[nRealCount
] <<= m_aCurrencyString
;
325 case PROPERTYHANDLE_DECIMALSEPARATOR
:
326 if( !m_bRODecimalSeparator
)
328 pNames
[nRealCount
] = aOrgNames
[nProp
];
329 pValues
[nRealCount
] <<= m_bDecimalSeparator
;
334 DBG_ERRORFILE( "invalid index to save a path" );
337 aNames
.realloc(nRealCount
);
338 aValues
.realloc(nRealCount
);
339 PutProperties( aNames
, aValues
);
344 void SvtSysLocaleOptions_Impl::SetLocaleString( const OUString
& rStr
)
346 if (!m_bROLocale
&& rStr
!= m_aLocaleString
)
348 m_aLocaleString
= rStr
;
350 ULONG nHint
= SYSLOCALEOPTIONS_HINT_LOCALE
;
351 nHint
|= ChangeLocaleSettings();
357 ULONG
SvtSysLocaleOptions_Impl::ChangeLocaleSettings()
359 // An empty config value denotes SYSTEM locale
360 if ( m_aLocaleString
.getLength() )
361 m_eLocaleLanguageType
= MsLangId::convertIsoStringToLanguage( m_aLocaleString
);
363 m_eLocaleLanguageType
= LANGUAGE_SYSTEM
;
365 // new locale and no fixed currency => locale default currency might change
366 if ( !m_aCurrencyString
.getLength() )
367 nHint
|= SYSLOCALEOPTIONS_HINT_CURRENCY
;
372 void SvtSysLocaleOptions_Impl::SetCurrencyString( const OUString
& rStr
)
374 if (!m_bROCurrency
&& rStr
!= m_aCurrencyString
)
376 m_aCurrencyString
= rStr
;
378 Broadcast( SYSLOCALEOPTIONS_HINT_CURRENCY
);
382 void SvtSysLocaleOptions_Impl::SetDecimalSeparatorAsLocale( sal_Bool bSet
)
384 if(bSet
!= m_bDecimalSeparator
)
386 m_bDecimalSeparator
= bSet
;
388 UpdateMiscSettings_Impl();
393 void SvtSysLocaleOptions_Impl::ChangeDefaultCurrency() const
395 const Link
& rLink
= SvtSysLocaleOptions::GetCurrencyChangeLink();
401 void SvtSysLocaleOptions_Impl::Notify( const Sequence
< rtl::OUString
>& seqPropertyNames
)
404 Sequence
< Any
> seqValues
= GetProperties( seqPropertyNames
);
405 Sequence
< sal_Bool
> seqROStates
= GetReadOnlyStates( seqPropertyNames
);
406 sal_Int32 nCount
= seqPropertyNames
.getLength();
407 for( sal_Int32 nProp
= 0; nProp
< nCount
; ++nProp
)
409 if( seqPropertyNames
[nProp
] == PROPERTYNAME_LOCALE
)
411 DBG_ASSERT( seqValues
[nProp
].getValueTypeClass() == TypeClass_STRING
, "Locale property type" );
412 seqValues
[nProp
] >>= m_aLocaleString
;
413 m_bROLocale
= seqROStates
[nProp
];
414 nHint
|= SYSLOCALEOPTIONS_HINT_LOCALE
;
415 nHint
|= ChangeLocaleSettings();
417 else if( seqPropertyNames
[nProp
] == PROPERTYNAME_CURRENCY
)
419 DBG_ASSERT( seqValues
[nProp
].getValueTypeClass() == TypeClass_STRING
, "Currency property type" );
420 seqValues
[nProp
] >>= m_aCurrencyString
;
421 m_bROCurrency
= seqROStates
[nProp
];
422 nHint
|= SYSLOCALEOPTIONS_HINT_CURRENCY
;
424 else if( seqPropertyNames
[nProp
] == PROPERTYNAME_DECIMALSEPARATOR
)
426 seqValues
[nProp
] >>= m_bDecimalSeparator
;
427 m_bRODecimalSeparator
= seqROStates
[nProp
];
428 UpdateMiscSettings_Impl();
434 /* -----------------10.02.2004 15:25-----------------
436 --------------------------------------------------*/
437 void SvtSysLocaleOptions_Impl::UpdateMiscSettings_Impl()
439 AllSettings
aAllSettings( Application::GetSettings() );
440 MiscSettings aMiscSettings
= aAllSettings
.GetMiscSettings();
441 aMiscSettings
.SetEnableLocalizedDecimalSep(m_bDecimalSeparator
);
442 aAllSettings
.SetMiscSettings( aMiscSettings
);
443 Application::SetSettings( aAllSettings
);
446 // ====================================================================
448 SvtSysLocaleOptions::SvtSysLocaleOptions()
450 MutexGuard
aGuard( GetMutex() );
453 RTL_LOGFILE_CONTEXT(aLog
, "svtools ( ??? ) ::SvtSysLocaleOptions_Impl::ctor()");
454 pOptions
= new SvtSysLocaleOptions_Impl
;
456 ItemHolder2::holdConfigItem(E_SYSLOCALEOPTIONS
);
462 SvtSysLocaleOptions::~SvtSysLocaleOptions()
464 MutexGuard
aGuard( GetMutex() );
474 Mutex
& SvtSysLocaleOptions::GetMutex()
476 static Mutex
* pMutex
= NULL
;
479 MutexGuard
aGuard( Mutex::getGlobalMutex() );
482 // #i77768# Due to a static reference in the toolkit lib
483 // we need a mutex that lives longer than the svtools library.
484 // Otherwise the dtor would use a destructed mutex!!
492 sal_Bool
SvtSysLocaleOptions::IsModified()
494 MutexGuard
aGuard( GetMutex() );
495 return pOptions
->IsModified();
499 void SvtSysLocaleOptions::Commit()
501 MutexGuard
aGuard( GetMutex() );
506 BOOL
SvtSysLocaleOptions::AddListener( SvtListener
& rLst
)
508 MutexGuard
aGuard( GetMutex() );
509 return rLst
.StartListening( pOptions
->GetBroadcaster() );
513 BOOL
SvtSysLocaleOptions::RemoveListener( SvtListener
& rLst
)
515 MutexGuard
aGuard( GetMutex() );
516 return rLst
.EndListening( pOptions
->GetBroadcaster() );
520 void SvtSysLocaleOptions::BlockBroadcasts( BOOL bBlock
)
522 MutexGuard
aGuard( GetMutex() );
523 pOptions
->BlockBroadcasts( bBlock
);
527 const OUString
& SvtSysLocaleOptions::GetLocaleConfigString() const
529 MutexGuard
aGuard( GetMutex() );
530 return pOptions
->GetLocaleString();
534 void SvtSysLocaleOptions::SetLocaleConfigString( const OUString
& rStr
)
536 MutexGuard
aGuard( GetMutex() );
537 pOptions
->SetLocaleString( rStr
);
541 const OUString
& SvtSysLocaleOptions::GetCurrencyConfigString() const
543 MutexGuard
aGuard( GetMutex() );
544 return pOptions
->GetCurrencyString();
548 void SvtSysLocaleOptions::SetCurrencyConfigString( const OUString
& rStr
)
550 MutexGuard
aGuard( GetMutex() );
551 pOptions
->SetCurrencyString( rStr
);
555 LanguageType
SvtSysLocaleOptions::GetLocaleLanguageType() const
557 MutexGuard
aGuard( GetMutex() );
558 return pOptions
->GetLocaleLanguageType();
561 /*-- 11.02.2004 13:31:41---------------------------------------------------
563 -----------------------------------------------------------------------*/
564 sal_Bool
SvtSysLocaleOptions::IsDecimalSeparatorAsLocale() const
566 MutexGuard
aGuard( GetMutex() );
567 return pOptions
->IsDecimalSeparatorAsLocale();
569 /*-- 11.02.2004 13:31:41---------------------------------------------------
571 -----------------------------------------------------------------------*/
572 void SvtSysLocaleOptions::SetDecimalSeparatorAsLocale( sal_Bool bSet
)
574 MutexGuard
aGuard( GetMutex() );
575 pOptions
->SetDecimalSeparatorAsLocale(bSet
);
579 sal_Bool
SvtSysLocaleOptions::IsReadOnly( EOption eOption
) const
581 MutexGuard
aGuard( GetMutex() );
582 return pOptions
->IsReadOnly( eOption
);
586 void SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( String
& rAbbrev
,
587 LanguageType
& eLang
, const ::rtl::OUString
& rConfigString
)
589 sal_Int32 nDelim
= rConfigString
.indexOf( '-' );
592 rAbbrev
= rConfigString
.copy( 0, nDelim
);
593 String
aIsoStr( rConfigString
.copy( nDelim
+1 ) );
594 eLang
= MsLangId::convertIsoStringToLanguage( aIsoStr
);
598 rAbbrev
= rConfigString
;
599 eLang
= (rAbbrev
.Len() ? LANGUAGE_NONE
: LANGUAGE_SYSTEM
);
605 ::rtl::OUString
SvtSysLocaleOptions::CreateCurrencyConfigString(
606 const String
& rAbbrev
, LanguageType eLang
)
608 String
aIsoStr( MsLangId::convertLanguageToIsoString( eLang
) );
611 ::rtl::OUStringBuffer
aStr( rAbbrev
.Len() + 1 + aIsoStr
.Len() );
612 aStr
.append( rAbbrev
.GetBuffer(), rAbbrev
.Len() );
613 aStr
.append( sal_Unicode('-') );
614 aStr
.append( aIsoStr
.GetBuffer(), aIsoStr
.Len() );
615 return aStr
.makeStringAndClear();
623 void SvtSysLocaleOptions::SetCurrencyChangeLink( const Link
& rLink
)
625 MutexGuard
aGuard( GetMutex() );
626 DBG_ASSERT( !CurrencyChangeLink::get().IsSet(), "SvtSysLocaleOptions::SetCurrencyChangeLink: already set" );
627 CurrencyChangeLink::get() = rLink
;
632 const Link
& SvtSysLocaleOptions::GetCurrencyChangeLink()
634 MutexGuard
aGuard( GetMutex() );
635 return CurrencyChangeLink::get();