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 .
20 #include "cellkeytranslator.hxx"
21 #include <comphelper/processfactory.hxx>
22 #include <i18nlangtag/mslangid.hxx>
23 #include <i18nlangtag/lang.h>
24 #include <rtl/ustring.hxx>
26 #include <com/sun/star/i18n/TransliterationModules.hpp>
28 using ::com::sun::star::uno::Sequence
;
31 using namespace ::com::sun::star
;
35 LOCALE_MATCH_NONE
= 0,
37 LOCALE_MATCH_LANG_SCRIPT
,
38 LOCALE_MATCH_LANG_SCRIPT_COUNTRY
,
42 static LocaleMatch
lclLocaleCompare(const lang::Locale
& rLocale1
, const LanguageTag
& rLanguageTag2
)
44 LocaleMatch eMatchLevel
= LOCALE_MATCH_NONE
;
45 LanguageTag
aLanguageTag1( rLocale1
);
47 if ( aLanguageTag1
.getLanguage() == rLanguageTag2
.getLanguage() )
48 eMatchLevel
= LOCALE_MATCH_LANG
;
52 if ( aLanguageTag1
.getScript() == rLanguageTag2
.getScript() )
53 eMatchLevel
= LOCALE_MATCH_LANG_SCRIPT
;
57 if ( aLanguageTag1
.getCountry() == rLanguageTag2
.getCountry() )
58 eMatchLevel
= LOCALE_MATCH_LANG_SCRIPT_COUNTRY
;
62 if (aLanguageTag1
== rLanguageTag2
)
63 return LOCALE_MATCH_ALL
;
68 ScCellKeyword::ScCellKeyword(const sal_Char
* pName
, OpCode eOpCode
, const lang::Locale
& rLocale
) :
75 ::std::unique_ptr
<ScCellKeywordTranslator
> ScCellKeywordTranslator::spInstance
;
77 static void lclMatchKeyword(OUString
& rName
, const ScCellKeywordHashMap
& aMap
,
78 OpCode eOpCode
= ocNone
, const lang::Locale
* pLocale
= NULL
)
80 ScCellKeywordHashMap::const_iterator itrEnd
= aMap
.end();
81 ScCellKeywordHashMap::const_iterator itr
= aMap
.find(rName
);
83 if ( itr
== itrEnd
|| itr
->second
.empty() )
84 // No candidate strings exist. Bail out.
87 if ( eOpCode
== ocNone
&& !pLocale
)
89 // Since no locale nor opcode matching is needed, simply return
90 // the first item on the list.
91 rName
= OUString::createFromAscii( itr
->second
.front().mpName
);
95 LanguageTag
aLanguageTag( pLocale
? *pLocale
: lang::Locale("","",""));
96 const sal_Char
* aBestMatchName
= itr
->second
.front().mpName
;
97 LocaleMatch eLocaleMatchLevel
= LOCALE_MATCH_NONE
;
98 bool bOpCodeMatched
= false;
100 list
<ScCellKeyword
>::const_iterator itrListEnd
= itr
->second
.end();
101 list
<ScCellKeyword
>::const_iterator itrList
= itr
->second
.begin();
102 for ( ; itrList
!= itrListEnd
; ++itrList
)
104 if ( eOpCode
!= ocNone
&& pLocale
)
106 if ( itrList
->meOpCode
== eOpCode
)
108 LocaleMatch eLevel
= lclLocaleCompare(itrList
->mrLocale
, aLanguageTag
);
109 if ( eLevel
== LOCALE_MATCH_ALL
)
111 // Name with matching opcode and locale found.
112 rName
= OUString::createFromAscii( itrList
->mpName
);
115 else if ( eLevel
> eLocaleMatchLevel
)
117 // Name with a better matching locale.
118 eLocaleMatchLevel
= eLevel
;
119 aBestMatchName
= itrList
->mpName
;
121 else if ( !bOpCodeMatched
)
122 // At least the opcode matches.
123 aBestMatchName
= itrList
->mpName
;
125 bOpCodeMatched
= true;
128 else if ( eOpCode
!= ocNone
&& !pLocale
)
130 if ( itrList
->meOpCode
== eOpCode
)
132 // Name with a matching opcode preferred.
133 rName
= OUString::createFromAscii( itrList
->mpName
);
139 LocaleMatch eLevel
= lclLocaleCompare(itrList
->mrLocale
, aLanguageTag
);
140 if ( eLevel
== LOCALE_MATCH_ALL
)
142 // Name with matching locale preferred.
143 rName
= OUString::createFromAscii( itrList
->mpName
);
146 else if ( eLevel
> eLocaleMatchLevel
)
148 // Name with a better matching locale.
149 eLocaleMatchLevel
= eLevel
;
150 aBestMatchName
= itrList
->mpName
;
155 // No preferred strings found. Return the best matching name.
156 rName
= OUString::createFromAscii(aBestMatchName
);
159 void ScCellKeywordTranslator::transKeyword(OUString
& rName
, const lang::Locale
* pLocale
, OpCode eOpCode
)
161 if ( !spInstance
.get() )
162 spInstance
.reset( new ScCellKeywordTranslator
);
164 LanguageType eLang
= pLocale
? LanguageTag(*pLocale
).makeFallback().getLanguageType() : LANGUAGE_SYSTEM
;
165 Sequence
<sal_Int32
> aOffsets
;
166 rName
= spInstance
->maTransWrapper
.transliterate(rName
, eLang
, 0, rName
.getLength(), &aOffsets
);
167 lclMatchKeyword(rName
, spInstance
->maStringNameMap
, eOpCode
, pLocale
);
170 ScCellKeywordTranslator::ScCellKeywordTranslator() :
171 maTransWrapper( ::comphelper::getProcessComponentContext(),
172 i18n::TransliterationModules_LOWERCASE_UPPERCASE
)
177 ScCellKeywordTranslator::~ScCellKeywordTranslator()
183 const sal_Unicode
* from
;
188 void ScCellKeywordTranslator::init()
190 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
192 // The file below has been autogenerated by sc/workben/celltrans/parse.py.
193 // To add new locale keywords, edit sc/workben/celltrans/keywords_utf16.txt
194 // and re-run the parse.py script.
196 // All keywords must be uppercase, and the mapping must be from the
197 // localized keyword to the English keyword.
199 // Make sure that the original keyword file (keywords_utf16.txt) is
200 // encoded in UCS-2/UTF-16!
202 #include "cellkeywords.inl"
205 void ScCellKeywordTranslator::addToMap(const OUString
& rKey
, const sal_Char
* pName
, const lang::Locale
& rLocale
, OpCode eOpCode
)
207 ScCellKeyword
aKeyItem( pName
, eOpCode
, rLocale
);
209 ScCellKeywordHashMap::iterator itrEnd
= maStringNameMap
.end();
210 ScCellKeywordHashMap::iterator itr
= maStringNameMap
.find(rKey
);
215 list
<ScCellKeyword
> aList
;
216 aList
.push_back(aKeyItem
);
217 maStringNameMap
.insert( ScCellKeywordHashMap::value_type(rKey
, aList
) );
220 itr
->second
.push_back(aKeyItem
);
223 void ScCellKeywordTranslator::addToMap(const TransItem
* pItems
, const lang::Locale
& rLocale
)
225 for (sal_uInt16 i
= 0; pItems
[i
].from
!= NULL
; ++i
)
226 addToMap(OUString(pItems
[i
].from
), pItems
[i
].to
, rLocale
, pItems
[i
].func
);
229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */