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 "transliterationImpl.hxx"
28 #include "servicename.hxx"
29
30 #include <com/sun/star/i18n/TransliterationType.hpp>
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
33 #include <com/sun/star/container/XEnumeration.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
36
37 #include <comphelper/processfactory.hxx>
38 #include <rtl/string.h>
39 #include <rtl/ustring.hxx>
40 #include <rtl/ustrbuf.hxx>
41
42 #include <algorithm>
43
44 #if OSL_DEBUG_LEVEL > 1
45 #include <stdio.h>
46 #endif
47
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::lang;
50 using namespace rtl;
51 using namespace com::sun::star::container;
52
53 namespace com { namespace sun { namespace star { namespace i18n {
54
55 #define ERROR RuntimeException()
56
57 #define TmItem1( name ) \
58 {TransliterationModules_##name, TransliterationModulesNew_##name, #name}
59
60 #define TmItem2( name ) \
61 {(TransliterationModules)0, TransliterationModulesNew_##name, #name}
62
63 // Ignore Module list
64 static struct TMlist {
65 TransliterationModules tm;
66 TransliterationModulesNew tmn;
67 const sal_Char *implName;
68 } TMlist[] = { // Modules ModulesNew
69 TmItem1 (IGNORE_CASE), // 0. (1<<8 256) (7)
70 TmItem1 (IGNORE_WIDTH), // 1. (1<<9 512) (8)
71 TmItem1 (IGNORE_KANA), // 2. (1<<10 1024) (9)
72 // No enum define for this trans. application has to use impl name to load it
73 // TmItem1 (IGNORE_CASE_SIMPLE), // (1<<11 1024) (66)
74
75 TmItem1 (ignoreTraditionalKanji_ja_JP), // 3. (1<<12 4096) (10)
76 TmItem1 (ignoreTraditionalKana_ja_JP), // 4. (1<<13 8192) (11)
77 TmItem1 (ignoreMinusSign_ja_JP), // 5. (1<<13 16384) (12)
78 TmItem1 (ignoreIterationMark_ja_JP), // 6. (1<<14 32768) (13)
79 TmItem1 (ignoreSeparator_ja_JP), // 7. (1<<15 65536) (14)
80 TmItem1 (ignoreSize_ja_JP), // 15. (1<<23 16777216) (22)
81 TmItem1 (ignoreMiddleDot_ja_JP), // 17. (1<<25 67108864) (24)
82 TmItem1 (ignoreSpace_ja_JP), // 18. (1<<26 134217728) (25)
83 TmItem1 (ignoreZiZu_ja_JP), // 8. (1<<16 131072) (15)
84 TmItem1 (ignoreBaFa_ja_JP), // 9. (1<<17 262144) (16)
85 TmItem1 (ignoreTiJi_ja_JP), // 10. (1<<18 524288) (17)
86 TmItem1 (ignoreHyuByu_ja_JP), // 11. (1<<19 1048576) (18)
87 TmItem1 (ignoreSeZe_ja_JP), // 12. (1<<20 2097152) (19)
88 TmItem1 (ignoreIandEfollowedByYa_ja_JP), // 13. (1<<21 4194304) (20)
89 TmItem1 (ignoreKiKuFollowedBySa_ja_JP), // 14. (1<<22 8388608) (21)
90 TmItem1 (ignoreProlongedSoundMark_ja_JP), // 16. (1<<24 33554432) (23)
91
92 TmItem1 (UPPERCASE_LOWERCASE), // 19. (1) (1)
93 TmItem1 (LOWERCASE_UPPERCASE), // 20. (2) (2)
94 TmItem1 (HALFWIDTH_FULLWIDTH), // 21. (3) (3)
95 TmItem1 (FULLWIDTH_HALFWIDTH), // 22. (4) (4)
96 TmItem1 (KATAKANA_HIRAGANA), // 23. (5) (5)
97 TmItem1 (HIRAGANA_KATAKANA), // 24. (6) (6)
98
99 TmItem1 (smallToLarge_ja_JP), // 25. (1<<27 268435456) (26)
100 TmItem1 (largeToSmall_ja_JP), // 26. (1<<28 536870912) (27)
101 TmItem2 (NumToTextLower_zh_CN), // 27. () (28)
102 TmItem2 (NumToTextUpper_zh_CN), // 28. () (29)
103 TmItem2 (NumToTextLower_zh_TW), // 29. () (30)
104 TmItem2 (NumToTextUpper_zh_TW), // 30. () (31)
105 TmItem2 (NumToTextFormalHangul_ko), // 31. () (32)
106 TmItem2 (NumToTextFormalLower_ko), // 32. () (33)
107 TmItem2 (NumToTextFormalUpper_ko), // 33. () (34)
108 TmItem2 (NumToTextInformalHangul_ko), // 34. () (35)
109 TmItem2 (NumToTextInformalLower_ko), // 35. () (36)
110 TmItem2 (NumToTextInformalUpper_ko), // 36. () (37)
111 TmItem2 (NumToCharLower_zh_CN), // 37. () (38)
112 TmItem2 (NumToCharUpper_zh_CN), // 38. () (39)
113 TmItem2 (NumToCharLower_zh_TW), // 39. () (40)
114 TmItem2 (NumToCharUpper_zh_TW), // 40. () (41)
115 TmItem2 (NumToCharHangul_ko), // 41. () (42)
116 TmItem2 (NumToCharLower_ko), // 42. () (43)
117 TmItem2 (NumToCharUpper_ko), // 43. () (44)
118 TmItem2 (NumToCharFullwidth), // 44. () (45)
119 TmItem2 (NumToCharKanjiShort_ja_JP), // 45. () (46)
120 TmItem2 (TextToNumLower_zh_CN), // 46. () (47)
121 TmItem2 (TextToNumUpper_zh_CN), // 47. () (48)
122 TmItem2 (TextToNumLower_zh_TW), // 48. () (49)
123 TmItem2 (TextToNumUpper_zh_TW), // 49. () (50)
124 TmItem2 (TextToNumFormalHangul_ko), // 50. () (51)
125 TmItem2 (TextToNumFormalLower_ko), // 51. () (52)
126 TmItem2 (TextToNumFormalUpper_ko), // 52. () (53)
127 TmItem2 (TextToNumInformalHangul_ko), // 53. () (54)
128 TmItem2 (TextToNumInformalLower_ko), // 54. () (55)
129 TmItem2 (TextToNumInformalUpper_ko), // 55. () (56)
130
131 TmItem2 (CharToNumLower_zh_CN), // 56. () (59)
132 TmItem2 (CharToNumUpper_zh_CN), // 57. () (60)
133 TmItem2 (CharToNumLower_zh_TW), // 58. () (61)
134 TmItem2 (CharToNumUpper_zh_TW), // 59. () (62)
135 TmItem2 (CharToNumHangul_ko), // 60. () (63)
136 TmItem2 (CharToNumLower_ko), // 61. () (64)
137 TmItem2 (CharToNumUpper_ko), // 62. () (65)
138
139 // no enum defined for these trans. application has to use impl name to load them
140 // TmItem2 (NumToCharArabic_Indic), // () (67)
141 // TmItem2 (NumToCharEstern_Arabic_Indic),// () (68)
142 // TmItem2 (NumToCharIndic), // () (69)
143 // TmItem2 (NumToCharThai), // () (70)
144 {(TransliterationModules)0, (TransliterationModulesNew)0, NULL}
145 };
146
147 // Constructor/Destructor
TransliterationImpl(const Reference<XMultiServiceFactory> & xMSF)148 TransliterationImpl::TransliterationImpl(const Reference <XMultiServiceFactory>& xMSF) : xSMgr(xMSF)
149 {
150 numCascade = 0;
151 caseignoreOnly = sal_True;
152
153 if ( xMSF.is() )
154 {
155 Reference < XInterface > xI=
156 xMSF->createInstance(OUString::createFromAscii("com.sun.star.i18n.LocaleData"));
157 if ( xI.is() ) {
158 Any x = xI->queryInterface( ::getCppuType( (const uno::Reference< i18n::XLocaleData >*)0) );
159 x >>= localedata;
160 }
161 }
162 }
163
~TransliterationImpl()164 TransliterationImpl::~TransliterationImpl()
165 {
166 localedata.clear();
167 clear();
168 }
169
170
171 // Methods
172 OUString SAL_CALL
getName()173 TransliterationImpl::getName() throw(RuntimeException)
174 {
175 if (numCascade == 1 && bodyCascade[0].is())
176 return bodyCascade[0]->getName();
177 if (numCascade < 1)
178 return ( OUString::createFromAscii("Not Loaded"));
179 throw ERROR;
180 }
181
182 sal_Int16 SAL_CALL
getType()183 TransliterationImpl::getType() throw(RuntimeException)
184 {
185 if (numCascade > 1)
186 return (TransliterationType::CASCADE|TransliterationType::IGNORE);
187 if (numCascade > 0 && bodyCascade[0].is())
188 return(bodyCascade[0]->getType());
189 throw ERROR;
190 }
191
192 void SAL_CALL
loadModule(TransliterationModules modType,const Locale & rLocale)193 TransliterationImpl::loadModule( TransliterationModules modType, const Locale& rLocale )
194 throw(RuntimeException)
195 {
196 clear();
197 if (modType&TransliterationModules_IGNORE_MASK && modType&TransliterationModules_NON_IGNORE_MASK) {
198 throw ERROR;
199 } else if (modType&TransliterationModules_IGNORE_MASK) {
200 #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \
201 TransliterationModules_IGNORE_WIDTH | \
202 TransliterationModules_IGNORE_KANA)
203 sal_Int32 mask = ((modType&TransliterationModules_IGNORE_CASE_MASK) == modType) ?
204 TransliterationModules_IGNORE_CASE_MASK : TransliterationModules_IGNORE_MASK;
205 for (sal_Int16 i = 0; TMlist[i].tm & mask; i++) {
206 if (modType & TMlist[i].tm)
207 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName),
208 bodyCascade[numCascade], rLocale))
209 numCascade++;
210 }
211 } else if (modType&TransliterationModules_NON_IGNORE_MASK) {
212 for (sal_Int16 i = 0; TMlist[i].tm; i++) {
213 if (TMlist[i].tm == modType) {
214 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), bodyCascade[numCascade], rLocale))
215 numCascade++;
216 break;
217 }
218 }
219 }
220 }
221
222 void SAL_CALL
loadModuleNew(const Sequence<TransliterationModulesNew> & modType,const Locale & rLocale)223 TransliterationImpl::loadModuleNew( const Sequence < TransliterationModulesNew > & modType, const Locale& rLocale )
224 throw(RuntimeException)
225 {
226 clear();
227 sal_Int32 mask = 0, count = modType.getLength();
228 if (count > maxCascade)
229 throw ERROR; // could not handle more than maxCascade
230 for (sal_Int16 i = 0; i < count; i++) {
231 for (sal_Int16 j = 0; TMlist[j].tmn; j++) {
232 if (TMlist[j].tmn == modType[i]) {
233 if (mask == 0)
234 mask = TMlist[i].tm && (TMlist[i].tm&TransliterationModules_IGNORE_MASK) ?
235 TransliterationModules_IGNORE_MASK : TransliterationModules_NON_IGNORE_MASK;
236 else if (mask == TransliterationModules_IGNORE_MASK &&
237 (TMlist[i].tm&TransliterationModules_IGNORE_MASK) == 0)
238 throw ERROR; // could not mess up ignore trans. with non_ignore trans.
239 if (loadModuleByName(OUString::createFromAscii(TMlist[j].implName), bodyCascade[numCascade], rLocale))
240 numCascade++;
241 break;
242 }
243 }
244 }
245 }
246
247 void SAL_CALL
loadModuleByImplName(const OUString & implName,const Locale & rLocale)248 TransliterationImpl::loadModuleByImplName(const OUString& implName, const Locale& rLocale)
249 throw(RuntimeException)
250 {
251 clear();
252 if (loadModuleByName(implName, bodyCascade[numCascade], rLocale))
253 numCascade++;
254 }
255
256
257 void SAL_CALL
loadModulesByImplNames(const Sequence<OUString> & implNameList,const Locale & rLocale)258 TransliterationImpl::loadModulesByImplNames(const Sequence< OUString >& implNameList, const Locale& rLocale ) throw(RuntimeException)
259 {
260 if (implNameList.getLength() > maxCascade || implNameList.getLength() <= 0)
261 throw ERROR;
262
263 clear();
264 for (sal_Int32 i = 0; i < implNameList.getLength(); i++)
265 if (loadModuleByName(implNameList[i], bodyCascade[numCascade], rLocale))
266 numCascade++;
267 }
268
269
270 Sequence<OUString> SAL_CALL
getAvailableModules(const Locale & rLocale,sal_Int16 sType)271 TransliterationImpl::getAvailableModules( const Locale& rLocale, sal_Int16 sType ) throw(RuntimeException)
272 {
273 const Sequence<OUString> &translist = localedata->getTransliterations(rLocale);
274 Sequence<OUString> r(translist.getLength());
275 Reference<XExtendedTransliteration> body;
276 sal_Int32 n = 0;
277 for (sal_Int32 i = 0; i < translist.getLength(); i++)
278 {
279 if (loadModuleByName(translist[i], body, rLocale)) {
280 if (body->getType() & sType)
281 r[n++] = translist[i];
282 body.clear();
283 }
284 }
285 r.realloc(n);
286 return (r);
287 }
288
289
290 OUString SAL_CALL
transliterate(const OUString & inStr,sal_Int32 startPos,sal_Int32 nCount,Sequence<sal_Int32> & offset)291 TransliterationImpl::transliterate( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
292 Sequence< sal_Int32 >& offset ) throw(RuntimeException)
293 {
294 if (numCascade == 0)
295 return inStr;
296
297 if (offset.getLength() != nCount)
298 offset.realloc(nCount);
299 if (numCascade == 1)
300 {
301 if ( startPos == 0 && nCount == inStr.getLength() )
302 return bodyCascade[0]->transliterate( inStr, 0, nCount, offset);
303 else
304 {
305 OUString tmpStr = inStr.copy(startPos, nCount);
306 tmpStr = bodyCascade[0]->transliterate(tmpStr, 0, nCount, offset);
307 if ( startPos )
308 {
309 sal_Int32 * pArr = offset.getArray();
310 nCount = offset.getLength();
311 for (sal_Int32 j = 0; j < nCount; j++)
312 pArr[j] += startPos;
313 }
314 return tmpStr;
315 }
316 }
317 else
318 {
319 OUString tmpStr = inStr.copy(startPos, nCount);
320 sal_Int32 * pArr = offset.getArray();
321 for (sal_Int32 j = 0; j < nCount; j++)
322 pArr[j] = startPos + j;
323
324 sal_Int16 from = 0, to = 1, tmp;
325 Sequence<sal_Int32> off[2];
326
327 off[to] = offset;
328 off[from].realloc(nCount);
329 for (sal_Int32 i = 0; i < numCascade; i++) {
330 tmpStr = bodyCascade[i]->transliterate(tmpStr, 0, nCount, off[from]);
331
332 nCount = tmpStr.getLength();
333
334 tmp = from; from = to; to = tmp;
335 for (sal_Int32 j = 0; j < nCount; j++)
336 off[to][j] = off[from][off[to][j]];
337 }
338 offset = off[to];
339 return tmpStr;
340 }
341 }
342
343
344 //
345 OUString SAL_CALL
folding(const OUString & inStr,sal_Int32 startPos,sal_Int32 nCount,Sequence<sal_Int32> & offset)346 TransliterationImpl::folding( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
347 Sequence< sal_Int32 >& offset ) throw(RuntimeException)
348 {
349 if (numCascade == 0)
350 return inStr;
351
352 if (offset.getLength() != nCount)
353 offset.realloc(nCount);
354 if (numCascade == 1)
355 {
356 if ( startPos == 0 && nCount == inStr.getLength() )
357 return bodyCascade[0]->folding( inStr, 0, nCount, offset);
358 else
359 {
360 OUString tmpStr = inStr.copy(startPos, nCount);
361 tmpStr = bodyCascade[0]->folding(tmpStr, 0, nCount, offset);
362 if ( startPos )
363 {
364 sal_Int32 * pArr = offset.getArray();
365 nCount = offset.getLength();
366 for (sal_Int32 j = 0; j < nCount; j++)
367 pArr[j] += startPos;
368 }
369 return tmpStr;
370 }
371 }
372 else
373 {
374 OUString tmpStr = inStr.copy(startPos, nCount);
375 sal_Int32 * pArr = offset.getArray();
376 for (sal_Int32 j = 0; j < nCount; j++)
377 pArr[j] = startPos + j;
378
379 sal_Int16 from = 0, to = 1, tmp;
380 Sequence<sal_Int32> off[2];
381
382 off[to] = offset;
383 for (sal_Int32 i = 0; i < numCascade; i++) {
384 tmpStr = bodyCascade[i]->folding(tmpStr, 0, nCount, off[from]);
385
386 nCount = tmpStr.getLength();
387
388 tmp = from; from = to; to = tmp;
389 for (sal_Int32 j = 0; j < nCount; j++)
390 off[to][j] = off[from][off[to][j]];
391 }
392 offset = off[to];
393 return tmpStr;
394 }
395 }
396
397 OUString SAL_CALL
transliterateString2String(const OUString & inStr,sal_Int32 startPos,sal_Int32 nCount)398 TransliterationImpl::transliterateString2String( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount ) throw(RuntimeException)
399 {
400 if (numCascade == 0)
401 return inStr;
402 else if (numCascade == 1)
403 return bodyCascade[0]->transliterateString2String( inStr, startPos, nCount);
404 else {
405 OUString tmpStr = bodyCascade[0]->transliterateString2String(inStr, startPos, nCount);
406
407 for (sal_Int32 i = 1; i < numCascade; i++)
408 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
409 return tmpStr;
410 }
411 }
412
413 OUString SAL_CALL
transliterateChar2String(sal_Unicode inChar)414 TransliterationImpl::transliterateChar2String( sal_Unicode inChar ) throw(RuntimeException)
415 {
416 if (numCascade == 0)
417 return OUString(&inChar, 1);
418 else if (numCascade == 1)
419 return bodyCascade[0]->transliterateChar2String( inChar);
420 else {
421 OUString tmpStr = bodyCascade[0]->transliterateChar2String(inChar);
422
423 for (sal_Int32 i = 1; i < numCascade; i++)
424 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
425 return tmpStr;
426 }
427 }
428
429 sal_Unicode SAL_CALL
transliterateChar2Char(sal_Unicode inChar)430 TransliterationImpl::transliterateChar2Char( sal_Unicode inChar ) throw(MultipleCharsOutputException, RuntimeException)
431 {
432 sal_Unicode tmpChar = inChar;
433 for (sal_Int32 i = 0; i < numCascade; i++)
434 tmpChar = bodyCascade[i]->transliterateChar2Char(tmpChar);
435 return tmpChar;
436 }
437
438
439 sal_Bool SAL_CALL
equals(const OUString & str1,sal_Int32 pos1,sal_Int32 nCount1,sal_Int32 & nMatch1,const OUString & str2,sal_Int32 pos2,sal_Int32 nCount2,sal_Int32 & nMatch2)440 TransliterationImpl::equals(
441 const OUString& str1, sal_Int32 pos1, sal_Int32 nCount1, sal_Int32& nMatch1,
442 const OUString& str2, sal_Int32 pos2, sal_Int32 nCount2, sal_Int32& nMatch2)
443 throw(RuntimeException)
444 {
445 // since this is an API function make it user fail safe
446 if ( nCount1 < 0 ) {
447 pos1 += nCount1;
448 nCount1 = -nCount1;
449 }
450 if ( nCount2 < 0 ) {
451 pos2 += nCount2;
452 nCount2 = -nCount2;
453 }
454 if ( !nCount1 || !nCount2 ||
455 pos1 >= str1.getLength() || pos2 >= str2.getLength() ||
456 pos1 < 0 || pos2 < 0 ) {
457 nMatch1 = nMatch2 = 0;
458 // two empty strings return true, else false
459 return !nCount1 && !nCount2 && pos1 == str1.getLength() && pos2 == str2.getLength();
460 }
461 if ( pos1 + nCount1 > str1.getLength() )
462 nCount1 = str1.getLength() - pos1;
463 if ( pos2 + nCount2 > str2.getLength() )
464 nCount2 = str2.getLength() - pos2;
465
466 if (caseignoreOnly && caseignore.is())
467 return caseignore->equals(str1, pos1, nCount1, nMatch1, str2, pos2, nCount2, nMatch2);
468
469 Sequence<sal_Int32> offset1, offset2;
470
471 OUString tmpStr1 = folding(str1, pos1, nCount1, offset1);
472 OUString tmpStr2 = folding(str2, pos2, nCount2, offset2);
473 // Length of offset1 and offset2 may still be 0 if there was no folding
474 // necessary!
475
476 const sal_Unicode *p1 = tmpStr1.getStr();
477 const sal_Unicode *p2 = tmpStr2.getStr();
478 sal_Int32 i, nLen = ::std::min( tmpStr1.getLength(), tmpStr2.getLength());
479 for (i = 0; i < nLen; ++i, ++p1, ++p2 ) {
480 if (*p1 != *p2) {
481 // return number of matched code points so far
482 nMatch1 = (i < offset1.getLength()) ? offset1[i] : i;
483 nMatch2 = (i < offset2.getLength()) ? offset2[i] : i;
484 return sal_False;
485 }
486 }
487 // i==nLen
488 if ( tmpStr1.getLength() != tmpStr2.getLength() ) {
489 // return number of matched code points so far
490 nMatch1 = (i <= offset1.getLength()) ? offset1[i-1] + 1 : i;
491 nMatch2 = (i <= offset2.getLength()) ? offset2[i-1] + 1 : i;
492 return sal_False;
493 } else {
494 nMatch1 = nCount1;
495 nMatch2 = nCount2;
496 return sal_True;
497 }
498 }
499
500 #define MaxOutput 2
501
502 Sequence< OUString > SAL_CALL
getRange(const Sequence<OUString> & inStrs,const sal_Int32 length,sal_Int16 _numCascade)503 TransliterationImpl::getRange(const Sequence< OUString > &inStrs,
504 const sal_Int32 length, sal_Int16 _numCascade) throw(RuntimeException)
505 {
506 if (_numCascade >= numCascade || ! bodyCascade[_numCascade].is())
507 return inStrs;
508
509 sal_Int32 j_tmp = 0;
510 Sequence< OUString > ostr(MaxOutput*length);
511 for (sal_Int32 j = 0; j < length; j+=2) {
512 const Sequence< OUString >& temp = bodyCascade[_numCascade]->transliterateRange(inStrs[j], inStrs[j+1]);
513
514 for ( sal_Int32 k = 0; k < temp.getLength(); k++) {
515 if ( j_tmp >= MaxOutput*length ) throw ERROR;
516 ostr[j_tmp++] = temp[k];
517 }
518 }
519 ostr.realloc(j_tmp);
520
521 return this->getRange(ostr, j_tmp, ++_numCascade);
522 }
523
524
525 Sequence< OUString > SAL_CALL
transliterateRange(const OUString & str1,const OUString & str2)526 TransliterationImpl::transliterateRange( const OUString& str1, const OUString& str2 )
527 throw(RuntimeException)
528 {
529 if (numCascade == 1)
530 return bodyCascade[0]->transliterateRange(str1, str2);
531
532 Sequence< OUString > ostr(2);
533 ostr[0] = str1;
534 ostr[1] = str2;
535
536 return this->getRange(ostr, 2, 0);
537 }
538
539
540 sal_Int32 SAL_CALL
compareSubstring(const OUString & str1,sal_Int32 off1,sal_Int32 len1,const OUString & str2,sal_Int32 off2,sal_Int32 len2)541 TransliterationImpl::compareSubstring(
542 const OUString& str1, sal_Int32 off1, sal_Int32 len1,
543 const OUString& str2, sal_Int32 off2, sal_Int32 len2)
544 throw(RuntimeException)
545 {
546 if (caseignoreOnly && caseignore.is())
547 return caseignore->compareSubstring(str1, off1, len1, str2, off2, len2);
548
549 Sequence <sal_Int32> offset;
550
551 OUString in_str1 = this->transliterate(str1, off1, len1, offset);
552 OUString in_str2 = this->transliterate(str2, off2, len2, offset);
553 const sal_Unicode* unistr1 = in_str1.getStr();
554 const sal_Unicode* unistr2 = in_str2.getStr();
555 sal_Int32 strlen1 = in_str1.getLength();
556 sal_Int32 strlen2 = in_str2.getLength();
557
558 while (strlen1 && strlen2) {
559 if (*unistr1 != *unistr2)
560 return *unistr1 > *unistr2 ? 1 : -1;
561
562 unistr1++; unistr2++; strlen1--; strlen2--;
563 }
564 return strlen1 == strlen2 ? 0 : (strlen1 > strlen2 ? 1 : -1);
565 }
566
567
568 sal_Int32 SAL_CALL
compareString(const OUString & str1,const OUString & str2)569 TransliterationImpl::compareString(const OUString& str1, const OUString& str2 ) throw (RuntimeException)
570 {
571 if (caseignoreOnly && caseignore.is())
572 return caseignore->compareString(str1, str2);
573 else
574 return this->compareSubstring(str1, 0, str1.getLength(), str2, 0, str2.getLength());
575 }
576
577
578 void
clear()579 TransliterationImpl::clear()
580 {
581 for (sal_Int32 i = 0; i < numCascade; i++)
582 if (bodyCascade[i].is())
583 bodyCascade[i].clear();
584 numCascade = 0;
585 caseignore.clear();
586 caseignoreOnly = sal_True;
587 }
588
loadBody(OUString & implName,Reference<XExtendedTransliteration> & body)589 void TransliterationImpl::loadBody( OUString &implName, Reference<XExtendedTransliteration>& body )
590 throw (RuntimeException)
591 {
592 Reference< XContentEnumerationAccess > xEnumAccess( xSMgr, UNO_QUERY );
593 Reference< XEnumeration > xEnum(xEnumAccess->createContentEnumeration(
594 OUString::createFromAscii(TRLT_SERVICELNAME_L10N)));
595 if (xEnum.is()) {
596 while (xEnum->hasMoreElements()) {
597 Any a = xEnum->nextElement();
598 Reference< XServiceInfo > xsInfo;
599 if (a >>= xsInfo) {
600 if (implName.equals(xsInfo->getImplementationName())) {
601 Reference< XSingleServiceFactory > xFactory;
602 if (a >>= xFactory) {
603 Reference< XInterface > xI = xFactory->createInstance();
604 if (xI.is()) {
605 a = xI->queryInterface(::getCppuType((
606 const Reference<XExtendedTransliteration>*)0));
607 a >>= body;
608 return;
609 }
610 }
611 }
612 }
613 }
614 }
615 throw ERROR;
616 }
617
618 sal_Bool SAL_CALL
loadModuleByName(const OUString & implName,Reference<XExtendedTransliteration> & body,const Locale & rLocale)619 TransliterationImpl::loadModuleByName( const OUString& implName,
620 Reference<XExtendedTransliteration>& body, const Locale& rLocale) throw(RuntimeException)
621 {
622 OUString cname = OUString::createFromAscii(TRLT_IMPLNAME_PREFIX) + implName;
623 loadBody(cname, body);
624 if (body.is()) {
625 body->loadModule((TransliterationModules)0, rLocale); // toUpper/toLoad need rLocale
626
627 // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed
628 for (sal_Int16 i = 0; i < 3; i++) {
629 if (implName.compareToAscii(TMlist[i].implName) == 0) {
630 if (i == 0) // current module is caseignore
631 body->loadModule(TMlist[0].tm, rLocale); // caseingore need to setup module name
632 if (! caseignore.is()) {
633 OUString bname = OUString::createFromAscii(TRLT_IMPLNAME_PREFIX) +
634 OUString::createFromAscii(TMlist[0].implName);
635 loadBody(bname, caseignore);
636 }
637 if (caseignore.is())
638 caseignore->loadModule(TMlist[i].tm, rLocale);
639 return sal_True;
640 }
641 }
642 caseignoreOnly = sal_False; // has other module than just ignore case/kana/width
643 }
644 return body.is();
645 }
646
647 const sal_Char cTrans[] = "com.sun.star.i18n.Transliteration";
648
649 OUString SAL_CALL
getImplementationName()650 TransliterationImpl::getImplementationName() throw( RuntimeException )
651 {
652 return OUString::createFromAscii(cTrans);
653 }
654
655
656 sal_Bool SAL_CALL
supportsService(const OUString & rServiceName)657 TransliterationImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
658 {
659 return !rServiceName.compareToAscii(cTrans);
660 }
661
662 Sequence< OUString > SAL_CALL
getSupportedServiceNames(void)663 TransliterationImpl::getSupportedServiceNames(void) throw( RuntimeException )
664 {
665 Sequence< OUString > aRet(1);
666 aRet[0] = OUString::createFromAscii(cTrans);
667 return aRet;
668 }
669
670 } } } }
671