|
|
|
|
#include "transform.h"
|
|
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace PDFImport
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// classification of some Unicode characters
|
|
|
|
|
static const uint TABLE_SIZE = 0x0100;
|
|
|
|
|
static const uint NB_TABLES = 5;
|
|
|
|
|
static const uint OFFSET[NB_TABLES] = {
|
|
|
|
|
0x00, 0x01, 0x20, 0x21, 0x22
|
|
|
|
|
};
|
|
|
|
|
static const char TABLE[NB_TABLES][TABLE_SIZE] = {
|
|
|
|
|
#define U Unknown
|
|
|
|
|
#define P Punctuation
|
|
|
|
|
#define S SymbolChar
|
|
|
|
|
#define D Digit
|
|
|
|
|
#define L Letter
|
|
|
|
|
|
|
|
|
|
#define H Hyphen
|
|
|
|
|
#define B Bullet
|
|
|
|
|
#define I SuperScript
|
|
|
|
|
#define Y SpecialSymbol
|
|
|
|
|
#define G Ligature
|
|
|
|
|
|
|
|
|
|
#define A Accent
|
|
|
|
|
#define E Punctuation_Accent
|
|
|
|
|
#define C Letter_CanHaveAccent
|
|
|
|
|
|
|
|
|
|
#define X LatexSpecial
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
{ // 0x0000 to 0x00FF
|
|
|
|
|
U,U,U,U,U,U,U,U,U,P,P,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
//
|
|
|
|
|
P,P,E,S,S,S,S,P,P,P,S,S,E,H,E,S, D,D,D,D,D,D,D,D,D,D,P,P,S,S,S,P,
|
|
|
|
|
// ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
|
|
|
|
S,C,L,C,L,C,L,C,C,C,C,C,C,L,C,C, L,L,C,C,C,C,L,C,L,C,C,S,X,S,A,A,
|
|
|
|
|
// @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
|
|
|
|
|
E,C,L,C,L,C,L,C,C,C,C,C,C,L,C,C, L,L,C,C,C,C,L,C,L,C,C,S,S,S,A,U,
|
|
|
|
|
// ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
//
|
|
|
|
|
U,U,S,S,S,S,S,S,A,S,U,P,U,H,S,A, A,S,I,I,E,U,U,S,A,I,U,P,S,S,S,P,
|
|
|
|
|
// <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
|
|
L,L,L,L,L,L,C,L,L,L,L,L,L,L,L,L, L,L,L,L,L,L,L,S,C,L,L,L,L,L,L,L,
|
|
|
|
|
// <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
|
|
L,L,L,L,L,L,C,L,L,L,L,L,L,L,L,L, L,L,L,L,L,L,L,S,C,L,L,L,L,L,L,L
|
|
|
|
|
// <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
|
|
},
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
{ // 0x0100 to 0x01FF
|
|
|
|
|
L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L, L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
|
|
|
|
|
L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L, L,C,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
|
|
|
|
|
L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L, L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
|
|
|
|
|
L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L, L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,S,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
L,L,U,U,U,U,U,L,L,S,U,U,U,U,L,L, L,U,U,U,U,L,L,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,S,P,U,U,U,U,U,U,U,U,U,L,L,L, L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
|
|
|
|
|
L,L,L,L,L,L,L,L,L,L,L,L,L,L,U,U, L,U,U,U,L,L,U,U,L,L,L,L,L,L,L,L
|
|
|
|
|
},
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
{ // 0x2000 to 0x20FF
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,P,P,P,P,P,P,P,P,
|
|
|
|
|
S,S,B,U,U,U,P,U,U,U,U,U,U,U,U,U, S,U,P,P,U,U,U,U,U,Y,Y,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,Y,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,S,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
|
|
|
|
|
},
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
{ // 0x2100 to 0x21FF
|
|
|
|
|
U,U,U,G,U,U,U,U,U,G,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,S,U,U,U,U,U,U,U,Y,Y,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, Y,Y,Y,Y,Y,U,U,U,U,U,Y,Y,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,Y,U, U,U,U,U,U,Y,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,Y,Y,Y, Y,Y,Y,Y,Y,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
|
|
|
|
|
},
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
{ // 0x2200 to 0x22FF
|
|
|
|
|
Y,U,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,U,Y, U,Y,Y,U,U,Y,U,Y,U,Y,Y,U,U,Y,Y,U,
|
|
|
|
|
Y,U,U,U,U,U,U,Y,Y,Y,Y,Y,U,U,U,U, U,U,U,U,Y,Y,Y,U,U,U,U,U,Y,U,U,U,
|
|
|
|
|
U,Y,U,U,U,Y,U,Y,Y,Y,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,Y,Y,U,U,U,U,U,
|
|
|
|
|
Y,Y,Y,U,Y,Y,U,U,U,U,U,U,U,U,Y,Y, Y,Y,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,Y,Y,Y,Y,Y,Y,Y,Y,U,U,U,U,U,U, U,U,U,U,U,Y,U,Y,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,Y,Y,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,Y,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,
|
|
|
|
|
U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U, U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
|
|
|
|
|
}
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
#undef U
|
|
|
|
|
#undef P
|
|
|
|
|
#undef S
|
|
|
|
|
#undef D
|
|
|
|
|
#undef L
|
|
|
|
|
|
|
|
|
|
#undef H
|
|
|
|
|
#undef B
|
|
|
|
|
#undef I
|
|
|
|
|
#undef Y
|
|
|
|
|
|
|
|
|
|
#undef A
|
|
|
|
|
#undef E
|
|
|
|
|
#undef C
|
|
|
|
|
#undef X
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CharType type(Unicode u)
|
|
|
|
|
{
|
|
|
|
|
uint offset = u / TABLE_SIZE;
|
|
|
|
|
uint index = u % TABLE_SIZE;
|
|
|
|
|
for (uint i=0; i<NB_TABLES; i++) {
|
|
|
|
|
if ( offset==OFFSET[i] ) return (CharType)TABLE[i][index];
|
|
|
|
|
if ( offset<OFFSET[i] ) break;
|
|
|
|
|
}
|
|
|
|
|
if ( u>=0xFB00 && u<=0xFB06 ) return Ligature;
|
|
|
|
|
return Unknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
static const Unicode LIGATURE_DATA[][MaxLigatureLength+1] = {
|
|
|
|
|
{ 0xFB00, 0x0066, 0x0066, 0x0000 }, // ff
|
|
|
|
|
{ 0xFB01, 0x0066, 0x0069, 0x0000 }, // fi
|
|
|
|
|
{ 0xFB02, 0x0066, 0x006C, 0x0000 }, // fl
|
|
|
|
|
{ 0xFB03, 0x0066, 0x0066, 0x0069 }, // ffi
|
|
|
|
|
{ 0xFB04, 0x0066, 0x0066, 0x006c }, // ffl
|
|
|
|
|
// 0xFB05, 0xFB06 ??
|
|
|
|
|
// latex does not generate a ligature for ffe...
|
|
|
|
|
{ 0x0000, 0x0000, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint checkLigature(Unicode u, Unicode res[MaxLigatureLength])
|
|
|
|
|
{
|
|
|
|
|
if ( type(u)==Unknown ) kdDebug(30516) << "unknown char " << u << endl;
|
|
|
|
|
if ( type(u)!=Ligature ) {
|
|
|
|
|
res[0] = u;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint i = 0;
|
|
|
|
|
while ( LIGATURE_DATA[i][0]!=0 ) {
|
|
|
|
|
if ( LIGATURE_DATA[i][0]==u ) {
|
|
|
|
|
uint k = 0;
|
|
|
|
|
for (; k<MaxLigatureLength; k++) {
|
|
|
|
|
if ( LIGATURE_DATA[i][k+1]==0 ) break;
|
|
|
|
|
res[k] = LIGATURE_DATA[i][k+1];
|
|
|
|
|
}
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
kdDebug(30516) << "undefined ligature !! " << u <<endl;
|
|
|
|
|
res[0] = u;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
static const Unicode SUPER_DATA[][2] = {
|
|
|
|
|
{ 0x00B9, 0x0031 }, // 1
|
|
|
|
|
{ 0x00B2, 0x0032 }, // 2
|
|
|
|
|
{ 0x00B3, 0x0033 }, // 3
|
|
|
|
|
{ 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const Unicode BULLET_DATA[][2] = {
|
|
|
|
|
{ 0x2022, 0x00B7 }, // full circle
|
|
|
|
|
{ 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//static const SpecialData SPECIAL_DATA[] = {
|
|
|
|
|
// #### FIXME : add missing characters (table 0x20 to 0x22)
|
|
|
|
|
// { 0x2190, SpecialSymbol, 0x00AC }, // <-
|
|
|
|
|
// { 0x2192, SpecialSymbol, 0x00AE }, // ->
|
|
|
|
|
// { 0x2212, SpecialSymbol, 0x002D }, // -
|
|
|
|
|
// { 0x2217, SpecialSymbol, 0x002A }, // *
|
|
|
|
|
// { 0x221A, SpecialSymbol, 0x00D6 }, // squareroot
|
|
|
|
|
// { 0x2229, SpecialSymbol, 0x00C7 }, // intersection
|
|
|
|
|
// { 0x222A, SpecialSymbol, 0x00C8 }, // union
|
|
|
|
|
// { 0x0000, Unknown, 0x0000 }
|
|
|
|
|
//};
|
|
|
|
|
|
|
|
|
|
CharType checkSpecial(Unicode u, Unicode &res)
|
|
|
|
|
{
|
|
|
|
|
CharType t = type(u);
|
|
|
|
|
|
|
|
|
|
// special mapping
|
|
|
|
|
switch (t) {
|
|
|
|
|
case Unknown:
|
|
|
|
|
kdDebug(30516) << "unknown special " << QString(QChar(u))
|
|
|
|
|
<< " (" << u << ")" << endl;
|
|
|
|
|
break;
|
|
|
|
|
case SuperScript: {
|
|
|
|
|
uint i = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if ( SUPER_DATA[i][0]==0 ) {
|
|
|
|
|
kdDebug(30516) << "undefined superscript !!" << endl;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( SUPER_DATA[i][0]==u ) {
|
|
|
|
|
res = SUPER_DATA[i][1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Bullet:{
|
|
|
|
|
uint i = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if ( BULLET_DATA[i][0]==0 ) {
|
|
|
|
|
kdDebug(30516) << "undefined bullet !!" << endl;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( BULLET_DATA[i][0]==u ) {
|
|
|
|
|
res = BULLET_DATA[i][1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
enum AccentType {
|
|
|
|
|
NoAccent,
|
|
|
|
|
Grave, Acute, Circumflex, Tilde, Diaeresis, Degree,
|
|
|
|
|
Macron, LowLine, Dot, Comma, DQuote, Cedilla
|
|
|
|
|
};
|
|
|
|
|
struct AccentData {
|
|
|
|
|
Unicode u;
|
|
|
|
|
AccentType type;
|
|
|
|
|
};
|
|
|
|
|
static const AccentData ACCENT_DATA[] = {
|
|
|
|
|
{ 0x0060, Grave }, // `
|
|
|
|
|
{ 0x00B4, Acute }, // '
|
|
|
|
|
{ 0x005E, Circumflex }, // ^
|
|
|
|
|
{ 0x007E, Tilde }, // ~
|
|
|
|
|
{ 0x00A8, Diaeresis }, // <20>
|
|
|
|
|
{ 0x00B0, Degree }, // <20>
|
|
|
|
|
{ 0x00AF, Macron }, // macron
|
|
|
|
|
{ 0x005F, LowLine }, // _
|
|
|
|
|
{ 0x002E, Dot }, // .
|
|
|
|
|
// { 0x00B7, Dot }, ????
|
|
|
|
|
{ 0x002C, Comma }, // ,
|
|
|
|
|
{ 0x0022, DQuote }, // "
|
|
|
|
|
{ 0x00B8, Cedilla }, // cedilla
|
|
|
|
|
{ 0x0000, NoAccent }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CombiData {
|
|
|
|
|
AccentType type;
|
|
|
|
|
Unicode upper, lower;
|
|
|
|
|
};
|
|
|
|
|
static const CombiData A_DATA[] = {
|
|
|
|
|
{ Grave, 0x00C0, 0x00E0 },
|
|
|
|
|
{ Acute, 0x00C1, 0x00E1 },
|
|
|
|
|
{ Circumflex, 0x00C2, 0x00E2 },
|
|
|
|
|
{ Tilde, 0x00C3, 0x00E3 },
|
|
|
|
|
{ Diaeresis, 0x00C4, 0x00E4 },
|
|
|
|
|
{ Degree, 0x00C5, 0x00E5 },
|
|
|
|
|
{ Macron, 0x0100, 0x0101 },
|
|
|
|
|
{ Dot, 0x0226, 0x0227 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData C_DATA[] = {
|
|
|
|
|
{ Acute, 0x0106, 0x0107 },
|
|
|
|
|
{ Circumflex, 0x0108, 0x0109 },
|
|
|
|
|
{ Dot, 0x010A, 0x010B },
|
|
|
|
|
{ Cedilla, 0x00C7, 0x00E7 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData E_DATA[] = {
|
|
|
|
|
{ Grave, 0x00C8, 0x00E8 },
|
|
|
|
|
{ Acute, 0x00C9, 0x00E9 },
|
|
|
|
|
{ Circumflex, 0x00CA, 0x00EA },
|
|
|
|
|
{ Diaeresis, 0x00CB, 0x00EB },
|
|
|
|
|
{ Macron, 0x0112, 0x0113 },
|
|
|
|
|
{ Dot, 0x0116, 0x0117 },
|
|
|
|
|
{ Cedilla, 0x0228, 0x0229 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData G_DATA[] = {
|
|
|
|
|
{ Acute, 0x01F4, 0x01F5 },
|
|
|
|
|
{ Circumflex, 0x011C, 0x011D },
|
|
|
|
|
{ Comma, 0x0122, 0x0000 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData H_DATA[] = {
|
|
|
|
|
{ Circumflex, 0x0124, 0x0125 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData I_DATA[] = {
|
|
|
|
|
{ Grave, 0x00CC, 0x0000 },
|
|
|
|
|
{ Acute, 0x00CD, 0x0000 },
|
|
|
|
|
{ Circumflex, 0x00CE, 0x0000 },
|
|
|
|
|
{ Tilde, 0x0128, 0x0000 },
|
|
|
|
|
{ Diaeresis, 0x00CF, 0x0000 },
|
|
|
|
|
{ Macron, 0x012A, 0x0000 },
|
|
|
|
|
{ Dot, 0x0130, 0x0000 },
|
|
|
|
|
{ Cedilla, 0x012E, 0x0000 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData J_DATA[] = {
|
|
|
|
|
{ Circumflex, 0x0134, 0x0135 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData K_DATA[] = {
|
|
|
|
|
{ Comma, 0x0136, 0x0137 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData L_DATA[] = {
|
|
|
|
|
{ Acute, 0x0139, 0x013A },
|
|
|
|
|
{ Comma, 0x013B, 0x013C },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData N_DATA[] = {
|
|
|
|
|
{ Acute, 0x0143, 0x0144 },
|
|
|
|
|
{ Comma, 0x0145, 0x0146 },
|
|
|
|
|
{ Cedilla, 0x00D1, 0x00F1 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData O_DATA[] = {
|
|
|
|
|
{ Grave, 0x00D2, 0x00F2 },
|
|
|
|
|
{ Acute, 0x00D3, 0x00F3 },
|
|
|
|
|
{ Circumflex, 0x00D4, 0x00F4 },
|
|
|
|
|
{ Tilde, 0x00D5, 0x00F5 },
|
|
|
|
|
{ Diaeresis, 0x00D6, 0x00F6 },
|
|
|
|
|
{ Macron, 0x014C, 0x014D },
|
|
|
|
|
{ DQuote, 0x0150, 0x0151 },
|
|
|
|
|
{ Dot, 0x022E, 0x022F },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 },
|
|
|
|
|
};
|
|
|
|
|
static const CombiData R_DATA[] = {
|
|
|
|
|
{ Acute, 0x0154, 0x0155 },
|
|
|
|
|
{ Comma, 0x0156, 0x0157 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData S_DATA[] = {
|
|
|
|
|
{ Acute, 0x015A, 0x015B },
|
|
|
|
|
{ Circumflex, 0x015C, 0x015D },
|
|
|
|
|
{ Comma, 0x0218, 0x0219 },
|
|
|
|
|
{ Cedilla, 0x015E, 0x015F },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData T_DATA[] = {
|
|
|
|
|
{ Comma, 0x021A, 0x021B },
|
|
|
|
|
{ Cedilla, 0x0162, 0x0163 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData U_DATA[] = {
|
|
|
|
|
{ Grave, 0x00D9, 0x00F9 },
|
|
|
|
|
{ Acute, 0x00DA, 0x00FA },
|
|
|
|
|
{ Circumflex, 0x00DB, 0x00FB },
|
|
|
|
|
{ Tilde, 0x0168, 0x0169 },
|
|
|
|
|
{ Diaeresis, 0x00DC, 0x00FC },
|
|
|
|
|
{ Macron, 0x016A, 0x016B },
|
|
|
|
|
{ Dot, 0x016E, 0x016F },
|
|
|
|
|
{ DQuote, 0x0170, 0x0171 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData W_DATA[] = {
|
|
|
|
|
{ Circumflex, 0x0174, 0x0175 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData Y_DATA[] = {
|
|
|
|
|
{ Acute, 0x00DD, 0x00FD },
|
|
|
|
|
{ Circumflex, 0x0176, 0x0177 },
|
|
|
|
|
{ Diaeresis, 0x0178, 0x00FF },
|
|
|
|
|
{ Macron, 0x0232, 0x0233 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData Z_DATA[] = {
|
|
|
|
|
{ Acute, 0x0179, 0x017A },
|
|
|
|
|
{ Dot, 0x017B, 0x017C },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const CombiData *LETTER_DATA[26] = {
|
|
|
|
|
A_DATA, 0, C_DATA, 0, E_DATA, 0, G_DATA, H_DATA, I_DATA, J_DATA,
|
|
|
|
|
K_DATA, L_DATA, 0, N_DATA, O_DATA, 0, 0, R_DATA, S_DATA, T_DATA,
|
|
|
|
|
U_DATA, 0, W_DATA, 0, Y_DATA, Z_DATA
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const CombiData AE_DATA[] = {
|
|
|
|
|
{ Acute, 0x01FC, 0x01FD },
|
|
|
|
|
{ Macron, 0x01E2, 0x01E3 },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData NULL_DATA[] = {
|
|
|
|
|
{ Acute, 0x01FE, 0x01FF },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
static const CombiData I_LOWER_DATA[] = {
|
|
|
|
|
{ Grave, 0x0000, 0x00EC },
|
|
|
|
|
{ Acute, 0x0000, 0x00ED },
|
|
|
|
|
{ Circumflex, 0x0000, 0x00EE },
|
|
|
|
|
{ Tilde, 0x0000, 0x0129 },
|
|
|
|
|
{ Diaeresis, 0x0000, 0x00EF },
|
|
|
|
|
{ Macron, 0x0000, 0x012B },
|
|
|
|
|
{ Dot, 0x0000, 0x0045 },
|
|
|
|
|
{ Cedilla, 0x0000, 0x012F },
|
|
|
|
|
{ NoAccent, 0x0000, 0x0000 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SpecialCombiData {
|
|
|
|
|
Unicode upper, lower;
|
|
|
|
|
const CombiData *data;
|
|
|
|
|
};
|
|
|
|
|
static const SpecialCombiData SPECIAL_COMBI_DATA[] = {
|
|
|
|
|
{ 0x00C6, 0x00E6, AE_DATA },
|
|
|
|
|
{ 0x00D8, 0x00E8, NULL_DATA },
|
|
|
|
|
{ 0x0000, 0x0131, I_LOWER_DATA },
|
|
|
|
|
{ 0x0000, 0x0000, 0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unicode checkCombi(Unicode letter, Unicode accent)
|
|
|
|
|
{
|
|
|
|
|
// quick check
|
|
|
|
|
if ( !isAccent( type(accent) ) ) return 0;
|
|
|
|
|
if ( type(letter)!=Letter_CanHaveAccent ) return 0;
|
|
|
|
|
|
|
|
|
|
// find accent
|
|
|
|
|
uint i = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if ( ACCENT_DATA[i].u==0 ) return 0;
|
|
|
|
|
if ( ACCENT_DATA[i].u==accent ) break;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find letter
|
|
|
|
|
const CombiData *data = 0;
|
|
|
|
|
bool upper = true;
|
|
|
|
|
if ( letter>='A' && letter<='Z' )
|
|
|
|
|
data = LETTER_DATA[letter-'A'];
|
|
|
|
|
else if ( letter>='a' && letter<='z' ) {
|
|
|
|
|
data = LETTER_DATA[letter-'a'];
|
|
|
|
|
upper = false;
|
|
|
|
|
} else {
|
|
|
|
|
uint k = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if ( SPECIAL_COMBI_DATA[k].data==0 ) return 0;
|
|
|
|
|
if ( letter==SPECIAL_COMBI_DATA[k].upper ) {
|
|
|
|
|
data = SPECIAL_COMBI_DATA[k].data;
|
|
|
|
|
break;
|
|
|
|
|
} else if ( letter==SPECIAL_COMBI_DATA[k].lower ) {
|
|
|
|
|
data = SPECIAL_COMBI_DATA[k].data;
|
|
|
|
|
upper = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
k++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( data==0 ) return 0;
|
|
|
|
|
|
|
|
|
|
// find combi
|
|
|
|
|
uint l = 0;
|
|
|
|
|
while ( data[l].type!=NoAccent ) {
|
|
|
|
|
if ( data[l].type==ACCENT_DATA[i].type )
|
|
|
|
|
return (upper ? data[l].upper : data[l].lower);
|
|
|
|
|
l++;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|