#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; }