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