Logo Search packages:      
Sourcecode: hanterm-xf version File versions  Download package

automata.c

/*
   Hangul Automata

   Written by Song Jaekyung
 */

#ifdef HAVE_CONFIG_H
#include <xtermcfg.h>
#endif
#include "ptyx.h"
#include "data.h"
#include "xterm.h"
#include "hangul.h"


static void display_temp PROTO((int f, int m, int l));
#ifdef QUEUE_DRAW
static void display_temp2 PROTO((int f, int m, int l));
#else
#define display_temp2(f,m,l) display_temp(f,m,l)
#endif
static int ascii PROTO((int c, Char *buf));
static void automata_error PROTO((void));
static void draw_cell PROTO((int x, int y, int len));

#define F_NULL 1
#define M_NULL 2
#define L_NULL 1

int hangul_state = 0;
Char temp_hangul[8] = {0};
static int f = F_NULL, m = M_NULL, l = L_NULL;
static int sp = 0, pc, ppc, stack[10];
static int in_ks PROTO((int f, int m, int l));

#define push(x)   ( stack[ sp++ ] = (x) )
#define pop()     ( stack[ --sp ] )

/* table_for_3 에서 사용될 flag */

#define     F_F   0x100       /* 초성 */
#define F_M 0x200       /* 중성 */
#define F_L 0x400       /* 종성 */
#define F_A 0x800       /* ASCII */

/* 3 벌식에서 자판 변환 */

static unsigned short table_for_3[] =
{
    24 | F_L, '"' | F_A, '#' | F_A, '$' | F_A, '%' | F_A, '&' | F_A,    /* ! " # $ % & */
    18 | F_F, '(' | F_A, ')' | F_A, '*' | F_A, '+' | F_A, ',' | F_A,    /* ' ( ) * + , */
    '-' | F_A, '.' | F_A, 13 | F_M, 17 | F_F, 29 | F_L, 22 | F_L, /* - . / 0 1 2 */
    19 | F_L, 19 | F_M, 26 | F_M, 5 | F_M, 12 | F_M, 28 | F_M,    /* 3 4 5 6 7 8 */
    20 | F_M, ':' | F_A, 9 | F_F, '2' | F_A, '=' | F_A, '3' | F_A,      /* 9 : ; < = > */
    '?' | F_A, '@' | F_A, 8 | F_L, '!' | F_A, 11 | F_L, 10 | F_L, /* ? @ A B C D */
    26 | F_L, 3 | F_L, '/' | F_A, 39 | F_A, '8' | F_A, '4' | F_A, /* E F G H I J */
    '5' | F_A, '6' | F_A, '1' | F_A, '0' | F_A, '9' | F_A, '>' | F_A,   /* K L M N O P */
    28 | F_L, 6 | F_M, 7 | F_L, ';' | F_A, '7' | F_A, 16 | F_L,         /* Q R S T U V */
    27 | F_L, 20 | F_L, '<' | F_A, 25 | F_L, '[' | F_A, 92 | F_A, /* W X Y Z [ \ */
    ']' | F_A, '^' | F_A, '_' | F_A, '`' | F_A, 23 | F_L, 20 | F_M,     /* ] ^ _ ` a b */
    10 | F_M, 29 | F_M, 11 | F_M, 3 | F_M, 27 | F_M, 4 | F_F,     /* c d e f g h */
    8 | F_F, 13 | F_F, 2 | F_F, 14 | F_F, 20 | F_F, 11 | F_F,     /* i j k l m n */
    16 | F_F, 19 | F_F, 21 | F_L, 4 | F_M, 5 | F_L, 7 | F_M,      /* o p q r s t */
    5 | F_F, 13 | F_M, 9 | F_L, 2 | F_L, 7 | F_F, 17 | F_L, /* u v w x y z */
};

/* 3 벌식에서 영문자 -> 초성 변환
   결과: 초성이 아니면 0
 */
static int fcon3(c)
int c;
{
    if (c >= '!' && c <= 'z')
      if (table_for_3[c - '!'] & F_F)
          return table_for_3[c - '!'] & 0xff;
    return 0;
}

/* 3 벌식에서 영문자 -> 중성 변환
   결과: 중성이 아니면 0
 */
static int vow3(c)
int c;
{
    if (c >= '!' && c <= 'z')
      if (table_for_3[c - '!'] & F_M)
          return table_for_3[c - '!'] & 0xff;
    return 0;
}

/* 3 벌식에서 영문자 -> 받침 변환
   결과: 받침이 아니면 0
 */
static int lcon3(c)
int c;
{
    if (c >= '!' && c <= 'z')
      if (table_for_3[c - '!'] & F_L)
          return table_for_3[c - '!'] & 0xff;
    return 0;
}

/* 3 벌식에서 (현재초성, 입력영문) -> 복합초성 처리 */

static int comfcon3(v, c)
int v, c;
{
#ifdef DELETED
    switch (v) {
    case 2:             /* ㄱ */
      switch (c) {
      case 'k':         /* ㄱ */
          return 3;           /* ㄲ */
      }
      break;
    case 5:             /* ㄷ */
      switch (c) {
      case 'u':
          return 6;           /* ㄸ */
      }
      break;
    case 9:             /* ㅂ */
      switch (c) {
      case ';':
          return 10;
      }
      break;
    case 11:                  /* ㅅ */
      switch (c) {
      case 'n':
          return 12;
      }
      break;
    case 14:                  /* ㅈ */
      switch (c) {
      case 'l':
          return 15;
      }
    }
#else
    if (v == 2 && c == 'k')
      return 3;
    if (v == 5 && c == 'u')
      return 6;
    if (v == 9 && c == ';')
      return 10;
    if (v == 11 && c == 'n')
      return 12;
    if (v == 14 && c == 'l')
      return 15;
#endif
    return 0;
}

/* 3 벌식에서 (현재모음, 입력 영문) -> 복합 모음 처리 */

static int comvow3(v, c)
int v, c;
{
    switch (v) {
    case 13:                  /* ㅗ */
      switch (c) {
      case 'f':         /* ㅗㅏ */
          return 14;
      case 'r':         /* ㅗㅐ */
          return 15;
      case 'd':         /* ㅗㅣ */
          return 18;
      }
      break;
    case 20:                  /* ㅜ */
      switch (c) {
      case 't':         /* ㅜㅓ */
          return 21;
      case 'c':         /* ㅜㅔ */
          return 22;
      case 'd':         /* ㅜㅣ */
          return 23;
      }
      break;

      /* 3 벌식 자판은 ㅡㅣ 가 있으므로 ... */
    }
    return 0;
}

/* 3 벌식에서 (현재 받침, 영문자 입력) -> 받침 */

static int comcon3(k, c)
int k;
int c;
{
    switch (k) {
    case 2:             /* ㄱ */
      switch (c) {
      case 'x':
          return 3;           /* ㄱㄱ */
      case 'q':
          return 4;           /* ㄱㅅ */
      }
      break;
    case 5:             /* ㄴ */
      switch (c) {
      case '!':         /* ㄴㅈ */
          return 6;
      case '1':
          return 7;           /* ㄴㅎ */
      }
      break;
    case 9:             /* ㄹ */
      switch (c) {
      case 'x':         /* ㄹㄱ */
          return 10;
      case 'z':         /* ㄹㅁ */
          return 11;
      case '3':         /* ㄹㅂ */
          return 12;
      case 'q':         /* ㄹㅅ */
          return 13;
      case 'W':         /* ㄹㅌ */
          return 14;
      case 'Q':         /* ㄹㅍ */
          return 15;
      case '1':         /* ㄹㅎ */
          return 16;
      }
      break;
    case 19:
      switch (c) {
      case 'q':         /* ㅂㅅ */
          return 20;
      }
      break;
    }
    return 0;
}

/* 3 벌식에서 영문자 처리 */

static int ascii3(c, buf)
int c;
Char *buf;
{
    if (c >= '!' && c <= 'z')
      if (table_for_3[c - '!'] & F_A)
          c = table_for_3[c - '!'] & 0xff;
    return ascii(c, buf);
}

/* 2 벌식에서 영문자 -> 조합형 초성 변환
   결과: 초성이 아니면 0
 */
static int fcon(c)
int c;
{
    static char table[] =
    {
    /*E */ 6, /*F */ 0, /*G */ 0, /*H */ 0, /*I */ 0, /*J */ 0, /*K */ 0,
    /*L */ 0, /*M */ 0, /*N */ 0, /*O */ 0, /*P */ 0, /*Q */ 10, /*R */ 3,
    /*S */ 0, /*T */ 12, /*U */ 0, /*V */ 0, /*W */ 15, /*X */ 0, /*Y */ 0,
    /*Z */ 0, /*[ */ 0, /*\ */ 0, /*] */ 0, /*^ */ 0, /*_*/ 0, /*` */ 0,
    /*a */ 8, /*b */ 0, /*c */ 16, /*d */ 13, /*e */ 5, /*f */ 7, /*g */ 20,
    /*h */ 0, /*i */ 0, /*j */ 0, /*k */ 0, /*l */ 0, /*m */ 0, /*n */ 0,
    /*o */ 0, /*p */ 0, /*q */ 9, /*r */ 2, /*s */ 4, /*t */ 11, /*u */ 0,
    /*v */ 19, /*w */ 14, /*x */ 18, /*y */ 0, /*z */ 17};

    if (c < 'E' || c > 'z')
      return 0;
    return table[c - 'E'];
}

/* 2 벌식에서 영문자 -> 중성 변환
   결과: 중성이 아니면 0
 */
static int vow(c)
int c;
{
    static char table[] =
    {
    /*O */ 6, /*P */ 12, /*Q */ 0, /*R */ 0, /*S */ 0, /*T */ 0, /*U */ 0,
    /*V */ 0, /*W */ 0, /*X */ 0, /*Y */ 0, /*Z */ 0, /*[ */ 0, /*\ */ 0,
    /*] */ 0, /*^ */ 0, /*_*/ 0, /*` */ 0, /*a */ 0, /*b */ 26, /*c */ 0,
    /*d */ 0, /*e */ 0, /*f */ 0, /*g */ 0, /*h */ 13, /*i */ 5, /*j */ 7,
    /*k */ 3, /*l */ 29, /*m */ 27, /*n */ 20, /*o */ 4, /*p */ 10, /*q */ 0,
    /*r */ 0, /*s */ 0, /*t */ 0, /*u */ 11, /*v */ 0, /*w */ 0, /*x */ 0,
    /*y */ 19};

    if (c < 'O' || c > 'y')
      return 0;
    return table[c - 'O'];
}

/* 2벌식에서 영문자 -> 받침 변환
   결과: 받침이 아니면 0
 */
static int lcon(c)
int c;
{
    static char table[] =
    {
    /*R */ 3, /*S */ 0, /*T */ 22,/*U */ 0, /*V */ 0, /*W */ 0, /*X */ 0,
    /*Y */ 0, /*Z */ 0, /*[ */ 0, /*\ */ 0, /*] */ 0, /*^ */ 0, /*_*/ 0,
    /*` */ 0, /*a */ 17,/*b */ 0, /*c */ 25,/*d */ 23,/*e */ 8, /*f */ 9,
    /*g */ 29,/*h */ 0, /*i */ 0, /*j */ 0, /*k */ 0, /*l */ 0, /*m */ 0,
    /*n */ 0, /*o */ 0, /*p */ 0, /*q */ 19,/*r */ 2, /*s */ 5, /*t */ 21,
    /*u */ 0, /*v */ 28, /*w */24,/*x */ 27,/*y */ 0, /*z */ 26};

    if (c < 'R' || c > 'z')
      return 0;
    return table[c - 'R'];
}

/* 2 벌식에서 (현재 받침, 영문자 입력) -> 받침 변환 */

static int comcon(k, c)
int k;
int c;
{
    switch (k) {
    case 2:             /* ㄱ */
      switch (c) {
      case 't':
          return 4;           /* ㄱㅅ */
      }
      break;
    case 5:             /* ㄴ */
      switch (c) {
      case 'w':         /* ㄴㅈ */
          return 6;
      case 'g':         /* ㄴㅎ */
          return 7;
      }
      break;
    case 9:             /* ㄹ */
      switch (c) {
      case 'r':         /* ㄹㄱ */
          return 10;
      case 'a':         /* ㄹㅁ */
          return 11;
      case 'q':         /* ㄹㅂ */
          return 12;
      case 't':         /* ㄹㅅ */
          return 13;
      case 'x':         /* ㄹㅌ */
          return 14;
      case 'v':         /* ㄹㅍ */
          return 15;
      case 'g':         /* ㄹㅎ */
          return 16;
      }
      break;
    case 19:                  /* ㅂ */
      switch (c) {
      case 't':         /* ㅂㅅ */
          return 20;
      }
      break;
    }
    return 0;
}

/* 2벌식에서 (현재 중성, 영문 입력) -> 중성 변환 */

static int comvow(v, c)
int v;
int c;
{
    switch (v) {
    case 13:                  /* ㅗ */
      switch (c) {
      case 'k':         /* ㅗㅏ */
          return 14;
      case 'o':         /* ㅗㅐ */
          return 15;
      case 'l':         /* ㅗㅣ */
          return 18;
      }
      break;
    case 20:                  /* ㅜ */
      switch (c) {
      case 'j':         /* ㅜㅓ */
          return 21;
      case 'p':         /* ㅜㅔ */
          return 22;
      case 'l':         /* ㅜㅣ */
          return 23;
      }
      break;
    case 27:                  /* ㅡ */
      switch (c) {
      case 'l':         /* ㅡㅣ */
          return 28;
      }
      break;
    }
    return 0;
}

/* 2 벌식에서 영문 처리 */

static int ascii(c, buf)
int c;
Char *buf;
{
    if (c == -1) {
      if (hangul_state)
          hangul_state = 0;
      else {
          hangul_state = 1;
          f = 1;
          m = 2;
          l = 1;
      }
      show_status(&term->screen, 0, 0);
      return 0;
    } else if (c == -2) {     /* flush output */
      f = 1;
      m = 2;
      l = 1;
      return 0;
    } else if (hangul_state && c == 27 && term->misc.esc_hangul_toggle) {
      hangul_state = 0;
      show_status(&term->screen, 0, 0);
      buf[0] = c;
      return 1;
    } else {
      buf[0] = c;
      return 1;
    }
}

static void automata_error()
{
    Bell(XkbBI_MinorError, 0);
}

/* (영문 입력) -> 쓰이는 코드에따라 완성형이나 조합형 문자열
   c : 영문 ASCII
   -1 : 한영 toggle
   -2 : 현재 구성중인 한글을 돌려 준다. flush.
   buf : 완성된 글자의 KS C 5601 - 1992 코드
   결과: buf 에 몇 바이트나 들어 갔는가
   외부 참조: display_temp() : 현재 구성중인 한글을 화면에 그려 준다.
   term->screen.keyboard : 자판 결정. 2 = 2벌식, 3 = 3벌식
   convert_3_to_ks() : 조합->완성 변환. 변환된 후 문자열 길이를
   돌려 줘야 한다. 2 또는 8
   show_status() : 한글 상태 인지 영문 상태인지 표시한다.
 */

#ifdef USE_NEW_AUTOMATA
/* 완성형코드를 쓰는 경우 코드에 없는 문자를 입력하는것을 금지한다.
   적합하지않는 코드가 오는 경우 이미 구성하고있는 글자를
   보내는 방식이 아니라 거부하는 방식을 취한다. 
   즉 초성없이 중성이나 종성이 오는 경우와 같이 부절적한 경우
   삑소리를 내며 입력을 거부한다.
   이 기능은 영문상태를 한글상태로 착각하고 계속 타이핑을 하는 경우나
   연속되는 두 키를 서로 바꾸어 쳤을때 기존 입력방식이 기다란
   한글 자모의 코드를 내는 것이 싫어서 만든 방식입니다. 
   단점: 초성이나 중성 문자코드을 입력하는게 불편하다.  */

int hangul_automata(c, buf)
int c;                        /* input character */
Char *buf;
{
    int t, t2, rs;

    if (hangul_state == 0)    /* 영문 상태 */
      return ascii(c, buf);

    if (term->screen.keyboard == 2) {     /* 두벌식 */
      switch (hangul_state) {
      case 1:           /* 초성을 기다림 */
          sp = 0;
          if ((t = fcon(c))) {
            display_temp(t, 2, 1);
            f = t;
            hangul_state = 2;
            return 0;
          } else if ((t = vow(c))) {
            display_temp(1, t, 1);
            f = 1;
            m = t;
            push(2);
            hangul_state = 3;
            return 0;
          } else {
            return ascii(c, buf);
          }
          break;
      case 2:           /* 중성 기다림 */
          if ((t = vow(c))) {
            display_temp(f, t, 1);
            push(2);
            m = t;
            hangul_state = 3;
            return 0;
          } else if ((t = fcon(c))) {
            rs = (*convert_3_to_code) (f, 2, 1, buf);
            display_temp(t, 2, 1);
            sp = 0;
            f = t;
            hangul_state = 2;
            return rs;
          } else if (c == '\b' || c == 0x7f) {
            display_temp(-1, -1, -1);
            hangul_state = 1;
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, 2, 1, buf);
            display_temp(-1, -1, -1);
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      case 3:           /* 종성 기다림 */
          if ((t = lcon(c)) && in_ks(f, m, t)) {
            display_temp(f, m, t);
            push(L_NULL);
            l = t;
            pc = c;
            hangul_state = 4;
            return 0;
          } else if ((t = comvow(m, c))) {
            display_temp(f, t, 1);
            push(m);
            m = t;
            return 0;
          } 
          if ((t = fcon(c))) {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            display_temp(t, 2, 1);
            f = t;
            sp = 0;
            hangul_state = 2;
            return rs;
          } else if ((t = vow(c))) {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            f = 1;
            m = t;
            l = 1;
            display_temp2(f, m, l);
            sp = 0;
            push(2);
            return rs;
          }
#ifdef linux
          else if (c == '\b' || c == 0x7f)
#else
          else if (c == '\b')
#endif
          {             /* back space */
            m = pop();
            if (m == 2) {     /* we extracted all */
                if (f == 1) {
                  hangul_state = 1;
                  f = -1;
                } else {
                  hangul_state = 2;
                }
            }
            display_temp(f, m, 1);
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            display_temp(-1, -1, -1);
            sp = 0;
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      case 4:           /* 복합 받침 기다림 */
          if ((t = comcon(l, c)) && in_ks(f, m, t)) {
            display_temp(f, m, t);
            push(l);
            l = t;
            ppc = pc;
            pc = c;
            return 0;
          } else if ((t = vow(c))) {
            rs = (*convert_3_to_code) (f, m, pop(), buf);
            display_temp2(f = fcon(pc), m = t, 1);
            sp = 0;
            push(2);
            hangul_state = 3;
            return rs;
          } else if ((t = fcon(c))) {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp2(t, 2, 1);
            f = t;
            sp = 0;
            hangul_state = 2;
            return rs;
          }
#ifdef linux
          else if (c == '\b' || c == 0x7f)
#else
          else if (c == '\b')
#endif
          {             /* back space */
            display_temp(f, m, l = pop());
            if (l == 1) {
                hangul_state = 3;
                pc = 0;
            } else {
                pc = ppc;
                ppc = 0;
            }
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp(-1, -1, -1);
            sp = 0;
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      }
    } else if (term->screen.keyboard == 3) {    /* 세벌식 */
      if ((t = fcon3(c))) { /* 초성 */
          if (m != M_NULL) { /* 중성이 이미 있다 */
            (*convert_3_to_code)(f, m, l, buf);
            sp = 0;
            m = M_NULL; l = L_NULL;
            f = t;
            push((f << 10) | (m << 5) | l);
            display_temp2(f, m, l);
            return 2;
          }
          if (f != F_NULL) { /* 초성이 이미 있다 */
            t2 = comfcon3(f, c);
            if (t2) {
                f = t2;
                push((f << 10) | (m << 5) | l);
                display_temp(f, m, l);
                return 0;
            }
            automata_error();
            return 0;
          }
          /* 첫 입력이다 */
          f = t;
          push((f << 10) | (m << 5) | l);
          display_temp(f, m, l);
          return 0;
      } else if ((t = vow3(c))) { /* 모음 */
#if 0
          if (l != L_NULL || f == F_NULL) {
            /* 초성이 없거나 받침이 있다 */
            automata_error();
            return 0;
          }
#endif
          if (m == M_NULL) {
            /* 중성이 없다 */
            if (!in_ks(f, t, l)) {
                automata_error();
                return 0;
            }
            m = t;
            push((f << 10) | (m << 5) | l);
            display_temp(f, m, l);
            return 0;
          }
          /* 이미 중성이 있는 경우, 복모음 테스트 */
          if ((t2 = comvow3(m, c))) {
            if (in_ks(f, t2, l)) {
                m = t2;
                push((f << 10) | (m << 5) | l);
                display_temp(f, m, l);
                return 0;
            }
          } 
          /* 복모음으로 모으는게 실패했거나 완성형에 없는 복모음이다 */
          /* 새 한글모으기를 시작 */
          (*convert_3_to_code)(f, m, l, buf);
          sp = 0;
          f = F_NULL;
          m = t;
          l = L_NULL;
          push((f << 10) | (m << 5) | l);
          display_temp2(f, m, l);
          return 2;
      } else if ((t = lcon3(c))) { /* 받침이다 */
          if (l != L_NULL) { /* 이미 받침이 있다 */
            t2 = comcon3(l, c);
            if (t2 && in_ks(f, m, t2)) {
                l = t2;
                display_temp(f, m, l);
                push((f << 10) | (m << 5) | l);
                return 0;
            } 
            automata_error();
            return 0;
          } else {
            if (in_ks(f, m, t)) {
                l = t;
                display_temp(f, m, l);
                push((f << 10) | (m << 5) | l);
                return 0;
            } else {
                /* 이 받침을 갖는 글자가 완성형에 없다 */
                automata_error();
                return 0;
            }
          }
      }
#ifdef linux
      else if (c == '\b' || c == 0x7f)
#else
      else if (c == '\b')
#endif
      {
          if (sp > 0) {
            (void)pop();            /* 맨위의 글자는 버린다 */
            if (sp > 0) {
                t = stack[sp - 1];
                f = t >> 10;
                m = (t >> 5) & 0x1f;
                l = t & 0x1f;
                display_temp(f, m, l);
                return 0;
            }
            display_temp(-1, -1, -1);
            automata_clear();
            return 0;
          } else {
            return ascii3(c, buf);
          }
      } else {
          /* 한글도 아니고 backspace도 아니다 */
          if (f != F_NULL || m != M_NULL || l != L_NULL) {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp(-1, -1, -1);
            automata_clear();
          } else {
            rs = 0;
          }
          return rs + ascii3(c, buf + rs);
      }
    }
    return 0;
}
#else /* !USE_NEW_AUTOMATA */

int hangul_automata(c, buf)
int c;                        /* input character */
Char *buf;
{
    int t, t2, rs;

    if (hangul_state == 0)    /* 영문 상태 */
      return ascii(c, buf);

    if (term->screen.keyboard == 2) {     /* 2 벌식 */
      switch (hangul_state) {
      case 1:           /* 초성을 기다림 */
          sp = 0;
          if (t = fcon(c)) {
            display_temp(t, 2, 1);
            f = t;
            hangul_state = 2;
            return 0;
          } else if (t = vow(c)) {
            display_temp(1, t, 1);
            f = 1;
            m = t;
            push(2);
            hangul_state = 3;
            return 0;
          } else {
            return ascii(c, buf);
          }
          break;
      case 2:           /* 중성 기다림 */
          if (t = vow(c)) {
            display_temp(f, t, 1);
            push(2);
            m = t;
            hangul_state = 3;
            return 0;
          } else if (t = fcon(c)) {
            rs = (*convert_3_to_code) (f, 2, 1, buf);
            display_temp(t, 2, 1);
            sp = 0;
            f = t;
            hangul_state = 2;
            return rs;
          } else if (c == '\b' || c == 0x7f) {
            display_temp(-1, -1, -1);
            hangul_state = 1;
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, 2, 1, buf);
            display_temp(-1, -1, -1);
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      case 3:           /* 종성 기다림 */
          if ((t = lcon(c)) && in_ks(f, m, t)) {
            display_temp(f, m, t);
            push(1);
            l = t;
            pc = c;
            hangul_state = 4;
            return 0;
          } else if (t = comvow(m, c)) {
            display_temp(f, t, 1);
            push(m);
            m = t;
            return 0;
          } else if (t = fcon(c)) {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            display_temp(t, 2, 1);
            f = t;
            sp = 0;
            hangul_state = 2;
            return rs;
          } else if (t = vow(c)) {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            f = 1;
            m = t;
            l = 1;
            display_temp2(f, m, l);
            sp = 0;
            push(2);
            return rs;
          }
#ifdef linux
          else if (c == '\b' || c == 0x7f)
#else
          else if (c == '\b')
#endif
          {             /* back space */
            m = pop();
            if (m == 2) {     /* we extracted all */
                if (f == 1) {
                  hangul_state = 1;
                  f = -1;
                } else {
                  hangul_state = 2;
                }
            }
            display_temp(f, m, 1);
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, m, 1, buf);
            display_temp(-1, -1, -1);
            sp = 0;
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      case 4:           /* 복합 받침 기다림 */
          if (t = comcon(l, c)) {
            display_temp(f, m, t);
            push(l);
            l = t;
            pc = c;
            return 0;
          } else if (t = vow(c)) {
            rs = (*convert_3_to_code) (f, m, pop(), buf);
            display_temp2(f = fcon(pc), m = t, 1);
            sp = 0;
            push(2);
            hangul_state = 3;
            return rs;
          } else if (t = fcon(c)) {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp2(t, 2, 1);
            f = t;
            sp = 0;
            hangul_state = 2;
            return rs;
          }
#ifdef linux
          else if (c == '\b' || c == 0x7f)
#else
          else if (c == '\b')
#endif
          {             /* back space */
            display_temp(f, m, l = pop());
            if (l == 1)
                hangul_state = 3;
            return 0;
          } else {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp(-1, -1, -1);
            sp = 0;
            hangul_state = 1;
            return ascii(c, buf + rs) + rs;
          }
          break;
      }
    } else if (term->screen.keyboard == 3) {    /* 3 벌식 */
      if (t = fcon3(c)) {
          t2 = 0;
          if (f > 1 && !(t2 = comfcon3(f, c)) || m > 2 || l > 1) {      
            /* 중성이 있거나 받침이 있음 */
            rs = (*convert_3_to_code) (f, m, l, buf);
            sp = 0;
            m = 2;
            l = 1;
          } else {
            if (t2) {
                t = t2;
            }
            rs = 0;
          }
          f = t;
          if (rs)
            display_temp2(f, m, l);
          else
            display_temp(f, m, l);
          /* new char */
          push((f << 10) | (m << 5) | l);
          return rs;
      } else if (t = vow3(c)) {
          t2 = 0;
          if (m > 2 && !(t2 = comvow3(m, c)) || l > 1) {    /* 받침이 있음 */
            rs = (*convert_3_to_code) (f, m, l, buf);
            sp = 0;
            f = 1;
            l = 1;
          } else {
            if (t2) {
                t = t2;
            }
            rs = 0;
          }
          m = t;
          if (rs)
            display_temp2(f, m, l);
          else
            display_temp(f, m, l);
          /* new char */
          push((f << 10) | (m << 5) | l);
          return rs;
      } else if (t = lcon3(c)) {
          t2 = 0;
          if ((f != F_NULL && m == M_NULL) || (l != L_NULL && !(t2 = comcon3(l, c)))) {   /* 초성은 있고 중성이 없음 */
            rs = (*convert_3_to_code) (f, m, l, buf);
            sp = 0;
            f = 1;
            m = 2;
          } else {
            if (t2) {
                t = t2;
            }
            rs = 0;
          }
          l = t;
          if (rs)
            display_temp2(f, m, l);
          else
            display_temp(f, m, l);
          /* new char */
          push((f << 10) | (m << 5) | l);
          return rs;
      }
#ifdef linux
      else if (c == '\b' || c == 0x7f)
#else
      else if (c == '\b')
#endif
      {
          if (sp > 0) {
            (void)pop();            /* 맨위의 글자는 버린다 */
            if (sp > 0) {
                t = stack[sp - 1];
                f = t >> 10;
                m = (t >> 5) & 0x1f;
                l = t & 0x1f;
                display_temp(f, m, l);
                return 0;
            }
            display_temp(-1, -1, -1);
            automata_clear();
            return 0;
          } else {
            return ascii3(c, buf);
          }
      } else {
          if (f > 1 || m > 2 || l > 1) {
            rs = (*convert_3_to_code) (f, m, l, buf);
            display_temp(-1, -1, -1);
            automata_clear();
          } else {
            rs = 0;
          }
          return rs + ascii3(c, buf + rs);
      }
    }
}
#endif /* !USE_NEW_AUTOMATA*/

void automata_clear()
{
    f = F_NULL;
    m = M_NULL;
    l = L_NULL;
    sp = 0;
    temp_hangul[0] = 0;
}

static void display_temp(f, m, l)
int f, m, l;
{
    if (f < 0) {
      HideCursor();
      temp_hangul[0] = 0;
    } else
      convert_3_to_code(f, m, l, temp_hangul);
    ShowCursor();
}

#ifdef QUEUE_DRAW
int hangul_queue_draw_id = 0;
static num_queue = 0;
static struct {
    int x, y, len;
} queue_buf[30];

void add_draw_queue(x, y, len)
int x, y, len;
{
    int n;
    for (n = 0; n < num_queue; n++) {
      if (queue_buf[n].x == x && queue_buf[n].y == y) {
          if (len > queue_buf[n].len)
            queue_buf[n].len = len;
          return;
      }
    }
    queue_buf[n].x = x;
    queue_buf[n].y = y;
    queue_buf[n].len = len;
    num_queue++;
    /* FIXME */
    if (num_queue >= 30)
      num_queue--;
}

void adjust_draw_queue(amount)
int amount;
{
    int n;
    for (n = 0; n < num_queue; n++) {
      queue_buf[n].y -= amount;
    }
}

static void draw_cell(x, y, len)
int x, y, len;
{
    ScrnRefresh(&term->screen, y, x, 1, len, 1);
}


static void hangul_queue_draw(closure, id)      /* XtTimerCallbackProc */
XtPointer closure;
XtIntervalId *id;
{
    int n;
    TScreen *screen = &term->screen;
    hangul_queue_draw_id = 0;
    ShowCursor();
    for (n = 0; n < num_queue; n++) {
      if (queue_buf[n].x != screen->cursor_col || queue_buf[n].y != screen->cursor_row)
          draw_cell(queue_buf[n].x, queue_buf[n].y, queue_buf[n].len);
      else if (queue_buf[n].len > 1) {
          if (temp_hangul[0])
            draw_cell(queue_buf[n].x + 2, queue_buf[n].y, queue_buf[n].len - 2);
          else
            draw_cell(queue_buf[n].x + 1, queue_buf[n].y, queue_buf[n].len - 1);
      }
    }
    num_queue = 0;
}


static void display_temp2(f, m, l)
int f, m, l;
{
    unsigned long interval = 150;
    if (!chat_mode && !hangul_queue_draw_id)
      hangul_queue_draw_id = XtAppAddTimeOut(app_con, interval, hangul_queue_draw, NULL);
    if (f < 0) {
      /* HideCursor (); */
      if (hangul_queue_draw_id) {
          add_draw_queue(term->screen.cursor_col, term->screen.cursor_row, 2);
      }
      temp_hangul[0] = 0;
    } else
      convert_3_to_code(f, m, l, temp_hangul);
    /*  ShowCursor(); */
}
#endif

static int in_ks(f, m, l)
int f, m, l;
{
    Char buf[8];
    if (term->screen.code != C_WANSUNG) return 1;

    return convert_3_to_ks(f, m, l, buf) == 2;
}

Generated by  Doxygen 1.6.0   Back to index