Date: prev next · Thread: first prev next last
2011 Archives by date, by thread · List index


Hi

Changed function lcl_formatPersianWord to be more generic, and added support
for some more numbering types:
English word: one, two, three, ...
English cardinal: first, second, third, ...
English cardinal semi-word: 1st, 2nd, 3rd, ...
Persian cardinal word.

I used C++ macros, but do not know whether libreoffice community
likes using it or not?
Any feedback is welcomed.

Thanks
-Elahi
From 094397fd2e5ca6d59b7541aa749212a2e57e2375 Mon Sep 17 00:00:00 2001
From: Mohammad Elahi <ElahiMohammad@gmail.com>
Date: Thu, 1 Sep 2011 04:16:47 +0430
Subject: [PATCH] Add more numbering types, English word, English cardinal, ...

Making lcl_formatPersianWord more generic and rename it to lcl_formatNumberWord.
And adding three more numbering types based on it.
English Numbers in word
English cardinal numbers in word
English cardinal numbers in digits with word suffix
Persian cardinal numbers in word
---
 .../defaultnumberingprovider.cxx                   |  344 ++++++++++++++++++-
 offapi/com/sun/star/style/NumberingType.idl        |   28 ++
 2 files changed, 353 insertions(+), 19 deletions(-)

diff --git a/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx 
b/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
index 7a02463..4c43d7d 100644
--- a/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
+++ b/i18npool/source/defaultnumberingprovider/defaultnumberingprovider.cxx
@@ -215,8 +215,72 @@ static sal_Unicode lowerLetter[] = {
     0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
 };
 
+#define DEFINE_WORD_TABLE(X) \
+NumberWordTable X {                                                      \
+    {                                                                    \
+        {                                                                \
+            X##_T1[0], X##_T1[1], X##_T1[2], X##_T1[3], X##_T1[4],       \
+            X##_T1[5], X##_T1[6], X##_T1[7], X##_T1[8], X##_T1[9],       \
+            X##_T1[10],X##_T1[11],X##_T1[12],X##_T1[13],X##_T1[14],      \
+            X##_T1[15],X##_T1[16],X##_T1[17],X##_T1[18],X##_T1[19]       \
+        },                                                               \
+        {                                                                \
+            X##_E1[0], X##_E1[1], X##_E1[2], X##_E1[3], X##_E1[4],       \
+            X##_E1[5], X##_E1[6], X##_E1[7], X##_E1[8], X##_E1[9],       \
+            X##_E1[10],X##_E1[11],X##_E1[12],X##_E1[13],X##_E1[14],      \
+            X##_E1[15],X##_E1[16],X##_E1[17],X##_E1[18],X##_E1[19]       \
+        }                                                                \
+    },                                                                   \
+    {                                                                    \
+        {                                                                \
+            X##_T2[0], X##_T2[1], X##_T2[2], X##_T2[3], X##_T2[4],       \
+            X##_T2[5], X##_T2[6], X##_T2[7]                              \
+        },                                                               \
+        {                                                                \
+            X##_E2[0], X##_E2[1], X##_E2[2], X##_E2[3], X##_E2[4],       \
+            X##_E2[5], X##_E2[6], X##_E2[7]                              \
+        },                                                               \
+    },                                                                   \
+    {                                                                    \
+        {                                                                \
+            X##_T3[0], X##_T3[1], X##_T3[2], X##_T3[3], X##_T3[4],       \
+            X##_T3[5], X##_T3[6], X##_T3[7], X##_T3[8]                   \
+        },                                                               \
+        {                                                                \
+            X##_E3[0], X##_E3[1], X##_E3[2], X##_E3[3], X##_E3[4],       \
+            X##_E3[5], X##_E3[6], X##_E3[7], X##_E3[8]                   \
+        },                                                               \
+    },                                                                   \
+    {                                                                    \
+        {                                                                \
+            X##_T4[0], X##_T4[1], X##_T4[2]                              \
+        },                                                               \
+        {                                                                \
+            X##_E4[0], X##_E4[1], X##_E4[2]                              \
+        }                                                                \
+    },                                                                   \
+    {                                                                    \
+        X##_S[0], X##_S[1], X##_S[2], X##_S[3], X##_S[4]                 \
+    }                                                                    \
+};
+
+typedef struct
+{
+    // the second table is used for irregular cardinal numbers is not empty
+    sal_Unicode *(table1[2][20]);    //0-19
+    sal_Unicode *(table2[2][8]);     //20-90
+    sal_Unicode *(table3[2][9]);     //100-900
+    sal_Unicode *(table4[2][3]);     //1000-1000000-1000000000
+
+    sal_Unicode *(separators[5]);
+    // separators are used as:
+    // One (separator 4) Thousand (separator 3) two hundred (separator 2) thirty (separator 1) two 
(separator 0)
+    // Note: separator 0 is only used in cardinal numbers which are ordinary, exceptions are the 
non empty ones
+    // in exception tables below: exception tables are used for the first written word for 
cardinal numbers
+}NumberWordTable;
+
 // Tables used for numbering in persian words
-static sal_Unicode table_PersianWord_decade1[][7]={
+static sal_Unicode table_PersianWord_T1[20][7]={
     {0},                                                 // 0
     {0x06cc, 0x06a9, 0},                                 // 1
     {0x062f, 0x0648, 0},                                 // 2
@@ -239,7 +303,30 @@ static sal_Unicode table_PersianWord_decade1[][7]={
     {0x0646, 0x0648, 0x0632, 0x062f, 0x0647, 0}          // 19
 };
 
-static sal_Unicode table_PersianWord_decade2[][6]={
+static sal_Unicode table_PersianWord_E1[20][4]={
+    {0},
+    {0},
+    {0},
+    {0x0633, 0x0648, 0x0645, 0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0}
+};
+
+static sal_Unicode table_PersianWord_T2[8][6]={
     {0x0628, 0x06cc, 0x0633, 0x062a, 0},                 // 20
     {0x0633, 0x06cc, 0},                                 // 30
     {0x0686, 0x0647, 0x0644, 0},                         // 40
@@ -250,7 +337,18 @@ static sal_Unicode table_PersianWord_decade2[][6]={
     {0x0646, 0x0648, 0x062f, 0}                          // 90
 };
 
-static sal_Unicode table_PersianWord_decade3[][7]={
+static sal_Unicode table_PersianWord_E2[8][1]={
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0}
+};
+
+static sal_Unicode table_PersianWord_T3[9][7]={
     {0x0635, 0x062f, 0},                                 // 100
     {0x062f, 0x0648, 0x06cc, 0x0633, 0x062a, 0},         // 200
     {0x0633, 0x06cc, 0x0635, 0x062f, 0},                 // 300
@@ -262,12 +360,155 @@ static sal_Unicode table_PersianWord_decade3[][7]={
     {0x0646, 0x0647, 0x0635, 0x062f, 0}                  // 900
 };
 
-static sal_Unicode table_PersianWord_decadeX[][8]={
+static sal_Unicode table_PersianWord_E3[9][1]={
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0}
+};
+
+static sal_Unicode table_PersianWord_T4[3][8]={
     {0x0647, 0x0632, 0x0627, 0x0631, 0},                        // 1000
     {0x0645, 0x06cc, 0x0644, 0x06cc, 0x0648, 0x0646, 0},        // 1000000
     {0x0645, 0x06cc, 0x0644, 0x06cc, 0x0627, 0x0631, 0x062f, 0} // 1000000000
 };
 
+static sal_Unicode table_PersianWord_E4[3][1]={
+    {0},
+    {0},
+    {0}
+};
+
+static sal_Unicode table_PersianWord_S[5][4]={
+    {0x0645,0},
+    {0x20,0x0648,0x20,0},
+    {0x20,0x0648,0x20,0},
+    {0x20,0x0648,0x20,0},
+    {0x20,0}
+};
+
+DEFINE_WORD_TABLE(table_PersianWord);
+
+// tables to define numbers in word (English)
+static sal_Unicode table_EnglishWord_T1[20][10]={
+    {0x0},
+    {'o','n','e',0},
+    {'t','w','o',0},
+    {'t','h','r','e','e',0},
+    {'f','o','u','r',0},
+    {'f','i','v','e',0},
+    {'s','i','x',0},
+    {'s','e','v','e','n',0},
+    {'e','i','g','h','t',0},
+    {'n','i','n','e',0},
+    {'t','e','n',0},
+    {'e','l','e','v','e','n',0},
+    {'t','w','e','l','v','e',0},
+    {'t','h','i','r','t','e','e','n',0},
+    {'f','o','u','r','t','e','e','n',0},
+    {'f','i','f','t','e','e','n',0},
+    {'s','i','x','t','e','e','n',0},
+    {'s','e','v','e','n','t','e','e','n',0},
+    {'e','i','g','h','t','e','e','n',0},
+    {'n','i','n','e','t','e','e','n',0},
+};
+
+
+static sal_Unicode table_EnglishWord_E1[20][7]={
+    {0x0},
+    {'f','i','r','s','t',0},
+    {'s','e','c','o','n','d',0},
+    {'t','h','i','r','d',0},
+    {0},
+    {'f','i','f','t','h',0},
+    {0},
+    {0},
+    {0},
+    {'n','i','n','t','h',0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+};
+
+static sal_Unicode table_EnglishWord_T2[8][8]={
+    {'t','w','e','n','t','y',0},
+    {'t','h','i','r','t','y',0},
+    {'f','o','r','t','y',0},
+    {'f','i','f','t','y',0},
+    {'s','i','x','t','y',0},
+    {'s','e','v','e','n','t','y',0},
+    {'e','i','g','h','t','y',0},
+    {'n','i','n','e','t','y',0},
+};
+
+static sal_Unicode table_EnglishWord_E2[8][11]={
+    {'t','w','e','n','t','i','e','t','h',0},
+    {'t','h','i','r','t','i','e','t','h',0},
+    {'f','o','r','t','i','e','t','h',0},
+    {'f','i','f','t','i','e','t','h',0},
+    {'s','i','x','t','i','e','t','h',0},
+    {'s','e','v','e','n','t','i','e','t','h',0},
+    {'e','i','g','h','t','i','e','t','h',0},
+    {'n','i','n','e','t','i','e','t','h',0},
+};
+
+static sal_Unicode table_EnglishWord_T3[9][14]={
+    {'o','n','e',' ','h','u','n','d','r','e','d',0},
+    {'t','w','o',' ','h','u','n','d','r','e','d',0},
+    {'t','h','r','e','e',' ','h','u','n','d','r','e','d',0},
+    {'f','o','u','r',' ','h','u','n','d','r','e','d',0},
+    {'f','i','v','e',' ','h','u','n','d','r','e','d',0},
+    {'s','i','x',' ','h','u','n','d','r','e','d',0},
+    {'s','e','v','e','n',' ','h','u','n','d','r','e','d',0},
+    {'e','i','g','h','t',' ','h','u','n','d','r','e','d',0},
+    {'n','i','n','e',' ','h','u','n','d','r','e','d',0},
+};
+
+static sal_Unicode table_EnglishWord_E3[9][1]={
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+    {0},
+};
+
+static sal_Unicode table_EnglishWord_T4[3][9]={
+    {'t','h','o','u','s','a','n','d',0},
+    {'m','i','l','l','i','o','n',0},
+    {'b','i','l','l','i','o','n',0}
+};
+
+static sal_Unicode table_EnglishWord_E4[3][1]={
+    {0},
+    {0},
+    {0}
+};
+
+static sal_Unicode table_EnglishWord_S[5][3]={
+    {'t','h',0},
+    {'-',0},
+    {' ',0},
+    {',',' ',0},
+    {' ',0}
+};
+
+DEFINE_WORD_TABLE(table_EnglishWord);
 
 DefaultNumberingProvider::DefaultNumberingProvider( const Reference < XMultiServiceFactory >& xMSF 
) : xSMgr(xMSF),translit(NULL)
 {
@@ -399,57 +640,85 @@ void lcl_formatChars3( sal_Unicode table_capital[], sal_Unicode 
table_small[], i
     respectively limited by sal_Int32 >=0.
     The caller assures that nNumber is not negative.
  */
+
 static
-void lcl_formatPersianWord( sal_Int32 nNumber, OUString& rsResult )
+void lcl_formatNumberWord( sal_Int32 nNumber, NumberWordTable& tables, sal_Bool bCapitalize, 
sal_Bool bUseCardinal, OUString& rsResult )
     throw( IllegalArgumentException, RuntimeException )
 {
     OUStringBuffer aTemp(64);
     unsigned char nDigit;
-    sal_Unicode asPersianWord_conjunction_data[] = {0x20,0x0648,0x20,0};
-    OUString asPersianWord_conjunction( asPersianWord_conjunction_data );
     unsigned char nSection = 0;
 
-    while (int nPart = nNumber % 1000)
+    // Write first word using cardinal exception table if it is not empty
+    #define UseTableAppendElement(table,element)                                                \
+        {                                                                                       \
+            if(bUseCardinal && table[1][element] && table[1][element][0] )                      \
+            {                                                                                   \
+                aTemp.insert( 0, table[1][element]);                                            \
+                bUseCardinal = false;                                                           \
+            }                                                                                   \
+            else                                                                                \
+            {                                                                                   \
+                if(bUseCardinal && table[0][element] && table[0][element][0] )                  \
+                {                                                                               \
+                    aTemp.insert( 0, tables.separators[0]);                                     \
+                    bUseCardinal = false;                                                       \
+                }                                                                               \
+                aTemp.insert( 0, table[0][element]);                                            \
+            }                                                                                   \
+        }
+
+    // ChooseTable returns exception table element if necessary for cardinal numbers and set 
exception to false otherwise return regular table
+    while (nNumber)
     {
+        int nPart = nNumber % 1000;
         if (nSection)
         {
-            if (nSection > SAL_N_ELEMENTS( table_PersianWord_decadeX))
+            if (nSection > 3)
                 throw IllegalArgumentException();   // does not happen with sal_Int32
-            aTemp.insert( 0, asPersianWord_conjunction).insert( 0, 
table_PersianWord_decadeX[nSection-1]);
+            if(aTemp.getLength())
+                aTemp.insert( 0, tables.separators[3]);
+
+            UseTableAppendElement(tables.table4, nSection-1);
         }
 
         if ((nDigit = nPart % 100) < 20)
         {
             if (aTemp.getLength())
-                aTemp.insert( 0, sal_Unicode(0x0020));
-            aTemp.insert( 0, table_PersianWord_decade1[nDigit]);
+                aTemp.insert( 0, tables.separators[4]);
+            UseTableAppendElement(tables.table1, nDigit);
         }
         else
         {
             if ((nDigit = nPart % 10))
             {
                 if (aTemp.getLength())
-                    aTemp.insert( 0, asPersianWord_conjunction);
-                aTemp.insert( 0, table_PersianWord_decade1[nDigit]);
+                    aTemp.insert( 0, tables.separators[4]);
+                UseTableAppendElement(tables.table1, nDigit);
             }
             if ((nDigit = (nPart / 10) % 10))
             {
                 if (aTemp.getLength())
-                    aTemp.insert( 0, asPersianWord_conjunction);
-                aTemp.insert( 0, table_PersianWord_decade2[nDigit-2]);
+                    aTemp.insert( 0, tables.separators[1]);
+                UseTableAppendElement(tables.table2, nDigit-2);
             }
         }
 
         if ((nDigit = nPart / 100))
         {
             if (aTemp.getLength())
-                aTemp.insert( 0, asPersianWord_conjunction);
-            aTemp.insert( 0, table_PersianWord_decade3[nDigit-1]);
+                aTemp.insert( 0, tables.separators[2]);
+            UseTableAppendElement(tables.table3, nDigit-1);
         }
 
         nNumber /= 1000;
         nSection++;
     }
+
+    // Make first character capital if bCapitalize is set
+    if(bCapitalize && 'a'<aTemp[0] && aTemp[0]<'z')
+        aTemp.setCharAt(0, aTemp[0]+'A'-'a');
+
     rsResult += aTemp.makeStringAndClear();
 }
 
@@ -626,6 +895,35 @@ DefaultNumberingProvider::makeNumberingString( const 
Sequence<beans::PropertyVal
           case CHARS_LOWER_LETTER:
                lcl_formatChars( lowerLetter, 26, number-1, result );
                break;
+          case CHARS_ENGLISH_WORD:
+               lcl_formatNumberWord(number, table_EnglishWord, sal_True, sal_False, result);
+               break;
+          case CHARS_ENGLISH_CARDINAL_WORD:
+               lcl_formatNumberWord(number, table_EnglishWord, sal_True, sal_True, result);
+               break;
+          case CHARS_ENGLISH_CARDINAL_SEMI_WORD:
+               {
+                   result += OUString::valueOf(number);
+                   if(10<number && number<20)
+                       result+=OUString::createFromAscii("th");
+                   else
+                   switch(number%10)
+                   {
+                       case 1:
+                           result+=OUString::createFromAscii("st");
+                           break;
+                       case 2:
+                           result+=OUString::createFromAscii("nd");
+                           break;
+                       case 3:
+                           result+=OUString::createFromAscii("rd");
+                           break;
+                       default:
+                           result+=OUString::createFromAscii("th");
+                           break;
+                   }
+                   break;
+                }
           case ROMAN_UPPER:
                result += toRoman( number );
                break;
@@ -855,7 +1153,11 @@ DefaultNumberingProvider::makeNumberingString( const 
Sequence<beans::PropertyVal
               break;
 
           case CHARS_PERSIAN_WORD:
-              lcl_formatPersianWord(number, result);
+              lcl_formatNumberWord(number, table_PersianWord, sal_True, sal_False, result);
+              break;
+
+          case CHARS_PERSIAN_CARDINAL_WORD:
+              lcl_formatNumberWord(number, table_PersianWord, sal_True, sal_True, result);
               break;
 
           default:
@@ -893,6 +1195,9 @@ static const Supported_NumberingType aSupportedTypes[] =
 {
         {style::NumberingType::CHARS_UPPER_LETTER,      "A", LANG_ALL},
         {style::NumberingType::CHARS_LOWER_LETTER,      "a", LANG_ALL},
+        {style::NumberingType::CHARS_ENGLISH_WORD,      NULL, LANG_ALL},
+        {style::NumberingType::CHARS_ENGLISH_CARDINAL_WORD,      NULL, LANG_ALL},
+        {style::NumberingType::CHARS_ENGLISH_CARDINAL_SEMI_WORD,      NULL, LANG_ALL},
         {style::NumberingType::ROMAN_UPPER,                     "I", LANG_ALL},
         {style::NumberingType::ROMAN_LOWER,                     "i", LANG_ALL},
         {style::NumberingType::ARABIC,                          "1", LANG_ALL},
@@ -944,6 +1249,7 @@ static const Supported_NumberingType aSupportedTypes[] =
         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_SR, S_CYR_A ", " S_CYR_B ", .., " 
S_CYR_A S_CYR_A ", " S_CYR_B S_CYR_B ", ... (sr)", LANG_ALL},
         {style::NumberingType::CHARS_PERSIAN,   NULL, LANG_CTL},
         {style::NumberingType::CHARS_PERSIAN_WORD,   NULL, LANG_CTL},
+        {style::NumberingType::CHARS_PERSIAN_CARDINAL_WORD,   NULL, LANG_CTL},
         {style::NumberingType::CHARS_GREEK_LOWER_LETTER,   C_GR_A ", " C_GR_B ", ... (gr)", 
LANG_ALL},
         {style::NumberingType::CHARS_GREEK_UPPER_LETTER,   S_GR_A ", " S_GR_B ", ... (gr)", 
LANG_ALL},
 };
diff --git a/offapi/com/sun/star/style/NumberingType.idl 
b/offapi/com/sun/star/style/NumberingType.idl
index 0c31f26..8cd77e8 100644
--- a/offapi/com/sun/star/style/NumberingType.idl
+++ b/offapi/com/sun/star/style/NumberingType.idl
@@ -500,6 +500,34 @@ published constants NumberingType
      */
     const short CHARS_PERSIAN_WORD = 55;
 
+    //-------------------------------------------------------------------------
+    /** Numbering in Persian Cardinal words
+
+        @since OOo 3.5
+     */
+    const short CHARS_PERSIAN_CARDINAL_WORD = 56;
+
+    //-------------------------------------------------------------------------
+    /** Numbering in English words
+
+        @since OOo 3.5
+     */
+    const short CHARS_ENGLISH_WORD = 57;
+
+    //-------------------------------------------------------------------------
+    /** Numbering in English Cardinal words
+
+        @since OOo 3.5
+     */
+    const short CHARS_ENGLISH_CARDINAL_WORD = 58;
+
+    //-------------------------------------------------------------------------
+    /** Numbering in English Cardinal semi-words
+
+        @since OOo 3.5
+     */
+    const short CHARS_ENGLISH_CARDINAL_SEMI_WORD = 59;
+
 };
 
 //=============================================================================
-- 
1.7.4.1


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.