1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "cellkeytranslator.hxx"
22 #include "comphelper/processfactory.hxx"
23 #include "i18nlangtag/mslangid.hxx"
24 #include "i18nlangtag/lang.h"
25 #include "rtl/ustring.hxx"
27 #include <com/sun/star/i18n/TransliterationModules.hpp>
29 using ::com::sun::star::lang::Locale
;
30 using ::com::sun::star::uno::Sequence
;
32 using ::boost::unordered_map
;
34 using namespace ::com::sun::star
;
38 LOCALE_MATCH_NONE
= 0,
40 LOCALE_MATCH_LANG_SCRIPT
,
41 LOCALE_MATCH_LANG_SCRIPT_COUNTRY
,
45 static LocaleMatch
lclLocaleCompare(const Locale
& rLocale1
, const LanguageTag
& rLanguageTag2
)
47 LocaleMatch eMatchLevel
= LOCALE_MATCH_NONE
;
48 LanguageTag
aLanguageTag1( rLocale1
);
50 if ( aLanguageTag1
.getLanguage() == rLanguageTag2
.getLanguage() )
51 eMatchLevel
= LOCALE_MATCH_LANG
;
55 if ( aLanguageTag1
.getScript() == rLanguageTag2
.getScript() )
56 eMatchLevel
= LOCALE_MATCH_LANG_SCRIPT
;
60 if ( aLanguageTag1
.getCountry() == rLanguageTag2
.getCountry() )
61 eMatchLevel
= LOCALE_MATCH_LANG_SCRIPT_COUNTRY
;
65 if (aLanguageTag1
== rLanguageTag2
)
66 return LOCALE_MATCH_ALL
;
71 ScCellKeyword::ScCellKeyword(const sal_Char
* pName
, OpCode eOpCode
, const Locale
& rLocale
) :
78 ::std::auto_ptr
<ScCellKeywordTranslator
> ScCellKeywordTranslator::spInstance(NULL
);
80 static void lclMatchKeyword(OUString
& rName
, const ScCellKeywordHashMap
& aMap
,
81 OpCode eOpCode
= ocNone
, const Locale
* pLocale
= NULL
)
83 ScCellKeywordHashMap::const_iterator itrEnd
= aMap
.end();
84 ScCellKeywordHashMap::const_iterator itr
= aMap
.find(rName
);
86 if ( itr
== itrEnd
|| itr
->second
.empty() )
87 // No candidate strings exist. Bail out.
90 if ( eOpCode
== ocNone
&& !pLocale
)
92 // Since no locale nor opcode matching is needed, simply return
93 // the first item on the list.
94 rName
= OUString::createFromAscii( itr
->second
.front().mpName
);
98 LanguageTag
aLanguageTag( pLocale
? *pLocale
: Locale("","",""));
99 const sal_Char
* aBestMatchName
= itr
->second
.front().mpName
;
100 LocaleMatch eLocaleMatchLevel
= LOCALE_MATCH_NONE
;
101 bool bOpCodeMatched
= false;
103 list
<ScCellKeyword
>::const_iterator itrListEnd
= itr
->second
.end();
104 list
<ScCellKeyword
>::const_iterator itrList
= itr
->second
.begin();
105 for ( ; itrList
!= itrListEnd
; ++itrList
)
107 if ( eOpCode
!= ocNone
&& pLocale
)
109 if ( itrList
->meOpCode
== eOpCode
)
111 LocaleMatch eLevel
= lclLocaleCompare(itrList
->mrLocale
, aLanguageTag
);
112 if ( eLevel
== LOCALE_MATCH_ALL
)
114 // Name with matching opcode and locale found.
115 rName
= OUString::createFromAscii( itrList
->mpName
);
118 else if ( eLevel
> eLocaleMatchLevel
)
120 // Name with a better matching locale.
121 eLocaleMatchLevel
= eLevel
;
122 aBestMatchName
= itrList
->mpName
;
124 else if ( !bOpCodeMatched
)
125 // At least the opcode matches.
126 aBestMatchName
= itrList
->mpName
;
128 bOpCodeMatched
= true;
131 else if ( eOpCode
!= ocNone
&& !pLocale
)
133 if ( itrList
->meOpCode
== eOpCode
)
135 // Name with a matching opcode preferred.
136 rName
= OUString::createFromAscii( itrList
->mpName
);
140 else if ( !eOpCode
&& pLocale
)
142 LocaleMatch eLevel
= lclLocaleCompare(itrList
->mrLocale
, aLanguageTag
);
143 if ( eLevel
== LOCALE_MATCH_ALL
)
145 // Name with matching locale preferred.
146 rName
= OUString::createFromAscii( itrList
->mpName
);
149 else if ( eLevel
> eLocaleMatchLevel
)
151 // Name with a better matching locale.
152 eLocaleMatchLevel
= eLevel
;
153 aBestMatchName
= itrList
->mpName
;
158 // No preferred strings found. Return the best matching name.
159 rName
= OUString::createFromAscii(aBestMatchName
);
162 void ScCellKeywordTranslator::transKeyword(OUString
& rName
, const Locale
* pLocale
, OpCode eOpCode
)
164 if ( !spInstance
.get() )
165 spInstance
.reset( new ScCellKeywordTranslator
);
167 LanguageType eLang
= pLocale
? LanguageTag(*pLocale
).makeFallback().getLanguageType() : LANGUAGE_SYSTEM
;
168 Sequence
<sal_Int32
> aOffsets
;
169 rName
= spInstance
->maTransWrapper
.transliterate(rName
, eLang
, 0, rName
.getLength(), &aOffsets
);
170 lclMatchKeyword(rName
, spInstance
->maStringNameMap
, eOpCode
, pLocale
);
173 ScCellKeywordTranslator::ScCellKeywordTranslator() :
174 maTransWrapper( ::comphelper::getProcessComponentContext(),
175 i18n::TransliterationModules_LOWERCASE_UPPERCASE
)
180 ScCellKeywordTranslator::~ScCellKeywordTranslator()
186 const sal_Unicode
* from
;
191 void ScCellKeywordTranslator::init()
193 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
195 // The file below has been autogenerated by sc/workben/celltrans/parse.py.
196 // To add new locale keywords, edit sc/workben/celltrans/keywords_utf16.txt
197 // and re-run the parse.py script.
199 // All keywords must be uppercase, and the mapping must be from the
200 // localized keyword to the English keyword.
202 // Make sure that the original keyword file (keywords_utf16.txt) is
203 // encoded in UCS-2/UTF-16!
205 #include "cellkeywords.inl"
208 void ScCellKeywordTranslator::addToMap(const OUString
& rKey
, const sal_Char
* pName
, const Locale
& rLocale
, OpCode eOpCode
)
210 ScCellKeyword
aKeyItem( pName
, eOpCode
, rLocale
);
212 ScCellKeywordHashMap::iterator itrEnd
= maStringNameMap
.end();
213 ScCellKeywordHashMap::iterator itr
= maStringNameMap
.find(rKey
);
218 list
<ScCellKeyword
> aList
;
219 aList
.push_back(aKeyItem
);
220 maStringNameMap
.insert( ScCellKeywordHashMap::value_type(rKey
, aList
) );
223 itr
->second
.push_back(aKeyItem
);
226 void ScCellKeywordTranslator::addToMap(const TransItem
* pItems
, const Locale
& rLocale
)
228 for (sal_uInt16 i
= 0; pItems
[i
].from
!= NULL
; ++i
)
229 addToMap(OUString(pItems
[i
].from
), pItems
[i
].to
, rLocale
, pItems
[i
].func
);
232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */