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