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