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

hangul.c

/*
    Hangul routines

    written by Song Jaekyung
*/

#include "ptyx.h"
#include "data.h"
#include "hangul.h"
#include <stdio.h>

/* fuzzy baselibe stuff. defined in charproc.c */
extern int englift;
extern int eng_ascent;
extern int eng_descent;

#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
extern int font_no_zero_width_char;
extern int font_minus_width_char_byte1;
extern int font_minus_width_char_byte2;
#endif

extern int convert_3_to_ks();
extern int convert_3_to_johab();
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
#include "ksc.h"
extern int convert_3_to_utf8();
unsigned short convert_char_ksc5601_to_ucs2(/*byte1, byte2*/);
unsigned short convert_char_ucs2_to_ksc5601(/*code_ucs2*/);
int convert_wc_to_mb(/*char *s, unsigned long wc*/);
int convert_mb_to_wc(/*unsigned long *p, char *s, unsigned n*/);
#endif

int convert_3_to_jo844();
extern int (*converter)();
extern int (*chat_callback)();
extern int v_write();

void HandleToggleHangul(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    if (chat_mode)
      chat_mode_input(-1, 0, 0, 0);
    else {
      if (hanja_mode)
          toggle_hanja_mode(0);
      unparseputc(-1, term->screen.respond);
    }
}

void HandleToggleChat(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    if (!hanja_mode) {
      chat_callback = v_write;
      toggle_chat_mode("");
    }
}

void HandleChangeKeyboard(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    if (chat_mode)
      chat_mode_input(-2, 0, 0, 0);
    else
      unparseputc(-2, term->screen.respond);

    /* hangul keyboard status: 2 -> 390 -> 391 -> 2 */
    if (term->screen.keyboard == 2)
      term->screen.keyboard = 390;
    else if (term->screen.keyboard == 390)
      term->screen.keyboard = 391;
    else if (term->screen.keyboard == 391)
      term->screen.keyboard = 2;

    show_status(&term->screen, 0, 0);
}

void HandleChangeCode(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{

    extern int font_jo_mode;

    term->screen.code = (term->screen.code + 1) % (C_LASTNUM+1);
    if (!chat_mode) {
      if (term->screen.code == C_WANSUNG) {
          converter = convert_3_to_ks;
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
      } else if (term->screen.code == C_UTF8) {
          converter = convert_3_to_utf8;
#endif
      } else {

/*        if( font_jo_mode == TRUE ) 
            converter = convert_3_to_jo844;
          else */
            converter = convert_3_to_johab;
      }
    }
    show_status(&term->screen, 0, 0);
}

code_input(fd, str, len)
    int fd;
    unsigned char *str;
    int len;
{
    int code = 0;
    char buf[2];

    sscanf((char*)str+9, "%x", &code);
    if (code >= 0xa1a1 && code <= 0xfefe) {
      buf[0] = code >> 8;
      buf[1] = code & 0xff;
      v_write(fd, buf, 2);
    }
    return -1;
}

void HandleCodeInput(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    if (!chat_mode && !hanja_mode) {
      chat_callback = code_input;
      toggle_chat_mode(S_CHARCODE); /* 문자코드 */
    }
}

/* hanja */
void HandleHanjaInput(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    extern Bool can_use_hanja;
    extern Char temp_hangul[8];
    extern int hangul_state;
    Char tmp[8];
    unsigned int han_code;

    if (hangul_state && !chat_mode) {
      if (temp_hangul[0] && !hanja_mode) {
          convert_johab_to_ks(temp_hangul, tmp, 2);
          han_code = (tmp[0] << 8) + tmp[1];
          toggle_hanja_mode(han_code); /* 한자 입력 모드 */
      }
      else
          toggle_hanja_mode(0);
    }
}


#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.6 */
/* str + n - 1 위치 마지막 글자가 미완성시 코드길이를 넘겨준다. */
adjust_hangul_string(str, n, code)
register unsigned char *str;
register int n;               /* length of string */
register int code;
#else
/* str + n - 1 에 있는 캐릭터가 한글의 첫번째 바이트면 1 을 돌려줍니다. */
adjust_hangul_string(str, n)
register unsigned char *str;
register int n;               /* length of string */
#endif
{
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    if (code == C_UTF8) {
      int l = 0;
      while (n > 0) {
          if (*str < (unsigned char)0xc0) l = 1;
          else if (*str < (unsigned char)0xe0) l = 2;
          else if (*str < (unsigned char)0xf0) l = 3;
          else if (*str < (unsigned char)0xf8) l = 4;
          else if (*str < (unsigned char)0xfc) l = 5;
          else l = 6;

          n -= l;
          str += l;
      }
      return (n == 0) ? 0 : (l + n);
    }
    else 
#endif
    {
      while (n > 0) {
          if (*str & 0x80) {
            str += 2;
            n -= 2;
          } else {
            str += 1;
            n -= 1;
          }
      }
      return (n != 0);
    }
}

#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
int get_hangul_coding_length(str, n, maxlen_scr, code)
unsigned char *str;
int n;
int maxlen_scr;
int code;
{
    int len_code = 0;
    int l = 0;

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    if (code == C_UTF8) {
      int len_scr = 0;
      int len_scr1;

      while (n > 0) {
          len_scr1 = 2;
          if (*str < (unsigned char)0xc0) l = 1, len_scr1 = 1;
          else if (*str < (unsigned char)0xe0) l = 2;
          else if (*str < (unsigned char)0xf0) l = 3;
          else if (*str < (unsigned char)0xf8) l = 4;
          else if (*str < (unsigned char)0xfc) l = 5;
          else l = 6;

          maxlen_scr -= len_scr1;
          len_code += l;
          if (maxlen_scr <= 0) return len_code;
          n -= l;
          str += l;
      }
      return len_code;
    }
    else 
#endif
    {
      while (n > 0) {
          if (*str & 0x80) {
            str += 2;
            l = 2;
            n -= 2;
          } else {
            str += 1;
            l = 1;
            n -= 1;
          }
          maxlen_scr -= l;
          len_code += l;
          if (maxlen_scr <= 0) return len_code;
      }
      return len_code;
    }
}

int get_hangul_screen_length(str, n, code)
unsigned char *str;
int n;
int code;
{
    int len_scr = 0;
    int len_scr1;

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    if (code == C_UTF8) {
      int l = 0;
      while (n > 0) {
          len_scr1 = 2;
          if (*str < (unsigned char)0xc0) l = 1, len_scr1 = 1;
          else if (*str < (unsigned char)0xe0) l = 2;
          else if (*str < (unsigned char)0xf0) l = 3;
          else if (*str < (unsigned char)0xf8) l = 4;
          else if (*str < (unsigned char)0xfc) l = 5;
          else l = 6;

          n -= l;
          str += l;
          len_scr += len_scr1;
      }
      return len_scr;
    }
    else 
#endif
    {
      while (n > 0) {
          if (*str & 0x80) {
            str += 2;
            n -= 2;
            len_scr1 = 2;
          } else {
            str += 1;
            n -= 1;
            len_scr1 = 1;
          }
          len_scr += len_scr1;
      }
      return len_scr;
    }
}
#endif

show_status(screen, leftcol, ncols)
    TScreen *screen;
    int leftcol, ncols;
{
    extern int hangul_state;
    static char *mode_str[] = {S_HANGUL, S_ENGLISH};
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    static char *code_str[] = {S_WANSUNG, S_JOHAB, S_UTF8};
#else
    static char *code_str[] = {S_WANSUNG, S_JOHAB};
#endif
    static char *keyboard_str[] = {S_2BULSIK, S_3BUL_90, S_3BUL_FINAL};
    int keyboard_idx; /* keyboard string을 표시하기 위한 index */

    Pixel fg_pix, bg_pix;
    GC currentGC, currentHGC;

    char *str;
    int x, y;
    int xOffset_mode = 0;
    int xOffset_code = xOffset_mode + ST_MODE_LEN;
    int xOffset_layout = xOffset_code;

    fg_pix = screen->foreground;
    bg_pix = term->core.background_pixel;

    currentGC = screen->normalGC;
    currentHGC = screen->normalHGC;

    XSetForeground(screen->display, currentGC, fg_pix);
    XSetBackground(screen->display, currentGC, bg_pix);
    XSetForeground(screen->display, currentHGC, fg_pix);
    XSetBackground(screen->display, currentHGC, bg_pix);

    if (hangul_state)
      str = mode_str[0];
    else
      str = mode_str[1];
    x = screen->border + screen->scrollbar + FontWidth(screen) * xOffset_mode;
    y = FullHeight(screen) - screen->border - screen->descent;

    if (leftcol < 6)
      HDrawImageString(screen->display, TextWindow(screen),
                   currentGC, currentHGC, x, y, str,
                   ST_MODE_LEN);
    x = screen->border + screen->scrollbar + FontWidth(screen) * xOffset_code;
    if (!(screen->showStatus.hideCode)) {
        xOffset_layout += ST_CODE_LEN;
        HDrawImageString(screen->display, TextWindow(screen),
                 currentGC, currentHGC,
                 x, y, code_str[screen->code], ST_CODE_LEN);
        x = screen->border + screen->scrollbar + FontWidth(screen) * xOffset_layout;
    }
    switch (screen->keyboard) {
        case 2:
            keyboard_idx = 0;
            break;
        case 390:
            keyboard_idx = 1;
            break;
        case 391:
            keyboard_idx = 2;
            break;
        default:
            keyboard_idx = 0; /* should not occur */
            break;
    }
    if (!(screen->showStatus.hideHanLayout)) {
        HDrawImageString(screen->display, TextWindow(screen),
                 currentGC, currentHGC,
                 x, y, keyboard_str[keyboard_idx], ST_KBD_LEN);
    }
    if (leftcol + ncols > 7)
      show_chat_buf();
}

/*
 * This can be used uninitialized and it can crash hanterm
 * when you 'cat' huge files to the screen.
 *
 * Daeshik Kim (dkim@surecom.com)
 */
GC fillgc = NULL;

/* str 은 2 byte 조합형 */

HDrawImageString(d, w, gc, hgc, x, y, str, len)
    Display *d;
    Window w;
    GC gc, hgc;
    int x, y;
    char* str;
    int len;
{
    TScreen *screen = &term->screen;
    static XChar2b buf[TEXT_BUF_SIZE];
    int n, width;
    char *p;
    XGCValues values;
    extern int font_ks_mode;

    while (len > 0) {
      if (*str & 0x80) {
          for (p = str; len > 0 && *p & 0x80; p += 2, len -= 2)
            ;
          n = convert_johab_to_display(str, buf, p - str);
/*          XDrawImageString16(d, w, hgc, x, y, buf, n); : by ysyun */
/* by ysyun : 04/08/94 */
            if( gc == hgc )
                XDrawImageString(d, w, gc, x, y, (char*)buf, 2*n);
            else if( font_ks_mode == -1 )
#if !defined(NO_PATCH_HDRAWIMAGESTRING_BUG) /* by hanmaum 1998.2.2 */
{
#if defined(NO_PATCH_HDRAWIMAGESTRING_FILL) /* by hanmaum 1998.2.3 */
              static XChar2b buf2[TEXT_BUF_SIZE];
            register int i;
            int hlen = (p-str)/2;
/* static variable has zeros initially.
            for (i = 0; i < hlen; i++) buf2[i].byte1 = buf2[i].byte2 = 0;
*/
                XDrawImageString16(d, w, hgc, x, y, buf2, hlen);
#else
            int width, ascent, descent;

            width = (p - str) * FontWidth(screen);
            ascent = (screen->ascent > screen->fnt_hangul->ascent) 
                  ? screen->ascent : screen->fnt_hangul->ascent;
            descent = (screen->descent > screen->fnt_hangul->descent)
                  ? screen->descent : screen->fnt_hangul->descent;

            XGetGCValues(d, hgc, GCBackground, &values);
            XSetForeground(d, fillgc, values.background);
            XFillRectangle(d, w, fillgc, x, y - ascent,
                         width, ascent + descent);
#endif
                XDrawString16(d, w, hgc, x, y, buf, n);
}
#else
              XDrawString16(d, w, hgc, x, y, buf, n);
#endif
          else
                XDrawImageString16(d, w, hgc, x, y, buf, n);
  
/* end of modification */
/***** by hanmaum 1998.2.2
   The below workaround is not needed if you apply the above buf2 patch by me
   #if defined(DGUX_XSERVER) || defined(DGUX)
*****/
#if defined(NO_PATCH_HDRAWIMAGESTRING_BUG) /* by hanmaum 1998.2.2 */
    /*
     * In DGUX XServer, XDrawImageString16() with hangul johab fonts which
     * uses ASCENT area does not work.
     *
     * Beware, it's the DG XServer so even when you use remote
     * hanterm from Sun4 machines; you sill get the same result.
     *
     * However, fortunately, XDrawString16() works - so
     * let XDrawImageString16() draw whatever needs to be done; then
     * add the broken ASCENT area with XDrawString16().
     *
     * Daeshik Kim - DKIM
     */
          XDrawString16(d, w, hgc, x, y, buf, n);
#endif
          width = (p - str) * FontWidth(screen);
#if !defined(NO_PATCH_HDRAWIMAGESTRING_FILL) /* by hanmaum 1998.2.3 */
        if (font_ks_mode != -1) {
#endif
          if (screen->ascent > screen->fnt_hangul->ascent) {
            XGetGCValues(d, hgc, GCBackground, &values);
            XSetForeground(d, fillgc, values.background);
            XFillRectangle(d, w, fillgc, x, y - screen->ascent,
                         width,
                         screen->ascent - screen->fnt_hangul->ascent);
          }
          if (screen->descent > screen->fnt_hangul->descent) {
            XGetGCValues(d, hgc, GCBackground, &values);
            XSetForeground(d, fillgc, values.background);
            XFillRectangle(d, w, fillgc, x,
                         y + screen->fnt_hangul->descent, width,
                         screen->descent - 
                         screen->fnt_hangul->descent);
          }
#if !defined(NO_PATCH_HDRAWIMAGESTRING_FILL) /* by hanmaum 1998.2.3 */
        }
#endif
      }
      else {
#if !defined(NO_PATCH_LINE_DRAW)
        p = str;
        if (*p && ((unsigned char)*p) < 20) {
          extern Pixmap vtgraphics[]; /* Bitmaps */
          XCopyPlane(d, vtgraphics[*p], w, gc, 0, 0,
            FontWidth(screen), FontHeight(screen),
            x, y - screen->ascent, 1);
          p++;
          len--;
          width = FontWidth(screen);
        } else {
          for (; len > 0 && !(*p & 0x80) && (!*p || *p >= 20); p++, len--)
            ;
#else
          for (p = str; len > 0 && !(*p & 0x80); p++, len--)
            ;
#endif
          XDrawImageString(d, w, gc, x, y - englift, str, p - str);
          width = (p - str) * FontWidth(screen);
          if (screen->ascent > eng_ascent) {
            XGetGCValues(d, hgc, GCBackground, &values);
            XSetForeground(d, fillgc, values.background);
            XFillRectangle(d, w, fillgc, x,
                           y - screen->ascent, width,
                           screen->ascent - eng_ascent);
          }
          if (screen->descent > eng_descent) {
            XGetGCValues(d, hgc, GCBackground, &values);
            XSetForeground(d, fillgc, values.background);
            XFillRectangle(d, w, fillgc, x,
                           y + screen->fnt_norm->descent, width,
                           screen->descent - 
                           eng_descent);
          }
#if !defined(NO_PATCH_LINE_DRAW)
        }
#endif
      }
      x += width;
      str = p;
    }
}

/* str 은 2 byte 조합형 */

HDrawString(d, w, gc, hgc, x, y, str, len)
    Display *d;
    Window w;
    GC gc, hgc;
    int x, y;
    char* str;
    int len;
{
    register TScreen *screen = &term->screen;
    XChar2b buf[200];
    int n, width;
    char *p;

    while (len > 0) {
      if (*str & 0x80) {
          for (p = str; len > 0 && *p & 0x80; p += 2, len -= 2)
            ;
          n = convert_johab_to_display(str, buf, p - str);
          XDrawString16(d, w, hgc, x, y, buf, n);
      }
      else {
#if !defined(NO_PATCH_LINE_DRAW)
#if 1 /* skip or display */
        p = str;
        if (*p && ((unsigned char)*p) < 20) {
            /* skip */
            p++;
            len--;
        } else {
#else
        p = str;
        if (*p && ((unsigned char)*p) < 20) {
          extern Pixmap vtgraphics[]; /* Bitmaps */
          XCopyPlane(d, vtgraphics[*p], w, gc, 0, 0,
            FontWidth(screen), FontHeight(screen),
            x, y - screen->ascent, 1);
          p++;
          len--;
          width = FontWidth(screen);
        } else {
#endif
          for (; len > 0 && !(*p & 0x80) && (!*p || *p >= 20); p++, len--)
            ;
#else
          for (p = str; len > 0 && !(*p & 0x80); p++, len--)
            ;
#endif
          XDrawString(d, w, gc, x, y - englift, str, p - str);
#if !defined(NO_PATCH_LINE_DRAW)
          }
#endif
      }
      width = (p - str) * FontWidth(screen);
      x += width;
      str = p;
    }
}

#define ks_table1_index(h, l) (((h)-0xb0)*(0xff-0xa1)+((l)-0xa1))

static unsigned char ks_table1[][3] = {
   2,  3,  1,   2,  3,  2,   2,  3,  5,   2,  3,  8,
   2,  3,  9,   2,  3, 10,   2,  3, 11,   2,  3, 17,
   2,  3, 19,   2,  3, 20,   2,  3, 21,   2,  3, 22,
   2,  3, 23,   2,  3, 24,   2,  3, 25,   2,  3, 27,
   2,  3, 28,   2,  3, 29,   2,  4,  1,   2,  4,  2,
   2,  4,  5,   2,  4,  9,   2,  4, 17,   2,  4, 19,
   2,  4, 21,   2,  4, 22,   2,  4, 23,   2,  5,  1,
   2,  5,  2,   2,  5,  5,   2,  5,  9,   2,  5, 21,
   2,  5, 23,   2,  6,  1,   2,  6,  5,   2,  6,  9,
   2,  7,  1,   2,  7,  2,   2,  7,  5,   2,  7,  8,
   2,  7,  9,   2,  7, 11,   2,  7, 17,   2,  7, 19,
   2,  7, 21,   2,  7, 22,   2,  7, 23,   2,  7, 24,
   2,  7, 27,   2,  7, 28,   2,  7, 29,   2, 10,  1,
   2, 10,  5,   2, 10,  9,   2, 10, 17,   2, 10, 19,
   2, 10, 21,   2, 10, 22,   2, 10, 23,   2, 11,  1,
   2, 11,  2,   2, 11,  3,   2, 11,  5,   2, 11,  8,
   2, 11,  9,   2, 11, 17,   2, 11, 19,   2, 11, 21,
   2, 11, 22,   2, 11, 23,   2, 11, 27,   2, 12,  1,
   2, 12,  5,   2, 12,  9,   2, 12, 19,   2, 12, 21,
   2, 13,  1,   2, 13,  2,   2, 13,  5,   2, 13,  8,
   2, 13,  9,   2, 13, 11,   2, 13, 13,   2, 13, 16,
   2, 13, 17,   2, 13, 19,   2, 13, 21,   2, 13, 23,
   2, 13, 24,   2, 14,  1,   2, 14,  2,   2, 14,  5,
   2, 14,  9,   2, 14, 11,   2, 14, 17,   2, 14, 19,
   2, 14, 21,   2, 14, 23,   2, 15,  1,   2, 15,  5,
   2, 15,  9,   2, 15, 19,   2, 15, 22,   2, 15, 23,
   2, 18,  1,   2, 18,  2,   2, 18,  5,   2, 18,  9,
   2, 18, 17,   2, 18, 19,   2, 18, 21,   2, 18, 23,
   2, 19,  1,   2, 19,  5,   2, 19,  9,   2, 19, 19,
   2, 19, 21,   2, 20,  1,   2, 20,  2,   2, 20,  5,
   2, 20,  8,   2, 20,  9,   2, 20, 10,   2, 20, 11,
   2, 20, 16,   2, 20, 17,   2, 20, 19,   2, 20, 21,
   2, 20, 23,   2, 20, 24,   2, 21,  1,   2, 21,  2,
   2, 21,  5,   2, 21,  9,   2, 21, 22,   2, 21, 23,
   2, 22,  1,   2, 22, 21,   2, 23,  1,   2, 23,  2,
   2, 23,  5,   2, 23,  9,   2, 23, 17,   2, 23, 19,
   2, 23, 21,   2, 26,  1,   2, 26,  5,   2, 26,  9,
   2, 27,  1,   2, 27,  2,   2, 27,  5,   2, 27,  8,
   2, 27,  9,   2, 27, 10,   2, 27, 17,   2, 27, 19,
   2, 27, 21,   2, 27, 23,   2, 28,  1,   2, 29,  1,
   2, 29,  2,   2, 29,  5,   2, 29,  8,   2, 29,  9,
   2, 29, 11,   2, 29, 17,   2, 29, 19,   2, 29, 21,
   2, 29, 23,   2, 29, 24,   2, 29, 28,   3,  3,  1,
   3,  3,  2,   3,  3,  3,   3,  3,  5,   3,  3,  9,
   3,  3, 11,   3,  3, 17,   3,  3, 19,   3,  3, 21,
   3,  3, 22,   3,  3, 23,   3,  3, 27,   3,  4,  1,
   3,  4,  2,   3,  4,  5,   3,  4,  9,   3,  4, 17,
   3,  4, 19,   3,  4, 21,   3,  4, 22,   3,  4, 23,
   3,  5,  1,   3,  5,  2,   3,  5,  9,   3,  7,  1,
   3,  7,  2,   3,  7,  3,   3,  7,  5,   3,  7,  9,
   3,  7, 17,   3,  7, 19,   3,  7, 21,   3,  7, 22,
   3,  7, 23,   3, 10,  1,   3, 10,  2,   3, 10,  5,
   3, 10, 17,   3, 10, 21,   3, 10, 23,   3, 11,  1,
   3, 11,  5,   3, 11,  9,   3, 11, 21,   3, 11, 22,
   3, 11, 27,   3, 12,  1,   3, 13,  1,   3, 13,  2,
   3, 13,  5,   3, 13,  7,   3, 13,  9,   3, 13, 17,
   3, 13, 19,   3, 13, 21,   3, 13, 23,   3, 13, 24,
   3, 13, 25,   3, 14,  1,   3, 14,  2,   3, 14,  9,
   3, 14, 22,   3, 14, 23,   3, 15,  1,   3, 15,  2,
   3, 15, 23,   3, 18,  1,   3, 18,  5,   3, 18,  9,
   3, 18, 17,   3, 18, 19,   3, 18, 23,   3, 19,  1,
   3, 20,  1,   3, 20,  2,   3, 20,  5,   3, 20,  9,
   3, 20, 16,   3, 20, 17,   3, 20, 19,   3, 20, 21,
   3, 20, 23,   3, 20, 24,   3, 21,  1,   3, 21,  9,
   3, 21, 22,   3, 21, 23,   3, 22,  1,   3, 22,  2,
   3, 22,  5,   3, 22,  9,   3, 22, 17,   3, 22, 19,
   3, 22, 22,   3, 23,  1,   3, 23,  5,   3, 23,  9,
   3, 23, 17,   3, 23, 19,   3, 26,  1,   3, 27,  1,
   3, 27,  2,   3, 27,  5,   3, 27,  7,   3, 27,  9,
   3, 27, 11,   3, 27, 16,   3, 27, 17,   3, 27, 19,
   3, 27, 21,   3, 27, 23,   3, 27, 27,   3, 29,  1,
   3, 29,  2,   3, 29,  5,   3, 29,  9,   3, 29, 17,
   3, 29, 19,   3, 29, 21,   3, 29, 23,   4,  3,  1,
   4,  3,  2,   4,  3,  3,   4,  3,  5,   4,  3,  8,
   4,  3,  9,   4,  3, 10,   4,  3, 11,   4,  3, 17,
   4,  3, 19,   4,  3, 21,   4,  3, 22,   4,  3, 23,
   4,  3, 24,   4,  3, 25,   4,  3, 27,   4,  3, 29,
   4,  4,  1,   4,  4,  2,   4,  4,  5,   4,  4,  9,
   4,  4, 17,   4,  4, 19,   4,  4, 21,   4,  4, 22,
   4,  4, 23,   4,  5,  1,   4,  5,  2,   4,  5,  5,
   4,  5,  9,   4,  5, 17,   4,  5, 23,   4,  7,  1,
   4,  7,  2,   4,  7,  4,   4,  7,  5,   4,  7,  9,
   4,  7, 11,   4,  7, 12,   4,  7, 17,   4,  7, 19,
   4,  7, 21,   4,  7, 22,   4,  7, 23,   4,  7, 29,
   4, 10,  1,   4, 10,  2,   4, 10,  5,   4, 10,  9,
   4, 10, 17,   4, 10, 19,   4, 10, 21,   4, 10, 22,
   4, 10, 23,   4, 11,  1,   4, 11,  2,   4, 11,  5,
   4, 11,  9,   4, 11, 17,   4, 11, 19,   4, 11, 22,
   4, 11, 23,   4, 11, 26,   4, 12,  1,   4, 12,  5,
   4, 13,  1,   4, 13,  2,   4, 13,  5,   4, 13,  9,
   4, 13, 11,   4, 13, 17,   4, 13, 19,   4, 13, 21,
   4, 13, 23,   4, 13, 28,   4, 13, 29,   4, 14,  1,
   4, 14,  5,   4, 14,  9,   4, 14, 22,   4, 18,  1,
   4, 18,  5,   4, 18,  9,   4, 18, 17,   4, 18, 19,
   4, 18, 21,   4, 19,  1,   4, 19,  2,   4, 19,  5,
   4, 19,  9,   4, 19, 19,   4, 19, 21,   4, 19, 23,
   4, 20,  1,   4, 20,  2,   4, 20,  5,   4, 20,  8,
   4, 20,  9,   4, 20, 17,   4, 20, 19,   4, 20, 21,
   4, 20, 23,   4, 21,  1,   4, 21, 22,   4, 22,  1,
   4, 23,  1,   4, 23,  5,   4, 23,  9,   4, 23, 17,
   4, 23, 19,   4, 26,  1,   4, 26,  2,   4, 26,  9,
   4, 26, 17,   4, 26, 19,   4, 26, 23,   4, 27,  1,
   4, 27,  2,   4, 27,  5,   4, 27,  9,   4, 27, 10,
   4, 27, 11,   4, 27, 17,   4, 27, 19,   4, 27, 21,
   4, 27, 23,   4, 27, 24,   4, 27, 28,   4, 28,  1,
   4, 28,  5,   4, 28,  9,   4, 29,  1,   4, 29,  2,
   4, 29,  5,   4, 29,  9,   4, 29, 11,   4, 29, 17,
   4, 29, 19,   4, 29, 21,   4, 29, 23,   4, 29, 28,
   5,  3,  1,   5,  3,  2,   5,  3,  3,   5,  3,  5,
   5,  3,  8,   5,  3,  9,   5,  3, 10,   5,  3, 11,
   5,  3, 12,   5,  3, 16,   5,  3, 17,   5,  3, 19,
   5,  3, 21,   5,  3, 22,   5,  3, 23,   5,  3, 24,
   5,  3, 25,   5,  3, 29,   5,  4,  1,   5,  4,  2,
   5,  4,  5,   5,  4,  9,   5,  4, 17,   5,  4, 19,
   5,  4, 21,   5,  4, 22,   5,  4, 23,   5,  5,  1,
   5,  7,  1,   5,  7,  2,   5,  7,  3,   5,  7,  5,
   5,  7,  8,   5,  7,  9,   5,  7, 11,   5,  7, 12,
   5,  7, 17,   5,  7, 19,   5,  7, 21,   5,  7, 23,
   5,  7, 25,   5,  7, 28,   5, 10,  1,   5, 10,  2,
   5, 10,  5,   5, 10,  9,   5, 10, 17,   5, 10, 19,
   5, 10, 21,   5, 10, 22,   5, 10, 23,   5, 11,  1,
   5, 11,  5,   5, 11,  9,   5, 11, 22,   5, 11, 23,
   5, 12,  1,   5, 12,  5,   5, 13,  1,   5, 13,  2,
   5, 13,  5,   5, 13,  8,   5, 13,  9,   5, 13, 11,
   5, 13, 13,   5, 13, 17,   5, 13, 19,   5, 13, 21,
   5, 13, 23,   5, 13, 25,   5, 13, 27,   5, 14,  1,
   5, 14,  5,   5, 14,  9,   5, 15,  1,   5, 15, 22,
   5, 18,  1,   5, 18,  5,   5, 18,  9,   5, 18, 17,
   5, 18, 19,   5, 18, 21,   5, 19,  1,   5, 20,  1,
   5, 20,  2,   5, 20,  5,   5, 20,  9,   5, 20, 17,
   5, 20, 19,   5, 20, 21,   5, 20, 23,   5, 21,  1,
   5, 21, 22,   5, 22,  1,   5, 22, 23,   5, 23,  1,
   5, 23,  5,   5, 23,  9,   5, 23, 19,   5, 23, 21,
   5, 23, 23,   5, 26,  1,   5, 26,  5,   5, 26,  9,
   5, 26, 17,   5, 26, 23,   5, 27,  1,   5, 27,  2,
   5, 27,  5,   5, 27,  8,   5, 27,  9,   5, 27, 11,
   5, 27, 17,   5, 27, 19,   5, 27, 21,   5, 27, 23,
   5, 28,  1,   5, 29,  1,   5, 29,  2,   5, 29,  5,
   5, 29,  8,   5, 29,  9,   5, 29, 17,   5, 29, 19,
   5, 29, 21,   5, 29, 22,   5, 29, 23,   5, 29, 24,
   6,  3,  1,   6,  3,  2,   6,  3,  5,   6,  3,  9,
   6,  3, 17,   6,  3, 19,   6,  3, 21,   6,  3, 22,
   6,  3, 23,   6,  3, 29,   6,  4,  1,   6,  4,  2,
   6,  4,  5,   6,  4,  9,   6,  4, 17,   6,  4, 19,
   6,  4, 21,   6,  4, 22,   6,  4, 23,   6,  7,  1,
   6,  7,  2,   6,  7,  5,   6,  7,  9,   6,  7, 11,
   6,  7, 12,   6,  7, 17,   6,  7, 19,   6,  7, 21,
   6,  7, 22,   6,  7, 23,   6,  7, 29,   6, 10,  1,
   6, 10,  2,   6, 10,  5,   6, 10,  9,   6, 10, 17,
   6, 10, 19,   6, 10, 21,   6, 10, 22,   6, 10, 23,
   6, 11,  1,   6, 11, 22,   6, 13,  1,   6, 13,  2,
   6, 13,  5,   6, 13,  9,   6, 13, 23,   6, 14,  1,
   6, 14,  9,   6, 15,  1,   6, 18,  1,   6, 18,  5,
   6, 20,  1,   6, 20,  2,   6, 20,  5,   6, 20,  9,
   6, 20, 16,   6, 20, 17,   6, 20, 23,   6, 22,  1,
   6, 23,  1,   6, 23,  5,   6, 23,  9,   6, 23, 17,
   6, 23, 19,   6, 23, 23,   6, 27,  1,   6, 27,  2,
   6, 27,  5,   6, 27,  8,   6, 27,  9,   6, 27, 17,
   6, 27, 19,   6, 27, 21,   6, 28,  1,   6, 28,  5,
   6, 28,  9,   6, 28, 17,   6, 28, 19,   6, 29,  1,
   6, 29,  5,   6, 29,  9,   6, 29, 17,   6, 29, 19,
   6, 29, 21,   6, 29, 23,   7,  3,  1,   7,  3,  2,
   7,  3,  5,   7,  3,  9,   7,  3, 17,   7,  3, 19,
   7,  3, 21,   7,  3, 22,   7,  3, 23,   7,  3, 24,
   7,  3, 28,   7,  3, 29,   7,  4,  1,   7,  4,  2,
   7,  4,  5,   7,  4,  9,   7,  4, 17,   7,  4, 19,
   7,  4, 21,   7,  4, 22,   7,  4, 23,   7,  5,  1,
   7,  5,  2,   7,  5,  5,   7,  5, 21,   7,  5, 23,
   7,  7,  1,   7,  7,  2,   7,  7,  5,   7,  7,  9,
   7,  7, 17,   7,  7, 19,   7,  7, 21,   7,  7, 22,
   7,  7, 23,   7,  7, 29,   7, 10,  1,   7, 10,  2,
   7, 10,  5,   7, 10,  9,   7, 10, 17,   7, 10, 19,
   7, 10, 21,   7, 10, 23,   7, 11,  1,   7, 11,  2,
   7, 11,  5,   7, 11,  9,   7, 11, 17,   7, 11, 19,
   7, 11, 21,   7, 11, 22,   7, 11, 23,   7, 12,  1,
   7, 12,  5,   7, 12, 19,   7, 12, 21,   7, 13,  1,
   7, 13,  2,   7, 13,  5,   7, 13,  9,   7, 13, 17,
   7, 13, 19,   7, 13, 21,   7, 13, 23,   7, 14,  1,
   7, 14,  5,   7, 14, 23,   7, 15, 22,   7, 18,  1,
   7, 18,  5,   7, 18,  9,   7, 18, 17,   7, 18, 19,
   7, 18, 21,   7, 18, 23,   7, 19,  1,   7, 19,  5,
   7, 19,  9,   7, 19, 19,   7, 19, 21,   7, 19, 23,
   7, 20,  1,   7, 20,  2,   7, 20,  5,   7, 20,  9,
   7, 20, 17,   7, 20, 19,   7, 20, 21,   7, 20, 23,
   7, 21,  1,   7, 21, 22,   7, 22,  1,   7, 23,  1,
   7, 23,  2,   7, 23,  5,   7, 23,  9,   7, 23, 17,
   7, 23, 21,   7, 23, 23,   7, 26,  1,   7, 26,  2,
   7, 26,  5,   7, 26,  9,   7, 26, 17,   7, 26, 19,
   7, 26, 21,   7, 26, 23,   7, 27,  1,   7, 27,  2,
   7, 27,  5,   7, 27,  9,   7, 27, 17,   7, 27, 19,
   7, 27, 21,   7, 27, 23,   7, 27, 24,   7, 27, 27,
   7, 27, 28,   7, 29,  1,   7, 29,  2,   7, 29,  5,
   7, 29,  9,   7, 29, 17,   7, 29, 19,   7, 29, 21,
   7, 29, 23,   8,  3,  1,   8,  3,  2,   8,  3,  5,
   8,  3,  7,   8,  3,  8,   8,  3,  9,   8,  3, 10,
   8,  3, 11,   8,  3, 17,   8,  3, 19,   8,  3, 21,
   8,  3, 23,   8,  3, 24,   8,  3, 27,   8,  3, 29,
   8,  4,  1,   8,  4,  2,   8,  4,  5,   8,  4,  9,
   8,  4, 17,   8,  4, 19,   8,  4, 21,   8,  4, 22,
   8,  4, 23,   8,  4, 24,   8,  5,  1,   8,  5,  2,
   8,  5,  9,   8,  5, 23,   8,  7,  1,   8,  7,  2,
   8,  7,  5,   8,  7,  9,   8,  7, 11,   8,  7, 17,
   8,  7, 19,   8,  7, 21,   8,  7, 23,   8,  7, 24,
   8,  7, 29,   8, 10,  1,   8, 10,  2,   8, 10,  5,
   8, 10,  9,   8, 10, 17,   8, 10, 19,   8, 10, 21,
   8, 10, 22,   8, 10, 23,   8, 11,  1,   8, 11,  2,
   8, 11,  5,   8, 11,  9,   8, 11, 21,   8, 11, 22,
   8, 11, 23,   8, 11, 25,   8, 12,  1,   8, 13,  1,
   8, 13,  2,   8, 13,  4,   8, 13,  5,   8, 13,  9,
   8, 13, 11,   8, 13, 17,   8, 13, 19,   8, 13, 21,
   8, 13, 23,   8, 14,  1,   8, 14,  5,   8, 14, 22,
   8, 14, 23,   8, 18,  1,   8, 18,  5,   8, 18,  9,
   8, 18, 19,   8, 18, 21,   8, 18, 23,   8, 19,  1,
   8, 19,  5,   8, 19,  9,   8, 19, 19,   8, 19, 21,
   8, 20,  1,   8, 20,  2,   8, 20,  3,   8, 20,  5,
   8, 20,  8,   8, 20,  9,   8, 20, 10,   8, 20, 11,
   8, 20, 17,   8, 20, 19,   8, 20, 21,   8, 20, 23,
   8, 20, 27,   8, 20, 29,   8, 21,  1,   8, 21,  5,
   8, 21,  9,   8, 21, 19,   8, 21, 21,   8, 22,  1,
   8, 23,  1,   8, 23,  5,   8, 23,  9,   8, 26,  1,
   8, 26,  5,   8, 26,  9,   8, 26, 17,   8, 26, 21,
   8, 27,  1,   8, 27,  5,   8, 27,  9,   8, 27, 17,
   8, 27, 21,   8, 29,  1,   8, 29,  2,   8, 29,  5,
   8, 29,  8,   8, 29,  9,   8, 29, 11,   8, 29, 17,
   8, 29, 19,   8, 29, 21,   8, 29, 22,   8, 29, 23,
   8, 29, 25,   8, 29, 27,   9,  3,  1,   9,  3,  2,
   9,  3,  3,   9,  3,  4,   9,  3,  5,   9,  3,  8,
   9,  3,  9,   9,  3, 10,   9,  3, 11,   9,  3, 12,
   9,  3, 17,   9,  3, 19,   9,  3, 21,   9,  3, 23,
   9,  3, 27,   9,  4,  1,   9,  4,  2,   9,  4,  5,
   9,  4,  9,   9,  4, 17,   9,  4, 19,   9,  4, 21,
   9,  4, 22,   9,  4, 23,   9,  4, 27,   9,  5,  1,
   9,  5,  2,   9,  5,  5,   9,  5, 19,   9,  7,  1,
   9,  7,  2,   9,  7,  5,   9,  7,  8,   9,  7,  9,
   9,  7, 11,   9,  7, 17,   9,  7, 19,   9,  7, 21,
   9,  7, 23,   9,  7, 24,   9, 10,  1,   9, 10,  2,
   9, 10,  5,   9, 10,  8,   9, 10,  9,   9, 10, 17,
   9, 10, 19,   9, 10, 21,   9, 10, 22,   9, 10, 23,
   9, 11,  1,   9, 11,  2,   9, 11,  5,   9, 11,  9,
   9, 11, 19,   9, 11, 21,   9, 11, 22,   9, 11, 23,
   9, 11, 27,   9, 12,  1,   9, 12,  5,   9, 13,  1,
   9, 13,  2,   9, 13,  3,   9, 13,  5,   9, 13,  9,
   9, 13, 17,   9, 13, 19,   9, 13, 21,   9, 13, 23,
   9, 14,  1,   9, 14,  5,   9, 14, 22,   9, 15,  1,
   9, 15, 22,   9, 18,  1,   9, 18,  2,   9, 18,  5,
   9, 18,  9,   9, 18, 17,   9, 18, 19,   9, 19,  1,
   9, 19,  5,   9, 20,  1,   9, 20,  2,   9, 20,  5,
   9, 20,  8,   9, 20,  9,   9, 20, 10,   9, 20, 11,
   9, 20, 17,   9, 20, 19,   9, 20, 21,   9, 20, 23,
   9, 20, 27,   9, 20, 28,   9, 21,  1,   9, 21,  9,
   9, 21, 22,   9, 22,  1,   9, 23,  1,   9, 23,  2,
   9, 23,  5,   9, 23,  9,   9, 23, 23,   9, 26,  1,
   9, 26,  5,   9, 26,  9,   9, 26, 17,   9, 26, 21,
   9, 26, 23,   9, 27,  1,   9, 27,  2,   9, 27,  5,
   9, 27,  9,   9, 27, 17,   9, 27, 19,   9, 27, 21,
   9, 29,  1,   9, 29,  2,   9, 29,  5,   9, 29,  9,
   9, 29, 11,   9, 29, 17,   9, 29, 19,   9, 29, 21,
   9, 29, 23,   9, 29, 24,   9, 29, 25,  10,  3,  1,
  10,  3,  2,  10,  3,  5,  10,  3,  9,  10,  3, 11,
  10,  3, 17,  10,  3, 19,  10,  3, 21,  10,  3, 22,
  10,  3, 23,  10,  3, 29,  10,  4,  1,  10,  4,  2,
  10,  4,  5,  10,  4,  9,  10,  4, 17,  10,  4, 19,
  10,  4, 21,  10,  4, 22,  10,  4, 23,  10,  5,  1,
  10,  5,  2,  10,  5, 17,  10,  7,  1,  10,  7,  2,
  10,  7,  5,  10,  7,  8,  10,  7,  9,  10,  7, 17,
  10,  7, 21,  10,  7, 22,  10,  7, 23,  10, 10,  1,
  10, 10, 23,  10, 11,  1,  10, 11,  2,  10, 11, 17,
  10, 11, 19,  10, 11, 21,  10, 11, 22,  10, 11, 23,
  10, 13,  1,  10, 13,  2,  10, 13,  5,  10, 13,  9,
  10, 13, 17,  10, 13, 19,  10, 13, 23,  10, 18,  1,
  10, 19,  1,  10, 19, 23,  10, 20,  1,  10, 20,  2,
  10, 20,  5,  10, 20,  9,  10, 20, 17,  10, 20, 21,
  10, 20, 23,  10, 26,  1,  10, 26, 23,  10, 27,  1,
  10, 27,  5,  10, 27,  9,  10, 27, 17,  10, 27, 19,
  10, 29,  1,  10, 29,  2,  10, 29,  5,  10, 29,  9,
  10, 29, 17,  10, 29, 19,  10, 29, 21,  10, 29, 23,
  11,  3,  1,  11,  3,  2,  11,  3,  4,  11,  3,  5,
  11,  3,  8,  11,  3,  9,  11,  3, 10,  11,  3, 11,
  11,  3, 17,  11,  3, 19,  11,  3, 21,  11,  3, 22,
  11,  3, 23,  11,  3, 27,  11,  4,  1,  11,  4,  2,
  11,  4,  5,  11,  4,  9,  11,  4, 17,  11,  4, 19,
  11,  4, 21,  11,  4, 22,  11,  4, 23,  11,  5,  1,
  11,  5,  2,  11,  5,  5,  11,  5,  9,  11,  5, 17,
  11,  5, 19,  11,  5, 21,  11,  5, 23,  11,  6,  1,
  11,  6,  5,  11,  6,  9,  11,  6, 17,  11,  6, 23,
  11,  7,  1,  11,  7,  2,  11,  7,  3,  11,  7,  4,
  11,  7,  5,  11,  7,  8,  11,  7,  9,  11,  7, 11,
  11,  7, 12,  11,  7, 17,  11,  7, 19,  11,  7, 21,
  11,  7, 22,  11,  7, 23,  11,  7, 28,  11, 10,  1,
  11, 10,  2,  11, 10,  5,  11, 10,  9,  11, 10, 17,
  11, 10, 19,  11, 10, 21,  11, 10, 22,  11, 10, 23,
  11, 11,  1,  11, 11,  2,  11, 11,  5,  11, 11,  9,
  11, 11, 17,  11, 11, 19,  11, 11, 21,  11, 11, 22,
  11, 11, 23,  11, 12,  1,  11, 12,  5,  11, 12,  9,
  11, 12, 23,  11, 13,  1,  11, 13,  2,  11, 13,  3,
  11, 13,  5,  11, 13,  9,  11, 13, 11,  11, 13, 17,
  11, 13, 19,  11, 13, 21,  11, 13, 23,  11, 13, 27,
  11, 14,  1,  11, 14,  2,  11, 14,  5,  11, 14,  9,
  11, 14, 23,  11, 15,  1,  11, 15,  5,  11, 15,  9,
  11, 15, 17,  11, 15, 21,  11, 15, 22,  11, 18,  1,
  11, 18,  5,  11, 18,  9,  11, 18, 17,  11, 18, 19,
  11, 18, 21,  11, 19,  1,  11, 19,  2,  11, 19,  5,
  11, 19,  9,  11, 19, 17,  11, 19, 19,  11, 19, 21,
  11, 19, 23,  11, 20,  1,  11, 20,  2,  11, 20,  5,
  11, 20,  8,  11, 20,  9,  11, 20, 17,  11, 20, 19,
  11, 20, 21,  11, 20, 23,  11, 20, 25,  11, 20, 27,
  11, 20, 28,  11, 21,  1,  11, 21, 22,  11, 22,  1,
  11, 22,  2,  11, 22,  5,  11, 22,  9,  11, 22, 17,
  11, 22, 23,  11, 23,  1,  11, 23,  2,  11, 23,  5,
  11, 23,  9,  11, 23, 17,  11, 23, 19,  11, 23, 21,
  11, 23, 23,  11, 26,  1,  11, 26,  2,  11, 26,  9,
  11, 26, 17,  11, 26, 21,  11, 26, 23,  11, 27,  1,
  11, 27,  2,  11, 27,  5,  11, 27,  9,  11, 27, 10,
  11, 27, 17,  11, 27, 19,  11, 27, 21,  11, 27, 23,
  11, 29,  1,  11, 29,  2,  11, 29,  5,  11, 29,  8,
  11, 29,  9,  11, 29, 16,  11, 29, 17,  11, 29, 19,
  11, 29, 21,  11, 29, 23,  11, 29, 28,  12,  3,  1,
  12,  3,  2,  12,  3,  4,  12,  3,  5,  12,  3,  9,
  12,  3, 17,  12,  3, 19,  12,  3, 22,  12,  3, 23,
  12,  3, 29,  12,  4,  1,  12,  4,  2,  12,  4,  5,
  12,  4,  9,  12,  4, 17,  12,  4, 19,  12,  4, 22,
  12,  4, 23,  12,  5, 23,  12,  7,  1,  12,  7,  2,
  12,  7,  5,  12,  7,  9,  12,  7, 11,  12,  7, 17,
  12,  7, 19,  12,  7, 22,  12,  7, 23,  12, 10,  1,
  12, 10,  5,  12, 10,  9,  12, 12,  5,  12, 13,  1,
  12, 13,  2,  12, 13,  5,  12, 13,  8,  12, 13,  9,
  12, 13, 11,  12, 13, 17,  12, 13, 19,  12, 13, 23,
  12, 14,  1,  12, 14,  2,  12, 14,  5,  12, 14, 22,
  12, 15,  1,  12, 15, 22,  12, 18,  1,  12, 18,  5,
  12, 18,  9,  12, 18, 17,  12, 18, 19,  12, 19,  1,
  12, 20,  1,  12, 20,  2,  12, 20,  5,  12, 20,  9,
  12, 20, 17,  12, 20, 19,  12, 20, 23,  12, 21,  1,
  12, 21, 22,  12, 22,  1,  12, 23,  1,  12, 23,  5,
  12, 26, 23,  12, 27,  1,  12, 27,  2,  12, 27,  5,
  12, 27,  9,  12, 27, 11,  12, 27, 16,  12, 27, 17,
  12, 27, 19,  12, 28,  1,  12, 28,  5,  12, 28,  9,
  12, 28, 17,  12, 29,  1,  12, 29,  2,  12, 29,  5,
  12, 29,  9,  12, 29, 17,  12, 29, 19,  12, 29, 21,
  12, 29, 23,  13,  3,  1,  13,  3,  2,  13,  3,  5,
  13,  3,  6,  13,  3,  7,  13,  3,  9,  13,  3, 10,
  13,  3, 11,  13,  3, 16,  13,  3, 17,  13,  3, 19,
  13,  3, 21,  13,  3, 22,  13,  3, 23,  13,  3, 27,
  13,  3, 28,  13,  4,  1,  13,  4,  2,  13,  4,  5,
  13,  4,  9,  13,  4, 17,  13,  4, 19,  13,  4, 21,
  13,  4, 22,  13,  4, 23,  13,  5,  1,  13,  5,  2,
  13,  5,  5,  13,  5,  9,  13,  5, 12,  13,  5, 17,
  13,  5, 19,  13,  5, 21,  13,  5, 23,  13,  5, 27,
  13,  5, 29,  13,  6,  1,  13,  6,  5,  13,  6,  9,
  13,  6, 19,  13,  7,  1,  13,  7,  2,  13,  7,  5,
  13,  7,  6,  13,  7,  8,  13,  7,  9,  13,  7, 10,
  13,  7, 11,  13,  7, 17,  13,  7, 19,  13,  7, 20,
  13,  7, 21,  13,  7, 22,  13,  7, 23,  13,  7, 24,
  13,  7, 26,  13,  7, 28,  13, 10,  1,  13, 10,  2,
  13, 10,  5,  13, 10,  9,  13, 10, 17,  13, 10, 19,
  13, 10, 21,  13, 10, 23,  13, 11,  1,  13, 11,  2,
  13, 11,  3,  13, 11,  5,  13, 11,  9,  13, 11, 11,
  13, 11, 12,  13, 11, 17,  13, 11, 19,  13, 11, 20,
  13, 11, 21,  13, 11, 22,  13, 11, 23,  13, 11, 27,
  13, 11, 28,  13, 11, 29,  13, 12,  1,  13, 12,  5,
  13, 12,  9,  13, 12, 17,  13, 12, 19,  13, 12, 21,
  13, 12, 22,  13, 13,  1,  13, 13,  2,  13, 13,  5,
  13, 13,  9,  13, 13, 10,  13, 13, 11,  13, 13, 13,
  13, 13, 16,  13, 13, 17,  13, 13, 19,  13, 13, 21,
  13, 13, 23,  13, 13, 25,  13, 14,  1,  13, 14,  2,
  13, 14,  5,  13, 14,  9,  13, 14, 17,  13, 14, 19,
  13, 14, 21,  13, 14, 22,  13, 14, 23,  13, 15,  1,
  13, 15,  2,  13, 15,  5,  13, 15, 17,  13, 15, 21,
  13, 15, 23,  13, 18,  1,  13, 18,  2,  13, 18,  5,
  13, 18,  9,  13, 18, 17,  13, 18, 19,  13, 18, 21,
  13, 18, 23,  13, 19,  1,  13, 19,  2,  13, 19,  5,
  13, 19,  9,  13, 19, 17,  13, 19, 19,  13, 19, 21,
  13, 19, 23,  13, 20,  1,  13, 20,  2,  13, 20,  5,
  13, 20,  9,  13, 20, 10,  13, 20, 11,  13, 20, 17,
  13, 20, 19,  13, 20, 21,  13, 20, 23,  13, 21,  1,
  13, 21,  2,  13, 21,  5,  13, 21,  9,  13, 21, 17,
  13, 21, 19,  13, 21, 22,  13, 21, 23,  13, 22,  1,
  13, 22,  2,  13, 22,  5,  13, 22,  9,  13, 22, 17,
  13, 22, 19,  13, 22, 23,  13, 23,  1,  13, 23,  2,
  13, 23,  5,  13, 23,  9,  13, 23, 17,  13, 23, 19,
  13, 23, 21,  13, 23, 23,  13, 26,  1,  13, 26,  2,
  13, 26,  5,  13, 26,  9,  13, 26, 17,  13, 26, 19,
  13, 26, 21,  13, 26, 23,  13, 26, 25,  13, 27,  1,
  13, 27,  2,  13, 27,  5,  13, 27,  9,  13, 27, 15,
  13, 27, 17,  13, 27, 19,  13, 27, 21,  13, 27, 23,
  13, 27, 24,  13, 27, 25,  13, 27, 26,  13, 27, 27,
  13, 27, 28,  13, 27, 29,  13, 28,  1,  13, 28,  5,
  13, 28,  9,  13, 28, 17,  13, 28, 21,  13, 29,  1,
  13, 29,  2,  13, 29,  5,  13, 29,  9,  13, 29, 10,
  13, 29, 11,  13, 29, 16,  13, 29, 17,  13, 29, 19,
  13, 29, 21,  13, 29, 22,  13, 29, 23,  13, 29, 24,
  13, 29, 28,  14,  3,  1,  14,  3,  2,  14,  3,  5,
  14,  3,  7,  14,  3,  8,  14,  3,  9,  14,  3, 11,
  14,  3, 17,  14,  3, 19,  14,  3, 21,  14,  3, 22,
  14,  3, 23,  14,  3, 24,  14,  4,  1,  14,  4,  2,
  14,  4,  5,  14,  4,  9,  14,  4, 17,  14,  4, 19,
  14,  4, 21,  14,  4, 22,  14,  4, 23,  14,  5,  1,
  14,  5,  2,  14,  5,  5,  14,  5,  7,  14,  5,  9,
  14,  5, 17,  14,  5, 23,  14,  6,  1,  14,  6,  5,
  14,  6,  9,  14,  7,  1,  14,  7,  2,  14,  7,  5,
  14,  7,  9,  14,  7, 11,  14,  7, 17,  14,  7, 19,
  14,  7, 21,  14,  7, 23,  14,  7, 24,  14, 10,  1,
  14, 10,  2,  14, 10,  5,  14, 10,  9,  14, 10, 17,
  14, 10, 19,  14, 10, 21,  14, 10, 23,  14, 11,  1,
  14, 11,  5,  14, 11,  9,  14, 11, 17,  14, 11, 19,
  14, 11, 22,  14, 11, 23,  14, 12,  1,  14, 13,  1,
  14, 13,  2,  14, 13,  5,  14, 13,  9,  14, 13, 11,
  14, 13, 17,  14, 13, 19,  14, 13, 21,  14, 13, 23,
  14, 13, 24,  14, 13, 25,  14, 13, 29,  14, 14,  1,
  14, 14,  2,  14, 14,  9,  14, 14, 19,  14, 14, 21,
  14, 14, 23,  14, 15,  1,  14, 15, 22,  14, 15, 23,
  14, 18,  1,  14, 18,  5,  14, 18,  9,  14, 18, 17,
  14, 18, 19,  14, 18, 21,  14, 18, 23,  14, 19,  1,
  14, 19,  2,  14, 19,  5,  14, 19, 23,  14, 20,  1,
  14, 20,  2,  14, 20,  5,  14, 20,  9,  14, 20, 10,
  14, 20, 11,  14, 20, 17,  14, 20, 19,  14, 20, 21,
  14, 20, 23,  14, 21,  1,  14, 21, 22,  14, 22,  1,
  14, 23,  1,  14, 23,  2,  14, 23,  5,  14, 23,  9,
  14, 23, 17,  14, 23, 19,  14, 23, 21,  14, 26,  1,
  14, 26,  5,  14, 26,  9,  14, 26, 17,  14, 27,  1,
  14, 27,  2,  14, 27,  5,  14, 27,  9,  14, 27, 17,
  14, 27, 19,  14, 27, 21,  14, 27, 23,  14, 29,  1,
  14, 29,  2,  14, 29,  5,  14, 29,  8,  14, 29,  9,
  14, 29, 11,  14, 29, 17,  14, 29, 19,  14, 29, 21,
  14, 29, 23,  14, 29, 24,  14, 29, 27,  14, 29, 28,
  15,  3,  1,  15,  3,  2,  15,  3,  5,  15,  3,  7,
  15,  3,  9,  15,  3, 12,  15,  3, 17,  15,  3, 19,
  15,  3, 21,  15,  3, 22,  15,  3, 23,  15,  4,  1,
  15,  4,  2,  15,  4,  5,  15,  4,  9,  15,  4, 17,
  15,  4, 19,  15,  4, 21,  15,  4, 22,  15,  4, 23,
  15,  5,  1,  15,  5,  5,  15,  5, 23,  15,  7,  1,
  15,  7,  2,  15,  7,  5,  15,  7,  9,  15,  7, 17,
  15,  7, 19,  15,  7, 21,  15,  7, 22,  15,  7, 23,
  15, 10,  1,  15, 10, 23,  15, 11,  1,  15, 11, 22,
  15, 13,  1,  15, 13,  2,  15, 13,  5,  15, 13,  9,
  15, 13, 17,  15, 13, 19,  15, 13, 21,  15, 13, 23,
  15, 13, 25,  15, 14,  1,  15, 14,  2,  15, 14,  9,
  15, 14, 22,  15, 15,  1,  15, 15, 22,  15, 18,  1,
  15, 18,  5,  15, 18,  9,  15, 18, 17,  15, 18, 19,
  15, 19, 23,  15, 20,  1,  15, 20,  2,  15, 20,  5,
  15, 20,  9,  15, 20, 17,  15, 20, 19,  15, 20, 23,
  15, 21,  1,  15, 21, 22,  15, 21, 23,  15, 23,  1,
  15, 26,  1,  15, 27,  1,  15, 27, 17,  15, 27, 21,
  15, 27, 23,  15, 29,  1,  15, 29,  2,  15, 29,  5,
  15, 29,  9,  15, 29, 17,  15, 29, 19,  15, 29, 23,
  15, 29, 24,  15, 29, 29,  16,  3,  1,  16,  3,  2,
  16,  3,  5,  16,  3,  7,  16,  3,  9,  16,  3, 17,
  16,  3, 19,  16,  3, 21,  16,  3, 22,  16,  3, 23,
  16,  3, 24,  16,  4,  1,  16,  4,  2,  16,  4,  5,
  16,  4,  9,  16,  4, 17,  16,  4, 19,  16,  4, 21,
  16,  4, 22,  16,  4, 23,  16,  5,  1,  16,  5,  5,
  16,  5,  7,  16,  5,  9,  16,  5, 17,  16,  5, 23,
  16,  7,  1,  16,  7,  2,  16,  7,  5,  16,  7,  9,
  16,  7, 17,  16,  7, 19,  16,  7, 21,  16,  7, 22,
  16,  7, 23,  16, 10,  1,  16, 10,  2,  16, 10,  5,
  16, 10,  9,  16, 10, 17,  16, 10, 19,  16, 10, 21,
  16, 10, 23,  16, 11,  1,  16, 11,  5,  16, 11, 22,
  16, 12,  1,  16, 12,  5,  16, 12, 23,  16, 13,  1,
  16, 13,  2,  16, 13,  5,  16, 13,  9,  16, 13, 17,
  16, 13, 19,  16, 13, 21,  16, 13, 23,  16, 14,  1,
  16, 14,  5,  16, 14,  9,  16, 14, 23,  16, 18,  1,
  16, 18,  5,  16, 18,  9,  16, 18, 17,  16, 18, 19,
  16, 18, 21,  16, 18, 23,  16, 19,  1,  16, 19, 17,
  16, 20,  1,  16, 20,  2,  16, 20,  5,  16, 20,  9,
  16, 20, 17,  16, 20, 19,  16, 20, 21,  16, 20, 23,
  16, 21,  1,  16, 21, 22,  16, 22,  1,  16, 22,  5,
  16, 23,  1,  16, 23,  5,  16, 23,  9,  16, 23, 17,
  16, 23, 19,  16, 23, 21,  16, 23, 23,  16, 26,  1,
  16, 26,  5,  16, 26,  9,  16, 26, 17,  16, 26, 23,
  16, 27,  1,  16, 27,  2,  16, 27,  5,  16, 27,  9,
  16, 27, 17,  16, 27, 19,  16, 27, 21,  16, 27, 23,
  16, 29,  1,  16, 29,  2,  16, 29,  5,  16, 29,  8,
  16, 29,  9,  16, 29, 10,  16, 29, 17,  16, 29, 19,
  16, 29, 21,  16, 29, 23,  17,  3,  1,  17,  3,  2,
  17,  3,  5,  17,  3,  9,  17,  3, 17,  17,  3, 19,
  17,  3, 21,  17,  3, 23,  17,  4,  1,  17,  4,  2,
  17,  4,  5,  17,  4,  9,  17,  4, 17,  17,  4, 19,
  17,  4, 21,  17,  4, 22,  17,  4, 23,  17,  5,  1,
  17,  5,  2,  17,  5, 23,  17,  7,  1,  17,  7,  2,
  17,  7,  5,  17,  7,  8,  17,  7,  9,  17,  7, 17,
  17,  7, 19,  17,  7, 21,  17,  7, 22,  17,  7, 23,
  17, 10,  1,  17, 10,  2,  17, 10,  5,  17, 10,  9,
  17, 10, 17,  17, 10, 19,  17, 10, 21,  17, 10, 23,
  17, 11,  1,  17, 11,  5,  17, 11,  9,  17, 11, 17,
  17, 11, 19,  17, 11, 21,  17, 11, 22,  17, 11, 23,
  17, 12,  1,  17, 13,  1,  17, 13,  2,  17, 13,  5,
  17, 13,  9,  17, 13, 17,  17, 13, 19,  17, 13, 21,
  17, 13, 23,  17, 14,  1,  17, 14,  2,  17, 14,  5,
  17, 14,  9,  17, 14, 17,  17, 14, 23,  17, 15,  1,
  17, 15, 23,  17, 18,  1,  17, 18,  9,  17, 19,  1,
  17, 20,  1,  17, 20,  2,  17, 20,  5,  17, 20,  9,
  17, 20, 17,  17, 20, 19,  17, 20, 21,  17, 20, 23,
  17, 21,  1,  17, 21,  5,  17, 21,  9,  17, 21, 23,
  17, 22,  1,  17, 22, 23,  17, 23,  1,  17, 23,  2,
  17, 23,  5,  17, 23,  9,  17, 23, 17,  17, 23, 19,
  17, 23, 21,  17, 23, 23,  17, 26,  1,  17, 26,  5,
  17, 26,  9,  17, 26, 17,  17, 27,  1,  17, 27,  2,
  17, 27,  5,  17, 27,  9,  17, 27, 17,  17, 27, 19,
  17, 27, 23,  17, 29,  1,  17, 29,  2,  17, 29,  5,
  17, 29,  9,  17, 29, 17,  17, 29, 19,  17, 29, 21,
  17, 29, 23,  18,  3,  1,  18,  3,  2,  18,  3,  5,
  18,  3,  9,  18,  3, 10,  18,  3, 17,  18,  3, 19,
  18,  3, 21,  18,  3, 22,  18,  3, 23,  18,  4,  1,
  18,  4,  2,  18,  4,  5,  18,  4,  9,  18,  4, 17,
  18,  4, 19,  18,  4, 21,  18,  4, 22,  18,  4, 23,
  18,  5,  1,  18,  5, 23,  18,  7,  1,  18,  7,  2,
  18,  7,  5,  18,  7,  9,  18,  7, 11,  18,  7, 17,
  18,  7, 19,  18,  7, 21,  18,  7, 22,  18,  7, 23,
  18, 10,  1,  18, 10,  2,  18, 10,  5,  18, 10,  9,
  18, 10, 17,  18, 10, 19,  18, 10, 21,  18, 10, 23,
  18, 11,  1,  18, 11,  5,  18, 11, 22,  18, 12,  1,
  18, 12,  5,  18, 13,  1,  18, 13,  2,  18, 13,  5,
  18, 13,  9,  18, 13, 17,  18, 13, 19,  18, 13, 21,
  18, 13, 23,  18, 13, 28,  18, 14,  1,  18, 14,  5,
  18, 15,  1,  18, 18,  1,  18, 18,  5,  18, 18, 21,
  18, 18, 23,  18, 19,  1,  18, 20,  1,  18, 20,  2,
  18, 20,  5,  18, 20,  9,  18, 20, 17,  18, 20, 19,
  18, 20, 21,  18, 20, 23,  18, 21,  1,  18, 21, 22,
  18, 22,  1,  18, 23,  1,  18, 23,  2,  18, 23,  5,
  18, 23,  9,  18, 23, 17,  18, 23, 19,  18, 23, 23,
  18, 26,  1,  18, 26,  5,  18, 26,  9,  18, 26, 17,
  18, 26, 23,  18, 27,  1,  18, 27,  2,  18, 27,  5,
  18, 27,  8,  18, 27,  9,  18, 27, 11,  18, 27, 17,
  18, 27, 19,  18, 27, 21,  18, 28,  1,  18, 28,  5,
  18, 28,  9,  18, 28, 17,  18, 28, 19,  18, 29,  1,
  18, 29,  2,  18, 29,  5,  18, 29,  9,  18, 29, 17,
  18, 29, 19,  18, 29, 21,  18, 29, 23,  19,  3,  1,
  19,  3,  2,  19,  3,  3,  19,  3,  5,  19,  3,  9,
  19,  3, 11,  19,  3, 17,  19,  3, 19,  19,  3, 21,
  19,  3, 22,  19,  3, 23,  19,  3, 27,  19,  4,  1,
  19,  4,  2,  19,  4,  5,  19,  4,  9,  19,  4, 17,
  19,  4, 19,  19,  4, 21,  19,  4, 22,  19,  4, 23,
  19,  5,  1,  19,  5,  2,  19,  7,  1,  19,  7,  2,
  19,  7,  5,  19,  7,  9,  19,  7, 17,  19,  7, 19,
  19,  7, 21,  19,  7, 22,  19,  7, 23,  19, 10,  1,
  19, 10,  2,  19, 10,  5,  19, 10,  9,  19, 10, 17,
  19, 10, 19,  19, 10, 21,  19, 10, 23,  19, 11,  1,
  19, 11,  5,  19, 11,  9,  19, 11, 17,  19, 11, 19,
  19, 11, 22,  19, 11, 23,  19, 12,  1,  19, 12,  9,
  19, 12, 19,  19, 12, 21,  19, 13,  1,  19, 13,  2,
  19, 13,  5,  19, 13,  9,  19, 13, 17,  19, 13, 19,
  19, 13, 21,  19, 13, 23,  19, 14,  1,  19, 14, 23,
  19, 18,  1,  19, 18,  5,  19, 19,  1,  19, 19,  5,
  19, 19,  9,  19, 19, 19,  19, 19, 21,  19, 20,  1,
  19, 20,  2,  19, 20,  5,  19, 20,  8,  19, 20,  9,
  19, 20, 11,  19, 20, 17,  19, 20, 19,  19, 20, 21,
  19, 20, 23,  19, 21,  1,  19, 21, 23,  19, 23,  1,
  19, 23,  5,  19, 23,  9,  19, 23, 17,  19, 23, 21,
  19, 26,  1,  19, 26,  5,  19, 26,  9,  19, 26, 17,
  19, 26, 21,  19, 26, 23,  19, 27,  1,  19, 27,  5,
  19, 27,  9,  19, 27, 17,  19, 27, 19,  19, 27, 21,
  19, 29,  1,  19, 29,  2,  19, 29,  5,  19, 29,  9,
  19, 29, 17,  19, 29, 19,  19, 29, 21,  19, 29, 23,
  20,  3,  1,  20,  3,  2,  20,  3,  5,  20,  3,  9,
  20,  3, 14,  20,  3, 17,  20,  3, 19,  20,  3, 21,
  20,  3, 23,  20,  4,  1,  20,  4,  2,  20,  4,  5,
  20,  4,  9,  20,  4, 17,  20,  4, 19,  20,  4, 21,
  20,  4, 22,  20,  4, 23,  20,  5,  1,  20,  5, 23,
  20,  7,  1,  20,  7,  2,  20,  7,  5,  20,  7,  9,
  20,  7, 11,  20,  7, 17,  20,  7, 19,  20,  7, 21,
  20,  7, 23,  20, 10,  1,  20, 10,  2,  20, 10,  5,
  20, 10,  9,  20, 10, 17,  20, 10, 19,  20, 10, 21,
  20, 10, 23,  20, 11,  1,  20, 11,  2,  20, 11,  5,
  20, 11,  9,  20, 11, 17,  20, 11, 19,  20, 11, 21,
  20, 11, 22,  20, 11, 23,  20, 12,  1,  20, 12,  5,
  20, 12,  9,  20, 12, 19,  20, 13,  1,  20, 13,  2,
  20, 13,  5,  20, 13,  9,  20, 13, 14,  20, 13, 17,
  20, 13, 19,  20, 13, 21,  20, 13, 23,  20, 13, 27,
  20, 14,  1,  20, 14,  2,  20, 14,  5,  20, 14,  9,
  20, 14, 21,  20, 14, 23,  20, 15,  1,  20, 15,  2,
  20, 15,  5,  20, 15, 21,  20, 15, 23,  20, 18,  1,
  20, 18,  2,  20, 18,  5,  20, 18,  9,  20, 18, 19,
  20, 18, 21,  20, 18, 23,  20, 19,  1,  20, 19,  5,
  20, 19,  9,  20, 19, 19,  20, 19, 21,  20, 20,  1,
  20, 20,  2,  20, 20,  5,  20, 20,  9,  20, 20, 14,
  20, 20, 17,  20, 20, 21,  20, 20, 23,  20, 21,  1,
  20, 21,  5,  20, 21,  9,  20, 21, 17,  20, 21, 23,
  20, 22,  1,  20, 22,  2,  20, 22,  5,  20, 22,  9,
  20, 22, 23,  20, 23,  1,  20, 23,  2,  20, 23,  5,
  20, 23,  9,  20, 23, 17,  20, 23, 19,  20, 23, 21,
  20, 23, 23,  20, 26,  1,  20, 26,  2,  20, 26,  5,
  20, 26,  9,  20, 26, 17,  20, 26, 21,  20, 26, 23,
  20, 27,  1,  20, 27,  2,  20, 27,  5,  20, 27,  7,
  20, 27,  8,  20, 27,  9,  20, 27, 10,  20, 27, 17,
  20, 27, 19,  20, 27, 21,  20, 27, 23,  20, 27, 27,
  20, 28,  1,  20, 28,  5,  20, 28,  9,  20, 28, 17,
  20, 28, 19,  20, 28, 23,  20, 29,  1,  20, 29,  2,
  20, 29,  5,  20, 29,  9,  20, 29, 17,  20, 29, 19,
  20, 29, 21,  20, 29, 23,};

static unsigned short ks_table2[][4] = {
  0xa4bf,  1,  3,  1,  0xa4c0,  1,  4,  1,
  0xa4c1,  1,  5,  1,  0xa4c2,  1,  6,  1,
  0xa4c3,  1,  7,  1,  0xa4c4,  1, 10,  1,
  0xa4c5,  1, 11,  1,  0xa4c6,  1, 12,  1,
  0xa4c7,  1, 13,  1,  0xa4c8,  1, 14,  1,
  0xa4c9,  1, 15,  1,  0xa4ca,  1, 18,  1,
  0xa4cb,  1, 19,  1,  0xa4cc,  1, 20,  1,
  0xa4cd,  1, 21,  1,  0xa4ce,  1, 22,  1,
  0xa4cf,  1, 23,  1,  0xa4d0,  1, 26,  1,
  0xa4d1,  1, 27,  1,  0xa4d2,  1, 28,  1,
  0xa4d3,  1, 29,  1,  0xa4a1,  2,  2,  1,
  0xa4a2,  3,  2,  1,  0xa4a4,  4,  2,  1,
  0xa4a7,  5,  2,  1,  0xa4a8,  6,  2,  1,
  0xa4a9,  7,  2,  1,  0xa4b1,  8,  2,  1,
  0xa4b2,  9,  2,  1,  0xa4b3, 10,  2,  1,
  0xa4b5, 11,  2,  1,  0xa4b6, 12,  2,  1,
  0xa4b7, 13,  2,  1,  0xa4b8, 14,  2,  1,
  0xa4b9, 15,  2,  1,  0xa4ba, 16,  2,  1,
  0xa4bb, 17,  2,  1,  0xa4bc, 18,  2,  1,
  0xa4bd, 19,  2,  1,  0xa4be, 20,  2,  1,
};

/* 받침이 없을 때 (모음) 에 따라 어떤 모양의 초성을 쓸 건지 결정 */

static int fcon_map1[] = {
    0, 0,
    0, 0, 0, 0, 0, 0,              /* (채움),ㅏ,ㅐ,ㅑ,ㅒ,ㅓ */
    0, 0,
    0, 0, 0, 1, 3, 3,              /* ㅔ,ㅕ,ㅖ,ㅗ,ㅗㅏ,ㅗㅐ */
    0, 0,
    3, 1, 2, 4, 4, 4,              /* ㅗㅣ,ㅛ,ㅜ,ㅜㅓ,ㅜㅔ,ㅜㅣ */
    0, 0,
    2, 1, 3, 0                     /* ㅠ,ㅡ,ㅡㅣ,ㅣ */
};

/* 받침이 있을 때 (모음) 에 따라 어떤 모양의 초성을 쓸 건지 결정 */

static int fcon_map2[] = {
    0, 0,
    5, 5, 5, 5, 5, 5,              /* (채움),ㅏ,ㅐ,ㅑ,ㅒ,ㅓ */
    0, 0,
    5, 5, 5, 6, 8, 8,              /* ㅔ,ㅕ,ㅖ,ㅗ,ㅗㅏ,ㅗㅐ */
    0, 0,
    8, 6, 7, 9, 9, 9,              /* ㅗㅣ,ㅛ,ㅜ,ㅜㅓ,ㅜㅔ,ㅜㅣ */
    0, 0,
    7, 6, 8, 5                     /* ㅠ,ㅡ,ㅡㅣ,ㅣ */
};

/* (모음) 에 따른 font index */

static int vow_base[] = {
    0, 0,
    0, 311, 314, 317, 320, 323,          /* (채움),ㅏ,ㅐ,ㅑ,ㅒ,ㅓ */
    0, 0,
    326, 329, 332, 335, 339, 343,    /* ㅔ,ㅕ,ㅖ,ㅗ,ㅗㅏ,ㅗㅐ */
    0, 0,
    347, 351, 355, 358, 361, 364,    /* ㅗㅣ,ㅛ,ㅜ,ㅜㅓ,ㅜㅔ,ㅜㅣ */
    0, 0,
    367, 370, 374, 378             /* ㅠ,ㅡ,ㅡㅣ,ㅣ */
};

/* (모음) 이 ㅗ 형태인지 아닌지 구별 */

static int vow_kind[] = {
    0, 0,
    0, 0, 0, 0, 0, 0,              /* (채움),ㅏ,ㅐ,ㅑ,ㅒ,ㅓ */
    0, 0,
    0, 0, 0, 1, 1, 1,              /* ㅔ,ㅕ,ㅖ,ㅗ,ㅗㅏ,ㅗㅐ */
    0, 0,
    1, 1, 0, 0, 0, 0,              /* ㅗㅣ,ㅛ,ㅜ,ㅜㅓ,ㅜㅔ,ㅜㅣ */
    0, 0,
    0, 1, 1, 0                     /* ㅠ,ㅡ,ㅡㅣ,ㅣ */
};

/* (받침) 에 따라 모음 모양에 영향 */

static int lcon_kind[] = {
    0, 0, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};

/* (모음) 에 따라 받침 모양 결정 */

static int lcon_map[] = {
    0, 0,
    0, 0, 2, 0, 2, 1,
    0, 0,
    2, 1, 2, 3, 0, 0,
    0, 0,
    0, 3, 3, 1, 1, 1,
    0, 0,
    3, 3, 0, 1
};

/* 완성형 코드를 조합형 코드로 바꾼다.
   h : 완성형 코드 첫 바이트
   l : 완성형 코드 두번째 바이트
   des : 조합형 코드를 3 바이트로 돌려준다.
*/

void convert_ks_to_3(h, l, des)
    int h, l;
    unsigned char *des;
{
    int c;
    int i;

    if ((i = ks_table1_index(h, l)) >= 0 && i < sizeof(ks_table1)/sizeof(ks_table1[0])) {
      *des++ = ks_table1[i][0];
      *des++ = ks_table1[i][1];
      *des++ = ks_table1[i][2];
    }
    else {
      c = (h << 8) | l;
      for (i = 0; i < 40; i++)
          if (ks_table2[i][0] == c) {
            *des++ = ks_table2[i][1];
            *des++ = ks_table2[i][2];
            *des++ = ks_table2[i][3];
            return;
          }
      *des++ = 0xff;    /* 그래픽 코드 */
      *des++ = h;
      *des++ = l;
    }
}

/* 조합형 초성 - 완성형 낱자 변환 */

static unsigned char johab_fcon_to_wan[] = {
    0,
    0xd4, 0xa1, 0xa2, 0xa4, 0xa7,    /* (채움),ㄱ,ㄲ,ㄴ,ㄷ */
    0xa8, 0xa9, 0xb1, 0xb2, 0xb3,    /* ㄸ,ㄹ,ㅁ,ㅂ,ㅃ */
    0xb5, 0xb6, 0xb7, 0xb8, 0xb9,    /* ㅅ,ㅆ,ㅇ,ㅈ,ㅉ */
    0xba, 0xbb, 0xbc, 0xbd, 0xbe     /* ㅊ,ㅋ,ㅌ,ㅍ,ㅎ */
};

/* 조합형 중성 -> 완성형 낱자 변환 */

static unsigned char johab_vow_to_wan[] = {
    0, 0,
    0xd4, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,   /* (채움),ㅏ,ㅐ,ㅑ,ㅒ,ㅓ */
    0, 0,
    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, /* ㅔ,ㅕ,ㅖ,ㅗ,ㅗㅏ,ㅗㅐ */
    0, 0,
    0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* ㅗㅣ,ㅛ,ㅜ,ㅜㅓ,ㅜㅔ,ㅜㅣ */
    0, 0,
    0xd0, 0xd1, 0xd2, 0xd3         /* ㅠ,ㅡ,ㅡㅣ,ㅣ */
};

/* 조합형 종성 -> 완성형 낱자 변환 */

static unsigned char johab_lcon_to_wan[] = {
    0,
    0xd4, 0xa1, 0xa2, 0xa3, 0xa4,    /* (채움), ㄱ, ㄲ, ㄱㅅ, ㄴ */
    0xa5, 0xa6, 0xa7, 0xa9, 0xaa,    /* ㄴㅈ, ㄴㅎ, ㄷ, ㄹ, ㄹㄱ */
    0xab, 0xac, 0xad, 0xae, 0xaf,    /* ㄹㅁ, ㄹㅂ, ㄹㅅ, ㄹㅌ, ㄹㅍ */
    0xb0, 0xb1, 0,    0xb2, 0xb4,    /* ㄹㅎ, ㅁ, 0, ㅂ, ㅂㅅ */
    0xb5, 0xb6, 0xb7, 0xb8, 0xba,    /* ㅅ, ㅆ, ㅇ, ㅈ, ㅊ */
    0xbb, 0xbc, 0xbd, 0xbe           /* ㅋ, ㅌ, ㅍ, ㅎ */
};

/* 조합형 코드를 완성형 코드로 바꾼다.
   f : 초성 (1 = (채움), 2 = ㄱ, 3 = ㄲ, 4 = ㄴ, 5 = ㄷ, 6 = ㄸ, 7 = ㄹ, ...
   m : 중성 (2 = (채움), 3 = ㅏ, 4 = ㅐ, 5 = ㅑ, 6 = ㅒ, 7 = ㅓ, 8 = *, ...
   l : 종성 (1 = (채움), 2 = ㄱ, 3 = ㄲ, 4 = ㄱㅅ, 5 = ㄴ, 6 = ㄴㅈ, ...
   des : 완성형 코드
         완성형 코드에 없을 경우에는 다음과 같이 8 byte 를 돌려 준다.
       (채움) (초성) (중성) (종성)
       (채움) = 0xA4D4
       (초성) = 0xA4A1 - 0xA4FE
       (초성) = 0xA4A1 - 0xA4FE
       (초성) = 0xA4A1 - 0xA4FE
   결과 : des 에 넣어진 byte 수, 2 | 8
*/
int convert_3_to_ks(f, m, l, des)
    unsigned int f, m, l;
    unsigned char *des;
{
    unsigned char key[3];
    register int hi, lo, mi, result, found;

    if (f == 0xff) {
      des[0] = m;
      des[1] = l;
      return 2;
    }
    key[0] = f;
    key[1] = m;
    key[2] = l;
    lo = 0;
    hi = sizeof(ks_table1)/3 - 1;
    found = 0;
    while (lo + 1 < hi) {
      mi = (lo + hi)/2;
      result = strncmp((char*)ks_table1[mi], (char*)key, 3);
      if (result == 0) {
          found = 1;
          break;
      }
      else if (result > 0) {
          hi = mi;
      }
      else {
          lo = mi;
      }
    }
    if (!found) {
      if (!strncmp((char*)ks_table1[lo], (char*)key, 3)) {
          found = 1;
          mi = lo;
      }
      if (!strncmp((char*)ks_table1[hi], (char*)key, 3)) {
          found = 1;
          mi = hi;
      }
    }
    if (!found) {
      for (mi = 0; mi < 40; mi++)
          if (ks_table2[mi][1] == f && ks_table2[mi][2] == m &&
            ks_table2[mi][3] == l) {
            des[0] = ks_table2[mi][0] >> 8;
            des[1] = ks_table2[mi][0];
            return 2;   /* found */
          }
    }
    else {
      des[0] = mi / (0xff-0xa1) + 0xb0;
      des[1] = mi % (0xff-0xa1) + 0xa1;
      return 2;         /* found */
    }

    /* 완성형 표에 없다. ``KS C 5601 - 1992 정보 교환용 부호 해설''
       3.3 절에 설명된 방법으로 encoding 한다. */

    *des++ = 0xa4;                 /* 채움 */
    *des++ = 0xd4;
    *des++ = 0xa4;                 /* 낱자는 모두 a4 행에 있다. */
    *des++ = johab_fcon_to_wan[f];
    *des++ = 0xa4;
    *des++ = johab_vow_to_wan[m];
    *des++ = 0xa4;
    *des++ = johab_lcon_to_wan[l];
    return 8;
}

convert_3_to_display(f, m, l, des)
    int f, m, l;
    XChar2b *des;
{
    int ind;
    int i;

    i = 0;
    if (f == 0xff) {    /* 그래픽 코드 */
      ind = (m - 0xa1) * 94 + l - 0xa1 + 0x211;
      des[i].byte1 = ind / 256;
      des[i].byte2 = ind % 256;
      return 1;
    }
    if (f < 1 || f > 20 || m < 2 || m > 29 || l < 1 || l > 29) {
      des[i].byte1 = 0;      /* 공백 */
      des[i].byte2 = 0;
      return 1;
    }
    if (f != 1) {            /* 채움이 아니면 ... */
      ind = f * 10 + (l > 1 ? fcon_map2[m] : fcon_map1[m]) - 19;
      des[i].byte1 = ind >> 8;
      des[i].byte2 = ind;
      i++;
    }
    if (m != 2) {            /* 채움이 아니면 ... */
      ind = vow_base[m];
      switch (vow_kind[m]) {
      case 0:                      /* ㅗ 계열이 아니면 ... */
          ind += lcon_kind[l];
          break;
      case 1:                      /* ㅗ, ㅗㅏ, ㅗㅐ, ... 계열 */
          ind += ((f == 2 || f == 17) ? 0 : 1) + (l > 1 ? 2 : 0);
                        /* ㄱ,ㅋ 일때 특별처리 */
          break;
      }
#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
        if (i > 0 && font_no_zero_width_char != 0) {
            des[i].byte1 = font_minus_width_char_byte1;
            des[i].byte2 = font_minus_width_char_byte2;
            i++;
        }
#endif
      des[i].byte1 = ind >> 8;
      des[i].byte2 = ind;
      i++;
    }
    if (l != 1) {
      ind = l * 4 + lcon_map[m] + (l < 18 ? 397 : 393);
                        /* l == 18 일때 아무받침도 아니기때문에
                           특별 처리 */
#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
        if (i > 0 && font_no_zero_width_char != 0) {
            des[i].byte1 = font_minus_width_char_byte1;
            des[i].byte2 = font_minus_width_char_byte2;
            i++;
        }
#endif
      des[i].byte1 = ind >> 8;
      des[i].byte2 = ind;
      i++;
    }
    if (f != 1 && m == 2 && l == 1) {     /* initial sound only? */
#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
      if (font_no_zero_width_char == 0) {
#endif
      des[i].byte1 = 0; /* dummy for no zero width */
      des[i].byte2 = 0;
      i++;
#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
      }
#endif
    }
    return i;
}

/* src 는 2 byte 조합형
   des 는 font index
*/
convert_johab_to_display(src, des, len)
    unsigned char *src;
    XChar2b *des;
    int len;
{
    unsigned char buf[3];
    int n, f, m, l;
    XChar2b *org;

/* addition by wsyang for supporting Wansung font : 3, 1994*/

    extern int font_ks_mode;
    extern int font_jo_mode;
    unsigned char tmp[400];

    if (font_ks_mode != -1) {
      convert_johab_to_ks(src, tmp, len);
      src = tmp;
      org = des;
      while (len > 0) {
          if (font_ks_mode != 't') {
              des->byte1 = (*src++) - (unsigned char)0x80;
              des->byte2 = (*src++) - (unsigned char)0x80;
          } else {
              des->byte1 = (*src++);
              des->byte2 = (*src++);
            }
          des++;
          len -= 2;
      }
    } else {
/* end of patch by wsyang */
      org = des;
      while (len > 0) {
          convert_johab_to_3(src, &f, &m, &l);
          if(font_jo_mode == TRUE) n = convert_3_to_jo844(f, m, l, des);
          else n = convert_3_to_display(f, m, l, des);
          src += 2;
          len -= 2;
          des += n;
        }
    }
    return (des - org);
}

/* 3 바이트로 된 조합형 -> 2 바이트 조합형 */

int convert_3_to_johab( f , m , l , buf )
    int f, m, l;
    unsigned char *buf;
{
    if (f == 0xff) {
      if (m >= 0xa1 && m <= 0xac) {
          buf[0] = (m - 0xa1) / 2 + 0xd9;
          if (m & 1) {        /* 0xa1, 0xa3, 0xa5, ... */
            buf[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91-0x7f+0x31; /* bug ! */
          } else {
            buf[1] = l;
          }
      } else if (m >= 0xad && m <= 0xaf) { /* 정의 안된 영역 */
          buf[0] = 0xd9;      /* 공란문자로 채움 */
          buf[1] = 0x31;
      } else if (m == 0xc9 || m == 0xfe) {
          buf[0] = 0xd8;
          if (m & 1) {
            buf[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91;
          } else {
            buf[1] = l;
          }
      } else if (m > 0xc9 && m < 0xfe) {
          buf[0] = (m - 0xca) / 2 + 0xe0;
          if (m & 1) {
            buf[1] = l;
          } else {
            buf[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91-0x7f+0x31; /* bug ! */
          }
      }
    } else {
      buf[0] = 0x80 | (f << 2) | (m >> 3);
      buf[1] = (m << 5) | l;
    }
    return 2;
}

static char jamo_index1[]= {        /* 0:fill, 2:ㄱ, ... */
   0,  0,  1,  2,  3,  4,  5,  6,
   7,  8,  9,  10, 11, 12, 13, 14,
   15, 16, 17, 18, 19,  0,  0,  0,
   0,  0,   0,  0,  0,  0,  0,  0
};
static char jamo_index2[]= {        /* 0:fill 1:ㅏ, ... */
   0,  0,  0,  1,  2,  3,  4,  5,
   0,  0,  6,  7,  8,  9,  10, 11,
   0,  0, 12, 13, 14, 15,  16, 17,
   0,  0, 18, 19, 20, 21,   0,  0
};
static char jamo_index3[]= {        /* 0:fill, 2:ㄱ, ... */
   0,  0,  1,  2,  3,  4,  5,  6,
   7,  8,  9, 10, 11, 12,  13, 14,
   15, 16, 0, 17, 18, 19,  20, 21,
   22, 23, 24, 25, 26, 27,  0,  0
};

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
static char johab_index1[]= {       /* 0:fill, 1:ㄱ, ... */
   0,  2,  3,  4,  5,  6,  7,  8,
   9,  10, 11, 12, 13, 14, 15, 16,
   17, 18, 19, 20,  0,  0,  0,  0,
   0,  0,   0,  0,  0,  0,  0,  0
};
static char johab_index2[]= {       /* 0:fill 1:ㅏ, ... */
   0,  3,  4,  5,  6,  7,  10, 11,
   12,  13, 14, 15, 18, 19, 20, 21,
   22,  23, 26, 27, 28, 29,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0
};
static char johab_index3[]= {       /* 0:fill 1:ㄱ, ... */
   1,  2,  3,  4,  5,  6,  7,  8,  
   9, 10, 11, 12, 13, 14, 15, 16, 
   17, 19, 20, 21, 22, 23, 24, 25, 
   26, 27, 28, 29,  0,  0,  0,  0
};
#endif

int
convert_3_to_jo844(f, m, l, des)
      int f, m, l;
      XChar2b *des;
{
      int ind;
      int i=0;

   unsigned h1, h2, h3, type1, type2, type3;
   static char type1_no[]= {
         0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3,
         3, 3, 1, 2, 4, 4, 4, 2, 1, 3, 0
   };
   static char type1_yes[]= {
         5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7,
         7, 7, 6, 6, 7, 7, 7, 6, 6, 7, 5,
   };
   static char _type3[]= {
         0, 0, 2, 0, 2, 1, 2, 1, 2, 3, 0,
         2, 1, 3, 3, 1, 2, 1, 3, 3, 1, 1
   };

      if (f==0xff || f < 1 || f > 20 || m < 2 || m > 29 || l < 1 || l > 29) {
   des[i].byte1 = 0;        /* 공백 */
   des[i].byte2 = 0;
   return 1;
      }

   h1 = jamo_index1[f];
   h2 = jamo_index2[m];
   h3 = jamo_index3[l];
   /* 초성종류 :
                                       받침있는 것에서 중성따라 : 받침없는 것에서 종성따라
   */
   type1 = h3 ? type1_yes[h2] : type1_no[h2];
   /* 중성종류 :
                                       초성이 없거나 ㄱ ㅋ 이면 안 더하고 (딴거면 1),
                                       받침이 있으면 2 더하고 (아님 0) */
   type2 = ((h1 == 0 || h1 == 1 || h1 == 16) ? 0 : 1) + (h3 ? 2 : 0);
   type3 = _type3[h2];


   i = 0;
   if (h1) {
         ind = type1 * 20 + h1;
         des[i].byte1 = ind >> 8;
         des[i].byte2 = ind;
         i++;
   }
   if (h2) {
         ind = type2 * 22 + h2 + 160;
         des[i].byte1 = ind >> 8;
         des[i].byte2 = ind;
         i++;
   }
   if (h3) {
         ind = type3 * 28 + h3 + 160 + 88;
         des[i].byte1 = ind >> 8;
         des[i].byte2 = ind;
         i++;
   }

   if (f != 1 && m == 2 && l == 1) {   
         des[i].byte1 = 0;
         des[i].byte2 = 0;
         i++; 
   }

   return i;
}

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
/* 3 바이트로 된 조합형 -> UTF-8 */

int convert_3_to_utf8( f , m , l , buf )
    int f, m, l;
    unsigned char *buf;
{
    int index_f, index_m, index_l;
    unsigned long code = 0;

#if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    printf("convert_3_to_utf8(%02x,%02x,%02x)\n", f, m, l);
#endif

    if (f == 0xff) {
      code = convert_char_ksc5601_to_ucs2((unsigned char)m, (unsigned char)l);
    }
    else {
      index_f = jamo_index1[f];
      index_m = jamo_index2[m];
      index_l = jamo_index3[l];

      if (index_f > 0 && index_m > 0 && index_l >= 0) {
          code = 0xac00 + ((((index_f-1) * 21) + (index_m-1)) * 28) + index_l;
          /* 0xac00 <= code <= 0xd7a3 */
      }
      else if (index_f > 0 && index_m == 0 && index_l == 0) {
          code = 0x3100
                | (johab_fcon_to_wan[index_f+1] - (unsigned char)0x70);
      }
      else if (index_f == 0 && index_m > 0 && index_l == 0) {
          code = 0x3100
                | (johab_vow_to_wan[index_m+2] - (unsigned char)0x70);
      }
      else if (index_f > 0 && index_m == 0 && index_l == 0) {
          code = 0x3100
                | (johab_lcon_to_wan[index_l+1] - (unsigned char)0x70);
      }
    }

    if (code > 0)
      return convert_wc_to_mb(buf, code);

#if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
      printf("convert_3_to_utf8() scope error! (%d,%d,%d)\n", f, m, l);
#endif
    buf[0] = '?';
    buf[1] = '?';
    return 2;
}
#endif

/* 조합형 문자를 3 바이트 조합형으로 바꾼다. */

convert_johab_to_3(src, f, m, l)
    unsigned char *src;
    unsigned int *f, *m, *l;
{
    if (src[0] >= 0x84 && src[0] <= 0xd3) { /* 보통 한글 */
      *f = (unsigned char)((src[0] >> 2) & 0x1f);
      *m = (unsigned char)(((src[0] << 3) | (src[1] >> 5)) & 0x1f);
      *l = (unsigned char)(src[1] & 0x1f);
    } else {                  /* 특수 문자 */
      *f = (unsigned char)0xff;
      if (src[0] >= 0xd9 && src[0] <= 0xde) { /* 심벌들 */
          *m = (unsigned char)((src[0] - 0xd9)*2 + 0xa1);
      } else if (src[0] >= 0xe0 && src[0] <= 0xf9) { /* 한자 */
          *m = (unsigned char)((src[0] - 0xe0)*2 + 0xca); /* good */
      } else if (src[0] == 0xd8) {
          *m = (unsigned char) 0xc9;
      }
      if (src[1] >= 0x31 && src[1] <= 0x7e) {
          *l = (unsigned char)(src[1] - 0x31 + 0xa1);
      } else if (src[1] >= 0x91 && src[1] <= 0xa0) {
          *l = (unsigned char)(src[1] -  0x91 + (0x7f - 0x31) + 0xa1);
      } else if (src[1] >= 0xa1 && src[1] <= 0xfe) {
          *l = src[1];
          if (src[0] == 0xd8) {
            *m = (unsigned char)0xfe;
          }
          else{
            (*m)++;
          }
      } else {
          *l = 0;
      }
    }
}

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
/* 조합형 문자를 UTF-8로 바꾼다. */

int
convert_johab_to_utf8(src, des, len)
    unsigned char *src;
    unsigned char *des;
    int len;
{
    unsigned int f, m, l;
    int des_len = 0;

#if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    printf("convert_johab_to_utf8() : ");
    if (len == 1) printf("%02x)", src[0]);
    else if (len > 1) printf("%02x, %02x, ...)", src[0], src[1]);
    printf("\n");
#endif

    while (len > 0) { 
      if (src[0] < (unsigned char)0x80) {
          des[0] = src[0];
          src++, des++, len--, des_len++;
      }
      else if (src[0] >= 0x84 && src[0] <= 0xd3) { /* 보통 한글 */
          f = (unsigned char)((src[0] >> 2) & 0x1f);
          m = (unsigned char)(((src[0] << 3) | (src[1] >> 5)) & 0x1f);
          l = (unsigned char)(src[1] & 0x1f);

          des_len += convert_3_to_utf8(f, m, l, des);
          des += des_len;
          src += 2; len -= 2;
      } else {                /* 특수 문자 */
          f = (unsigned char)0xff;
          if (src[0] >= 0xd9 && src[0] <= 0xde) { /* 심벌들 */
            m = (unsigned char)((src[0] - 0xd9)*2 + 0xa1);
          } else if (src[0] >= 0xe0 && src[0] <= 0xf9) { /* 한자 */
            m = (unsigned char)((src[0] - 0xe0)*2 + 0xca); /* good */
          } else if (src[0] == 0xd8) {
            m = (unsigned char) 0xc9;
          }
          if (src[1] >= 0x31 && src[1] <= 0x7e) {
            l = (unsigned char)(src[1] - 0x31 + 0xa1);
          } else if (src[1] >= 0x91 && src[1] <= 0xa0) {
            l = (unsigned char)(src[1] -  0x91 + (0x7f - 0x31) + 0xa1);
          } else if (src[1] >= 0xa1 && src[1] <= 0xfe) {
            l = src[1];
            if (src[0] == 0xd8) {
                m = (unsigned char)0xfe;
            }
            else{
                m++;
            }
          } else {
            l = 0;
          }

          des_len += convert_3_to_utf8(f, m, l, des);
          des += des_len;
          src += 2; len -= 2;
      }
#if 0 /* not reached */
      else
      {
  #if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
          printf("convert_johab_to_utf8() scope error! (%02x,%02x)\n",
                src[0],src[1]);
  #endif
          des[0] = '?';
          des[1] = '?';
          des += 2; des_len += 2;
          src += 2; len -= 2;
      }
#endif
    }

    return des_len;
}
#endif

/* 완성형 문자열을 2 바이트 조합형 문자열로 바꾼다.
   조합형 문자열의 길이를 돌려준다. */

convert_ks_to_johab(src, des, n)
    unsigned char *src, *des;
    int n;
{
    int l;
    unsigned char tmp[3];
    unsigned char *org_des;
    extern int font_jo_mode;

    org_des = des;
    while (n > 0) {
      if (*src & 0x80) {
          convert_ks_to_3(*src, *(src+1), tmp);
/*        if( font_jo_mode == TRUE )
            l = convert_3_to_jo844(tmp[0], tmp[1], tmp[2], des);
          else */
            l = convert_3_to_johab(tmp[0], tmp[1], tmp[2], des);
          src += l;
          des += l;
          n -= l;
      } else {
          *des++ = *src++;
          n--;
      }
    }
    return (des - org_des);
}

/* 조합형 문자열을 완성형 문자열로 바꾼다. 변환된 완성형 문자열의 길이를
   돌려준다. */

int convert_johab_to_ks(src, des, len)
    unsigned char *src, *des;
    int len;
{
    int f, m, l;
    unsigned char *org_des;

    org_des = des;
    while (len > 0) {
      if (*src & 0x80) {
          convert_johab_to_3(src, &f, &m, &l);
          des += convert_3_to_ks(f, m, l, des);
          src += 2;
          len -= 2;
      } else {
          *des++ = *src++;
          --len;
      }
    }
    *des = 0;
    return des - org_des;
}

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
/* UTF-8 -> 2 바이트 조합형 */

int convert_utf8_to_johab( src, des, src_len )
    unsigned char *src;
    unsigned char *des;
    int src_len;
{
    int des_len = 0;
    int chr_len;
    unsigned long code;
    int ret;

#if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    printf("convert_utf8_to_johab()\n");
#endif

    for (; src_len > 0; src += chr_len, src_len -= chr_len) {
      if (src[0] < (unsigned char)0x80) {
          chr_len = 1; 
          *(des++) = src[0];
          des_len++;
          continue;
      }

      ret = convert_mb_to_wc(&code, src, src_len);
      if (ret > 0) {
          chr_len = ret;

          /* 11172 hangul area */
          if (code >= (unsigned long)0xac00 && code <= (unsigned long)0xd7a3) 
          {
            unsigned index_f, index_m, index_l, code_x;

            code_x = code - (unsigned long)0xac00;
            index_l = code_x % 28;
            code_x /= 28;
            index_m = code_x % 21;
            code_x /= 21;
            index_f = code_x;

            *(des++) = 0x80 | (johab_index1[index_f+1] << 2) 
                          | (johab_index2[index_m+1] >> 3);
            *(des++) = (johab_index2[index_m+1] << 5) 
                        | johab_index3[index_l];
            des_len+=2;

            continue;
          }
#if 1 /* convert to single jamo in johab code */
          else if (code >= 0x3131 && code <= 0x3181) {
            int i, f, m, l, len;
            unsigned short ks_code = 
                  ((unsigned short)code - 0x3131) + 0xa4a1;
            for (i = 0; i < 40; i++) {
                if ((unsigned long)ks_table2[i][0] == ks_code) {
                  f = (unsigned char)ks_table2[i][1];
                  m = (unsigned char)ks_table2[i][2];
                  l = (unsigned char)ks_table2[i][3];
                  len = convert_3_to_johab(f, m, l, des);
                  des += len;
                  des_len += len;
                  break;
                }
            }
            if (i < 40) continue;
          }
#endif
          else { /* refer table */
            int f, m, l;
            int len;
            unsigned short ksc_code = convert_char_ucs2_to_ksc5601(
                      (unsigned short)code);
            if (ksc_code > 0) {
                f = (unsigned char)0xff;
                m = (unsigned char)(ksc_code >> 8);
                l = (unsigned char)(ksc_code & 0xff);
                len = convert_3_to_johab(f, m, l, des);
                if (len > 0) {
                  des += len;
                  des_len += len;
                  continue;
                }
            }
          }
      }

      {
          int i;

          for (i = 1; i <= 6 && i < src_len; i++) {
            if (src[i] & 0x40) break;
          }
          chr_len = i;

#if defined(DEBUG_PATCH_UTF8) /* by hanmaum 1998.2.5 */
          printf("convert_utf8_to_johab() scope error! (");
          for (i = 0; i < chr_len; i++)
                printf("%02x",src[i]);
          printf(")\n");
#endif
      }

      /* screen width is assumed as 2. check is needed. */
      *(des++) = '?';
      *(des++) = '?';
      des_len += 2;
    }

    return des_len;

#if 0
    if (f == 0xff) {
      if (m >= 0xa1 && m <= 0xac) {
          des[0] = (m - 0xa1) / 2 + 0xd9;
          if (m & 1) {        /* 0xa1, 0xa3, 0xa5, ... */
            des[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91-0x7f+0x31; /* bug ! */
          } else {
            des[1] = l;
          }
      } else if (m >= 0xad && m <= 0xaf) { /* 정의 안된 영역 */
          des[0] = 0xd9;      /* 공란문자로 채움 */
          des[1] = 0x31;
      } else if (m == 0xc9 || m == 0xfe) {
          des[0] = 0xd8;
          if (m & 1) {
            des[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91;
          } else {
            des[1] = l;
          }
      } else if (m > 0xc9 && m < 0xfe) {
          des[0] = (m - 0xca) / 2 + 0xe0;
          if (m & 1) {
            des[1] = l;
          } else {
            des[1] = (l-0xa1 < 0x7f-0x31) ? l-0xa1+0x31 : l-0xa1+0x91-0x7f+0x31; /* bug ! */
          }
      }
    } else 
#endif
}

unsigned short convert_char_ksc5601_to_ucs2(byte1, byte2)
unsigned char byte1, byte2;
{
      int tab_idx = ((int)byte1 - 0x00a1) * 94 + (int)byte2 - 0x00a1;
      long code_ucs2;

      if (tab_idx >= 0 && tab_idx < ksc5601max) {
            code_ucs2 = tabksc5601[tab_idx];
            if (code_ucs2 != -1) return code_ucs2;
      }
      return 0;
}

#define MAX_UCS2 0xffff

unsigned short convert_char_ucs2_to_ksc5601(code_ucs2)
unsigned short code_ucs2;
{
      register int i;
#if 0 /* Use reverse table. some memory is used. */
      static unsigned short tabrev[MAX_UCS2+1];
      static Boolean tabrev_set = False;
      long l;

      if (tabrev_set == False) {
            for (i = 0; i < ksc5601max; i++) {
                  l = tabksc5601[i];
                  if (l == -1) continue;

                  if (l >= 0 && l <= (unsigned long)MAX_UCS2) {
                        tabrev[l] = ((i/94+0xa1) << 8) | (i%94+0xa1);
                  }
                  else if (l < 0)
                        tabrev[(unsigned short)l] = i;
            }
            tabrev_set = True;
      }

      return tabrev[code_ucs2];
#else
      for (i = 0; i < ksc5601max; i++) {
            if (code_ucs2 == tabksc5601[i])
                  return ((i/94+0xa1) << 8) | (i%94+0xa1);
      }
#endif
      return 0;
}

enum
{
      T1    = 0x00,
      Tx    = 0x80,
      T2    = 0xC0,
      T3    = 0xE0,
      T4    = 0xF0,
      T5    = 0xF8,
      T6    = 0xFC,

      Bit1  = 7,
      Bitx  = 6,
      Bit2  = 5,
      Bit3  = 4,
      Bit4  = 3,
      Bit5  = 2,
      Bit6  = 2,

      Mask1 = (1<<Bit1)-1,
      Maskx = (1<<Bitx)-1,
      Mask2 = (1<<Bit2)-1,
      Mask3 = (1<<Bit3)-1,
      Mask4 = (1<<Bit4)-1,
      Mask5 = (1<<Bit5)-1,
      Mask6 = (1<<Bit6)-1,

      Wchar1      = ((unsigned long)1<<Bit1)-1,
      Wchar2      = ((unsigned long)1<<(Bit2+Bitx))-1,
      Wchar3      = ((unsigned long)1<<(Bit3+2*Bitx))-1,
      Wchar4      = ((unsigned long)1<<(Bit4+3*Bitx))-1,
      Wchar5      = ((unsigned long)1<<(Bit5+4*Bitx))-1
};

int
convert_wc_to_mb(s, wc)
char *s;
unsigned long wc;
{
      if(s == 0)
            return 0;         /* no shift states */
      if(wc & ~Wchar2) {
            if(wc & ~Wchar4) {
                  if(wc & ~Wchar5) {
                        /* 6 bytes */
                        s[0] = T6 | ((wc >> 5*Bitx) & Mask6);
                        s[1] = Tx | ((wc >> 4*Bitx) & Maskx);
                        s[2] = Tx | ((wc >> 3*Bitx) & Maskx);
                        s[3] = Tx | ((wc >> 2*Bitx) & Maskx);
                        s[4] = Tx | ((wc >> 1*Bitx) & Maskx);
                        s[5] = Tx |  (wc & Maskx);
                        return 6;
                  }
                  /* 5 bytes */
                  s[0] = T5 |  (wc >> 4*Bitx);
                  s[1] = Tx | ((wc >> 3*Bitx) & Maskx);
                  s[2] = Tx | ((wc >> 2*Bitx) & Maskx);
                  s[3] = Tx | ((wc >> 1*Bitx) & Maskx);
                  s[4] = Tx |  (wc & Maskx);
                  return 5;
            }
            if(wc & ~Wchar3) {
                  /* 4 bytes */
                  s[0] = T4 |  (wc >> 3*Bitx);
                  s[1] = Tx | ((wc >> 2*Bitx) & Maskx);
                  s[2] = Tx | ((wc >> 1*Bitx) & Maskx);
                  s[3] = Tx |  (wc & Maskx);
                  return 4;
            }
            /* 3 bytes */
            s[0] = T3 |  (wc >> 2*Bitx);
            s[1] = Tx | ((wc >> 1*Bitx) & Maskx);
            s[2] = Tx |  (wc & Maskx);
            return 3;
      }
      if(wc & ~Wchar1) {
            /* 2 bytes */
            s[0] = T2 | (wc >> 1*Bitx);
            s[1] = Tx | (wc & Maskx);
            return 2;
      }
      /* 1 byte */
      s[0] = T1 | wc;
      return 1;
}

int
convert_mb_to_wc(p, s, n)
unsigned long *p;
char *s;
unsigned n;
{
      unsigned char *us;
      int c0, c1, c2, c3, c4, c5;
      unsigned long wc;

      if(s == 0)
            return 0;         /* no shift states */

      if(n < 1)
            goto badlen;
      us = (unsigned char*)s;
      c0 = us[0];
      if(c0 >= T3) {
            if(n < 3)
                  goto badlen;
            c1 = us[1] ^ Tx;
            c2 = us[2] ^ Tx;
            if((c1|c2) & T2)
                  goto bad;
            if(c0 >= T5) {
                  if(n < 5)
                        goto badlen;
                  c3 = us[3] ^ Tx;
                  c4 = us[4] ^ Tx;
                  if((c3|c4) & T2)
                        goto bad;
                  if(c0 >= T6) {
                        /* 6 bytes */
                        if(n < 6)
                              goto badlen;
                        c5 = us[5] ^ Tx;
                        if(c5 & T2)
                              goto bad;
                        wc = ((((((((((c0 & Mask6) << Bitx) |
                              c1) << Bitx) | c2) << Bitx) |
                              c3) << Bitx) | c4) << Bitx) | c5;
                        if(wc <= Wchar5)
                              goto bad;
                        *p = wc;
                        return 6;
                  }
                  /* 5 bytes */
                  wc = ((((((((c0 & Mask5) << Bitx) |
                        c1) << Bitx) | c2) << Bitx) |
                        c3) << Bitx) | c4;
                  if(wc <= Wchar4)
                        goto bad;
                  *p = wc;
                  return 5;
            }
            if(c0 >= T4) {
                  /* 4 bytes */
                  if(n < 4)
                        goto badlen;
                  c3 = us[3] ^ Tx;
                  if(c3 & T2)
                        goto bad;
                  wc = ((((((c0 & Mask4) << Bitx) |
                        c1) << Bitx) | c2) << Bitx) |
                        c3;
                  if(wc <= Wchar3)
                        goto bad;
                  *p = wc;
                  return 4;
            }
            /* 3 bytes */
            wc = ((((c0 & Mask3) << Bitx) |
                  c1) << Bitx) | c2;
            if(wc <= Wchar2)
                  goto bad;
            *p = wc;
            return 3;
      }
      if(c0 >= T2) {
            /* 2 bytes */
            if(n < 2)
                  goto badlen;
            c1 = us[1] ^ Tx;
            if(c1 & T2)
                  goto bad;
            wc = ((c0 & Mask2) << Bitx) |
                  c1;
            if(wc <= Wchar1)
                  goto bad;
            *p = wc;
            return 2;
      }
      /* 1 byte */
      if(c0 >= Tx)
            goto bad;
      *p = c0;
      return 1;

bad:
      return -1;
badlen:
      return -2;
}
#endif


Generated by  Doxygen 1.6.0   Back to index