Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / i18npool / source / transliteration / transliterationImpl.cxx
blob195f7a7896438076fe8e3b5703fcdd0048573c7f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <transliterationImpl.hxx>
22 #include <servicename.hxx>
24 #include <com/sun/star/i18n/LocaleData2.hpp>
25 #include <com/sun/star/i18n/TransliterationType.hpp>
26 #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
28 #include <comphelper/sequence.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <rtl/instance.hxx>
31 #include <rtl/ustring.hxx>
33 #include <algorithm>
34 #include <numeric>
36 using namespace com::sun::star::uno;
37 using namespace com::sun::star::i18n;
38 using namespace com::sun::star::lang;
41 namespace i18npool {
43 #define ERROR RuntimeException()
45 #define TmItem1( name ) \
46 {TransliterationModules_##name, TransliterationModulesNew_##name, #name}
48 #define TmItem2( name ) \
49 {TransliterationModules(0), TransliterationModulesNew_##name, #name}
51 // Ignore Module list
52 static struct TMlist {
53 TransliterationModules tm;
54 TransliterationModulesNew tmn;
55 const sal_Char *implName;
56 } const TMlist[] = { // Modules ModulesNew
57 TmItem1 (IGNORE_CASE), // 0. (1<<8 256) (7)
58 TmItem1 (IGNORE_WIDTH), // 1. (1<<9 512) (8)
59 TmItem1 (IGNORE_KANA), // 2. (1<<10 1024) (9)
60 // No enum define for this trans. application has to use impl name to load it
61 // TmItem1 (IGNORE_CASE_SIMPLE), // (1<<11 1024) (66)
63 TmItem1 (ignoreTraditionalKanji_ja_JP), // 3. (1<<12 4096) (10)
64 TmItem1 (ignoreTraditionalKana_ja_JP), // 4. (1<<13 8192) (11)
65 TmItem1 (ignoreMinusSign_ja_JP), // 5. (1<<13 16384) (12)
66 TmItem1 (ignoreIterationMark_ja_JP), // 6. (1<<14 32768) (13)
67 TmItem1 (ignoreSeparator_ja_JP), // 7. (1<<15 65536) (14)
68 TmItem1 (ignoreSize_ja_JP), // 15. (1<<23 16777216) (22)
69 TmItem1 (ignoreMiddleDot_ja_JP), // 17. (1<<25 67108864) (24)
70 TmItem1 (ignoreSpace_ja_JP), // 18. (1<<26 134217728) (25)
71 TmItem1 (ignoreZiZu_ja_JP), // 8. (1<<16 131072) (15)
72 TmItem1 (ignoreBaFa_ja_JP), // 9. (1<<17 262144) (16)
73 TmItem1 (ignoreTiJi_ja_JP), // 10. (1<<18 524288) (17)
74 TmItem1 (ignoreHyuByu_ja_JP), // 11. (1<<19 1048576) (18)
75 TmItem1 (ignoreSeZe_ja_JP), // 12. (1<<20 2097152) (19)
76 TmItem1 (ignoreIandEfollowedByYa_ja_JP), // 13. (1<<21 4194304) (20)
77 TmItem1 (ignoreKiKuFollowedBySa_ja_JP), // 14. (1<<22 8388608) (21)
78 TmItem1 (ignoreProlongedSoundMark_ja_JP), // 16. (1<<24 33554432) (23)
80 TmItem1 (UPPERCASE_LOWERCASE), // 19. (1) (1)
81 TmItem1 (LOWERCASE_UPPERCASE), // 20. (2) (2)
82 TmItem1 (HALFWIDTH_FULLWIDTH), // 21. (3) (3)
83 TmItem1 (FULLWIDTH_HALFWIDTH), // 22. (4) (4)
84 TmItem1 (KATAKANA_HIRAGANA), // 23. (5) (5)
85 TmItem1 (HIRAGANA_KATAKANA), // 24. (6) (6)
87 TmItem1 (smallToLarge_ja_JP), // 25. (1<<27 268435456) (26)
88 TmItem1 (largeToSmall_ja_JP), // 26. (1<<28 536870912) (27)
89 TmItem2 (NumToTextLower_zh_CN), // 27. () (28)
90 TmItem2 (NumToTextUpper_zh_CN), // 28. () (29)
91 TmItem2 (NumToTextLower_zh_TW), // 29. () (30)
92 TmItem2 (NumToTextUpper_zh_TW), // 30. () (31)
93 TmItem2 (NumToTextFormalHangul_ko), // 31. () (32)
94 TmItem2 (NumToTextFormalLower_ko), // 32. () (33)
95 TmItem2 (NumToTextFormalUpper_ko), // 33. () (34)
96 TmItem2 (NumToTextInformalHangul_ko), // 34. () (35)
97 TmItem2 (NumToTextInformalLower_ko), // 35. () (36)
98 TmItem2 (NumToTextInformalUpper_ko), // 36. () (37)
99 TmItem2 (NumToCharLower_zh_CN), // 37. () (38)
100 TmItem2 (NumToCharUpper_zh_CN), // 38. () (39)
101 TmItem2 (NumToCharLower_zh_TW), // 39. () (40)
102 TmItem2 (NumToCharUpper_zh_TW), // 40. () (41)
103 TmItem2 (NumToCharHangul_ko), // 41. () (42)
104 TmItem2 (NumToCharLower_ko), // 42. () (43)
105 TmItem2 (NumToCharUpper_ko), // 43. () (44)
106 TmItem2 (NumToCharFullwidth), // 44. () (45)
107 TmItem2 (NumToCharKanjiShort_ja_JP), // 45. () (46)
108 TmItem2 (TextToNumLower_zh_CN), // 46. () (47)
109 TmItem2 (TextToNumUpper_zh_CN), // 47. () (48)
110 TmItem2 (TextToNumLower_zh_TW), // 48. () (49)
111 TmItem2 (TextToNumUpper_zh_TW), // 49. () (50)
112 TmItem2 (TextToNumFormalHangul_ko), // 50. () (51)
113 TmItem2 (TextToNumFormalLower_ko), // 51. () (52)
114 TmItem2 (TextToNumFormalUpper_ko), // 52. () (53)
115 TmItem2 (TextToNumInformalHangul_ko), // 53. () (54)
116 TmItem2 (TextToNumInformalLower_ko), // 54. () (55)
117 TmItem2 (TextToNumInformalUpper_ko), // 55. () (56)
119 TmItem2 (CharToNumLower_zh_CN), // 56. () (59)
120 TmItem2 (CharToNumUpper_zh_CN), // 57. () (60)
121 TmItem2 (CharToNumLower_zh_TW), // 58. () (61)
122 TmItem2 (CharToNumUpper_zh_TW), // 59. () (62)
123 TmItem2 (CharToNumHangul_ko), // 60. () (63)
124 TmItem2 (CharToNumLower_ko), // 61. () (64)
125 TmItem2 (CharToNumUpper_ko), // 62. () (65)
127 // no enum defined for these trans. application has to use impl name to load them
128 // TmItem2 (NumToCharArabic_Indic), // () (67)
129 // TmItem2 (NumToCharEstern_Arabic_Indic),// () (68)
130 // TmItem2 (NumToCharIndic), // () (69)
131 // TmItem2 (NumToCharThai), // () (70)
132 {TransliterationModules(0), TransliterationModulesNew(0), nullptr}
135 // Constructor/Destructor
136 TransliterationImpl::TransliterationImpl(const Reference <XComponentContext>& xContext) : mxContext(xContext)
138 numCascade = 0;
139 caseignoreOnly = true;
141 mxLocaledata.set(LocaleData2::create(xContext));
144 TransliterationImpl::~TransliterationImpl()
146 mxLocaledata.clear();
147 clear();
151 // Methods
152 OUString SAL_CALL
153 TransliterationImpl::getName()
155 if (numCascade == 1 && bodyCascade[0].is())
156 return bodyCascade[0]->getName();
157 if (numCascade < 1)
158 return ( OUString("Not Loaded"));
159 throw ERROR;
162 sal_Int16 SAL_CALL
163 TransliterationImpl::getType()
165 if (numCascade > 1)
166 return (TransliterationType::CASCADE|TransliterationType::IGNORE);
167 if (numCascade > 0 && bodyCascade[0].is())
168 return bodyCascade[0]->getType();
169 throw ERROR;
172 static TransliterationModules operator&(TransliterationModules lhs, TransliterationModules rhs) {
173 return TransliterationModules(sal_Int32(lhs) & sal_Int32(rhs));
175 static TransliterationModules operator|(TransliterationModules lhs, TransliterationModules rhs) {
176 return TransliterationModules(sal_Int32(lhs) | sal_Int32(rhs));
179 void SAL_CALL
180 TransliterationImpl::loadModule( TransliterationModules modType, const Locale& rLocale )
182 clear();
183 if (bool(modType & TransliterationModules_IGNORE_MASK) &&
184 bool(modType & TransliterationModules_NON_IGNORE_MASK))
186 throw ERROR;
187 } else if (bool(modType & TransliterationModules_IGNORE_MASK)) {
188 #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \
189 TransliterationModules_IGNORE_WIDTH | \
190 TransliterationModules_IGNORE_KANA)
191 TransliterationModules mask = ((modType & TransliterationModules_IGNORE_CASE_MASK) == modType) ?
192 TransliterationModules_IGNORE_CASE_MASK : TransliterationModules_IGNORE_MASK;
193 for (sal_Int16 i = 0; bool(TMlist[i].tm & mask); i++) {
194 if (bool(modType & TMlist[i].tm))
195 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName),
196 bodyCascade[numCascade], rLocale))
197 numCascade++;
199 // additional transliterations from TranslationModuleExtra (we cannot extend TransliterationModule)
200 if (bool(modType & TransliterationModules(TransliterationModulesExtra::IGNORE_DIACRITICS_CTL)))
202 if (loadModuleByName("ignoreDiacritics_CTL", bodyCascade[numCascade], rLocale))
203 numCascade++;
205 if (bool(modType & TransliterationModules(TransliterationModulesExtra::IGNORE_KASHIDA_CTL)))
206 if (loadModuleByName("ignoreKashida_CTL", bodyCascade[numCascade], rLocale))
207 numCascade++;
209 } else if (bool(modType & TransliterationModules_NON_IGNORE_MASK)) {
210 for (sal_Int16 i = 0; bool(TMlist[i].tm); i++) {
211 if (TMlist[i].tm == modType) {
212 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), bodyCascade[numCascade], rLocale))
213 numCascade++;
214 break;
220 void SAL_CALL
221 TransliterationImpl::loadModuleNew( const Sequence < TransliterationModulesNew > & modType, const Locale& rLocale )
223 clear();
224 TransliterationModules mask = TransliterationModules_END_OF_MODULE;
225 sal_Int32 count = modType.getLength();
226 if (count > maxCascade)
227 throw ERROR; // could not handle more than maxCascade
228 for (sal_Int32 i = 0; i < count; i++) {
229 for (sal_Int16 j = 0; bool(TMlist[j].tmn); j++) {
230 if (TMlist[j].tmn == modType[i]) {
231 if (mask == TransliterationModules_END_OF_MODULE)
232 mask = bool(TMlist[i].tm) && bool(TMlist[i].tm & TransliterationModules_IGNORE_MASK) ?
233 TransliterationModules_IGNORE_MASK : TransliterationModules_NON_IGNORE_MASK;
234 else if (mask == TransliterationModules_IGNORE_MASK &&
235 (TMlist[i].tm&TransliterationModules_IGNORE_MASK) == TransliterationModules_END_OF_MODULE)
236 throw ERROR; // could not mess up ignore trans. with non_ignore trans.
237 if (loadModuleByName(OUString::createFromAscii(TMlist[j].implName), bodyCascade[numCascade], rLocale))
238 numCascade++;
239 break;
245 void SAL_CALL
246 TransliterationImpl::loadModuleByImplName(const OUString& implName, const Locale& rLocale)
248 clear();
249 if (loadModuleByName(implName, bodyCascade[numCascade], rLocale))
250 numCascade++;
254 void SAL_CALL
255 TransliterationImpl::loadModulesByImplNames(const Sequence< OUString >& implNameList, const Locale& rLocale )
257 if (implNameList.getLength() > maxCascade || implNameList.getLength() <= 0)
258 throw ERROR;
260 clear();
261 for (const auto& rName : implNameList)
262 if (loadModuleByName(rName, bodyCascade[numCascade], rLocale))
263 numCascade++;
267 Sequence<OUString> SAL_CALL
268 TransliterationImpl::getAvailableModules( const Locale& rLocale, sal_Int16 sType )
270 const Sequence<OUString> &translist = mxLocaledata->getTransliterations(rLocale);
271 std::vector<OUString> r;
272 r.reserve(translist.getLength());
273 Reference<XExtendedTransliteration> body;
274 for (const auto& rTrans : translist)
276 if (loadModuleByName(rTrans, body, rLocale)) {
277 if (body->getType() & sType)
278 r.push_back(rTrans);
279 body.clear();
282 return comphelper::containerToSequence(r);
286 OUString SAL_CALL
287 TransliterationImpl::transliterate( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
288 Sequence< sal_Int32 >& offset )
290 if (numCascade == 0)
291 return inStr;
293 if (offset.getLength() != nCount)
294 offset.realloc(nCount);
295 if (numCascade == 1)
297 if ( startPos == 0 && nCount == inStr.getLength() )
298 return bodyCascade[0]->transliterate( inStr, 0, nCount, offset);
299 else
301 OUString tmpStr = inStr.copy(startPos, nCount);
302 tmpStr = bodyCascade[0]->transliterate(tmpStr, 0, nCount, offset);
303 if ( startPos )
305 for (sal_Int32 & j : offset)
306 j += startPos;
308 return tmpStr;
311 else
313 OUString tmpStr = inStr.copy(startPos, nCount);
315 std::iota(offset.begin(), offset.end(), startPos);
317 sal_Int16 from = 0, to = 1;
318 Sequence<sal_Int32> off[2];
320 off[to] = offset;
321 off[from].realloc(nCount);
322 for (sal_Int32 i = 0; i < numCascade; i++) {
323 tmpStr = bodyCascade[i]->transliterate(tmpStr, 0, nCount, off[from]);
325 nCount = tmpStr.getLength();
327 assert(off[from].getLength() == nCount);
328 std::swap(from, to);
329 // tdf#89665: don't use operator[] to write - too slow!
330 // interestingly gcc 4.9 -Os won't even inline the const operator[]
331 sal_Int32 const*const pFrom(off[from].getConstArray());
332 sal_Int32 *const pTo(off[to].getArray());
333 for (sal_Int32 j = 0; j < nCount; j++)
335 assert(pTo[j] < off[from].getLength());
336 pTo[j] = pFrom[pTo[j]];
339 offset = off[to];
340 return tmpStr;
345 OUString SAL_CALL
346 TransliterationImpl::folding( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
347 Sequence< sal_Int32 >& offset )
349 if (numCascade == 0)
350 return inStr;
352 if (offset.getLength() != nCount)
353 offset.realloc(nCount);
354 if (numCascade == 1)
356 if ( startPos == 0 && nCount == inStr.getLength() )
357 return bodyCascade[0]->folding( inStr, 0, nCount, offset);
358 else
360 OUString tmpStr = inStr.copy(startPos, nCount);
361 tmpStr = bodyCascade[0]->folding(tmpStr, 0, nCount, offset);
362 if ( startPos )
364 for (sal_Int32 & j : offset)
365 j += startPos;
367 return tmpStr;
370 else
372 OUString tmpStr = inStr.copy(startPos, nCount);
374 std::iota(offset.begin(), offset.end(), startPos);
376 sal_Int16 from = 0, to = 1;
377 Sequence<sal_Int32> off[2];
379 off[to] = offset;
380 for (sal_Int32 i = 0; i < numCascade; i++) {
381 tmpStr = bodyCascade[i]->folding(tmpStr, 0, nCount, off[from]);
383 nCount = tmpStr.getLength();
385 std::swap(from, to);
386 for (sal_Int32 j = 0; j < nCount; j++)
387 off[to][j] = off[from][off[to][j]];
389 offset = off[to];
390 return tmpStr;
394 OUString SAL_CALL
395 TransliterationImpl::transliterateString2String( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount )
397 if (numCascade == 0)
398 return inStr;
399 else if (numCascade == 1)
400 return bodyCascade[0]->transliterateString2String( inStr, startPos, nCount);
401 else {
402 OUString tmpStr = bodyCascade[0]->transliterateString2String(inStr, startPos, nCount);
404 for (sal_Int32 i = 1; i < numCascade; i++)
405 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
406 return tmpStr;
410 OUString SAL_CALL
411 TransliterationImpl::transliterateChar2String( sal_Unicode inChar )
413 if (numCascade == 0)
414 return OUString(&inChar, 1);
415 else if (numCascade == 1)
416 return bodyCascade[0]->transliterateChar2String( inChar);
417 else {
418 OUString tmpStr = bodyCascade[0]->transliterateChar2String(inChar);
420 for (sal_Int32 i = 1; i < numCascade; i++)
421 tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
422 return tmpStr;
426 sal_Unicode SAL_CALL
427 TransliterationImpl::transliterateChar2Char( sal_Unicode inChar )
429 sal_Unicode tmpChar = inChar;
430 for (sal_Int32 i = 0; i < numCascade; i++)
431 tmpChar = bodyCascade[i]->transliterateChar2Char(tmpChar);
432 return tmpChar;
436 sal_Bool SAL_CALL
437 TransliterationImpl::equals(
438 const OUString& str1, sal_Int32 pos1, sal_Int32 nCount1, sal_Int32& nMatch1,
439 const OUString& str2, sal_Int32 pos2, sal_Int32 nCount2, sal_Int32& nMatch2)
441 // since this is an API function make it user fail safe
442 if ( nCount1 < 0 ) {
443 pos1 += nCount1;
444 nCount1 = -nCount1;
446 if ( nCount2 < 0 ) {
447 pos2 += nCount2;
448 nCount2 = -nCount2;
450 if ( !nCount1 || !nCount2 ||
451 pos1 >= str1.getLength() || pos2 >= str2.getLength() ||
452 pos1 < 0 || pos2 < 0 ) {
453 nMatch1 = nMatch2 = 0;
454 // two empty strings return true, else false
455 return !nCount1 && !nCount2 && pos1 == str1.getLength() && pos2 == str2.getLength();
457 if ( pos1 + nCount1 > str1.getLength() )
458 nCount1 = str1.getLength() - pos1;
459 if ( pos2 + nCount2 > str2.getLength() )
460 nCount2 = str2.getLength() - pos2;
462 if (caseignoreOnly && caseignore.is())
463 return caseignore->equals(str1, pos1, nCount1, nMatch1, str2, pos2, nCount2, nMatch2);
465 Sequence<sal_Int32> offset1, offset2;
467 OUString tmpStr1 = folding(str1, pos1, nCount1, offset1);
468 OUString tmpStr2 = folding(str2, pos2, nCount2, offset2);
469 // Length of offset1 and offset2 may still be 0 if there was no folding
470 // necessary!
472 const sal_Unicode *p1 = tmpStr1.getStr();
473 const sal_Unicode *p2 = tmpStr2.getStr();
474 sal_Int32 i, nLen = ::std::min( tmpStr1.getLength(), tmpStr2.getLength());
475 for (i = 0; i < nLen; ++i, ++p1, ++p2 ) {
476 if (*p1 != *p2) {
477 // return number of matched code points so far
478 nMatch1 = (i < offset1.getLength()) ? offset1.getConstArray()[i] : i;
479 nMatch2 = (i < offset2.getLength()) ? offset2.getConstArray()[i] : i;
480 return false;
483 // i==nLen
484 if ( tmpStr1.getLength() != tmpStr2.getLength() ) {
485 // return number of matched code points so far
486 nMatch1 = (i <= offset1.getLength()) ? offset1.getConstArray()[i-1] + 1 : i;
487 nMatch2 = (i <= offset2.getLength()) ? offset2.getConstArray()[i-1] + 1 : i;
488 return false;
489 } else {
490 nMatch1 = nCount1;
491 nMatch2 = nCount2;
492 return true;
496 Sequence< OUString >
497 TransliterationImpl::getRange(const Sequence< OUString > &inStrs,
498 const sal_Int32 length, sal_Int16 _numCascade)
500 if (_numCascade >= numCascade || ! bodyCascade[_numCascade].is())
501 return inStrs;
503 sal_Int32 j_tmp = 0;
504 constexpr sal_Int32 nMaxOutput = 2;
505 const sal_Int32 nMaxOutputLength = nMaxOutput*length;
506 std::vector<OUString> ostr;
507 ostr.reserve(nMaxOutputLength);
508 for (sal_Int32 j = 0; j < length; j+=2) {
509 const Sequence< OUString >& temp = bodyCascade[_numCascade]->transliterateRange(inStrs[j], inStrs[j+1]);
511 for (const auto& rStr : temp) {
512 if ( j_tmp++ >= nMaxOutputLength ) throw ERROR;
513 ostr.push_back(rStr);
517 return getRange(comphelper::containerToSequence(ostr), j_tmp, ++_numCascade);
521 Sequence< OUString > SAL_CALL
522 TransliterationImpl::transliterateRange( const OUString& str1, const OUString& str2 )
524 if (numCascade == 1)
525 return bodyCascade[0]->transliterateRange(str1, str2);
527 Sequence< OUString > ostr{ str1, str2 };
529 return getRange(ostr, 2, 0);
533 sal_Int32 SAL_CALL
534 TransliterationImpl::compareSubstring(
535 const OUString& str1, sal_Int32 off1, sal_Int32 len1,
536 const OUString& str2, sal_Int32 off2, sal_Int32 len2)
538 if (caseignoreOnly && caseignore.is())
539 return caseignore->compareSubstring(str1, off1, len1, str2, off2, len2);
541 Sequence <sal_Int32> offset;
543 OUString in_str1 = transliterate(str1, off1, len1, offset);
544 OUString in_str2 = transliterate(str2, off2, len2, offset);
545 const sal_Unicode* unistr1 = in_str1.getStr();
546 const sal_Unicode* unistr2 = in_str2.getStr();
547 sal_Int32 strlen1 = in_str1.getLength();
548 sal_Int32 strlen2 = in_str2.getLength();
550 while (strlen1 && strlen2) {
551 if (*unistr1 != *unistr2)
552 return *unistr1 > *unistr2 ? 1 : -1;
554 unistr1++; unistr2++; strlen1--; strlen2--;
556 return strlen1 == strlen2 ? 0 : (strlen1 > strlen2 ? 1 : -1);
560 sal_Int32 SAL_CALL
561 TransliterationImpl::compareString(const OUString& str1, const OUString& str2 )
563 if (caseignoreOnly && caseignore.is())
564 return caseignore->compareString(str1, str2);
565 else
566 return compareSubstring(str1, 0, str1.getLength(), str2, 0, str2.getLength());
570 void
571 TransliterationImpl::clear()
573 for (sal_Int32 i = 0; i < numCascade; i++)
574 if (bodyCascade[i].is())
575 bodyCascade[i].clear();
576 numCascade = 0;
577 caseignore.clear();
578 caseignoreOnly = true;
581 namespace
583 /** structure to cache the last transliteration body used. */
584 struct TransBody
586 OUString Name;
587 css::uno::Reference< css::i18n::XExtendedTransliteration > Body;
589 class theTransBodyMutex : public rtl::Static<osl::Mutex, theTransBodyMutex> {};
592 void TransliterationImpl::loadBody( OUString const &implName, Reference<XExtendedTransliteration>& body )
594 assert(!implName.isEmpty());
595 ::osl::MutexGuard guard(theTransBodyMutex::get());
596 static TransBody lastTransBody;
597 if (implName != lastTransBody.Name)
599 lastTransBody.Body.set(
600 mxContext->getServiceManager()->createInstanceWithContext(implName, mxContext), UNO_QUERY_THROW);
601 lastTransBody.Name = implName;
603 body = lastTransBody.Body;
606 bool
607 TransliterationImpl::loadModuleByName( const OUString& implName,
608 Reference<XExtendedTransliteration>& body, const Locale& rLocale)
610 OUString cname = TRLT_IMPLNAME_PREFIX + implName;
611 loadBody(cname, body);
612 if (body.is()) {
613 body->loadModule(TransliterationModules(0), rLocale); // toUpper/toLoad need rLocale
615 // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed
616 for (sal_Int16 i = 0; i < 3; i++) {
617 if (implName.equalsAscii(TMlist[i].implName)) {
618 if (i == 0) // current module is caseignore
619 body->loadModule(TMlist[0].tm, rLocale); // caseignore need to setup module name
620 if (! caseignore.is()) {
621 OUString bname = TRLT_IMPLNAME_PREFIX +
622 OUString::createFromAscii(TMlist[0].implName);
623 loadBody(bname, caseignore);
625 if (caseignore.is())
626 caseignore->loadModule(TMlist[i].tm, rLocale);
627 return true;
630 caseignoreOnly = false; // has other module than just ignore case/kana/width
632 return body.is();
635 OUString SAL_CALL
636 TransliterationImpl::getImplementationName()
638 return "com.sun.star.i18n.Transliteration";
641 sal_Bool SAL_CALL
642 TransliterationImpl::supportsService(const OUString& rServiceName)
644 return cppu::supportsService(this, rServiceName);
647 Sequence< OUString > SAL_CALL
648 TransliterationImpl::getSupportedServiceNames()
650 return { "com.sun.star.i18n.Transliteration" };
655 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
656 com_sun_star_i18n_Transliteration_get_implementation(
657 css::uno::XComponentContext *context,
658 css::uno::Sequence<css::uno::Any> const &)
660 return cppu::acquire(new i18npool::TransliterationImpl(context));
663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */