1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: indexentrysupplier_default.cxx,v $
10 * $Revision: 1.14.22.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_i18npool.hxx"
33 #include <indexentrysupplier_default.hxx>
34 #include <localedata.hxx>
35 #include <i18nutil/unicode.hxx>
36 #include <com/sun/star/i18n/CollatorOptions.hpp>
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::lang
;
40 using namespace ::rtl
;
42 namespace com
{ namespace sun
{ namespace star
{ namespace i18n
{
44 IndexEntrySupplier_Unicode::IndexEntrySupplier_Unicode(
45 const com::sun::star::uno::Reference
< com::sun::star::lang::XMultiServiceFactory
>& rxMSF
) :
46 IndexEntrySupplier_Common(rxMSF
)
48 implementationName
= "com.sun.star.i18n.IndexEntrySupplier_Unicode";
49 index
= new Index(rxMSF
);
52 IndexEntrySupplier_Unicode::~IndexEntrySupplier_Unicode()
57 sal_Bool SAL_CALL
IndexEntrySupplier_Unicode::loadAlgorithm( const lang::Locale
& rLocale
,
58 const OUString
& rAlgorithm
, sal_Int32 collatorOptions
) throw (RuntimeException
)
60 index
->init(rLocale
, rAlgorithm
);
61 return IndexEntrySupplier_Common::loadAlgorithm(rLocale
, rAlgorithm
, collatorOptions
);
64 OUString SAL_CALL
IndexEntrySupplier_Unicode::getIndexKey( const OUString
& rIndexEntry
,
65 const OUString
& rPhoneticEntry
, const lang::Locale
& rLocale
) throw (RuntimeException
)
67 return index
->getIndexDescription(getEntry(rIndexEntry
, rPhoneticEntry
, rLocale
));
70 sal_Int16 SAL_CALL
IndexEntrySupplier_Unicode::compareIndexEntry(
71 const OUString
& rIndexEntry1
, const OUString
& rPhoneticEntry1
, const lang::Locale
& rLocale1
,
72 const OUString
& rIndexEntry2
, const OUString
& rPhoneticEntry2
, const lang::Locale
& rLocale2
)
73 throw (RuntimeException
)
76 index
->getIndexWeight(getEntry(rIndexEntry1
, rPhoneticEntry1
, rLocale1
)) -
77 index
->getIndexWeight(getEntry(rIndexEntry2
, rPhoneticEntry2
, rLocale2
));
79 return IndexEntrySupplier_Common::compareIndexEntry(
80 rIndexEntry1
, rPhoneticEntry1
, rLocale1
,
81 rIndexEntry2
, rPhoneticEntry2
, rLocale2
);
82 return result
> 0 ? 1 : -1;
85 OUString SAL_CALL
IndexEntrySupplier_Unicode::getIndexCharacter( const OUString
& rIndexEntry
,
86 const lang::Locale
& rLocale
, const OUString
& rAlgorithm
) throw (RuntimeException
) {
88 if (loadAlgorithm( rLocale
, rAlgorithm
, CollatorOptions::CollatorOptions_IGNORE_CASE_ACCENT
))
89 return index
->getIndexDescription(rIndexEntry
);
91 return IndexEntrySupplier_Common::getIndexCharacter(rIndexEntry
, rLocale
, rAlgorithm
);
94 IndexTable::IndexTable()
99 IndexTable::~IndexTable()
101 if (table
) free(table
);
104 void IndexTable::init(sal_Unicode start_
, sal_Unicode end_
, IndexKey
*keys
, sal_Int16 key_count
, Index
*index
)
108 table
= (sal_uInt8
*) malloc((end
-start
+1)*sizeof(sal_uInt8
));
109 for (sal_Unicode i
= start
; i
<= end
; i
++) {
111 for (j
= 0; j
< key_count
; j
++) {
112 if (keys
[j
].key
> 0 && (i
== keys
[j
].key
|| index
->compare(i
, keys
[j
].key
) == 0)) {
113 table
[i
-start
] = sal::static_int_cast
<sal_uInt8
>(j
);
118 table
[i
-start
] = 0xFF;
122 Index::Index(const com::sun::star::uno::Reference
< com::sun::star::lang::XMultiServiceFactory
>& rxMSF
)
124 collator
= new CollatorImpl(rxMSF
);
132 sal_Int16
Index::compare(sal_Unicode c1
, sal_Unicode c2
)
134 return sal::static_int_cast
<sal_Int16
>( collator
->compareString(OUString(&c1
, 1), OUString(&c2
, 1)) );
137 sal_Int16
Index::getIndexWeight(const OUString
& rIndexEntry
)
139 sal_Int32 startPos
=0;
140 if (skipping_chars
.getLength() > 0)
141 while (skipping_chars
.indexOf(rIndexEntry
[startPos
]) >= 0)
143 if (mkey_count
> 0) {
144 for (sal_Int16 i
= 0; i
< mkey_count
; i
++) {
145 sal_Int32 len
= keys
[mkeys
[i
]].mkey
.getLength();
146 if (collator
->compareSubstring(rIndexEntry
, startPos
, len
,
147 keys
[mkeys
[i
]].mkey
, 0, len
) == 0)
151 sal_Unicode code
= rIndexEntry
[startPos
];
152 for (sal_Int16 i
= 0; i
< table_count
; i
++) {
153 if (tables
[i
].start
<= code
&& code
<= tables
[i
].end
)
154 return tables
[i
].table
[code
-tables
[i
].start
];
159 OUString
Index::getIndexDescription(const OUString
& rIndexEntry
)
161 sal_Int16 wgt
= getIndexWeight(rIndexEntry
);
162 if (wgt
< MAX_KEYS
) {
163 if (keys
[wgt
].desc
.getLength())
164 return keys
[wgt
].desc
;
165 else if (keys
[wgt
].key
> 0)
166 return OUString(&keys
[wgt
].key
, 1);
168 return keys
[wgt
].mkey
;
171 sal_uInt32 indexChar
=rIndexEntry
.iterateCodePoints(&nPos
, 0);
172 return OUString(&indexChar
, 1);
175 #define LOCALE_EN lang::Locale(OUString::createFromAscii("en"), OUString(), OUString())
177 void Index::makeIndexKeys(const lang::Locale
&rLocale
, const OUString
&algorithm
) throw (RuntimeException
)
179 OUString keyStr
= LocaleData().getIndexKeysByAlgorithm(rLocale
, algorithm
);
181 if (!keyStr
.getLength()) {
182 keyStr
= LocaleData().getIndexKeysByAlgorithm(LOCALE_EN
,
183 LocaleData().getDefaultIndexAlgorithm(LOCALE_EN
));
185 throw RuntimeException();
188 sal_Int16 len
= sal::static_int_cast
<sal_Int16
>( keyStr
.getLength() );
189 mkey_count
=key_count
=0;
190 skipping_chars
=OUString();
193 for (i
= 0; i
< len
&& key_count
< MAX_KEYS
; i
++)
195 sal_Unicode curr
= keyStr
[i
];
196 sal_Unicode close
= sal_Unicode(')');
198 if (unicode::isWhiteSpace(curr
))
202 case sal_Unicode('-'):
203 if (key_count
> 0 && i
+ 1 < len
) {
204 for (curr
= keyStr
[++i
]; key_count
< MAX_KEYS
&& keys
[key_count
-1].key
< curr
; key_count
++) {
205 keys
[key_count
].key
= keys
[key_count
-1].key
+1;
206 keys
[key_count
].desc
= OUString();
209 throw RuntimeException();
211 case sal_Unicode('['):
212 for (i
++; i
< len
&& keyStr
[i
] != sal_Unicode(']'); i
++) {
213 if (unicode::isWhiteSpace(keyStr
[i
])) {
215 } else if (keyStr
[i
] == sal_Unicode('_')) {
216 for (curr
=keyStr
[i
-1]+1; curr
<= keyStr
[i
+1]; curr
++)
217 skipping_chars
+=OUString(curr
);
220 skipping_chars
+=OUString(keyStr
[i
]);
224 case sal_Unicode('{'):
225 close
= sal_Unicode('}');
226 case sal_Unicode('('):
229 for (end
=i
+1; end
< len
&& keyStr
[end
] != close
; end
++) ;
231 if (end
>= len
) // no found
232 throw RuntimeException();
233 if (close
== sal_Unicode(')'))
234 keys
[key_count
-1].desc
= keyStr
.copy(i
+1, end
-i
-1);
236 mkeys
[mkey_count
++]=key_count
;
237 keys
[key_count
].key
= 0;
238 keys
[key_count
].mkey
= keyStr
.copy(i
+1, end
-i
-1);
239 keys
[key_count
++].desc
=OUString();
243 throw RuntimeException();
246 keys
[key_count
].key
= curr
;
247 keys
[key_count
++].desc
= OUString();
251 for (i
= 0; i
< mkey_count
; i
++) {
252 for (j
=i
+1; j
< mkey_count
; j
++) {
253 if (keys
[mkeys
[i
]].mkey
.getLength() < keys
[mkeys
[j
]].mkey
.getLength()) {
254 sal_Int16 k
= mkeys
[i
];
262 void Index::init(const lang::Locale
&rLocale
, const OUString
& algorithm
) throw (RuntimeException
)
264 makeIndexKeys(rLocale
, algorithm
);
266 Sequence
< UnicodeScript
> scriptList
= LocaleData().getUnicodeScripts( rLocale
);
268 if (scriptList
.getLength() == 0) {
269 scriptList
= LocaleData().getUnicodeScripts(LOCALE_EN
);
270 if (scriptList
.getLength() == 0)
271 throw RuntimeException();
274 table_count
= sal::static_int_cast
<sal_Int16
>( scriptList
.getLength() );
275 if (table_count
> MAX_TABLES
)
276 throw RuntimeException();
278 collator
->loadCollatorAlgorithm(algorithm
, rLocale
, CollatorOptions::CollatorOptions_IGNORE_CASE_ACCENT
);
280 sal_Unicode start
= unicode::getUnicodeScriptStart((UnicodeScript
)0);
281 sal_Unicode end
= unicode::getUnicodeScriptEnd((UnicodeScript
)0);
282 for (sal_Int16 i
= (scriptList
[0] == (UnicodeScript
)0) ? 1 : 0; i
< scriptList
.getLength(); i
++) {
283 if (unicode::getUnicodeScriptStart(scriptList
[i
]) != end
+1) {
284 tables
[j
++].init(start
, end
, keys
, key_count
, this);
285 start
= unicode::getUnicodeScriptStart(scriptList
[i
]);
287 end
= unicode::getUnicodeScriptEnd(scriptList
[i
]);
289 tables
[j
++].init(start
, end
, keys
, key_count
, this);