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_i18npool.hxx" 26 27 #include <characterclassificationImpl.hxx> 28 #include <rtl/ustrbuf.hxx> 29 30 using namespace com::sun::star::uno; 31 using namespace com::sun::star::lang; 32 using namespace rtl; 33 34 namespace com { namespace sun { namespace star { namespace i18n { 35 36 CharacterClassificationImpl::CharacterClassificationImpl( 37 const Reference < lang::XMultiServiceFactory >& rxMSF ) : xMSF( rxMSF ) 38 { 39 if (createLocaleSpecificCharacterClassification(OUString::createFromAscii("Unicode"), Locale())) 40 xUCI = cachedItem->xCI; 41 } 42 43 CharacterClassificationImpl::~CharacterClassificationImpl() { 44 // Clear lookuptable 45 for (size_t l = 0; l < lookupTable.size(); l++) 46 delete lookupTable[l]; 47 lookupTable.clear(); 48 } 49 50 51 OUString SAL_CALL 52 CharacterClassificationImpl::toUpper( const OUString& Text, sal_Int32 nPos, 53 sal_Int32 nCount, const Locale& rLocale ) throw(RuntimeException) 54 { 55 return getLocaleSpecificCharacterClassification(rLocale)->toUpper(Text, nPos, nCount, rLocale); 56 } 57 58 OUString SAL_CALL 59 CharacterClassificationImpl::toLower( const OUString& Text, sal_Int32 nPos, 60 sal_Int32 nCount, const Locale& rLocale ) throw(RuntimeException) 61 { 62 return getLocaleSpecificCharacterClassification(rLocale)->toLower(Text, nPos, nCount, rLocale); 63 } 64 65 OUString SAL_CALL 66 CharacterClassificationImpl::toTitle( const OUString& Text, sal_Int32 nPos, 67 sal_Int32 nCount, const Locale& rLocale ) throw(RuntimeException) 68 { 69 return getLocaleSpecificCharacterClassification(rLocale)->toTitle(Text, nPos, nCount, rLocale); 70 } 71 72 sal_Int16 SAL_CALL 73 CharacterClassificationImpl::getType( const OUString& Text, sal_Int32 nPos ) 74 throw(RuntimeException) 75 { 76 if (xUCI.is()) 77 return xUCI->getType(Text, nPos); 78 throw RuntimeException(); 79 } 80 81 sal_Int16 SAL_CALL 82 CharacterClassificationImpl::getCharacterDirection( const OUString& Text, sal_Int32 nPos ) 83 throw(RuntimeException) 84 { 85 if (xUCI.is()) 86 return xUCI->getCharacterDirection(Text, nPos); 87 throw RuntimeException(); 88 } 89 90 sal_Int16 SAL_CALL 91 CharacterClassificationImpl::getScript( const OUString& Text, sal_Int32 nPos ) 92 throw(RuntimeException) 93 { 94 if (xUCI.is()) 95 return xUCI->getScript(Text, nPos); 96 throw RuntimeException(); 97 } 98 99 sal_Int32 SAL_CALL 100 CharacterClassificationImpl::getCharacterType( const OUString& Text, sal_Int32 nPos, 101 const Locale& rLocale ) throw(RuntimeException) 102 { 103 return getLocaleSpecificCharacterClassification(rLocale)->getCharacterType(Text, nPos, rLocale); 104 } 105 106 sal_Int32 SAL_CALL 107 CharacterClassificationImpl::getStringType( const OUString& Text, sal_Int32 nPos, 108 sal_Int32 nCount, const Locale& rLocale ) throw(RuntimeException) 109 { 110 return getLocaleSpecificCharacterClassification(rLocale)->getStringType(Text, nPos, nCount, rLocale); 111 } 112 113 ParseResult SAL_CALL CharacterClassificationImpl::parseAnyToken( 114 const OUString& Text, sal_Int32 nPos, const Locale& rLocale, 115 sal_Int32 startCharTokenType, const OUString& userDefinedCharactersStart, 116 sal_Int32 contCharTokenType, const OUString& userDefinedCharactersCont ) 117 throw(RuntimeException) 118 { 119 return getLocaleSpecificCharacterClassification(rLocale)->parseAnyToken(Text, nPos, rLocale, 120 startCharTokenType,userDefinedCharactersStart, 121 contCharTokenType, userDefinedCharactersCont); 122 } 123 124 125 ParseResult SAL_CALL CharacterClassificationImpl::parsePredefinedToken( 126 sal_Int32 nTokenType, const OUString& Text, sal_Int32 nPos, 127 const Locale& rLocale, sal_Int32 startCharTokenType, 128 const OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType, 129 const OUString& userDefinedCharactersCont ) throw(RuntimeException) 130 { 131 return getLocaleSpecificCharacterClassification(rLocale)->parsePredefinedToken( 132 nTokenType, Text, nPos, rLocale, startCharTokenType, userDefinedCharactersStart, 133 contCharTokenType, userDefinedCharactersCont); 134 } 135 136 sal_Bool SAL_CALL CharacterClassificationImpl::createLocaleSpecificCharacterClassification(const OUString& serviceName, const Locale& rLocale) 137 { 138 // to share service between same Language but different Country code, like zh_CN and zh_SG 139 for (size_t l = 0; l < lookupTable.size(); l++) { 140 cachedItem = lookupTable[l]; 141 if (serviceName == cachedItem->aName) { 142 lookupTable.push_back( cachedItem = new lookupTableItem(rLocale, serviceName, cachedItem->xCI) ); 143 return sal_True; 144 } 145 } 146 147 Reference < XInterface > xI = xMSF->createInstance( 148 OUString::createFromAscii("com.sun.star.i18n.CharacterClassification_") + serviceName); 149 150 Reference < XCharacterClassification > xCI; 151 if ( xI.is() ) { 152 xI->queryInterface(::getCppuType((const Reference< XCharacterClassification>*)0) ) >>= xCI; 153 if (xCI.is()) { 154 lookupTable.push_back( cachedItem = new lookupTableItem(rLocale, serviceName, xCI) ); 155 return sal_True; 156 } 157 } 158 return sal_False; 159 } 160 161 Reference < XCharacterClassification > SAL_CALL 162 CharacterClassificationImpl::getLocaleSpecificCharacterClassification(const Locale& rLocale) 163 throw(RuntimeException) 164 { 165 // reuse instance if locale didn't change 166 if (cachedItem && cachedItem->equals(rLocale)) 167 return cachedItem->xCI; 168 else if (xMSF.is()) { 169 for (size_t i = 0; i < lookupTable.size(); i++) { 170 cachedItem = lookupTable[i]; 171 if (cachedItem->equals(rLocale)) 172 return cachedItem->xCI; 173 } 174 175 static sal_Unicode under = (sal_Unicode)'_'; 176 static OUString tw(OUString::createFromAscii("TW")); 177 sal_Int32 l = rLocale.Language.getLength(); 178 sal_Int32 c = rLocale.Country.getLength(); 179 sal_Int32 v = rLocale.Variant.getLength(); 180 OUStringBuffer aBuf(l+c+v+3); 181 182 // load service with name <base>_<lang>_<country>_<varian> 183 if ((l > 0 && c > 0 && v > 0 && 184 createLocaleSpecificCharacterClassification(aBuf.append(rLocale.Language).append(under).append( 185 rLocale.Country).append(under).append(rLocale.Variant).makeStringAndClear(), rLocale)) || 186 // load service with name <base>_<lang>_<country> 187 (l > 0 && c > 0 && 188 createLocaleSpecificCharacterClassification(aBuf.append(rLocale.Language).append(under).append( 189 rLocale.Country).makeStringAndClear(), rLocale)) || 190 (l > 0 && c > 0 && rLocale.Language.compareToAscii("zh") == 0 && 191 (rLocale.Country.compareToAscii("HK") == 0 || 192 rLocale.Country.compareToAscii("MO") == 0) && 193 // if the country code is HK or MO, one more step to try TW. 194 createLocaleSpecificCharacterClassification(aBuf.append(rLocale.Language).append(under).append( 195 tw).makeStringAndClear(), rLocale)) || 196 (l > 0 && 197 // load service with name <base>_<lang> 198 createLocaleSpecificCharacterClassification(rLocale.Language, rLocale))) { 199 return cachedItem->xCI; 200 } else if (xUCI.is()) { 201 lookupTable.push_back( cachedItem = new lookupTableItem(rLocale, OUString::createFromAscii("Unicode"), xUCI) ); 202 return cachedItem->xCI; 203 } 204 } 205 throw RuntimeException(); 206 } 207 208 const sal_Char cClass[] = "com.sun.star.i18n.CharacterClassification"; 209 210 OUString SAL_CALL 211 CharacterClassificationImpl::getImplementationName(void) 212 throw( RuntimeException ) 213 { 214 return OUString::createFromAscii(cClass); 215 } 216 217 sal_Bool SAL_CALL 218 CharacterClassificationImpl::supportsService(const rtl::OUString& rServiceName) 219 throw( RuntimeException ) 220 { 221 return !rServiceName.compareToAscii(cClass); 222 } 223 224 Sequence< OUString > SAL_CALL 225 CharacterClassificationImpl::getSupportedServiceNames(void) throw( RuntimeException ) 226 { 227 Sequence< OUString > aRet(1); 228 aRet[0] = OUString::createFromAscii(cClass); 229 return aRet; 230 } 231 232 } } } } 233