You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
14 KiB
412 lines
14 KiB
/**
|
|
* This file is part of the HTML rendering engine for KDE.
|
|
*
|
|
* Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
|
|
*
|
|
* (C) Hebrew algorithm by herouth@netvision.net.il
|
|
* and schlpbch@iam.unibe.ch
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "rendering/enumerate.h"
|
|
|
|
#include <qstring.h>
|
|
#include <qvaluelist.h>
|
|
|
|
namespace khtml {
|
|
|
|
namespace Enumerate {
|
|
|
|
QString toRoman( int number, bool upper )
|
|
{
|
|
if (number < 1 || number > 3999) return QString::number(number);
|
|
QString roman;
|
|
static const QChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
|
|
static const QChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
|
|
const QChar *digits = upper ? udigits : ldigits;
|
|
int i, d = 0;
|
|
|
|
do
|
|
{
|
|
int num = number % 10;
|
|
|
|
if ( num % 5 < 4 )
|
|
for ( i = num % 5; i > 0; i-- )
|
|
roman.prepend( digits[ d ] );
|
|
|
|
if ( num >= 4 && num <= 8)
|
|
roman.prepend( digits[ d+1 ] );
|
|
|
|
if ( num == 9 )
|
|
roman.prepend( digits[ d+2 ] );
|
|
|
|
if ( num % 5 == 4 )
|
|
roman.prepend( digits[ d ] );
|
|
|
|
number /= 10;
|
|
d += 2;
|
|
}
|
|
while ( number );
|
|
|
|
return roman;
|
|
}
|
|
|
|
QString toGeorgian( int number )
|
|
{
|
|
QString georgian;
|
|
const QChar tenthousand = 0x10ef;
|
|
static const QChar thousands[9] = {0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec,
|
|
0x10ed, 0x10ee, 0x10f4, 0x10f5 };
|
|
static const QChar hundreds[9] = {0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10f3,
|
|
0x10e4, 0x10e5, 0x10e6, 0x10e7 };
|
|
static const QChar tens[9] = {0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc,
|
|
0x10f2, 0x10dd, 0x10de, 0x10df };
|
|
static const QChar units[9] = {0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4,
|
|
0x10d5, 0x10d6, 0x10f1, 0x10d7 };
|
|
|
|
if (number < 1 || number > 19999) return QString::number(number);
|
|
if (number >= 10000) {
|
|
georgian.append(tenthousand);
|
|
number = number - 10000;
|
|
}
|
|
if (number >= 1000) {
|
|
georgian.append(thousands[number/1000-1]);
|
|
number = number % 1000;
|
|
}
|
|
if (number >= 100) {
|
|
georgian.append(hundreds[number/100-1]);
|
|
number = number % 100;
|
|
}
|
|
if (number >= 10) {
|
|
georgian.append(tens[number/10-1]);
|
|
number = number % 10;
|
|
}
|
|
if (number >= 1) {
|
|
georgian.append(units[number-1]);
|
|
}
|
|
|
|
return georgian;
|
|
}
|
|
|
|
QString toArmenian( int number )
|
|
{
|
|
QString armenian;
|
|
int onethousand = 0x57c;
|
|
int hundreds = 0x572;
|
|
int tens = 0x569;
|
|
int units = 0x560;
|
|
|
|
// The standard defines values over 1999, but 7000 is very hard to render
|
|
if (number < 1 || number > 1999) return QString::number(number);
|
|
if (number >= 1000) {
|
|
armenian.append(QChar(onethousand));
|
|
number = number - 1000;
|
|
}
|
|
if (number >= 100) {
|
|
armenian.append(QChar(hundreds+number/100));
|
|
number = number % 100;
|
|
}
|
|
if (number >= 10) {
|
|
armenian.append(QChar(tens+number/10));
|
|
number = number % 10;
|
|
}
|
|
if (number >= 1) {
|
|
armenian.append(QChar(units+number));
|
|
}
|
|
|
|
return armenian;
|
|
}
|
|
|
|
QString toHebrew( int number ) {
|
|
static const QChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
|
|
|
|
QString letter;
|
|
if (number < 1) return QString::number(number);
|
|
if (number>999) {
|
|
letter = toHebrew(number/1000) + QString::fromLatin1("'");
|
|
number = number%1000;
|
|
}
|
|
|
|
int hunderts = (number/400);
|
|
if (hunderts > 0) {
|
|
for(int i=0; i<hunderts; i++) {
|
|
letter += QChar(1511 + 3);
|
|
}
|
|
}
|
|
number = number % 400;
|
|
if ((number / 100) != 0) {
|
|
letter += QChar (1511 + (number / 100) -1);
|
|
}
|
|
number = number % 100;
|
|
int tens = number/10;
|
|
if (tens > 0 && !(number == 15 || number == 16)) {
|
|
letter += tenDigit[tens-1];
|
|
}
|
|
if (number == 15 || number == 16) { // special because of religious
|
|
letter += QChar(1487 + 9); // reasons
|
|
letter += QChar(1487 + number - 9);
|
|
} else {
|
|
number = number % 10;
|
|
if (number != 0) {
|
|
letter += QChar (1487 + number);
|
|
}
|
|
}
|
|
return letter;
|
|
}
|
|
|
|
static inline QString toLatin( int number, int base ) {
|
|
if (number < 1) return QString::number(number);
|
|
QValueList<QChar> letters;
|
|
while(number > 0) {
|
|
number--; // number 0 is letter a
|
|
QChar letter = (QChar) (base + (number % 26));
|
|
letters.prepend(letter);
|
|
number /= 26;
|
|
}
|
|
QString str;
|
|
str.setLength(letters.size());
|
|
int i=0;
|
|
while(!letters.isEmpty()) {
|
|
str[i++] = letters.front();
|
|
letters.pop_front();
|
|
}
|
|
return str;
|
|
}
|
|
|
|
QString toLowerLatin( int number ) {
|
|
return toLatin( number, 'a' );
|
|
}
|
|
|
|
QString toUpperLatin( int number ) {
|
|
return toLatin( number, 'A' );
|
|
}
|
|
|
|
static inline QString toAlphabetic( int number, int base, const QChar alphabet[] ) {
|
|
if (number < 1) return QString::number(number);
|
|
QValueList<QChar> letters;
|
|
while(number > 0) {
|
|
number--; // number 0 is letter 1
|
|
QChar letter = alphabet[number % base];
|
|
letters.prepend(letter);
|
|
number /= base;
|
|
}
|
|
QString str;
|
|
str.setLength(letters.size());
|
|
int i=0;
|
|
while(!letters.isEmpty()) {
|
|
str[i++] = letters.front();
|
|
letters.pop_front();
|
|
}
|
|
return str;
|
|
}
|
|
|
|
QString toHiragana( int number ) {
|
|
static const QChar hiragana[48] = {0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D,
|
|
0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
|
|
0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B,
|
|
0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078,
|
|
0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086,
|
|
0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F,
|
|
0x3090, 0x3091, 0x9092, 0x3093};
|
|
return toAlphabetic( number, 48, hiragana );
|
|
}
|
|
|
|
QString toHiraganaIroha( int number ) {
|
|
static const QChar hiragana[47] = {0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
|
|
0x3061, 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B,
|
|
0x3088, 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, 0x306A,
|
|
0x3089, 0x3080, 0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084,
|
|
0x307E, 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, 0x3042, 0x3055,
|
|
0x304D, 0x3086, 0x3081, 0x307F, 0x3057, 0x3091, 0x3072, 0x3082,
|
|
0x305B, 0x3059 };
|
|
return toAlphabetic( number, 47, hiragana );
|
|
}
|
|
|
|
QString toKatakana( int number ) {
|
|
static const QChar katakana[48] = {0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
|
|
0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB,
|
|
0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA,
|
|
0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5,
|
|
0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
|
|
0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC,
|
|
0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x90F2, 0x30F3};
|
|
return toAlphabetic( number, 48, katakana );
|
|
}
|
|
|
|
QString toKatakanaIroha( int number ) {
|
|
static const QChar katakana[47] = {0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
|
|
0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB,
|
|
0x30E8, 0x30BF, 0x30EC, 0x30ED, 0x30C4, 0x30CD, 0x30CA,
|
|
0x30E9, 0x30E0, 0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF,
|
|
0x30E4, 0x30DE, 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
|
|
0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
|
|
0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x90B9};
|
|
return toAlphabetic( number, 47, katakana );
|
|
}
|
|
|
|
QString toLowerGreek( int number ) {
|
|
static const QChar greek[24] = { 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7,
|
|
0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE,
|
|
0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6,
|
|
0x3C7, 0x3C8, 0x3C0};
|
|
|
|
return toAlphabetic( number, 24, greek );
|
|
}
|
|
|
|
QString toUpperGreek( int number ) {
|
|
// The standard claims to be base 24, but only lists 19 letters.
|
|
static const QChar greek[19] = { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398,
|
|
0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F,
|
|
0x3A0, 0x3A1, 0x3A3, 0x3A9};
|
|
|
|
return toAlphabetic( number, 19, greek );
|
|
}
|
|
|
|
static inline QString toNumeric( int number, int base ) {
|
|
QString letter = QString::number(number);
|
|
for(unsigned int i = 0; i < letter.length(); i++) {
|
|
if (letter[i].isDigit())
|
|
letter[i] = QChar(letter[i].digitValue()+base);
|
|
}
|
|
return letter;
|
|
}
|
|
|
|
QString toArabicIndic( int number ) {
|
|
return toNumeric(number, 0x660);
|
|
}
|
|
|
|
QString toPersianUrdu( int number ) {
|
|
return toNumeric(number, 0x6F0);
|
|
}
|
|
|
|
QString toLao( int number ) {
|
|
return toNumeric(number, 0xED0);
|
|
}
|
|
|
|
QString toThai( int number ) {
|
|
return toNumeric(number, 0xE50);
|
|
}
|
|
|
|
QString toTibetan( int number ) {
|
|
return toNumeric(number, 0xF20);
|
|
}
|
|
|
|
static inline QString toIdeographic(int number, const QChar digits[], const QChar digitmarkers[]) {
|
|
if (number < 0 || number > 9999) return QString::number(number);
|
|
|
|
QString grp = QString::number(number);
|
|
|
|
// ### Append group markers to handle numbers > 9999
|
|
|
|
QString str;
|
|
|
|
// special case
|
|
if (number < 20 && number >= 10) {
|
|
str.append(digitmarkers[0]);
|
|
str.append(digits[grp[1].digitValue()]);
|
|
return str;
|
|
}
|
|
|
|
int len = grp.length();
|
|
bool collapseZero = false;
|
|
for (int i = 0; i < len ; i++) {
|
|
int digit = grp[i].digitValue();
|
|
// Add digit markers to digits > 0
|
|
if ((len-i-1) > 0 && digit > 0)
|
|
str.append(digitmarkers[(len-i-2)]);
|
|
// Add digit, but collapse consecutive zeros
|
|
if (!collapseZero || digit > 0) {
|
|
str.append(digits[digit]);
|
|
|
|
if (digit == 0)
|
|
collapseZero = true;
|
|
else
|
|
collapseZero = false;
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
QString toTradChineseFormal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
|
|
static const QChar digits[10] = {0x96f6, 0x4e00,
|
|
0x4ebc, 0x4e09,
|
|
0x56db, 0x4e94,
|
|
0x516d, 0x4e03,
|
|
0x516b, 0x4e5d};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
QString toTradChineseInformal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digits[10] = {0x96f6, 0x4e00,
|
|
0x4ebc, 0x4e09,
|
|
0x56db, 0x4e94,
|
|
0x516d, 0x4e03,
|
|
0x516b, 0x4e5d};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
QString toSimpChineseFormal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
|
|
static const QChar digits[10] = {0x96f6, 0x58f9,
|
|
0x8cb3, 0x53c3,
|
|
0x8086, 0x4f0d,
|
|
0x9678, 0x67d2,
|
|
0x634c, 0x7396};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
QString toSimpChineseInformal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digits[10] = {0x96f6, 0x58f9,
|
|
0x8cb3, 0x53c3,
|
|
0x8086, 0x4f0d,
|
|
0x9678, 0x67d2,
|
|
0x634c, 0x7396};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
QString toJapaneseFormal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x62fe, 0x4f70, 0x4edf};
|
|
static const QChar digits[10] = {0x96f6, 0x58f9,
|
|
0x8cb3, 0x53c3,
|
|
0x8086, 0x4f0d,
|
|
0x9678, 0x67d2,
|
|
0x634c, 0x7396};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
QString toJapaneseInformal( int number ) {
|
|
// static const QChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
|
|
static const QChar digits[10] = {0x96f6, 0x58f9,
|
|
0x8d30, 0x53c1,
|
|
0x8086, 0x4f0d,
|
|
0x9646, 0x67d2,
|
|
0x634c, 0x7396};
|
|
return toIdeographic(number, digits, digitMarkers);
|
|
}
|
|
|
|
}} // namespace
|