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