KHtml

enumerate.cpp
1 /**
2  * This file is part of the HTML rendering engine for KDE.
3  *
4  * Copyright (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
5  *
6  * (C) Hebrew algorithm by [email protected]
8  *
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.
13  *
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.
18  *
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.
23  *
24  */
25 
26 #include "rendering/enumerate.h"
27 
28 #include <QCharRef>
29 #include <QList>
30 
31 namespace khtml
32 {
33 
34 namespace Enumerate
35 {
36 
37 QString toRoman(int number, bool upper)
38 {
39  if (number < 1 || number > 3999) {
40  return QString::number(number);
41  }
42  QString roman;
43  static const QChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
44  static const QChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
45  const QChar *digits = upper ? udigits : ldigits;
46  int i, d = 0;
47 
48  do {
49  int num = number % 10;
50 
51  if (num % 5 < 4)
52  for (i = num % 5; i > 0; i--) {
53  roman.prepend(digits[ d ]);
54  }
55 
56  if (num >= 4 && num <= 8) {
57  roman.prepend(digits[ d + 1 ]);
58  }
59 
60  if (num == 9) {
61  roman.prepend(digits[ d + 2 ]);
62  }
63 
64  if (num % 5 == 4) {
65  roman.prepend(digits[ d ]);
66  }
67 
68  number /= 10;
69  d += 2;
70  } while (number);
71 
72  return roman;
73 }
74 
75 QString toGeorgian(int number)
76 {
77  // numbers from table at http://xml-maiden.com/numbering/table.xhtml
78  QString georgian;
79  const QChar tenthousand = 0x10F5;
80  static const QChar thousands[9] = {0x10E9, 0x10EA, 0x10EB, 0x10EC,
81  0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0
82  };
83  static const QChar hundreds[9] = {0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4,
84  0x10E5, 0x10E6, 0x10E7, 0x10E8
85  };
86  static const QChar tens[9] = {0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC,
87  0x10F2, 0x10DD, 0x10DE, 0x10DF
88  };
89  static const QChar units[9] = {0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4,
90  0x10D5, 0x10D6, 0x10F1, 0x10D7
91  };
92 
93  if (number < 1 || number > 19999) {
94  return QString::number(number);
95  }
96  if (number >= 10000) {
97  georgian.append(tenthousand);
98  number = number - 10000;
99  }
100  if (number >= 1000) {
101  georgian.append(thousands[number / 1000 - 1]);
102  number = number % 1000;
103  }
104  if (number >= 100) {
105  georgian.append(hundreds[number / 100 - 1]);
106  number = number % 100;
107  }
108  if (number >= 10) {
109  georgian.append(tens[number / 10 - 1]);
110  number = number % 10;
111  }
112  if (number >= 1) {
113  georgian.append(units[number - 1]);
114  }
115 
116  return georgian;
117 }
118 
119 QString toArmenian(int number)
120 {
121  QString armenian;
122  int thousands = 0x57b;
123  int hundreds = 0x572;
124  int tens = 0x569;
125  int units = 0x560;
126 
127  // The standard defines values upto 9999, but 7000 is odd
128  if (number < 1 || number > 6999) {
129  return QString::number(number);
130  }
131  if (number >= 1000) {
132  armenian.append(QChar(thousands + number / 1000));
133  number = number % 1000;
134  }
135  if (number >= 100) {
136  armenian.append(QChar(hundreds + number / 100));
137  number = number % 100;
138  }
139  if (number >= 10) {
140  armenian.append(QChar(tens + number / 10));
141  number = number % 10;
142  }
143  if (number >= 1) {
144  armenian.append(QChar(units + number));
145  }
146 
147  return armenian;
148 }
149 
150 QString toHebrew(int number)
151 {
152  static const QChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
153 
154  QString letter;
155  if (number < 1) {
156  return QString::number(number);
157  }
158  if (number > 999) {
159  letter = toHebrew(number / 1000) + QLatin1Char('\'');
160  number = number % 1000;
161  }
162 
163  int hunderts = (number / 400);
164  if (hunderts > 0) {
165  for (int i = 0; i < hunderts; i++) {
166  letter += QChar(1511 + 3);
167  }
168  }
169  number = number % 400;
170  if ((number / 100) != 0) {
171  letter += QChar(1511 + (number / 100) - 1);
172  }
173  number = number % 100;
174  int tens = number / 10;
175  if (tens > 0 && !(number == 15 || number == 16)) {
176  letter += tenDigit[tens - 1];
177  }
178  if (number == 15 || number == 16) { // special because of religious
179  letter += QChar(1487 + 9); // reasons
180  letter += QChar(1487 + number - 9);
181  } else {
182  number = number % 10;
183  if (number != 0) {
184  letter += QChar(1487 + number);
185  }
186  }
187  return letter;
188 }
189 
190 static inline QString toLatin(int number, int base)
191 {
192  if (number < 1) {
193  return QString::number(number);
194  }
195  QList<QChar> letters;
196  while (number > 0) {
197  number--; // number 0 is letter a
198  QChar letter = (QChar)(base + (number % 26));
199  letters.prepend(letter);
200  number /= 26;
201  }
202  QString str;
203  str.reserve(letters.size());
204  int i = 0;
205  while (!letters.isEmpty()) {
206  str[i++] = letters.front();
207  letters.pop_front();
208  }
209  return str;
210 }
211 
212 QString toLowerLatin(int number)
213 {
214  return toLatin(number, 'a');
215 }
216 
217 QString toUpperLatin(int number)
218 {
219  return toLatin(number, 'A');
220 }
221 
222 static inline QString toAlphabetic(int number, int base, const QChar alphabet[])
223 {
224  if (number < 1) {
225  return QString::number(number);
226  }
227  QList<QChar> letters;
228  while (number > 0) {
229  number--; // number 0 is letter 1
230  QChar letter = alphabet[number % base];
231  letters.prepend(letter);
232  number /= base;
233  }
234  QString str;
235  str.reserve(letters.size());
236  int i = 0;
237  while (!letters.isEmpty()) {
238  str[i++] = letters.front();
239  letters.pop_front();
240  }
241  return str;
242 }
243 
244 QString toHiragana(int number)
245 {
246  static const QChar hiragana[48] = {0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D,
247  0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
248  0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B,
249  0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078,
250  0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086,
251  0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F,
252  0x3090, 0x3091, 0x9092, 0x3093
253  };
254  return toAlphabetic(number, 48, hiragana);
255 }
256 
257 QString toHiraganaIroha(int number)
258 {
259  static const QChar hiragana[47] = {0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
260  0x3061, 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B,
261  0x3088, 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, 0x306A,
262  0x3089, 0x3080, 0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084,
263  0x307E, 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, 0x3042, 0x3055,
264  0x304D, 0x3086, 0x3081, 0x307F, 0x3057, 0x3091, 0x3072, 0x3082,
265  0x305B, 0x3059
266  };
267  return toAlphabetic(number, 47, hiragana);
268 }
269 
270 QString toKatakana(int number)
271 {
272  static const QChar katakana[48] = {0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
273  0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB,
274  0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA,
275  0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5,
276  0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
277  0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC,
278  0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x90F2, 0x30F3
279  };
280  return toAlphabetic(number, 48, katakana);
281 }
282 
283 QString toKatakanaIroha(int number)
284 {
285  static const QChar katakana[47] = {0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
286  0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB,
287  0x30E8, 0x30BF, 0x30EC, 0x30ED, 0x30C4, 0x30CD, 0x30CA,
288  0x30E9, 0x30E0, 0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF,
289  0x30E4, 0x30DE, 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
290  0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
291  0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x90B9
292  };
293  return toAlphabetic(number, 47, katakana);
294 }
295 
296 QString toLowerGreek(int number)
297 {
298  static const QChar greek[24] = { 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6,
299  0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC,
300  0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3,
301  0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9
302  };
303 
304  return toAlphabetic(number, 24, greek);
305 }
306 
307 QString toUpperGreek(int number)
308 {
309  // The standard claims to be base 24, but only lists 19 letters.
310  static const QChar greek[19] = { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398,
311  0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F,
312  0x3A0, 0x3A1, 0x3A3, 0x3A9
313  };
314 
315  return toAlphabetic(number, 19, greek);
316 }
317 
318 static inline QString toNumeric(int number, int base)
319 {
320  QString letter = QString::number(number);
321  for (int i = 0; i < letter.length(); i++) {
322  if (letter[i].isDigit()) {
323  letter[i] = QChar(letter[i].digitValue() + base);
324  }
325  }
326  return letter;
327 }
328 
329 QString toArabicIndic(int number)
330 {
331  return toNumeric(number, 0x660);
332 }
333 
334 QString toPersianUrdu(int number)
335 {
336  return toNumeric(number, 0x6F0);
337 }
338 
339 QString toLao(int number)
340 {
341  return toNumeric(number, 0xED0);
342 }
343 
344 QString toThai(int number)
345 {
346  return toNumeric(number, 0xE50);
347 }
348 
349 QString toTibetan(int number)
350 {
351  return toNumeric(number, 0xF20);
352 }
353 
354 static inline QString toIdeographic(int number, const QChar digits[], const QChar digitmarkers[])
355 {
356  if (number < 0 || number > 9999) {
357  return QString::number(number);
358  }
359 
360  QString grp = QString::number(number);
361 
362  // ### Append group markers to handle numbers > 9999
363 
364  QString str;
365 
366  // special case
367  if (number < 20 && number >= 10) {
368  str.append(digitmarkers[0]);
369  str.append(digits[grp[1].digitValue()]);
370  return str;
371  }
372 
373  int len = grp.length();
374  bool collapseZero = false;
375  for (int i = 0; i < len; i++) {
376  int digit = grp[i].digitValue();
377  // Add digit markers to digits > 0
378  if ((len - i - 1) > 0 && digit > 0) {
379  str.append(digitmarkers[(len - i - 2)]);
380  }
381  // Add digit, but collapse consecutive zeros
382  if (!collapseZero || digit > 0) {
383  str.append(digits[digit]);
384 
385  if (digit == 0) {
386  collapseZero = true;
387  } else {
388  collapseZero = false;
389  }
390  }
391  }
392  return str;
393 }
394 
395 QString toTradChineseFormal(int number)
396 {
397 // static const QChar groupMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
398  static const QChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
399  static const QChar digits[10] = {0x96f6, 0x4e00,
400  0x4ebc, 0x4e09,
401  0x56db, 0x4e94,
402  0x516d, 0x4e03,
403  0x516b, 0x4e5d
404  };
405  return toIdeographic(number, digits, digitMarkers);
406 }
407 
408 QString toTradChineseInformal(int number)
409 {
410 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
411  static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
412  static const QChar digits[10] = {0x96f6, 0x4e00,
413  0x4ebc, 0x4e09,
414  0x56db, 0x4e94,
415  0x516d, 0x4e03,
416  0x516b, 0x4e5d
417  };
418  return toIdeographic(number, digits, digitMarkers);
419 }
420 
421 QString toSimpChineseFormal(int number)
422 {
423 // static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
424  static const QChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
425  static const QChar digits[10] = {0x96f6, 0x58f9,
426  0x8cb3, 0x53c3,
427  0x8086, 0x4f0d,
428  0x9678, 0x67d2,
429  0x634c, 0x7396
430  };
431  return toIdeographic(number, digits, digitMarkers);
432 }
433 
434 QString toSimpChineseInformal(int number)
435 {
436 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
437  static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
438  static const QChar digits[10] = {0x96f6, 0x58f9,
439  0x8cb3, 0x53c3,
440  0x8086, 0x4f0d,
441  0x9678, 0x67d2,
442  0x634c, 0x7396
443  };
444  return toIdeographic(number, digits, digitMarkers);
445 }
446 
447 QString toJapaneseFormal(int number)
448 {
449 // static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
450  static const QChar digitMarkers[3] = {0x62fe, 0x4f70, 0x4edf};
451  static const QChar digits[10] = {0x96f6, 0x58f9,
452  0x8cb3, 0x53c3,
453  0x8086, 0x4f0d,
454  0x9678, 0x67d2,
455  0x634c, 0x7396
456  };
457  return toIdeographic(number, digits, digitMarkers);
458 }
459 
460 QString toJapaneseInformal(int number)
461 {
462 // static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
463  static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
464  static const QChar digits[10] = {0x96f6, 0x58f9,
465  0x8d30, 0x53c1,
466  0x8086, 0x4f0d,
467  0x9646, 0x67d2,
468  0x634c, 0x7396
469  };
470  return toIdeographic(number, digits, digitMarkers);
471 }
472 
473 }
474 } // namespace
QString & append(QChar ch)
QString & prepend(QChar ch)
This file is part of the HTML rendering engine for KDE.
int size() const const
QString number(int n, int base)
void pop_front()
bool isEmpty() const const
T & front()
int length() const const
void reserve(int size)
void prepend(const T &value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:47:53 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.