1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*b3f79822SAndrew Rist * distributed with this work for additional information
6*b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17*b3f79822SAndrew Rist * specific language governing permissions and limitations
18*b3f79822SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*b3f79822SAndrew Rist *************************************************************/
21*b3f79822SAndrew Rist
22*b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include "cellkeytranslator.hxx"
28cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
29cdf0e10cSrcweir #include "i18npool/mslangid.hxx"
30cdf0e10cSrcweir #include "i18npool/lang.h"
31cdf0e10cSrcweir #include "rtl/ustring.hxx"
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include <com/sun/star/i18n/TransliterationModules.hpp>
34cdf0e10cSrcweir
35cdf0e10cSrcweir using ::com::sun::star::lang::Locale;
36cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
37cdf0e10cSrcweir using ::std::list;
38cdf0e10cSrcweir using ::std::hash_map;
39cdf0e10cSrcweir using ::rtl::OUString;
40cdf0e10cSrcweir
41cdf0e10cSrcweir using namespace ::com::sun::star;
42cdf0e10cSrcweir
43cdf0e10cSrcweir enum LocaleMatch
44cdf0e10cSrcweir {
45cdf0e10cSrcweir LOCALE_MATCH_NONE = 0,
46cdf0e10cSrcweir LOCALE_MATCH_LANG,
47cdf0e10cSrcweir LOCALE_MATCH_LANG_COUNTRY,
48cdf0e10cSrcweir LOCALE_MATCH_ALL
49cdf0e10cSrcweir };
50cdf0e10cSrcweir
lclLocaleCompare(const Locale & rLocale1,const Locale & rLocale2)51cdf0e10cSrcweir static LocaleMatch lclLocaleCompare(const Locale& rLocale1, const Locale& rLocale2)
52cdf0e10cSrcweir {
53cdf0e10cSrcweir LocaleMatch eMatchLevel = LOCALE_MATCH_NONE;
54cdf0e10cSrcweir if ( !rLocale1.Language.compareTo(rLocale1.Language) )
55cdf0e10cSrcweir eMatchLevel = LOCALE_MATCH_LANG;
56cdf0e10cSrcweir else
57cdf0e10cSrcweir return eMatchLevel;
58cdf0e10cSrcweir
59cdf0e10cSrcweir if ( !rLocale1.Country.compareTo(rLocale2.Country) )
60cdf0e10cSrcweir eMatchLevel = LOCALE_MATCH_LANG_COUNTRY;
61cdf0e10cSrcweir else
62cdf0e10cSrcweir return eMatchLevel;
63cdf0e10cSrcweir
64cdf0e10cSrcweir if ( !rLocale1.Variant.compareTo(rLocale2.Variant) )
65cdf0e10cSrcweir eMatchLevel = LOCALE_MATCH_ALL;
66cdf0e10cSrcweir
67cdf0e10cSrcweir return eMatchLevel;
68cdf0e10cSrcweir }
69cdf0e10cSrcweir
ScCellKeyword(const sal_Char * pName,OpCode eOpCode,const Locale & rLocale)70cdf0e10cSrcweir ScCellKeyword::ScCellKeyword(const sal_Char* pName, OpCode eOpCode, const Locale& rLocale) :
71cdf0e10cSrcweir mpName(pName),
72cdf0e10cSrcweir meOpCode(eOpCode),
73cdf0e10cSrcweir mrLocale(rLocale)
74cdf0e10cSrcweir {
75cdf0e10cSrcweir }
76cdf0e10cSrcweir
77cdf0e10cSrcweir ::std::auto_ptr<ScCellKeywordTranslator> ScCellKeywordTranslator::spInstance(NULL);
78cdf0e10cSrcweir
lclMatchKeyword(String & rName,const ScCellKeywordHashMap & aMap,OpCode eOpCode=ocNone,const Locale * pLocale=NULL)79cdf0e10cSrcweir static void lclMatchKeyword(String& rName, const ScCellKeywordHashMap& aMap,
80cdf0e10cSrcweir OpCode eOpCode = ocNone, const Locale* pLocale = NULL)
81cdf0e10cSrcweir {
82cdf0e10cSrcweir ScCellKeywordHashMap::const_iterator itrEnd = aMap.end();
83cdf0e10cSrcweir ScCellKeywordHashMap::const_iterator itr = aMap.find(rName);
84cdf0e10cSrcweir
85cdf0e10cSrcweir if ( itr == itrEnd || itr->second.empty() )
86cdf0e10cSrcweir // No candidate strings exist. Bail out.
87cdf0e10cSrcweir return;
88cdf0e10cSrcweir
89cdf0e10cSrcweir if ( eOpCode == ocNone && !pLocale )
90cdf0e10cSrcweir {
91cdf0e10cSrcweir // Since no locale nor opcode matching is needed, simply return
92cdf0e10cSrcweir // the first item on the list.
93cdf0e10cSrcweir rName = String::CreateFromAscii( itr->second.front().mpName );
94cdf0e10cSrcweir return;
95cdf0e10cSrcweir }
96cdf0e10cSrcweir
97cdf0e10cSrcweir const sal_Char* aBestMatchName = itr->second.front().mpName;
98cdf0e10cSrcweir LocaleMatch eLocaleMatchLevel = LOCALE_MATCH_NONE;
99cdf0e10cSrcweir bool bOpCodeMatched = false;
100cdf0e10cSrcweir
101cdf0e10cSrcweir list<ScCellKeyword>::const_iterator itrListEnd = itr->second.end();
102cdf0e10cSrcweir list<ScCellKeyword>::const_iterator itrList = itr->second.begin();
103cdf0e10cSrcweir for ( ; itrList != itrListEnd; ++itrList )
104cdf0e10cSrcweir {
105cdf0e10cSrcweir if ( eOpCode != ocNone && pLocale )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir if ( itrList->meOpCode == eOpCode )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
110cdf0e10cSrcweir if ( eLevel == LOCALE_MATCH_ALL )
111cdf0e10cSrcweir {
112cdf0e10cSrcweir // Name with matching opcode and locale found.
113cdf0e10cSrcweir rName = String::CreateFromAscii( itrList->mpName );
114cdf0e10cSrcweir return;
115cdf0e10cSrcweir }
116cdf0e10cSrcweir else if ( eLevel > eLocaleMatchLevel )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir // Name with a better matching locale.
119cdf0e10cSrcweir eLocaleMatchLevel = eLevel;
120cdf0e10cSrcweir aBestMatchName = itrList->mpName;
121cdf0e10cSrcweir }
122cdf0e10cSrcweir else if ( !bOpCodeMatched )
123cdf0e10cSrcweir // At least the opcode matches.
124cdf0e10cSrcweir aBestMatchName = itrList->mpName;
125cdf0e10cSrcweir
126cdf0e10cSrcweir bOpCodeMatched = true;
127cdf0e10cSrcweir }
128cdf0e10cSrcweir }
129cdf0e10cSrcweir else if ( eOpCode != ocNone && !pLocale )
130cdf0e10cSrcweir {
131cdf0e10cSrcweir if ( itrList->meOpCode == eOpCode )
132cdf0e10cSrcweir {
133cdf0e10cSrcweir // Name with a matching opcode preferred.
134cdf0e10cSrcweir rName = String::CreateFromAscii( itrList->mpName );
135cdf0e10cSrcweir return;
136cdf0e10cSrcweir }
137cdf0e10cSrcweir }
138cdf0e10cSrcweir else if ( !eOpCode && pLocale )
139cdf0e10cSrcweir {
140cdf0e10cSrcweir LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
141cdf0e10cSrcweir if ( eLevel == LOCALE_MATCH_ALL )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir // Name with matching locale preferred.
144cdf0e10cSrcweir rName = String::CreateFromAscii( itrList->mpName );
145cdf0e10cSrcweir return;
146cdf0e10cSrcweir }
147cdf0e10cSrcweir else if ( eLevel > eLocaleMatchLevel )
148cdf0e10cSrcweir {
149cdf0e10cSrcweir // Name with a better matching locale.
150cdf0e10cSrcweir eLocaleMatchLevel = eLevel;
151cdf0e10cSrcweir aBestMatchName = itrList->mpName;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir }
154cdf0e10cSrcweir }
155cdf0e10cSrcweir
156cdf0e10cSrcweir // No preferred strings found. Return the best matching name.
157cdf0e10cSrcweir rName = String::CreateFromAscii(aBestMatchName);
158cdf0e10cSrcweir }
159cdf0e10cSrcweir
transKeyword(String & rName,const Locale * pLocale,OpCode eOpCode)160cdf0e10cSrcweir void ScCellKeywordTranslator::transKeyword(String& rName, const Locale* pLocale, OpCode eOpCode)
161cdf0e10cSrcweir {
162cdf0e10cSrcweir if ( !spInstance.get() )
163cdf0e10cSrcweir spInstance.reset( new ScCellKeywordTranslator );
164cdf0e10cSrcweir
165cdf0e10cSrcweir LanguageType eLang = pLocale ? MsLangId::convertLocaleToLanguageWithFallback(*pLocale) : LANGUAGE_SYSTEM;
166cdf0e10cSrcweir Sequence<sal_Int32> aOffsets;
167cdf0e10cSrcweir rName = spInstance->maTransWrapper.transliterate(rName, eLang, 0, rName.Len(), &aOffsets);
168cdf0e10cSrcweir lclMatchKeyword(rName, spInstance->maStringNameMap, eOpCode, pLocale);
169cdf0e10cSrcweir }
170cdf0e10cSrcweir
ScCellKeywordTranslator()171cdf0e10cSrcweir ScCellKeywordTranslator::ScCellKeywordTranslator() :
172cdf0e10cSrcweir maTransWrapper( ::comphelper::getProcessServiceFactory(),
173cdf0e10cSrcweir i18n::TransliterationModules_LOWERCASE_UPPERCASE )
174cdf0e10cSrcweir {
175cdf0e10cSrcweir init();
176cdf0e10cSrcweir }
177cdf0e10cSrcweir
~ScCellKeywordTranslator()178cdf0e10cSrcweir ScCellKeywordTranslator::~ScCellKeywordTranslator()
179cdf0e10cSrcweir {
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
182cdf0e10cSrcweir struct TransItem
183cdf0e10cSrcweir {
184cdf0e10cSrcweir const sal_Unicode* from;
185cdf0e10cSrcweir const sal_Char* to;
186cdf0e10cSrcweir OpCode func;
187cdf0e10cSrcweir };
188cdf0e10cSrcweir
init()189cdf0e10cSrcweir void ScCellKeywordTranslator::init()
190cdf0e10cSrcweir {
191cdf0e10cSrcweir ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
192cdf0e10cSrcweir
193cdf0e10cSrcweir // The file below has been autogenerated by sc/workben/celltrans/parse.py.
194cdf0e10cSrcweir // To add new locale keywords, edit sc/workben/celltrans/keywords_utf16.txt
195cdf0e10cSrcweir // and re-run the parse.py script.
196cdf0e10cSrcweir //
197cdf0e10cSrcweir // All keywords must be uppercase, and the mapping must be from the
198cdf0e10cSrcweir // localized keyword to the English keyword.
199cdf0e10cSrcweir //
200cdf0e10cSrcweir // Make sure that the original keyword file (keywords_utf16.txt) is
201cdf0e10cSrcweir // encoded in UCS-2/UTF-16!
202cdf0e10cSrcweir
203cdf0e10cSrcweir #include "cellkeywords.inl"
204cdf0e10cSrcweir }
205cdf0e10cSrcweir
addToMap(const String & rKey,const sal_Char * pName,const Locale & rLocale,OpCode eOpCode)206cdf0e10cSrcweir void ScCellKeywordTranslator::addToMap(const String& rKey, const sal_Char* pName, const Locale& rLocale, OpCode eOpCode)
207cdf0e10cSrcweir {
208cdf0e10cSrcweir ScCellKeyword aKeyItem( pName, eOpCode, rLocale );
209cdf0e10cSrcweir
210cdf0e10cSrcweir ScCellKeywordHashMap::iterator itrEnd = maStringNameMap.end();
211cdf0e10cSrcweir ScCellKeywordHashMap::iterator itr = maStringNameMap.find(rKey);
212cdf0e10cSrcweir
213cdf0e10cSrcweir if ( itr == itrEnd )
214cdf0e10cSrcweir {
215cdf0e10cSrcweir // New keyword.
216cdf0e10cSrcweir list<ScCellKeyword> aList;
217cdf0e10cSrcweir aList.push_back(aKeyItem);
218cdf0e10cSrcweir maStringNameMap.insert( ScCellKeywordHashMap::value_type(rKey, aList) );
219cdf0e10cSrcweir }
220cdf0e10cSrcweir else
221cdf0e10cSrcweir itr->second.push_back(aKeyItem);
222cdf0e10cSrcweir }
223cdf0e10cSrcweir
addToMap(const TransItem * pItems,const Locale & rLocale)224cdf0e10cSrcweir void ScCellKeywordTranslator::addToMap(const TransItem* pItems, const Locale& rLocale)
225cdf0e10cSrcweir {
226cdf0e10cSrcweir for (sal_uInt16 i = 0; pItems[i].from != NULL; ++i)
227cdf0e10cSrcweir addToMap(String(pItems[i].from), pItems[i].to, rLocale, pItems[i].func);
228cdf0e10cSrcweir }
229