390 lines
9.3 KiB
C
390 lines
9.3 KiB
C
|
|
#include "wc.h"
|
|
#include "johab.h"
|
|
#include "wtf.h"
|
|
#ifdef USE_UNICODE
|
|
#include "ucs.h"
|
|
#endif
|
|
|
|
#define C0 WC_JOHAB_MAP_C0
|
|
#define GL WC_JOHAB_MAP_GL
|
|
#define C1 WC_JOHAB_MAP_C1
|
|
#define GH WC_JOHAB_MAP_GH
|
|
#define GB WC_JOHAB_MAP_GB
|
|
#define JJ WC_JOHAB_MAP_JJ
|
|
#define JB WC_JOHAB_MAP_JB
|
|
#define HB WC_JOHAB_MAP_HB
|
|
#define CJ WC_JOHAB_MAP_CJ
|
|
#define CB WC_JOHAB_MAP_CB
|
|
|
|
/*
|
|
00-1F 20-30 31-40 41-7E 7F 80 81-83 84-90 91-D3 D4-D7 D8-DE DF E0-F9 FA-FE FF
|
|
C0 GL GL GL C0 - - J J - H - H - -
|
|
- - J B - - J J B B B B B B -
|
|
|
|
C0 GL GH GB C0 C1 CJ JJ JB CB HB CB HB CB C1
|
|
*/
|
|
|
|
wc_uint8 WC_JOHAB_MAP[ 0x100 ] = {
|
|
C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
|
|
C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
|
|
/* 20 */
|
|
GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL,
|
|
/* 30 31 */
|
|
GL, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH, GH,
|
|
/* 40 41 */
|
|
GH, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB,
|
|
GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB,
|
|
GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB,
|
|
GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, GB, C0,
|
|
|
|
/* 80 83 84 */
|
|
C1, CJ, CJ, CJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ, JJ,
|
|
/* 90 91 */
|
|
JJ, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB,
|
|
JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB,
|
|
JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB,
|
|
JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB, JB,
|
|
/* D3 D4 D7 D8 DF */
|
|
JB, JB, JB, JB, CB, CB, CB, CB, HB, HB, HB, HB, HB, HB, HB, CB,
|
|
HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, HB,
|
|
/* F9 FA FE FF */
|
|
HB, HB, HB, HB, HB, HB, HB, HB, HB, HB, CB, CB, CB, CB, CB, C1,
|
|
};
|
|
|
|
static wc_uint8 johab1_N_map[ 3 ][ 32 ] = {
|
|
{ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
|
15,16,17,18,19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 6, 7, 8, 9,10,11,
|
|
0, 0,12,13,14,15,16,17, 0, 0,18,19,20,21, 0, 0 },
|
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
|
|
16,17, 0,18,19,20,21,22,23,24,25,26,27,28, 0, 0 }
|
|
};
|
|
|
|
static wc_uint8 N_johab1_map[ 3 ][ 32 ] = {
|
|
{ 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,
|
|
18,19,20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 3, 4, 5, 6, 7,10,11,12,13,14,15,18,19,20,21,22,
|
|
23,26,27,28,29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
|
|
17,19,20,21,22,23,24,25,26,27,28,29, 0, 0, 0, 0 }
|
|
};
|
|
|
|
wc_wchar_t
|
|
wc_johab_to_ksx1001(wc_wchar_t cc)
|
|
{
|
|
#ifdef USE_UNICODE
|
|
static wc_table *t = NULL;
|
|
#endif
|
|
|
|
switch (cc.ccs) {
|
|
case WC_CCS_JOHAB:
|
|
return wc_johab_to_ksx1001(wc_johab_to_cs128w(cc));
|
|
case WC_CCS_JOHAB_1:
|
|
case WC_CCS_JOHAB_2:
|
|
#ifdef USE_UNICODE
|
|
if (WcOption.ucs_conv) {
|
|
if (t == NULL)
|
|
t = wc_get_ucs_table(WC_CCS_KS_X_1001);
|
|
cc = wc_any_to_any(cc, t);
|
|
} else
|
|
#endif
|
|
cc.ccs = WC_CCS_UNKNOWN_W;
|
|
break;
|
|
case WC_CCS_JOHAB_3:
|
|
if (cc.code >= 0x2121)
|
|
cc.ccs = WC_CCS_KS_X_1001;
|
|
else
|
|
cc.ccs = WC_CCS_UNKNOWN_W;
|
|
break;
|
|
}
|
|
return cc;
|
|
}
|
|
|
|
wc_wchar_t
|
|
wc_ksx1001_to_johab(wc_wchar_t cc)
|
|
{
|
|
cc.code &= 0x7f7f;
|
|
if ((cc.code >= 0x2121 && cc.code < 0x2421) ||
|
|
(cc.code > 0x2453 && cc.code <= 0x2C7E) ||
|
|
(cc.code >= 0x4A21 && cc.code <= 0x7D7E)) {
|
|
cc.ccs = WC_CCS_JOHAB_3;
|
|
return cc;
|
|
}
|
|
#ifdef USE_UNICODE
|
|
if (WcOption.ucs_conv)
|
|
cc = wc_ucs_to_johab(wc_any_to_ucs(cc));
|
|
else
|
|
#endif
|
|
cc.ccs = WC_CCS_UNKNOWN_W;
|
|
return cc;
|
|
}
|
|
|
|
#ifdef USE_UNICODE
|
|
wc_wchar_t
|
|
wc_ucs_to_johab(wc_uint32 ucs)
|
|
{
|
|
wc_table *t;
|
|
wc_wchar_t cc;
|
|
|
|
if (ucs >= WC_C_UCS2_HANGUL && ucs <= WC_C_UCS2_HANGUL_END) {
|
|
ucs -= WC_C_UCS2_HANGUL;
|
|
cc.code = WC_N_JOHAB1(ucs);
|
|
cc.ccs = WC_CCS_JOHAB;
|
|
} else if (ucs >= 0x3131 && ucs <= 0x3163) {
|
|
t = wc_get_ucs_table(WC_CCS_JOHAB_2);
|
|
cc = wc_ucs_to_any(ucs, t);
|
|
} else {
|
|
t = wc_get_ucs_table(WC_CCS_JOHAB_3);
|
|
cc = wc_ucs_to_any(ucs, t);
|
|
}
|
|
return cc;
|
|
}
|
|
#endif
|
|
|
|
wc_uint32
|
|
wc_johab1_to_N(wc_uint32 code)
|
|
{
|
|
wc_uint32 a, b, c;
|
|
|
|
a = johab1_N_map[0][(code >> 10) & 0x1F];
|
|
b = johab1_N_map[1][(code >> 5) & 0x1F];
|
|
c = johab1_N_map[2][ code & 0x1F];
|
|
if (a && b && c)
|
|
return ((a - 1) * 21 + (b - 1)) * 28 + (c - 1);
|
|
return WC_C_JOHAB_ERROR;
|
|
}
|
|
|
|
wc_uint32
|
|
wc_N_to_johab1(wc_uint32 code)
|
|
{
|
|
wc_uint32 a, b, c;
|
|
|
|
a = N_johab1_map[0][(code / 28) / 21 & 0x1F];
|
|
b = N_johab1_map[1][(code / 28) % 21 & 0x1F];
|
|
c = N_johab1_map[2][ code % 28 & 0x1F];
|
|
return 0x8000 | (a << 10) | (b << 5) | c;
|
|
}
|
|
|
|
/* 0x1F21 - 0x2C7E, 0x4A21 - 0x7C7E
|
|
(0x1F21 - 0x207E are not in KS X 1001) */
|
|
#define johab3_to_ksx1001(ub, lb) \
|
|
{ \
|
|
if (ub < 0xe0) { \
|
|
ub = ((ub - 0xd8) << 1) + 0x1f; \
|
|
} else { \
|
|
ub = ((ub - 0xe0) << 1) + 0x4a; \
|
|
} \
|
|
if (lb < 0xa1) { \
|
|
lb -= (lb < 0x91) ? 0x10 : 0x22; \
|
|
} else { \
|
|
ub++; \
|
|
lb -= 0x80; \
|
|
} \
|
|
}
|
|
|
|
#define ksx1001_to_johab3(ub, lb) \
|
|
{ \
|
|
if (ub < 0x4a) { \
|
|
ub -= 0x1f; \
|
|
lb += (ub & 0x1) ? 0x80 : ((lb < 0x6f) ? 0x10 : 0x22); \
|
|
ub = (ub >> 1) + 0xd8; \
|
|
} else { \
|
|
ub -= 0x4a; \
|
|
lb += (ub & 0x1) ? 0x80 : ((lb < 0x6f) ? 0x10 : 0x22); \
|
|
ub = (ub >> 1) + 0xe0; \
|
|
} \
|
|
}
|
|
|
|
wc_wchar_t
|
|
wc_johab_to_cs128w(wc_wchar_t cc)
|
|
{
|
|
wc_uint32 n;
|
|
wc_uchar ub, lb;
|
|
|
|
if (cc.code < 0xD800) {
|
|
n = WC_JOHAB1_N(cc.code);
|
|
if (n != WC_C_JOHAB_ERROR) {
|
|
cc.code = WC_N_CS94x128(n);
|
|
cc.ccs = WC_CCS_JOHAB_1;
|
|
} else {
|
|
n = WC_JOHAB2_N(cc.code);
|
|
cc.code = WC_N_CS128W(n);
|
|
cc.ccs = WC_CCS_JOHAB_2;
|
|
}
|
|
} else {
|
|
ub = cc.code >> 8;
|
|
lb = cc.code & 0xff;
|
|
johab3_to_ksx1001(ub, lb);
|
|
cc.code = ((wc_uint32)ub << 8) | lb;
|
|
cc.ccs = WC_CCS_JOHAB_3;
|
|
}
|
|
return cc;
|
|
}
|
|
|
|
wc_wchar_t
|
|
wc_cs128w_to_johab(wc_wchar_t cc)
|
|
{
|
|
wc_uint32 n;
|
|
wc_uchar ub, lb;
|
|
|
|
switch (cc.ccs) {
|
|
case WC_CCS_JOHAB_1:
|
|
n = WC_CS94x128_N(cc.code);
|
|
cc.code = WC_N_JOHAB1(n);
|
|
break;
|
|
case WC_CCS_JOHAB_2:
|
|
n = WC_CS128W_N(cc.code);
|
|
cc.code = WC_N_JOHAB2(n);
|
|
break;
|
|
case WC_CCS_JOHAB_3:
|
|
ub = (cc.code >> 8) & 0x7f;
|
|
lb = cc.code & 0x7f;
|
|
ksx1001_to_johab3(ub, lb);
|
|
cc.code = ((wc_uint32)ub << 8) | lb;
|
|
}
|
|
cc.ccs = WC_CCS_JOHAB;
|
|
return cc;
|
|
}
|
|
|
|
Str
|
|
wc_conv_from_johab(Str is, wc_ces ces)
|
|
{
|
|
Str os;
|
|
wc_uchar *sp = (wc_uchar *)is->ptr;
|
|
wc_uchar *ep = sp + is->length;
|
|
wc_uchar *p;
|
|
int state = WC_JOHAB_NOSTATE;
|
|
|
|
for (p = sp; p < ep && *p < 0x80; p++)
|
|
;
|
|
if (p == ep)
|
|
return is;
|
|
os = Strnew_size(is->length);
|
|
if (p > sp)
|
|
Strcat_charp_n(os, is->ptr, (int)(p - sp));
|
|
|
|
for (; p < ep; p++) {
|
|
switch (state) {
|
|
case WC_JOHAB_NOSTATE:
|
|
switch (WC_JOHAB_MAP[*p] & WC_JOHAB_MAP_1) {
|
|
case WC_JOHAB_MAP_UJ:
|
|
state = WC_JOHAB_HANGUL1;
|
|
break;
|
|
case WC_JOHAB_MAP_UH:
|
|
state = WC_JOHAB_HANJA1;
|
|
break;
|
|
case WC_JOHAB_MAP_C1:
|
|
wtf_push_unknown(os, p, 1);
|
|
break;
|
|
default:
|
|
Strcat_char(os, (char)*p);
|
|
break;
|
|
}
|
|
break;
|
|
case WC_JOHAB_HANGUL1:
|
|
if (WC_JOHAB_MAP[*p] & WC_JOHAB_MAP_LJ)
|
|
wtf_push(os, WC_CCS_JOHAB, ((wc_uint32)*(p-1) << 8) | *p);
|
|
else
|
|
wtf_push_unknown(os, p-1, 2);
|
|
state = WC_JOHAB_NOSTATE;
|
|
break;
|
|
case WC_JOHAB_HANJA1:
|
|
if (WC_JOHAB_MAP[*p] & WC_JOHAB_MAP_LH)
|
|
wtf_push(os, WC_CCS_JOHAB, ((wc_uint32)*(p-1) << 8) | *p);
|
|
else
|
|
wtf_push_unknown(os, p-1, 2);
|
|
state = WC_JOHAB_NOSTATE;
|
|
break;
|
|
}
|
|
}
|
|
switch (state) {
|
|
case WC_JOHAB_HANGUL1:
|
|
case WC_JOHAB_HANJA1:
|
|
wtf_push_unknown(os, p-1, 1);
|
|
break;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
void
|
|
wc_push_to_johab(Str os, wc_wchar_t cc, wc_status *st)
|
|
{
|
|
while (1) {
|
|
switch (cc.ccs) {
|
|
case WC_CCS_US_ASCII:
|
|
Strcat_char(os, (char)cc.code);
|
|
return;
|
|
case WC_CCS_JOHAB_1:
|
|
case WC_CCS_JOHAB_2:
|
|
case WC_CCS_JOHAB_3:
|
|
cc = wc_cs128w_to_johab(cc);
|
|
case WC_CCS_JOHAB:
|
|
Strcat_char(os, (char)(cc.code >> 8));
|
|
Strcat_char(os, (char)(cc.code & 0xff));
|
|
return;
|
|
case WC_CCS_KS_X_1001:
|
|
cc = wc_ksx1001_to_johab(cc);
|
|
continue;
|
|
case WC_CCS_UNKNOWN_W:
|
|
if (!WcOption.no_replace)
|
|
Strcat_charp(os, WC_REPLACE_W);
|
|
return;
|
|
case WC_CCS_UNKNOWN:
|
|
if (!WcOption.no_replace)
|
|
Strcat_charp(os, WC_REPLACE);
|
|
return;
|
|
default:
|
|
#ifdef USE_UNICODE
|
|
if (WcOption.ucs_conv)
|
|
cc = wc_any_to_any_ces(cc, st);
|
|
else
|
|
#endif
|
|
cc.ccs = WC_CCS_IS_WIDE(cc.ccs) ? WC_CCS_UNKNOWN_W : WC_CCS_UNKNOWN;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
Str
|
|
wc_char_conv_from_johab(wc_uchar c, wc_status *st)
|
|
{
|
|
static Str os;
|
|
static wc_uchar johabu;
|
|
|
|
if (st->state == -1) {
|
|
st->state = WC_JOHAB_NOSTATE;
|
|
os = Strnew_size(8);
|
|
}
|
|
|
|
switch (st->state) {
|
|
case WC_JOHAB_NOSTATE:
|
|
switch (WC_JOHAB_MAP[c] & WC_JOHAB_MAP_1) {
|
|
case WC_JOHAB_MAP_UJ:
|
|
johabu = c;
|
|
st->state = WC_JOHAB_HANGUL1;
|
|
return NULL;
|
|
case WC_JOHAB_MAP_UH:
|
|
johabu = c;
|
|
st->state = WC_JOHAB_HANJA1;
|
|
return NULL;
|
|
case WC_JOHAB_MAP_C1:
|
|
break;
|
|
default:
|
|
Strcat_char(os, (char)c);
|
|
break;
|
|
}
|
|
break;
|
|
case WC_JOHAB_HANGUL1:
|
|
if (WC_JOHAB_MAP[c] & WC_JOHAB_MAP_LJ)
|
|
wtf_push(os, WC_CCS_JOHAB, ((wc_uint32)johabu << 8) | c);
|
|
break;
|
|
case WC_JOHAB_HANJA1:
|
|
if (WC_JOHAB_MAP[c] & WC_JOHAB_MAP_LH)
|
|
wtf_push(os, WC_CCS_JOHAB, ((wc_uint32)johabu << 8) | c);
|
|
break;
|
|
}
|
|
st->state = -1;
|
|
return os;
|
|
}
|