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 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 50 vcl::I18nHelper::~I18nHelper() 51 { 52 ImplDestroyWrappers(); 53 } 54 55 void vcl::I18nHelper::ImplDestroyWrappers() 56 { 57 delete mpLocaleDataWrapper; 58 mpLocaleDataWrapper = NULL; 59 60 delete mpTransliterationWrapper; 61 mpTransliterationWrapper= NULL; 62 } 63 64 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 78 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 87 const ::com::sun::star::lang::Locale& vcl::I18nHelper::getLocale() const 88 { 89 return maLocale; 90 } 91 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 */ 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 123 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 142 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 160 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 175 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 182 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