LCOV - code coverage report
Current view: top level - i18npool/source/nativenumber - nativenumbersupplier.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 154 448 34.4 %
Date: 2015-06-13 12:38:46 Functions: 12 19 63.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11