/*
  IIIMGdkEventKey.c
  Copyright (C) 2003 Free Standards Group

  Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions: The above copyright notice and this
  permission notice shall be included in all copies or substantial
  portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL OPENI18N WG OR FREE STANDARDS GROUP. BE LIABLE
  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
  THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
  ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.

  Except as contained in this notice, the names of OpenI18N WG and/or
  Free Standards Group shall not be used in advertising or otherwise to
  promote the sale, use or other dealings in this Software without prior
  written authorization from OpenI18N WG and/or Free Standards Group
  as applicable.

  Author: MIYASHITA, Hisashi <himi@OpenI18N.org>

*/
#include <gdk/gdkkeysyms.h>
#include "IIIMGdkEventKey.h"

#ifdef	linux
#define	USE_KANA_TABLE	1	/* for japanese kana support */
#endif /* linux */

#if	USE_KANA_TABLE
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static Atom kanawin_atom = 0;
static Atom kanaflag_atom = 0;
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
typedef struct KEYMAP_ENTRY2 {
  IIIMP_int32 iiimf_keycode;
  guint gdk_keysym;
  guint gdk_alt_keysym;
  IIIMP_int32 iiimf_keychar;
  guint hardware_keycode;
} KeymapEntry2;
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static KeymapEntry2 kana_normal_keymapTable[] = {
  { IIIMF_KEYCODE_1, GDK_kana_NU, GDK_1, 0xff87, 0 },
  { IIIMF_KEYCODE_2, GDK_kana_FU, GDK_2, 0xff8c, 0 },
  { IIIMF_KEYCODE_3, GDK_kana_A, GDK_3, 0xff71, 0 },
  { IIIMF_KEYCODE_4, GDK_kana_U, GDK_4, 0xff73, 0 },
  { IIIMF_KEYCODE_5, GDK_kana_E, GDK_5, 0xff74, 0 },
  { IIIMF_KEYCODE_6, GDK_kana_O, GDK_6, 0xff75, 0 },
  { IIIMF_KEYCODE_7, GDK_kana_YA, GDK_7, 0xff94, 0 },
  { IIIMF_KEYCODE_8, GDK_kana_YU, GDK_8, 0xff95, 0 },
  { IIIMF_KEYCODE_9, GDK_kana_YO, GDK_9, 0xff96, 0 },
  { IIIMF_KEYCODE_0, GDK_kana_WA, GDK_0, 0xff9c, 0 },
  { '-',			 GDK_kana_HO, GDK_minus, 0xff8e, 0 },
  { '~',			 GDK_kana_HE, GDK_asciicircum, 0xff8d, 0 },
  { IIIMF_KEYCODE_Q, GDK_kana_TA, GDK_q, 0xff80, 0 },
  { IIIMF_KEYCODE_W, GDK_kana_TE, GDK_w, 0xff83, 0 },
  { IIIMF_KEYCODE_E, GDK_kana_I, GDK_e, 0xff72, 0 },
  { IIIMF_KEYCODE_R, GDK_kana_SU, GDK_r, 0xff7d, 0 },
  { IIIMF_KEYCODE_T, GDK_kana_KA, GDK_t, 0xff76, 0 },
  { IIIMF_KEYCODE_Y, GDK_kana_N, GDK_y, 0xff9d, 0 },
  { IIIMF_KEYCODE_U, GDK_kana_NA, GDK_u, 0xff85, 0 },
  { IIIMF_KEYCODE_I, GDK_kana_NI, GDK_i, 0xff86, 0 },
  { IIIMF_KEYCODE_O, GDK_kana_RA, GDK_o, 0xff97, 0 },
  { IIIMF_KEYCODE_P, GDK_kana_SE, GDK_p, 0xff7e, 0 },
  { IIIMF_KEYCODE_AT, GDK_voicedsound, GDK_at, 0xff9e, 0 },
  { IIIMF_KEYCODE_OPEN_BRACKET, GDK_semivoicedsound, GDK_bracketleft, 0xff9f, 0 },
  { IIIMF_KEYCODE_A, GDK_kana_CHI, GDK_a, 0xff81, 0 },
  { IIIMF_KEYCODE_S, GDK_kana_TO, GDK_s, 0xff84, 0 },
  { IIIMF_KEYCODE_D, GDK_kana_SHI, GDK_d, 0xff7c, 0 },
  { IIIMF_KEYCODE_F, GDK_kana_HA, GDK_f, 0xff8a, 0 },
  { IIIMF_KEYCODE_G, GDK_kana_KI, GDK_g, 0xff77, 0 },
  { IIIMF_KEYCODE_H, GDK_kana_KU, GDK_h, 0xff78, 0 },
  { IIIMF_KEYCODE_J, GDK_kana_MA, GDK_j, 0xff8f, 0 },
  { IIIMF_KEYCODE_K, GDK_kana_NO, GDK_k, 0xff89, 0 },
  { IIIMF_KEYCODE_L, GDK_kana_RI, GDK_l, 0xff98, 0 },
  { IIIMF_KEYCODE_SEMICOLON, GDK_kana_RE, GDK_semicolon, 0xff9a, 0 },
  { ':',				    GDK_kana_KE, GDK_colon, 0xff79, 0 },
  { IIIMF_KEYCODE_CLOSE_BRACKET, GDK_kana_MU, GDK_bracketright, 0xff91, 0 },
  { IIIMF_KEYCODE_Z, GDK_kana_TSU, GDK_z, 0xff82, 0 },
  { IIIMF_KEYCODE_X, GDK_kana_SA, GDK_x, 0xff7b, 0 },
  { IIIMF_KEYCODE_C, GDK_kana_SO, GDK_c, 0xff7f, 0 },
  { IIIMF_KEYCODE_V, GDK_kana_HI, GDK_v, 0xff8b, 0 },
  { IIIMF_KEYCODE_B, GDK_kana_KO, GDK_b, 0xff7a, 0 },
  { IIIMF_KEYCODE_N, GDK_kana_MI, GDK_n, 0xff90, 0 },
  { IIIMF_KEYCODE_M, GDK_kana_MO, GDK_m, 0xff93, 0 },
  { IIIMF_KEYCODE_COMMA, GDK_kana_NE, GDK_comma, 0xff88, 0 },
  { IIIMF_KEYCODE_PERIOD, GDK_kana_RU, GDK_period, 0xff99, 0},
  { IIIMF_KEYCODE_SLASH, GDK_kana_ME, GDK_slash, 0xff92, 0 },
  /* hack to japanese keyboard */
  /* backslash is duplicate for RO and prolongedsound */
  { IIIMF_KEYCODE_BACK_SLASH, GDK_kana_RO, GDK_underscore, 0xff9b, 0 },
  { IIIMF_KEYCODE_BACK_SLASH, GDK_prolongedsound, GDK_bar, 0xff70, 0 },
  { 0, 0, 0 }
};
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static KeymapEntry2 kana_shift_keymapTable[] = {
  { IIIMF_KEYCODE_3, GDK_kana_a, GDK_numbersign, 0xff67, 0 },
  { IIIMF_KEYCODE_4, GDK_kana_u, GDK_dollar, 0xff69, 0 },
  { IIIMF_KEYCODE_5, GDK_kana_e, GDK_percent, 0xff6a, 0 },
  { IIIMF_KEYCODE_6, GDK_kana_o, GDK_ampersand, 0xff6b, 0 },
  { IIIMF_KEYCODE_7, GDK_kana_ya, GDK_apostrophe, 0xff6c, 0 },
  { IIIMF_KEYCODE_8, GDK_kana_yu, GDK_parenleft, 0xff6d, 0 },
  { IIIMF_KEYCODE_9, GDK_kana_yo, GDK_parenright, 0xff6e, 0 },
  { IIIMF_KEYCODE_0, GDK_kana_WO, GDK_asciitilde, 0xff66, 0 },
  { IIIMF_KEYCODE_E, GDK_kana_i, GDK_E, 0xff68, 0 },
  { IIIMF_KEYCODE_OPEN_BRACKET, GDK_kana_openingbracket, GDK_braceleft, 0xff62, 0 },
  { IIIMF_KEYCODE_CLOSE_BRACKET, GDK_kana_closingbracket, GDK_braceright, 0xff63, 0 },
  { IIIMF_KEYCODE_Z, GDK_kana_tsu, GDK_Z, 0xff6f, 0 },
  /* GDK_less does not return correct keycode on VineLinux 1.1 */
  { IIIMF_KEYCODE_COMMA, GDK_kana_comma, GDK_comma, 0xff64, 0 },
  { IIIMF_KEYCODE_PERIOD, GDK_kana_fullstop, GDK_greater, 0xff61, 0 },
  { IIIMF_KEYCODE_SLASH, GDK_kana_conjunctive, GDK_question, 0xff65, 0 },
  { 0, 0, 0 }
};
#endif /* USE_KANA_TABLE */

enum IIIMF_MODIFIERS
{
  IIIMF_SHIFT_MODIFIER = 1,
  IIIMF_CONTROL_MODIFIER = 2,
  IIIMF_META_MODIFIER = 4,
  IIIMF_ALT_MODIFIER = 8,
  IIIMF_ALT_GRAPH_MODIFIER = 32
};

#if	USE_KANA_TABLE
static void
set_keymap_table(GdkDisplay *display)
{
  GdkKeymap *keymap;
  gint i;
  gboolean result;
  GdkKeymapKey *keys;
  gint n_keys;

#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2
  keymap = gdk_keymap_get_for_display (gdk_drawable_get_display (e->window));
#else
  keymap = gdk_keymap_get_default ();
#endif

  /* Get Keycodes for Kana keys */
  for (i = 0; kana_normal_keymapTable[i].iiimf_keycode != 0; i++)
    {
      result = gdk_keymap_get_entries_for_keyval
         (keymap, kana_normal_keymapTable[i].gdk_keysym, &keys, &n_keys);
      if ((result) && (n_keys))
        {
          kana_normal_keymapTable[i].hardware_keycode = keys->keycode;
          g_free (keys);
        }
      else
        {
          result = gdk_keymap_get_entries_for_keyval
             (keymap, kana_normal_keymapTable[i].gdk_alt_keysym, &keys, &n_keys);
          if ((result != FALSE) && (n_keys >= 1))
            {
              kana_normal_keymapTable[i].hardware_keycode = keys->keycode;
              g_free (keys);
            }
        }
    }
  for (i = 0; kana_shift_keymapTable[i].iiimf_keycode != 0; i++)
    {
      result = gdk_keymap_get_entries_for_keyval
         (keymap, kana_shift_keymapTable[i].gdk_keysym, &keys, &n_keys);
      if ((result) && (n_keys))
        {
          kana_shift_keymapTable[i].hardware_keycode = keys->keycode;
          g_free (keys);
        }
      else
        {
          result = gdk_keymap_get_entries_for_keyval
             (keymap, kana_shift_keymapTable[i].gdk_alt_keysym, &keys, &n_keys);
          if ((result != FALSE) && (n_keys >= 1))
            {
              kana_shift_keymapTable[i].hardware_keycode = keys->keycode;
              g_free (keys);
            }
        }
    }
}
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static int
ignore_error(Display *displayp, XErrorEvent *eventp)
{
  return 0;
}
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static gint
get_kana_flag (GdkEventKey *e)
{
  static int KanaMode = -1;
  int (*oldhandler)(Display *, XErrorEvent *) = NULL;
  Window kana_w;
  GdkDisplay *gdkdisplay;
  Display *xdisplay;
  Atom ret_type;
  gint ret_format;
  unsigned long nitems, bytes_left;
  unsigned long *tmp = 0;

  if (KanaMode == -2)
    return 0;

  if (!e->window)
    return -2;

  gdkdisplay = gdk_drawable_get_display (e->window);
  xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);

  if (KanaMode == -1)
    {
      if (!getenv("HTT_GENERATES_KANAKEY"))
        {
          KanaMode = -2;
          return 0;
        }

      KanaMode = 0;
      set_keymap_table(gdkdisplay);
    }

  if (!kanawin_atom)
    {
      kanawin_atom = XInternAtom(xdisplay, "HTT_KANA_WIN", False);
      kanaflag_atom = XInternAtom(xdisplay, "HTT_KANA_FLAG", False);
    }

  XSync(xdisplay, False);
  oldhandler = XSetErrorHandler(ignore_error);
 
  kana_w = XGetSelectionOwner(xdisplay, kanawin_atom);

  if (kana_w == None)
    {
      XSync(xdisplay, False);
      XSetErrorHandler(oldhandler);
      return 0;
    }

  XGetWindowProperty(xdisplay, kana_w,
                     kanaflag_atom, 0, 4, False, XA_WINDOW,
                     &ret_type, &ret_format,
                     &nitems, &bytes_left, (unsigned char **) &tmp);

  XSync(xdisplay, False);
  XSetErrorHandler(oldhandler);

  if ((tmp != NULL) && (ret_type == XA_WINDOW) && ((*tmp == 0) || (*tmp == 1)))
    KanaMode = *tmp;
  if (tmp)
    free((char*)tmp);

  return KanaMode;
}
#endif /* USE_KANA_TABLE */

#if	USE_KANA_TABLE
static void
toggle_kana_flag (GdkEventKey *e)
{
  int (*oldhandler)(Display *, XErrorEvent *) = NULL;
  int kanamode;
  Window kana_w;
  GdkDisplay *gdkdisplay;
  Display *xdisplay;

  kanamode = get_kana_flag (e);
  if (kanamode < 0)
    return;

  if (kanamode == 0)
    kanamode = 1;
  else
    kanamode = 0;

  gdkdisplay = gdk_drawable_get_display (e->window);
  xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);

  XSync(xdisplay, False);
  oldhandler = XSetErrorHandler(ignore_error);

  kana_w = XGetSelectionOwner(xdisplay, kanawin_atom);

  if (kana_w != None)
    {
      XChangeProperty(xdisplay, kana_w, kanaflag_atom, XA_WINDOW, 32,
                      PropModeReplace,
                      (unsigned char*) &kanamode,
                      sizeof(kanamode));
    }

  XSync(xdisplay, False);
  XSetErrorHandler(oldhandler);
}
#endif /* USE_KANA_TABLE */

static int
g2icode (guint kv)
{
  switch (kv)
    {
    case GDK_VoidSymbol:
      return 0;
    case GDK_BackSpace:
      return IIIMF_KEYCODE_BACK_SPACE;
    case GDK_Tab:
      return IIIMF_KEYCODE_TAB;
    case GDK_Linefeed:
      return IIIMF_KEYCODE_ENTER;
    case GDK_Clear:
      return -IIIMF_KEYCODE_CLEAR;
    case GDK_Return:
      return IIIMF_KEYCODE_ENTER;
    case GDK_Pause:
      return IIIMF_KEYCODE_PAUSE;
    case GDK_Scroll_Lock:
      return -IIIMF_KEYCODE_SCROLL_LOCK;
    case GDK_Sys_Req:
      return 0;
    case GDK_Escape:
      return IIIMF_KEYCODE_ESCAPE;
    case GDK_Delete:
      return IIIMF_KEYCODE_DELETE;
    case GDK_Multi_key:
      return IIIMF_KEYCODE_COMPOSE;
    case GDK_Codeinput:
      return -IIIMF_KEYCODE_CODE_INPUT;
    case GDK_SingleCandidate:
    case GDK_MultipleCandidate:
      return 0;
    case GDK_PreviousCandidate:
      return -IIIMF_KEYCODE_PREVIOUS_CANDIDATE;
    case GDK_Kanji:
      return -IIIMF_KEYCODE_KANJI;
    case GDK_Muhenkan:
      return -IIIMF_KEYCODE_NONCONVERT;
    case GDK_Henkan_Mode:
      /* case GDK_Henkan: */
      return -IIIMF_KEYCODE_CONVERT;
    case GDK_Romaji:
      return -IIIMF_KEYCODE_ROMAN_CHARACTERS;
    case GDK_Hiragana:
      return -IIIMF_KEYCODE_HIRAGANA;
    case GDK_Katakana:
      return -IIIMF_KEYCODE_KATAKANA;
    case GDK_Hiragana_Katakana:
      return 0;
    case GDK_Zenkaku:
      return -IIIMF_KEYCODE_FULL_WIDTH;
    case GDK_Hankaku:
      return -IIIMF_KEYCODE_HALF_WIDTH;
    case GDK_Kana_Lock:
      return -IIIMF_KEYCODE_KANA_LOCK;
    case GDK_Home:
      return -IIIMF_KEYCODE_HOME;
    case GDK_Left:
      return -IIIMF_KEYCODE_LEFT;
    case GDK_Up:
      return -IIIMF_KEYCODE_UP;
    case GDK_Right:
      return -IIIMF_KEYCODE_RIGHT;
    case GDK_Down:
      return -IIIMF_KEYCODE_DOWN;
    case GDK_Page_Up:
      return -IIIMF_KEYCODE_PAGE_UP;
    case GDK_Page_Down:
      return -IIIMF_KEYCODE_PAGE_DOWN;
    case GDK_End:
      return -IIIMF_KEYCODE_END;
    case GDK_Print:
      return -IIIMF_KEYCODE_PRINTSCREEN;
    case GDK_Insert:
      return IIIMF_KEYCODE_INSERT;
    case GDK_Undo:
      return -IIIMF_KEYCODE_UNDO;
    case GDK_Find:
      return -IIIMF_KEYCODE_FIND;
    case GDK_Cancel:
      return -IIIMF_KEYCODE_CANCEL;
    case GDK_Help:
      return -IIIMF_KEYCODE_HELP;
    case GDK_Mode_switch:
      /* case GDK_script_switch: */
      return -IIIMF_KEYCODE_MODECHANGE;
    case GDK_Num_Lock:
      return -IIIMF_KEYCODE_NUM_LOCK;
    case GDK_KP_Space:
      return IIIMF_KEYCODE_SPACE;
    case GDK_KP_Tab:
      return IIIMF_KEYCODE_TAB;
    case GDK_KP_Enter:
      return IIIMF_KEYCODE_ENTER;
    case GDK_KP_F1:
      return -IIIMF_KEYCODE_F1;
    case GDK_KP_F2:
      return -IIIMF_KEYCODE_F2;
    case GDK_KP_F3:
      return -IIIMF_KEYCODE_F3;
    case GDK_KP_F4:
      return -IIIMF_KEYCODE_F4;
    case GDK_KP_Home:
      return -IIIMF_KEYCODE_HOME;
    case GDK_KP_Left:
      return -IIIMF_KEYCODE_LEFT;
    case GDK_KP_Up:
      return -IIIMF_KEYCODE_UP;
    case GDK_KP_Right:
      return -IIIMF_KEYCODE_RIGHT;
    case GDK_KP_Down:
      return -IIIMF_KEYCODE_DOWN;
    case GDK_KP_Page_Up:
      return -IIIMF_KEYCODE_PAGE_UP;
    case GDK_KP_Page_Down:
      return -IIIMF_KEYCODE_PAGE_DOWN;
    case GDK_KP_End:
      return -IIIMF_KEYCODE_END;
    case GDK_KP_Insert:
      return IIIMF_KEYCODE_INSERT;
    case GDK_KP_Delete:
      return IIIMF_KEYCODE_DELETE;
    case GDK_KP_Equal:
      return IIIMF_KEYCODE_EQUALS;
    case GDK_KP_Multiply:
      return IIIMF_KEYCODE_MULTIPLY;
    case GDK_KP_Add:
      return IIIMF_KEYCODE_ADD;
    case GDK_KP_Separator:
      return IIIMF_KEYCODE_SEPARATOR;
    case GDK_KP_Subtract:
      return IIIMF_KEYCODE_SUBTRACT;
    case GDK_KP_Decimal:
      return IIIMF_KEYCODE_DECIMAL;
    case GDK_KP_Divide:
      return IIIMF_KEYCODE_DIVIDE;
    case GDK_KP_0:
      return IIIMF_KEYCODE_NUMPAD0;
    case GDK_KP_1:
      return IIIMF_KEYCODE_NUMPAD1;
    case GDK_KP_2:
      return IIIMF_KEYCODE_NUMPAD2;
    case GDK_KP_3:
      return IIIMF_KEYCODE_NUMPAD3;
    case GDK_KP_4:
      return IIIMF_KEYCODE_NUMPAD4;
    case GDK_KP_5:
      return IIIMF_KEYCODE_NUMPAD5;
    case GDK_KP_6:
      return IIIMF_KEYCODE_NUMPAD6;
    case GDK_KP_7:
      return IIIMF_KEYCODE_NUMPAD7;
    case GDK_KP_8:
      return IIIMF_KEYCODE_NUMPAD8;
    case GDK_KP_9:
      return IIIMF_KEYCODE_NUMPAD9;
    case GDK_F1:
      return -IIIMF_KEYCODE_F1;
    case GDK_F2:
      return -IIIMF_KEYCODE_F2;
    case GDK_F3:
      return -IIIMF_KEYCODE_F3;
    case GDK_F4:
      return -IIIMF_KEYCODE_F4;
    case GDK_F5:
      return -IIIMF_KEYCODE_F5;
    case GDK_F6:
      return -IIIMF_KEYCODE_F6;
    case GDK_F7:
      return -IIIMF_KEYCODE_F7;
    case GDK_F8:
      return -IIIMF_KEYCODE_F8;
    case GDK_F9:
      return -IIIMF_KEYCODE_F9;
    case GDK_F10:
      return -IIIMF_KEYCODE_F10;
    case GDK_F11:
      /*case GDK_L1: */
      return -IIIMF_KEYCODE_F11;
    case GDK_F12:
      /* case GDK_L2: */
      return -IIIMF_KEYCODE_F12;
    case GDK_F13:
      /* case GDK_L3: */
      return -IIIMF_KEYCODE_F13;
    case GDK_F14:
      /* case GDK_L4: */
      return -IIIMF_KEYCODE_F14;
    case GDK_F15:
      /* case GDK_L5: */
      return -IIIMF_KEYCODE_F15;
    case GDK_F16:
      /* case GDK_L6: */
      return -IIIMF_KEYCODE_F16;
    case GDK_F17:
      /* case GDK_L7: */
      return -IIIMF_KEYCODE_F17;
    case GDK_F18:
      /* case GDK_L8: */
      return -IIIMF_KEYCODE_F18;
    case GDK_F19:
      /* case GDK_L9: */
      return -IIIMF_KEYCODE_F19;
    case GDK_F20:
      /* case GDK_L10: */
      return -IIIMF_KEYCODE_F20;
    case GDK_F21:
      /* case GDK_R1: */
      return -IIIMF_KEYCODE_F21;
    case GDK_F22:
      /* case GDK_R2: */
      return -IIIMF_KEYCODE_F22;
    case GDK_F23:
      /* case GDK_R3: */
      return -IIIMF_KEYCODE_F23;
    case GDK_F24:
      /* case GDK_R4: */
      return -IIIMF_KEYCODE_F24;
    case GDK_Shift_L:
    case GDK_Shift_R:
      return -IIIMF_KEYCODE_SHIFT;
    case GDK_Control_L:
    case GDK_Control_R:
      return -IIIMF_KEYCODE_CONTROL;
    case GDK_Caps_Lock:
      return -IIIMF_KEYCODE_CAPS_LOCK;
    case GDK_Meta_L:
    case GDK_Meta_R:
      return -IIIMF_KEYCODE_META;
    case GDK_Alt_L:
    case GDK_Alt_R:
      return -IIIMF_KEYCODE_ALT;
    case GDK_dead_grave:
      return IIIMF_KEYCODE_DEAD_GRAVE;
    case GDK_dead_acute:
      return IIIMF_KEYCODE_DEAD_ACUTE;
    case GDK_dead_circumflex:
      return IIIMF_KEYCODE_DEAD_CIRCUMFLEX;
    case GDK_dead_tilde:
      return IIIMF_KEYCODE_DEAD_TILDE;
    case GDK_dead_macron:
      return IIIMF_KEYCODE_DEAD_MACRON;
    case GDK_dead_breve:
      return IIIMF_KEYCODE_DEAD_BREVE;
    case GDK_dead_abovedot:
      return IIIMF_KEYCODE_DEAD_ABOVEDOT;
    case GDK_dead_diaeresis:
      return IIIMF_KEYCODE_DEAD_DIAERESIS;
    case GDK_dead_abovering:
      return IIIMF_KEYCODE_DEAD_ABOVERING;
    case GDK_dead_doubleacute:
      return IIIMF_KEYCODE_DEAD_DOUBLEACUTE;
    case GDK_dead_caron:
      return IIIMF_KEYCODE_DEAD_CARON;
    case GDK_dead_cedilla:
      return IIIMF_KEYCODE_DEAD_CEDILLA;
    case GDK_dead_ogonek:
      return IIIMF_KEYCODE_DEAD_OGONEK;
    case GDK_dead_iota:
      return IIIMF_KEYCODE_DEAD_IOTA;
    case GDK_dead_voiced_sound:
      return IIIMF_KEYCODE_DEAD_VOICED_SOUND;
    case GDK_dead_semivoiced_sound:
      return IIIMF_KEYCODE_DEAD_SEMIVOICED_SOUND;

    case GDK_space:
      return IIIMF_KEYCODE_SPACE;
    case GDK_exclam:
      return IIIMF_KEYCODE_EXCLAMATION_MARK;
    case GDK_quotedbl:
      return IIIMF_KEYCODE_QUOTEDBL;
    case GDK_numbersign:
      return IIIMF_KEYCODE_NUMBER_SIGN;
    case GDK_dollar:
      return IIIMF_KEYCODE_DOLLAR;
    case GDK_ampersand:
      return IIIMF_KEYCODE_AMPERSAND;
    case GDK_apostrophe:
      /* case GDK_quoteright: */
      return IIIMF_KEYCODE_QUOTE;
    case GDK_parenleft:
      return IIIMF_KEYCODE_LEFT_PARENTHESIS;
    case GDK_parenright:
      return IIIMF_KEYCODE_RIGHT_PARENTHESIS;
    case GDK_asterisk:
      return IIIMF_KEYCODE_ASTERISK;
    case GDK_plus:
      return IIIMF_KEYCODE_PLUS;
    case GDK_comma:
      return IIIMF_KEYCODE_COMMA;
    case GDK_minus:
      return IIIMF_KEYCODE_MINUS;
    case GDK_period:
      return IIIMF_KEYCODE_PERIOD;
    case GDK_slash:
      return IIIMF_KEYCODE_SLASH;
    case GDK_0:
      return IIIMF_KEYCODE_0;
    case GDK_1:
      return IIIMF_KEYCODE_1;
    case GDK_2:
      return IIIMF_KEYCODE_2;
    case GDK_3:
      return IIIMF_KEYCODE_3;
    case GDK_4:
      return IIIMF_KEYCODE_4;
    case GDK_5:
      return IIIMF_KEYCODE_5;
    case GDK_6:
      return IIIMF_KEYCODE_6;
    case GDK_7:
      return IIIMF_KEYCODE_7;
    case GDK_8:
      return IIIMF_KEYCODE_8;
    case GDK_9:
      return IIIMF_KEYCODE_9;
    case GDK_colon:
      return IIIMF_KEYCODE_COLON;
    case GDK_semicolon:
      return IIIMF_KEYCODE_SEMICOLON;
    case GDK_less:
      return IIIMF_KEYCODE_LESS;
    case GDK_equal:
      return IIIMF_KEYCODE_EQUALS;
    case GDK_greater:
      return IIIMF_KEYCODE_GREATER;
    case GDK_at:
      return IIIMF_KEYCODE_AT;
    case GDK_A:
      return IIIMF_KEYCODE_A;
    case GDK_B:
      return IIIMF_KEYCODE_B;
    case GDK_C:
      return IIIMF_KEYCODE_C;
    case GDK_D:
      return IIIMF_KEYCODE_D;
    case GDK_E:
      return IIIMF_KEYCODE_E;
    case GDK_F:
      return IIIMF_KEYCODE_F;
    case GDK_G:
      return IIIMF_KEYCODE_G;
    case GDK_H:
      return IIIMF_KEYCODE_H;
    case GDK_I:
      return IIIMF_KEYCODE_I;
    case GDK_J:
      return IIIMF_KEYCODE_J;
    case GDK_K:
      return IIIMF_KEYCODE_K;
    case GDK_L:
      return IIIMF_KEYCODE_L;
    case GDK_M:
      return IIIMF_KEYCODE_M;
    case GDK_N:
      return IIIMF_KEYCODE_N;
    case GDK_O:
      return IIIMF_KEYCODE_O;
    case GDK_P:
      return IIIMF_KEYCODE_P;
    case GDK_Q:
      return IIIMF_KEYCODE_Q;
    case GDK_R:
      return IIIMF_KEYCODE_R;
    case GDK_S:
      return IIIMF_KEYCODE_S;
    case GDK_T:
      return IIIMF_KEYCODE_T;
    case GDK_U:
      return IIIMF_KEYCODE_U;
    case GDK_V:
      return IIIMF_KEYCODE_V;
    case GDK_W:
      return IIIMF_KEYCODE_W;
    case GDK_X:
      return IIIMF_KEYCODE_X;
    case GDK_Y:
      return IIIMF_KEYCODE_Y;
    case GDK_Z:
      return IIIMF_KEYCODE_Z;

    case GDK_bracketleft:
      return IIIMF_KEYCODE_OPEN_BRACKET;
    case GDK_backslash:
      return IIIMF_KEYCODE_BACK_SLASH;
    case GDK_bracketright:
      return IIIMF_KEYCODE_CLOSE_BRACKET;
    case GDK_asciicircum:
      return IIIMF_KEYCODE_CIRCUMFLEX;
    case GDK_underscore:
      return IIIMF_KEYCODE_UNDERSCORE;
    case GDK_grave:
      /* case GDK_quoteleft: */
      return IIIMF_KEYCODE_BACK_QUOTE;

    case GDK_a:
      return IIIMF_KEYCODE_A;
    case GDK_b:
      return IIIMF_KEYCODE_B;
    case GDK_c:
      return IIIMF_KEYCODE_C;
    case GDK_d:
      return IIIMF_KEYCODE_D;
    case GDK_e:
      return IIIMF_KEYCODE_E;
    case GDK_f:
      return IIIMF_KEYCODE_F;
    case GDK_g:
      return IIIMF_KEYCODE_G;
    case GDK_h:
      return IIIMF_KEYCODE_H;
    case GDK_i:
      return IIIMF_KEYCODE_I;
    case GDK_j:
      return IIIMF_KEYCODE_J;
    case GDK_k:
      return IIIMF_KEYCODE_K;
    case GDK_l:
      return IIIMF_KEYCODE_L;
    case GDK_m:
      return IIIMF_KEYCODE_M;
    case GDK_n:
      return IIIMF_KEYCODE_N;
    case GDK_o:
      return IIIMF_KEYCODE_O;
    case GDK_p:
      return IIIMF_KEYCODE_P;
    case GDK_q:
      return IIIMF_KEYCODE_Q;
    case GDK_r:
      return IIIMF_KEYCODE_R;
    case GDK_s:
      return IIIMF_KEYCODE_S;
    case GDK_t:
      return IIIMF_KEYCODE_T;
    case GDK_u:
      return IIIMF_KEYCODE_U;
    case GDK_v:
      return IIIMF_KEYCODE_V;
    case GDK_w:
      return IIIMF_KEYCODE_W;
    case GDK_x:
      return IIIMF_KEYCODE_X;
    case GDK_y:
      return IIIMF_KEYCODE_Y;
    case GDK_z:
      return IIIMF_KEYCODE_Z;
    case GDK_braceleft:
      return IIIMF_KEYCODE_BRACELEFT;
    case GDK_braceright:
      return IIIMF_KEYCODE_BRACERIGHT;

    case GDK_exclamdown:
      return IIIMF_KEYCODE_INVERTED_EXCLAMATION_MARK;

    case GDK_EuroSign:
      return IIIMF_KEYCODE_EURO_SIGN;

    case GDK_Zenkaku_Hankaku:
      return IIIMF_KEYCODE_KANJI;

    default:
      return 0;
    }

  return 0;
}

static int
modifier (guint st)
{
  int mod = 0;

  if (st & GDK_SHIFT_MASK)
    mod |= IIIMF_SHIFT_MODIFIER;
  if (st & GDK_CONTROL_MASK)
    mod |= IIIMF_CONTROL_MODIFIER;
  if (st & GDK_MOD1_MASK)
    mod |= IIIMF_ALT_MODIFIER;
  if (st & GDK_MOD3_MASK)
    mod |= IIIMF_ALT_GRAPH_MODIFIER;

  return mod;
}

IIIMF_status
convert_GdkEventKey_to_IIIMCF_keyevent (GdkEventKey * e,
					IIIMCF_keyevent * pkev)
{
  int c;
  guint keyval;

#if	USE_KANA_TABLE
  gint kanaflag;
  gint i;

  kanaflag = get_kana_flag(e);
  if (kanaflag >= 0)
    {
      if (e->keyval == GDK_Hiragana_Katakana)
        toggle_kana_flag(e);
    }

  if (kanaflag == 1)
    {
      if (e->state & GDK_SHIFT_MASK)
        {
          /* check kana_shift_keymapTable first is ShiftMask */
          for (i = 0; kana_shift_keymapTable[i].iiimf_keycode != 0; i++)
            {
              if (kana_shift_keymapTable[i].hardware_keycode == e->hardware_keycode)
                {
                  pkev->keycode = kana_shift_keymapTable[i].iiimf_keycode;
                  pkev->keychar = kana_shift_keymapTable[i].iiimf_keychar;
                  if (pkev->keycode)
                    {
                      pkev->modifier = modifier (e->state);
                      pkev->time_stamp = e->time;
                      return IIIMF_STATUS_SUCCESS;
                    }
                  break;
                }
            }
        }

      for (i = 0; kana_normal_keymapTable[i].iiimf_keycode != 0; i++)
        {
          if (kana_normal_keymapTable[i].hardware_keycode == e->hardware_keycode)
            {
              pkev->keycode = kana_normal_keymapTable[i].iiimf_keycode;
              pkev->keychar = kana_normal_keymapTable[i].iiimf_keychar;
              if (pkev->keycode)
                {
                  pkev->modifier = modifier (e->state);
                  pkev->time_stamp = e->time;
                  return IIIMF_STATUS_SUCCESS;
                }
              break;
            }
        }

      for (i = 0; kana_shift_keymapTable[i].iiimf_keycode != 0; i++)
        {
          if (kana_shift_keymapTable[i].hardware_keycode == e->hardware_keycode)
            {
              pkev->keycode = kana_shift_keymapTable[i].iiimf_keycode;
              pkev->keychar = kana_shift_keymapTable[i].iiimf_keychar;
              if (pkev->keycode)
                {
                  pkev->modifier = modifier (e->state);
                  pkev->time_stamp = e->time;
                  return IIIMF_STATUS_SUCCESS;
                }
              break;
            }
        }
    }
  else
    {
      for (i = 0; kana_normal_keymapTable[i].iiimf_keycode != 0; i++)
        {
          if (kana_normal_keymapTable[i].gdk_keysym == e->keyval)
            {
              pkev->keycode = kana_normal_keymapTable[i].iiimf_keycode;
              pkev->keychar = kana_normal_keymapTable[i].iiimf_keychar;
              if (pkev->keycode)
                {
                  pkev->modifier = modifier (e->state);
                  pkev->time_stamp = e->time;
                  return IIIMF_STATUS_SUCCESS;
                }
              break;
            }
        }

      for (i = 0; kana_shift_keymapTable[i].iiimf_keycode != 0; i++)
        {
          if (kana_shift_keymapTable[i].gdk_keysym == e->keyval)
            {
              pkev->keycode = kana_normal_keymapTable[i].iiimf_keycode;
              pkev->keychar = kana_normal_keymapTable[i].iiimf_keychar;
              if (pkev->keycode)
                {
                  pkev->modifier = modifier (e->state);
                  pkev->time_stamp = e->time;
                  return IIIMF_STATUS_SUCCESS;
                }
              break;
            }
        }
    }
#endif /* USE_KANA_TABLE */

  /* first, try to get keycode from KeySym */
  c = g2icode (e->keyval);
  if (c == 0)
    {
      GdkKeymap *keymap;
#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2
      keymap =
	gdk_keymap_get_for_display (gdk_drawable_get_display (e->window));
#else
      keymap = gdk_keymap_get_default ();
#endif
      /* 
       * Cannot get IIIMF keycode from keysym.
       * So, we genarate base keysym by ignoring mod mask from hardware keycode.
       */
      if (!gdk_keymap_translate_keyboard_state (keymap, e->hardware_keycode,
						0, 0, &keyval, NULL, NULL,
						NULL))
	return IIIMF_STATUS_FAIL;


      /* retry */
      c = g2icode (keyval);

      if (c == 0)
	return IIIMF_STATUS_FAIL;
    }
  if (c < 0)
    {
      pkev->keychar = 0;
      pkev->keycode = -c;
    }
  else
    {
      pkev->keychar = gdk_keyval_to_unicode (e->keyval);
      pkev->keycode = c;
    }
  pkev->modifier = modifier (e->state);

  pkev->time_stamp = e->time;

  return IIIMF_STATUS_SUCCESS;
}

static guint
i2gmodifier (int st)
{
  int mod = 0;
  if (st & IIIMF_SHIFT_MODIFIER)
    mod |= GDK_SHIFT_MASK;
  if (st & IIIMF_CONTROL_MODIFIER)
    mod |= GDK_CONTROL_MASK;
  if (st & IIIMF_ALT_MODIFIER)
    mod |= GDK_MOD1_MASK;

  return mod;
}

static guint
i2gcode (int kv, int kc)
{
  switch (kv)
    {

      /* case IIIMF_KEYCODE_UNDEFINED */
    case IIIMF_KEYCODE_CANCEL:
      return GDK_Cancel;
    case IIIMF_KEYCODE_BACK_SPACE:
      return GDK_BackSpace;
    case IIIMF_KEYCODE_TAB:
      return GDK_Tab;
    case IIIMF_KEYCODE_ENTER:
      return GDK_Return;
    case IIIMF_KEYCODE_CLEAR:
      return GDK_Clear;
    case IIIMF_KEYCODE_SHIFT:
      return GDK_Shift_L;	/* ... */
    case IIIMF_KEYCODE_CONTROL:
      return GDK_Control_L;	/* ... */
    case IIIMF_KEYCODE_ALT:
      return GDK_Alt_L;
    case IIIMF_KEYCODE_PAUSE:
      return GDK_Pause;
    case IIIMF_KEYCODE_CAPS_LOCK:
      return GDK_Caps_Lock;
      /*
         case IIIMF_KEYCODE_KANA
         case IIIMF_KEYCODE_FINAL
       */
    case IIIMF_KEYCODE_KANJI:
      return GDK_Kanji;

    case IIIMF_KEYCODE_ESCAPE:
      return GDK_Escape;
    case IIIMF_KEYCODE_CONVERT:
      return GDK_Henkan_Mode;
    case IIIMF_KEYCODE_NONCONVERT:
      return GDK_Muhenkan;
      /* case IIIMF_KEYCODE_ACCEPT */
    case IIIMF_KEYCODE_MODECHANGE:
      return GDK_Mode_switch;
    case IIIMF_KEYCODE_SPACE:
      return GDK_space;
    case IIIMF_KEYCODE_PAGE_UP:
      return GDK_Page_Up;
    case IIIMF_KEYCODE_PAGE_DOWN:
      return GDK_Page_Down;
    case IIIMF_KEYCODE_END:
      return GDK_End;
    case IIIMF_KEYCODE_HOME:
      return GDK_Home;
    case IIIMF_KEYCODE_LEFT:
      return GDK_Left;
    case IIIMF_KEYCODE_UP:
      return GDK_Up;
    case IIIMF_KEYCODE_RIGHT:
      return GDK_Right;
    case IIIMF_KEYCODE_DOWN:
      return GDK_Down;
    case IIIMF_KEYCODE_COMMA:
      return GDK_comma;
    case IIIMF_KEYCODE_MINUS:
      return GDK_minus;
    case IIIMF_KEYCODE_PERIOD:
      return GDK_period;
    case IIIMF_KEYCODE_SLASH:
      return GDK_slash;
    case IIIMF_KEYCODE_0:
      return GDK_0;
    case IIIMF_KEYCODE_1:
      return GDK_1;
    case IIIMF_KEYCODE_2:
      return GDK_2;
    case IIIMF_KEYCODE_3:
      return GDK_3;
    case IIIMF_KEYCODE_4:
      return GDK_4;
    case IIIMF_KEYCODE_5:
      return GDK_5;
    case IIIMF_KEYCODE_6:
      return GDK_6;
    case IIIMF_KEYCODE_7:
      return GDK_7;
    case IIIMF_KEYCODE_8:
      return GDK_8;
    case IIIMF_KEYCODE_9:
      return GDK_9;
    case IIIMF_KEYCODE_SEMICOLON:
      return GDK_semicolon;
    case IIIMF_KEYCODE_EQUALS:
      return GDK_equal;
    case IIIMF_KEYCODE_A:
      return GDK_a;
    case IIIMF_KEYCODE_B:
      return GDK_b;
    case IIIMF_KEYCODE_C:
      return GDK_c;
    case IIIMF_KEYCODE_D:
      return GDK_d;
    case IIIMF_KEYCODE_E:
      return GDK_e;
    case IIIMF_KEYCODE_F:
      return GDK_f;
    case IIIMF_KEYCODE_G:
      return GDK_g;
    case IIIMF_KEYCODE_H:
      return GDK_h;
    case IIIMF_KEYCODE_I:
      return GDK_i;
    case IIIMF_KEYCODE_J:
      return GDK_j;
    case IIIMF_KEYCODE_K:
      return GDK_k;
    case IIIMF_KEYCODE_L:
      return GDK_l;
    case IIIMF_KEYCODE_M:
      return GDK_m;
    case IIIMF_KEYCODE_N:
      return GDK_n;
    case IIIMF_KEYCODE_O:
      return GDK_o;
    case IIIMF_KEYCODE_P:
      return GDK_p;
    case IIIMF_KEYCODE_Q:
      return GDK_q;
    case IIIMF_KEYCODE_R:
      return GDK_r;
    case IIIMF_KEYCODE_S:
      return GDK_s;
    case IIIMF_KEYCODE_T:
      return GDK_t;
    case IIIMF_KEYCODE_U:
      return GDK_u;
    case IIIMF_KEYCODE_V:
      return GDK_v;
    case IIIMF_KEYCODE_W:
      return GDK_w;
    case IIIMF_KEYCODE_X:
      return GDK_x;
    case IIIMF_KEYCODE_Y:
      return GDK_y;
    case IIIMF_KEYCODE_Z:
      return GDK_z;
    case IIIMF_KEYCODE_OPEN_BRACKET:
      return GDK_bracketleft;
    case IIIMF_KEYCODE_BACK_SLASH:
      return GDK_backslash;
    case IIIMF_KEYCODE_CLOSE_BRACKET:
      return GDK_bracketright;
    case IIIMF_KEYCODE_NUMPAD0:
      return GDK_KP_0;
    case IIIMF_KEYCODE_NUMPAD1:
      return GDK_KP_1;
    case IIIMF_KEYCODE_NUMPAD2:
      return GDK_KP_2;
    case IIIMF_KEYCODE_NUMPAD3:
      return GDK_KP_3;
    case IIIMF_KEYCODE_NUMPAD4:
      return GDK_KP_4;
    case IIIMF_KEYCODE_NUMPAD5:
      return GDK_KP_5;
    case IIIMF_KEYCODE_NUMPAD6:
      return GDK_KP_6;
    case IIIMF_KEYCODE_NUMPAD7:
      return GDK_KP_7;
    case IIIMF_KEYCODE_NUMPAD8:
      return GDK_KP_8;
    case IIIMF_KEYCODE_NUMPAD9:
      return GDK_KP_9;
    case IIIMF_KEYCODE_MULTIPLY:
      return GDK_KP_Multiply;
    case IIIMF_KEYCODE_ADD:
      return GDK_KP_Add;
    case IIIMF_KEYCODE_SEPARATOR:
      return GDK_KP_Separator;
    case IIIMF_KEYCODE_SUBTRACT:
      return GDK_KP_Subtract;
    case IIIMF_KEYCODE_DECIMAL:
      return GDK_KP_Decimal;
    case IIIMF_KEYCODE_DIVIDE:
      return GDK_KP_Divide;
    case IIIMF_KEYCODE_F1:
      return GDK_F1;
    case IIIMF_KEYCODE_F2:
      return GDK_F2;
    case IIIMF_KEYCODE_F3:
      return GDK_F3;
    case IIIMF_KEYCODE_F4:
      return GDK_F4;
    case IIIMF_KEYCODE_F5:
      return GDK_F5;
    case IIIMF_KEYCODE_F6:
      return GDK_F6;
    case IIIMF_KEYCODE_F7:
      return GDK_F7;
    case IIIMF_KEYCODE_F8:
      return GDK_F8;
    case IIIMF_KEYCODE_F9:
      return GDK_F9;
    case IIIMF_KEYCODE_F10:
      return GDK_F10;
    case IIIMF_KEYCODE_F11:
      return GDK_F11;
    case IIIMF_KEYCODE_F12:
      return GDK_F12;
    case IIIMF_KEYCODE_DELETE:
      return GDK_Delete;
    case IIIMF_KEYCODE_DEAD_GRAVE:
      return GDK_dead_grave;
    case IIIMF_KEYCODE_DEAD_ACUTE:
      return GDK_dead_acute;
    case IIIMF_KEYCODE_DEAD_CIRCUMFLEX:
      return GDK_dead_circumflex;
    case IIIMF_KEYCODE_DEAD_TILDE:
      return GDK_dead_tilde;
    case IIIMF_KEYCODE_DEAD_MACRON:
      return GDK_dead_macron;
    case IIIMF_KEYCODE_DEAD_BREVE:
      return GDK_dead_breve;
    case IIIMF_KEYCODE_DEAD_ABOVEDOT:
      return GDK_dead_abovedot;
    case IIIMF_KEYCODE_DEAD_DIAERESIS:
      return GDK_dead_diaeresis;
    case IIIMF_KEYCODE_DEAD_ABOVERING:
      return GDK_dead_abovering;
    case IIIMF_KEYCODE_DEAD_DOUBLEACUTE:
      return GDK_dead_doubleacute;
    case IIIMF_KEYCODE_DEAD_CARON:
      return GDK_dead_caron;
    case IIIMF_KEYCODE_DEAD_CEDILLA:
      return GDK_dead_cedilla;
    case IIIMF_KEYCODE_DEAD_OGONEK:
      return GDK_dead_ogonek;
    case IIIMF_KEYCODE_DEAD_IOTA:
      return GDK_dead_iota;
    case IIIMF_KEYCODE_DEAD_VOICED_SOUND:
      return GDK_dead_voiced_sound;
    case IIIMF_KEYCODE_DEAD_SEMIVOICED_SOUND:
      return GDK_dead_semivoiced_sound;
    case IIIMF_KEYCODE_NUM_LOCK:
      return GDK_Num_Lock;
    case IIIMF_KEYCODE_SCROLL_LOCK:
      return GDK_Scroll_Lock;
    case IIIMF_KEYCODE_AMPERSAND:
      return GDK_ampersand;
    case IIIMF_KEYCODE_ASTERISK:
      return GDK_asterisk;
    case IIIMF_KEYCODE_QUOTEDBL:
      return GDK_quotedbl;
    case IIIMF_KEYCODE_LESS:
      return GDK_less;
    case IIIMF_KEYCODE_PRINTSCREEN:
      return GDK_Print;
    case IIIMF_KEYCODE_INSERT:
      return GDK_Insert;
    case IIIMF_KEYCODE_HELP:
      return GDK_Help;
    case IIIMF_KEYCODE_META:
      return GDK_Meta_L;
    case IIIMF_KEYCODE_GREATER:
      return GDK_greater;
    case IIIMF_KEYCODE_BRACELEFT:
      return GDK_braceleft;
    case IIIMF_KEYCODE_BRACERIGHT:
      return GDK_braceright;
    case IIIMF_KEYCODE_BACK_QUOTE:
      return GDK_grave;
    case IIIMF_KEYCODE_QUOTE:
      return GDK_apostrophe;
    case IIIMF_KEYCODE_KP_UP:
      return GDK_KP_Up;
    case IIIMF_KEYCODE_KP_DOWN:
      return GDK_KP_Down;
    case IIIMF_KEYCODE_KP_LEFT:
      return GDK_KP_Left;
    case IIIMF_KEYCODE_KP_RIGHT:
      return GDK_KP_Right;
      /* case IIIMF_KEYCODE_ALPHANUMERIC */
    case IIIMF_KEYCODE_KATAKANA:
      return GDK_Katakana;
    case IIIMF_KEYCODE_HIRAGANA:
      return GDK_Hiragana;
    case IIIMF_KEYCODE_FULL_WIDTH:
      return GDK_Zenkaku;
    case IIIMF_KEYCODE_HALF_WIDTH:
      return GDK_Hankaku;
    case IIIMF_KEYCODE_ROMAN_CHARACTERS:
      return GDK_Romaji;
      /* case IIIMF_KEYCODE_ALL_CANDIDATES */
    case IIIMF_KEYCODE_PREVIOUS_CANDIDATE:
      return GDK_PreviousCandidate;
    case IIIMF_KEYCODE_CODE_INPUT:
      return GDK_Codeinput;
    case IIIMF_KEYCODE_JAPANESE_KATAKANA:
      return GDK_Katakana;
    case IIIMF_KEYCODE_JAPANESE_HIRAGANA:
      return GDK_Hiragana;
/*	case IIIMF_KEYCODE_JAPANESE_ROMAN */
    case IIIMF_KEYCODE_KANA_LOCK:
      return GDK_Kana_Lock;
      /* case IIIMF_KEYCODE_INPUT_METHOD_ON_OFF */
    case IIIMF_KEYCODE_AT:
      return GDK_at;
    case IIIMF_KEYCODE_COLON:
      return GDK_colon;
    case IIIMF_KEYCODE_CIRCUMFLEX:
      return GDK_asciicircum;
    case IIIMF_KEYCODE_DOLLAR:
      return GDK_dollar;
    case IIIMF_KEYCODE_EURO_SIGN:
      return GDK_EuroSign;
    case IIIMF_KEYCODE_EXCLAMATION_MARK:
      return GDK_exclam;
    case IIIMF_KEYCODE_INVERTED_EXCLAMATION_MARK:
      return GDK_exclamdown;
    case IIIMF_KEYCODE_LEFT_PARENTHESIS:
      return GDK_parenleft;
    case IIIMF_KEYCODE_NUMBER_SIGN:
      return GDK_numbersign;
    case IIIMF_KEYCODE_PLUS:
      return GDK_plus;
    case IIIMF_KEYCODE_RIGHT_PARENTHESIS:
      return GDK_parenright;
    case IIIMF_KEYCODE_UNDERSCORE:
      return GDK_underscore;
    case IIIMF_KEYCODE_F13:
      return GDK_F13;
    case IIIMF_KEYCODE_F14:
      return GDK_F14;
    case IIIMF_KEYCODE_F15:
      return GDK_F15;
    case IIIMF_KEYCODE_F16:
      return GDK_F16;
    case IIIMF_KEYCODE_F17:
      return GDK_F17;
    case IIIMF_KEYCODE_F18:
      return GDK_F18;
    case IIIMF_KEYCODE_F19:
      return GDK_F19;
    case IIIMF_KEYCODE_F20:
      return GDK_F20;
    case IIIMF_KEYCODE_F21:
      return GDK_F21;
    case IIIMF_KEYCODE_F22:
      return GDK_F22;
    case IIIMF_KEYCODE_F23:
      return GDK_F23;
    case IIIMF_KEYCODE_F24:
      return GDK_F24;
      /*
         case IIIMF_KEYCODE_COMPOSE:
         case IIIMF_KEYCODE_ALT_GRAPH
         case IIIMF_KEYCODE_STOP
         case IIIMF_KEYCODE_AGAIN
         case IIIMF_KEYCODE_PROPS
       */
    case IIIMF_KEYCODE_UNDO:
      return GDK_Undo;
      /*
         case IIIMF_KEYCODE_COPY
         case IIIMF_KEYCODE_PASTE
       */
    case IIIMF_KEYCODE_FIND:
      return GDK_Find;
      /* case IIIMF_KEYCODE_CUT */

    default:
      return (guint) (kv & 0x7fffffff);
    }
  return 0;
}

IIIMF_status
convert_IIIMCF_keyevent_to_GdkEventKey (IIIMCF_keyevent * pkev,
					GdkEventKey * e)
{
  guint c;
  GdkKeymap *keymap;
  GdkKeymapKey *keys;
  gint n_keys;

#if	USE_KANA_TABLE
  gint i;

  for (i = 0; kana_normal_keymapTable[i].iiimf_keycode != 0; i++)
    {
      if (kana_normal_keymapTable[i].iiimf_keychar == pkev->keychar)
        {
          e->keyval = kana_normal_keymapTable[i].gdk_keysym;
          goto FINDKEYVAL;

          break;
        }
    }

  for (i = 0; kana_shift_keymapTable[i].iiimf_keycode != 0; i++)
    {
      if (kana_shift_keymapTable[i].iiimf_keychar == pkev->keychar)
        {
          e->keyval = kana_shift_keymapTable[i].gdk_keysym;
          goto FINDKEYVAL;

          break;
        }
    }
#endif /* USE_KANA_TABLE */

  if (pkev->keychar)
    {
      e->keyval = gdk_unicode_to_keyval (pkev->keychar);
    }
  else
    {
      c = i2gcode (pkev->keycode, pkev->keychar);
      if (c == 0)
	return IIIMF_STATUS_FAIL;
      e->keyval = c;
    }

#if	USE_KANA_TABLE
FINDKEYVAL:
#endif /* USE_KANA_TABLE */

#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2
  keymap = gdk_keymap_get_for_display (gdk_drawable_get_display (e->window));
#else
  keymap = gdk_keymap_get_default ();
#endif


  e->state = i2gmodifier (pkev->modifier);

  if (!gdk_keymap_get_entries_for_keyval (keymap, e->keyval, &keys, &n_keys))
    return IIIMF_STATUS_FAIL;

  if (n_keys)
    {
      e->hardware_keycode = keys[0].keycode;
      g_free (keys);
    }

  e->time = pkev->time_stamp;

  return IIIMF_STATUS_SUCCESS;
}

/* Local Variables: */
/* c-file-style: "gnu" */
/* End: */
