Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / i18npool / source / defaultnumberingprovider / defaultnumberingprovider.cxx
blob99cf26fe60cbc7111b5f3d0b2f992ad8792b0160
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <defaultnumberingprovider.hxx>
21 #include <com/sun/star/lang/IllegalArgumentException.hpp>
22 #include <com/sun/star/style/NumberingType.hpp>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/configuration/theDefaultProvider.hpp>
25 #include <com/sun/star/text/HoriOrientation.hpp>
26 #include <osl/diagnose.h>
27 #include <rtl/ref.hxx>
28 #include <localedata.hxx>
29 #include <nativenumbersupplier.hxx>
30 #include <stdio.h>
31 #include <string.h>
32 #include <comphelper/propertysequence.hxx>
33 #include <cppuhelper/supportsservice.hxx>
35 // Cyrillic upper case
36 #define C_CYR_A "\xD0\x90"
37 #define C_CYR_B "\xD0\x91"
38 // Cyrillic lower case
39 #define S_CYR_A "\xD0\xB0"
40 #define S_CYR_B "\xD0\xB1"
42 //Greek upper case
43 #define C_GR_A "\xCE\x91"
44 #define C_GR_B "\xCE\x92"
45 //Greek lower case
46 #define S_GR_A "\xCE\xB1"
47 #define S_GR_B "\xCE\xB2"
49 //Hebrew
50 #define S_HE_ALEPH "\xD7\x90"
51 #define S_HE_YOD "\xD7\x99"
52 #define S_HE_QOF "\xD7\xA7"
54 //Arabic-Indic
55 #define S_AR_ONE "\xd9\xa1"
56 #define S_AR_TWO "\xd9\xa2"
57 #define S_AR_THREE "\xd9\xa3"
59 // East Arabic-Indic
60 #define S_FA_ONE "\xDB\xB1"
61 #define S_FA_TWO "\xDB\xB2"
62 #define S_FA_THREE "\xDB\xB3"
64 // Indic Devanagari
65 #define S_HI_ONE "\xDB\xB1"
66 #define S_HI_TWO "\xDB\xB2"
67 #define S_HI_THREE "\xDB\xB3"
69 #include <math.h>
70 #include <sal/macros.h>
71 #include <rtl/ustring.hxx>
72 #include <rtl/ustrbuf.hxx>
73 #include <com/sun/star/i18n/XTransliteration.hpp>
74 #include <com/sun/star/i18n/TransliterationType.hpp>
75 #include <com/sun/star/i18n/XLocaleData.hpp>
77 #include <bullet.h>
79 using namespace com::sun::star;
80 using namespace com::sun::star::uno;
81 using namespace ::com::sun::star::i18n;
82 using namespace com::sun::star::lang;
84 namespace i18npool {
86 static const sal_Unicode table_Alphabet_ar[] = {
87 0x0623, 0x0628, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E,
88 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635,
89 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x0642,
90 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649
93 static const sal_Unicode table_Alphabet_ar_abjad[] = {
94 0x0627, 0x0628, 0x062c, 0x062f, 0x0647, 0x0648, 0x0632, 0x062d,
95 0x0637, 0x064a, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639,
96 0x0641, 0x0635, 0x0642, 0x0631, 0x0634, 0x062a, 0x062b, 0x062e,
97 0x0630, 0x0636, 0x0638, 0x063a
100 static const sal_Unicode table_Alphabet_th[] = {
101 0x0E01, 0x0E02, 0x0E04, 0x0E07,
102 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
103 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
104 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
105 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
106 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E
109 static const sal_Unicode table_Alphabet_he[] = {
110 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
111 0x05D8, 0x05D9, 0x05DB, 0x05DC, 0x05DE, 0x05E0, 0x05E1, 0x05E2,
112 0x05E4, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA
115 static const sal_Unicode table_Alphabet_ne[] = {
116 0x0915, 0x0916, 0x0917, 0x0918, 0x0919, 0x091A, 0x091B, 0x091C,
117 0x091D, 0x091E, 0x091F, 0x0920, 0x0921, 0x0922, 0x0923, 0x0924,
118 0x0925, 0x0926, 0x0927, 0x0928, 0x092A, 0x092B, 0x092C, 0x092D,
119 0x092E, 0x092F, 0x0930, 0x0932, 0x0935, 0x0936, 0x0937, 0x0938,
120 0x0939
123 static const sal_Unicode table_Alphabet_km[] = {
124 0x1780, 0x1781, 0x1782, 0x1783, 0x1784, 0x1785, 0x1786, 0x1787,
125 0x1788, 0x1789, 0x178A, 0x178B, 0x178C, 0x178D, 0x178E, 0x178F,
126 0x1790, 0x1791, 0x1792, 0x1793, 0x1794, 0x1795, 0x1796, 0x1797,
127 0x1798, 0x1799, 0x179A, 0x179B, 0x179C, 0x179F,
128 0x17A0, 0x17A1, 0x17A2
131 static const sal_Unicode table_Alphabet_lo[] = {
132 0x0E81, 0x0E82, 0x0E84, 0x0E87, 0x0E88, 0x0E8A, 0x0E8D, 0x0E94,
133 0x0E95, 0x0E96, 0x0E97, 0x0E99, 0x0E9A, 0x0E9B, 0x0E9C,
134 0x0E9D, 0x0E9E, 0x0E9F, 0x0EA1, 0x0EA2, 0x0EA3, 0x0EA5, 0x0EA7,
135 0x0EAA, 0x0EAB, 0x0EAD, 0x0EAE, 0x0EAF, 0x0EAE, 0x0EDC, 0x0EDD
138 static const sal_Unicode table_Alphabet_dz[] = {
139 0x0F40, 0x0F41, 0x0F42, 0x0F44, 0x0F45, 0x0F46, 0x0F47, 0x0F49,
140 0x0F4F, 0x0F50, 0x0F51, 0x0F53, 0x0F54, 0x0F55, 0x0F56, 0x0F58,
141 0x0F59, 0x0F5A, 0x0F5B, 0x0F5D, 0x0F5E, 0x0F5F, 0x0F60, 0x0F61,
142 0x0F62, 0x0F63, 0x0F64, 0x0F66, 0x0F67, 0x0F68
145 static const sal_Unicode table_Alphabet_my[] = {
146 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
147 0x1008,/*0x1009,*/0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
148 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
149 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
150 0x1020, 0x1021
153 // Bulgarian Cyrillic upper case letters
154 static const sal_Unicode table_CyrillicUpperLetter_bg[] = {
155 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418,
156 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422,
157 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042E,
158 0x042F
161 // Bulgarian cyrillic lower case letters
162 static const sal_Unicode table_CyrillicLowerLetter_bg[] = {
163 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438,
164 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442,
165 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044E,
166 0x044F
169 // Russian Cyrillic upper letters
170 static const sal_Unicode table_CyrillicUpperLetter_ru[] = {
171 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
172 0x0418, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420,
173 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428,
174 0x0429, 0x042B, 0x042D, 0x042E, 0x042F
177 // Russian cyrillic lower letters
178 static const sal_Unicode table_CyrillicLowerLetter_ru[] = {
179 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
180 0x0438, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440,
181 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448,
182 0x0449, 0x044B, 0x044D, 0x044E, 0x044F
185 // Serbian Cyrillic upper letters
186 static const sal_Unicode table_CyrillicUpperLetter_sr[] = {
187 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0402, 0x0415, 0x0416,
188 0x0417, 0x0418, 0x0408, 0x041A, 0x041B, 0x0409, 0x041C, 0x041D,
189 0x040A, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x040B, 0x0423,
190 0x0424, 0x0425, 0x0426, 0x0427, 0x040F, 0x0428
193 // Serbian cyrillic lower letters
194 static const sal_Unicode table_CyrillicLowerLetter_sr[] = {
195 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0452, 0x0435, 0x0436,
196 0x0437, 0x0438, 0x0458, 0x043A, 0x043B, 0x0459, 0x043C, 0x043D,
197 0x045A, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x045B, 0x0443,
198 0x0444, 0x0445, 0x0446, 0x0447, 0x045F, 0x0448
201 static const sal_Unicode table_GreekUpperLetter[] = {
202 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x03DB, 0x0396, 0x0397, 0x0398,
203 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03DF,
204 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03E0
207 static const sal_Unicode table_GreekLowerLetter[] = {
208 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03DB, 0x03B6, 0x03B7, 0x03B8,
209 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03DF,
210 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03E1
213 static const sal_Unicode table_Alphabet_fa[] = {
214 0x0622, 0x0628, 0x067E, 0x062A, 0x062B, 0x062C, 0x0686, 0x062D,
215 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0698, 0x0633, 0x0634,
216 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x0640, 0x0641, 0x0642,
217 0x06A9, 0x06AF, 0x0644, 0x0645, 0x0646, 0x0648, 0x0647, 0x06CC
220 static const sal_Unicode upperLetter[] = {
221 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
222 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
223 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A
226 static const sal_Unicode lowerLetter[] = {
227 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
228 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
229 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
232 // Tables used for numbering in persian words
233 static const sal_Unicode table_PersianWord_decade1[][7]={
234 {0}, // 0
235 {0x06cc, 0x06a9, 0}, // 1
236 {0x062f, 0x0648, 0}, // 2
237 {0x0633, 0x0647, 0}, // 3
238 {0x0686, 0x0647, 0x0627, 0x0631, 0}, // 4
239 {0x067e, 0x0646, 0x062c, 0}, // 5
240 {0x0634, 0x0634, 0}, // 6
241 {0x0647, 0x0641, 0x062a, 0}, // 7
242 {0x0647, 0x0634, 0x062a, 0}, // 8
243 {0x0646, 0x0647, 0}, // 9
244 {0x062f, 0x0647, 0}, // 10
245 {0x06cc, 0x0627, 0x0632, 0x062f, 0x0647, 0}, // 11
246 {0x062f, 0x0648, 0x0627, 0x0632, 0x062f, 0x0647, 0}, // 12
247 {0x0633, 0x06cc, 0x0632, 0x062f, 0x0647, 0}, // 13
248 {0x0686, 0x0647, 0x0627, 0x0631, 0x062f, 0x0647, 0}, // 14
249 {0x067e, 0x0627, 0x0646, 0x0632, 0x062f, 0x0647, 0}, // 15
250 {0x0634, 0x0627, 0x0646, 0x0632, 0x062f, 0x0647, 0}, // 16
251 {0x0647, 0x0641, 0x062f, 0x0647, 0}, // 17
252 {0x0647, 0x062c, 0x062f, 0x0647, 0}, // 18
253 {0x0646, 0x0648, 0x0632, 0x062f, 0x0647, 0} // 19
256 static const sal_Unicode table_PersianWord_decade2[][6]={
257 {0x0628, 0x06cc, 0x0633, 0x062a, 0}, // 20
258 {0x0633, 0x06cc, 0}, // 30
259 {0x0686, 0x0647, 0x0644, 0}, // 40
260 {0x067e, 0x0646, 0x062c, 0x0627, 0x0647, 0}, // 50
261 {0x0634, 0x0635, 0x062a, 0}, // 60
262 {0x0647, 0x0641, 0x062a, 0x0627, 0x062f, 0}, // 70
263 {0x0647, 0x0634, 0x062a, 0x0627, 0x062f, 0}, // 80
264 {0x0646, 0x0648, 0x062f, 0} // 90
267 static const sal_Unicode table_PersianWord_decade3[][7]={
268 {0x0635, 0x062f, 0}, // 100
269 {0x062f, 0x0648, 0x06cc, 0x0633, 0x062a, 0}, // 200
270 {0x0633, 0x06cc, 0x0635, 0x062f, 0}, // 300
271 {0x0686, 0x0647, 0x0627, 0x0631, 0x0635, 0x062f, 0}, // 400
272 {0x067e, 0x0627, 0x0646, 0x0635, 0x062f, 0}, // 500
273 {0x0634, 0x0635, 0x062f, 0}, // 600
274 {0x0647, 0x0641, 0x062a, 0x0635, 0x062f, 0}, // 700
275 {0x0647, 0x0634, 0x062a, 0x0635, 0x062f, 0}, // 800
276 {0x0646, 0x0647, 0x0635, 0x062f, 0} // 900
279 static const sal_Unicode table_PersianWord_decadeX[][8]={
280 {0x0647, 0x0632, 0x0627, 0x0631, 0}, // 1000
281 {0x0645, 0x06cc, 0x0644, 0x06cc, 0x0648, 0x0646, 0}, // 1000000
282 {0x0645, 0x06cc, 0x0644, 0x06cc, 0x0627, 0x0631, 0x062f, 0} // 1000000000
286 DefaultNumberingProvider::DefaultNumberingProvider( const Reference < XComponentContext >& rxContext ) : m_xContext(rxContext),translit(nullptr)
291 DefaultNumberingProvider::~DefaultNumberingProvider()
295 Sequence< Reference<container::XIndexAccess> >
296 DefaultNumberingProvider::getDefaultOutlineNumberings(const Locale& rLocale )
298 return LocaleDataImpl::get()->getOutlineNumberingLevels( rLocale );
301 Sequence< Sequence<beans::PropertyValue> >
302 DefaultNumberingProvider::getDefaultContinuousNumberingLevels( const Locale& rLocale )
304 return LocaleDataImpl::get()->getContinuousNumberingLevels( rLocale );
307 OUString toRoman( sal_Int32 n )
310 // i, ii, iii, iv, v, vi, vii, vii, viii, ix
311 // (Dummy),1000,500,100,50,10,5,1
312 static const sal_Char coRomanArr[] = "MDCLXVI--"; // +2 Dummy entries !!
313 const sal_Char* cRomanStr = coRomanArr;
314 sal_uInt16 nMask = 1000;
315 sal_uInt32 nOver1000 = n / nMask;
316 n -= ( nOver1000 * nMask );
318 OUStringBuffer sTmp;
319 while(nOver1000--)
320 sTmp.append(*coRomanArr);
322 while( nMask )
324 sal_uInt8 nNumber = sal_uInt8( n / nMask );
325 sal_uInt8 nDiff = 1;
326 n %= nMask;
328 if( 5 < nNumber )
330 if( nNumber < 9 )
331 sTmp.append(*(cRomanStr-1));
332 ++nDiff;
333 nNumber -= 5;
335 switch( nNumber )
337 case 3: sTmp.append(*cRomanStr); SAL_FALLTHROUGH;
338 case 2: sTmp.append(*cRomanStr); SAL_FALLTHROUGH;
339 case 1: sTmp.append(*cRomanStr); break;
340 case 4: sTmp.append(*cRomanStr).append(*(cRomanStr-nDiff)); break;
341 case 5: sTmp.append(*(cRomanStr-nDiff)); break;
344 nMask /= 10; // to the next decade
345 cRomanStr += 2;
347 return sTmp.makeStringAndClear();
350 // not used:
352 static
353 void lcl_formatChars( const sal_Unicode table[], int tableSize, int n, OUString& s )
355 // string representation of n is appended to s.
356 // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>AA, 27=>AB, ...
357 // if A=='a' then 0=>a, 1=>b, ..., 25=>z, 26=>aa, 27=>ab, ...
359 if( n>=tableSize ) lcl_formatChars( table, tableSize, (n-tableSize)/tableSize, s );
361 s += OUStringLiteral1( table[ n % tableSize ] );
364 static
365 void lcl_formatChars1( const sal_Unicode table[], int tableSize, int n, OUString& s )
367 // string representation of n is appended to s.
368 // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>AA, 27=>BB, ...
369 // if A=='a' then 0=>a, 1=>b, ..., 25=>z, 26=>aa, 27=>bb, ...
371 int repeat_count = n / tableSize + 1;
373 for( int i=0; i<repeat_count; i++ )
374 s += OUStringLiteral1( table[ n%tableSize ] );
377 static
378 void lcl_formatChars2( const sal_Unicode table_capital[], const sal_Unicode table_small[], int tableSize, int n, OUString& s )
380 // string representation of n is appended to s.
381 // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>Aa, 27=>Ab, ...
383 if( n>=tableSize )
385 lcl_formatChars2( table_capital, table_small, tableSize, (n-tableSize)/tableSize, s );
386 s += OUStringLiteral1( table_small[ n % tableSize ] );
387 } else
388 s += OUStringLiteral1( table_capital[ n % tableSize ] );
391 static
392 void lcl_formatChars3( const sal_Unicode table_capital[], const sal_Unicode table_small[], int tableSize, int n, OUString& s )
394 // string representation of n is appended to s.
395 // if A=='A' then 0=>A, 1=>B, ..., 25=>Z, 26=>Aa, 27=>Bb, ...
397 int repeat_count = n / tableSize + 1;
398 s += OUStringLiteral1( table_capital[ n%tableSize ] );
400 for( int i=1; i<repeat_count; i++ )
401 s += OUStringLiteral1( table_small[ n%tableSize ] );
405 /** Returns number's representation in persian words up to 999999999999
406 respectively limited by sal_Int32 >=0.
407 The caller assures that nNumber is not negative.
409 @throws IllegalArgumentException
410 @throws RuntimeException
412 static
413 void lcl_formatPersianWord( sal_Int32 nNumber, OUString& rsResult )
415 OUStringBuffer aTemp(64);
416 static const sal_Unicode asPersianWord_conjunction_data[] = {0x20,0x0648,0x20,0};
417 OUString asPersianWord_conjunction( asPersianWord_conjunction_data );
418 unsigned char nSection = 0;
420 while (int nPart = nNumber % 1000)
422 if (nSection)
424 if (nSection > SAL_N_ELEMENTS( table_PersianWord_decadeX))
425 throw IllegalArgumentException(); // does not happen with sal_Int32
426 aTemp.insert( 0, asPersianWord_conjunction).insert( 0, table_PersianWord_decadeX[nSection-1]);
429 unsigned int nDigit;
430 if ((nDigit = nPart % 100) < 20)
432 if (!aTemp.isEmpty())
433 aTemp.insert( 0, u' ');
434 aTemp.insert( 0, table_PersianWord_decade1[nDigit]);
436 else
438 if ((nDigit = nPart % 10) != 0)
440 if (!aTemp.isEmpty())
441 aTemp.insert( 0, asPersianWord_conjunction);
442 aTemp.insert( 0, table_PersianWord_decade1[nDigit]);
444 if ((nDigit = (nPart / 10) % 10) != 0)
446 if (!aTemp.isEmpty())
447 aTemp.insert( 0, asPersianWord_conjunction);
448 aTemp.insert( 0, table_PersianWord_decade2[nDigit-2]);
452 if ((nDigit = nPart / 100) != 0)
454 if (!aTemp.isEmpty())
455 aTemp.insert( 0, asPersianWord_conjunction);
456 aTemp.insert( 0, table_PersianWord_decade3[nDigit-1]);
459 nNumber /= 1000;
460 nSection++;
462 rsResult += aTemp.makeStringAndClear();
466 // Greek Letter Numbering
468 // KERAIA separates numerals from other text
469 #define STIGMA u'\x03DB'
470 #define LEFT_KERAIA u'\x0375'
471 #define MYRIAD_SYM u'\x039C'
472 #define DOT_SYM u'.'
473 #define SIGMA_OFFSET 19
474 #define TAU_OFFSET 20
475 #define MYRIAD 10000
478 * Return the 1-999999 number's representation in the Greek numbering system.
479 * Adding a "left keraia" to represent numbers in the range 10000 ... 999999 is
480 * not orthodox, so it's better to use the myriad notation and call this method
481 * only for numbers up to 9999.
483 static
484 OUString gr_smallNum(const sal_Unicode table[], int n)
486 if (n > 9999)
487 throw IllegalArgumentException();
489 int i = 0;
490 OUStringBuffer sb;
491 for (int v = n; v > 0; v /= 10, i++) {
492 int digit = v % 10;
493 if (digit == 0)
494 continue;
496 sal_Unicode sign = table[(digit - 1) + 9 * (i % 3)];
497 if (sign == STIGMA) {
498 sb.insert(0, table[TAU_OFFSET]);
499 sb.insert(0, table[SIGMA_OFFSET]);
500 } else {
501 sb.insert(0, sign);
504 if (i > 2)
505 sb.insert(0, LEFT_KERAIA);
508 return sb.makeStringAndClear();
511 static
512 void lcl_formatCharsGR(const sal_Unicode table[], int n, OUString& s )
514 OUStringBuffer sb;
515 int myriadPower = 2;
517 for (int divisor = MYRIAD * MYRIAD; divisor > 1; divisor /= MYRIAD, myriadPower--) {
518 if (n > divisor - 1) {
520 * Follow the Diophantus representation of:
521 * A myriad sign, M(10000) as many times as the power
522 * followed by the multiplier for the myriad
523 * followed by a dot
524 * followed by the rest
525 * This is enough for 32-bit integers
527 for (int i = 0; i < myriadPower; i++)
528 sb.append(MYRIAD_SYM);
530 sb.append(gr_smallNum(table, n/divisor));
531 n %= divisor;
533 if (n > 0)
534 sb.append(DOT_SYM);
537 sb.append(gr_smallNum(table,n));
539 s += sb.makeStringAndClear();
542 static
543 bool should_ignore( const OUString& s )
545 // return true if blank or null
546 return s == " " || (!s.isEmpty() && s[0]==0);
549 static
550 Any getPropertyByName( const Sequence<beans::PropertyValue>& aProperties,
551 const char* name, bool bRequired )
553 for( int i=0; i<aProperties.getLength(); i++ )
554 if( aProperties[i].Name.equalsAscii(name) )
555 return aProperties[i].Value;
556 if(bRequired)
557 throw IllegalArgumentException();
558 return Any();
561 //XNumberingFormatter
562 OUString
563 DefaultNumberingProvider::makeNumberingString( const Sequence<beans::PropertyValue>& aProperties,
564 const Locale& aLocale )
566 // the Sequence of PropertyValues is expected to have at least 4 elements:
567 // elt Name Type purpose
570 // 0. "Prefix" OUString
571 // 1. "NumberingType" sal_Int16 type of formatting from style::NumberingType (roman, arabic, etc)
572 // 2. "Suffix" OUString
573 // ... ... ...
574 // n. "Value" sal_Int32 the number to be formatted
575 // example:
576 // given the Sequence { '(', NumberingType::ROMAN_UPPER, ')', ..., 7 }
577 // makeNumberingString() returns the string "(VII)".
579 // Q: why is the type of numType sal_Int16 instead of style::NumberingType?
580 // A: an Any can't hold a style::NumberingType for some reason.
581 // add.: style::NumberingType holds constants of type sal_Int16, it's not an enum type
583 sal_Int16 natNum = 0;
584 sal_Int16 tableSize = 0;
585 const sal_Unicode *table = nullptr; // initialize to avoid compiler warning
586 bool bRecycleSymbol = false;
587 OUString sNatNumParams;
588 Locale locale;
590 OUString prefix;
591 sal_Int16 numType = -1; // type of formatting from style::NumberingType (roman, arabic, etc)
592 OUString suffix;
593 sal_Int32 number = -12345; // the number that needs to be formatted.
595 // int nProperties = aProperties.getLength();
596 // int last = nProperties-1;
598 try {
599 getPropertyByName(aProperties, "Prefix", false) >>=prefix;
600 } catch (Exception&) {
601 //prefix _must_ be empty here!
603 try {
604 getPropertyByName(aProperties, "Suffix", false) >>=suffix;
605 } catch (Exception&) {
606 //suffix _must_ be empty here!
608 try {
609 getPropertyByName(aProperties, "NumberingType", true) >>=numType;
610 } catch (Exception& ) {
611 numType = -1;
613 try {
614 getPropertyByName(aProperties, "Value", true) >>=number;
615 } catch (Exception& ) {
616 number = -1;
619 if( number <= 0 )
620 throw IllegalArgumentException();
622 // start empty
623 OUString result;
625 // append prefix
626 if( !should_ignore(prefix) ) result += prefix;
628 // append formatted number
629 using namespace style::NumberingType;
630 switch( numType )
632 case CHARS_UPPER_LETTER:
633 lcl_formatChars( upperLetter, 26, number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>AB, ...
634 break;
635 case CHARS_LOWER_LETTER:
636 lcl_formatChars( lowerLetter, 26, number-1, result );
637 break;
638 case TEXT_NUMBER: // ordinal indicators (1st, 2nd, 3rd, ...)
639 natNum = NativeNumberMode::NATNUM12;
640 sNatNumParams = "capitalize ordinal-number";
641 locale = aLocale;
642 break;
643 case TEXT_CARDINAL: // cardinal number names (One, Two, Three, ...)
644 natNum = NativeNumberMode::NATNUM12;
645 sNatNumParams = "capitalize";
646 locale = aLocale;
647 break;
648 case TEXT_ORDINAL: // ordinal number names (First, Second, Third, ...)
649 natNum = NativeNumberMode::NATNUM12;
650 sNatNumParams = "capitalize ordinal";
651 locale = aLocale;
652 break;
653 case ROMAN_UPPER:
654 result += toRoman( number );
655 break;
656 case ROMAN_LOWER:
657 result += toRoman( number ).toAsciiLowerCase();
658 break;
659 case ARABIC:
660 result += OUString::number( number );
661 break;
662 case NUMBER_NONE:
663 return OUString(); // ignore prefix and suffix
664 case CHAR_SPECIAL:
665 // apparently, we're supposed to return an empty string in this case...
666 return OUString(); // ignore prefix and suffix
667 case PAGE_DESCRIPTOR:
668 case BITMAP:
669 OSL_ASSERT(false);
670 throw IllegalArgumentException();
671 case CHARS_UPPER_LETTER_N:
672 lcl_formatChars1( upperLetter, 26, number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>BB, ...
673 break;
674 case CHARS_LOWER_LETTER_N:
675 lcl_formatChars1( lowerLetter, 26, number-1, result ); // 1=>A, 2=>B, ..., 26=>Z, 27=>AA, 28=>BB, ...
676 break;
677 case TRANSLITERATION:
678 try {
679 const OUString &tmp = OUString::number( number );
680 OUString transliteration;
681 getPropertyByName(aProperties, "Transliteration", true) >>= transliteration;
682 if ( !translit )
683 translit = new TransliterationImpl(m_xContext);
684 translit->loadModuleByImplName(transliteration, aLocale);
685 result += translit->transliterateString2String(tmp, 0, tmp.getLength());
686 } catch (Exception& ) {
687 // When transliteration property is missing, return default number (bug #101141#)
688 result += OUString::number( number );
689 // OSL_ASSERT(0);
690 // throw IllegalArgumentException();
692 break;
693 case NATIVE_NUMBERING:
694 natNum = NativeNumberMode::NATNUM1;
695 locale = aLocale;
696 break;
697 case FULLWIDTH_ARABIC:
698 natNum = NativeNumberMode::NATNUM3;
699 locale = aLocale;
700 break;
701 case NUMBER_LOWER_ZH:
702 natNum = NativeNumberMode::NATNUM7;
703 locale.Language = "zh";
704 break;
705 case NUMBER_UPPER_ZH:
706 natNum = NativeNumberMode::NATNUM8;
707 locale.Language = "zh";
708 break;
709 case NUMBER_UPPER_ZH_TW:
710 natNum = NativeNumberMode::NATNUM8;
711 locale.Language = "zh";
712 locale.Country = "TW";
713 break;
714 case NUMBER_TRADITIONAL_JA:
715 natNum = NativeNumberMode::NATNUM8;
716 locale.Language = "ja";
717 break;
718 case NUMBER_UPPER_KO:
719 natNum = NativeNumberMode::NATNUM8;
720 locale.Language = "ko";
721 break;
722 case NUMBER_HANGUL_KO:
723 natNum = NativeNumberMode::NATNUM11;
724 locale.Language = "ko";
725 break;
727 case CIRCLE_NUMBER:
728 table = table_CircledNumber;
729 tableSize = SAL_N_ELEMENTS(table_CircledNumber);
730 break;
731 case TIAN_GAN_ZH:
732 table = table_TianGan_zh;
733 tableSize = SAL_N_ELEMENTS(table_TianGan_zh);
734 break;
735 case DI_ZI_ZH:
736 table = table_DiZi_zh;
737 tableSize = SAL_N_ELEMENTS(table_DiZi_zh);
738 break;
739 case AIU_FULLWIDTH_JA:
740 table = table_AIUFullWidth_ja_JP;
741 tableSize = SAL_N_ELEMENTS(table_AIUFullWidth_ja_JP);
742 bRecycleSymbol = true;
743 break;
744 case AIU_HALFWIDTH_JA:
745 table = table_AIUHalfWidth_ja_JP;
746 tableSize = SAL_N_ELEMENTS(table_AIUHalfWidth_ja_JP);
747 bRecycleSymbol = true;
748 break;
749 case IROHA_FULLWIDTH_JA:
750 table = table_IROHAFullWidth_ja_JP;
751 tableSize = SAL_N_ELEMENTS(table_IROHAFullWidth_ja_JP);
752 bRecycleSymbol = true;
753 break;
754 case IROHA_HALFWIDTH_JA:
755 table = table_IROHAHalfWidth_ja_JP;
756 tableSize = SAL_N_ELEMENTS(table_IROHAHalfWidth_ja_JP);
757 bRecycleSymbol = true;
758 break;
759 case HANGUL_JAMO_KO:
760 table = table_HangulJamo_ko;
761 tableSize = SAL_N_ELEMENTS(table_HangulJamo_ko);
762 bRecycleSymbol = true;
763 break;
764 case HANGUL_SYLLABLE_KO:
765 table = table_HangulSyllable_ko;
766 tableSize = SAL_N_ELEMENTS(table_HangulSyllable_ko);
767 bRecycleSymbol = true;
768 break;
769 case HANGUL_CIRCLED_JAMO_KO:
770 table = table_HangulCircledJamo_ko;
771 tableSize = SAL_N_ELEMENTS(table_HangulCircledJamo_ko);
772 bRecycleSymbol = true;
773 break;
774 case HANGUL_CIRCLED_SYLLABLE_KO:
775 table = table_HangulCircledSyllable_ko;
776 tableSize = SAL_N_ELEMENTS(table_HangulCircledSyllable_ko);
777 bRecycleSymbol = true;
778 break;
779 case CHARS_ARABIC:
780 lcl_formatChars(table_Alphabet_ar, SAL_N_ELEMENTS(table_Alphabet_ar), number - 1, result);
781 break;
782 case CHARS_ARABIC_ABJAD:
783 lcl_formatChars(table_Alphabet_ar_abjad, SAL_N_ELEMENTS(table_Alphabet_ar_abjad), number - 1, result);
784 break;
785 case NUMBER_ARABIC_INDIC:
786 natNum = NativeNumberMode::NATNUM1;
787 locale.Language = "ar";
788 break;
789 case NUMBER_EAST_ARABIC_INDIC:
790 natNum = NativeNumberMode::NATNUM1;
791 locale.Language = "fa";
792 break;
793 case NUMBER_INDIC_DEVANAGARI:
794 natNum = NativeNumberMode::NATNUM1;
795 locale.Language = "hi";
796 break;
797 case CHARS_THAI:
798 lcl_formatChars(table_Alphabet_th, SAL_N_ELEMENTS(table_Alphabet_th), number - 1, result);
799 break;
800 case CHARS_HEBREW:
801 lcl_formatChars(table_Alphabet_he, SAL_N_ELEMENTS(table_Alphabet_he), number - 1, result);
802 break;
803 case NUMBER_HEBREW:
804 natNum = NativeNumberMode::NATNUM1;
805 locale.Language = "he";
806 break;
807 case CHARS_NEPALI:
808 lcl_formatChars(table_Alphabet_ne, SAL_N_ELEMENTS(table_Alphabet_ne), number - 1, result);
809 break;
810 case CHARS_KHMER:
811 lcl_formatChars(table_Alphabet_km, SAL_N_ELEMENTS(table_Alphabet_km), number - 1, result);
812 break;
813 case CHARS_LAO:
814 lcl_formatChars(table_Alphabet_lo, SAL_N_ELEMENTS(table_Alphabet_lo), number - 1, result);
815 break;
816 case CHARS_MYANMAR:
817 lcl_formatChars(table_Alphabet_my, SAL_N_ELEMENTS(table_Alphabet_my), number - 1, result);
818 break;
819 case CHARS_TIBETAN:
820 lcl_formatChars(table_Alphabet_dz, SAL_N_ELEMENTS(table_Alphabet_dz), number - 1, result);
821 break;
822 case CHARS_CYRILLIC_UPPER_LETTER_BG:
823 lcl_formatChars2( table_CyrillicUpperLetter_bg,
824 table_CyrillicLowerLetter_bg,
825 SAL_N_ELEMENTS(table_CyrillicLowerLetter_bg), number-1,
826 result); // 1=>a, 2=>b, ..., 28=>z, 29=>Aa, 30=>Ab, ...
827 break;
828 case CHARS_CYRILLIC_LOWER_LETTER_BG:
829 lcl_formatChars( table_CyrillicLowerLetter_bg,
830 SAL_N_ELEMENTS(table_CyrillicLowerLetter_bg), number-1,
831 result); // 1=>a, 2=>b, ..., 28=>z, 29=>aa, 30=>ab, ...
832 break;
833 case CHARS_CYRILLIC_UPPER_LETTER_N_BG:
834 lcl_formatChars3( table_CyrillicUpperLetter_bg,
835 table_CyrillicLowerLetter_bg,
836 SAL_N_ELEMENTS(table_CyrillicLowerLetter_bg), number-1,
837 result); // 1=>a, 2=>b, ..., 28=>z, 29=>Aa, 30=>Bb, ...
838 break;
839 case CHARS_CYRILLIC_LOWER_LETTER_N_BG:
840 lcl_formatChars1( table_CyrillicLowerLetter_bg,
841 SAL_N_ELEMENTS(table_CyrillicLowerLetter_bg), number-1,
842 result); // 1=>a, 2=>b, ..., 28=>z, 29=>aa, 30=>bb, ...
843 break;
844 case CHARS_CYRILLIC_UPPER_LETTER_RU:
845 lcl_formatChars2( table_CyrillicUpperLetter_ru,
846 table_CyrillicLowerLetter_ru,
847 SAL_N_ELEMENTS(table_CyrillicLowerLetter_ru), number-1,
848 result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Ab, ...
849 break;
850 case CHARS_CYRILLIC_LOWER_LETTER_RU:
851 lcl_formatChars( table_CyrillicLowerLetter_ru,
852 SAL_N_ELEMENTS(table_CyrillicLowerLetter_ru), number-1,
853 result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>ab, ...
854 break;
855 case CHARS_CYRILLIC_UPPER_LETTER_N_RU:
856 lcl_formatChars3( table_CyrillicUpperLetter_ru,
857 table_CyrillicLowerLetter_ru,
858 SAL_N_ELEMENTS(table_CyrillicLowerLetter_ru), number-1,
859 result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Bb, ...
860 break;
861 case CHARS_CYRILLIC_LOWER_LETTER_N_RU:
862 lcl_formatChars1( table_CyrillicLowerLetter_ru,
863 SAL_N_ELEMENTS(table_CyrillicLowerLetter_ru), number-1,
864 result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>bb, ...
865 break;
866 case CHARS_CYRILLIC_UPPER_LETTER_SR:
867 lcl_formatChars2( table_CyrillicUpperLetter_sr,
868 table_CyrillicLowerLetter_sr,
869 SAL_N_ELEMENTS(table_CyrillicLowerLetter_sr), number-1,
870 result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Ab, ...
871 break;
872 case CHARS_CYRILLIC_LOWER_LETTER_SR:
873 lcl_formatChars( table_CyrillicLowerLetter_sr,
874 SAL_N_ELEMENTS(table_CyrillicLowerLetter_sr), number-1,
875 result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>ab, ...
876 break;
877 case CHARS_CYRILLIC_UPPER_LETTER_N_SR:
878 lcl_formatChars3( table_CyrillicUpperLetter_sr,
879 table_CyrillicLowerLetter_sr,
880 SAL_N_ELEMENTS(table_CyrillicLowerLetter_sr), number-1,
881 result); // 1=>a, 2=>b, ..., 27=>z, 28=>Aa, 29=>Bb, ...
882 break;
883 case CHARS_CYRILLIC_LOWER_LETTER_N_SR:
884 lcl_formatChars1( table_CyrillicLowerLetter_sr,
885 SAL_N_ELEMENTS(table_CyrillicLowerLetter_sr), number-1,
886 result); // 1=>a, 2=>b, ..., 27=>z, 28=>aa, 29=>bb, ...
887 break;
889 case CHARS_GREEK_LOWER_LETTER:
890 lcl_formatCharsGR( table_GreekLowerLetter, number, result);
891 break;
893 case CHARS_GREEK_UPPER_LETTER:
894 lcl_formatCharsGR( table_GreekUpperLetter, number, result);
895 break;
897 case CHARS_PERSIAN:
898 lcl_formatChars(table_Alphabet_fa, SAL_N_ELEMENTS(table_Alphabet_fa), number - 1, result);
899 break;
901 case CHARS_PERSIAN_WORD:
902 lcl_formatPersianWord(number, result);
903 break;
905 default:
906 OSL_ASSERT(false);
907 throw IllegalArgumentException();
910 if (natNum) {
911 rtl::Reference<NativeNumberSupplierService> xNatNum(new NativeNumberSupplierService);
912 result += xNatNum->getNativeNumberStringParams(OUString::number(number), locale,
913 natNum, sNatNumParams);
914 } else if (tableSize) {
915 if ( number > tableSize && !bRecycleSymbol)
916 result += OUString::number( number);
917 else
918 result += OUString(&table[--number % tableSize], 1);
921 // append suffix
922 if( !should_ignore(suffix) ) result += suffix;
924 return result;
927 #define LANG_ALL (1 << 0)
928 #define LANG_CJK (1 << 1)
929 #define LANG_CTL (1 << 2)
931 struct Supported_NumberingType
933 sal_Int16 nType;
934 const sal_Char* cSymbol;
935 sal_Int16 langOption;
937 static const Supported_NumberingType aSupportedTypes[] =
939 {style::NumberingType::CHARS_UPPER_LETTER, "A", LANG_ALL},
940 {style::NumberingType::CHARS_LOWER_LETTER, "a", LANG_ALL},
941 {style::NumberingType::ROMAN_UPPER, "I", LANG_ALL},
942 {style::NumberingType::ROMAN_LOWER, "i", LANG_ALL},
943 {style::NumberingType::ARABIC, "1", LANG_ALL},
944 {style::NumberingType::NUMBER_NONE, "''", LANG_ALL},
945 {style::NumberingType::CHAR_SPECIAL, "Bullet", LANG_ALL},
946 {style::NumberingType::PAGE_DESCRIPTOR, "Page", LANG_ALL},
947 {style::NumberingType::BITMAP, "Bitmap", LANG_ALL},
948 {style::NumberingType::TEXT_NUMBER, "1st", LANG_ALL},
949 {style::NumberingType::TEXT_CARDINAL, "One", LANG_ALL},
950 {style::NumberingType::TEXT_ORDINAL, "First", LANG_ALL},
951 {style::NumberingType::CHARS_UPPER_LETTER_N, "AAA", LANG_ALL},
952 {style::NumberingType::CHARS_LOWER_LETTER_N, "aaa", LANG_ALL},
953 {style::NumberingType::NATIVE_NUMBERING, "Native Numbering", LANG_CJK|LANG_CTL},
954 {style::NumberingType::FULLWIDTH_ARABIC, nullptr, LANG_CJK},
955 {style::NumberingType::CIRCLE_NUMBER, nullptr, LANG_CJK},
956 {style::NumberingType::NUMBER_LOWER_ZH, nullptr, LANG_CJK},
957 {style::NumberingType::NUMBER_UPPER_ZH, nullptr, LANG_CJK},
958 {style::NumberingType::NUMBER_UPPER_ZH_TW, nullptr, LANG_CJK},
959 {style::NumberingType::TIAN_GAN_ZH, nullptr, LANG_CJK},
960 {style::NumberingType::DI_ZI_ZH, nullptr, LANG_CJK},
961 {style::NumberingType::NUMBER_TRADITIONAL_JA, nullptr, LANG_CJK},
962 {style::NumberingType::AIU_FULLWIDTH_JA, nullptr, LANG_CJK},
963 {style::NumberingType::AIU_HALFWIDTH_JA, nullptr, LANG_CJK},
964 {style::NumberingType::IROHA_FULLWIDTH_JA, nullptr, LANG_CJK},
965 {style::NumberingType::IROHA_HALFWIDTH_JA, nullptr, LANG_CJK},
966 {style::NumberingType::NUMBER_UPPER_KO, nullptr, LANG_CJK},
967 {style::NumberingType::NUMBER_HANGUL_KO, nullptr, LANG_CJK},
968 {style::NumberingType::HANGUL_JAMO_KO, nullptr, LANG_CJK},
969 {style::NumberingType::HANGUL_SYLLABLE_KO, nullptr, LANG_CJK},
970 {style::NumberingType::HANGUL_CIRCLED_JAMO_KO, nullptr, LANG_CJK},
971 {style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO, nullptr, LANG_CJK},
972 {style::NumberingType::CHARS_ARABIC, nullptr, LANG_CTL},
973 {style::NumberingType::CHARS_ARABIC_ABJAD, nullptr, LANG_CTL},
974 {style::NumberingType::NUMBER_ARABIC_INDIC, S_AR_ONE ", " S_AR_TWO ", " S_AR_THREE ", ...", LANG_CTL},
975 {style::NumberingType::NUMBER_EAST_ARABIC_INDIC, S_FA_ONE ", " S_FA_TWO ", " S_FA_THREE ", ...", LANG_CTL},
976 {style::NumberingType::NUMBER_INDIC_DEVANAGARI, S_HI_ONE ", " S_HI_TWO ", " S_HI_THREE ", ...", LANG_CTL},
977 {style::NumberingType::CHARS_THAI, nullptr, LANG_CTL},
978 {style::NumberingType::CHARS_HEBREW, nullptr, LANG_CTL},
979 {style::NumberingType::NUMBER_HEBREW, S_HE_ALEPH ", " S_HE_YOD ", " S_HE_QOF ", ...", LANG_CTL},
980 {style::NumberingType::CHARS_NEPALI, nullptr, LANG_CTL},
981 {style::NumberingType::CHARS_KHMER, nullptr, LANG_CTL},
982 {style::NumberingType::CHARS_LAO, nullptr, LANG_CTL},
983 {style::NumberingType::CHARS_MYANMAR, nullptr, LANG_CTL},
984 {style::NumberingType::CHARS_TIBETAN, nullptr, LANG_CTL},
985 {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},
986 {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},
987 {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},
988 {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},
989 {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},
990 {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},
991 {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},
992 {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},
993 {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},
994 {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},
995 {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},
996 {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},
997 {style::NumberingType::CHARS_PERSIAN, nullptr, LANG_CTL},
998 {style::NumberingType::CHARS_PERSIAN_WORD, nullptr, LANG_CTL},
999 {style::NumberingType::CHARS_GREEK_UPPER_LETTER, C_GR_A ", " C_GR_B ", ... (gr)", LANG_ALL},
1000 {style::NumberingType::CHARS_GREEK_LOWER_LETTER, S_GR_A ", " S_GR_B ", ... (gr)", LANG_ALL},
1002 static const sal_Int32 nSupported_NumberingTypes = SAL_N_ELEMENTS(aSupportedTypes);
1004 OUString DefaultNumberingProvider::makeNumberingIdentifier(sal_Int16 index)
1006 if (index < 0 || index >= nSupported_NumberingTypes)
1007 throw RuntimeException();
1009 if (aSupportedTypes[index].cSymbol)
1010 return OUString(aSupportedTypes[index].cSymbol, strlen(aSupportedTypes[index].cSymbol), RTL_TEXTENCODING_UTF8);
1011 else {
1012 OUString result;
1013 Locale aLocale("en", OUString(), OUString());
1014 Sequence<beans::PropertyValue> aProperties(2);
1015 aProperties[0].Name = "NumberingType";
1016 aProperties[0].Value <<= aSupportedTypes[index].nType;
1017 aProperties[1].Name = "Value";
1018 for (sal_Int32 j = 1; j <= 3; j++) {
1019 aProperties[1].Value <<= j;
1020 result += makeNumberingString( aProperties, aLocale );
1021 result += ", ";
1023 result += "...";
1024 return result;
1028 bool
1029 DefaultNumberingProvider::isScriptFlagEnabled(const OUString& aName)
1031 if (! xHierarchicalNameAccess.is()) {
1032 Reference< XMultiServiceFactory > xConfigProvider =
1033 configuration::theDefaultProvider::get(m_xContext);
1035 if (! xConfigProvider.is())
1036 throw RuntimeException();
1038 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1040 {"nodepath", uno::Any(OUString("/org.openoffice.Office.Common/I18N"))}
1041 }));
1043 Reference<XInterface> xInterface = xConfigProvider->createInstanceWithArguments(
1044 "com.sun.star.configuration.ConfigurationAccess", aArgs);
1046 xHierarchicalNameAccess.set(xInterface, UNO_QUERY_THROW);
1049 Any aEnabled = xHierarchicalNameAccess->getByHierarchicalName(aName);
1051 bool enabled = false;
1053 aEnabled >>= enabled;
1055 return enabled;
1058 Sequence< sal_Int16 > DefaultNumberingProvider::getSupportedNumberingTypes( )
1060 Sequence< sal_Int16 > aRet(nSupported_NumberingTypes );
1061 sal_Int16* pArray = aRet.getArray();
1063 bool cjkEnabled = isScriptFlagEnabled("CJK/CJKFont");
1064 bool ctlEnabled = isScriptFlagEnabled("CTL/CTLFont");
1066 for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++) {
1067 if ( (aSupportedTypes[i].langOption & LANG_ALL) ||
1068 ((aSupportedTypes[i].langOption & LANG_CJK) && cjkEnabled) ||
1069 ((aSupportedTypes[i].langOption & LANG_CTL) && ctlEnabled) )
1070 pArray[i] = aSupportedTypes[i].nType;
1072 return aRet;
1075 sal_Int16 DefaultNumberingProvider::getNumberingType( const OUString& rNumberingIdentifier )
1077 for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
1078 if(rNumberingIdentifier == makeNumberingIdentifier(i))
1079 return aSupportedTypes[i].nType;
1080 throw RuntimeException();
1083 sal_Bool DefaultNumberingProvider::hasNumberingType( const OUString& rNumberingIdentifier )
1085 for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
1086 if(rNumberingIdentifier == makeNumberingIdentifier(i))
1087 return true;
1088 return false;
1091 OUString DefaultNumberingProvider::getNumberingIdentifier( sal_Int16 nNumberingType )
1093 for(sal_Int16 i = 0; i < nSupported_NumberingTypes; i++)
1094 if(nNumberingType == aSupportedTypes[i].nType)
1095 return makeNumberingIdentifier(i);
1096 return OUString();
1099 OUString DefaultNumberingProvider::getImplementationName()
1101 return OUString("com.sun.star.text.DefaultNumberingProvider");
1104 sal_Bool DefaultNumberingProvider::supportsService(const OUString& rServiceName)
1106 return cppu::supportsService(this, rServiceName);
1109 Sequence< OUString > DefaultNumberingProvider::getSupportedServiceNames()
1111 Sequence< OUString > aRet { "com.sun.star.text.DefaultNumberingProvider" };
1112 return aRet;
1117 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1118 com_sun_star_text_DefaultNumberingProvider_get_implementation(
1119 css::uno::XComponentContext *context,
1120 css::uno::Sequence<css::uno::Any> const &)
1122 return cppu::acquire(new i18npool::DefaultNumberingProvider(context));
1125 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */