fix logic
[personal-kdelibs.git] / khtml / rendering / enumerate.cpp
blob157c1a7f9403f98b357906605ce1513aef91e066
1 /**
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>
31 namespace khtml {
33 namespace Enumerate {
35 QString toRoman( int number, bool upper )
37 if (number < 1 || number > 3999) return QString::number(number);
38 QString roman;
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;
42 int i, d = 0;
46 int num = number % 10;
48 if ( num % 5 < 4 )
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 ] );
55 if ( num == 9 )
56 roman.prepend( digits[ d+2 ] );
58 if ( num % 5 == 4 )
59 roman.prepend( digits[ d ] );
61 number /= 10;
62 d += 2;
64 while ( number );
66 return roman;
69 QString toGeorgian( int number )
71 // numbers from table at http://xml-maiden.com/numbering/table.xhtml
72 QString georgian;
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;
88 if (number >= 1000) {
89 georgian.append(thousands[number/1000-1]);
90 number = number % 1000;
92 if (number >= 100) {
93 georgian.append(hundreds[number/100-1]);
94 number = number % 100;
96 if (number >= 10) {
97 georgian.append(tens[number/10-1]);
98 number = number % 10;
100 if (number >= 1) {
101 georgian.append(units[number-1]);
104 return georgian;
107 QString toArmenian( int number )
109 QString armenian;
110 int thousands = 0x57b;
111 int hundreds = 0x572;
112 int tens = 0x569;
113 int units = 0x560;
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;
121 if (number >= 100) {
122 armenian.append(QChar(hundreds+number/100));
123 number = number % 100;
125 if (number >= 10) {
126 armenian.append(QChar(tens+number/10));
127 number = number % 10;
129 if (number >= 1) {
130 armenian.append(QChar(units+number));
133 return armenian;
136 QString toHebrew( int number ) {
137 static const QChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
139 QString letter;
140 if (number < 1) return QString::number(number);
141 if (number>999) {
142 letter = toHebrew(number/1000) + QLatin1Char('\'');
143 number = number%1000;
146 int hunderts = (number/400);
147 if (hunderts > 0) {
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);
164 } else {
165 number = number % 10;
166 if (number != 0) {
167 letter += QChar (1487 + number);
170 return letter;
173 static inline QString toLatin( int number, int base ) {
174 if (number < 1) return QString::number(number);
175 QList<QChar> letters;
176 while(number > 0) {
177 number--; // number 0 is letter a
178 QChar letter = (QChar) (base + (number % 26));
179 letters.prepend(letter);
180 number /= 26;
182 QString str;
183 str.reserve(letters.size());
184 int i=0;
185 while(!letters.isEmpty()) {
186 str[i++] = letters.front();
187 letters.pop_front();
189 return str;
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;
203 while(number > 0) {
204 number--; // number 0 is letter 1
205 QChar letter = alphabet[number % base];
206 letters.prepend(letter);
207 number /= base;
209 QString str;
210 str.reserve(letters.size());
211 int i=0;
212 while(!letters.isEmpty()) {
213 str[i++] = letters.front();
214 letters.pop_front();
216 return str;
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,
237 0x305B, 0x3059 };
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);
287 return letter;
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
317 QString str;
319 // special case
320 if (number < 20 && number >= 10) {
321 str.append(digitmarkers[0]);
322 str.append(digits[grp[1].digitValue()]);
323 return str;
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]);
337 if (digit == 0)
338 collapseZero = true;
339 else
340 collapseZero = false;
343 return str;
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,
350 0x4ebc, 0x4e09,
351 0x56db, 0x4e94,
352 0x516d, 0x4e03,
353 0x516b, 0x4e5d};
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,
361 0x4ebc, 0x4e09,
362 0x56db, 0x4e94,
363 0x516d, 0x4e03,
364 0x516b, 0x4e5d};
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,
372 0x8cb3, 0x53c3,
373 0x8086, 0x4f0d,
374 0x9678, 0x67d2,
375 0x634c, 0x7396};
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,
383 0x8cb3, 0x53c3,
384 0x8086, 0x4f0d,
385 0x9678, 0x67d2,
386 0x634c, 0x7396};
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,
394 0x8cb3, 0x53c3,
395 0x8086, 0x4f0d,
396 0x9678, 0x67d2,
397 0x634c, 0x7396};
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,
405 0x8d30, 0x53c1,
406 0x8086, 0x4f0d,
407 0x9646, 0x67d2,
408 0x634c, 0x7396};
409 return toIdeographic(number, digits, digitMarkers);
412 }} // namespace