/src/libreoffice/i18nutil/source/utility/unicode.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <com/sun/star/i18n/UnicodeType.hpp> |
21 | | #include <com/sun/star/i18n/ScriptType.hpp> |
22 | | #include <i18nlangtag/languagetag.hxx> |
23 | | #include <i18nlangtag/languagetagicu.hxx> |
24 | | #include <i18nutil/unicode.hxx> |
25 | | #include <sal/log.hxx> |
26 | | #include <unicode/numfmt.h> |
27 | | #include <unicode/uchar.h> |
28 | | #include "unicode_data.h" |
29 | | #include <rtl/character.hxx> |
30 | | #include <o3tl/string_view.hxx> |
31 | | #include <memory> |
32 | | |
33 | | // Workaround for glibc braindamage: |
34 | | // glibc 2.4's langinfo.h does "#define CURRENCY_SYMBOL __CURRENCY_SYMBOL" |
35 | | // which (obviously) breaks UnicodeType::CURRENCY_SYMBOL |
36 | | #undef CURRENCY_SYMBOL |
37 | | |
38 | | using namespace ::com::sun::star::i18n; |
39 | | |
40 | | template<class L, typename T> |
41 | 289 | static T getScriptType( const sal_Unicode ch, const L* typeList, T unknownType ) { |
42 | | |
43 | 289 | sal_Int16 i = 0; |
44 | 289 | css::i18n::UnicodeScript type = typeList[0].to; |
45 | 289 | while (type < UnicodeScript_kScriptCount && ch > UnicodeScriptType[static_cast<int>(type)][UnicodeScriptTypeTo]) { |
46 | 0 | type = typeList[++i].to; |
47 | 0 | } |
48 | | |
49 | 289 | return (type < UnicodeScript_kScriptCount && |
50 | 289 | ch >= UnicodeScriptType[static_cast<int>(typeList[i].from)][int(UnicodeScriptTypeFrom)]) ? |
51 | 278 | typeList[i].value : unknownType; |
52 | 289 | } |
53 | | |
54 | | sal_Int16 |
55 | 289 | unicode::getUnicodeScriptType( const sal_Unicode ch, const ScriptTypeList* typeList, sal_Int16 unknownType ) { |
56 | 289 | return getScriptType(ch, typeList, unknownType); |
57 | 289 | } |
58 | | |
59 | | sal_Unicode |
60 | 0 | unicode::getUnicodeScriptStart( UnicodeScript type) { |
61 | 0 | return UnicodeScriptType[static_cast<int>(type)][UnicodeScriptTypeFrom]; |
62 | 0 | } |
63 | | |
64 | | sal_Unicode |
65 | 0 | unicode::getUnicodeScriptEnd( UnicodeScript type) { |
66 | 0 | return UnicodeScriptType[static_cast<int>(type)][UnicodeScriptTypeTo]; |
67 | 0 | } |
68 | | |
69 | | sal_Int16 |
70 | | unicode::getUnicodeType(const sal_uInt32 ch) |
71 | 5.37M | { |
72 | 5.37M | static thread_local sal_uInt32 c = 0x00; |
73 | 5.37M | static thread_local sal_Int16 r = 0x00; |
74 | | |
75 | 5.37M | if (ch == c) return r; |
76 | 4.72M | else c = ch; |
77 | | |
78 | 4.72M | switch (u_charType(ch)) |
79 | 4.72M | { |
80 | 242k | case U_UNASSIGNED: |
81 | 242k | r = css::i18n::UnicodeType::UNASSIGNED; |
82 | 242k | break; |
83 | 306k | case U_UPPERCASE_LETTER: |
84 | 306k | r = css::i18n::UnicodeType::UPPERCASE_LETTER; |
85 | 306k | break; |
86 | 404k | case U_LOWERCASE_LETTER: |
87 | 404k | r = css::i18n::UnicodeType::LOWERCASE_LETTER; |
88 | 404k | break; |
89 | 5.16k | case U_TITLECASE_LETTER: |
90 | 5.16k | r = css::i18n::UnicodeType::TITLECASE_LETTER; |
91 | 5.16k | break; |
92 | 19.7k | case U_MODIFIER_LETTER: |
93 | 19.7k | r = css::i18n::UnicodeType::MODIFIER_LETTER; |
94 | 19.7k | break; |
95 | 2.20M | case U_OTHER_LETTER: |
96 | 2.20M | r = css::i18n::UnicodeType::OTHER_LETTER; |
97 | 2.20M | break; |
98 | 191k | case U_NON_SPACING_MARK: |
99 | 191k | r = css::i18n::UnicodeType::NON_SPACING_MARK; |
100 | 191k | break; |
101 | 359 | case U_ENCLOSING_MARK: |
102 | 359 | r = css::i18n::UnicodeType::ENCLOSING_MARK; |
103 | 359 | break; |
104 | 31.6k | case U_COMBINING_SPACING_MARK: |
105 | 31.6k | r = css::i18n::UnicodeType::COMBINING_SPACING_MARK; |
106 | 31.6k | break; |
107 | 57.7k | case U_DECIMAL_DIGIT_NUMBER: |
108 | 57.7k | r = css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER; |
109 | 57.7k | break; |
110 | 9.39k | case U_LETTER_NUMBER: |
111 | 9.39k | r = css::i18n::UnicodeType::LETTER_NUMBER; |
112 | 9.39k | break; |
113 | 15.9k | case U_OTHER_NUMBER: |
114 | 15.9k | r = css::i18n::UnicodeType::OTHER_NUMBER; |
115 | 15.9k | break; |
116 | 6.61k | case U_SPACE_SEPARATOR: |
117 | 6.61k | r = css::i18n::UnicodeType::SPACE_SEPARATOR; |
118 | 6.61k | break; |
119 | 0 | case U_LINE_SEPARATOR: |
120 | 0 | r = css::i18n::UnicodeType::LINE_SEPARATOR; |
121 | 0 | break; |
122 | 0 | case U_PARAGRAPH_SEPARATOR: |
123 | 0 | r = css::i18n::UnicodeType::PARAGRAPH_SEPARATOR; |
124 | 0 | break; |
125 | 766k | case U_CONTROL_CHAR: |
126 | 766k | r = css::i18n::UnicodeType::CONTROL; |
127 | 766k | break; |
128 | 58.1k | case U_FORMAT_CHAR: |
129 | 58.1k | r = css::i18n::UnicodeType::FORMAT; |
130 | 58.1k | break; |
131 | 5 | case U_PRIVATE_USE_CHAR: |
132 | 5 | r = css::i18n::UnicodeType::PRIVATE_USE; |
133 | 5 | break; |
134 | 3 | case U_SURROGATE: |
135 | 3 | r = css::i18n::UnicodeType::SURROGATE; |
136 | 3 | break; |
137 | 13.6k | case U_DASH_PUNCTUATION: |
138 | 13.6k | r = css::i18n::UnicodeType::DASH_PUNCTUATION; |
139 | 13.6k | break; |
140 | 810 | case U_INITIAL_PUNCTUATION: |
141 | 810 | r = css::i18n::UnicodeType::INITIAL_PUNCTUATION; |
142 | 810 | break; |
143 | 11.2k | case U_FINAL_PUNCTUATION: |
144 | 11.2k | r = css::i18n::UnicodeType::FINAL_PUNCTUATION; |
145 | 11.2k | break; |
146 | 623 | case U_CONNECTOR_PUNCTUATION: |
147 | 623 | r = css::i18n::UnicodeType::CONNECTOR_PUNCTUATION; |
148 | 623 | break; |
149 | 161k | case U_OTHER_PUNCTUATION: |
150 | 161k | r = css::i18n::UnicodeType::OTHER_PUNCTUATION; |
151 | 161k | break; |
152 | 31.5k | case U_MATH_SYMBOL: |
153 | 31.5k | r = css::i18n::UnicodeType::MATH_SYMBOL; |
154 | 31.5k | break; |
155 | 13.3k | case U_CURRENCY_SYMBOL: |
156 | 13.3k | r = css::i18n::UnicodeType::CURRENCY_SYMBOL; |
157 | 13.3k | break; |
158 | 23.3k | case U_MODIFIER_SYMBOL: |
159 | 23.3k | r = css::i18n::UnicodeType::MODIFIER_SYMBOL; |
160 | 23.3k | break; |
161 | 118k | case U_OTHER_SYMBOL: |
162 | 118k | r = css::i18n::UnicodeType::OTHER_SYMBOL; |
163 | 118k | break; |
164 | 21.0k | case U_START_PUNCTUATION: |
165 | 21.0k | r = css::i18n::UnicodeType::START_PUNCTUATION; |
166 | 21.0k | break; |
167 | 8.43k | case U_END_PUNCTUATION: |
168 | 8.43k | r = css::i18n::UnicodeType::END_PUNCTUATION; |
169 | 8.43k | break; |
170 | 4.72M | } |
171 | | |
172 | 4.72M | return r; |
173 | 4.72M | } |
174 | | |
175 | | sal_uInt8 |
176 | 0 | unicode::getUnicodeDirection( const sal_Unicode ch ) { |
177 | 0 | static thread_local sal_Unicode c = 0x00; |
178 | 0 | static thread_local sal_uInt8 r = 0x00; |
179 | |
|
180 | 0 | if (ch == c) return r; |
181 | 0 | else c = ch; |
182 | | |
183 | 0 | sal_Int16 address = UnicodeDirectionIndex[ch >> 8]; |
184 | 0 | r = (address < UnicodeDirectionNumberBlock) |
185 | 0 | ? UnicodeDirectionBlockValue[address] |
186 | 0 | : UnicodeDirectionValue[((address - UnicodeDirectionNumberBlock) << 8) + (ch & 0xff)]; |
187 | 0 | return r; |
188 | 0 | } |
189 | | |
190 | 0 | sal_uInt32 unicode::GetMirroredChar(sal_uInt32 nChar) { |
191 | 0 | nChar = u_charMirror(nChar); |
192 | 0 | return nChar; |
193 | 0 | } |
194 | | |
195 | 0 | static constexpr auto bit(sal_Int16 name) { return 1U << name; } |
196 | | |
197 | | bool unicode::isControl(const sal_uInt32 ch) |
198 | 0 | { |
199 | 0 | const auto CONTROLMASK = bit(css::i18n::UnicodeType::CONTROL) | |
200 | 0 | bit(css::i18n::UnicodeType::FORMAT) | |
201 | 0 | bit(css::i18n::UnicodeType::LINE_SEPARATOR) | |
202 | 0 | bit(css::i18n::UnicodeType::PARAGRAPH_SEPARATOR); |
203 | 0 | return (bit(getUnicodeType(ch)) & CONTROLMASK) != 0; |
204 | 0 | } |
205 | | |
206 | | bool unicode::isAlpha(const sal_uInt32 ch) |
207 | 0 | { |
208 | 0 | const auto ALPHAMASK = bit(css::i18n::UnicodeType::UPPERCASE_LETTER) | |
209 | 0 | bit(css::i18n::UnicodeType::LOWERCASE_LETTER) | |
210 | 0 | bit(css::i18n::UnicodeType::TITLECASE_LETTER) | |
211 | 0 | bit(css::i18n::UnicodeType::MODIFIER_LETTER) | |
212 | 0 | bit(css::i18n::UnicodeType::OTHER_LETTER); |
213 | 0 | return (bit(getUnicodeType(ch)) & ALPHAMASK) != 0; |
214 | 0 | } |
215 | | |
216 | 0 | bool unicode::isSpace(const sal_uInt32 ch) { |
217 | 0 | const auto SPACEMASK = bit(css::i18n::UnicodeType::SPACE_SEPARATOR) | |
218 | 0 | bit(css::i18n::UnicodeType::LINE_SEPARATOR) | |
219 | 0 | bit(css::i18n::UnicodeType::PARAGRAPH_SEPARATOR); |
220 | 0 | return (bit(getUnicodeType(ch)) & SPACEMASK) != 0; |
221 | 0 | } |
222 | | |
223 | | bool unicode::isWhiteSpace(const sal_uInt32 ch) |
224 | 0 | { |
225 | 0 | const auto CONTROLSPACE = bit(0x09) | bit(0x0a) | bit(0x0b) | bit(0x0c) | bit(0x0d) | bit(0x1c) |
226 | 0 | | bit(0x1d) | bit(0x1e) | bit(0x1f); |
227 | 0 | return (ch != 0xa0 && isSpace(ch)) || (ch <= 0x1F && (bit(ch) & CONTROLSPACE)); |
228 | 0 | } |
229 | | |
230 | | sal_Int16 unicode::getScriptClassFromUScriptCode(UScriptCode eScript) |
231 | 75.9M | { |
232 | | //See unicode/uscript.h |
233 | 75.9M | sal_Int16 nRet; |
234 | 75.9M | switch (eScript) |
235 | 75.9M | { |
236 | 0 | case USCRIPT_INVALID_CODE: |
237 | 18.6M | case USCRIPT_COMMON: |
238 | 21.8M | case USCRIPT_INHERITED: |
239 | 21.8M | case USCRIPT_UNWRITTEN_LANGUAGES: |
240 | 59.2M | case USCRIPT_UNKNOWN: |
241 | 59.2M | case USCRIPT_MATHEMATICAL_NOTATION: |
242 | 59.2M | case USCRIPT_SYMBOLS: |
243 | 59.2M | case USCRIPT_CODE_LIMIT: |
244 | 59.2M | nRet = ScriptType::WEAK; |
245 | 59.2M | break; |
246 | 6.33k | case USCRIPT_ARMENIAN: |
247 | 111k | case USCRIPT_CHEROKEE: |
248 | 189k | case USCRIPT_COPTIC: |
249 | 4.31M | case USCRIPT_CYRILLIC: |
250 | 4.78M | case USCRIPT_GEORGIAN: |
251 | 4.78M | case USCRIPT_GOTHIC: |
252 | 4.81M | case USCRIPT_GREEK: |
253 | 5.51M | case USCRIPT_LATIN: |
254 | 5.51M | case USCRIPT_OGHAM: |
255 | 5.51M | case USCRIPT_OLD_ITALIC: |
256 | 5.51M | case USCRIPT_RUNIC: |
257 | 5.67M | case USCRIPT_CANADIAN_ABORIGINAL: |
258 | 6.50M | case USCRIPT_BRAILLE: |
259 | 6.51M | case USCRIPT_CYPRIOT: |
260 | 6.51M | case USCRIPT_OSMANYA: |
261 | 6.51M | case USCRIPT_SHAVIAN: |
262 | 6.51M | case USCRIPT_KATAKANA_OR_HIRAGANA: |
263 | 6.79M | case USCRIPT_GLAGOLITIC: |
264 | 6.79M | case USCRIPT_CIRTH: |
265 | 6.79M | case USCRIPT_OLD_CHURCH_SLAVONIC_CYRILLIC: |
266 | 6.79M | case USCRIPT_OLD_HUNGARIAN: |
267 | 6.79M | case USCRIPT_LATIN_FRAKTUR: |
268 | 6.79M | case USCRIPT_LATIN_GAELIC: |
269 | 6.79M | nRet = ScriptType::LATIN; |
270 | 6.79M | break; |
271 | 0 | case USCRIPT_BOPOMOFO: |
272 | 6.01k | case USCRIPT_HAN: |
273 | 129k | case USCRIPT_HANGUL: |
274 | 130k | case USCRIPT_HIRAGANA: |
275 | 166k | case USCRIPT_KATAKANA: |
276 | 166k | case USCRIPT_YI: |
277 | 166k | case USCRIPT_SIMPLIFIED_HAN: |
278 | 166k | case USCRIPT_TRADITIONAL_HAN: |
279 | 166k | case USCRIPT_JAPANESE: |
280 | 166k | case USCRIPT_KOREAN: |
281 | 167k | case USCRIPT_TANGUT: |
282 | 167k | case USCRIPT_KHITAN_SMALL_SCRIPT: |
283 | 167k | nRet = ScriptType::ASIAN; |
284 | 167k | break; |
285 | 1.49M | case USCRIPT_ARABIC: |
286 | 1.49M | case USCRIPT_BENGALI: |
287 | 1.49M | case USCRIPT_DESERET: |
288 | 1.53M | case USCRIPT_DEVANAGARI: |
289 | 1.86M | case USCRIPT_ETHIOPIC: |
290 | 1.86M | case USCRIPT_GUJARATI: |
291 | 1.86M | case USCRIPT_GURMUKHI: |
292 | 1.92M | case USCRIPT_HEBREW: |
293 | 1.92M | case USCRIPT_KANNADA: |
294 | 1.96M | case USCRIPT_KHMER: |
295 | 1.96M | case USCRIPT_LAO: |
296 | 1.96M | case USCRIPT_MALAYALAM: |
297 | 1.96M | case USCRIPT_MONGOLIAN: |
298 | 2.04M | case USCRIPT_MYANMAR: |
299 | 2.04M | case USCRIPT_ORIYA: |
300 | 2.04M | case USCRIPT_SINHALA: |
301 | 2.09M | case USCRIPT_SYRIAC: |
302 | 2.09M | case USCRIPT_TAMIL: |
303 | 2.09M | case USCRIPT_TELUGU: |
304 | 2.09M | case USCRIPT_THAANA: |
305 | 2.09M | case USCRIPT_THAI: |
306 | 2.09M | case USCRIPT_TIBETAN: |
307 | 2.22M | case USCRIPT_TAGALOG: |
308 | 2.25M | case USCRIPT_HANUNOO: |
309 | 2.27M | case USCRIPT_BUHID: |
310 | 2.30M | case USCRIPT_TAGBANWA: |
311 | 2.54M | case USCRIPT_LIMBU: |
312 | 2.55M | case USCRIPT_LINEAR_B: |
313 | 2.58M | case USCRIPT_TAI_LE: |
314 | 2.58M | case USCRIPT_UGARITIC: |
315 | 2.80M | case USCRIPT_BUGINESE: |
316 | 2.80M | case USCRIPT_KHAROSHTHI: |
317 | 2.97M | case USCRIPT_SYLOTI_NAGRI: |
318 | 3.06M | case USCRIPT_NEW_TAI_LUE: |
319 | 3.23M | case USCRIPT_TIFINAGH: |
320 | 3.23M | case USCRIPT_OLD_PERSIAN: |
321 | 3.68M | case USCRIPT_BALINESE: |
322 | 3.74M | case USCRIPT_BATAK: |
323 | 3.74M | case USCRIPT_BLISSYMBOLS: |
324 | 3.74M | case USCRIPT_BRAHMI: |
325 | 4.00M | case USCRIPT_CHAM: |
326 | 4.00M | case USCRIPT_DEMOTIC_EGYPTIAN: |
327 | 4.00M | case USCRIPT_HIERATIC_EGYPTIAN: |
328 | 4.00M | case USCRIPT_EGYPTIAN_HIEROGLYPHS: |
329 | 4.00M | case USCRIPT_KHUTSURI: |
330 | 4.00M | case USCRIPT_PAHAWH_HMONG: |
331 | 4.00M | case USCRIPT_HARAPPAN_INDUS: |
332 | 4.11M | case USCRIPT_JAVANESE: |
333 | 4.20M | case USCRIPT_KAYAH_LI: |
334 | 4.77M | case USCRIPT_LEPCHA: |
335 | 4.77M | case USCRIPT_LINEAR_A: |
336 | 4.86M | case USCRIPT_MANDAEAN: |
337 | 4.86M | case USCRIPT_MAYAN_HIEROGLYPHS: |
338 | 4.86M | case USCRIPT_MEROITIC: |
339 | 5.34M | case USCRIPT_NKO: |
340 | 5.34M | case USCRIPT_ORKHON: |
341 | 5.34M | case USCRIPT_OLD_PERMIC: |
342 | 5.40M | case USCRIPT_PHAGS_PA: |
343 | 5.40M | case USCRIPT_PHOENICIAN: |
344 | 5.40M | case USCRIPT_PHONETIC_POLLARD: |
345 | 5.40M | case USCRIPT_RONGORONGO: |
346 | 5.40M | case USCRIPT_SARATI: |
347 | 5.40M | case USCRIPT_ESTRANGELO_SYRIAC: |
348 | 5.40M | case USCRIPT_WESTERN_SYRIAC: |
349 | 5.40M | case USCRIPT_EASTERN_SYRIAC: |
350 | 5.40M | case USCRIPT_TENGWAR: |
351 | 5.86M | case USCRIPT_VAI: |
352 | 5.86M | case USCRIPT_VISIBLE_SPEECH: |
353 | 5.86M | case USCRIPT_CUNEIFORM: |
354 | 5.86M | case USCRIPT_CARIAN: |
355 | 6.07M | case USCRIPT_LANNA: |
356 | 6.07M | case USCRIPT_LYCIAN: |
357 | 6.07M | case USCRIPT_LYDIAN: |
358 | 6.12M | case USCRIPT_OL_CHIKI: |
359 | 6.18M | case USCRIPT_REJANG: |
360 | 6.27M | case USCRIPT_SAURASHTRA: |
361 | 6.27M | case USCRIPT_SIGN_WRITING: |
362 | 6.34M | case USCRIPT_SUNDANESE: |
363 | 6.34M | case USCRIPT_MOON: |
364 | 6.42M | case USCRIPT_MEITEI_MAYEK: |
365 | 6.42M | case USCRIPT_IMPERIAL_ARAMAIC: |
366 | 6.42M | case USCRIPT_AVESTAN: |
367 | 6.42M | case USCRIPT_CHAKMA: |
368 | 6.42M | case USCRIPT_KAITHI: |
369 | 6.42M | case USCRIPT_MANICHAEAN: |
370 | 6.42M | case USCRIPT_INSCRIPTIONAL_PAHLAVI: |
371 | 6.42M | case USCRIPT_PSALTER_PAHLAVI: |
372 | 6.42M | case USCRIPT_BOOK_PAHLAVI: |
373 | 6.42M | case USCRIPT_INSCRIPTIONAL_PARTHIAN: |
374 | 9.39M | case USCRIPT_SAMARITAN: |
375 | 9.52M | case USCRIPT_TAI_VIET: |
376 | 9.64M | case USCRIPT_BAMUM: |
377 | 9.69M | case USCRIPT_LISU: |
378 | 9.69M | case USCRIPT_NAKHI_GEBA: |
379 | 9.69M | case USCRIPT_OLD_SOUTH_ARABIAN: |
380 | 9.69M | case USCRIPT_BASSA_VAH: |
381 | 9.69M | case USCRIPT_DUPLOYAN_SHORTAND: |
382 | 9.69M | case USCRIPT_ELBASAN: |
383 | 9.69M | case USCRIPT_GRANTHA: |
384 | 9.69M | case USCRIPT_KPELLE: |
385 | 9.69M | case USCRIPT_LOMA: |
386 | 9.77M | case USCRIPT_MENDE: |
387 | 9.77M | case USCRIPT_MEROITIC_CURSIVE: |
388 | 9.77M | case USCRIPT_OLD_NORTH_ARABIAN: |
389 | 9.77M | case USCRIPT_NABATAEAN: |
390 | 9.77M | case USCRIPT_PALMYRENE: |
391 | 9.77M | case USCRIPT_SINDHI: |
392 | 9.77M | case USCRIPT_WARANG_CITI: |
393 | 9.77M | default: // anything new is going to be pretty wild |
394 | 9.77M | nRet = ScriptType::COMPLEX; |
395 | 9.77M | break; |
396 | 75.9M | } |
397 | 75.9M | return nRet; |
398 | 75.9M | } |
399 | | |
400 | | sal_Int16 unicode::getScriptClassFromLanguageTag( const LanguageTag& rLanguageTag ) |
401 | 0 | { |
402 | 0 | constexpr int32_t nBuf = 42; |
403 | 0 | UScriptCode aBuf[nBuf]; |
404 | 0 | if (rLanguageTag.hasScript()) |
405 | 0 | { |
406 | 0 | aBuf[0] = static_cast<UScriptCode>(u_getPropertyValueEnum( UCHAR_SCRIPT, |
407 | 0 | OUStringToOString( rLanguageTag.getScript(), RTL_TEXTENCODING_ASCII_US).getStr())); |
408 | 0 | } |
409 | 0 | else |
410 | 0 | { |
411 | 0 | OUString aName; |
412 | 0 | if (rLanguageTag.getCountry().isEmpty()) |
413 | 0 | aName = rLanguageTag.getLanguage(); |
414 | 0 | else |
415 | 0 | aName = rLanguageTag.getLanguage() + "-" + rLanguageTag.getCountry(); |
416 | 0 | UErrorCode status = U_ZERO_ERROR; |
417 | 0 | const int32_t nScripts = uscript_getCode( |
418 | 0 | OUStringToOString( aName, RTL_TEXTENCODING_ASCII_US).getStr(), |
419 | 0 | aBuf, nBuf, &status); |
420 | | // U_BUFFER_OVERFLOW_ERROR would be set with too many scripts for buffer |
421 | | // and required capacity returned, but really.. |
422 | 0 | if (nScripts == 0 || !U_SUCCESS(status)) |
423 | 0 | return css::i18n::ScriptType::LATIN; |
424 | 0 | } |
425 | 0 | return getScriptClassFromUScriptCode( aBuf[0]); |
426 | 0 | } |
427 | | |
428 | | OString unicode::getExemplarLanguageForUScriptCode(UScriptCode eScript) |
429 | 0 | { |
430 | 0 | OString sRet; |
431 | 0 | switch (eScript) |
432 | 0 | { |
433 | 0 | case USCRIPT_CODE_LIMIT: |
434 | 0 | case USCRIPT_INVALID_CODE: |
435 | 0 | case USCRIPT_MATHEMATICAL_NOTATION: |
436 | 0 | case USCRIPT_SYMBOLS: |
437 | 0 | sRet = "zxx"_ostr; |
438 | 0 | break; |
439 | 0 | case USCRIPT_COMMON: |
440 | 0 | case USCRIPT_INHERITED: |
441 | 0 | case USCRIPT_UNWRITTEN_LANGUAGES: |
442 | 0 | case USCRIPT_UNKNOWN: |
443 | 0 | sRet = "und"_ostr; |
444 | 0 | break; |
445 | 0 | case USCRIPT_ARABIC: |
446 | 0 | sRet = "ar"_ostr; |
447 | 0 | break; |
448 | 0 | case USCRIPT_ARMENIAN: |
449 | 0 | sRet = "hy"_ostr; |
450 | 0 | break; |
451 | 0 | case USCRIPT_BENGALI: |
452 | 0 | sRet = "bn"_ostr; |
453 | 0 | break; |
454 | 0 | case USCRIPT_BOPOMOFO: |
455 | 0 | sRet = "zh"_ostr; |
456 | 0 | break; |
457 | 0 | case USCRIPT_CHEROKEE: |
458 | 0 | sRet = "chr"_ostr; |
459 | 0 | break; |
460 | 0 | case USCRIPT_COPTIC: |
461 | 0 | sRet = "cop"_ostr; |
462 | 0 | break; |
463 | 0 | case USCRIPT_CYRILLIC: |
464 | 0 | sRet = "ru"_ostr; |
465 | 0 | break; |
466 | 0 | case USCRIPT_DESERET: |
467 | 0 | sRet = "en"_ostr; |
468 | 0 | break; |
469 | 0 | case USCRIPT_DEVANAGARI: |
470 | 0 | sRet = "hi"_ostr; |
471 | 0 | break; |
472 | 0 | case USCRIPT_ETHIOPIC: |
473 | 0 | sRet = "am"_ostr; |
474 | 0 | break; |
475 | 0 | case USCRIPT_GEORGIAN: |
476 | 0 | case USCRIPT_KHUTSURI: |
477 | 0 | sRet = "ka"_ostr; |
478 | 0 | break; |
479 | 0 | case USCRIPT_GOTHIC: |
480 | 0 | sRet = "got"_ostr; |
481 | 0 | break; |
482 | 0 | case USCRIPT_GREEK: |
483 | 0 | sRet = "el"_ostr; |
484 | 0 | break; |
485 | 0 | case USCRIPT_GUJARATI: |
486 | 0 | case USCRIPT_KHOJKI: |
487 | 0 | sRet = "gu"_ostr; |
488 | 0 | break; |
489 | 0 | case USCRIPT_GURMUKHI: |
490 | 0 | sRet = "pa"_ostr; |
491 | 0 | break; |
492 | 0 | case USCRIPT_HAN: |
493 | 0 | sRet = "zh"_ostr; |
494 | 0 | break; |
495 | 0 | case USCRIPT_HANGUL: |
496 | 0 | case USCRIPT_KOREAN: |
497 | 0 | case USCRIPT_JAMO: |
498 | 0 | sRet = "ko"_ostr; // Jamo - elements of Hangul Syllables |
499 | 0 | break; |
500 | 0 | case USCRIPT_HEBREW: |
501 | 0 | sRet = "hr"_ostr; |
502 | 0 | break; |
503 | 0 | case USCRIPT_HIRAGANA: |
504 | 0 | sRet = "ja"_ostr; |
505 | 0 | break; |
506 | 0 | case USCRIPT_KANNADA: |
507 | 0 | sRet = "kn"_ostr; |
508 | 0 | break; |
509 | 0 | case USCRIPT_KATAKANA: |
510 | 0 | sRet = "ja"_ostr; |
511 | 0 | break; |
512 | 0 | case USCRIPT_KHMER: |
513 | 0 | sRet = "km"_ostr; |
514 | 0 | break; |
515 | 0 | case USCRIPT_LAO: |
516 | 0 | sRet = "lo"_ostr; |
517 | 0 | break; |
518 | 0 | case USCRIPT_LATIN: |
519 | 0 | sRet = "en"_ostr; |
520 | 0 | break; |
521 | 0 | case USCRIPT_MALAYALAM: |
522 | 0 | sRet = "ml"_ostr; |
523 | 0 | break; |
524 | 0 | case USCRIPT_MONGOLIAN: |
525 | 0 | sRet = "mn"_ostr; |
526 | 0 | break; |
527 | 0 | case USCRIPT_MYANMAR: |
528 | 0 | sRet = "my"_ostr; |
529 | 0 | break; |
530 | 0 | case USCRIPT_OGHAM: |
531 | 0 | sRet = "pgl"_ostr; |
532 | 0 | break; |
533 | 0 | case USCRIPT_OLD_ITALIC: |
534 | 0 | sRet = "osc"_ostr; |
535 | 0 | break; |
536 | 0 | case USCRIPT_ORIYA: |
537 | 0 | sRet = "or"_ostr; |
538 | 0 | break; |
539 | 0 | case USCRIPT_RUNIC: |
540 | 0 | sRet = "ang"_ostr; |
541 | 0 | break; |
542 | 0 | case USCRIPT_SINHALA: |
543 | 0 | sRet = "si"_ostr; |
544 | 0 | break; |
545 | 0 | case USCRIPT_SYRIAC: |
546 | 0 | case USCRIPT_ESTRANGELO_SYRIAC: |
547 | 0 | sRet = "syr"_ostr; |
548 | 0 | break; |
549 | 0 | case USCRIPT_TAMIL: |
550 | 0 | case USCRIPT_GRANTHA: |
551 | 0 | sRet = "ta"_ostr; |
552 | 0 | break; |
553 | 0 | case USCRIPT_TELUGU: |
554 | 0 | sRet = "te"_ostr; |
555 | 0 | break; |
556 | 0 | case USCRIPT_THAANA: |
557 | 0 | sRet = "dv"_ostr; |
558 | 0 | break; |
559 | 0 | case USCRIPT_THAI: |
560 | 0 | sRet = "th"_ostr; |
561 | 0 | break; |
562 | 0 | case USCRIPT_TIBETAN: |
563 | 0 | sRet = "bo"_ostr; |
564 | 0 | break; |
565 | 0 | case USCRIPT_CANADIAN_ABORIGINAL: |
566 | 0 | sRet = "iu"_ostr; |
567 | 0 | break; |
568 | 0 | case USCRIPT_YI: |
569 | 0 | sRet = "ii"_ostr; |
570 | 0 | break; |
571 | 0 | case USCRIPT_TAGALOG: |
572 | 0 | sRet = "tl"_ostr; |
573 | 0 | break; |
574 | 0 | case USCRIPT_HANUNOO: |
575 | 0 | sRet = "hnn"_ostr; |
576 | 0 | break; |
577 | 0 | case USCRIPT_BUHID: |
578 | 0 | sRet = "bku"_ostr; |
579 | 0 | break; |
580 | 0 | case USCRIPT_TAGBANWA: |
581 | 0 | sRet = "tbw"_ostr; |
582 | 0 | break; |
583 | 0 | case USCRIPT_BRAILLE: |
584 | 0 | sRet = "en"_ostr; |
585 | 0 | break; |
586 | 0 | case USCRIPT_CYPRIOT: |
587 | 0 | sRet = "ecy"_ostr; |
588 | 0 | break; |
589 | 0 | case USCRIPT_LIMBU: |
590 | 0 | sRet = "lif"_ostr; |
591 | 0 | break; |
592 | 0 | case USCRIPT_LINEAR_B: |
593 | 0 | sRet = "gmy"_ostr; |
594 | 0 | break; |
595 | 0 | case USCRIPT_OSMANYA: |
596 | 0 | sRet = "so"_ostr; |
597 | 0 | break; |
598 | 0 | case USCRIPT_SHAVIAN: |
599 | 0 | sRet = "en"_ostr; |
600 | 0 | break; |
601 | 0 | case USCRIPT_TAI_LE: |
602 | 0 | sRet = "tdd"_ostr; |
603 | 0 | break; |
604 | 0 | case USCRIPT_UGARITIC: |
605 | 0 | sRet = "uga"_ostr; |
606 | 0 | break; |
607 | 0 | case USCRIPT_KATAKANA_OR_HIRAGANA: |
608 | 0 | sRet = "ja"_ostr; |
609 | 0 | break; |
610 | 0 | case USCRIPT_BUGINESE: |
611 | 0 | sRet = "bug"_ostr; |
612 | 0 | break; |
613 | 0 | case USCRIPT_GLAGOLITIC: |
614 | 0 | sRet = "ch"_ostr; |
615 | 0 | break; |
616 | 0 | case USCRIPT_KHAROSHTHI: |
617 | 0 | case USCRIPT_BRAHMI: |
618 | 0 | sRet = "pra"_ostr; |
619 | 0 | break; |
620 | 0 | case USCRIPT_SYLOTI_NAGRI: |
621 | 0 | sRet = "syl"_ostr; |
622 | 0 | break; |
623 | 0 | case USCRIPT_NEW_TAI_LUE: |
624 | 0 | sRet = "khb"_ostr; |
625 | 0 | break; |
626 | 0 | case USCRIPT_TIFINAGH: |
627 | 0 | sRet = "tmh"_ostr; |
628 | 0 | break; |
629 | 0 | case USCRIPT_OLD_PERSIAN: |
630 | 0 | sRet = "peo"_ostr; |
631 | 0 | break; |
632 | 0 | case USCRIPT_BALINESE: |
633 | 0 | sRet = "ban"_ostr; |
634 | 0 | break; |
635 | 0 | case USCRIPT_BATAK: |
636 | 0 | sRet = "btk"_ostr; |
637 | 0 | break; |
638 | 0 | case USCRIPT_BLISSYMBOLS: |
639 | 0 | sRet = "en"_ostr; |
640 | 0 | break; |
641 | 0 | case USCRIPT_CHAM: |
642 | 0 | sRet = "cja"_ostr; |
643 | 0 | break; |
644 | 0 | case USCRIPT_CIRTH: |
645 | 0 | case USCRIPT_TENGWAR: |
646 | 0 | sRet = "sjn"_ostr; |
647 | 0 | break; |
648 | 0 | case USCRIPT_OLD_CHURCH_SLAVONIC_CYRILLIC: |
649 | 0 | sRet = "cu"_ostr; |
650 | 0 | break; |
651 | 0 | case USCRIPT_DEMOTIC_EGYPTIAN: |
652 | 0 | case USCRIPT_HIERATIC_EGYPTIAN: |
653 | 0 | case USCRIPT_EGYPTIAN_HIEROGLYPHS: |
654 | 0 | sRet = "egy"_ostr; |
655 | 0 | break; |
656 | 0 | case USCRIPT_SIMPLIFIED_HAN: |
657 | 0 | sRet = "zh"_ostr; |
658 | 0 | break; |
659 | 0 | case USCRIPT_TRADITIONAL_HAN: |
660 | 0 | sRet = "zh"_ostr; |
661 | 0 | break; |
662 | 0 | case USCRIPT_PAHAWH_HMONG: |
663 | 0 | sRet = "blu"_ostr; |
664 | 0 | break; |
665 | 0 | case USCRIPT_OLD_HUNGARIAN: |
666 | 0 | sRet = "ohu"_ostr; |
667 | 0 | break; |
668 | 0 | case USCRIPT_HARAPPAN_INDUS: |
669 | 0 | sRet = "xiv"_ostr; |
670 | 0 | break; |
671 | 0 | case USCRIPT_JAVANESE: |
672 | 0 | sRet = "kaw"_ostr; |
673 | 0 | break; |
674 | 0 | case USCRIPT_KAYAH_LI: |
675 | 0 | sRet = "eky"_ostr; |
676 | 0 | break; |
677 | 0 | case USCRIPT_LATIN_FRAKTUR: |
678 | 0 | sRet = "de"_ostr; |
679 | 0 | break; |
680 | 0 | case USCRIPT_LATIN_GAELIC: |
681 | 0 | sRet = "ga"_ostr; |
682 | 0 | break; |
683 | 0 | case USCRIPT_LEPCHA: |
684 | 0 | sRet = "lep"_ostr; |
685 | 0 | break; |
686 | 0 | case USCRIPT_LINEAR_A: |
687 | 0 | sRet = "ecr"_ostr; |
688 | 0 | break; |
689 | 0 | case USCRIPT_MAYAN_HIEROGLYPHS: |
690 | 0 | sRet = "myn"_ostr; |
691 | 0 | break; |
692 | 0 | case USCRIPT_MEROITIC_CURSIVE: |
693 | 0 | case USCRIPT_MEROITIC: |
694 | 0 | sRet = "xmr"_ostr; |
695 | 0 | break; |
696 | 0 | case USCRIPT_NKO: |
697 | 0 | sRet = "nqo"_ostr; |
698 | 0 | break; |
699 | 0 | case USCRIPT_ORKHON: |
700 | 0 | sRet = "otk"_ostr; |
701 | 0 | break; |
702 | 0 | case USCRIPT_OLD_PERMIC: |
703 | 0 | sRet = "kv"_ostr; |
704 | 0 | break; |
705 | 0 | case USCRIPT_PHAGS_PA: |
706 | 0 | sRet = "xng"_ostr; |
707 | 0 | break; |
708 | 0 | case USCRIPT_PHOENICIAN: |
709 | 0 | sRet = "phn"_ostr; |
710 | 0 | break; |
711 | 0 | case USCRIPT_PHONETIC_POLLARD: |
712 | 0 | sRet = "hmd"_ostr; |
713 | 0 | break; |
714 | 0 | case USCRIPT_RONGORONGO: |
715 | 0 | sRet = "rap"_ostr; |
716 | 0 | break; |
717 | 0 | case USCRIPT_SARATI: |
718 | 0 | sRet = "qya"_ostr; |
719 | 0 | break; |
720 | 0 | case USCRIPT_WESTERN_SYRIAC: |
721 | 0 | sRet = "tru"_ostr; |
722 | 0 | break; |
723 | 0 | case USCRIPT_EASTERN_SYRIAC: |
724 | 0 | sRet = "aii"_ostr; |
725 | 0 | break; |
726 | 0 | case USCRIPT_VAI: |
727 | 0 | sRet = "vai"_ostr; |
728 | 0 | break; |
729 | 0 | case USCRIPT_VISIBLE_SPEECH: |
730 | 0 | sRet = "en"_ostr; |
731 | 0 | break; |
732 | 0 | case USCRIPT_CUNEIFORM: |
733 | 0 | sRet = "akk"_ostr; |
734 | 0 | break; |
735 | 0 | case USCRIPT_CARIAN: |
736 | 0 | sRet = "xcr"_ostr; |
737 | 0 | break; |
738 | 0 | case USCRIPT_JAPANESE: |
739 | 0 | sRet = "ja"_ostr; |
740 | 0 | break; |
741 | 0 | case USCRIPT_LANNA: |
742 | 0 | sRet = "nod"_ostr; |
743 | 0 | break; |
744 | 0 | case USCRIPT_LYCIAN: |
745 | 0 | sRet = "xlc"_ostr; |
746 | 0 | break; |
747 | 0 | case USCRIPT_LYDIAN: |
748 | 0 | sRet = "xld"_ostr; |
749 | 0 | break; |
750 | 0 | case USCRIPT_OL_CHIKI: |
751 | 0 | sRet = "sat"_ostr; |
752 | 0 | break; |
753 | 0 | case USCRIPT_REJANG: |
754 | 0 | sRet = "rej"_ostr; |
755 | 0 | break; |
756 | 0 | case USCRIPT_SAURASHTRA: |
757 | 0 | sRet = "saz"_ostr; |
758 | 0 | break; |
759 | 0 | case USCRIPT_SIGN_WRITING: |
760 | 0 | sRet = "en"_ostr; |
761 | 0 | break; |
762 | 0 | case USCRIPT_SUNDANESE: |
763 | 0 | sRet = "su"_ostr; |
764 | 0 | break; |
765 | 0 | case USCRIPT_MOON: |
766 | 0 | sRet = "en"_ostr; |
767 | 0 | break; |
768 | 0 | case USCRIPT_MEITEI_MAYEK: |
769 | 0 | sRet = "mni"_ostr; |
770 | 0 | break; |
771 | 0 | case USCRIPT_IMPERIAL_ARAMAIC: |
772 | 0 | sRet = "arc"_ostr; |
773 | 0 | break; |
774 | 0 | case USCRIPT_AVESTAN: |
775 | 0 | sRet = "ae"_ostr; |
776 | 0 | break; |
777 | 0 | case USCRIPT_CHAKMA: |
778 | 0 | sRet = "ccp"_ostr; |
779 | 0 | break; |
780 | 0 | case USCRIPT_KAITHI: |
781 | 0 | sRet = "awa"_ostr; |
782 | 0 | break; |
783 | 0 | case USCRIPT_MANICHAEAN: |
784 | 0 | sRet = "xmn"_ostr; |
785 | 0 | break; |
786 | 0 | case USCRIPT_INSCRIPTIONAL_PAHLAVI: |
787 | 0 | case USCRIPT_PSALTER_PAHLAVI: |
788 | 0 | case USCRIPT_BOOK_PAHLAVI: |
789 | 0 | case USCRIPT_INSCRIPTIONAL_PARTHIAN: |
790 | 0 | sRet = "xpr"_ostr; |
791 | 0 | break; |
792 | 0 | case USCRIPT_SAMARITAN: |
793 | 0 | sRet = "heb"_ostr; |
794 | 0 | break; |
795 | 0 | case USCRIPT_TAI_VIET: |
796 | 0 | sRet = "blt"_ostr; |
797 | 0 | break; |
798 | 0 | case USCRIPT_MANDAEAN: /* Aliased to USCRIPT_MANDAIC in icu 4.6. */ |
799 | 0 | sRet = "mic"_ostr; |
800 | 0 | break; |
801 | 0 | case USCRIPT_NABATAEAN: |
802 | 0 | sRet = "mis-Nbat"_ostr; // Uncoded with script |
803 | 0 | break; |
804 | 0 | case USCRIPT_PALMYRENE: |
805 | 0 | sRet = "mis-Palm"_ostr; // Uncoded with script |
806 | 0 | break; |
807 | 0 | case USCRIPT_BAMUM: |
808 | 0 | sRet = "bax"_ostr; |
809 | 0 | break; |
810 | 0 | case USCRIPT_LISU: |
811 | 0 | sRet = "lis"_ostr; |
812 | 0 | break; |
813 | 0 | case USCRIPT_NAKHI_GEBA: |
814 | 0 | sRet = "nxq"_ostr; |
815 | 0 | break; |
816 | 0 | case USCRIPT_OLD_SOUTH_ARABIAN: |
817 | 0 | sRet = "xsa"_ostr; |
818 | 0 | break; |
819 | 0 | case USCRIPT_BASSA_VAH: |
820 | 0 | sRet = "bsq"_ostr; |
821 | 0 | break; |
822 | 0 | case USCRIPT_DUPLOYAN_SHORTAND: |
823 | 0 | sRet = "fr"_ostr; |
824 | 0 | break; |
825 | 0 | case USCRIPT_ELBASAN: |
826 | 0 | sRet = "sq"_ostr; |
827 | 0 | break; |
828 | 0 | case USCRIPT_KPELLE: |
829 | 0 | sRet = "kpe"_ostr; |
830 | 0 | break; |
831 | 0 | case USCRIPT_LOMA: |
832 | 0 | sRet = "lom"_ostr; |
833 | 0 | break; |
834 | 0 | case USCRIPT_MENDE: |
835 | 0 | sRet = "men"_ostr; |
836 | 0 | break; |
837 | 0 | case USCRIPT_OLD_NORTH_ARABIAN: |
838 | 0 | sRet = "xna"_ostr; |
839 | 0 | break; |
840 | 0 | case USCRIPT_SINDHI: |
841 | 0 | sRet = "sd"_ostr; |
842 | 0 | break; |
843 | 0 | case USCRIPT_WARANG_CITI: |
844 | 0 | sRet = "hoc"_ostr; |
845 | 0 | break; |
846 | 0 | case USCRIPT_AFAKA: |
847 | 0 | sRet = "djk"_ostr; |
848 | 0 | break; |
849 | 0 | case USCRIPT_JURCHEN: |
850 | 0 | sRet = "juc"_ostr; |
851 | 0 | break; |
852 | 0 | case USCRIPT_MRO: |
853 | 0 | sRet = "cmr"_ostr; |
854 | 0 | break; |
855 | 0 | case USCRIPT_NUSHU: |
856 | 0 | sRet = "mis-Nshu"_ostr; // Uncoded with script |
857 | 0 | break; |
858 | 0 | case USCRIPT_SHARADA: |
859 | 0 | sRet = "sa"_ostr; |
860 | 0 | break; |
861 | 0 | case USCRIPT_SORA_SOMPENG: |
862 | 0 | sRet = "srb"_ostr; |
863 | 0 | break; |
864 | 0 | case USCRIPT_TAKRI: |
865 | 0 | sRet = "doi"_ostr; |
866 | 0 | break; |
867 | 0 | case USCRIPT_TANGUT: |
868 | 0 | sRet = "txg"_ostr; |
869 | 0 | break; |
870 | 0 | case USCRIPT_WOLEAI: |
871 | 0 | sRet = "woe"_ostr; |
872 | 0 | break; |
873 | 0 | case USCRIPT_ANATOLIAN_HIEROGLYPHS: |
874 | 0 | sRet = "hlu"_ostr; |
875 | 0 | break; |
876 | 0 | case USCRIPT_TIRHUTA: |
877 | 0 | sRet = "mai"_ostr; |
878 | 0 | break; |
879 | 0 | case USCRIPT_CAUCASIAN_ALBANIAN: |
880 | 0 | sRet = "xag"_ostr; |
881 | 0 | break; |
882 | 0 | case USCRIPT_MAHAJANI: |
883 | 0 | sRet = "mwr"_ostr; |
884 | 0 | break; |
885 | 0 | case USCRIPT_AHOM: |
886 | 0 | sRet = "aho"_ostr; |
887 | 0 | break; |
888 | 0 | case USCRIPT_HATRAN: |
889 | 0 | sRet = "qly-Hatr"_ostr; |
890 | 0 | break; |
891 | 0 | case USCRIPT_MODI: |
892 | 0 | sRet = "mr-Modi"_ostr; |
893 | 0 | break; |
894 | 0 | case USCRIPT_MULTANI: |
895 | 0 | sRet = "skr-Mutl"_ostr; |
896 | 0 | break; |
897 | 0 | case USCRIPT_PAU_CIN_HAU: |
898 | 0 | sRet = "ctd-Pauc"_ostr; |
899 | 0 | break; |
900 | 0 | case USCRIPT_SIDDHAM: |
901 | 0 | sRet = "sa-Sidd"_ostr; |
902 | 0 | break; |
903 | 0 | case USCRIPT_ADLAM: |
904 | 0 | sRet = "mis-Adlm"_ostr; // Adlam for Fulani, no language code |
905 | 0 | break; |
906 | 0 | case USCRIPT_BHAIKSUKI: |
907 | 0 | sRet = "mis-Bhks"_ostr; // Bhaiksuki for some Buddhist texts, no language code |
908 | 0 | break; |
909 | 0 | case USCRIPT_MARCHEN: |
910 | 0 | sRet = "bo-Marc"_ostr; |
911 | 0 | break; |
912 | 0 | case USCRIPT_NEWA: |
913 | 0 | sRet = "new-Newa"_ostr; |
914 | 0 | break; |
915 | 0 | case USCRIPT_OSAGE: |
916 | 0 | sRet = "osa-Osge"_ostr; |
917 | 0 | break; |
918 | 0 | case USCRIPT_HAN_WITH_BOPOMOFO: |
919 | 0 | sRet = "mis-Hanb"_ostr; // Han with Bopomofo, zh-Hanb ? |
920 | 0 | break; |
921 | 0 | case USCRIPT_SYMBOLS_EMOJI: |
922 | 0 | sRet = "mis-Zsye"_ostr; // Emoji variant |
923 | 0 | break; |
924 | 0 | case USCRIPT_MASARAM_GONDI: |
925 | 0 | sRet = "gon-Gonm"_ostr; // macro language code, could be wsg,esg,gno |
926 | 0 | break; |
927 | 0 | case USCRIPT_SOYOMBO: |
928 | 0 | sRet = "mn-Soyo"_ostr; // abugida to write Mongolian, also Tibetan and Sanskrit |
929 | 0 | break; |
930 | 0 | case USCRIPT_ZANABAZAR_SQUARE: |
931 | 0 | sRet = "mn-Zanb"_ostr; // abugida to write Mongolian |
932 | 0 | break; |
933 | 0 | case USCRIPT_DOGRA: |
934 | 0 | sRet = "dgo"_ostr; // Dogri proper |
935 | 0 | break; |
936 | 0 | case USCRIPT_GUNJALA_GONDI: |
937 | 0 | sRet = "wsg"_ostr; // Adilabad Gondi |
938 | 0 | break; |
939 | 0 | case USCRIPT_MAKASAR: |
940 | 0 | sRet = "mak"_ostr; |
941 | 0 | break; |
942 | 0 | case USCRIPT_MEDEFAIDRIN: |
943 | 0 | sRet = "dmf-Medf"_ostr; |
944 | 0 | break; |
945 | 0 | case USCRIPT_HANIFI_ROHINGYA: |
946 | 0 | sRet = "rhg"_ostr; |
947 | 0 | break; |
948 | 0 | case USCRIPT_SOGDIAN: |
949 | 0 | case USCRIPT_OLD_SOGDIAN: |
950 | 0 | sRet = "sog"_ostr; |
951 | 0 | break; |
952 | 0 | case USCRIPT_ELYMAIC: |
953 | 0 | sRet = "arc-Elym"_ostr; |
954 | 0 | break; |
955 | 0 | case USCRIPT_NYIAKENG_PUACHUE_HMONG: |
956 | 0 | sRet = "hmn-Hmnp"_ostr; // macrolanguage code |
957 | 0 | break; |
958 | 0 | case USCRIPT_NANDINAGARI: |
959 | 0 | sRet = "sa-Nand"_ostr; |
960 | 0 | break; |
961 | 0 | case USCRIPT_WANCHO: |
962 | 0 | sRet = "nnp-Wcho"_ostr; |
963 | 0 | break; |
964 | 0 | case USCRIPT_CHORASMIAN: |
965 | 0 | sRet = "xco-Chrs"_ostr; |
966 | 0 | break; |
967 | 0 | case USCRIPT_DIVES_AKURU: |
968 | 0 | sRet = "dv-Diak"_ostr; |
969 | 0 | break; |
970 | 0 | case USCRIPT_KHITAN_SMALL_SCRIPT: |
971 | 0 | sRet = "zkt-Kits"_ostr; |
972 | 0 | break; |
973 | 0 | case USCRIPT_YEZIDI: |
974 | 0 | sRet = "kmr-Yezi"_ostr; |
975 | 0 | break; |
976 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 70) |
977 | 0 | case USCRIPT_CYPRO_MINOAN: |
978 | 0 | sRet = "mis-Cpmn"_ostr; // Uncoded with script |
979 | 0 | break; |
980 | 0 | case USCRIPT_OLD_UYGHUR: |
981 | 0 | sRet = "oui-Ougr"_ostr; |
982 | 0 | break; |
983 | 0 | case USCRIPT_TANGSA: |
984 | 0 | sRet = "nst-Tnsa"_ostr; |
985 | 0 | break; |
986 | 0 | case USCRIPT_TOTO: |
987 | 0 | sRet = "txo-Toto"_ostr; |
988 | 0 | break; |
989 | 0 | case USCRIPT_VITHKUQI: |
990 | 0 | sRet = "sq-Vith"_ostr; // macrolanguage code |
991 | 0 | break; |
992 | 0 | #endif |
993 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 72) |
994 | 0 | case USCRIPT_KAWI: |
995 | 0 | sRet = "mis-Kawi"_ostr; // Uncoded with script |
996 | 0 | break; |
997 | 0 | case USCRIPT_NAG_MUNDARI: |
998 | 0 | sRet = "unr-Nagm"_ostr; |
999 | 0 | break; |
1000 | 0 | #endif |
1001 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 75) |
1002 | 0 | case USCRIPT_ARABIC_NASTALIQ: |
1003 | 0 | sRet = "fa-Aran"_ostr; |
1004 | 0 | break; |
1005 | 0 | #endif |
1006 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 76) |
1007 | 0 | case USCRIPT_GARAY: |
1008 | 0 | sRet = "wo-Gara"_ostr; |
1009 | 0 | break; |
1010 | 0 | case USCRIPT_GURUNG_KHEMA: |
1011 | 0 | sRet = "gvr-Gukh"_ostr; |
1012 | 0 | break; |
1013 | 0 | case USCRIPT_KIRAT_RAI: |
1014 | 0 | sRet = "bap-Krai"_ostr; |
1015 | 0 | break; |
1016 | 0 | case USCRIPT_OL_ONAL: |
1017 | 0 | sRet = "unr-Onao"_ostr; |
1018 | 0 | break; |
1019 | 0 | case USCRIPT_SUNUWAR: |
1020 | 0 | sRet = "suz-Sunu"_ostr; |
1021 | 0 | break; |
1022 | 0 | case USCRIPT_TODHRI: |
1023 | 0 | sRet = "sq-Todr"_ostr; |
1024 | 0 | break; |
1025 | 0 | case USCRIPT_TULU_TIGALARI: |
1026 | 0 | sRet = "sa-Tutg"_ostr; |
1027 | 0 | break; |
1028 | 0 | #endif |
1029 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 78) |
1030 | 0 | case USCRIPT_BERIA_ERFE: |
1031 | 0 | sRet = "zag-Berf"_ostr; |
1032 | 0 | break; |
1033 | 0 | case USCRIPT_SIDETIC: |
1034 | 0 | sRet = "xsd-Sidt"_ostr; |
1035 | 0 | break; |
1036 | 0 | case USCRIPT_TAI_YO: |
1037 | 0 | sRet = "tyj-Tayo"_ostr; |
1038 | 0 | break; |
1039 | 0 | case USCRIPT_TOLONG_SIKI: |
1040 | 0 | sRet = "kru-Tols"_ostr; |
1041 | 0 | break; |
1042 | 0 | case USCRIPT_TRADITIONAL_HAN_WITH_LATIN: |
1043 | 0 | sRet = "zh-Hntl"_ostr; |
1044 | 0 | break; |
1045 | 0 | #endif |
1046 | 0 | #if (U_ICU_VERSION_MAJOR_NUM >= 79) |
1047 | 0 | case USCRIPT_PROTO_CUNEIFORM: |
1048 | 0 | sRet = "mis-Pcun"_ostr; |
1049 | 0 | break; |
1050 | 0 | case USCRIPT_SEAL: |
1051 | 0 | sRet = "zh-Zslh"_ostr; |
1052 | 0 | break; |
1053 | 0 | #endif |
1054 | 0 | } |
1055 | 0 | return sRet; |
1056 | 0 | } |
1057 | | |
1058 | | //Format a number as a percentage according to the rules of the given |
1059 | | //language, e.g. 100 -> "100%" for en-US vs "100 %" for de-DE |
1060 | | OUString unicode::formatPercent(double dNumber, |
1061 | | const LanguageTag &rLangTag) |
1062 | 0 | { |
1063 | | // get a currency formatter for this locale ID |
1064 | 0 | UErrorCode errorCode=U_ZERO_ERROR; |
1065 | |
|
1066 | 0 | LanguageTag aLangTag(rLangTag); |
1067 | | |
1068 | | // As of CLDR Version 24 these languages were not listed as using spacing |
1069 | | // between number and % but are reported as such by our l10n groups |
1070 | | // http://www.unicode.org/cldr/charts/24/by_type/numbers.number_formatting_patterns.html |
1071 | | // so format using French which has the desired rules |
1072 | 0 | if (aLangTag.getLanguage() == "es" || aLangTag.getLanguage() == "sl") |
1073 | 0 | aLangTag.reset(u"fr-FR"_ustr); |
1074 | |
|
1075 | 0 | icu::Locale aLocale = LanguageTagIcu::getIcuLocale(aLangTag); |
1076 | |
|
1077 | 0 | std::unique_ptr<icu::NumberFormat> xF( |
1078 | 0 | icu::NumberFormat::createPercentInstance(aLocale, errorCode)); |
1079 | 0 | if(U_FAILURE(errorCode)) |
1080 | 0 | { |
1081 | 0 | SAL_WARN("i18n", "icu::NumberFormat::createPercentInstance failed"); |
1082 | 0 | return OUString::number(dNumber) + "%"; |
1083 | 0 | } |
1084 | | |
1085 | 0 | icu::UnicodeString output; |
1086 | 0 | xF->format(dNumber/100, output); |
1087 | 0 | OUString aRet(reinterpret_cast<const sal_Unicode *>(output.getBuffer()), |
1088 | 0 | output.length()); |
1089 | 0 | if (rLangTag.getLanguage() == "de") |
1090 | 0 | { |
1091 | | //narrow no-break space instead of (normal) no-break space |
1092 | 0 | return aRet.replace(0x00A0, 0x202F); |
1093 | 0 | } |
1094 | 0 | return aRet; |
1095 | 0 | } |
1096 | | |
1097 | | bool ToggleUnicodeCodepoint::AllowMoreInput(sal_uInt32 uChar) |
1098 | 0 | { |
1099 | 0 | assert(!mbInputEnded); |
1100 | |
|
1101 | 0 | if (uChar == 0) |
1102 | 0 | return false; |
1103 | | |
1104 | | //arbitrarily chosen maximum length allowed - normal max usage would be around 30. |
1105 | 0 | if( maInput.getLength() > 255 ) |
1106 | 0 | return false; |
1107 | | |
1108 | 0 | bool bPreventNonHex = false; |
1109 | 0 | if( maInput.indexOf("U+") != -1 ) |
1110 | 0 | bPreventNonHex = true; |
1111 | |
|
1112 | 0 | switch ( unicode::getUnicodeType(uChar) ) |
1113 | 0 | { |
1114 | 0 | case css::i18n::UnicodeType::SURROGATE: |
1115 | 0 | if (bPreventNonHex || mbIsHexString) |
1116 | 0 | { |
1117 | 0 | return false; |
1118 | 0 | } |
1119 | | |
1120 | 0 | if( rtl::isLowSurrogate(uChar) && maUtf16.isEmpty() && maInput.isEmpty() ) |
1121 | 0 | { |
1122 | 0 | maUtf16.append(sal_Unicode(uChar)); |
1123 | 0 | return true; |
1124 | 0 | } |
1125 | 0 | if( rtl::isHighSurrogate(uChar) && maInput.isEmpty() ) |
1126 | 0 | maUtf16.insert(0, sal_Unicode(uChar)); |
1127 | 0 | if (maUtf16.getLength() == 2) |
1128 | 0 | { |
1129 | 0 | assert(rtl::isHighSurrogate(maUtf16[0]) && rtl::isLowSurrogate(maUtf16[1])); |
1130 | | // The resulting codepoint may itself be combining, so may allow more |
1131 | 0 | sal_uInt32 nUCS4 = rtl::combineSurrogates(maUtf16[0], maUtf16[1]); |
1132 | 0 | maUtf16.setLength(0); |
1133 | 0 | return AllowMoreInput(nUCS4); |
1134 | 0 | } |
1135 | | // unexpected order of high/low, so don't accept more |
1136 | 0 | if( !maUtf16.isEmpty() ) |
1137 | 0 | maInput.append(maUtf16); |
1138 | 0 | if( !maCombining.isEmpty() ) |
1139 | 0 | maInput.append(maCombining); |
1140 | 0 | return false; |
1141 | | |
1142 | 0 | case css::i18n::UnicodeType::NON_SPACING_MARK: |
1143 | 0 | case css::i18n::UnicodeType::COMBINING_SPACING_MARK: |
1144 | 0 | if (bPreventNonHex || mbIsHexString) |
1145 | 0 | { |
1146 | 0 | return false; |
1147 | 0 | } |
1148 | | |
1149 | | //extreme edge case: already invalid high/low surrogates with preceding combining chars, and now an extra combining mark. |
1150 | 0 | if( !maUtf16.isEmpty() ) |
1151 | 0 | { |
1152 | 0 | maInput = maUtf16; |
1153 | 0 | if( !maCombining.isEmpty() ) |
1154 | 0 | maInput.append(maCombining); |
1155 | 0 | return false; |
1156 | 0 | } |
1157 | 0 | maCombining.insertUtf32(0, uChar); |
1158 | 0 | break; |
1159 | | |
1160 | 0 | default: |
1161 | | //extreme edge case: already invalid high/low surrogates with preceding combining chars, and now an extra character. |
1162 | 0 | if( !maUtf16.isEmpty() ) |
1163 | 0 | { |
1164 | 0 | maInput = maUtf16; |
1165 | 0 | if( !maCombining.isEmpty() ) |
1166 | 0 | maInput.append(maCombining); |
1167 | 0 | return false; |
1168 | 0 | } |
1169 | | |
1170 | 0 | if( !maCombining.isEmpty() ) |
1171 | 0 | { |
1172 | 0 | maCombining.insertUtf32(0, uChar); |
1173 | 0 | maInput = maCombining; |
1174 | 0 | return false; |
1175 | 0 | } |
1176 | | |
1177 | | // 0 - 1f are control characters. Do not process those. |
1178 | 0 | if( uChar < 0x20 ) |
1179 | 0 | { |
1180 | 0 | return false; |
1181 | 0 | } |
1182 | | |
1183 | 0 | switch( uChar ) |
1184 | 0 | { |
1185 | 0 | case 'u': |
1186 | 0 | case 'U': |
1187 | | // U+ notation found. Continue looking for another one. |
1188 | 0 | if( mbRequiresU ) |
1189 | 0 | { |
1190 | 0 | mbRequiresU = false; |
1191 | 0 | maInput.insert(0,"U+"); |
1192 | 0 | } |
1193 | | // treat as a normal character |
1194 | 0 | else |
1195 | 0 | { |
1196 | 0 | if( !bPreventNonHex ) |
1197 | 0 | maInput.insertUtf32(0, uChar); |
1198 | 0 | return false; |
1199 | 0 | } |
1200 | 0 | break; |
1201 | 0 | case '+': |
1202 | | // + already found: skip when not U, or edge case of +U+xxxx |
1203 | 0 | if( mbRequiresU || (maInput.indexOf("U+") == 0) ) |
1204 | 0 | return false; |
1205 | | // hex chars followed by '+' - now require a 'U' |
1206 | 0 | else if ( !maInput.isEmpty() ) |
1207 | 0 | mbRequiresU = true; |
1208 | | // treat as a normal character |
1209 | 0 | else |
1210 | 0 | { |
1211 | 0 | if( !bPreventNonHex ) |
1212 | 0 | maInput.insertUtf32(0, uChar); |
1213 | 0 | return false; |
1214 | 0 | } |
1215 | 0 | break; |
1216 | 0 | default: |
1217 | | // + already found. Since not U, cancel further input |
1218 | 0 | if( mbRequiresU ) |
1219 | 0 | return false; |
1220 | | // maximum digits per notation is 8: only one notation |
1221 | 0 | else if( maInput.indexOf("U+") == -1 && maInput.getLength() == 8 ) |
1222 | 0 | return false; |
1223 | | // maximum digits per notation is 8: previous notation found |
1224 | 0 | else if( maInput.indexOf("U+") == 8 ) |
1225 | 0 | return false; |
1226 | | // a hex character. Add to string. |
1227 | 0 | else if( rtl::isAsciiHexDigit(uChar) ) |
1228 | 0 | { |
1229 | 0 | mbIsHexString = true; |
1230 | 0 | maInput.insertUtf32(0, uChar); |
1231 | 0 | } |
1232 | | // not a hex character: stop input. keep if it is the first input provided |
1233 | 0 | else |
1234 | 0 | { |
1235 | 0 | if( maInput.isEmpty() ) |
1236 | 0 | maInput.insertUtf32(0, uChar); |
1237 | 0 | return false; |
1238 | 0 | } |
1239 | 0 | } |
1240 | 0 | } |
1241 | 0 | return true; |
1242 | 0 | } |
1243 | | |
1244 | | OUString ToggleUnicodeCodepoint::StringToReplace() |
1245 | 0 | { |
1246 | | // this function potentially modifies the input string. No more addition of characters |
1247 | | #ifndef NDEBUG |
1248 | | mbInputEnded = true; |
1249 | | #endif |
1250 | |
|
1251 | 0 | if( maInput.isEmpty() ) |
1252 | 0 | { |
1253 | | //edge case - input finished with incomplete low surrogate or combining characters without a base |
1254 | 0 | if (!maUtf16.isEmpty()) |
1255 | 0 | maInput = maUtf16; |
1256 | 0 | if (!maCombining.isEmpty()) |
1257 | 0 | maInput.append(maCombining); |
1258 | 0 | return maInput.toString(); |
1259 | 0 | } |
1260 | | |
1261 | 0 | if( !mbIsHexString ) |
1262 | 0 | return maInput.toString(); |
1263 | | |
1264 | | //validate unicode notation. |
1265 | 0 | OUString sIn; |
1266 | 0 | sal_uInt32 nUnicode = 0; |
1267 | 0 | sal_Int32 nUPlus = maInput.indexOf("U+"); |
1268 | | //if U+ notation used, strip off all extra chars added not in U+ notation |
1269 | 0 | if( nUPlus != -1 ) |
1270 | 0 | { |
1271 | 0 | maInput.remove(0, nUPlus); |
1272 | 0 | sIn = maInput.copy(2).makeStringAndClear(); |
1273 | 0 | nUPlus = sIn.indexOf("U+"); |
1274 | 0 | } |
1275 | 0 | else |
1276 | 0 | sIn = maInput.toString(); |
1277 | 0 | while( nUPlus != -1 ) |
1278 | 0 | { |
1279 | 0 | nUnicode = o3tl::toUInt32(sIn.subView(0, nUPlus), 16); |
1280 | | //prevent creating control characters or invalid Unicode values |
1281 | 0 | if( !rtl::isUnicodeCodePoint(nUnicode) || nUnicode < 0x20 ) |
1282 | 0 | maInput = sIn.subView(nUPlus); |
1283 | 0 | sIn = sIn.copy(nUPlus+2); |
1284 | 0 | nUPlus = sIn.indexOf("U+"); |
1285 | 0 | } |
1286 | |
|
1287 | 0 | nUnicode = sIn.toUInt32(16); |
1288 | 0 | if( !rtl::isUnicodeCodePoint(nUnicode) || nUnicode < 0x20 ) |
1289 | 0 | maInput.truncate().append( sIn[sIn.getLength()-1] ); |
1290 | 0 | return maInput.toString(); |
1291 | 0 | } |
1292 | | |
1293 | | OUString ToggleUnicodeCodepoint::ReplacementString() |
1294 | 0 | { |
1295 | 0 | OUString sIn = StringToReplace(); |
1296 | 0 | OUStringBuffer output = ""; |
1297 | 0 | sal_Int32 nUPlus = sIn.indexOf("U+"); |
1298 | | // convert from hex notation to glyph |
1299 | 0 | if( nUPlus != -1 || (sIn.getLength() > 1 && mbIsHexString) ) |
1300 | 0 | { |
1301 | 0 | sal_uInt32 nUnicode = 0; |
1302 | 0 | if( nUPlus == 0) |
1303 | 0 | { |
1304 | 0 | sIn = sIn.copy(2); |
1305 | 0 | nUPlus = sIn.indexOf("U+"); |
1306 | 0 | } |
1307 | 0 | while( nUPlus > 0 ) |
1308 | 0 | { |
1309 | 0 | nUnicode = o3tl::toUInt32(sIn.subView(0, nUPlus), 16); |
1310 | 0 | output.appendUtf32( nUnicode ); |
1311 | |
|
1312 | 0 | sIn = sIn.copy(nUPlus+2); |
1313 | 0 | nUPlus = sIn.indexOf("U+"); |
1314 | 0 | } |
1315 | 0 | nUnicode = sIn.toUInt32(16); |
1316 | 0 | output.appendUtf32( nUnicode ); |
1317 | 0 | } |
1318 | | // convert from glyph to hex notation |
1319 | 0 | else |
1320 | 0 | { |
1321 | 0 | sal_Int32 nPos = 0; |
1322 | 0 | while( nPos < sIn.getLength() ) |
1323 | 0 | { |
1324 | 0 | OUStringBuffer aTmp = OUString::number(sIn.iterateCodePoints(&nPos),16); |
1325 | | //pad with zeros - minimum length of 4. |
1326 | 0 | for( sal_Int32 i = 4 - aTmp.getLength(); i > 0; --i ) |
1327 | 0 | aTmp.insert( 0,"0" ); |
1328 | 0 | output.append( "U+" + aTmp ); |
1329 | 0 | } |
1330 | 0 | } |
1331 | 0 | return output.makeStringAndClear(); |
1332 | 0 | } |
1333 | | |
1334 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |