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