merged tag ooo/OOO330_m14
[LibreOffice.git] / i18npool / source / indexentry / indexentrysupplier_default.cxx
blob7de3f540eaa79026bee4c9f62b652ac68d7ccf0d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 #include <indexentrysupplier_default.hxx>
31 #include <localedata.hxx>
32 #include <i18nutil/unicode.hxx>
33 #include <com/sun/star/i18n/CollatorOptions.hpp>
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::lang;
37 using namespace ::rtl;
39 namespace com { namespace sun { namespace star { namespace i18n {
41 IndexEntrySupplier_Unicode::IndexEntrySupplier_Unicode(
42 const com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory >& rxMSF ) :
43 IndexEntrySupplier_Common(rxMSF)
45 implementationName = "com.sun.star.i18n.IndexEntrySupplier_Unicode";
46 index = new Index(rxMSF);
49 IndexEntrySupplier_Unicode::~IndexEntrySupplier_Unicode()
51 delete index;
54 sal_Bool SAL_CALL IndexEntrySupplier_Unicode::loadAlgorithm( const lang::Locale& rLocale,
55 const OUString& rAlgorithm, sal_Int32 collatorOptions ) throw (RuntimeException)
57 index->init(rLocale, rAlgorithm);
58 return IndexEntrySupplier_Common::loadAlgorithm(rLocale, rAlgorithm, collatorOptions);
61 OUString SAL_CALL IndexEntrySupplier_Unicode::getIndexKey( const OUString& rIndexEntry,
62 const OUString& rPhoneticEntry, const lang::Locale& rLocale ) throw (RuntimeException)
64 return index->getIndexDescription(getEntry(rIndexEntry, rPhoneticEntry, rLocale));
67 sal_Int16 SAL_CALL IndexEntrySupplier_Unicode::compareIndexEntry(
68 const OUString& rIndexEntry1, const OUString& rPhoneticEntry1, const lang::Locale& rLocale1,
69 const OUString& rIndexEntry2, const OUString& rPhoneticEntry2, const lang::Locale& rLocale2 )
70 throw (RuntimeException)
72 sal_Int16 result =
73 index->getIndexWeight(getEntry(rIndexEntry1, rPhoneticEntry1, rLocale1)) -
74 index->getIndexWeight(getEntry(rIndexEntry2, rPhoneticEntry2, rLocale2));
75 if (result == 0)
76 return IndexEntrySupplier_Common::compareIndexEntry(
77 rIndexEntry1, rPhoneticEntry1, rLocale1,
78 rIndexEntry2, rPhoneticEntry2, rLocale2);
79 return result > 0 ? 1 : -1;
82 OUString SAL_CALL IndexEntrySupplier_Unicode::getIndexCharacter( const OUString& rIndexEntry,
83 const lang::Locale& rLocale, const OUString& rAlgorithm ) throw (RuntimeException) {
85 if (loadAlgorithm( rLocale, rAlgorithm, CollatorOptions::CollatorOptions_IGNORE_CASE_ACCENT))
86 return index->getIndexDescription(rIndexEntry);
87 else
88 return IndexEntrySupplier_Common::getIndexCharacter(rIndexEntry, rLocale, rAlgorithm);
91 IndexTable::IndexTable()
93 table = NULL;
96 IndexTable::~IndexTable()
98 if (table) free(table);
101 void IndexTable::init(sal_Unicode start_, sal_Unicode end_, IndexKey *keys, sal_Int16 key_count, Index *index)
103 start=start_;
104 end=end_;
105 table = (sal_uInt8*) malloc((end-start+1)*sizeof(sal_uInt8));
106 for (sal_Unicode i = start; i <= end; i++) {
107 sal_Int16 j;
108 for (j = 0; j < key_count; j++) {
109 if (keys[j].key > 0 && (i == keys[j].key || index->compare(i, keys[j].key) == 0)) {
110 table[i-start] = sal::static_int_cast<sal_uInt8>(j);
111 break;
114 if (j == key_count)
115 table[i-start] = 0xFF;
119 Index::Index(const com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory >& rxMSF)
121 collator = new CollatorImpl(rxMSF);
124 Index::~Index()
126 delete collator;
129 sal_Int16 Index::compare(sal_Unicode c1, sal_Unicode c2)
131 return sal::static_int_cast<sal_Int16>( collator->compareString(OUString(&c1, 1), OUString(&c2, 1)) );
134 sal_Int16 Index::getIndexWeight(const OUString& rIndexEntry)
136 sal_Int32 startPos=0;
137 if (skipping_chars.getLength() > 0)
138 while (skipping_chars.indexOf(rIndexEntry[startPos]) >= 0)
139 startPos++;
140 if (mkey_count > 0) {
141 for (sal_Int16 i = 0; i < mkey_count; i++) {
142 sal_Int32 len = keys[mkeys[i]].mkey.getLength();
143 if (collator->compareSubstring(rIndexEntry, startPos, len,
144 keys[mkeys[i]].mkey, 0, len) == 0)
145 return mkeys[i];
148 sal_Unicode code = rIndexEntry[startPos];
149 for (sal_Int16 i = 0; i < table_count; i++) {
150 if (tables[i].start <= code && code <= tables[i].end)
151 return tables[i].table[code-tables[i].start];
153 return 0xFF;
156 OUString Index::getIndexDescription(const OUString& rIndexEntry)
158 sal_Int16 wgt = getIndexWeight(rIndexEntry);
159 if (wgt < MAX_KEYS) {
160 if (keys[wgt].desc.getLength())
161 return keys[wgt].desc;
162 else if (keys[wgt].key > 0)
163 return OUString(&keys[wgt].key, 1);
164 else
165 return keys[wgt].mkey;
167 sal_Int32 nPos=0;
168 sal_uInt32 indexChar=rIndexEntry.iterateCodePoints(&nPos, 0);
169 return OUString(&indexChar, 1);
172 #define LOCALE_EN lang::Locale(OUString::createFromAscii("en"), OUString(), OUString())
174 void Index::makeIndexKeys(const lang::Locale &rLocale, const OUString &algorithm) throw (RuntimeException)
176 OUString keyStr = LocaleData().getIndexKeysByAlgorithm(rLocale, algorithm);
178 if (!keyStr.getLength()) {
179 keyStr = LocaleData().getIndexKeysByAlgorithm(LOCALE_EN,
180 LocaleData().getDefaultIndexAlgorithm(LOCALE_EN));
181 if (!keyStr)
182 throw RuntimeException();
185 sal_Int16 len = sal::static_int_cast<sal_Int16>( keyStr.getLength() );
186 mkey_count=key_count=0;
187 skipping_chars=OUString();
188 sal_Int16 i, j;
190 for (i = 0; i < len && key_count < MAX_KEYS; i++)
192 sal_Unicode curr = keyStr[i];
193 sal_Unicode close = sal_Unicode(')');
195 if (unicode::isWhiteSpace(curr))
196 continue;
198 switch(curr) {
199 case sal_Unicode('-'):
200 if (key_count > 0 && i + 1 < len ) {
201 for (curr = keyStr[++i]; key_count < MAX_KEYS && keys[key_count-1].key < curr; key_count++) {
202 keys[key_count].key = keys[key_count-1].key+1;
203 keys[key_count].desc = OUString();
205 } else
206 throw RuntimeException();
207 break;
208 case sal_Unicode('['):
209 for (i++; i < len && keyStr[i] != sal_Unicode(']'); i++) {
210 if (unicode::isWhiteSpace(keyStr[i])) {
211 continue;
212 } else if (keyStr[i] == sal_Unicode('_')) {
213 for (curr=keyStr[i-1]+1; curr <= keyStr[i+1]; curr++)
214 skipping_chars+=OUString(curr);
215 i+=2;
216 } else {
217 skipping_chars+=OUString(keyStr[i]);
220 break;
221 case sal_Unicode('{'):
222 close = sal_Unicode('}');
223 case sal_Unicode('('):
224 if (key_count > 0) {
225 sal_Int16 end = i+1;
226 for (end=i+1; end < len && keyStr[end] != close; end++) ;
228 if (end >= len) // no found
229 throw RuntimeException();
230 if (close == sal_Unicode(')'))
231 keys[key_count-1].desc = keyStr.copy(i+1, end-i-1);
232 else {
233 mkeys[mkey_count++]=key_count;
234 keys[key_count].key = 0;
235 keys[key_count].mkey = keyStr.copy(i+1, end-i-1);
236 keys[key_count++].desc=OUString();
238 i=end+1;
239 } else
240 throw RuntimeException();
241 break;
242 default:
243 keys[key_count].key = curr;
244 keys[key_count++].desc = OUString();
245 break;
248 for (i = 0; i < mkey_count; i++) {
249 for (j=i+1; j < mkey_count; j++) {
250 if (keys[mkeys[i]].mkey.getLength() < keys[mkeys[j]].mkey.getLength()) {
251 sal_Int16 k = mkeys[i];
252 mkeys[i] = mkeys[j];
253 mkeys[j] = k;
259 void Index::init(const lang::Locale &rLocale, const OUString& algorithm) throw (RuntimeException)
261 makeIndexKeys(rLocale, algorithm);
263 Sequence< UnicodeScript > scriptList = LocaleData().getUnicodeScripts( rLocale );
265 if (scriptList.getLength() == 0) {
266 scriptList = LocaleData().getUnicodeScripts(LOCALE_EN);
267 if (scriptList.getLength() == 0)
268 throw RuntimeException();
271 table_count = sal::static_int_cast<sal_Int16>( scriptList.getLength() );
272 if (table_count > MAX_TABLES)
273 throw RuntimeException();
275 collator->loadCollatorAlgorithm(algorithm, rLocale, CollatorOptions::CollatorOptions_IGNORE_CASE_ACCENT);
276 sal_Int16 j=0;
277 sal_Unicode start = unicode::getUnicodeScriptStart((UnicodeScript)0);
278 sal_Unicode end = unicode::getUnicodeScriptEnd((UnicodeScript)0);
279 for (sal_Int16 i= (scriptList[0] == (UnicodeScript)0) ? 1 : 0; i< scriptList.getLength(); i++) {
280 if (unicode::getUnicodeScriptStart(scriptList[i]) != end+1) {
281 tables[j++].init(start, end, keys, key_count, this);
282 start = unicode::getUnicodeScriptStart(scriptList[i]);
284 end = unicode::getUnicodeScriptEnd(scriptList[i]);
286 tables[j++].init(start, end, keys, key_count, this);
287 table_count = j;
290 } } } }