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