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
CharacterClassificationImpl(const Reference<lang::XMultiServiceFactory> & rxMSF)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
~CharacterClassificationImpl()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
toUpper(const OUString & Text,sal_Int32 nPos,sal_Int32 nCount,const Locale & rLocale)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
toLower(const OUString & Text,sal_Int32 nPos,sal_Int32 nCount,const Locale & rLocale)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
toTitle(const OUString & Text,sal_Int32 nPos,sal_Int32 nCount,const Locale & rLocale)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
getType(const OUString & Text,sal_Int32 nPos)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
getCharacterDirection(const OUString & Text,sal_Int32 nPos)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
getScript(const OUString & Text,sal_Int32 nPos)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
getCharacterType(const OUString & Text,sal_Int32 nPos,const Locale & rLocale)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
getStringType(const OUString & Text,sal_Int32 nPos,sal_Int32 nCount,const Locale & rLocale)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
parseAnyToken(const OUString & Text,sal_Int32 nPos,const Locale & rLocale,sal_Int32 startCharTokenType,const OUString & userDefinedCharactersStart,sal_Int32 contCharTokenType,const OUString & userDefinedCharactersCont)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
parsePredefinedToken(sal_Int32 nTokenType,const OUString & Text,sal_Int32 nPos,const Locale & rLocale,sal_Int32 startCharTokenType,const OUString & userDefinedCharactersStart,sal_Int32 contCharTokenType,const OUString & userDefinedCharactersCont)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
createLocaleSpecificCharacterClassification(const OUString & serviceName,const Locale & rLocale)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
getLocaleSpecificCharacterClassification(const Locale & rLocale)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
getImplementationName(void)211 CharacterClassificationImpl::getImplementationName(void)
212 throw( RuntimeException )
213 {
214 return OUString::createFromAscii(cClass);
215 }
216
217 sal_Bool SAL_CALL
supportsService(const rtl::OUString & rServiceName)218 CharacterClassificationImpl::supportsService(const rtl::OUString& rServiceName)
219 throw( RuntimeException )
220 {
221 return !rServiceName.compareToAscii(cClass);
222 }
223
224 Sequence< OUString > SAL_CALL
getSupportedServiceNames(void)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