Initial revision
authorChoe Hwanjin <choe.hwanjin@gmail.com>
Mon, 8 Nov 2004 11:39:11 +0000 (20:39 +0900)
committerChoe Hwanjin <choe.hwanjin@gmail.com>
Mon, 8 Nov 2004 11:39:11 +0000 (20:39 +0900)
git-svn-id: http://kldp.net/svn/hangul/trunk/hangul@3 8f00fcd2-89fc-0310-932e-b01be5b65e01

17 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
configure.ac [new file with mode: 0644]
hangul/Makefile.am [new file with mode: 0644]
hangul/hangul.h [new file with mode: 0644]
hangul/hangulctype.c [new file with mode: 0644]
hangul/hangulinputcontext.c [new file with mode: 0644]
hangul/hangulkeyboard.h [new file with mode: 0644]
pyhangul/Makefile [new file with mode: 0644]
pyhangul/pyhangul.c [new file with mode: 0644]
pyhangul/setup.py [new file with mode: 0644]
test/Makefile.am [new file with mode: 0644]
test/test.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..bc93913
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Choe Hwanjin <krisna (at) kldp.org>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..2a149e1
--- /dev/null
@@ -0,0 +1,6 @@
+SUBDIRS = hangul test
+
+EXTRA_DIST = \
+    pyhangul/Makefile \
+    pyhangul/pyhangul.c \
+    pyhangul/setup.py
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..8cf0191
--- /dev/null
@@ -0,0 +1,30 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.57)
+AC_INIT(libhangul, 0.0.1, http://kldp.net/projects/hangul/)
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([hangul/hangul.h])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_RANLIB
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_CHECK_HEADERS([locale.h stdint.h stdlib.h string.h wchar.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_C_CONST
+AC_C_INLINE
+
+# Checks for library functions.
+AC_CONFIG_FILES([
+Makefile
+hangul/Makefile
+test/Makefile
+])
+AC_OUTPUT
diff --git a/hangul/Makefile.am b/hangul/Makefile.am
new file mode 100644 (file)
index 0000000..da7bae0
--- /dev/null
@@ -0,0 +1,12 @@
+
+noinst_LIBRARIES = libhangul.a
+
+libhangul_a_CFLAGS =
+
+libhangul_a_SOURCES = \
+       hangulctype.c \
+       hangulinputcontext.c \
+       hangulkeyboard.h \
+       hangul.h
+
+libhangul_a_LIBADD =
diff --git a/hangul/hangul.h b/hangul/hangul.h
new file mode 100644 (file)
index 0000000..500a83e
--- /dev/null
@@ -0,0 +1,116 @@
+/* libhangul
+ * Copyright (C) 2004 Choe Hwanjin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _HANGUL_H_
+#define _HANGUL_H_
+
+#include <wchar.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* hangulctype.c */
+enum {
+    HANGUL_CHOSEONG_FILLER  = 0x115f,   /* hangul choseong filler */
+    HANGUL_JUNGSEONG_FILLER = 0x1160    /* hangul jungseong filler */
+};
+
+bool hangul_is_choseong(wchar_t ch);
+bool hangul_is_jungseong(wchar_t ch);
+bool hangul_is_jongseong(wchar_t ch);
+
+wchar_t hangul_choseong_to_cjamo(wchar_t ch);
+wchar_t hangul_jungseong_to_cjamo(wchar_t ch);
+wchar_t hangul_jongseong_to_cjamo(wchar_t ch);
+
+wchar_t hangul_choseong_to_jongseong(wchar_t ch);
+wchar_t hangul_jongseong_to_choseong(wchar_t ch);
+void    hangul_jongseong_dicompose(wchar_t ch, wchar_t* jong, wchar_t* cho);
+
+wchar_t hangul_jamo_to_syllable(wchar_t choseong,
+                               wchar_t jungseong,
+                               wchar_t jongseong);
+
+/* hangulinputcontext.c */
+typedef struct _HangulJamoCombination HangulJamoCombination;
+typedef struct _HangulBuffer HangulBuffer;
+typedef struct _HangulInputContext HangulInputContext;
+
+enum {
+    HANGUL_KEYBOARD_2,
+    HANGUL_KEYBOARD_32,
+    HANGUL_KEYBOARD_3FINAL,
+    HANGUL_KEYBOARD_390,
+    HANGUL_KEYBOARD_3NOSHIFT
+};
+
+enum {
+    HANGUL_OUTPUT_SYLLABLE,
+    HANGUL_OUTPUT_JAMO
+};
+
+enum {
+    HANGUL_INPUT_FILTER_2,
+    HANGUL_INPUT_FILTER_3
+};
+
+struct _HangulJamoCombination {
+    uint32_t key;
+    wchar_t code;
+};
+
+struct _HangulBuffer {
+    wchar_t choseong;
+    wchar_t jungseong;
+    wchar_t jongseong;
+
+    wchar_t stack[12];
+    int     index;
+};
+
+struct _HangulInputContext {
+    int type;
+    const wchar_t *keyboard_table;
+    const HangulJamoCombination *combination_table;
+    int combination_table_size;
+    HangulBuffer buffer;
+    int output_mode;
+
+    wchar_t preedit_string[64];
+    wchar_t commit_string[64];
+};
+
+HangulInputContext* hangul_ic_new(int keyboard);
+void hangul_ic_delete(HangulInputContext *hic);
+bool hangul_ic_filter(HangulInputContext *hic, int ascii, bool capslock);
+void hangul_ic_reset(HangulInputContext *hic);
+bool hangul_ic_backspace(HangulInputContext *hic);
+
+void hangul_ic_set_output_mode(HangulInputContext *hic, int mode);
+void hangul_ic_set_keyboard(HangulInputContext *hic, int keyboard);
+const wchar_t* hangul_ic_get_preedit_string(HangulInputContext *hic);
+const wchar_t* hangul_ic_get_commit_string(HangulInputContext *hic);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HANGUL_H_ */
diff --git a/hangul/hangulctype.c b/hangul/hangulctype.c
new file mode 100644 (file)
index 0000000..915b941
--- /dev/null
@@ -0,0 +1,277 @@
+/* libhangul
+ * Copyright (C) 2004 Choe Hwanjin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <wchar.h>
+
+#include "hangul.h"
+
+bool
+hangul_is_choseong(wchar_t ch)
+{
+    return ch >= 0x1100 && ch <= 0x1159;
+}
+
+bool
+hangul_is_jungseong(wchar_t ch)
+{
+    return ch >= 0x1161 && ch <= 0x11a2;
+}
+
+bool
+hangul_is_jongseong(wchar_t ch)
+{
+    return ch >= 0x11a7 && ch <= 0x11f9;
+}
+
+wchar_t
+hangul_choseong_to_cjamo(wchar_t ch)
+{
+    static wchar_t table[] = {
+       0x3131,     /* 0x1100 */
+       0x3132,     /* 0x1101 */
+       0x3134,     /* 0x1102 */
+       0x3137,     /* 0x1103 */
+       0x3138,     /* 0x1104 */
+       0x3139,     /* 0x1105 */
+       0x3141,     /* 0x1106 */
+       0x3142,     /* 0x1107 */
+       0x3143,     /* 0x1108 */
+       0x3145,     /* 0x1109 */
+       0x3146,     /* 0x110a */
+       0x3147,     /* 0x110b */
+       0x3148,     /* 0x110c */
+       0x3149,     /* 0x110d */
+       0x314a,     /* 0x110e */
+       0x314b,     /* 0x110f */
+       0x314c,     /* 0x1110 */
+       0x314d,     /* 0x1111 */
+       0x314e,     /* 0x1112 */
+    };
+
+    if (ch < 0x1100 || ch > 0x1112)
+       return ch;
+    return table[ch - 0x1100];
+}
+
+wchar_t
+hangul_jungseong_to_cjamo(wchar_t ch)
+{
+    static wchar_t table[] = {
+       0x314f,     /* 0x1161 */
+       0x3150,     /* 0x1162 */
+       0x3151,     /* 0x1163 */
+       0x3152,     /* 0x1164 */
+       0x3153,     /* 0x1165 */
+       0x3154,     /* 0x1166 */
+       0x3155,     /* 0x1167 */
+       0x3156,     /* 0x1168 */
+       0x3157,     /* 0x1169 */
+       0x3158,     /* 0x116a */
+       0x3159,     /* 0x116b */
+       0x315a,     /* 0x116c */
+       0x315b,     /* 0x116d */
+       0x315c,     /* 0x116e */
+       0x315d,     /* 0x116f */
+       0x315e,     /* 0x1170 */
+       0x315f,     /* 0x1171 */
+       0x3160,     /* 0x1172 */
+       0x3161,     /* 0x1173 */
+       0x3162,     /* 0x1174 */
+       0x3163      /* 0x1175 */
+    };
+
+    if (ch < 0x1161 || ch > 0x1175)
+       return 0;
+    return table[ch - 0x1161];
+}
+
+wchar_t
+hangul_jongseong_to_cjamo(wchar_t ch)
+{
+    static wchar_t table[] = {
+       0x3131,     /* 0x11a8 */
+       0x3132,     /* 0x11a9 */
+       0x3133,     /* 0x11aa */
+       0x3134,     /* 0x11ab */
+       0x3135,     /* 0x11ac */
+       0x3136,     /* 0x11ad */
+       0x3137,     /* 0x11ae */
+       0x3139,     /* 0x11af */
+       0x313a,     /* 0x11b0 */
+       0x313b,     /* 0x11b1 */
+       0x313c,     /* 0x11b2 */
+       0x313d,     /* 0x11b3 */
+       0x313e,     /* 0x11b4 */
+       0x313f,     /* 0x11b5 */
+       0x3140,     /* 0x11b6 */
+       0x3141,     /* 0x11b7 */
+       0x3142,     /* 0x11b8 */
+       0x3144,     /* 0x11b9 */
+       0x3145,     /* 0x11ba */
+       0x3146,     /* 0x11bb */
+       0x3147,     /* 0x11bc */
+       0x3148,     /* 0x11bd */
+       0x314a,     /* 0x11be */
+       0x314b,     /* 0x11bf */
+       0x314c,     /* 0x11c0 */
+       0x314d,     /* 0x11c1 */
+       0x314e      /* 0x11c2 */
+    };
+
+    if (ch < 0x11a8 || ch > 0x11c2)
+       return 0;
+    return table[ch - 0x11a8];
+}
+
+wchar_t
+hangul_choseong_to_jongseong(wchar_t ch)
+{
+    static wchar_t table[] = {
+       0x11a8,  /* choseong kiyeok      -> jongseong kiyeok      */
+       0x11a9,  /* choseong ssangkiyeok -> jongseong ssangkiyeok */
+       0x11ab,  /* choseong nieun       -> jongseong nieun       */
+       0x11ae,  /* choseong tikeut      -> jongseong tikeut      */
+       0x0,     /* choseong ssangtikeut -> jongseong tikeut      */
+       0x11af,  /* choseong rieul       -> jongseong rieul       */
+       0x11b7,  /* choseong mieum       -> jongseong mieum       */
+       0x11b8,  /* choseong pieup       -> jongseong pieup       */
+       0x0,     /* choseong ssangpieup  -> jongseong pieup       */
+       0x11ba,  /* choseong sios        -> jongseong sios        */
+       0x11bb,  /* choseong ssangsios   -> jongseong ssangsios   */
+       0x11bc,  /* choseong ieung       -> jongseong ieung       */
+       0x11bd,  /* choseong cieuc       -> jongseong cieuc       */
+       0x0,     /* choseong ssangcieuc  -> jongseong cieuc       */
+       0x11be,  /* choseong chieuch     -> jongseong chieuch     */
+       0x11bf,  /* choseong khieukh     -> jongseong khieukh     */
+       0x11c0,  /* choseong thieuth     -> jongseong thieuth     */
+       0x11c1,  /* choseong phieuph     -> jongseong phieuph     */
+       0x11c2   /* choseong hieuh       -> jongseong hieuh       */
+    };
+    if (ch < 0x1100 || ch > 0x1112)
+       return 0;
+    return table[ch - 0x1100];
+}
+
+wchar_t
+hangul_jongseong_to_choseong(wchar_t ch)
+{
+    static wchar_t table[] = {
+      0x1100,  /* jongseong kiyeok        -> choseong kiyeok       */
+      0x1101,  /* jongseong ssangkiyeok   -> choseong ssangkiyeok  */
+      0x1109,  /* jongseong kiyeok-sios   -> choseong sios         */
+      0x1102,  /* jongseong nieun         -> choseong nieun        */
+      0x110c,  /* jongseong nieun-cieuc   -> choseong cieuc        */
+      0x1112,  /* jongseong nieun-hieuh   -> choseong hieuh        */
+      0x1103,  /* jongseong tikeut        -> choseong tikeut       */
+      0x1105,  /* jongseong rieul         -> choseong rieul        */
+      0x1100,  /* jongseong rieul-kiyeok  -> choseong kiyeok       */
+      0x1106,  /* jongseong rieul-mieum   -> choseong mieum        */
+      0x1107,  /* jongseong rieul-pieup   -> choseong pieup        */
+      0x1109,  /* jongseong rieul-sios    -> choseong sios         */
+      0x1110,  /* jongseong rieul-thieuth -> choseong thieuth      */
+      0x1111,  /* jongseong rieul-phieuph -> choseong phieuph      */
+      0x1112,  /* jongseong rieul-hieuh   -> choseong hieuh        */
+      0x1106,  /* jongseong mieum         -> choseong mieum        */
+      0x1107,  /* jongseong pieup         -> choseong pieup        */
+      0x1109,  /* jongseong pieup-sios    -> choseong sios         */
+      0x1109,  /* jongseong sios          -> choseong sios         */
+      0x110a,  /* jongseong ssangsios     -> choseong ssangsios    */
+      0x110b,  /* jongseong ieung         -> choseong ieung        */
+      0x110c,  /* jongseong cieuc         -> choseong cieuc        */
+      0x110e,  /* jongseong chieuch       -> choseong chieuch      */
+      0x110f,  /* jongseong khieukh       -> choseong khieukh      */
+      0x1110,  /* jongseong thieuth       -> choseong thieuth      */
+      0x1111,  /* jongseong phieuph       -> choseong phieuph      */
+      0x1112   /* jongseong hieuh         -> choseong hieuh        */
+    };
+    if (ch < 0x11a8 || ch > 0x11c2)
+       return 0;
+    return table[ch - 0x11a8];
+}
+
+void
+hangul_jongseong_dicompose(wchar_t ch, wchar_t* jong, wchar_t* cho)
+{
+    static wchar_t table[][2] = {
+    { 0,      0x1100 }, /* jong kiyeok       = cho  kiyeok               */
+    { 0x11a8, 0x1100 }, /* jong ssangkiyeok   = jong kiyeok + cho kiyeok  */
+    { 0x11a8, 0x1109 }, /* jong kiyeok-sios   = jong kiyeok + cho sios    */
+    { 0,      0x1102 }, /* jong nieun        = cho  nieun                */
+    { 0x11ab, 0x110c }, /* jong nieun-cieuc   = jong nieun  + cho cieuc   */
+    { 0x11ab, 0x1112 }, /* jong nieun-hieuh   = jong nieun  + cho hieuh   */
+    { 0,      0x1103 }, /* jong tikeut       = cho  tikeut               */
+    { 0,      0x1105 }, /* jong rieul         = cho  rieul                */
+    { 0x11af, 0x1100 }, /* jong rieul-kiyeok  = jong rieul  + cho kiyeok  */
+    { 0x11af, 0x1106 }, /* jong rieul-mieum   = jong rieul  + cho mieum   */
+    { 0x11af, 0x1107 }, /* jong rieul-pieup   = jong rieul  + cho pieup   */
+    { 0x11af, 0x1109 }, /* jong rieul-sios    = jong rieul  + cho sios    */
+    { 0x11af, 0x1110 }, /* jong rieul-thieuth = jong rieul  + cho thieuth */
+    { 0x11af, 0x1111 }, /* jong rieul-phieuph = jong rieul  + cho phieuph */
+    { 0x11af, 0x1112 }, /* jong rieul-hieuh   = jong rieul  + cho hieuh   */
+    { 0,      0x1106 }, /* jong mieum         = cho  mieum                */
+    { 0,      0x1107 }, /* jong pieup         = cho  pieup                */
+    { 0x11b8, 0x1109 }, /* jong pieup-sios    = jong pieup  + cho sios    */
+    { 0,      0x1109 }, /* jong sios          = cho  sios                 */
+    { 0x11ba, 0x1109 }, /* jong ssangsios     = jong sios   + cho sios    */
+    { 0,      0x110b }, /* jong ieung         = cho  ieung                */
+    { 0,      0x110c }, /* jong cieuc         = cho  cieuc                */
+    { 0,      0x110e }, /* jong chieuch       = cho  chieuch              */
+    { 0,      0x110f }, /* jong khieukh       = cho  khieukh              */
+    { 0,      0x1110 }, /* jong thieuth       = cho  thieuth              */
+    { 0,      0x1111 }, /* jong phieuph       = cho  phieuph              */
+    { 0,      0x1112 }  /* jong hieuh         = cho  hieuh                */
+    };
+
+    *jong = table[ch - 0x11a8][0];
+    *cho  = table[ch - 0x11a8][1];
+}
+
+wchar_t
+hangul_jamo_to_syllable(wchar_t choseong, wchar_t jungseong, wchar_t jongseong)
+{
+    static wchar_t hangul_base    = 0xac00;
+    static wchar_t choseong_base  = 0x1100;
+    static wchar_t jungseong_base = 0x1161;
+    static wchar_t jongseong_base = 0x11a7;
+    static int njungseong = 21;
+    static int njongseong = 28;
+    wchar_t ch;
+
+    /* we use 0x11a7 like a Jongseong filler */
+    if (jongseong == 0)
+       jongseong = 0x11a7;         /* Jongseong filler */
+
+    if (!(choseong  >= 0x1100 && choseong  <= 0x1112))
+       return 0;
+    if (!(jungseong >= 0x1161 && jungseong <= 0x1175))
+       return 0;
+    if (!(jongseong >= 0x11a7 && jongseong <= 0x11c2))
+       return 0;
+
+    choseong  -= choseong_base;
+    jungseong -= jungseong_base;
+    jongseong -= jongseong_base;
+
+    ch = ((choseong * njungseong) + jungseong) * njongseong + jongseong
+       + hangul_base;
+    return ch;
+}
diff --git a/hangul/hangulinputcontext.c b/hangul/hangulinputcontext.c
new file mode 100644 (file)
index 0000000..4ee4cc3
--- /dev/null
@@ -0,0 +1,585 @@
+/* libhangul
+ * Copyright (C) 2004 Choe Hwanjin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "hangul.h"
+#include "hangulkeyboard.h"
+
+#define N_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
+
+static void    hangul_buffer_push(HangulBuffer *buffer, wchar_t ch);
+static wchar_t hangul_buffer_pop (HangulBuffer *buffer);
+static wchar_t hangul_buffer_peek(HangulBuffer *buffer);
+
+static void    hangul_buffer_clear(HangulBuffer *buffer);
+static int     hangul_buffer_get_string(HangulBuffer *buffer, wchar_t*buf, int buflen);
+static int     hangul_buffer_get_jamo_string(HangulBuffer *buffer, wchar_t *buf, int buflen);
+
+static wchar_t hangul_ic_translate_jamo(HangulInputContext *hic, int ascii);
+static wchar_t hangul_ic_combine_jamo(HangulInputContext *hic, wchar_t first, wchar_t second);
+
+static void
+hangul_buffer_push(HangulBuffer *buffer, wchar_t ch)
+{
+    if (hangul_is_choseong(ch)) {
+       buffer->choseong = ch;
+    } else if (hangul_is_jungseong(ch)) {
+       buffer->jungseong = ch;
+    } else if (hangul_is_jongseong(ch)) {
+       buffer->jongseong = ch;
+    } else {
+    }
+
+    buffer->stack[++buffer->index] = ch;
+}
+
+static wchar_t
+hangul_buffer_pop(HangulBuffer *buffer)
+{
+    return buffer->stack[buffer->index--];
+}
+
+static wchar_t
+hangul_buffer_peek(HangulBuffer *buffer)
+{
+    return buffer->stack[buffer->index];
+}
+
+static void
+hangul_buffer_clear(HangulBuffer *buffer)
+{
+    buffer->choseong = 0;
+    buffer->jungseong = 0;
+    buffer->jongseong = 0;
+
+    buffer->index = -1;
+    buffer->stack[0]  = 0;
+    buffer->stack[1]  = 0;
+    buffer->stack[2]  = 0;
+    buffer->stack[3]  = 0;
+    buffer->stack[4]  = 0;
+    buffer->stack[5]  = 0;
+    buffer->stack[6]  = 0;
+    buffer->stack[7]  = 0;
+    buffer->stack[8]  = 0;
+    buffer->stack[9]  = 0;
+    buffer->stack[10] = 0;
+    buffer->stack[11] = 0;
+}
+
+static int
+hangul_buffer_get_jamo_string(HangulBuffer *buffer, wchar_t *buf, int buflen)
+{
+    int n = 0;
+
+    if (buffer->choseong) {
+       buf[n++] = buffer->choseong;
+    } else {
+       buf[n++] = HANGUL_CHOSEONG_FILLER;
+    }
+
+    if (buffer->jungseong) {
+       buf[n++] = buffer->jungseong;
+    } else {
+       buf[n++] = HANGUL_JUNGSEONG_FILLER;
+    }
+
+    if (buffer->jongseong) {
+       buf[n++] = buffer->jongseong;
+    }
+
+    buf[n] = L'\0';
+
+    return n;
+}
+
+static int
+hangul_buffer_get_string(HangulBuffer *buffer, wchar_t *buf, int buflen)
+{
+    wchar_t ch = L'\0';
+    int n = 0;
+
+    if (buffer->choseong) {
+       if (buffer->jungseong) {
+           /* have cho, jung, jong or no jong */
+           ch = hangul_jamo_to_syllable(buffer->choseong,
+                                        buffer->jungseong, 
+                                        buffer->jongseong);
+           buf[n++] = ch;
+       } else {
+           if (buffer->jongseong) {
+               /* have cho, jong */
+               ch = hangul_choseong_to_cjamo(buffer->choseong);
+               buf[n++] = ch;
+               ch = hangul_jongseong_to_cjamo(buffer->jongseong);
+               buf[n++] = ch;
+           } else {
+               /* have cho */
+               ch = hangul_choseong_to_cjamo(buffer->choseong);
+               buf[n++] = ch;
+           }
+       }
+    } else {
+       if (buffer->jungseong) {
+           if (buffer->jongseong) {
+               /* have jung, jong */
+               ch = hangul_jungseong_to_cjamo(buffer->jungseong);
+               buf[n++] = ch;
+               ch = hangul_jongseong_to_cjamo(buffer->jongseong);
+               buf[n++] = ch;
+           } else {
+               /* have jung */
+               ch = hangul_jungseong_to_cjamo(buffer->jungseong);
+               buf[n++] = ch;
+           }
+       } else {
+           if (buffer->jongseong) { 
+               /* have jong */
+               ch = hangul_jongseong_to_cjamo(buffer->jongseong);
+               buf[n++] = ch;
+           } else {
+               /* have nothing */
+               buf[n] = L'\0';
+           }
+       }
+    }
+    buf[n] = L'\0';
+
+    return n;
+}
+
+static bool
+hangul_buffer_backspace(HangulBuffer *buffer)
+{
+    if (buffer->index >= 0) {
+       wchar_t ch = hangul_buffer_pop(buffer);
+       if (ch == 0)
+           return false;
+
+       if (hangul_is_choseong(ch)) {
+           ch = hangul_buffer_peek(buffer);
+           buffer->choseong = hangul_is_choseong(ch) ? ch : 0;
+           return true;
+       } else if (hangul_is_jungseong(ch)) {
+           ch = hangul_buffer_peek(buffer);
+           buffer->jungseong = hangul_is_jungseong(ch) ? ch : 0;
+           return true;
+       } else if (hangul_is_jongseong(ch)) {
+           ch = hangul_buffer_peek(buffer);
+           buffer->jongseong = hangul_is_jongseong(ch) ? ch : 0;
+           return true;
+       }
+    }
+    return false;
+}
+
+static wchar_t
+hangul_ic_translate_jamo(HangulInputContext *hic, int ascii)
+{
+    wchar_t ch = ascii;
+
+    if (ascii >= '!' && ascii <= '~') {
+       ch = hic->keyboard_table[ascii - '!'];
+    }
+
+    return ch;
+}
+
+static wchar_t
+hangul_ic_combine_jamo(HangulInputContext *hic, wchar_t first, wchar_t second)
+{
+    int min, max, mid;
+    uint32_t key;
+
+    /* make key */
+    key = first << 16 | second;
+
+    /* binary search in table */
+    min = 0;
+    max = hic->combination_table_size - 1;
+
+    while (max >= min) {
+       mid = (min + max) / 2;
+       if (hic->combination_table[mid].key < key)
+           min = mid + 1;
+       else if (hic->combination_table[mid].key > key)
+           max = mid - 1;
+       else
+           return hic->combination_table[mid].code;
+    }
+    return 0;
+}
+
+static inline void
+hangul_ic_push(HangulInputContext *hic, wchar_t ch)
+{
+    hangul_buffer_push(&hic->buffer, ch);
+}
+
+static inline wchar_t
+hangul_ic_pop(HangulInputContext *hic)
+{
+    return hangul_buffer_pop(&hic->buffer);
+}
+
+static inline wchar_t
+hangul_ic_peek(HangulInputContext *hic)
+{
+    return hangul_buffer_peek(&hic->buffer);
+}
+
+static inline void
+hangul_ic_save_preedit_string(HangulInputContext *hic)
+{
+    if (hic->output_mode == HANGUL_OUTPUT_JAMO) {
+       hangul_buffer_get_jamo_string(&hic->buffer,
+                                     hic->preedit_string,
+                                     N_ELEMENTS(hic->preedit_string));
+    } else {
+       hangul_buffer_get_string(&hic->buffer,
+                                hic->preedit_string,
+                                N_ELEMENTS(hic->preedit_string));
+    }
+}
+
+static inline void
+hangul_ic_save_commit_string(HangulInputContext *hic)
+{
+    if (hic->output_mode == HANGUL_OUTPUT_JAMO) {
+       hangul_buffer_get_jamo_string(&hic->buffer,
+                                     hic->commit_string,
+                                     N_ELEMENTS(hic->commit_string));
+    } else {
+       hangul_buffer_get_string(&hic->buffer,
+                                hic->commit_string,
+                                N_ELEMENTS(hic->commit_string));
+    }
+    hangul_buffer_clear(&hic->buffer);
+}
+
+static bool
+hangul_ic_filter_2(HangulInputContext *hic, wchar_t ch)
+{
+    wchar_t jong;
+    wchar_t combined;
+
+    if (hic->buffer.jongseong) {
+       if (hangul_is_choseong(ch)) {
+           jong = hangul_choseong_to_jongseong(ch);
+           combined = hangul_ic_combine_jamo(hic,
+                                             hic->buffer.jongseong, jong);
+           if (hangul_is_jongseong(combined)) {
+               hangul_ic_push(hic, combined);
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, ch);
+           }
+       } else if (hangul_is_jungseong(ch)) {
+           wchar_t pop, peek;
+           pop = hangul_ic_pop(hic);
+           peek = hangul_ic_peek(hic);
+
+           if (hangul_is_jungseong(peek)) {
+               hic->buffer.jongseong = 0;
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, hangul_jongseong_to_choseong(pop));
+               hangul_ic_push(hic, ch);
+           } else {
+               wchar_t choseong = 0, jongseong = 0; 
+               hangul_jongseong_dicompose(hic->buffer.jongseong,
+                                          &jongseong, &choseong);
+               hangul_ic_push(hic, jongseong);
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, choseong);
+               hangul_ic_push(hic, ch);
+           }
+       } else {
+           goto none_hangul;
+       }
+    } else if (hic->buffer.jungseong) {
+       if (hangul_is_choseong(ch)) {
+           if (hic->buffer.choseong) {
+               jong = hangul_choseong_to_jongseong(ch);
+               if (hangul_is_jongseong(jong)) {
+                   hangul_ic_push(hic, jong);
+               } else {
+                   hangul_ic_save_commit_string(hic);
+                   hangul_ic_push(hic, ch);
+               }
+           } else {
+               hangul_ic_push(hic, ch);
+           }
+       } else if (hangul_is_jungseong(ch)) {
+           combined = hangul_ic_combine_jamo(hic, hic->buffer.jungseong, ch);
+           if (hangul_is_jungseong(combined)) {
+               hangul_ic_push(hic, combined);
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, ch);
+           }
+       } else {
+           goto none_hangul;
+       }
+    } else if (hic->buffer.choseong) {
+       if (hangul_is_choseong(ch)) {
+           combined = hangul_ic_combine_jamo(hic, hic->buffer.choseong, ch);
+           if (hangul_is_choseong(combined)) {
+               hangul_ic_push(hic, combined);
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, ch);
+           }
+       } else if (hangul_is_jungseong(ch)) {
+           hangul_ic_push(hic, ch);
+       } else {
+           goto none_hangul;
+       }
+    } else {
+       if (hangul_is_choseong(ch)) {
+           hangul_ic_push(hic, ch);
+       } else if (hangul_is_jungseong(ch)) {
+           hangul_ic_push(hic, ch);
+       } else {
+           goto none_hangul;
+       }
+    }
+
+    hangul_ic_save_preedit_string(hic);
+    return true;
+
+none_hangul:
+    hangul_ic_save_commit_string(hic);
+    return false;
+}
+
+static bool
+hangul_ic_filter_3(HangulInputContext *hic, wchar_t ch)
+{
+    if (hangul_is_choseong(ch)) {
+       if (hic->buffer.choseong == 0) {
+           hangul_ic_push(hic, ch);
+       } else {
+           wchar_t choseong = 0;
+           if (hangul_is_choseong(hangul_ic_peek(hic))) {
+               choseong = hangul_ic_combine_jamo(hic,
+                                                 hic->buffer.choseong, ch);
+           }
+           if (choseong) {
+               hangul_ic_push(hic, choseong);
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, ch);
+           }
+       }
+    } else if (hangul_is_jungseong(ch)) {
+       if (hic->buffer.jungseong == 0) {
+           hangul_ic_push(hic, ch);
+       } else {
+           wchar_t jungseong = 0;
+           if (hangul_is_jungseong(hangul_ic_peek(hic))) {
+               jungseong = hangul_ic_combine_jamo(hic,
+                                                 hic->buffer.jungseong, ch);
+           }
+           if (jungseong) {
+               hangul_ic_push(hic, jungseong);
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hangul_ic_push(hic, ch);
+           }
+       }
+    } else if (hangul_is_jongseong(ch)) {
+       if (hic->buffer.jongseong == 0) {
+           hangul_ic_push(hic, ch);
+       } else {
+           wchar_t jongseong = 0;
+           if (hangul_is_jongseong(hangul_ic_peek(hic))) {
+               jongseong = hangul_ic_combine_jamo(hic,
+                                                  hic->buffer.jongseong, ch);
+               if (jongseong) {
+                   hangul_ic_push(hic, jongseong);
+               } else {
+                   hangul_ic_save_commit_string(hic);
+                   hangul_ic_push(hic, ch);
+               }
+           }
+       }
+    } else {
+       hangul_ic_save_commit_string(hic);
+       return false;
+    }
+
+    hangul_ic_save_preedit_string(hic);
+    return true;
+}
+
+bool
+hangul_ic_filter(HangulInputContext *hic, int ascii, bool capslock)
+{
+    wchar_t ch;
+
+    if (hic == NULL)
+       return false;
+
+    if (capslock) {
+       if (isupper(ascii)) {
+           ascii = tolower(ascii);
+       } else {
+           ascii = toupper(ascii);
+       }
+    }
+
+    ch = hangul_ic_translate_jamo(hic, ascii);
+
+    hic->preedit_string[0] = 0;
+    hic->commit_string[0] = 0;
+
+    if (hic->type == HANGUL_INPUT_FILTER_2)
+       return hangul_ic_filter_2(hic, ch);
+    else
+       return hangul_ic_filter_3(hic, ch);
+}
+
+const wchar_t*
+hangul_ic_get_preedit_string(HangulInputContext *hic)
+{
+    if (hic == NULL)
+       return NULL;
+
+    return hic->preedit_string;
+}
+
+const wchar_t*
+hangul_ic_get_commit_string(HangulInputContext *hic)
+{
+    if (hic == NULL)
+       return NULL;
+
+    return hic->commit_string;
+}
+
+void
+hangul_ic_reset(HangulInputContext *hic)
+{
+    if (hic == NULL)
+       return;
+
+    hangul_ic_save_commit_string(hic);
+}
+
+bool
+hangul_ic_backspace(HangulInputContext *hic)
+{
+    int ret;
+
+    if (hic == NULL)
+       return false;
+
+    ret = hangul_buffer_backspace(&hic->buffer);
+    if (ret)
+       hangul_ic_save_preedit_string(hic);
+    return ret;
+}
+
+void
+hangul_ic_set_output_mode(HangulInputContext *hic, int mode)
+{
+    if (hic == NULL)
+       return;
+
+    hic->output_mode = mode;
+}
+
+void
+hangul_ic_set_keyboard(HangulInputContext *hic, int keyboard)
+{
+    if (hic == NULL)
+       return;
+
+    switch (keyboard) {
+    case HANGUL_KEYBOARD_2:
+       hic->type = HANGUL_INPUT_FILTER_2;
+       hic->keyboard_table = hangul_keyboard_table_2;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    case HANGUL_KEYBOARD_32:
+       hic->type = HANGUL_INPUT_FILTER_3;
+       hic->keyboard_table = hangul_keyboard_table_32;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    case HANGUL_KEYBOARD_3FINAL:
+       hic->type = HANGUL_INPUT_FILTER_3;
+       hic->keyboard_table = hangul_keyboard_table_3final;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    case HANGUL_KEYBOARD_390:
+       hic->type = HANGUL_INPUT_FILTER_3;
+       hic->keyboard_table = hangul_keyboard_table_390;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    case HANGUL_KEYBOARD_3NOSHIFT:
+       hic->type = HANGUL_INPUT_FILTER_3;
+       hic->keyboard_table = hangul_keyboard_table_3sun;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    default:
+       hic->type = HANGUL_INPUT_FILTER_2;
+       hic->keyboard_table = hangul_keyboard_table_2;
+       hic->combination_table = hangul_combination_table_default;
+       hic->combination_table_size = N_ELEMENTS(hangul_combination_table_default);
+       break;
+    }
+}
+
+HangulInputContext*
+hangul_ic_new(int keyboard)
+{
+    HangulInputContext *hic;
+
+    hic = malloc(sizeof(HangulInputContext));
+    if (hic == NULL)
+       return NULL;
+
+    hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+
+    hangul_ic_set_output_mode(hic, HANGUL_OUTPUT_SYLLABLE);
+    hangul_ic_set_keyboard(hic, keyboard);
+
+    hangul_buffer_clear(&hic->buffer);
+
+    return hic;
+}
+
+void
+hangul_ic_delete(HangulInputContext *hic)
+{
+    if (hic == NULL)
+       return;
+
+    free(hic);
+}
diff --git a/hangul/hangulkeyboard.h b/hangul/hangulkeyboard.h
new file mode 100644 (file)
index 0000000..a0584ae
--- /dev/null
@@ -0,0 +1,611 @@
+#include "hangul.h"
+
+static const wchar_t hangul_keyboard_table_2[] = {
+    0x0021,     /* exclam:       exclamation mark               */
+    0x0022,     /* quotedbl:     quotation mark                 */
+    0x0023,     /* numbersign:   number sign                    */
+    0x0024,     /* dollar:       dollar sign                    */
+    0x0025,     /* percent:      percent sign                   */
+    0x0026,     /* ampersand:    ampersand                      */
+    0x0027,     /* apostrophe:   apostrophe                     */
+    0x0028,     /* parenleft:    left parenthesis               */
+    0x0029,     /* parenright:   right parenthesis              */
+    0x002a,     /* asterisk:     asterisk                       */
+    0x002b,     /* plus:         plus sign                      */
+    0x002c,     /* comma:        comma                          */
+    0x002d,     /* minus:        minus sign                     */
+    0x002e,     /* period:       period                         */
+    0x002f,     /* slash:        slash                          */
+    0x0030,     /* 0:            0                              */
+    0x0031,     /* 1:            1                              */
+    0x0032,     /* 2:            2                              */
+    0x0033,     /* 3:            3                              */
+    0x0034,     /* 4:            4                              */
+    0x0035,     /* 5:            5                              */
+    0x0036,     /* 6:            6                              */
+    0x0037,     /* 7:            7                              */
+    0x0038,     /* 8:            8                              */
+    0x0039,     /* 9:            9                              */
+    0x003a,     /* colon:        colon                          */
+    0x003b,     /* semicolon:    semicolon                      */
+    0x003c,     /* less:         less-than sign                 */
+    0x003d,     /* equal:        equals sign                    */
+    0x003e,     /* greater:      greater-than sign              */
+    0x003f,     /* question:     question mark                  */
+    0x0040,     /* at:           commercial at                  */
+    0x1106,     /* A:            choseong mieum                 */
+    0x1172,     /* B:            jungseong yu                   */
+    0x110e,     /* C:            choseong chieuch               */
+    0x110b,     /* D:            choseong ieung                 */
+    0x1104,     /* E:            choseong ssangtikeut           */
+    0x1105,     /* F:            choseong rieul                 */
+    0x1112,     /* G:            choseong hieuh                 */
+    0x1169,     /* H:            jungseong o                    */
+    0x1163,     /* I:            jungseong ya                   */
+    0x1165,     /* J:            jungseong eo                   */
+    0x1161,     /* K:            jungseong a                    */
+    0x1175,     /* L:            jungseong i                    */
+    0x1173,     /* M:            jungseong eu                   */
+    0x116e,     /* N:            jungseong u                    */
+    0x1164,     /* O:            jungseong yae                  */
+    0x1168,     /* P:            jungseong ye                   */
+    0x1108,     /* Q:            choseong ssangpieup            */
+    0x1101,     /* R:            choseong ssangkiyeok           */
+    0x1102,     /* S:            choseong nieun                 */
+    0x110a,     /* T:            choseong ssangsios             */
+    0x1167,     /* U:            jungseong yeo                  */
+    0x1111,     /* V:            choseong phieuph               */
+    0x110d,     /* W:            choseong ssangcieuc            */
+    0x1110,     /* X:            choseong thieuth               */
+    0x116d,     /* Y:            jungseong yo                   */
+    0x110f,     /* Z:            choseong khieukh               */
+    0x005b,     /* bracketleft:  left bracket                   */
+    0x005c,     /* backslash:    backslash                      */
+    0x005d,     /* bracketright: right bracket                  */
+    0x005e,     /* asciicircum:  circumflex accent              */
+    0x005f,     /* underscore:   underscore                     */
+    0x0060,     /* quoteleft:    grave accent                   */
+    0x1106,     /* a:            choseong  mieum                */
+    0x1172,     /* b:            jungseong yu                   */
+    0x110e,     /* c:            choseong  chieuch              */
+    0x110b,     /* d:            choseong  ieung                */
+    0x1103,     /* e:            choseong  tikeut               */
+    0x1105,     /* f:            choseong  rieul                */
+    0x1112,     /* g:            choseong  hieuh                */
+    0x1169,     /* h:            jungseong o                    */
+    0x1163,     /* i:            jungseong ya                   */
+    0x1165,     /* j:            jungseong eo                   */
+    0x1161,     /* k:            jungseong a                    */
+    0x1175,     /* l:            jungseong i                    */
+    0x1173,     /* m:            jungseong eu                   */
+    0x116e,     /* n:            jungseong u                    */
+    0x1162,     /* o:            jungseong ae                   */
+    0x1166,     /* p:            jungseong e                    */
+    0x1107,     /* q:            choseong  pieup                */
+    0x1100,     /* r:            choseong  kiyeok               */
+    0x1102,     /* s:            choseong  nieun                */
+    0x1109,     /* t:            choseong  sios                 */
+    0x1167,     /* u:            jungseong yeo                  */
+    0x1111,     /* v:            choseong  phieuph              */
+    0x110c,     /* w:            choseong  cieuc                */
+    0x1110,     /* x:            choseong  thieuth              */
+    0x116d,     /* y:            jungseong yo                   */
+    0x110f,     /* z:            choseong  khieukh              */
+    0x007b,     /* braceleft:    left brace                     */
+    0x007c,     /* bar:          vertical bar                   */
+    0x007d,     /* braceright:   right brace                    */
+    0x007e      /* asciitilde:   tilde                          */
+};
+
+static const wchar_t hangul_keyboard_table_32[] = {
+    0x0021,    /* exclam:      exclamation mark                */
+    0x0022,    /* quotedbl:    quotation mark                  */
+    0x0023,    /* numbersign:  number sign                     */
+    0x0024,    /* dollar:      dollar sign                     */
+    0x0025,    /* percent:     percent sign                    */
+    0x0026,    /* ampersand:   ampersand                       */
+    0x0027,    /* apostrophe:  apostrophe                      */
+    0x0028,    /* parenleft:   left parenthesis                */
+    0x0029,    /* parenright:  right parenthesis               */
+    0x002a,    /* asterisk:    asterisk                        */
+    0x002b,    /* plus:        plus sign                       */
+    0x002c,    /* comma:       comma                           */
+    0x002d,    /* minus:       minus sign                      */
+    0x002e,    /* period:      period                          */
+    0x002f,    /* slash:       slash                           */
+    0x0030,    /* 0:           0                               */
+    0x0031,    /* 1:           1                               */
+    0x0032,    /* 2:           2                               */
+    0x0033,    /* 3:           3                               */
+    0x0034,    /* 4:           4                               */
+    0x0035,    /* 5:           5                               */
+    0x0036,    /* 6:           6                               */
+    0x0037,    /* 7:           7                               */
+    0x0038,    /* 8:           8                               */
+    0x0039,    /* 9:           9                               */
+    0x003a,    /* colon:       colon                           */
+    0x003b,    /* semicolon:   semicolon                       */
+    0x003c,    /* less:        less-than sign                  */
+    0x003d,    /* equal:       equals sign                     */
+    0x003e,    /* greater:     greater-than sign               */
+    0x003f,    /* question:    question mark                   */
+    0x0040,    /* at:          commercial at                   */
+    0x11b7,    /* A:           jongseong mieum                 */
+    0x1172,    /* B:           jungseong yu                    */
+    0x11be,    /* C:           jongseong chieuch               */
+    0x11bc,    /* D:           jongseong ieung                 */
+    0x11ae,    /* E:           jongseong tikeut                */
+    0x11af,    /* F:           jongseong rieul                 */
+    0x11c2,    /* G:           jongseong hieuh                 */
+    0x1169,    /* H:           jungseong o                     */
+    0x1163,    /* I:           jungseong ya                    */
+    0x1165,    /* J:           jungseong eo                    */
+    0x1161,    /* K:           jungseong a                     */
+    0x1175,    /* L:           jungseong i                     */
+    0x1173,    /* M:           jungseong eu                    */
+    0x116e,    /* N:           jungseong u                     */
+    0x1164,    /* O:           jungseong yae                   */
+    0x1168,    /* P:           jungseong ye                    */
+    0x11b8,    /* Q:           jongseong pieup                 */
+    0x11a8,    /* R:           jongseong kiyeok                */
+    0x11ab,    /* S:           jongseong nieun                 */
+    0x11ba,    /* T:           jongseong sios                  */
+    0x1167,    /* U:           jungseong yeo                   */
+    0x11c1,    /* V:           jongseong phieuph               */
+    0x11bd,    /* W:           jongseong cieuc                 */
+    0x11c0,    /* X:           jongseong thieuth               */
+    0x116d,    /* Y:           jungseong yo                    */
+    0x11bf,    /* Z:           jongseong khieukh               */
+    0x002a,    /* bracketleft: left bracket                    */
+    0x005c,    /* backslash:   backslash                       */
+    0x005d,    /* bracketright:right bracket                   */
+    0x005e,    /* asciicircum: circumflex accent               */
+    0x005f,    /* underscore:  underscore                      */
+    0x0060,    /* quoteleft:   grave accent                    */
+    0x1106,    /* a:           choseong  mieum                 */
+    0x1172,    /* b:           jungseong yu                    */
+    0x110e,    /* c:           choseong  chieuch               */
+    0x110b,    /* d:           choseong  ieung                 */
+    0x1103,    /* e:           choseong  tikeut                */
+    0x1105,    /* f:           choseong  rieul                 */
+    0x1112,    /* g:           choseong  hieuh                 */
+    0x1169,    /* h:           jungseong o                     */
+    0x1163,    /* i:           jungseong ya                    */
+    0x1165,    /* j:           jungseong eo                    */
+    0x1161,    /* k:           jungseong a                     */
+    0x1175,    /* l:           jungseong i                     */
+    0x1173,    /* m:           jungseong eu                    */
+    0x116e,    /* n:           jungseong u                     */
+    0x1162,    /* o:           jungseong ae                    */
+    0x1166,    /* p:           jungseong e                     */
+    0x1107,    /* q:           choseong  pieup                 */
+    0x1100,    /* r:           choseong  kiyeok                */
+    0x1102,    /* s:           choseong  nieun                 */
+    0x1109,    /* t:           choseong  sios                  */
+    0x1167,    /* u:           jungseong yeo                   */
+    0x1111,    /* v:           choseong  phieuph               */
+    0x110c,    /* w:           choseong  cieuc                 */
+    0x1110,    /* x:           choseong  thieuth               */
+    0x116d,    /* y:           jungseong yo                    */
+    0x110f,    /* z:           choseong  khieukh               */
+    0x007b,    /* braceleft:   left brace                      */
+    0x007c,    /* bar:         vertical bar                    */
+    0x007d,    /* braceright:  right brace                     */
+    0x203b,    /* asciitilde:  tilde                           */
+};
+
+static const wchar_t hangul_keyboard_table_390[] = {
+    0x11bd,    /* exclam:              jongseong cieuc                 */
+    0x0022,    /* quotedbl:    quotatioin mark                 */
+    0x0023,    /* numbersign:  number sign                     */
+    0x0024,    /* dollar:              dollar sign                     */
+    0x0025,    /* percent:             percent sign                    */
+    0x0026,    /* ampersand:   ampersand                       */
+    0x1110,    /* apostrophe:  choseong thieuth                */
+    0x0028,    /* parenleft:   left parenthesis                */
+    0x0029,    /* parenright:  right parenthesis               */
+    0x002a,    /* asterisk:    asterisk                        */
+    0x002b,    /* plus:                plus sign                       */
+    0x002c,    /* comma:               comma                           */
+    0x002d,    /* minus:               minus sign                      */
+    0x002e,    /* period:              period                          */
+    0x1169,    /* slash:               jungseong o                     */
+    0x110f,    /* 0:           choseong  khieukh               */
+    0x11c2,    /* 1:           jongseong hieuh                 */
+    0x11bb,    /* 2:           jongseong ssangsios             */
+    0x11b8,    /* 3:           jongseong pieup                 */
+    0x116d,    /* 4:           jungseong yo                    */
+    0x1172,    /* 5:           jungseong yu                    */
+    0x1163,    /* 6:           jungseong ya                    */
+    0x1168,    /* 7:           jungseong ye                    */
+    0x1174,    /* 8:           jungseong yi                    */
+    0x116e,    /* 9:           jungseong u                     */
+    0x003a,    /* colon:               colon                           */
+    0x1107,    /* semicolon:   choseong  pieup                 */
+    0x0032,    /* less:                2                               */
+    0x003d,    /* equal:               euals sign                      */
+    0x0033,    /* greater:             3                               */
+    0x003f,    /* question:    question mark                   */
+    0x0040,    /* at:          commertial at                   */
+    0x11ae,    /* A:           jongseong tikeut                */
+    0x0021,    /* B:           exclamation mark                */
+    0x11b1,    /* C:           jongseong rieul-mieum           */
+    0x11b0,    /* D:           jongseong rieul-kiyeok          */
+    0x11bf,    /* E:           jongseong khieukh               */
+    0x11a9,    /* F:           jongseong ssangkiyeok           */
+    0x002f,    /* G:           slash                           */
+    0x0027,    /* H:           apostrophe                      */
+    0x0038,    /* I:           8                               */
+    0x0034,    /* J:           4                               */
+    0x0035,    /* K:           5                               */
+    0x0036,    /* L:           6                               */
+    0x0031,    /* M:           1                               */
+    0x0030,    /* N:           0                               */
+    0x0039,    /* O:           9                               */
+    0x003e,    /* P:           greater-than sign               */
+    0x11c1,    /* Q:           jongseong phieuph               */
+    0x1164,    /* R:           jungseong yae                   */
+    0x11ad,    /* S:           jongseong nieun-hieuh           */
+    0x003b,    /* T:           semicolon                       */
+    0x0037,    /* U:           7                               */
+    0x11b6,    /* V:           jongseong rieul-hieuh           */
+    0x11c0,    /* W:           jongseong thikeuth              */
+    0x11b9,    /* X:           jongseong pieup-sios            */
+    0x003c,    /* Y:           less-than sign                  */
+    0x11be,    /* Z:           jongseong chieuch               */
+    0x005b,    /* bracketleft: left bracket                    */
+    0x005c,    /* backslash:   backslash                       */
+    0x005d,    /* bracketright:        right bracket                   */
+    0x005e,    /* asciicircum: circumflex accent               */
+    0x005f,    /* underscore:  underscore                      */
+    0x0060,    /* quoteleft:   grave accent                    */
+    0x11bc,    /* a:           jongseong ieung                 */
+    0x116e,    /* b:           jungseong u                     */
+    0x1166,    /* c:           jungseong e                     */
+    0x1175,    /* d:           jungseong i                     */
+    0x1167,    /* e:           jungseong yeo                   */
+    0x1161,    /* f:           jungseong a                     */
+    0x1173,    /* g:           jungseong eu                    */
+    0x1102,    /* h:           choseong  nieun                 */
+    0x1106,    /* i:           choseong  mieum                 */
+    0x110b,    /* j:           choseong  ieung                 */
+    0x1100,    /* k:           choseong  kiyeok                */
+    0x110c,    /* l:           choseong  cieuc                 */
+    0x1112,    /* m:           choseong  hieuh                 */
+    0x1109,    /* n:           choseong  sios                  */
+    0x110e,    /* o:           choseong  chieuch               */
+    0x1111,    /* p:           choseong  phieuph               */
+    0x11ba,    /* q:           jongseong sios                  */
+    0x1162,    /* r:           jungseong ae                    */
+    0x11ab,    /* s:           jongseong nieun                 */
+    0x1165,    /* t:           jungseong eo                    */
+    0x1103,    /* u:           choseong  tikeut                */
+    0x1169,    /* v:           jungseong o                     */
+    0x11af,    /* w:           jongseong rieul                 */
+    0x11a8,    /* x:           jongseong kiyeok                */
+    0x1105,    /* y:           choseong  rieul                 */
+    0x11b7,    /* z:           jongseong mieum                 */
+    0x007b,    /* braceleft:   left brace                      */
+    0x007c,    /* bar:         vertical line(bar)              */
+    0x007d,    /* braceright:  right brace                     */
+    0x007e,    /* asciitilde:  tilde                           */
+};
+
+static const wchar_t hangul_keyboard_table_3final[] = {
+    0x11a9,    /* exclam:              jongseong ssangkiyeok           */
+    0x00b7,    /* quotedbl:    middle dot                      */
+    0x11bd,    /* numbersign:  jognseong cieuc                 */
+    0x11b5,    /* dollar:              jongseong rieul-phieuph         */
+    0x11b4,    /* percent:             jongseong rieul-thieuth         */
+    0x201c,    /* ampersand:   left double quotation mark      */
+    0x1110,    /* apostrophe:  choseong  thieuth               */
+    0x0027,    /* parenleft:   apostrophe                      */
+    0x007e,    /* parenright:  Tilde                           */
+    0x201d,    /* asterisk:    right double quotation mark     */
+    0x002b,    /* plus:                plus sign                       */
+    0x002c,    /* comma:               comma                           */
+    0x0029,    /* minus:               right parenthesis               */
+    0x002e,    /* period:              period                          */
+    0x1169,    /* slash:               jungseong o                     */
+    0x110f,    /* 0:           choseong  khieukh               */
+    0x11c2,    /* 1:           jongseong hieuh                 */
+    0x11bb,    /* 2:           jongseong ssangsios             */
+    0x11b8,    /* 3:           jongseong pieup                 */
+    0x116d,    /* 4:           jungseong yo                    */
+    0x1172,    /* 5:           jungseong yu                    */
+    0x1163,    /* 6:           jungseong ya                    */
+    0x1168,    /* 7:           jungseong ye                    */
+    0x1174,    /* 8:           jungseong yi                    */
+    0x116e,    /* 9:           jungseong u                     */
+    0x0034,    /* colon:               4                               */
+    0x1107,    /* semicolon:   choseong  pieup                 */
+    0x002c,    /* less:                comma                           */
+    0x003e,    /* equal:               greater-than sign               */
+    0x002e,    /* greater:             period                          */
+    0x0021,    /* question:    exclamation mark                */
+    0x11b0,    /* at:          jongseong rieul-kiyeok          */
+    0x11ae,    /* A:           jongseong tikeut                */
+    0x003f,    /* B:           question mark                   */
+    0x11bf,    /* C:           jongseong khieukh               */
+    0x11b2,    /* D:           jongseong rieul-pieup           */
+    0x11ac,    /* E:           jongseong nieun-cieuc           */
+    0x11b1,    /* F:           jongseong rieul-mieum           */
+    0x1164,    /* G:           jungseong yae                   */
+    0x0030,    /* H:           0                               */
+    0x0037,    /* I:           7                               */
+    0x0031,    /* J:           1                               */
+    0x0032,    /* K:           2                               */
+    0x0033,    /* L:           3                               */
+    0x0022,    /* M:           double quotation mark           */
+    0x002d,    /* N:           minus sign                      */
+    0x0038,    /* O:           8                               */
+    0x0039,    /* P:           9                               */
+    0x11c1,    /* Q:           jongseong phieuph               */
+    0x11b6,    /* R:           jongseong rieul-hieuh           */
+    0x11ad,    /* S:           jongseong nieun-hieuh           */
+    0x11b3,    /* T:           jongseong rieul-sios            */
+    0x0036,    /* U:           6                               */
+    0x11aa,    /* V:           jongseong kiyeok-sios           */
+    0x11c0,    /* W:           jongseong thikeuth              */
+    0x11b9,    /* X:           jongseong pieup-sios            */
+    0x0035,    /* Y:           5                               */
+    0x11be,    /* Z:           jongseong chieuch               */
+    0x0028,    /* bracketleft: left parenthesis                */
+    0x003a,    /* backslash:   colon                           */
+    0x003c,    /* bracketright:        less-than sign                  */
+    0x003d,    /* asciicircum: equals sign                     */
+    0x003b,    /* underscore:  semicolon                       */
+    0x002a,    /* quoteleft:   asterisk                        */
+    0x11bc,    /* a:           jongseong ieung                 */
+    0x116e,    /* b:           jungseong u                     */
+    0x1166,    /* c:           jungseong e                     */
+    0x1175,    /* d:           jungseong i                     */
+    0x1167,    /* e:           jungseong yeo                   */
+    0x1161,    /* f:           jungseong a                     */
+    0x1173,    /* g:           jungseong eu                    */
+    0x1102,    /* h:           choseong  nieun                 */
+    0x1106,    /* i:           choseong  mieum                 */
+    0x110b,    /* j:           choseong  ieung                 */
+    0x1100,    /* k:           choseong  kiyeok                */
+    0x110c,    /* l:           choseong  cieuc                 */
+    0x1112,    /* m:           choseong  hieuh                 */
+    0x1109,    /* n:           choseong  sios                  */
+    0x110e,    /* o:           choseong  chieuch               */
+    0x1111,    /* p:           choseong  phieuph               */
+    0x11ba,    /* q:           jongseong sios                  */
+    0x1162,    /* r:           jungseong ae                    */
+    0x11ab,    /* s:           jongseong nieun                 */
+    0x1165,    /* t:           jungseong eo                    */
+    0x1103,    /* u:           choseong  tikeut                */
+    0x1169,    /* v:           jungseong o                     */
+    0x11af,    /* w:           jongseong rieul                 */
+    0x11a8,    /* x:           jongseong kiyeok                */
+    0x1105,    /* y:           choseong  rieul                 */
+    0x11b7,    /* z:           jongseong mieum                 */
+    0x0025,    /* braceleft:   percent sign                    */
+    0x005c,    /* bar:         backslash                       */
+    0x002f,    /* braceright:  slash                           */
+    0x203b,    /* asciitilde:  reference mark                  */
+};
+
+static const wchar_t hangul_keyboard_table_3sun[] = {
+    0x0021,    /* exclam:              exclamation mark                */
+    0x0022,    /* quotedbl:    quotatioin mark                 */
+    0x0023,    /* numbersign:  number sign                     */
+    0x0024,    /* dollar:              dollar sign                     */
+    0x0025,    /* percent:             percent sign                    */
+    0x0026,    /* ampersand:   ampersand                       */
+    0x1110,    /* apostrophe:  choseong thieuth                */
+    0x0028,    /* parenleft:   left parenthesis                */
+    0x0029,    /* parenright:  right parenthesis               */
+    0x002a,    /* asterisk:    asterisk                        */
+    0x002b,    /* plus:                plus sign                       */
+    0x002c,    /* comma:               comma                           */
+    0x11bd,    /* minus:               jongseong cieuc                 */
+    0x002e,    /* period:              period                          */
+    0x11ae,    /* slash:               jongseong tikeut                */
+    0x1164,    /* 0:           choseong  yae                   */
+    0x11c2,    /* 1:           jongseong hieuh                 */
+    0x11bb,    /* 2:           jongseong ssangsios             */
+    0x11b8,    /* 3:           jongseong pieup                 */
+    0x116d,    /* 4:           jungseong yo                    */
+    0x1172,    /* 5:           jungseong yu                    */
+    0x1163,    /* 6:           jungseong ya                    */
+    0x1168,    /* 7:           jungseong ye                    */
+    0x1174,    /* 8:           jungseong yi                    */
+    0x110f,    /* 9:           choseong khieukh                */
+    0x003a,    /* colon:               colon                           */
+    0x1107,    /* semicolon:   choseong  pieup                 */
+    0x0032,    /* less:                2                               */
+    0x11be,    /* equal:               jongseong chieuch               */
+    0x0033,    /* greater:             3                               */
+    0x003f,    /* question:    question mark                   */
+    0x0040,    /* at:          commertial at                   */
+    0x11bc,    /* A:           jongseong ieung                 */
+    0x0021,    /* B:           exclamation mark                */
+    0x005c,    /* C:           backslash                       */
+    0x005d,    /* D:           right bracket                   */
+    0x1167,    /* E:           jungseong yeo                   */
+    0x1161,    /* F:           jungseong a                     */
+    0x002f,    /* G:           slash                           */
+    0x0027,    /* H:           apostrophe                      */
+    0x0038,    /* I:           8                               */
+    0x0034,    /* J:           4                               */
+    0x0035,    /* K:           5                               */
+    0x0036,    /* L:           6                               */
+    0x0031,    /* M:           1                               */
+    0x0030,    /* N:           0                               */
+    0x0039,    /* O:           9                               */
+    0x003e,    /* P:           greater-than sign               */
+    0x11ba,    /* Q:           jongseong sios                  */
+    0x1162,    /* R:           jungseong ae                    */
+    0x005b,    /* S:           left bracket                    */
+    0x003b,    /* T:           semicolon                       */
+    0x0037,    /* U:           7                               */
+    0x1169,    /* V:           jungseong o                     */
+    0x11af,    /* W:           jongseong rieul                 */
+    0x003d,    /* X:           equals sign                     */
+    0x003c,    /* Y:           less-than sign                  */
+    0x002d,    /* Z:           minus sign                      */
+    0x11c0,    /* bracketleft: jongseong thieuth               */
+    0x11bf,    /* backslash:   jongseong khieukh               */
+    0x11c1,    /* bracketright:        jongseong phieuph               */
+    0x005e,    /* asciicircum: circumflex accent               */
+    0x005f,    /* underscore:  underscore                      */
+    0x0060,    /* quoteleft:   grave accent                    */
+    0x11bc,    /* a:           jongseong ieung                 */
+    0x116e,    /* b:           jungseong u                     */
+    0x1166,    /* c:           jungseong e                     */
+    0x1175,    /* d:           jungseong i                     */
+    0x1167,    /* e:           jungseong yeo                   */
+    0x1161,    /* f:           jungseong a                     */
+    0x1173,    /* g:           jungseong eu                    */
+    0x1102,    /* h:           choseong  nieun                 */
+    0x1106,    /* i:           choseong  mieum                 */
+    0x110b,    /* j:           choseong  ieung                 */
+    0x1100,    /* k:           choseong  kiyeok                */
+    0x110c,    /* l:           choseong  cieuc                 */
+    0x1112,    /* m:           choseong  hieuh                 */
+    0x1109,    /* n:           choseong  sios                  */
+    0x110e,    /* o:           choseong  chieuch               */
+    0x1111,    /* p:           choseong  phieuph               */
+    0x11ba,    /* q:           jongseong sios                  */
+    0x1162,    /* r:           jungseong ae                    */
+    0x11ab,    /* s:           jongseong nieun                 */
+    0x1165,    /* t:           jungseong eo                    */
+    0x1103,    /* u:           choseong  tikeut                */
+    0x1169,    /* v:           jungseong o                     */
+    0x11af,    /* w:           jongseong rieul                 */
+    0x11a8,    /* x:           jongseong kiyeok                */
+    0x1105,    /* y:           choseong  rieul                 */
+    0x11b7,    /* z:           jongseong mieum                 */
+    0x007b,    /* braceleft:   left brace                      */
+    0x007c,    /* bar:         vertical line(bar)              */
+    0x007d,    /* braceright:  right brace                     */
+    0x007e,    /* asciitilde:  tilde                           */
+};
+
+static const wchar_t hangul_keyboard_table_3yet[] = {
+    0x11bd,    /* exclam:              jongseong cieuc                 */
+    0x0022,    /* quotedbl:    quotatioin mark                 */
+    0x0023,    /* numbersign:  number sign                     */
+    0x0024,    /* dollar:              dollar sign                     */
+    0x0025,    /* percent:             percent sign                    */
+    0x0026,    /* ampersand:   ampersand                       */
+    0x1110,    /* apostrophe:  choseong thieuth                */
+    0x0028,    /* parenleft:   left parenthesis                */
+    0x0029,    /* parenright:  right parenthesis               */
+    0x002a,    /* asterisk:    asterisk                        */
+    0x002b,    /* plus:                plus sign                       */
+    0x002c,    /* comma:               comma                           */
+    0x002d,    /* minus:               minus sign                      */
+    0x002e,    /* period:              period                          */
+    0x1169,    /* slash:               jungseong o                     */
+    0x110f,    /* 0:           choseong  khieukh               */
+    0x11c2,    /* 1:           jongseong hieuh                 */
+    0x11bb,    /* 2:           jongseong ssangsios             */
+    0x11b8,    /* 3:           jongseong pieup                 */
+    0x116d,    /* 4:           jungseong yo                    */
+    0x1172,    /* 5:           jungseong yu                    */
+    0x1163,    /* 6:           jungseong ya                    */
+    0x1168,    /* 7:           jungseong ye                    */
+    0x1174,    /* 8:           jungseong yi                    */
+    0x116e,    /* 9:           jungseong u                     */
+    0x003a,    /* colon:               colon                           */
+    0x1107,    /* semicolon:   choseong  pieup                 */
+    0x113c,    /* less:                choseong chitueumsios           */
+    0x003d,    /* equal:               euals sign                      */
+    0x113e,    /* greater:             choseong ceongchieumsios        */
+    0x003f,    /* question:    question mark                   */
+    0x11eb,    /* at:          jongseong pansios               */
+    0x11ae,    /* A:           jongseong tikeut                */
+    0x116e,    /* B:           jungseong u                     */
+    0x11b1,    /* C:           jongseong rieul-mieum           */
+    0x11b0,    /* D:           jongseong rieul-kiyeok          */
+    0x11bf,    /* E:           jongseong khieukh               */
+    0x11a9,    /* F:           jongseong ssangkiyeok           */
+    0x119e,    /* G:           jungseong araea                 */
+    0x1102,    /* H:           choseong nieun                  */
+    0x1154,    /* I:           choseong chitueumchieuch        */
+    0x114c,    /* J:           choseong yesieung               */
+    0x114e,    /* K:           choseong chitueumcieuc          */
+    0x1150,    /* L:           choseong ceongchieumcieuc       */
+    0x1159,    /* M:           choseong yeorinhieuh            */
+    0x1140,    /* N:           choseong pansios                */
+    0x1155,    /* O:           choseong ceongchieumchieuch     */
+    0x1111,    /* P:           choseong phieuph                */
+    0x11c1,    /* Q:           jongseong phieuph               */
+    0x1164,    /* R:           jungseong yae                   */
+    0x11ad,    /* S:           jongseong nieun-hieuh           */
+    0x1165,    /* T:           jungseong eo                    */
+    0x302e,    /* U:           single dot tone mark            */
+    0x11b6,    /* V:           jongseong rieul-hieuh           */
+    0x11c0,    /* W:           jongseong thikeuth              */
+    0x11b9,    /* X:           jongseong pieup-sios            */
+    0x302f,    /* Y:           double dot tone mark            */
+    0x11be,    /* Z:           jongseong chieuch               */
+    0x005b,    /* bracketleft: left bracket                    */
+    0x005c,    /* backslash:   backslash                       */
+    0x005d,    /* bracketright:        right bracket                   */
+    0x005e,    /* asciicircum: circumflex accent               */
+    0x005f,    /* underscore:  underscore                      */
+    0x11f9,    /* quoteleft:   jongseong yeorinhieuh           */
+    0x11bc,    /* a:           jongseong ieung                 */
+    0x116e,    /* b:           jungseong u                     */
+    0x1166,    /* c:           jungseong e                     */
+    0x1175,    /* d:           jungseong i                     */
+    0x1167,    /* e:           jungseong yeo                   */
+    0x1161,    /* f:           jungseong a                     */
+    0x1173,    /* g:           jungseong eu                    */
+    0x1102,    /* h:           choseong  nieun                 */
+    0x1106,    /* i:           choseong  mieum                 */
+    0x110b,    /* j:           choseong  ieung                 */
+    0x1100,    /* k:           choseong  kiyeok                */
+    0x110c,    /* l:           choseong  cieuc                 */
+    0x1112,    /* m:           choseong  hieuh                 */
+    0x1109,    /* n:           choseong  sios                  */
+    0x110e,    /* o:           choseong  chieuch               */
+    0x1111,    /* p:           choseong  phieuph               */
+    0x11ba,    /* q:           jongseong sios                  */
+    0x1162,    /* r:           jungseong ae                    */
+    0x11ab,    /* s:           jongseong nieun                 */
+    0x1165,    /* t:           jungseong eo                    */
+    0x1103,    /* u:           choseong  tikeut                */
+    0x1169,    /* v:           jungseong o                     */
+    0x11af,    /* w:           jongseong rieul                 */
+    0x11a8,    /* x:           jongseong kiyeok                */
+    0x1105,    /* y:           choseong  rieul                 */
+    0x11b7,    /* z:           jongseong mieum                 */
+    0x007b,    /* braceleft:   left brace                      */
+    0x007c,    /* bar:         vertical line(bar)              */
+    0x007d,    /* braceright:  right brace                     */
+    0x11f0,    /* asciitilde:  jongseong yesieung              */
+};
+
+static const HangulJamoCombination hangul_combination_table_default[] = {
+  { 0x11001100, 0x1101 }, /* choseong  kiyeok + kiyeok = ssangkiyeok   */
+  { 0x11031103, 0x1104 }, /* choseong  tikeut + tikeut = ssangtikeut   */
+  { 0x11071107, 0x1108 }, /* choseong  pieup  + pieup  = ssangpieup    */
+  { 0x11091109, 0x110a }, /* choseong  sios   + sios   = ssangsios     */
+  { 0x110c110c, 0x110d }, /* choseong  cieuc  + cieuc  = ssangcieuc    */
+  { 0x11691161, 0x116a }, /* jungseong o      + a      = wa            */
+  { 0x11691162, 0x116b }, /* jungseong o      + ae     = wae           */
+  { 0x11691175, 0x116c }, /* jungseong o      + i      = oe            */
+  { 0x116e1165, 0x116f }, /* jungseong u      + eo     = weo           */
+  { 0x116e1166, 0x1170 }, /* jungseong u      + e      = we            */
+  { 0x116e1175, 0x1171 }, /* jungseong u      + i      = wi            */
+  { 0x11731175, 0x1174 }, /* jungseong eu     + i      = yi            */
+  { 0x11a811a8, 0x11a9 }, /* jongseong kiyeok + kiyeok = ssangekiyeok  */
+  { 0x11a811ba, 0x11aa }, /* jongseong kiyeok + sios   = kiyeok-sois   */
+  { 0x11ab11bd, 0x11ac }, /* jongseong nieun  + cieuc  = nieun-cieuc   */
+  { 0x11ab11c2, 0x11ad }, /* jongseong nieun  + hieuh  = nieun-hieuh   */
+  { 0x11af11a8, 0x11b0 }, /* jongseong rieul  + kiyeok = rieul-kiyeok  */
+  { 0x11af11b7, 0x11b1 }, /* jongseong rieul  + mieum  = rieul-mieum   */
+  { 0x11af11b8, 0x11b2 }, /* jongseong rieul  + pieup  = rieul-pieup   */
+  { 0x11af11ba, 0x11b3 }, /* jongseong rieul  + sios   = rieul-sios    */
+  { 0x11af11c0, 0x11b4 }, /* jongseong rieul  + thieuth = rieul-thieuth        */
+  { 0x11af11c1, 0x11b5 }, /* jongseong rieul  + phieuph = rieul-phieuph        */
+  { 0x11af11c2, 0x11b6 }, /* jongseong rieul  + hieuh  = rieul-hieuh   */
+  { 0x11b811ba, 0x11b9 }, /* jongseong pieup  + sios   = pieup-sios    */
+  { 0x11ba11ba, 0x11bb }, /* jongseong sios   + sios   = ssangsios     */
+};
diff --git a/pyhangul/Makefile b/pyhangul/Makefile
new file mode 100644 (file)
index 0000000..1cfeda8
--- /dev/null
@@ -0,0 +1,9 @@
+
+all:
+       python setup.py build
+
+clean:
+       rm -rf build
+
+install:
+       python setup.py install
diff --git a/pyhangul/pyhangul.c b/pyhangul/pyhangul.c
new file mode 100644 (file)
index 0000000..50c4d88
--- /dev/null
@@ -0,0 +1,179 @@
+#include <Python.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "../hangul/hangul.h"
+
+static PyObject *_pyhangul_error;
+
+// User defined Object
+typedef struct {
+    PyObject_HEAD
+} PY_HANGUL;
+
+typedef struct {
+    PyObject_HEAD
+
+    HangulInputContext *hic;
+} PY_HANGULIC;
+
+extern PyTypeObject PY_HANGULIC_Type;
+
+static PyObject *_create_ic(PY_HANGUL *self, PyObject *args)
+{ 
+    PY_HANGULIC *imObject;
+    int keyboard;
+
+    if(!PyArg_ParseTuple(args,"i",&keyboard)) {
+       PyErr_SetString(_pyhangul_error,
+                       "Usage: create_ic(keyboard)\n"
+                       "\tkeyboard: hangul2, hangul3{2,90,f,s}");
+       return NULL;
+    }
+
+    imObject = PyObject_NEW(PY_HANGULIC, &PY_HANGULIC_Type);
+    if(imObject == NULL) {
+       PyErr_SetString(_pyhangul_error,"Fail to create PY_HANGULIC Object");
+       return NULL;
+    }
+
+    imObject->hic = hangul_ic_new(keyboard);
+
+    return (PyObject *)imObject;
+}
+
+static PyMethodDef _pyhangul_methods[] = {
+    { "create_ic", (PyCFunction) _create_ic, METH_VARARGS, NULL },
+    { NULL,      NULL, 0, NULL } 
+};
+
+void inithangul(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule("hangul", _pyhangul_methods);
+    PyModule_AddIntConstant(m, "hangul2", HANGUL_KEYBOARD_2);
+    PyModule_AddIntConstant(m, "hangul32", HANGUL_KEYBOARD_32);
+    PyModule_AddIntConstant(m, "hangul390", HANGUL_KEYBOARD_390);
+    PyModule_AddIntConstant(m, "hangul3f", HANGUL_KEYBOARD_3FINAL);
+    PyModule_AddIntConstant(m, "hangul3s", HANGUL_KEYBOARD_3NOSHIFT);
+    //PyModule_AddIntConstant(m, "Hangul3_Yetgeul", HANGUL_KEYBOARD_3YETGUL);
+
+    d = PyModule_GetDict(m);
+    _pyhangul_error = PyErr_NewException("_pyhangul.error", NULL, NULL);
+    PyDict_SetItemString(d, "error", _pyhangul_error);
+} 
+
+// im's member function
+static PyObject *_pyhangulic_filter(PY_HANGULIC *self, PyObject *args)
+{
+    int ret;
+    int ascii, capslock; 
+
+    if(!PyArg_ParseTuple(args,"ii", &ascii, &capslock)) {
+       PyErr_SetString(_pyhangul_error,"Usage: filter(ascii, capslock)");
+       return NULL;
+    }
+
+    ret = hangul_ic_filter(self->hic, ascii, capslock);
+
+    return Py_BuildValue("i", ret);
+}
+
+static PyObject *_pyhangulic_reset(PY_HANGULIC *self, PyObject *args)
+{
+    hangul_ic_reset(self->hic);
+
+    return Py_None;
+}
+
+static PyObject *_pyhangulic_backspace(PY_HANGULIC *self, PyObject *args)
+{
+    int ret;
+
+    ret = hangul_ic_backspace(self->hic);
+
+    return Py_BuildValue("i", ret);
+}
+
+static PyObject *_pyhangulic_preedit_string(PY_HANGULIC *self, PyObject *args)
+{
+    int len;
+    const wchar_t *str;
+
+    str = hangul_ic_get_preedit_string(self->hic);
+    len = wcslen(str);
+    return PyUnicode_FromWideChar(str, len);
+}
+
+static PyObject *_pyhangulic_commit_string(PY_HANGULIC *self, PyObject *args)
+{
+    int len;
+    const wchar_t *str;
+
+    str = hangul_ic_get_commit_string(self->hic);
+    len = wcslen(str);
+    return PyUnicode_FromWideChar(str, len);
+}
+
+// PY_HANGULIC methods
+static PyMethodDef PY_HANGULIC_methods[] = {
+    { "filter",        (PyCFunction)_pyhangulic_filter,         METH_VARARGS, NULL},
+    { "reset",         (PyCFunction)_pyhangulic_reset,          METH_VARARGS, NULL},
+    { "backspace",     (PyCFunction)_pyhangulic_backspace,      METH_VARARGS, NULL},
+    { "preedit_string",(PyCFunction)_pyhangulic_preedit_string, METH_VARARGS, NULL},
+    { "commit_string", (PyCFunction)_pyhangulic_commit_string,  METH_VARARGS, NULL},
+    { NULL, NULL, 0, NULL }
+};
+
+// PY_HANGULIC dealloc
+static void PY_HANGULIC_dealloc(PY_HANGULIC *self)
+{
+    hangul_ic_delete(self->hic);
+    self->hic = NULL;
+    PyMem_Free((char *) self);
+}
+
+// PY_HANGULIC getattr
+static PyObject * PY_HANGULIC_getattr(PY_HANGULIC *self, char *name)
+{
+    PyObject *res;
+    res = Py_FindMethod(PY_HANGULIC_methods, (PyObject *)self, name);
+    if(res != NULL)
+       return res;
+    PyErr_Clear();
+    PyErr_SetString(_pyhangul_error,"UnKnown method");
+    return NULL;
+}
+
+// PY_HANGULIC repr
+static PyObject * PY_HANGULIC_repr(PY_HANGULIC *self)
+{
+    char buf[300];
+    sprintf(buf,"<Class pyhangul at %lx>",(long)self);
+    return PyString_FromString(buf);
+}
+
+
+// PY_HANGUL Type
+PyTypeObject PY_HANGULIC_Type = {
+#ifndef MS_WIN32
+    PyObject_HEAD_INIT(&PyType_Type)
+#else
+    PyObject_HEAD_INIT(NULL)
+#endif
+       0,
+    "hangul.hangulic",
+    sizeof(PY_HANGULIC),
+    0,
+    (destructor)PY_HANGULIC_dealloc,
+    0,
+    (getattrfunc)PY_HANGULIC_getattr,
+    0,
+    0,
+    (reprfunc)PY_HANGULIC_repr,
+};
diff --git a/pyhangul/setup.py b/pyhangul/setup.py
new file mode 100644 (file)
index 0000000..9bfab20
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import sys
+from distutils.core import setup, Extension 
+
+classifiers = """\
+Development Status :: 5 - Production/Stable
+Intended Audience :: Developers
+License :: OSI Approved :: GNU GPL
+Programming Language :: Python
+Programming Language :: C
+Topic :: Software Development :: Libraries :: Python Modules
+Operating System :: Microsoft :: Windows
+Operating System :: Unix
+"""
+if sys.platform == "win32": # for MinGW
+       include_dirs = [r'\MinGW\include', r'..']
+       library_dirs = [r'\MinGW\lib', r'..']
+       libraries = []
+       data_files = []
+       
+else:
+       include_dirs = [
+               '/usr/include'
+               '/usr/local/include'
+       ]
+       library_dirs = [
+               '/usr/lib',
+               '/usr/local/lib',
+               '../hangul'
+       ]
+       libraries = ['hangul']
+       data_files = []
+
+if sys.version_info < (2, 3):
+       _setup = setup
+       def setup(**kwargs):
+               if kwargs.has_key("classifiers"): 
+                       del kwargs["classifiers"]
+                       _setup(**kwargs)
+
+setup(name = "pyhangul", 
+       version = "0.0.1", 
+       description="libhangul for Python.",
+       author = "Joon-cheol Park", 
+       author_email="jooncheol@gmail.com", 
+       license = "GPL",
+       url="http://hangul.kldp.net", 
+       ext_modules=[Extension("hangul", ["pyhangul.c"],
+                                include_dirs = include_dirs,
+                                library_dirs = library_dirs,
+                                libraries = libraries)],
+       classifiers = filter(None, classifiers.split("\n")),
+       data_files=data_files
+       ) 
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644 (file)
index 0000000..4a463be
--- /dev/null
@@ -0,0 +1,6 @@
+
+noinst_PROGRAMS = test
+
+test_CFLAGS =
+test_SOURCES = test.c
+test_LDADD = ../hangul/libhangul.a
diff --git a/test/test.c b/test/test.c
new file mode 100644 (file)
index 0000000..6492092
--- /dev/null
@@ -0,0 +1,55 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <wchar.h>
+
+#include "../hangul/hangul.h"
+
+int
+main(int argc, char *argv[])
+{
+    int n;
+    int ascii;
+    int keyboard = HANGUL_KEYBOARD_2;
+    char commit[32] = { '\0', };
+    HangulInputContext *hic;
+
+    if (argc > 1) {
+       keyboard = atoi(argv[1]);
+    }
+
+    setlocale(LC_CTYPE, "");
+
+    hic = hangul_ic_new(keyboard);
+    if (hic == NULL) {
+       printf("hic is null\n");
+       return -1;
+    }
+
+    for (ascii = getchar(); ascii != EOF; ascii = getchar()) {
+       int ret = hangul_ic_filter(hic, ascii, 0);
+       n = wcstombs(commit, hangul_ic_get_commit_string(hic), sizeof(commit));
+       commit[n] = '\0';
+       if (strlen(commit) > 0) {
+           printf("%s", commit);
+       }
+       if (!ret) {
+           printf("%c", ascii);
+       }
+    } 
+    hangul_ic_reset(hic);
+    n = wcstombs(commit, hangul_ic_get_commit_string(hic), sizeof(commit));
+    commit[n] = '\0';
+    if (strlen(commit) > 0) {
+       printf("%s", commit);
+    }
+
+    hangul_ic_delete(hic);
+
+    return 0;
+}