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