xref: /trunk/main/vcl/source/app/i18nhelp.cxx (revision 9f62ea84)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include "unotools/localedatawrapper.hxx"
28 #include "unotools/transliterationwrapper.hxx"
29 
30 #include "i18npool/mslangid.hxx"
31 
32 #include "rtl/ustrbuf.hxx"
33 
34 #include "vcl/i18nhelp.hxx"
35 
36 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
37 #include "com/sun/star/i18n/TransliterationModules.hpp"
38 
39 using namespace ::com::sun::star;
40 
I18nHelper(::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rxMSF,const::com::sun::star::lang::Locale & rLocale)41 vcl::I18nHelper::I18nHelper(  ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF, const ::com::sun::star::lang::Locale& rLocale )
42 {
43     mxMSF = rxMSF;
44     maLocale = rLocale;
45     mpLocaleDataWrapper = NULL;
46     mpTransliterationWrapper= NULL;
47     mbTransliterateIgnoreCase = sal_False;
48 }
49 
~I18nHelper()50 vcl::I18nHelper::~I18nHelper()
51 {
52     ImplDestroyWrappers();
53 }
54 
ImplDestroyWrappers()55 void vcl::I18nHelper::ImplDestroyWrappers()
56 {
57     delete mpLocaleDataWrapper;
58     mpLocaleDataWrapper = NULL;
59 
60     delete mpTransliterationWrapper;
61     mpTransliterationWrapper= NULL;
62 }
63 
ImplGetTransliterationWrapper() const64 utl::TransliterationWrapper& vcl::I18nHelper::ImplGetTransliterationWrapper() const
65 {
66     if ( !mpTransliterationWrapper )
67     {
68         sal_Int32 nModules = i18n::TransliterationModules_IGNORE_WIDTH;
69         if ( mbTransliterateIgnoreCase )
70             nModules |= i18n::TransliterationModules_IGNORE_CASE;
71 
72         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = new utl::TransliterationWrapper( mxMSF, (i18n::TransliterationModules)nModules );
73         ((vcl::I18nHelper*)this)->mpTransliterationWrapper->loadModuleIfNeeded( MsLangId::convertLocaleToLanguage( maLocale ) );
74     }
75     return *mpTransliterationWrapper;
76 }
77 
ImplGetLocaleDataWrapper() const78 LocaleDataWrapper& vcl::I18nHelper::ImplGetLocaleDataWrapper() const
79 {
80     if ( !mpLocaleDataWrapper )
81     {
82         ((vcl::I18nHelper*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( mxMSF, maLocale );
83     }
84     return *mpLocaleDataWrapper;
85 }
86 
getLocale() const87 const ::com::sun::star::lang::Locale& vcl::I18nHelper::getLocale() const
88 {
89     return maLocale;
90 }
91 
is_formatting_mark(sal_Unicode c)92 inline bool is_formatting_mark( sal_Unicode c )
93 {
94 	if( (c >= 0x200B) && (c <= 0x200F) )	// BiDi and zero-width-markers
95 		return true;
96 	if( (c >= 0x2028) && (c <= 0x202E) )	// BiDi and paragraph-markers
97 		return true;
98 	return false;
99 }
100 
101 /* #i100057# filter formatting marks out of strings before passing them to
102    the transliteration. The real solution would have been an additional TransliterationModule
103    to ignore these marks during transliteration; however changin the code in i18npool that actually
104    implements this could produce unwanted side effects.
105 
106    Of course this copying around is not really good, but looking at i18npool, one more time
107    will not hurt.
108 */
filterFormattingChars(const String & rStr)109 String vcl::I18nHelper::filterFormattingChars( const String& rStr )
110 {
111     sal_Int32 nUnicodes = rStr.Len();
112     rtl::OUStringBuffer aBuf( nUnicodes );
113     const sal_Unicode* pStr = rStr.GetBuffer();
114     while( nUnicodes-- )
115     {
116         if( ! is_formatting_mark( *pStr ) )
117             aBuf.append( *pStr );
118         pStr++;
119     }
120     return aBuf.makeStringAndClear();
121 }
122 
CompareString(const String & rStr1,const String & rStr2) const123 sal_Int32 vcl::I18nHelper::CompareString( const String& rStr1, const String& rStr2 ) const
124 {
125 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
126 
127     if ( mbTransliterateIgnoreCase )
128     {
129         // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
130         // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
131         ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = sal_False;
132         delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
133         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
134     }
135 
136 
137     String aStr1( filterFormattingChars(rStr1) );
138     String aStr2( filterFormattingChars(rStr2) );
139     return ImplGetTransliterationWrapper().compareString( aStr1, aStr2 );
140 }
141 
MatchString(const String & rStr1,const String & rStr2) const142 sal_Bool vcl::I18nHelper::MatchString( const String& rStr1, const String& rStr2 ) const
143 {
144 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
145 
146     if ( !mbTransliterateIgnoreCase )
147     {
148         // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
149         // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
150         ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = sal_True;
151         delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
152         ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
153     }
154 
155     String aStr1( filterFormattingChars(rStr1) );
156     String aStr2( filterFormattingChars(rStr2) );
157     return ImplGetTransliterationWrapper().isMatch( aStr1, aStr2 );
158 }
159 
MatchMnemonic(const String & rString,sal_Unicode cMnemonicChar) const160 sal_Bool vcl::I18nHelper::MatchMnemonic( const String& rString, sal_Unicode cMnemonicChar ) const
161 {
162 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
163 
164     sal_Bool bEqual = sal_False;
165     sal_uInt16 n = rString.Search( '~' );
166     if ( n != STRING_NOTFOUND )
167     {
168         String aMatchStr( rString, n+1, STRING_LEN );   // not only one char, because of transliteration...
169         bEqual = MatchString( cMnemonicChar, aMatchStr );
170     }
171     return bEqual;
172 }
173 
174 
GetDate(const Date & rDate) const175 String vcl::I18nHelper::GetDate( const Date& rDate ) const
176 {
177 	::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );
178 
179     return ImplGetLocaleDataWrapper().getDate( rDate );
180 }
181 
GetNum(long nNumber,sal_uInt16 nDecimals,sal_Bool bUseThousandSep,sal_Bool bTrailingZeros) const182 String vcl::I18nHelper::GetNum( long nNumber, sal_uInt16 nDecimals, sal_Bool bUseThousandSep, sal_Bool bTrailingZeros ) const
183 {
184     return ImplGetLocaleDataWrapper().getNum( nNumber, nDecimals, bUseThousandSep, bTrailingZeros );
185 }
186