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