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 TransliterationImpl::TransBody TransliterationImpl::lastTransBody; 148 149 // Constructor/Destructor 150 TransliterationImpl::TransliterationImpl(const Reference <XMultiServiceFactory>& xMSF) : xSMgr(xMSF) 151 { 152 numCascade = 0; 153 caseignoreOnly = sal_True; 154 155 if ( xMSF.is() ) 156 { 157 Reference < XInterface > xI= 158 xMSF->createInstance(OUString::createFromAscii("com.sun.star.i18n.LocaleData")); 159 if ( xI.is() ) { 160 Any x = xI->queryInterface( ::getCppuType( (const uno::Reference< i18n::XLocaleData >*)0) ); 161 x >>= localedata; 162 } 163 } 164 } 165 166 TransliterationImpl::~TransliterationImpl() 167 { 168 localedata.clear(); 169 clear(); 170 } 171 172 173 // Methods 174 OUString SAL_CALL 175 TransliterationImpl::getName() throw(RuntimeException) 176 { 177 if (numCascade == 1 && bodyCascade[0].is()) 178 return bodyCascade[0]->getName(); 179 if (numCascade < 1) 180 return ( OUString::createFromAscii("Not Loaded")); 181 throw ERROR; 182 } 183 184 sal_Int16 SAL_CALL 185 TransliterationImpl::getType() throw(RuntimeException) 186 { 187 if (numCascade > 1) 188 return (TransliterationType::CASCADE|TransliterationType::IGNORE); 189 if (numCascade > 0 && bodyCascade[0].is()) 190 return(bodyCascade[0]->getType()); 191 throw ERROR; 192 } 193 194 void SAL_CALL 195 TransliterationImpl::loadModule( TransliterationModules modType, const Locale& rLocale ) 196 throw(RuntimeException) 197 { 198 clear(); 199 if (modType&TransliterationModules_IGNORE_MASK && modType&TransliterationModules_NON_IGNORE_MASK) { 200 throw ERROR; 201 } else if (modType&TransliterationModules_IGNORE_MASK) { 202 #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \ 203 TransliterationModules_IGNORE_WIDTH | \ 204 TransliterationModules_IGNORE_KANA) 205 sal_Int32 mask = ((modType&TransliterationModules_IGNORE_CASE_MASK) == modType) ? 206 TransliterationModules_IGNORE_CASE_MASK : TransliterationModules_IGNORE_MASK; 207 for (sal_Int16 i = 0; TMlist[i].tm & mask; i++) { 208 if (modType & TMlist[i].tm) 209 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), 210 bodyCascade[numCascade], rLocale)) 211 numCascade++; 212 } 213 } else if (modType&TransliterationModules_NON_IGNORE_MASK) { 214 for (sal_Int16 i = 0; TMlist[i].tm; i++) { 215 if (TMlist[i].tm == modType) { 216 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), bodyCascade[numCascade], rLocale)) 217 numCascade++; 218 break; 219 } 220 } 221 } 222 } 223 224 void SAL_CALL 225 TransliterationImpl::loadModuleNew( const Sequence < TransliterationModulesNew > & modType, const Locale& rLocale ) 226 throw(RuntimeException) 227 { 228 clear(); 229 sal_Int32 mask = 0, count = modType.getLength(); 230 if (count > maxCascade) 231 throw ERROR; // could not handle more than maxCascade 232 for (sal_Int16 i = 0; i < count; i++) { 233 for (sal_Int16 j = 0; TMlist[j].tmn; j++) { 234 if (TMlist[j].tmn == modType[i]) { 235 if (mask == 0) 236 mask = TMlist[i].tm && (TMlist[i].tm&TransliterationModules_IGNORE_MASK) ? 237 TransliterationModules_IGNORE_MASK : TransliterationModules_NON_IGNORE_MASK; 238 else if (mask == TransliterationModules_IGNORE_MASK && 239 (TMlist[i].tm&TransliterationModules_IGNORE_MASK) == 0) 240 throw ERROR; // could not mess up ignore trans. with non_ignore trans. 241 if (loadModuleByName(OUString::createFromAscii(TMlist[j].implName), bodyCascade[numCascade], rLocale)) 242 numCascade++; 243 break; 244 } 245 } 246 } 247 } 248 249 void SAL_CALL 250 TransliterationImpl::loadModuleByImplName(const OUString& implName, const Locale& rLocale) 251 throw(RuntimeException) 252 { 253 clear(); 254 if (loadModuleByName(implName, bodyCascade[numCascade], rLocale)) 255 numCascade++; 256 } 257 258 259 void SAL_CALL 260 TransliterationImpl::loadModulesByImplNames(const Sequence< OUString >& implNameList, const Locale& rLocale ) throw(RuntimeException) 261 { 262 if (implNameList.getLength() > maxCascade || implNameList.getLength() <= 0) 263 throw ERROR; 264 265 clear(); 266 for (sal_Int32 i = 0; i < implNameList.getLength(); i++) 267 if (loadModuleByName(implNameList[i], bodyCascade[numCascade], rLocale)) 268 numCascade++; 269 } 270 271 272 Sequence<OUString> SAL_CALL 273 TransliterationImpl::getAvailableModules( const Locale& rLocale, sal_Int16 sType ) throw(RuntimeException) 274 { 275 const Sequence<OUString> &translist = localedata->getTransliterations(rLocale); 276 Sequence<OUString> r(translist.getLength()); 277 Reference<XExtendedTransliteration> body; 278 sal_Int32 n = 0; 279 for (sal_Int32 i = 0; i < translist.getLength(); i++) 280 { 281 if (loadModuleByName(translist[i], body, rLocale)) { 282 if (body->getType() & sType) 283 r[n++] = translist[i]; 284 body.clear(); 285 } 286 } 287 r.realloc(n); 288 return (r); 289 } 290 291 292 OUString SAL_CALL 293 TransliterationImpl::transliterate( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount, 294 Sequence< sal_Int32 >& offset ) throw(RuntimeException) 295 { 296 if (numCascade == 0) 297 return inStr; 298 299 if (offset.getLength() != nCount) 300 offset.realloc(nCount); 301 if (numCascade == 1) 302 { 303 if ( startPos == 0 && nCount == inStr.getLength() ) 304 return bodyCascade[0]->transliterate( inStr, 0, nCount, offset); 305 else 306 { 307 OUString tmpStr = inStr.copy(startPos, nCount); 308 tmpStr = bodyCascade[0]->transliterate(tmpStr, 0, nCount, offset); 309 if ( startPos ) 310 { 311 sal_Int32 * pArr = offset.getArray(); 312 nCount = offset.getLength(); 313 for (sal_Int32 j = 0; j < nCount; j++) 314 pArr[j] += startPos; 315 } 316 return tmpStr; 317 } 318 } 319 else 320 { 321 OUString tmpStr = inStr.copy(startPos, nCount); 322 sal_Int32 * pArr = offset.getArray(); 323 for (sal_Int32 j = 0; j < nCount; j++) 324 pArr[j] = startPos + j; 325 326 sal_Int16 from = 0, to = 1, tmp; 327 Sequence<sal_Int32> off[2]; 328 329 off[to] = offset; 330 off[from].realloc(nCount); 331 for (sal_Int32 i = 0; i < numCascade; i++) { 332 tmpStr = bodyCascade[i]->transliterate(tmpStr, 0, nCount, off[from]); 333 334 nCount = tmpStr.getLength(); 335 336 tmp = from; from = to; to = tmp; 337 for (sal_Int32 j = 0; j < nCount; j++) 338 off[to][j] = off[from][off[to][j]]; 339 } 340 offset = off[to]; 341 return tmpStr; 342 } 343 } 344 345 346 // 347 OUString SAL_CALL 348 TransliterationImpl::folding( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount, 349 Sequence< sal_Int32 >& offset ) throw(RuntimeException) 350 { 351 if (numCascade == 0) 352 return inStr; 353 354 if (offset.getLength() != nCount) 355 offset.realloc(nCount); 356 if (numCascade == 1) 357 { 358 if ( startPos == 0 && nCount == inStr.getLength() ) 359 return bodyCascade[0]->folding( inStr, 0, nCount, offset); 360 else 361 { 362 OUString tmpStr = inStr.copy(startPos, nCount); 363 tmpStr = bodyCascade[0]->folding(tmpStr, 0, nCount, offset); 364 if ( startPos ) 365 { 366 sal_Int32 * pArr = offset.getArray(); 367 nCount = offset.getLength(); 368 for (sal_Int32 j = 0; j < nCount; j++) 369 pArr[j] += startPos; 370 } 371 return tmpStr; 372 } 373 } 374 else 375 { 376 OUString tmpStr = inStr.copy(startPos, nCount); 377 sal_Int32 * pArr = offset.getArray(); 378 for (sal_Int32 j = 0; j < nCount; j++) 379 pArr[j] = startPos + j; 380 381 sal_Int16 from = 0, to = 1, tmp; 382 Sequence<sal_Int32> off[2]; 383 384 off[to] = offset; 385 for (sal_Int32 i = 0; i < numCascade; i++) { 386 tmpStr = bodyCascade[i]->folding(tmpStr, 0, nCount, off[from]); 387 388 nCount = tmpStr.getLength(); 389 390 tmp = from; from = to; to = tmp; 391 for (sal_Int32 j = 0; j < nCount; j++) 392 off[to][j] = off[from][off[to][j]]; 393 } 394 offset = off[to]; 395 return tmpStr; 396 } 397 } 398 399 OUString SAL_CALL 400 TransliterationImpl::transliterateString2String( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount ) throw(RuntimeException) 401 { 402 if (numCascade == 0) 403 return inStr; 404 else if (numCascade == 1) 405 return bodyCascade[0]->transliterateString2String( inStr, startPos, nCount); 406 else { 407 OUString tmpStr = bodyCascade[0]->transliterateString2String(inStr, startPos, nCount); 408 409 for (sal_Int32 i = 1; i < numCascade; i++) 410 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength()); 411 return tmpStr; 412 } 413 } 414 415 OUString SAL_CALL 416 TransliterationImpl::transliterateChar2String( sal_Unicode inChar ) throw(RuntimeException) 417 { 418 if (numCascade == 0) 419 return OUString(&inChar, 1); 420 else if (numCascade == 1) 421 return bodyCascade[0]->transliterateChar2String( inChar); 422 else { 423 OUString tmpStr = bodyCascade[0]->transliterateChar2String(inChar); 424 425 for (sal_Int32 i = 1; i < numCascade; i++) 426 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength()); 427 return tmpStr; 428 } 429 } 430 431 sal_Unicode SAL_CALL 432 TransliterationImpl::transliterateChar2Char( sal_Unicode inChar ) throw(MultipleCharsOutputException, RuntimeException) 433 { 434 sal_Unicode tmpChar = inChar; 435 for (sal_Int32 i = 0; i < numCascade; i++) 436 tmpChar = bodyCascade[i]->transliterateChar2Char(tmpChar); 437 return tmpChar; 438 } 439 440 441 sal_Bool SAL_CALL 442 TransliterationImpl::equals( 443 const OUString& str1, sal_Int32 pos1, sal_Int32 nCount1, sal_Int32& nMatch1, 444 const OUString& str2, sal_Int32 pos2, sal_Int32 nCount2, sal_Int32& nMatch2) 445 throw(RuntimeException) 446 { 447 // since this is an API function make it user fail safe 448 if ( nCount1 < 0 ) { 449 pos1 += nCount1; 450 nCount1 = -nCount1; 451 } 452 if ( nCount2 < 0 ) { 453 pos2 += nCount2; 454 nCount2 = -nCount2; 455 } 456 if ( !nCount1 || !nCount2 || 457 pos1 >= str1.getLength() || pos2 >= str2.getLength() || 458 pos1 < 0 || pos2 < 0 ) { 459 nMatch1 = nMatch2 = 0; 460 // two empty strings return true, else false 461 return !nCount1 && !nCount2 && pos1 == str1.getLength() && pos2 == str2.getLength(); 462 } 463 if ( pos1 + nCount1 > str1.getLength() ) 464 nCount1 = str1.getLength() - pos1; 465 if ( pos2 + nCount2 > str2.getLength() ) 466 nCount2 = str2.getLength() - pos2; 467 468 if (caseignoreOnly && caseignore.is()) 469 return caseignore->equals(str1, pos1, nCount1, nMatch1, str2, pos2, nCount2, nMatch2); 470 471 Sequence<sal_Int32> offset1, offset2; 472 473 OUString tmpStr1 = folding(str1, pos1, nCount1, offset1); 474 OUString tmpStr2 = folding(str2, pos2, nCount2, offset2); 475 // Length of offset1 and offset2 may still be 0 if there was no folding 476 // necessary! 477 478 const sal_Unicode *p1 = tmpStr1.getStr(); 479 const sal_Unicode *p2 = tmpStr2.getStr(); 480 sal_Int32 i, nLen = ::std::min( tmpStr1.getLength(), tmpStr2.getLength()); 481 for (i = 0; i < nLen; ++i, ++p1, ++p2 ) { 482 if (*p1 != *p2) { 483 // return number of matched code points so far 484 nMatch1 = (i < offset1.getLength()) ? offset1[i] : i; 485 nMatch2 = (i < offset2.getLength()) ? offset2[i] : i; 486 return sal_False; 487 } 488 } 489 // i==nLen 490 if ( tmpStr1.getLength() != tmpStr2.getLength() ) { 491 // return number of matched code points so far 492 nMatch1 = (i <= offset1.getLength()) ? offset1[i-1] + 1 : i; 493 nMatch2 = (i <= offset2.getLength()) ? offset2[i-1] + 1 : i; 494 return sal_False; 495 } else { 496 nMatch1 = nCount1; 497 nMatch2 = nCount2; 498 return sal_True; 499 } 500 } 501 502 #define MaxOutput 2 503 504 Sequence< OUString > SAL_CALL 505 TransliterationImpl::getRange(const Sequence< OUString > &inStrs, 506 const sal_Int32 length, sal_Int16 _numCascade) throw(RuntimeException) 507 { 508 if (_numCascade >= numCascade || ! bodyCascade[_numCascade].is()) 509 return inStrs; 510 511 sal_Int32 j_tmp = 0; 512 Sequence< OUString > ostr(MaxOutput*length); 513 for (sal_Int32 j = 0; j < length; j+=2) { 514 const Sequence< OUString >& temp = bodyCascade[_numCascade]->transliterateRange(inStrs[j], inStrs[j+1]); 515 516 for ( sal_Int32 k = 0; k < temp.getLength(); k++) { 517 if ( j_tmp >= MaxOutput*length ) throw ERROR; 518 ostr[j_tmp++] = temp[k]; 519 } 520 } 521 ostr.realloc(j_tmp); 522 523 return this->getRange(ostr, j_tmp, ++_numCascade); 524 } 525 526 527 Sequence< OUString > SAL_CALL 528 TransliterationImpl::transliterateRange( const OUString& str1, const OUString& str2 ) 529 throw(RuntimeException) 530 { 531 if (numCascade == 1) 532 return bodyCascade[0]->transliterateRange(str1, str2); 533 534 Sequence< OUString > ostr(2); 535 ostr[0] = str1; 536 ostr[1] = str2; 537 538 return this->getRange(ostr, 2, 0); 539 } 540 541 542 sal_Int32 SAL_CALL 543 TransliterationImpl::compareSubstring( 544 const OUString& str1, sal_Int32 off1, sal_Int32 len1, 545 const OUString& str2, sal_Int32 off2, sal_Int32 len2) 546 throw(RuntimeException) 547 { 548 if (caseignoreOnly && caseignore.is()) 549 return caseignore->compareSubstring(str1, off1, len1, str2, off2, len2); 550 551 Sequence <sal_Int32> offset; 552 553 OUString in_str1 = this->transliterate(str1, off1, len1, offset); 554 OUString in_str2 = this->transliterate(str2, off2, len2, offset); 555 const sal_Unicode* unistr1 = in_str1.getStr(); 556 const sal_Unicode* unistr2 = in_str2.getStr(); 557 sal_Int32 strlen1 = in_str1.getLength(); 558 sal_Int32 strlen2 = in_str2.getLength(); 559 560 while (strlen1 && strlen2) { 561 if (*unistr1 != *unistr2) 562 return *unistr1 > *unistr2 ? 1 : -1; 563 564 unistr1++; unistr2++; strlen1--; strlen2--; 565 } 566 return strlen1 == strlen2 ? 0 : (strlen1 > strlen2 ? 1 : -1); 567 } 568 569 570 sal_Int32 SAL_CALL 571 TransliterationImpl::compareString(const OUString& str1, const OUString& str2 ) throw (RuntimeException) 572 { 573 if (caseignoreOnly && caseignore.is()) 574 return caseignore->compareString(str1, str2); 575 else 576 return this->compareSubstring(str1, 0, str1.getLength(), str2, 0, str2.getLength()); 577 } 578 579 580 void 581 TransliterationImpl::clear() 582 { 583 for (sal_Int32 i = 0; i < numCascade; i++) 584 if (bodyCascade[i].is()) 585 bodyCascade[i].clear(); 586 numCascade = 0; 587 caseignore.clear(); 588 caseignoreOnly = sal_True; 589 } 590 591 void TransliterationImpl::loadBody( OUString &implName, Reference<XExtendedTransliteration>& body ) 592 throw (RuntimeException) 593 { 594 ::osl::MutexGuard guard(lastTransBody.mutex); 595 596 if (implName.equals(lastTransBody.Name)) 597 { 598 // Use the cached body instead of going through the expensive looping again. 599 body = lastTransBody.Body; 600 return; 601 } 602 603 Reference< XContentEnumerationAccess > xEnumAccess( xSMgr, UNO_QUERY ); 604 Reference< XEnumeration > xEnum(xEnumAccess->createContentEnumeration( 605 OUString::createFromAscii(TRLT_SERVICELNAME_L10N))); 606 if (xEnum.is()) { 607 while (xEnum->hasMoreElements()) { 608 Any a = xEnum->nextElement(); 609 Reference< XServiceInfo > xsInfo; 610 if (a >>= xsInfo) { 611 if (implName.equals(xsInfo->getImplementationName())) { 612 Reference< XSingleServiceFactory > xFactory; 613 if (a >>= xFactory) { 614 Reference< XInterface > xI = xFactory->createInstance(); 615 if (xI.is()) { 616 a = xI->queryInterface(::getCppuType(( 617 const Reference<XExtendedTransliteration>*)0)); 618 a >>= body; 619 lastTransBody.Name = implName; 620 lastTransBody.Body = body; 621 return; 622 } 623 } 624 } 625 } 626 } 627 } 628 throw ERROR; 629 } 630 631 sal_Bool SAL_CALL 632 TransliterationImpl::loadModuleByName( const OUString& implName, 633 Reference<XExtendedTransliteration>& body, const Locale& rLocale) throw(RuntimeException) 634 { 635 OUString cname = OUString::createFromAscii(TRLT_IMPLNAME_PREFIX) + implName; 636 loadBody(cname, body); 637 if (body.is()) { 638 body->loadModule((TransliterationModules)0, rLocale); // toUpper/toLoad need rLocale 639 640 // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed 641 for (sal_Int16 i = 0; i < 3; i++) { 642 if (implName.compareToAscii(TMlist[i].implName) == 0) { 643 if (i == 0) // current module is caseignore 644 body->loadModule(TMlist[0].tm, rLocale); // caseingore need to setup module name 645 if (! caseignore.is()) { 646 OUString bname = OUString::createFromAscii(TRLT_IMPLNAME_PREFIX) + 647 OUString::createFromAscii(TMlist[0].implName); 648 loadBody(bname, caseignore); 649 } 650 if (caseignore.is()) 651 caseignore->loadModule(TMlist[i].tm, rLocale); 652 return sal_True; 653 } 654 } 655 caseignoreOnly = sal_False; // has other module than just ignore case/kana/width 656 } 657 return body.is(); 658 } 659 660 const sal_Char cTrans[] = "com.sun.star.i18n.Transliteration"; 661 662 OUString SAL_CALL 663 TransliterationImpl::getImplementationName() throw( RuntimeException ) 664 { 665 return OUString::createFromAscii(cTrans); 666 } 667 668 669 sal_Bool SAL_CALL 670 TransliterationImpl::supportsService(const OUString& rServiceName) throw( RuntimeException ) 671 { 672 return !rServiceName.compareToAscii(cTrans); 673 } 674 675 Sequence< OUString > SAL_CALL 676 TransliterationImpl::getSupportedServiceNames(void) throw( RuntimeException ) 677 { 678 Sequence< OUString > aRet(1); 679 aRet[0] = OUString::createFromAscii(cTrans); 680 return aRet; 681 } 682 683 } } } } 684