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 <rtl/ustrbuf.hxx>
28 #include <indexentrysupplier_asian.hxx>
29 #include <data/indexdata_alphanumeric.h>
30 
31 using namespace ::com::sun::star::uno;
32 using namespace ::com::sun::star::lang;
33 using namespace ::rtl;
34 
35 namespace com { namespace sun { namespace star { namespace i18n {
36 
37 extern "C" { static void SAL_CALL thisModule() {} }
38 
39 IndexEntrySupplier_asian::IndexEntrySupplier_asian(
40     const Reference < XMultiServiceFactory >& rxMSF ) : IndexEntrySupplier_Common(rxMSF)
41 {
42 	implementationName = "com.sun.star.i18n.IndexEntrySupplier_asian";
43 #ifdef SAL_DLLPREFIX
44     OUString lib=OUString::createFromAscii(SAL_DLLPREFIX"index_data"SAL_DLLEXTENSION);
45 #else
46     OUString lib=OUString::createFromAscii("index_data"SAL_DLLEXTENSION);
47 #endif
48     hModule = osl_loadModuleRelative(
49         &thisModule, lib.pData, SAL_LOADMODULE_DEFAULT );
50 }
51 
52 IndexEntrySupplier_asian::~IndexEntrySupplier_asian()
53 {
54     if (hModule) osl_unloadModule(hModule);
55 }
56 
57 OUString SAL_CALL
58 IndexEntrySupplier_asian::getIndexCharacter( const OUString& rIndexEntry,
59     const Locale& rLocale, const OUString& rAlgorithm ) throw (RuntimeException)
60 {
61     sal_Int32 i=0;
62     sal_uInt32 ch = rIndexEntry.iterateCodePoints(&i, 0);
63     if (hModule) {
64         OUString get=OUString::createFromAscii("get_indexdata_");
65         sal_uInt16** (*func)(sal_Int16*)=NULL;
66         if (rLocale.Language.equalsAscii("zh") && OUString::createFromAscii("TW HK MO").indexOf(rLocale.Country) >= 0)
67             func=(sal_uInt16** (*)(sal_Int16*))osl_getFunctionSymbol(hModule, (get+rLocale.Language+OUString::createFromAscii("_TW_")+rAlgorithm).pData);
68         if (!func)
69             func=(sal_uInt16** (*)(sal_Int16*))osl_getFunctionSymbol(hModule, (get+rLocale.Language+OUString('_')+rAlgorithm).pData);
70         if (func) {
71             sal_Int16 max_index;
72             sal_uInt16** idx=func(&max_index);
73             if (((sal_Int16)(ch >> 8)) <= max_index) {
74                 sal_uInt16 address=idx[0][ch >> 8];
75                 if (address != 0xFFFF) {
76                     address=idx[1][address+(ch & 0xFF)];
77                     return idx[2] ? OUString(&idx[2][address]) : OUString(address);
78                 }
79             }
80         }
81     }
82     // using alphanumeric index for non-define stirng
83     return OUString(&idxStr[(ch & 0xFFFFFF00) ? 0 : ch], 1);
84 }
85 
86 OUString SAL_CALL
87 IndexEntrySupplier_asian::getIndexKey( const OUString& rIndexEntry,
88     const OUString& rPhoneticEntry, const Locale& rLocale) throw (RuntimeException)
89 {
90     return getIndexCharacter(getEntry(rIndexEntry, rPhoneticEntry, rLocale), rLocale, aAlgorithm);
91 }
92 
93 sal_Int16 SAL_CALL
94 IndexEntrySupplier_asian::compareIndexEntry(
95 	const OUString& rIndexEntry1, const OUString& rPhoneticEntry1, const Locale& rLocale1,
96 	const OUString& rIndexEntry2, const OUString& rPhoneticEntry2, const Locale& rLocale2 )
97 	throw (RuntimeException)
98 {
99     sal_Int32 result = collator->compareString(getEntry(rIndexEntry1, rPhoneticEntry1, rLocale1),
100                                     getEntry(rIndexEntry2, rPhoneticEntry2, rLocale2));
101 
102     // equivalent of phonetic entries does not mean equivalent of index entries.
103     // we have to continue comparing index entry here.
104     if (result == 0 && usePhonetic && rPhoneticEntry1.getLength() > 0 &&
105             rLocale1.Language == rLocale2.Language && rLocale1.Country == rLocale2.Country &&
106             rLocale1.Variant == rLocale2.Variant)
107         result = collator->compareString(rIndexEntry1, rIndexEntry2);
108     return sal::static_int_cast< sal_Int16 >(result); // result in { -1, 0, 1 }
109 }
110 
111 OUString SAL_CALL
112 IndexEntrySupplier_asian::getPhoneticCandidate( const OUString& rIndexEntry,
113         const Locale& rLocale ) throw (RuntimeException)
114 {
115     if (hModule) {
116         sal_uInt16 **(*func)(sal_Int16*)=NULL;
117         const sal_Char *func_name=NULL;
118         if (rLocale.Language.equalsAscii("zh"))
119             func_name=(OUString::createFromAscii("TW HK MO").indexOf(rLocale.Country) >= 0) ?  "get_zh_zhuyin" : "get_zh_pinyin";
120         else if (rLocale.Language.equalsAscii("ko"))
121             func_name="get_ko_phonetic";
122         if (func_name)
123             func=(sal_uInt16 **(*)(sal_Int16*))osl_getFunctionSymbol(hModule, OUString::createFromAscii(func_name).pData);
124         if (func) {
125             OUStringBuffer candidate;
126             sal_Int16 max_index;
127             sal_uInt16** idx=func(&max_index);
128             OUString aIndexEntry=rIndexEntry;
129             for (sal_Int32 i=0,j=0; i < rIndexEntry.getLength(); i=j) {
130                 sal_uInt32 ch = rIndexEntry.iterateCodePoints(&j, 1);
131                 if (((sal_Int16)(ch>>8)) <= max_index) {
132                     sal_uInt16 address = idx[0][ch>>8];
133                     if (address != 0xFFFF) {
134                         address = idx[1][address + (ch & 0xFF)];
135                         if (i > 0 && rLocale.Language.equalsAscii("zh"))
136                             candidate.appendAscii(" ");
137                         if (idx[2])
138                             candidate.append(&idx[2][address]);
139                         else
140                             candidate.append(address);
141                     } else
142                         candidate.appendAscii(" ");
143                 }
144             }
145             return candidate.makeStringAndClear();
146         }
147     }
148     return OUString();
149 }
150 } } } }
151