update dev300-m58
[ooovba.git] / configmgr / source / xml / matchlocale.cxx
blob1e8f4008118590665035a73ee044435992589bfc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: matchlocale.cxx,v $
10 * $Revision: 1.12 $
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_configmgr.hxx"
33 #include "matchlocale.hxx"
35 #include <rtl/ustrbuf.hxx>
37 #include <algorithm>
38 #include <iterator>
40 namespace configmgr
42 // -----------------------------------------------------------------------------
43 namespace localehelper
45 // -----------------------------------------------------------------------------
46 namespace uno = ::com::sun::star::uno;
47 namespace lang = ::com::sun::star::lang;
49 #define ARRAYSIZE( arr ) (sizeof(arr) / sizeof 0[arr] )
50 // -----------------------------------------------------------------------------
51 struct StaticLocale
53 char const * aLanguage;
54 char const * aCountry;
57 char const * const c_sAnyLanguage = "*"; // exported !
58 char const * const c_sDefLanguage = "x-default"; // exported !
60 char const * const c_sNoCountry = "";
62 char const * const c_sLanguageEnglish = "en";
63 char const * const c_sCountryUS = "US";
65 StaticLocale const c_aFallbackLocales[] =
67 { c_sLanguageEnglish, c_sCountryUS }, // english [cannot make 'en' better than 'en-US' :-(]
68 { c_sAnyLanguage, c_sNoCountry } // just take the first you find
70 std::vector< com::sun::star::lang::Locale >::size_type const c_nFallbackLocales = ARRAYSIZE(c_aFallbackLocales);
72 // -----------------------------------------------------------------------------
73 bool isAnyLanguage(rtl::OUString const & _sLanguage)
75 return !!_sLanguage.equalsAscii(c_sAnyLanguage);
78 // -----------------------------------------------------------------------------
79 bool isDefaultLanguage(rtl::OUString const & _sLanguage)
81 return !!_sLanguage.equalsAscii(c_sDefLanguage);
84 // -----------------------------------------------------------------------------
85 rtl::OUString getAnyLanguage()
87 return rtl::OUString::createFromAscii( c_sAnyLanguage );
90 // -----------------------------------------------------------------------------
91 rtl::OUString getDefaultLanguage()
93 return rtl::OUString::createFromAscii( c_sDefLanguage );
96 // -----------------------------------------------------------------------------
97 com::sun::star::lang::Locale getAnyLocale()
99 return com::sun::star::lang::Locale( getAnyLanguage(), rtl::OUString(), rtl::OUString() );
102 // -----------------------------------------------------------------------------
103 com::sun::star::lang::Locale getDefaultLocale()
105 return com::sun::star::lang::Locale( getDefaultLanguage(), rtl::OUString(), rtl::OUString() );
108 // -----------------------------------------------------------------------------
109 static inline sal_Int32 countrySeparatorPos(rtl::OUString const& aLocaleName_)
111 sal_Int32 pos = aLocaleName_.indexOf('-');
112 if (pos == 1) // allow for x-LL or i-LL
113 pos = aLocaleName_.indexOf('-',pos+1);
115 if (pos < 0)
116 pos = aLocaleName_.indexOf('_');
118 return pos;
120 // -------------------------------------------------------------------------
121 static inline sal_Int32 countryLength(rtl::OUString const& aLocaleName_, sal_Int32 nCountryPos)
123 sal_Int32 pos1 = aLocaleName_.indexOf('.',nCountryPos);
124 sal_Int32 pos2 = aLocaleName_.indexOf('_',nCountryPos);
126 if (pos1 < 0) pos1 = aLocaleName_.getLength();
128 if (pos2 < 0 || pos1 < pos2)
129 return pos1 - nCountryPos;
131 else
132 return pos2 - nCountryPos;
134 // -------------------------------------------------------------------------
135 static inline void splitLocaleString(rtl::OUString const& aLocaleName_, rtl::OUString& rLanguage_, rtl::OUString& rCountry_)
137 sal_Int32 nCountryPos = countrySeparatorPos(aLocaleName_);
138 if (nCountryPos >= 0)
140 rLanguage_ = aLocaleName_.copy(0,nCountryPos).toAsciiLowerCase();
142 ++nCountryPos; // advance past separator
143 sal_Int32 nCountryLength = countryLength(aLocaleName_, nCountryPos);
145 rCountry_ = aLocaleName_.copy(nCountryPos,nCountryLength).toAsciiUpperCase();
147 else
149 rLanguage_ = aLocaleName_.toAsciiLowerCase();
150 rCountry_ = rtl::OUString();
153 // -----------------------------------------------------------------------------
155 // -----------------------------------------------------------------------------
156 // conversion helpers
157 com::sun::star::lang::Locale makeLocale(rtl::OUString const& sLocaleName_)
159 com::sun::star::lang::Locale aResult;
160 splitLocaleString(sLocaleName_, aResult.Language, aResult.Country);
161 return aResult;
163 rtl::OUString makeIsoLocale(com::sun::star::lang::Locale const& aUnoLocale_)
165 rtl::OUStringBuffer aResult(aUnoLocale_.Language.toAsciiLowerCase());
166 if (aUnoLocale_.Country.getLength())
168 aResult.append( sal_Unicode('-') ).append(aUnoLocale_.Country.toAsciiUpperCase());
170 return aResult.makeStringAndClear();
172 static
173 com::sun::star::lang::Locale makeLocale(StaticLocale const& aConstLocale_)
175 com::sun::star::lang::Locale aResult;
176 aResult.Language = rtl::OUString::createFromAscii(aConstLocale_.aLanguage);
177 aResult.Country = rtl::OUString::createFromAscii(aConstLocale_.aCountry);
178 return aResult;
180 // -----------------------------------------------------------------------------
181 template <class T>
182 inline
183 void addLocaleSeq_impl(T const* first, T const* last, std::vector< com::sun::star::lang::Locale >& rSeq)
185 com::sun::star::lang::Locale (* const xlate)(T const&) = &makeLocale;
187 std::transform(first, last, std::back_inserter(rSeq), xlate);
189 // -----------------------------------------------------------------------------
190 // -----------------------------------------------------------------------------
191 template <class T>
192 inline
193 std::vector< com::sun::star::lang::Locale > makeLocaleSeq_impl(uno::Sequence< T > const& aLocales_)
195 sal_Int32 const nLocaleCount = aLocales_.getLength();
197 T const* pLocaleBegin = aLocales_.getConstArray();
199 std::vector< com::sun::star::lang::Locale > aResult;
200 aResult.reserve( nLocaleCount + c_nFallbackLocales ); // make room for fallback stuff as well
202 addLocaleSeq_impl(pLocaleBegin, pLocaleBegin + nLocaleCount, aResult);
204 return aResult;
206 // -----------------------------------------------------------------------------
208 void addFallbackLocales(std::vector< com::sun::star::lang::Locale >& aTargetList_)
210 addLocaleSeq_impl(c_aFallbackLocales, c_aFallbackLocales + c_nFallbackLocales, aTargetList_);
212 // -----------------------------------------------------------------------------
214 std::vector< com::sun::star::lang::Locale > makeLocaleSequence(uno::Sequence<rtl::OUString> const& sLocaleNames_)
216 return makeLocaleSeq_impl(sLocaleNames_);
218 // -----------------------------------------------------------------------------
220 uno::Sequence<rtl::OUString> makeIsoSequence(std::vector< com::sun::star::lang::Locale > const& aLocales_)
222 std::vector< com::sun::star::lang::Locale >::size_type const nLocaleCount = aLocales_.size();
223 sal_Int32 const nSeqSize = sal_Int32(nLocaleCount);
224 OSL_ASSERT( nSeqSize >= 0 && sal_uInt32(nSeqSize) == nLocaleCount );
226 uno::Sequence<rtl::OUString> aResult(nSeqSize);
227 std::transform(aLocales_.begin(), aLocales_.end(), aResult.getArray(), &makeIsoLocale);
229 return aResult;
231 // -----------------------------------------------------------------------------
232 bool designatesAllLocales(com::sun::star::lang::Locale const& aLocale_)
234 return aLocale_.Language.equalsAscii(c_sAnyLanguage);
236 bool designatesAllLocales(std::vector< com::sun::star::lang::Locale > const& aLocales_)
238 return aLocales_.size() <= 1 &&
239 (aLocales_.size() == 0 || designatesAllLocales(aLocales_));
241 // -----------------------------------------------------------------------------
243 MatchQuality match(com::sun::star::lang::Locale const& aLocale_, com::sun::star::lang::Locale const& aTarget_)
245 // check language
246 if (!aLocale_.Language.equals(aTarget_.Language))
248 // can we accept any language
249 if (aTarget_.Language.equalsAscii(c_sAnyLanguage))
250 return MATCH_LANGUAGE;
252 return MISMATCH;
255 // check for exact match
256 else if (aLocale_.Country.equals(aTarget_.Country))
257 return MATCH_LOCALE;
259 // check for plain language
260 else if (aLocale_.Country.getLength() == 0)
261 return MATCH_LANGUAGE_PLAIN;
263 // so we are left with the wrong country
264 else
265 return MATCH_LANGUAGE;
268 // -----------------------------------------------------------------------------
270 /// check the given position and quality, if they are an improvement
271 bool MatchResult::improve(std::vector< com::sun::star::lang::Locale >::size_type nPos_, MatchQuality eQuality_)
273 // is this a match at all ?
274 if (eQuality_ == MISMATCH)
275 return false;
277 // is the position worse ?
278 if (nPos_ > m_nPos )
279 return false;
281 // is this just a non-positive quality change ?
282 if (nPos_ == m_nPos && eQuality_ <= m_eQuality)
283 return false;
285 // Improvement found
286 m_nPos = nPos_;
287 m_eQuality = eQuality_;
289 return true;
292 // -----------------------------------------------------------------------------
294 bool isMatch(com::sun::star::lang::Locale const& aLocale_, std::vector< com::sun::star::lang::Locale > const& aTarget_, MatchQuality eRequiredQuality_)
296 std::vector< com::sun::star::lang::Locale >::size_type const nEnd = aTarget_.size();
298 for (std::vector< com::sun::star::lang::Locale >::size_type nPos = 0; nPos < nEnd; ++nPos)
300 MatchQuality eQuality = match(aLocale_, aTarget_[nPos]);
301 if (eQuality >= eRequiredQuality_)
303 return true;
306 return false;
308 // -----------------------------------------------------------------------------
310 static
311 inline
312 std::vector< com::sun::star::lang::Locale >::size_type getSearchLimitPosition(MatchResult const& aPrevMatch_,std::vector< com::sun::star::lang::Locale > const& aTarget_)
314 std::vector< com::sun::star::lang::Locale >::size_type nSize = aTarget_.size();
316 if (aPrevMatch_.isMatch())
318 std::vector< com::sun::star::lang::Locale >::size_type nMatchPos = aPrevMatch_.position();
320 OSL_ENSURE(nMatchPos < nSize,"localehelper::getSearchLimitPosition: ERROR - previous position is out-of-bounds");
322 if (nMatchPos < nSize)
324 return nMatchPos + 1;
327 return nSize;
329 // -----------------------------------------------------------------------------
331 bool improveMatch(MatchResult& rMatch_, com::sun::star::lang::Locale const& aLocale_, std::vector< com::sun::star::lang::Locale > const& aTarget_)
333 std::vector< com::sun::star::lang::Locale >::size_type const nEnd = getSearchLimitPosition(rMatch_,aTarget_);
335 for (std::vector< com::sun::star::lang::Locale >::size_type nPos = 0; nPos < nEnd; ++nPos)
337 if (rMatch_.improve(nPos, match(aLocale_, aTarget_[nPos])))
339 return true;
342 return false;
344 // -----------------------------------------------------------------------------
347 // -----------------------------------------------------------------------------
348 // class FindBestLocale
349 // -----------------------------------------------------------------------------
351 inline
352 void FindBestLocale::implSetTarget(std::vector< com::sun::star::lang::Locale > const& aTarget_)
354 m_aTarget = aTarget_;
355 addFallbackLocales(m_aTarget);
357 // -----------------------------------------------------------------------------
359 FindBestLocale::FindBestLocale(com::sun::star::lang::Locale const& aTarget_)
361 std::vector< com::sun::star::lang::Locale > aSeq(1,aTarget_);
362 implSetTarget( aSeq );
364 // -----------------------------------------------------------------------------
366 bool FindBestLocale::accept(com::sun::star::lang::Locale const& aLocale_)
368 return improveMatch(m_aResult, aLocale_, m_aTarget);
370 // -----------------------------------------------------------------------------
372 void FindBestLocale::reset(bool bNeedLocale_)
374 if (bNeedLocale_)
375 m_aResult.reset();
377 else // mark as best match already (no improvement possible)
378 m_aResult = m_aResult.best();
380 // -----------------------------------------------------------------------------
382 } // namespace locale helper
383 // -----------------------------------------------------------------------------
385 } // namespace