xref: /aoo41x/main/vcl/source/app/i18nhelp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include "unotools/localedatawrapper.hxx"
32 #include "unotools/transliterationwrapper.hxx"
33 
34 #include "i18npool/mslangid.hxx"
35 
36 #include "rtl/ustrbuf.hxx"
37 
38 #include "vcl/i18nhelp.hxx"
39 
40 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
41 #include "com/sun/star/i18n/TransliterationModules.hpp"
42 
43 using namespace ::com::sun::star;
44 
45 vcl::I18nHelper::I18nHelper(  ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF, const ::com::sun::star::lang::Locale& rLocale )
46 {
47     mxMSF = rxMSF;
48     maLocale = rLocale;
49     mpLocaleDataWrapper = NULL;
50     mpTransliterationWrapper= NULL;
51     mbTransliterateIgnoreCase = sal_False;
52 }
53 
54 vcl::I18nHelper::~I18nHelper()
55 {
56     ImplDestroyWrappers();
57 }
58 
59 void vcl::I18nHelper::ImplDestroyWrappers()
60 {
61     delete mpLocaleDataWrapper;
62     mpLocaleDataWrapper = NULL;
63 
64     delete mpTransliterationWrapper;
65     mpTransliterationWrapper= NULL;
66 }
67 
68 utl::TransliterationWrapper& vcl::I18nHelper::ImplGetTransliterationWrapper() const
69 {
70     if ( !mpTransliterationWrapper )
71     {
72         sal_Int32 nModules = i18n::TransliterationModules_IGNORE_WIDTH;
73         if ( mbTransliterateIgnoreCase )
74             nModules |= i18n::TransliterationModules_IGNORE_CASE;
75 
76         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = new utl::TransliterationWrapper( mxMSF, (i18n::TransliterationModules)nModules );
77         ((vcl::I18nHelper*)this)->mpTransliterationWrapper->loadModuleIfNeeded( MsLangId::convertLocaleToLanguage( maLocale ) );
78     }
79     return *mpTransliterationWrapper;
80 }
81 
82 LocaleDataWrapper& vcl::I18nHelper::ImplGetLocaleDataWrapper() const
83 {
84     if ( !mpLocaleDataWrapper )
85     {
86         ((vcl::I18nHelper*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( mxMSF, maLocale );
87     }
88     return *mpLocaleDataWrapper;
89 }
90 
91 const ::com::sun::star::lang::Locale& vcl::I18nHelper::getLocale() const
92 {
93     return maLocale;
94 }
95 
96 inline bool is_formatting_mark( sal_Unicode c )
97 {
98 	if( (c >= 0x200B) && (c <= 0x200F) )	// BiDi and zero-width-markers
99 		return true;
100 	if( (c >= 0x2028) && (c <= 0x202E) )	// BiDi and paragraph-markers
101 		return true;
102 	return false;
103 }
104 
105 /* #i100057# filter formatting marks out of strings before passing them to
106    the transliteration. The real solution would have been an additional TransliterationModule
107    to ignore these marks during transliteration; however changin the code in i18npool that actually
108    implements this could produce unwanted side effects.
109 
110    Of course this copying around is not really good, but looking at i18npool, one more time
111    will not hurt.
112 */
113 String vcl::I18nHelper::filterFormattingChars( const String& rStr )
114 {
115     sal_Int32 nUnicodes = rStr.Len();
116     rtl::OUStringBuffer aBuf( nUnicodes );
117     const sal_Unicode* pStr = rStr.GetBuffer();
118     while( nUnicodes-- )
119     {
120         if( ! is_formatting_mark( *pStr ) )
121             aBuf.append( *pStr );
122         pStr++;
123     }
124     return aBuf.makeStringAndClear();
125 }
126 
127 sal_Int32 vcl::I18nHelper::CompareString( const String& rStr1, const String& rStr2 ) const
128 {
129 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
130 
131     if ( mbTransliterateIgnoreCase )
132     {
133         // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
134         // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
135         ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = sal_False;
136         delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
137         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
138     }
139 
140 
141     String aStr1( filterFormattingChars(rStr1) );
142     String aStr2( filterFormattingChars(rStr2) );
143     return ImplGetTransliterationWrapper().compareString( aStr1, aStr2 );
144 }
145 
146 sal_Bool vcl::I18nHelper::MatchString( const String& rStr1, const String& rStr2 ) const
147 {
148 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
149 
150     if ( !mbTransliterateIgnoreCase )
151     {
152         // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
153         // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
154         ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = sal_True;
155         delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
156         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
157     }
158 
159     String aStr1( filterFormattingChars(rStr1) );
160     String aStr2( filterFormattingChars(rStr2) );
161     return ImplGetTransliterationWrapper().isMatch( aStr1, aStr2 );
162 }
163 
164 sal_Bool vcl::I18nHelper::MatchMnemonic( const String& rString, sal_Unicode cMnemonicChar ) const
165 {
166 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
167 
168     sal_Bool bEqual = sal_False;
169     sal_uInt16 n = rString.Search( '~' );
170     if ( n != STRING_NOTFOUND )
171     {
172         String aMatchStr( rString, n+1, STRING_LEN );   // not only one char, because of transliteration...
173         bEqual = MatchString( cMnemonicChar, aMatchStr );
174     }
175     return bEqual;
176 }
177 
178 
179 String vcl::I18nHelper::GetDate( const Date& rDate ) const
180 {
181 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
182 
183     return ImplGetLocaleDataWrapper().getDate( rDate );
184 }
185 
186 String vcl::I18nHelper::GetNum( long nNumber, sal_uInt16 nDecimals, sal_Bool bUseThousandSep, sal_Bool bTrailingZeros ) const
187 {
188     return ImplGetLocaleDataWrapper().getNum( nNumber, nDecimals, bUseThousandSep, bTrailingZeros );
189 }
190