로마자 구현
authorChoe Hwanjin <choe.hwanjin@gmail.com>
Fri, 16 Oct 2009 13:41:41 +0000 (22:41 +0900)
committerChoe Hwanjin <choe.hwanjin@gmail.com>
Fri, 16 Oct 2009 13:41:41 +0000 (22:41 +0900)
 * 로마자 입력 방식 구현
 * 로마자 입력 방식 테스트 코드 구현
 * backspace에서 stack이 바닥나면 초중성 코드를 모두 지운다.
   로마자 입력방식에서 임의로 추가된 중성 코드가 backspace 입력될때
   같이 지워지기 위한 구현

git-svn-id: http://kldp.net/svn/hangul/libhangul/trunk@199 8f00fcd2-89fc-0310-932e-b01be5b65e01

hangul/hangul.h
hangul/hangulinputcontext.c
hangul/hangulkeyboard.h
test/test.c

index fd6442d..b1ba34a 100644 (file)
@@ -80,7 +80,8 @@ enum {
 
 enum {
     HANGUL_KEYBOARD_TYPE_JAMO,
-    HANGUL_KEYBOARD_TYPE_JASO
+    HANGUL_KEYBOARD_TYPE_JASO,
+    HANGUL_KEYBOARD_TYPE_ROMAJA
 };
 
 /* keyboard */
index 8bf3242..96d2302 100644 (file)
@@ -131,11 +131,21 @@ static const HangulKeyboard hangul_keyboard_3yet = {
     (ucschar*)hangul_keyboard_table_3yet
 };
 
+static const HangulKeyboard hangul_keyboard_romaja = {
+    HANGUL_KEYBOARD_TYPE_ROMAJA,
+    (ucschar*)hangul_keyboard_table_romaja
+};
+
 static const HangulCombination hangul_combination_default = {
     N_ELEMENTS(hangul_combination_table_default),
     (HangulCombinationItem*)hangul_combination_table_default
 };
 
+static const HangulCombination hangul_combination_romaja = {
+    N_ELEMENTS(hangul_combination_table_romaja),
+    (HangulCombinationItem*)hangul_combination_table_romaja
+};
+
 static const HangulCombination hangul_combination_full = {
     N_ELEMENTS(hangul_combination_table_full),
     (HangulCombinationItem*)hangul_combination_table_full
@@ -471,17 +481,24 @@ hangul_buffer_backspace(HangulBuffer *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;
+       if (buffer->index >= 0) {
+           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;
+           }
+       } else {
+           buffer->choseong = 0;
+           buffer->jungseong = 0;
+           buffer->jongseong = 0;
            return true;
        }
     }
@@ -812,6 +829,183 @@ hangul_ic_process_jaso(HangulInputContext *hic, ucschar ch)
     return true;
 }
 
+static bool
+hangul_ic_process_romaja(HangulInputContext *hic, int ascii, ucschar ch)
+{
+    ucschar jong;
+    ucschar combined;
+
+    if (!hangul_is_jaso(ch) && ch > 0) {
+       hangul_ic_save_commit_string(hic);
+       hangul_ic_append_commit_string(hic, ch);
+       return true;
+    }
+
+    if (isupper(ascii)) {
+       hangul_ic_save_commit_string(hic);
+    }
+
+    if (hic->buffer.jongseong) {
+       if (ascii == 'x' || ascii == 'X') {
+           ch = 0x110c;
+           hangul_ic_save_commit_string(hic);
+           if (!hangul_ic_push(hic, ch)) {
+               return false;
+           }
+       } else if (hangul_is_choseong(ch) || hangul_is_jongseong(ch)) {
+           if (hangul_is_jongseong(ch))
+               jong = ch;
+           else
+               jong = hangul_choseong_to_jongseong(ch);
+           combined = hangul_combination_combine(hic->combination,
+                                             hic->buffer.jongseong, jong);
+           if (hangul_is_jongseong(combined)) {
+               if (!hangul_ic_push(hic, combined)) {
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               }
+           } else {
+               hangul_ic_save_commit_string(hic);
+               if (!hangul_ic_push(hic, ch)) {
+                   return false;
+               }
+           }
+       } else if (hangul_is_jungseong(ch)) {
+           if (hic->buffer.jongseong == 0x11bc) {
+               hangul_ic_save_commit_string(hic);
+               hic->buffer.choseong = 0x110b;
+               hangul_ic_push(hic, ch);
+           } else {
+               ucschar pop, peek;
+               pop = hangul_ic_pop(hic);
+               peek = hangul_ic_peek(hic);
+
+               if (hangul_is_jungseong(peek)) {
+                   if (pop == 0x11aa) {
+                       hic->buffer.jongseong = 0x11a8;
+                   } else {
+                       hic->buffer.jongseong = 0;
+                   }
+                   hangul_ic_save_commit_string(hic);
+                   hangul_ic_push(hic, hangul_jongseong_to_choseong(pop));
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               } else {
+                   ucschar choseong = 0, jongseong = 0; 
+                   hangul_jongseong_dicompose(hic->buffer.jongseong,
+                                              &jongseong, &choseong);
+                   hic->buffer.jongseong = jongseong;
+                   hangul_ic_save_commit_string(hic);
+                   hangul_ic_push(hic, choseong);
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               }
+           }
+       } else {
+           goto flush;
+       }
+    } 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)) {
+                   if (!hangul_ic_push(hic, jong)) {
+                       if (!hangul_ic_push(hic, ch)) {
+                           return false;
+                       }
+                   }
+               } else {
+                   hangul_ic_save_commit_string(hic);
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               }
+           } else {
+               if (!hangul_ic_push(hic, ch)) {
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               }
+           }
+       } else if (hangul_is_jungseong(ch)) {
+           combined = hangul_combination_combine(hic->combination,
+                                                 hic->buffer.jungseong, ch);
+           if (hangul_is_jungseong(combined)) {
+               if (!hangul_ic_push(hic, combined)) {
+                   return false;
+               }
+           } else {
+               hangul_ic_save_commit_string(hic);
+               hic->buffer.choseong = 0x110b;
+               if (!hangul_ic_push(hic, ch)) {
+                   return false;
+               }
+           }
+       } else if (hangul_is_jongseong(ch)) {
+           if (!hangul_ic_push(hic, ch)) {
+               if (!hangul_ic_push(hic, ch)) {
+                   return false;
+               }
+           }
+       } else {
+           goto flush;
+       }
+    } else if (hic->buffer.choseong) {
+       if (hangul_is_choseong(ch)) {
+           combined = hangul_combination_combine(hic->combination,
+                                                 hic->buffer.choseong, ch);
+           if (combined == 0) {
+               hic->buffer.jungseong = 0x1173;
+               hangul_ic_flush_internal(hic);
+               if (!hangul_ic_push(hic, ch)) {
+                   return false;
+               }
+           } else {
+               if (!hangul_ic_push(hic, combined)) {
+                   if (!hangul_ic_push(hic, ch)) {
+                       return false;
+                   }
+               }
+           }
+       } else if (hangul_is_jongseong(ch)) {
+           hic->buffer.jungseong = 0x1173;
+           hangul_ic_save_commit_string(hic);
+           if (ascii == 'x' || ascii == 'X')
+               ch = 0x110c;
+           if (!hangul_ic_push(hic, ch)) {
+               return false;
+           }
+       } else {
+           if (!hangul_ic_push(hic, ch)) {
+               if (!hangul_ic_push(hic, ch)) {
+                   return false;
+               }
+           }
+       }
+    } else {
+       if (ascii == 'x' || ascii == 'X') {
+           ch = 0x110c;
+       }
+
+       if (!hangul_ic_push(hic, ch)) {
+           return false;
+       } else {
+           if (hic->buffer.choseong == 0 && hic->buffer.jungseong != 0)
+               hic->buffer.choseong = 0x110b;
+       }
+    }
+
+    hangul_ic_save_preedit_string(hic);
+    return true;
+
+flush:
+    hangul_ic_flush_internal(hic);
+    return false;
+}
+
 bool
 hangul_ic_process(HangulInputContext *hic, int ascii)
 {
@@ -829,8 +1023,10 @@ hangul_ic_process(HangulInputContext *hic, int ascii)
 
     if (hangul_keyboard_get_type(hic->keyboard) == HANGUL_KEYBOARD_TYPE_JAMO)
        return hangul_ic_process_jamo(hic, c);
-    else
+    else if (hangul_keyboard_get_type(hic->keyboard) == HANGUL_KEYBOARD_TYPE_JASO)
        return hangul_ic_process_jaso(hic, c);
+    else
+       return hangul_ic_process_romaja(hic, ascii, c);
 }
 
 const ucschar*
@@ -1142,6 +1338,11 @@ hangul_ic_select_keyboard(HangulInputContext *hic, const char* id)
        hic->combination = &hangul_combination_full;
        hic->output_mode = HANGUL_OUTPUT_JAMO;
        hic->use_jamo_mode_only = TRUE;
+    } else if (strcmp(id, "ro") == 0) {
+       hic->keyboard = &hangul_keyboard_romaja;
+       hic->combination = &hangul_combination_romaja;
+       hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+       hic->use_jamo_mode_only = FALSE;
     } else {
        hic->keyboard = &hangul_keyboard_2;
        hic->combination = &hangul_combination_default;
index aa609ea..e3cccd4 100644 (file)
@@ -784,6 +784,137 @@ static const ucschar hangul_keyboard_table_3yet[] = {
     0x0000      /* 0x7F delete                                       */
 };
 
+static const ucschar hangul_keyboard_table_romaja[] = {
+    0x0000,     /* 0x00 null                                         */
+    0x0000,     /* 0x01 start of heading                             */
+    0x0000,     /* 0x02 start of text                                */
+    0x0000,     /* 0x03 end of text                                  */
+    0x0000,     /* 0x04 end of transmission                          */
+    0x0000,     /* 0x05 enquiry                                      */
+    0x0000,     /* 0x06 acknowledge                                  */
+    0x0000,     /* 0x07 bell                                         */
+    0x0000,     /* 0x08 backspace                                    */
+    0x0000,     /* 0x09 character tabulation                         */
+    0x0000,     /* 0x0A line feed (lf)                               */
+    0x0000,     /* 0x0B line tabulation                              */
+    0x0000,     /* 0x0C form feed (ff)                               */
+    0x0000,     /* 0x0D carriage return (cr)                         */
+    0x0000,     /* 0x0E shift out                                    */
+    0x0000,     /* 0x0F shift in                                     */
+    0x0000,     /* 0x10 data link escape                             */
+    0x0000,     /* 0x11 device control one                           */
+    0x0000,     /* 0x12 device control two                           */
+    0x0000,     /* 0x13 device control three                         */
+    0x0000,     /* 0x14 device control four                          */
+    0x0000,     /* 0x15 negative acknowledge                         */
+    0x0000,     /* 0x16 synchronous idle                             */
+    0x0000,     /* 0x17 end of transmission block                    */
+    0x0000,     /* 0x18 cancel                                       */
+    0x0000,     /* 0x19 end of medium                                */
+    0x0000,     /* 0x1A substitute                                   */
+    0x0000,     /* 0x1B escape                                       */
+    0x0000,     /* 0x1C information separator four                   */
+    0x0000,     /* 0x1D information separator three                  */
+    0x0000,     /* 0x1E information separator two                    */
+    0x0000,     /* 0x1F information separator one                    */
+    0x0000,     /* 0x20 space                                        */
+    0x0021,     /* 0x21 exclam:       exclamation mark               */
+    0x0022,     /* 0x22 quotedbl:     quotation mark                 */
+    0x0023,     /* 0x23 numbersign:   number sign                    */
+    0x0024,     /* 0x24 dollar:       dollar sign                    */
+    0x0025,     /* 0x25 percent:      percent sign                   */
+    0x0026,     /* 0x26 ampersand:    ampersand                      */
+    0x0027,     /* 0x27 apostrophe:   apostrophe                     */
+    0x0028,     /* 0x28 parenleft:    left parenthesis               */
+    0x0029,     /* 0x29 parenright:   right parenthesis              */
+    0x002a,     /* 0x2A asterisk:     asterisk                       */
+    0x002b,     /* 0x2B plus:         plus sign                      */
+    0x002c,     /* 0x2C comma:        comma                          */
+    0x002d,     /* 0x2D minus:        minus sign                     */
+    0x002e,     /* 0x2E period:       period                         */
+    0x002f,     /* 0x2F slash:        slash                          */
+    0x0030,     /* 0x30 0:            0                              */
+    0x0031,     /* 0x31 1:            1                              */
+    0x0032,     /* 0x32 2:            2                              */
+    0x0033,     /* 0x33 3:            3                              */
+    0x0034,     /* 0x34 4:            4                              */
+    0x0035,     /* 0x35 5:            5                              */
+    0x0036,     /* 0x36 6:            6                              */
+    0x0037,     /* 0x37 7:            7                              */
+    0x0038,     /* 0x38 8:            8                              */
+    0x0039,     /* 0x39 9:            9                              */
+    0x003a,     /* 0x3A colon:        colon                          */
+    0x003b,     /* 0x3B semicolon:    semicolon                      */
+    0x003c,     /* 0x3C less:         less-than sign                 */
+    0x003d,     /* 0x3D equal:        equals sign                    */
+    0x003e,     /* 0x3E greater:      greater-than sign              */
+    0x003f,     /* 0x3F question:     question mark                  */
+    0x0040,     /* 0x40 at:           commercial at                  */
+    0x1161,     /* 0x41 A:            jungseong a                    */
+    0x1107,     /* 0x42 B:            choseong  pieup                */
+    0x110e,     /* 0x43 C:            choseong  chieuch              */
+    0x1103,     /* 0x44 D:            choseong  tikeut               */
+    0x1166,     /* 0x45 E:            jungseong e                    */
+    0x1111,     /* 0x46 F:            choseong  phieuph              */
+    0x1100,     /* 0x47 G:            choseong  kiyeok               */
+    0x1112,     /* 0x48 H:            choseong  heiuh                */
+    0x1175,     /* 0x49 I:            jungseong i                    */
+    0x110c,     /* 0x4A J:            choseong  cieuc                */
+    0x110f,     /* 0x4B K:            choseong  khieukh              */
+    0x1105,     /* 0x4C L:            choseong  rieul                */
+    0x1106,     /* 0x4D M:            choseong  mieum                */
+    0x1102,     /* 0x4E N:            choseong  nieun                */
+    0x1169,     /* 0x4F O:            jungseong o                    */
+    0x1111,     /* 0x50 P:            choseong  phieuph              */
+    0x110f,     /* 0x51 Q:            choseong  khieukh              */
+    0x1105,     /* 0x52 R:            choseong  rieul                */
+    0x1109,     /* 0x53 S:            choseong  sios                 */
+    0x1110,     /* 0x54 T:            choseong  thieuth              */
+    0x116e,     /* 0x55 U:            jungseong u                    */
+    0x1107,     /* 0x56 V:            choseong  pieup                */
+    0x116e,     /* 0x57 W:            jungseong u                    */
+    0x110c,     /* 0x58 X:            choseong  cieuc                */
+    0x1175,     /* 0x59 Y:            jungseong i                    */
+    0x110c,     /* 0x5A Z:            choseong  cieuc                */
+    0x005b,     /* 0x5B bracketleft:  left bracket                   */
+    0x005c,     /* 0x5C backslash:    backslash                      */
+    0x005d,     /* 0x5D bracketright: right bracket                  */
+    0x005e,     /* 0x5E asciicircum:  circumflex accent              */
+    0x005f,     /* 0x5F underscore:   underscore                     */
+    0x0060,     /* 0x60 quoteleft:    grave accent                   */
+    0x1161,     /* 0x61 a:            jungseong a                    */
+    0x1107,     /* 0x62 b:            choseong  pieup                */
+    0x110e,     /* 0x63 c:            choseong  chieuch              */
+    0x1103,     /* 0x64 d:            choseong  tikeut               */
+    0x1166,     /* 0x65 e:            jungseong e                    */
+    0x1111,     /* 0x66 f:            choseong  phieuph              */
+    0x1100,     /* 0x67 g:            choseong  kiyeok               */
+    0x1112,     /* 0x68 h:            choseong  hieuh                */
+    0x1175,     /* 0x69 i:            jungseong i                    */
+    0x110c,     /* 0x6A j:            choseong  cieuc                */
+    0x110f,     /* 0x6B k:            choseong  khieukh              */
+    0x1105,     /* 0x6C l:            choseong  rieul                */
+    0x1106,     /* 0x6D m:            choseong  mieum                */
+    0x1102,     /* 0x6E n:            choseong  nieun                */
+    0x1169,     /* 0x6F o:            jungseong o                    */
+    0x1111,     /* 0x70 p:            choseong  pieup                */
+    0x110f,     /* 0x71 q:            choseong  khieukh              */
+    0x1105,     /* 0x72 r:            choseong  rieul                */
+    0x1109,     /* 0x73 s:            choseong  sios                 */
+    0x1110,     /* 0x74 t:            choseong  thieuth              */
+    0x116e,     /* 0x75 u:            jungseong u                    */
+    0x1107,     /* 0x76 v:            choseong  phieuph              */
+    0x116e,     /* 0x77 w:            jungseong u                    */
+    0x11aa,     /* 0x78 x:            jongseong kiyeoksios           */
+    0x1175,     /* 0x79 y:            jungseong i                    */
+    0x110c,     /* 0x7A z:            choseong  cieuc                */
+    0x007b,     /* 0x7B braceleft:    left brace                     */
+    0x007c,     /* 0x7C bar:          vertical bar                   */
+    0x007d,     /* 0x7D braceright:   right brace                    */
+    0x007e,     /* 0x7E asciitilde:   tilde                          */
+    0x0000      /* 0x7F delete                                       */
+};
+
 static const HangulCombinationItem hangul_combination_table_default[] = {
   { 0x11001100, 0x1101 }, /* choseong  kiyeok + kiyeok  = ssangkiyeok   */
   { 0x11031103, 0x1104 }, /* choseong  tikeut + tikeut  = ssangtikeut   */
@@ -812,6 +943,54 @@ static const HangulCombinationItem hangul_combination_table_default[] = {
   { 0x11ba11ba, 0x11bb }, /* jongseong sios   + sios    = ssangsios     */
 };
 
+static const HangulCombinationItem hangul_combination_table_romaja[] = {
+  { 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    */
+  { 0x110e1112, 0x110e }, /* choseong  chieuch+ hieuh   = chieuch       */
+  { 0x11611166, 0x1162 }, /* jungseong a      + e       = ae            */
+  { 0x11611175, 0x1162 }, /* jungseong a      + i       = ae            */
+  { 0x11631166, 0x1164 }, /* jungseong ya     + e       = yae           */
+  { 0x11631175, 0x1164 }, /* jungseong ya     + i       = yae           */
+  { 0x11661169, 0x1165 }, /* jungseong e      + o       = eo            */
+  { 0x1166116e, 0x1173 }, /* jungseong e      + u       = eu            */
+  { 0x11681169, 0x1167 }, /* jungseong ye     + o       = yeo           */
+  { 0x11691161, 0x116a }, /* jungseong o      + a       = wa            */
+  { 0x11691162, 0x116b }, /* jungseong o      + ae      = wae           */
+  { 0x11691175, 0x116c }, /* jungseong o      + i       = oe            */
+  { 0x116a1166, 0x116b }, /* jungseong wa     + e       = wae           */
+  { 0x116a1175, 0x116b }, /* jungseong wa     + i       = wae           */
+  { 0x116e1161, 0x116a }, /* jungseong u      + a       = wa            */
+  { 0x116e1165, 0x116f }, /* jungseong u      + eo      = weo           */
+  { 0x116e1166, 0x1170 }, /* jungseong u      + e       = we            */
+  { 0x116e1169, 0x116f }, /* jungseong u      + o       = weo           */
+  { 0x116e1175, 0x1171 }, /* jungseong u      + i       = wi            */
+  { 0x11701169, 0x116f }, /* jungseong we     + o       = weo           */
+  { 0x11731175, 0x1174 }, /* jungseong eu     + i       = yi            */
+  { 0x11751161, 0x1163 }, /* jungseong i      + a       = ya            */
+  { 0x11751162, 0x1164 }, /* jungseong i      + ae      = yae           */
+  { 0x11751165, 0x1167 }, /* jungseong i      + eo      = yeo           */
+  { 0x11751166, 0x1168 }, /* jungseong i      + e       = ye            */
+  { 0x11751169, 0x116d }, /* jungseong i      + o       = yo            */
+  { 0x1175116e, 0x1172 }, /* jungseong i      + u       = yu            */
+  { 0x11a811a8, 0x11a9 }, /* jongseong kiyeok + kiyeok  = ssangekiyeok  */
+  { 0x11a811ba, 0x11aa }, /* jongseong kiyeok + sios    = kiyeok-sois   */
+  { 0x11ab11a8, 0x11bc }, /* jongseong nieun  + kiyeok  = ieung         */
+  { 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     */
+};
+
 static const HangulCombinationItem hangul_combination_table_full[] = {
   { 0x11001100, 0x1101 }, /* choseong ssangkiyeok           = kiyeok + kiyeok */
   { 0x11021100, 0x1113 }, /* choseong nieun-kiyeok          = nieun + kiyeok */
index 788231d..484a0c1 100644 (file)
@@ -5,6 +5,122 @@
 
 #define countof(x)  ((sizeof(x)) / (sizeof(x[0])))
 
+START_TEST(test_hangul_ic_process_romaja)
+{
+    HangulInputContext* ic;
+    const ucschar* preedit;
+    const ucschar* commit;
+
+    // romaja keyboard test
+    ic = hangul_ic_new("ro");
+
+    // basic test: han produces 한
+    hangul_ic_process(ic, 'h');
+    hangul_ic_process(ic, 'a');
+    hangul_ic_process(ic, 'n');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xd55c); // 한
+    fail_unless(commit[0] == 0);
+
+    hangul_ic_reset(ic);
+
+    // insert ㅇ when a syllable is not started with consonant
+    hangul_ic_process(ic, 'a');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xc544); // 아
+    fail_unless(commit[0] == 0);
+
+    // remove correctly when automatically ㅇ was inserted
+    hangul_ic_backspace(ic);
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0);
+    fail_unless(commit[0] == 0);
+
+    // append ㅡ when a syllable is not ended with vowel
+    hangul_ic_process(ic, 't');
+    hangul_ic_process(ic, 't');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0x314c); // ㅌ
+    fail_unless(commit[0] == 0xd2b8);  // 트
+
+    // ng makes trailing ㅇ
+    hangul_ic_reset(ic);
+    hangul_ic_process(ic, 'g');
+    hangul_ic_process(ic, 'a');
+    hangul_ic_process(ic, 'n');
+    hangul_ic_process(ic, 'g');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xac15); // 강
+    fail_unless(commit[0] == 0);
+
+    // gangi makes 강이
+    hangul_ic_process(ic, 'i');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xc774); // 이
+    fail_unless(commit[0] == 0xac15);  // 강
+
+    // nanG makes 난ㄱ
+    // uppercase makes new syllable
+    hangul_ic_process(ic, 'n');
+    hangul_ic_process(ic, 'a');
+    hangul_ic_process(ic, 'n');
+    hangul_ic_process(ic, 'G');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0x3131); // ㄱ
+    fail_unless(commit[0] == 0xb09c);  // 난
+
+    // special operation for x
+    // x generate ㅈ for leading consonant
+    hangul_ic_reset(ic);
+    hangul_ic_process(ic, 'x');
+    hangul_ic_process(ic, 'x');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0x3148); // 지
+    fail_unless(commit[0] == 0xc988);
+
+    hangul_ic_reset(ic);
+    hangul_ic_process(ic, 'x');
+    hangul_ic_process(ic, 'y');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xc9c0); // 지
+    fail_unless(commit[0] == 0x0);
+
+    // x generate ㄱㅅ for trailing consonant
+    // and ㅅ will be transferred to next syllable when next input
+    // character is vowel.
+    hangul_ic_reset(ic);
+    hangul_ic_process(ic, 's');
+    hangul_ic_process(ic, 'e');
+    hangul_ic_process(ic, 'x');
+    hangul_ic_process(ic, 'y');
+
+    preedit = hangul_ic_get_preedit_string(ic);
+    commit = hangul_ic_get_commit_string(ic);
+    fail_unless(preedit[0] == 0xc2dc); // 시
+    fail_unless(commit[0] == 0xc139);  // 섹
+    
+    hangul_ic_delete(ic);
+}
+END_TEST
+
 START_TEST(test_syllable_iterator)
 {
     ucschar str[] = {
@@ -123,6 +239,7 @@ Suite* libhangul_suite()
     Suite* s = suite_create("libhangul");
 
     TCase* hangul = tcase_create("hangul");
+    tcase_add_test(hangul, test_hangul_ic_process_romaja);
     tcase_add_test(hangul, test_syllable_iterator);
     suite_add_tcase(s, hangul);