/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_i18npool.hxx" #include #include #include using namespace com::sun::star; using namespace com::sun::star::lang; using namespace com::sun::star::uno; using namespace rtl; namespace com { namespace sun { namespace star { namespace i18n { CollatorImpl::CollatorImpl( const Reference < XMultiServiceFactory >& rxMSF ) : xMSF(rxMSF) { if ( rxMSF.is()) { Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii("com.sun.star.i18n.LocaleData")); if ( xI.is() ) xI->queryInterface(::getCppuType((const Reference< XLocaleData>*)0)) >>= localedata; } cachedItem = NULL; } CollatorImpl::~CollatorImpl() { // Clear lookuptable for (size_t l = 0; l < lookupTable.size(); l++) delete lookupTable[l]; lookupTable.clear(); } sal_Int32 SAL_CALL CollatorImpl::compareSubstring( const OUString& str1, sal_Int32 off1, sal_Int32 len1, const OUString& str2, sal_Int32 off2, sal_Int32 len2) throw(RuntimeException) { if (cachedItem) return cachedItem->xC->compareSubstring(str1, off1, len1, str2, off2, len2); sal_Unicode *unistr1 = (sal_Unicode*) str1.getStr() + off1; sal_Unicode *unistr2 = (sal_Unicode*) str2.getStr() + off2; for (int i = 0; i < len1 && i < len2; i++) if (unistr1[i] != unistr2[i]) return unistr1[i] < unistr2[i] ? -1 : 1; return len1 == len2 ? 0 : (len1 < len2 ? -1 : 1); } sal_Int32 SAL_CALL CollatorImpl::compareString( const OUString& in_str1, const OUString& in_str2) throw(RuntimeException) { if (cachedItem) return cachedItem->xC->compareString(in_str1, in_str2); return CollatorImpl::compareSubstring(in_str1, 0, in_str1.getLength(), in_str2, 0, in_str2.getLength()); } sal_Int32 SAL_CALL CollatorImpl::loadDefaultCollator(const lang::Locale& rLocale, sal_Int32 collatorOptions) throw(RuntimeException) { const Sequence< Implementation > &imp = localedata->getCollatorImplementations(rLocale); for (sal_Int16 i = 0; i < imp.getLength(); i++) if (imp[i].isDefault) return loadCollatorAlgorithm(imp[i].unoID, rLocale, collatorOptions); throw RuntimeException(); // not default is defined //return 0; } sal_Int32 SAL_CALL CollatorImpl::loadCollatorAlgorithm(const OUString& impl, const lang::Locale& rLocale, sal_Int32 collatorOptions) throw(RuntimeException) { if (! cachedItem || ! cachedItem->equals(rLocale, impl)) loadCachedCollator(rLocale, impl); if (cachedItem) cachedItem->xC->loadCollatorAlgorithm(cachedItem->algorithm, nLocale = rLocale, collatorOptions); else throw RuntimeException(); // impl could not be loaded return 0; } void SAL_CALL CollatorImpl::loadCollatorAlgorithmWithEndUserOption(const OUString& impl, const lang::Locale& rLocale, const Sequence< sal_Int32 >& collatorOptions) throw(RuntimeException) { sal_Int32 options = 0; for (sal_Int32 i = 0; i < collatorOptions.getLength(); i++) options |= collatorOptions[i]; loadCollatorAlgorithm(impl, rLocale, options); } Sequence< OUString > SAL_CALL CollatorImpl::listCollatorAlgorithms( const lang::Locale& rLocale ) throw(RuntimeException) { nLocale = rLocale; const Sequence< Implementation > &imp = localedata->getCollatorImplementations(rLocale); Sequence< OUString > list(imp.getLength()); for (sal_Int32 i = 0; i < imp.getLength(); i++) { //if the current algorithm is default and the position is not on the first one, then switch if (imp[i].isDefault && i) { list[i] = list[0]; list[0] = imp[i].unoID; } else list[i] = imp[i].unoID; } return list; } Sequence< sal_Int32 > SAL_CALL CollatorImpl::listCollatorOptions( const OUString& /*collatorAlgorithmName*/ ) throw(RuntimeException) { Sequence< OUString > option_str = localedata->getCollationOptions(nLocale); Sequence< sal_Int32 > option_int(option_str.getLength()); for (sal_Int32 i = 0; i < option_str.getLength(); i++) option_int[i] = option_str[i].equalsAscii("IGNORE_CASE") ? CollatorOptions::CollatorOptions_IGNORE_CASE : option_str[i].equalsAscii("IGNORE_KANA") ? CollatorOptions::CollatorOptions_IGNORE_KANA : option_str[i].equalsAscii("IGNORE_WIDTH") ? CollatorOptions::CollatorOptions_IGNORE_WIDTH : 0; return option_int; } sal_Bool SAL_CALL CollatorImpl::createCollator(const lang::Locale& rLocale, const OUString& serviceName, const OUString& rSortAlgorithm) throw(RuntimeException) { for (size_t l = 0; l < lookupTable.size(); l++) { cachedItem = lookupTable[l]; if (cachedItem->service.equals(serviceName)) {// cross locale sharing lookupTable.push_back(cachedItem = new lookupTableItem(rLocale, rSortAlgorithm, serviceName, cachedItem->xC)); return sal_True; } } if (xMSF.is()) { Reference < XInterface > xI = xMSF->createInstance(OUString::createFromAscii("com.sun.star.i18n.Collator_") + serviceName); if (xI.is()) { Reference < XCollator > xC; xI->queryInterface( getCppuType((const Reference< XCollator>*)0) ) >>= xC; if (xC.is()) { lookupTable.push_back(cachedItem = new lookupTableItem(rLocale, rSortAlgorithm, serviceName, xC)); return sal_True; } } return sal_False; } throw RuntimeException(); } void SAL_CALL CollatorImpl::loadCachedCollator(const lang::Locale& rLocale, const OUString& rSortAlgorithm) throw(RuntimeException) { for (size_t i = 0; i < lookupTable.size(); i++) { cachedItem = lookupTable[i]; if (cachedItem->equals(rLocale, rSortAlgorithm)) { return; } } static sal_Unicode under = (sal_Unicode) '_'; static OUString tw(OUString::createFromAscii("TW")); static OUString unicode(OUString::createFromAscii("Unicode")); sal_Int32 l = rLocale.Language.getLength(); sal_Int32 c = rLocale.Country.getLength(); sal_Int32 v = rLocale.Variant.getLength(); sal_Int32 a = rSortAlgorithm.getLength(); OUStringBuffer aBuf(l+c+v+a+4); if ((l > 0 && c > 0 && v > 0 && a > 0 && // load service with name ____ createCollator(rLocale, aBuf.append(rLocale.Language).append(under).append(rLocale.Country).append( under).append(rLocale.Variant).append(under).append(rSortAlgorithm).makeStringAndClear(), rSortAlgorithm)) || (l > 0 && c > 0 && a > 0 && // load service with name ___ createCollator(rLocale, aBuf.append(rLocale.Language).append(under).append(rLocale.Country).append( under).append(rSortAlgorithm).makeStringAndClear(), rSortAlgorithm)) || (l > 0 && c > 0 && a > 0 && rLocale.Language.equalsAscii("zh") && (rLocale.Country.equalsAscii("HK") || rLocale.Country.equalsAscii("MO")) && // if the country code is HK or MO, one more step to try TW. createCollator(rLocale, aBuf.append(rLocale.Language).append(under).append(tw).append(under).append( rSortAlgorithm).makeStringAndClear(), rSortAlgorithm)) || (l > 0 && a > 0 && // load service with name __ createCollator(rLocale, aBuf.append(rLocale.Language).append(under).append(rSortAlgorithm).makeStringAndClear(), rSortAlgorithm)) || // load service with name _ (a > 0 && createCollator(rLocale, rSortAlgorithm, rSortAlgorithm)) || // load default service with name _Unicode createCollator(rLocale, unicode, rSortAlgorithm)) { return; } else { cachedItem = NULL; throw RuntimeException(); // could not load any service } } const sal_Char cCollator[] = "com.sun.star.i18n.Collator"; OUString SAL_CALL CollatorImpl::getImplementationName() throw( RuntimeException ) { return OUString::createFromAscii(cCollator); } sal_Bool SAL_CALL CollatorImpl::supportsService(const OUString& rServiceName) throw( RuntimeException ) { return rServiceName.equalsAscii(cCollator); } Sequence< OUString > SAL_CALL CollatorImpl::getSupportedServiceNames() throw( RuntimeException ) { Sequence< OUString > aRet(1); aRet[0] = OUString::createFromAscii(cCollator); return aRet; } } } } }