Branch data Line data Source code
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 <i18npool/mslangid.hxx>
21 : : #include <rtl/ustrbuf.hxx>
22 : : #include <sal/macros.h>
23 : : #include <nativenumbersupplier.hxx>
24 : : #include <localedata.hxx>
25 : : #include <data/numberchar.h>
26 : : #include <comphelper/string.hxx>
27 : :
28 : : using namespace ::com::sun::star::uno;
29 : : using namespace ::com::sun::star::lang;
30 : : using namespace ::com::sun::star::lang;
31 : : using namespace ::rtl;
32 : :
33 : :
34 : : typedef struct {
35 : : sal_Int16 number;
36 : : sal_Unicode *multiplierChar;
37 : : sal_Int16 numberFlag;
38 : : sal_Int16 exponentCount;
39 : : sal_Int16 *multiplierExponent;
40 : : } Number;
41 : :
42 : :
43 : : #define NUMBER_OMIT_ZERO (1 << 0)
44 : : #define NUMBER_OMIT_ONLY_ZERO (1 << 1)
45 : : #define NUMBER_OMIT_ONE_1 (1 << 2)
46 : : #define NUMBER_OMIT_ONE_2 (1 << 3)
47 : : #define NUMBER_OMIT_ONE_3 (1 << 4)
48 : : #define NUMBER_OMIT_ONE_4 (1 << 5)
49 : : #define NUMBER_OMIT_ONE_5 (1 << 6)
50 : : #define NUMBER_OMIT_ONE_6 (1 << 7)
51 : : #define NUMBER_OMIT_ONE_7 (1 << 8)
52 : : #define NUMBER_OMIT_ONE (NUMBER_OMIT_ONE_1|NUMBER_OMIT_ONE_2|NUMBER_OMIT_ONE_3|NUMBER_OMIT_ONE_4|NUMBER_OMIT_ONE_5|NUMBER_OMIT_ONE_6|NUMBER_OMIT_ONE_7)
53 : : #define NUMBER_OMIT_ONE_CHECK(bit) (1 << (2 + bit))
54 : : #define NUMBER_OMIT_ALL ( NUMBER_OMIT_ZERO|NUMBER_OMIT_ONE|NUMBER_OMIT_ONLY_ZERO )
55 : : #define NUMBER_OMIT_ZERO_ONE ( NUMBER_OMIT_ZERO|NUMBER_OMIT_ONE )
56 : : #define NUMBER_OMIT_ONE_67 (NUMBER_OMIT_ONE_6|NUMBER_OMIT_ONE_7)
57 : : #define NUMBER_OMIT_ZERO_ONE_67 ( NUMBER_OMIT_ZERO|NUMBER_OMIT_ONE_67 )
58 : :
59 : :
60 : : #define MAX_SAL_UINT32 0xFFFFFFFF
61 : : #define MAX_VALUE (MAX_SAL_UINT32 - 9) / 10
62 : :
63 : : namespace com { namespace sun { namespace star { namespace i18n {
64 : :
65 : : OUString SAL_CALL getHebrewNativeNumberString(const OUString& aNumberString, sal_Bool useGeresh);
66 : :
67 : 0 : OUString SAL_CALL AsciiToNativeChar( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
68 : : Sequence< sal_Int32 >& offset, sal_Bool useOffset, sal_Int16 number ) throw(RuntimeException)
69 : : {
70 : 0 : const sal_Unicode *src = inStr.getStr() + startPos;
71 : 0 : rtl_uString *newStr = comphelper::string::rtl_uString_alloc(nCount);
72 [ # # ]: 0 : if (useOffset)
73 : 0 : offset.realloc(nCount);
74 : :
75 [ # # ]: 0 : for (sal_Int32 i = 0; i < nCount; i++)
76 : : {
77 : 0 : sal_Unicode ch = src[i];
78 [ # # ][ # # ]: 0 : if (isNumber(ch))
79 : 0 : newStr->buffer[i] = NumberChar[number][ ch - NUMBER_ZERO ];
80 [ # # ][ # # ]: 0 : else if (i+1 < nCount && isNumber(src[i+1])) {
[ # # ]
81 [ # # ][ # # ]: 0 : if (i > 0 && isNumber(src[i-1]) && isSeparator(ch))
[ # # ][ # # ]
82 [ # # ]: 0 : newStr->buffer[i] = SeparatorChar[number] ? SeparatorChar[number] : ch;
83 : : else
84 : 0 : newStr->buffer[i] = isDecimal(ch) ? (DecimalChar[number] ? DecimalChar[number] : ch) :
85 [ # # ][ # # ]: 0 : isMinus(ch) ? (MinusChar[number] ? MinusChar[number] : ch) : ch;
[ # # ][ # # ]
86 : : }
87 : : else
88 : 0 : newStr->buffer[i] = ch;
89 [ # # ]: 0 : if (useOffset)
90 : 0 : offset[i] = startPos + i;
91 : : }
92 : 0 : return OUString(newStr, SAL_NO_ACQUIRE); // take ownership
93 : : }
94 : :
95 : 0 : sal_Bool SAL_CALL AsciiToNative_numberMaker(const sal_Unicode *str, sal_Int32 begin, sal_Int32 len,
96 : : sal_Unicode *dst, sal_Int32& count, sal_Int16 multiChar_index, Sequence< sal_Int32 >& offset, sal_Bool useOffset, sal_Int32 startPos,
97 : : Number *number, sal_Unicode* numberChar)
98 : : {
99 [ # # ]: 0 : sal_Unicode multiChar = (multiChar_index == -1 ? 0 : number->multiplierChar[multiChar_index]);
100 [ # # ]: 0 : if ( len <= number->multiplierExponent[number->exponentCount-1] ) {
101 [ # # ]: 0 : if (number->multiplierExponent[number->exponentCount-1] > 1) {
102 : : sal_Int16 i;
103 : 0 : sal_Bool notZero = false;
104 [ # # ]: 0 : for (i = 0; i < len; i++, begin++) {
105 [ # # ][ # # ]: 0 : if (notZero || str[begin] != NUMBER_ZERO) {
106 : 0 : dst[count] = numberChar[str[begin] - NUMBER_ZERO];
107 [ # # ]: 0 : if (useOffset)
108 : 0 : offset[count] = begin + startPos;
109 : 0 : count++;
110 : 0 : notZero = sal_True;
111 : : }
112 : : }
113 [ # # ][ # # ]: 0 : if (notZero && multiChar > 0) {
114 : 0 : dst[count] = multiChar;
115 [ # # ]: 0 : if (useOffset)
116 : 0 : offset[count] = begin + startPos;
117 : 0 : count++;
118 : : }
119 : 0 : return notZero;
120 [ # # ]: 0 : } else if (str[begin] != NUMBER_ZERO) {
121 [ # # ][ # # ]: 0 : if (!(number->numberFlag & (multiChar_index < 0 ? 0 : NUMBER_OMIT_ONE_CHECK(multiChar_index))) || str[begin] != NUMBER_ONE) {
[ # # ]
122 : 0 : dst[count] = numberChar[str[begin] - NUMBER_ZERO];
123 [ # # ]: 0 : if (useOffset)
124 : 0 : offset[count] = begin + startPos;
125 : 0 : count++;
126 : : }
127 [ # # ]: 0 : if (multiChar > 0) {
128 : 0 : dst[count] = multiChar;
129 [ # # ]: 0 : if (useOffset)
130 : 0 : offset[count] = begin + startPos;
131 : 0 : count++;
132 : : }
133 [ # # ][ # # ]: 0 : } else if (!(number->numberFlag & NUMBER_OMIT_ZERO) && count > 0 && dst[count-1] != numberChar[0]) {
[ # # ]
134 : 0 : dst[count] = numberChar[0];
135 [ # # ]: 0 : if (useOffset)
136 : 0 : offset[count] = begin + startPos;
137 : 0 : count++;
138 : : }
139 : 0 : return str[begin] != NUMBER_ZERO;
140 : : } else {
141 : 0 : sal_Bool printPower = sal_False;
142 : : // sal_Int16 last = 0;
143 [ # # ]: 0 : for (sal_Int16 i = 1; i <= number->exponentCount; i++) {
144 [ # # ]: 0 : sal_Int32 tmp = len - (i == number->exponentCount ? 0 : number->multiplierExponent[i]);
145 [ # # ]: 0 : if (tmp > 0) {
146 : : printPower |= AsciiToNative_numberMaker(str, begin, tmp, dst, count,
147 [ # # ]: 0 : (i == number->exponentCount ? -1 : i), offset, useOffset, startPos, number, numberChar);
148 : 0 : begin += tmp;
149 : 0 : len -= tmp;
150 : : }
151 : : }
152 [ # # ]: 0 : if (printPower) {
153 [ # # ][ # # ]: 0 : if (count > 0 && number->multiplierExponent[number->exponentCount-1] == 1 &&
[ # # ]
154 : 0 : dst[count-1] == numberChar[0])
155 : 0 : count--;
156 [ # # ]: 0 : if (multiChar > 0) {
157 : 0 : dst[count] = multiChar;
158 [ # # ]: 0 : if (useOffset)
159 : 0 : offset[count] = begin + startPos;
160 : 0 : count++;
161 : : }
162 : : }
163 : 0 : return printPower;
164 : : }
165 : : }
166 : :
167 : 0 : OUString SAL_CALL AsciiToNative( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
168 : : Sequence< sal_Int32 >& offset, sal_Bool useOffset, Number* number ) throw(RuntimeException)
169 : : {
170 : 0 : rtl::OUString aRet;
171 : :
172 : 0 : sal_Int32 strLen = inStr.getLength() - startPos;
173 : 0 : sal_Unicode *numberChar = NumberChar[number->number];
174 : :
175 [ # # ]: 0 : if (nCount > strLen)
176 : 0 : nCount = strLen;
177 : :
178 [ # # ]: 0 : if (nCount > 0)
179 : : {
180 : 0 : const sal_Unicode *str = inStr.getStr() + startPos;
181 [ # # ]: 0 : sal_Unicode *newStr = new sal_Unicode[nCount * 2 + 1];
182 [ # # ]: 0 : sal_Unicode *srcStr = new sal_Unicode[nCount + 1]; // for keeping number without comma
183 : 0 : sal_Int32 i, len = 0, count = 0;
184 : :
185 [ # # ]: 0 : if (useOffset)
186 [ # # ]: 0 : offset.realloc( nCount * 2 );
187 : 0 : sal_Bool doDecimal = sal_False;
188 : :
189 [ # # ]: 0 : for (i = 0; i <= nCount; i++)
190 : : {
191 [ # # ][ # # ]: 0 : if (i < nCount && isNumber(str[i])) {
[ # # ]
192 [ # # ]: 0 : if (doDecimal) {
193 : 0 : newStr[count] = numberChar[str[i] - NUMBER_ZERO];
194 [ # # ]: 0 : if (useOffset)
195 [ # # ]: 0 : offset[count] = i + startPos;
196 : 0 : count++;
197 : : }
198 : : else
199 : 0 : srcStr[len++] = str[i];
200 : : } else {
201 [ # # ]: 0 : if (len > 0) {
202 [ # # ][ # # ]: 0 : if (isSeparator(str[i]) && i < nCount-1 && isNumber(str[i+1]))
[ # # ][ # # ]
203 : 0 : continue; // skip comma inside number string
204 : 0 : sal_Bool notZero = sal_False;
205 [ # # ]: 0 : for (sal_Int32 begin = 0, end = len % number->multiplierExponent[0];
206 : 0 : end <= len; begin = end, end += number->multiplierExponent[0]) {
207 [ # # ]: 0 : if (end == 0) continue;
208 : 0 : sal_Int32 _count = count;
209 : : notZero |= AsciiToNative_numberMaker(srcStr, begin, end - begin, newStr, count,
210 [ # # ][ # # ]: 0 : end == len ? -1 : 0, offset, useOffset, i - len + startPos, number, numberChar);
211 [ # # ][ # # ]: 0 : if (count > 0 && number->multiplierExponent[number->exponentCount-1] == 1 &&
[ # # ]
212 : 0 : newStr[count-1] == numberChar[0])
213 : 0 : count--;
214 [ # # ][ # # ]: 0 : if (notZero && _count == count) {
215 [ # # ]: 0 : if (end != len) {
216 : 0 : newStr[count] = number->multiplierChar[0];
217 [ # # ]: 0 : if (useOffset)
218 [ # # ]: 0 : offset[count] = i - len + startPos;
219 : 0 : count++;
220 : : }
221 : : }
222 : : }
223 [ # # ][ # # ]: 0 : if (! notZero && ! (number->numberFlag & NUMBER_OMIT_ONLY_ZERO)) {
224 : 0 : newStr[count] = numberChar[0];
225 [ # # ]: 0 : if (useOffset)
226 [ # # ]: 0 : offset[count] = i - len + startPos;
227 : 0 : count++;
228 : : }
229 : 0 : len = 0;
230 : : }
231 [ # # ]: 0 : if (i < nCount) {
232 [ # # ][ # # ]: 0 : if ((doDecimal = (!doDecimal && isDecimal(str[i]) && i < nCount-1 && isNumber(str[i+1]))) != sal_False)
[ # # ][ # # ]
[ # # ][ # # ]
233 [ # # ]: 0 : newStr[count] = (DecimalChar[number->number] ? DecimalChar[number->number] : str[i]);
234 [ # # ][ # # ]: 0 : else if (isMinus(str[i]) && i < nCount-1 && isNumber(str[i+1]))
[ # # ][ # # ]
235 [ # # ]: 0 : newStr[count] = (MinusChar[number->number] ? MinusChar[number->number] : str[i]);
236 [ # # ][ # # ]: 0 : else if (isSeparator(str[i]) && i < nCount-1 && isNumber(str[i+1]))
[ # # ][ # # ]
237 [ # # ]: 0 : newStr[count] = (SeparatorChar[number->number] ? SeparatorChar[number->number] : str[i]);
238 : : else
239 : 0 : newStr[count] = str[i];
240 [ # # ]: 0 : if (useOffset)
241 [ # # ]: 0 : offset[count] = i + startPos;
242 : 0 : count++;
243 : : }
244 : : }
245 : : }
246 : :
247 [ # # ]: 0 : delete[] srcStr;
248 : :
249 [ # # ]: 0 : if (useOffset)
250 [ # # ]: 0 : offset.realloc(count);
251 : 0 : aRet = OUString(newStr, count);
252 [ # # ]: 0 : delete[] newStr;
253 : : }
254 : 0 : return aRet;
255 : : }
256 : 0 : static void SAL_CALL NativeToAscii_numberMaker(sal_Int16 max, sal_Int16 prev, const sal_Unicode *str,
257 : : sal_Int32& i, sal_Int32 nCount, sal_Unicode *dst, sal_Int32& count, Sequence< sal_Int32 >& offset, sal_Bool useOffset,
258 : : OUString& numberChar, OUString& multiplierChar)
259 : : {
260 : 0 : sal_Int16 curr = 0, num = 0, end = 0, shift = 0;
261 [ # # ]: 0 : while (++i < nCount) {
262 [ # # ]: 0 : if ((curr = sal::static_int_cast<sal_Int16>( numberChar.indexOf(str[i]) )) >= 0) {
263 [ # # ]: 0 : if (num > 0)
264 : 0 : break;
265 : 0 : num = curr % 10;
266 [ # # ]: 0 : } else if ((curr = sal::static_int_cast<sal_Int16>( multiplierChar.indexOf(str[i]) )) >= 0) {
267 : 0 : curr = MultiplierExponent_7_CJK[curr % ExponentCount_7_CJK];
268 [ # # ][ # # ]: 0 : if (prev > curr && num == 0) num = 1; // One may be omitted in informal format
269 : 0 : shift = end = 0;
270 [ # # ]: 0 : if (curr >= max)
271 : 0 : max = curr;
272 [ # # ]: 0 : else if (curr > prev)
273 : 0 : shift = max - curr;
274 : : else
275 : 0 : end = curr;
276 [ # # ]: 0 : while (end++ < prev) {
277 [ # # ]: 0 : dst[count] = NUMBER_ZERO + (end == prev ? num : 0);
278 [ # # ]: 0 : if (useOffset)
279 : 0 : offset[count] = i;
280 : 0 : count++;
281 : : }
282 [ # # ]: 0 : if (shift) {
283 : 0 : count -= max;
284 [ # # ]: 0 : for (sal_Int16 j = 0; j < shift; j++, count++) {
285 : 0 : dst[count] = dst[count + curr];
286 [ # # ]: 0 : if (useOffset)
287 : 0 : offset[count] = offset[count + curr];
288 : : }
289 : 0 : max = curr;
290 : : }
291 : : NativeToAscii_numberMaker(max, curr, str, i, nCount, dst,
292 : 0 : count, offset, useOffset, numberChar, multiplierChar);
293 : 0 : return;
294 : : } else
295 : 0 : break;
296 : : }
297 [ # # ]: 0 : while (end++ < prev) {
298 [ # # ]: 0 : dst[count] = NUMBER_ZERO + (end == prev ? num : 0);
299 [ # # ]: 0 : if (useOffset)
300 : 0 : offset[count] = i - 1;
301 : 0 : count++;
302 : : }
303 : : }
304 : :
305 : 0 : static OUString SAL_CALL NativeToAscii(const OUString& inStr,
306 : : sal_Int32 startPos, sal_Int32 nCount, Sequence< sal_Int32 >& offset, sal_Bool useOffset ) throw(RuntimeException)
307 : : {
308 : 0 : OUString aRet;
309 : :
310 : 0 : sal_Int32 strLen = inStr.getLength() - startPos;
311 : :
312 [ # # ]: 0 : if (nCount > strLen)
313 : 0 : nCount = strLen;
314 : :
315 [ # # ]: 0 : if (nCount > 0) {
316 : 0 : const sal_Unicode *str = inStr.getStr() + startPos;
317 [ # # ]: 0 : sal_Unicode *newStr = new sal_Unicode[nCount * MultiplierExponent_7_CJK[0] + 2];
318 [ # # ]: 0 : if (useOffset)
319 [ # # ]: 0 : offset.realloc( nCount * MultiplierExponent_7_CJK[0] + 1 );
320 : 0 : sal_Int32 count = 0, index;
321 : : sal_Int32 i;
322 : :
323 : 0 : OUString numberChar, multiplierChar, decimalChar, minusChar, separatorChar;
324 : 0 : numberChar = OUString((sal_Unicode*)NumberChar, 10*NumberChar_Count);
325 : 0 : multiplierChar = OUString((sal_Unicode*) MultiplierChar_7_CJK, ExponentCount_7_CJK*Multiplier_Count);
326 : 0 : decimalChar = OUString(DecimalChar, NumberChar_Count);
327 : 0 : minusChar = OUString(MinusChar, NumberChar_Count);
328 : 0 : separatorChar = OUString(SeparatorChar, NumberChar_Count);
329 : :
330 [ # # ]: 0 : for ( i = 0; i < nCount; i++) {
331 [ # # ]: 0 : if ((index = multiplierChar.indexOf(str[i])) >= 0) {
332 [ # # ][ # # ]: 0 : if (count == 0 || !isNumber(newStr[count-1])) { // add 1 in front of multiplier
[ # # ]
333 : 0 : newStr[count] = NUMBER_ONE;
334 [ # # ]: 0 : if (useOffset)
335 [ # # ]: 0 : offset[count] = i;
336 : 0 : count++;
337 : : }
338 : 0 : index = MultiplierExponent_7_CJK[index % ExponentCount_7_CJK];
339 : : NativeToAscii_numberMaker(
340 : 0 : sal::static_int_cast<sal_Int16>( index ), sal::static_int_cast<sal_Int16>( index ),
341 : : str, i, nCount, newStr, count, offset, useOffset,
342 [ # # ]: 0 : numberChar, multiplierChar);
343 : : } else {
344 [ # # ]: 0 : if ((index = numberChar.indexOf(str[i])) >= 0)
345 : 0 : newStr[count] = sal::static_int_cast<sal_Unicode>( (index % 10) + NUMBER_ZERO );
346 [ # # ][ # # : 0 : else if ((index = separatorChar.indexOf(str[i])) >= 0 &&
# # # # ]
[ # # ]
347 : 0 : (i < nCount-1 && (numberChar.indexOf(str[i+1]) >= 0 ||
348 : 0 : multiplierChar.indexOf(str[i+1]) >= 0)))
349 : 0 : newStr[count] = SeparatorChar[NumberChar_HalfWidth];
350 [ # # ][ # # : 0 : else if ((index = decimalChar.indexOf(str[i])) >= 0 &&
# # # # ]
[ # # ]
351 : 0 : (i < nCount-1 && (numberChar.indexOf(str[i+1]) >= 0 ||
352 : 0 : multiplierChar.indexOf(str[i+1]) >= 0)))
353 : : // Only when decimal point is followed by numbers,
354 : : // it will be convert to ASCII decimal point
355 : 0 : newStr[count] = DecimalChar[NumberChar_HalfWidth];
356 [ # # ][ # # : 0 : else if ((index = minusChar.indexOf(str[i])) >= 0 &&
# # # # ]
[ # # ]
357 : 0 : (i < nCount-1 && (numberChar.indexOf(str[i+1]) >= 0 ||
358 : 0 : multiplierChar.indexOf(str[i+1]) >= 0)))
359 : : // Only when minus is followed by numbers,
360 : : // it will be convert to ASCII minus sign
361 : 0 : newStr[count] = MinusChar[NumberChar_HalfWidth];
362 : : else
363 : 0 : newStr[count] = str[i];
364 [ # # ]: 0 : if (useOffset)
365 [ # # ]: 0 : offset[count] = i;
366 : 0 : count++;
367 : : }
368 : : }
369 : :
370 [ # # ]: 0 : if (useOffset) {
371 [ # # ]: 0 : offset.realloc(count);
372 [ # # ]: 0 : for (i = 0; i < count; i++)
373 [ # # ]: 0 : offset[i] += startPos;
374 : : }
375 : 0 : aRet = OUString(newStr, count);
376 [ # # ]: 0 : delete[] newStr;
377 : : }
378 : 0 : return aRet;
379 : : }
380 : :
381 : : static Number natnum4[4] = {
382 : : { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh], 0,
383 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
384 : : { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], 0,
385 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
386 : : { NumberChar_Modern_ja, MultiplierChar_7_CJK[Multiplier_Modern_ja], NUMBER_OMIT_ZERO_ONE_67,
387 : : ExponentCount_7_CJK, MultiplierExponent_7_CJK },
388 : : { NumberChar_Lower_ko, MultiplierChar_6_CJK[Multiplier_Lower_ko], NUMBER_OMIT_ZERO,
389 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
390 : : };
391 : :
392 : : static Number natnum5[4] = {
393 : : { NumberChar_Upper_zh, MultiplierChar_6_CJK[Multiplier_Upper_zh], 0,
394 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
395 : : { NumberChar_Upper_zh_TW, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], 0,
396 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
397 : : { NumberChar_Traditional_ja, MultiplierChar_7_CJK[Multiplier_Traditional_ja], NUMBER_OMIT_ZERO_ONE_67,
398 : : ExponentCount_7_CJK, MultiplierExponent_7_CJK },
399 : : { NumberChar_Upper_ko, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], NUMBER_OMIT_ZERO,
400 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
401 : : };
402 : :
403 : : static Number natnum6[4] = {
404 : : { NumberChar_FullWidth, MultiplierChar_6_CJK[Multiplier_Lower_zh], 0,
405 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
406 : : { NumberChar_FullWidth, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], 0,
407 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
408 : : { NumberChar_FullWidth, MultiplierChar_7_CJK[Multiplier_Modern_ja], NUMBER_OMIT_ZERO_ONE_67,
409 : : ExponentCount_7_CJK, MultiplierExponent_7_CJK },
410 : : { NumberChar_FullWidth, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ZERO,
411 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
412 : : };
413 : :
414 : : static Number natnum7[4] = {
415 : : { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh], NUMBER_OMIT_ALL,
416 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
417 : : { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], NUMBER_OMIT_ALL,
418 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
419 : : { NumberChar_Modern_ja, MultiplierChar_2_CJK[Multiplier_Modern_ja], NUMBER_OMIT_ZERO_ONE,
420 : : ExponentCount_2_CJK, MultiplierExponent_2_CJK },
421 : : { NumberChar_Lower_ko, MultiplierChar_6_CJK[Multiplier_Lower_ko], NUMBER_OMIT_ALL,
422 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
423 : : };
424 : :
425 : : static Number natnum8[4] = {
426 : : { NumberChar_Upper_zh, MultiplierChar_6_CJK[Multiplier_Upper_zh], NUMBER_OMIT_ALL,
427 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
428 : : { NumberChar_Upper_zh_TW, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], NUMBER_OMIT_ALL,
429 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
430 : : { NumberChar_Traditional_ja, MultiplierChar_2_CJK[Multiplier_Traditional_ja], NUMBER_OMIT_ZERO_ONE,
431 : : ExponentCount_2_CJK, MultiplierExponent_2_CJK },
432 : : { NumberChar_Upper_ko, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], NUMBER_OMIT_ALL,
433 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK },
434 : : };
435 : :
436 : : static Number natnum10 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ZERO,
437 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK };
438 : : static Number natnum11 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ALL,
439 : : ExponentCount_6_CJK, MultiplierExponent_6_CJK };
440 : :
441 : : //! ATTENTION: Do not change order of elements!
442 : : //! Append new languages to the end of the list!
443 : : static const sal_Char *natnum1Locales[] = {
444 : : "zh_CN",
445 : : "zh_TW",
446 : : "ja",
447 : : "ko",
448 : : "he",
449 : : "ar",
450 : : "th",
451 : : "hi",
452 : : "or",
453 : : "mr",
454 : : "bn",
455 : : "pa",
456 : : "gu",
457 : : "ta",
458 : : "te",
459 : : "kn",
460 : : "ml",
461 : : "lo",
462 : : "bo",
463 : : "my",
464 : : "km",
465 : : "mn",
466 : : "ne",
467 : : "dz",
468 : : "fa"
469 : : };
470 : : static sal_Int16 nbOfLocale = SAL_N_ELEMENTS(natnum1Locales);
471 : :
472 : : //! ATTENTION: Do not change order of elements!
473 : : //! Number and order must match elements of natnum1Locales!
474 : : static sal_Int16 natnum1[] = {
475 : : NumberChar_Lower_zh,
476 : : NumberChar_Lower_zh,
477 : : NumberChar_Modern_ja,
478 : : NumberChar_Lower_ko,
479 : : NumberChar_he,
480 : : NumberChar_Indic_ar,
481 : : NumberChar_th,
482 : : NumberChar_hi,
483 : : NumberChar_or,
484 : : NumberChar_mr,
485 : : NumberChar_bn,
486 : : NumberChar_pa,
487 : : NumberChar_gu,
488 : : NumberChar_ta,
489 : : NumberChar_te,
490 : : NumberChar_kn,
491 : : NumberChar_ml,
492 : : NumberChar_lo,
493 : : NumberChar_bo,
494 : : NumberChar_my,
495 : : NumberChar_km,
496 : : NumberChar_mn,
497 : : NumberChar_ne,
498 : : NumberChar_dz,
499 : : NumberChar_EastIndic_ar
500 : : };
501 : : static sal_Int16 sizeof_natnum1 = SAL_N_ELEMENTS(natnum1);
502 : :
503 : : //! ATTENTION: Do not change order of elements!
504 : : //! Order must match first elements of natnum1Locales!
505 : : static sal_Int16 natnum2[] = {
506 : : NumberChar_Upper_zh,
507 : : NumberChar_Upper_zh_TW,
508 : : NumberChar_Traditional_ja,
509 : : NumberChar_Upper_ko,
510 : : NumberChar_he
511 : : };
512 : : static sal_Int16 sizeof_natnum2 = SAL_N_ELEMENTS(natnum2);
513 : :
514 : : #define isLang(lang) rLocale.Language.equalsAsciiL(lang, 2)
515 : :
516 : 0 : static sal_Int16 SAL_CALL getLanguageNumber( const Locale& rLocale)
517 : : {
518 : : // return zh_TW for TW, HK and MO, return zh_CN for other zh locales.
519 [ # # ][ # # ]: 0 : if (isLang("zh")) return MsLangId::isTraditionalChinese(rLocale) ? 1 : 0;
520 : :
521 [ # # ]: 0 : for (sal_Int16 i = 2; i < nbOfLocale; i++)
522 [ # # ]: 0 : if (isLang(natnum1Locales[i]))
523 : 0 : return i;
524 : :
525 : 0 : return -1;
526 : : }
527 : :
528 : 0 : OUString SAL_CALL NativeNumberSupplier::getNativeNumberString(const OUString& aNumberString, const Locale& rLocale,
529 : : sal_Int16 nNativeNumberMode, Sequence< sal_Int32 >& offset) throw (RuntimeException)
530 : : {
531 : 0 : Number *number = 0;
532 : 0 : sal_Int16 num = -1;
533 : :
534 [ # # ]: 0 : if (isValidNatNum(rLocale, nNativeNumberMode)) {
535 : 0 : sal_Int16 langnum = getLanguageNumber(rLocale);
536 [ # # # # : 0 : switch (nNativeNumberMode) {
# # # # #
# # # # ]
537 : : case NativeNumberMode::NATNUM0: // Ascii
538 : 0 : return NativeToAscii(aNumberString, 0, aNumberString.getLength(), offset, useOffset);
539 : : case NativeNumberMode::NATNUM1: // Char, Lower
540 : 0 : num = natnum1[langnum];
541 : 0 : break;
542 : : case NativeNumberMode::NATNUM2: // Char, Upper
543 : 0 : num = natnum2[langnum];
544 : 0 : break;
545 : : case NativeNumberMode::NATNUM3: // Char, FullWidth
546 : 0 : num = NumberChar_FullWidth;
547 : 0 : break;
548 : : case NativeNumberMode::NATNUM4: // Text, Lower, Long
549 : 0 : number = &natnum4[langnum];
550 : 0 : break;
551 : : case NativeNumberMode::NATNUM5: // Text, Upper, Long
552 : 0 : number = &natnum5[langnum];
553 : 0 : break;
554 : : case NativeNumberMode::NATNUM6: // Text, FullWidth
555 : 0 : number = &natnum6[langnum];
556 : 0 : break;
557 : : case NativeNumberMode::NATNUM7: // Text. Lower, Short
558 : 0 : number = &natnum7[langnum];
559 : 0 : break;
560 : : case NativeNumberMode::NATNUM8: // Text, Upper, Short
561 : 0 : number = &natnum8[langnum];
562 : 0 : break;
563 : : case NativeNumberMode::NATNUM9: // Char, Hangul
564 : 0 : num = NumberChar_Hangul_ko;
565 : 0 : break;
566 : : case NativeNumberMode::NATNUM10: // Text, Hangul, Long
567 : 0 : number = &natnum10;
568 : 0 : break;
569 : : case NativeNumberMode::NATNUM11: // Text, Hangul, Short
570 : 0 : number = &natnum11;
571 : 0 : break;
572 : : default:
573 : 0 : break;
574 : : }
575 : : }
576 : :
577 [ # # ][ # # ]: 0 : if (number || num >= 0) {
578 [ # # # # : 0 : if (!aLocale.Language.equals(rLocale.Language) ||
# # ][ # # ]
579 : 0 : !aLocale.Country.equals(rLocale.Country) ||
580 : 0 : !aLocale.Variant.equals(rLocale.Variant)) {
581 [ # # ][ # # ]: 0 : LocaleDataItem item = LocaleData().getLocaleItem( rLocale );
[ # # ]
582 : 0 : aLocale = rLocale;
583 : 0 : DecimalChar[NumberChar_HalfWidth]=item.decimalSeparator.toChar();
584 [ # # ][ # # ]: 0 : if (DecimalChar[NumberChar_HalfWidth] > 0x7E || DecimalChar[NumberChar_HalfWidth] < 0x21)
585 : 0 : DecimalChar[NumberChar_FullWidth]=0xFF0E;
586 : : else
587 : 0 : DecimalChar[NumberChar_FullWidth]=DecimalChar[NumberChar_HalfWidth]+0xFEE0;
588 : 0 : SeparatorChar[NumberChar_HalfWidth]=item.thousandSeparator.toChar();
589 [ # # ][ # # ]: 0 : if (SeparatorChar[NumberChar_HalfWidth] > 0x7E || SeparatorChar[NumberChar_HalfWidth] < 0x21)
590 : 0 : SeparatorChar[NumberChar_FullWidth]=0xFF0C;
591 : : else
592 : 0 : SeparatorChar[NumberChar_FullWidth]=SeparatorChar[NumberChar_HalfWidth]+0xFEE0;
593 : : }
594 [ # # ]: 0 : if (number)
595 : 0 : return AsciiToNative( aNumberString, 0, aNumberString.getLength(), offset, useOffset, number );
596 [ # # ]: 0 : else if (num == NumberChar_he)
597 : : return getHebrewNativeNumberString(aNumberString,
598 : 0 : nNativeNumberMode == NativeNumberMode::NATNUM2);
599 : : else
600 : 0 : return AsciiToNativeChar(aNumberString, 0, aNumberString.getLength(), offset, useOffset, num);
601 : : }
602 : : else
603 : 0 : return aNumberString;
604 : : }
605 : :
606 : 0 : OUString SAL_CALL NativeNumberSupplier::getNativeNumberString(const OUString& aNumberString, const Locale& rLocale,
607 : : sal_Int16 nNativeNumberMode) throw (RuntimeException)
608 : : {
609 [ # # ]: 0 : Sequence< sal_Int32 > offset;
610 [ # # ][ # # ]: 0 : return getNativeNumberString(aNumberString, rLocale, nNativeNumberMode, offset);
611 : : }
612 : :
613 : 0 : sal_Unicode SAL_CALL NativeNumberSupplier::getNativeNumberChar( const sal_Unicode inChar, const Locale& rLocale, sal_Int16 nNativeNumberMode ) throw(com::sun::star::uno::RuntimeException)
614 : : {
615 [ # # ]: 0 : if (nNativeNumberMode == NativeNumberMode::NATNUM0) { // Ascii
616 [ # # ]: 0 : for (sal_Int16 i = 0; i < NumberChar_Count; i++)
617 [ # # ]: 0 : for (sal_Int16 j = 0; j < 10; j++)
618 [ # # ]: 0 : if (inChar == NumberChar[i][j])
619 : 0 : return j;
620 : 0 : return inChar;
621 : : }
622 [ # # ][ # # ]: 0 : else if (isNumber(inChar) && isValidNatNum(rLocale, nNativeNumberMode)) {
[ # # ][ # # ]
623 : 0 : sal_Int16 langnum = getLanguageNumber(rLocale);
624 [ # # # # : 0 : switch (nNativeNumberMode) {
# ]
625 : : case NativeNumberMode::NATNUM1: // Char, Lower
626 : : case NativeNumberMode::NATNUM4: // Text, Lower, Long
627 : : case NativeNumberMode::NATNUM7: // Text. Lower, Short
628 : 0 : return NumberChar[natnum1[langnum]][inChar - NUMBER_ZERO];
629 : : case NativeNumberMode::NATNUM2: // Char, Upper
630 : : case NativeNumberMode::NATNUM5: // Text, Upper, Long
631 : : case NativeNumberMode::NATNUM8: // Text, Upper, Short
632 : 0 : return NumberChar[natnum2[langnum]][inChar - NUMBER_ZERO];
633 : : case NativeNumberMode::NATNUM3: // Char, FullWidth
634 : : case NativeNumberMode::NATNUM6: // Text, FullWidth
635 : 0 : return NumberChar[NumberChar_FullWidth][inChar - NUMBER_ZERO];
636 : : case NativeNumberMode::NATNUM9: // Char, Hangul
637 : : case NativeNumberMode::NATNUM10: // Text, Hangul, Long
638 : : case NativeNumberMode::NATNUM11: // Text, Hangul, Short
639 : 0 : return NumberChar[NumberChar_Hangul_ko][inChar - NUMBER_ZERO];
640 : : default:
641 : 0 : break;
642 : : }
643 : : }
644 : 0 : return inChar;
645 : : }
646 : :
647 : 0 : sal_Bool SAL_CALL NativeNumberSupplier::isValidNatNum( const Locale& rLocale, sal_Int16 nNativeNumberMode ) throw (RuntimeException)
648 : : {
649 : 0 : sal_Int16 langnum = getLanguageNumber(rLocale);
650 : :
651 [ # # # # : 0 : switch (nNativeNumberMode) {
# # ]
652 : : case NativeNumberMode::NATNUM0: // Ascii
653 : : case NativeNumberMode::NATNUM3: // Char, FullWidth
654 : 0 : return sal_True;
655 : : case NativeNumberMode::NATNUM1: // Char, Lower
656 : 0 : return (langnum >= 0);
657 : : case NativeNumberMode::NATNUM2: // Char, Upper
658 [ # # ]: 0 : if (langnum == 4) // Hebrew numbering
659 : 0 : return sal_True;
660 : : case NativeNumberMode::NATNUM4: // Text, Lower, Long
661 : : case NativeNumberMode::NATNUM5: // Text, Upper, Long
662 : : case NativeNumberMode::NATNUM6: // Text, FullWidth
663 : : case NativeNumberMode::NATNUM7: // Text. Lower, Short
664 : : case NativeNumberMode::NATNUM8: // Text, Upper, Short
665 [ # # ][ # # ]: 0 : return (langnum >= 0 && langnum < 4); // CJK numbering
666 : : case NativeNumberMode::NATNUM9: // Char, Hangul
667 : : case NativeNumberMode::NATNUM10: // Text, Hangul, Long
668 : : case NativeNumberMode::NATNUM11: // Text, Hangul, Short
669 : 0 : return (langnum == 3); // Korean numbering
670 : : }
671 : 0 : return sal_False;
672 : : }
673 : :
674 : 0 : NativeNumberXmlAttributes SAL_CALL NativeNumberSupplier::convertToXmlAttributes( const Locale& rLocale, sal_Int16 nNativeNumberMode ) throw (RuntimeException)
675 : : {
676 : : static const sal_Int16 attShort = 0;
677 : : static const sal_Int16 attMedium = 1;
678 : : static const sal_Int16 attLong = 2;
679 : : static const sal_Char *attType[] = { "short", "medium", "long" };
680 : :
681 : 0 : sal_Int16 number = NumberChar_HalfWidth, type = attShort;
682 : :
683 [ # # ]: 0 : if (isValidNatNum(rLocale, nNativeNumberMode)) {
684 : 0 : sal_Int16 langnum = getLanguageNumber(rLocale);
685 [ # # # # : 0 : switch (nNativeNumberMode) {
# # # # #
# # # # ]
686 : : case NativeNumberMode::NATNUM0: // Ascii
687 : 0 : number = NumberChar_HalfWidth;
688 : 0 : type = attShort;
689 : 0 : break;
690 : : case NativeNumberMode::NATNUM1: // Char, Lower
691 : 0 : number = natnum1[langnum];
692 : 0 : type = attShort;
693 : 0 : break;
694 : : case NativeNumberMode::NATNUM2: // Char, Upper
695 : 0 : number = natnum2[langnum];
696 [ # # ]: 0 : type = number == NumberChar_he ? attMedium : attShort;
697 : 0 : break;
698 : : case NativeNumberMode::NATNUM3: // Char, FullWidth
699 : 0 : number = NumberChar_FullWidth;
700 : 0 : type = attShort;
701 : 0 : break;
702 : : case NativeNumberMode::NATNUM4: // Text, Lower, Long
703 : 0 : number = natnum1[langnum];
704 : 0 : type = attLong;
705 : 0 : break;
706 : : case NativeNumberMode::NATNUM5: // Text, Upper, Long
707 : 0 : number = natnum2[langnum];
708 : 0 : type = attLong;
709 : 0 : break;
710 : : case NativeNumberMode::NATNUM6: // Text, FullWidth
711 : 0 : number = NumberChar_FullWidth;
712 : 0 : type = attLong;
713 : 0 : break;
714 : : case NativeNumberMode::NATNUM7: // Text. Lower, Short
715 : 0 : number = natnum1[langnum];
716 : 0 : type = attMedium;
717 : 0 : break;
718 : : case NativeNumberMode::NATNUM8: // Text, Upper, Short
719 : 0 : number = natnum2[langnum];
720 : 0 : type = attMedium;
721 : 0 : break;
722 : : case NativeNumberMode::NATNUM9: // Char, Hangul
723 : 0 : number = NumberChar_Hangul_ko;
724 : 0 : type = attShort;
725 : 0 : break;
726 : : case NativeNumberMode::NATNUM10: // Text, Hangul, Long
727 : 0 : number = NumberChar_Hangul_ko;
728 : 0 : type = attLong;
729 : 0 : break;
730 : : case NativeNumberMode::NATNUM11: // Text, Hangul, Short
731 : 0 : number = NumberChar_Hangul_ko;
732 : 0 : type = attMedium;
733 : 0 : break;
734 : : default:
735 : 0 : break;
736 : : }
737 : : }
738 : 0 : return NativeNumberXmlAttributes(rLocale, OUString(&NumberChar[number][1], 1),
739 : 0 : OUString::createFromAscii(attType[type]));
740 : : }
741 : :
742 : 0 : static sal_Bool natNumIn(sal_Int16 num, sal_Int16 natnum[], sal_Int16 len)
743 : : {
744 [ # # ]: 0 : for (sal_Int16 i = 0; i < len; i++)
745 [ # # ]: 0 : if (natnum[i] == num)
746 : 0 : return sal_True;
747 : 0 : return sal_False;
748 : : }
749 : :
750 : 0 : sal_Int16 SAL_CALL NativeNumberSupplier::convertFromXmlAttributes( const NativeNumberXmlAttributes& aAttr ) throw (RuntimeException)
751 : : {
752 : : sal_Unicode numberChar[NumberChar_Count];
753 [ # # ]: 0 : for (sal_Int16 i = 0; i < NumberChar_Count; i++)
754 : 0 : numberChar[i] = NumberChar[i][1];
755 : 0 : OUString number(numberChar, NumberChar_Count);
756 : :
757 : 0 : sal_Int16 num = sal::static_int_cast<sal_Int16>( number.indexOf(aAttr.Format) );
758 : :
759 [ # # ]: 0 : if ( aAttr.Style == "short" ) {
760 [ # # ]: 0 : if (num == NumberChar_FullWidth)
761 : 0 : return NativeNumberMode::NATNUM3;
762 [ # # ]: 0 : else if (num == NumberChar_Hangul_ko)
763 : 0 : return NativeNumberMode::NATNUM9;
764 [ # # ]: 0 : else if (natNumIn(num, natnum1, sizeof_natnum1))
765 : 0 : return NativeNumberMode::NATNUM1;
766 [ # # ]: 0 : else if (natNumIn(num, natnum2, sizeof_natnum2))
767 : 0 : return NativeNumberMode::NATNUM2;
768 [ # # ]: 0 : } else if ( aAttr.Style == "medium" ) {
769 [ # # ]: 0 : if (num == NumberChar_Hangul_ko)
770 : 0 : return NativeNumberMode::NATNUM11;
771 [ # # ]: 0 : else if (num == NumberChar_he)
772 : 0 : return NativeNumberMode::NATNUM2;
773 [ # # ]: 0 : else if (natNumIn(num, natnum1, sizeof_natnum1))
774 : 0 : return NativeNumberMode::NATNUM7;
775 [ # # ]: 0 : else if (natNumIn(num, natnum2, sizeof_natnum2))
776 : 0 : return NativeNumberMode::NATNUM8;
777 [ # # ]: 0 : } else if ( aAttr.Style == "long" ) {
778 [ # # ]: 0 : if (num == NumberChar_FullWidth)
779 : 0 : return NativeNumberMode::NATNUM6;
780 [ # # ]: 0 : else if (num == NumberChar_Hangul_ko)
781 : 0 : return NativeNumberMode::NATNUM10;
782 [ # # ]: 0 : else if (natNumIn(num, natnum1, sizeof_natnum1))
783 : 0 : return NativeNumberMode::NATNUM4;
784 [ # # ]: 0 : else if (natNumIn(num, natnum2, sizeof_natnum2))
785 : 0 : return NativeNumberMode::NATNUM5;
786 : : } else {
787 [ # # ]: 0 : throw RuntimeException();
788 : : }
789 : 0 : return NativeNumberMode::NATNUM0;
790 : : }
791 : :
792 : :
793 : : // Following code generates Hebrew Number,
794 : : // see numerical system in the Hebrew Numbering System in following link for details,
795 : : // http://people.netscape.com/smontagu/writings/HebrewNumbers.html
796 : :
797 : : struct HebrewNumberChar {
798 : : sal_Unicode code;
799 : : sal_Int16 value;
800 : : } HebrewNumberCharArray[] = {
801 : : { 0x05ea, 400 },
802 : : { 0x05ea, 400 },
803 : : { 0x05e9, 300 },
804 : : { 0x05e8, 200 },
805 : : { 0x05e7, 100 },
806 : : { 0x05e6, 90 },
807 : : { 0x05e4, 80 },
808 : : { 0x05e2, 70 },
809 : : { 0x05e1, 60 },
810 : : { 0x05e0, 50 },
811 : : { 0x05de, 40 },
812 : : { 0x05dc, 30 },
813 : : { 0x05db, 20 },
814 : : { 0x05d9, 10 },
815 : : { 0x05d8, 9 },
816 : : { 0x05d7, 8 },
817 : : { 0x05d6, 7 },
818 : : { 0x05d5, 6 },
819 : : { 0x05d4, 5 },
820 : : { 0x05d3, 4 },
821 : : { 0x05d2, 3 },
822 : : { 0x05d1, 2 },
823 : : { 0x05d0, 1 }
824 : : };
825 : :
826 : : static sal_Int16 nbOfHebrewNumberChar = sizeof(HebrewNumberCharArray)/sizeof(HebrewNumberChar);
827 : :
828 : : static sal_Unicode thousand[] = {0x05d0, 0x05dc, 0x05e3, 0x0};
829 : : static sal_Unicode thousands[] = {0x05d0, 0x05dc, 0x05e4, 0x05d9, 0x0};
830 : : static sal_Unicode thousands_last[] = {0x05d0, 0x05dc, 0x05e4, 0x05d9, 0x05dd, 0x0};
831 : : static sal_Unicode geresh = 0x05f3;
832 : : static sal_Unicode gershayim = 0x05f4;
833 : :
834 : 0 : void makeHebrewNumber(sal_Int64 value, OUStringBuffer& output, sal_Bool isLast, sal_Bool useGeresh)
835 : : {
836 : 0 : sal_Int16 num = sal::static_int_cast<sal_Int16>(value % 1000);
837 : :
838 [ # # ]: 0 : if (value > 1000) {
839 : 0 : makeHebrewNumber(value / 1000, output, num != 0, useGeresh);
840 : 0 : output.appendAscii(" ");
841 : : }
842 [ # # ]: 0 : if (num == 0) {
843 [ # # ][ # # ]: 0 : output.append(value == 1000 ? thousand : isLast ? thousands_last : thousands);
844 : : } else {
845 : 0 : sal_Int16 nbOfChar = 0;
846 [ # # ][ # # ]: 0 : for (sal_Int32 j = 0; num > 0 && j < nbOfHebrewNumberChar; j++) {
[ # # ]
847 [ # # ]: 0 : if (num - HebrewNumberCharArray[j].value >= 0) {
848 : 0 : nbOfChar++;
849 [ # # ][ # # ]: 0 : if (num == 15 || num == 16) // substitution for 15 and 16
850 : 0 : j++;
851 : 0 : num = sal::static_int_cast<sal_Int16>( num - HebrewNumberCharArray[j].value );
852 : 0 : output.append(HebrewNumberCharArray[j].code);
853 : : }
854 : : }
855 [ # # ]: 0 : if (useGeresh) {
856 [ # # ]: 0 : if (nbOfChar > 1) // a number is written as more than one character
857 : 0 : output.insert(output.getLength() - 1, gershayim);
858 [ # # ]: 0 : else if (nbOfChar == 1) // a number is written as a single character
859 : 0 : output.append(geresh);
860 : : }
861 : : }
862 : 0 : }
863 : :
864 : 0 : OUString SAL_CALL getHebrewNativeNumberString(const OUString& aNumberString, sal_Bool useGeresh)
865 : : {
866 : 0 : sal_Int64 value = 0;
867 : 0 : sal_Int32 i, count = 0, len = aNumberString.getLength();
868 : 0 : const sal_Unicode *src = aNumberString.getStr();
869 : :
870 [ # # ]: 0 : for (i = 0; i < len; i++) {
871 : 0 : sal_Unicode ch = src[i];
872 [ # # ][ # # ]: 0 : if (isNumber(ch)) {
873 [ # # ]: 0 : if (++count >= 20) // Number is too long, could not be handled.
874 : 0 : return aNumberString;
875 : 0 : value = value * 10 + (ch - NUMBER_ZERO);
876 : : }
877 [ # # ][ # # ]: 0 : else if (isSeparator(ch) && count > 0) continue;
878 [ # # ][ # # ]: 0 : else if (isMinus(ch) && count == 0) continue;
879 : 0 : else break;
880 : : }
881 : :
882 [ # # ]: 0 : if (value > 0) {
883 : 0 : OUStringBuffer output(count*2 + 2 + len - i);
884 : :
885 [ # # ]: 0 : makeHebrewNumber(value, output, sal_True, useGeresh);
886 : :
887 [ # # ]: 0 : if (i < len)
888 [ # # ]: 0 : output.append(aNumberString.copy(i));
889 : :
890 [ # # ]: 0 : return output.makeStringAndClear();
891 : : }
892 : : else
893 : 0 : return aNumberString;
894 : : }
895 : :
896 : : static const sal_Char* implementationName = "com.sun.star.i18n.NativeNumberSupplier";
897 : :
898 : 0 : OUString SAL_CALL NativeNumberSupplier::getImplementationName() throw( RuntimeException )
899 : : {
900 : 0 : return OUString::createFromAscii( implementationName );
901 : : }
902 : :
903 : : sal_Bool SAL_CALL
904 : 0 : NativeNumberSupplier::supportsService(const OUString& rServiceName) throw( RuntimeException )
905 : : {
906 : 0 : return rServiceName.compareToAscii(implementationName) == 0;
907 : : }
908 : :
909 : : Sequence< OUString > SAL_CALL
910 : 0 : NativeNumberSupplier::getSupportedServiceNames() throw( RuntimeException )
911 : : {
912 : 0 : Sequence< OUString > aRet(1);
913 [ # # ]: 0 : aRet[0] = OUString::createFromAscii( implementationName );
914 : 0 : return aRet;
915 : : }
916 : :
917 : : } } } }
918 : :
919 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|