2 * This file is part of the HTML rendering engine for KDE.
4 * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
6 * (C) Hebrew algorithm by herouth@netvision.net.il
7 * and schlpbch@iam.unibe.ch
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include "rendering/enumerate.h"
28 #include <QtCore/QCharRef>
29 #include <QtCore/QList>
35 QString
toRoman( int number
, bool upper
)
37 if (number
< 1 || number
> 3999) return QString::number(number
);
39 static const QChar ldigits
[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
40 static const QChar udigits
[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
41 const QChar
*digits
= upper
? udigits
: ldigits
;
46 int num
= number
% 10;
49 for ( i
= num
% 5; i
> 0; i
-- )
50 roman
.prepend( digits
[ d
] );
52 if ( num
>= 4 && num
<= 8)
53 roman
.prepend( digits
[ d
+1 ] );
56 roman
.prepend( digits
[ d
+2 ] );
59 roman
.prepend( digits
[ d
] );
69 QString
toGeorgian( int number
)
71 // numbers from table at http://xml-maiden.com/numbering/table.xhtml
73 const QChar tenthousand
= 0x10F5;
74 static const QChar thousands
[9] = {0x10E9, 0x10EA, 0x10EB, 0x10EC,
75 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0 };
76 static const QChar hundreds
[9] = {0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4,
77 0x10E5, 0x10E6, 0x10E7, 0x10E8 };
78 static const QChar tens
[9] = {0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC,
79 0x10F2, 0x10DD, 0x10DE, 0x10DF };
80 static const QChar units
[9] = {0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4,
81 0x10D5, 0x10D6, 0x10F1, 0x10D7 };
83 if (number
< 1 || number
> 19999) return QString::number(number
);
84 if (number
>= 10000) {
85 georgian
.append(tenthousand
);
86 number
= number
- 10000;
89 georgian
.append(thousands
[number
/1000-1]);
90 number
= number
% 1000;
93 georgian
.append(hundreds
[number
/100-1]);
94 number
= number
% 100;
97 georgian
.append(tens
[number
/10-1]);
101 georgian
.append(units
[number
-1]);
107 QString
toArmenian( int number
)
110 int thousands
= 0x57b;
111 int hundreds
= 0x572;
115 // The standard defines values upto 9999, but 7000 is odd
116 if (number
< 1 || number
> 6999) return QString::number(number
);
117 if (number
>= 1000) {
118 armenian
.append(QChar(thousands
+number
/1000));
119 number
= number
% 1000;
122 armenian
.append(QChar(hundreds
+number
/100));
123 number
= number
% 100;
126 armenian
.append(QChar(tens
+number
/10));
127 number
= number
% 10;
130 armenian
.append(QChar(units
+number
));
136 QString
toHebrew( int number
) {
137 static const QChar tenDigit
[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
140 if (number
< 1) return QString::number(number
);
142 letter
= toHebrew(number
/1000) + QLatin1Char('\'');
143 number
= number
%1000;
146 int hunderts
= (number
/400);
148 for(int i
=0; i
<hunderts
; i
++) {
149 letter
+= QChar(1511 + 3);
152 number
= number
% 400;
153 if ((number
/ 100) != 0) {
154 letter
+= QChar (1511 + (number
/ 100) -1);
156 number
= number
% 100;
157 int tens
= number
/10;
158 if (tens
> 0 && !(number
== 15 || number
== 16)) {
159 letter
+= tenDigit
[tens
-1];
161 if (number
== 15 || number
== 16) { // special because of religious
162 letter
+= QChar(1487 + 9); // reasons
163 letter
+= QChar(1487 + number
- 9);
165 number
= number
% 10;
167 letter
+= QChar (1487 + number
);
173 static inline QString
toLatin( int number
, int base
) {
174 if (number
< 1) return QString::number(number
);
175 QList
<QChar
> letters
;
177 number
--; // number 0 is letter a
178 QChar letter
= (QChar
) (base
+ (number
% 26));
179 letters
.prepend(letter
);
183 str
.reserve(letters
.size());
185 while(!letters
.isEmpty()) {
186 str
[i
++] = letters
.front();
192 QString
toLowerLatin( int number
) {
193 return toLatin( number
, 'a' );
196 QString
toUpperLatin( int number
) {
197 return toLatin( number
, 'A' );
200 static inline QString
toAlphabetic( int number
, int base
, const QChar alphabet
[] ) {
201 if (number
< 1) return QString::number(number
);
202 QList
<QChar
> letters
;
204 number
--; // number 0 is letter 1
205 QChar letter
= alphabet
[number
% base
];
206 letters
.prepend(letter
);
210 str
.reserve(letters
.size());
212 while(!letters
.isEmpty()) {
213 str
[i
++] = letters
.front();
219 QString
toHiragana( int number
) {
220 static const QChar hiragana
[48] = {0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D,
221 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
222 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B,
223 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078,
224 0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086,
225 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F,
226 0x3090, 0x3091, 0x9092, 0x3093};
227 return toAlphabetic( number
, 48, hiragana
);
230 QString
toHiraganaIroha( int number
) {
231 static const QChar hiragana
[47] = {0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
232 0x3061, 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B,
233 0x3088, 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, 0x306A,
234 0x3089, 0x3080, 0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084,
235 0x307E, 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, 0x3042, 0x3055,
236 0x304D, 0x3086, 0x3081, 0x307F, 0x3057, 0x3091, 0x3072, 0x3082,
238 return toAlphabetic( number
, 47, hiragana
);
241 QString
toKatakana( int number
) {
242 static const QChar katakana
[48] = {0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
243 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB,
244 0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA,
245 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5,
246 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
247 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC,
248 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x90F2, 0x30F3};
249 return toAlphabetic( number
, 48, katakana
);
252 QString
toKatakanaIroha( int number
) {
253 static const QChar katakana
[47] = {0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
254 0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB,
255 0x30E8, 0x30BF, 0x30EC, 0x30ED, 0x30C4, 0x30CD, 0x30CA,
256 0x30E9, 0x30E0, 0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF,
257 0x30E4, 0x30DE, 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
258 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
259 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x90B9};
260 return toAlphabetic( number
, 47, katakana
);
263 QString
toLowerGreek( int number
) {
264 static const QChar greek
[24] = { 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6,
265 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC,
266 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3,
267 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9};
269 return toAlphabetic( number
, 24, greek
);
272 QString
toUpperGreek( int number
) {
273 // The standard claims to be base 24, but only lists 19 letters.
274 static const QChar greek
[19] = { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398,
275 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F,
276 0x3A0, 0x3A1, 0x3A3, 0x3A9};
278 return toAlphabetic( number
, 19, greek
);
281 static inline QString
toNumeric( int number
, int base
) {
282 QString letter
= QString::number(number
);
283 for(int i
= 0; i
< letter
.length(); i
++) {
284 if (letter
[i
].isDigit())
285 letter
[i
] = QChar(letter
[i
].digitValue()+base
);
290 QString
toArabicIndic( int number
) {
291 return toNumeric(number
, 0x660);
294 QString
toPersianUrdu( int number
) {
295 return toNumeric(number
, 0x6F0);
298 QString
toLao( int number
) {
299 return toNumeric(number
, 0xED0);
302 QString
toThai( int number
) {
303 return toNumeric(number
, 0xE50);
306 QString
toTibetan( int number
) {
307 return toNumeric(number
, 0xF20);
310 static inline QString
toIdeographic(int number
, const QChar digits
[], const QChar digitmarkers
[]) {
311 if (number
< 0 || number
> 9999) return QString::number(number
);
313 QString grp
= QString::number(number
);
315 // ### Append group markers to handle numbers > 9999
320 if (number
< 20 && number
>= 10) {
321 str
.append(digitmarkers
[0]);
322 str
.append(digits
[grp
[1].digitValue()]);
326 int len
= grp
.length();
327 bool collapseZero
= false;
328 for (int i
= 0; i
< len
; i
++) {
329 int digit
= grp
[i
].digitValue();
330 // Add digit markers to digits > 0
331 if ((len
-i
-1) > 0 && digit
> 0)
332 str
.append(digitmarkers
[(len
-i
-2)]);
333 // Add digit, but collapse consecutive zeros
334 if (!collapseZero
|| digit
> 0) {
335 str
.append(digits
[digit
]);
340 collapseZero
= false;
346 QString
toTradChineseFormal( int number
) {
347 // static const QChar groupMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
348 static const QChar digitMarkers
[3] = {0x4e07, 0x4ebf, 0x5146};
349 static const QChar digits
[10] = {0x96f6, 0x4e00,
354 return toIdeographic(number
, digits
, digitMarkers
);
357 QString
toTradChineseInformal( int number
) {
358 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
359 static const QChar digitMarkers
[3] = {0x842c, 0x5104, 0x5146};
360 static const QChar digits
[10] = {0x96f6, 0x4e00,
365 return toIdeographic(number
, digits
, digitMarkers
);
368 QString
toSimpChineseFormal( int number
) {
369 // static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
370 static const QChar digitMarkers
[3] = {0x4e07, 0x4ebf, 0x5146};
371 static const QChar digits
[10] = {0x96f6, 0x58f9,
376 return toIdeographic(number
, digits
, digitMarkers
);
379 QString
toSimpChineseInformal( int number
) {
380 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
381 static const QChar digitMarkers
[3] = {0x842c, 0x5104, 0x5146};
382 static const QChar digits
[10] = {0x96f6, 0x58f9,
387 return toIdeographic(number
, digits
, digitMarkers
);
390 QString
toJapaneseFormal( int number
) {
391 // static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
392 static const QChar digitMarkers
[3] = {0x62fe, 0x4f70, 0x4edf};
393 static const QChar digits
[10] = {0x96f6, 0x58f9,
398 return toIdeographic(number
, digits
, digitMarkers
);
401 QString
toJapaneseInformal( int number
) {
402 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
403 static const QChar digitMarkers
[3] = {0x842c, 0x5104, 0x5146};
404 static const QChar digits
[10] = {0x96f6, 0x58f9,
409 return toIdeographic(number
, digits
, digitMarkers
);