xref: /AOO41X/main/sc/source/core/tool/cellkeytranslator.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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