[Libreoffice-commits] core.git: i18npool/source offapi/com svl/CppunitTest_svl_qa_cppunit.mk svl/qa

Mike Kaganski mike.kaganski at collabora.com
Tue May 15 09:42:58 UTC 2018


 i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx |   66 ++----
 i18npool/source/nativenumber/nativenumbersupplier.cxx                 |  107 ++++++++--
 offapi/com/sun/star/i18n/NativeNumberMode.idl                         |   11 +
 svl/CppunitTest_svl_qa_cppunit.mk                                     |   14 +
 svl/qa/unit/svl.cxx                                                   |   12 +
 5 files changed, 152 insertions(+), 58 deletions(-)

New commits:
commit 56a7f308cf57f87d9e2cdeb77f48b570f81de85e
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Sun May 13 03:09:43 2018 +0300

    tdf#115007: add NatNum codes for cardinal/ordinal number names/indicators
    
    ... based on libnumbertext integrated since commit
    f1579d3d6c5f5f3a651825e035b93bee7a4f43c6.
    
    [NatNum12] gives cardinal number names (one, two, three, ...)
    [NatNum13] gives ordinal number names (first, second, third, ...)
    [NatNum14] gives ordinal indicators (1st, 2nd, 3rd, ...)
    
    Change-Id: Ie2afdeeb82da1b36e9755c02d7b2276c77be9c72
    Reviewed-on: https://gerrit.libreoffice.org/54186
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx b/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
index e222611a2afe..af4e27d0f69f 100644
--- a/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
+++ b/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
@@ -19,7 +19,6 @@
 
 #include <defaultnumberingprovider.hxx>
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
-#include <com/sun/star/linguistic2/NumberText.hpp>
 #include <com/sun/star/style/NumberingType.hpp>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/configuration/theDefaultProvider.hpp>
@@ -32,9 +31,6 @@
 #include <string.h>
 #include <comphelper/propertysequence.hxx>
 #include <cppuhelper/supportsservice.hxx>
-#include <i18nlangtag/languagetag.hxx>
-#include <unordered_map>
-#include <map>
 
 // Cyrillic upper case
 #define C_CYR_A "\xD0\x90"
@@ -588,6 +584,7 @@ DefaultNumberingProvider::makeNumberingString( const Sequence<beans::PropertyVal
      sal_Int16 tableSize = 0;
      const sal_Unicode *table = nullptr;     // initialize to avoid compiler warning
      bool bRecycleSymbol = false;
+     bool bCapitalize = false;
      Locale locale;
 
      OUString  prefix;
@@ -639,45 +636,20 @@ DefaultNumberingProvider::makeNumberingString( const Sequence<beans::PropertyVal
                lcl_formatChars( lowerLetter, 26, number-1, result );
                break;
           case TEXT_NUMBER:
+               natNum = NativeNumberMode::NATNUM14; // ordinal indicators (1st, 2nd, 3rd, ...)
+               locale = aLocale;
+               bCapitalize = true;
+               break;
           case TEXT_CARDINAL:
+               natNum = NativeNumberMode::NATNUM12; // cardinal number names (one, two, three, ...)
+               locale = aLocale;
+               bCapitalize = true;
+               break;
           case TEXT_ORDINAL:
-               {
-                   static css::uno::Reference< css::linguistic2::XNumberText > xNumberText;
-                   if (!xNumberText.is())
-                       xNumberText = linguistic2::NumberText::create( m_xContext );
-                   OUString aLoc = LanguageTag::convertToBcp47(aLocale);
-                   OUString numbertext_prefix = "";
-                   if (numType == TEXT_NUMBER)
-                       numbertext_prefix += "ordinal-number ";
-                   else if (numType == TEXT_ORDINAL)
-                       numbertext_prefix += "ordinal ";
-                   // Several hundreds of headings could result typing lags because
-                   // of the continuous update of the multiple number names during typing.
-                   // We fix this by buffering the result of the conversion.
-                   static std::unordered_map<sal_Int32,std::map<OUString, OUString> > aBuff;
-                   auto aBuffItem = aBuff.find(number);
-                   std::map<OUString, OUString> aItem;
-                   if (aBuffItem == aBuff.end() || !aBuffItem->second.count(numbertext_prefix + aLoc))
-                   {
-                       OUString snumber = OUString::number(number);
-                       OUString aNum =
-                           xNumberText->getNumberText( numbertext_prefix + snumber, aLocale);
-                       if ( !xCharClass.is() )
-                           xCharClass = CharacterClassification::create( m_xContext );
-                       // use number at missing number to text conversion
-                       if (aNum.getLength() == 0)
-                           aNum = snumber;
-                       // capitalize first letter
-                       aItem[numbertext_prefix + aLoc] = xCharClass->toTitle(aNum, 0, 1, aLocale) + aNum.copy(1);
-                       aBuff.insert(std::make_pair(number, aItem));
-                   }
-                   else
-                   {
-                       aItem = aBuffItem->second;
-                   }
-                   result += aItem[numbertext_prefix + aLoc];
-                   break;
-               }
+               natNum = NativeNumberMode::NATNUM13; // ordinal number names (first, second, third, ...)
+               locale = aLocale;
+               bCapitalize = true;
+               break;
           case ROMAN_UPPER:
                result += toRoman( number );
                break;
@@ -937,7 +909,17 @@ DefaultNumberingProvider::makeNumberingString( const Sequence<beans::PropertyVal
 
         if (natNum) {
             rtl::Reference<NativeNumberSupplierService> xNatNum(new NativeNumberSupplierService);
-            result += xNatNum->getNativeNumberString(OUString::number( number ), locale, natNum);
+            OUString aNum
+                = xNatNum->getNativeNumberString(OUString::number(number), locale, natNum);
+            if (bCapitalize)
+            {
+                if (!xCharClass.is())
+                    xCharClass = CharacterClassification::create(m_xContext);
+                // capitalize first letter
+                result += xCharClass->toTitle(aNum, 0, 1, aLocale) + aNum.copy(1);
+            }
+            else
+                result += aNum;
         } else if (tableSize) {
             if ( number > tableSize && !bRecycleSymbol)
                 result += OUString::number( number);
diff --git a/i18npool/source/nativenumber/nativenumbersupplier.cxx b/i18npool/source/nativenumber/nativenumbersupplier.cxx
index 6dc7c792c931..f3c40a2b7d61 100644
--- a/i18npool/source/nativenumber/nativenumbersupplier.cxx
+++ b/i18npool/source/nativenumber/nativenumbersupplier.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <i18nlangtag/languagetag.hxx>
 #include <i18nlangtag/mslangid.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <sal/macros.h>
@@ -24,8 +25,12 @@
 #include <localedata.hxx>
 #include "data/numberchar.h"
 #include <comphelper/string.hxx>
+#include <comphelper/processfactory.hxx>
 #include <cppuhelper/supportsservice.hxx>
+#include <map>
 #include <memory>
+#include <unordered_map>
+#include <com/sun/star/linguistic2/NumberText.hpp>
 
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::i18n;
@@ -250,7 +255,10 @@ OUString AsciiToNative( const OUString& inStr, sal_Int32 nCount,
     }
     return aRet;
 }
-static void NativeToAscii_numberMaker(sal_Int16 max, sal_Int16 prev, const sal_Unicode *str,
+
+namespace
+{
+void 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, bool useOffset,
         OUString& numberChar, OUString& multiplierChar)
 {
@@ -300,7 +308,7 @@ static void NativeToAscii_numberMaker(sal_Int16 max, sal_Int16 prev, const sal_U
 }
 
 /// @throws RuntimeException
-static OUString NativeToAscii(const OUString& inStr,
+OUString NativeToAscii(const OUString& inStr,
         sal_Int32 nCount, Sequence< sal_Int32 >& offset, bool useOffset )
 {
     OUString aRet;
@@ -374,7 +382,7 @@ static OUString NativeToAscii(const OUString& inStr,
     return aRet;
 }
 
-static const Number natnum4[4] = {
+const Number natnum4[4] = {
         { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh], 0,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
         { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], 0,
@@ -385,7 +393,7 @@ static const Number natnum4[4] = {
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
 };
 
-static const Number natnum5[4] = {
+const Number natnum5[4] = {
         { NumberChar_Upper_zh, MultiplierChar_6_CJK[Multiplier_Upper_zh], 0,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
         { NumberChar_Upper_zh_TW, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], 0,
@@ -396,7 +404,7 @@ static const Number natnum5[4] = {
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
 };
 
-static const Number natnum6[4] = {
+const Number natnum6[4] = {
         { NumberChar_FullWidth, MultiplierChar_6_CJK[Multiplier_Lower_zh], 0,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
         { NumberChar_FullWidth, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], 0,
@@ -407,7 +415,7 @@ static const Number natnum6[4] = {
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
 };
 
-static const Number natnum7[4] = {
+const Number natnum7[4] = {
         { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh], NUMBER_OMIT_ALL,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
         { NumberChar_Lower_zh, MultiplierChar_6_CJK[Multiplier_Lower_zh_TW], NUMBER_OMIT_ALL,
@@ -418,7 +426,7 @@ static const Number natnum7[4] = {
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
 };
 
-static const Number natnum8[4] = {
+const Number natnum8[4] = {
         { NumberChar_Upper_zh, MultiplierChar_6_CJK[Multiplier_Upper_zh], NUMBER_OMIT_ALL,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
         { NumberChar_Upper_zh_TW, MultiplierChar_6_CJK[Multiplier_Upper_zh_TW], NUMBER_OMIT_ALL,
@@ -429,14 +437,14 @@ static const Number natnum8[4] = {
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK },
 };
 
-static const Number natnum10 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ZERO,
+const Number natnum10 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ZERO,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK };
-static const Number natnum11 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ALL,
+const Number natnum11 = { NumberChar_Hangul_ko, MultiplierChar_6_CJK[Multiplier_Hangul_ko], NUMBER_OMIT_ALL,
                 ExponentCount_6_CJK, MultiplierExponent_6_CJK };
 
 //! ATTENTION: Do not change order of elements!
 //! Append new languages to the end of the list!
-static const sal_Char *natnum1Locales[] = {
+const sal_Char *natnum1Locales[] = {
     "zh_CN",
     "zh_TW",
     "ja",
@@ -464,11 +472,11 @@ static const sal_Char *natnum1Locales[] = {
     "fa",
     "cu"
 };
-static sal_Int16 nbOfLocale = SAL_N_ELEMENTS(natnum1Locales);
+sal_Int16 nbOfLocale = SAL_N_ELEMENTS(natnum1Locales);
 
 //! ATTENTION: Do not change order of elements!
 //! Number and order must match elements of natnum1Locales!
-static const sal_Int16 natnum1[] = {
+const sal_Int16 natnum1[] = {
     NumberChar_Lower_zh,
     NumberChar_Lower_zh,
     NumberChar_Modern_ja,
@@ -496,20 +504,20 @@ static const sal_Int16 natnum1[] = {
     NumberChar_EastIndic_ar,
     NumberChar_cu
 };
-static const sal_Int16 sizeof_natnum1 = SAL_N_ELEMENTS(natnum1);
+const sal_Int16 sizeof_natnum1 = SAL_N_ELEMENTS(natnum1);
 
 //! ATTENTION: Do not change order of elements!
 //! Order must match first elements of natnum1Locales!
-static const sal_Int16 natnum2[] = {
+const sal_Int16 natnum2[] = {
     NumberChar_Upper_zh,
     NumberChar_Upper_zh_TW,
     NumberChar_Traditional_ja,
     NumberChar_Upper_ko,
     NumberChar_he
 };
-static const sal_Int16 sizeof_natnum2 = SAL_N_ELEMENTS(natnum2);
+const sal_Int16 sizeof_natnum2 = SAL_N_ELEMENTS(natnum2);
 
-static sal_Int16 getLanguageNumber( const Locale& rLocale)
+sal_Int16 getLanguageNumber( const Locale& rLocale)
 {
     // return zh_TW for TW, HK and MO, return zh_CN for other zh locales.
     if (rLocale.Language == "zh") return MsLangId::isTraditionalChinese(rLocale) ? 1 : 0;
@@ -521,12 +529,76 @@ static sal_Int16 getLanguageNumber( const Locale& rLocale)
     return -1;
 }
 
+OUString getNumberText(const Locale& aLocale, sal_Int16 numType, const OUString& rNumberString)
+{
+    assert(numType == NativeNumberMode::NATNUM12 || numType == NativeNumberMode::NATNUM13
+           || numType == NativeNumberMode::NATNUM14);
+
+    sal_Int32 i, count = 0;
+    const sal_Int32 len = rNumberString.getLength();
+    const sal_Unicode* src = rNumberString.getStr();
+
+    OUStringBuffer sBuf(len);
+    for (i = 0; i < len; i++)
+    {
+        sal_Unicode ch = src[i];
+        if (isNumber(ch))
+        {
+            ++count;
+            sBuf.append(ch);
+        }
+        else if (isSeparator(ch) && count > 0)
+            continue;
+        else if (isMinus(ch) && count == 0)
+            sBuf.append(ch);
+        else
+            break;
+    }
+
+    if (count == 0)
+        return rNumberString;
+
+    OUString aNumberStr = sBuf.makeStringAndClear();
+
+    static auto xNumberText
+        = css::linguistic2::NumberText::create(comphelper::getProcessComponentContext());
+    OUString aLoc = LanguageTag::convertToBcp47(aLocale);
+    OUString numbertext_prefix;
+    if (numType == NativeNumberMode::NATNUM14)
+        numbertext_prefix = "ordinal-number ";
+    else if (numType == NativeNumberMode::NATNUM13)
+        numbertext_prefix = "ordinal ";
+    // Several hundreds of headings could result typing lags because
+    // of the continuous update of the multiple number names during typing.
+    // We fix this by buffering the result of the conversion.
+    static std::unordered_map<OUString, std::map<OUString, OUString>> aBuff;
+    auto& rItems = aBuff[aNumberStr];
+    auto& rItem = rItems[numbertext_prefix + aLoc];
+    if (rItem.isEmpty())
+    {
+        rItem = xNumberText->getNumberText(numbertext_prefix + aNumberStr, aLocale);
+        // use number at missing number to text conversion
+        if (rItem.isEmpty())
+            rItem = aNumberStr;
+    }
+    OUString sResult = rItem;
+    if (i < len)
+        sResult += rNumberString.copy(i);
+    return sResult;
+}
+}
+
 OUString NativeNumberSupplierService::getNativeNumberString(const OUString& aNumberString, const Locale& rLocale,
                 sal_Int16 nNativeNumberMode, Sequence< sal_Int32 >& offset)
 {
     if (!isValidNatNum(rLocale, nNativeNumberMode))
         return aNumberString;
 
+    if (nNativeNumberMode == NativeNumberMode::NATNUM12
+        || nNativeNumberMode == NativeNumberMode::NATNUM13
+        || nNativeNumberMode == NativeNumberMode::NATNUM14)
+        return getNumberText(rLocale, nNativeNumberMode, aNumberString);
+
     sal_Int16 langnum = getLanguageNumber(rLocale);
     if (langnum == -1)
         return aNumberString;
@@ -664,6 +736,9 @@ sal_Bool SAL_CALL NativeNumberSupplierService::isValidNatNum( const Locale& rLoc
     switch (nNativeNumberMode) {
         case NativeNumberMode::NATNUM0:     // Ascii
         case NativeNumberMode::NATNUM3:     // Char, FullWidth
+        case NativeNumberMode::NATNUM12:    // Cardinal number names (one, two, three, ...)
+        case NativeNumberMode::NATNUM13:    // Ordinal number names (first, second, third, ...)
+        case NativeNumberMode::NATNUM14:    // Ordinal indicators (1st, 2nd, 3rd, ...)
             return true;
         case NativeNumberMode::NATNUM1:     // Char, Lower
             return (langnum >= 0);
diff --git a/offapi/com/sun/star/i18n/NativeNumberMode.idl b/offapi/com/sun/star/i18n/NativeNumberMode.idl
index 6af461350e7e..f19980b96edc 100644
--- a/offapi/com/sun/star/i18n/NativeNumberMode.idl
+++ b/offapi/com/sun/star/i18n/NativeNumberMode.idl
@@ -146,6 +146,17 @@ published constants NativeNumberMode
       */
     const short NATNUM11    = 11;
 
+    /** Transliteration to cardinal number names (one, two, three, ...)
+     */
+    const short NATNUM12 = 12;
+
+    /** Transliteration to ordinal number names (first, second, third, ...)
+     */
+    const short NATNUM13 = 13;
+
+    /** Transliteration to ordinal indicators (1st, 2nd, 3rd, ...)
+     */
+    const short NATNUM14 = 14;
 };
 
 }; }; }; };
diff --git a/svl/CppunitTest_svl_qa_cppunit.mk b/svl/CppunitTest_svl_qa_cppunit.mk
index 65be44e40b6f..a067efe8794f 100644
--- a/svl/CppunitTest_svl_qa_cppunit.mk
+++ b/svl/CppunitTest_svl_qa_cppunit.mk
@@ -27,6 +27,16 @@ $(eval $(call gb_CppunitTest_use_externals,svl_qa_cppunit, \
 	icu_headers \
 ))
 
+ifeq ($(ENABLE_LIBNUMBERTEXT),TRUE)
+$(eval $(call gb_CppunitTest_use_package,svl_qa_cppunit, \
+    libnumbertext_numbertext \
+))
+endif
+
+$(eval $(call gb_CppunitTest_add_defs,svl_qa_cppunit, \
+    -DENABLE_LIBNUMBERTEXT=$(if $(filter TRUE,$(ENABLE_LIBNUMBERTEXT)),1,0) \
+))
+
 $(eval $(call gb_CppunitTest_add_exception_objects,svl_qa_cppunit, \
 	svl/qa/unit/svl \
 ))
@@ -52,6 +62,10 @@ $(eval $(call gb_CppunitTest_set_include,svl_qa_cppunit,\
 $(eval $(call gb_CppunitTest_use_components,svl_qa_cppunit,\
 	i18npool/util/i18npool \
 	configmgr/source/configmgr \
+	$(if $(filter TRUE,$(ENABLE_LIBNUMBERTEXT)), \
+	    framework/util/fwk \
+	    lingucomponent/source/numbertext/numbertext \
+	) \
 ))
 
 $(eval $(call gb_CppunitTest_use_ure,svl_qa_cppunit))
diff --git a/svl/qa/unit/svl.cxx b/svl/qa/unit/svl.cxx
index 633e82b75eb2..b744e5a3bfbb 100644
--- a/svl/qa/unit/svl.cxx
+++ b/svl/qa/unit/svl.cxx
@@ -1383,6 +1383,18 @@ void Test::testUserDefinedNumberFormats()
         checkPreviewString(aFormatter, sCode, 120, eLang, sExpected);
         sCode = "[DBNum2][$-0404]General\\ ";
         checkPreviewString(aFormatter, sCode, 120, eLang, sExpected);
+#if ENABLE_LIBNUMBERTEXT
+        // tdf#115007 - cardinal/ordinal number names/indicators
+        sCode = "[NatNum12]0";
+        sExpected = "one hundred twenty-three";
+        checkPreviewString(aFormatter, sCode, 123, eLang, sExpected);
+        sCode = "[NatNum13]0";
+        sExpected = "one hundred twenty-third";
+        checkPreviewString(aFormatter, sCode, 123, eLang, sExpected);
+        sCode = "[NatNum14]0";
+        sExpected = "123rd";
+        checkPreviewString(aFormatter, sCode, 123, eLang, sExpected);
+#endif
     }
     {  // tdf#105968 engineering format with value rounded up to next magnitude
         sCode = "##0.00E+00";


More information about the Libreoffice-commits mailing list