1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 #include <defaultnumberingprovider.hxx>
31 #include <com/sun/star/style/NumberingType.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/text/HoriOrientation.hpp>
34 #include <localedata.hxx>
35 #include <nativenumbersupplier.hxx>
36 #include <stdio.h>
37 #include <string.h>
38 
39 // Cyrillic upper case
40 #define C_CYR_A "\xD0\x90"
41 #define C_CYR_B "\xD0\x91"
42 // Cyrillic lower case
43 #define S_CYR_A "\xD0\xB0"
44 #define S_CYR_B "\xD0\xB1"
45 
46 #include <math.h>
47 #include <rtl/ustring.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <com/sun/star/i18n/XTransliteration.hpp>
50 #include <com/sun/star/i18n/TransliterationType.hpp>
51 #include <com/sun/star/i18n/TransliterationModulesNew.hpp>
52 #include <com/sun/star/i18n/XLocaleData.hpp>
53 
54 #include <bullet.h>
55 
56 using namespace com::sun::star;
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::lang;
59 using namespace ::rtl;
60 
61 namespace com { namespace sun { namespace star { namespace i18n {
62 
63 static sal_Unicode table_Alphabet_ar[] = {
64 	0x0623, 0x0628, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E,
65 	0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635,
66 	0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x0642,
67 	0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649
68 };
69 
70 static sal_Unicode table_Alphabet_th[] = {
71 	0x0E01, 0x0E02, 0x0E04, 0x0E07,
72 	0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
73 	0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
74 	0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
75 	0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
76 	0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E
77 };
78 
79 static sal_Unicode table_Alphabet_he[] = {
80 	0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
81 	0x05D8, 0x05D9, 0x05DB, 0x05DC, 0x05DE, 0x05E0, 0x05E1, 0x05E2,
82 	0x05E4, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA
83 };
84 
85 static sal_Unicode table_Alphabet_ne[] = {
86     0x0915, 0x0916, 0x0917, 0x0918, 0x0919, 0x091A, 0x091B, 0x091C,
87     0x091D, 0x091E, 0x091F, 0x0920, 0x0921, 0x0922, 0x0923, 0x0924,
88     0x0925, 0x0926, 0x0927, 0x0928, 0x092A, 0x092B, 0x092C, 0x092D,
89     0x092E, 0x092F, 0x0930, 0x0932, 0x0935, 0x0936, 0x0937, 0x0938,
90     0x0939
91 };
92 
93 static sal_Unicode table_Alphabet_km[] = {
94 	0x1780, 0x1781, 0x1782, 0x1783, 0x1784, 0x1785, 0x1786, 0x1787,
95 	0x1788, 0x1789, 0x178A, 0x178B, 0x178C, 0x178D, 0x178E, 0x178F,
96 	0x1790, 0x1791, 0x1792, 0x1793, 0x1794, 0x1795, 0x1796, 0x1797,
97 	0x1798, 0x1799, 0x179A, 0x179B, 0x179C, 0x179F,
98 	0x17A0, 0x17A1, 0x17A2
99 };
100 
101 static sal_Unicode table_Alphabet_lo[] = {
102     0x0E81, 0x0E82, 0x0E84, 0x0E87, 0x0E88, 0x0E8A, 0x0E8D, 0x0E94,
103     0x0E95, 0x0E96, 0x0E97, 0x0E99, 0x0E9A, 0x0E9B, 0x0E9C,
104     0x0E9D, 0x0E9E, 0x0E9F, 0x0EA1, 0x0EA2, 0x0EA3, 0x0EA5, 0x0EA7,
105     0x0EAA, 0x0EAB, 0x0EAD, 0x0EAE, 0x0EAF, 0x0EAE, 0x0EDC, 0x0EDD
106 };
107 
108 static sal_Unicode table_Alphabet_dz[] = {
109     0x0F40, 0x0F41, 0x0F42, 0x0F44, 0x0F45, 0x0F46, 0x0F47, 0x0F49,
110     0x0F4F, 0x0F50, 0x0F51, 0x0F53, 0x0F54, 0x0F55, 0x0F56, 0x0F58,
111     0x0F59, 0x0F5A, 0x0F5B, 0x0F5D, 0x0F5E, 0x0F5F, 0x0F60, 0x0F61,
112     0x0F62, 0x0F63, 0x0F64, 0x0F66, 0x0F67, 0x0F68
113 };
114 
115 static sal_Unicode table_Alphabet_my[] = {
116     0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
117     0x1008,/*0x1009,*/0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
118     0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
119     0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
120     0x1020, 0x1021
121 };
122 
123 // Bulgarian Cyrillic upper case letters
124 static sal_Unicode table_CyrillicUpperLetter_bg[] = {
125     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418,
126     0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422,
127     0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042E,
128     0x042F
129 };
130 
131 // Bulgarian cyrillic lower case letters
132 static sal_Unicode table_CyrillicLowerLetter_bg[] = {
133     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438,
134     0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442,
135     0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044E,
136     0x044F
137 };
138 
139 // Russian Cyrillic upper letters
140 static sal_Unicode table_CyrillicUpperLetter_ru[] = {
141     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
142     0x0418, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420,
143     0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428,
144     0x0429, 0x042B, 0x042D, 0x042E, 0x042F
145 };
146 
147 // Russian cyrillic lower letters
148 static sal_Unicode table_CyrillicLowerLetter_ru[] = {
149     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
150     0x0438, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440,
151     0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448,
152     0x0449, 0x044B, 0x044D, 0x044E, 0x044F
153 };
154 
155 // Serbian Cyrillic upper letters
156 static sal_Unicode table_CyrillicUpperLetter_sr[] = {
157     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0402, 0x0415, 0x0416,
158     0x0417, 0x0418, 0x0408, 0x041A, 0x041B, 0x0409, 0x041C, 0x041D,
159     0x040A, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x040B, 0x0423,
160     0x0424, 0x0425, 0x0426, 0x0427, 0x040F, 0x0428
161 };
162 
163 // Serbian cyrillic lower letters
164 static sal_Unicode table_CyrillicLowerLetter_sr[] = {
165     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0452, 0x0435, 0x0436,
166     0x0437, 0x0438, 0x0458, 0x043A, 0x043B, 0x0459, 0x043C, 0x043D,
167     0x045A, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x045B, 0x0443,
168     0x0444, 0x0445, 0x0446, 0x0447, 0x045F, 0x0448
169 };
170 
171 static sal_Unicode table_Alphabet_fa[] = {
172     0x0622, 0x0628, 0x067E, 0x062A, 0x062B, 0x062C, 0x0686, 0x062D,
173     0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0698, 0x0633, 0x0634,
174     0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x0640, 0x0641, 0x0642,
175     0x06A9, 0x06AF, 0x0644, 0x0645, 0x0646, 0x0648, 0x0647, 0x06CC
176 };
177 
178 static sal_Unicode upperLetter[] = {
179     0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
180     0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
181     0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A
182 };
183 
184 static sal_Unicode lowerLetter[] = {
185     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
186     0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
187     0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
188 };
189 
190 DefaultNumberingProvider::DefaultNumberingProvider( const Reference < XMultiServiceFactory >& xMSF ) : xSMgr(xMSF),translit(NULL)
191 {
192 
193 }
194 
195 DefaultNumberingProvider::~DefaultNumberingProvider()
196 {
197         delete translit;
198 }
199 
200 void DefaultNumberingProvider::impl_loadTranslit()
201 {
202     if ( !translit )
203         translit = new TransliterationImpl(xSMgr);
204 }
205 
206 Sequence< Reference<container::XIndexAccess> >
207 DefaultNumberingProvider::getDefaultOutlineNumberings(const Locale& rLocale ) throw(RuntimeException)
208 {
209      return LocaleData().getOutlineNumberingLevels( rLocale );
210 }
211 
212 Sequence< Sequence<beans::PropertyValue> >
213 DefaultNumberingProvider::getDefaultContinuousNumberingLevels( const Locale& rLocale ) throw(RuntimeException)
214 {
215      return LocaleData().getContinuousNumberingLevels( rLocale );
216 }
217 
218 OUString toRoman( sal_Int32 n )
219 {
220 
221 //              i, ii, iii, iv, v, vi, vii, vii, viii, ix
222 //                                                      (Dummy),1000,500,100,50,10,5,1
223         static const sal_Char coRomanArr[] = "MDCLXVI--";       // +2 Dummy entries !!
224         const sal_Char* cRomanStr = coRomanArr;
225         sal_uInt16 nMask = 1000;
226         sal_uInt32 nOver1000 = n / nMask;
227         n -= ( nOver1000 * nMask );
228 
229         OUStringBuffer sTmp;
230     while(nOver1000--)
231         sTmp.append(sal_Unicode(*coRomanArr));
232 
233         while( nMask )
234         {
235                 sal_uInt8 nZahl = sal_uInt8( n / nMask );
236                 sal_uInt8 nDiff = 1;
237                 n %= nMask;
238 
239                 if( 5 < nZahl )
240                 {
241                         if( nZahl < 9 )
242                                 sTmp.append(sal_Unicode(*(cRomanStr-1)));
243                         ++nDiff;
244                         nZahl -= 5;
245                 }
246                 switch( nZahl )
247                 {
248                 case 3: sTmp.append(sal_Unicode(*cRomanStr));           //no break!
249                 case 2: sTmp.append(sal_Unicode(*cRomanStr));           //no break!
250                 case 1: sTmp.append(sal_Unicode(*cRomanStr));           break;
251                 case 4: sTmp.append(sal_Unicode(*cRomanStr)).append(sal_Unicode(*(cRomanStr-nDiff))); break;
252                 case 5: sTmp.append(sal_Unicode(*(cRomanStr-nDiff)));   break;
253                 }
254 
255                 nMask /= 10;                    // to the next decade
256                 cRomanStr += 2;
257         }
258         return sTmp.makeStringAndClear();
259 }
260 
261 // not used:
262 #if 0
263 
264 static
265 const char* expected_name( int i, int last )
266 {
267      if(0);
268      else if( i==0    ) return "Prefix";
269      else if( i==1    ) return "NumberingType";
270      else if( i==2    ) return "Suffix";
271      else if( i==last ) return "Value";
272      else { OSL_ASSERT(0); return ""; }
273 }
274 static
275 const char* expected_type( int i, int last )
276 {
277      if(0);
278      else if( i==0    ) return "OUString";
279      else if( i==1    ) return "sal_Int16";
280      else if( i==2    ) return "OUString";
281      else if( i==last ) return "sal_Int32";
282      else { OSL_ASSERT(0); return ""; }
283 }
284 static
285 void failedToConvert( int i, int last )
286 {
287      throw IllegalArgumentException();
288 }
289 
290 #endif
291 
292 static
293 void lcl_formatChars( sal_Unicode table[], int tableSize, int n, OUString& s )
294 {
295      // string representation of n is appended to s.
296      // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>AA, 27=>AB, ...
297      // if A=='a' then 0=>a, 1=>b, ..., 25=>z, 26=>aa, 27=>ab, ...
298 
299      if( n>=tableSize ) lcl_formatChars( table, tableSize, (n-tableSize)/tableSize, s );
300 
301      s += OUString::valueOf( table[ n % tableSize ] );
302 }
303 
304 static
305 void lcl_formatChars1( sal_Unicode table[], int tableSize, int n, OUString& s )
306 {
307      // string representation of n is appended to s.
308      // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>AA, 27=>BB, ...
309      // if A=='a' then 0=>a, 1=>b, ..., 25=>z, 26=>aa, 27=>bb, ...
310 
311      int repeat_count = n / tableSize + 1;
312 
313      for( int i=0; i<repeat_count; i++ )
314          s += OUString::valueOf( table[ n%tableSize ] );
315 }
316 
317 static
318 void lcl_formatChars2( sal_Unicode table_capital[], sal_Unicode table_small[], int tableSize, int n, OUString& s )
319 {
320      // string representation of n is appended to s.
321      // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>Aa, 27=>Ab, ...
322 
323      if( n>=tableSize )
324      {
325           lcl_formatChars2( table_capital, table_small, tableSize, (n-tableSize)/tableSize, s );
326           s += OUString::valueOf( table_small[ n % tableSize ] );
327      } else
328           s += OUString::valueOf( table_capital[ n % tableSize ] );
329 }
330 
331 static
332 void lcl_formatChars3( sal_Unicode table_capital[], sal_Unicode table_small[], int tableSize, int n, OUString& s )
333 {
334      // string representation of n is appended to s.
335      // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>Aa, 27=>Bb, ...
336 
337      int repeat_count = n / tableSize + 1;
338      s += OUString::valueOf( table_capital[ n%tableSize ] );
339 
340      for( int i=1; i<repeat_count; i++ )
341          s += OUString::valueOf( table_small[ n%tableSize ] );
342 }
343 
344 static
345 int should_ignore( OUString s )
346 {
347         // return true if blank or null
348         return s.compareToAscii(" ")==0 || (s.getLength()>0 && s[0]==0);
349 }
350 
351 static
352 Any getPropertyByName( const Sequence<beans::PropertyValue>& aProperties,
353                                                 const char* name, sal_Bool bRequired )
354 {
355         for( int i=0; i<aProperties.getLength(); i++ )
356                 if( aProperties[i].Name.equalsAscii(name) )
357                         return aProperties[i].Value;
358         if(bRequired)
359             throw IllegalArgumentException();
360         return Any();
361 }
362 
363 //XNumberingFormatter
364 OUString
365 DefaultNumberingProvider::makeNumberingString( const Sequence<beans::PropertyValue>& aProperties,
366                                                const Locale& aLocale )
367      throw( IllegalArgumentException, RuntimeException )
368 {
369      // the Sequence of PropertyValues is expected to have at least 4 elements:
370      // elt Name              Type             purpose
371      // -----------------------------------------------------------------
372      //
373      // 0.  "Prefix"          OUString
374      // 1.  "NumberingType"   sal_Int16        type of formatting from style::NumberingType (roman, arabic, etc)
375      // 2.  "Suffix"          OUString
376      // ... ...               ...
377      // n.  "Value"           sal_Int32        the number to be formatted
378      // example:
379      // given the Sequence { '(', NumberingType::ROMAN_UPPER, ')', ..., 7 }
380      // makeNumberingString() returns the string "(VII)".
381 
382      // Q: why is the type of numType sal_Int16 instead of style::NumberingType?
383      // A: an Any can't hold a style::NumberingType for some reason.
384         //      add.: style::NumberingType holds constants of type sal_Int16, it's not an enum type
385 
386      sal_Int16 natNum = 0;
387      sal_Int16 tableSize = 0;
388      sal_Unicode *table = NULL;     // initialize to avoid compiler warning
389      sal_Bool recycleSymbol = sal_False;
390      Locale locale;
391 
392      OUString  prefix;
393      sal_Int16        numType = -1; // type of formatting from style::NumberingType (roman, arabic, etc)
394      OUString  suffix;
395      sal_Int32        number = -12345; // the number that needs to be formatted.
396 
397 //     int nProperties = aProperties.getLength();
398 //     int last        = nProperties-1;
399 
400      try {
401         getPropertyByName(aProperties, "Prefix", sal_False)      >>=prefix;
402      } catch (Exception&) {
403         //prefix _must_ be empty here!
404      }
405      try {
406         getPropertyByName(aProperties, "Suffix", sal_False)      >>=suffix;
407      } catch (Exception&) {
408         //suffix _must_ be empty here!
409      }
410      try {
411         getPropertyByName(aProperties, "NumberingType", sal_True)   >>=numType;
412      } catch (Exception& ) {
413         numType = -1;
414      }
415      try {
416         getPropertyByName(aProperties, "Value", sal_True)       >>=number;
417      } catch (Exception& ) {
418         number = -1;
419      }
420 
421      if( number <= 0 )
422           throw IllegalArgumentException();
423 
424      // start empty
425      OUString result;
426 
427       // append prefix
428       if( !should_ignore(prefix) ) result += prefix;
429 
430       // append formatted number
431       using namespace style::NumberingType;
432       switch( numType )
433       {
434           case CHARS_UPPER_LETTER:
435                lcl_formatChars( upperLetter, 26, number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>AB, ...
436                break;
437           case CHARS_LOWER_LETTER:
438                lcl_formatChars( lowerLetter, 26, number-1, result );
439                break;
440           case ROMAN_UPPER:
441                result += toRoman( number );
442                break;
443           case ROMAN_LOWER:
444                result += toRoman( number ).toAsciiLowerCase();
445                break;
446           case ARABIC:
447                result += OUString::valueOf( number );
448                break;
449           case NUMBER_NONE:
450                return OUString::createFromAscii(""); // ignore prefix and suffix
451           case CHAR_SPECIAL:
452                // apparently, we're supposed to return an empty string in this case...
453                return OUString::createFromAscii(""); // ignore prefix and suffix
454           case PAGE_DESCRIPTOR:
455           case BITMAP:
456                OSL_ASSERT(0);
457                throw IllegalArgumentException();
458           case CHARS_UPPER_LETTER_N:
459                lcl_formatChars1( upperLetter, 26, number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>BB, ...
460                break;
461           case CHARS_LOWER_LETTER_N:
462                lcl_formatChars1( lowerLetter, 26,  number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>BB, ...
463                break;
464           case TRANSLITERATION:
465                try {
466                     const OUString &tmp = OUString::valueOf( number );
467                     OUString transliteration;
468                     getPropertyByName(aProperties, "Transliteration", sal_True) >>= transliteration;
469                     impl_loadTranslit();
470                     translit->loadModuleByImplName(transliteration, aLocale);
471                     result += translit->transliterateString2String(tmp, 0, tmp.getLength());
472                } catch (Exception& ) {
473                     // When translteration property is missing, return default number (bug #101141#)
474                     result += OUString::valueOf( number );
475                     // OSL_ASSERT(0);
476                     // throw IllegalArgumentException();
477                }
478                break;
479           case NATIVE_NUMBERING:
480                 natNum = NativeNumberMode::NATNUM1;
481                 locale = aLocale;
482                 break;
483           case FULLWIDTH_ARABIC:
484                 natNum = NativeNumberMode::NATNUM3;
485                 locale = aLocale;
486                 break;
487           case NUMBER_LOWER_ZH:
488                 natNum = NativeNumberMode::NATNUM7;
489                 locale.Language = OUString::createFromAscii("zh");
490                 break;
491           case NUMBER_UPPER_ZH_TW:
492                 locale.Country = OUString::createFromAscii("TW");
493           case NUMBER_UPPER_ZH:
494                 natNum = NativeNumberMode::NATNUM8;
495                 locale.Language = OUString::createFromAscii("zh");
496                 break;
497           case NUMBER_TRADITIONAL_JA:
498                 natNum = NativeNumberMode::NATNUM8;
499                 locale.Language = OUString::createFromAscii("ja");
500                 break;
501           case NUMBER_UPPER_KO:
502                 natNum = NativeNumberMode::NATNUM8;
503                 locale.Language = OUString::createFromAscii("ko");
504                 break;
505           case NUMBER_HANGUL_KO:
506                 natNum = NativeNumberMode::NATNUM11;
507                 locale.Language = OUString::createFromAscii("ko");
508                 break;
509 
510           case CIRCLE_NUMBER:
511               table = table_CircledNumber;
512               tableSize = sizeof(table_CircledNumber) / sizeof(sal_Unicode);
513               break;
514           case TIAN_GAN_ZH:
515               table = table_TianGan_zh;
516               tableSize = sizeof(table_TianGan_zh) / sizeof(sal_Unicode);
517               break;
518           case DI_ZI_ZH:
519               table = table_DiZi_zh;
520               tableSize = sizeof(table_DiZi_zh) / sizeof(sal_Unicode);
521               break;
522           case AIU_FULLWIDTH_JA:
523               table = table_AIUFullWidth_ja_JP;
524               tableSize = sizeof(table_AIUFullWidth_ja_JP) / sizeof(sal_Unicode);
525               recycleSymbol = sal_True;
526               break;
527           case AIU_HALFWIDTH_JA:
528               table = table_AIUHalfWidth_ja_JP;
529               tableSize = sizeof(table_AIUHalfWidth_ja_JP) / sizeof(sal_Unicode);
530               recycleSymbol = sal_True;
531               break;
532           case IROHA_FULLWIDTH_JA:
533               table = table_IROHAFullWidth_ja_JP;
534               tableSize = sizeof(table_IROHAFullWidth_ja_JP) / sizeof(sal_Unicode);
535               recycleSymbol = sal_True;
536               break;
537           case IROHA_HALFWIDTH_JA:
538               table = table_IROHAHalfWidth_ja_JP;
539               tableSize = sizeof(table_IROHAHalfWidth_ja_JP) / sizeof(sal_Unicode);
540               recycleSymbol = sal_True;
541               break;
542           case HANGUL_JAMO_KO:
543               table = table_HangulJamo_ko;
544               tableSize = sizeof(table_HangulJamo_ko) / sizeof(sal_Unicode);
545               recycleSymbol = sal_True;
546               break;
547           case HANGUL_SYLLABLE_KO:
548               table = table_HangulSyllable_ko;
549               tableSize = sizeof(table_HangulSyllable_ko) / sizeof(sal_Unicode);
550               recycleSymbol = sal_True;
551               break;
552           case HANGUL_CIRCLED_JAMO_KO:
553               table = table_HangulCircledJamo_ko;
554               tableSize = sizeof(table_HangulCircledJamo_ko) / sizeof(sal_Unicode);
555               recycleSymbol = sal_True;
556               break;
557           case HANGUL_CIRCLED_SYLLABLE_KO:
558               table = table_HangulCircledSyllable_ko;
559               tableSize = sizeof(table_HangulCircledSyllable_ko) / sizeof(sal_Unicode);
560               recycleSymbol = sal_True;
561               break;
562           case CHARS_ARABIC:
563               lcl_formatChars(table_Alphabet_ar, sizeof(table_Alphabet_ar) / sizeof(sal_Unicode), number - 1, result);
564               break;
565           case CHARS_THAI:
566               lcl_formatChars(table_Alphabet_th, sizeof(table_Alphabet_th) / sizeof(sal_Unicode), number - 1, result);
567               break;
568           case CHARS_HEBREW:
569               lcl_formatChars(table_Alphabet_he, sizeof(table_Alphabet_he) / sizeof(sal_Unicode), number - 1, result);
570               break;
571           case CHARS_NEPALI:
572               lcl_formatChars(table_Alphabet_ne, sizeof(table_Alphabet_ne) / sizeof(sal_Unicode), number - 1, result);
573               break;
574           case CHARS_KHMER:
575               lcl_formatChars(table_Alphabet_km, sizeof(table_Alphabet_km) / sizeof(sal_Unicode), number - 1, result);
576               break;
577           case CHARS_LAO:
578               lcl_formatChars(table_Alphabet_lo, sizeof(table_Alphabet_lo) / sizeof(sal_Unicode), number - 1, result);
579               break;
580           case CHARS_MYANMAR:
581               lcl_formatChars(table_Alphabet_my, sizeof(table_Alphabet_my) / sizeof(sal_Unicode), number - 1, result);
582               break;
583          case CHARS_TIBETAN:
584               lcl_formatChars(table_Alphabet_dz, sizeof(table_Alphabet_dz) / sizeof(sal_Unicode), number - 1, result);
585               break;
586          case CHARS_CYRILLIC_UPPER_LETTER_BG:
587               lcl_formatChars2( table_CyrillicUpperLetter_bg,
588                       table_CyrillicLowerLetter_bg,
589                       sizeof(table_CyrillicLowerLetter_bg) /
590                       sizeof(table_CyrillicLowerLetter_bg[0]), number-1,
591                       result); // 1=>a, 2=>b, ..., 28=>z, 29=>Aa, 30=>Ab, ...
592               break;
593          case CHARS_CYRILLIC_LOWER_LETTER_BG:
594               lcl_formatChars( table_CyrillicLowerLetter_bg,
595                       sizeof(table_CyrillicLowerLetter_bg) /
596                       sizeof(table_CyrillicLowerLetter_bg[0]), number-1,
597                       result); // 1=>a, 2=>b, ..., 28=>z, 29=>aa, 30=>ab, ...
598               break;
599          case CHARS_CYRILLIC_UPPER_LETTER_N_BG:
600               lcl_formatChars3( table_CyrillicUpperLetter_bg,
601                       table_CyrillicLowerLetter_bg,
602                       sizeof(table_CyrillicLowerLetter_bg) /
603                       sizeof(table_CyrillicLowerLetter_bg[0]), number-1,
604                       result); // 1=>a, 2=>b, ..., 28=>z, 29=>Aa, 30=>Bb, ...
605               break;
606          case CHARS_CYRILLIC_LOWER_LETTER_N_BG:
607               lcl_formatChars1( table_CyrillicLowerLetter_bg,
608                       sizeof(table_CyrillicLowerLetter_bg) /
609                       sizeof(table_CyrillicLowerLetter_bg[0]), number-1,
610                       result); // 1=>a, 2=>b, ..., 28=>z, 29=>aa, 30=>bb, ...
611               break;
612          case CHARS_CYRILLIC_UPPER_LETTER_RU:
613               lcl_formatChars2( table_CyrillicUpperLetter_ru,
614                       table_CyrillicLowerLetter_ru,
615                       sizeof(table_CyrillicLowerLetter_ru) /
616                       sizeof(table_CyrillicLowerLetter_ru[0]), number-1,
617                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Ab, ...
618               break;
619          case CHARS_CYRILLIC_LOWER_LETTER_RU:
620               lcl_formatChars( table_CyrillicLowerLetter_ru,
621                       sizeof(table_CyrillicLowerLetter_ru) /
622                       sizeof(table_CyrillicLowerLetter_ru[0]), number-1,
623                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>ab, ...
624               break;
625          case CHARS_CYRILLIC_UPPER_LETTER_N_RU:
626               lcl_formatChars3( table_CyrillicUpperLetter_ru,
627                       table_CyrillicLowerLetter_ru,
628                       sizeof(table_CyrillicLowerLetter_ru) /
629                       sizeof(table_CyrillicLowerLetter_ru[0]), number-1,
630                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Bb, ...
631               break;
632          case CHARS_CYRILLIC_LOWER_LETTER_N_RU:
633               lcl_formatChars1( table_CyrillicLowerLetter_ru,
634                       sizeof(table_CyrillicLowerLetter_ru) /
635                       sizeof(table_CyrillicLowerLetter_ru[0]), number-1,
636                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>bb, ...
637               break;
638          case CHARS_CYRILLIC_UPPER_LETTER_SR:
639               lcl_formatChars2( table_CyrillicUpperLetter_sr,
640                       table_CyrillicLowerLetter_sr,
641                       sizeof(table_CyrillicLowerLetter_sr) /
642                       sizeof(table_CyrillicLowerLetter_sr[0]), number-1,
643                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Ab, ...
644               break;
645          case CHARS_CYRILLIC_LOWER_LETTER_SR:
646               lcl_formatChars( table_CyrillicLowerLetter_sr,
647                       sizeof(table_CyrillicLowerLetter_sr) /
648                       sizeof(table_CyrillicLowerLetter_sr[0]), number-1,
649                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>ab, ...
650               break;
651          case CHARS_CYRILLIC_UPPER_LETTER_N_SR:
652               lcl_formatChars3( table_CyrillicUpperLetter_sr,
653                       table_CyrillicLowerLetter_sr,
654                       sizeof(table_CyrillicLowerLetter_sr) /
655                       sizeof(table_CyrillicLowerLetter_sr[0]), number-1,
656                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Bb, ...
657               break;
658          case CHARS_CYRILLIC_LOWER_LETTER_N_SR:
659               lcl_formatChars1( table_CyrillicLowerLetter_sr,
660                       sizeof(table_CyrillicLowerLetter_sr) /
661                       sizeof(table_CyrillicLowerLetter_sr[0]), number-1,
662                       result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>bb, ...
663               break;
664           case CHARS_PERSIAN:
665               lcl_formatChars(table_Alphabet_fa, sizeof(table_Alphabet_fa) / sizeof(sal_Unicode), number - 1, result);
666               break;
667 
668           default:
669                OSL_ASSERT(0);
670                throw IllegalArgumentException();
671       }
672 
673         if (natNum) {
674             NativeNumberSupplier sNatNum;
675             result += sNatNum.getNativeNumberString(OUString::valueOf( number ), locale, natNum);
676         } else if (tableSize) {
677             if ( number > tableSize && !recycleSymbol)
678                 result += OUString::valueOf( number);
679             else
680                 result += OUString(&table[--number % tableSize], 1);
681         }
682 
683         // append suffix
684         if( !should_ignore(suffix) ) result += suffix;
685 
686         return result;
687 }
688 /* -----------------------------21.02.01 15:57--------------------------------
689 
690  ---------------------------------------------------------------------------*/
691 
692 #define LANG_ALL        (1 << 0)
693 #define LANG_CJK        (1 << 1)
694 #define LANG_CTL        (1 << 2)
695 
696 struct Supported_NumberingType
697 {
698         sal_Int16               nType;
699         const sal_Char* cSymbol;
700         sal_Int16               langOption;
701 };
702 static const Supported_NumberingType aSupportedTypes[] =
703 {
704         {style::NumberingType::CHARS_UPPER_LETTER,      "A", LANG_ALL},
705         {style::NumberingType::CHARS_LOWER_LETTER,      "a", LANG_ALL},
706         {style::NumberingType::ROMAN_UPPER,                     "I", LANG_ALL},
707         {style::NumberingType::ROMAN_LOWER,                     "i", LANG_ALL},
708         {style::NumberingType::ARABIC,                          "1", LANG_ALL},
709         {style::NumberingType::NUMBER_NONE,                     "''", LANG_ALL},
710         {style::NumberingType::CHAR_SPECIAL,                    "Bullet", LANG_ALL},
711         {style::NumberingType::PAGE_DESCRIPTOR,                 "Page", LANG_ALL},
712         {style::NumberingType::BITMAP,                          "Bitmap", LANG_ALL},
713         {style::NumberingType::CHARS_UPPER_LETTER_N,    "AAA", LANG_ALL},
714         {style::NumberingType::CHARS_LOWER_LETTER_N,    "aaa", LANG_ALL},
715         {style::NumberingType::NATIVE_NUMBERING,        "Native Numbering", LANG_CJK|LANG_CTL},
716         {style::NumberingType::FULLWIDTH_ARABIC,        NULL, LANG_CJK},
717         {style::NumberingType::CIRCLE_NUMBER,           NULL, LANG_CJK},
718         {style::NumberingType::NUMBER_LOWER_ZH,         NULL, LANG_CJK},
719         {style::NumberingType::NUMBER_UPPER_ZH,         NULL, LANG_CJK},
720         {style::NumberingType::NUMBER_UPPER_ZH_TW,      NULL, LANG_CJK},
721         {style::NumberingType::TIAN_GAN_ZH,             NULL, LANG_CJK},
722         {style::NumberingType::DI_ZI_ZH,                NULL, LANG_CJK},
723         {style::NumberingType::NUMBER_TRADITIONAL_JA,   NULL, LANG_CJK},
724         {style::NumberingType::AIU_FULLWIDTH_JA,        NULL, LANG_CJK},
725         {style::NumberingType::AIU_HALFWIDTH_JA,        NULL, LANG_CJK},
726         {style::NumberingType::IROHA_FULLWIDTH_JA,      NULL, LANG_CJK},
727         {style::NumberingType::IROHA_HALFWIDTH_JA,      NULL, LANG_CJK},
728         {style::NumberingType::NUMBER_UPPER_KO,         NULL, LANG_CJK},
729         {style::NumberingType::NUMBER_HANGUL_KO,        NULL, LANG_CJK},
730         {style::NumberingType::HANGUL_JAMO_KO,          NULL, LANG_CJK},
731         {style::NumberingType::HANGUL_SYLLABLE_KO,      NULL, LANG_CJK},
732         {style::NumberingType::HANGUL_CIRCLED_JAMO_KO,  NULL, LANG_CJK},
733         {style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO,      NULL, LANG_CJK},
734         {style::NumberingType::CHARS_ARABIC,    NULL, LANG_CTL},
735         {style::NumberingType::CHARS_THAI,      NULL, LANG_CTL},
736         {style::NumberingType::CHARS_HEBREW,    NULL, LANG_CTL},
737         {style::NumberingType::CHARS_NEPALI,    NULL, LANG_CTL},
738         {style::NumberingType::CHARS_KHMER,     NULL, LANG_CTL},
739         {style::NumberingType::CHARS_LAO,       NULL, LANG_CTL},
740         {style::NumberingType::CHARS_MYANMAR,   NULL, LANG_CTL},
741         {style::NumberingType::CHARS_TIBETAN,   NULL, LANG_CTL},
742         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_BG,   C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_A S_CYR_B ", ... (bg)", LANG_ALL},
743         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_BG,   S_CYR_A ", " S_CYR_B ", .., " S_CYR_A S_CYR_A ", " S_CYR_A S_CYR_B ", ... (bg)", LANG_ALL},
744         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_BG, C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_B S_CYR_B ", ... (bg)", LANG_ALL},
745         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_BG, S_CYR_A ", " S_CYR_B ", .., " S_CYR_A S_CYR_A ", " S_CYR_B S_CYR_B ", ... (bg)", LANG_ALL},
746         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU,   C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_A S_CYR_B ", ... (ru)", LANG_ALL},
747         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU,   S_CYR_A ", " S_CYR_B ", .., " S_CYR_A S_CYR_A ", " S_CYR_A S_CYR_B ", ... (ru)", LANG_ALL},
748         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_RU, C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_B S_CYR_B ", ... (ru)", LANG_ALL},
749         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_RU, S_CYR_A ", " S_CYR_B ", .., " S_CYR_A S_CYR_A ", " S_CYR_B S_CYR_B ", ... (ru)", LANG_ALL},
750         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_SR,   C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_A S_CYR_B ", ... (sr)", LANG_ALL},
751         {style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_SR,   S_CYR_A ", " S_CYR_B ", .., " S_CYR_A S_CYR_A ", " S_CYR_A S_CYR_B ", ... (sr)", LANG_ALL},
752         {style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_SR, C_CYR_A ", " C_CYR_B ", .., " C_CYR_A S_CYR_A ", " C_CYR_B S_CYR_B ", ... (sr)", LANG_ALL},
753         {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},
754         {style::NumberingType::CHARS_PERSIAN,   NULL, LANG_CTL},
755 };
756 static const sal_Int32 nSupported_NumberingTypes = sizeof(aSupportedTypes) / sizeof(Supported_NumberingType);
757 /* -----------------------------21.02.01 15:57--------------------------------
758 
759  ---------------------------------------------------------------------------*/
760 
761 OUString DefaultNumberingProvider::makeNumberingIdentifier(sal_Int16 index)
762                                 throw(RuntimeException)
763 {
764         if (aSupportedTypes[index].cSymbol)
765             return OUString(aSupportedTypes[index].cSymbol, strlen(aSupportedTypes[index].cSymbol), RTL_TEXTENCODING_UTF8);
766 //            return OUString::createFromAscii(aSupportedTypes[index].cSymbol);
767         else {
768             OUString result;
769             Locale aLocale(OUString::createFromAscii("en"), OUString(), OUString());
770             Sequence<beans::PropertyValue> aProperties(2);
771             aProperties[0].Name = OUString::createFromAscii("NumberingType");
772             aProperties[0].Value <<= aSupportedTypes[index].nType;
773             aProperties[1].Name = OUString::createFromAscii("Value");
774             for (sal_Int32 j = 1; j <= 3; j++) {
775                 aProperties[1].Value <<= j;
776                 result += makeNumberingString( aProperties, aLocale );
777                 result += OUString::createFromAscii(", ");
778             }
779             result += OUString::createFromAscii("...");
780             return result;
781         }
782 }
783 
784 sal_Bool SAL_CALL
785 DefaultNumberingProvider::isScriptFlagEnabled(const OUString& aName) throw(RuntimeException)
786 {
787     if (! xHierarchicalNameAccess.is()) {
788         Reference< XInterface > xInterface;
789 
790         xInterface = xSMgr->createInstance(OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider"));
791         Reference< XMultiServiceFactory > xConfigProvider =
792                 Reference< XMultiServiceFactory >(xInterface, UNO_QUERY );
793 
794         if (! xConfigProvider.is())
795             throw RuntimeException();
796 
797         Sequence< Any > aArgs(1);
798         beans::PropertyValue aPath;
799         aPath.Name = OUString::createFromAscii("nodepath");
800         aPath.Value <<= OUString::createFromAscii("/org.openoffice.Office.Common/I18N"),
801         aArgs[0] <<= aPath;
802 
803         xInterface = xConfigProvider->createInstanceWithArguments(
804             OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), aArgs);
805 
806         xHierarchicalNameAccess.set(xInterface, UNO_QUERY);
807 
808         if (! xHierarchicalNameAccess.is())
809             throw RuntimeException();
810     }
811 
812     Any aEnabled = xHierarchicalNameAccess->getByHierarchicalName(aName);
813 
814     sal_Bool enabled = sal_False;
815 
816     aEnabled >>= enabled;
817 
818     return enabled;
819 }
820 
821 Sequence< sal_Int16 > DefaultNumberingProvider::getSupportedNumberingTypes(  )
822                                 throw(RuntimeException)
823 {
824         Sequence< sal_Int16 > aRet(nSupported_NumberingTypes );
825         sal_Int16* pArray = aRet.getArray();
826 
827         sal_Bool cjkEnabled = isScriptFlagEnabled(OUString::createFromAscii("CJK/CJKFont"));
828         sal_Bool ctlEnabled = isScriptFlagEnabled(OUString::createFromAscii("CTL/CTLFont"));
829 
830         for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++) {
831             if ( (aSupportedTypes[i].langOption & LANG_ALL) ||
832                     ((aSupportedTypes[i].langOption & LANG_CJK) && cjkEnabled) ||
833                     ((aSupportedTypes[i].langOption & LANG_CTL) && ctlEnabled) )
834                 pArray[i] = aSupportedTypes[i].nType;
835         }
836         return aRet;
837 }
838 /* -----------------------------21.02.01 15:57--------------------------------
839 
840  ---------------------------------------------------------------------------*/
841 sal_Int16 DefaultNumberingProvider::getNumberingType( const OUString& rNumberingIdentifier )
842                                 throw(RuntimeException)
843 {
844         for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
845                 if(rNumberingIdentifier.equals(makeNumberingIdentifier(i)))
846                         return aSupportedTypes[i].nType;
847         throw RuntimeException();
848 }
849 /* -----------------------------21.02.01 15:57--------------------------------
850 
851  ---------------------------------------------------------------------------*/
852 sal_Bool DefaultNumberingProvider::hasNumberingType( const OUString& rNumberingIdentifier )
853                                 throw(RuntimeException)
854 {
855         for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
856                 if(rNumberingIdentifier.equals(makeNumberingIdentifier(i)))
857                         return sal_True;
858         return sal_False;
859 }
860 /* -----------------------------21.02.01 15:57--------------------------------
861 
862  ---------------------------------------------------------------------------*/
863 OUString DefaultNumberingProvider::getNumberingIdentifier( sal_Int16 nNumberingType )
864                                 throw(RuntimeException)
865 {
866         for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
867             if(nNumberingType == aSupportedTypes[i].nType)
868                 return makeNumberingIdentifier(i);
869         return OUString();
870 }
871 /* -----------------------------05.07.01 13:34--------------------------------
872 
873  ---------------------------------------------------------------------------*/
874 const sal_Char cDefaultNumberingProvider[] = "com.sun.star.text.DefaultNumberingProvider";
875 OUString DefaultNumberingProvider::getImplementationName(void)
876                 throw( RuntimeException )
877 {
878     return OUString::createFromAscii(cDefaultNumberingProvider);
879 }
880 /* -----------------------------05.07.01 13:34--------------------------------
881 
882  ---------------------------------------------------------------------------*/
883 sal_Bool DefaultNumberingProvider::supportsService(const rtl::OUString& rServiceName)
884                 throw( RuntimeException )
885 {
886     return rServiceName.equalsAscii(cDefaultNumberingProvider);
887 }
888 /* -----------------------------05.07.01 13:34--------------------------------
889 
890  ---------------------------------------------------------------------------*/
891 Sequence< OUString > DefaultNumberingProvider::getSupportedServiceNames(void)
892                 throw( RuntimeException )
893 {
894     Sequence< OUString > aRet(1);
895     aRet[0] = OUString::createFromAscii(cDefaultNumberingProvider);
896     return aRet;
897 }
898 
899 } } } }
900