/*
* hangul.c - $Revision: 1.14 $
*
* KoreanCodecs Hangul Module C Implementation
*
* Author : Hye-Shik Chang <perky@FreeBSD.org>
* Date : $Date: 2002/07/19 00:01:53 $
* Created : 25 April 2002
*
* This file is part of KoreanCodecs.
*
* KoreanCodecs is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* KoreanCodecs 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KoreanCodecs; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
static char *version =
"$Id: hangul.c,v 1.14 2002/07/19 00:01:53 perky Exp $";
#include "Python.h"
enum { /* Jaeum Codes on U+3100 */
G = 0x3131, GG, GS, N, NJ, NH, D, DD, L, LG, LM, LB,
LS, LT, LP, LH, M, B, BB, BS, S, SS, NG, J, JJ, C, K, T, P, H
};
enum { /* Moeum Codes on U+3100 */
A = 0x314f, AE, YA, YAE, EO, E, YEO, YE, O, WA, WAE, OE, YO,
U, WEO, WE, WI, YU, EU, YI, I
};
#define NCHOSUNG 19
#define NJUNGSUNG 21
#define NJONGSUNG 28
#define NJAEUM 30
#define NMOEUM 21
#define JAEUM_BOTTOM G
#define JAEUM_TOP H
#define MOEUM_BOTTOM A
#define MOEUM_TOP I
#define HANGUL_BOTTOM 0xac00
#define HANGUL_TOP 0xd7a3
#define JBASE_CHOSUNG 0x1100
#define JBASE_JUNGSUNG 0x1161
#define JBASE_JONGSUNG 0x11A8
#define CHOSUNG_FILLER 0x115f
#define JUNGSUNG_FILLER 0x1160
static PyObject *UniNull, *UniSpace;
static PyObject *ErrorObject;
#define MAX_MULTIJAMO 3
typedef struct _jamotype {
char *name;
Py_UNICODE code;
int multi[MAX_MULTIJAMO];
char orders[3]; /* cho, jung, jong */
} jamotype;
#define CODE(c) #c,c
#define NOMULTI {0,0,0}
#define J_C {0,-1,-1}
#define J_J {-1,-1,0}
#define J_CJ {0,-1,0}
#define M_J {-1,0,-1}
static jamotype jamos[] = {
/* JAEUM */
{ CODE(G), NOMULTI, J_CJ }, { CODE(GG), {G, G,}, J_CJ }, { CODE(GS), {G, S,}, J_J },
{ CODE(N), NOMULTI, J_CJ }, { CODE(NJ), {N, J,}, J_J }, { CODE(NH), {N, H,}, J_J },
{ CODE(D), NOMULTI, J_CJ }, { CODE(DD), {D, D,}, J_C }, { CODE(L), NOMULTI, J_CJ },
{ CODE(LG), {L, G,}, J_J }, { CODE(LM), {L, M,}, J_J }, { CODE(LB), {L, B,}, J_J },
{ CODE(LS), {L, S,}, J_J }, { CODE(LT), {L, T,}, J_J }, { CODE(LP), {L, P,}, J_J },
{ CODE(LH), {L, H,}, J_J }, { CODE(M), NOMULTI, J_CJ }, { CODE(B), NOMULTI, J_CJ },
{ CODE(BB), {B, B,}, J_C }, { CODE(BS), {B, S,}, J_J }, { CODE(S), NOMULTI, J_CJ },
{ CODE(SS), {S, S,}, J_CJ }, { CODE(NG), NOMULTI, J_CJ }, { CODE(J), NOMULTI, J_CJ },
{ CODE(JJ), {J, J,}, J_C }, { CODE(C), NOMULTI, J_CJ }, { CODE(K), NOMULTI, J_CJ },
{ CODE(T), NOMULTI, J_CJ }, { CODE(P), NOMULTI, J_CJ }, { CODE(H), NOMULTI, J_CJ },
/* MOEUM */
{ CODE(A), NOMULTI, M_J }, { CODE(AE), {A, I,}, M_J }, { CODE(YA), NOMULTI, M_J },
{ CODE(YAE), {YA,I}, M_J }, { CODE(EO), NOMULTI, M_J }, { CODE(E), NOMULTI, M_J },
{ CODE(YEO), NOMULTI, M_J }, { CODE(YE), {YEO,I}, M_J }, { CODE(O), NOMULTI, M_J },
{ CODE(WA), {O, A}, M_J }, { CODE(WAE), {O,A,I}, M_J }, { CODE(OE), {O, I}, M_J },
{ CODE(YO), NOMULTI, M_J }, { CODE(U), NOMULTI, M_J }, { CODE(WEO), {U, EO}, M_J },
{ CODE(WE), {U, E}, M_J }, { CODE(WI), {U, I}, M_J }, { CODE(YU), NOMULTI, M_J },
{ CODE(EU), NOMULTI, M_J }, { CODE(YI), {EU, I}, M_J }, { CODE(I), NOMULTI, M_J },
/* END MARKER */
{ 0, 0, NOMULTI, {0,} },
};
#undef NOMULTI
#undef CODE
static jamotype *jamo_chosung[NCHOSUNG], *jamo_jungsung[NJUNGSUNG], *jamo_jongsung[NJONGSUNG];
#define getJamotype(c) jamos[(c)-JAEUM_BOTTOM]
#define isJaeum(c) (JAEUM_BOTTOM <= (c) && (c) <= JAEUM_TOP)
#define isMoeum(c) (MOEUM_BOTTOM <= (c) && (c) <= MOEUM_TOP)
#define isHangulSyllable(c) (HANGUL_BOTTOM <= (c) && (c) <= HANGUL_TOP)
#define isChosung(c) (getJamotype(c).orders[0] >= 0)
#define isJungsung(c) (getJamotype(c).orders[1] >= 0)
#define isJongsung(c) (getJamotype(c).orders[2] >= 0)
#define getChosungOrder(c) (getJamotype(c).orders[0])
#define getJungsungOrder(c) (getJamotype(c).orders[1])
#define getJongsungOrder(c) (getJamotype(c).orders[2])
static char hangul_isJaeum__doc__[] = "isJaeum(code): Verify whether the code is Jaeum.";
static PyObject *
hangul_isJaeum(PyObject *self, PyObject *args)
{
Py_UNICODE *code;
int codelen, istrue = 0;
if (!PyArg_ParseTuple(args, "u#:isJaeum", &code, &codelen))
return NULL;
if (codelen)
for (istrue = 1; codelen--; code++)
if (!isJaeum(*code)) {
istrue = 0;
break;
}
if (istrue) {
Py_INCREF(Py_True);
return Py_True;
}
else {
Py_INCREF(Py_False);
return Py_False;
}
}
static char hangul_isMoeum__doc__[] = "isMoeum(code): Verify whether the code is Moeum.";
static PyObject *
hangul_isMoeum(PyObject *self, PyObject *args)
{
Py_UNICODE *code;
int codelen, istrue = 0;
if (!PyArg_ParseTuple(args, "u#:isMoeum", &code, &codelen))
return NULL;
if (codelen)
for (istrue = 1; codelen--; code++)
if (!isMoeum(*code)) {
istrue = 0;
break;
}
if (istrue) {
Py_INCREF(Py_True);
return Py_True;
}
else {
Py_INCREF(Py_False);
return Py_False;
}
}
static char hangul_ishangul__doc__[] = "ishangul(code): Verify whether the code is hangul.";
static PyObject *
hangul_ishangul(PyObject *self, PyObject *args)
{
Py_UNICODE *code;
int codelen, istrue = 0;
if (!PyArg_ParseTuple(args, "u#:ishangul", &code, &codelen))
return NULL;
if (codelen)
for (istrue = 1; codelen--; code++)
if (!(isHangulSyllable(*code) || isJaeum(*code) || isMoeum(*code))) {
istrue = 0;
break;
}
if (istrue) {
Py_INCREF(Py_True);
return Py_True;
}
else {
Py_INCREF(Py_False);
return Py_False;
}
}
static char hangul_join__doc__[] = "join([chosung, jungsung, jongsung]): Assemble hangul syllable from jamos.";
static PyObject *
hangul_join(PyObject *self, PyObject *args)
{
PyObject *argchar, *argelems[3];
Py_UNICODE elems[3], *uobj;
int i;
if (!PyArg_ParseTuple(args, "O:join", &argchar))
return NULL;
if (PyList_Check(argchar)) {
if (PyList_GET_SIZE(argchar) != 3)
goto argerr;
for (i = 0; i < 3; i ++)
argelems[i] = PyList_GET_ITEM(argchar, i);
}
else if (PyTuple_Check(argchar)) {
if (PyTuple_GET_SIZE(argchar) != 3)
goto argerr;
for (i = 0; i < 3; i ++)
argelems[i] = PyTuple_GET_ITEM(argchar, i);
}
else {
argerr: PyErr_Format(PyExc_ValueError, "need list or tuple with 3 unicode elements");
return NULL;
}
for (i = 0; i < 3; i ++) {
if ((uobj = PyUnicode_AsUnicode(argelems[i])) == NULL)
goto argerr;
if (PyUnicode_GET_SIZE(argelems[i]))
elems[i] = *uobj;
else
elems[i] = 0;
}
if ( (elems[0] && (!isJaeum(elems[0]) || !isChosung(elems[0]))) /* Chosung validity */
|| (elems[1] && (!isMoeum(elems[1]))) /* Jungsung validity */
|| (elems[2] && (!isJaeum(elems[2]) || !isJongsung(elems[2]))) ) {
PyErr_Format(ErrorObject, "not valid jamo combination");
return NULL;
}
if ((!elems[0] || !elems[1]) && elems[2]) {
PyErr_Format(ErrorObject, "trying to assemble character which "
"is not in unicode map");
return NULL;
}
else if (elems[0] && !elems[1]) {
Py_INCREF(argelems[0]);
return argelems[0];
}
else if (elems[1] && !elems[0]) {
Py_INCREF(argelems[1]);
return argelems[1];
}
else if (!elems[0]) { /* [Null, Null, Null] */
Py_INCREF(UniSpace);
return UniSpace;
}
else {
Py_UNICODE code;
code = ((getChosungOrder(elems[0]) * NJUNGSUNG) + getJungsungOrder(elems[1])) *
NJONGSUNG + (elems[2]?getJongsungOrder(elems[2]):0) + HANGUL_BOTTOM;
return PyUnicode_FromUnicode(&code, 1);
}
}
static char hangul_split__doc__[] = "split(code): Disassemble hangul syllable into jamos.";
static PyObject *
hangul_split(PyObject *self, PyObject *args)
{
Py_UNICODE *code;
PyObject *r;
int codelen;
if (!PyArg_ParseTuple(args, "u#:split", &code, &codelen))
return NULL;
if (codelen < 1) {
PyErr_Format(PyExc_ValueError, "need not null unicode string");
return NULL;
}
if (isHangulSyllable(*code)) {
Py_UNICODE cho, jung, jong;
PyObject *jongobj;
Py_UNICODE hseq, t;
hseq = *code - HANGUL_BOTTOM;
cho = jamo_chosung[hseq / (NJUNGSUNG*NJONGSUNG)]->code;
jung = jamo_jungsung[(hseq / NJONGSUNG) % NJUNGSUNG]->code;
if ((t = hseq % NJONGSUNG)) {
jong = jamo_jongsung[t]->code;
jongobj = PyUnicode_FromUnicode(&jong, 1);
} else {
jongobj = UniNull;
Py_INCREF(UniNull);
}
r = PyTuple_New(3);
PyTuple_SET_ITEM(r, 0, PyUnicode_FromUnicode(&cho, 1));
PyTuple_SET_ITEM(r, 1, PyUnicode_FromUnicode(&jung, 1));
PyTuple_SET_ITEM(r, 2, jongobj);
return r;
}
else if (isJaeum(*code)) {
r = PyTuple_New(3);
PyTuple_SET_ITEM(r, 0, PyUnicode_FromUnicode(code, 1));
PyTuple_SET_ITEM(r, 1, UniNull); Py_INCREF(UniNull);
PyTuple_SET_ITEM(r, 2, UniNull); Py_INCREF(UniNull);
return r;
}
else if (isMoeum(*code)) {
r = PyTuple_New(3);
PyTuple_SET_ITEM(r, 0, UniNull); Py_INCREF(UniNull);
PyTuple_SET_ITEM(r, 1, PyUnicode_FromUnicode(code, 1));
PyTuple_SET_ITEM(r, 2, UniNull); Py_INCREF(UniNull);
return r;
}
else {
PyErr_Format(ErrorObject, "not a hangul code");
return NULL;
}
}
static char hangul_conjoin__doc__[] = "conjoin(unicodestring): conjoin unicode johab string into unicode syllable string";
static PyObject *
hangul_conjoin(PyObject *self, PyObject *args)
{
PyObject *r;
Py_UNICODE *code, *dst, *dstorg, c;
int cho, jung, jong;
int codelen, i;
if (!PyArg_ParseTuple(args, "u#:conjoin", &code, &codelen))
return NULL;
dstorg = dst = PyMem_New(Py_UNICODE, codelen);
for (i = 0; i < codelen; i++) {
c = code[i];
if ((JBASE_CHOSUNG <= c && c <= 0x1112) || c == CHOSUNG_FILLER) {
if (codelen > i+1 && JUNGSUNG_FILLER <= code[i+1] && code[i+1] <= 0x1175) {
if (c == CHOSUNG_FILLER) cho = -1;
else cho = c - JBASE_CHOSUNG;
if (code[i+1] == JUNGSUNG_FILLER) jung = -1;
else jung = code[i+1] - JBASE_JUNGSUNG;
if (codelen > i+2 && JBASE_JONGSUNG <= code[i+2] && code[i+2] <= 0x11c2) {
jong = code[i+2] - JBASE_JONGSUNG + 1;
i += 2;
}
else {
jong = 0; i++;
}
if (jong && (cho == -1 || jung == -1)) { /* can't trans to syllable */
if (cho >= 0) *(dst++) = jamo_chosung[cho]->code;
if (jung >= 0) *(dst++) = jamo_jungsung[jung]->code;
*(dst++) = jamo_jongsung[jong]->code;
}
else if (cho == -1) /* jungsung only */
*(dst++) = jamo_jungsung[jung]->code;
else if (jung == -1) /* chosung only */
*(dst++) = jamo_chosung[cho]->code;
else /* full set */
*(dst++) = HANGUL_BOTTOM + (cho * NJUNGSUNG + jung) * NJONGSUNG + jong;
}
else if (c != CHOSUNG_FILLER) /* chosung only */
*(dst++) = jamo_chosung[c-JBASE_CHOSUNG]->code;
}
else if (JBASE_JUNGSUNG <= c && c <= 0x1175) /* jungsung only */
*(dst++) = jamo_jungsung[c-JBASE_JUNGSUNG]->code;
else
*(dst++) = c;
}
r = PyUnicode_FromUnicode(dstorg, dst-dstorg);
PyMem_Del(dstorg);
return r;
}
static char hangul_disjoint__doc__[] = "disjoint(unicodestring): disjoint unicode syllable string into unicode johab string";
static PyObject *
hangul_disjoint(PyObject *self, PyObject *args)
{
Py_UNICODE *code, *dst, *dstorg, c;
PyObject *r;
int codelen, i;
if (!PyArg_ParseTuple(args, "u#:split", &code, &codelen))
return NULL;
dstorg = dst = PyMem_New(Py_UNICODE, codelen*3);
for (i = 0; i < codelen; i++) {
c = code[i];
if (isHangulSyllable(c)) {
int hseq;
Py_UNICODE jong;
hseq = c - HANGUL_BOTTOM;
jong = hseq % NJONGSUNG;
*(dst++) = hseq / (NJUNGSUNG * NJONGSUNG) + JBASE_CHOSUNG;
*(dst++) = (hseq / NJONGSUNG) % NJUNGSUNG + JBASE_JUNGSUNG;
if (jong)
*(dst++) = jong + JBASE_JONGSUNG - 1;
}
else if (isJaeum(c) && isChosung(c)) {
*(dst++) = getChosungOrder(c) + JBASE_CHOSUNG;
*(dst++) = JUNGSUNG_FILLER;
}
else if (isMoeum(c)) {
*(dst++) = CHOSUNG_FILLER;
*(dst++) = getJungsungOrder(c) + JBASE_JUNGSUNG;
} else
*(dst++) = c;
}
r = PyUnicode_FromUnicode(dstorg, dst-dstorg);
PyMem_Del(dstorg);
return r;
}
static char pseudofinal[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 2 */
1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 3 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, /* 4 */
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 5 */
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 6 */
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
};
static char hangul_format__doc__[] = "format(fmt, arg1, arg2, ...) or format(fmt, kw1=arg1, kw2=arg2"
", ...):\nformat unicode string and fix korean suffixes after arguments";
static PyObject *
hangul_format(PyObject *self, PyObject *args, PyObject *kwargs)
{
/*--- Poor Structure of this function ;)
hangul_format(fmt, *args, **kwargs)
-> insert end fmtmarkers(U+115E which is not used by Unicode) after every format position
-> PyUnicode_Format
-> Fix and update hangul suffixes in place of fmtmarkers
-> make PyObject and return.
*/
#define FMTMARKER 0x115E
Py_UNICODE *fmt, *fmtout, *fcur;
PyObject *r;
int fmtsize;
int inpth, infmt, escape;
{
PyObject *fmtobj;
int argsize;
argsize = PyTuple_GET_SIZE(args);
if (!argsize || !PyUnicode_Check(fmtobj = PyTuple_GET_ITEM(args, 0))) {
PyErr_Format(PyExc_TypeError, "needs unicode format string.");
return NULL;
}
fmtsize = PyUnicode_GET_SIZE(fmtobj);
fmt = PyUnicode_AS_UNICODE(fmtobj);
if (!kwargs)
args = PyTuple_GetSlice(args, 1, argsize);
}
fmtout = PyMem_New(Py_UNICODE, fmtsize + fmtsize/2);
inpth = infmt = escape = 0;
for (fcur = fmtout; fmtsize--; fmt++) {
if (*fmt != FMTMARKER) /* skip bogus markers */
*(fcur++) = *fmt;
if (escape)
escape = 0;
else if (*fmt == '\\')
escape = 1;
else if (infmt) {
if (!inpth && (('A' <= *fmt && *fmt <= 'Z') || ('a' <= *fmt && *fmt <= 'z'))) {
*(fcur++) = FMTMARKER;
infmt = 0;
}
else if (inpth && *fmt == ')')
inpth = 0;
else if (*fmt == '(')
inpth = 1;
else if (*fmt == '%')
infmt = 0;
}
else if (*fmt == '%')
infmt = 1;
}
r = PyUnicode_Format(
PyUnicode_FromUnicode(fmtout, fcur-fmtout),
kwargs?kwargs:args
);
if (!kwargs) {
Py_DECREF(args);
} /* {} to avoid gcc warning */
if (!r)
goto out;
fmt = PyUnicode_AS_UNICODE(r);
fmtsize = PyUnicode_GET_SIZE(r);
#define HAS_FINAL() ( \
(past = *(fmt-1)), \
isHangulSyllable(past) ? \
((past-HANGUL_BOTTOM) % NJONGSUNG > 0) \
: (past < 0x80 ? pseudofinal[past] : 0) \
)
#define HAS_FINAL_OR_NOTSYL() ( \
(past = *(fmt-1)), \
isHangulSyllable(past) ? \
((past-HANGUL_BOTTOM) % NJONGSUNG > 0) \
: 1 \
)
#define PROCESSSUFFIX(nofinal, existfinal) \
if (next == nofinal || next == existfinal) { \
*(fcur++) = HAS_FINAL() ? (existfinal) : (nofinal); \
fmtsize--; fmt++; \
}
#define PROCESSSUFFIX_IDA(jongsungadder, existfinal) \
if (next == existfinal) { \
if (HAS_FINAL_OR_NOTSYL()) \
*(fcur++) = existfinal; \
else \
*(fcur-1) += jongsungadder; \
fmtsize-=3; fmt+=3; \
}
for (fcur = fmtout; fmtsize--; fmt++) {
if (*fmt == FMTMARKER) {
if (fcur > fmtout && fmtsize > 0) {
Py_UNICODE past, next = *(fmt+1);
if (next == '(' && fmtsize > 2 && *(fmt+3) == ')') { /* ida suffxes */
next = *(fmt+2);
PROCESSSUFFIX_IDA(0, 0xc774) /* (I)DA */
else PROCESSSUFFIX_IDA(17, 0xc785) /* (IP)NIDA */
else PROCESSSUFFIX_IDA(4, 0xc778) /* (IN)- */
}
else if (0xac00 <= next && next <= 0xc774) {
PROCESSSUFFIX(0xb97c, 0xc744) /* REUL, EUL */
else PROCESSSUFFIX(0xb294, 0xc740) /* NEUN, EUN */
else PROCESSSUFFIX(0xac00, 0xc774) /* GA, I */
else PROCESSSUFFIX(0xc640, 0xacfc) /* WA, GWA */
}
}
}
else
*(fcur++) = *fmt;
}
/* these were written separatedly for win32 compilers */
#undef PROCESSSUFFIX
#undef PROCESSSUFFIX_IDA
#undef HAS_FINAL
#undef HAS_FINAL_OR_NOTSYL
Py_DECREF(r);
r = PyUnicode_FromUnicode(fmtout, fcur-fmtout);
out:
PyMem_Free(fmtout);
return r;
}
/* List of methods defined in the module */
#define meth(name, func, doc) {name, (PyCFunction)func, METH_VARARGS, doc}
#define meth_kw(name, func, doc) {name, (PyCFunction)func, METH_VARARGS|METH_KEYWORDS, doc}
static struct PyMethodDef hangul_methods[] = {
meth("isJaeum", hangul_isJaeum, hangul_isJaeum__doc__),
meth("isMoeum", hangul_isMoeum, hangul_isMoeum__doc__),
meth("ishangul", hangul_ishangul, hangul_ishangul__doc__),
meth("join", hangul_join, hangul_join__doc__),
meth("split", hangul_split, hangul_split__doc__),
meth("conjoin", hangul_conjoin, hangul_conjoin__doc__),
meth("disjoint", hangul_disjoint, hangul_disjoint__doc__),
meth_kw("format", hangul_format, hangul_format__doc__),
{NULL, NULL},
};
#define SET_INTCONSTANT(dict, value) \
PyDict_SetItemString(dict, #value, PyInt_FromLong((long) value))
#define SET_STRCONSTANT(dict, value) \
PyDict_SetItemString(dict, #value, PyString_FromString(value))
#define SET_CHARCONSTANT(dict, value) \
PyDict_SetItemString(dict, #value, PyString_FromFormat("%c", value))
/* Initialization function for the module */
void
inithangul(void)
{
PyObject *m, *d, *tmp;
Py_UNICODE tuni[2];
int i;
/* Create the module and add the functions */
m = Py_InitModule("hangul", hangul_methods);
UniNull = PyUnicode_FromUnicode(NULL, 0);
tuni[0] = 0x3000; /* Unicode Double-wide Space */
UniSpace = PyUnicode_FromUnicode(tuni, 1);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
SET_INTCONSTANT(d, NCHOSUNG);
SET_INTCONSTANT(d, NJUNGSUNG);
SET_INTCONSTANT(d, NJONGSUNG);
{
PyObject *Chosung, *Jungsung, *Jongsung;
PyObject *Jaeum, *Moeum;
PyObject *JaeumDict, *MoeumDict;
PyObject *JaeumCodes, *MoeumCodes;
PyObject *JaeumMulti, *MoeumMulti;
int cur_cho, cur_jung, cur_jong;
int cur_jaeum, cur_moeum;
jamotype *jamo;
/* Bind Chosung, Jungsung, Jongsung lists */
cur_cho = cur_jung = cur_jong = 0;
Chosung = PyList_New(NCHOSUNG);
Jungsung = PyList_New(NJUNGSUNG);
Jongsung = PyList_New(NJONGSUNG);
PyDict_SetItemString(d, "Chosung", Chosung);
PyDict_SetItemString(d, "Jungsung", Jungsung);
PyDict_SetItemString(d, "Jongsung", Jongsung);
jamo_jongsung[cur_jong] = NULL;
Py_INCREF(UniNull);
PyList_SET_ITEM(Jongsung, cur_jong++, UniNull);
/* Create Jaeum and Moeum meta class */
JaeumDict = PyDict_New();
MoeumDict = PyDict_New();
tmp = PyString_FromString("Jaeum");
Jaeum = PyClass_New(NULL, JaeumDict, tmp);
Py_DECREF(tmp);
tmp = PyString_FromString("Moeum");
Moeum = PyClass_New(NULL, MoeumDict, tmp);
Py_DECREF(tmp);
/* Bind meta class members */
PyDict_SetItemString(d, "Jaeum", Jaeum);
PyDict_SetItemString(d, "Moeum", Moeum);
PyDict_SetItemString(JaeumDict, "Chosung", Chosung);
PyDict_SetItemString(MoeumDict, "Jungsung", Jungsung);
PyDict_SetItemString(JaeumDict, "Jongsung", Jongsung);
/* Create Jaeum and Moeum Members */
JaeumCodes = PyTuple_New(NJAEUM);
MoeumCodes = PyTuple_New(NMOEUM);
JaeumMulti = PyDict_New();
MoeumMulti = PyDict_New();
cur_jaeum = cur_moeum = 0;
PyDict_SetItemString(JaeumDict, "Codes", JaeumCodes);
PyDict_SetItemString(MoeumDict, "Codes", MoeumCodes);
PyDict_SetItemString(JaeumDict, "Width", PyInt_FromLong(NJAEUM));
PyDict_SetItemString(MoeumDict, "Width", PyInt_FromLong(NMOEUM));
PyDict_SetItemString(JaeumDict, "MultiElement", JaeumMulti);
PyDict_SetItemString(MoeumDict, "MultiElement", MoeumMulti);
for (jamo = jamos; jamo->name; jamo++) {
PyObject *unijamo, *multicls;
int tuplen;
tuni[0] = jamo->code;
unijamo = PyUnicode_FromUnicode(tuni, 1);
PyDict_SetItemString(d, jamo->name, unijamo);
if (isJaeum(jamo->code)) {
PyTuple_SET_ITEM(JaeumCodes, cur_jaeum++, unijamo);
Py_INCREF(unijamo);
if (isChosung(jamo->code)) {
jamo->orders[0] = cur_cho;
jamo_chosung[cur_cho] = jamo;
PyList_SET_ITEM(Chosung, cur_cho++, unijamo);
Py_INCREF(unijamo);
PyDict_SetItemString(JaeumDict, jamo->name, unijamo);
}
if (isJongsung(jamo->code)) {
jamo->orders[2] = cur_jong;
jamo_jongsung[cur_jong] = jamo;
PyList_SET_ITEM(Jongsung, cur_jong++, unijamo);
Py_INCREF(unijamo);
PyDict_SetItemString(JaeumDict, jamo->name, unijamo);
}
multicls = JaeumMulti;
}
else { /* Moeum */
PyTuple_SET_ITEM(MoeumCodes, cur_moeum++, unijamo);
Py_INCREF(unijamo);
if (isJungsung(jamo->code)) {
jamo->orders[1] = cur_jung;
jamo_jungsung[cur_jung] = jamo;
PyList_SET_ITEM(Jungsung, cur_jung++, unijamo);
Py_INCREF(unijamo);
PyDict_SetItemString(MoeumDict, jamo->name, unijamo);
}
multicls = MoeumMulti;
}
if (jamo->multi[0]) {
tuplen = jamo->multi[2] ? 3 : 2;
tmp = PyTuple_New(tuplen);
for (i = 0; i < tuplen; i++) {
tuni[0] = jamo->multi[i];
PyTuple_SET_ITEM(tmp, i, PyUnicode_FromUnicode(tuni, 1));
}
PyDict_SetItem(multicls, unijamo, tmp);
Py_DECREF(tmp);
}
Py_DECREF(unijamo);
}
Py_DECREF(Chosung); Py_DECREF(Jungsung); Py_DECREF(Jongsung);
Py_DECREF(JaeumDict); Py_DECREF(MoeumDict);
Py_DECREF(JaeumCodes); Py_DECREF(MoeumCodes);
Py_DECREF(JaeumMulti); Py_DECREF(MoeumMulti);
}
tmp = PyTuple_New(2);
tuni[0] = HANGUL_BOTTOM;
PyTuple_SET_ITEM(tmp, 0, PyUnicode_FromUnicode(tuni, 1));
tuni[0] = HANGUL_TOP;
PyTuple_SET_ITEM(tmp, 1, PyUnicode_FromUnicode(tuni, 1));
PyDict_SetItemString(d, "ZONE", tmp);
Py_DECREF(tmp);
tuni[0] = JBASE_CHOSUNG;
PyDict_SetItemString(d, "JBASE_CHOSUNG", PyUnicode_FromUnicode(tuni, 1));
tuni[0] = JBASE_JUNGSUNG;
PyDict_SetItemString(d, "JBASE_JUNGSUNG", PyUnicode_FromUnicode(tuni, 1));
tuni[0] = JBASE_JONGSUNG;
PyDict_SetItemString(d, "JBASE_JONGSUNG", PyUnicode_FromUnicode(tuni, 1));
tuni[0] = CHOSUNG_FILLER;
PyDict_SetItemString(d, "CHOSUNG_FILLER", PyUnicode_FromUnicode(tuni, 1));
tuni[0] = JUNGSUNG_FILLER;
PyDict_SetItemString(d, "JUNGSUNG_FILLER", PyUnicode_FromUnicode(tuni, 1));
PyDict_SetItemString(d, "Null", UniNull);
PyDict_SetItemString(d, "Space", UniSpace);
PyDict_SetItemString(d, "version", PyString_FromString(version));
ErrorObject = PyErr_NewException("hangul.UnicodeHangulError", NULL, NULL);
PyDict_SetItemString(d, "UnicodeHangulError", ErrorObject);
Py_DECREF(ErrorObject);
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize the hangul module");
}
syntax highlighted by Code2HTML, v. 0.9.1