/*
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 */
 
#ifndef XK_KATAKANA
#define XK_KATAKANA
#endif

#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Sunkeysym.h>
#include <X11/Xmd.h>

/*
#include "KeyMap.h"
*/

#define kana_table 1 /* for japanese kana support */

typedef struct KEYMAP_ENTRY {
    long awtKey;
    KeySym x11Key;
    Bool printable;
} KeymapEntry;

#if kana_table
typedef struct KEYMAP_ENTRY2 {
    long awtKey;
    KeySym x11Key;
    KeySym alt_x11Key;
    int keychar;
    Bool printable;
    KeyCode keycode;
} KeymapEntry2;
#endif

static int awt_MetaMask = 0;
static int awt_AltMask = 0;
static int awt_NumLockMask = 0;
static int awt_KanaLockMask = 0;

#ifdef	linux
#include <X11/Xatom.h>
static int KanaMode = -1;
static Atom kanawin_atom = 0;
static Atom kanaflag_atom = 0;
static Window kana_w = 0;
#endif /* linux */

/* extract the definitions below from java header files */
#undef java_awt_event_KeyEvent_COMPONENT_EVENT_MASK
#define java_awt_event_KeyEvent_COMPONENT_EVENT_MASK 1LL
#undef java_awt_event_KeyEvent_CONTAINER_EVENT_MASK
#define java_awt_event_KeyEvent_CONTAINER_EVENT_MASK 2LL
#undef java_awt_event_KeyEvent_FOCUS_EVENT_MASK
#define java_awt_event_KeyEvent_FOCUS_EVENT_MASK 4LL
#undef java_awt_event_KeyEvent_KEY_EVENT_MASK
#define java_awt_event_KeyEvent_KEY_EVENT_MASK 8LL
#undef java_awt_event_KeyEvent_MOUSE_EVENT_MASK
#define java_awt_event_KeyEvent_MOUSE_EVENT_MASK 16LL
#undef java_awt_event_KeyEvent_MOUSE_MOTION_EVENT_MASK
#define java_awt_event_KeyEvent_MOUSE_MOTION_EVENT_MASK 32LL
#undef java_awt_event_KeyEvent_WINDOW_EVENT_MASK
#define java_awt_event_KeyEvent_WINDOW_EVENT_MASK 64LL
#undef java_awt_event_KeyEvent_ACTION_EVENT_MASK
#define java_awt_event_KeyEvent_ACTION_EVENT_MASK 128LL
#undef java_awt_event_KeyEvent_ADJUSTMENT_EVENT_MASK
#define java_awt_event_KeyEvent_ADJUSTMENT_EVENT_MASK 256LL
#undef java_awt_event_KeyEvent_ITEM_EVENT_MASK
#define java_awt_event_KeyEvent_ITEM_EVENT_MASK 512LL
#undef java_awt_event_KeyEvent_TEXT_EVENT_MASK
#define java_awt_event_KeyEvent_TEXT_EVENT_MASK 1024LL
#undef java_awt_event_KeyEvent_RESERVED_ID_MAX
#define java_awt_event_KeyEvent_RESERVED_ID_MAX 1999L
#undef java_awt_event_KeyEvent_serialVersionUID
#define java_awt_event_KeyEvent_serialVersionUID -1825314779160409405LL
#undef java_awt_event_KeyEvent_COMPONENT_FIRST
#define java_awt_event_KeyEvent_COMPONENT_FIRST 100L
#undef java_awt_event_KeyEvent_COMPONENT_LAST
#define java_awt_event_KeyEvent_COMPONENT_LAST 103L
#undef java_awt_event_KeyEvent_COMPONENT_MOVED
#define java_awt_event_KeyEvent_COMPONENT_MOVED 100L
#undef java_awt_event_KeyEvent_COMPONENT_RESIZED
#define java_awt_event_KeyEvent_COMPONENT_RESIZED 101L
#undef java_awt_event_KeyEvent_COMPONENT_SHOWN
#define java_awt_event_KeyEvent_COMPONENT_SHOWN 102L
#undef java_awt_event_KeyEvent_COMPONENT_HIDDEN
#define java_awt_event_KeyEvent_COMPONENT_HIDDEN 103L
#undef java_awt_event_KeyEvent_serialVersionUID
#define java_awt_event_KeyEvent_serialVersionUID 8101406823902992965LL
#undef java_awt_event_KeyEvent_SHIFT_MASK
#define java_awt_event_KeyEvent_SHIFT_MASK 1L
#undef java_awt_event_KeyEvent_CTRL_MASK
#define java_awt_event_KeyEvent_CTRL_MASK 2L
#undef java_awt_event_KeyEvent_META_MASK
#define java_awt_event_KeyEvent_META_MASK 4L
#undef java_awt_event_KeyEvent_ALT_MASK
#define java_awt_event_KeyEvent_ALT_MASK 8L
#undef java_awt_event_KeyEvent_BUTTON1_MASK
#define java_awt_event_KeyEvent_BUTTON1_MASK 16L
#undef java_awt_event_KeyEvent_BUTTON2_MASK
#define java_awt_event_KeyEvent_BUTTON2_MASK 8L
#undef java_awt_event_KeyEvent_BUTTON3_MASK
#define java_awt_event_KeyEvent_BUTTON3_MASK 4L
#undef java_awt_event_KeyEvent_KEY_FIRST
#define java_awt_event_KeyEvent_KEY_FIRST 400L
#undef java_awt_event_KeyEvent_KEY_LAST
#define java_awt_event_KeyEvent_KEY_LAST 402L
#undef java_awt_event_KeyEvent_KEY_TYPED
#define java_awt_event_KeyEvent_KEY_TYPED 400L
#undef java_awt_event_KeyEvent_KEY_PRESSED
#define java_awt_event_KeyEvent_KEY_PRESSED 401L
#undef java_awt_event_KeyEvent_KEY_RELEASED
#define java_awt_event_KeyEvent_KEY_RELEASED 402L
#undef java_awt_event_KeyEvent_VK_ENTER
#define java_awt_event_KeyEvent_VK_ENTER 10L
#undef java_awt_event_KeyEvent_VK_BACK_SPACE
#define java_awt_event_KeyEvent_VK_BACK_SPACE 8L
#undef java_awt_event_KeyEvent_VK_TAB
#define java_awt_event_KeyEvent_VK_TAB 9L
#undef java_awt_event_KeyEvent_VK_CANCEL
#define java_awt_event_KeyEvent_VK_CANCEL 3L
#undef java_awt_event_KeyEvent_VK_CLEAR
#define java_awt_event_KeyEvent_VK_CLEAR 12L
#undef java_awt_event_KeyEvent_VK_SHIFT
#define java_awt_event_KeyEvent_VK_SHIFT 16L
#undef java_awt_event_KeyEvent_VK_CONTROL
#define java_awt_event_KeyEvent_VK_CONTROL 17L
#undef java_awt_event_KeyEvent_VK_ALT
#define java_awt_event_KeyEvent_VK_ALT 18L
#undef java_awt_event_KeyEvent_VK_PAUSE
#define java_awt_event_KeyEvent_VK_PAUSE 19L
#undef java_awt_event_KeyEvent_VK_CAPS_LOCK
#define java_awt_event_KeyEvent_VK_CAPS_LOCK 20L
#undef java_awt_event_KeyEvent_VK_ESCAPE
#define java_awt_event_KeyEvent_VK_ESCAPE 27L
#undef java_awt_event_KeyEvent_VK_SPACE
#define java_awt_event_KeyEvent_VK_SPACE 32L
#undef java_awt_event_KeyEvent_VK_PAGE_UP
#define java_awt_event_KeyEvent_VK_PAGE_UP 33L
#undef java_awt_event_KeyEvent_VK_PAGE_DOWN
#define java_awt_event_KeyEvent_VK_PAGE_DOWN 34L
#undef java_awt_event_KeyEvent_VK_END
#define java_awt_event_KeyEvent_VK_END 35L
#undef java_awt_event_KeyEvent_VK_HOME
#define java_awt_event_KeyEvent_VK_HOME 36L
#undef java_awt_event_KeyEvent_VK_LEFT
#define java_awt_event_KeyEvent_VK_LEFT 37L
#undef java_awt_event_KeyEvent_VK_UP
#define java_awt_event_KeyEvent_VK_UP 38L
#undef java_awt_event_KeyEvent_VK_RIGHT
#define java_awt_event_KeyEvent_VK_RIGHT 39L
#undef java_awt_event_KeyEvent_VK_DOWN
#define java_awt_event_KeyEvent_VK_DOWN 40L
#undef java_awt_event_KeyEvent_VK_COMMA
#define java_awt_event_KeyEvent_VK_COMMA 44L
#undef java_awt_event_KeyEvent_VK_PERIOD
#define java_awt_event_KeyEvent_VK_PERIOD 46L
#undef java_awt_event_KeyEvent_VK_MINUS
#define java_awt_event_KeyEvent_VK_MINUS 0x2D
#undef java_awt_event_KeyEvent_VK_SLASH
#define java_awt_event_KeyEvent_VK_SLASH 47L
#undef java_awt_event_KeyEvent_VK_0
#define java_awt_event_KeyEvent_VK_0 48L
#undef java_awt_event_KeyEvent_VK_1
#define java_awt_event_KeyEvent_VK_1 49L
#undef java_awt_event_KeyEvent_VK_2
#define java_awt_event_KeyEvent_VK_2 50L
#undef java_awt_event_KeyEvent_VK_3
#define java_awt_event_KeyEvent_VK_3 51L
#undef java_awt_event_KeyEvent_VK_4
#define java_awt_event_KeyEvent_VK_4 52L
#undef java_awt_event_KeyEvent_VK_5
#define java_awt_event_KeyEvent_VK_5 53L
#undef java_awt_event_KeyEvent_VK_6
#define java_awt_event_KeyEvent_VK_6 54L
#undef java_awt_event_KeyEvent_VK_7
#define java_awt_event_KeyEvent_VK_7 55L
#undef java_awt_event_KeyEvent_VK_8
#define java_awt_event_KeyEvent_VK_8 56L
#undef java_awt_event_KeyEvent_VK_9
#define java_awt_event_KeyEvent_VK_9 57L
#undef java_awt_event_KeyEvent_VK_SEMICOLON
#define java_awt_event_KeyEvent_VK_SEMICOLON 59L
#undef java_awt_event_KeyEvent_VK_EQUALS
#define java_awt_event_KeyEvent_VK_EQUALS 61L
#undef java_awt_event_KeyEvent_VK_A
#define java_awt_event_KeyEvent_VK_A 65L
#undef java_awt_event_KeyEvent_VK_B
#define java_awt_event_KeyEvent_VK_B 66L
#undef java_awt_event_KeyEvent_VK_C
#define java_awt_event_KeyEvent_VK_C 67L
#undef java_awt_event_KeyEvent_VK_D
#define java_awt_event_KeyEvent_VK_D 68L
#undef java_awt_event_KeyEvent_VK_E
#define java_awt_event_KeyEvent_VK_E 69L
#undef java_awt_event_KeyEvent_VK_F
#define java_awt_event_KeyEvent_VK_F 70L
#undef java_awt_event_KeyEvent_VK_G
#define java_awt_event_KeyEvent_VK_G 71L
#undef java_awt_event_KeyEvent_VK_H
#define java_awt_event_KeyEvent_VK_H 72L
#undef java_awt_event_KeyEvent_VK_I
#define java_awt_event_KeyEvent_VK_I 73L
#undef java_awt_event_KeyEvent_VK_J
#define java_awt_event_KeyEvent_VK_J 74L
#undef java_awt_event_KeyEvent_VK_K
#define java_awt_event_KeyEvent_VK_K 75L
#undef java_awt_event_KeyEvent_VK_L
#define java_awt_event_KeyEvent_VK_L 76L
#undef java_awt_event_KeyEvent_VK_M
#define java_awt_event_KeyEvent_VK_M 77L
#undef java_awt_event_KeyEvent_VK_N
#define java_awt_event_KeyEvent_VK_N 78L
#undef java_awt_event_KeyEvent_VK_O
#define java_awt_event_KeyEvent_VK_O 79L
#undef java_awt_event_KeyEvent_VK_P
#define java_awt_event_KeyEvent_VK_P 80L
#undef java_awt_event_KeyEvent_VK_Q
#define java_awt_event_KeyEvent_VK_Q 81L
#undef java_awt_event_KeyEvent_VK_R
#define java_awt_event_KeyEvent_VK_R 82L
#undef java_awt_event_KeyEvent_VK_S
#define java_awt_event_KeyEvent_VK_S 83L
#undef java_awt_event_KeyEvent_VK_T
#define java_awt_event_KeyEvent_VK_T 84L
#undef java_awt_event_KeyEvent_VK_U
#define java_awt_event_KeyEvent_VK_U 85L
#undef java_awt_event_KeyEvent_VK_V
#define java_awt_event_KeyEvent_VK_V 86L
#undef java_awt_event_KeyEvent_VK_W
#define java_awt_event_KeyEvent_VK_W 87L
#undef java_awt_event_KeyEvent_VK_X
#define java_awt_event_KeyEvent_VK_X 88L
#undef java_awt_event_KeyEvent_VK_Y
#define java_awt_event_KeyEvent_VK_Y 89L
#undef java_awt_event_KeyEvent_VK_Z
#define java_awt_event_KeyEvent_VK_Z 90L
#undef java_awt_event_KeyEvent_VK_OPEN_BRACKET
#define java_awt_event_KeyEvent_VK_OPEN_BRACKET 91L
#undef java_awt_event_KeyEvent_VK_BACK_SLASH
#define java_awt_event_KeyEvent_VK_BACK_SLASH 92L
#undef java_awt_event_KeyEvent_VK_CLOSE_BRACKET
#define java_awt_event_KeyEvent_VK_CLOSE_BRACKET 93L
#undef java_awt_event_KeyEvent_VK_NUMPAD0
#define java_awt_event_KeyEvent_VK_NUMPAD0 96L
#undef java_awt_event_KeyEvent_VK_NUMPAD1
#define java_awt_event_KeyEvent_VK_NUMPAD1 97L
#undef java_awt_event_KeyEvent_VK_NUMPAD2
#define java_awt_event_KeyEvent_VK_NUMPAD2 98L
#undef java_awt_event_KeyEvent_VK_NUMPAD3
#define java_awt_event_KeyEvent_VK_NUMPAD3 99L
#undef java_awt_event_KeyEvent_VK_NUMPAD4
#define java_awt_event_KeyEvent_VK_NUMPAD4 100L
#undef java_awt_event_KeyEvent_VK_NUMPAD5
#define java_awt_event_KeyEvent_VK_NUMPAD5 101L
#undef java_awt_event_KeyEvent_VK_NUMPAD6
#define java_awt_event_KeyEvent_VK_NUMPAD6 102L
#undef java_awt_event_KeyEvent_VK_NUMPAD7
#define java_awt_event_KeyEvent_VK_NUMPAD7 103L
#undef java_awt_event_KeyEvent_VK_NUMPAD8
#define java_awt_event_KeyEvent_VK_NUMPAD8 104L
#undef java_awt_event_KeyEvent_VK_NUMPAD9
#define java_awt_event_KeyEvent_VK_NUMPAD9 105L
#undef java_awt_event_KeyEvent_VK_MULTIPLY
#define java_awt_event_KeyEvent_VK_MULTIPLY 106L
#undef java_awt_event_KeyEvent_VK_ADD
#define java_awt_event_KeyEvent_VK_ADD 107L
#undef java_awt_event_KeyEvent_VK_SEPARATER
#define java_awt_event_KeyEvent_VK_SEPARATER 108L
#undef java_awt_event_KeyEvent_VK_SUBTRACT
#define java_awt_event_KeyEvent_VK_SUBTRACT 109L
#undef java_awt_event_KeyEvent_VK_DECIMAL
#define java_awt_event_KeyEvent_VK_DECIMAL 110L
#undef java_awt_event_KeyEvent_VK_DIVIDE
#define java_awt_event_KeyEvent_VK_DIVIDE 111L
#undef java_awt_event_KeyEvent_VK_F1
#define java_awt_event_KeyEvent_VK_F1 112L
#undef java_awt_event_KeyEvent_VK_F2
#define java_awt_event_KeyEvent_VK_F2 113L
#undef java_awt_event_KeyEvent_VK_F3
#define java_awt_event_KeyEvent_VK_F3 114L
#undef java_awt_event_KeyEvent_VK_F4
#define java_awt_event_KeyEvent_VK_F4 115L
#undef java_awt_event_KeyEvent_VK_F5
#define java_awt_event_KeyEvent_VK_F5 116L
#undef java_awt_event_KeyEvent_VK_F6
#define java_awt_event_KeyEvent_VK_F6 117L
#undef java_awt_event_KeyEvent_VK_F7
#define java_awt_event_KeyEvent_VK_F7 118L
#undef java_awt_event_KeyEvent_VK_F8
#define java_awt_event_KeyEvent_VK_F8 119L
#undef java_awt_event_KeyEvent_VK_F9
#define java_awt_event_KeyEvent_VK_F9 120L
#undef java_awt_event_KeyEvent_VK_F10
#define java_awt_event_KeyEvent_VK_F10 121L
#undef java_awt_event_KeyEvent_VK_F11
#define java_awt_event_KeyEvent_VK_F11 122L
#undef java_awt_event_KeyEvent_VK_F12
#define java_awt_event_KeyEvent_VK_F12 123L
#undef java_awt_event_KeyEvent_VK_DELETE
#define java_awt_event_KeyEvent_VK_DELETE 127L
#undef java_awt_event_KeyEvent_VK_NUM_LOCK
#define java_awt_event_KeyEvent_VK_NUM_LOCK 144L
#undef java_awt_event_KeyEvent_VK_SCROLL_LOCK
#define java_awt_event_KeyEvent_VK_SCROLL_LOCK 145L
#undef java_awt_event_KeyEvent_VK_PRINTSCREEN
#define java_awt_event_KeyEvent_VK_PRINTSCREEN 154L
#undef java_awt_event_KeyEvent_VK_INSERT
#define java_awt_event_KeyEvent_VK_INSERT 155L
#undef java_awt_event_KeyEvent_VK_HELP
#define java_awt_event_KeyEvent_VK_HELP 156L
#undef java_awt_event_KeyEvent_VK_META
#define java_awt_event_KeyEvent_VK_META 157L
#undef java_awt_event_KeyEvent_VK_BACK_QUOTE
#define java_awt_event_KeyEvent_VK_BACK_QUOTE 192L
#undef java_awt_event_KeyEvent_VK_QUOTE
#define java_awt_event_KeyEvent_VK_QUOTE 222L
#undef java_awt_event_KeyEvent_VK_FINAL
#define java_awt_event_KeyEvent_VK_FINAL 24L
#undef java_awt_event_KeyEvent_VK_CONVERT
#define java_awt_event_KeyEvent_VK_CONVERT 28L
#undef java_awt_event_KeyEvent_VK_NONCONVERT
#define java_awt_event_KeyEvent_VK_NONCONVERT 29L
#undef java_awt_event_KeyEvent_VK_ACCEPT
#define java_awt_event_KeyEvent_VK_ACCEPT 30L
#undef java_awt_event_KeyEvent_VK_MODECHANGE
#define java_awt_event_KeyEvent_VK_MODECHANGE 31L
#undef java_awt_event_KeyEvent_VK_KANA
#define java_awt_event_KeyEvent_VK_KANA 21L
#undef java_awt_event_KeyEvent_VK_KANJI
#define java_awt_event_KeyEvent_VK_KANJI 25L
#undef java_awt_event_KeyEvent_VK_UNDEFINED
#define java_awt_event_KeyEvent_VK_UNDEFINED 0L
#undef java_awt_event_KeyEvent_CHAR_UNDEFINED
#define java_awt_event_KeyEvent_CHAR_UNDEFINED 0L

#undef java_awt_event_KeyEvent_VK_CUT
#define java_awt_event_KeyEvent_VK_CUT                      0xFFD1
#undef java_awt_event_KeyEvent_VK_COPY
#define java_awt_event_KeyEvent_VK_COPY                     0xFFCD
#undef java_awt_event_KeyEvent_VK_PASTE
#define java_awt_event_KeyEvent_VK_PASTE                    0xFFCF
#undef java_awt_event_KeyEvent_VK_UNDO
#define java_awt_event_KeyEvent_VK_UNDO                     0xFFCB
#undef java_awt_event_KeyEvent_VK_AGAIN
#define java_awt_event_KeyEvent_VK_AGAIN                    0xFFC9
#undef java_awt_event_KeyEvent_VK_FIND
#define java_awt_event_KeyEvent_VK_FIND                     0xFFD0
#undef java_awt_event_KeyEvent_VK_PROPS
#define java_awt_event_KeyEvent_VK_PROPS                    0xFFCA
#undef java_awt_event_KeyEvent_VK_STOP
#define java_awt_event_KeyEvent_VK_STOP                     0xFFC8

#undef java_awt_event_KeyEvent_VK_AT
#define java_awt_event_KeyEvent_VK_AT                       0x0200

#undef java_awt_event_InputEvent_SHIFT_MASK
#define java_awt_event_InputEvent_SHIFT_MASK 1L
#undef java_awt_event_InputEvent_CTRL_MASK
#define java_awt_event_InputEvent_CTRL_MASK 2L
#undef java_awt_event_InputEvent_META_MASK
#define java_awt_event_InputEvent_META_MASK 4L
#undef java_awt_event_InputEvent_ALT_MASK
#define java_awt_event_InputEvent_ALT_MASK 8L
#undef java_awt_event_InputEvent_BUTTON1_MASK
#define java_awt_event_InputEvent_BUTTON1_MASK 16L
#undef java_awt_event_InputEvent_BUTTON2_MASK
#define java_awt_event_InputEvent_BUTTON2_MASK 8L
#undef java_awt_event_InputEvent_BUTTON3_MASK
#define java_awt_event_InputEvent_BUTTON3_MASK 4L

typedef	enum {
    FALSE = 0,
    TRUE = 1
} bool_t;

typedef unsigned short unicode;

#if kana_table
static KeymapEntry2 kana_normal_keymapTable[] = {
    { java_awt_event_KeyEvent_VK_1, XK_kana_NU, XK_1, 0xff87, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_2, XK_kana_FU, XK_2, 0xff8c, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_3, XK_kana_A, XK_3, 0xff71, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_4, XK_kana_U, XK_4, 0xff73, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_5, XK_kana_E, XK_5, 0xff74, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_6, XK_kana_O, XK_6, 0xff75, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_7, XK_kana_YA, XK_7, 0xff94, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_8, XK_kana_YU, XK_8, 0xff95, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_9, XK_kana_YO, XK_9, 0xff96, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_0, XK_kana_WA, XK_0, 0xff9c, TRUE, 0 },
    { '-',			    XK_kana_HO, XK_minus, 0xff8e, TRUE, 0 },
    { '~',			    XK_kana_HE, XK_asciicircum, 0xff8d, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_Q, XK_kana_TA, XK_q, 0xff80, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_W, XK_kana_TE, XK_w, 0xff83, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_E, XK_kana_I, XK_e, 0xff72, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_R, XK_kana_SU, XK_r, 0xff7d, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_T, XK_kana_KA, XK_t, 0xff76, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_Y, XK_kana_N, XK_y, 0xff9d, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_U, XK_kana_NA, XK_u, 0xff85, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_I, XK_kana_NI, XK_i, 0xff86, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_O, XK_kana_RA, XK_o, 0xff97, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_P, XK_kana_SE, XK_p, 0xff7e, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_AT, XK_voicedsound, XK_at, 0xff9e, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_semivoicedsound, XK_bracketleft, 0xff9f, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_A, XK_kana_CHI, XK_a, 0xff81, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_S, XK_kana_TO, XK_s, 0xff84, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_D, XK_kana_SHI, XK_d, 0xff7c, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_F, XK_kana_HA, XK_f, 0xff8a, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_G, XK_kana_KI, XK_g, 0xff77, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_H, XK_kana_KU, XK_h, 0xff78, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_J, XK_kana_MA, XK_j, 0xff8f, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_K, XK_kana_NO, XK_k, 0xff89, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_L, XK_kana_RI, XK_l, 0xff98, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_SEMICOLON, XK_kana_RE, XK_semicolon, 0xff9a, TRUE, 0 },
    { ':',				    XK_kana_KE, XK_colon, 0xff79, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_kana_MU, XK_bracketright, 0xff91, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_Z, XK_kana_TSU, XK_z, 0xff82, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_X, XK_kana_SA, XK_x, 0xff7b, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_C, XK_kana_SO, XK_c, 0xff7f, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_V, XK_kana_HI, XK_v, 0xff8b, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_B, XK_kana_KO, XK_b, 0xff7a, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_N, XK_kana_MI, XK_n, 0xff90, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_M, XK_kana_MO, XK_m, 0xff93, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_COMMA, XK_kana_NE, XK_comma, 0xff88, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_PERIOD, XK_kana_RU, XK_period, 0xff99, TRUE , 0},
    { java_awt_event_KeyEvent_VK_SLASH, XK_kana_ME, XK_slash, 0xff92, TRUE, 0 },
    /* hack to japanese keyboard */
    /* backslash is duplicate for RO and prolongedsound */
    { java_awt_event_KeyEvent_VK_BACK_SLASH, XK_kana_RO, XK_underscore, 0xff9b, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_BACK_SLASH, XK_prolongedsound, XK_bar, 0xff70, TRUE, 0 },
    { 0, 0, 0 }
};

static KeymapEntry2 kana_shift_keymapTable[] = {
    { java_awt_event_KeyEvent_VK_3, XK_kana_a, XK_numbersign, 0xff67, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_4, XK_kana_u, XK_dollar, 0xff69, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_5, XK_kana_e, XK_percent, 0xff6a, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_6, XK_kana_o, XK_ampersand, 0xff6b, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_7, XK_kana_ya, XK_apostrophe, 0xff6c, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_8, XK_kana_yu, XK_parenleft, 0xff6d, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_9, XK_kana_yo, XK_parenright, 0xff6e, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_0, XK_kana_WO, XK_asciitilde, 0xff66, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_E, XK_kana_i, XK_E, 0xff68, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_kana_openingbracket, XK_braceleft, 0xff62, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_kana_closingbracket, XK_braceright, 0xff63, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_Z, XK_kana_tsu, XK_Z, 0xff6f, TRUE, 0 },
    /* XK_less does not return correct keycode on VineLinux 1.1 */
    { java_awt_event_KeyEvent_VK_COMMA, XK_kana_comma, XK_comma, 0xff64, TRUE, 0 },
    { java_awt_event_KeyEvent_VK_PERIOD, XK_kana_fullstop, XK_greater, 0xff61, TRUE,0 },
    { java_awt_event_KeyEvent_VK_SLASH, XK_kana_conjunctive, XK_question, 0xff65, TRUE,0 },
    { 0, 0, 0 }
};
#endif

static KeymapEntry keymapTable[] = {
    { java_awt_event_KeyEvent_VK_A, XK_a, TRUE },
    { java_awt_event_KeyEvent_VK_B, XK_b, TRUE },
    { java_awt_event_KeyEvent_VK_C, XK_c, TRUE },
    { java_awt_event_KeyEvent_VK_D, XK_d, TRUE },
    { java_awt_event_KeyEvent_VK_E, XK_e, TRUE },
    { java_awt_event_KeyEvent_VK_F, XK_f, TRUE },
    { java_awt_event_KeyEvent_VK_G, XK_g, TRUE },
    { java_awt_event_KeyEvent_VK_H, XK_h, TRUE },
    { java_awt_event_KeyEvent_VK_I, XK_i, TRUE },
    { java_awt_event_KeyEvent_VK_J, XK_j, TRUE },
    { java_awt_event_KeyEvent_VK_K, XK_k, TRUE },
    { java_awt_event_KeyEvent_VK_L, XK_l, TRUE },
    { java_awt_event_KeyEvent_VK_M, XK_m, TRUE },
    { java_awt_event_KeyEvent_VK_N, XK_n, TRUE },
    { java_awt_event_KeyEvent_VK_O, XK_o, TRUE },
    { java_awt_event_KeyEvent_VK_P, XK_p, TRUE },
    { java_awt_event_KeyEvent_VK_Q, XK_q, TRUE },
    { java_awt_event_KeyEvent_VK_R, XK_r, TRUE },
    { java_awt_event_KeyEvent_VK_S, XK_s, TRUE },
    { java_awt_event_KeyEvent_VK_T, XK_t, TRUE },
    { java_awt_event_KeyEvent_VK_U, XK_u, TRUE },
    { java_awt_event_KeyEvent_VK_V, XK_v, TRUE },
    { java_awt_event_KeyEvent_VK_W, XK_w, TRUE },
    { java_awt_event_KeyEvent_VK_X, XK_x, TRUE },
    { java_awt_event_KeyEvent_VK_Y, XK_y, TRUE },
    { java_awt_event_KeyEvent_VK_Z, XK_z, TRUE },

    { java_awt_event_KeyEvent_VK_ENTER, XK_Return, TRUE },
    { java_awt_event_KeyEvent_VK_ENTER, XK_KP_Enter, TRUE },
    { java_awt_event_KeyEvent_VK_ENTER, XK_Linefeed, TRUE },

    { java_awt_event_KeyEvent_VK_BACK_SPACE, XK_BackSpace, TRUE },
    { java_awt_event_KeyEvent_VK_TAB, XK_Tab, TRUE },
    { java_awt_event_KeyEvent_VK_TAB, XK_ISO_Left_Tab, TRUE },
    { java_awt_event_KeyEvent_VK_CANCEL, XK_Cancel, FALSE },
    { java_awt_event_KeyEvent_VK_CLEAR, XK_Clear, FALSE },
    { java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_L, FALSE },
    { java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_R, FALSE }, 
    { java_awt_event_KeyEvent_VK_CONTROL, XK_Control_L, FALSE },
    { java_awt_event_KeyEvent_VK_CONTROL, XK_Control_R, FALSE }, 
    { java_awt_event_KeyEvent_VK_ALT, XK_Alt_L, FALSE },
    { java_awt_event_KeyEvent_VK_ALT, XK_Alt_R, FALSE },
    { java_awt_event_KeyEvent_VK_META, XK_Meta_L, FALSE },
    { java_awt_event_KeyEvent_VK_META, XK_Meta_R, FALSE }, 
    { java_awt_event_KeyEvent_VK_PAUSE, XK_Pause, FALSE },
    { java_awt_event_KeyEvent_VK_CAPS_LOCK, XK_Caps_Lock, FALSE },
    { java_awt_event_KeyEvent_VK_ESCAPE, XK_Escape, TRUE },
    { java_awt_event_KeyEvent_VK_SPACE, XK_space, TRUE },

    { java_awt_event_KeyEvent_VK_PAGE_UP, XK_Page_Up, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_UP, XK_R9, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_UP, XK_Prior, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_UP, XK_F29, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Page_Down, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_R15, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Next, FALSE },
    { java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_F35, FALSE },
    { java_awt_event_KeyEvent_VK_END, XK_End, FALSE },
    { java_awt_event_KeyEvent_VK_END, XK_R13, FALSE },
    { java_awt_event_KeyEvent_VK_HOME, XK_Home, FALSE },
    { java_awt_event_KeyEvent_VK_HOME, XK_R7, FALSE },
    { java_awt_event_KeyEvent_VK_HOME, XK_F27, FALSE },

    { java_awt_event_KeyEvent_VK_LEFT, XK_Left, FALSE },
    { java_awt_event_KeyEvent_VK_UP, XK_Up, FALSE },
    { java_awt_event_KeyEvent_VK_RIGHT, XK_Right, FALSE },
    { java_awt_event_KeyEvent_VK_DOWN, XK_Down, FALSE },
    { java_awt_event_KeyEvent_VK_INSERT, XK_Insert, FALSE },
    { java_awt_event_KeyEvent_VK_HELP, XK_Help, FALSE },

    { java_awt_event_KeyEvent_VK_0, XK_0, TRUE },
    { java_awt_event_KeyEvent_VK_1, XK_1, TRUE },
    { java_awt_event_KeyEvent_VK_2, XK_2, TRUE },
    { java_awt_event_KeyEvent_VK_3, XK_3, TRUE },
    { java_awt_event_KeyEvent_VK_4, XK_4, TRUE },
    { java_awt_event_KeyEvent_VK_5, XK_5, TRUE },
    { java_awt_event_KeyEvent_VK_6, XK_6, TRUE },
    { java_awt_event_KeyEvent_VK_7, XK_7, TRUE },
    { java_awt_event_KeyEvent_VK_8, XK_8, TRUE },
    { java_awt_event_KeyEvent_VK_9, XK_9, TRUE },

    { java_awt_event_KeyEvent_VK_EQUALS, XK_equal, TRUE },
    { java_awt_event_KeyEvent_VK_BACK_SLASH, XK_backslash, TRUE },
    { java_awt_event_KeyEvent_VK_BACK_QUOTE, XK_grave, TRUE },
    { java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_bracketleft, TRUE },
    { java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_bracketright, TRUE },
    { java_awt_event_KeyEvent_VK_SEMICOLON, XK_semicolon, TRUE },
    { java_awt_event_KeyEvent_VK_QUOTE, XK_apostrophe, TRUE },
    { java_awt_event_KeyEvent_VK_MINUS, XK_minus, TRUE },
    { java_awt_event_KeyEvent_VK_COMMA, XK_comma, TRUE },
    { java_awt_event_KeyEvent_VK_PERIOD, XK_period, TRUE },
    { java_awt_event_KeyEvent_VK_SLASH, XK_slash, TRUE },

    { java_awt_event_KeyEvent_VK_NUMPAD0, XK_KP_0, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD1, XK_KP_1, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD2, XK_KP_2, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD3, XK_KP_3, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD4, XK_KP_4, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD5, XK_KP_5, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD6, XK_KP_6, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD7, XK_KP_7, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD8, XK_KP_8, TRUE },
    { java_awt_event_KeyEvent_VK_NUMPAD9, XK_KP_9, TRUE },
    { java_awt_event_KeyEvent_VK_MULTIPLY, XK_KP_Multiply, TRUE },
    { java_awt_event_KeyEvent_VK_ADD, XK_KP_Add, TRUE },
    { java_awt_event_KeyEvent_VK_SUBTRACT, XK_KP_Subtract, TRUE },
    { java_awt_event_KeyEvent_VK_DECIMAL, XK_KP_Decimal, TRUE },
    { java_awt_event_KeyEvent_VK_DIVIDE, XK_KP_Divide, TRUE },
    { java_awt_event_KeyEvent_VK_EQUALS, XK_KP_Equal, TRUE },
    { java_awt_event_KeyEvent_VK_INSERT, XK_KP_Insert, FALSE },
    { java_awt_event_KeyEvent_VK_ENTER, XK_KP_Enter, FALSE },

    { java_awt_event_KeyEvent_VK_F1, XK_F1, FALSE },
    { java_awt_event_KeyEvent_VK_F2, XK_F2, FALSE },
    { java_awt_event_KeyEvent_VK_F3, XK_F3, FALSE },
    { java_awt_event_KeyEvent_VK_F4, XK_F4, FALSE },
    { java_awt_event_KeyEvent_VK_F5, XK_F5, FALSE },
    { java_awt_event_KeyEvent_VK_F6, XK_F6, FALSE },
    { java_awt_event_KeyEvent_VK_F7, XK_F7, FALSE },
    { java_awt_event_KeyEvent_VK_F8, XK_F8, FALSE },
    { java_awt_event_KeyEvent_VK_F9, XK_F9, FALSE },
    { java_awt_event_KeyEvent_VK_F10, XK_F10, FALSE },
    /* next two entries for for 4173902 */
    { java_awt_event_KeyEvent_VK_F11, SunXK_F36, FALSE },
    { java_awt_event_KeyEvent_VK_F12, SunXK_F37, FALSE },
    { java_awt_event_KeyEvent_VK_F11, XK_F11, FALSE },
    { java_awt_event_KeyEvent_VK_F12, XK_F12, FALSE },

    { java_awt_event_KeyEvent_VK_DELETE, XK_Delete, TRUE },
    { java_awt_event_KeyEvent_VK_DELETE, XK_KP_Delete, TRUE },

    { java_awt_event_KeyEvent_VK_NUM_LOCK, XK_Num_Lock, FALSE },
    { java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_Scroll_Lock, FALSE },
    { java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_Print, FALSE },

    { java_awt_event_KeyEvent_VK_ACCEPT, XK_Execute, FALSE },

#ifdef	JAVA_12_BUG
    /* bugs in Java2 4124396

	- Convert key (right of Space key): generates VK_KANJI,
		should generate VK_CONVERT.
	- Nihongo On-Off key (right of Convert key): generates VK_CONVERT,
		should generate VK_KANJI.

    */

    { java_awt_event_KeyEvent_VK_CONVERT, XK_Henkan_Mode, FALSE },
    { java_awt_event_KeyEvent_VK_KANJI, XK_Kanji, FALSE },
#else
    { java_awt_event_KeyEvent_VK_KANJI, XK_Henkan_Mode, FALSE },
    { java_awt_event_KeyEvent_VK_CONVERT, XK_Kanji, FALSE },
#endif

    { java_awt_event_KeyEvent_VK_NONCONVERT, XK_Muhenkan, FALSE },

    { java_awt_event_KeyEvent_VK_KANA, XK_Katakana, FALSE },
    { java_awt_event_KeyEvent_VK_KANA, XK_kana_switch, FALSE },

    { java_awt_event_KeyEvent_VK_CUT, XK_F20, FALSE },
    { java_awt_event_KeyEvent_VK_COPY, XK_F16, FALSE },
    { java_awt_event_KeyEvent_VK_PASTE, XK_F18, FALSE },
    { java_awt_event_KeyEvent_VK_UNDO, XK_F14, FALSE },
    { java_awt_event_KeyEvent_VK_FIND, XK_F19, FALSE },
    { java_awt_event_KeyEvent_VK_PROPS, XK_F13, FALSE },

    { 0, 0, 0 }
};

static KeySym getX11KeySym(long awtKey) 
{
    int i;
    for (i = 0; keymapTable[i].awtKey != 0; i++) {
        if (keymapTable[i].awtKey == awtKey) {
	  /* stop checking printable or not, otherwise
	     arrow keys won't work
	    if (keymapTable[i].printable == FALSE) return 0;
	    */
	  return keymapTable[i].x11Key;
        }
    }
    return 0;
}

static long getAWTKeyCode(long keysym) 
{
    int i;
    for (i = 0; keymapTable[i].awtKey != 0; i++) {
        if (keymapTable[i].x11Key == keysym) {
	  return keymapTable[i].awtKey;
        }
    }
    return 0;
}

/* for kana */
#if kana_table
static void getAWTKeyCode2(long keysym, int *keycode, int *keychar) 
{
    int i;
	  *keycode = 0;
	  *keychar = 0;

    for (i = 0; kana_normal_keymapTable[i].awtKey != 0; i++) {
        if (kana_normal_keymapTable[i].x11Key == keysym) {
	  *keycode = kana_normal_keymapTable[i].awtKey;
	  *keychar = kana_normal_keymapTable[i].keychar;
	  return;
        }
    }
    for (i = 0; kana_shift_keymapTable[i].awtKey != 0; i++) {
        if (kana_shift_keymapTable[i].x11Key == keysym) {
	  *keycode = kana_shift_keymapTable[i].awtKey;
	  *keychar = kana_shift_keymapTable[i].keychar;
	  return;
        }
    }
    return;
}
#endif

static void
set_mod_mask(int modnum, int *mask) {
    switch(modnum) {
      case 1: 
	*mask = Mod1Mask;
	break;			
      case 2: 
	*mask = Mod2Mask;
	break;		
      case 3: 
	*mask = Mod3Mask;
	break;			
      case 4: 
	*mask = Mod4Mask;
	break;	
      case 5:
	*mask = Mod5Mask;
	break;
      default:
	*mask = 0;
    }
}

static void
setup_modifier_map(Display *disp)
{
    XModifierKeymap *modmap; 
    int i, k, nkeys;
    KeyCode keycode, metaL, metaR, altL, altR, numLock, Mode_switch;

    metaL = XKeysymToKeycode(disp, XK_Meta_L);
    metaR = XKeysymToKeycode(disp, XK_Meta_R);
    altR = XKeysymToKeycode(disp, XK_Alt_R);
    altL = XKeysymToKeycode(disp, XK_Alt_L);
    numLock = XKeysymToKeycode(disp, XK_Num_Lock);
    Mode_switch = XKeysymToKeycode(disp, XK_Mode_switch);

    modmap = XGetModifierMapping(disp);
    nkeys = modmap->max_keypermod;
    for(i = 3*nkeys; 
	i < (nkeys*8) && (awt_MetaMask == 0 || awt_AltMask == 0 || awt_NumLockMask == 0 || awt_KanaLockMask ==0);
            i++) {
	keycode = modmap->modifiermap[i];
	k = (i/nkeys) - 2;
	if (awt_MetaMask == 0 && (keycode == metaL || keycode == metaR)) {
	    set_mod_mask(k, &awt_MetaMask);
	} else if (awt_AltMask == 0 && (keycode == altL || keycode == altR)) {
 	    set_mod_mask(k, &awt_AltMask);
	} else if (awt_NumLockMask == 0 && keycode == numLock) {
            set_mod_mask(k, &awt_NumLockMask);
	} else if (awt_KanaLockMask == 0 && keycode == Mode_switch) {
            set_mod_mask(k, &awt_KanaLockMask);
        }
    }
    XFreeModifiermap(modmap);

#ifdef	linux
    /* hack for Linux XFree86 */
    if (getenv("HTT_USES_LINUX_XKEYSYM")){
	    for (i = 0; keymapTable[i].awtKey != 0; i++) {
		if (keymapTable[i].x11Key == XK_Henkan_Mode) {
		  keymapTable[i].x11Key = XK_Zenkaku_Hankaku;
		  break;
		}
	    }
	    for (i = 0; keymapTable[i].awtKey != 0; i++) {
		if (keymapTable[i].x11Key == XK_Kanji) {
		  keymapTable[i].x11Key = XK_Henkan_Mode;
		  break;
		}
	    }
	    for (i = 0; keymapTable[i].awtKey != 0; i++) {
		if (keymapTable[i].x11Key == XK_Execute) {
		  keymapTable[i].x11Key = XK_Muhenkan;
		  break;
		}
	    }
    }

    /* hack for Linux XFree86 */
    if (getenv("HTT_GENERATES_KANAKEY")){
	KanaMode = 0;
    } else {
	return;
    }

    /* Get Keycodes for Kana keys */
    for (i = 0; kana_normal_keymapTable[i].awtKey != 0; i++) {
	kana_normal_keymapTable[i].keycode = XKeysymToKeycode(disp,
						kana_normal_keymapTable[i].x11Key);
	if (kana_normal_keymapTable[i].keycode == 0) {
		kana_normal_keymapTable[i].keycode = XKeysymToKeycode(disp,
						kana_normal_keymapTable[i].alt_x11Key);
	}
#ifdef	DEBUG
	printf("xkey=%x(%x) -> %x\n", kana_normal_keymapTable[i].x11Key,
					kana_normal_keymapTable[i].keychar,
					kana_normal_keymapTable[i].keycode);
#endif
    }
    for (i = 0; kana_shift_keymapTable[i].awtKey != 0; i++) {
	kana_shift_keymapTable[i].keycode = XKeysymToKeycode(disp,
						kana_shift_keymapTable[i].x11Key);
	if (kana_shift_keymapTable[i].keycode == 0) {
		kana_shift_keymapTable[i].keycode = XKeysymToKeycode(disp,
						kana_shift_keymapTable[i].alt_x11Key);
	}
#ifdef	DEBUG
	printf("xkey=%x(%x) -> %x\n", kana_shift_keymapTable[i].x11Key,
					kana_shift_keymapTable[i].keychar,
					kana_shift_keymapTable[i].keycode);
#endif
    }

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

    kana_w = XGetSelectionOwner(disp, kanawin_atom);

    if (kana_w == None) {
	kana_w = XCreateSimpleWindow(disp, RootWindow(disp, 0),
			0, 0, 1, 1, 0, 0, 0);

	XSetSelectionOwner(disp, kanawin_atom, kana_w, CurrentTime);

	XChangeProperty(disp, kana_w, kanaflag_atom, XA_WINDOW, 32,
				PropModeReplace,
				&KanaMode, sizeof(KanaMode));
    }

    GetKanaFlag(disp);
#endif /* linux */
}

#ifdef linux
GetKanaFlag(Display *disp)
{
    Atom            ret_type;
    int             ret_format;
    unsigned long   nitems, bytes_left;
    unsigned long  *tmp;

    XGetWindowProperty(disp, kana_w,
			kanaflag_atom, 0, 4, False, XA_WINDOW,
			&ret_type, &ret_format,
			&nitems, &bytes_left, &tmp);

    if (ret_type == XA_WINDOW) {
       KanaMode = *tmp;
    }
}
#endif /* linux */

/*
	XKeysymToKeycode() does not return correct keycode for XK_Delete.
	So we store and keep the value of KeyCode at the first key typed,
	then use in modify_Event()
*/

static long keyCode_XK_Delete = 0;

static void
modify_Event(XEvent *xevent, long keyCode, unicode keyChar, long modifiers)
{
    KeySym keysym = 0;

    if (xevent->type != KeyPress && xevent->type != KeyRelease)
        return;

    switch(keyCode) {
      case java_awt_event_KeyEvent_VK_ENTER:
      case java_awt_event_KeyEvent_VK_BACK_SPACE:
      case java_awt_event_KeyEvent_VK_TAB:
      case java_awt_event_KeyEvent_VK_ESCAPE:
      case java_awt_event_KeyEvent_VK_MULTIPLY:
      case java_awt_event_KeyEvent_VK_ADD:
      case java_awt_event_KeyEvent_VK_SUBTRACT:
      case java_awt_event_KeyEvent_VK_DIVIDE:
      case java_awt_event_KeyEvent_VK_EQUALS:
      case java_awt_event_KeyEvent_VK_DECIMAL:
          keysym = getX11KeySym(keyCode);
          break;
      default:
          if ((keyChar != 0 && keyChar < 256)
	      || (keyChar >= 0xff61 && keyChar <= 0xff9f)) {
              keysym = keyChar;
          } else {
              keysym = getX11KeySym(keyCode);
          }
          break;
    }

    if (keysym != 0) {
	if (modifiers & java_awt_event_InputEvent_CTRL_MASK) {
	    switch (keysym + 64) {
	      case '[':
	      case ']':
	      case '\\':
	      case '_':
		keysym += 64;
		break;
	      default:
	 	if (keysym < 254) {
		  if (modifiers & java_awt_event_InputEvent_SHIFT_MASK) {
		    if (isalpha(keysym + 'A' - 1)) {
		      keysym += ('A' - 1);
		    }
		  } else {
		    if (isalpha(keysym + 'a' - 1)) {
		      keysym += ('a' - 1);
		    }
		  }
		}
		break;
	    }
	}

	/*
	 * 0xff61 is Unicode value of first XK_kana_fullstop.
	 * We need X Keysym to Unicode map in post1.1 release
	 * to support more intenational keyboard.
	 */
	/*
	 * 0xff63 is duplicate with INSERT
	 */
	if (keyCode != java_awt_event_KeyEvent_VK_INSERT &&
	    keyCode != java_awt_event_KeyEvent_VK_ACCEPT &&
	    keyCode != java_awt_event_KeyEvent_VK_ENTER &&
	    (keysym >= 0xff61 && keysym <= 0xff9f)) {
	    keysym = keysym - 0xff61 + XK_kana_fullstop;

	    /*
	     * modifier needs to be set
	     */
	    xevent->xkey.state |= awt_KanaLockMask;
	}

	/* workaround, do we have to set NumLock mask for
	   all KP_ keysym??? */
	if(keysym == XK_KP_Decimal){
	    xevent->xkey.state |= awt_NumLockMask;
        }

	if (xevent->xany.display)
	    xevent->xkey.keycode = XKeysymToKeycode(xevent->xany.display,
						    keysym);
	else
	    xevent->xkey.keycode = keysym; /* hack */

	/* workaround for XKeysymToKeycode() */
	if (keyCode == java_awt_event_KeyEvent_VK_DELETE){
	    xevent->xkey.keycode = keyCode_XK_Delete;
	}
    }

    if (keysym >= 'A' && keysym <= 'Z') {
	xevent->xkey.state |= ShiftMask;
    }
    if (modifiers & java_awt_event_InputEvent_SHIFT_MASK) {
	xevent->xkey.state |= ShiftMask;
    }
    if (modifiers & java_awt_event_InputEvent_CTRL_MASK) {
	xevent->xkey.state |= ControlMask;
    }
    if (modifiers & java_awt_event_InputEvent_META_MASK) {
	xevent->xkey.state |= awt_MetaMask;
    }
    if (modifiers & java_awt_event_InputEvent_ALT_MASK) {
	xevent->xkey.state |= awt_AltMask;
    }
    if (modifiers & java_awt_event_InputEvent_BUTTON1_MASK) {
        xevent->xkey.state |= Button1Mask;
    }
    if (modifiers & java_awt_event_InputEvent_BUTTON2_MASK) {
        xevent->xkey.state |= Button2Mask;
    }
    if (modifiers & java_awt_event_InputEvent_BUTTON3_MASK) {
        xevent->xkey.state |= Button3Mask;
    }
}

static int first_call = True;

void
VirtualKeyToXKeyEvent(CARD32 keyCode, CARD32 keyChar,
		      CARD32 state, XKeyEvent *kev) {

    if (first_call && kev->display != (Display*)0) {
	setup_modifier_map(kev->display);
    }
    first_call = False;
    modify_Event((XEvent*)kev, keyCode, keyChar, state);
    return;
}

/*
  KeyEventToVirtualKey() :
     Convert X KeyEvent to IIIMP keyCode, keyChar, state values
 */
Bool
KeyEventToVirtualKey(XKeyEvent *ev, int *keycode_ret,
		     int *keychar_ret, int *state_ret) {
  KeySym keysym;
  char buf[64];
  int len = sizeof(buf);
  int state;
  int i;

  *keychar_ret = 0;
  *keycode_ret = 0;

  if (first_call && ev->display != (Display*)0) {
     setup_modifier_map(ev->display);
  }
  first_call = False;

  state = ev->state;

  /* LockMask, NumLockMask, KanaLockMask should be ignored for
     Java Client compatibility */
  if(state & LockMask){
    state -= LockMask;
  }
  if(state & awt_NumLockMask){
    state -= awt_NumLockMask;
  }
  if(state & awt_KanaLockMask){
    state -= awt_KanaLockMask;
  }

  /* IIIMP's control_mask(1<<1) and X's control_mask(1<<2)is
       different, so it should be changed */
  if (state & ControlMask) {
    state -= (1<<2);
    state |= (1<<1);
  }

  *state_ret = state;

  len = XLookupString(ev, buf, len - 1, &keysym, NULL);

#ifdef  linux
   /* Linux generates XK_Mode_switch at Shift + Henkan_Mode */
   if (getenv("HTT_USES_LINUX_XKEYSYM")&&
        ((state & ShiftMask) && keysym == XK_Mode_switch)){
        keysym = XK_Henkan_Mode;
   } else
#endif /* linux */
  if (IsModifierKey(keysym)) {
	return False;
  }

#ifdef	linux
  if (KanaMode != -1){
	if (keysym == XK_Hiragana_Katakana){
#ifdef	DEBUG
		printf("Kanakey is pressed\n");
#endif
		if (KanaMode == 1){
			KanaMode = 0;
#ifdef	DEBUG
		printf("	off\n");
#endif
		} else {
			KanaMode = 1;
#ifdef	DEBUG
		printf("	on\n");
#endif
		}
		XChangeProperty(ev->display, kana_w, kanaflag_atom,
				XA_WINDOW, 32,
				PropModeReplace,
				&KanaMode, sizeof(KanaMode));
		return False;
	}
  }

  if (KanaMode != -1){
  	GetKanaFlag(ev->display);
  }	 

  if (KanaMode == 1) {
	if (ev->state & ShiftMask) {
		/* check kana_shift_keymapTable first is ShiftMask */
		for (i = 0; kana_shift_keymapTable[i].awtKey != 0; i++) {
			if (kana_shift_keymapTable[i].keycode == ev->keycode) {
				getAWTKeyCode2(kana_shift_keymapTable[i].x11Key, keycode_ret, keychar_ret);
				if (*keycode_ret) {
					return True;
				}
				break;
			}
		}
	}

	for (i = 0; kana_normal_keymapTable[i].awtKey != 0; i++) {
		if (kana_normal_keymapTable[i].keycode == ev->keycode) {
			getAWTKeyCode2(kana_normal_keymapTable[i].x11Key, keycode_ret, keychar_ret);
			if (*keycode_ret) {
				return True;
			}
			break;
		}
	}

	for (i = 0; kana_shift_keymapTable[i].awtKey != 0; i++) {
		if (kana_shift_keymapTable[i].keycode == ev->keycode) {
			getAWTKeyCode2(kana_shift_keymapTable[i].x11Key, keycode_ret, keychar_ret);
			if (*keycode_ret) {
				return True;
			}
			break;
		}
	}
   }
#endif /* linux */

  /* store keycode for XK_Delete */
  if(keysym == XK_Delete && keyCode_XK_Delete == 0){
	keyCode_XK_Delete = ev->keycode;
  }

  if (keysym < 256) {
    if ((ev->state & ControlMask)) {
	if (isalpha(keysym)) {
	  keysym = toupper(keysym);
	}
    }
    *keycode_ret = getAWTKeyCode(keysym);
    if (*keycode_ret == 0 && (ev->state & ShiftMask)) {
	/* when Shift key is pressed, need to get the normal keysym,
	   then get the AWT keycode */
	if (ev->display != (Display*)0) {
	   *keycode_ret = getAWTKeyCode(XKeycodeToKeysym(ev->display,
							ev->keycode, 0));
	}
    }
    if (*keycode_ret == 0) {
        *keycode_ret = keysym;
    }
    *keychar_ret = keysym;
    return True;
  } else {
    *keycode_ret = getAWTKeyCode(keysym);
    switch (keysym) {
    case XK_KP_Decimal:
      *keychar_ret = '.';
      break;
    case XK_KP_Add:
      *keychar_ret = '+';
      break;
    case XK_KP_Subtract:
      *keychar_ret = '-';
      break;
    case XK_KP_Divide:
      *keychar_ret = '/';
      break;
    case XK_KP_Multiply:
      *keychar_ret = '*';
      break;
    case XK_KP_0:
      *keychar_ret = '0';
      break;
    case XK_KP_1:
      *keychar_ret = '1';
      break;
    case XK_KP_2:
      *keychar_ret = '2';
      break;
    case XK_KP_3:
      *keychar_ret = '3';
      break;
    case XK_KP_4:
      *keychar_ret = '4';
      break;
    case XK_KP_5:
      *keychar_ret = '5';
      break;
    case XK_KP_6:
      *keychar_ret = '6';
      break;
    case XK_KP_7:
      *keychar_ret = '7';
      break;
    case XK_KP_8:
      *keychar_ret = '8';
      break;
    case XK_KP_9:
      *keychar_ret = '9';
      break;
    }
    if(*keycode_ret) {
        return True;
    }

    /* get Kana code */
    getAWTKeyCode2(keysym, keycode_ret, keychar_ret);

    if (*keycode_ret) {
        return True;
    }

    if (*keycode_ret == 0 && (ev->state & ShiftMask)) {
        /* when Shift key is pressed, need to get the normal keysym,
	   then get the AWT keycode */
	*keycode_ret = getAWTKeyCode(XKeycodeToKeysym(ev->display,
							ev->keycode, 0));
    }

    if (*keycode_ret) {
        return True;
    }
  }
  return False;
}
